mirror of
https://git.kappach.at/lda/Parsee.git
synced 2025-05-12 20:03:46 +02:00
326 lines
7.6 KiB
C
326 lines
7.6 KiB
C
#include <StanzaBuilder.h>
|
|
|
|
#include <Cytoplasm/Memory.h>
|
|
#include <Cytoplasm/Array.h>
|
|
#include <Cytoplasm/Json.h>
|
|
#include <Cytoplasm/Str.h>
|
|
|
|
#include <StringStream.h>
|
|
#include <Parsee.h>
|
|
|
|
struct StanzaBuilder {
|
|
Array *sub_items;
|
|
|
|
char *replying_to_stanza;
|
|
char *replying_to_sender;
|
|
char *from, *to;
|
|
char *editing;
|
|
char *type;
|
|
char *body;
|
|
char *oob;
|
|
char *id;
|
|
};
|
|
|
|
StanzaBuilder *
|
|
CreateStanzaBuilder(char *from, char *to, char *id)
|
|
{
|
|
StanzaBuilder *builder;
|
|
if (!from || !to)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
builder = Malloc(sizeof(*builder));
|
|
|
|
builder->sub_items = ArrayCreate();
|
|
|
|
builder->id = id ? StrRandom(64) : StrDuplicate(id);
|
|
builder->from = StrDuplicate(from);
|
|
builder->to = StrDuplicate(to);
|
|
|
|
builder->replying_to_stanza = NULL;
|
|
builder->replying_to_sender = NULL;
|
|
builder->editing = NULL;
|
|
builder->type = NULL;
|
|
builder->body = NULL;
|
|
builder->oob = NULL;
|
|
|
|
return SetStanzaType(builder, "chat");
|
|
}
|
|
|
|
StanzaBuilder *
|
|
SetStanzaType(StanzaBuilder *builder, char *type)
|
|
{
|
|
if (!builder || !type)
|
|
{
|
|
return builder;
|
|
}
|
|
|
|
Free(builder->type);
|
|
builder->type = StrDuplicate(type);
|
|
|
|
return builder;
|
|
}
|
|
|
|
StanzaBuilder *
|
|
SetStanzaReply(StanzaBuilder *builder, char *stanza, char *sender)
|
|
{
|
|
if (!builder || !stanza || !sender)
|
|
{
|
|
return builder;
|
|
}
|
|
|
|
Free(builder->replying_to_stanza);
|
|
Free(builder->replying_to_sender);
|
|
builder->replying_to_stanza = StrDuplicate(stanza);
|
|
builder->replying_to_sender = StrDuplicate(sender);
|
|
return builder;
|
|
}
|
|
StanzaBuilder *
|
|
SetStanzaEdit(StanzaBuilder *builder, char *to)
|
|
{
|
|
if (!builder || !to)
|
|
{
|
|
return builder;
|
|
}
|
|
|
|
Free(builder->editing);
|
|
builder->editing = StrDuplicate(to);
|
|
return builder;
|
|
}
|
|
StanzaBuilder *
|
|
SetStanzaBody(StanzaBuilder *builder, char *body)
|
|
{
|
|
if (!builder || !body)
|
|
{
|
|
return builder;
|
|
}
|
|
|
|
Free(builder->body);
|
|
builder->body = StrDuplicate(body);
|
|
return builder;
|
|
}
|
|
StanzaBuilder *
|
|
SetStanzaID(StanzaBuilder *builder, char *id)
|
|
{
|
|
if (!builder || !id)
|
|
{
|
|
return builder;
|
|
}
|
|
|
|
Free(builder->id);
|
|
builder->id = StrDuplicate(id);
|
|
return builder;
|
|
}
|
|
StanzaBuilder *
|
|
SetStanzaLink(StanzaBuilder *builder, char *oob)
|
|
{
|
|
if (!builder || !oob)
|
|
{
|
|
return builder;
|
|
}
|
|
|
|
Free(builder->oob);
|
|
builder->oob = StrDuplicate(oob);
|
|
return builder;
|
|
}
|
|
StanzaBuilder *
|
|
AddStanzaElem(StanzaBuilder *builder, XMLElement *item)
|
|
{
|
|
if (!builder || !item)
|
|
{
|
|
return builder;
|
|
}
|
|
|
|
ArrayAdd(builder->sub_items, item);
|
|
return builder;
|
|
}
|
|
|
|
XMLElement *
|
|
ExportStanza(StanzaBuilder *builder)
|
|
{
|
|
XMLElement *elem, *request, *markable;
|
|
size_t i;
|
|
if (!builder)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
elem = XMLCreateTag("message");
|
|
XMLAddAttr(elem, "from", builder->from);
|
|
XMLAddAttr(elem, "to", builder->to);
|
|
XMLAddAttr(elem, "id", builder->id);
|
|
XMLAddAttr(elem, "type", builder->type);
|
|
|
|
request = XMLCreateTag("request");
|
|
XMLAddAttr(request, "xmlns", "urn:xmpp:receipts");
|
|
XMLAddChild(elem, request);
|
|
|
|
markable = XMLCreateTag("markable");
|
|
XMLAddAttr(markable, "xmlns", "urn:xmpp:chat-markers:0");
|
|
XMLAddChild(elem, markable);
|
|
|
|
if (builder->editing)
|
|
{
|
|
XMLElement *xedit = XMLCreateTag("replace");
|
|
XMLAddAttr(xedit, "xmlns", "urn:xmpp:message-correct:0");
|
|
XMLAddAttr(xedit, "id", builder->editing);
|
|
XMLAddChild(elem, xedit);
|
|
}
|
|
if (builder->oob)
|
|
{
|
|
XMLElement *xoob, *oob_data, *oob_url;
|
|
|
|
xoob = XMLCreateTag("x");
|
|
oob_url = XMLCreateTag("url");
|
|
oob_data = XMLCreateText(builder->oob);
|
|
|
|
XMLAddAttr(xoob, "xmlns", "jabber:x:oob");
|
|
|
|
XMLAddChild(elem, xoob);
|
|
XMLAddChild(xoob, oob_url);
|
|
XMLAddChild(oob_url, oob_data);
|
|
}
|
|
if (builder->replying_to_stanza &&
|
|
builder->replying_to_sender &&
|
|
builder->body)
|
|
{
|
|
int off = ParseeFindDatastartU(builder->body);
|
|
char *ostr = StrInt(off);
|
|
XMLElement *reply = XMLCreateTag("reply");
|
|
XMLElement *fallback = XMLCreateTag("fallback");
|
|
XMLElement *fall_body = XMLCreateTag("body");
|
|
|
|
XMLAddAttr(reply, "to", builder->replying_to_sender);
|
|
XMLAddAttr(reply, "id", builder->replying_to_stanza);
|
|
XMLAddAttr(reply, "xmlns", "urn:xmpp:reply:0");
|
|
|
|
XMLAddAttr(fallback, "xmlns", "urn:xmpp:fallback:0");
|
|
XMLAddAttr(fallback, "for", "urn:xmpp:reply:0");
|
|
|
|
XMLAddAttr(fall_body, "start", "0");
|
|
XMLAddAttr(fall_body, "end", ostr);
|
|
XMLAddChild(fallback, fall_body);
|
|
|
|
XMLAddChild(elem, reply);
|
|
XMLAddChild(elem, fallback);
|
|
|
|
Free(ostr);
|
|
}
|
|
|
|
if (builder->body)
|
|
{
|
|
XMLElement *body = XMLCreateTag("body");
|
|
XMLElement *text = XMLCreateText(builder->body);
|
|
|
|
XMLAddChild(elem, body);
|
|
XMLAddChild(body, text);
|
|
}
|
|
|
|
for (i = 0; i < ArraySize(builder->sub_items); i++)
|
|
{
|
|
XMLElement *sub_item = ArrayGet(builder->sub_items, i);
|
|
XMLElement *dup = XMLCopy(sub_item);
|
|
|
|
XMLAddChild(elem, dup);
|
|
}
|
|
return elem;
|
|
}
|
|
|
|
void
|
|
WriteoutStanza(StanzaBuilder *builder, XMPPComponent *jabber, size_t max)
|
|
{
|
|
XMLElement *elem;
|
|
if (!builder || !jabber)
|
|
{
|
|
return;
|
|
}
|
|
if (!max)
|
|
{
|
|
max = 10000; /* XMPP recommended limit */
|
|
}
|
|
|
|
elem = ExportStanza(builder);
|
|
XMPPSendStanza(jabber, elem, max);
|
|
XMLFreeElement(elem);
|
|
}
|
|
|
|
StanzaBuilder *
|
|
SetStanzaXParsee(StanzaBuilder *builder, HashMap *e)
|
|
{
|
|
XMLElement *parsee;
|
|
if (!builder || !e)
|
|
{
|
|
return builder;
|
|
}
|
|
parsee = XMLCreateTag("x-parsee");
|
|
XMLAddAttr(parsee, "xmlns", "https://at.kappach.at/jabber/parsee#info");
|
|
{
|
|
XMLElement *parsee_version, *ver_elem;
|
|
XMLElement *parsee_link, *link_elem;
|
|
XMLElement *parsee_event, *event_elem;
|
|
XMLElement *parsee_json, *json_elem;
|
|
char *event_id = GrabString(e, 1, "event_id");
|
|
char *json = NULL;
|
|
Stream *stream = StrStreamWriter(&json);
|
|
|
|
JsonEncode(e, stream, JSON_DEFAULT);
|
|
StreamFlush(stream);
|
|
StreamClose(stream);
|
|
|
|
parsee_version = XMLCreateTag("version");
|
|
ver_elem = XMLCreateText(VERSION "[" CODE "]");
|
|
XMLAddChild(parsee_version, ver_elem);
|
|
XMLAddChild(parsee, parsee_version);
|
|
|
|
parsee_json = XMLCreateTag("json");
|
|
json_elem = XMLCreateText(json);
|
|
XMLAddChild(parsee_json, json_elem);
|
|
XMLAddChild(parsee, parsee_json);
|
|
Free(json);
|
|
|
|
parsee_link = XMLCreateTag("repository");
|
|
link_elem = XMLCreateText(REPOSITORY);
|
|
XMLAddChild(parsee_link, link_elem);
|
|
XMLAddChild(parsee, parsee_link);
|
|
|
|
if (event_id)
|
|
{
|
|
parsee_event = XMLCreateTag("event-id");
|
|
event_elem = XMLCreateText(event_id);
|
|
XMLAddChild(parsee_event, event_elem);
|
|
XMLAddChild(parsee, parsee_event);
|
|
}
|
|
}
|
|
AddStanzaElem(builder, parsee);
|
|
return builder;
|
|
}
|
|
|
|
void
|
|
DestroyStanzaBuilder(StanzaBuilder *builder)
|
|
{
|
|
size_t i;
|
|
if (!builder)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < ArraySize(builder->sub_items); i++)
|
|
{
|
|
XMLElement *sub_item = ArrayGet(builder->sub_items, i);
|
|
|
|
XMLFreeElement(sub_item);
|
|
}
|
|
ArrayFree(builder->sub_items);
|
|
|
|
Free(builder->replying_to_stanza);
|
|
Free(builder->replying_to_sender);
|
|
Free(builder->editing);
|
|
Free(builder->from);
|
|
Free(builder->body);
|
|
Free(builder->type);
|
|
Free(builder->oob);
|
|
Free(builder->to);
|
|
Free(builder->id);
|
|
Free(builder);
|
|
}
|