aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToni Uhlig <matzeton@googlemail.com>2021-09-30 21:12:57 +0200
committerToni Uhlig <matzeton@googlemail.com>2021-09-30 21:12:57 +0200
commit6c04dfe2caff1e03ba5c898b591327439452f616 (patch)
tree11c6f6955de188c48015641c1ae2e63b0d0e50d6
parentec7cfa85530082127703278cf1ae5167990c0f45 (diff)
CMS functionality works just find..minimal-working-example
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r--.clang-format77
-rw-r--r--src/Content.cpp28
-rw-r--r--src/Content.hpp30
-rw-r--r--src/ContentManager.cpp89
-rw-r--r--src/ContentManager.hpp32
-rw-r--r--src/EventManager.cpp314
-rw-r--r--src/EventManager.hpp48
-rw-r--r--src/Filesystem.cpp165
-rw-r--r--src/Filesystem.hpp30
-rw-r--r--src/RequestResponse.cpp32
-rw-r--r--src/RequestResponse.hpp25
-rw-r--r--src/TemplateManager.cpp57
-rw-r--r--src/TemplateManager.hpp28
-rw-r--r--src/content/blog/Blog.cpp36
-rw-r--r--src/content/blog/Blog.hpp20
-rw-r--r--src/main.cpp202
-rw-r--r--wwwroot/index.html35
-rw-r--r--wwwroot/index.tmpl1
18 files changed, 751 insertions, 498 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..aeb942a
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,77 @@
+Language: Cpp
+BasedOnStyle : LLVM
+Standard : Cpp03
+# BasedOnStyle: LLVM
+BraceWrapping:
+ AfterClass: false
+ AfterControlStatement: false
+ AfterEnum: false
+ AfterFunction: false
+ AfterNamespace: false
+ AfterObjCDeclaration: false
+ AfterStruct: false
+ AfterUnion: false
+ BeforeCatch: false
+ BeforeElse: false
+ IndentBraces: true
+ConstructorInitializerIndentWidth: 4
+AlignEscapedNewlinesLeft: false
+AlignTrailingComments: true
+AllowShortBlocksOnASingleLine: true
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: false
+AlwaysBreakTemplateDeclarations: true
+AlwaysBreakBeforeMultilineStrings: true
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+ColumnLimit: 120
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+DerivePointerAlignment: false
+ExperimentalAutoDetectBinPacking: false
+IndentCaseLabels: true
+IndentWrappedFunctionNames: false
+IndentFunctionDeclarationAfterType: false
+MaxEmptyLinesToKeep: 1
+KeepEmptyLinesAtTheStartOfBlocks: true
+NamespaceIndentation: None
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: false
+
+PenaltyExcessCharacter : 500
+PenaltyReturnTypeOnItsOwnLine : 120
+PenaltyBreakBeforeFirstCallParameter : 100
+PenaltyBreakString : 20
+PenaltyBreakComment : 10
+PenaltyBreakFirstLessLess : 0
+
+SpacesBeforeTrailingComments: 1
+Cpp11BracedListStyle: true
+IndentWidth: 4
+TabWidth: 4
+UseTab: Never
+BreakBeforeBraces: Allman
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+SpacesInAngles : false
+SpaceInEmptyParentheses : false
+SpacesInCStyleCastParentheses : false
+SpaceAfterCStyleCast : false
+SpacesInContainerLiterals : true
+SpaceBeforeAssignmentOperators : true
+ContinuationIndentWidth : 4
+SpaceBeforeParens : ControlStatements
+DisableFormat : false
+AccessModifierOffset : -4
+PointerAlignment : Middle
+AlignAfterOpenBracket : Align
+AllowAllParametersOfDeclarationOnNextLine : true
+BinPackArguments : false
+BinPackParameters : false
+AlignOperands : true
+AlignConsecutiveAssignments : false
+AllowShortFunctionsOnASingleLine : None
+BreakBeforeBinaryOperators : None
+AlwaysBreakAfterReturnType : None
+SortIncludes : false
diff --git a/src/Content.cpp b/src/Content.cpp
deleted file mode 100644
index b2977bb..0000000
--- a/src/Content.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "Content.hpp"
-
-TemplatedContent::TemplatedContent(std::string filesystemPath) : m_FilesystemPath(filesystemPath)
-{
-}
-
-bool TemplatedContent::Init()
-{
- return false;
-}
-
-void TemplatedContent::Shutdown()
-{
-}
-
-bool TemplatedContent::Render(RequestResponse & rr, std::string & out)
-{
- (void)rr;
-
- out = "tmpl";
-
- return false;
-}
-
-void TemplatedContent::GetRequiredFiles(std::vector<std::string> & requiredFiles) const
-{
- requiredFiles.push_back(m_FilesystemPath);
-}
diff --git a/src/Content.hpp b/src/Content.hpp
index c379522..82eb35e 100644
--- a/src/Content.hpp
+++ b/src/Content.hpp
@@ -8,30 +8,20 @@
#include <tuple>
#include <vector>
-typedef std::vector<std::string> Redirections;
+using Redirections = std::vector<std::string>;
+using RenderData = std::unordered_map<std::string, std::string>;
-class Content {
+class Content
+{
public:
- virtual bool Init() = 0;
- virtual void Shutdown() = 0;
- virtual bool Render(RequestResponse & rr, std::string & out) = 0;
+ virtual bool Init() = 0;
+ virtual void Shutdown() = 0;
- virtual std::string const & GetBaseUri() const = 0;
- virtual Redirections const & GetRedirections() const = 0;
- virtual void GetRequiredFiles(std::vector<std::string> & requiredFiles) const = 0;
-};
-
-class TemplatedContent : public Content {
-public:
- explicit TemplatedContent(std::string mainTemplate);
-
- virtual bool Init();
- virtual void Shutdown();
- virtual bool Render(RequestResponse & rr, std::string & out);
- virtual void GetRequiredFiles(std::vector<std::string> & requiredFiles) const;
+ virtual bool Render(RequestResponse & rr, RenderData & rd) = 0;
-private:
- std::string m_FilesystemPath;
+ virtual std::string const & GetUriBasePath() const = 0;
+ virtual std::string const & GetMainTemplate() const = 0;
+ virtual Redirections const & GetRedirections() const = 0;
};
#endif
diff --git a/src/ContentManager.cpp b/src/ContentManager.cpp
index a1787bd..6beef5a 100644
--- a/src/ContentManager.cpp
+++ b/src/ContentManager.cpp
@@ -1,61 +1,90 @@
#include "ContentManager.hpp"
+void ContentManager::SetStaticFilesystem(std::shared_ptr<Filesystem> & static_fs)
+{
+ m_StaticFilesystem = static_fs;
+}
+
+void ContentManager::SetTemplateSystem(std::shared_ptr<TemplateManager> & tmgr)
+{
+ m_TemplateManager = tmgr;
+}
+
bool ContentManager::RegisterModule(std::shared_ptr<Content> ctnt)
{
- std::string const & basePath = ctnt->GetBaseUri();
- Redirections const & rs = ctnt->GetRedirections();
+ std::string const & basePath = ctnt->GetUriBasePath();
+ Redirections const & rs = ctnt->GetRedirections();
- m_ContentModules[basePath] = ctnt;
- for (auto & redirect : rs)
- {
- m_ContentModules[redirect] = ctnt;
- }
+ m_ContentModules[basePath] = ctnt;
+ for (auto & redirect : rs)
+ {
+ m_ContentModules[redirect] = ctnt;
+ }
- return false;
+ return false;
}
bool ContentManager::InitAll(void)
{
- bool ret = true;
+ bool ret = true;
- for (auto & content : m_ContentModules)
- {
- if (content.second->Init() == false)
+ for (auto & content : m_ContentModules)
{
- ret = false;
+ if (content.second->Init() == false)
+ {
+ ret = false;
+ }
}
- }
- return ret;
+ return ret;
}
void ContentManager::ShutdownAll(void)
{
- std::unordered_map<std::shared_ptr<Content>, bool> shutdownModules;
+ std::unordered_map<std::shared_ptr<Content>, bool> shutdownModules;
- for (auto & content : m_ContentModules)
- {
- auto const & search = shutdownModules.find(content.second);
- if (search != shutdownModules.end())
+ for (auto & content : m_ContentModules)
{
- continue;
- } else {
- content.second->Shutdown();
- shutdownModules[content.second] = true;
+ auto const & search = shutdownModules.find(content.second);
+ if (search != shutdownModules.end())
+ {
+ continue;
+ }
+ else
+ {
+ content.second->Shutdown();
+ shutdownModules[content.second] = true;
+ }
}
- }
- m_ContentModules.clear();
+ m_ContentModules.clear();
}
-bool ContentManager::Render(std::string & basePath)
+bool ContentManager::Render(char const * basePath, RequestResponse & rr, std::string & out)
{
- (void)basePath;
+ if (m_ContentModules.find(basePath) == m_ContentModules.end())
+ {
+ return false;
+ }
+
+ RenderData rd;
+ auto & cntm = m_ContentModules[basePath];
+ auto & main = cntm->GetMainTemplate();
+
+ if (m_ContentModules[basePath]->Render(rr, rd) == false)
+ {
+ return false;
+ }
+
+ if (m_TemplateManager->RenderTemplate(main, rd, out) == false)
+ {
+ return false;
+ }
- return false;
+ return true;
}
ContentModules const & ContentManager::GetAllModules() const
{
- return m_ContentModules;
+ return m_ContentModules;
}
diff --git a/src/ContentManager.hpp b/src/ContentManager.hpp
index 033be59..83f4bc9 100644
--- a/src/ContentManager.hpp
+++ b/src/ContentManager.hpp
@@ -2,25 +2,37 @@
#define CONTENTMANAGER_H 1
#include "Content.hpp"
+#include "Filesystem.hpp"
+#include "TemplateManager.hpp"
#include <memory>
#include <unordered_map>
-typedef std::unordered_map<std::string, std::shared_ptr<Content>> ContentModules;
+using ContentModules = std::unordered_map<std::string, std::shared_ptr<Content> >;
-class ContentManager {
+class ContentManager
+{
public:
- ContentManager() {}
- ~ContentManager() { ShutdownAll(); }
+ ContentManager()
+ {
+ }
+ ~ContentManager()
+ {
+ ShutdownAll();
+ }
- bool RegisterModule(std::shared_ptr<Content> ctnt);
- bool InitAll(void);
- void ShutdownAll(void);
- bool Render(std::string & basePath);
- ContentModules const & GetAllModules() const;
+ void SetStaticFilesystem(std::shared_ptr<Filesystem> & static_fs);
+ void SetTemplateSystem(std::shared_ptr<TemplateManager> & tmgr);
+ bool RegisterModule(std::shared_ptr<Content> ctnt);
+ bool InitAll(void);
+ void ShutdownAll(void);
+ bool Render(char const * basePath, RequestResponse & rr, std::string & out);
+ ContentModules const & GetAllModules() const;
private:
- ContentModules m_ContentModules;
+ std::shared_ptr<Filesystem> m_StaticFilesystem;
+ std::shared_ptr<TemplateManager> m_TemplateManager;
+ ContentModules m_ContentModules;
};
#endif
diff --git a/src/EventManager.cpp b/src/EventManager.cpp
index ad480bc..3270297 100644
--- a/src/EventManager.cpp
+++ b/src/EventManager.cpp
@@ -8,171 +8,199 @@
#include <event2/util.h>
#include <signal.h>
-extern "C" {
-static void GenerateInternalErrorPage(struct evhttp_request * const req,
- std::string text)
+extern "C"
{
- evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type",
- "text/html");
-
- struct evbuffer *const output = evbuffer_new();
- if (output != nullptr) {
- evbuffer_add(output, text.c_str(), text.size());
- evhttp_send_reply(req, 500, "Internal Error", output);
- evbuffer_free(output);
- }
-}
+ static void GenerateInternalErrorPage(struct evhttp_request * const req, std::string text)
+ {
+ evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/html");
+
+ struct evbuffer * const output = evbuffer_new();
+ if (output != nullptr)
+ {
+ evbuffer_add(output, text.c_str(), text.size());
+ evhttp_send_reply(req, 500, "Internal Error", output);
+ evbuffer_free(output);
+ }
+ }
-static void EvGenericInterceptor(struct evhttp_request *const req,
- void *ev_c_callback) {
- if (ev_c_callback != nullptr) {
- struct ev_callback *const evcb = (struct ev_callback *)ev_c_callback;
- evcb->cb(req, evcb->ud);
- } else {
- GenerateInternalErrorPage(req, "EvGenericInterceptor: ev_c_callback == nullptr");
- }
-}
+ static void EvGenericInterceptor(struct evhttp_request * const req, void * ev_c_callback)
+ {
+ if (ev_c_callback != nullptr)
+ {
+ struct ev_callback * const evcb = (struct ev_callback *)ev_c_callback;
+ evcb->cb(req, evcb->ud);
+ }
+ else
+ {
+ GenerateInternalErrorPage(req, "EvGenericInterceptor: ev_c_callback == nullptr");
+ }
+ }
-static void EvContentManagerInterceptor(struct evhttp_request * const req,
- void * ev_c_callback) {
- if (ev_c_callback != nullptr) {
- Content * const cntnt = (Content *)ev_c_callback;
- RequestResponse rr(req);
- std::string out;
- if (cntnt->Render(rr, out) == false) {
- std::string text;
- text = "ContentModule(\"" + cntnt->GetBaseUri() + "\")->Render() failed.\n";
- GenerateInternalErrorPage(req, text);
- } else {
- evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type",
- "text/html");
-
- struct evbuffer *const output = evbuffer_new();
- if (output != nullptr) {
- evbuffer_add(output, out.c_str(), out.size());
- evhttp_send_reply(req, HTTP_OK, "OK", output);
- evbuffer_free(output);
- }
+ static void EvContentManagerInterceptor(struct evhttp_request * const req, void * ev_c_callback)
+ {
+ if (ev_c_callback != nullptr)
+ {
+ struct evhttp_uri const * const uri = evhttp_request_get_evhttp_uri(req);
+ if (uri == nullptr)
+ {
+ GenerateInternalErrorPage(req, "EvContentManagerInterceptor: uri == nullptr");
+ return;
+ }
+
+ char const * const path = evhttp_uri_get_path(uri);
+ if (path == nullptr)
+ {
+ GenerateInternalErrorPage(req, "EvContentManagerInterceptor: path == nullptr");
+ return;
+ }
+
+ std::shared_ptr<ContentManager> const cmgr = *(std::shared_ptr<ContentManager> const *)ev_c_callback;
+ RequestResponse rr(req);
+ std::string out;
+
+ if (cmgr->Render(path, rr, out) == false)
+ {
+ std::string text;
+ text = "ContentModule(\"" + std::string(path) + "\")->Render() failed.\n";
+ GenerateInternalErrorPage(req, text);
+ }
+ else
+ {
+ evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/html");
+
+ struct evbuffer * const output = evbuffer_new();
+ if (output != nullptr)
+ {
+ evbuffer_add(output, out.c_str(), out.size());
+ evhttp_send_reply(req, HTTP_OK, "OK", output);
+ evbuffer_free(output);
+ }
+ }
+ }
+ else
+ {
+ GenerateInternalErrorPage(req, "EvContentManagerInterceptor: ev_c_callback == nullptr");
+ }
}
- } else {
- GenerateInternalErrorPage(req, "EvContentManagerInterceptor: ev_c_callback == nullptr");
- }
-}
-static void do_term(int sig, short events, void *arg) {
- (void)events;
- struct event_base *base = (struct event_base *)arg;
- event_base_loopbreak(base);
- fprintf(stderr, "Got %i, Terminating\n", sig);
-}
+ static void do_term(int sig, short events, void * arg)
+ {
+ (void)events;
+ struct event_base * base = (struct event_base *)arg;
+ event_base_loopbreak(base);
+ fprintf(stderr, "Got %i, Terminating\n", sig);
+ }
}
-static inline void default_evhttp_callback(struct evhttp_request * const req,
- EvUserData ud) {
- (void)ud;
+static inline void default_evhttp_callback(struct evhttp_request * const req, EvUserData ud)
+{
+ (void)ud;
- evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type",
- "text/html");
+ evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/html");
- struct evbuffer *const output = evbuffer_new();
- if (output != nullptr) {
- evbuffer_add_printf(output, "%s\n",
- "<html><body><b>default page</b></body></html>");
- evhttp_send_reply(req, 200, "OK", output);
- evbuffer_free(output);
- }
+ struct evbuffer * const output = evbuffer_new();
+ if (output != nullptr)
+ {
+ evbuffer_add_printf(output, "%s\n", "<html><body><b>default page</b></body></html>");
+ evhttp_send_reply(req, 200, "OK", output);
+ evbuffer_free(output);
+ }
}
-EventManager::EventManager() : m_DefaultCallback({default_evhttp_callback, nullptr})
+EventManager::EventManager(std::shared_ptr<ContentManager> & cmgr)
+ : m_ContentManager(cmgr), m_DefaultCallback({default_evhttp_callback, nullptr})
{
}
-EventManager::~EventManager() {
- if (m_EvConfig != nullptr)
- event_config_free(m_EvConfig);
- if (m_EvHttp != nullptr)
- evhttp_free(m_EvHttp);
- if (m_EvTermEvent != nullptr)
- event_free(m_EvTermEvent);
- if (m_EvBase != nullptr)
- event_base_free(m_EvBase);
+EventManager::~EventManager()
+{
+ if (m_EvConfig != nullptr)
+ event_config_free(m_EvConfig);
+ if (m_EvHttp != nullptr)
+ evhttp_free(m_EvHttp);
+ if (m_EvTermEvent != nullptr)
+ event_free(m_EvTermEvent);
+ if (m_EvBase != nullptr)
+ event_base_free(m_EvBase);
}
-bool EventManager::Init(std::string host, uint16_t port) {
- struct event_config *cfg = nullptr;
-
- if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
- return false;
- }
-
- event_enable_debug_logging(EVENT_DBG_ALL);
-
- cfg = event_config_new();
- event_config_set_flag(cfg, EVENT_BASE_FLAG_STARTUP_IOCP);
-
- m_EvBase = event_base_new_with_config(cfg);
- if (m_EvBase == nullptr) {
- fprintf(stderr, "Couldn't create an event_base: exiting\n");
- return false;
- }
- event_config_free(cfg);
- cfg = nullptr;
-
- /* Create a new evhttp object to handle requests. */
- m_EvHttp = evhttp_new(m_EvBase);
- if (m_EvHttp == nullptr) {
- fprintf(stderr, "couldn't create evhttp. Exiting.\n");
- return false;
- }
-
- for (auto & uc : m_UrlCallbacks) {
- struct ev_callback * const evcb = &std::get<1>(uc);
- if (evhttp_set_cb(m_EvHttp, std::get<0>(uc).c_str(), EvGenericInterceptor,
- evcb) != 0) {
- return false;
+bool EventManager::Init(std::string host, uint16_t port)
+{
+ struct event_config * cfg = nullptr;
+
+ if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
+ {
+ return false;
+ }
+
+ event_enable_debug_logging(EVENT_DBG_ALL);
+
+ cfg = event_config_new();
+ event_config_set_flag(cfg, EVENT_BASE_FLAG_STARTUP_IOCP);
+
+ m_EvBase = event_base_new_with_config(cfg);
+ if (m_EvBase == nullptr)
+ {
+ fprintf(stderr, "Couldn't create an event_base: exiting\n");
+ return false;
}
- }
- for (auto & cm : m_ContentModules) {
- std::shared_ptr<Content> content = cm.second;
- if (evhttp_set_cb(m_EvHttp, cm.first.c_str(), EvContentManagerInterceptor,
- content.get()) != 0) {
- return false;
+ event_config_free(cfg);
+ cfg = nullptr;
+
+ /* Create a new evhttp object to handle requests. */
+ m_EvHttp = evhttp_new(m_EvBase);
+ if (m_EvHttp == nullptr)
+ {
+ fprintf(stderr, "couldn't create evhttp. Exiting.\n");
+ return false;
}
- }
- evhttp_set_gencb(m_EvHttp, EvGenericInterceptor, &m_DefaultCallback);
-
- m_EvSocket = evhttp_bind_socket_with_handle(m_EvHttp, host.c_str(), port);
- if (m_EvSocket == nullptr) {
- fprintf(stderr, "couldn't bind to %s:%d. Exiting.\n", host.c_str(), port);
- return false;
- }
-
- m_EvTermEvent = evsignal_new(m_EvBase, SIGINT, do_term, m_EvBase);
- if (m_EvTermEvent == nullptr) {
- return false;
- }
- if (event_add(m_EvTermEvent, NULL) != 0) {
- return false;
- }
-
- event_base_dispatch(m_EvBase);
-
- return true;
-}
-void EventManager::SetDefaultCallback(EvFunction fn, EvUserData dat) {
- m_DefaultCallback.cb = fn;
- m_DefaultCallback.ud = dat;
-}
+ for (auto & uc : m_UrlCallbacks)
+ {
+ struct ev_callback * const evcb = &std::get<1>(uc);
+ if (evhttp_set_cb(m_EvHttp, std::get<0>(uc).c_str(), EvGenericInterceptor, evcb) != 0)
+ {
+ return false;
+ }
+ }
+ for (auto & cm : m_ContentManager->GetAllModules())
+ {
+ if (evhttp_set_cb(m_EvHttp, cm.first.c_str(), EvContentManagerInterceptor, &m_ContentManager) != 0)
+ {
+ return false;
+ }
+ }
+ evhttp_set_gencb(m_EvHttp, EvGenericInterceptor, &m_DefaultCallback);
-void EventManager::AddCallback(std::string url, EvFunction fn, EvUserData dat) {
- m_UrlCallbacks.push_back(EvUrlCallback(url, {fn, dat}));
+ m_EvSocket = evhttp_bind_socket_with_handle(m_EvHttp, host.c_str(), port);
+ if (m_EvSocket == nullptr)
+ {
+ fprintf(stderr, "couldn't bind to %s:%d. Exiting.\n", host.c_str(), port);
+ return false;
+ }
+
+ m_EvTermEvent = evsignal_new(m_EvBase, SIGINT, do_term, m_EvBase);
+ if (m_EvTermEvent == nullptr)
+ {
+ return false;
+ }
+ if (event_add(m_EvTermEvent, NULL) != 0)
+ {
+ return false;
+ }
+
+ event_base_dispatch(m_EvBase);
+
+ return true;
}
-void EventManager::AddContentManager(ContentManager const & cmgr)
+void EventManager::SetDefaultCallback(EvFunction fn, EvUserData dat)
{
- ContentModules new_mods = m_ContentModules;
+ m_DefaultCallback.cb = fn;
+ m_DefaultCallback.ud = dat;
+}
- new_mods.insert(cmgr.GetAllModules().begin(), cmgr.GetAllModules().end());
- m_ContentModules = new_mods;
+void EventManager::AddCallback(std::string url, EvFunction fn, EvUserData dat)
+{
+ m_UrlCallbacks.push_back(EvUrlCallback(url, {fn, dat}));
}
diff --git a/src/EventManager.hpp b/src/EventManager.hpp
index db9d461..cf09e14 100644
--- a/src/EventManager.hpp
+++ b/src/EventManager.hpp
@@ -12,38 +12,38 @@
#include <string>
#include <vector>
-typedef void *EvUserData;
-typedef void ev_c_callback(struct evhttp_request *, EvUserData);
-typedef std::function<void(struct evhttp_request *, EvUserData)> EvFunction;
+using EvUserData = void *;
+using EvFunction = std::function<void(struct evhttp_request *, EvUserData)>;
-struct ev_callback {
- EvFunction cb;
- EvUserData ud;
+struct ev_callback
+{
+ EvFunction cb;
+ EvUserData ud;
};
-typedef std::tuple<std::string, struct ev_callback> EvUrlCallback;
+using EvUrlCallback = std::tuple<std::string, struct ev_callback>;
-class EventManager {
+class EventManager
+{
public:
- EventManager();
- ~EventManager();
+ EventManager(std::shared_ptr<ContentManager> & cmgr);
+ ~EventManager();
- bool Init(std::string = "127.0.0.1", uint16_t port = 9000);
- void SetDefaultCallback(EvFunction fn, EvUserData dat);
- void AddCallback(std::string url, EvFunction fn, EvUserData dat);
- void AddContentManager(ContentManager const & cmgr);
+ bool Init(std::string = "127.0.0.1", uint16_t port = 9000);
+ void SetDefaultCallback(EvFunction fn, EvUserData dat);
+ void AddCallback(std::string url, EvFunction fn, EvUserData dat);
private:
- struct ev_callback m_DefaultCallback;
- std::vector<EvUrlCallback> m_UrlCallbacks;
- ContentModules m_ContentModules;
-
- struct event_config *m_EvConfig = nullptr;
- struct event_base *m_EvBase = nullptr;
- struct evhttp *m_EvHttp = nullptr;
- struct evhttp_bound_socket *m_EvSocket = nullptr;
- struct evconnlistener *m_EvListener = nullptr;
- struct event *m_EvTermEvent = nullptr;
+ std::shared_ptr<ContentManager> m_ContentManager;
+ struct ev_callback m_DefaultCallback;
+ std::vector<EvUrlCallback> m_UrlCallbacks;
+
+ struct event_config * m_EvConfig = nullptr;
+ struct event_base * m_EvBase = nullptr;
+ struct evhttp * m_EvHttp = nullptr;
+ struct evhttp_bound_socket * m_EvSocket = nullptr;
+ struct evconnlistener * m_EvListener = nullptr;
+ struct event * m_EvTermEvent = nullptr;
};
#endif
diff --git a/src/Filesystem.cpp b/src/Filesystem.cpp
index 022c1a5..09e5146 100644
--- a/src/Filesystem.cpp
+++ b/src/Filesystem.cpp
@@ -5,76 +5,121 @@
#include <fstream>
#include <iostream>
-static std::string make_path_relative(std::string &path, std::string &root) {
- return std::filesystem::relative(path, root);
+static std::string make_path_relative(std::string & path, std::string & root)
+{
+ return std::filesystem::relative(path, root);
}
-bool Filesystem::AddSingleFile(std::string path, std::string root) {
- std::ifstream ifs(path, std::ios::binary | std::ios::ate);
-
- if (!ifs) {
- return false;
- }
-
- auto end = ifs.tellg();
- if (end <= 0) {
- return false;
- }
- if (!ifs.seekg(0, std::ios::beg)) {
- return false;
- }
-
- auto size = std::size_t(end - ifs.tellg());
-
- if (size == 0) {
- return false;
- }
-
- struct file_data fd = {};
- try {
- fd.data.reserve(size);
- } catch (const std::exception &e) {
- return false;
- }
-
- if (!ifs.read((char *)fd.data.data(), fd.data.size())) {
- return false;
- }
-
- std::string relpath = make_path_relative(path, root);
- if (m_Files.count(relpath) > 0) {
- std::cout << "Adding file: " << path << " and overwriting " << relpath
- << std::endl;
- } else {
- std::cout << "Adding file: " << path << " as " << relpath << std::endl;
- }
-
- std::string ext = std::filesystem::path(relpath).extension();
- if (ext == ".html" || ext == ".tmpl")
- {
- std::string tmpl(fd.data.data(), fd.data.data() + fd.data.size());
- m_Templates[relpath] = inja::Template(tmpl);
- std::cout << "File: " << relpath << " may contain a renderable template." << std::endl;
- } else {
+bool Filesystem::AddSingleFile(std::string path, std::string root)
+{
+ std::ifstream ifs(path, std::ios::binary | std::ios::ate);
+
+ if (!ifs)
+ {
+ return false;
+ }
+
+ auto end = ifs.tellg();
+ if (end <= 0)
+ {
+ return false;
+ }
+ if (!ifs.seekg(0, std::ios::beg))
+ {
+ return false;
+ }
+
+ auto size = std::size_t(end - ifs.tellg());
+
+ if (size == 0)
+ {
+ return false;
+ }
+
+ struct file_data fd = {};
+ try
+ {
+ fd.data.resize(size);
+ }
+ catch (const std::exception & e)
+ {
+ return false;
+ }
+
+ if (!ifs.read((char *)fd.data.data(), fd.data.size()))
+ {
+ return false;
+ }
+
+ std::string relpath = make_path_relative(path, root);
+ if (m_Files.count(relpath) > 0)
+ {
+ std::cout << "Adding file: " << path << " (" << size << " bytes) and overwriting " << relpath << " to " << this
+ << std::endl;
+ }
+ else
+ {
+ std::cout << "Adding file: " << path << " (" << size << " bytes) as " << relpath << " to " << this << std::endl;
+ }
+
m_Files[relpath] = fd;
- }
- return true;
+ return true;
}
-bool Filesystem::Scan(std::string root) {
- for (const auto &entry : std::filesystem::directory_iterator(root)) {
- AddSingleFile(entry.path(), root);
- }
- return true;
+bool Filesystem::Scan(std::string root)
+{
+ bool retval = true;
+
+ for (const auto & entry : std::filesystem::directory_iterator(root))
+ {
+ if (AddSingleFile(entry.path(), root) == false)
+ {
+ retval = true;
+ }
+ }
+
+ return retval;
}
-void Filesystem::AddInjaCallback(std::string functionName, std::size_t numberOfArgs, inja::CallbackFunction function)
+bool Filesystem::Scan(std::string root, std::vector<std::string> extensions, bool exclude_extensions)
{
- m_Inja.add_callback(functionName, numberOfArgs, function);
+ bool retval = true;
+
+ for (const auto & entry : std::filesystem::directory_iterator(root))
+ {
+ std::string ext = std::filesystem::path(entry).extension();
+ bool found_extension = false;
+
+ for (const auto & extension : extensions)
+ {
+ if (ext == "." + extension)
+ {
+ found_extension = true;
+ break;
+ }
+ }
+
+ if (found_extension == true && exclude_extensions == false)
+ {
+ if (AddSingleFile(entry.path(), root) == false)
+ {
+ retval = false;
+ }
+ }
+ if (found_extension == false && exclude_extensions == true)
+ {
+ if (AddSingleFile(entry.path(), root) == false)
+ {
+ retval = false;
+ }
+ }
+ }
+
+ return retval;
}
-void Filesystem::AddVoidInjaCallback(std::string functionName, std::size_t numberOfArgs, inja::VoidCallbackFunction function)
+const std::unordered_map<std::string, struct file_data> & Filesystem::GetFiles() const
{
- m_Inja.add_void_callback(functionName, numberOfArgs, function);
+ return m_Files;
}
diff --git a/src/Filesystem.hpp b/src/Filesystem.hpp
index 7ebfb84..13733c9 100644
--- a/src/Filesystem.hpp
+++ b/src/Filesystem.hpp
@@ -2,28 +2,32 @@
#define FILESYSTEM_H 1
#include <inja/inja.hpp>
-#include <unordered_map>
#include <string>
+#include <unordered_map>
#include <vector>
-struct file_data {
- std::vector<unsigned char> data;
+struct file_data
+{
+ std::vector<unsigned char> data;
};
-class Filesystem {
+class Filesystem
+{
public:
- Filesystem() {}
- ~Filesystem() {}
+ Filesystem()
+ {
+ }
+ ~Filesystem()
+ {
+ }
- bool AddSingleFile(std::string path, std::string root);
- bool Scan(std::string root = "./wwwroot");
- void AddInjaCallback(std::string functionName, std::size_t numberOfArgs, inja::CallbackFunction function);
- void AddVoidInjaCallback(std::string functionName, std::size_t numberOfArgs, inja::VoidCallbackFunction function);
+ bool AddSingleFile(std::string path, std::string root);
+ bool Scan(std::string root = "./wwwroot");
+ bool Scan(std::string root, std::vector<std::string> extensions, bool exclude_extensions = false);
+ const std::unordered_map<std::string, struct file_data> & GetFiles() const;
private:
- std::unordered_map<std::string, struct file_data> m_Files;
- inja::TemplateStorage m_Templates;
- inja::Environment m_Inja;
+ std::unordered_map<std::string, struct file_data> m_Files;
};
#endif
diff --git a/src/RequestResponse.cpp b/src/RequestResponse.cpp
index be8a0d0..2567253 100644
--- a/src/RequestResponse.cpp
+++ b/src/RequestResponse.cpp
@@ -10,38 +10,38 @@ RequestResponse::~RequestResponse()
void RequestResponse::UseInputHeader()
{
- m_InputHeader = evhttp_request_get_input_headers(m_Request);
+ m_InputHeader = evhttp_request_get_input_headers(m_Request);
}
void RequestResponse::UseOutputHeader()
{
- m_OutputHeader = evhttp_request_get_output_headers(m_Request);
+ m_OutputHeader = evhttp_request_get_output_headers(m_Request);
}
-bool RequestResponse::AddOutputHeader(std::string & key, std::string & value)
+bool RequestResponse::AddOutputHeaderByRef(std::string & key, std::string & value)
{
- return evhttp_add_header(m_OutputHeader, key.c_str(), value.c_str());
+ return evhttp_add_header(m_OutputHeader, key.c_str(), value.c_str());
}
-bool RequestResponse::AddOutputHeader2(std::string key, std::string value)
+bool RequestResponse::AddOutputHeader(std::string key, std::string value)
{
- return AddOutputHeader(key, value);
+ return AddOutputHeaderByRef(key, value);
}
-bool RequestResponse::GetInputHeader(std::string & key, std::string & value)
+bool RequestResponse::GetInputHeaderByRef(std::string & key, std::string & value)
{
- char const * const v = evhttp_find_header(m_InputHeader, key.c_str());
+ char const * const v = evhttp_find_header(m_InputHeader, key.c_str());
- if (v == nullptr)
- {
- return false;
- }
+ if (v == nullptr)
+ {
+ return false;
+ }
- value = v;
- return true;
+ value = v;
+ return true;
}
-bool RequestResponse::GetInputHeader2(std::string key, std::string value)
+bool RequestResponse::GetInputHeader(std::string key, std::string value)
{
- return GetInputHeader(key, value);
+ return GetInputHeader(key, value);
}
diff --git a/src/RequestResponse.hpp b/src/RequestResponse.hpp
index 24577aa..8a7e1d3 100644
--- a/src/RequestResponse.hpp
+++ b/src/RequestResponse.hpp
@@ -5,24 +5,25 @@
#include <string>
-class RequestResponse {
+class RequestResponse
+{
public:
- RequestResponse(struct evhttp_request * const req);
- ~RequestResponse();
+ RequestResponse(struct evhttp_request * const req);
+ ~RequestResponse();
- void UseInputHeader();
- void UseOutputHeader();
+ void UseInputHeader();
+ void UseOutputHeader();
- bool AddOutputHeader(std::string & key, std::string & value);
- bool AddOutputHeader2(std::string key, std::string value);
+ bool AddOutputHeaderByRef(std::string & key, std::string & value);
+ bool AddOutputHeader(std::string key, std::string value);
- bool GetInputHeader(std::string & key, std::string & value);
- bool GetInputHeader2(std::string key, std::string value);
+ bool GetInputHeaderByRef(std::string & key, std::string & value);
+ bool GetInputHeader(std::string key, std::string value);
private:
- struct evhttp_request * const m_Request;
- struct evkeyvalq * m_InputHeader;
- struct evkeyvalq * m_OutputHeader;
+ struct evhttp_request * const m_Request;
+ struct evkeyvalq * m_InputHeader;
+ struct evkeyvalq * m_OutputHeader;
};
#endif
diff --git a/src/TemplateManager.cpp b/src/TemplateManager.cpp
new file mode 100644
index 0000000..06771ea
--- /dev/null
+++ b/src/TemplateManager.cpp
@@ -0,0 +1,57 @@
+#include "TemplateManager.hpp"
+
+#include <filesystem>
+
+TemplateManager::TemplateManager()
+{
+ AddInjaCallback("test_fn", 0, [](inja::Arguments & args) {
+ (void)args;
+ return "Just a test fn.";
+ });
+ AddInjaCallback("test_return_true", 0, [](inja::Arguments & args) {
+ (void)args;
+ return true;
+ });
+}
+
+void TemplateManager::ParseTemplates(Filesystem const & fs)
+{
+ for (auto & tpl : fs.GetFiles())
+ {
+ std::string tmpl(tpl.second.data.data(), tpl.second.data.data() + tpl.second.data.size());
+ m_Templates[tpl.first] = m_Inja.parse(tmpl);
+ std::cout << "File: " << tpl.first << " may contain a renderable template." << std::endl;
+ }
+}
+
+void TemplateManager::AddInjaCallback(std::string functionName,
+ std::size_t numberOfArgs,
+ inja::CallbackFunction function)
+{
+ m_Inja.add_callback(functionName, numberOfArgs, function);
+}
+
+void TemplateManager::AddVoidInjaCallback(std::string functionName,
+ std::size_t numberOfArgs,
+ inja::VoidCallbackFunction function)
+{
+ m_Inja.add_void_callback(functionName, numberOfArgs, function);
+}
+
+bool TemplateManager::TemplateExists(std::string const & templatePath)
+{
+ return m_Templates.find(templatePath) != m_Templates.end();
+}
+
+bool TemplateManager::RenderTemplate(std::string const & templatePath, RenderData const & rd, std::string & out)
+{
+ if (TemplateExists(templatePath) == false)
+ {
+ return false;
+ }
+
+ inja::json ij(rd);
+ out = m_Inja.render(m_Templates[templatePath].content, ij);
+
+ return true;
+}
diff --git a/src/TemplateManager.hpp b/src/TemplateManager.hpp
new file mode 100644
index 0000000..7b89d71
--- /dev/null
+++ b/src/TemplateManager.hpp
@@ -0,0 +1,28 @@
+#ifndef TEMPLATEMANAGER_H
+#define TEMPLATEMANAGER_H 1
+
+#include "Content.hpp"
+#include "Filesystem.hpp"
+
+#include <inja/inja.hpp>
+
+class TemplateManager
+{
+public:
+ TemplateManager();
+ ~TemplateManager()
+ {
+ }
+
+ void ParseTemplates(Filesystem const & fs);
+ void AddInjaCallback(std::string functionName, std::size_t numberOfArgs, inja::CallbackFunction function);
+ void AddVoidInjaCallback(std::string functionName, std::size_t numberOfArgs, inja::VoidCallbackFunction function);
+ bool TemplateExists(std::string const & templatePath);
+ bool RenderTemplate(std::string const & templatePath, RenderData const & rd, std::string & out);
+
+private:
+ inja::TemplateStorage m_Templates;
+ inja::Environment m_Inja;
+};
+
+#endif
diff --git a/src/content/blog/Blog.cpp b/src/content/blog/Blog.cpp
index f72ef70..56a23c1 100644
--- a/src/content/blog/Blog.cpp
+++ b/src/content/blog/Blog.cpp
@@ -1,37 +1,41 @@
#include "Blog.hpp"
-Blog::Blog(std::string baseUri, std::string templatePath) : TemplatedContent(templatePath), m_BaseUri(baseUri), m_Redirections()
+Blog::Blog(std::string uriBasePath, std::string mainTemplatePath)
+ : Content(), m_UriBasePath(uriBasePath), m_MainTemplatePath(mainTemplatePath)
{
- m_Redirections.push_back(baseUri + "-data");
+ m_Redirections.push_back(uriBasePath + "/");
+ m_Redirections.push_back(uriBasePath + "/index.html");
}
-bool Blog::Init(void)
+bool Blog::Init()
{
- return true;
+ return true;
}
-void Blog::Shutdown(void)
+void Blog::Shutdown()
{
}
-bool Blog::Render(RequestResponse & rr, std::string & out)
+bool Blog::Render(RequestResponse & rr, RenderData & rd)
{
- (void)rr;
+ rd["blah"] = "Yoh!";
+ rr.UseOutputHeader();
+ rr.AddOutputHeader("bla", "blubb");
- rr.UseOutputHeader();
- rr.AddOutputHeader2("bla", "blubb");
- out = "blog-bla";
+ return true;
+}
- return true;
+std::string const & Blog::GetUriBasePath() const
+{
+ return m_UriBasePath;
}
-std::string const & Blog::GetBaseUri(void) const
+std::string const & Blog::GetMainTemplate() const
{
- return m_BaseUri;
+ return m_MainTemplatePath;
}
-Redirections const &
-Blog::GetRedirections(void) const
+Redirections const & Blog::GetRedirections() const
{
- return m_Redirections;
+ return m_Redirections;
}
diff --git a/src/content/blog/Blog.hpp b/src/content/blog/Blog.hpp
index 1de6e0f..086acc7 100644
--- a/src/content/blog/Blog.hpp
+++ b/src/content/blog/Blog.hpp
@@ -3,21 +3,23 @@
#include "../../Content.hpp"
-class Blog : public TemplatedContent
+class Blog : public Content
{
public:
- explicit Blog(std::string baseUri, std::string templatePath);
+ explicit Blog(std::string uriBasePath, std::string mainTemplatePath);
- bool Init(void);
- void Shutdown(void);
- bool Render(RequestResponse & rr, std::string & out);
+ bool Init();
+ void Shutdown();
+ bool Render(RequestResponse & rr, RenderData & rd);
- std::string const & GetBaseUri() const;
- Redirections const & GetRedirections() const;
+ std::string const & GetUriBasePath() const;
+ std::string const & GetMainTemplate() const;
+ Redirections const & GetRedirections() const;
private:
- std::string m_BaseUri;
- Redirections m_Redirections;
+ std::string m_UriBasePath;
+ std::string m_MainTemplatePath;
+ Redirections m_Redirections;
};
#endif
diff --git a/src/main.cpp b/src/main.cpp
index 198f065..98f19c5 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,105 +1,131 @@
#include "ContentManager.hpp"
-#include "content/blog/Blog.hpp"
#include "EventManager.hpp"
#include "Filesystem.hpp"
+#include "TemplateManager.hpp"
+
+#include "content/blog/Blog.hpp"
#include <event2/buffer.h>
#include <inja/inja.hpp>
#include <iostream>
-static void example_inja_render(struct evhttp_request *const req,
- EvUserData ud) {
- (void)ud;
-
- inja::Environment env;
- nlohmann::json data;
- data["name"] = "Peter";
- data["city"] = "Brunswick";
- data["age"] = 29;
- data["names"] = {"Jeff", "Seb"};
- data["brother"]["name"] = "Chris";
- data["brother"]["daughters"] = {"Maria", "Helen"};
- data["brother"]["daughter0"] = {{"name", "Maria"}};
- data["is_happy"] = true;
- data["is_sad"] = false;
- data["relatives"]["mother"] = "Maria";
- data["relatives"]["brother"] = "Chris";
- data["relatives"]["sister"] = "Jenny";
- data["vars"] = {2, 3, 4, 0, -1, -2, -3};
-
- auto reply = env.render(
- "<html><body>\n"
- "Hello {{ name }}! I come from {{ city }}.<br>\n"
- "Hello {{ names.1 }}!<br>\n"
- "Hello {{ brother.name }}!<br>\n"
- "Hello {{ brother.daughter0.name }}!<br>\n"
- "{{ \"{{ no_value }}\" }}<br>\n"
- "Hello{# This is a comment #}!<br>\n"
- "{# --- #Todo --- #}<br>\n"
- "{% for name in names %}a{% endfor %}<br>\n"
- "Hello {% for name in names %}{{ name }} {% endfor %}!<br>\n"
- "Hello {% for name in names %}{{ loop.index }}: {{ name }}, {% "
- "endfor %}!<br>\n"
- "{% for type, name in relatives %}{{ type }}: {{ name }}, {% endfor "
- "%}<br>\n"
- "{% for v in vars %}{% if v > 0 %}+{% endif %}{% endfor %}<br>\n"
- "{% for name in names %}{{ loop.index }}: {{ name }}{% if not "
- "loop.is_last %}, {% endif %}{% endfor %}!<br>\n"
- "{% for name in names %}{{ loop.index }}: {{ name }}{% if "
- "loop.is_last == false %}, {% endif %}{% endfor %}!<br>\n"
- "{% for name in names %}a{% endfor %}<br>\n"
- "</body></html>\n",
- data);
-
- evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type",
- "text/html");
-
- struct evbuffer *const output = evbuffer_new();
- if (output != nullptr) {
- evbuffer_add(output, reply.c_str(), reply.size());
- evhttp_send_reply(req, 200, "OK", output);
- evbuffer_free(output);
- }
+static void example_inja_render(struct evhttp_request * const req, EvUserData ud)
+{
+ (void)ud;
+
+ inja::Environment env;
+ nlohmann::json data;
+ data["name"] = "Peter";
+ data["city"] = "Brunswick";
+ data["age"] = 29;
+ data["names"] = {"Jeff", "Seb"};
+ data["brother"]["name"] = "Chris";
+ data["brother"]["daughters"] = {"Maria", "Helen"};
+ data["brother"]["daughter0"] = {{"name", "Maria"}};
+ data["is_happy"] = true;
+ data["is_sad"] = false;
+ data["relatives"]["mother"] = "Maria";
+ data["relatives"]["brother"] = "Chris";
+ data["relatives"]["sister"] = "Jenny";
+ data["vars"] = {2, 3, 4, 0, -1, -2, -3};
+
+ auto reply = env.render(
+ "<html><body>\n"
+ "Hello {{ name }}! I come from {{ city }}.<br>\n"
+ "Hello {{ names.1 }}!<br>\n"
+ "Hello {{ brother.name }}!<br>\n"
+ "Hello {{ brother.daughter0.name }}!<br>\n"
+ "{{ \"{{ no_value }}\" }}<br>\n"
+ "Hello{# This is a comment #}!<br>\n"
+ "{# --- #Todo --- #}<br>\n"
+ "{% for name in names %}a{% endfor %}<br>\n"
+ "Hello {% for name in names %}{{ name }} {% endfor %}!<br>\n"
+ "Hello {% for name in names %}{{ loop.index }}: {{ name }}, {% "
+ "endfor %}!<br>\n"
+ "{% for type, name in relatives %}{{ type }}: {{ name }}, {% endfor "
+ "%}<br>\n"
+ "{% for v in vars %}{% if v > 0 %}+{% endif %}{% endfor %}<br>\n"
+ "{% for name in names %}{{ loop.index }}: {{ name }}{% if not "
+ "loop.is_last %}, {% endif %}{% endfor %}!<br>\n"
+ "{% for name in names %}{{ loop.index }}: {{ name }}{% if "
+ "loop.is_last == false %}, {% endif %}{% endfor %}!<br>\n"
+ "{% for name in names %}a{% endfor %}<br>\n"
+ "</body></html>\n",
+ data);
+
+ evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/html");
+
+ struct evbuffer * const output = evbuffer_new();
+ if (output != nullptr)
+ {
+ evbuffer_add(output, reply.c_str(), reply.size());
+ evhttp_send_reply(req, 200, "OK", output);
+ evbuffer_free(output);
+ }
}
-int main(int argc, char **argv) {
- char const *host = "127.0.0.1";
- uint16_t port = 9000;
-
- if (argc <= 1) {
- std::cout << "usage: cpp-web [HOST] [PORT] [WWWROOTs..]" << std::endl;
- }
-
- if (argc > 1) {
- host = argv[1];
- }
- if (argc > 2) {
- port = atoi(argv[2]);
- }
-
- Filesystem fs;
- for (auto i = 3; i < argc; ++i) {
- if (fs.Scan(argv[i]) != true) {
- return 1;
+int main(int argc, char ** argv)
+{
+ char const * host = "127.0.0.1";
+ uint16_t port = 9000;
+
+ if (argc <= 1 || argc > 5)
+ {
+ std::cout << "usage: cpp-web [HOST] [PORT] [STATIC-WWWROOT] [DYNAMIC-WWWROOT]" << std::endl;
+ if (argc > 5)
+ {
+ return 1;
+ }
}
- }
- fs.Scan();
- ContentManager ctmgr;
- ctmgr.RegisterModule(std::make_shared<Blog>("/blog", "index.html"));
+ if (argc > 1)
+ {
+ host = argv[1];
+ }
+ if (argc > 2)
+ {
+ port = atoi(argv[2]);
+ }
- if (ctmgr.InitAll() == false)
- {
- std::cout << "InitAll() failed." << std::endl;
- return 1;
- }
+ std::shared_ptr<Filesystem> static_fs = std::make_shared<Filesystem>();
+ if (argc > 3)
+ {
+ if (static_fs->Scan(argv[3]) != true)
+ {
+ return 1;
+ }
+ }
+ static_fs->Scan("./wwwroot", {"html", "tmpl"}, true);
+
+ Filesystem dynamic_fs;
+ if (argc > 4)
+ {
+ if (dynamic_fs.Scan(argv[4]) != true)
+ {
+ return 1;
+ }
+ }
+ dynamic_fs.Scan("./wwwroot", {"html", "tmpl"}, false);
+
+ std::shared_ptr<TemplateManager> tmgr = std::make_shared<TemplateManager>();
+ tmgr->ParseTemplates(dynamic_fs);
+
+ std::shared_ptr<ContentManager> ctmgr = std::make_shared<ContentManager>();
+ ctmgr->SetStaticFilesystem(static_fs);
+ ctmgr->SetTemplateSystem(tmgr);
+ ctmgr->RegisterModule(std::make_shared<Blog>("/blog", "index.html"));
+
+ if (ctmgr->InitAll() == false)
+ {
+ std::cout << "InitAll() failed." << std::endl;
+ return 1;
+ }
- EventManager evmgr;
- //evmgr.SetDefaultCallback(example_inja_render, {});
- evmgr.AddCallback("/bla", example_inja_render, {});
- evmgr.AddContentManager(ctmgr);
- evmgr.Init(host, port);
+ EventManager evmgr(ctmgr);
+ // evmgr.SetDefaultCallback(example_inja_render, {});
+ evmgr.AddCallback("/bla", example_inja_render, {});
+ evmgr.Init(host, port);
- //ctmgr.ShutdownAll();
+ // ctmgr.ShutdownAll();
}
diff --git a/wwwroot/index.html b/wwwroot/index.html
index c0edd6c..002ea72 100644
--- a/wwwroot/index.html
+++ b/wwwroot/index.html
@@ -1,31 +1,8 @@
<html><body>
- Hello {{ name }}! I come from {{ city }}.<br>
-
- Hello {{ names.1 }}!<br>
-
- Hello {{ brother.name }}!<br>
-
- Hello {{ brother.daughter0.name }}!<br>
-
- {{ \"{{ no_value }}\" }}<br>
-
- Hello{# This is a comment #}!<br>
-
- {# --- #Todo --- #}<br>
-
- {% for name in names %}a{% endfor %}<br>
-
- Hello {% for name in names %}{{ name }} {% endfor %}!<br>
-
- Hello {% for name in names %}{{ loop.index }}: {{ name }}, {% endfor %}!<br>
-
- {% for type, name in relatives %}{{ type }}: {{ name }}, {% endfor %}<br>
-
- {% for v in vars %}{% if v > 0 %}+{% endif %}{% endfor %}<br>
-
- {% for name in names %}{{ loop.index }}: {{ name }}{% if not loop.is_last %}, {% endif %}{% endfor %}!<br>
-
- {% for name in names %}{{ loop.index }}: {{ name }}{% if loop.is_last == false %}, {% endif %}{% endfor %}!<br>
-
- {% for name in names %}a{% endfor %}<br>
+<p>
+<b>blabla</b>
+Test fn....: <b>{{ test_fn }}</b><br>
+Test RetFN.: <b>{{ test_return_true }}</b><br>
+Blog Render: <b>{{ blah }}</b><br>
+</p>
</body></html>
diff --git a/wwwroot/index.tmpl b/wwwroot/index.tmpl
new file mode 100644
index 0000000..b42f18c
--- /dev/null
+++ b/wwwroot/index.tmpl
@@ -0,0 +1 @@
+<html><body><b>INDEX TMPL</b></body></html>