diff options
author | Roland Reichwein <mail@reichwein.it> | 2020-04-28 19:00:17 +0200 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2020-04-28 19:00:17 +0200 |
commit | 095c82585f2e4a9963c33c0988d453b0278bc0c7 (patch) | |
tree | af345d356a84278f4df9cf7b999871a9bfba4bd8 /plugins/weblog/weblog.cpp | |
parent | 37da545bc5f1bd5c3d810699cc685c36cdcd27fa (diff) |
Paged list
Diffstat (limited to 'plugins/weblog/weblog.cpp')
-rw-r--r-- | plugins/weblog/weblog.cpp | 101 |
1 files changed, 86 insertions, 15 deletions
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 <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/replace.hpp> #include <boost/property_tree/ptree.hpp> @@ -152,7 +154,7 @@ namespace { } } - std::vector<ArticleInfo> getArticleList(fs::path& path) + std::vector<ArticleInfo> getArticleList(fs::path& path, size_t page) { std::vector<ArticleInfo> 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<std::string(const std::string& key)>& GetRequestParam, - std::function<plugin_interface_setter_type>& SetResponseHeader) + std::function<plugin_interface_setter_type>& SetResponseHeader, + size_t page) { try { HtmlPage htmlPage{GetRequestParam, "<h1>"s + GetRequestParam("WEBLOG_NAME") + "</h1>"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{"<a href=\"" + (link / article.path.filename()).string() + "/\">"}; - std::string linkend{"</a>"}; - htmlPage += "<h2>"s + linkstart + article.subject + linkend + "</h2>"s + article.date + "<br/>"s; - - auto sv{shortVersion(article.path)}; - if (sv.size()) { - htmlPage += sv + " "s + linkstart + "more..." + linkend; + else { + for (const auto& article: list) { + std::string linkstart{"<a href=\"" + (link / article.path.filename()).string() + "/\">"}; + std::string linkend{"</a>"}; + htmlPage += "<h2>"s + linkstart + article.subject + linkend + "</h2>"s + article.date + "<br/>"s; + + auto sv{shortVersion(article.path)}; + if (sv.size()) { + htmlPage += sv + " "s + linkstart + "more..." + linkend; + } } + htmlPage += "<br/><br/><br/>"; + if (page > 0) + htmlPage += "<a href=\"?page="s + std::to_string(page - 1) + "\"><<newer</a> "s; + htmlPage += "page "s + std::to_string(page + 1); + if (list.size() == number_of_articles_on_front_page) + htmlPage += " <a href=\"?page="s + std::to_string(page + 1) + "\">older>></a>"s; + htmlPage += "<br/>"; } 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<char>(i); + } catch (...) { + return result; + } + + pos += 2; + } else { + result += c; + } + pos++; + } + + return result; + } + + std::unordered_map<std::string, std::string> SplitQueryString(std::string& s) + { + std::unordered_map<std::string, std::string> 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<std::string, std::string> 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); |