123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- #include "httpserver.h"
- #include "../tunnelconstructor.h"
- #include "../memorymanagment.h"
- #include "crow/mustache.h"
- #include "../htmldata.h"
- #include "../tunnelconstructor.h"
- #include "../versionnumber.h"
- HttpServer::HttpServer(const std::string &address, uint16_t port) : address_(address), port_(port)
- {
- app_.loglevel(crow::LogLevel::Critical);
- setup();
- }
- void HttpServer::run()
- {
- app_.bindaddr(address_).port(port_).multithreaded().run();
- }
- void HttpServer::setup()
- {
- CROW_CATCHALL_ROUTE(app_)
- ([](crow::response& res) {
- if (res.code == 404)
- {
- res.body = "The URL does not seem to be correct.";
- }
- else if (res.code == 405)
- {
- res.body = "The HTTP method does not seem to be correct.";
- }
- res.end();
- });
- CROW_ROUTE(app_, "/generate/html")([&](const crow::request& req, crow::response& res){
- res.set_header("Content-Type", "text/html");
- const auto language = lang(req);
- auto constructor = initTunnelConstructorViaUrlQuery(req, language);
- if (constructor.second == false)
- {
- res.code = 400;
- res.write( errorPage(reinterpret_cast<const char*>(constructor.first.errorString().c_str()), language, query(req)));
- res.end();
- return;
- }
- const auto text = configPage( reinterpret_cast<const char*>(constructor.first.generate().c_str()) , language, constructor.first.isCommentsEnabled(), query(req));
- res.write(text);
- res.end();
- });
- CROW_ROUTE(app_, "/favicon.png")([&](const crow::request& req, crow::response& res){
- res.set_header("Content-Type", "image/png");
- res.add_header("Content-Length", std::to_string(sizeof(faviconB64)));
- res.write(std::string(reinterpret_cast<const char*>(faviconB64), sizeof(faviconB64)));
- res.end();
- });
- CROW_ROUTE(app_, "/")([&](const crow::request& req, crow::response& res){
- res.set_header("Content-Type", "text/html");
- const auto language = lang(req);
- const auto text = mainPage(language);
- res.write(text);
- res.end();
- });
- }
- Notepad::Lang HttpServer::lang(const crow::request &req)
- {
- const auto lang = req.url_params.get("lang");
- if (lang)
- {
- auto& ctx = app_.get_context<crow::CookieParser>(req);
- ctx.set_cookie("lang", lang).path("/").max_age(60*60*24).httponly();
- return Notepad::stringToLang(lang);
- }
- auto& ctxCookie = app_.get_context<crow::CookieParser>(req);
- const std::string langFromCookie = ctxCookie.get_cookie("lang");
- if (langFromCookie.empty())
- {
- auto& ctxFromHeader = app_.get_context<LanguageHandler>(req);
- return ctxFromHeader.lang;
- }
- return langFromCookie == "en" ? Notepad::Lang::en : Notepad::Lang::ru;
- }
- std::pair<TunnelConstructor, bool> HttpServer::initTunnelConstructorViaUrlQuery(const crow::request &req, Notepad::Lang lang)
- {
- TunnelConstructor constructor;
- constructor.setLang(lang);
- bool comments = false;
- int8_t inbound_length = 3;
- int8_t outbound_length = 3;
- int8_t inbound_quantity = 5;
- int8_t outbound_quantity = 5;
- int8_t inbound_lengthVariance = 0;
- int8_t outbound_lengthVariance = 0;
- int8_t keepalive = 0;
- for (const auto& key: req.url_params.keys())
- {
- if (key == "name" and not constructor.setName(req.url_params.get("name")))
- {
- return { constructor, false };
- }
- else if (key == "type" and not constructor.setTunnelType( TunnelConstructor::stringToTunnelType(req.url_params.get("type")) ))
- {
- return { constructor, false };
- }
- else if (key == "inbound.length")
- {
- try { inbound_length = std::stoi(req.url_params.get("inbound.length")); } catch (...) { }
- }
- else if (key == "outbound.length")
- {
- try { outbound_length = std::stoi(req.url_params.get("outbound.length")); } catch (...) { }
- }
- else if (key == "inbound.quntity")
- {
- try { inbound_quantity = std::stoi(req.url_params.get("inbound.quntity")); } catch (...) { }
- }
- else if (key == "outbound.quntity")
- {
- try { outbound_quantity = std::stoi(req.url_params.get("outbound.quntity")); } catch (...) { }
- }
- else if (key == "inbound.lengthVariance")
- {
- try { inbound_lengthVariance = std::stoi(req.url_params.get("inbound.lengthVariance")); } catch (...) { }
- }
- else if (key == "outbound.lengthVariance")
- {
- try { outbound_lengthVariance = std::stoi(req.url_params.get("outbound.lengthVariance")); } catch (...) { }
- }
- else if (key == "blinded" and not constructor.setBlindedLeaseSet(std::string(req.url_params.get("blinded")) == "true"))
- {
- return { constructor, false };
- }
- else if (key == "transient" and not constructor.setTransient(std::string(req.url_params.get("transient")) == "true"))
- {
- return { constructor, false };
- }
- else if (key == "comments")
- {
- comments = std::string(req.url_params.get("comments")) == "true";
- }
- else if (key == "keepalive")
- {
- try { keepalive = std::stoi(req.url_params.get("keepalive")); } catch (...) { }
- }
- }
- if (not constructor.setComments(comments))
- {
- return { constructor, false };
- }
- if (not constructor.setLength(inbound_length, outbound_length))
- {
- return { constructor, false };
- }
- if (not constructor.setQuantity(inbound_quantity, outbound_quantity))
- {
- return { constructor, false };
- }
- if (not constructor.setLengthVariance(inbound_lengthVariance, outbound_lengthVariance))
- {
- return { constructor, false };
- }
- if (not constructor.setKeepAlive(keepalive))
- {
- return { constructor, false };
- }
- return { constructor, true };
- }
- std::string HttpServer::query(const crow::request &req)
- {
- std::string q;
- for (const auto& key: req.url_params.keys())
- {
- if (key == "lang") continue;
- if (q.empty())
- {
- q = "?";
- }
- else
- {
- q += "&";
- }
- q += key + "=" + req.url_params.get(key);
- }
- return q;
- }
- std::string HttpServer::configPage(const std::string& generated, Notepad::Lang lang, bool comments, const std::string& query)
- {
- crow::mustache::context ctx;
- ctx["lang_code"] = Notepad::langToCode(lang);
- ctx["tagline"] = reinterpret_cast<const char*>(Notepad::WebUi::tagline(lang));
- ctx["payload"] = generated;
- ctx["go_back"] = reinterpret_cast<const char*>(Notepad::WebUi::configGoBack(lang));
- ctx["url"] = query;
- ctx["version"] = VERSION;
- static const auto templ = crow::mustache::compile(HTML_CONFIG_PAGE);
- std::string pageWithoutCommentsHighlight = templ.render_string(ctx);
- if (! comments) return pageWithoutCommentsHighlight;
- std::istringstream stream(pageWithoutCommentsHighlight);
- std::string buffer;
- std::string result;
- while (std::getline(stream, buffer))
- {
- if (!buffer.empty() && buffer[0] == '#')
- {
- buffer = "<span class=\"code-block-comment\">" + buffer + "</span>";
- }
- result += buffer + "\n";
- }
- return result;
- }
- std::string HttpServer::errorPage(const std::string &text, Notepad::Lang lang, const std::string& query)
- {
- crow::mustache::context ctx;
- ctx["lang_code"] = Notepad::langToCode(lang);
- ctx["tagline"] = reinterpret_cast<const char*>(Notepad::WebUi::tagline(lang));
- ctx["text"] = text;
- ctx["go_back"] = reinterpret_cast<const char*>(Notepad::WebUi::configGoBack(lang));
- ctx["url"] = query;
- ctx["version"] = VERSION;
- static const auto templ = crow::mustache::compile(HTML_ERROR_PAGE);
- return templ.render_string(ctx);
- }
- std::string HttpServer::mainPage(Notepad::Lang lang)
- {
- static std::map<Notepad::Lang, std::string> map;
- auto iter = map.find(lang);
- if (iter != map.end())
- {
- return iter->second;
- }
- crow::mustache::context ctx;
- ctx["lang_code"] = Notepad::langToCode(lang);
- ctx["tagline"] = reinterpret_cast<const char*>(Notepad::WebUi::tagline(lang));
- ctx["th_option"] = reinterpret_cast<const char*>(Notepad::WebUi::mainThOption(lang));
- ctx["th_value"] = reinterpret_cast<const char*>(Notepad::WebUi::mainThInput(lang));
- ctx["tunnel_name"] = reinterpret_cast<const char*>(Notepad::WebUi::mainTunnelName(lang));
- ctx["tunnel_name_p"] = reinterpret_cast<const char*>(Notepad::WebUi::mainTunnelName(lang));
- ctx["tunnel_type"] = reinterpret_cast<const char*>(Notepad::WebUi::mainTunnelType(lang));
- ctx["client_tcp"] = reinterpret_cast<const char*>(Notepad::WebUi::mainDropdownClientTCP(lang));
- ctx["client_udp"] = reinterpret_cast<const char*>(Notepad::WebUi::mainDropdownClientUDP(lang));
- ctx["server_tcp"] = reinterpret_cast<const char*>(Notepad::WebUi::mainDropdownServerTCP(lang));
- ctx["server_udp"] = reinterpret_cast<const char*>(Notepad::WebUi::mainDropdownServerUDP(lang));
- ctx["server_http"] = reinterpret_cast<const char*>(Notepad::WebUi::mainDropdownServerHTTP(lang));
- ctx["server_irc"] = reinterpret_cast<const char*>(Notepad::WebUi::mainDropdownServerIRC(lang));
- ctx["socks_proxy"] = reinterpret_cast<const char*>(Notepad::WebUi::mainDropdownSOCKSProxy(lang));
- ctx["http_proxy"] = reinterpret_cast<const char*>(Notepad::WebUi::mainDropdownHTTPProxy(lang));
- ctx["inbound"] = reinterpret_cast<const char*>(Notepad::WebUi::mainInbound(lang));
- ctx["outbound"] = reinterpret_cast<const char*>(Notepad::WebUi::mainOutbound(lang));
- ctx["length"] = reinterpret_cast<const char*>(Notepad::WebUi::mainLength(lang));
- ctx["quantity"] = reinterpret_cast<const char*>(Notepad::WebUi::mainQuantity(lang));
- ctx["variance"] = reinterpret_cast<const char*>(Notepad::WebUi::mainVariance(lang));
- ctx["b33"] = reinterpret_cast<const char*>(Notepad::WebUi::mainB33(lang));
- ctx["transient"] = reinterpret_cast<const char*>(Notepad::WebUi::mainTransient(lang));
- ctx["keepalive"] = reinterpret_cast<const char*>(Notepad::WebUi::mainKeepalive(lang));
- ctx["comments"] = reinterpret_cast<const char*>(Notepad::WebUi::mainComments(lang));
- ctx["generate"] = reinterpret_cast<const char*>(Notepad::WebUi::mainGenerate(lang));
- ctx["version"] = VERSION;
- const auto templ = crow::mustache::compile(HTML_MAIN_PAGE);
- map[lang] = templ.render_string(ctx);
- return map[lang];
- }
|