diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/EventManager.cpp | 6 | ||||
-rw-r--r-- | src/EventManager.hpp | 1 | ||||
-rw-r--r-- | src/Filesystem.cpp | 14 | ||||
-rw-r--r-- | src/Filesystem.hpp | 3 | ||||
-rw-r--r-- | src/TemplateManager.cpp | 63 | ||||
-rw-r--r-- | src/content/blog/Blog.cpp | 54 | ||||
-rw-r--r-- | src/content/blog/Blog.hpp | 4 | ||||
-rw-r--r-- | src/content/markdown/Markdown.cpp | 32 | ||||
-rw-r--r-- | src/main.cpp | 57 |
9 files changed, 128 insertions, 106 deletions
diff --git a/src/EventManager.cpp b/src/EventManager.cpp index 6c735a8..d45dcee 100644 --- a/src/EventManager.cpp +++ b/src/EventManager.cpp @@ -189,13 +189,15 @@ bool EventManager::Init(std::string host, uint16_t port) } 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) + if (evhttp_bind_socket(m_EvHttp, host.c_str(), port) != 0) { fprintf(stderr, "couldn't bind to %s:%d. Exiting.\n", host.c_str(), port); return false; } + evhttp_set_allowed_methods(m_EvHttp, EVHTTP_REQ_GET | EVHTTP_REQ_POST | EVHTTP_REQ_HEAD); + evhttp_set_default_content_type(m_EvHttp, NULL); + m_EvTermEvent = evsignal_new(m_EvBase, SIGINT, do_term, m_EvBase); if (m_EvTermEvent == nullptr) { diff --git a/src/EventManager.hpp b/src/EventManager.hpp index 5d74602..f994510 100644 --- a/src/EventManager.hpp +++ b/src/EventManager.hpp @@ -42,7 +42,6 @@ private: 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; }; diff --git a/src/Filesystem.cpp b/src/Filesystem.cpp index 04dbb1b..9fe13bb 100644 --- a/src/Filesystem.cpp +++ b/src/Filesystem.cpp @@ -72,8 +72,18 @@ bool Filesystem::AddSingleFile(std::string path, std::string root) std::cout << "Adding file: " << path << " (" << size << " bytes) as " << relpath << " to " << this << std::endl; } - fd.mime = magic_file(m_Magic, path.c_str()); - m_Files[relpath] = fd; + { + char const * const mp = magic_file(m_Magic, path.c_str()); + if (mp != NULL) + { + fd.mime = magic_file(m_Magic, path.c_str()); + } + else + { + fd.mime = "application/octet-stream"; + } + m_Files[relpath] = fd; + } return true; } diff --git a/src/Filesystem.hpp b/src/Filesystem.hpp index 02150fb..98fbdcd 100644 --- a/src/Filesystem.hpp +++ b/src/Filesystem.hpp @@ -9,11 +9,12 @@ #include <vector> using FilesDict = std::unordered_map<std::string, struct file_data>; +using Data = std::vector<unsigned char>; struct file_data { std::string mime; - std::vector<unsigned char> data; + Data data; }; class Filesystem diff --git a/src/TemplateManager.cpp b/src/TemplateManager.cpp index ddde2c4..1e027f2 100644 --- a/src/TemplateManager.cpp +++ b/src/TemplateManager.cpp @@ -4,36 +4,45 @@ 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; - }); + 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; + }); /* * indent(input: str, width: int, first: bool, blank: bool); */ - AddInjaCallback("indent", 4, [](inja::Arguments & args) { - std::stringstream stream(args.at(0)->get<std::string>()); - std::string line, out; - bool is_first_line = true; - while (std::getline(stream, line)) - { - if (is_first_line == false || args.at(2)->get<bool>() == true) - { - if (line != "" || args.at(3)->get<bool>() == false) - { - line.insert(0, args.at(1)->get<std::size_t>(), ' '); - } - } - line += '\n'; - out += line; - is_first_line = false; - } - return out; - }); + AddInjaCallback("indent", + 4, + [](inja::Arguments & args) + { + std::stringstream stream(args.at(0)->get<std::string>()); + std::string line, out; + bool is_first_line = true; + while (std::getline(stream, line)) + { + if (is_first_line == false || args.at(2)->get<bool>() == true) + { + if (line != "" || args.at(3)->get<bool>() == false) + { + line.insert(0, args.at(1)->get<std::size_t>(), ' '); + } + } + line += '\n'; + out += line; + is_first_line = false; + } + return out; + }); } void TemplateManager::ParseTemplates(Filesystem & fs) diff --git a/src/content/blog/Blog.cpp b/src/content/blog/Blog.cpp index d2a66c8..ba8638e 100644 --- a/src/content/blog/Blog.cpp +++ b/src/content/blog/Blog.cpp @@ -41,9 +41,9 @@ bool Blog::Init() m_Redirections.push_back(std::filesystem::path(jfile.first).stem()); } - std::sort(m_BlogEntriesSortedByDate.begin(), m_BlogEntriesSortedByDate.end(), [](auto const & a, auto const & b) { - return a->publishDate > b->publishDate; - }); + std::sort(m_BlogEntriesSortedByDate.begin(), + m_BlogEntriesSortedByDate.end(), + [](auto const & a, auto const & b) { return a->publishDate > b->publishDate; }); m_BlogContents.Init(); @@ -100,17 +100,19 @@ bool Blog::ValidateAndSetMetdadata(BlogMetadata const & blogMetadata, BlogEntry { bool retval = true; std::function<bool(BlogMetadata const &, std::string const)> validateMetadata = - [blogEntry](BlogMetadata const & bm, std::string const tname) { - if (bm.find(tname) == bm.cend()) - { - std::cerr << "Metadata validation: JSON key '" << tname << "' missing in " - << blogEntry->metadata_filename << std::endl; - return false; - } - return true; - }; - std::function<bool(std::string const &, std::time_t &)> parseDateTime = [](std::string const & timeStr, - std::time_t & time) { + [blogEntry](BlogMetadata const & bm, std::string const tname) + { + if (bm.find(tname) == bm.cend()) + { + std::cerr << "Metadata validation: JSON key '" << tname << "' missing in " << blogEntry->metadata_filename + << std::endl; + return false; + } + return true; + }; + std::function<bool(std::string const &, std::time_t &)> parseDateTime = + [](std::string const & timeStr, std::time_t & time) + { std::tm tm = {}; std::stringstream ss(timeStr); ss >> std::get_time(&tm, "%d.%m.%y %H:%M"); @@ -124,6 +126,27 @@ bool Blog::ValidateAndSetMetdadata(BlogMetadata const & blogMetadata, BlogEntry return true; }; + if (validateMetadata(blogMetadata, "title") == false) + { + retval = false; + } + blogEntry->title = blogMetadata["title"]; + + if (validateMetadata(blogMetadata, "tags") == false) + { + retval = false; + } + for (auto const & tag : blogMetadata["tags"]) + { + blogEntry->tags.push_back(tag); + } + + if (validateMetadata(blogMetadata, "author") == false) + { + retval = false; + } + blogEntry->author = blogMetadata["author"]; + if (validateMetadata(blogMetadata, "createDate") == false || parseDateTime(blogMetadata["createDate"], blogEntry->createDate) == false) { @@ -184,6 +207,9 @@ void Blog::GenerateBlogListing(RenderData & rd) RenderData re; re["metadata_filename"] = e->metadata_filename; re["content_filename"] = e->content_filename; + re["title"] = e->title; + re["tags"] = e->tags; + re["author"] = e->author; re["createDate"] = e->createDate; re["publishDate"] = e->publishDate; re["published"] = e->published; diff --git a/src/content/blog/Blog.hpp b/src/content/blog/Blog.hpp index f577d69..d99185a 100644 --- a/src/content/blog/Blog.hpp +++ b/src/content/blog/Blog.hpp @@ -16,6 +16,10 @@ struct blog_entry std::string const metadata_filename; std::string const content_filename; + + std::string title; + std::vector<std::string> tags; + std::string author; std::time_t createDate; std::time_t publishDate; bool published; diff --git a/src/content/markdown/Markdown.cpp b/src/content/markdown/Markdown.cpp index 63358b4..a85f333 100644 --- a/src/content/markdown/Markdown.cpp +++ b/src/content/markdown/Markdown.cpp @@ -1,5 +1,7 @@ #include "Markdown.hpp" +#include <md4c-html.h> + Markdown::Markdown(std::string uriBasePath, std::string markdownFilesPath, std::string mainTemplatePath) : Content(), m_UriBasePath(uriBasePath), @@ -8,6 +10,13 @@ Markdown::Markdown(std::string uriBasePath, std::string markdownFilesPath, std:: { } +extern "C" void markdown_to_html_conversion(const MD_CHAR * const text, MD_SIZE size, void * const userdata) +{ + std::string * html = (std::string *)userdata; + + html->append(text, size); +} + bool Markdown::Init() { std::cout << "Markdown files path: " << m_MarkdownFilesPath << std::endl; @@ -22,8 +31,27 @@ bool Markdown::Init() for (auto const & mfile : fs.GetFiles()) { - m_Markdowns[mfile.first] = - std::make_shared<std::string>(std::string(mfile.second.data.begin(), mfile.second.data.end())); + Data const & data = mfile.second.data; + std::string html; + + html.reserve(data.size() / 8 + 64); + int ret = md_html((MD_CHAR const *)data.data(), + data.size(), + markdown_to_html_conversion, + &html, + MD_DIALECT_GITHUB, + MD_FLAG_COLLAPSEWHITESPACE | MD_FLAG_PERMISSIVEURLAUTOLINKS | MD_FLAG_PERMISSIVEWWWAUTOLINKS | + MD_FLAG_PERMISSIVEEMAILAUTOLINKS | MD_FLAG_PERMISSIVEAUTOLINKS | MD_FLAG_TABLES | + MD_FLAG_STRIKETHROUGH | MD_FLAG_LATEXMATHSPANS | MD_FLAG_WIKILINKS | MD_FLAG_TASKLISTS | + MD_FLAG_UNDERLINE); + + if (ret != 0) + { + std::cerr << "Markdown HTML rendering failed." << std::endl; + return false; + } + + m_Markdowns[mfile.first] = std::make_shared<std::string>(html); } return true; diff --git a/src/main.cpp b/src/main.cpp index 50f0ec5..4969d70 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,61 +11,6 @@ #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); - } -} - int main(int argc, char ** argv) { char const * host = "127.0.0.1"; @@ -130,8 +75,6 @@ int main(int argc, char ** argv) } EventManager evmgr(ctmgr); - // evmgr.SetDefaultCallback(example_inja_render, {}); - evmgr.AddCallback("/bla", example_inja_render, {}); evmgr.Init(host, port); // ctmgr.ShutdownAll(); |