From 095c82585f2e4a9963c33c0988d453b0278bc0c7 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Tue, 28 Apr 2020 19:00:17 +0200 Subject: Paged list --- plugins/weblog/weblog.cpp | 101 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 86 insertions(+), 15 deletions(-) (limited to 'plugins/weblog/weblog.cpp') diff --git a/plugins/weblog/weblog.cpp b/plugins/weblog/weblog.cpp index 07b6447..a69fdb6 100644 --- a/plugins/weblog/weblog.cpp +++ b/plugins/weblog/weblog.cpp @@ -1,5 +1,7 @@ #include "weblog.h" +#include "stringutil.h" + #include #include #include @@ -152,7 +154,7 @@ namespace { } } - std::vector getArticleList(fs::path& path) + std::vector getArticleList(fs::path& path, size_t page) { std::vector result; @@ -166,11 +168,12 @@ namespace { } } - size_t size{std::min(number_of_articles_on_front_page, result.size())}; + size_t index0{std::min(number_of_articles_on_front_page * (page), result.size())}; + size_t index1{std::min(number_of_articles_on_front_page * (page + 1), result.size())}; // sort backwards - std::partial_sort(result.begin(), result.begin() + size, result.end(), [](const ArticleInfo& a0, const ArticleInfo& a1){ return a0.date > a1.date;}); + std::partial_sort(result.begin(), result.begin() + index1, result.end(), [](const ArticleInfo& a0, const ArticleInfo& a1){ return a0.date > a1.date;}); - return {result.begin(), result.begin() + size}; + return {result.begin() + index0, result.begin() + index1}; } std::string plainTextFromPTree(const pt::ptree& tree) @@ -271,25 +274,35 @@ namespace { std::string generateIndexPage(fs::path& path, std::function& GetRequestParam, - std::function& SetResponseHeader) + std::function& SetResponseHeader, + size_t page) { try { HtmlPage htmlPage{GetRequestParam, "

"s + GetRequestParam("WEBLOG_NAME") + "

"s}; fs::path link{ GetRequestParam("rel_target")}; - auto list{getArticleList(path)}; + auto list{getArticleList(path, page)}; if (list.empty()) htmlPage += "(no articles found.)"; - for (const auto& article: list) { - std::string linkstart{""}; - std::string linkend{""}; - htmlPage += "

"s + linkstart + article.subject + linkend + "

"s + article.date + "
"s; - - auto sv{shortVersion(article.path)}; - if (sv.size()) { - htmlPage += sv + " "s + linkstart + "more..." + linkend; + else { + for (const auto& article: list) { + std::string linkstart{""}; + std::string linkend{""}; + htmlPage += "

"s + linkstart + article.subject + linkend + "

"s + article.date + "
"s; + + auto sv{shortVersion(article.path)}; + if (sv.size()) { + htmlPage += sv + " "s + linkstart + "more..." + linkend; + } } + htmlPage += "


"; + if (page > 0) + htmlPage += "<<newer "s; + htmlPage += "page "s + std::to_string(page + 1); + if (list.size() == number_of_articles_on_front_page) + htmlPage += " older>>"s; + htmlPage += "
"; } return htmlPage; } catch (const std::exception& ex) { @@ -334,6 +347,56 @@ namespace { } } + std::string urlDecode(std::string s) + { + std::string result; + + size_t pos = 0; + while (pos < s.size()) { + char c {s[pos]}; + if (c == '+') { + result += ' '; + } else if (c == '%' && pos + 2 < s.size()) { + try { + int i = stoi(s.substr(pos + 1, 2), 0, 16); + if (i < 0 || i > 255) + return result; + + result += static_cast(i); + } catch (...) { + return result; + } + + pos += 2; + } else { + result += c; + } + pos++; + } + + return result; + } + + std::unordered_map SplitQueryString(std::string& s) + { + std::unordered_map result; + + size_t qpos = s.find('?'); + if (qpos != s.npos) { + auto list {split(s.substr(qpos + 1), "&")}; + for (auto i: list) { + size_t apos = i.find('='); + if (apos != i.npos) { + result[urlDecode(i.substr(0, apos))] = urlDecode(i.substr(apos + 1)); + } + } + } + + s = s.substr(0, qpos); + + return result; + } + } // anonymous namespace std::string weblog_plugin::name() @@ -370,6 +433,8 @@ std::string weblog_plugin::generate_page( return HttpStatus("400", "Illegal request: "s + target, SetResponseHeader); } + std::unordered_map query { SplitQueryString(rel_target) }; + // Build the path to the requested file std::string doc_root{GetRequestParam("doc_root")}; if (rel_target.size() >= 4 && std::all_of(rel_target.begin(), rel_target.begin() + 4, isdigit)) { @@ -384,8 +449,14 @@ std::string weblog_plugin::generate_page( SetResponseHeader("content_type", "text/html"); + size_t page {0}; + auto it {query.find("page")}; + if (it != query.end()) { + page = stoul(it->second); + } + if (is_index_page(rel_target)) - return generateIndexPage(path, GetRequestParam, SetResponseHeader); + return generateIndexPage(path, GetRequestParam, SetResponseHeader, page); if (is_article_page(rel_target, path)) return generateArticlePage(path, GetRequestParam, SetResponseHeader); -- cgit v1.2.3