From bb47b9c23a29dee2a8d801655a237ec50078b348 Mon Sep 17 00:00:00 2001 From: Wilfried Goesgens Date: Sat, 2 Nov 2013 16:12:48 +0100 Subject: [PATCH] XMPP: add function to generate XML-Stanzas --- citadel/modules/xmpp/serv_xmpp.c | 90 +++++++++++++++++++++ citadel/modules/xmpp/serv_xmpp.h | 18 +++++ citadel/modules/xmpp/xmpp_messages.c | 17 ++-- citadel/modules/xmpp/xmpp_presence.c | 87 ++++++++++++-------- citadel/modules/xmpp/xmpp_query_namespace.c | 48 ++++++----- citadel/modules/xmpp/xmpp_sasl_service.c | 17 ++-- 6 files changed, 206 insertions(+), 71 deletions(-) diff --git a/citadel/modules/xmpp/serv_xmpp.c b/citadel/modules/xmpp/serv_xmpp.c index 1e0f704b4..96ffaf4f5 100644 --- a/citadel/modules/xmpp/serv_xmpp.c +++ b/citadel/modules/xmpp/serv_xmpp.c @@ -103,6 +103,96 @@ void XPrintf(const char *Format, ...) } +void XPrint(const char *Token, long tlen, + int Flags, + ...) + +{ + int BodySeen = 0; + int ArgType; + int Finished = 0; + char *PName; + long PLen; + char *Val; + long VLen; + va_list arg_ptr; + + XPUT("<"); + XPut(Token, tlen); + + va_start(arg_ptr, Flags); + while (!Finished) + { + ArgType = va_arg(arg_ptr, int); + switch (ArgType) + { + case TYPE_STR: + PName = va_arg(arg_ptr, char*); + PLen = va_arg(arg_ptr, long); + Val = va_arg(arg_ptr, char*); + VLen = va_arg(arg_ptr, long); + XPUT(" "); + XPut(PName, PLen); + XPUT("=\""); + XPutProp(Val, VLen); + XPUT("\""); + break; + case TYPE_OPTSTR: + PName = va_arg(arg_ptr, char*); + PLen = va_arg(arg_ptr, long); + Val = va_arg(arg_ptr, char*); + VLen = va_arg(arg_ptr, long); + if (VLen > 0) + { + XPUT(" "); + XPut(PName, PLen); + XPUT("=\""); + XPutProp(Val, VLen); + XPUT("\""); + } + break; + case TYPE_INT: + PName = va_arg(arg_ptr, char*); + PLen = va_arg(arg_ptr, long); + VLen = va_arg(arg_ptr, long); + XPUT(" "); + XPut(PName, PLen); + XPUT("=\""); + XPrintf("%ld", VLen); + XPUT("\""); + break; + case TYPE_BODYSTR: + BodySeen = 1; + XPUT(">"); + Val = va_arg(arg_ptr, char*); + VLen = va_arg(arg_ptr, long); + XPutBody(Val, VLen); + break; + case TYPE_ARGEND: + Finished = 1; + break; + } + } + if (Flags == XCLOSED) + { + if (BodySeen) + { + XPUT(""); + } + else + { + XPUT(">"); + } + } + else + XPUT(">"); + va_end(arg_ptr); +} + #ifdef HAVE_XML_STOPPARSER /* Stop the parser if an entity declaration is hit. */ static void xmpp_entity_declaration(void *userData, const XML_Char *entityName, diff --git a/citadel/modules/xmpp/serv_xmpp.h b/citadel/modules/xmpp/serv_xmpp.h index 84bc29d5c..715abd41d 100644 --- a/citadel/modules/xmpp/serv_xmpp.h +++ b/citadel/modules/xmpp/serv_xmpp.h @@ -124,3 +124,21 @@ void AddXMPPEndHandler(const char *key, long len, xmpp_handler_func Handler, int Flags); + + +#define XCLOSED (1<<0) +void XPrint(const char *Token, long tlen, + int Flags, + ...); + +#define TYPE_STR 1 +#define TYPE_OPTSTR 2 +#define TYPE_INT 3 +#define TYPE_BODYSTR 4 +#define TYPE_ARGEND 5 +#define XPROPERTY(NAME, VALUE, VLEN) TYPE_STR, NAME, sizeof(NAME)-1, VALUE, VLEN +#define XOPROPERTY(NAME, VALUE, VLEN) TYPE_OPTSTR, NAME, sizeof(NAME)-1, VALUE, VLEN +#define XCPROPERTY(NAME, VALUE) TYPE_STR, NAME, sizeof(NAME)-1, VALUE, sizeof(VALUE) - 1 +#define XIPROPERTY(NAME, LVALUE) TYPE_INT, NAME, SIZEOF(NAME)-1 +#define XBODY(VALUE, VLEN) TYPE_BODYSTR, VALUE, VLEN +#define XCFGBODY(WHICH) TYPE_BODYSTR, config.WHICH, configlen.WHICH diff --git a/citadel/modules/xmpp/xmpp_messages.c b/citadel/modules/xmpp/xmpp_messages.c index 33a2e1ddb..b2e2dadf4 100644 --- a/citadel/modules/xmpp/xmpp_messages.c +++ b/citadel/modules/xmpp/xmpp_messages.c @@ -75,18 +75,17 @@ void xmpp_output_incoming_messages(void) CCC->FirstExpressMessage = CCC->FirstExpressMessage->next; end_critical_section(S_SESSION_TABLE); - - XPUT("client_jid, strlen(Xmpp->client_jid)); - XPUT("\" from=\""); - XPutProp(ptr->sender_email, strlen(ptr->sender_email)); - XPUT("\" >"); + XPrint(HKEY("message"), 0, + XCPROPERTY("type", "chat"), + XPROPERTY("to", Xmpp->client_jid, strlen(Xmpp->client_jid)), + XPROPERTY("from", ptr->sender_email, strlen(ptr->sender_email)), + TYPE_ARGEND); if (ptr->text != NULL) { striplt(ptr->text); - XPUT(""); - XPutBody(ptr->text, strlen(ptr->text)); - XPUT(""); + XPrint(HKEY("body"), XCLOSED, + XBODY(ptr->text, strlen(ptr->text)), + TYPE_ARGEND); free(ptr->text); } XPUT(""); diff --git a/citadel/modules/xmpp/xmpp_presence.c b/citadel/modules/xmpp/xmpp_presence.c index 521d257c4..9191f8f65 100644 --- a/citadel/modules/xmpp/xmpp_presence.c +++ b/citadel/modules/xmpp/xmpp_presence.c @@ -65,11 +65,10 @@ */ void xmpp_indicate_presence(char *presence_jid) { - XPUT("client_jid, strlen(XMPP->client_jid)); - XPUT("\">"); + XPrint(HKEY("presence"), + XPROPERTY("from", presence_jid, strlen(presence_jid)), + XPROPERTY("to", XMPP->client_jid, strlen(XMPP->client_jid)), + TYPE_ARGEND); } @@ -125,17 +124,19 @@ void xmpp_wholist_presence_dump(void *data, const char *supplied_el, const char void xmpp_destroy_buddy(char *presence_jid, int aggressively) { static int unsolicited_id = 1; struct CitContext *CCC = CC; + char Buf[64]; + long blen; if (!presence_jid) return; if (!XMPP) return; if (!XMPP->client_jid) return; /* Transmit non-presence information */ - XPUT("client_jid, strlen(XMPP->client_jid)); - XPUT("\">"); + XPrint(HKEY("presence"), XCLOSED, + XCPROPERTY("type", "unavailable"), + XPROPERTY("from", presence_jid, strlen(presence_jid)), + XPROPERTY("to", XMPP->client_jid, strlen(XMPP->client_jid)), + TYPE_ARGEND); /* * Setting the "aggressively" flag also sends an "unsubscribed" presence update. @@ -144,32 +145,38 @@ void xmpp_destroy_buddy(char *presence_jid, int aggressively) { * it as a rejection of a subscription request. */ if (aggressively) { - XPUT("client_jid, strlen(XMPP->client_jid)); - XPUT("\">"); + XPrint(HKEY("presence"), XCLOSED, + XCPROPERTY("type", "unsubscribed"), + XPROPERTY("from", presence_jid, strlen(presence_jid)), + XPROPERTY("to", XMPP->client_jid, strlen(XMPP->client_jid)), + TYPE_ARGEND); } // FIXME ... we should implement xmpp_indicate_nonpresence so we can use it elsewhere + blen = snprintf(Buf, sizeof(Buf), "unbuddy_%x", ++unsolicited_id); + /* Do an unsolicited roster update that deletes the contact. */ - XPUT("cs_inet_email, strlen(CCC->cs_inet_email)); - XPUT("\" to=\""); - XPutProp(XMPP->client_jid, strlen(XMPP->client_jid)); - XPUT("\" id=\"unbuddy_"); - XPrintf("%x", ++unsolicited_id); - XPUT("\">"); - - XPUT("" - "" - ""); - XPutBody(CFG_KEY(c_humannode)); - XPUT("" - "" + XPrint(HKEY("iq"), 0, + XCPROPERTY("type", "result"), + XPROPERTY("from", CCC->cs_inet_email, strlen(CCC->cs_inet_email)), + XPROPERTY("to", XMPP->client_jid, strlen(XMPP->client_jid)), + XPROPERTY("id", Buf, blen), + TYPE_ARGEND); + + XPrint(HKEY("query"), 0, + XCPROPERTY("xmlns", "jabber:iq:roster"), + TYPE_ARGEND); + + XPrint(HKEY("item"), 0, + XCPROPERTY("subscription", "remove"), + XPROPERTY("jid", presence_jid, strlen(presence_jid)), + TYPE_ARGEND); + + XPrint(HKEY("group"), XCLOSED, + XCFGBODY(c_humannode), + TYPE_ARGEND); + XPUT("" "" "" ); @@ -209,16 +216,26 @@ void xmpp_presence_notify(char *presence_jid, int event_type) { visible_sessions, presence_jid, CC->cs_pid); if ( (event_type == XMPP_EVT_LOGIN) && (visible_sessions == 1) ) { + long blen; + char Buf[64]; XMPP_syslog(LOG_DEBUG, "Telling session %d that <%s> logged in\n", CC->cs_pid, presence_jid); /* Do an unsolicited roster update that adds a new contact. */ assert(which_cptr_is_relevant >= 0); - XPUT("" - ""); + + blen = snprintf(Buf, sizeof(Buf), "unsolicited_%x", ++unsolicited_id); + + XPrint(HKEY("iq"), 0, + XCPROPERTY("type", "result"), + XPROPERTY("id", Buf, blen), + TYPE_ARGEND); + + XPrint(HKEY("query"), 0, + XCPROPERTY("xmlns", "jabber:iq:roster"), + TYPE_ARGEND); + xmpp_roster_item(&cptr[which_cptr_is_relevant]); XPUT(""); diff --git a/citadel/modules/xmpp/xmpp_query_namespace.c b/citadel/modules/xmpp/xmpp_query_namespace.c index e791f3e6b..0da671c5f 100644 --- a/citadel/modules/xmpp/xmpp_query_namespace.c +++ b/citadel/modules/xmpp/xmpp_query_namespace.c @@ -61,16 +61,19 @@ */ void xmpp_roster_item(struct CitContext *cptr) { + struct CitContext *CCC=CC; - XPUT("cs_inet_email, strlen(cptr->cs_inet_email)); - XPUT("\" name=\""); - XPutProp(cptr->user.fullname, strlen(cptr->user.fullname)); - XPUT("\">" - ""); - XPutBody(CFG_KEY(c_humannode)); - XPUT("" - ""); + XPrint(HKEY("item"), 0, + XCPROPERTY("subscription", "both"), + XPROPERTY("jid", CCC->cs_inet_email, strlen(CCC->cs_inet_email)), + XPROPERTY("name", cptr->user.fullname, strlen(cptr->user.fullname)), + TYPE_ARGEND); + + XPrint(HKEY("group"), XCLOSED, + XCFGBODY(c_humannode), + TYPE_ARGEND); + + XPUT(""); } /* @@ -113,7 +116,13 @@ void xmpp_query_namespace(char *iq_id, char *iq_from, char *iq_to, char *query_x { int supported_namespace = 0; int roster_query = 0; - + const char *TypeStr; + long TLen; + ConstStr Type[] = { + {HKEY("result")}, + {HKEY("error")} + }; + /* We need to know before we begin the response whether this is a supported namespace, so * unfortunately all supported namespaces need to be defined here *and* down below where * they are handled. @@ -131,19 +140,18 @@ void xmpp_query_namespace(char *iq_id, char *iq_from, char *iq_to, char *query_x * Beginning of query result. */ if (supported_namespace) { - XPUT(""); + + XPrint(HKEY("iq"), 0, + XPROPERTY("type", TypeStr, TLen), + XOPROPERTY("to", iq_from, strlen(iq_from)), + XPROPERTY("id", iq_id, strlen(iq_id))); /* * Is this a query we know how to handle? diff --git a/citadel/modules/xmpp/xmpp_sasl_service.c b/citadel/modules/xmpp/xmpp_sasl_service.c index 968cef950..fd4986137 100644 --- a/citadel/modules/xmpp/xmpp_sasl_service.c +++ b/citadel/modules/xmpp/xmpp_sasl_service.c @@ -163,18 +163,21 @@ void xmpp_non_sasl_authenticate(char *iq_id, char *username, char *password, cha if (result == login_ok) { result = CtdlTryPassword(password, strlen(password)); if (result == pass_ok) { - XPUT(""); /* success */ + XPrint(HKEY("iq"), XCLOSED, + XCPROPERTY("type", "result"), + XPROPERTY("ID", iq_id, strlen(iq_id)), + TYPE_ARGEND); + /* success */ return; } } /* failure */ - XPUT("" - "" + XPrint(HKEY("iq"), 0, + XCPROPERTY("type", "error"), + XPROPERTY("ID", iq_id, strlen(iq_id)), + TYPE_ARGEND); + XPUT("" "" "" "" -- 2.30.2