Parsee/src/XMPPCommand/Commands.c
LDA 0cb19a15d8 [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...
2024-07-14 22:24:59 +02:00

224 lines
4.5 KiB
C

#include <XMPPCommand.h>
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Array.h>
#include <Cytoplasm/Str.h>
struct XMPPCommand {
XMPPCmdCallback callback;
char *node, *name;
char *form_instruction;
char *form_title;
/* TODO: On-the-fly generation of options */
Array *options;
XMPPOptionWriter otf;
};
XMPPCommand *
XMPPBasicCmd(char *node, char *name, XMPPCmdCallback callback_funct)
{
XMPPCommand *cmd;
if (!node || !name || !callback_funct)
{
return NULL;
}
cmd = Malloc(sizeof(*cmd));
cmd->callback = callback_funct;
cmd->node = StrDuplicate(node);
cmd->name = StrDuplicate(name);
cmd->form_instruction = NULL;
cmd->form_title = NULL;
/* 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)
{
if (!cmd)
{
return;
}
Free(cmd->form_title);
cmd->form_title = StrDuplicate(title);
}
void
XMPPSetFormInstruction(XMPPCommand *cmd, char *instruction)
{
if (!cmd)
{
return;
}
Free(cmd->form_instruction);
cmd->form_instruction = StrDuplicate(instruction);
}
void
XMPPFreeCommand(XMPPCommand *cmd)
{
size_t i;
if (!cmd)
{
return;
}
for (i = 0; i < ArraySize(cmd->options); i++)
{
XMPPOption *opt = ArrayGet(cmd->options, i);
XMPPFreeOption(opt);
}
ArrayFree(cmd->options);
XMPPSetFormInstruction(cmd, NULL);
XMPPSetFormTitle(cmd, NULL);
Free(cmd->node);
Free(cmd->name);
Free(cmd);
}
void
XMPPAddOption(XMPPCommand *cmd, XMPPOption *opt)
{
if (!cmd || !opt)
{
return;
}
if (!cmd->options)
{
cmd->options = ArrayCreate();
}
ArrayAdd(cmd->options, opt);
}
XMLElement *
XMPPFormifyCommand(XMPPCommandManager *m, XMPPCommand *cmd, char *from)
{
XMLElement *x, *field;
size_t i;
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;
}
x = XMLCreateTag("x");
XMLAddAttr(x, "xmlns", "jabber:x:data");
XMLAddAttr(x, "type", "form");
if (cmd->form_title)
{
XMLElement *instr_xml, *instr_txt;
instr_xml = XMLCreateTag("title");
instr_txt = XMLCreateText(cmd->form_title);
XMLAddChild(instr_xml, instr_txt);
XMLAddChild(x, instr_xml);
}
if (cmd->form_instruction)
{
XMLElement *instr_xml, *instr_txt;
instr_xml = XMLCreateTag("instructions");
instr_txt = XMLCreateText(cmd->form_instruction);
XMLAddChild(instr_xml, instr_txt);
XMLAddChild(x, instr_xml);
}
/* TODO: Other fields */
for (i = 0; i < ArraySize(cmd->options); i++)
{
XMPPOption *opt = ArrayGet(cmd->options, i);
field = XMPPOptionToXML(opt);
XMLAddChild(x, field);
}
return x;
}
char *
XMPPGetCommandNode(XMPPCommand *cmd)
{
return cmd ? cmd->node : NULL;
}
char *
XMPPGetCommandDesc(XMPPCommand *cmd)
{
return cmd ? cmd->name : NULL;
}
bool
XMPPCommandRequiresForm(XMPPCommand *cmd)
{
return cmd ? (cmd->otf || !!cmd->options) : false;
}
void
XMPPExecuteCommand(XMPPCommandManager *m, XMPPCommand *cmd, char *from, XMLElement *to, XMLElement *form)
{
if (!m || !cmd || !from || !to)
{
return;
}
cmd->callback(m, from, form, to);
}
bool
XMPPVerifyForm(XMPPCommand *cmd, XMLElement *form)
{
size_t i;
if (!cmd || !form)
{
return false;
}
for (i = 0; i < ArraySize(cmd->options); i++)
{
XMPPOption *opt = ArrayGet(cmd->options, i);
if (XMPPIsOptionRequired(opt))
{
/* Check in the form for a field with the right var */
char *var = XMPPOptionVar(opt);
XMLElement *field = XMLookForTKV(form, "field", "var", var);
if (!field)
{
/* Required field not found; die. */
return false;
}
/* TODO: Verify type, array membership, uniqueness, etc... */
}
}
return true;
}