diff options
| author | Roland Reichwein <mail@reichwein.it> | 2020-05-10 18:18:37 +0200 | 
|---|---|---|
| committer | Roland Reichwein <mail@reichwein.it> | 2020-05-10 18:18:37 +0200 | 
| commit | 6c1cc0b2c854dd56dcb6238816a6ce2cb493c71c (patch) | |
| tree | de041dfb3bc12a04fa4defdbd286d098f34adddc /plugins/webbox | |
| parent | 5b32a4415c9776dd6cae859c8d718b5e68f01d81 (diff) | |
Separated out lib
Diffstat (limited to 'plugins/webbox')
| -rw-r--r-- | plugins/webbox/Makefile | 11 | ||||
| -rw-r--r-- | plugins/webbox/webbox.cpp | 164 | 
2 files changed, 76 insertions, 99 deletions
diff --git a/plugins/webbox/Makefile b/plugins/webbox/Makefile index 5ff22f7..1c49fda 100644 --- a/plugins/webbox/Makefile +++ b/plugins/webbox/Makefile @@ -19,7 +19,7 @@ endif  # -fprofile-instr-generate -fcoverage-mapping  # gcc:--coverage -CXXFLAGS+= -Wall -I. +CXXFLAGS+= -Wall -I. -I../..  CXXFLAGS+= -pthread -fvisibility=hidden -fPIC  ifeq ($(CXX),clang++-10) @@ -40,7 +40,8 @@ LIBS=\  -lboost_regex \  -lpthread \  -lssl -lcrypto \ --ldl +-ldl \ +-lcommon  ifeq ($(CXX),clang++-10)  LIBS+= \ @@ -56,6 +57,8 @@ LIBS+= \  -lstdc++fs  endif +LDFLAGS+=-L../../libcommon +  PROGSRC=\      file.cpp \      stringutil.cpp \ @@ -75,8 +78,8 @@ all: $(PROJECTNAME).so  test-$(PROJECTNAME): $(TESTSRC:.cpp=.o)  	$(CXX) $(CXXFLAGS) $^ $(LIBS) -o $@ -$(PROJECTNAME).so: $(SRC:.cpp=.o) -	$(CXX) -shared $(CXXFLAGS) $^ $(LIBS) -o $@ +$(PROJECTNAME).so: ../../libcommon/libcommon.a $(SRC:.cpp=.o) +	$(CXX) -shared $(LDFLAGS) $^ $(LDLIBS) $(LIBS) -o $@  dep: $(TESTSRC:.cpp=.d) diff --git a/plugins/webbox/webbox.cpp b/plugins/webbox/webbox.cpp index c58bd0c..53322b5 100644 --- a/plugins/webbox/webbox.cpp +++ b/plugins/webbox/webbox.cpp @@ -3,6 +3,8 @@  #include "file.h"  #include "stringutil.h" +#include "libcommon/mime.h" +  #include <boost/algorithm/string/predicate.hpp>  #include <boost/algorithm/string/replace.hpp>  #include <boost/algorithm/string/split.hpp> @@ -127,6 +129,9 @@ namespace {     std::function<std::string(const std::string& key)>& m_GetRequestParam; // request including body (POST...)     std::function<void(const std::string& key, const std::string& value)>& m_SetResponseHeader; // to be added to result string +   std::string m_pathInfo; // path inside webbox, derived from request +   fs::path m_path; // local filesystem path +     std::unordered_map<std::string, std::string> paramHash;     std::string webboxPath; @@ -150,14 +155,27 @@ namespace {     {      if (webboxStaticHtml == "")       webboxStaticHtml = STATIC_HTML_DOC_ROOT; +   +    m_pathInfo = urlDecode(GetRequestParam("rel_target")); +    size_t pos {m_pathInfo.find('?')}; +    if (pos != m_pathInfo.npos) { +     m_pathInfo = m_pathInfo.substr(0, pos); +    } + +    if (m_pathInfo.find("..") != m_pathInfo.npos) { +     throw std::runtime_error("Bad path: "s + m_pathInfo); +    } + +    m_path = webboxPath; +    if (!m_pathInfo.empty()) +     m_path /= m_pathInfo;     }   }; - // Used to return errors by generating response page and HTTP status code - std::string HttpStatus(std::string status, std::string message, CommandParameters& commandParameters) + std::string HttpStatus(std::string status, std::string message, std::function<void(const std::string& key, const std::string& value)>& SetResponseHeader)   { -  commandParameters.m_SetResponseHeader("status", status); -  commandParameters.m_SetResponseHeader("content_type", "text/html"); +  SetResponseHeader("status", status); +  SetResponseHeader("content_type", "text/html");    auto it{status_map.find(status)};    std::string description{"(Unknown)"}; @@ -167,6 +185,12 @@ namespace {    return "<html><body><h1>"s + status + " "s + description + "</h1><p>"s + message + "</p></body></html>";   } + // Used to return errors by generating response page and HTTP status code + std::string HttpStatus(std::string status, std::string message, CommandParameters& commandParameters) + { +  return HttpStatus(status, message, commandParameters.m_SetResponseHeader); + } +  } // anonymous namespace  class Command @@ -186,21 +210,6 @@ public:     return HttpStatus("403", "Bad request method", p);    } -  // Set parameters from FastCGI request environment -  m_pathInfo = urlDecode(p.m_GetRequestParam("rel_target")); -  size_t pos {m_pathInfo.find('?')}; -  if (pos != m_pathInfo.npos) { -   m_pathInfo = m_pathInfo.substr(0, pos); -  } - -  if (m_pathInfo.find("..") != m_pathInfo.npos) { -   return HttpStatus("403", "Bad path: "s + m_pathInfo, p); -  } - -  m_path = p.webboxPath; -  if (!m_pathInfo.empty()) -   m_path /= m_pathInfo; -    return this->start(p);   } @@ -220,9 +229,6 @@ protected:   std::string m_requestMethod;   bool m_isWriteCommand; // if true, command must be prevented if p.webboxReadOnly - // calculated during start of execute() - std::string m_pathInfo; // path inside webbox, derived from request - fs::path m_path; // local filesystem path  };  class GetCommand: public Command @@ -306,13 +312,13 @@ protected:    pt::ptree list;    pt::ptree entry; -  if (m_pathInfo != ""s) { // Add ".." if not in top directory of this webbox +  if (p.m_pathInfo != ""s) { // Add ".." if not in top directory of this webbox     entry.put_value("..");     entry.put("<xmlattr>.type", "dir");     list.push_back(pt::ptree::value_type("listentry", entry));    } -  fs::directory_iterator dir(m_path); +  fs::directory_iterator dir(p.m_path);    std::vector<std::string> files;    std::vector<std::string> dirs; @@ -412,7 +418,7 @@ protected:    std::string dirname = tree.get<std::string>("dirname");    try { -   if (fs::create_directory(m_path / dirname)) +   if (fs::create_directory(p.m_path / dirname))      return "Successfully created directory";     else      return "Error creating directory"; @@ -449,7 +455,7 @@ protected:     for (const auto& element: elements) {      if (element.first == "file"s) {       std::string filename{element.second.data()}; -     fs::path path {m_path / filename}; +     fs::path path {p.m_path / filename};       auto filesize {fs::file_size(path)}; @@ -514,7 +520,7 @@ protected:     return HttpStatus("400", "No files found", p);    try { -   fs::current_path(m_path); +   fs::current_path(p.m_path);    } catch (const std::exception& ex) {     return HttpStatus("500", "Change path error: "s + ex.what(), p);    } @@ -566,7 +572,7 @@ protected:      if (element.first == "file"s) {       std::string filename{element.second.data()}; -     fs::path path{m_path / filename}; +     fs::path path{p.m_path / filename};       if (fs::is_directory(path)) {        try { @@ -624,10 +630,10 @@ protected:     auto elements {tree.get_child("request")};     for (const auto& element: elements) {      if (element.first == "target") { -     targetDir = m_path / element.second.data(); +     targetDir = p.m_path / element.second.data();      } else if (element.first == "file") {       std::string filename{element.second.data()}; -     fs::path old_path{m_path / filename}; +     fs::path old_path{p.m_path / filename};       fs::path new_path{targetDir / filename};       try {        fs::rename(old_path, new_path); @@ -674,8 +680,8 @@ protected:    std::string oldname{tree.get<std::string>("request.oldname")};    std::string newname{tree.get<std::string>("request.newname")}; -  fs::path oldpath{m_path / oldname}; -  fs::path newpath{m_path / newname}; +  fs::path oldpath{p.m_path / oldname}; +  fs::path newpath{p.m_path / newname};    try {     fs::rename(oldpath, newpath); @@ -753,7 +759,7 @@ protected:          } else {           filecontent = filecontent.substr(start + "\r\n\r\n"s.size()); -         fs::path path{ m_path / filename}; +         fs::path path{ p.m_path / filename};           try {            File::setFile(path, filecontent);           } catch (const std::exception& ex) { @@ -784,54 +790,18 @@ protected:   virtual std::string start(CommandParameters& p)   {    try { -   std::string result{File::getFile(m_path)}; +   std::string result{File::getFile(p.m_path)}; -   p.m_SetResponseHeader("content_disposition", "attachment; filename=\""s + m_path.filename().string() + "\""s); +   p.m_SetResponseHeader("content_disposition", "attachment; filename=\""s + p.m_path.filename().string() + "\""s);     p.m_SetResponseHeader("content_type", "application/octet-stream");     return result;    } catch (const std::exception& ex) { -   return HttpStatus("404", "Bad file: "s + m_path.filename().string(), p); +   return HttpStatus("404", "Bad file: "s + p.m_path.filename().string(), p);    }   }  }; -// Return a reasonable mime type based on the extension of a file. -static 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"; -} -  class StaticHtmlCommand: public GetCommand  {  public: @@ -846,7 +816,7 @@ protected:   {    // redirect to xyz/ if xyz was requested    std::string target = p.m_GetRequestParam("target"); -  if (m_pathInfo == "" && !target.empty() && target.back() != '/') { +  if (p.m_pathInfo == "" && !target.empty() && target.back() != '/') {     p.m_SetResponseHeader("location", target + "/");     return HttpStatus("301", "Use correct index: /"s, p);    }  @@ -854,20 +824,20 @@ protected:    try {     fs::path file_path; -   if (m_pathInfo == "/" || m_pathInfo == "") { +   if (p.m_pathInfo == "/" || p.m_pathInfo == "") {      file_path = p.webboxStaticHtml / "index.html"; -   } else if (boost::algorithm::starts_with(m_pathInfo, STATIC_HTML_TARGET)) { -    file_path = p.webboxStaticHtml / m_pathInfo.substr(STATIC_HTML_TARGET.size()); +   } else if (boost::algorithm::starts_with(p.m_pathInfo, STATIC_HTML_TARGET)) { +    file_path = p.webboxStaticHtml / p.m_pathInfo.substr(STATIC_HTML_TARGET.size());     } else { -    return HttpStatus("500", "Bad request: "s + m_pathInfo, p); +    return HttpStatus("500", "Bad request: "s + p.m_pathInfo, p);     } -   p.m_SetResponseHeader("content_type", mime_type(file_path)); +   p.m_SetResponseHeader("content_type", mime_type(file_path.string()));     std::string result{File::getFile(file_path)};     return result;    } catch (const std::exception& ex) { -   return HttpStatus("500", "Server error: "s + m_pathInfo, p); +   return HttpStatus("500", "Server error: "s + p.m_pathInfo, p);    }   }  }; @@ -908,23 +878,27 @@ std::string webbox_plugin::generate_page(  {   // Queries under STATIC_HTML_TARGET will be served statically from STATIC_HTML_DOC_ROOT - CommandParameters commandParameters(GetServerParam, GetRequestParam, SetResponseHeader); -  - std::string commandName; -  - auto it {commandParameters.paramHash.find("command")}; - if (it != commandParameters.paramHash.end()) -  commandName = it->second; + try { +  CommandParameters commandParameters(GetServerParam, GetRequestParam, SetResponseHeader); +   +  std::string commandName; +   +  auto it {commandParameters.paramHash.find("command")}; +  if (it != commandParameters.paramHash.end()) +   commandName = it->second; - auto commands_it{m_commands.find(commandName)}; - if (commands_it != m_commands.end()) { -  try { -   return commands_it->second->execute(commandParameters); -  } catch (const std::exception& ex) { -   return HttpStatus("500", "Processing command: "s + commandName + ", "s + ex.what(), commandParameters); -  } - } else -  return HttpStatus("400", "Bad command: "s + commandName, commandParameters); +  auto commands_it{m_commands.find(commandName)}; +  if (commands_it != m_commands.end()) { +   try { +    return commands_it->second->execute(commandParameters); +   } catch (const std::exception& ex) { +    return HttpStatus("500", "Processing command: "s + commandName + ", "s + ex.what(), commandParameters); +   } +  } else +   return HttpStatus("400", "Bad command: "s + commandName, commandParameters); + } catch (const std::exception& ex) { +  return HttpStatus("500", ex.what(), SetResponseHeader); + }  }  void webbox_plugin::registerCommand(std::shared_ptr<Command> command)  | 
