Salīdzināt revīzijas

15 Revīzijas

17 mainīti faili ar 120 papildinājumiem un 108 dzēšanām

6
.gitmodules ārējs
Parādīt failu

@ -4,6 +4,6 @@
[submodule "submodules/cpp-httplib"]
path = submodules/cpp-httplib
url = https://github.com/yhirose/cpp-httplib
[submodule "submodules/qssb.h"]
path = submodules/qssb.h
url = https://gitea.quitesimple.org/crtxcr/qssb.h.git
[submodule "submodules/exile.h"]
path = submodules/exile.h
url = https://gitea.quitesimple.org/crtxcr/exile.h.git

Parādīt failu

@ -3,7 +3,7 @@ CPPSTD=c++20
CXXFLAGS=-std=$(CPPSTD) -O0 -g -no-pie -pipe -MMD -Wall -Wextra
RELEASE_CXXFLAGS=-std=$(CPPSTD) -O3 -pipe -MMD -Wall -Wextra
LDFLAGS=-lsqlite3 -lpthread -lcrypto -lstdc++fs
INCLUDEFLAGS=-I submodules/sqlitemoderncpp/hdr -I submodules/cpp-httplib -I submodules/qssb.h
INCLUDEFLAGS=-I submodules/sqlitemoderncpp/hdr -I submodules/cpp-httplib -I submodules/exile.h
CXX=g++

Parādīt failu

@ -72,8 +72,7 @@ Building
Dependencies:
- cpp-httplib: https://github.com/yhirose/cpp-httplib
- SqliteModernCpp: https://github.com/SqliteModernCpp
- qssb.h: https://gitea.quitesimple.org/crtxcr/qssb.h
- libseccomp: https://github.com/seccomp/libseccomp
- exile.h: https://gitea.quitesimple.org/crtxcr/exile.h
- sqlite3: https://sqlite.org/index.html
The first three are header-only libraries that are included as a git submodule. The others must

2
cache/fscache.cpp ārējs
Parādīt failu

@ -46,7 +46,7 @@ void FsCache::removePrefix(std::string_view prefix)
// TODO: lock dir
for(auto &entry : std::filesystem::directory_iterator(std::filesystem::path{this->path}))
{
if(std::string_view(entry.path().filename().c_str()).starts_with(prefix) == 0)
if(std::string_view(entry.path().filename().c_str()).starts_with(prefix))
{
std::filesystem::remove_all(entry);
}

Parādīt failu

@ -167,6 +167,7 @@ Response HandlerPageView::handleRequest(PageDao &pageDao, std::string pagename,
}
}
std::string revisionstr = std::to_string(revision->revision);
std::string customtitle = parser.extractCommand("pagetitle", revision->content);
page.setVar("content", parsedcontent);
page.setVar("index", indexcontent);
page.setVar("editedby", revision->author);
@ -174,6 +175,10 @@ Response HandlerPageView::handleRequest(PageDao &pageDao, std::string pagename,
page.setVar("historyurl", this->urlProvider->pageHistory(pagename));
page.setVar("revision", revisionstr);
setPageVars(page, pagename);
if(!customtitle.empty())
{
page.setVar("title", createPageTitle(customtitle));
}
std::string body = page.render();
if(revisionid == 0 && !this->userSession->loggedIn)
{

Parādīt failu

@ -25,7 +25,11 @@ Response HandlerSearch::handleRequest(const Request &r)
std::string q = r.get("q");
if(q.empty())
{
return errorResponse("Missing search term", "No search term supplied");
TemplatePage searchForm = this->templ->getPage("searchform");
response.setBody(searchForm.render());
response.setStatus(200);
setGeneralVars(searchForm);
return response;
}
auto pageDao = this->database->createPageDao();

Parādīt failu

@ -8,10 +8,10 @@
class IParser
{
public:
virtual std::string extractCommand(std::string cmdname, std::string content) const = 0;
virtual std::vector<Headline> extractHeadlines(std::string content) const = 0;
virtual std::string parse(const PageDao &pagedao, UrlProvider &provider, std::string content) const = 0;
virtual std::vector<std::string> extractCategories(std::string content) const = 0;
virtual std::string extractCommand(std::string cmdname, const std::string &content) const = 0;
virtual std::vector<Headline> extractHeadlines(const std::string &content) const = 0;
virtual std::string parse(const PageDao &pagedao, UrlProvider &provider, const std::string &content) const = 0;
virtual std::vector<std::string> extractCategories(const std::string &content) const = 0;
virtual ~IParser(){};
};

Parādīt failu

@ -27,7 +27,7 @@ SOFTWARE.
#include "parser.h"
#include "utils.h"
#include "htmllink.h"
std::vector<Headline> Parser::extractHeadlines(std::string content) const
std::vector<Headline> Parser::extractHeadlines(const std::string &content) const
{
std::vector<Headline> result;
std::string reg = R"(\[h(1|2|3)\](.*?)\[/h\1\])";
@ -46,7 +46,7 @@ std::vector<Headline> Parser::extractHeadlines(std::string content) const
return result;
}
std::vector<std::string> Parser::extractCategories(std::string content) const
std::vector<std::string> Parser::extractCategories(const std::string &content) const
{
std::vector<std::string> result;
std::string reg = R"(\[category\](.*?)\[/category\])";
@ -62,7 +62,7 @@ std::vector<std::string> Parser::extractCategories(std::string content) const
return result;
}
std::string Parser::extractCommand(std::string cmdname, std::string content) const
std::string Parser::extractCommand(std::string cmdname, const std::string &content) const
{
std::string cmd = "[cmd:" + cmdname + "]";
std::string cmdend = "[/cmd:" + cmdname + "]";
@ -116,31 +116,36 @@ std::string Parser::processLink(const PageDao &pageDao, UrlProvider &urlProvider
return htmllink.render();
}
std::string Parser::parse(const PageDao &pagedao, UrlProvider &provider, std::string content) const
std::string Parser::parse(const PageDao &pagedao, UrlProvider &provider, const std::string &content) const
{
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|link|wikilink|h\d|cmd:rename|cmd:redirect|category)*?\]((\s|\S)*?)\[/\1])");
result = utils::regex_callback_replacer(tagfinder, content, [&](std::smatch &match) {
std::string tag = match.str(1);
std::string content = match.str(2);
std::string justreplace[] = {"b", "i", "u", "ul", "li", "ol"};
content = parse(pagedao, provider, content);
if(std::find(std::begin(justreplace), std::end(justreplace), tag) != std::end(justreplace))
std::regex tagfinder(
R"(\[(b|i|u|li||ul|ol|link|wikilink|h\d|cmd:rename|cmd:redirect|cmd:pagetitle|category)*?\]((\s|\S)*?)\[/\1])");
result = utils::regex_callback_replacer(
tagfinder, content,
[&](std::smatch &match)
{
return "<" + tag + ">" + content + "</" + tag + ">";
}
if(tag == "link" || tag == "wikilink")
{
return this->processLink(pagedao, provider,
match); // TODO: recreate this so we don't check inside the function stuff again
}
if(tag[0] == 'h')
{
return "<" + tag + " id='" + content + "'>" + content + "</" + tag + ">";
}
return std::string("");
});
std::string tag = match.str(1);
std::string content = match.str(2);
std::string justreplace[] = {"b", "i", "u", "ul", "li", "ol"};
content = parse(pagedao, provider, content);
if(std::find(std::begin(justreplace), std::end(justreplace), tag) != std::end(justreplace))
{
return "<" + tag + ">" + content + "</" + tag + ">";
}
if(tag == "link" || tag == "wikilink")
{
return this->processLink(
pagedao, provider,
match); // TODO: recreate this so we don't check inside the function stuff again
}
if(tag[0] == 'h')
{
return "<" + tag + " id='" + content + "'>" + content + "</" + tag + ">";
}
return std::string("");
});
result = utils::strreplace(result, "\r\n", "<br>");
return result;
}

Parādīt failu

@ -8,10 +8,10 @@ class Parser : public IParser
std::string processLink(const PageDao &pageDao, UrlProvider &urlProvider, std::smatch &match) const;
public:
std::string extractCommand(std::string cmdname, std::string content) const;
std::vector<Headline> extractHeadlines(std::string content) const override;
std::vector<std::string> extractCategories(std::string content) const override;
std::string parse(const PageDao &pagedao, UrlProvider &provider, std::string content) const override;
std::string extractCommand(std::string cmdname, const std::string &content) const;
std::vector<Headline> extractHeadlines(const std::string &content) const override;
std::vector<std::string> extractCategories(const std::string &content) const override;
std::string parse(const PageDao &pagedao, UrlProvider &provider, const std::string &content) const override;
using IParser::IParser;
~Parser(){};
};

Parādīt failu

@ -12,7 +12,8 @@
#include <filesystem>
#include <sys/mount.h>
#include <sys/capability.h>
#include <qssb.h>
#define HAVE_LANDLOCK 0
#include <exile.h>
#include "../logger.h"
#include "../utils.h"
#include "../random.h"
@ -45,7 +46,7 @@ bool SandboxLinux::enable(std::vector<std::string> fsPaths)
std::sort(fsPaths.begin(), fsPaths.end(),
[](const std::string &a, const std::string &b) { return a.length() < b.length(); });
struct qssb_policy *policy = qssb_init_policy();
struct exile_policy *policy = exile_init_policy();
if(policy == NULL)
{
Logger::error() << "Failed to init sandboxing policy (worker) ";
@ -53,30 +54,22 @@ bool SandboxLinux::enable(std::vector<std::string> fsPaths)
}
for(unsigned int i = 0; i < fsPaths.size(); i++)
{
qssb_append_path_policy(policy, QSSB_FS_ALLOW_READ | QSSB_FS_ALLOW_WRITE, fsPaths[i].c_str());
exile_append_path_policy(policy, EXILE_FS_ALLOW_ALL_READ | EXILE_FS_ALLOW_ALL_WRITE, fsPaths[i].c_str());
}
policy->drop_caps = 1;
policy->not_dumpable = 1;
policy->no_new_privs = 1;
policy->mount_path_policies_to_chroot = 1;
/* TODO: as said, a whitelist approach is better. As such, this list is bound to be incomplete in the
* sense that more could be listed here and some critical ones are probably missing */
policy->vow_promises = EXILE_SYSCALL_VOW_STDIO | EXILE_SYSCALL_VOW_WPATH | EXILE_SYSCALL_VOW_CPATH |
EXILE_SYSCALL_VOW_RPATH | EXILE_SYSCALL_VOW_INET | EXILE_SYSCALL_VOW_UNIX |
EXILE_SYSCALL_VOW_THREAD;
/* TODO: use qssb groups */
long blacklisted_syscalls[] = {QSSB_SYS(setuid), QSSB_SYS(connect), QSSB_SYS(chroot), QSSB_SYS(pivot_root),
QSSB_SYS(mount), QSSB_SYS(setns), QSSB_SYS(unshare), QSSB_SYS(ptrace),
QSSB_SYS(personality), QSSB_SYS(prctl), QSSB_SYS(execveat), QSSB_SYS(execve),
QSSB_SYS(fork)};
qssb_append_syscalls_policy(policy, QSSB_SYSCALL_DENY_KILL_PROCESS, blacklisted_syscalls,
sizeof(blacklisted_syscalls) / sizeof(blacklisted_syscalls[0]));
qssb_append_syscall_default_policy(policy, QSSB_SYSCALL_ALLOW);
if(qssb_enable_policy(policy) != 0)
if(exile_enable_policy(policy) != 0)
{
Logger::error() << "Sandbox: Activation of seccomp blacklist failed!";
qssb_free_policy(policy);
exile_free_policy(policy);
return false;
}
qssb_free_policy(policy);
exile_free_policy(policy);
return true;
}

1
submodules/exile.h Apakšmodulis

Submodule submodules/exile.h added at 4824c6eaa9

Parādīt failu

@ -6,16 +6,15 @@
<title>{qswiki:var:title}</title>
<body>
<nav>
<ul>
<li><a href="{qswiki:config:linkindex}"><h2>{qswiki:config:wikiname}</h2></a></li>
</ul>
<ul id="nav">
<li><a href="{qswiki:config:linkrecent}">Recent changes</a></li>
<li><a href="{qswiki:config:linkallpages}">All pages</a></li>
<li><a href="{qswiki:config:linkallcats}">All categories</a></li>
</ul>
<li><a href="{qswiki:config:linkindex}"><h2>{qswiki:config:wikiname}</h2></a></li>
<li><a href="{qswiki:config:linkrecent}">Recent changes</a></li>
<li><a href="{qswiki:config:linkallpages}">All pages</a></li>
<li><a href="{qswiki:config:linkallcats}">All categories</a></li>
<li id="searchlink"><a href="{qswiki:config:linksearch}">Search</a></li>
</ul>
<ul id="right" class="search">
<li><div><form action="{qswiki:config:wikipath}" method="GET"><input type="hidden" name="action" value="search"/><input type="text" name="q" value="search here" onfocus="this.value=''"></form></div></li>
<ul id="right" class="search">
<li><div id="searchbar"><form action="{qswiki:config:wikipath}" method="GET"><input type="hidden" name="action" value="search"/><input type="text" name="q" value="search here" onfocus="this.value=''"></form></div></li>
</ul>
</nav>

Parādīt failu

@ -6,20 +6,15 @@
<title>{qswiki:var:title}</title>
<body>
<nav>
<ul>
<li><a href="{qswiki:config:linkindex}"><h2>{qswiki:config:wikiname}</h2></a></li>
</ul>
<ul id="nav">
<li><a href="{qswiki:config:linkindex}"><h2>{qswiki:config:wikiname}</h2></a></li>
<li><a href="{qswiki:config:linkrecent}">Recent changes</a></li>
<li><a href="{qswiki:config:linkallpages}">All pages</a></li>
<li><a href="{qswiki:config:linkallcats}">All categories</a></li>
</ul>
<ul>
<li id="searchlink"><a href="{qswiki:config:linksearch}">Search</a></li>
{qswiki:var:headerlinks}
</ul>
</ul>
<ul id="right" class="search">
<li><div><form action="{qswiki:config:wikipath}" method="GET"><input type="hidden" name="action" value="search"/><input type="text" value="search here" onfocus="this.value=''" name="q"/></form></div></li>
<li><div id="searchbar"><form action="{qswiki:config:wikipath}" method="GET"><input type="hidden" name="action" value="search"/><input type="text" value="search here" onfocus="this.value=''" name="q"/></form></div></li>
</ul>
</nav>
</nav>

Parādīt failu

@ -0,0 +1,7 @@
{qswiki:include:general_header}
<main id="content">
<h2>Search</h2><br>
Search content of pages:
<form action="{qswiki:config:wikipath}" method="GET"><input type="hidden" name="action" value="search"/><input type="text" name="q" value="search here" onfocus="this.value=''"></form>
</main>
{qswiki:include:general_footer}

Parādīt failu

@ -23,7 +23,7 @@ h1, h2, h3
{
margin: 0;
padding: 0;
display: inline;
display: inline;
}
nav
@ -37,6 +37,7 @@ nav
grid-area: nav;
}
nav ul
{
background-color: #062463;
@ -47,16 +48,12 @@ nav ul
display: flex;
align-items: center;
flex-wrap: wrap;
}
nav li
{
margin: 0;
padding: 0;
}
nav a, nav a:visited
@ -68,7 +65,6 @@ nav a, nav a:visited
font-weight: bold;
text-align: center;
line-height: 100%;
}
nav a:hover, nav a:focus
@ -81,8 +77,6 @@ nav a:hover, nav a:focus
font-weight: bold;
}
a, a:visited
{
color: #062463;;
@ -92,40 +86,36 @@ a:hover
{
background-color: #062463;
color: white;
}
#content
{
padding: 15px;
font-family: monospace;
font-size: 14pt;
flex: 1;
grid-area: main
padding: 15px;
font-family: monospace;
font-size: 14pt;
flex: 1;
grid-area: main
}
#sidebar
{
grid-area: side;
grid-area: side;
}
#sidebar ul
{
list-style-type: none;
list-style-type: none;
}
#sidebar a, a:visited
{
color: #062463;
}
#sidebar a:hover
{
background-color: #062463;
color: white;
background-color: #062463;
color: white;
}
#content a, a:visited
@ -135,11 +125,10 @@ list-style-type: none;
#content a:hover
{
background-color: #062463;
color: white;
background-color: #062463;
color: white;
}
footer
{
width: 100%;
@ -160,6 +149,7 @@ footer ul
flex-wrap: wrap;
align-items: center;
}
footer li
{
margin: 0;
@ -168,14 +158,12 @@ footer li
line-height: 45px;
color: white;
font-weight: bold;
//flex: 1 1 0;
text-align: center;
}
footer a, a:visited
{
text-decoration: none;
color: white;
display: inline-block;
}
@ -190,7 +178,7 @@ footer a:hover, ul#nav a:focus
#cats
{
background-color: #062463;
background-color: #062463;
}
.letter_search_result
@ -198,20 +186,27 @@ background-color: #062463;
text-decoration: underline;
font-weight: bold;
}
ol
{
counter-reset: item;
}
.indexlink
{
display: block;
display: block;
}
.notexists
{
color: red !important;
font-weight: bold;
}
#searchlink
{
display: none;
}
@media screen and (orientation: portrait)
{
@ -219,13 +214,23 @@ display: block;
{
display: none;
}
#footer li:nth-child(-n+2)
{
display: none;
}
#footer li:nth-of-type(3)
{
text-align: center;
width: 100%;
}
#searchlink {
display: inline;
}
#searchbar {
display: none;
}
}