comparison 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
comparison
equal deleted inserted replaced
416:48e7808c4191 417:c3ae9251c197
11 * 11 *
12 * You should have received a copy of the GNU General Public License 12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software 13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 * 15 *
16 * Jabber 16 * Copyrights
17 * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/ 17 *
18 * Portions created by or assigned to Jabber.com, Inc. are
19 * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact
20 * information for Jabber.com, Inc. is available at http://www.jabber.com/.
21 *
22 * Portions Copyright (c) 1998-1999 Jeremie Miller.
23 *
24 * Acknowledgements
25 *
26 * Special thanks to the Jabber Open Source Contributors for their
27 * suggestions and support of Jabber.
28 *
18 */ 29 */
19 30
20 #include "libxode.h" 31 #include "libxode.h"
21 32
22 /* Internal routines */ 33 /* Internal routines */
33 { 44 {
34 p = pool_heap(1*1024); 45 p = pool_heap(1*1024);
35 } 46 }
36 47
37 /* Allocate & zero memory */ 48 /* Allocate & zero memory */
38 result = (xmlnode)pmalloc(p, sizeof(_xmlnode)); 49 result = (xmlnode)pmalloco(p, sizeof(_xmlnode));
39 memset(result, '\0', sizeof(_xmlnode));
40 50
41 /* Initialize fields */ 51 /* Initialize fields */
42 if (type != NTYPE_CDATA) 52 if (type != NTYPE_CDATA)
43 result->name = pstrdup(p,name); 53 result->name = pstrdup(p,name);
44 result->type = type; 54 result->type = type;
62 72
63 static xmlnode _xmlnode_insert(xmlnode parent, const char* name, unsigned int type) 73 static xmlnode _xmlnode_insert(xmlnode parent, const char* name, unsigned int type)
64 { 74 {
65 xmlnode result; 75 xmlnode result;
66 76
67 if(parent == NULL || name == NULL) return NULL; 77 if(parent == NULL || (type != NTYPE_CDATA && name == NULL)) return NULL;
68 78
69 /* If parent->firstchild is NULL, simply create a new node for the first child */ 79 /* If parent->firstchild is NULL, simply create a new node for the first child */
70 if (parent->firstchild == NULL) 80 if (parent->firstchild == NULL)
71 { 81 {
72 result = _xmlnode_new(parent->p, name, type); 82 result = _xmlnode_new(parent->p, name, type);
98 current = current->next; 108 current = current->next;
99 } 109 }
100 return NULL; 110 return NULL;
101 } 111 }
102 112
103 static char* _xmlnode_merge(pool p, char* dest, unsigned int destsize, const char* src, unsigned int srcsize) 113 void _xmlnode_merge(xmlnode data)
104 { 114 {
105 char* result; 115 xmlnode cur;
106 result = (char*)pmalloc(p, destsize + srcsize + 1); 116 char *merge, *scur;
107 memcpy(result, dest, destsize); 117 int imerge;
108 memcpy(result+destsize, src, srcsize); 118
109 result[destsize + srcsize] = '\0'; 119 /* get total size of all merged cdata */
110 120 imerge = 0;
111 /* 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 */ 121 for(cur = data; cur != NULL && cur->type == NTYPE_CDATA; cur = cur->next)
112 p->size -= destsize; 122 imerge += cur->data_sz;
113 123
114 return result; 124 /* copy in current data and then spin through all of them and merge */
125 scur = merge = pmalloc(data->p,imerge + 1);
126 for(cur = data; cur != NULL && cur->type == NTYPE_CDATA; cur = cur->next)
127 {
128 memcpy(scur,cur->data,cur->data_sz);
129 scur += cur->data_sz;
130 }
131 *scur = '\0';
132
133 /* this effectively hides all of the merged-in chunks */
134 data->next = cur;
135 if(cur == NULL)
136 data->parent->lastchild = data;
137 else
138 cur->prev = data;
139
140 /* reset data */
141 data->data = merge;
142 data->data_sz = imerge;
115 } 143 }
116 144
117 static void _xmlnode_hide_sibling(xmlnode child) 145 static void _xmlnode_hide_sibling(xmlnode child)
118 { 146 {
119 if(child == NULL) 147 if(child == NULL)
153 spool s; 181 spool s;
154 int level=0,dir=0; 182 int level=0,dir=0;
155 xmlnode tmp; 183 xmlnode tmp;
156 184
157 if(!node || xmlnode_get_type(node)!=NTYPE_TAG) 185 if(!node || xmlnode_get_type(node)!=NTYPE_TAG)
158 return NULL; 186 return NULL;
159 187
160 s = spool_new(xmlnode_pool(node)); 188 s = spool_new(xmlnode_pool(node));
161 if(!s) return(NULL); 189 if(!s) return(NULL);
162 190
163 while(1) 191 while(1)
164 { 192 {
165 if(dir==0) 193 if(dir==0)
166 { 194 {
167 if(xmlnode_get_type(node) == NTYPE_TAG) 195 if(xmlnode_get_type(node) == NTYPE_TAG)
168 { 196 {
169 if(xmlnode_has_children(node)) 197 if(xmlnode_has_children(node))
170 { 198 {
171 _xmlnode_tag2str(s,node,1); 199 _xmlnode_tag2str(s,node,1);
172 node = xmlnode_get_firstchild(node); 200 node = xmlnode_get_firstchild(node);
173 level++; 201 level++;
174 continue; 202 continue;
175 } 203 }else{
176 else 204 _xmlnode_tag2str(s,node,0);
177 { 205 }
178 _xmlnode_tag2str(s,node,0); 206 }else{
179 } 207 spool_add(s,strescape(xmlnode_pool(node),xmlnode_get_data(node)));
180 } 208 }
181 else 209 }
182 { 210
183 spool_add(s,strescape(xmlnode_pool(node),xmlnode_get_data(node))); 211 tmp = xmlnode_get_nextsibling(node);
184 } 212 if(!tmp)
185 } 213 {
186 214 node = xmlnode_get_parent(node);
187 tmp = xmlnode_get_nextsibling(node); 215 level--;
188 if(!tmp) 216 if(level>=0) _xmlnode_tag2str(s,node,2);
189 { 217 if(level<1) break;
190 node = xmlnode_get_parent(node); 218 dir = 1;
191 level--; 219 }else{
192 if(level>=0) _xmlnode_tag2str(s,node,2); 220 node = tmp;
193 if(level<1) break; 221 dir = 0;
194 dir = 1; 222 }
195 }
196 else
197 {
198 node = tmp;
199 dir = 0;
200 }
201 } 223 }
202 224
203 return s; 225 return s;
204 } 226 }
205 227
258 } 280 }
259 281
260 282
261 /* 283 /*
262 * xmlnode_insert_cdata -- append character data to a tag 284 * xmlnode_insert_cdata -- append character data to a tag
263 * If last child of the parent is CDATA, merges CDATA nodes. Otherwise
264 * creates a CDATA node, and appends it to the parent's child list.
265 * 285 *
266 * parameters 286 * parameters
267 * parent -- parent tag 287 * parent -- parent tag
268 * CDATA -- character data 288 * CDATA -- character data
269 * size -- size of CDATA 289 * size -- size of CDATA
281 return NULL; 301 return NULL;
282 302
283 if(size == -1) 303 if(size == -1)
284 size = strlen(CDATA); 304 size = strlen(CDATA);
285 305
286 if ((parent->lastchild != NULL) && (parent->lastchild->type == NTYPE_CDATA)) 306 result = _xmlnode_insert(parent, NULL, NTYPE_CDATA);
287 { 307 if (result != NULL)
288 result = parent->lastchild; 308 {
289 result->data = _xmlnode_merge(result->p, result->data, result->data_sz, CDATA, size); 309 result->data = (char*)pmalloc(result->p, size + 1);
290 result->data_sz = result->data_sz + size; 310 memcpy(result->data, CDATA, size);
291 } 311 result->data[size] = '\0';
292 else 312 result->data_sz = size;
293 {
294 result = _xmlnode_insert(parent, "", NTYPE_CDATA);
295 if (result != NULL)
296 {
297 result->data = (char*)pmalloc(result->p, size + 1);
298 memcpy(result->data, CDATA, size);
299 result->data[size] = '\0';
300 result->data_sz = size;
301 }
302 } 313 }
303 314
304 return result; 315 return result;
305 } 316 }
306 317
312 * parent -- pointer to the parent tag 323 * parent -- pointer to the parent tag
313 * name -- "name" for the child tag of that name 324 * name -- "name" for the child tag of that name
314 * "name/name" for a sub child (recurses) 325 * "name/name" for a sub child (recurses)
315 * "?attrib" to match the first tag with that attrib defined 326 * "?attrib" to match the first tag with that attrib defined
316 * "?attrib=value" to match the first tag with that attrib and value 327 * "?attrib=value" to match the first tag with that attrib and value
317 * or any combination: "name/name/?attrib", etc 328 * "=cdata" to match the cdata contents of the child
329 * or any combination: "name/name/?attrib", "name=cdata", etc
318 * 330 *
319 * results 331 * results
320 * a pointer to the tag matching search criteria 332 * a pointer to the tag matching search criteria
321 * or NULL if search was unsuccessfull 333 * or NULL if search was unsuccessfull
322 */ 334 */
323 xmlnode xmlnode_get_tag(xmlnode parent, const char* name) 335 xmlnode xmlnode_get_tag(xmlnode parent, const char* name)
324 { 336 {
325 char *str, *slash, *qmark, *equals; 337 char *str, *slash, *qmark, *equals;
326 xmlnode step, ret; 338 xmlnode step, ret;
327 339
340
328 if(parent == NULL || parent->firstchild == NULL || name == NULL || name == '\0') return NULL; 341 if(parent == NULL || parent->firstchild == NULL || name == NULL || name == '\0') return NULL;
329 342
330 if(strstr(name, "/") == NULL && strstr(name,"?") == NULL) 343 if(strstr(name, "/") == NULL && strstr(name,"?") == NULL && strstr(name, "=") == NULL)
331 return _xmlnode_search(parent->firstchild, name, NTYPE_TAG); 344 return _xmlnode_search(parent->firstchild, name, NTYPE_TAG);
332 345
333 /* jer's note: why can't I modify the name directly, why do I have to strdup it? damn c grrr! */
334 str = strdup(name); 346 str = strdup(name);
335 slash = strstr(str, "/"); 347 slash = strstr(str, "/");
336 qmark = strstr(str, "?"); 348 qmark = strstr(str, "?");
337 equals = strstr(str, "="); 349 equals = strstr(str, "=");
338 350
351 if(equals != NULL && (slash == NULL || equals < slash) && (qmark == NULL || equals < qmark))
352 { /* of type =cdata */
353
354 *equals = '\0';
355 equals++;
356
357 for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step))
358 {
359 if(xmlnode_get_type(step) != NTYPE_TAG)
360 continue;
361
362 if(*str != '\0')
363 if(j_strcmp(xmlnode_get_name(step),str) != 0)
364 continue;
365
366 if(j_strcmp(xmlnode_get_data(step),equals) != 0)
367 continue;
368
369 break;
370 }
371
372 free(str);
373 return step;
374 }
375
376
339 if(qmark != NULL && (slash == NULL || qmark < slash)) 377 if(qmark != NULL && (slash == NULL || qmark < slash))
340 { /* of type ?attrib */ 378 { /* of type ?attrib */
341 379
342 *qmark = '\0'; 380 *qmark = '\0';
343 qmark++; 381 qmark++;
526 return NULL; 564 return NULL;
527 } 565 }
528 566
529 char* xmlnode_get_data(xmlnode node) 567 char* xmlnode_get_data(xmlnode node)
530 { 568 {
531 xmlnode cur; 569 if(xmlnode_get_type(node) == NTYPE_TAG) /* loop till we find a CDATA in the children */
570 for(node = xmlnode_get_firstchild(node); node != NULL; node = xmlnode_get_nextsibling(node))
571 if(xmlnode_get_type(node) == NTYPE_CDATA) break;
532 572
533 if(node == NULL) return NULL; 573 if(node == NULL) return NULL;
534 574
535 if(xmlnode_get_type(node) == NTYPE_TAG) /* loop till we find a CDATA */ 575 /* check for a dirty node w/ unassembled cdata chunks */
536 { 576 if(xmlnode_get_type(node->next) == NTYPE_CDATA)
537 for(cur = xmlnode_get_firstchild(node); cur != NULL; cur = xmlnode_get_nextsibling(cur)) 577 _xmlnode_merge(node);
538 if(xmlnode_get_type(cur) == NTYPE_CDATA) 578
539 return cur->data; 579 return node->data;
540 }else{
541 return node->data;
542 }
543 return NULL;
544 } 580 }
545 581
546 int xmlnode_get_datasz(xmlnode node) 582 int xmlnode_get_datasz(xmlnode node)
547 { 583 {
548 if (node != NULL) 584 if(xmlnode_get_type(node) != NTYPE_CDATA) return 0;
549 return node->data_sz; 585
550 return (int)NULL; 586 /* check for a dirty node w/ unassembled cdata chunks */
587 if(xmlnode_get_type(node->next) == NTYPE_CDATA)
588 _xmlnode_merge(node);
589 return node->data_sz;
551 } 590 }
552 591
553 int xmlnode_get_type(xmlnode node) 592 int xmlnode_get_type(xmlnode node)
554 { 593 {
555 if (node != NULL) 594 if (node != NULL)
556 return node->type; 595 return node->type;
557 return (int)NULL; 596 return NTYPE_UNDEF;
558 } 597 }
559 598
560 int xmlnode_has_children(xmlnode node) 599 int xmlnode_has_children(xmlnode node)
561 { 600 {
562 if ((node != NULL) && (node->firstchild != NULL)) 601 if ((node != NULL) && (node->firstchild != NULL))