diff --git a/.gitignore b/.gitignore index 2dc89de..2ac11a3 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ parsee .* data data/* + +tools/out +tools/out/* diff --git a/LICENSE b/LICENSE index d4c693c..56fdd03 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -For the files src/XML/*, src/include/XML.h, and Makefile, see COPYING.CC0 +For the files src/XML/*, tools/*, src/include/XML.h, and Makefile, see COPYING.CC0 For the file src/Signal.c, it is based on Telodendria, which requires COPYING.TELO to be present. For any other file in src/, see COPYING.AGPL as the primary license. diff --git a/src/Routes/Root.c b/src/Routes/Root.c index db57b7e..fba70b9 100644 --- a/src/Routes/Root.c +++ b/src/Routes/Root.c @@ -9,6 +9,7 @@ RouteHead(RouteRoot, arr, argp) { ParseeHttpArg *args = argp; + const ParseeConfig *config = args->data->config; const char *quote = RandInt(2) ? "Kinda jealous of that, to be fair." : "Why look inward when you can challenge the mainstream media?"; @@ -29,6 +30,7 @@ RouteHead(RouteRoot, arr, argp) P(" html {"); P(" background-color: #222;"); P(" color: #eee;"); + P(" font-family: sans-serif;"); P(" }"); P(" blockquote {"); P(" border-left: 2px solid #ccc;"); @@ -65,9 +67,24 @@ RouteHead(RouteRoot, arr, argp) P(" href='https://kappach.at/parsee'"); P(" >the actual page."); P("

"); + P("

Permissions?

"); + P("

"); + P(" If you have problems running commands, you may want to "); + P(" look into if you have set yourself as an admin."); + P("

"); + P(" If you happen to have a build-from-source copy of %s,", NAME); + P(" please build all utilities and run "); + P(" tools/out/adminify '%s' '[glob]'.", config->db_path); + P("

"); P("

Extra information

"); P("

"); + P("

Dev documentations!!!!

"); + P(" Developers may be interested into looking up the "); + P(" at.kappach.at "); + P(" page for extensions used by Parsee on Matrix. "); + P("

"); + P("

"); P("

Parsee statistics

"); P("
");
     P("Software: %s (v%s/Cyto %s)\n", NAME, VERSION, CytoplasmGetVersionStr());
@@ -79,13 +96,13 @@ RouteHead(RouteRoot, arr, argp)
     P("            ");
     P("        

"); - P("

"); + P("

"); P(" Good luck, and have fun! :D"); - P("

"); - P("

—LDA

"); + P("
"); + P("

— LDA

"); P(" "); P(""); #undef P diff --git a/src/XEP-0393.c b/src/XEP-0393.c index a53067b..474af60 100644 --- a/src/XEP-0393.c +++ b/src/XEP-0393.c @@ -195,6 +195,13 @@ XEP393Decode(StrView view, XEP393Element *root) { Spanify(XEP393_MONO); } + else if (curr == '\n') + { + /* TODO: Remove this */ + span_view.start = subview.start; + span_view.end = subview.start; + Spanify(XEP393_NL); + } else { /* Text character: update end */ @@ -249,6 +256,9 @@ ShoveXML(XEP393Element *element, XMLElement *xmlparent) head = XMLCreateTag("i"); XMLAddChild(xmlparent, head); break; + case XEP393_NL: + XMLAddChild(xmlparent, XMLCreateTag("br")); + break; case XEP393_EMPH: head = XMLCreateTag("strong"); XMLAddChild(xmlparent, head); @@ -285,7 +295,7 @@ XEP393ToXMLString(XEP393Element *xepd) return NULL; } - root = XMLCreateTag("pre"); + root = XMLCreateTag("span"); ShoveXML(xepd, root); writer = StrStreamWriter(&ret); diff --git a/src/include/XEP393.h b/src/include/XEP393.h index 72a6a04..8c8bff8 100644 --- a/src/include/XEP393.h +++ b/src/include/XEP393.h @@ -8,7 +8,8 @@ typedef enum XEP393Type { XEP393_ITALIC, XEP393_EMPH, XEP393_MONO, - XEP393_TEXT + XEP393_TEXT, + XEP393_NL } XEP393Type; typedef struct XEP393Element { struct XEP393Element *parent; diff --git a/tools/Makefile b/tools/Makefile new file mode 100644 index 0000000..7fa93bc --- /dev/null +++ b/tools/Makefile @@ -0,0 +1,35 @@ +# Makefile for building Parsee +# ================================ +# TODO: Consider making something akin to a configure script that checks +# for dependencies, or maybe even use *autoconf* (the devil!) + + +# =========================== Parsee Flags ============================= +NAME=Parsee +VERSION=0.0.0 +REPOSITORY=$(shell git remote get-url origin) + +# =========================== Compilation Flags ============================ +CYTO_INC=/usr/local/include/ # Where Cytoplasm's include path is + # located. +CYTO_LIB=/usr/local/lib # Where's Cytoplasm's library is + # located. + +SOURCE=. +OBJECT=out +CC=cc +CFLAGS=-I$(SOURCE) -I$(CYTO_INC) -DNAME="\"$(NAME)\"" -DVERSION="\"$(VERSION)\"" -DREPOSITORY=\"$(REPOSITORY)\" -g -ggdb -Wall -Werror +LDFLAGS=-L $(CYTO_LIB) -lCytoplasm -g -ggdb +# ============================ Compilation ================================= +SRC_FILES:=$(shell find $(SOURCE) -name '*.c') +OBJ_FILES:=${subst $(SOURCE)/,$(OBJECT)/,$(patsubst %.c, %, $(SRC_FILES))} + +all: $(OBJ_FILES) + +$(OBJECT)/%: $(SOURCE)/%.c + @mkdir -p $(shell dirname "$@") + $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ + +clean: + rm -rf $(OBJECT) + diff --git a/tools/adminify.c b/tools/adminify.c new file mode 100644 index 0000000..d7fe8a3 --- /dev/null +++ b/tools/adminify.c @@ -0,0 +1,123 @@ +/* adminify.c - Small utility to add/view an admin to the Parsee DB. + * ============================================================ + * Yes, it's a matter of editing a JSON object, but this may change + * in the future(LMDB?), so I prefer using Cytoplasm's DB API. + * Also, this allows some basic automation instead of having to hack + * together code to send a message on Matrix/command on XMPP. The main + * problem is that this would also mean that the user is already admin, + * which in case of a first-time install, isn't true. + * + * TODO: Check if the DB already exists instead of auto-creating one + * when that isn't true. + * + * Under CC0, as its a rather useful example of a Parsee tool. + * See LICENSE for more information about Parsee's licensing. */ + +#include +#include +#include +#include + +#include + +static void +AddAdmin(Db *parsee, char *glob) +{ + DbRef *ref; + HashMap *j; + Array *admins; + bool exists = true; + + ref = DbLock(parsee, 1, "admins"); + if (!ref) + { + ref = DbCreate(parsee, 1, "admins"); + } + j = DbJson(ref); + admins = JsonValueAsArray(HashMapGet(j, "admins")); + if (!admins) + { + exists = false; + admins = ArrayCreate(); + } + + ArrayAdd(admins, JsonValueString(glob)); + + if (!exists) + { + HashMapSet(j, "admins", JsonValueArray(admins)); + } + DbUnlock(parsee, ref); +} +static void +ListAdmins(Db *parsee) +{ + DbRef *ref; + HashMap *j; + Array *admins; + size_t i; + + ref = DbLock(parsee, 1, "admins"); + if (!ref) + { + ref = DbCreate(parsee, 1, "admins"); + } + j = DbJson(ref); + admins = JsonValueAsArray(HashMapGet(j, "admins")); + + for (i = 0; i < ArraySize(admins); i++) + { + char *admin = JsonValueAsString(ArrayGet(admins, i)); + + Log(LOG_INFO, "- %s", admin); + } + + DbUnlock(parsee, ref); + +} + +int +Main(Array *args, HashMap *env) +{ + char *db_path, *glob, *exec; + Db *parsee; + + exec = ArrayGet(args, 0); + + if (ArraySize(args) < 2) + { + Log(LOG_ERR, "Usage: %s [DB path] [glob]", exec); + return EXIT_FAILURE; + } + + db_path = ArrayGet(args, 1); + glob = ArrayGet(args, 2); + + parsee = DbOpen(db_path, 0); + if (parsee) + { + + if (glob) + { + Log(LOG_NOTICE, "Adding glob '%s' to database %s", glob, db_path); + AddAdmin(parsee, glob); + Log(LOG_INFO, "Successfully added glob %s.", glob); + Log(LOG_INFO, "*I'm jealous of all these admins!*"); + + DbClose(parsee); + return EXIT_SUCCESS; + } + + /* List admins */ + Log(LOG_INFO, "Admin list:"); + LogConfigIndent(LogConfigGlobal()); + ListAdmins(parsee); + LogConfigUnindent(LogConfigGlobal()); + + DbClose(parsee); + return EXIT_SUCCESS; + } + + Log(LOG_ERR, "%s: couldn't open DB '%s'", exec, db_path); + return EXIT_FAILURE; +}