diff options
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | config.cpp | 102 | ||||
-rw-r--r-- | config.h | 40 | ||||
-rw-r--r-- | webserver.conf | 13 |
4 files changed, 149 insertions, 9 deletions
@@ -1,6 +1,3 @@ Plugin: https://www.boost.org/doc/libs/1_72_0/doc/html/boost_dll/tutorial.html#boost_dll.tutorial.symbol_shadowing_problem__linux_ HTTP+HTTPS: https://www.boost.org/doc/libs/1_72_0/libs/beast/doc/html/beast/examples.html#beast.examples.servers -Config: https://www.boost.org/doc/libs/1_72_0/doc/html/property_tree/tutorial.html Certbot: https://certbot.eff.org/lets-encrypt/debianbuster-other - -Configfile configurable @@ -3,7 +3,10 @@ #include <boost/property_tree/ptree.hpp> #include <boost/property_tree/xml_parser.hpp> +#include <iostream> + namespace pt = boost::property_tree; +using namespace std::string_literals; void Config::readConfigfile(std::string filename) { @@ -13,15 +16,80 @@ void Config::readConfigfile(std::string filename) pt::ptree tree; - pt::read_xml(filename, tree); + pt::read_xml(filename, tree, pt::xml_parser::no_comments | pt::xml_parser::trim_whitespace); + // mandatory m_user = tree.get<std::string>("webserver.user"); - m_group = tree.get<std::string>("webserver.group1"); + m_group = tree.get<std::string>("webserver.group"); + + // optional entries + auto elements = tree.get_child_optional("webserver"); + if (elements) { + for (const auto& element: *elements) { + if (element.first == "plugin-directory"s) { + m_plugin_directories.push_back(element.second.data()); + } else if (element.first == "sites"s) { + for (const auto& site: element.second) { + if (site.first != "site"s) + throw std::runtime_error("<site> expected in <sites>"); + Site site_struct; + for (const auto& x: site.second) { + if (x.first == "name"s) { + site_struct.name = x.second.data(); + } else if (x.first == "host"s) { + site_struct.host = x.second.data(); + } else if (x.first == "path"s) { + Path path; + auto attrs = x.second.get_child("<xmlattr>"); + path.requested = attrs.get<std::string>("requested"); + std::string type = attrs.get<std::string>("type"); + if (type == "files") { + path.type = Files; + } else if (type == "plugin") { + path.type = Plugin; + } else + throw std::runtime_error("Unknown type: "s + type); + for (const auto& param: x.second) { + if (param.first.size() > 0 && param.first[0] != '<') // exclude meta-elements like <xmlattr> + path.params[param.first.data()] = param.second.data(); + } + site_struct.paths.push_back(path); + } else + throw std::runtime_error("Unknown element: "s + x.first); + } + m_sites.push_back(site_struct); + } + } else if (element.first == "sockets"s) { + for (const auto& socket: element.second) { + if (socket.first != "socket"s) + throw std::runtime_error("<socket> expected in <sockets>"); + Socket socket_struct; + for (const auto& x: socket.second) { + if (x.first == "address"s) { + socket_struct.address = x.second.data(); + } else if (x.first == "port"s) { + socket_struct.port = x.second.data(); + } else if (x.first == "protocol"s) { + if (x.second.data() == "http"s) + socket_struct.protocol = HTTP; + else if (x.second.data() == "https"s) + socket_struct.protocol = HTTPS; + else + throw std::runtime_error("Unknown protocol: "s + x.second.data()); + } else + throw std::runtime_error("Unknown element: "s + x.first); + } + m_sockets.push_back(socket_struct); + } + } + } + } } Config::Config(const std::string& filename) { readConfigfile(filename); + dump(); } std::string Config::User() const @@ -33,3 +101,33 @@ std::string Config::Group() const { return m_group; } + +void Config::dump() const +{ + std::cout << "=== Configuration ===========================" << std::endl; + std::cout << "User: " << m_user << std::endl; + std::cout << "Group: " << m_user << std::endl; + + std::cout << "Plugin Directories:"; + for (const auto& dir: m_plugin_directories) + std::cout << " " << dir; + std::cout << std::endl; + + for (const auto& site: m_sites) { + std::cout << "Site: " << site.name << ": " << site.host << std::endl; + if (site.paths.size() == 0) + std::cout << " Warning: No paths configured." << std::endl; + for (const auto& path: site.paths) { + std::cout << " Path: " << path.requested << " -> " << ((path.type == Files) ? "files" : "plugin") << std::endl; + for (const auto& param: path.params) { + std::cout << " " << param.first << ": " << param.second << std::endl; + } + } + } + + for (const auto& socket: m_sockets) { + std::cout << "Socket: " << socket.address << ":" << socket.port << " (" << (socket.protocol == HTTP ? "HTTP" : "HTTPS") << ")" << std::endl; + } + std::cout << "=============================================" << std::endl; +} + @@ -1,6 +1,41 @@ #pragma once #include <string> +#include <unordered_map> +#include <vector> + +enum PathType +{ + Files, // serve files + Plugin // delegate to plugin +}; + +struct Path +{ + std::string requested; // the requested path + PathType type; + std::unordered_map<std::string, std::string> params; // what to serve, e.g. which filesystem path, or which plugin +}; + +struct Site +{ + std::string name; + std::string host; + std::vector<Path> paths; +}; + +enum SocketProtocol +{ + HTTP, + HTTPS +}; + +struct Socket +{ + std::string address; + std::string port; + SocketProtocol protocol; +}; class Config { @@ -10,6 +45,9 @@ class Config std::string m_user; std::string m_group; + std::vector<std::string> m_plugin_directories; + std::vector<Site> m_sites; + std::vector<Socket> m_sockets; public: Config(const std::string& filename); @@ -17,5 +55,7 @@ class Config // Data getters std::string User() const; std::string Group() const; + + void dump() const; }; diff --git a/webserver.conf b/webserver.conf index c3580c8..42bc383 100644 --- a/webserver.conf +++ b/webserver.conf @@ -1,14 +1,19 @@ <webserver> - <user>www-data<user> + <user>www-data</user> <group>www-data</group> - <plugin-directory>/usr/lib/webserver/plugins</plugin-directory> + <plugin-directory><a c="d">b<e>f</e></a>/usr/lib/webserver/plugins</plugin-directory> <plugin-directory>/usr/local/lib/webserver/plugins</plugin-directory> <sites> <site> <name>antcom.de</name> <host>antcom.de</host> - <path requested="/" type="files">/var/www/antcom.de</path> - <path requested="/webbox" type="plugin">webbox</path> + <path requested="/" type="files"> + <target>/var/www/antcom.de</target> + </path> + <path requested="/webbox" type="plugin"> + <plugin>webbox</plugin> + <target>/var/lib/webbox</target> + </path> </site> <!-- <site> |