比较提交

5 次代码提交

作者 SHA1 备注 提交日期
70f7289c8c More checks for printable asciis 2025-11-03 20:46:12 +01:00
d0de7b8f3b utils:catv() when printing exception 2025-11-03 20:08:48 +01:00
f0f5846a4a gateway: httpgateway: Add exception handler
Something at some point changed so this becomes necessar
2025-11-03 20:07:54 +01:00
e90b08dbde logger.h: Use utils::catv()
Who knows, clever people are everywhere
2025-11-03 20:00:34 +01:00
ffa59d4b36 utils: Introduce catv() 2025-11-03 19:59:26 +01:00
修改 5 个文件,包含 87 行新增3 行删除

查看文件

@@ -20,6 +20,7 @@ SOFTWARE.
*/ */
#include "httpgateway.h" #include "httpgateway.h"
#include "../logger.h" #include "../logger.h"
#include <stdexcept>
HttpGateway::HttpGateway(std::string listenaddr, int port, uint64_t maxPayloadLength) HttpGateway::HttpGateway(std::string listenaddr, int port, uint64_t maxPayloadLength)
{ {
this->listenaddr = listenaddr; this->listenaddr = listenaddr;
@@ -34,6 +35,11 @@ bool HttpGateway::keepReading()
Request HttpGateway::convertRequest(httplib::Request request) Request HttpGateway::convertRequest(httplib::Request request)
{ {
if(!utils::is_printable_ascii(request.target))
{
throw std::runtime_error("Invalid chars in URI: " + utils::catv(request.target));
}
Request result; Request result;
result.setRequestMethod(request.method); result.setRequestMethod(request.method);
result.setUrl(request.target); result.setUrl(request.target);
@@ -55,6 +61,12 @@ Request HttpGateway::convertRequest(httplib::Request request)
if(request.has_header("COOKIE")) if(request.has_header("COOKIE"))
{ {
std::string cookie = request.get_header_value("COOKIE");
if(!utils::is_printable_ascii(cookie))
{
/* We better bail */
throw std::runtime_error("Cookie with non printable chars sent");
}
result.initCookies(request.get_header_value("COOKIE")); result.initCookies(request.get_header_value("COOKIE"));
} }
result.setIp("127.0.0.1"); result.setIp("127.0.0.1");
@@ -82,6 +94,27 @@ httplib::Response HttpGateway::convertResponse(Response response)
void HttpGateway::work(RequestWorker &worker) void HttpGateway::work(RequestWorker &worker)
{ {
httplib::Server server; httplib::Server server;
server.set_exception_handler([](const httplib::Request& req, httplib::Response& res, std::exception_ptr ep) {
auto fmt = "<h1>Error 500</h1><p>%s</p>";
char buf[BUFSIZ];
try
{
std::rethrow_exception(ep);
}
catch (std::exception &e)
{
std::string exception = utils::html_xss(e.what());
snprintf(buf, sizeof(buf), fmt, exception.c_str());
Logger::error() << "Exception caught in Httpgateway::work():" << utils::html_xss(utils::catv(e.what()));
}
catch (...)
{
snprintf(buf, sizeof(buf), fmt, "Unknown Exception");
Logger::error() << "Unknown exception caught in Httpgateway::work()";
}
res.set_content(buf, "text/html");
res.status = 500;
});
server.set_payload_max_length(this->maxPayloadLength); server.set_payload_max_length(this->maxPayloadLength);
auto handler = [&](const httplib::Request &req, httplib::Response &res) auto handler = [&](const httplib::Request &req, httplib::Response &res)
{ {
@@ -94,4 +127,5 @@ void HttpGateway::work(RequestWorker &worker)
server.Get("/(.*)", handler); server.Get("/(.*)", handler);
server.Post("/(.*)", handler); server.Post("/(.*)", handler);
server.listen(this->listenaddr.c_str(), this->listenport); server.listen(this->listenaddr.c_str(), this->listenport);
} }

查看文件

@@ -2,6 +2,7 @@
#define LOGGER_H #define LOGGER_H
#include <iostream> #include <iostream>
#include <chrono> #include <chrono>
#include "utils.h"
class Logger class Logger
{ {
private: private:
@@ -24,7 +25,15 @@ class Logger
{ {
(*out) << time(0) << " " << prefix; (*out) << time(0) << " " << prefix;
} }
(*out) << val;
if constexpr (std::is_convertible_v<T, std::string_view>)
{
(*out) << utils::catv(val);
}
else
{
(*out) << val;
}
headerSent = true; headerSent = true;
return *this; // or maybe out itself? probably not. return *this; // or maybe out itself? probably not.
} }

查看文件

@@ -230,8 +230,8 @@ int main(int argc, char **argv)
} }
catch(const std::exception &e) catch(const std::exception &e)
{ {
Logger::error() << e.what(); Logger::error() << utils::catv(e.what());
std::cerr << e.what() << std::endl; std::cerr << utils::catv(e.what()) << std::endl;
} }
return 0; return 0;
} }

查看文件

@@ -214,3 +214,40 @@ std::string utils::trim(std::string_view view)
} }
return std::string{view}; return std::string{view};
} }
std::string utils::catv(std::string_view view)
{
std::string result;
result.reserve(view.length());
for(auto c : view)
{
if (!isascii(c))
{
result += "M-";
result += toascii(c);
}
else if(iscntrl(c))
{
result += '^';
result += c == '\177' ? '?': c | 0100;
}
else
{
result += c;
}
}
return result;
}
bool utils::is_printable_ascii(std::string view)
{
for(char c : view)
{
if( !(c >= ' ' && c <= '~'))
{
return false;
}
}
return true;
}

查看文件

@@ -91,6 +91,10 @@ template <class T> inline std::string toString(const T &v)
} }
std::string trim(std::string_view view); std::string trim(std::string_view view);
std::string catv(std::string_view view);
bool is_printable_ascii(std::string view);
} // namespace utils } // namespace utils
#endif #endif