* fill the migrate buffer so the new sock_getln works
[citadel.git] / citadel / modules / jabber / xmpp_query_namespace.c
index f1d49a188ebde6ae72c449f80371a7a175a055f5..64aba16c518fa2ddc593f956b7ad266ff9ce90f2 100644 (file)
@@ -3,9 +3,21 @@
  *
  * Handle <iq> <get> <query> type situations (namespace queries)
  *
- * Copyright (c) 2007 by Art Cancro
- * This code is released under the terms of the GNU General Public License.
+ * Copyright (c) 2007-2009 by Art Cancro
  *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #include "sysdep.h"
@@ -33,6 +45,7 @@
 #include <string.h>
 #include <limits.h>
 #include <ctype.h>
+#include <expat.h>
 #include <libcitadel.h>
 #include "citadel.h"
 #include "server.h"
@@ -42,9 +55,6 @@
 #include "internet_addressing.h"
 #include "md5.h"
 #include "ctdl_module.h"
-
-#ifdef HAVE_EXPAT
-#include <expat.h>
 #include "serv_xmpp.h"
 
 
@@ -70,20 +80,25 @@ void jabber_roster_item(struct CitContext *cptr) {
 void jabber_iq_roster_query(void)
 {
        struct CitContext *cptr;
+       int nContexts, i;
        int aide = (CC->user.axlevel >= 6);
 
        cprintf("<query xmlns=\"jabber:iq:roster\">");
 
-       for (cptr = ContextList; cptr != NULL; cptr = cptr->next) {
-
-               if (
-                  (((cptr->cs_flags&CS_STEALTH)==0) || (aide))
-                  && (cptr->user.usernum != CC->user.usernum)
-                  ) {
-                       jabber_roster_item(cptr);
+       cptr = CtdlGetContextArray(&nContexts);
+       if (cptr) {
+               for (i=0; i<nContexts; i++) {
+                       if (cptr[i].logged_in) {
+                               if (
+                                       (((cptr[i].cs_flags&CS_STEALTH)==0) || (aide))
+                                       && (cptr[i].user.usernum != CC->user.usernum)
+                               ) {
+                                       jabber_roster_item(&cptr[i]);
+                               }
+                       }
                }
+               free (cptr);
        }
-
        cprintf("</query>");
 }
 
@@ -97,14 +112,32 @@ xmpp_query_namespace(purple5b5c1e5a, , vcard-temp:query)
  *
  */
 
-void xmpp_query_namespace(char *iq_id, char *iq_from, char *iq_to, char *query_xmlns) {
+void xmpp_query_namespace(char *iq_id, char *iq_from, char *iq_to, char *query_xmlns)
+{
+       int supported_namespace = 0;
 
-       lprintf(CTDL_DEBUG, "xmpp_query_namespace(%s, %s, %s, %s)\n", iq_id, iq_from, iq_to, query_xmlns);
+       /* 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.
+        */
+       if (
+               (!strcasecmp(query_xmlns, "jabber:iq:roster:query"))
+               && (!strcasecmp(query_xmlns, "jabber:iq:auth:query"))
+       ) {
+               supported_namespace = 1;
+       }
+
+       CtdlLogPrintf(CTDL_DEBUG, "xmpp_query_namespace(%s, %s, %s, %s)\n", iq_id, iq_from, iq_to, query_xmlns);
 
        /*
         * Beginning of query result.
         */
-       cprintf("<iq type=\"result\" ");
+       if (supported_namespace) {
+               cprintf("<iq type=\"result\" ");
+       }
+       else {
+               cprintf("<iq type=\"error\" ");
+       }
        if (!IsEmptyStr(iq_from)) {
                cprintf("to=\"%s\" ", iq_from);
        }
@@ -118,16 +151,24 @@ void xmpp_query_namespace(char *iq_id, char *iq_from, char *iq_to, char *query_x
                jabber_iq_roster_query();
        }
 
-       else if (!strcasecmp(query_xmlns, "jabber:iq:auth")) {
-               jabber_offer_non_sasl_authentication();
+       else if (!strcasecmp(query_xmlns, "jabber:iq:auth:query")) {
+               cprintf("<query xmlns=\"jabber:iq:auth\">"
+                       "<username/><password/><resource/>"
+                       "</query>"
+               );
+       }
+
+       else {
+               CtdlLogPrintf(CTDL_DEBUG, "Unknown namespace; returning <service-unavailable/>\n");
+               cprintf("<error code=\"503\" type=\"cancel\">"
+                       "<service-unavailable xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/>"
+                       "</error>"
+               );
        }
 
        /*
-        * End of query result.  If we didn't hit any known namespaces then we will
-        * have simply delivered an empty result stanza, which should be ok.
+        * End of query result.  If we didn't hit any known namespaces then we should
+        * deliver a "service unavailable" error (see RFC3921 section 2.4 and 11.1.5.4)
         */
        cprintf("</iq>");
-
 }
-
-#endif /* HAVE_EXPAT */