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>  | 
