summaryrefslogtreecommitdiffhomepage
path: root/plugins/statistics/statistics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/statistics/statistics.cpp')
-rw-r--r--plugins/statistics/statistics.cpp97
1 files changed, 97 insertions, 0 deletions
diff --git a/plugins/statistics/statistics.cpp b/plugins/statistics/statistics.cpp
new file mode 100644
index 0000000..03f4c94
--- /dev/null
+++ b/plugins/statistics/statistics.cpp
@@ -0,0 +1,97 @@
+#include "statistics.h"
+
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/coroutine2/coroutine.hpp>
+#include <boost/process.hpp>
+
+#include <algorithm>
+#include <filesystem>
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <unordered_map>
+
+using namespace std::string_literals;
+namespace bp = boost::process;
+namespace fs = std::filesystem;
+
+namespace {
+
+ // Used to return errors by generating response page and HTTP status code
+ std::string HttpStatus(std::string status, std::string message, std::function<plugin_interface_setter_type>& SetResponseHeader)
+ {
+ SetResponseHeader("status", status);
+ SetResponseHeader("content_type", "text/html");
+ return status + " " + message;
+ }
+
+} // anonymous namespace
+
+std::string statistics_plugin::name()
+{
+ return "statistics";
+}
+
+statistics_plugin::statistics_plugin()
+{
+ //std::cout << "Plugin constructor" << std::endl;
+}
+
+statistics_plugin::~statistics_plugin()
+{
+ //std::cout << "Plugin destructor" << std::endl;
+}
+
+std::string statistics_plugin::generate_page(
+ std::function<std::string(const std::string& key)>& GetServerParam,
+ std::function<std::string(const std::string& key)>& GetRequestParam, // request including body (POST...)
+ std::function<void(const std::string& key, const std::string& value)>& SetResponseHeader // to be added to result string
+)
+{
+ try {
+ // Request path must not contain "..".
+ std::string rel_target{GetRequestParam("rel_target")};
+ size_t query_pos{rel_target.find("?")};
+ if (query_pos != rel_target.npos)
+ rel_target = rel_target.substr(0, query_pos);
+
+ std::string target{GetRequestParam("target")};
+ if (rel_target.find("..") != std::string::npos) {
+ return HttpStatus("400", "Illegal request: "s + target, SetResponseHeader);
+ }
+
+ // Build the path to the requested file
+ std::string doc_root{GetRequestParam("doc_root")};
+ fs::path path {fs::path{doc_root} / rel_target};
+ if (target.size() && target.back() != '/' && fs::is_directory(path)) {
+ std::string location{GetRequestParam("location") + "/"s};
+ SetResponseHeader("location", location);
+ return HttpStatus("301", "Correcting directory path", SetResponseHeader);
+ }
+
+ try {
+ SetResponseHeader("content_type", "text/html");
+
+ std::string header {"<!DOCTYPE html><html><head>"
+ "<meta charset=\"utf-8\"/>"
+ "<title>Webserver Statistics</title>"
+ "</head><body>"};
+ std::string footer{"<br/><br/><br/></body></html>"};
+
+ std::string result{header};
+
+ result += "<h1>Webserver Statistics</h1>";
+ result += "<pre>"s + GetServerParam("statistics") + "</pre>"s;
+
+ result += footer;
+
+ return result;
+ } catch (const std::exception& ex) {
+ return HttpStatus("500", "Statistics error: "s + ex.what(), SetResponseHeader);
+ }
+
+ } catch (const std::exception& ex) {
+ return HttpStatus("500", "Unknown Error: "s + ex.what(), SetResponseHeader);
+ }
+}
+