Comparar commits
14 Commits
0325cdf936
...
d3bd5f79cc
Autor | SHA1 | Data | |
---|---|---|---|
d3bd5f79cc | |||
995a980d49 | |||
2ee760d9ca | |||
ffeea8cfd1 | |||
a81963181a | |||
d18c0669ce | |||
ecd45a61c8 | |||
2b1c3c71b7 | |||
a1042720a7 | |||
6dbe8d34dc | |||
51b259f385 | |||
0cad11004f | |||
2102cf4e6b | |||
86890660f4 |
@ -129,9 +129,8 @@ std::optional<Revision> RevisionDaoSqlite::getCurrentForPage(std::string pagenam
|
||||
try
|
||||
{
|
||||
auto query = *db << "SELECT (SELECT username FROM user WHERE id = author), comment, content, "
|
||||
"strftime('%s',creationtime), page, revisionid FROM revision WHERE page = (SELECT id FROM "
|
||||
"page WHERE name = ? ) AND revisionid = (SELECT lastrevision FROM page WHERE name = ?)";
|
||||
query << pagename << pagename;
|
||||
"strftime('%s',creationtime), page.name, revisionid FROM revision INNER JOIN page ON revision.page = page.id WHERE page.name = ? AND page.lastrevision = revision.revisionid";
|
||||
query << pagename;
|
||||
query >>
|
||||
std::tie(result.author, result.comment, result.content, result.timestamp, result.page, result.revision);
|
||||
}
|
||||
@ -155,7 +154,7 @@ std::optional<Revision> RevisionDaoSqlite::getRevisionForPage(std::string pagena
|
||||
auto query =
|
||||
*db
|
||||
<< "SELECT (SELECT username FROM user WHERE id = author), comment, content, strftime('%s',creationtime), "
|
||||
"page, revisionid FROM revision WHERE page = (SELECT id FROM page WHERE name = ? ) AND revisionid = ?";
|
||||
"page.name, revisionid FROM revision INNER JOIN page ON revision.page = page.id WHERE page.name = ? AND revisionid = ? ";
|
||||
query << pagename << revision;
|
||||
query >>
|
||||
std::tie(result.author, result.comment, result.content, result.timestamp, result.page, result.revision);
|
||||
|
28
dynamic/dynamiccontentfactory.h
Arquivo normal
28
dynamic/dynamiccontentfactory.h
Arquivo normal
@ -0,0 +1,28 @@
|
||||
#ifndef DYNAMICCONTENTFACTORY_H
|
||||
#define DYNAMICCONTENTFACTORY_H
|
||||
|
||||
#include "dynamiccontent.h"
|
||||
|
||||
class DynamicContentFactory
|
||||
{
|
||||
private:
|
||||
Template *templ;
|
||||
Database *db;
|
||||
UrlProvider *urlProvider;
|
||||
|
||||
public:
|
||||
DynamicContentFactory(Template &templ, Database &db, UrlProvider &urlProvider)
|
||||
{
|
||||
this->templ = &templ;
|
||||
this->db = &db;
|
||||
this->urlProvider = &urlProvider;
|
||||
}
|
||||
|
||||
template <class T> inline std::shared_ptr<T> createDynamicContent()
|
||||
{
|
||||
return std::make_shared<T>(*this->templ, *this->db, *this->urlProvider);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
#endif // DYNAMICCONTENTFACTORY_H_INCLUDED
|
@ -6,7 +6,11 @@ std::string DynamicContentIncludePage::render()
|
||||
auto rev = revisionDao->getCurrentForPage(this->argument);
|
||||
if(rev)
|
||||
{
|
||||
return rev->content;
|
||||
/* Quite dirty */
|
||||
if(rev->content.find("[cmd:allowinclude]1[") != std::string::npos)
|
||||
{
|
||||
return rev->content;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "handlerfeedgenerator.h"
|
||||
#include "../parser.h"
|
||||
#include "../revisionrenderer.h"
|
||||
std::vector<HandlerFeedGenerator::EntryRevisionPair> HandlerFeedGenerator::fetchEntries(
|
||||
std::vector<std::string> categories)
|
||||
{
|
||||
@ -67,6 +68,8 @@ std::string HandlerFeedGenerator::generateAtom(const std::vector<HandlerFeedGene
|
||||
subtitle = "All pages";
|
||||
}
|
||||
|
||||
RevisionRenderer revisionRenderer { *this->templ, *this->database, *this->urlProvider };
|
||||
|
||||
for(const EntryRevisionPair &entry : entries)
|
||||
{
|
||||
const Page &page = entry.first;
|
||||
@ -82,13 +85,12 @@ std::string HandlerFeedGenerator::generateAtom(const std::vector<HandlerFeedGene
|
||||
std::string entryurl =
|
||||
this->urlProvider->combine({this->urlProvider->rootUrl(), this->urlProvider->page(page.name)});
|
||||
TemplatePage atomentry = this->templ->getPage("feeds/atomentry");
|
||||
atomentry.setVar("entrytitle", utils::html_xss(page.title));
|
||||
atomentry.setVar("entrytitle", page.title);
|
||||
atomentry.setVar("entryurl", utils::html_xss(entryurl));
|
||||
atomentry.setVar("entryid", utils::html_xss(entryurl));
|
||||
atomentry.setVar("entrypublished", entryPublished);
|
||||
atomentry.setVar("entryupdated", entryUpdated);
|
||||
Parser parser;
|
||||
atomentry.setVar("entrycontent", utils::html_xss(parser.parse(*pageDao, *this->urlProvider, current.content)));
|
||||
atomentry.setVar("entrycontent", utils::html_xss(revisionRenderer.renderContent(current, page.title)));
|
||||
stream << atomentry.render();
|
||||
}
|
||||
stream << atomfooter;
|
||||
|
@ -23,6 +23,7 @@ SOFTWARE.
|
||||
#include "../request.h"
|
||||
|
||||
#include "../parser.h"
|
||||
#include "../revisionrenderer.h"
|
||||
bool HandlerPageEdit::canAccess([[maybe_unused]] std::string page)
|
||||
{
|
||||
return effectivePermissions(page).canEdit();
|
||||
@ -41,7 +42,7 @@ Response HandlerPageEdit::handleRequest(PageDao &pageDao, std::string pagename,
|
||||
return errorResponse("No permission", "You don't have permission to create new pages");
|
||||
}
|
||||
auto revisiondao = this->database->createRevisionDao();
|
||||
auto revision = this->database->createRevisionDao()->getCurrentForPage(pagename);
|
||||
auto revision = revisiondao->getCurrentForPage(pagename);
|
||||
std::string body;
|
||||
|
||||
unsigned int current_revision = 0;
|
||||
@ -50,6 +51,15 @@ Response HandlerPageEdit::handleRequest(PageDao &pageDao, std::string pagename,
|
||||
body = revision->content;
|
||||
current_revision = revision->revision;
|
||||
}
|
||||
std::string from = r.get("frompage");
|
||||
if(!from.empty())
|
||||
{
|
||||
if(!effectivePermissions(from).canRead())
|
||||
{
|
||||
return this->errorResponse("Permission denied", "No access permissions, so you can't use this page as a template");
|
||||
}
|
||||
body = revisiondao->getCurrentForPage(from)->content;
|
||||
}
|
||||
if(r.getRequestMethod() == "POST")
|
||||
{
|
||||
if(r.post("do") == "submit")
|
||||
@ -115,12 +125,16 @@ Response HandlerPageEdit::handleRequest(PageDao &pageDao, std::string pagename,
|
||||
{
|
||||
std::string newContent = r.post("content");
|
||||
Parser parser;
|
||||
std::string title = parser.extractCommand("pagetitle", newContent);
|
||||
TemplatePage templatePage = this->templ->getPage("page_creation_preview");
|
||||
templatePage.setVar("actionurl", urlProvider->editPage(pagename));
|
||||
templatePage.setVar("preview_content", parser.parse(pageDao, *this->urlProvider, newContent));
|
||||
|
||||
RevisionRenderer revisionRenderer { *this->templ, *this->database, *this->urlProvider };
|
||||
|
||||
templatePage.setVar("preview_content", revisionRenderer.renderContent(newContent));
|
||||
templatePage.setVar("content", newContent);
|
||||
setPageVars(templatePage, pagename);
|
||||
templatePage.setVar("title", createPageTitle("Preview: " + pagename));
|
||||
templatePage.setVar("title", createPageTitle("Preview: " + title));
|
||||
templatePage.setVar("comment", r.post("comment"));
|
||||
Response response;
|
||||
response.setBody(templatePage.render());
|
||||
|
@ -27,6 +27,7 @@ SOFTWARE.
|
||||
#include "../dynamic/dynamiccontentincludepage.h"
|
||||
#include "../dynamic/dynamiccontentsetvar.h"
|
||||
#include "../dynamic/dynamiccontentgetvar.h"
|
||||
#include "../revisionrenderer.h"
|
||||
|
||||
bool HandlerPageView::canAccess(std::string page)
|
||||
{
|
||||
@ -90,19 +91,20 @@ Response HandlerPageView::handleRequest(PageDao &pageDao, std::string pagename,
|
||||
|
||||
std::optional<Revision> revision;
|
||||
std::string templatepartname;
|
||||
auto revisionDao = this->database->createRevisionDao();
|
||||
try
|
||||
{
|
||||
if(revisionid > 0)
|
||||
{
|
||||
if(!effectivePermissions(pagename).canSeePageHistory())
|
||||
{
|
||||
auto current = this->database->createRevisionDao()->getCurrentForPage(pagename);
|
||||
auto current = revisionDao->getCurrentForPage(pagename);
|
||||
if(current && current->revision > revisionid)
|
||||
{
|
||||
return errorResponse("Error", "You are not allowed to view older revisions of this page");
|
||||
}
|
||||
}
|
||||
revision = this->database->createRevisionDao()->getRevisionForPage(pagename, revisionid);
|
||||
revision = revisionDao->getRevisionForPage(pagename, revisionid);
|
||||
if(!revision)
|
||||
{
|
||||
return errorResponse("Revision not found", "No such revision found");
|
||||
@ -122,7 +124,7 @@ Response HandlerPageView::handleRequest(PageDao &pageDao, std::string pagename,
|
||||
return r;
|
||||
}
|
||||
}
|
||||
revision = this->database->createRevisionDao()->getCurrentForPage(pagename);
|
||||
revision = revisionDao->getCurrentForPage(pagename);
|
||||
templatepartname = "page_view";
|
||||
}
|
||||
}
|
||||
@ -132,82 +134,20 @@ Response HandlerPageView::handleRequest(PageDao &pageDao, std::string pagename,
|
||||
return errorResponse("Database error", "While trying to fetch revision, a database error occured");
|
||||
}
|
||||
|
||||
TemplatePage page = this->templ->getPage(templatepartname);
|
||||
|
||||
Parser parser;
|
||||
Response result;
|
||||
result.setStatus(200);
|
||||
std::string indexcontent;
|
||||
std::string parsedcontent;
|
||||
|
||||
std::map<std::string, std::string> dynamicVarsMap;
|
||||
std::function<std::string(std::string_view, std::string_view)> dynamicParseCallback =
|
||||
[&](std::string_view key, std::string_view value) -> std::string
|
||||
{
|
||||
if(key == "dynamic:postlist")
|
||||
{
|
||||
std::shared_ptr<DynamicContentPostList> postlist = createDynamic<DynamicContentPostList>();
|
||||
postlist->setArgument(std::string(value));
|
||||
return postlist->render();
|
||||
}
|
||||
if(key == "dynamic:includepage")
|
||||
{
|
||||
if((effectivePermissions(std::string(value)).canRead()))
|
||||
{
|
||||
std::shared_ptr<DynamicContentIncludePage> includePage = createDynamic<DynamicContentIncludePage>();
|
||||
includePage->setArgument(std::string(value));
|
||||
return parser.parseDynamics(includePage->render(), dynamicParseCallback);
|
||||
}
|
||||
}
|
||||
if(key == "dynamic:setvar")
|
||||
{
|
||||
std::shared_ptr<DynamicContentSetVar> setVar = createDynamic<DynamicContentSetVar>();
|
||||
setVar->setMap(dynamicVarsMap);
|
||||
setVar->setArgument(std::string(value));
|
||||
return setVar->render();
|
||||
}
|
||||
if(key == "dynamic:getvar")
|
||||
{
|
||||
std::shared_ptr<DynamicContentGetVar> getVar = createDynamic<DynamicContentGetVar>();
|
||||
getVar->setMap(dynamicVarsMap);
|
||||
getVar->setArgument(std::string(value));
|
||||
return getVar->render();
|
||||
}
|
||||
return std::string{};
|
||||
};
|
||||
std::string resolvedContent = parser.parseDynamics(revision->content, dynamicParseCallback);
|
||||
if(revisionid > 0)
|
||||
{
|
||||
indexcontent = createIndexContent(parser, resolvedContent);
|
||||
parsedcontent = parser.parse(pageDao, *this->urlProvider, resolvedContent);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string cachekeyindexcontent = "page:indexcontent:" + pagename;
|
||||
std::string cachekeyparsedcontent = "page:parsedcontent:" + pagename;
|
||||
auto cachedindexcontent = this->cache->get(cachekeyindexcontent);
|
||||
auto cachedparsedcontent = this->cache->get(cachekeyparsedcontent);
|
||||
if(cachedindexcontent)
|
||||
{
|
||||
indexcontent = *cachedindexcontent;
|
||||
}
|
||||
else
|
||||
{
|
||||
indexcontent = createIndexContent(parser, resolvedContent);
|
||||
this->cache->put(cachekeyindexcontent, indexcontent);
|
||||
}
|
||||
if(cachedparsedcontent)
|
||||
{
|
||||
parsedcontent = *cachedparsedcontent;
|
||||
}
|
||||
else
|
||||
{
|
||||
parsedcontent = parser.parse(pageDao, *this->urlProvider, resolvedContent);
|
||||
this->cache->put(cachekeyparsedcontent, parsedcontent);
|
||||
}
|
||||
}
|
||||
std::string revisionstr = std::to_string(revision->revision);
|
||||
RevisionRenderer revisionRenderer { *this->templ, *this->database, *this->urlProvider };
|
||||
|
||||
|
||||
std::string customtitle = parser.extractCommand("pagetitle", revision->content);
|
||||
std::string parsedcontent = revisionRenderer.renderContent(revision.value(), customtitle);
|
||||
/* TODO: Dynamic includes not considered, probably fine in practise */
|
||||
std::string indexcontent = createIndexContent(parser, revision->content);
|
||||
|
||||
std::string revisionstr = std::to_string(revision->revision);
|
||||
TemplatePage page = this->templ->getPage(templatepartname);
|
||||
page.setVar("content", parsedcontent);
|
||||
page.setVar("index", indexcontent);
|
||||
page.setVar("editedby", revision->author);
|
||||
|
@ -148,7 +148,7 @@ std::string Parser::parse(const PageDao &pagedao, UrlProvider &provider, const s
|
||||
std::string result;
|
||||
// we don't care about commands, but we nevertheless replace them with empty strings
|
||||
std::regex tagfinder(
|
||||
R"(\[(b|i|u|li||ul|ol|code|blockquote|img|link|wikilink|h\d|cmd:visible|cmd:rename|cmd:redirect|cmd:pagetitle|category|dynamic:postlist|dynamic:includepage|dynamic:getvar|dynamic:setvar)*?\]((\s|\S)*?)\[/\1])");
|
||||
R"(\[(b|i|u|li||ul|ol|code|blockquote|img|link|wikilink|h\d|cmd:visible|cmd:rename|cmd:redirect|cmd:pagetitle|cmd:allowinclude|category|dynamic:postlist|dynamic:includepage|dynamic:getvar|dynamic:setvar)*?\]((\s|\S)*?)\[/\1])");
|
||||
result = utils::regex_callback_replacer(
|
||||
tagfinder, content,
|
||||
[&](std::smatch &match)
|
||||
|
67
revisionrenderer.cpp
Arquivo normal
67
revisionrenderer.cpp
Arquivo normal
@ -0,0 +1,67 @@
|
||||
#include "revisionrenderer.h"
|
||||
#include "templatepage.h"
|
||||
#include "dynamic/dynamiccontentpostlist.h"
|
||||
#include "dynamic/dynamiccontentincludepage.h"
|
||||
#include "dynamic/dynamiccontentgetvar.h"
|
||||
#include "dynamic/dynamiccontentsetvar.h"
|
||||
#include "parser.h"
|
||||
#include "htmllink.h"
|
||||
|
||||
std::string RevisionRenderer::dynamicCallback(std::string_view key, std::string_view value)
|
||||
{
|
||||
if(key == "dynamic:postlist")
|
||||
{
|
||||
auto postlist = this->dynamicContentFactory.createDynamicContent<DynamicContentPostList>();
|
||||
postlist->setArgument(std::string(value));
|
||||
return postlist->render();
|
||||
}
|
||||
if(key == "dynamic:includepage")
|
||||
{
|
||||
auto includePage = this->dynamicContentFactory.createDynamicContent<DynamicContentIncludePage>();
|
||||
includePage->setArgument(std::string(value));
|
||||
return parser.parseDynamics(includePage->render(), std::bind(&RevisionRenderer::dynamicCallback, this, std::placeholders::_1, std::placeholders::_2));
|
||||
}
|
||||
if(key == "dynamic:setvar")
|
||||
{
|
||||
auto setVar = this->dynamicContentFactory.createDynamicContent<DynamicContentSetVar>();
|
||||
setVar->setMap(dynamicVarsMap);
|
||||
setVar->setArgument(std::string(value));
|
||||
return setVar->render();
|
||||
}
|
||||
if(key == "dynamic:getvar")
|
||||
{
|
||||
auto getVar = this->dynamicContentFactory.createDynamicContent<DynamicContentGetVar>();
|
||||
getVar->setMap(dynamicVarsMap);
|
||||
getVar->setArgument(std::string(value));
|
||||
return getVar->render();
|
||||
}
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
std::string RevisionRenderer::renderContent(std::string content)
|
||||
{
|
||||
dynamicVarsMap["pagetitle"] = parser.extractCommand("pagetitle", content);
|
||||
dynamicVarsMap["createdon"] = utils::toISODate(time(NULL));
|
||||
|
||||
std::string resolvedContent = parser.parseDynamics(content, std::bind(&RevisionRenderer::dynamicCallback, this, std::placeholders::_1, std::placeholders::_2));
|
||||
|
||||
return parser.parse(*this->db->createPageDao(), *this->urlProvider, resolvedContent);
|
||||
}
|
||||
|
||||
std::string RevisionRenderer::renderContent(const Revision &r, std::string_view customTitle)
|
||||
{
|
||||
auto revisionDao = this->db->createRevisionDao();
|
||||
auto firstRevision = revisionDao->getRevisionForPage(r.page, 1);
|
||||
if(!firstRevision)
|
||||
{
|
||||
throw std::runtime_error("Could not get first revision for page, which is odd. Solar flares?");
|
||||
}
|
||||
|
||||
|
||||
dynamicVarsMap["createdon"] = utils::toISODate(firstRevision.value().timestamp);
|
||||
dynamicVarsMap["pagetitle"] = customTitle;
|
||||
|
||||
std::string resolvedContent = parser.parseDynamics(r.content, std::bind(&RevisionRenderer::dynamicCallback, this, std::placeholders::_1, std::placeholders::_2));
|
||||
|
||||
return parser.parse(*this->db->createPageDao(), *this->urlProvider, resolvedContent);
|
||||
}
|
29
revisionrenderer.h
Arquivo normal
29
revisionrenderer.h
Arquivo normal
@ -0,0 +1,29 @@
|
||||
#ifndef REVISIONRENDERER_H
|
||||
#define REVISIONRENDERER_H
|
||||
#include "revision.h"
|
||||
#include "templatepage.h"
|
||||
#include "dynamic/dynamiccontentfactory.h"
|
||||
#include "iparser.h"
|
||||
#include "parser.h"
|
||||
class RevisionRenderer
|
||||
{
|
||||
private:
|
||||
DynamicContentFactory dynamicContentFactory;
|
||||
Database *db;
|
||||
UrlProvider *urlProvider;
|
||||
std::map<std::string, std::string> dynamicVarsMap;
|
||||
|
||||
std::string dynamicCallback(std::string_view key, std::string_view value);
|
||||
Parser parser;
|
||||
|
||||
public:
|
||||
RevisionRenderer(Template &templ, Database &db, UrlProvider &urlProvider) :dynamicContentFactory(templ, db, urlProvider)
|
||||
{
|
||||
this->db = &db;
|
||||
this->urlProvider = &urlProvider;
|
||||
}
|
||||
std::string renderContent(std::string content);
|
||||
std::string renderContent(const Revision &r, std::string_view customTitle);
|
||||
};
|
||||
|
||||
#endif // REVISIONRENDERER_H
|
@ -1 +1 @@
|
||||
Subproject commit b324921c1aeff2976544128e4bb2a0979a4aa595
|
||||
Subproject commit d92c31446687cfa336a6332b1015b4fe289fbdec
|
@ -1 +1 @@
|
||||
Subproject commit f2ca26010a2bb6d9e270d6ade2e8789c02ac3b31
|
||||
Subproject commit e711a1d53a9210f8f562f774901e5e044d20e67a
|
Carregando…
Referência em uma nova issue
Block a user