mirror of https://github.com/CrowCpp/Crow.git
parent
a166a6d3cb
commit
87adb19e43
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 += """; break;
|
||||
case '\'': out += "'"; break;
|
||||
case '/': out += "/"; break;
|
||||
case '`': out += "`"; break;
|
||||
case '=': out += "="; 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue