1 /* iksemel (XML parser for Jabber)
2 ** Copyright (C) 2000-2007 Gurer Ozen <madcat@e-kolay.net>
3 ** This code is free software; you can redistribute it and/or
4 ** modify it under the terms of GNU Lesser General Public License.
5 */
6
7 #include "common.h"
8 #include "iksemel.h"
9
10 #define IKS_COMMON \
11 struct iks_struct *next, *prev; \
12 struct iks_struct *parent; \
13 enum ikstype type; \
14 ikstack *s
15
16 struct iks_struct {
17 IKS_COMMON;
18 };
19
20 struct iks_tag {
21 IKS_COMMON;
22 struct iks_struct *children, *last_child;
23 struct iks_struct *attribs, *last_attrib;
24 char *name;
25 };
26
27 #define IKS_TAG_NAME(x) ((struct iks_tag *) (x) )->name
28 #define IKS_TAG_CHILDREN(x) ((struct iks_tag *) (x) )->children
29 #define IKS_TAG_LAST_CHILD(x) ((struct iks_tag *) (x) )->last_child
30 #define IKS_TAG_ATTRIBS(x) ((struct iks_tag *) (x) )->attribs
31 #define IKS_TAG_LAST_ATTRIB(x) ((struct iks_tag *) (x) )->last_attrib
32
33 struct iks_cdata {
34 IKS_COMMON;
35 char *cdata;
36 size_t len;
37 };
38
39 #define IKS_CDATA_CDATA(x) ((struct iks_cdata *) (x) )->cdata
40 #define IKS_CDATA_LEN(x) ((struct iks_cdata *) (x) )->len
41
42 struct iks_attrib {
43 IKS_COMMON;
44 char *name;
45 char *value;
46 };
47
48 #define IKS_ATTRIB_NAME(x) ((struct iks_attrib *) (x) )->name
49 #define IKS_ATTRIB_VALUE(x) ((struct iks_attrib *) (x) )->value
50
51 /***** Node Creating & Deleting *****/
52
53 iks *
iks_new(const char * name)54 iks_new (const char *name)
55 {
56 ikstack *s;
57 iks *x;
58
59 s = iks_stack_new (sizeof (struct iks_tag) * 6, 256);
60 if (!s) return NULL;
61 x = iks_new_within (name, s);
62 if (!x) {
63 iks_stack_delete (&s);
64 return NULL;
65 }
66 return x;
67 }
68
69 iks *
iks_new_within(const char * name,ikstack * s)70 iks_new_within (const char *name, ikstack *s)
71 {
72 iks *x;
73 size_t len;
74
75 if (name) len = sizeof (struct iks_tag); else len = sizeof (struct iks_cdata);
76 x = iks_stack_alloc (s, len);
77 if (!x) return NULL;
78 memset (x, 0, len);
79 x->s = s;
80 x->type = IKS_TAG;
81 if (name) {
82 IKS_TAG_NAME (x) = iks_stack_strdup (s, name, 0);
83 if (!IKS_TAG_NAME (x)) return NULL;
84 }
85 return x;
86 }
87
88 iks *
iks_insert(iks * x,const char * name)89 iks_insert (iks *x, const char *name)
90 {
91 iks *y;
92
93 if (!x) return NULL;
94
95 y = iks_new_within (name, x->s);
96 if (!y) return NULL;
97 y->parent = x;
98 if (!IKS_TAG_CHILDREN (x)) IKS_TAG_CHILDREN (x) = y;
99 if (IKS_TAG_LAST_CHILD (x)) {
100 IKS_TAG_LAST_CHILD (x)->next = y;
101 y->prev = IKS_TAG_LAST_CHILD (x);
102 }
103 IKS_TAG_LAST_CHILD (x) = y;
104 return y;
105 }
106
107 iks *
iks_insert_cdata(iks * x,const char * data,size_t len)108 iks_insert_cdata (iks *x, const char *data, size_t len)
109 {
110 iks *y;
111
112 if(!x || !data) return NULL;
113 if(len == 0) len = strlen (data);
114
115 y = IKS_TAG_LAST_CHILD (x);
116 if (y && y->type == IKS_CDATA) {
117 IKS_CDATA_CDATA (y) = iks_stack_strcat (x->s, IKS_CDATA_CDATA (y), IKS_CDATA_LEN (y), data, len);
118 IKS_CDATA_LEN (y) += len;
119 } else {
120 y = iks_insert (x, NULL);
121 if (!y) return NULL;
122 y->type = IKS_CDATA;
123 IKS_CDATA_CDATA (y) = iks_stack_strdup (x->s, data, len);
124 if (!IKS_CDATA_CDATA (y)) return NULL;
125 IKS_CDATA_LEN (y) = len;
126 }
127 return y;
128 }
129
130 iks *
iks_insert_attrib(iks * x,const char * name,const char * value)131 iks_insert_attrib (iks *x, const char *name, const char *value)
132 {
133 iks *y;
134
135 if (!x) return NULL;
136
137 y = IKS_TAG_ATTRIBS (x);
138 while (y) {
139 if (strcmp (name, IKS_ATTRIB_NAME (y)) == 0) break;
140 y = y->next;
141 }
142 if (NULL == y) {
143 if (!value) return NULL;
144 y = iks_stack_alloc (x->s, sizeof (struct iks_attrib));
145 if (!y) return NULL;
146 memset (y, 0, sizeof (struct iks_attrib));
147 y->type = IKS_ATTRIBUTE;
148 y->s = x->s;
149 IKS_ATTRIB_NAME (y) = iks_stack_strdup (x->s, name, 0);
150 if (!IKS_ATTRIB_NAME (y)) return NULL;
151 y->parent = x;
152 if (!IKS_TAG_ATTRIBS (x)) IKS_TAG_ATTRIBS (x) = y;
153 if (IKS_TAG_LAST_ATTRIB (x)) {
154 IKS_TAG_LAST_ATTRIB (x)->next = y;
155 y->prev = IKS_TAG_LAST_ATTRIB (x);
156 }
157 IKS_TAG_LAST_ATTRIB (x) = y;
158 }
159
160 if (value) {
161 IKS_ATTRIB_VALUE (y) = iks_stack_strdup (x->s, value, 0);
162 if (!IKS_ATTRIB_VALUE (y)) return NULL;
163 } else {
164 if (y->next) y->next->prev = y->prev;
165 if (y->prev) y->prev->next = y->next;
166 if (IKS_TAG_ATTRIBS (x) == y) IKS_TAG_ATTRIBS (x) = y->next;
167 if (IKS_TAG_LAST_ATTRIB (x) == y) IKS_TAG_LAST_ATTRIB (x) = y->prev;
168 }
169
170 return y;
171 }
172
173 iks *
iks_insert_node(iks * x,iks * y)174 iks_insert_node (iks *x, iks *y)
175 {
176 y->parent = x;
177 if (!IKS_TAG_CHILDREN (x)) IKS_TAG_CHILDREN (x) = y;
178 if (IKS_TAG_LAST_CHILD (x)) {
179 IKS_TAG_LAST_CHILD (x)->next = y;
180 y->prev = IKS_TAG_LAST_CHILD (x);
181 }
182 IKS_TAG_LAST_CHILD (x) = y;
183 return y;
184 }
185
186 iks *
iks_append(iks * x,const char * name)187 iks_append (iks *x, const char *name)
188 {
189 iks *y;
190
191 if (!x) return NULL;
192 y = iks_new_within (name, x->s);
193 if (!y) return NULL;
194
195 if (x->next) {
196 x->next->prev = y;
197 } else {
198 IKS_TAG_LAST_CHILD (x->parent) = y;
199 }
200 y->next = x->next;
201 x->next = y;
202 y->parent = x->parent;
203 y->prev = x;
204
205 return y;
206 }
207
208 iks *
iks_prepend(iks * x,const char * name)209 iks_prepend (iks *x, const char *name)
210 {
211 iks *y;
212
213 if (!x) return NULL;
214 y = iks_new_within (name, x->s);
215 if (!y) return NULL;
216
217 if (x->prev) {
218 x->prev->next = y;
219 } else {
220 IKS_TAG_CHILDREN (x->parent) = y;
221 }
222 y->prev = x->prev;
223 x->prev = y;
224 y->parent = x->parent;
225 y->next = x;
226
227 return y;
228 }
229
230 iks *
iks_append_cdata(iks * x,const char * data,size_t len)231 iks_append_cdata (iks *x, const char *data, size_t len)
232 {
233 iks *y;
234
235 if (!x || !data) return NULL;
236 if (len == 0) len = strlen (data);
237
238 y = iks_new_within (NULL, x->s);
239 if (!y) return NULL;
240 y->type = IKS_CDATA;
241 IKS_CDATA_CDATA (y) = iks_stack_strdup (x->s, data, len);
242 if (!IKS_CDATA_CDATA (y)) return NULL;
243 IKS_CDATA_LEN (y) = len;
244
245 if (x->next) {
246 x->next->prev = y;
247 } else {
248 IKS_TAG_LAST_CHILD (x->parent) = y;
249 }
250 y->next = x->next;
251 x->next = y;
252 y->parent = x->parent;
253 y->prev = x;
254
255 return y;
256 }
257
258 iks *
iks_prepend_cdata(iks * x,const char * data,size_t len)259 iks_prepend_cdata (iks *x, const char *data, size_t len)
260 {
261 iks *y;
262
263 if (!x || !data) return NULL;
264 if (len == 0) len = strlen (data);
265
266 y = iks_new_within (NULL, x->s);
267 if (!y) return NULL;
268 y->type = IKS_CDATA;
269 IKS_CDATA_CDATA(y) = iks_stack_strdup (x->s, data, len);
270 if (!IKS_CDATA_CDATA (y)) return NULL;
271 IKS_CDATA_LEN (y) = len;
272
273 if (x->prev) {
274 x->prev->next = y;
275 } else {
276 IKS_TAG_CHILDREN (x->parent) = y;
277 }
278 y->prev = x->prev;
279 x->prev = y;
280 y->parent = x->parent;
281 y->next = x;
282
283 return y;
284 }
285
286 void
iks_hide(iks * x)287 iks_hide (iks *x)
288 {
289 iks *y;
290
291 if (!x) return;
292
293 if (x->prev) x->prev->next = x->next;
294 if (x->next) x->next->prev = x->prev;
295 y = x->parent;
296 if (y) {
297 if (IKS_TAG_CHILDREN (y) == x) IKS_TAG_CHILDREN (y) = x->next;
298 if (IKS_TAG_LAST_CHILD (y) == x) IKS_TAG_LAST_CHILD (y) = x->prev;
299 }
300 }
301
302 void
iks_delete(iks * x)303 iks_delete (iks *x)
304 {
305 if (x) iks_stack_delete (&x->s);
306 }
307
308 /***** Node Traversing *****/
309
310 iks *
iks_next(iks * x)311 iks_next (iks *x)
312 {
313 if (x) return x->next;
314 return NULL;
315 }
316
317 iks *
iks_next_tag(iks * x)318 iks_next_tag (iks *x)
319 {
320 if (x) {
321 while (1) {
322 x = x->next;
323 if (NULL == x) break;
324 if (IKS_TAG == x->type) return x;
325 }
326 }
327 return NULL;
328 }
329
330 iks *
iks_prev(iks * x)331 iks_prev (iks *x)
332 {
333 if (x) return x->prev;
334 return NULL;
335 }
336
337 iks *
iks_prev_tag(iks * x)338 iks_prev_tag (iks *x)
339 {
340 if (x) {
341 while (1) {
342 x = x->prev;
343 if (NULL == x) break;
344 if (IKS_TAG == x->type) return x;
345 }
346 }
347 return NULL;
348 }
349
350 iks *
iks_parent(iks * x)351 iks_parent (iks *x)
352 {
353 if (x) return x->parent;
354 return NULL;
355 }
356
357 iks *
iks_root(iks * x)358 iks_root (iks *x)
359 {
360 if (x) {
361 while (x->parent)
362 x = x->parent;
363 }
364 return x;
365 }
366
367 iks *
iks_child(iks * x)368 iks_child (iks *x)
369 {
370 if (x && IKS_TAG == x->type) return IKS_TAG_CHILDREN (x);
371 return NULL;
372 }
373
374 iks *
iks_first_tag(iks * x)375 iks_first_tag (iks *x)
376 {
377 if (x) {
378 x = IKS_TAG_CHILDREN (x);
379 while (x) {
380 if (IKS_TAG == x->type) return x;
381 x = x->next;
382 }
383 }
384 return NULL;
385 }
386
387 iks *
iks_attrib(iks * x)388 iks_attrib (iks *x)
389 {
390 if (x) return IKS_TAG_ATTRIBS (x);
391 return NULL;
392 }
393
394 iks *
iks_find(iks * x,const char * name)395 iks_find (iks *x, const char *name)
396 {
397 iks *y;
398
399 if (!x) return NULL;
400 y = IKS_TAG_CHILDREN (x);
401 while (y) {
402 if (IKS_TAG == y->type && IKS_TAG_NAME (y) && strcmp (IKS_TAG_NAME (y), name) == 0) return y;
403 y = y->next;
404 }
405 return NULL;
406 }
407
408 char *
iks_find_cdata(iks * x,const char * name)409 iks_find_cdata (iks *x, const char *name)
410 {
411 iks *y;
412
413 y = iks_find (x, name);
414 if (!y) return NULL;
415 y = IKS_TAG_CHILDREN (y);
416 if (!y || IKS_CDATA != y->type) return NULL;
417 return IKS_CDATA_CDATA (y);
418 }
419
420 char *
iks_find_attrib(iks * x,const char * name)421 iks_find_attrib (iks *x, const char *name)
422 {
423 iks *y;
424
425 if (!x) return NULL;
426
427 y = IKS_TAG_ATTRIBS (x);
428 while (y) {
429 if (IKS_ATTRIB_NAME (y) && strcmp (IKS_ATTRIB_NAME (y), name) == 0)
430 return IKS_ATTRIB_VALUE (y);
431 y = y->next;
432 }
433 return NULL;
434 }
435
436 iks *
iks_find_with_attrib(iks * x,const char * tagname,const char * attrname,const char * value)437 iks_find_with_attrib (iks *x, const char *tagname, const char *attrname, const char *value)
438 {
439 iks *y;
440
441 if (NULL == x) return NULL;
442
443 if (tagname) {
444 for (y = IKS_TAG_CHILDREN (x); y; y = y->next) {
445 if (IKS_TAG == y->type
446 && strcmp (IKS_TAG_NAME (y), tagname) == 0
447 && iks_strcmp (iks_find_attrib (y, attrname), value) == 0) {
448 return y;
449 }
450 }
451 } else {
452 for (y = IKS_TAG_CHILDREN (x); y; y = y->next) {
453 if (IKS_TAG == y->type
454 && iks_strcmp (iks_find_attrib (y, attrname), value) == 0) {
455 return y;
456 }
457 }
458 }
459 return NULL;
460 }
461
462 /***** Node Information *****/
463
464 ikstack *
iks_stack(iks * x)465 iks_stack (iks *x)
466 {
467 if (x) return x->s;
468 return NULL;
469 }
470
471 enum ikstype
iks_type(iks * x)472 iks_type (iks *x)
473 {
474 if (x) return x->type;
475 return IKS_NONE;
476 }
477
478 char *
iks_name(iks * x)479 iks_name (iks *x)
480 {
481 if (x) {
482 if (IKS_TAG == x->type)
483 return IKS_TAG_NAME (x);
484 else
485 return IKS_ATTRIB_NAME (x);
486 }
487 return NULL;
488 }
489
490 char *
iks_cdata(iks * x)491 iks_cdata (iks *x)
492 {
493 if (x) {
494 if (IKS_CDATA == x->type)
495 return IKS_CDATA_CDATA (x);
496 else
497 return IKS_ATTRIB_VALUE (x);
498 }
499 return NULL;
500 }
501
502 size_t
iks_cdata_size(iks * x)503 iks_cdata_size (iks *x)
504 {
505 if (x) return IKS_CDATA_LEN (x);
506 return 0;
507 }
508
509 int
iks_has_children(iks * x)510 iks_has_children (iks *x)
511 {
512 if (x && IKS_TAG == x->type && IKS_TAG_CHILDREN (x)) return 1;
513 return 0;
514 }
515
516 int
iks_has_attribs(iks * x)517 iks_has_attribs (iks *x)
518 {
519 if (x && IKS_TAG == x->type && IKS_TAG_ATTRIBS (x)) return 1;
520 return 0;
521 }
522
523 /***** Serializing *****/
524
525 static size_t
escape_size(char * src,size_t len)526 escape_size (char *src, size_t len)
527 {
528 size_t sz;
529 char c;
530 int i;
531
532 sz = 0;
533 for (i = 0; i < len; i++) {
534 c = src[i];
535 switch (c) {
536 case '&': sz += 5; break;
537 case '\'': sz += 6; break;
538 case '"': sz += 6; break;
539 case '<': sz += 4; break;
540 case '>': sz += 4; break;
541 default: sz++; break;
542 }
543 }
544 return sz;
545 }
546
547 static char *
my_strcat(char * dest,char * src,size_t len)548 my_strcat (char *dest, char *src, size_t len)
549 {
550 if (0 == len) len = strlen (src);
551 memcpy (dest, src, len);
552 return dest + len;
553 }
554
555 static char *
escape(char * dest,char * src,size_t len)556 escape (char *dest, char *src, size_t len)
557 {
558 char c;
559 int i;
560 int j = 0;
561
562 for (i = 0; i < len; i++) {
563 c = src[i];
564 if ('&' == c || '<' == c || '>' == c || '\'' == c || '"' == c) {
565 if (i - j > 0) dest = my_strcat (dest, src + j, i - j);
566 j = i + 1;
567 switch (c) {
568 case '&': dest = my_strcat (dest, "&", 5); break;
569 case '\'': dest = my_strcat (dest, "'", 6); break;
570 case '"': dest = my_strcat (dest, """, 6); break;
571 case '<': dest = my_strcat (dest, "<", 4); break;
572 case '>': dest = my_strcat (dest, ">", 4); break;
573 }
574 }
575 }
576 if (i - j > 0) dest = my_strcat (dest, src + j, i - j);
577 return dest;
578 }
579
580 char *
iks_string(ikstack * s,iks * x)581 iks_string (ikstack *s, iks *x)
582 {
583 size_t size;
584 int level, dir;
585 iks *y, *z;
586 char *ret, *t;
587
588 if (!x) return NULL;
589
590 if (x->type == IKS_CDATA) {
591 if (s) {
592 return iks_stack_strdup (s, IKS_CDATA_CDATA (x), IKS_CDATA_LEN (x));
593 } else {
594 ret = iks_malloc (IKS_CDATA_LEN (x));
595 memcpy (ret, IKS_CDATA_CDATA (x), IKS_CDATA_LEN (x));
596 return ret;
597 }
598 }
599
600 size = 0;
601 level = 0;
602 dir = 0;
603 y = x;
604 while (1) {
605 if (dir==0) {
606 if (y->type == IKS_TAG) {
607 size++;
608 size += strlen (IKS_TAG_NAME (y));
609 for (z = IKS_TAG_ATTRIBS (y); z; z = z->next) {
610 if (z->type == IKS_NONE) {
611 continue;
612 }
613 size += 4 + strlen (IKS_ATTRIB_NAME (z))
614 + escape_size (IKS_ATTRIB_VALUE (z), strlen (IKS_ATTRIB_VALUE (z)));
615 }
616 if (IKS_TAG_CHILDREN (y)) {
617 size++;
618 y = IKS_TAG_CHILDREN (y);
619 level++;
620 continue;
621 } else {
622 size += 2;
623 }
624 } else {
625 size += escape_size (IKS_CDATA_CDATA (y), IKS_CDATA_LEN (y));
626 }
627 }
628 z = y->next;
629 if (z) {
630 if (0 == level) {
631 if (IKS_TAG_CHILDREN (y)) size += 3 + strlen (IKS_TAG_NAME (y));
632 break;
633 }
634 y = z;
635 dir = 0;
636 } else {
637 y = y->parent;
638 level--;
639 if (level >= 0) size += 3 + strlen (IKS_TAG_NAME (y));
640 if (level < 1) break;
641 dir = 1;
642 }
643 }
644
645 if (s) ret = iks_stack_alloc (s, size + 1);
646 else ret = iks_malloc (size + 1);
647
648 if (!ret) return NULL;
649
650 t = ret;
651 level = 0;
652 dir = 0;
653 while (1) {
654 if (dir==0) {
655 if (x->type == IKS_TAG) {
656 *t++ = '<';
657 t = my_strcat (t, IKS_TAG_NAME (x), 0);
658 y = IKS_TAG_ATTRIBS (x);
659 while (y) {
660 *t++ = ' ';
661 t = my_strcat (t, IKS_ATTRIB_NAME (y), 0);
662 *t++ = '=';
663 *t++ = '\'';
664 t = escape (t, IKS_ATTRIB_VALUE (y), strlen (IKS_ATTRIB_VALUE (y)));
665 *t++ = '\'';
666 y = y->next;
667 }
668 if (IKS_TAG_CHILDREN (x)) {
669 *t++ = '>';
670 x = IKS_TAG_CHILDREN (x);
671 level++;
672 continue;
673 } else {
674 *t++ = '/';
675 *t++ = '>';
676 }
677 } else {
678 t = escape (t, IKS_CDATA_CDATA (x), IKS_CDATA_LEN (x));
679 }
680 }
681 y = x->next;
682 if (y) {
683 if (0 == level) {
684 if (IKS_TAG_CHILDREN (x)) {
685 *t++ = '<';
686 *t++ = '/';
687 t = my_strcat (t, IKS_TAG_NAME (x), 0);
688 *t++ = '>';
689 }
690 break;
691 }
692 x = y;
693 dir = 0;
694 } else {
695 x = x->parent;
696 level--;
697 if (level >= 0) {
698 *t++ = '<';
699 *t++ = '/';
700 t = my_strcat (t, IKS_TAG_NAME (x), 0);
701 *t++ = '>';
702 }
703 if (level < 1) break;
704 dir = 1;
705 }
706 }
707 *t = '\0';
708
709 return ret;
710 }
711
712 /***** Copying *****/
713
714 iks *
iks_copy_within(iks * x,ikstack * s)715 iks_copy_within (iks *x, ikstack *s)
716 {
717 int level=0, dir=0;
718 iks *copy = NULL;
719 iks *cur = NULL;
720 iks *y;
721
722 while (1) {
723 if (dir == 0) {
724 if (x->type == IKS_TAG) {
725 if (copy == NULL) {
726 copy = iks_new_within (IKS_TAG_NAME (x), s);
727 cur = copy;
728 } else {
729 cur = iks_insert (cur, IKS_TAG_NAME (x));
730 }
731 for (y = IKS_TAG_ATTRIBS (x); y; y = y->next) {
732 iks_insert_attrib (cur, IKS_ATTRIB_NAME (y), IKS_ATTRIB_VALUE (y));
733 }
734 if (IKS_TAG_CHILDREN (x)) {
735 x = IKS_TAG_CHILDREN (x);
736 level++;
737 continue;
738 } else {
739 cur = cur->parent;
740 }
741 } else {
742 iks_insert_cdata (cur, IKS_CDATA_CDATA (x), IKS_CDATA_LEN (x));
743 }
744 }
745 y = x->next;
746 if (y) {
747 if (0 == level) break;
748 x = y;
749 dir = 0;
750 } else {
751 if (level < 2) break;
752 level--;
753 x = x->parent;
754 cur = cur->parent;
755 dir = 1;
756 }
757 }
758 return copy;
759 }
760
761 iks *
iks_copy(iks * x)762 iks_copy (iks *x)
763 {
764 return iks_copy_within (x, iks_stack_new (sizeof (struct iks_tag) * 6, 256));
765 }
766