diff options
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/static-files/static-files.cpp | 68 | 
1 files changed, 66 insertions, 2 deletions
diff --git a/plugins/static-files/static-files.cpp b/plugins/static-files/static-files.cpp index 358e239..ad85f22 100644 --- a/plugins/static-files/static-files.cpp +++ b/plugins/static-files/static-files.cpp @@ -1,8 +1,49 @@  #include "static-files.h" +#include <filesystem> +#include <fstream>  #include <iostream> +#include <string>  using namespace std::string_literals; +namespace fs = std::filesystem; + +namespace { + +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"); + } +} + +std::string extend_index_html(std::string path) +{ + if (path.size() == 0 || (path.size() && path.back() == '/')) +  path.append("index.html"); + return path; +} + +// 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 static_files_plugin::name()  { @@ -26,9 +67,32 @@ std::string static_files_plugin::generate_page(  )  {   try { -  return "Static Files "s + GetServerParam("path"s); +  // 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 be absolute and not contain "..". +  std::string rel_target{GetRequestParam("rel_target")}; +  if (rel_target.find("..") != std::string::npos) { +   std::string target{GetRequestParam("target")}; +   return HttpStatus("400", "Illegal request: "s + target, SetResponseHeader); +  } + +  // Build the path to the requested file +  std::string doc_root{GetRequestParam("doc_root")}; +  std::string path {fs::path{doc_root} / extend_index_html(rel_target)}; + +  try { +   return getFile(path); +  } catch (const std::runtime_error& ex) { +   return HttpStatus("404", "Not found: "s + GetRequestParam("target"), SetResponseHeader); +  } catch (const std::exception& ex) { +   return HttpStatus("500", "Internal Server Error: "s + ex.what(), SetResponseHeader); +  } +   } catch (const std::exception& ex) { -  return "Error: "s + ex.what(); +  return HttpStatus("500", "Unknown Error: "s + ex.what(), SetResponseHeader);   }  }  | 
