#include #include #include #include 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; }