summaryrefslogtreecommitdiffhomepage
path: root/plugins/weblog/weblog.cpp
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2020-04-19 19:46:14 +0200
committerRoland Reichwein <mail@reichwein.it>2020-04-19 19:46:14 +0200
commit8b93572b386256c53c12012be87adabd73d80520 (patch)
treeaee710ea38d6b7487f49d191c5c63b3306ee6950 /plugins/weblog/weblog.cpp
parente093da01dcefac72502b4fa0c8375760cf98934e (diff)
Weblog (WIP)
Diffstat (limited to 'plugins/weblog/weblog.cpp')
-rw-r--r--plugins/weblog/weblog.cpp121
1 files changed, 119 insertions, 2 deletions
diff --git a/plugins/weblog/weblog.cpp b/plugins/weblog/weblog.cpp
index ef90a53..1c58b73 100644
--- a/plugins/weblog/weblog.cpp
+++ b/plugins/weblog/weblog.cpp
@@ -1,8 +1,90 @@
#include "weblog.h"
+#include <boost/algorithm/string/predicate.hpp>
+
+#include <filesystem>
+#include <fstream>
#include <iostream>
+#include <string>
using namespace std::string_literals;
+namespace fs = std::filesystem;
+
+namespace {
+
+// Return a reasonable mime type based on the extension of a file.
+std::string
+mime_type(fs::path path)
+{
+ using boost::algorithm::iequals;
+ auto const ext = [&path]
+ {
+ size_t pos = path.string().rfind(".");
+ if (pos == std::string::npos)
+ return std::string{};
+ return path.string().substr(pos);
+ }();
+ if(iequals(ext, ".htm")) return "text/html"; // TODO: unordered_map
+ if(iequals(ext, ".html")) return "text/html";
+ if(iequals(ext, ".php")) return "text/html";
+ if(iequals(ext, ".css")) return "text/css";
+ if(iequals(ext, ".txt")) return "text/plain";
+ if(iequals(ext, ".js")) return "application/javascript";
+ if(iequals(ext, ".json")) return "application/json";
+ if(iequals(ext, ".xml")) return "application/xml";
+ if(iequals(ext, ".swf")) return "application/x-shockwave-flash";
+ if(iequals(ext, ".flv")) return "video/x-flv";
+ if(iequals(ext, ".png")) return "image/png";
+ if(iequals(ext, ".jpe")) return "image/jpeg";
+ if(iequals(ext, ".jpeg")) return "image/jpeg";
+ if(iequals(ext, ".jpg")) return "image/jpeg";
+ if(iequals(ext, ".gif")) return "image/gif";
+ if(iequals(ext, ".bmp")) return "image/bmp";
+ if(iequals(ext, ".ico")) return "image/vnd.microsoft.icon";
+ if(iequals(ext, ".tiff")) return "image/tiff";
+ if(iequals(ext, ".tif")) return "image/tiff";
+ if(iequals(ext, ".svg")) return "image/svg+xml";
+ if(iequals(ext, ".svgz")) return "image/svg+xml";
+ return "application/text";
+}
+
+std::string getFile(const fs::path& filename)
+{
+ std::ifstream file(filename.string(), std::ios::in | std::ios::binary | std::ios::ate);
+
+ if (file.is_open()) {
+ std::ifstream::pos_type fileSize = file.tellg();
+ file.seekg(0, std::ios::beg);
+
+ std::string bytes(fileSize, ' ');
+ file.read(reinterpret_cast<char*>(bytes.data()), fileSize);
+
+ return bytes;
+
+ } else {
+ throw std::runtime_error("Opening "s + filename.string() + " for reading");
+ }
+}
+
+bool is_index_page(std::string& path)
+{
+ return (path.size() == 0 || path.back() == '/');
+}
+
+std::string generateIndexPage(std::function<plugin_interface_setter_type>& SetResponseHeader)
+{
+ return "<html><body><h1>Blog</h1></body></html>";
+}
+
+// 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;
+}
+
+}
std::string weblog_plugin::name()
{
@@ -19,8 +101,43 @@ weblog_plugin::~weblog_plugin()
//std::cout << "Plugin destructor" << std::endl;
}
-std::string weblog_plugin::generate_page(std::string path)
+std::string weblog_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
+)
{
- return "Blog "s + path;
+ try {
+ // Make sure we can handle the method
+ std::string method {GetRequestParam("method")};
+ if (method != "GET" && method != "HEAD")
+ return HttpStatus("400", "Unknown HTTP method", SetResponseHeader);
+
+ // Request path must not contain "..".
+ std::string rel_target{GetRequestParam("rel_target")};
+ 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);
+ }
+
+ SetResponseHeader("content_type", "text/html");
+
+ if (is_index_page(rel_target))
+ return generateIndexPage(SetResponseHeader);
+
+ return HttpStatus("404", "Bad path specification: "s + rel_target, SetResponseHeader);
+
+ } catch (const std::exception& ex) {
+ return HttpStatus("500", "Unknown Error: "s + ex.what(), SetResponseHeader);
+ }
}