summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2020-05-10 18:18:37 +0200
committerRoland Reichwein <mail@reichwein.it>2020-05-10 18:18:37 +0200
commit6c1cc0b2c854dd56dcb6238816a6ce2cb493c71c (patch)
treede041dfb3bc12a04fa4defdbd286d098f34adddc
parent5b32a4415c9776dd6cae859c8d718b5e68f01d81 (diff)
Separated out lib
-rw-r--r--Makefile14
-rw-r--r--libcommon/Makefile123
-rw-r--r--libcommon/mime.cpp41
-rw-r--r--libcommon/mime.h5
-rw-r--r--plugins/cgi/Makefile11
-rw-r--r--plugins/cgi/cgi.cpp39
-rw-r--r--plugins/static-files/Makefile11
-rw-r--r--plugins/static-files/static-files.cpp40
-rw-r--r--plugins/webbox/Makefile11
-rw-r--r--plugins/webbox/webbox.cpp164
-rw-r--r--plugins/weblog/Makefile11
-rw-r--r--plugins/weblog/weblog.cpp41
-rw-r--r--response.cpp38
13 files changed, 289 insertions, 260 deletions
diff --git a/Makefile b/Makefile
index 2e3f006..b9fb155 100644
--- a/Makefile
+++ b/Makefile
@@ -50,7 +50,8 @@ LIBS=\
-lcrypt \
-lpthread \
-lssl -lcrypto \
--ldl
+-ldl \
+-lcommon
#-lboost_coroutine \
#-lboost_program_options \
@@ -71,7 +72,7 @@ LIBS+= \
-lstdc++fs
endif
-LDFLAGS+=-pie
+LDFLAGS+=-pie -Llibcommon
PROGSRC=\
auth.cpp \
@@ -106,9 +107,12 @@ all: build
test-$(PROJECTNAME): $(TESTSRC:.cpp=.o)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) $(LIBS) -o $@
-$(PROJECTNAME): $(SRC:.cpp=.o)
+$(PROJECTNAME): libcommon/libcommon.a $(SRC:.cpp=.o)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) $(LIBS) -o $@
+libcommon/libcommon.a:
+ $(MAKE) -C libcommon
+
dep: $(TESTSRC:.cpp=.d)
%.d: %.cpp
@@ -157,6 +161,7 @@ clean:
-rm -f plugins/*.so
-find . -name '*.o' -o -name '*.d' -o -name '*.gcno' -o -name '*.gcda' | xargs rm -f
for i in $(PLUGINS) ; do make -C plugins/$$i clean ; done
+ $(MAKE) -C libcommon clean
DISTFILES= \
archive.h \
@@ -206,6 +211,9 @@ DISTFILES= \
debian/webserver.install \
debian/webserver.manpages \
debian/webserver.service \
+ libcommon/Makefile \
+ libcommon/mime.h \
+ libcommon/mime.cpp \
plugins/cgi/cgi.h \
plugins/cgi/Makefile \
plugins/cgi/cgi.cpp \
diff --git a/libcommon/Makefile b/libcommon/Makefile
new file mode 100644
index 0000000..3314549
--- /dev/null
+++ b/libcommon/Makefile
@@ -0,0 +1,123 @@
+# Static library to be included both in main program an in plugins (.so)
+
+DISTROS=debian10
+VERSION=$(shell dpkg-parsechangelog --show-field Version)
+PROJECTNAME=libcommon
+
+CXX=clang++-10
+
+ifeq ($(shell which $(CXX)),)
+CXX=clang++
+endif
+
+ifeq ($(shell which $(CXX)),)
+CXX=g++-9
+endif
+
+ifeq ($(CXXFLAGS),)
+#CXXFLAGS=-O2 -DNDEBUG
+CXXFLAGS=-O0 -g -D_DEBUG
+endif
+# -fprofile-instr-generate -fcoverage-mapping
+# gcc:--coverage
+
+CXXFLAGS+= -Wall -I.
+
+CXXFLAGS+= -pthread -fvisibility=hidden -fPIC
+ifeq ($(CXX),clang++-10)
+CXXFLAGS+=-std=c++20 #-stdlib=libc++
+else
+CXXFLAGS+=-std=c++17
+endif
+
+CXXTESTFLAGS=-Igoogletest/include -Igooglemock/include/ -Igoogletest -Igooglemock
+
+LIBS=\
+-lboost_context \
+-lboost_coroutine \
+-lboost_program_options \
+-lboost_system \
+-lboost_thread \
+-lboost_filesystem \
+-lboost_regex \
+-lpthread \
+-lssl -lcrypto \
+-ldl
+
+ifeq ($(CXX),clang++-10)
+LIBS+= \
+-fuse-ld=lld-10 \
+-lstdc++
+#-lc++ \
+#-lc++abi
+#-lc++fs
+#-lstdc++fs
+else
+LIBS+= \
+-lstdc++ \
+-lstdc++fs
+endif
+
+PROGSRC=\
+ mime.cpp
+
+TESTSRC=\
+ test-webserver.cpp \
+ googlemock/src/gmock-all.cpp \
+ googletest/src/gtest-all.cpp \
+ $(PROGSRC)
+
+SRC=$(PROGSRC)
+
+all: $(PROJECTNAME).a
+
+# testsuite ----------------------------------------------
+test-$(PROJECTNAME): $(TESTSRC:.cpp=.o)
+ $(CXX) $(CXXFLAGS) $^ $(LIBS) -o $@
+
+$(PROJECTNAME).a: $(SRC:.cpp=.o)
+ ar rcs $@ $^
+
+dep: $(TESTSRC:.cpp=.d)
+
+%.d: %.cpp
+ $(CXX) $(CXXFLAGS) $(CXXTESTFLAGS) -MM -MP -MF $@ -c $<
+
+%.o: %.cpp %.d
+ $(CXX) $(CXXFLAGS) $(CXXTESTFLAGS) -c $< -o $@
+
+googletest/src/%.o: googletest/src/%.cc
+ $(CXX) $(CXXFLAGS) $(CXXTESTFLAGS) -c $< -o $@
+
+# dependencies
+
+ADD_DEP=Makefile
+
+
+# misc ---------------------------------------------------
+deb:
+ # build binary deb package
+ dpkg-buildpackage -us -uc -rfakeroot
+
+deb-src:
+ dpkg-source -b .
+
+$(DISTROS): deb-src
+ sudo pbuilder build --basetgz /var/cache/pbuilder/$@.tgz --buildresult result/$@ ../webserver_$(VERSION).dsc ; \
+
+debs: $(DISTROS)
+
+clean:
+ -rm -f test-$(PROJECTNAME) $(PROJECTNAME)
+ -find . -name '*.a' -o -name '*.o' -o -name '*.so' -o -name '*.d' -o -name '*.gcno' -o -name '*.gcda' | xargs rm -f
+
+zip: clean
+ -rm -f ../$(PROJECTNAME).zip
+ zip -r ../$(PROJECTNAME).zip *
+ ls -l ../$(PROJECTNAME).zip
+
+
+
+.PHONY: clean all zip install deb deb-src debs all $(DISTROS)
+
+-include $(wildcard $(SRC:.cpp=.d))
diff --git a/libcommon/mime.cpp b/libcommon/mime.cpp
new file mode 100644
index 0000000..f093596
--- /dev/null
+++ b/libcommon/mime.cpp
@@ -0,0 +1,41 @@
+#include "mime.h"
+
+#include <boost/beast/http.hpp>
+
+namespace beast = boost::beast;
+
+// Return a reasonable mime type based on the extension of a file.
+std::string mime_type(const std::string& path)
+{
+ using beast::iequals;
+ auto const ext = [&path]
+ {
+ auto const pos = path.rfind(".");
+ if (pos == std::string::npos)
+ return std::string{};
+ return path.substr(pos);
+ }();
+ if(iequals(ext, ".htm")) return "text/html";
+ 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";
+}
+
diff --git a/libcommon/mime.h b/libcommon/mime.h
new file mode 100644
index 0000000..c05eb45
--- /dev/null
+++ b/libcommon/mime.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#include <string>
+
+std::string mime_type(const std::string& path);
diff --git a/plugins/cgi/Makefile b/plugins/cgi/Makefile
index b3e8548..8faebdc 100644
--- a/plugins/cgi/Makefile
+++ b/plugins/cgi/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=\
cgi.cpp
@@ -73,8 +76,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/cgi/cgi.cpp b/plugins/cgi/cgi.cpp
index 0824d67..480ae9e 100644
--- a/plugins/cgi/cgi.cpp
+++ b/plugins/cgi/cgi.cpp
@@ -1,5 +1,7 @@
#include "cgi.h"
+#include "libcommon/mime.h"
+
#include <boost/algorithm/string/predicate.hpp>
#include <boost/coroutine2/coroutine.hpp>
#include <boost/process.hpp>
@@ -45,41 +47,6 @@ 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";
- 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";
- }
-
typedef boost::coroutines2::coroutine<std::string> coro_t;
// returns true iff std::string is empty or contains newline
@@ -306,7 +273,7 @@ std::string cgi_plugin::generate_page(
return HttpStatus("500", "Bad file status access: "s + rel_target, SetResponseHeader);
}
- SetResponseHeader("content_type", mime_type(path));
+ SetResponseHeader("content_type", mime_type(path.string()));
CGIContext context(GetServerParam, GetRequestParam, SetResponseHeader, path, file_path, path_info);
diff --git a/plugins/static-files/Makefile b/plugins/static-files/Makefile
index fdc0896..e96257d 100644
--- a/plugins/static-files/Makefile
+++ b/plugins/static-files/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=\
static-files.cpp
@@ -73,8 +76,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/static-files/static-files.cpp b/plugins/static-files/static-files.cpp
index 011e37f..3f1c63a 100644
--- a/plugins/static-files/static-files.cpp
+++ b/plugins/static-files/static-files.cpp
@@ -1,5 +1,7 @@
#include "static-files.h"
+#include "libcommon/mime.h"
+
#include <boost/algorithm/string/predicate.hpp>
#include <filesystem>
@@ -12,42 +14,6 @@ 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);
@@ -126,7 +92,7 @@ std::string static_files_plugin::generate_page(
return HttpStatus("301", "Correcting directory path", SetResponseHeader);
}
path = {extend_index_html(path)};
- SetResponseHeader("content_type", mime_type(path));
+ SetResponseHeader("content_type", mime_type(path.string()));
try {
return getFile(path);
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)
diff --git a/plugins/weblog/Makefile b/plugins/weblog/Makefile
index 58d1801..b9f278a 100644
--- a/plugins/weblog/Makefile
+++ b/plugins/weblog/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=\
stringutil.cpp \
weblog.cpp
@@ -74,8 +77,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/weblog/weblog.cpp b/plugins/weblog/weblog.cpp
index 4ed468e..4a14799 100644
--- a/plugins/weblog/weblog.cpp
+++ b/plugins/weblog/weblog.cpp
@@ -2,6 +2,8 @@
#include "stringutil.h"
+#include "libcommon/mime.h"
+
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/property_tree/ptree.hpp>
@@ -23,41 +25,6 @@ namespace {
const size_t number_of_articles_on_front_page {10};
const std::string article_filename{"article.data"};
- // 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";
- }
-
// 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)
{
@@ -92,7 +59,7 @@ namespace {
bool is_index_file(std::string& rel_target, fs::path& path)
{
// must be top-level file, recognized as mime_type()
- return rel_target.find("/") == rel_target.npos && mime_type(path) != "application/text";
+ return rel_target.find("/") == rel_target.npos && mime_type(path.string()) != "application/text";
}
bool is_article_page(std::string& rel_target, fs::path& path)
@@ -344,7 +311,7 @@ namespace {
std::string generateStaticFile(fs::path& path, std::function<plugin_interface_setter_type>& SetResponseHeader)
{
try {
- SetResponseHeader("content_type", mime_type(path));
+ SetResponseHeader("content_type", mime_type(path.string()));
return getFile(path);
} catch (const std::exception& ex) {
return HttpStatus("500", "Reading Article file: "s + ex.what(), SetResponseHeader);
diff --git a/response.cpp b/response.cpp
index 2320379..4c76bb3 100644
--- a/response.cpp
+++ b/response.cpp
@@ -5,6 +5,8 @@
#include "file.h"
#include "os.h"
+#include "libcommon/mime.h"
+
#include <boost/algorithm/string/predicate.hpp>
#include <functional>
@@ -202,42 +204,6 @@ void SetResponseHeader(const std::string& key, const std::string& value, respons
throw std::runtime_error("Unsupported response field: "s + key);
}
-// Return a reasonable mime type based on the extension of a file.
-beast::string_view
-mime_type(beast::string_view path)
-{
- using beast::iequals;
- auto const ext = [&path]
- {
- auto const pos = path.rfind(".");
- if (pos == beast::string_view::npos)
- return beast::string_view{};
- return path.substr(pos);
- }();
- if(iequals(ext, ".htm")) return "text/html";
- 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";
-}
-
response_type HttpStatus(std::string status, std::string message, response_type& res)
{
if (status != "200") { // already handled at res init