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