Mercurial > hg
annotate mcabber/libjabber/xmlnode.c @ 1579:a2dd83167bc9
Fix display error in the roster
When displaying the group item counts in the roster, the number could
wrap -- and overwrite the vertical line.
Issue reported by "Dennis" in the MUC room.
author | Mikael Berthe <mikael@lilotux.net> |
---|---|
date | Mon, 13 Apr 2009 22:48:48 +0200 |
parents | 5f43b532cc37 |
children |
rev | line source |
---|---|
25 | 1 /* |
2 * This program is free software; you can redistribute it and/or modify | |
3 * it under the terms of the GNU General Public License as published by | |
4 * the Free Software Foundation; either version 2 of the License, or | |
5 * (at your option) any later version. | |
6 * | |
7 * This program is distributed in the hope that it will be useful, | |
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
10 * GNU General Public License for more details. | |
11 * | |
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 | |
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
15 * | |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
16 * Copyrights |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
17 * |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
18 * Portions created by or assigned to Jabber.com, Inc. are |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
19 * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
20 * information for Jabber.com, Inc. is available at http://www.jabber.com/. |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
21 * |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
22 * Portions Copyright (c) 1998-1999 Jeremie Miller. |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
23 * |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
24 * Acknowledgements |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
25 * |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
26 * Special thanks to the Jabber Open Source Contributors for their |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
27 * suggestions and support of Jabber. |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
28 * |
25 | 29 */ |
30 | |
31 #include "libxode.h" | |
32 | |
33 /* Internal routines */ | |
34 xmlnode _xmlnode_new(pool p, const char* name, unsigned int type) | |
35 { | |
36 xmlnode result = NULL; | |
37 if (type > NTYPE_LAST) | |
38 return NULL; | |
39 | |
40 if (type != NTYPE_CDATA && name == NULL) | |
41 return NULL; | |
42 | |
43 if (p == NULL) | |
44 { | |
45 p = pool_heap(1*1024); | |
46 } | |
47 | |
48 /* Allocate & zero memory */ | |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
49 result = (xmlnode)pmalloco(p, sizeof(_xmlnode)); |
25 | 50 |
51 /* Initialize fields */ | |
52 if (type != NTYPE_CDATA) | |
53 result->name = pstrdup(p,name); | |
54 result->type = type; | |
55 result->p = p; | |
56 return result; | |
57 } | |
58 | |
59 static xmlnode _xmlnode_append_sibling(xmlnode lastsibling, const char* name, unsigned int type) | |
60 { | |
61 xmlnode result; | |
62 | |
63 result = _xmlnode_new(xmlnode_pool(lastsibling), name, type); | |
64 if (result != NULL) | |
65 { | |
66 /* Setup sibling pointers */ | |
67 result->prev = lastsibling; | |
68 lastsibling->next = result; | |
69 } | |
70 return result; | |
71 } | |
72 | |
73 static xmlnode _xmlnode_insert(xmlnode parent, const char* name, unsigned int type) | |
74 { | |
75 xmlnode result; | |
76 | |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
77 if(parent == NULL || (type != NTYPE_CDATA && name == NULL)) return NULL; |
25 | 78 |
79 /* If parent->firstchild is NULL, simply create a new node for the first child */ | |
80 if (parent->firstchild == NULL) | |
81 { | |
82 result = _xmlnode_new(parent->p, name, type); | |
83 parent->firstchild = result; | |
84 } | |
85 /* Otherwise, append this to the lastchild */ | |
86 else | |
87 { | |
88 result= _xmlnode_append_sibling(parent->lastchild, name, type); | |
89 } | |
90 result->parent = parent; | |
91 parent->lastchild = result; | |
92 return result; | |
93 | |
94 } | |
95 | |
96 static xmlnode _xmlnode_search(xmlnode firstsibling, const char* name, unsigned int type) | |
97 { | |
98 xmlnode current; | |
99 | |
100 /* Walk the sibling list, looking for a NTYPE_TAG xmlnode with | |
101 the specified name */ | |
102 current = firstsibling; | |
103 while (current != NULL) | |
104 { | |
105 if ((current->type == type) && (j_strcmp(current->name, name) == 0)) | |
106 return current; | |
107 else | |
108 current = current->next; | |
109 } | |
110 return NULL; | |
111 } | |
112 | |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
113 void _xmlnode_merge(xmlnode data) |
25 | 114 { |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
115 xmlnode cur; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
116 char *merge, *scur; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
117 int imerge; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
118 |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
119 /* get total size of all merged cdata */ |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
120 imerge = 0; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
121 for(cur = data; cur != NULL && cur->type == NTYPE_CDATA; cur = cur->next) |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
122 imerge += cur->data_sz; |
25 | 123 |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
124 /* copy in current data and then spin through all of them and merge */ |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
125 scur = merge = pmalloc(data->p,imerge + 1); |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
126 for(cur = data; cur != NULL && cur->type == NTYPE_CDATA; cur = cur->next) |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
127 { |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
128 memcpy(scur,cur->data,cur->data_sz); |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
129 scur += cur->data_sz; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
130 } |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
131 *scur = '\0'; |
25 | 132 |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
133 /* this effectively hides all of the merged-in chunks */ |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
134 data->next = cur; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
135 if(cur == NULL) |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
136 data->parent->lastchild = data; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
137 else |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
138 cur->prev = data; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
139 |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
140 /* reset data */ |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
141 data->data = merge; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
142 data->data_sz = imerge; |
25 | 143 } |
144 | |
145 static void _xmlnode_hide_sibling(xmlnode child) | |
146 { | |
147 if(child == NULL) | |
148 return; | |
149 | |
150 if(child->prev != NULL) | |
151 child->prev->next = child->next; | |
152 if(child->next != NULL) | |
153 child->next->prev = child->prev; | |
154 } | |
155 | |
156 void _xmlnode_tag2str(spool s, xmlnode node, int flag) | |
157 { | |
158 xmlnode tmp; | |
159 | |
160 if(flag==0 || flag==1) | |
161 { | |
162 spooler(s,"<",xmlnode_get_name(node),s); | |
163 tmp = xmlnode_get_firstattrib(node); | |
164 while(tmp) { | |
165 spooler(s," ",xmlnode_get_name(tmp),"='",strescape(xmlnode_pool(node),xmlnode_get_data(tmp)),"'",s); | |
166 tmp = xmlnode_get_nextsibling(tmp); | |
167 } | |
168 if(flag==0) | |
169 spool_add(s,"/>"); | |
170 else | |
171 spool_add(s,">"); | |
172 } | |
173 else | |
174 { | |
175 spooler(s,"</",xmlnode_get_name(node),">",s); | |
176 } | |
177 } | |
178 | |
179 spool _xmlnode2spool(xmlnode node) | |
180 { | |
181 spool s; | |
182 int level=0,dir=0; | |
183 xmlnode tmp; | |
184 | |
185 if(!node || xmlnode_get_type(node)!=NTYPE_TAG) | |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
186 return NULL; |
25 | 187 |
188 s = spool_new(xmlnode_pool(node)); | |
189 if(!s) return(NULL); | |
190 | |
191 while(1) | |
192 { | |
193 if(dir==0) | |
194 { | |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
195 if(xmlnode_get_type(node) == NTYPE_TAG) |
25 | 196 { |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
197 if(xmlnode_has_children(node)) |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
198 { |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
199 _xmlnode_tag2str(s,node,1); |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
200 node = xmlnode_get_firstchild(node); |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
201 level++; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
202 continue; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
203 }else{ |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
204 _xmlnode_tag2str(s,node,0); |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
205 } |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
206 }else{ |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
207 spool_add(s,strescape(xmlnode_pool(node),xmlnode_get_data(node))); |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
208 } |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
209 } |
25 | 210 |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
211 tmp = xmlnode_get_nextsibling(node); |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
212 if(!tmp) |
25 | 213 { |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
214 node = xmlnode_get_parent(node); |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
215 level--; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
216 if(level>=0) _xmlnode_tag2str(s,node,2); |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
217 if(level<1) break; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
218 dir = 1; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
219 }else{ |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
220 node = tmp; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
221 dir = 0; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
222 } |
25 | 223 } |
224 | |
225 return s; | |
226 } | |
227 | |
228 | |
229 /* External routines */ | |
230 | |
231 | |
232 /* | |
233 * xmlnode_new_tag -- create a tag node | |
234 * Automatically creates a memory pool for the node. | |
235 * | |
236 * parameters | |
237 * name -- name of the tag | |
238 * | |
239 * returns | |
240 * a pointer to the tag node | |
241 * or NULL if it was unsuccessfull | |
242 */ | |
243 xmlnode xmlnode_new_tag(const char* name) | |
244 { | |
245 return _xmlnode_new(NULL, name, NTYPE_TAG); | |
246 } | |
247 | |
248 | |
249 /* | |
250 * xmlnode_new_tag_pool -- create a tag node within given pool | |
251 * | |
252 * parameters | |
253 * p -- previously created memory pool | |
254 * name -- name of the tag | |
255 * | |
256 * returns | |
257 * a pointer to the tag node | |
258 * or NULL if it was unsuccessfull | |
259 */ | |
260 xmlnode xmlnode_new_tag_pool(pool p, const char* name) | |
261 { | |
262 return _xmlnode_new(p, name, NTYPE_TAG); | |
263 } | |
264 | |
265 | |
266 /* | |
267 * xmlnode_insert_tag -- append a child tag to a tag | |
268 * | |
269 * parameters | |
270 * parent -- pointer to the parent tag | |
271 * name -- name of the child tag | |
272 * | |
273 * returns | |
274 * a pointer to the child tag node | |
275 * or NULL if it was unsuccessfull | |
276 */ | |
277 xmlnode xmlnode_insert_tag(xmlnode parent, const char* name) | |
278 { | |
279 return _xmlnode_insert(parent, name, NTYPE_TAG); | |
280 } | |
281 | |
282 | |
283 /* | |
284 * xmlnode_insert_cdata -- append character data to a tag | |
285 * | |
286 * parameters | |
287 * parent -- parent tag | |
288 * CDATA -- character data | |
289 * size -- size of CDATA | |
290 * or -1 for null-terminated CDATA strings | |
291 * | |
292 * returns | |
293 * a pointer to the child CDATA node | |
294 * or NULL if it was unsuccessfull | |
295 */ | |
296 xmlnode xmlnode_insert_cdata(xmlnode parent, const char* CDATA, unsigned int size) | |
297 { | |
298 xmlnode result; | |
299 | |
300 if(CDATA == NULL || parent == NULL) | |
301 return NULL; | |
302 | |
879
5f43b532cc37
Remove a few libjabber warnings
Mikael Berthe <mikael@lilotux.net>
parents:
417
diff
changeset
|
303 if(size == (unsigned int)-1) |
25 | 304 size = strlen(CDATA); |
305 | |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
306 result = _xmlnode_insert(parent, NULL, NTYPE_CDATA); |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
307 if (result != NULL) |
25 | 308 { |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
309 result->data = (char*)pmalloc(result->p, size + 1); |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
310 memcpy(result->data, CDATA, size); |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
311 result->data[size] = '\0'; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
312 result->data_sz = size; |
25 | 313 } |
314 | |
315 return result; | |
316 } | |
317 | |
318 | |
319 /* | |
320 * xmlnode_get_tag -- find given tag in an xmlnode tree | |
321 * | |
322 * parameters | |
323 * parent -- pointer to the parent tag | |
324 * name -- "name" for the child tag of that name | |
325 * "name/name" for a sub child (recurses) | |
326 * "?attrib" to match the first tag with that attrib defined | |
327 * "?attrib=value" to match the first tag with that attrib and value | |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
328 * "=cdata" to match the cdata contents of the child |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
329 * or any combination: "name/name/?attrib", "name=cdata", etc |
25 | 330 * |
331 * results | |
332 * a pointer to the tag matching search criteria | |
333 * or NULL if search was unsuccessfull | |
334 */ | |
335 xmlnode xmlnode_get_tag(xmlnode parent, const char* name) | |
336 { | |
337 char *str, *slash, *qmark, *equals; | |
338 xmlnode step, ret; | |
339 | |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
340 |
25 | 341 if(parent == NULL || parent->firstchild == NULL || name == NULL || name == '\0') return NULL; |
342 | |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
343 if(strstr(name, "/") == NULL && strstr(name,"?") == NULL && strstr(name, "=") == NULL) |
25 | 344 return _xmlnode_search(parent->firstchild, name, NTYPE_TAG); |
345 | |
346 str = strdup(name); | |
347 slash = strstr(str, "/"); | |
348 qmark = strstr(str, "?"); | |
349 equals = strstr(str, "="); | |
350 | |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
351 if(equals != NULL && (slash == NULL || equals < slash) && (qmark == NULL || equals < qmark)) |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
352 { /* of type =cdata */ |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
353 |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
354 *equals = '\0'; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
355 equals++; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
356 |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
357 for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step)) |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
358 { |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
359 if(xmlnode_get_type(step) != NTYPE_TAG) |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
360 continue; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
361 |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
362 if(*str != '\0') |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
363 if(j_strcmp(xmlnode_get_name(step),str) != 0) |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
364 continue; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
365 |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
366 if(j_strcmp(xmlnode_get_data(step),equals) != 0) |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
367 continue; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
368 |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
369 break; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
370 } |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
371 |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
372 free(str); |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
373 return step; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
374 } |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
375 |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
376 |
25 | 377 if(qmark != NULL && (slash == NULL || qmark < slash)) |
378 { /* of type ?attrib */ | |
379 | |
380 *qmark = '\0'; | |
381 qmark++; | |
382 if(equals != NULL) | |
383 { | |
384 *equals = '\0'; | |
385 equals++; | |
386 } | |
387 | |
388 for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step)) | |
389 { | |
390 if(xmlnode_get_type(step) != NTYPE_TAG) | |
391 continue; | |
392 | |
393 if(*str != '\0') | |
394 if(j_strcmp(xmlnode_get_name(step),str) != 0) | |
395 continue; | |
396 | |
397 if(xmlnode_get_attrib(step,qmark) == NULL) | |
398 continue; | |
399 | |
400 if(equals != NULL && j_strcmp(xmlnode_get_attrib(step,qmark),equals) != 0) | |
401 continue; | |
402 | |
403 break; | |
404 } | |
405 | |
406 free(str); | |
407 return step; | |
408 } | |
409 | |
410 | |
411 *slash = '\0'; | |
412 ++slash; | |
413 | |
414 for(step = parent->firstchild; step != NULL; step = xmlnode_get_nextsibling(step)) | |
415 { | |
416 if(xmlnode_get_type(step) != NTYPE_TAG) continue; | |
417 | |
418 if(j_strcmp(xmlnode_get_name(step),str) != 0) | |
419 continue; | |
420 | |
421 ret = xmlnode_get_tag(step, slash); | |
422 if(ret != NULL) | |
423 { | |
424 free(str); | |
425 return ret; | |
426 } | |
427 } | |
428 | |
429 free(str); | |
430 return NULL; | |
431 } | |
432 | |
433 | |
434 /* return the cdata from any tag */ | |
435 char *xmlnode_get_tag_data(xmlnode parent, const char *name) | |
436 { | |
437 xmlnode tag; | |
438 | |
439 tag = xmlnode_get_tag(parent, name); | |
440 if(tag == NULL) return NULL; | |
441 | |
442 return xmlnode_get_data(tag); | |
443 } | |
444 | |
445 | |
446 void xmlnode_put_attrib(xmlnode owner, const char* name, const char* value) | |
447 { | |
448 xmlnode attrib; | |
449 | |
450 if(owner == NULL || name == NULL || value == NULL) return; | |
451 | |
452 /* If there are no existing attributs, allocate a new one to start | |
453 the list */ | |
454 if (owner->firstattrib == NULL) | |
455 { | |
456 attrib = _xmlnode_new(owner->p, name, NTYPE_ATTRIB); | |
457 owner->firstattrib = attrib; | |
458 owner->lastattrib = attrib; | |
459 } | |
460 else | |
461 { | |
462 attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); | |
463 if(attrib == NULL) | |
464 { | |
465 attrib = _xmlnode_append_sibling(owner->lastattrib, name, NTYPE_ATTRIB); | |
466 owner->lastattrib = attrib; | |
467 } | |
468 } | |
469 /* Update the value of the attribute */ | |
470 attrib->data_sz = strlen(value); | |
471 attrib->data = pstrdup(owner->p, value); | |
472 | |
473 } | |
474 | |
475 char* xmlnode_get_attrib(xmlnode owner, const char* name) | |
476 { | |
477 xmlnode attrib; | |
478 | |
479 if (owner != NULL && owner->firstattrib != NULL) | |
480 { | |
481 attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); | |
482 if (attrib != NULL) | |
483 return (char*)attrib->data; | |
484 } | |
485 return NULL; | |
486 } | |
487 | |
488 void xmlnode_put_vattrib(xmlnode owner, const char* name, void *value) | |
489 { | |
490 xmlnode attrib; | |
491 | |
492 if (owner != NULL) | |
493 { | |
494 attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); | |
495 if (attrib == NULL) | |
496 { | |
497 xmlnode_put_attrib(owner, name, ""); | |
498 attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); | |
499 } | |
500 if (attrib != NULL) | |
501 attrib->firstchild = (xmlnode)value; | |
502 } | |
503 } | |
504 | |
505 void* xmlnode_get_vattrib(xmlnode owner, const char* name) | |
506 { | |
507 xmlnode attrib; | |
508 | |
509 if (owner != NULL && owner->firstattrib != NULL) | |
510 { | |
511 attrib = _xmlnode_search(owner->firstattrib, name, NTYPE_ATTRIB); | |
512 if (attrib != NULL) | |
513 return (void*)attrib->firstchild; | |
514 } | |
515 return NULL; | |
516 } | |
517 | |
518 xmlnode xmlnode_get_firstattrib(xmlnode parent) | |
519 { | |
520 if (parent != NULL) | |
521 return parent->firstattrib; | |
522 return NULL; | |
523 } | |
524 | |
525 xmlnode xmlnode_get_firstchild(xmlnode parent) | |
526 { | |
527 if (parent != NULL) | |
528 return parent->firstchild; | |
529 return NULL; | |
530 } | |
531 | |
532 xmlnode xmlnode_get_lastchild(xmlnode parent) | |
533 { | |
534 if (parent != NULL) | |
535 return parent->lastchild; | |
536 return NULL; | |
537 } | |
538 | |
539 xmlnode xmlnode_get_nextsibling(xmlnode sibling) | |
540 { | |
541 if (sibling != NULL) | |
542 return sibling->next; | |
543 return NULL; | |
544 } | |
545 | |
546 xmlnode xmlnode_get_prevsibling(xmlnode sibling) | |
547 { | |
548 if (sibling != NULL) | |
549 return sibling->prev; | |
550 return NULL; | |
551 } | |
552 | |
553 xmlnode xmlnode_get_parent(xmlnode node) | |
554 { | |
555 if (node != NULL) | |
556 return node->parent; | |
557 return NULL; | |
558 } | |
559 | |
560 char* xmlnode_get_name(xmlnode node) | |
561 { | |
562 if (node != NULL) | |
563 return node->name; | |
564 return NULL; | |
565 } | |
566 | |
567 char* xmlnode_get_data(xmlnode node) | |
568 { | |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
569 if(xmlnode_get_type(node) == NTYPE_TAG) /* loop till we find a CDATA in the children */ |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
570 for(node = xmlnode_get_firstchild(node); node != NULL; node = xmlnode_get_nextsibling(node)) |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
571 if(xmlnode_get_type(node) == NTYPE_CDATA) break; |
25 | 572 |
573 if(node == NULL) return NULL; | |
574 | |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
575 /* check for a dirty node w/ unassembled cdata chunks */ |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
576 if(xmlnode_get_type(node->next) == NTYPE_CDATA) |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
577 _xmlnode_merge(node); |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
578 |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
579 return node->data; |
25 | 580 } |
581 | |
582 int xmlnode_get_datasz(xmlnode node) | |
583 { | |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
584 if(xmlnode_get_type(node) != NTYPE_CDATA) return 0; |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
585 |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
586 /* check for a dirty node w/ unassembled cdata chunks */ |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
587 if(xmlnode_get_type(node->next) == NTYPE_CDATA) |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
588 _xmlnode_merge(node); |
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
589 return node->data_sz; |
25 | 590 } |
591 | |
592 int xmlnode_get_type(xmlnode node) | |
593 { | |
594 if (node != NULL) | |
595 return node->type; | |
417
c3ae9251c197
Sync libjabber with upstream
Mikael Berthe <mikael@lilotux.net>
parents:
25
diff
changeset
|
596 return NTYPE_UNDEF; |
25 | 597 } |
598 | |
599 int xmlnode_has_children(xmlnode node) | |
600 { | |
601 if ((node != NULL) && (node->firstchild != NULL)) | |
602 return 1; | |
603 return 0; | |
604 } | |
605 | |
606 int xmlnode_has_attribs(xmlnode node) | |
607 { | |
608 if ((node != NULL) && (node->firstattrib != NULL)) | |
609 return 1; | |
610 return 0; | |
611 } | |
612 | |
613 pool xmlnode_pool(xmlnode node) | |
614 { | |
615 if (node != NULL) | |
616 return node->p; | |
617 return (pool)NULL; | |
618 } | |
619 | |
620 void xmlnode_hide(xmlnode child) | |
621 { | |
622 xmlnode parent; | |
623 | |
624 if(child == NULL || child->parent == NULL) | |
625 return; | |
626 | |
627 parent = child->parent; | |
628 | |
629 /* first fix up at the child level */ | |
630 _xmlnode_hide_sibling(child); | |
631 | |
632 /* next fix up at the parent level */ | |
633 if(parent->firstchild == child) | |
634 parent->firstchild = child->next; | |
635 if(parent->lastchild == child) | |
636 parent->lastchild = child->prev; | |
637 } | |
638 | |
639 void xmlnode_hide_attrib(xmlnode parent, const char *name) | |
640 { | |
641 xmlnode attrib; | |
642 | |
643 if(parent == NULL || parent->firstattrib == NULL || name == NULL) | |
644 return; | |
645 | |
646 attrib = _xmlnode_search(parent->firstattrib, name, NTYPE_ATTRIB); | |
647 if(attrib == NULL) | |
648 return; | |
649 | |
650 /* first fix up at the child level */ | |
651 _xmlnode_hide_sibling(attrib); | |
652 | |
653 /* next fix up at the parent level */ | |
654 if(parent->firstattrib == attrib) | |
655 parent->firstattrib = attrib->next; | |
656 if(parent->lastattrib == attrib) | |
657 parent->lastattrib = attrib->prev; | |
658 } | |
659 | |
660 | |
661 | |
662 /* | |
663 * xmlnode2str -- convert given xmlnode tree into a string | |
664 * | |
665 * parameters | |
666 * node -- pointer to the xmlnode structure | |
667 * | |
668 * results | |
669 * a pointer to the created string | |
670 * or NULL if it was unsuccessfull | |
671 */ | |
672 char *xmlnode2str(xmlnode node) | |
673 { | |
674 return spool_print(_xmlnode2spool(node)); | |
675 } | |
676 | |
677 /* | |
678 * xmlnode2tstr -- convert given xmlnode tree into a newline terminated string | |
679 * | |
680 * parameters | |
681 * node -- pointer to the xmlnode structure | |
682 * | |
683 * results | |
684 * a pointer to the created string | |
685 * or NULL if it was unsuccessfull | |
686 */ | |
687 char* xmlnode2tstr(xmlnode node) | |
688 { | |
689 spool s = _xmlnode2spool(node); | |
690 if (s != NULL) | |
691 spool_add(s, "\n"); | |
692 return spool_print(s); | |
693 } | |
694 | |
695 | |
696 /* loop through both a and b comparing everything, attribs, cdata, children, etc */ | |
697 int xmlnode_cmp(xmlnode a, xmlnode b) | |
698 { | |
699 int ret = 0; | |
700 | |
701 while(1) | |
702 { | |
703 if(a == NULL && b == NULL) | |
704 return 0; | |
705 | |
706 if(a == NULL || b == NULL) | |
707 return -1; | |
708 | |
709 if(xmlnode_get_type(a) != xmlnode_get_type(b)) | |
710 return -1; | |
711 | |
712 switch(xmlnode_get_type(a)) | |
713 { | |
714 case NTYPE_ATTRIB: | |
715 ret = j_strcmp(xmlnode_get_name(a), xmlnode_get_name(b)); | |
716 if(ret != 0) | |
717 return -1; | |
718 ret = j_strcmp(xmlnode_get_data(a), xmlnode_get_data(b)); | |
719 if(ret != 0) | |
720 return -1; | |
721 break; | |
722 case NTYPE_TAG: | |
723 ret = j_strcmp(xmlnode_get_name(a), xmlnode_get_name(b)); | |
724 if(ret != 0) | |
725 return -1; | |
726 ret = xmlnode_cmp(xmlnode_get_firstattrib(a), xmlnode_get_firstattrib(b)); | |
727 if(ret != 0) | |
728 return -1; | |
729 ret = xmlnode_cmp(xmlnode_get_firstchild(a), xmlnode_get_firstchild(b)); | |
730 if(ret != 0) | |
731 return -1; | |
732 break; | |
733 case NTYPE_CDATA: | |
734 ret = j_strcmp(xmlnode_get_data(a), xmlnode_get_data(b)); | |
735 if(ret != 0) | |
736 return -1; | |
737 } | |
738 a = xmlnode_get_nextsibling(a); | |
739 b = xmlnode_get_nextsibling(b); | |
740 } | |
741 } | |
742 | |
743 | |
744 xmlnode xmlnode_insert_tag_node(xmlnode parent, xmlnode node) | |
745 { | |
746 xmlnode child; | |
747 | |
748 child = xmlnode_insert_tag(parent, xmlnode_get_name(node)); | |
749 if (xmlnode_has_attribs(node)) | |
750 xmlnode_insert_node(child, xmlnode_get_firstattrib(node)); | |
751 if (xmlnode_has_children(node)) | |
752 xmlnode_insert_node(child, xmlnode_get_firstchild(node)); | |
753 | |
754 return child; | |
755 } | |
756 | |
757 /* places copy of node and node's siblings in parent */ | |
758 void xmlnode_insert_node(xmlnode parent, xmlnode node) | |
759 { | |
760 if(node == NULL || parent == NULL) | |
761 return; | |
762 | |
763 while(node != NULL) | |
764 { | |
765 switch(xmlnode_get_type(node)) | |
766 { | |
767 case NTYPE_ATTRIB: | |
768 xmlnode_put_attrib(parent, xmlnode_get_name(node), xmlnode_get_data(node)); | |
769 break; | |
770 case NTYPE_TAG: | |
771 xmlnode_insert_tag_node(parent, node); | |
772 break; | |
773 case NTYPE_CDATA: | |
774 xmlnode_insert_cdata(parent, xmlnode_get_data(node), xmlnode_get_datasz(node)); | |
775 } | |
776 node = xmlnode_get_nextsibling(node); | |
777 } | |
778 } | |
779 | |
780 | |
781 /* produce full duplicate of x with a new pool, x must be a tag! */ | |
782 xmlnode xmlnode_dup(xmlnode x) | |
783 { | |
784 xmlnode x2; | |
785 | |
786 if(x == NULL) | |
787 return NULL; | |
788 | |
789 x2 = xmlnode_new_tag(xmlnode_get_name(x)); | |
790 | |
791 if (xmlnode_has_attribs(x)) | |
792 xmlnode_insert_node(x2, xmlnode_get_firstattrib(x)); | |
793 if (xmlnode_has_children(x)) | |
794 xmlnode_insert_node(x2, xmlnode_get_firstchild(x)); | |
795 | |
796 return x2; | |
797 } | |
798 | |
799 xmlnode xmlnode_dup_pool(pool p, xmlnode x) | |
800 { | |
801 xmlnode x2; | |
802 | |
803 if(x == NULL) | |
804 return NULL; | |
805 | |
806 x2 = xmlnode_new_tag_pool(p, xmlnode_get_name(x)); | |
807 | |
808 if (xmlnode_has_attribs(x)) | |
809 xmlnode_insert_node(x2, xmlnode_get_firstattrib(x)); | |
810 if (xmlnode_has_children(x)) | |
811 xmlnode_insert_node(x2, xmlnode_get_firstchild(x)); | |
812 | |
813 return x2; | |
814 } | |
815 | |
816 xmlnode xmlnode_wrap(xmlnode x,const char *wrapper) | |
817 { | |
818 xmlnode wrap; | |
819 if(x==NULL||wrapper==NULL) return NULL; | |
820 wrap=xmlnode_new_tag_pool(xmlnode_pool(x),wrapper); | |
821 if(wrap==NULL) return NULL; | |
822 wrap->firstchild=x; | |
823 wrap->lastchild=x; | |
824 x->parent=wrap; | |
825 return wrap; | |
826 } | |
827 | |
828 void xmlnode_free(xmlnode node) | |
829 { | |
830 if(node == NULL) | |
831 return; | |
832 | |
833 pool_free(node->p); | |
834 } |