Added changed from #292, #296, #304, and #317

This commit is contained in:
The-EDev 2022-01-12 03:39:49 +03:00
parent a166a6d3cb
commit 87adb19e43
No known key found for this signature in database
GPG Key ID: 51C45DC0C413DCD9
7 changed files with 205 additions and 92 deletions

View File

@ -220,6 +220,11 @@ namespace crow
{
ssl_server_ = std::move(std::unique_ptr<ssl_server_t>(new ssl_server_t(this, bindaddr_, port_, server_name_, &middlewares_, concurrency_, &ssl_context_)));
ssl_server_->set_tick_function(tick_interval_, tick_function_);
ssl_server_->signal_clear();
for (auto snum : signals_)
{
ssl_server_->signal_add(snum);
}
notify_server_start();
ssl_server_->run();
}

View File

@ -508,13 +508,24 @@ namespace crow
void do_write_static()
{
is_writing = true;
boost::asio::write(adaptor_.socket(), buffers_);
res.do_stream_file(adaptor_);
is_writing = true;
boost::asio::write(adaptor_.socket(), buffers_);
res.end();
res.clear();
buffers_.clear();
if (res.file_info.statResult == 0)
{
std::ifstream is(res.file_info.path.c_str(), std::ios::in | std::ios::binary);
char buf[16384];
while (is.read(buf, sizeof(buf)).gcount() > 0)
{
std::vector<asio::const_buffer> buffers;
buffers.push_back(boost::asio::buffer(buf));
do_write_sync(buffers);
}
}
res.end();
res.clear();
buffers_.clear();
}
void do_write_general()
@ -536,8 +547,30 @@ namespace crow
else
{
is_writing = true;
boost::asio::write(adaptor_.socket(), buffers_);
res.do_stream_body(adaptor_);
boost::asio::write(adaptor_.socket(), buffers_); // Write the response start / headers
if (res.body.length() > 0)
{
std::string buf;
std::vector<asio::const_buffer> buffers;
while (res.body.length() > 16384)
{
//buf.reserve(16385);
buf = res.body.substr(0, 16384);
res.body = res.body.substr(16384);
buffers.clear();
buffers.push_back(boost::asio::buffer(buf));
do_write_sync(buffers);
}
// Collect whatever is left (less than 16KB) and send it down the socket
// buf.reserve(is.length());
buf = res.body;
res.body.clear();
buffers.clear();
buffers.push_back(boost::asio::buffer(buf));
do_write_sync(buffers);
}
res.end();
res.clear();
@ -621,6 +654,31 @@ namespace crow
});
}
inline void do_write_sync(std::vector<asio::const_buffer>& buffers)
{
boost::asio::write(adaptor_.socket(), buffers, [&](std::error_code ec, std::size_t) {
if (!ec)
{
if (close_connection_)
{
adaptor_.shutdown_write();
adaptor_.close();
CROW_LOG_DEBUG << this << " from write (sync)(1)";
check_destroy();
}
return false;
}
else
{
CROW_LOG_ERROR << ec << " - happened while sending buffers";
CROW_LOG_DEBUG << this << " from write (sync)(2)";
check_destroy();
return true;
}
});
}
void check_destroy()
{
CROW_LOG_DEBUG << this << " is_reading " << is_reading << " is_writing " << is_writing;

View File

@ -197,6 +197,7 @@ namespace crow
///Return a static file as the response body
void set_static_file_info(std::string path){
utility::sanitize_filename(path);
file_info.path = path;
file_info.statResult = stat(file_info.path.c_str(), &file_info.statbuf);
#ifdef CROW_ENABLE_COMPRESSION
@ -225,91 +226,10 @@ namespace crow
}
}
/// Stream a static file.
template<typename Adaptor>
void do_stream_file(Adaptor& adaptor)
{
if (file_info.statResult == 0)
{
std::ifstream is(file_info.path.c_str(), std::ios::in | std::ios::binary);
write_streamed(is, adaptor);
}
}
/// Stream the response body (send the body in chunks).
template<typename Adaptor>
void do_stream_body(Adaptor& adaptor)
{
if (body.length() > 0)
{
write_streamed_string(body, adaptor);
}
}
private:
bool completed_{};
std::function<void()> complete_request_handler_;
std::function<bool()> is_alive_helper_;
static_file_info file_info;
template<typename Stream, typename Adaptor>
void write_streamed(Stream& is, Adaptor& adaptor)
{
char buf[16384];
while (is.read(buf, sizeof(buf)).gcount() > 0)
{
std::vector<asio::const_buffer> buffers;
buffers.push_back(boost::asio::buffer(buf));
write_buffer_list(buffers, adaptor);
}
}
//THIS METHOD DOES MODIFY THE BODY, AS IN IT EMPTIES IT
template<typename Adaptor>
void write_streamed_string(std::string& is, Adaptor& adaptor)
{
std::string buf;
std::vector<asio::const_buffer> buffers;
while (is.length() > 16384)
{
//buf.reserve(16385);
buf = is.substr(0, 16384);
is = is.substr(16384);
push_and_write(buffers, buf, adaptor);
}
//Collect whatever is left (less than 16KB) and send it down the socket
//buf.reserve(is.length());
buf = is;
is.clear();
push_and_write(buffers, buf, adaptor);
}
template<typename Adaptor>
inline void push_and_write(std::vector<asio::const_buffer>& buffers, std::string& buf, Adaptor& adaptor)
{
buffers.clear();
buffers.push_back(boost::asio::buffer(buf));
write_buffer_list(buffers, adaptor);
}
template<typename Adaptor>
inline void write_buffer_list(std::vector<asio::const_buffer>& buffers, Adaptor& adaptor)
{
boost::asio::write(adaptor.socket(), buffers, [this](std::error_code ec, std::size_t)
{
if (!ec)
{
return false;
}
else
{
CROW_LOG_ERROR << ec << " - happened while sending buffers";
this->end();
return true;
}
});
}
};
}

View File

@ -28,7 +28,7 @@ namespace crow
public:
Server(Handler* handler, std::string bindaddr, uint16_t port, std::string server_name = "Crow/0.3", std::tuple<Middlewares...>* middlewares = nullptr, uint16_t concurrency = 1, typename Adaptor::context* adaptor_ctx = nullptr)
: acceptor_(io_service_, tcp::endpoint(boost::asio::ip::address::from_string(bindaddr), port)),
signals_(io_service_, SIGINT, SIGTERM),
signals_(io_service_),
tick_timer_(io_service_),
handler_(handler),
concurrency_(concurrency == 0 ? 1 : concurrency),

View File

@ -53,7 +53,7 @@ namespace crow
case '\r': ret += "\\r"; break;
case '\t': ret += "\\t"; break;
default:
if (c < 0x20)
if (c >= 0 && c < 0x20)
{
ret += "\\u00";
auto to_hex = [](char c)

View File

@ -6,6 +6,8 @@
#include <functional>
#include "crow/json.h"
#include "crow/logging.h"
#include "crow/utility.h"
namespace crow
{
namespace mustache
@ -144,6 +146,8 @@ namespace crow
case '"': out += "&quot;"; break;
case '\'': out += "&#39;"; break;
case '/': out += "&#x2F;"; break;
case '`': out += "&#x60"; break;
case '=': out += "&#x3D"; break;
default: out += *it; break;
}
}
@ -596,7 +600,9 @@ namespace crow
inline template_t load(const std::string& filename)
{
return compile(detail::get_loader_ref()(filename));
std::string filename_sanitized(filename);
utility::sanitize_filename(filename_sanitized);
return compile(detail::get_loader_ref()(filename_sanitized));
}
}
}

View File

@ -8,6 +8,8 @@
#include <functional>
#include <string>
#include <boost/algorithm/string.hpp>
#include "crow/settings.h"
namespace crow
@ -544,6 +546,128 @@ template <typename F, typename Set>
return base64encode(data, size, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_");
}
inline static void sanitize_filename(std::string& data, char replacement = '_')
{
unsigned char i = 0, length_limit;
length_limit = data.length() < 255 ? data.length() : 255;
data = data.substr(0, length_limit);
for (; i < length_limit; i++)
{
switch ((unsigned char)data[i])
{
// WARNING While I can't see how using '\' or '/' would cause a problem, it still warrants an investigation
//case '/':
case '?':
case '<':
case '>':
//case '\\':
case ':':
case '*':
case '|':
case '\"':
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x07:
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f:
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x14:
case 0x15:
case 0x16:
case 0x17:
case 0x18:
case 0x19:
case 0x1a:
case 0x1b:
case 0x1c:
case 0x1d:
case 0x1e:
case 0x1f:
case 0x80:
case 0x81:
case 0x82:
case 0x83:
case 0x84:
case 0x85:
case 0x86:
case 0x87:
case 0x88:
case 0x89:
case 0x8a:
case 0x8b:
case 0x8c:
case 0x8d:
case 0x8e:
case 0x8f:
case 0x90:
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
case 0x98:
case 0x99:
case 0x9a:
case 0x9b:
case 0x9c:
case 0x9d:
case 0x9e:
case 0x9f:
data[i] = replacement;
break;
default:
break;
}
}
std::string str_replacement(1, replacement);
boost::ireplace_all(data, "..", str_replacement);
boost::ireplace_all(data, "CON", str_replacement);
boost::ireplace_all(data, "PRN", str_replacement);
boost::ireplace_all(data, "AUX", str_replacement);
boost::ireplace_all(data, "NUL", str_replacement);
boost::ireplace_all(data, "COM1", str_replacement);
boost::ireplace_all(data, "COM2", str_replacement);
boost::ireplace_all(data, "COM3", str_replacement);
boost::ireplace_all(data, "COM4", str_replacement);
boost::ireplace_all(data, "COM5", str_replacement);
boost::ireplace_all(data, "COM6", str_replacement);
boost::ireplace_all(data, "COM7", str_replacement);
boost::ireplace_all(data, "COM8", str_replacement);
boost::ireplace_all(data, "COM9", str_replacement);
boost::ireplace_all(data, "LPT1", str_replacement);
boost::ireplace_all(data, "LPT2", str_replacement);
boost::ireplace_all(data, "LPT3", str_replacement);
boost::ireplace_all(data, "LPT4", str_replacement);
boost::ireplace_all(data, "LPT5", str_replacement);
boost::ireplace_all(data, "LPT6", str_replacement);
boost::ireplace_all(data, "LPT7", str_replacement);
boost::ireplace_all(data, "LPT8", str_replacement);
boost::ireplace_all(data, "LPT9", str_replacement);
}
} // namespace utility
}