XMPP: add function to generate XML-Stanzas
authorWilfried Goesgens <dothebart@citadel.org>
Sat, 2 Nov 2013 15:12:48 +0000 (16:12 +0100)
committerWilfried Goesgens <dothebart@citadel.org>
Sat, 2 Nov 2013 15:12:48 +0000 (16:12 +0100)
citadel/modules/xmpp/serv_xmpp.c
citadel/modules/xmpp/serv_xmpp.h
citadel/modules/xmpp/xmpp_messages.c
citadel/modules/xmpp/xmpp_presence.c
citadel/modules/xmpp/xmpp_query_namespace.c
citadel/modules/xmpp/xmpp_sasl_service.c

index 1e0f704b4a7a75f9bf2a30a6ee67172c709aa689..96ffaf4f5b5a4f3847a5796e24186867f4a42681 100644 (file)
@@ -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("</");
+                       XPut(Token, tlen);
+                       XPUT(">");
+               }
+               else
+               {
+                       XPUT("></");
+                       XPut(Token, tlen);
+                       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,
index 84bc29d5cf9a04386d08b89510c7492ffc4d1cd0..715abd41dc0524d05fc301c1e9a84773d5c7583c 100644 (file)
@@ -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
index 33a2e1ddbeb548c3ba4335960763eda1bc431a12..b2e2dadf4869736fa5bc15a409f77505842d7917 100644 (file)
@@ -75,18 +75,17 @@ void xmpp_output_incoming_messages(void)
                CCC->FirstExpressMessage = CCC->FirstExpressMessage->next;
                end_critical_section(S_SESSION_TABLE);
 
-               
-               XPUT("<message type=\"chat\" to=\"");
-               XPutProp(Xmpp->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("<body>");
-                       XPutBody(ptr->text, strlen(ptr->text));
-                       XPUT("</body>");
+                       XPrint(HKEY("body"), XCLOSED,
+                              XBODY(ptr->text, strlen(ptr->text)),
+                              TYPE_ARGEND);
                        free(ptr->text);
                }
                XPUT("</message>");
index 521d257c4cb386d1e1c8a027f5b4a5331794cf16..9191f8f65561b413cc28c4b7e2938e360be6f105 100644 (file)
  */
 void xmpp_indicate_presence(char *presence_jid)
 {
-       XPUT("<presence from=\"");
-       XPutProp(presence_jid, strlen(presence_jid));
-       XPUT("\" to=\"");
-       XPutProp(XMPP->client_jid, strlen(XMPP->client_jid));
-       XPUT("\"></presence>");
+       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("<presence type=\"unavailable\" from=\"");
-       XPutProp(presence_jid, strlen(presence_jid));
-       XPUT("\" to=\"");
-       XPutProp(XMPP->client_jid, strlen(XMPP->client_jid));
-       XPUT("\"></presence>");
+       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("<presence type=\"unsubscribed\" from=\"");
-               XPutProp(presence_jid, strlen(presence_jid));
-               XPUT("\" to=\"");
-               XPutProp(XMPP->client_jid, strlen(XMPP->client_jid));
-               XPUT("\"></presence>");
+               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("<iq type=\"result\" from=\"");
-       XPutProp(CCC->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("<query xmlns=\"jabber:iq:roster\">"
-            "<item subscription=\"remove\" jid=\"");
-       XPutProp(presence_jid, strlen(presence_jid));
-       XPUT("\">" 
-            "<group>");
-       XPutBody(CFG_KEY(c_humannode));
-       XPUT("</group>"
-            "</item>"
+       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("</item>"
             "</query>"
             "</iq>"
        );
@@ -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("<iq type=\"result\" id=\"unsolicited_");
-               XPrintf("%x", ++unsolicited_id);
-               XPUT("\" >"
-                    "<query xmlns=\"jabber:iq:roster\">");
+
+               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("</query></iq>");
 
index e791f3e6bcac09305038cb502165288ee9976b4a..0da671c5f3aa9692236cc405d1b068b17f01427d 100644 (file)
  */
 void xmpp_roster_item(struct CitContext *cptr)
 {
+       struct CitContext *CCC=CC;
 
-       XPUT("<item subscription=\"both\" jid=\"");
-       XPutProp(cptr->cs_inet_email, strlen(cptr->cs_inet_email));
-       XPUT("\" name=\"");
-       XPutProp(cptr->user.fullname, strlen(cptr->user.fullname));
-       XPUT("\">"
-            "<group>");
-       XPutBody(CFG_KEY(c_humannode));
-       XPUT("</group>"
-            "</item>");
+       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("</item>");
 }
 
 /* 
@@ -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("<iq type=\"result\" ");
+               TypeStr = Type[0].Key;
+               TLen    = Type[0].len;
        }
        else {
-                XPUT("<iq type=\"error\" ");
+               TypeStr = Type[1].Key;
+               TLen    = Type[1].len;
        }
-       if (!IsEmptyStr(iq_from)) {
-               XPUT("to=\"");
-               XPutProp(iq_from, strlen(iq_from));
-               XPUT("\" ");
-       }
-       XPUT("id=\"");
-       XPutProp(iq_id, strlen(iq_id));
-       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?
index 968cef950025830a79e5491153be821a8d0b7a2b..fd4986137b1fa28ad484dd31f0f1cf726702bea9 100644 (file)
@@ -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("<iq type=\"result\" id=\"");
-                       XPutProp(iq_id, strlen(iq_id));
-                       XPUT("\"></iq>"); /* success */
+                       XPrint(HKEY("iq"), XCLOSED,
+                              XCPROPERTY("type", "result"),
+                              XPROPERTY("ID", iq_id, strlen(iq_id)),
+                              TYPE_ARGEND);
+                              /* success */
                        return;
                }
        }
 
        /* failure */
-       XPUT("<iq type=\"error\" id=\"");
-       XPutProp(iq_id, strlen(iq_id));
-       XPUT("\">"
-            "<error code=\"401\" type=\"auth\">"
+       XPrint(HKEY("iq"), 0,
+              XCPROPERTY("type", "error"),
+              XPROPERTY("ID", iq_id, strlen(iq_id)),
+              TYPE_ARGEND);
+       XPUT("<error code=\"401\" type=\"auth\">"
             "<not-authorized xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/>"
             "</error>"
             "</iq>"