summaryrefslogtreecommitdiffhomepage
path: root/plugins/weblog/weblog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/weblog/weblog.cpp')
-rw-r--r--plugins/weblog/weblog.cpp101
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) + "\">&lt;&lt;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&gt;&gt;</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);