Mercurial > ~mikael > mcabber > hg
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)) |