comparison src/protocols/jabber/xmlnode.c @ 3127:4e7cefc55971

[gaim-migrate @ 3142] Upgraded jabber to most recent stable version committer: Tailor Script <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Thu, 04 Apr 2002 03:04:57 +0000
parents 424a40f12a6c
children 67c4e9d39242
comparison
equal deleted inserted replaced
3126:e883f604174e 3127:4e7cefc55971
1 /* 1 /* --------------------------------------------------------------------------
2 * This program is free software; you can redistribute it and/or modify 2 *
3 * it under the terms of the GNU General Public License as published by 3 * License
4 * the Free Software Foundation; either version 2 of the License, or 4 *
5 * (at your option) any later version. 5 * The contents of this file are subject to the Jabber Open Source License
6 * 6 * Version 1.0 (the "JOSL"). You may not copy or use this file, in either
7 * This program is distributed in the hope that it will be useful, 7 * source code or executable form, except in compliance with the JOSL. You
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 8 * may obtain a copy of the JOSL at http://www.jabber.org/ or at
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 * http://www.opensource.org/.
10 * GNU General Public License for more details. 10 *
11 * 11 * Software distributed under the JOSL is distributed on an "AS IS" basis,
12 * You should have received a copy of the GNU General Public License 12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL
13 * along with this program; if not, write to the Free Software 13 * for the specific language governing rights and limitations under the
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 14 * JOSL.
15 * 15 *
16 * Jabber 16 * Copyrights
17 * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/ 17 *
18 */ 18 * Portions created by or assigned to Jabber.com, Inc. are
19 19 * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact
20 #include "libxode.h" 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 *
29 * Alternatively, the contents of this file may be used under the terms of the
30 * GNU General Public License Version 2 or later (the "GPL"), in which case
31 * the provisions of the GPL are applicable instead of those above. If you
32 * wish to allow use of your version of this file only under the terms of the
33 * GPL and not to allow others to use your version of this file under the JOSL,
34 * indicate your decision by deleting the provisions above and replace them
35 * with the notice and other provisions required by the GPL. If you do not
36 * delete the provisions above, a recipient may use your version of this file
37 * under either the JOSL or the GPL.
38 *
39 *
40 * --------------------------------------------------------------------------*/
41
42 #include "lib.h"
21 43
22 /* Internal routines */ 44 /* Internal routines */
23 xmlnode _xmlnode_new(pool p, const char* name, unsigned int type) 45 xmlnode _xmlnode_new(pool p, const char* name, unsigned int type)
24 { 46 {
25 xmlnode result = NULL; 47 xmlnode result = NULL;
33 { 55 {
34 p = pool_heap(1*1024); 56 p = pool_heap(1*1024);
35 } 57 }
36 58
37 /* Allocate & zero memory */ 59 /* Allocate & zero memory */
38 result = (xmlnode)pmalloc(p, sizeof(_xmlnode)); 60 result = (xmlnode)pmalloco(p, sizeof(_xmlnode));
39 memset(result, '\0', sizeof(_xmlnode));
40 61
41 /* Initialize fields */ 62 /* Initialize fields */
42 if (type != NTYPE_CDATA) 63 if (type != NTYPE_CDATA)
43 result->name = pstrdup(p,name); 64 result->name = pstrdup(p,name);
44 result->type = type; 65 result->type = type;
62 83
63 static xmlnode _xmlnode_insert(xmlnode parent, const char* name, unsigned int type) 84 static xmlnode _xmlnode_insert(xmlnode parent, const char* name, unsigned int type)
64 { 85 {
65 xmlnode result; 86 xmlnode result;
66 87
67 if(parent == NULL || name == NULL) return NULL; 88 if(parent == NULL || (type != NTYPE_CDATA && name == NULL)) return NULL;
68 89
69 /* If parent->firstchild is NULL, simply create a new node for the first child */ 90 /* If parent->firstchild is NULL, simply create a new node for the first child */
70 if (parent->firstchild == NULL) 91 if (parent->firstchild == NULL)
71 { 92 {
72 result = _xmlnode_new(parent->p, name, type); 93 result = _xmlnode_new(parent->p, name, type);
98 current = current->next; 119 current = current->next;
99 } 120 }
100 return NULL; 121 return NULL;
101 } 122 }
102 123
103 static char* _xmlnode_merge(pool p, char* dest, unsigned int destsize, const char* src, unsigned int srcsize) 124 void _xmlnode_merge(xmlnode data)
104 { 125 {
105 char* result; 126 xmlnode cur;
106 result = (char*)pmalloc(p, destsize + srcsize + 1); 127 char *merge, *scur;
107 memcpy(result, dest, destsize); 128 int imerge;
108 memcpy(result+destsize, src, srcsize); 129
109 result[destsize + srcsize] = '\0'; 130 /* get total size of all merged cdata */
110 131 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 */ 132 for(cur = data; cur != NULL && cur->type == NTYPE_CDATA; cur = cur->next)
112 p->size -= destsize; 133 imerge += cur->data_sz;
113 134
114 return result; 135 /* copy in current data and then spin through all of them and merge */
136 scur = merge = pmalloc(data->p,imerge + 1);
137 for(cur = data; cur != NULL && cur->type == NTYPE_CDATA; cur = cur->next)
138 {
139 memcpy(scur,cur->data,cur->data_sz);
140 scur += cur->data_sz;
141 }
142 *scur = '\0';
143
144 /* this effectively hides all of the merged-in chunks */
145 data->next = cur;
146 if(cur == NULL)
147 data->parent->lastchild = data;
148 else
149 cur->prev = data;
150
151 /* reset data */
152 data->data = merge;
153 data->data_sz = imerge;
154
115 } 155 }
116 156
117 static void _xmlnode_hide_sibling(xmlnode child) 157 static void _xmlnode_hide_sibling(xmlnode child)
118 { 158 {
119 if(child == NULL) 159 if(child == NULL)
153 spool s; 193 spool s;
154 int level=0,dir=0; 194 int level=0,dir=0;
155 xmlnode tmp; 195 xmlnode tmp;
156 196
157 if(!node || xmlnode_get_type(node)!=NTYPE_TAG) 197 if(!node || xmlnode_get_type(node)!=NTYPE_TAG)
158 return NULL; 198 return NULL;
159 199
160 s = spool_new(xmlnode_pool(node)); 200 s = spool_new(xmlnode_pool(node));
161 if(!s) return(NULL); 201 if(!s) return(NULL);
162 202
163 while(1) 203 while(1)
164 { 204 {
165 if(dir==0) 205 if(dir==0)
166 { 206 {
167 if(xmlnode_get_type(node) == NTYPE_TAG) 207 if(xmlnode_get_type(node) == NTYPE_TAG)
168 { 208 {
169 if(xmlnode_has_children(node)) 209 if(xmlnode_has_children(node))
170 { 210 {
171 _xmlnode_tag2str(s,node,1); 211 _xmlnode_tag2str(s,node,1);
172 node = xmlnode_get_firstchild(node); 212 node = xmlnode_get_firstchild(node);
173 level++; 213 level++;
174 continue; 214 continue;
175 } 215 }else{
176 else 216 _xmlnode_tag2str(s,node,0);
177 { 217 }
178 _xmlnode_tag2str(s,node,0); 218 }else{
179 } 219 spool_add(s,strescape(xmlnode_pool(node),xmlnode_get_data(node)));
180 } 220 }
181 else 221 }
182 {
183 spool_add(s,strescape(xmlnode_pool(node),xmlnode_get_data(node)));
184 }
185 }
186 222
187 tmp = xmlnode_get_nextsibling(node); 223 tmp = xmlnode_get_nextsibling(node);
188 if(!tmp) 224 if(!tmp)
189 { 225 {
190 node = xmlnode_get_parent(node); 226 node = xmlnode_get_parent(node);
191 level--; 227 level--;
192 if(level>=0) _xmlnode_tag2str(s,node,2); 228 if(level>=0) _xmlnode_tag2str(s,node,2);
193 if(level<1) break; 229 if(level<1) break;
194 dir = 1; 230 dir = 1;
195 } 231 }else{
196 else 232 node = tmp;
197 { 233 dir = 0;
198 node = tmp; 234 }
199 dir = 0;
200 }
201 } 235 }
202 236
203 return s; 237 return s;
204 } 238 }
205 239
258 } 292 }
259 293
260 294
261 /* 295 /*
262 * xmlnode_insert_cdata -- append character data to a tag 296 * 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 * 297 *
266 * parameters 298 * parameters
267 * parent -- parent tag 299 * parent -- parent tag
268 * CDATA -- character data 300 * CDATA -- character data
269 * size -- size of CDATA 301 * size -- size of CDATA
281 return NULL; 313 return NULL;
282 314
283 if(size == -1) 315 if(size == -1)
284 size = strlen(CDATA); 316 size = strlen(CDATA);
285 317
286 if ((parent->lastchild != NULL) && (parent->lastchild->type == NTYPE_CDATA)) 318 result = _xmlnode_insert(parent, NULL, NTYPE_CDATA);
287 { 319 if (result != NULL)
288 result = parent->lastchild; 320 {
289 result->data = _xmlnode_merge(result->p, result->data, result->data_sz, CDATA, size); 321 result->data = (char*)pmalloc(result->p, size + 1);
290 result->data_sz = result->data_sz + size; 322 memcpy(result->data, CDATA, size);
291 } 323 result->data[size] = '\0';
292 else 324 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 } 325 }
303 326
304 return result; 327 return result;
305 } 328 }
306 329
312 * parent -- pointer to the parent tag 335 * parent -- pointer to the parent tag
313 * name -- "name" for the child tag of that name 336 * name -- "name" for the child tag of that name
314 * "name/name" for a sub child (recurses) 337 * "name/name" for a sub child (recurses)
315 * "?attrib" to match the first tag with that attrib defined 338 * "?attrib" to match the first tag with that attrib defined
316 * "?attrib=value" to match the first tag with that attrib and value 339 * "?attrib=value" to match the first tag with that attrib and value
317 * or any combination: "name/name/?attrib", etc 340 * "=cdata" to match the cdata contents of the child
341 * or any combination: "name/name/?attrib", "name=cdata", etc
318 * 342 *
319 * results 343 * results
320 * a pointer to the tag matching search criteria 344 * a pointer to the tag matching search criteria
321 * or NULL if search was unsuccessfull 345 * or NULL if search was unsuccessfull
322 */ 346 */
323 xmlnode xmlnode_get_tag(xmlnode parent, const char* name) 347 xmlnode xmlnode_get_tag(xmlnode parent, const char* name)
324 { 348 {
325 char *str, *slash, *qmark, *equals; 349 char *str, *slash, *qmark, *equals;
326 xmlnode step, ret; 350 xmlnode step, ret;
327 351
352
328 if(parent == NULL || parent->firstchild == NULL || name == NULL || name == '\0') return NULL; 353 if(parent == NULL || parent->firstchild == NULL || name == NULL || name == '\0') return NULL;
329 354
330 if(strstr(name, "/") == NULL && strstr(name,"?") == NULL) 355 if(strstr(name, "/") == NULL && strstr(name,"?") == NULL && strstr(name, "=") == NULL)
331 return _xmlnode_search(parent->firstchild, name, NTYPE_TAG); 356 return _xmlnode_search(parent->firstchild, name, NTYPE_TAG);
332 357
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); 358 str = strdup(name);
335 slash = strstr(str, "/"); 359 slash = strstr(str, "/");
336 qmark = strstr(str, "?"); 360 qmark = strstr(str, "?");
337 equals = strstr(str, "="); 361 equals = strstr(str, "=");
338 362
363 if(equals != NULL && (slash == NULL || equals < slash) && (qmark == NULL || equals < qmark))
364 { /* of type =cdata */
365
366 *equals = '\0';
367 equals++;
368
369 for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step))
370 {
371 if(xmlnode_get_type(step) != NTYPE_TAG)
372 continue;
373
374 if(*str != '\0')
375 if(j_strcmp(xmlnode_get_name(step),str) != 0)
376 continue;
377
378 if(j_strcmp(xmlnode_get_data(step),equals) != 0)
379 continue;
380
381 break;
382 }
383
384 free(str);
385 return step;
386 }
387
388
339 if(qmark != NULL && (slash == NULL || qmark < slash)) 389 if(qmark != NULL && (slash == NULL || qmark < slash))
340 { /* of type ?attrib */ 390 { /* of type ?attrib */
341 391
342 *qmark = '\0'; 392 *qmark = '\0';
343 qmark++; 393 qmark++;
526 return NULL; 576 return NULL;
527 } 577 }
528 578
529 char* xmlnode_get_data(xmlnode node) 579 char* xmlnode_get_data(xmlnode node)
530 { 580 {
531 xmlnode cur; 581 if(xmlnode_get_type(node) == NTYPE_TAG) /* loop till we find a CDATA in the children */
582 for(node = xmlnode_get_firstchild(node); node != NULL; node = xmlnode_get_nextsibling(node))
583 if(xmlnode_get_type(node) == NTYPE_CDATA) break;
532 584
533 if(node == NULL) return NULL; 585 if(node == NULL) return NULL;
534 586
535 if(xmlnode_get_type(node) == NTYPE_TAG) /* loop till we find a CDATA */ 587 /* check for a dirty node w/ unassembled cdata chunks */
536 { 588 if(xmlnode_get_type(node->next) == NTYPE_CDATA)
537 for(cur = xmlnode_get_firstchild(node); cur != NULL; cur = xmlnode_get_nextsibling(cur)) 589 _xmlnode_merge(node);
538 if(xmlnode_get_type(cur) == NTYPE_CDATA) 590
539 return cur->data; 591 return node->data;
540 }else{
541 return node->data;
542 }
543 return NULL;
544 } 592 }
545 593
546 int xmlnode_get_datasz(xmlnode node) 594 int xmlnode_get_datasz(xmlnode node)
547 { 595 {
548 if (node != NULL) 596 if(xmlnode_get_type(node) != NTYPE_CDATA) return 0;
549 return node->data_sz; 597
550 return (int)NULL; 598 /* check for a dirty node w/ unassembled cdata chunks */
599 if(xmlnode_get_type(node->next) == NTYPE_CDATA)
600 _xmlnode_merge(node);
601 return node->data_sz;
551 } 602 }
552 603
553 int xmlnode_get_type(xmlnode node) 604 int xmlnode_get_type(xmlnode node)
554 { 605 {
555 if (node != NULL) 606 if (node != NULL)
556 return node->type; 607 return node->type;
557 return (int)NULL; 608 return NTYPE_UNDEF;
558 } 609 }
559 610
560 int xmlnode_has_children(xmlnode node) 611 int xmlnode_has_children(xmlnode node)
561 { 612 {
562 if ((node != NULL) && (node->firstchild != NULL)) 613 if ((node != NULL) && (node->firstchild != NULL))