diff mcabber/libjabber/xmlnode.c @ 417:c3ae9251c197

Sync libjabber with upstream Sync with jabberd-1.4.4.
author Mikael Berthe <mikael@lilotux.net>
date Thu, 01 Sep 2005 23:29:21 +0200
parents bf3d6e241714
children 5f43b532cc37
line wrap: on
line diff
--- a/mcabber/libjabber/xmlnode.c	Thu Sep 01 21:18:19 2005 +0200
+++ b/mcabber/libjabber/xmlnode.c	Thu Sep 01 23:29:21 2005 +0200
@@ -13,8 +13,19 @@
  *  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/
+ * Copyrights
+ *
+ * Portions created by or assigned to Jabber.com, Inc. are
+ * Copyright (c) 1999-2002 Jabber.com, Inc.  All Rights Reserved.  Contact
+ * information for Jabber.com, Inc. is available at http://www.jabber.com/.
+ *
+ * Portions Copyright (c) 1998-1999 Jeremie Miller.
+ *
+ * Acknowledgements
+ *
+ * Special thanks to the Jabber Open Source Contributors for their
+ * suggestions and support of Jabber.
+ *
  */
 
 #include "libxode.h"
@@ -35,8 +46,7 @@
     }
 
     /* Allocate & zero memory */
-    result = (xmlnode)pmalloc(p, sizeof(_xmlnode));
-    memset(result, '\0', sizeof(_xmlnode));
+    result = (xmlnode)pmalloco(p, sizeof(_xmlnode));
 
     /* Initialize fields */
     if (type != NTYPE_CDATA)
@@ -64,7 +74,7 @@
 {
     xmlnode result;
 
-    if(parent == NULL || name == NULL) return NULL;
+    if(parent == NULL || (type != NTYPE_CDATA && name == NULL)) return NULL;
 
     /* If parent->firstchild is NULL, simply create a new node for the first child */
     if (parent->firstchild == NULL)
@@ -100,18 +110,36 @@
     return NULL;
 }
 
-static char* _xmlnode_merge(pool p, char* dest, unsigned int destsize, const char* src, unsigned int srcsize)
+void _xmlnode_merge(xmlnode data)
 {
-    char* result;
-    result = (char*)pmalloc(p, destsize + srcsize + 1);
-    memcpy(result, dest, destsize);
-    memcpy(result+destsize, src, srcsize);
-    result[destsize + srcsize] = '\0';
+    xmlnode cur;
+    char *merge, *scur;
+    int imerge;
+
+    /* get total size of all merged cdata */
+    imerge = 0;
+    for(cur = data; cur != NULL && cur->type == NTYPE_CDATA; cur = cur->next)
+        imerge += cur->data_sz;
 
-    /* WARNING: major ugly hack: since we're throwing the old data away, let's jump in the pool and subtract it from the size, this is for xmlstream's big-node checking */
-    p->size -= destsize;
+    /* copy in current data and then spin through all of them and merge */
+    scur = merge = pmalloc(data->p,imerge + 1);
+    for(cur = data; cur != NULL && cur->type == NTYPE_CDATA; cur = cur->next)
+    {
+        memcpy(scur,cur->data,cur->data_sz);
+        scur += cur->data_sz;
+    }
+    *scur = '\0';
 
-    return result;
+    /* this effectively hides all of the merged-in chunks */
+    data->next = cur;
+    if(cur == NULL)
+        data->parent->lastchild = data;
+    else
+        cur->prev = data;
+
+    /* reset data */
+    data->data = merge;
+    data->data_sz = imerge;
 }
 
 static void _xmlnode_hide_sibling(xmlnode child)
@@ -155,7 +183,7 @@
     xmlnode tmp;
 
     if(!node || xmlnode_get_type(node)!=NTYPE_TAG)
-	return NULL;
+        return NULL;
 
     s = spool_new(xmlnode_pool(node));
     if(!s) return(NULL);
@@ -164,40 +192,34 @@
     {
         if(dir==0)
         {
-    	    if(xmlnode_get_type(node) == NTYPE_TAG)
-            {
-		        if(xmlnode_has_children(node))
-                {
-		            _xmlnode_tag2str(s,node,1);
-        		    node = xmlnode_get_firstchild(node);
-		            level++;
-		            continue;
-        		}
-                else
-                {
-		            _xmlnode_tag2str(s,node,0);
-		        }
-	        }
-            else
+            if(xmlnode_get_type(node) == NTYPE_TAG)
             {
-		        spool_add(s,strescape(xmlnode_pool(node),xmlnode_get_data(node)));
-	        }
-	    }
+                if(xmlnode_has_children(node))
+                {
+                    _xmlnode_tag2str(s,node,1);
+                    node = xmlnode_get_firstchild(node);
+                    level++;
+                    continue;
+                }else{
+                    _xmlnode_tag2str(s,node,0);
+                }
+            }else{
+                spool_add(s,strescape(xmlnode_pool(node),xmlnode_get_data(node)));
+            }
+        }
 
-    	tmp = xmlnode_get_nextsibling(node);
-	    if(!tmp)
+        tmp = xmlnode_get_nextsibling(node);
+        if(!tmp)
         {
-	        node = xmlnode_get_parent(node);
-	        level--;
-	        if(level>=0) _xmlnode_tag2str(s,node,2);
-	        if(level<1) break;
-	        dir = 1;
-	    }
-        else
-        {
-	        node = tmp;
-	        dir = 0;
-	    }
+            node = xmlnode_get_parent(node);
+            level--;
+            if(level>=0) _xmlnode_tag2str(s,node,2);
+            if(level<1) break;
+            dir = 1;
+        }else{
+            node = tmp;
+            dir = 0;
+        }
     }
 
     return s;
@@ -260,8 +282,6 @@
 
 /*
  *  xmlnode_insert_cdata -- append character data to a tag
- *  If last child of the parent is CDATA, merges CDATA nodes. Otherwise
- *  creates a CDATA node, and appends it to the parent's child list.
  *
  *  parameters
  *      parent -- parent tag
@@ -283,22 +303,13 @@
     if(size == -1)
         size = strlen(CDATA);
 
-    if ((parent->lastchild != NULL) && (parent->lastchild->type == NTYPE_CDATA))
-    {
-        result = parent->lastchild;
-        result->data = _xmlnode_merge(result->p, result->data, result->data_sz, CDATA, size);
-        result->data_sz = result->data_sz + size;
-    }
-    else
+    result = _xmlnode_insert(parent, NULL, NTYPE_CDATA);
+    if (result != NULL)
     {
-        result = _xmlnode_insert(parent, "", NTYPE_CDATA);
-        if (result != NULL)
-        {
-            result->data = (char*)pmalloc(result->p, size + 1);
-            memcpy(result->data, CDATA, size);
-            result->data[size] = '\0';
-            result->data_sz = size;
-        }
+        result->data = (char*)pmalloc(result->p, size + 1);
+        memcpy(result->data, CDATA, size);
+        result->data[size] = '\0';
+        result->data_sz = size;
     }
 
     return result;
@@ -314,7 +325,8 @@
  *              "name/name" for a sub child (recurses)
  *              "?attrib" to match the first tag with that attrib defined
  *              "?attrib=value" to match the first tag with that attrib and value
- *              or any combination: "name/name/?attrib", etc
+ *              "=cdata" to match the cdata contents of the child
+ *              or any combination: "name/name/?attrib", "name=cdata", etc
  *
  *  results
  *      a pointer to the tag matching search criteria
@@ -325,17 +337,43 @@
     char *str, *slash, *qmark, *equals;
     xmlnode step, ret;
 
+
     if(parent == NULL || parent->firstchild == NULL || name == NULL || name == '\0') return NULL;
 
-    if(strstr(name, "/") == NULL && strstr(name,"?") == NULL)
+    if(strstr(name, "/") == NULL && strstr(name,"?") == NULL && strstr(name, "=") == NULL)
         return _xmlnode_search(parent->firstchild, name, NTYPE_TAG);
 
-    /* jer's note: why can't I modify the name directly, why do I have to strdup it?  damn c grrr! */
     str = strdup(name);
     slash = strstr(str, "/");
     qmark = strstr(str, "?");
     equals = strstr(str, "=");
 
+    if(equals != NULL && (slash == NULL || equals < slash) && (qmark == NULL || equals < qmark))
+    { /* of type =cdata */
+
+        *equals = '\0';
+        equals++;
+
+        for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step))
+        {
+            if(xmlnode_get_type(step) != NTYPE_TAG)
+                continue;
+
+            if(*str != '\0')
+                if(j_strcmp(xmlnode_get_name(step),str) != 0)
+                    continue;
+
+            if(j_strcmp(xmlnode_get_data(step),equals) != 0)
+                continue;
+
+            break;
+        }
+
+        free(str);
+        return step;
+    }
+
+
     if(qmark != NULL && (slash == NULL || qmark < slash))
     { /* of type ?attrib */
 
@@ -528,33 +566,34 @@
 
 char* xmlnode_get_data(xmlnode node)
 {
-    xmlnode cur;
+    if(xmlnode_get_type(node) == NTYPE_TAG) /* loop till we find a CDATA in the children */
+        for(node = xmlnode_get_firstchild(node); node != NULL; node = xmlnode_get_nextsibling(node))
+            if(xmlnode_get_type(node) == NTYPE_CDATA) break;
 
     if(node == NULL) return NULL;
 
-    if(xmlnode_get_type(node) == NTYPE_TAG) /* loop till we find a CDATA */
-    {
-        for(cur = xmlnode_get_firstchild(node); cur != NULL; cur = xmlnode_get_nextsibling(cur))
-            if(xmlnode_get_type(cur) == NTYPE_CDATA)
-                return cur->data;
-    }else{
-        return node->data;
-    }
-    return NULL;
+    /* check for a dirty node w/ unassembled cdata chunks */
+    if(xmlnode_get_type(node->next) == NTYPE_CDATA)
+        _xmlnode_merge(node);
+
+    return node->data;
 }
 
 int xmlnode_get_datasz(xmlnode node)
 {
-    if (node != NULL)
-        return node->data_sz;
-    return (int)NULL;
+    if(xmlnode_get_type(node) != NTYPE_CDATA) return 0;
+
+    /* check for a dirty node w/ unassembled cdata chunks */
+    if(xmlnode_get_type(node->next) == NTYPE_CDATA)
+        _xmlnode_merge(node);
+    return node->data_sz;
 }
 
 int xmlnode_get_type(xmlnode node)
 {
     if (node != NULL)
         return node->type;
-    return (int)NULL;
+    return NTYPE_UNDEF;
 }
 
 int xmlnode_has_children(xmlnode node)