From 0cb19a15d85f2037f29398cca08979bec5d65792 Mon Sep 17 00:00:00 2001 From: LDA Date: Sun, 14 Jul 2024 22:24:59 +0200 Subject: [PATCH] [ADD/WIP] On-the-fly forms Still WIP-tier, also I need to make a way to index a multi-option list like a regular array with the forms thing, the current one-at-a-time idea is not great... --- src/XMPPCommand/Commands.c | 35 +++++++++++-- src/XMPPCommand/Manager.c | 2 +- src/XMPPCommands/DelAdmin.c | 99 +++++++++++++++++++++++++++++++++++++ src/include/XMPPCommand.h | 16 +++++- 4 files changed, 146 insertions(+), 6 deletions(-) create mode 100644 src/XMPPCommands/DelAdmin.c diff --git a/src/XMPPCommand/Commands.c b/src/XMPPCommand/Commands.c index d2b8908..7b418c6 100644 --- a/src/XMPPCommand/Commands.c +++ b/src/XMPPCommand/Commands.c @@ -13,6 +13,7 @@ struct XMPPCommand { /* TODO: On-the-fly generation of options */ Array *options; + XMPPOptionWriter otf; }; XMPPCommand * @@ -35,8 +36,20 @@ XMPPBasicCmd(char *node, char *name, XMPPCmdCallback callback_funct) /* No options -> no form required */ cmd->options = NULL; + cmd->otf = NULL; + return cmd; } +void +XMPPCmdOptionsCreator(XMPPCommand *cmd, XMPPOptionWriter writer) +{ + if (!cmd) + { + return; + } + cmd->otf = writer; +} + void XMPPSetFormTitle(XMPPCommand *cmd, char *title) { @@ -95,12 +108,28 @@ XMPPAddOption(XMPPCommand *cmd, XMPPOption *opt) } XMLElement * -XMPPFormifyCommand(XMPPCommand *cmd) +XMPPFormifyCommand(XMPPCommandManager *m, XMPPCommand *cmd, char *from) { XMLElement *x, *field; size_t i; - if (!cmd || !cmd->options) + if (!cmd || !m) + { + return NULL; + } + if (cmd->otf) + { + for (i = 0; i < ArraySize(cmd->options); i++) + { + XMPPOption *opt = ArrayGet(cmd->options, i); + XMPPFreeOption(opt); + } + ArrayFree(cmd->options); + cmd->options = NULL; + + cmd->otf(m, cmd, from); + } + if (!cmd->options) { return NULL; } @@ -152,7 +181,7 @@ XMPPGetCommandDesc(XMPPCommand *cmd) bool XMPPCommandRequiresForm(XMPPCommand *cmd) { - return cmd ? !!cmd->options : false; + return cmd ? (cmd->otf || !!cmd->options) : false; } void XMPPExecuteCommand(XMPPCommandManager *m, XMPPCommand *cmd, char *from, XMLElement *to, XMLElement *form) diff --git a/src/XMPPCommand/Manager.c b/src/XMPPCommand/Manager.c index 49bb251..580773f 100644 --- a/src/XMPPCommand/Manager.c +++ b/src/XMPPCommand/Manager.c @@ -271,7 +271,7 @@ XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeData *data) XMLAddChild(command_xml, actions); XMLAddChild(iq, command_xml); - x = XMPPFormifyCommand(cmd); + x = XMPPFormifyCommand(m, cmd, from); XMLAddChild(command_xml, x); pthread_mutex_lock(&jabber->write_lock); diff --git a/src/XMPPCommands/DelAdmin.c b/src/XMPPCommands/DelAdmin.c new file mode 100644 index 0000000..bab7fb5 --- /dev/null +++ b/src/XMPPCommands/DelAdmin.c @@ -0,0 +1,99 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +void +DelAdminCallback(XMPPCommandManager *m, char *from, XMLElement *form, XMLElement *out) +{ + ParseeData *data = XMPPGetManagerCookie(m); + char *trimmed = ParseeTrimJID(from); + char *glob = NULL; + + DbRef *admins; + Array *admin_list; + size_t i; + bool removed = false; + + GetFieldValue(glob, "glob", form); + + if (!ParseeIsAdmin(data, trimmed)) + { + SetNote("error", "User is not authorised to execute command."); + + Free(trimmed); + return; + } + if (!glob) + { + SetNote("error", "No glob found."); + Free(trimmed); + return; + } + + Log(LOG_INFO, "glob=%s", glob); + admins = DbLock(data->db, 1, "admins"); + admin_list = GrabArray(DbJson(admins), 1, "admins"); + + for (i = 0; i < ArraySize(admin_list); i++) + { + char *admin = JsonValueAsString(ArrayGet(admin_list, i)); + if (StrEquals(admin, glob)) + { + SetNote("info", "Admin sucessfully removed."); + removed = true; + JsonValueFree(ArrayDelete(admin_list, i)); + break; + } + } + + DbUnlock(data->db, admins); + Free(trimmed); + + if (!removed) + { + SetNote("warn", "Glob wasn't in list."); + } + /* TODO */ +} +void +FormDelAdminCallback(XMPPCommandManager *m, XMPPCommand *cmd, char *from) +{ + ParseeData *data = XMPPGetManagerCookie(m); + DbRef *admins; + Array *admin_list; + size_t i; + XMPPOption *admin_opt; + char *trimmed = ParseeTrimJID(from); + + if (!ParseeIsAdmin(data, trimmed)) + { + Free(trimmed); + admin_opt = XMPPCreateList(true, true, "glob", "[NOT AUTHORIZED!]"); + XMPPAddOption(cmd, admin_opt); + return; + } + Free(trimmed); + + admin_opt = XMPPCreateList(true, true, "glob", "[NVM!]"); + + admins = DbLock(data->db, 1, "admins"); + admin_list = GrabArray(DbJson(admins), 1, "admins"); + for (i = 0; i < ArraySize(admin_list); i++) + { + char *glob = JsonValueAsString(ArrayGet(admin_list, i)); + + XMPPAddListOption(admin_opt, glob); + } + + DbUnlock(data->db, admins); + XMPPAddOption(cmd, admin_opt); +} diff --git a/src/include/XMPPCommand.h b/src/include/XMPPCommand.h index d5e3226..e61fdcb 100644 --- a/src/include/XMPPCommand.h +++ b/src/include/XMPPCommand.h @@ -11,6 +11,7 @@ typedef struct XMPPCommandManager XMPPCommandManager; typedef struct XMPPCommand XMPPCommand; typedef struct XMPPOption XMPPOption; typedef void (*XMPPCmdCallback)(XMPPCommandManager *, char *, XMLElement *, XMLElement *); +typedef void (*XMPPOptionWriter)(XMPPCommandManager *, XMPPCommand *, char *); /** Creates a simple XMPP command manager, which routes commands * with a single-stage form system, with a {cookie} @@ -27,8 +28,9 @@ extern void * XMPPGetManagerCookie(XMPPCommandManager *manager); * Modifies: NOTHING * See-Also: XMPPRegisterCommand */ extern XMPPCommand * XMPPBasicCmd(char *node, char *name, XMPPCmdCallback cb); +extern void XMPPCmdOptionsCreator(XMPPCommand *cmd, XMPPOptionWriter writer); extern void XMPPAddOption(XMPPCommand *cmd, XMPPOption *opt); -extern XMLElement * XMPPFormifyCommand(XMPPCommand *cmd); +extern XMLElement * XMPPFormifyCommand(XMPPCommandManager *m, XMPPCommand *cmd, char *from); extern char * XMPPGetCommandNode(XMPPCommand *cmd); extern char * XMPPGetCommandDesc(XMPPCommand *cmd); extern void XMPPSetFormInstruction(XMPPCommand *cmd, char *instruction); @@ -91,6 +93,7 @@ extern bool XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeD /* --------------------------------- COMMANDS --------------------------------- */ +/* Please edit stc/XMPPThread.c (you can just force-save) for these to apply! */ #define XMPPCOMMANDS \ XMPP_COMMAND(StatusCallback, "stats", "Get Parsee statistics", {}) \ XMPP_COMMAND(CleanCallback, "clean", "Cleanup temporary Parsee data", {}) \ @@ -104,6 +107,11 @@ extern bool XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeD XMPPSetFormTitle(cmd, "Admin addition form"); \ XMPPSetFormInstruction(cmd, "Select a glob pattern to add as an admin"); \ }) \ + XMPP_COMMAND(DelAdminCallback, "del-admin", "Removes a glob from admin rights", { \ + XMPPCmdOptionsCreator(cmd, FormDelAdminCallback); \ + XMPPSetFormTitle(cmd, "Admin removal form"); \ + XMPPSetFormInstruction(cmd, "Select a glob pattern to remove as an admin"); \ + }) \ XMPP_COMMAND(AddNoflyCallback, "add-nofly", "Adds user to nofly", { \ XMPPOption *entity = XMPPCreateText(true, "entity", ""); \ XMPPOption *reason = XMPPCreateText(false, "reason", "Not behaving"); \ @@ -118,7 +126,11 @@ extern bool XMPPManageCommand(XMPPCommandManager *m, XMLElement *stanza, ParseeD #define XMPP_COMMAND(f,n,t,s) \ extern void \ - f(XMPPCommandManager *, char *, XMLElement *, XMLElement *); + f(XMPPCommandManager *, char *, XMLElement *, XMLElement *); \ + /* This symbol might not exist. We do, however, not care, as + * it is not always done. */ \ + extern void \ + Form##f(XMPPCommandManager *, XMPPCommand *, char *); \ XMPPCOMMANDS