src/server/webdav/xml.c

changeset 415
d938228c382e
parent 324
44cf877b3d9f
child 490
d218607f5a7e
equal deleted inserted replaced
414:99a34860c105 415:d938228c382e
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> 33 #include <cx/string.h>
34 #include <ucx/map.h> 34 #include <cx/map.h>
35 #include <ucx/buffer.h> 35 #include <cx/hash_map.h>
36 #include <cx/buffer.h>
37 #include <cx/linked_list.h>
36 38
37 #include "../util/util.h" 39 #include "../util/util.h"
38 #include "../util/pool.h" 40 #include "../util/pool.h"
39 41
40 #include "xml.h" 42 #include "xml.h"
45 47
46 /* 48 /*
47 * generates a string key for an xml namespace 49 * generates a string key for an xml namespace
48 * format: prefix '\0' href 50 * format: prefix '\0' href
49 */ 51 */
50 static sstr_t xml_namespace_key(UcxAllocator *a, WSNamespace *ns) { 52 static CxHashKey xml_namespace_key(CxAllocator *a, WSNamespace *ns) {
51 sstr_t key = sstrcat_a(a, 3, 53 cxmutstr key_data = cx_strcat_a(a, 3,
52 ns->prefix ? sstr((char*)ns->prefix) : S("\0"), 54 ns->prefix ? cx_str((char*)ns->prefix) : cx_strn("\0", 1),
53 S("\0"), 55 cx_strn("\0", 1),
54 sstr((char*)ns->href)); 56 cx_str((char*)ns->href));
55 return key; 57 return cx_hash_key_bytes((unsigned char*)key_data.ptr, key_data.length);
56 } 58 }
57 59
58 60
59 /***************************************************************************** 61 /*****************************************************************************
60 * Public functions 62 * Public functions
193 } 195 }
194 196
195 /* ------------------- wsxml_get_required_namespaces ------------------- */ 197 /* ------------------- wsxml_get_required_namespaces ------------------- */
196 198
197 typedef struct WSNsCollector { 199 typedef struct WSNsCollector {
198 UcxAllocator *a; 200 CxAllocator *a;
199 UcxMap *nsmap; 201 CxMap *nsmap;
200 WebdavNSList *def; 202 WebdavNSList *def;
201 int error; 203 int error;
202 } WSNsCollector; 204 } WSNsCollector;
203 205
204 static int nslist_node_begin(xmlNode *node, void *userdata) { 206 static int nslist_node_begin(xmlNode *node, void *userdata) {
205 WSNsCollector *col = userdata; 207 WSNsCollector *col = userdata;
206 // namespace required for all elements 208 // namespace required for all elements
207 if(node->type == XML_ELEMENT_NODE && node->ns) { 209 if(node->type == XML_ELEMENT_NODE && node->ns) {
208 // we create a list of unique prefix-href namespaces by putting 210 // we create a list of unique prefix-href namespaces by putting
209 // all namespaces in a map 211 // all namespaces in a map
210 sstr_t nskey = xml_namespace_key(col->a, node->ns); 212 CxHashKey nskey = xml_namespace_key(col->a, node->ns);
211 if(!nskey.ptr) { 213 if(!nskey.data.bytes) {
212 col->error = 1; 214 col->error = 1;
213 return 1; 215 return 1;
214 } 216 }
215 if(ucx_map_sstr_put(col->nsmap, nskey, node->ns)) { 217 if(cxMapPut(col->nsmap, nskey, node->ns)) {
216 col->error = 1; 218 col->error = 1;
217 return 1; 219 return 1;
218 } 220 }
219 221
220 // collect all namespace definitions for removing these namespaces 222 // collect all namespace definitions for removing these namespaces
221 // from col->nsmap later 223 // from col->nsmap later
222 WSNamespace *def = node->nsDef; 224 WSNamespace *def = node->nsDef;
223 while(def) { 225 while(def) {
224 WebdavNSList *newdef = col->a->malloc( 226 WebdavNSList *newdef = cxMalloc(col->a, sizeof(WebdavNSList));
225 col->a->pool, sizeof(WebdavNSList));
226 if(!newdef) { 227 if(!newdef) {
227 col->error = 1; 228 col->error = 1;
228 return 1; 229 return 1;
229 } 230 }
230 newdef->namespace = def; 231 newdef->namespace = def;
253 WSXmlNode *node, 254 WSXmlNode *node,
254 int *error) 255 int *error)
255 { 256 {
256 if(error) *error = 0; 257 if(error) *error = 0;
257 258
258 UcxAllocator a = util_pool_allocator(pool); 259 CxAllocator *a = pool_allocator(pool);
259 UcxMap *nsmap = ucx_map_new_a(&a, 16); 260 CxMap *nsmap = cxHashMapCreate(a, 16);
260 if(!nsmap) { 261 if(!nsmap) {
261 if(error) *error = 1; 262 if(error) *error = 1;
262 return NULL; 263 return NULL;
263 } 264 }
264 265
265 WSNsCollector col; 266 WSNsCollector col;
266 col.a = &a; 267 col.a = a;
267 col.nsmap = nsmap; 268 col.nsmap = nsmap;
268 col.def = NULL; 269 col.def = NULL;
269 270
270 // iterate over all xml elements 271 // iterate over all xml elements
271 // this will fill the hashmap with all namespaces 272 // this will fill the hashmap with all namespaces
277 } else { 278 } else {
278 // remove all namespace definitions from the map 279 // remove all namespace definitions from the map
279 // what we get is a map that contains all missing namespace definitions 280 // what we get is a map that contains all missing namespace definitions
280 WebdavNSList *def = col.def; 281 WebdavNSList *def = col.def;
281 while(def) { 282 while(def) {
282 sstr_t nskey = xml_namespace_key(&a, def->namespace); 283 CxHashKey nskey = xml_namespace_key(a, def->namespace);
283 if(!nskey.ptr) { 284 if(!nskey.data.bytes) {
284 if(error) *error = 1; 285 if(error) *error = 1;
285 break; 286 break;
286 } 287 }
287 ucx_map_sstr_remove(nsmap, nskey); 288 (void)cxMapRemove(nsmap, nskey);
288 def = def->next; 289 def = def->next;
289 } 290 }
290 291
291 // convert nsmap to a list 292 // convert nsmap to a list
292 UcxMapIterator i = ucx_map_iterator(nsmap); 293 CxIterator i = cxMapIteratorValues(nsmap);
293 WSNamespace *ns; 294 WSNamespace *ns;
294 UCX_MAP_FOREACH(key, ns, i) { 295 cx_foreach(WSNamespace *, ns, i) {
295 WebdavNSList *newelm = pool_malloc(pool, sizeof(WebdavNSList)); 296 WebdavNSList *newelm = pool_malloc(pool, sizeof(WebdavNSList));
296 if(!newelm) { 297 if(!newelm) {
297 if(error) *error = 1; 298 if(error) *error = 1;
298 list = NULL; 299 list = NULL;
299 break; 300 break;
300 } 301 }
301 newelm->namespace = ns; 302 newelm->namespace = ns;
302 newelm->next = NULL; 303 newelm->next = NULL;
303 newelm->prev = end; // NULL or the end of list 304 newelm->prev = NULL;
304 if(end) { 305 cx_linked_list_add((void**)&list, (void**)&end, offsetof(WebdavNSList, prev), offsetof(WebdavNSList, next), newelm);
305 end->next = newelm; // append new element 306 }
306 } else { 307 }
307 list = newelm; // start new list 308
308 } 309 cxMapDestroy(nsmap);
309 end = newelm;
310 }
311 }
312
313 ucx_map_free(nsmap);
314 return list; 310 return list;
315 } 311 }
316 312
317 313
318 static ssize_t buf_writefunc(void *buf, const char *s, size_t len) { 314 static ssize_t buf_writefunc(void *buf, const char *s, size_t len) {
319 int w = ucx_buffer_write(s, 1, len, buf); 315 int w = cxBufferWrite(s, 1, len, buf);
320 return w == 0 ? IO_ERROR : w; 316 return w == 0 ? IO_ERROR : w;
321 } 317 }
322 318
323 WSXmlData* wsxml_node2data( 319 WSXmlData* wsxml_node2data(
324 pool_handle_t *pool, 320 pool_handle_t *pool,
325 WSXmlNode *node) 321 WSXmlNode *node)
326 { 322 {
327 UcxBuffer *buf = ucx_buffer_new(NULL, 1024, UCX_BUFFER_AUTOEXTEND); 323 CxBuffer buf;
328 if(!buf) { 324 if(cxBufferInit(&buf, NULL, 1024, pool_allocator(pool), CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS)) {
329 return NULL; 325 return NULL;
330 } 326 }
331 327
332 int error = 0; 328 int error = 0;
333 WebdavNSList *nslist = wsxml_get_required_namespaces(pool, node, &error); 329 WebdavNSList *nslist = wsxml_get_required_namespaces(pool, node, &error);
335 return NULL; 331 return NULL;
336 } 332 }
337 333
338 Writer writer; 334 Writer writer;
339 char buffer[512]; 335 char buffer[512];
340 writer_init_with_stream(&writer, buf, buf_writefunc, buffer, 512); 336 writer_init_with_stream(&writer, &buf, buf_writefunc, buffer, 512);
341 337
342 WSXmlData *data = NULL; 338 WSXmlData *data = NULL;
343 if(!wsxml_write_nodes(pool, &writer, NULL, node) && !writer_flush(&writer)) { 339 if(!wsxml_write_nodes(pool, &writer, NULL, node) && !writer_flush(&writer)) {
344 data = pool_malloc(pool, sizeof(WSXmlData)); 340 data = pool_malloc(pool, sizeof(WSXmlData));
345 if(data) { 341 if(data) {
346 data->data = pool_malloc(pool, buf->size + 1); 342 data->data = pool_malloc(pool, buf.size + 1);
347 if(data->data) { 343 if(data->data) {
348 memcpy(data->data, buf->space, buf->size); 344 memcpy(data->data, buf.space, buf.size);
349 data->data[buf->size] = '\0'; 345 data->data[buf.size] = '\0';
350 data->length = buf->size; 346 data->length = buf.size;
351 data->namespaces = nslist; 347 data->namespaces = nslist;
352 } 348 }
353 } 349 }
354 } 350 }
355 351
356 ucx_buffer_free(buf); 352 cxBufferDestroy(&buf);
357 353
358 return data; 354 return data;
359 } 355 }
360 356
361 char* wsxml_nslist2string(pool_handle_t *pool, WebdavNSList *nslist) { 357 char* wsxml_nslist2string(pool_handle_t *pool, WebdavNSList *nslist) {
437 elm->namespace = ns; 433 elm->namespace = ns;
438 if(!ns) { 434 if(!ns) {
439 break; 435 break;
440 } 436 }
441 memset(ns, 0, sizeof(WSNamespace)); 437 memset(ns, 0, sizeof(WSNamespace));
442 ns->prefix = prefix_len > 0 ? (xmlChar*)sstrdup_pool(pool, sstrn(prefix, prefix_len)).ptr : NULL; 438 ns->prefix = prefix_len > 0 ? (xmlChar*)cx_strdup_pool(pool, cx_mutstrn(prefix, prefix_len)).ptr : NULL;
443 ns->href = (xmlChar*)sstrdup_pool(pool, sstrn(href, i-href_start)).ptr; 439 ns->href = (xmlChar*)cx_strdup_pool(pool, cx_mutstrn(href, i-href_start)).ptr;
444 if(list_current) { 440 if(list_current) {
445 list_current->next = elm; 441 list_current->next = elm;
446 } else { 442 } else {
447 list_start = elm; 443 list_start = elm;
448 } 444 }
501 /* 497 /*
502 * Map for all previously defined namespaces 498 * Map for all previously defined namespaces
503 * key: (char*) namespace prefix 499 * key: (char*) namespace prefix
504 * value: WSNamespace* 500 * value: WSNamespace*
505 */ 501 */
506 UcxMap *namespaces; 502 CxMap *namespaces;
507 503
508 /* 504 /*
509 * Should namespace definitions be created 505 * Should namespace definitions be created
510 */ 506 */
511 WSBool define_namespaces; 507 WSBool define_namespaces;
517 * type: 0 = element text, 1 = attribute text 513 * type: 0 = element text, 1 = attribute text
518 */ 514 */
519 static void xml_ser_text(Writer *out, int type, const char *text) { 515 static void xml_ser_text(Writer *out, int type, const char *text) {
520 size_t start = 0; 516 size_t start = 0;
521 size_t i; 517 size_t i;
522 sstr_t entityref = { NULL, 0 }; 518 cxstring entityref = { NULL, 0 };
523 for(i=0;text[i]!='\0';i++) { 519 for(i=0;text[i]!='\0';i++) {
524 char c = text[i]; 520 char c = text[i];
525 if(c == '&') { 521 if(c == '&') {
526 entityref = S("&amp;"); 522 entityref = (cxstring)CX_STR("&amp;");
527 } else if(type == 0) { 523 } else if(type == 0) {
528 if(c == '<') { 524 if(c == '<') {
529 entityref = S("&lt;"); 525 entityref = (cxstring)CX_STR("&lt;");
530 } else if(c == '>') { 526 } else if(c == '>') {
531 entityref = S("&gt;"); 527 entityref = (cxstring)CX_STR("&gt;");
532 } 528 }
533 } else { 529 } else {
534 if(c == '\"') { 530 if(c == '\"') {
535 entityref = S("&quot;"); 531 entityref = (cxstring)CX_STR("&quot;");
536 } else if(c == '\'') { 532 } else if(c == '\'') {
537 entityref = S("&apos;"); 533 entityref = (cxstring)CX_STR("&apos;");
538 } 534 }
539 } 535 }
540 536
541 if(entityref.ptr) { 537 if(entityref.ptr) {
542 size_t len = i-start; 538 size_t len = i-start;
562 Writer *out = xw->out; 558 Writer *out = xw->out;
563 writer_putc(out, '<'); 559 writer_putc(out, '<');
564 560
565 // write prefix and ':' 561 // write prefix and ':'
566 if(node->ns && node->ns->prefix) { 562 if(node->ns && node->ns->prefix) {
567 writer_puts(out, sstr((char*)node->ns->prefix)); 563 writer_puts(out, cx_str((char*)node->ns->prefix));
568 writer_putc(out, ':'); 564 writer_putc(out, ':');
569 } 565 }
570 566
571 // node name 567 // node name
572 writer_puts(out, sstr((char*)node->name)); 568 writer_puts(out, cx_str((char*)node->name));
573 569
574 // namespace definitions 570 // namespace definitions
575 if(xw->define_namespaces) { 571 if(xw->define_namespaces) {
576 xmlNs *nsdef = node->nsDef; 572 xmlNs *nsdef = node->nsDef;
577 while(nsdef) { 573 while(nsdef) {
578 // we define only namespaces without prefix or namespaces 574 // we define only namespaces without prefix or namespaces
579 // with prefix, that are not already defined 575 // with prefix, that are not already defined
580 // xw->namespaces contains all namespace, that were defined 576 // xw->namespaces contains all namespace, that were defined
581 // before xml serialization 577 // before xml serialization
582 if(!nsdef->prefix) { 578 if(!nsdef->prefix) {
583 writer_puts(out, S(" xmlns=\"")); 579 writer_put_lit(out, " xmlns=\"");
584 writer_puts(out, sstr((char*)nsdef->href)); 580 writer_put_str(out, (char*)nsdef->href);
585 writer_putc(out, '"'); 581 writer_putc (out, '"');
586 } else { 582 } else {
587 WSNamespace *n = xw->namespaces ? 583 WSNamespace *n = xw->namespaces ?
588 ucx_map_cstr_get(xw->namespaces, (char*)nsdef->prefix) : 584 cxMapGet(xw->namespaces, cx_hash_key_str((const char*)nsdef->prefix)) :
589 NULL; 585 NULL;
590 if(!n) { 586 if(!n) {
591 writer_puts(out, S(" xmlns:")); 587 writer_put_lit(out, " xmlns:");
592 writer_puts(out, sstr((char*)nsdef->prefix)); 588 writer_put_str(out, (const char*)nsdef->prefix);
593 writer_puts(out, S("=\"")); 589 writer_put_lit(out, "=\"");
594 writer_puts(out, sstr((char*)nsdef->href)); 590 writer_put_str(out, (const char*)nsdef->href);
595 writer_putc(out, '"'); 591 writer_putc (out, '"');
596 } 592 }
597 } 593 }
598 594
599 nsdef = nsdef->next; 595 nsdef = nsdef->next;
600 } 596 }
605 while(attr) { 601 while(attr) {
606 // format: ' [<prefix>:]<name>="<value>"' 602 // format: ' [<prefix>:]<name>="<value>"'
607 writer_putc(out, ' '); 603 writer_putc(out, ' ');
608 // optional namespace 604 // optional namespace
609 if(attr->ns && attr->ns->prefix) { 605 if(attr->ns && attr->ns->prefix) {
610 writer_puts(out, sstr((char*)attr->ns->prefix)); 606 writer_puts(out, cx_str((char*)attr->ns->prefix));
611 writer_putc(out, ':'); 607 writer_putc(out, ':');
612 } 608 }
613 // <name>=" 609 // <name>="
614 writer_puts(out, sstr((char*)attr->name)); 610 writer_put_str(out, (char*)attr->name);
615 writer_puts(out, S("=\"")); 611 writer_put_lit(out, "=\"");
616 // value 612 // value
617 xmlNode *value = attr->children; 613 xmlNode *value = attr->children;
618 while(value) { 614 while(value) {
619 if(value->content) { 615 if(value->content) {
620 xml_ser_text(out, 1, (const char*)value->content); 616 xml_ser_text(out, 1, (const char*)value->content);
628 } 624 }
629 625
630 if(node->children) { 626 if(node->children) {
631 writer_putc(out, '>'); 627 writer_putc(out, '>');
632 } else { 628 } else {
633 writer_puts(out, S("/>")); 629 writer_put_lit(out, "/>");
634 } 630 }
635 } 631 }
636 632
637 static int xml_ser_node_begin(xmlNode *node, void *userdata) { 633 static int xml_ser_node_begin(xmlNode *node, void *userdata) {
638 XmlWriter *xw = userdata; 634 XmlWriter *xw = userdata;
670 static int xml_ser_node_end(xmlNode *node, void *userdata) { 666 static int xml_ser_node_end(xmlNode *node, void *userdata) {
671 XmlWriter *xw = userdata; 667 XmlWriter *xw = userdata;
672 Writer *out = xw->out; 668 Writer *out = xw->out;
673 if(node->type == XML_ELEMENT_NODE) { 669 if(node->type == XML_ELEMENT_NODE) {
674 if(node->children) { 670 if(node->children) {
675 writer_puts(xw->out, S("</")); 671 writer_put_lit(xw->out, "</");
676 // write prefix and ':' 672 // write prefix and ':'
677 if(node->ns && node->ns->prefix) { 673 if(node->ns && node->ns->prefix) {
678 writer_puts(out, sstr((char*)node->ns->prefix)); 674 writer_puts(out, cx_str((char*)node->ns->prefix));
679 writer_putc(out, ':'); 675 writer_putc(out, ':');
680 } 676 }
681 // name and close tag 677 // name and close tag
682 writer_puts(out, sstr((char*)node->name)); 678 writer_puts(out, cx_str((char*)node->name));
683 writer_putc(out, '>'); 679 writer_putc(out, '>');
684 680
685 } // element was already closed in xml_ser_node_begin 681 } // element was already closed in xml_ser_node_begin
686 } 682 }
687 return 0; 683 return 0;
689 685
690 686
691 static int xml_write_nodes( 687 static int xml_write_nodes(
692 pool_handle_t *pool, 688 pool_handle_t *pool,
693 Writer *out, 689 Writer *out,
694 UcxMap *nsdefs, 690 CxMap *nsdefs,
695 WSBool createdefs, 691 WSBool createdefs,
696 xmlNode *node) 692 xmlNode *node)
697 { 693 {
698 XmlWriter xmlwriter; 694 XmlWriter xmlwriter;
699 xmlwriter.pool = pool; 695 xmlwriter.pool = pool;
717 } 713 }
718 714
719 int wsxml_write_nodes( 715 int wsxml_write_nodes(
720 pool_handle_t *pool, 716 pool_handle_t *pool,
721 Writer *out, 717 Writer *out,
722 UcxMap *nsdefs, 718 CxMap *nsdefs,
723 xmlNode *node) 719 xmlNode *node)
724 { 720 {
725 return xml_write_nodes(pool, out, nsdefs, TRUE, node); 721 return xml_write_nodes(pool, out, nsdefs, TRUE, node);
726 } 722 }
727 723

mercurial