Mercurial > pidgin
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)) |