28 |
28 |
29 #include <stdio.h> |
29 #include <stdio.h> |
30 #include <stdlib.h> |
30 #include <stdlib.h> |
31 #include <string.h> |
31 #include <string.h> |
32 |
32 |
|
33 #include <ucx/string.h> |
|
34 #include <ucx/map.h> |
|
35 |
|
36 #include "../util/util.h" |
|
37 |
33 #include "xml.h" |
38 #include "xml.h" |
|
39 |
|
40 /* ------------------------ utils ------------------------ */ |
|
41 |
|
42 /* |
|
43 * generates a string key for an xml namespace |
|
44 * format: prefix '\0' href |
|
45 */ |
|
46 static sstr_t namespace_key(UcxAllocator *a, WSNamespace *ns) { |
|
47 sstr_t key = sstrcat_a(a, 3, |
|
48 ns->prefix ? sstr((char*)ns->prefix) : S("\0"), |
|
49 S("\0"), |
|
50 sstr((char*)ns->href)); |
|
51 return key; |
|
52 } |
|
53 |
|
54 |
|
55 /* ------------------------ wsxml_iterator ------------------------ */ |
34 |
56 |
35 typedef struct StackElm { |
57 typedef struct StackElm { |
36 WSXmlNode *node; // list of nodes |
58 WSXmlNode *node; // list of nodes |
37 //WSXmlNode *parent; // if not NULL, call endcb after node->next is NULL |
59 //WSXmlNode *parent; // if not NULL, call endcb after node->next is NULL |
38 int endonly; |
60 int endonly; |
160 } |
182 } |
161 |
183 |
162 return ret; |
184 return ret; |
163 } |
185 } |
164 |
186 |
|
187 /* ------------------------ wsxml_get_namespaces ------------------------ */ |
|
188 |
|
189 typedef struct WSNsCollector { |
|
190 UcxAllocator *a; |
|
191 UcxMap *nsmap; |
|
192 WebdavNSList *def; |
|
193 int error; |
|
194 } WSNsCollector; |
|
195 |
|
196 static int nslist_node_begin(xmlNode *node, void *userdata) { |
|
197 WSNsCollector *col = userdata; |
|
198 // namespace required for all elements |
|
199 if(node->type == XML_ELEMENT_NODE && node->ns) { |
|
200 // we create a list of unique prefix-href namespaces by putting |
|
201 // all namespaces in a map |
|
202 sstr_t nskey = namespace_key(col->a, node->ns); |
|
203 if(!nskey.ptr) { |
|
204 col->error = 1; |
|
205 return 1; |
|
206 } |
|
207 if(ucx_map_sstr_put(col->nsmap, nskey, node->ns)) { |
|
208 col->error = 1; |
|
209 return 1; |
|
210 } |
|
211 |
|
212 // collect all namespace definitions for removing these namespaces |
|
213 // from col->nsmap later |
|
214 WSNamespace *def = node->nsDef; |
|
215 while(def) { |
|
216 WebdavNSList *newdef = col->a->malloc( |
|
217 col->a->pool, sizeof(WebdavNSList)); |
|
218 if(!newdef) { |
|
219 col->error = 1; |
|
220 return 1; |
|
221 } |
|
222 newdef->namespace = def; |
|
223 newdef->prev = NULL; |
|
224 newdef->next = NULL; |
|
225 // prepend newdef to the list |
|
226 if(col->def) { |
|
227 newdef->next = col->def; |
|
228 col->def->prev = newdef; |
|
229 } |
|
230 col->def = newdef; |
|
231 |
|
232 // continue with next namespace definition |
|
233 def = def->next; |
|
234 } |
|
235 } |
|
236 return 0; |
|
237 } |
|
238 |
|
239 static int nslist_node_end(xmlNode *node, void *userdata) { |
|
240 return 0; |
|
241 } |
|
242 |
|
243 WebdavNSList* wsxml_get_required_namespaces( |
|
244 pool_handle_t *pool, |
|
245 WSXmlNode *node, |
|
246 int *error) |
|
247 { |
|
248 if(error) *error = 0; |
|
249 |
|
250 UcxAllocator a = util_pool_allocator(pool); |
|
251 UcxMap *nsmap = ucx_map_new_a(&a, 16); |
|
252 if(!nsmap) { |
|
253 if(error) *error = 1; |
|
254 return NULL; |
|
255 } |
|
256 |
|
257 WSNsCollector col; |
|
258 col.a = &a; |
|
259 col.nsmap = nsmap; |
|
260 col.def = NULL; |
|
261 |
|
262 // iterate over all xml elements |
|
263 // this will fill the hashmap with all namespaces |
|
264 // all namespace definitions are added to col.def |
|
265 WebdavNSList *list = NULL; |
|
266 WebdavNSList *end = NULL; |
|
267 if(wsxml_iterator(pool, node, nslist_node_begin, nslist_node_end, &col)) { |
|
268 if(error) *error = 1; |
|
269 } else { |
|
270 // remove all namespace definitions from the map |
|
271 // what we get is a map that contains all missing namespace definitions |
|
272 WebdavNSList *def = col.def; |
|
273 while(def) { |
|
274 sstr_t nskey = namespace_key(&a, def->namespace); |
|
275 if(!nskey.ptr) { |
|
276 if(error) *error = 1; |
|
277 break; |
|
278 } |
|
279 ucx_map_sstr_remove(nsmap, nskey); |
|
280 def = def->next; |
|
281 } |
|
282 |
|
283 // convert nsmap to a list |
|
284 UcxMapIterator i = ucx_map_iterator(nsmap); |
|
285 WSNamespace *ns; |
|
286 UCX_MAP_FOREACH(key, ns, i) { |
|
287 WebdavNSList *newelm = pool_malloc(pool, sizeof(WebdavNSList)); |
|
288 if(!newelm) { |
|
289 if(error) *error = 1; |
|
290 list = NULL; |
|
291 break; |
|
292 } |
|
293 newelm->namespace = ns; |
|
294 newelm->next = NULL; |
|
295 newelm->prev = end; // NULL or the end of list |
|
296 if(end) { |
|
297 end->next = newelm; // append new element |
|
298 } else { |
|
299 list = newelm; // start new list |
|
300 } |
|
301 end = newelm; |
|
302 } |
|
303 } |
|
304 |
|
305 ucx_map_free(nsmap); |
|
306 return list; |
|
307 } |