diff src/protocols/jabber/jid.c @ 2086:424a40f12a6c

[gaim-migrate @ 2096] moving protocols from plugins/ to src/protocols. making it so that you can select which protocols are compiled statically. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Tue, 31 Jul 2001 01:00:39 +0000
parents
children 4e7cefc55971
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/jabber/jid.c	Tue Jul 31 01:00:39 2001 +0000
@@ -0,0 +1,287 @@
+/*
+ *  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 2 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.
+ *
+ *  Jabber
+ *  Copyright (C) 1998-1999 The Jabber Team http://jabber.org/
+ */
+
+#include "jabber.h"
+
+jid jid_safe(jid id)
+{
+    char *str;
+
+    if(strlen(id->server) == 0 || strlen(id->server) > 255)
+        return NULL;
+
+    /* lowercase the hostname, make sure it's valid characters */
+    for(str = id->server; *str != '\0'; str++)
+    {
+        *str = tolower(*str);
+        if(!(isalnum(*str) || *str == '.' || *str == '-' || *str == '_')) return NULL;
+    }
+
+    /* cut off the user */
+    if(id->user != NULL && strlen(id->user) > 64)
+        id->user[64] = '\0';
+
+    /* check for low and invalid ascii characters in the username */
+    if(id->user != NULL)
+        for(str = id->user; *str != '\0'; str++)
+            if(*str <= 32 || *str == ':' || *str == '@' || *str == '<' || *str == '>' || *str == '\'' || *str == '"' || *str == '&') return NULL;
+
+    return id;
+}
+
+jid jid_new(pool p, char *idstr)
+{
+    char *server, *resource, *type, *str;
+    jid id;
+
+    if(p == NULL || idstr == NULL || strlen(idstr) == 0)
+        return NULL;
+
+    /* user@server/resource */
+
+    str = pstrdup(p, idstr);
+
+    id = pmalloc(p,sizeof(struct jid_struct));
+    id->full = id->server = id->user = id->resource = NULL;
+    id->p = p;
+    id->next = NULL;
+
+    resource = strstr(str,"/");
+    if(resource != NULL)
+    {
+        *resource = '\0';
+        ++resource;
+        if(strlen(resource) > 0)
+            id->resource = resource;
+    }else{
+        resource = str + strlen(str); /* point to end */
+    }
+
+    type = strstr(str,":");
+    if(type != NULL && type < resource)
+    {
+        *type = '\0';
+        ++type;
+        str = type; /* ignore the type: prefix */
+    }
+
+    server = strstr(str,"@");
+    if(server == NULL || server > resource)
+    { /* if there's no @, it's just the server address */
+        id->server = str;
+    }else{
+        *server = '\0';
+        ++server;
+        id->server = server;
+        if(strlen(str) > 0)
+            id->user = str;
+    }
+
+    return jid_safe(id);
+}
+
+void jid_set(jid id, char *str, int item)
+{
+    char *old;
+
+    if(id == NULL)
+        return;
+
+    /* invalidate the cached copy */
+    id->full = NULL;
+
+    switch(item)
+    {
+    case JID_RESOURCE:
+        if(str != NULL && strlen(str) != 0)
+            id->resource = pstrdup(id->p, str);
+        else
+            id->resource = NULL;
+        break;
+    case JID_USER:
+        old = id->user;
+        if(str != NULL && strlen(str) != 0)
+            id->user = pstrdup(id->p, str);
+        else
+            id->user = NULL;
+        if(jid_safe(id) == NULL)
+            id->user = old; /* revert if invalid */
+        break;
+    case JID_SERVER:
+        old = id->server;
+        id->server = pstrdup(id->p, str);
+        if(jid_safe(id) == NULL)
+            id->server = old; /* revert if invalid */
+        break;
+    }
+
+}
+
+char *jid_full(jid id)
+{
+    spool s;
+
+    if(id == NULL)
+        return NULL;
+
+    /* use cached copy */
+    if(id->full != NULL)
+        return id->full;
+
+    s = spool_new(id->p);
+
+    if(id->user != NULL)
+        spooler(s, id->user,"@",s);
+
+    spool_add(s, id->server);
+
+    if(id->resource != NULL)
+        spooler(s, "/",id->resource,s);
+
+    id->full = spool_print(s);
+    return id->full;
+}
+
+/* parses a /resource?name=value&foo=bar into an xmlnode representing <resource name="value" foo="bar"/> */
+xmlnode jid_xres(jid id)
+{
+    char *cur, *qmark, *amp, *eq;
+    xmlnode x;
+
+    if(id == NULL || id->resource == NULL) return NULL;
+
+    cur = pstrdup(id->p, id->resource);
+    qmark = strstr(cur, "?");
+    if(qmark == NULL) return NULL;
+    *qmark = '\0';
+    qmark++;
+
+    x = _xmlnode_new(id->p, cur, NTYPE_TAG);
+
+    cur = qmark;
+    while(cur != '\0')
+    {
+        eq = strstr(cur, "=");
+        if(eq == NULL) break;
+        *eq = '\0';
+        eq++;
+
+        amp = strstr(eq, "&");
+        if(amp != NULL)
+        {
+            *amp = '\0';
+            amp++;
+        }
+
+        xmlnode_put_attrib(x,cur,eq);
+
+        if(amp != NULL)
+            cur = amp;
+        else
+            break;
+    }
+
+    return x;
+}
+
+/* local utils */
+int _jid_nullstrcmp(char *a, char *b)
+{
+    if(a == NULL && b == NULL) return 0;
+    if(a == NULL || b == NULL) return -1;
+    return strcmp(a,b);
+}
+int _jid_nullstrcasecmp(char *a, char *b)
+{
+    if(a == NULL && b == NULL) return 0;
+    if(a == NULL || b == NULL) return -1;
+    return strcasecmp(a,b);
+}
+
+int jid_cmp(jid a, jid b)
+{
+    if(a == NULL || b == NULL)
+        return -1;
+
+    if(_jid_nullstrcmp(a->resource, b->resource) != 0) return -1;
+    if(_jid_nullstrcasecmp(a->user, b->user) != 0) return -1;
+    if(_jid_nullstrcmp(a->server, b->server) != 0) return -1;
+
+    return 0;
+}
+
+/* suggested by Anders Qvist <quest@valdez.netg.se> */
+int jid_cmpx(jid a, jid b, int parts)
+{
+    if(a == NULL || b == NULL)
+        return -1;
+
+    if(parts & JID_RESOURCE && _jid_nullstrcmp(a->resource, b->resource) != 0) return -1;
+    if(parts & JID_USER && _jid_nullstrcasecmp(a->user, b->user) != 0) return -1;
+    if(parts & JID_SERVER && _jid_nullstrcmp(a->server, b->server) != 0) return -1;
+
+    return 0;
+}
+
+/* makes a copy of b in a's pool, requires a valid a first! */
+jid jid_append(jid a, jid b)
+{
+    jid next;
+
+    if(a == NULL)
+        return NULL;
+
+    if(b == NULL)
+        return a;
+
+    next = a;
+    while(next != NULL)
+    {
+        /* check for dups */
+        if(jid_cmp(next,b) == 0)
+            break;
+        if(next->next == NULL)
+            next->next = jid_new(a->p,jid_full(b));
+        next = next->next;
+    }
+    return a;
+}
+
+xmlnode jid_nodescan(jid id, xmlnode x)
+{
+    xmlnode cur;
+    pool p;
+    jid tmp;
+
+    if(id == NULL || xmlnode_get_firstchild(x) == NULL) return NULL;
+
+    p = pool_new();
+    for(cur = xmlnode_get_firstchild(x); cur != NULL; cur = xmlnode_get_nextsibling(cur))
+    {
+        if(xmlnode_get_type(cur) != NTYPE_TAG) continue;
+
+        tmp = jid_new(p,xmlnode_get_attrib(cur,"jid"));
+        if(tmp == NULL) continue;
+
+        if(jid_cmp(tmp,id) == 0) break;
+    }
+    pool_free(p);
+
+    return cur;
+}