1 /*
2
3 gg_xml.c -- XML Document implementation
4
5 version 5.0, 2020 August 1
6
7 Author: Sandro Furieri a.furieri@lqt.it
8
9 ------------------------------------------------------------------------------
10
11 Version: MPL 1.1/GPL 2.0/LGPL 2.1
12
13 The contents of this file are subject to the Mozilla Public License Version
14 1.1 (the "License"); you may not use this file except in compliance with
15 the License. You may obtain a copy of the License at
16 http://www.mozilla.org/MPL/
17
18 Software distributed under the License is distributed on an "AS IS" basis,
19 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
20 for the specific language governing rights and limitations under the
21 License.
22
23 The Original Code is the SpatiaLite library
24
25 The Initial Developer of the Original Code is Alessandro Furieri
26
27 Portions created by the Initial Developer are Copyright (C) 2008-2021
28 the Initial Developer. All Rights Reserved.
29
30 Contributor(s):
31
32 Alternatively, the contents of this file may be used under the terms of
33 either the GNU General Public License Version 2 or later (the "GPL"), or
34 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
35 in which case the provisions of the GPL or the LGPL are applicable instead
36 of those above. If you wish to allow use of your version of this file only
37 under the terms of either the GPL or the LGPL, and not to allow others to
38 use your version of this file under the terms of the MPL, indicate your
39 decision by deleting the provisions above and replace them with the notice
40 and other provisions required by the GPL or the LGPL. If you do not delete
41 the provisions above, a recipient may use your version of this file under
42 the terms of any one of the MPL, the GPL or the LGPL.
43
44 */
45
46 #include <stdlib.h>
47 #include <stdio.h>
48 #include <string.h>
49 #include <time.h>
50
51 #if defined(_WIN32) && !defined(__MINGW32__)
52 #include "config-msvc.h"
53 #else
54 #include "config.h"
55 #endif
56
57 #ifdef ENABLE_LIBXML2 /* LIBXML2 enabled: supporting XML documents */
58
59 #include <zlib.h>
60 #include <libxml/parser.h>
61 #include <libxml/xmlschemas.h>
62 #include <libxml/xpath.h>
63 #include <libxml/xpathInternals.h>
64
65 #include <spatialite_private.h>
66 #include <spatialite/sqlite.h>
67 #include <spatialite/debug.h>
68 #include <spatialite/gaiageo.h>
69 #include <spatialite/gaiaaux.h>
70
71
72 struct gaiaxml_namespace
73 {
74 /* a Namespace declaration */
75 int type;
76 xmlChar *prefix;
77 xmlChar *href;
78 struct gaiaxml_namespace *next;
79 };
80
81 struct gaiaxml_ns_list
82 {
83 /* a Namespaces list */
84 struct gaiaxml_namespace *first;
85 struct gaiaxml_namespace *last;
86 };
87
88 static int
is_valid_cache(struct splite_internal_cache * cache)89 is_valid_cache (struct splite_internal_cache *cache)
90 {
91 /* testing if the passed cache is a valid one */
92 if (cache == NULL)
93 return 0;
94 if (cache->magic1 != SPATIALITE_CACHE_MAGIC1
95 || cache->magic2 != SPATIALITE_CACHE_MAGIC2)
96 return 0;
97 return 1;
98 }
99
100 static struct gaiaxml_namespace *
splite_create_namespace(int type,const xmlChar * prefix,const xmlChar * href)101 splite_create_namespace (int type, const xmlChar * prefix, const xmlChar * href)
102 {
103 /* allocating and initializing a Namespace declaration */
104 int len;
105 struct gaiaxml_namespace *ptr = malloc (sizeof (struct gaiaxml_namespace));
106 ptr->type = type;
107 if (prefix == NULL)
108 ptr->prefix = NULL;
109 else
110 {
111 len = strlen ((const char *) prefix);
112 ptr->prefix = malloc (len + 1);
113 memcpy (ptr->prefix, prefix, len + 1);
114 }
115 if (href == NULL)
116 ptr->href = NULL;
117 else
118 {
119 len = strlen ((const char *) href);
120 ptr->href = malloc (len + 1);
121 memcpy (ptr->href, href, len + 1);
122 }
123 ptr->next = NULL;
124 return ptr;
125 }
126
127 static void
splite_free_namespace(struct gaiaxml_namespace * ptr)128 splite_free_namespace (struct gaiaxml_namespace *ptr)
129 {
130 /* memory cleanup - destroying a Namespace declaration */
131 if (ptr == NULL)
132 return;
133 if (ptr->prefix != NULL)
134 free (ptr->prefix);
135 if (ptr->href != NULL)
136 free (ptr->href);
137 free (ptr);
138 }
139
140 static struct gaiaxml_ns_list *
splite_create_ns_list(void)141 splite_create_ns_list (void)
142 {
143 /* allocating and initializing a Namespaces list */
144 struct gaiaxml_ns_list *ptr = malloc (sizeof (struct gaiaxml_ns_list));
145 ptr->first = NULL;
146 ptr->last = NULL;
147 return ptr;
148 }
149
150 static void
splite_free_ns_list(struct gaiaxml_ns_list * ptr)151 splite_free_ns_list (struct gaiaxml_ns_list *ptr)
152 {
153 /* memory cleanup - destroying a Namespaces list */
154 struct gaiaxml_namespace *p;
155 struct gaiaxml_namespace *p_n;
156 if (ptr == NULL)
157 return;
158 p = ptr->first;
159 while (p != NULL)
160 {
161 p_n = p->next;
162 splite_free_namespace (p);
163 p = p_n;
164 }
165 free (ptr);
166 }
167
168 static void
splite_add_namespace(struct gaiaxml_ns_list * list,int type,const xmlChar * prefix,const xmlChar * href)169 splite_add_namespace (struct gaiaxml_ns_list *list, int type,
170 const xmlChar * prefix, const xmlChar * href)
171 {
172 /* inserting a new Namespace into the list */
173 struct gaiaxml_namespace *ns;
174 if (list == NULL)
175 return;
176 ns = list->first;
177 while (ns != NULL)
178 {
179 /* checking if already defined */
180 int ok_type = 0;
181 int ok_prefix = 0;
182 int ok_href = 0;
183 if (ns->type == type)
184 ok_type = 1;
185 if (ns->prefix == NULL && prefix == NULL)
186 ok_prefix = 1;
187 if (ns->prefix != NULL && prefix != NULL)
188 {
189 if (strcmp ((const char *) (ns->prefix), (const char *) prefix)
190 == 0)
191 ok_prefix = 1;
192 }
193 if (ns->href == NULL && href == NULL)
194 ok_href = 1;
195 if (ns->href != NULL && href != NULL)
196 {
197 if (strcmp ((const char *) (ns->href), (const char *) href) ==
198 0)
199 ok_href = 1;
200 }
201 if (ok_type && ok_prefix && ok_href)
202 return;
203 ns = ns->next;
204 }
205 /* inserting a new Namespace */
206 ns = splite_create_namespace (type, prefix, href);
207 if (list->first == NULL)
208 list->first = ns;
209 if (list->last != NULL)
210 list->last->next = ns;
211 list->last = ns;
212 }
213
214 static void
spliteSilentError(void * ctx,const char * msg,...)215 spliteSilentError (void *ctx, const char *msg, ...)
216 {
217 /* shutting up XML Errors */
218 if (ctx != NULL)
219 ctx = NULL; /* suppressing stupid compiler warnings (unused args) */
220 if (msg != NULL)
221 ctx = NULL; /* suppressing stupid compiler warnings (unused args) */
222 }
223
224 static void
spliteParsingError(void * ctx,const char * msg,...)225 spliteParsingError (void *ctx, const char *msg, ...)
226 {
227 /* appending to the current Parsing Error buffer */
228 struct splite_internal_cache *cache = (struct splite_internal_cache *) ctx;
229 gaiaOutBufferPtr buf;
230 char out[65536];
231 va_list args;
232
233 if (ctx != NULL)
234 ctx = NULL; /* suppressing stupid compiler warnings (unused args) */
235 if (!is_valid_cache (cache))
236 return;
237 buf = (gaiaOutBufferPtr) (cache->xmlParsingErrors);
238
239 va_start (args, msg);
240 vsnprintf (out, 65536, msg, args);
241 gaiaAppendToOutBuffer (buf, out);
242 va_end (args);
243 }
244
245 static void
spliteSchemaValidationError(void * ctx,const char * msg,...)246 spliteSchemaValidationError (void *ctx, const char *msg, ...)
247 {
248 /* appending to the current SchemaValidation Error buffer */
249 struct splite_internal_cache *cache = (struct splite_internal_cache *) ctx;
250 gaiaOutBufferPtr buf;
251 char out[65536];
252 va_list args;
253
254 if (ctx != NULL)
255 ctx = NULL; /* suppressing stupid compiler warnings (unused args) */
256 if (!is_valid_cache (cache))
257 return;
258 buf = (gaiaOutBufferPtr) (cache->xmlSchemaValidationErrors);
259
260 va_start (args, msg);
261 vsnprintf (out, 65536, msg, args);
262 gaiaAppendToOutBuffer (buf, out);
263 va_end (args);
264 }
265
266 static void
spliteResetXmlErrors(struct splite_internal_cache * cache)267 spliteResetXmlErrors (struct splite_internal_cache *cache)
268 {
269 /* resetting the XML Error buffers */
270 gaiaOutBufferPtr buf;
271 if (!is_valid_cache (cache))
272 return;
273 buf = (gaiaOutBufferPtr) (cache->xmlParsingErrors);
274 gaiaOutBufferReset (buf);
275 buf = (gaiaOutBufferPtr) (cache->xmlSchemaValidationErrors);
276 gaiaOutBufferReset (buf);
277 }
278
279 GAIAGEO_DECLARE char *
gaiaXmlBlobGetLastParseError(const void * ptr)280 gaiaXmlBlobGetLastParseError (const void *ptr)
281 {
282 /* get the most recent XML Parse error/warning message */
283 struct splite_internal_cache *cache = (struct splite_internal_cache *) ptr;
284 gaiaOutBufferPtr buf;
285 if (!is_valid_cache (cache))
286 return NULL;
287 buf = (gaiaOutBufferPtr) (cache->xmlParsingErrors);
288 return buf->Buffer;
289 }
290
291 GAIAGEO_DECLARE char *
gaiaXmlBlobGetLastValidateError(const void * ptr)292 gaiaXmlBlobGetLastValidateError (const void *ptr)
293 {
294 /* get the most recent XML Validate error/warning message */
295 struct splite_internal_cache *cache = (struct splite_internal_cache *) ptr;
296 gaiaOutBufferPtr buf;
297 if (!is_valid_cache (cache))
298 return NULL;
299 buf = (gaiaOutBufferPtr) (cache->xmlSchemaValidationErrors);
300 return buf->Buffer;
301 }
302
303 GAIAGEO_DECLARE char *
gaiaXmlBlobGetLastXPathError(const void * ptr)304 gaiaXmlBlobGetLastXPathError (const void *ptr)
305 {
306 /* get the most recent XML Validate error/warning message */
307 struct splite_internal_cache *cache = (struct splite_internal_cache *) ptr;
308 gaiaOutBufferPtr buf;
309 if (!is_valid_cache (cache))
310 return NULL;
311 buf = (gaiaOutBufferPtr) (cache->xmlXPathErrors);
312 return buf->Buffer;
313 }
314
315 SPATIALITE_PRIVATE void
splite_free_xml_schema_cache_item(struct splite_xmlSchema_cache_item * p)316 splite_free_xml_schema_cache_item (struct splite_xmlSchema_cache_item *p)
317 {
318 /* freeing an XmlSchema Cache Item */
319 if (p->schemaURI)
320 free (p->schemaURI);
321 if (p->parserCtxt)
322 xmlSchemaFreeParserCtxt (p->parserCtxt);
323 if (p->schema)
324 xmlSchemaFree (p->schema);
325 if (p->schemaDoc)
326 xmlFreeDoc (p->schemaDoc);
327 p->schemaURI = NULL;
328 p->parserCtxt = NULL;
329 p->schemaDoc = NULL;
330 p->schema = NULL;
331 }
332
333 static int
splite_xmlSchemaCacheFind(struct splite_internal_cache * cache,const char * schemaURI,xmlDocPtr * schema_doc,xmlSchemaParserCtxtPtr * parser_ctxt,xmlSchemaPtr * schema)334 splite_xmlSchemaCacheFind (struct splite_internal_cache *cache,
335 const char *schemaURI, xmlDocPtr * schema_doc,
336 xmlSchemaParserCtxtPtr * parser_ctxt,
337 xmlSchemaPtr * schema)
338 {
339 /* attempting to retrieve some XmlSchema from within the Cache */
340 int i;
341 time_t now;
342 struct splite_xmlSchema_cache_item *p;
343 if (!is_valid_cache (cache))
344 return 0;
345 for (i = 0; i < MAX_XMLSCHEMA_CACHE; i++)
346 {
347 p = &(cache->xmlSchemaCache[i]);
348 if (p->schemaURI)
349 {
350 if (strcmp (schemaURI, p->schemaURI) == 0)
351 {
352 /* found a matching cache-item */
353 *schema_doc = p->schemaDoc;
354 *parser_ctxt = p->parserCtxt;
355 *schema = p->schema;
356 /* updating the timestamp */ time (&now);
357 p->timestamp = now;
358 return 1;
359 }
360 }
361 }
362 return 0;
363 }
364
365 static void
splite_xmlSchemaCacheInsert(struct splite_internal_cache * cache,const char * schemaURI,xmlDocPtr schema_doc,xmlSchemaParserCtxtPtr parser_ctxt,xmlSchemaPtr schema)366 splite_xmlSchemaCacheInsert (struct splite_internal_cache *cache,
367 const char *schemaURI, xmlDocPtr schema_doc,
368 xmlSchemaParserCtxtPtr parser_ctxt,
369 xmlSchemaPtr schema)
370 {
371 /* inserting a new XmlSchema item into the Cache */
372 int i;
373 int len = strlen (schemaURI);
374 time_t now;
375 time_t oldest;
376 struct splite_xmlSchema_cache_item *pSlot = NULL;
377 struct splite_xmlSchema_cache_item *p;
378 if (!is_valid_cache (cache))
379 return;
380 time (&now);
381 oldest = now;
382 for (i = 0; i < MAX_XMLSCHEMA_CACHE; i++)
383 {
384 p = &(cache->xmlSchemaCache[i]);
385 if (p->schemaURI == NULL)
386 {
387 /* found an empty slot */
388 pSlot = p;
389 break;
390 }
391 if (p->timestamp < oldest)
392 {
393 /* saving the oldest slot */
394 pSlot = p;
395 oldest = p->timestamp;
396 }
397 }
398 /* inserting into the Cache Slot */
399 splite_free_xml_schema_cache_item (pSlot);
400 pSlot->timestamp = now;
401 pSlot->schemaURI = malloc (len + 1);
402 strcpy (pSlot->schemaURI, schemaURI);
403 pSlot->schemaDoc = schema_doc;
404 pSlot->parserCtxt = parser_ctxt;
405 pSlot->schema = schema;
406 }
407
408 static void
sniff_sld_payload(xmlNodePtr node,int * layers,int * point,int * line,int * polygon,int * raster)409 sniff_sld_payload (xmlNodePtr node, int *layers, int *point, int *line,
410 int *polygon, int *raster)
411 {
412 /* recursively sniffing a generic SLD payload type */
413
414 while (node)
415 {
416 if (node->type == XML_ELEMENT_NODE)
417 {
418 const char *name = (const char *) (node->name);
419 if (strcmp (name, "FeatureTypeStyle") == 0)
420 *layers += 1;
421 if (strcmp (name, "CoverageStyle") == 0)
422 *layers += 1;
423 if (strcmp (name, "PointSymbolizer") == 0)
424 *point += 1;
425 if (strcmp (name, "LineSymbolizer") == 0)
426 *line += 1;
427 if (strcmp (name, "PolygonSymbolizer") == 0)
428 *polygon += 1;
429 if (strcmp (name, "RasterSymbolizer") == 0)
430 *raster += 1;
431 }
432 sniff_sld_payload (node->children, layers, point, line, polygon,
433 raster);
434 node = node->next;
435 }
436 }
437
438 static void
sniff_payload(xmlDocPtr xml_doc,int * is_iso_metadata,int * is_sld_se_vector_style,int * is_sld_se_raster_style,int * is_sld_style,int * is_svg,int * is_gpx,int * is_map_config)439 sniff_payload (xmlDocPtr xml_doc, int *is_iso_metadata,
440 int *is_sld_se_vector_style, int *is_sld_se_raster_style,
441 int *is_sld_style, int *is_svg, int *is_gpx, int *is_map_config)
442 {
443 /* sniffing the payload type */
444 xmlNodePtr root = xmlDocGetRootElement (xml_doc);
445 *is_iso_metadata = 0;
446 *is_sld_se_vector_style = 0;
447 *is_sld_se_raster_style = 0;
448 *is_svg = 0;
449 *is_gpx = 0;
450 if (root->name != NULL)
451 {
452 const char *name = (const char *) (root->name);
453 if (strcmp (name, "MD_Metadata") == 0)
454 *is_iso_metadata = 1;
455 if (strcmp (name, "FeatureTypeStyle") == 0
456 || strcmp (name, "PointSymbolizer") == 0
457 || strcmp (name, "LineSymbolizer") == 0
458 || strcmp (name, "PolygonSymbolizer") == 0
459 || strcmp (name, "TextSymbolizer") == 0)
460 *is_sld_se_vector_style = 1;
461 if (strcmp (name, "RasterSymbolizer") == 0
462 || strcmp (name, "CoverageStyle") == 0)
463 *is_sld_se_raster_style = 1;
464 if (strcmp (name, "StyledLayerDescriptor") == 0)
465 {
466 /* sniffing an SLD (1.0.0 ??) payload */
467 int layers = 0;
468 int point = 0;
469 int line = 0;
470 int polygon = 0;
471 int raster = 0;
472 xmlNodePtr node = xmlDocGetRootElement (xml_doc);
473 sniff_sld_payload (node, &layers, &point, &line, &polygon,
474 &raster);
475 if (layers == 1 && point == 0 && line == 0 && polygon == 0
476 && raster == 1)
477 {
478 /* raster style */
479 *is_sld_se_raster_style = 1;
480 }
481 if (layers == 1 && (point > 0 || line > 0 || polygon > 0)
482 && raster == 0)
483 {
484 /* vector style */
485 *is_sld_se_vector_style = 1;
486 }
487 *is_sld_style = 1;
488 }
489 if (strcmp (name, "svg") == 0)
490 *is_svg = 1;
491 if (strcmp (name, "gpx") == 0)
492 *is_gpx = 1;
493 if (strcmp (name, "RL2MapConfig") == 0)
494 *is_map_config = 1;
495 }
496 }
497
498 static void
find_iso_ids(xmlNodePtr node,const char * name,char ** string,int * open_tag,int * char_string,int * count)499 find_iso_ids (xmlNodePtr node, const char *name, char **string, int *open_tag,
500 int *char_string, int *count)
501 {
502 /* recursively scanning the DOM tree [fileIdentifier or parentIdentifier] */
503 xmlNode *cur_node = NULL;
504 int open = 0;
505 int cs = 0;
506
507 for (cur_node = node; cur_node; cur_node = cur_node->next)
508 {
509 if (cur_node->type == XML_ELEMENT_NODE)
510 {
511 const char *xname = (const char *) (cur_node->name);
512 if (*open_tag == 1)
513 {
514 if (strcmp (xname, "CharacterString") == 0)
515 {
516 cs = 1;
517 *char_string = 1;
518 }
519 }
520 if (strcmp (xname, name) == 0)
521 {
522 if (cur_node->parent != NULL)
523 {
524 if (cur_node->parent->type == XML_ELEMENT_NODE)
525 {
526 if (strcmp
527 ((const char *) (cur_node->parent->name),
528 "MD_Metadata") == 0)
529 {
530 /*
531 / only if <MD_Metadata>
532 / <fileIdentifier>
533 / <CharacterString>
534 */
535 open = 1;
536 *open_tag = 1;
537 }
538 }
539 }
540 }
541 }
542 if (cur_node->type == XML_TEXT_NODE && *open_tag == 1
543 && *char_string == 1)
544 {
545 if (cur_node->content != NULL)
546 {
547 int len = strlen ((const char *) cur_node->content);
548 char *buf = malloc (len + 1);
549 strcpy (buf, (const char *) cur_node->content);
550 if (*string)
551 free (*string);
552 *string = buf;
553 *count += 1;
554 }
555 }
556
557 find_iso_ids (cur_node->children, name, string, open_tag, char_string,
558 count);
559 if (open)
560 *open_tag = 0;
561 if (cs)
562 *char_string = 0;
563 }
564 }
565
566 static void
find_iso_title(xmlNodePtr node,char ** string,int * open_tag,int * char_string,int * count)567 find_iso_title (xmlNodePtr node, char **string, int *open_tag, int *char_string,
568 int *count)
569 {
570 /* recursively scanning the DOM tree [title] */
571 xmlNode *cur_node = NULL;
572 xmlNode *parent;
573 int open = 0;
574 int cs = 0;
575 int ok_parent;
576
577 for (cur_node = node; cur_node; cur_node = cur_node->next)
578 {
579 if (cur_node->type == XML_ELEMENT_NODE)
580 {
581 if (*open_tag == 1)
582 {
583 if (strcmp
584 ((const char *) (cur_node->name),
585 "CharacterString") == 0)
586 {
587 cs = 1;
588 *char_string = 1;
589 }
590 }
591 if (strcmp ((const char *) (cur_node->name), "title") == 0)
592 {
593 ok_parent = 0;
594 parent = cur_node->parent;
595 if (parent)
596 {
597 if (strcmp
598 ((const char *) (parent->name),
599 "CI_Citation") == 0)
600 ok_parent++;
601 }
602 if (ok_parent == 1)
603 {
604 parent = parent->parent;
605 if (strcmp
606 ((const char *) (parent->name),
607 "citation") == 0)
608 ok_parent++;
609 }
610 if (ok_parent == 2)
611 {
612 parent = parent->parent;
613 if (strcmp
614 ((const char *) (parent->name),
615 "MD_DataIdentification") == 0)
616 ok_parent++;
617 }
618 if (ok_parent == 3)
619 {
620 parent = parent->parent;
621 if (strcmp
622 ((const char *) (parent->name),
623 "identificationInfo") == 0)
624 ok_parent++;
625 }
626 if (ok_parent == 4)
627 {
628 parent = parent->parent;
629 if (strcmp
630 ((const char *) (parent->name),
631 "MD_Metadata") == 0)
632 ok_parent++;
633 }
634 if (ok_parent == 5)
635 {
636 /*
637 / only if <MD_Metadata>
638 / <identificationInfo>
639 / <MD_DataIdentification>
640 / <citation>
641 / <CI_Citation>
642 / <title>
643 */
644 open = 1;
645 *open_tag = 1;
646 }
647 }
648 }
649 if (cur_node->type == XML_TEXT_NODE && *open_tag == 1
650 && *char_string == 1)
651 {
652 if (cur_node->content != NULL)
653 {
654 int len = strlen ((const char *) cur_node->content);
655 char *buf = malloc (len + 1);
656 strcpy (buf, (const char *) cur_node->content);
657 if (*string)
658 free (*string);
659 *string = buf;
660 *count += 1;
661 }
662 }
663
664 find_iso_title (cur_node->children, string, open_tag, char_string,
665 count);
666 if (open)
667 *open_tag = 0;
668 if (cs)
669 *char_string = 0;
670 }
671 }
672
673 static void
find_iso_abstract(xmlNodePtr node,char ** string,int * open_tag,int * char_string,int * count)674 find_iso_abstract (xmlNodePtr node, char **string, int *open_tag,
675 int *char_string, int *count)
676 {
677 /* recursively scanning the DOM abstract [title] */
678 xmlNode *cur_node = NULL;
679 xmlNode *parent;
680 int open = 0;
681 int cs = 0;
682 int ok_parent;
683
684 for (cur_node = node; cur_node; cur_node = cur_node->next)
685 {
686 if (cur_node->type == XML_ELEMENT_NODE)
687 {
688 if (*open_tag == 1)
689 {
690 if (strcmp
691 ((const char *) (cur_node->name),
692 "CharacterString") == 0)
693 {
694 cs = 1;
695 *char_string = 1;
696 }
697 }
698 if (strcmp ((const char *) (cur_node->name), "abstract") == 0)
699 {
700 ok_parent = 0;
701 parent = cur_node->parent;
702 if (parent)
703 {
704 if (strcmp
705 ((const char *) (parent->name),
706 "MD_DataIdentification") == 0)
707 ok_parent++;
708 }
709 if (ok_parent == 1)
710 {
711 parent = parent->parent;
712 if (strcmp
713 ((const char *) (parent->name),
714 "identificationInfo") == 0)
715 ok_parent++;
716 }
717 if (ok_parent == 2)
718 {
719 parent = parent->parent;
720 if (strcmp
721 ((const char *) (parent->name),
722 "MD_Metadata") == 0)
723 ok_parent++;
724 }
725 if (ok_parent == 3)
726 {
727 /* only if <MD_Metadata>
728 / <identificationInfo>
729 / <MD_DataIdentification>
730 / <abstract>
731 */
732 open = 1;
733 *open_tag = 1;
734 }
735 }
736 }
737 if (cur_node->type == XML_TEXT_NODE && *open_tag == 1
738 && *char_string == 1)
739 {
740 if (cur_node->content != NULL)
741 {
742 int len = strlen ((const char *) cur_node->content);
743 char *buf = malloc (len + 1);
744 strcpy (buf, (const char *) cur_node->content);
745 if (*string)
746 free (*string);
747 *string = buf;
748 *count += 1;
749 }
750 }
751
752 find_iso_abstract (cur_node->children, string, open_tag, char_string,
753 count);
754 if (open)
755 *open_tag = 0;
756 if (cs)
757 *char_string = 0;
758 }
759 }
760
761 static void
find_bbox_coord(xmlNodePtr node,const char * name,double * coord,int * open_tag,int * decimal,int * count)762 find_bbox_coord (xmlNodePtr node, const char *name, double *coord,
763 int *open_tag, int *decimal, int *count)
764 {
765 /* recursively scanning an EX_GeographicBoundingBox sub-tree */
766 xmlNode *cur_node = NULL;
767 int open = 0;
768 int dec = 0;
769
770 for (cur_node = node; cur_node; cur_node = cur_node->next)
771 {
772 if (cur_node->type == XML_ELEMENT_NODE)
773 {
774 if (*open_tag == 1)
775 {
776 if (strcmp ((const char *) (cur_node->name), "Decimal") ==
777 0)
778 {
779 dec = 1;
780 *decimal = 1;
781 }
782 }
783 if (strcmp ((const char *) (cur_node->name), name) == 0)
784 {
785 open = 1;
786 *open_tag = 1;
787 }
788 }
789 if (cur_node->type == XML_TEXT_NODE && *open_tag == 1
790 && *decimal == 1)
791 {
792 if (cur_node->content != NULL)
793 {
794 /* found a coord value */
795 double value = atof ((const char *) cur_node->content);
796 *coord = value;
797 *count += 1;
798 }
799 }
800
801 find_bbox_coord (cur_node->children, name, coord, open_tag, decimal,
802 count);
803 if (open)
804 *open_tag = 0;
805 if (dec)
806 *decimal = 0;
807 }
808 }
809
810 static int
parse_bounding_box(xmlNodePtr node,double * minx,double * miny,double * maxx,double * maxy)811 parse_bounding_box (xmlNodePtr node, double *minx, double *miny, double *maxx,
812 double *maxy)
813 {
814 /* attempting to parse an EX_GeographicBoundingBox sub-tree */
815 int ok_minx = 0;
816 int ok_miny = 0;
817 int ok_maxx = 0;
818 int ok_maxy = 0;
819 int open_tag;
820 int decimal;
821 int count;
822 double coord;
823
824 /* retrieving minx - West */
825 open_tag = 0;
826 decimal = 0;
827 count = 0;
828 find_bbox_coord (node, "westBoundLongitude", &coord, &open_tag, &decimal,
829 &count);
830 if (count == 1)
831 {
832 *minx = coord;
833 ok_minx = 1;
834 }
835
836 /* retrieving maxx - East */
837 open_tag = 0;
838 decimal = 0;
839 count = 0;
840 find_bbox_coord (node, "eastBoundLongitude", &coord, &open_tag, &decimal,
841 &count);
842 if (count == 1)
843 {
844 *maxx = coord;
845 ok_maxx = 1;
846 }
847
848 /* retrieving miny - South */
849 open_tag = 0;
850 decimal = 0;
851 count = 0;
852 find_bbox_coord (node, "southBoundLatitude", &coord, &open_tag, &decimal,
853 &count);
854 if (count == 1)
855 {
856 *miny = coord;
857 ok_miny = 1;
858 }
859
860 /* retrieving maxy - North */
861 open_tag = 0;
862 decimal = 0;
863 count = 0;
864 find_bbox_coord (node, "northBoundLatitude", &coord, &open_tag, &decimal,
865 &count);
866 if (count == 1)
867 {
868 *maxy = coord;
869 ok_maxy = 1;
870 }
871
872 if (ok_minx && ok_miny && ok_maxx && ok_maxy)
873 {
874 /* ok, valid BBOX */
875 return 1;
876 }
877 return 0;
878 }
879
880 static void
find_iso_geometry(xmlNodePtr node,gaiaGeomCollPtr * geom)881 find_iso_geometry (xmlNodePtr node, gaiaGeomCollPtr * geom)
882 {
883 /* recursively scanning the DOM tree [geometry] */
884 xmlNode *cur_node = NULL;
885 xmlNode *parent;
886 int ok_parent;
887
888 for (cur_node = node; cur_node; cur_node = cur_node->next)
889 {
890 if (cur_node->type == XML_ELEMENT_NODE)
891 {
892 if (strcmp
893 ((const char *) (cur_node->name),
894 "EX_GeographicBoundingBox") == 0)
895 {
896 ok_parent = 0;
897 parent = cur_node->parent;
898 if (parent)
899 {
900 if (strcmp
901 ((const char *) (parent->name),
902 "geographicElement") == 0)
903 ok_parent++;
904 }
905 if (ok_parent == 1)
906 {
907 parent = parent->parent;
908 if (strcmp
909 ((const char *) (parent->name),
910 "EX_Extent") == 0)
911 ok_parent++;
912 }
913 if (ok_parent == 2)
914 {
915 parent = parent->parent;
916 if (strcmp ((const char *) (parent->name), "extent")
917 == 0)
918 ok_parent++;
919 }
920 if (ok_parent == 3)
921 {
922 parent = parent->parent;
923 if (strcmp
924 ((const char *) (parent->name),
925 "MD_DataIdentification") == 0)
926 ok_parent++;
927 }
928 if (ok_parent == 4)
929 {
930 parent = parent->parent;
931 if (strcmp
932 ((const char *) (parent->name),
933 "identificationInfo") == 0)
934 ok_parent++;
935 }
936 if (ok_parent == 5)
937 {
938 parent = parent->parent;
939 if (strcmp
940 ((const char *) (parent->name),
941 "MD_Metadata") == 0)
942 ok_parent++;
943 }
944 if (ok_parent == 6)
945 {
946 /* only if <MD_Metadata>
947 / <identificationInfo>
948 / <MD_DataIdentification>
949 / <extent>
950 / <EX_Extent>
951 / <geographicElement>
952 / <EX_GeographicBoundingBox>
953 */
954 double minx = 0.0;
955 double maxx = 0.0;
956 double miny = 0.0;
957 double maxy = 0.0;
958 if (parse_bounding_box
959 (cur_node, &minx, &miny, &maxx, &maxy))
960 {
961 gaiaPolygonPtr pg;
962 gaiaRingPtr rng;
963 gaiaGeomCollPtr g = *geom;
964 if (g == NULL)
965 {
966 g = gaiaAllocGeomColl ();
967 g->Srid = 4326;
968 g->DeclaredType = GAIA_MULTIPOLYGON;
969 }
970 pg = gaiaAddPolygonToGeomColl (g, 5, 0);
971 rng = pg->Exterior;
972 gaiaSetPoint (rng->Coords, 0, minx, miny);
973 gaiaSetPoint (rng->Coords, 1, maxx, miny);
974 gaiaSetPoint (rng->Coords, 2, maxx, maxy);
975 gaiaSetPoint (rng->Coords, 3, minx, maxy);
976 gaiaSetPoint (rng->Coords, 4, minx, miny);
977 *geom = g;
978 }
979 }
980 }
981 }
982 find_iso_geometry (cur_node->children, geom);
983 }
984 }
985
986 static void
retrieve_iso_identifiers(xmlDocPtr xml_doc,char ** fileIdentifier,char ** parentIdentifier,char ** title,char ** abstract,unsigned char ** geometry,short * geometry_len)987 retrieve_iso_identifiers (xmlDocPtr xml_doc, char **fileIdentifier,
988 char **parentIdentifier, char **title,
989 char **abstract, unsigned char **geometry,
990 short *geometry_len)
991 {
992 /*
993 / attempting to retrieve the FileIdentifier, ParentIdentifier,
994 / Title, Abstract and Geometry items from an ISO Metadata document
995 */
996 xmlNodePtr root = xmlDocGetRootElement (xml_doc);
997 int open_tag;
998 int char_string;
999 int count;
1000 char *string;
1001 gaiaGeomCollPtr geom = NULL;
1002
1003 *fileIdentifier = NULL;
1004 *parentIdentifier = NULL;
1005 *title = NULL;
1006 *abstract = NULL;
1007 *geometry = NULL;
1008
1009 /* attempting to retrieve the FileIdentifier item */
1010 open_tag = 0;
1011 char_string = 0;
1012 count = 0;
1013 string = NULL;
1014 find_iso_ids (root, "fileIdentifier", &string, &open_tag, &char_string,
1015 &count);
1016 if (string)
1017 {
1018 if (count == 1)
1019 *fileIdentifier = string;
1020 else
1021 free (string);
1022 }
1023
1024 /* attempting to retrieve the ParentIdentifier item */
1025 open_tag = 0;
1026 char_string = 0;
1027 count = 0;
1028 string = NULL;
1029 find_iso_ids (root, "parentIdentifier", &string, &open_tag, &char_string,
1030 &count);
1031 if (string)
1032 {
1033 if (count == 1)
1034 *parentIdentifier = string;
1035 else
1036 free (string);
1037 }
1038
1039 /* attempting to retrieve the Title item */
1040 open_tag = 0;
1041 char_string = 0;
1042 count = 0;
1043 string = NULL;
1044 find_iso_title (root, &string, &open_tag, &char_string, &count);
1045 if (string)
1046 {
1047 if (count == 1)
1048 *title = string;
1049 else
1050 free (string);
1051 }
1052
1053 /* attempting to retrieve the Abstract item */
1054 open_tag = 0;
1055 char_string = 0;
1056 count = 0;
1057 string = NULL;
1058 find_iso_abstract (root, &string, &open_tag, &char_string, &count);
1059 if (string)
1060 {
1061 if (count == 1)
1062 *abstract = string;
1063 else
1064 free (string);
1065 }
1066
1067 /* attempting to retrieve the Geometry item */
1068 open_tag = 0;
1069 char_string = 0;
1070 count = 0;
1071 string = NULL;
1072 find_iso_geometry (root, &geom);
1073 if (geom)
1074 {
1075 int blob_len;
1076 unsigned char *blob = NULL;
1077 gaiaMbrGeometry (geom);
1078 gaiaToSpatiaLiteBlobWkb (geom, &blob, &blob_len);
1079 gaiaFreeGeomColl (geom);
1080 *geometry = blob;
1081 *geometry_len = (short) blob_len;
1082 }
1083 }
1084
1085 static void
find_sld_name(xmlNodePtr node,char ** string)1086 find_sld_name (xmlNodePtr node, char **string)
1087 {
1088 /* recursively scanning the DOM tree [name] */
1089 while (node)
1090 {
1091 if (node->type == XML_ELEMENT_NODE)
1092 {
1093 const char *name = (const char *) (node->name);
1094 if (strcmp (name, "Name") == 0)
1095 {
1096 xmlNodePtr child = node->children;
1097 if (child)
1098 {
1099 if (child->type == XML_TEXT_NODE)
1100 {
1101 int len;
1102 const char *value =
1103 (const char *) (child->content);
1104 len = strlen (value);
1105 if (*string != NULL)
1106 free (*string);
1107 *string = malloc (len + 1);
1108 strcpy (*string, value);
1109 }
1110 }
1111 }
1112 }
1113 node = node->next;
1114 }
1115 }
1116
1117 static void
find_sld_title(xmlNodePtr node,char ** string)1118 find_sld_title (xmlNodePtr node, char **string)
1119 {
1120 /* recursively scanning the DOM tree [title] */
1121 while (node)
1122 {
1123 if (node->type == XML_ELEMENT_NODE)
1124 {
1125 const char *name = (const char *) (node->name);
1126 if (strcmp (name, "Title") == 0)
1127 {
1128 xmlNodePtr child = node->children;
1129 if (child)
1130 {
1131 if (child->type == XML_TEXT_NODE)
1132 {
1133 int len;
1134 const char *value =
1135 (const char *) (child->content);
1136 len = strlen (value);
1137 if (*string != NULL)
1138 free (*string);
1139 *string = malloc (len + 1);
1140 strcpy (*string, value);
1141 }
1142 }
1143 }
1144 if (strcmp (name, "Description") == 0)
1145 find_sld_title (node->children, string);
1146 }
1147 node = node->next;
1148 }
1149 }
1150
1151 static void
find_sld_abstract(xmlNodePtr node,char ** string)1152 find_sld_abstract (xmlNodePtr node, char **string)
1153 {
1154 /* recursively scanning the DOM tree [abstract] */
1155 while (node)
1156 {
1157 if (node->type == XML_ELEMENT_NODE)
1158 {
1159 const char *name = (const char *) (node->name);
1160 if (strcmp (name, "Abstract") == 0)
1161 {
1162 xmlNodePtr child = node->children;
1163 if (child)
1164 {
1165 if (child->type == XML_TEXT_NODE)
1166 {
1167 int len;
1168 const char *value =
1169 (const char *) (child->content);
1170 len = strlen (value);
1171 if (*string != NULL)
1172 free (*string);
1173 *string = malloc (len + 1);
1174 strcpy (*string, value);
1175 }
1176 }
1177 }
1178 if (strcmp (name, "Description") == 0)
1179 find_sld_abstract (node->children, string);
1180 }
1181 node = node->next;
1182 }
1183 }
1184
1185 static void
retrieve_sld_identifiers(xmlDocPtr xml_doc,char ** name,char ** title,char ** abstract)1186 retrieve_sld_identifiers (xmlDocPtr xml_doc, char **name, char **title,
1187 char **abstract)
1188 {
1189 /*
1190 / attempting to retrieve the Name, Title and Abstract items
1191 / from an SLD Style document
1192 */
1193 xmlNodePtr root = xmlDocGetRootElement (xml_doc);
1194 char *string;
1195 const char *xname = (const char *) (root->name);
1196
1197 *name = NULL;
1198 *title = NULL;
1199 *abstract = NULL;
1200
1201 if (xname != NULL)
1202 {
1203 if (strcmp (xname, "StyledLayerDescriptor") != 0)
1204 return;
1205 }
1206
1207 /* attempting to retrieve the Name item */
1208 string = NULL;
1209 find_sld_name (root->children, &string);
1210 if (string)
1211 *name = string;
1212
1213 /* attempting to retrieve the Title item */
1214 string = NULL;
1215 find_sld_title (root->children, &string);
1216 if (string)
1217 *title = string;
1218
1219 /* attempting to retrieve the Abstract item */
1220 string = NULL;
1221 find_sld_abstract (root->children, &string);
1222 if (string)
1223 *abstract = string;
1224 }
1225
1226 static void
find_sld_se_name(xmlNodePtr node,char ** string,int * style,int * rule)1227 find_sld_se_name (xmlNodePtr node, char **string, int *style, int *rule)
1228 {
1229 /* recursively scanning the DOM tree [name] */
1230 int is_style = 0;
1231 int is_rule = 0;
1232 while (node)
1233 {
1234 if (node->type == XML_ELEMENT_NODE)
1235 {
1236 const char *name = (const char *) (node->name);
1237 if (strcmp (name, "FeatureTypeStyle") == 0
1238 || strcmp (name, "CoverageStyle") == 0)
1239 {
1240 is_style = 1;
1241 *style = 1;
1242 }
1243 if (strcmp (name, "Rule") == 0)
1244 {
1245 is_rule = 1;
1246 *rule = 1;
1247 }
1248 if (strcmp (name, "Name") == 0)
1249 {
1250 if (*style == 1 && *rule == 0)
1251 {
1252 xmlNodePtr child = node->children;
1253 if (child)
1254 {
1255 if (child->type == XML_TEXT_NODE)
1256 {
1257 int len;
1258 const char *value =
1259 (const char *) (child->content);
1260 len = strlen (value);
1261 if (*string != NULL)
1262 free (*string);
1263 *string = malloc (len + 1);
1264 strcpy (*string, value);
1265 }
1266 }
1267 }
1268 }
1269 }
1270
1271 find_sld_se_name (node->children, string, style, rule);
1272 if (is_style)
1273 *style = 0;
1274 if (is_rule)
1275 *rule = 0;
1276 node = node->next;
1277 }
1278 }
1279
1280 static void
find_sld_se_title(xmlNodePtr node,char ** string,int * style,int * rule)1281 find_sld_se_title (xmlNodePtr node, char **string, int *style, int *rule)
1282 {
1283 /* recursively scanning the DOM tree [title] */
1284 int is_style = 0;
1285 int is_rule = 0;
1286 while (node)
1287 {
1288 if (node->type == XML_ELEMENT_NODE)
1289 {
1290 const char *name = (const char *) (node->name);
1291 if (strcmp (name, "FeatureTypeStyle") == 0
1292 || strcmp (name, "CoverageStyle") == 0)
1293 {
1294 is_style = 1;
1295 *style = 1;
1296 }
1297 if (strcmp (name, "Rule") == 0)
1298 {
1299 is_rule = 1;
1300 *rule = 1;
1301 }
1302 if (strcmp (name, "Title") == 0)
1303 {
1304 if (*style == 1 && *rule == 0)
1305 {
1306 xmlNodePtr child = node->children;
1307 if (child)
1308 {
1309 if (child->type == XML_TEXT_NODE)
1310 {
1311 int len;
1312 const char *value =
1313 (const char *) (child->content);
1314 len = strlen (value);
1315 if (*string != NULL)
1316 free (*string);
1317 *string = malloc (len + 1);
1318 strcpy (*string, value);
1319 }
1320 }
1321 }
1322 }
1323 }
1324
1325 find_sld_se_title (node->children, string, style, rule);
1326 if (is_style)
1327 *style = 0;
1328 if (is_rule)
1329 *rule = 0;
1330 node = node->next;
1331 }
1332 }
1333
1334 static void
find_sld_se_abstract(xmlNodePtr node,char ** string,int * style,int * rule)1335 find_sld_se_abstract (xmlNodePtr node, char **string, int *style, int *rule)
1336 {
1337 /* recursively scanning the DOM tree [abstract] */
1338 int is_style = 0;
1339 int is_rule = 0;
1340 while (node)
1341 {
1342 if (node->type == XML_ELEMENT_NODE)
1343 {
1344 const char *name = (const char *) (node->name);
1345 if (strcmp (name, "FeatureTypeStyle") == 0
1346 || strcmp (name, "CoverageStyle") == 0)
1347 {
1348 is_style = 1;
1349 *style = 1;
1350 }
1351 if (strcmp (name, "Rule") == 0)
1352 {
1353 is_rule = 1;
1354 *rule = 1;
1355 }
1356 if (strcmp (name, "Abstract") == 0)
1357 {
1358 if (*style == 1 && *rule == 0)
1359 {
1360 xmlNodePtr child = node->children;
1361 if (child)
1362 {
1363 if (child->type == XML_TEXT_NODE)
1364 {
1365 int len;
1366 const char *value =
1367 (const char *) (child->content);
1368 len = strlen (value);
1369 if (*string != NULL)
1370 free (*string);
1371 *string = malloc (len + 1);
1372 strcpy (*string, value);
1373 }
1374 }
1375 }
1376 }
1377 }
1378
1379 find_sld_se_abstract (node->children, string, style, rule);
1380 if (is_style)
1381 *style = 0;
1382 if (is_rule)
1383 *rule = 0;
1384 node = node->next;
1385 }
1386 }
1387
1388 static void
retrieve_sld_se_identifiers(xmlDocPtr xml_doc,char ** name,char ** title,char ** abstract)1389 retrieve_sld_se_identifiers (xmlDocPtr xml_doc, char **name, char **title,
1390 char **abstract)
1391 {
1392 /*
1393 / attempting to retrieve the Name, Title and Abstract items
1394 / from an SLD/SE Style document
1395 */
1396 xmlNodePtr root = xmlDocGetRootElement (xml_doc);
1397 int style;
1398 int rule;
1399 char *string;
1400 const char *xname = (const char *) (root->name);
1401
1402 *name = NULL;
1403 *title = NULL;
1404 *abstract = NULL;
1405
1406 /* attempting to retrieve the Name item */
1407 style = 0;
1408 rule = 0;
1409 string = NULL;
1410 if (xname != NULL)
1411 {
1412 if (strcmp (xname, "PointSymbolizer") == 0
1413 || strcmp (xname, "LineSymbolizer") == 0
1414 || strcmp (xname, "PolygonSymbolizer") == 0
1415 || strcmp (xname, "TextSymbolizer") == 0
1416 || strcmp (xname, "RasterSymbolizer") == 0)
1417 style = 1;
1418 }
1419 find_sld_se_name (root, &string, &style, &rule);
1420 if (string)
1421 *name = string;
1422
1423 /* attempting to retrieve the Title item */
1424 style = 0;
1425 rule = 0;
1426 string = NULL;
1427 if (xname != NULL)
1428 {
1429 if (strcmp (xname, "PointSymbolizer") == 0
1430 || strcmp (xname, "LineSymbolizer") == 0
1431 || strcmp (xname, "PolygonSymbolizer") == 0
1432 || strcmp (xname, "TextSymbolizer") == 0
1433 || strcmp (xname, "RasterSymbolizer") == 0)
1434 style = 1;
1435 }
1436 find_sld_se_title (root, &string, &style, &rule);
1437 if (string)
1438 *title = string;
1439
1440 /* attempting to retrieve the Abstract item */
1441 style = 0;
1442 rule = 0;
1443 string = NULL;
1444 if (xname != NULL)
1445 {
1446 if (strcmp (xname, "PointSymbolizer") == 0
1447 || strcmp (xname, "LineSymbolizer") == 0
1448 || strcmp (xname, "PolygonSymbolizer") == 0
1449 || strcmp (xname, "TextSymbolizer") == 0
1450 || strcmp (xname, "RasterSymbolizer") == 0)
1451 style = 1;
1452 }
1453 find_sld_se_abstract (root, &string, &style, &rule);
1454 if (string)
1455 *abstract = string;
1456 }
1457
1458 static void
find_map_config_name(xmlNodePtr node,char ** string)1459 find_map_config_name (xmlNodePtr node, char **string)
1460 {
1461 /* recursively scanning the DOM tree [name] */
1462 while (node)
1463 {
1464 if (node->type == XML_ELEMENT_NODE)
1465 {
1466 const char *name = (const char *) (node->name);
1467 if (strcmp (name, "Name") == 0)
1468 {
1469 xmlNodePtr child = node->children;
1470 if (child)
1471 {
1472 if (child->type == XML_TEXT_NODE)
1473 {
1474 int len;
1475 const char *value =
1476 (const char *) (child->content);
1477 len = strlen (value);
1478 if (*string != NULL)
1479 free (*string);
1480 *string = malloc (len + 1);
1481 strcpy (*string, value);
1482 }
1483 }
1484 }
1485 }
1486 node = node->next;
1487 }
1488 }
1489
1490 static void
find_map_config_title(xmlNodePtr node,char ** string)1491 find_map_config_title (xmlNodePtr node, char **string)
1492 {
1493 /* recursively scanning the DOM tree [title] */
1494 while (node)
1495 {
1496 if (node->type == XML_ELEMENT_NODE)
1497 {
1498 const char *name = (const char *) (node->name);
1499 if (strcmp (name, "Title") == 0)
1500 {
1501 xmlNodePtr child = node->children;
1502 if (child)
1503 {
1504 if (child->type == XML_TEXT_NODE)
1505 {
1506 int len;
1507 const char *value =
1508 (const char *) (child->content);
1509 len = strlen (value);
1510 if (*string != NULL)
1511 free (*string);
1512 *string = malloc (len + 1);
1513 strcpy (*string, value);
1514 }
1515 }
1516 }
1517 if (strcmp (name, "Description") == 0)
1518 find_map_config_title (node->children, string);
1519 }
1520 node = node->next;
1521 }
1522 }
1523
1524 static void
find_map_config_abstract(xmlNodePtr node,char ** string)1525 find_map_config_abstract (xmlNodePtr node, char **string)
1526 {
1527 /* recursively scanning the DOM tree [abstract] */
1528 while (node)
1529 {
1530 if (node->type == XML_ELEMENT_NODE)
1531 {
1532 const char *name = (const char *) (node->name);
1533 if (strcmp (name, "Abstract") == 0)
1534 {
1535 xmlNodePtr child = node->children;
1536 if (child)
1537 {
1538 if (child->type == XML_TEXT_NODE)
1539 {
1540 int len;
1541 const char *value =
1542 (const char *) (child->content);
1543 len = strlen (value);
1544 if (*string != NULL)
1545 free (*string);
1546 *string = malloc (len + 1);
1547 strcpy (*string, value);
1548 }
1549 }
1550 }
1551 if (strcmp (name, "Description") == 0)
1552 find_map_config_abstract (node->children, string);
1553 }
1554 node = node->next;
1555 }
1556 }
1557
1558 static void
retrieve_map_config_identifiers(xmlDocPtr xml_doc,char ** name,char ** title,char ** abstract)1559 retrieve_map_config_identifiers (xmlDocPtr xml_doc, char **name, char **title,
1560 char **abstract)
1561 {
1562 /*
1563 / attempting to retrieve the Name, Title and Abstract items
1564 / from a Map Config document
1565 */
1566 xmlNodePtr root = xmlDocGetRootElement (xml_doc);
1567 char *string;
1568 const char *xname = (const char *) (root->name);
1569
1570 *name = NULL;
1571 *title = NULL;
1572 *abstract = NULL;
1573
1574 if (xname != NULL)
1575 {
1576 if (strcmp (xname, "RL2MapConfig") != 0)
1577 return;
1578 }
1579
1580 /* attempting to retrieve the Name item */
1581 string = NULL;
1582 find_map_config_name (root->children, &string);
1583 if (string)
1584 *name = string;
1585
1586 /* attempting to retrieve the Title item */
1587 string = NULL;
1588 find_map_config_title (root->children, &string);
1589 if (string)
1590 *title = string;
1591
1592 /* attempting to retrieve the Abstract item */
1593 string = NULL;
1594 find_map_config_abstract (root->children, &string);
1595 if (string)
1596 *abstract = string;
1597 }
1598
1599 GAIAGEO_DECLARE void
gaiaXmlToBlob(const void * p_cache,const unsigned char * xml,int xml_len,int compressed,const char * schemaURI,unsigned char ** result,int * size,char ** parsing_errors,char ** schema_validation_errors)1600 gaiaXmlToBlob (const void *p_cache, const unsigned char *xml, int xml_len,
1601 int compressed, const char *schemaURI, unsigned char **result,
1602 int *size, char **parsing_errors,
1603 char **schema_validation_errors)
1604 {
1605 /* attempting to build an XmlBLOB buffer */
1606 xmlDocPtr xml_doc;
1607 xmlDocPtr schema_doc;
1608 xmlSchemaPtr schema = NULL;
1609 xmlSchemaParserCtxtPtr parser_ctxt;
1610 xmlSchemaValidCtxtPtr valid_ctxt;
1611 int is_iso_metadata = 0;
1612 int is_sld_se_vector_style = 0;
1613 int is_sld_se_raster_style = 0;
1614 int is_sld_style = 0;
1615 int is_svg = 0;
1616 int is_gpx = 0;
1617 int is_map_config = 0;
1618 int len;
1619 int zip_len;
1620 short uri_len = 0;
1621 short fileid_len = 0;
1622 short parentid_len = 0;
1623 short name_len = 0;
1624 short title_len = 0;
1625 short abstract_len = 0;
1626 short geometry_len = 0;
1627 char *fileIdentifier = NULL;
1628 char *parentIdentifier = NULL;
1629 char *name = NULL;
1630 char *title = NULL;
1631 char *abstract = NULL;
1632 unsigned char *geometry = NULL;
1633 uLong crc;
1634 Bytef *zip_buf = NULL;
1635 unsigned char *buf;
1636 unsigned char *ptr;
1637 unsigned char flags = 0x00;
1638 int endian_arch = gaiaEndianArch ();
1639 struct splite_internal_cache *cache =
1640 (struct splite_internal_cache *) p_cache;
1641 gaiaOutBufferPtr parsingBuf = NULL;
1642 gaiaOutBufferPtr schemaValidationBuf = NULL;
1643 xmlGenericErrorFunc silentError = NULL;
1644 xmlGenericErrorFunc parsingError = NULL;
1645 xmlGenericErrorFunc schemaError = NULL;
1646 if (is_valid_cache (cache))
1647 {
1648 parsingBuf = (gaiaOutBufferPtr) (cache->xmlParsingErrors);
1649 schemaValidationBuf =
1650 (gaiaOutBufferPtr) (cache->xmlSchemaValidationErrors);
1651 parsingError = (xmlGenericErrorFunc) spliteParsingError;
1652 schemaError = (xmlGenericErrorFunc) spliteSchemaValidationError;
1653 spliteResetXmlErrors (cache);
1654 }
1655
1656 *result = NULL;
1657 *size = 0;
1658 if (parsing_errors)
1659 *parsing_errors = NULL;
1660 if (schema_validation_errors)
1661 *schema_validation_errors = NULL;
1662 if (xml == NULL)
1663 return;
1664
1665 xmlSetGenericErrorFunc (NULL, silentError);
1666
1667 if (schemaURI != NULL)
1668 {
1669 if (splite_xmlSchemaCacheFind
1670 (cache, schemaURI, &schema_doc, &parser_ctxt, &schema))
1671 ;
1672 else
1673 {
1674 /* preparing the Schema */
1675 xmlSetGenericErrorFunc (cache, schemaError);
1676 schema_doc = xmlReadFile ((const char *) schemaURI, NULL, 0);
1677 if (schema_doc == NULL)
1678 {
1679 spatialite_e ("unable to load the Schema\n");
1680 if (schema_validation_errors)
1681 *schema_validation_errors =
1682 schemaValidationBuf->Buffer;
1683 xmlSetGenericErrorFunc ((void *) stderr, NULL);
1684 return;
1685 }
1686 parser_ctxt = xmlSchemaNewDocParserCtxt (schema_doc);
1687 if (parser_ctxt == NULL)
1688 {
1689 spatialite_e ("unable to prepare the Schema Context\n");
1690 xmlFreeDoc (schema_doc);
1691 if (schema_validation_errors)
1692 *schema_validation_errors =
1693 schemaValidationBuf->Buffer;
1694 xmlSetGenericErrorFunc ((void *) stderr, NULL);
1695 return;
1696 }
1697 schema = xmlSchemaParse (parser_ctxt);
1698 if (schema == NULL)
1699 {
1700 spatialite_e ("invalid Schema\n");
1701 xmlFreeDoc (schema_doc);
1702 if (schema_validation_errors)
1703 *schema_validation_errors =
1704 schemaValidationBuf->Buffer;
1705 xmlSetGenericErrorFunc ((void *) stderr, NULL);
1706 return;
1707 }
1708 splite_xmlSchemaCacheInsert (cache, schemaURI, schema_doc,
1709 parser_ctxt, schema);
1710 }
1711 }
1712
1713 /* testing if the XMLDocument is well-formed */
1714 xmlSetGenericErrorFunc (cache, parsingError);
1715 xml_doc =
1716 xmlReadMemory ((const char *) xml, xml_len, "noname.xml", NULL, 0);
1717 if (xml_doc == NULL)
1718 {
1719 /* parsing error; not a well-formed XML */
1720 spatialite_e ("XML parsing error\n");
1721 if (parsing_errors && parsingBuf)
1722 *parsing_errors = parsingBuf->Buffer;
1723 xmlSetGenericErrorFunc ((void *) stderr, NULL);
1724 return;
1725 }
1726 if (parsing_errors && parsingBuf)
1727 *parsing_errors = parsingBuf->Buffer;
1728
1729 if (schemaURI != NULL)
1730 {
1731 /* Schema validation */
1732 xmlSetGenericErrorFunc (cache, schemaError);
1733 valid_ctxt = xmlSchemaNewValidCtxt (schema);
1734 if (valid_ctxt == NULL)
1735 {
1736 spatialite_e ("unable to prepare a validation context\n");
1737 xmlFreeDoc (xml_doc);
1738 if (schema_validation_errors && schemaValidationBuf)
1739 *schema_validation_errors = schemaValidationBuf->Buffer;
1740 xmlSetGenericErrorFunc ((void *) stderr, NULL);
1741 return;
1742 }
1743 if (xmlSchemaValidateDoc (valid_ctxt, xml_doc) != 0)
1744 {
1745 spatialite_e ("Schema validation failed\n");
1746 xmlSchemaFreeValidCtxt (valid_ctxt);
1747 xmlFreeDoc (xml_doc);
1748 if (schema_validation_errors && schemaValidationBuf)
1749 *schema_validation_errors = schemaValidationBuf->Buffer;
1750 xmlSetGenericErrorFunc ((void *) stderr, NULL);
1751 return;
1752 }
1753 xmlSchemaFreeValidCtxt (valid_ctxt);
1754 }
1755
1756 /* testing for special cases: ISO Metadata, SLD/SE Styles and SVG */
1757 sniff_payload (xml_doc, &is_iso_metadata, &is_sld_se_vector_style,
1758 &is_sld_se_raster_style, &is_sld_style, &is_svg, &is_gpx,
1759 &is_map_config);
1760 if (is_iso_metadata)
1761 retrieve_iso_identifiers (xml_doc, &fileIdentifier,
1762 &parentIdentifier, &title, &abstract,
1763 &geometry, &geometry_len);
1764 if (is_sld_style)
1765 retrieve_sld_identifiers (xml_doc, &name, &title, &abstract);
1766 else if (is_sld_se_vector_style || is_sld_se_raster_style)
1767 retrieve_sld_se_identifiers (xml_doc, &name, &title, &abstract);
1768 else if (is_map_config)
1769 retrieve_map_config_identifiers (xml_doc, &name, &title, &abstract);
1770 xmlFreeDoc (xml_doc);
1771
1772 if (compressed)
1773 {
1774 /* compressing the XML payload */
1775 uLong zLen = compressBound (xml_len);
1776 zip_buf = malloc (zLen);
1777 if (compress (zip_buf, &zLen, (const Bytef *) xml, (uLong) xml_len) !=
1778 Z_OK)
1779 {
1780 /* compression error */
1781 spatialite_e ("XmlBLOB DEFLATE compress error\n");
1782 free (zip_buf);
1783 xmlSetGenericErrorFunc ((void *) stderr, NULL);
1784 return;
1785 }
1786 zip_len = (int) zLen;
1787 }
1788 else
1789 zip_len = xml_len;
1790
1791 /* reporting errors */
1792 if (parsing_errors && parsingBuf)
1793 *parsing_errors = parsingBuf->Buffer;
1794 if (schema_validation_errors && schemaValidationBuf)
1795 *schema_validation_errors = schemaValidationBuf->Buffer;
1796
1797 /* computing the XmlBLOB size */
1798 len = 39; /* fixed header-footer size */
1799 if (schemaURI)
1800 uri_len = (short) strlen ((const char *) schemaURI);
1801 if (fileIdentifier)
1802 fileid_len = (short) strlen ((const char *) fileIdentifier);
1803 if (parentIdentifier)
1804 parentid_len = strlen ((const char *) parentIdentifier);
1805 if (name)
1806 name_len = (short) strlen ((const char *) name);
1807 if (title)
1808 title_len = (short) strlen ((const char *) title);
1809 if (abstract)
1810 abstract_len = (short) strlen ((const char *) abstract);
1811 len += zip_len;
1812 len += uri_len;
1813 len += fileid_len;
1814 len += parentid_len;
1815 len += name_len;
1816 len += title_len;
1817 len += abstract_len;
1818 len += geometry_len;
1819 buf = malloc (len);
1820 *buf = GAIA_XML_START; /* START signature */
1821 flags |= GAIA_XML_LITTLE_ENDIAN;
1822 if (compressed)
1823 flags |= GAIA_XML_COMPRESSED;
1824 if (schemaURI != NULL)
1825 flags |= GAIA_XML_VALIDATED;
1826 if (is_iso_metadata)
1827 flags |= GAIA_XML_ISO_METADATA;
1828 if (is_sld_se_vector_style)
1829 flags |= GAIA_XML_SLD_SE_VECTOR_STYLE;
1830 if (is_sld_se_raster_style)
1831 flags |= GAIA_XML_SLD_SE_RASTER_STYLE;
1832 if (is_sld_style)
1833 flags |= GAIA_XML_SLD_STYLE;
1834 if (is_svg)
1835 flags |= GAIA_XML_SVG;
1836 if (is_gpx)
1837 flags |= GAIA_XML_GPX;
1838 if (is_map_config)
1839 flags |= GAIA_XML_MAP_CONFIG;
1840 *(buf + 1) = flags; /* XmlBLOB flags */
1841 *(buf + 2) = GAIA_XML_HEADER; /* HEADER signature */
1842 gaiaExport32 (buf + 3, xml_len, 1, endian_arch); /* the uncompressed XMLDocument size */
1843 gaiaExport32 (buf + 7, zip_len, 1, endian_arch); /* the compressed XMLDocument size */
1844 gaiaExport16 (buf + 11, uri_len, 1, endian_arch); /* the SchemaURI length in bytes */
1845 *(buf + 13) = GAIA_XML_SCHEMA; /* SCHEMA signature */
1846 ptr = buf + 14;
1847 if (schemaURI)
1848 {
1849 /* the SchemaURI */
1850 memcpy (ptr, schemaURI, uri_len);
1851 ptr += uri_len;
1852 }
1853 gaiaExport16 (ptr, fileid_len, 1, endian_arch); /* the FileIdentifier length in bytes */
1854 ptr += 2;
1855 *ptr = GAIA_XML_FILEID; /* FileIdentifier signature */
1856 ptr++;
1857 if (fileIdentifier)
1858 {
1859 /* the FileIdentifier */
1860 memcpy (ptr, fileIdentifier, fileid_len);
1861 free (fileIdentifier);
1862 ptr += fileid_len;
1863 }
1864 gaiaExport16 (ptr, parentid_len, 1, endian_arch); /* the ParentIdentifier length in bytes */
1865 ptr += 2;
1866 *ptr = GAIA_XML_PARENTID; /* ParentIdentifier signature */
1867 ptr++;
1868 if (parentIdentifier)
1869 {
1870 /* the ParentIdentifier */
1871 memcpy (ptr, parentIdentifier, parentid_len);
1872 free (parentIdentifier);
1873 ptr += parentid_len;
1874 }
1875 gaiaExport16 (ptr, name_len, 1, endian_arch); /* the Name length in bytes */
1876 ptr += 2;
1877 *ptr = GAIA_XML_NAME; /* Title signature */
1878 ptr++;
1879 if (name)
1880 {
1881 /* the Name */
1882 memcpy (ptr, name, name_len);
1883 free (name);
1884 ptr += name_len;
1885 }
1886 gaiaExport16 (ptr, title_len, 1, endian_arch); /* the Title length in bytes */
1887 ptr += 2;
1888 *ptr = GAIA_XML_TITLE; /* Title signature */
1889 ptr++;
1890 if (title)
1891 {
1892 /* the Title */
1893 memcpy (ptr, title, title_len);
1894 free (title);
1895 ptr += title_len;
1896 }
1897 gaiaExport16 (ptr, abstract_len, 1, endian_arch); /* the Abstract length in bytes */
1898 ptr += 2;
1899 *ptr = GAIA_XML_ABSTRACT; /* Abstract signature */
1900 ptr++;
1901 if (abstract)
1902 {
1903 /* the Abstract */
1904 memcpy (ptr, abstract, abstract_len);
1905 free (abstract);
1906 ptr += abstract_len;
1907 }
1908 gaiaExport16 (ptr, geometry_len, 1, endian_arch); /* the Geometry length in bytes */
1909 ptr += 2;
1910 *ptr = GAIA_XML_GEOMETRY; /* Geometry signature */
1911 ptr++;
1912 if (geometry)
1913 {
1914 /* the Geometry */
1915 memcpy (ptr, geometry, geometry_len);
1916 free (geometry);
1917 ptr += geometry_len;
1918 }
1919 *ptr = GAIA_XML_PAYLOAD; /* PAYLOAD signature */
1920 ptr++;
1921 if (compressed)
1922 {
1923 /* the compressed XML payload */
1924 memcpy (ptr, zip_buf, zip_len);
1925 free (zip_buf);
1926 ptr += zip_len;
1927 }
1928 else
1929 {
1930 /* the uncompressed XML payload */
1931 memcpy (ptr, xml, xml_len);
1932 ptr += xml_len;
1933 }
1934 *ptr = GAIA_XML_CRC32; /* CRC32 signature */
1935 ptr++;
1936 /* computing the CRC32 */
1937 crc = crc32 (0L, buf, ptr - buf);
1938 gaiaExportU32 (ptr, crc, 1, endian_arch); /* the CRC32 */
1939 ptr += 4;
1940 *ptr = GAIA_XML_END; /* END signature */
1941
1942 *result = buf;
1943 *size = len;
1944 xmlSetGenericErrorFunc ((void *) stderr, NULL);
1945 }
1946
1947 GAIAGEO_DECLARE void
gaiaXmlBlobCompression(const unsigned char * blob,int in_size,int compressed,unsigned char ** result,int * out_size)1948 gaiaXmlBlobCompression (const unsigned char *blob,
1949 int in_size, int compressed,
1950 unsigned char **result, int *out_size)
1951 {
1952 /* Return another XmlBLOB buffer compressed / uncompressed */
1953 int in_compressed = 0;
1954 int little_endian = 0;
1955 unsigned char flag;
1956 int in_xml_len;
1957 int in_zip_len = 0;
1958 short uri_len;
1959 short fileid_len;
1960 short parentid_len;
1961 short name_len;
1962 short title_len;
1963 short abstract_len;
1964 short geometry_len;
1965 int out_xml_len;
1966 int out_zip_len;
1967 uLong crc;
1968 Bytef *zip_buf = NULL;
1969 int len;
1970 char *schemaURI;
1971 char *fileIdentifier;
1972 char *parentIdentifier;
1973 char *name;
1974 char *title;
1975 char *abstract;
1976 unsigned char *geometry;
1977 int is_iso_metadata = 0;
1978 int is_sld_se_vector_style = 0;
1979 int is_sld_se_raster_style = 0;
1980 int is_sld_style = 0;
1981 int is_svg = 0;
1982 int is_gpx = 0;
1983 unsigned char *xml = NULL;
1984 unsigned char *buf;
1985 unsigned char *ptr;
1986 unsigned char flags;
1987 int legacy_blob = 0;
1988 int endian_arch = gaiaEndianArch ();
1989
1990 *result = NULL;
1991 *out_size = 0;
1992 /* validity check */
1993 if (!gaiaIsValidXmlBlob (blob, in_size))
1994 return; /* cannot be an XmlBLOB */
1995 if (*(blob + 2) == GAIA_XML_LEGACY_HEADER)
1996 legacy_blob = 1;
1997 flag = *(blob + 1);
1998 flag = *(blob + 1);
1999 if ((flag & GAIA_XML_LITTLE_ENDIAN) == GAIA_XML_LITTLE_ENDIAN)
2000 little_endian = 1;
2001 if ((flag & GAIA_XML_COMPRESSED) == GAIA_XML_COMPRESSED)
2002 in_compressed = 1;
2003 if ((flag & GAIA_XML_ISO_METADATA) == GAIA_XML_ISO_METADATA)
2004 is_iso_metadata = 1;
2005 if ((flag & GAIA_XML_SLD_SE_VECTOR_STYLE) == GAIA_XML_SLD_SE_VECTOR_STYLE)
2006 is_sld_se_vector_style = 1;
2007 if ((flag & GAIA_XML_SLD_SE_RASTER_STYLE) == GAIA_XML_SLD_SE_RASTER_STYLE)
2008 is_sld_se_raster_style = 1;
2009 if ((flag & GAIA_XML_SLD_STYLE) == GAIA_XML_SLD_STYLE)
2010 is_sld_style = 1;
2011 if ((flag & GAIA_XML_SVG) == GAIA_XML_SVG)
2012 is_svg = 1;
2013 if ((flag & GAIA_XML_GPX) == GAIA_XML_GPX)
2014 is_gpx = 1;
2015 in_xml_len = gaiaImport32 (blob + 3, little_endian, endian_arch);
2016 in_zip_len = gaiaImport32 (blob + 7, little_endian, endian_arch);
2017 uri_len = gaiaImport16 (blob + 11, little_endian, endian_arch);
2018 ptr = (unsigned char *) blob + 14;
2019 if (uri_len)
2020 {
2021 schemaURI = (char *) ptr;
2022 ptr += uri_len;
2023 }
2024 else
2025 {
2026 schemaURI = NULL;
2027 }
2028 fileid_len = gaiaImport16 (ptr, little_endian, endian_arch);
2029 ptr += 3;
2030 if (fileid_len)
2031 {
2032 fileIdentifier = (char *) ptr;
2033 ptr += fileid_len;
2034 }
2035 else
2036 {
2037 fileIdentifier = NULL;
2038 }
2039 parentid_len = gaiaImport16 (ptr, little_endian, endian_arch);
2040 ptr += 3;
2041 if (parentid_len)
2042 {
2043 parentIdentifier = (char *) ptr;
2044 ptr += parentid_len;
2045 }
2046 else
2047 {
2048 parentIdentifier = NULL;
2049 }
2050 if (!legacy_blob)
2051 {
2052 name_len = gaiaImport16 (ptr, little_endian, endian_arch);
2053 ptr += 3;
2054 if (name_len)
2055 {
2056 name = (char *) ptr;
2057 ptr += name_len;
2058 }
2059 else
2060 {
2061 name = NULL;
2062 }
2063 }
2064 else
2065 {
2066 name_len = 0;
2067 name = NULL;
2068 }
2069 title_len = gaiaImport16 (ptr, little_endian, endian_arch);
2070 ptr += 3;
2071 if (title_len)
2072 {
2073 title = (char *) ptr;
2074 ptr += title_len;
2075 }
2076 else
2077 {
2078 title = NULL;
2079 }
2080 abstract_len = gaiaImport16 (ptr, little_endian, endian_arch);
2081 ptr += 3;
2082 if (abstract_len)
2083 {
2084 abstract = (char *) ptr;
2085 ptr += abstract_len;
2086 }
2087 else
2088 {
2089 abstract = NULL;
2090 }
2091 geometry_len = gaiaImport16 (ptr, little_endian, endian_arch);
2092 ptr += 3;
2093 if (geometry_len)
2094 {
2095 geometry = (unsigned char *) ptr;
2096 ptr += geometry_len;
2097 }
2098 else
2099 {
2100 geometry = NULL;
2101 }
2102 ptr++;
2103
2104 if (in_compressed == compressed)
2105 {
2106 /* unchanged compression */
2107 out_xml_len = in_xml_len;
2108 out_zip_len = in_zip_len;
2109 zip_buf = (unsigned char *) ptr;
2110 }
2111 else if (compressed)
2112 {
2113 /* compressing the XML payload */
2114 uLong zLen;
2115 out_xml_len = in_xml_len;
2116 zLen = compressBound (out_xml_len);
2117 xml = (unsigned char *) ptr;
2118 zip_buf = malloc (zLen);
2119 if (compress
2120 (zip_buf, &zLen, (const Bytef *) xml,
2121 (uLong) out_xml_len) != Z_OK)
2122 {
2123 /* compression error */
2124 spatialite_e ("XmlBLOB DEFLATE compress error\n");
2125 free (zip_buf);
2126 return;
2127 }
2128 out_zip_len = (int) zLen;
2129 }
2130 else
2131 {
2132 /* unzipping the XML payload */
2133 uLong refLen = in_xml_len;
2134 const Bytef *in = ptr;
2135 xml = malloc (in_xml_len + 1);
2136 if (uncompress (xml, &refLen, in, in_zip_len) != Z_OK)
2137 {
2138 /* uncompress error */
2139 spatialite_e ("XmlBLOB DEFLATE uncompress error\n");
2140 free (xml);
2141 return;
2142 }
2143 *(xml + in_xml_len) = '\0';
2144 out_xml_len = in_xml_len;
2145 out_zip_len = out_xml_len;
2146 }
2147
2148 /* computing the XmlBLOB size */
2149 len = 39; /* fixed header-footer size */
2150 len += out_zip_len;
2151 len += uri_len;
2152 len += fileid_len;
2153 len += parentid_len;
2154 len += name_len;
2155 len += title_len;
2156 len += abstract_len;
2157 len += geometry_len;
2158 buf = malloc (len);
2159 *buf = GAIA_XML_START; /* START signature */
2160 flags = 0x00;
2161 flags |= GAIA_XML_LITTLE_ENDIAN;
2162 if (compressed)
2163 flags |= GAIA_XML_COMPRESSED;
2164 if (schemaURI != NULL)
2165 flags |= GAIA_XML_VALIDATED;
2166 if (is_iso_metadata)
2167 flags |= GAIA_XML_ISO_METADATA;
2168 if (is_sld_se_vector_style)
2169 flags |= GAIA_XML_SLD_SE_VECTOR_STYLE;
2170 if (is_sld_se_raster_style)
2171 flags |= GAIA_XML_SLD_SE_RASTER_STYLE;
2172 if (is_sld_style)
2173 flags |= GAIA_XML_SLD_STYLE;
2174 if (is_svg)
2175 flags |= GAIA_XML_SVG;
2176 if (is_gpx)
2177 flags |= GAIA_XML_GPX;
2178 *(buf + 1) = flags; /* XmlBLOB flags */
2179 *(buf + 2) = GAIA_XML_HEADER; /* HEADER signature */
2180 gaiaExport32 (buf + 3, out_xml_len, 1, endian_arch); /* the uncompressed XMLDocument size */
2181 gaiaExport32 (buf + 7, out_zip_len, 1, endian_arch); /* the compressed XMLDocument size */
2182 gaiaExport16 (buf + 11, uri_len, 1, endian_arch); /* the SchemaURI length in bytes */
2183 *(buf + 13) = GAIA_XML_SCHEMA; /* SCHEMA signature */
2184 ptr = buf + 14;
2185 if (schemaURI)
2186 {
2187 /* the SchemaURI */
2188 memcpy (ptr, schemaURI, uri_len);
2189 ptr += uri_len;
2190 }
2191 gaiaExport16 (ptr, fileid_len, 1, endian_arch); /* the FileIdentifier length in bytes */
2192 ptr += 2;
2193 *ptr = GAIA_XML_FILEID; /* FileIdentifier signature */
2194 ptr++;
2195 if (fileIdentifier)
2196 {
2197 /* the FileIdentifier */
2198 memcpy (ptr, fileIdentifier, fileid_len);
2199 ptr += fileid_len;
2200 }
2201 gaiaExport16 (ptr, parentid_len, 1, endian_arch); /* the ParentIdentifier length in bytes */
2202 ptr += 2;
2203 *ptr = GAIA_XML_PARENTID; /* ParentIdentifier signature */
2204 ptr++;
2205 if (parentIdentifier)
2206 {
2207 /* the ParentIdentifier */
2208 memcpy (ptr, parentIdentifier, parentid_len);
2209 ptr += parentid_len;
2210 }
2211 gaiaExport16 (ptr, name_len, 1, endian_arch); /* the Name length in bytes */
2212 ptr += 2;
2213 *ptr = GAIA_XML_NAME; /* Name signature */
2214 ptr++;
2215 if (name)
2216 {
2217 /* the Name */
2218 memcpy (ptr, name, name_len);
2219 ptr += name_len;
2220 }
2221 gaiaExport16 (ptr, title_len, 1, endian_arch); /* the Title length in bytes */
2222 ptr += 2;
2223 *ptr = GAIA_XML_TITLE; /* Title signature */
2224 ptr++;
2225 if (title)
2226 {
2227 /* the Title */
2228 memcpy (ptr, title, title_len);
2229 ptr += title_len;
2230 }
2231 gaiaExport16 (ptr, abstract_len, 1, endian_arch); /* the Abstract length in bytes */
2232 ptr += 2;
2233 *ptr = GAIA_XML_ABSTRACT; /* Abstract signature */
2234 ptr++;
2235 if (abstract)
2236 {
2237 /* the Abstract */
2238 memcpy (ptr, abstract, abstract_len);
2239 ptr += abstract_len;
2240 }
2241 gaiaExport16 (ptr, geometry_len, 1, endian_arch); /* the Geometry length in bytes */
2242 ptr += 2;
2243 *ptr = GAIA_XML_GEOMETRY; /* Geometry signature */
2244 ptr++;
2245 if (geometry)
2246 {
2247 /* the Geometry */
2248 memcpy (ptr, geometry, geometry_len);
2249 ptr += geometry_len;
2250 }
2251
2252 *ptr = GAIA_XML_PAYLOAD; /* PAYLOAD signature */
2253 ptr++;
2254 if (in_compressed == compressed)
2255 {
2256 /* the unchanged XML payload */
2257 memcpy (ptr, zip_buf, out_zip_len);
2258 ptr += out_zip_len;
2259 }
2260 else if (compressed)
2261 {
2262 /* the compressed XML payload */
2263 memcpy (ptr, zip_buf, out_zip_len);
2264 free (zip_buf);
2265 ptr += out_zip_len;
2266 }
2267 else
2268 {
2269 /* the uncompressed XML payload */
2270 memcpy (ptr, xml, out_xml_len);
2271 free (xml);
2272 ptr += out_xml_len;
2273 }
2274 *ptr = GAIA_XML_CRC32; /* CRC32 signature */
2275 ptr++;
2276 /* computing the CRC32 */
2277 crc = crc32 (0L, buf, ptr - buf);
2278 gaiaExportU32 (ptr, crc, 1, endian_arch); /* the CRC32 */
2279 ptr += 4;
2280 *ptr = GAIA_XML_END; /* END signature */
2281
2282 *result = buf;
2283 *out_size = len;
2284 }
2285
2286 static int
is_valid_legacy_xml_blob(const unsigned char * blob,int blob_size)2287 is_valid_legacy_xml_blob (const unsigned char *blob, int blob_size)
2288 {
2289 /* Checks if a BLOB actually is a valid LEGACY XmlBLOB buffer */
2290 int little_endian = 0;
2291 unsigned char flag;
2292 const unsigned char *ptr;
2293 short uri_len;
2294 short fileid_len;
2295 short parentid_len;
2296 short title_len;
2297 short abstract_len;
2298 short geometry_len;
2299 uLong crc;
2300 uLong refCrc;
2301 int endian_arch = gaiaEndianArch ();
2302
2303 /* validity check */
2304 if (blob_size < 36)
2305 return 0; /* cannot be an XmlBLOB */
2306 if (*blob != GAIA_XML_START)
2307 return 0; /* failed to recognize START signature */
2308 if (*(blob + (blob_size - 1)) != GAIA_XML_END)
2309 return 0; /* failed to recognize END signature */
2310 if (*(blob + (blob_size - 6)) != GAIA_XML_CRC32)
2311 return 0; /* failed to recognize CRC32 signature */
2312 if (*(blob + 2) != GAIA_XML_LEGACY_HEADER)
2313 return 0; /* failed to recognize HEADER signature */
2314 if (*(blob + 13) != GAIA_XML_SCHEMA)
2315 return 0; /* failed to recognize SCHEMA signature */
2316 flag = *(blob + 1);
2317 if ((flag & GAIA_XML_LITTLE_ENDIAN) == GAIA_XML_LITTLE_ENDIAN)
2318 little_endian = 1;
2319 ptr = blob + 11;
2320 uri_len = gaiaImport16 (ptr, little_endian, endian_arch);
2321 ptr += 2;
2322 if (*ptr != GAIA_XML_SCHEMA)
2323 return 0;
2324 ptr++;
2325 ptr += uri_len;
2326 fileid_len = gaiaImport16 (ptr, little_endian, endian_arch);
2327 ptr += 2;
2328 if (*ptr != GAIA_XML_FILEID)
2329 return 0;
2330 ptr++;
2331 ptr += fileid_len;
2332 parentid_len = gaiaImport16 (ptr, little_endian, endian_arch);
2333 ptr += 2;
2334 if (*ptr != GAIA_XML_PARENTID)
2335 return 0;
2336 ptr++;
2337 ptr += parentid_len;
2338 title_len = gaiaImport16 (ptr, little_endian, endian_arch);
2339 ptr += 2;
2340 if (*ptr != GAIA_XML_TITLE)
2341 return 0;
2342 ptr++;
2343 ptr += title_len;
2344 abstract_len = gaiaImport16 (ptr, little_endian, endian_arch);
2345 ptr += 2;
2346 if (*ptr != GAIA_XML_ABSTRACT)
2347 return 0;
2348 ptr++;
2349 ptr += abstract_len;
2350 geometry_len = gaiaImport16 (ptr, little_endian, endian_arch);
2351 ptr += 2;
2352 if (*ptr != GAIA_XML_GEOMETRY)
2353 return 0;
2354 ptr++;
2355 ptr += geometry_len;
2356 if (*ptr != GAIA_XML_PAYLOAD)
2357 return 0;
2358
2359 /* verifying the CRC32 */
2360 crc = crc32 (0L, blob, blob_size - 5);
2361 refCrc = gaiaImportU32 (blob + blob_size - 5, little_endian, endian_arch);
2362 if (crc != refCrc)
2363 return 0;
2364
2365 return 1;
2366 }
2367
2368 GAIAGEO_DECLARE int
gaiaIsValidXmlBlob(const unsigned char * blob,int blob_size)2369 gaiaIsValidXmlBlob (const unsigned char *blob, int blob_size)
2370 {
2371 /* Checks if a BLOB actually is a valid XmlBLOB buffer */
2372 int little_endian = 0;
2373 unsigned char flag;
2374 const unsigned char *ptr;
2375 short uri_len;
2376 short fileid_len;
2377 short parentid_len;
2378 short name_len;
2379 short title_len;
2380 short abstract_len;
2381 short geometry_len;
2382 uLong crc;
2383 uLong refCrc;
2384 int endian_arch = gaiaEndianArch ();
2385
2386 if (blob_size > 3)
2387 {
2388 /* legacy format */
2389 if (*(blob + 2) == GAIA_XML_LEGACY_HEADER)
2390 return is_valid_legacy_xml_blob (blob, blob_size);
2391 }
2392
2393 /* validity check */
2394 if (blob_size < 39)
2395 return 0; /* cannot be an XmlBLOB */
2396 if (*blob != GAIA_XML_START)
2397 return 0; /* failed to recognize START signature */
2398 if (*(blob + (blob_size - 1)) != GAIA_XML_END)
2399 return 0; /* failed to recognize END signature */
2400 if (*(blob + (blob_size - 6)) != GAIA_XML_CRC32)
2401 return 0; /* failed to recognize CRC32 signature */
2402 if (*(blob + 2) != GAIA_XML_HEADER)
2403 return 0; /* failed to recognize HEADER signature */
2404 if (*(blob + 13) != GAIA_XML_SCHEMA)
2405 return 0; /* failed to recognize SCHEMA signature */
2406 flag = *(blob + 1);
2407 if ((flag & GAIA_XML_LITTLE_ENDIAN) == GAIA_XML_LITTLE_ENDIAN)
2408 little_endian = 1;
2409 ptr = blob + 11;
2410 uri_len = gaiaImport16 (ptr, little_endian, endian_arch);
2411 ptr += 2;
2412 if (*ptr != GAIA_XML_SCHEMA)
2413 return 0;
2414 ptr++;
2415 ptr += uri_len;
2416 fileid_len = gaiaImport16 (ptr, little_endian, endian_arch);
2417 ptr += 2;
2418 if (*ptr != GAIA_XML_FILEID)
2419 return 0;
2420 ptr++;
2421 ptr += fileid_len;
2422 parentid_len = gaiaImport16 (ptr, little_endian, endian_arch);
2423 ptr += 2;
2424 if (*ptr != GAIA_XML_PARENTID)
2425 return 0;
2426 ptr++;
2427 ptr += parentid_len;
2428 name_len = gaiaImport16 (ptr, little_endian, endian_arch);
2429 ptr += 2;
2430 if (*ptr != GAIA_XML_NAME)
2431 return 0;
2432 ptr++;
2433 ptr += name_len;
2434 title_len = gaiaImport16 (ptr, little_endian, endian_arch);
2435 ptr += 2;
2436 if (*ptr != GAIA_XML_TITLE)
2437 return 0;
2438 ptr++;
2439 ptr += title_len;
2440 abstract_len = gaiaImport16 (ptr, little_endian, endian_arch);
2441 ptr += 2;
2442 if (*ptr != GAIA_XML_ABSTRACT)
2443 return 0;
2444 ptr++;
2445 ptr += abstract_len;
2446 geometry_len = gaiaImport16 (ptr, little_endian, endian_arch);
2447 ptr += 2;
2448 if (*ptr != GAIA_XML_GEOMETRY)
2449 return 0;
2450 ptr++;
2451 ptr += geometry_len;
2452 if (*ptr != GAIA_XML_PAYLOAD)
2453 return 0;
2454
2455 /* verifying the CRC32 */
2456 crc = crc32 (0L, blob, blob_size - 5);
2457 refCrc = gaiaImportU32 (blob + blob_size - 5, little_endian, endian_arch);
2458 if (crc != refCrc)
2459 return 0;
2460
2461 return 1;
2462 }
2463
2464 static void
find_xml_namespaces(xmlNode * node,struct gaiaxml_ns_list * list)2465 find_xml_namespaces (xmlNode * node, struct gaiaxml_ns_list *list)
2466 {
2467 /* recursively identifying all XML Namespaces from DOM-nodes */
2468 struct _xmlAttr *attr;
2469 while (node)
2470 {
2471 xmlNs *ns = node->ns;
2472 if (ns != NULL)
2473 splite_add_namespace (list, ns->type, ns->prefix, ns->href);
2474 attr = node->properties;
2475 while (attr != NULL)
2476 {
2477 ns = attr->ns;
2478 if (ns != NULL)
2479 splite_add_namespace (list, ns->type, ns->prefix, ns->href);
2480 attr = attr->next;
2481 }
2482 find_xml_namespaces (node->children, list);
2483 node = node->next;
2484 }
2485 }
2486
2487 static void
xml_out(gaiaOutBufferPtr buf,const xmlChar * str)2488 xml_out (gaiaOutBufferPtr buf, const xmlChar * str)
2489 {
2490 /* clean XML output */
2491 const xmlChar *p = str;
2492 while (*p != '\0')
2493 {
2494 if (*p == '>')
2495 gaiaAppendToOutBuffer (buf, ">");
2496 else if (*p == '<')
2497 gaiaAppendToOutBuffer (buf, "<");
2498 else if (*p == '&')
2499 gaiaAppendToOutBuffer (buf, "&");
2500 else if (*p == '"')
2501 gaiaAppendToOutBuffer (buf, """);
2502 else if (*p == '\'')
2503 gaiaAppendToOutBuffer (buf, "'");
2504 else
2505 {
2506 char xx[2];
2507 xx[0] = *p;
2508 xx[1] = '\0';
2509 gaiaAppendToOutBuffer (buf, xx);
2510 }
2511 p++;
2512 }
2513 }
2514
2515 static void
format_xml(xmlNode * root,xmlNode * node,struct gaiaxml_ns_list * list,gaiaOutBufferPtr buf,int indent,int * level)2516 format_xml (xmlNode * root, xmlNode * node, struct gaiaxml_ns_list *list,
2517 gaiaOutBufferPtr buf, int indent, int *level)
2518 {
2519 /* recursively printing the XML-DOM nodes */
2520 struct _xmlAttr *attr;
2521 xmlNode *child;
2522 xmlNs *ns;
2523 const xmlChar *namespace;
2524 char *indenting = NULL;
2525 const char no = '\0';
2526 const char *pre;
2527 int tab;
2528 int width;
2529 int has_children;
2530 int has_text;
2531 if (!indent)
2532 pre = &no;
2533 else
2534 {
2535 if (indent <= 8)
2536 tab = indent;
2537 else
2538 tab = 8;
2539 width = tab * *level;
2540 indenting = malloc (width + 2);
2541 *indenting = '\n';
2542 memset (indenting + 1, ' ', width);
2543 *(indenting + width + 1) = '\0';
2544 pre = indenting;
2545 }
2546
2547 while (node)
2548 {
2549 if (node->type == XML_COMMENT_NODE)
2550 {
2551 /* comment node */
2552 if (*pre != '\0')
2553 gaiaAppendToOutBuffer (buf, "<!--");
2554 else
2555 gaiaAppendToOutBuffer (buf, "\n<!--");
2556 xml_out (buf, node->content);
2557 gaiaAppendToOutBuffer (buf, "-->");
2558 }
2559 if (node->type == XML_ELEMENT_NODE)
2560 {
2561 if (*pre != '\0')
2562 gaiaAppendToOutBuffer (buf, pre);
2563 gaiaAppendToOutBuffer (buf, "<");
2564 ns = node->ns;
2565 namespace = NULL;
2566 if (ns != NULL)
2567 namespace = ns->prefix;
2568 if (namespace)
2569 {
2570 xml_out (buf, namespace);
2571 gaiaAppendToOutBuffer (buf, ":");
2572 }
2573 xml_out (buf, node->name);
2574 if (node == root)
2575 {
2576 /* Namespaces */
2577 struct gaiaxml_namespace *p_ns = list->first;
2578 while (p_ns != NULL)
2579 {
2580 if (p_ns->prefix == NULL)
2581 gaiaAppendToOutBuffer (buf, " xmlns=\"");
2582 else
2583 {
2584 gaiaAppendToOutBuffer (buf, " xmlns:");
2585 xml_out (buf, p_ns->prefix);
2586 gaiaAppendToOutBuffer (buf, "=\"");
2587 }
2588 xml_out (buf, p_ns->href);
2589 gaiaAppendToOutBuffer (buf, "\"");
2590 p_ns = p_ns->next;
2591 }
2592 }
2593 attr = node->properties;
2594 while (attr != NULL)
2595 {
2596 /* attributes */
2597 if (attr->type == XML_ATTRIBUTE_NODE)
2598 {
2599 xmlNode *text = attr->children;
2600 gaiaAppendToOutBuffer (buf, " ");
2601 ns = attr->ns;
2602 namespace = NULL;
2603 if (ns != NULL)
2604 namespace = ns->prefix;
2605 if (namespace)
2606 {
2607 xml_out (buf, namespace);
2608 gaiaAppendToOutBuffer (buf, ":");
2609 }
2610 xml_out (buf, attr->name);
2611 gaiaAppendToOutBuffer (buf, "=\"");
2612 if (text != NULL)
2613 {
2614 if (text->type == XML_TEXT_NODE)
2615 xml_out (buf, text->content);
2616 }
2617 gaiaAppendToOutBuffer (buf, "\"");
2618 }
2619 attr = attr->next;
2620 }
2621 has_children = 0;
2622 has_text = 0;
2623 child = node->children;
2624 while (child)
2625 {
2626 if (child->type == XML_ELEMENT_NODE
2627 || child->type == XML_COMMENT_NODE)
2628 has_children = 1;
2629 if (child->type == XML_TEXT_NODE)
2630 has_text++;
2631 child = child->next;
2632 }
2633 if (has_children)
2634 has_text = 0;
2635
2636 if (!has_text && !has_children)
2637 gaiaAppendToOutBuffer (buf, " />");
2638
2639 if (has_text)
2640 {
2641 child = node->children;
2642 if (child->type == XML_TEXT_NODE)
2643 {
2644 /* text node */
2645 gaiaAppendToOutBuffer (buf, ">");
2646 xml_out (buf, child->content);
2647 gaiaAppendToOutBuffer (buf, "</");
2648 ns = node->ns;
2649 namespace = NULL;
2650 if (ns != NULL)
2651 namespace = ns->prefix;
2652 if (namespace)
2653 {
2654 xml_out (buf, namespace);
2655 gaiaAppendToOutBuffer (buf, ":");
2656 }
2657 xml_out (buf, node->name);
2658 gaiaAppendToOutBuffer (buf, ">");
2659 }
2660 }
2661 if (has_children)
2662 {
2663 /* recursively expanding all children */
2664 gaiaAppendToOutBuffer (buf, ">");
2665 *level += 1;
2666 format_xml (root, node->children, list, buf, indent,
2667 level);
2668 *level -= 1;
2669 if (*pre != '\0')
2670 gaiaAppendToOutBuffer (buf, pre);
2671 gaiaAppendToOutBuffer (buf, "</");
2672 ns = node->ns;
2673 namespace = NULL;
2674 if (ns != NULL)
2675 namespace = ns->prefix;
2676 if (namespace)
2677 {
2678 xml_out (buf, namespace);
2679 gaiaAppendToOutBuffer (buf, ":");
2680 }
2681 xml_out (buf, node->name);
2682 gaiaAppendToOutBuffer (buf, ">");
2683 }
2684 }
2685 node = node->next;
2686 }
2687 if (indenting)
2688 free (indenting);
2689 }
2690
2691 static int
gaiaXmlFormat(xmlDocPtr xml_doc,xmlChar ** out,int * out_len,const xmlChar * encoding,int indent)2692 gaiaXmlFormat (xmlDocPtr xml_doc, xmlChar ** out, int *out_len,
2693 const xmlChar * encoding, int indent)
2694 {
2695 /* reformatting an XML Document - properly indenting */
2696 int level = 0;
2697 int ret;
2698 gaiaOutBuffer buf;
2699 const xmlChar *version = xml_doc->version;
2700 xmlNode *root = xmlDocGetRootElement (xml_doc);
2701 struct gaiaxml_ns_list *list = splite_create_ns_list ();
2702
2703 gaiaOutBufferInitialize (&buf);
2704 if (encoding != NULL)
2705 {
2706 gaiaAppendToOutBuffer (&buf, "<?xml version=\"");
2707 gaiaAppendToOutBuffer (&buf, (const char *) version);
2708 gaiaAppendToOutBuffer (&buf, "\" encoding=\"");
2709 gaiaAppendToOutBuffer (&buf, (const char *) encoding);
2710 gaiaAppendToOutBuffer (&buf, "\"?>");
2711 }
2712 else
2713 {
2714 gaiaAppendToOutBuffer (&buf, "<?xml version=\"");
2715 gaiaAppendToOutBuffer (&buf, (const char *) version);
2716 gaiaAppendToOutBuffer (&buf, "\"?>");
2717 }
2718
2719 find_xml_namespaces (root, list);
2720 format_xml (root, root, list, &buf, indent, &level);
2721 splite_free_ns_list (list);
2722
2723 if (buf.Error == 0 && buf.Buffer != NULL)
2724 {
2725 xmlChar *output;
2726 /* terminating the last line */
2727 gaiaAppendToOutBuffer (&buf, "\n");
2728 output = malloc (buf.WriteOffset + 1);
2729 memcpy (output, buf.Buffer, buf.WriteOffset);
2730 /* NULL-terminated string */
2731 *(output + buf.WriteOffset) = '\0';
2732 *out = output;
2733 *out_len = buf.WriteOffset + 1;
2734 ret = 1;
2735 }
2736 else
2737 {
2738 *out = NULL;
2739 *out_len = 0;
2740 ret = 0;
2741 }
2742 gaiaOutBufferReset (&buf);
2743 return ret;
2744 }
2745
2746 GAIAGEO_DECLARE char *
gaiaXmlTextFromBlob(const unsigned char * blob,int blob_size,int indent)2747 gaiaXmlTextFromBlob (const unsigned char *blob, int blob_size, int indent)
2748 {
2749 /* attempting to extract an XMLDocument from within an XmlBLOB buffer */
2750
2751 #ifndef OMIT_ICONV /* only if ICONV is supported */
2752 int compressed = 0;
2753 int little_endian = 0;
2754 unsigned char flag;
2755 const unsigned char *ptr;
2756 int xml_len;
2757 int zip_len;
2758 short uri_len;
2759 short fileid_len;
2760 short parentid_len;
2761 short name_len = 0;
2762 short title_len;
2763 short abstract_len;
2764 short geometry_len;
2765 unsigned char *xml;
2766 xmlDocPtr xml_doc;
2767 xmlChar *out;
2768 int out_len;
2769 xmlChar *encoding = NULL;
2770 void *cvt;
2771 char *utf8;
2772 int err;
2773 int legacy_blob = 0;
2774 int endian_arch = gaiaEndianArch ();
2775 xmlGenericErrorFunc silentError = (xmlGenericErrorFunc) spliteSilentError;
2776
2777 /* validity check */
2778 if (!gaiaIsValidXmlBlob (blob, blob_size))
2779 return NULL; /* cannot be an XmlBLOB */
2780 if (*(blob + 2) == GAIA_XML_LEGACY_HEADER)
2781 legacy_blob = 1;
2782 flag = *(blob + 1);
2783 if ((flag & GAIA_XML_LITTLE_ENDIAN) == GAIA_XML_LITTLE_ENDIAN)
2784 little_endian = 1;
2785 if ((flag & GAIA_XML_COMPRESSED) == GAIA_XML_COMPRESSED)
2786 compressed = 1;
2787 xml_len = gaiaImport32 (blob + 3, little_endian, endian_arch);
2788 zip_len = gaiaImport32 (blob + 7, little_endian, endian_arch);
2789 ptr = blob + 11;
2790 uri_len = gaiaImport16 (ptr, little_endian, endian_arch);
2791 ptr += 3 + uri_len;
2792 fileid_len = gaiaImport16 (ptr, little_endian, endian_arch);
2793 ptr += 3 + fileid_len;
2794 parentid_len = gaiaImport16 (ptr, little_endian, endian_arch);
2795 ptr += 3 + parentid_len;
2796 if (!legacy_blob)
2797 {
2798 name_len = gaiaImport16 (ptr, little_endian, endian_arch);
2799 ptr += 3 + name_len;
2800 }
2801 title_len = gaiaImport16 (ptr, little_endian, endian_arch);
2802 ptr += 3 + title_len;
2803 abstract_len = gaiaImport16 (ptr, little_endian, endian_arch);
2804 ptr += 3 + abstract_len;
2805 geometry_len = gaiaImport16 (ptr, little_endian, endian_arch);
2806 ptr += 3 + geometry_len;
2807 ptr++;
2808
2809 if (compressed)
2810 {
2811 /* unzipping the XML payload */
2812 uLong refLen = xml_len;
2813 const Bytef *in = ptr;
2814 xml = malloc (xml_len + 1);
2815 if (uncompress (xml, &refLen, in, zip_len) != Z_OK)
2816 {
2817 /* uncompress error */
2818 spatialite_e ("XmlBLOB DEFLATE uncompress error\n");
2819 free (xml);
2820 return NULL;
2821 }
2822 *(xml + xml_len) = '\0';
2823 }
2824 else
2825 {
2826 /* just copying the uncompressed XML payload */
2827 xml = malloc (xml_len + 1);
2828 memcpy (xml, ptr, xml_len);
2829 *(xml + xml_len) = '\0';
2830 }
2831 /* retrieving the XMLDocument encoding */
2832 xmlSetGenericErrorFunc (NULL, silentError);
2833 xml_doc =
2834 xmlReadMemory ((const char *) xml, xml_len, "noname.xml", NULL, 0);
2835 if (xml_doc == NULL)
2836 {
2837 /* parsing error; not a well-formed XML */
2838 xmlSetGenericErrorFunc ((void *) stderr, NULL);
2839 return NULL;
2840 }
2841 if (xml_doc->encoding)
2842 {
2843 /* using the internal character enconding */
2844 int enclen = (int) strlen ((const char *) xml_doc->encoding);
2845 encoding = malloc (enclen + 1);
2846 strcpy ((char *) encoding, (const char *) (xml_doc->encoding));
2847 }
2848 else
2849 {
2850 /* no declared encoding: defaulting to UTF-8 */
2851 encoding = malloc (6);
2852 strcpy ((char *) encoding, "UTF-8");
2853 }
2854
2855 if (indent < 0)
2856 {
2857 /* just returning the XMLDocument "as is" */
2858 xmlFreeDoc (xml_doc);
2859 cvt = gaiaCreateUTF8Converter ((const char *) encoding);
2860 free (encoding);
2861 if (cvt == NULL)
2862 {
2863 xmlSetGenericErrorFunc ((void *) stderr, NULL);
2864 return NULL;
2865 }
2866 utf8 = gaiaConvertToUTF8 (cvt, (const char *) xml, xml_len, &err);
2867 free (xml);
2868 gaiaFreeUTF8Converter (cvt);
2869 if (utf8 && !err)
2870 {
2871 xmlSetGenericErrorFunc ((void *) stderr, NULL);
2872 return utf8;
2873 }
2874 if (utf8)
2875 free (utf8);
2876 xmlSetGenericErrorFunc ((void *) stderr, NULL);
2877 return NULL;
2878 }
2879
2880 /* properly indenting the XMLDocument */
2881 gaiaXmlFormat (xml_doc, &out, &out_len, encoding, indent);
2882 free (xml);
2883 xmlFreeDoc (xml_doc);
2884 free (encoding);
2885 if (out)
2886 {
2887 xmlSetGenericErrorFunc ((void *) stderr, NULL);
2888 return (char *) out;
2889 }
2890 xmlSetGenericErrorFunc ((void *) stderr, NULL);
2891 return NULL;
2892
2893 #else
2894 if (blob != NULL && blob_size == 0 && indent == 0)
2895 blob = NULL; /* silencing stupid compiler warnings */
2896 #endif
2897 return NULL;
2898 }
2899
2900 GAIAGEO_DECLARE void
gaiaXmlFromBlob(const unsigned char * blob,int blob_size,int indent,unsigned char ** result,int * res_size)2901 gaiaXmlFromBlob (const unsigned char *blob, int blob_size, int indent,
2902 unsigned char **result, int *res_size)
2903 {
2904 /* attempting to extract an XMLDocument from within an XmlBLOB buffer */
2905 int compressed = 0;
2906 int little_endian = 0;
2907 unsigned char flag;
2908 const unsigned char *ptr;
2909 int xml_len;
2910 int zip_len;
2911 short uri_len;
2912 short fileid_len;
2913 short parentid_len;
2914 short name_len;
2915 short title_len;
2916 short abstract_len;
2917 short geometry_len;
2918 unsigned char *xml;
2919 xmlDocPtr xml_doc;
2920 xmlChar *out;
2921 int out_len;
2922 int legacy_blob = 0;
2923 int endian_arch = gaiaEndianArch ();
2924 xmlGenericErrorFunc silentError = (xmlGenericErrorFunc) spliteSilentError;
2925 *result = NULL;
2926 *res_size = 0;
2927
2928 /* validity check */
2929 if (!gaiaIsValidXmlBlob (blob, blob_size))
2930 return; /* cannot be an XmlBLOB */
2931 if (*(blob + 2) == GAIA_XML_LEGACY_HEADER)
2932 legacy_blob = 1;
2933 flag = *(blob + 1);
2934 if ((flag & GAIA_XML_LITTLE_ENDIAN) == GAIA_XML_LITTLE_ENDIAN)
2935 little_endian = 1;
2936 if ((flag & GAIA_XML_COMPRESSED) == GAIA_XML_COMPRESSED)
2937 compressed = 1;
2938 xml_len = gaiaImport32 (blob + 3, little_endian, endian_arch);
2939 zip_len = gaiaImport32 (blob + 7, little_endian, endian_arch);
2940 ptr = blob + 11;
2941 uri_len = gaiaImport16 (ptr, little_endian, endian_arch);
2942 ptr += 3 + uri_len;
2943 fileid_len = gaiaImport16 (ptr, little_endian, endian_arch);
2944 ptr += 3 + fileid_len;
2945 parentid_len = gaiaImport16 (ptr, little_endian, endian_arch);
2946 ptr += 3 + parentid_len;
2947 if (!legacy_blob)
2948 {
2949 name_len = gaiaImport16 (ptr, little_endian, endian_arch);
2950 ptr += 3 + name_len;
2951 }
2952 title_len = gaiaImport16 (ptr, little_endian, endian_arch);
2953 ptr += 3 + title_len;
2954 abstract_len = gaiaImport16 (ptr, little_endian, endian_arch);
2955 ptr += 3 + abstract_len;
2956 geometry_len = gaiaImport16 (ptr, little_endian, endian_arch);
2957 ptr += 3 + geometry_len;
2958 ptr++;
2959
2960 if (compressed)
2961 {
2962 /* unzipping the XML payload */
2963 uLong refLen = xml_len;
2964 const Bytef *in = ptr;
2965 xml = malloc (xml_len + 1);
2966 if (uncompress (xml, &refLen, in, zip_len) != Z_OK)
2967 {
2968 /* uncompress error */
2969 spatialite_e ("XmlBLOB DEFLATE uncompress error\n");
2970 free (xml);
2971 return;
2972 }
2973 *(xml + xml_len) = '\0';
2974 }
2975 else
2976 {
2977 /* just copying the uncompressed XML payload */
2978 xml = malloc (xml_len + 1);
2979 memcpy (xml, ptr, xml_len);
2980 *(xml + xml_len) = '\0';
2981 }
2982 if (indent < 0)
2983 {
2984 /* just returning the XMLDocument "as is" */
2985 *result = xml;
2986 *res_size = xml_len;
2987 return;
2988 }
2989
2990 /* properly indenting the XMLDocument */
2991 xmlSetGenericErrorFunc (NULL, silentError);
2992 xml_doc =
2993 xmlReadMemory ((const char *) xml, xml_len, "noname.xml", NULL, 0);
2994 if (xml_doc == NULL)
2995 {
2996 /* parsing error; not a well-formed XML */
2997 *result = xml;
2998 *res_size = xml_len;
2999 xmlSetGenericErrorFunc ((void *) stderr, NULL);
3000 return;
3001 }
3002 gaiaXmlFormat (xml_doc, &out, &out_len, xml_doc->encoding, indent);
3003 free (xml);
3004 xmlFreeDoc (xml_doc);
3005 *result = out;
3006 if (*(out + out_len - 1) == '\0' && out_len > 0)
3007 out_len -= 1;
3008 *res_size = out_len;
3009 xmlSetGenericErrorFunc ((void *) stderr, NULL);
3010 }
3011
3012 GAIAGEO_DECLARE int
gaiaXmlLoad(const void * p_cache,const char * path_or_url,unsigned char ** result,int * size,char ** parsing_errors)3013 gaiaXmlLoad (const void *p_cache, const char *path_or_url,
3014 unsigned char **result, int *size, char **parsing_errors)
3015 {
3016 /* attempting to load an external XML Document into a BLOB buffer */
3017 unsigned char *out;
3018 int len;
3019 xmlDocPtr xml_doc;
3020 struct splite_internal_cache *cache =
3021 (struct splite_internal_cache *) p_cache;
3022 gaiaOutBufferPtr parsingBuf = NULL;
3023 xmlGenericErrorFunc parsingError = NULL;
3024 if (is_valid_cache (cache))
3025 {
3026 parsingBuf = (gaiaOutBufferPtr) (cache->xmlParsingErrors);
3027 parsingError = (xmlGenericErrorFunc) spliteParsingError;
3028 spliteResetXmlErrors (cache);
3029 }
3030
3031 *result = NULL;
3032 *size = 0;
3033 if (parsing_errors)
3034 *parsing_errors = NULL;
3035 if (path_or_url == NULL)
3036 return 0;
3037
3038 /* testing if the XMLDocument is well-formed */
3039 xmlSetGenericErrorFunc (cache, parsingError);
3040 xml_doc = xmlReadFile (path_or_url, NULL, 0);
3041 if (xml_doc == NULL)
3042 {
3043 /* parsing error; not a well-formed XML */
3044 spatialite_e ("XML parsing error\n");
3045 if (parsing_errors && parsingBuf)
3046 *parsing_errors = parsingBuf->Buffer;
3047 xmlSetGenericErrorFunc ((void *) stderr, NULL);
3048 return 0;
3049 }
3050 if (parsing_errors && parsingBuf)
3051 *parsing_errors = parsingBuf->Buffer;
3052
3053 /* exporting the XML Document into a BLOB */
3054 xmlDocDumpFormatMemory (xml_doc, &out, &len, 0);
3055 xmlFreeDoc (xml_doc);
3056 *result = out;
3057 *size = len;
3058 xmlSetGenericErrorFunc ((void *) stderr, NULL);
3059 if (out == NULL)
3060 return 0;
3061 return 1;
3062 }
3063
3064 GAIAGEO_DECLARE int
gaiaXmlStore(const unsigned char * blob,int size,const char * path,int indent)3065 gaiaXmlStore (const unsigned char *blob, int size, const char *path, int indent)
3066 {
3067 /* attempting to store an XmlBLOB Document into an external file */
3068 FILE *fl;
3069 int wr;
3070 unsigned char *result = NULL;
3071 int res_size;
3072 gaiaXmlFromBlob (blob, size, indent, &result, &res_size);
3073 if (result == NULL)
3074 return 0;
3075
3076 /* exporting the XML Document into an external file */
3077 #ifdef _WIN32
3078 fl = gaia_win_fopen (path, "wb");
3079 #else
3080 fl = fopen (path, "wb");
3081 #endif
3082 if (fl == NULL)
3083 {
3084 spatialite_e ("Unable to open \"%s\"\n", path);
3085 return 0;
3086 }
3087 wr = fwrite (result, 1, res_size, fl);
3088 if (wr != res_size)
3089 {
3090 spatialite_e
3091 ("I/O error: written %d bytes into \"%s\", expected %d\n", wr,
3092 path, res_size);
3093 fclose (fl);
3094 return 0;
3095 }
3096 fclose (fl);
3097 return 1;
3098 }
3099
3100 GAIAGEO_DECLARE int
gaiaIsCompressedXmlBlob(const unsigned char * blob,int blob_size)3101 gaiaIsCompressedXmlBlob (const unsigned char *blob, int blob_size)
3102 {
3103 /* Checks if a valid XmlBLOB buffer is compressed or not */
3104 int compressed = 0;
3105 unsigned char flag;
3106
3107 /* validity check */
3108 if (!gaiaIsValidXmlBlob (blob, blob_size))
3109 return -1; /* cannot be an XmlBLOB */
3110 flag = *(blob + 1);
3111 if ((flag & GAIA_XML_COMPRESSED) == GAIA_XML_COMPRESSED)
3112 compressed = 1;
3113 return compressed;
3114 }
3115
3116 GAIAGEO_DECLARE int
gaiaIsSchemaValidatedXmlBlob(const unsigned char * blob,int blob_size)3117 gaiaIsSchemaValidatedXmlBlob (const unsigned char *blob, int blob_size)
3118 {
3119 /* Checks if a valid XmlBLOB buffer has successfully passed a formal Schema validation or not */
3120 int validated = 0;
3121 unsigned char flag;
3122
3123 /* validity check */
3124 if (!gaiaIsValidXmlBlob (blob, blob_size))
3125 return -1; /* cannot be an XmlBLOB */
3126 flag = *(blob + 1);
3127 if ((flag & GAIA_XML_VALIDATED) == GAIA_XML_VALIDATED)
3128 validated = 1;
3129 return validated;
3130 }
3131
3132 GAIAGEO_DECLARE int
gaiaIsIsoMetadataXmlBlob(const unsigned char * blob,int blob_size)3133 gaiaIsIsoMetadataXmlBlob (const unsigned char *blob, int blob_size)
3134 {
3135 /* Checks if a valid XmlBLOB buffer does actually contains an ISO Metadata or not */
3136 int iso_metadata = 0;
3137 unsigned char flag;
3138
3139 /* validity check */
3140 if (!gaiaIsValidXmlBlob (blob, blob_size))
3141 return -1; /* cannot be an XmlBLOB */
3142 flag = *(blob + 1);
3143 if (((flag & GAIA_XML_ISO_METADATA) == GAIA_XML_ISO_METADATA)
3144 && ((flag & GAIA_XML_MAP_CONFIG) != GAIA_XML_MAP_CONFIG))
3145 iso_metadata = 1;
3146 return iso_metadata;
3147 }
3148
3149 GAIAGEO_DECLARE int
gaiaIsSldSeVectorStyleXmlBlob(const unsigned char * blob,int blob_size)3150 gaiaIsSldSeVectorStyleXmlBlob (const unsigned char *blob, int blob_size)
3151 {
3152 /* Checks if a valid XmlBLOB buffer does actually contains an SLD/SE Vector Style or not */
3153 int sld_se_style = 0;
3154 unsigned char flag;
3155
3156 /* validity check */
3157 if (!gaiaIsValidXmlBlob (blob, blob_size))
3158 return -1; /* cannot be an XmlBLOB */
3159 flag = *(blob + 1);
3160 if (((flag & GAIA_XML_SLD_SE_VECTOR_STYLE) == GAIA_XML_SLD_SE_VECTOR_STYLE)
3161 && ((flag & GAIA_XML_SLD_STYLE) != GAIA_XML_SLD_STYLE))
3162 sld_se_style = 1;
3163 return sld_se_style;
3164 }
3165
3166 GAIAGEO_DECLARE int
gaiaIsSldSeRasterStyleXmlBlob(const unsigned char * blob,int blob_size)3167 gaiaIsSldSeRasterStyleXmlBlob (const unsigned char *blob, int blob_size)
3168 {
3169 /* Checks if a valid XmlBLOB buffer does actually contains an SLD/SE Raster Style or not */
3170 int sld_se_style = 0;
3171 unsigned char flag;
3172
3173 /* validity check */
3174 if (!gaiaIsValidXmlBlob (blob, blob_size))
3175 return -1; /* cannot be an XmlBLOB */
3176 flag = *(blob + 1);
3177 if ((flag & GAIA_XML_SLD_SE_RASTER_STYLE) == GAIA_XML_SLD_SE_RASTER_STYLE)
3178 sld_se_style = 1;
3179 return sld_se_style;
3180 }
3181
3182 GAIAGEO_DECLARE int
gaiaIsSldStyleXmlBlob(const unsigned char * blob,int blob_size)3183 gaiaIsSldStyleXmlBlob (const unsigned char *blob, int blob_size)
3184 {
3185 /* Checks if a valid XmlBLOB buffer does actually contains an SLD Style or not */
3186 int sld_style = 0;
3187 unsigned char flag;
3188
3189 /* validity check */
3190 if (!gaiaIsValidXmlBlob (blob, blob_size))
3191 return -1; /* cannot be an XmlBLOB */
3192 flag = *(blob + 1);
3193 if ((flag & GAIA_XML_SLD_STYLE) == GAIA_XML_SLD_STYLE)
3194 sld_style = 1;
3195 return sld_style;
3196 }
3197
3198 GAIAGEO_DECLARE int
gaiaIsMapConfigXmlBlob(const unsigned char * blob,int blob_size)3199 gaiaIsMapConfigXmlBlob (const unsigned char *blob, int blob_size)
3200 {
3201 /* Checks if a valid XmlBLOB buffer does actually contains a MapConfig or not */
3202 int sld_style = 0;
3203 unsigned char flag;
3204
3205 /* validity check */
3206 if (!gaiaIsValidXmlBlob (blob, blob_size))
3207 return -1; /* cannot be an XmlBLOB */
3208 flag = *(blob + 1);
3209 if ((flag & GAIA_XML_MAP_CONFIG) == GAIA_XML_MAP_CONFIG)
3210 sld_style = 1;
3211 return sld_style;
3212 }
3213
3214 GAIAGEO_DECLARE int
gaiaIsSvgXmlBlob(const unsigned char * blob,int blob_size)3215 gaiaIsSvgXmlBlob (const unsigned char *blob, int blob_size)
3216 {
3217 /* Checks if a valid XmlBLOB buffer does actually contains an SVG image or not */
3218 int svg = 0;
3219 unsigned char flag;
3220
3221 /* validity check */
3222 if (!gaiaIsValidXmlBlob (blob, blob_size))
3223 return -1; /* cannot be an XmlBLOB */
3224 flag = *(blob + 1);
3225 if ((flag & GAIA_XML_SVG) == GAIA_XML_SVG)
3226 svg = 1;
3227 return svg;
3228 }
3229
3230 GAIAGEO_DECLARE int
gaiaIsGpxXmlBlob(const unsigned char * blob,int blob_size)3231 gaiaIsGpxXmlBlob (const unsigned char *blob, int blob_size)
3232 {
3233 /* Checks if a valid XmlBLOB buffer does actually contains a GPX document or not */
3234 int gpx = 0;
3235 unsigned char flag;
3236
3237 /* validity check */
3238 if (!gaiaIsValidXmlBlob (blob, blob_size))
3239 return -1; /* cannot be an XmlBLOB */
3240 flag = *(blob + 1);
3241 if (((flag & GAIA_XML_GPX) == GAIA_XML_GPX)
3242 && ((flag & GAIA_XML_MAP_CONFIG) != GAIA_XML_MAP_CONFIG))
3243 gpx = 1;
3244 return gpx;
3245 }
3246
3247 GAIAGEO_DECLARE int
gaiaXmlBlobGetDocumentSize(const unsigned char * blob,int blob_size)3248 gaiaXmlBlobGetDocumentSize (const unsigned char *blob, int blob_size)
3249 {
3250 /* Return the XMLDocument size (in bytes) from a valid XmlBLOB buffer */
3251 int little_endian = 0;
3252 unsigned char flag;
3253 int xml_len;
3254 int endian_arch = gaiaEndianArch ();
3255
3256 /* validity check */
3257 if (!gaiaIsValidXmlBlob (blob, blob_size))
3258 return -1; /* cannot be an XmlBLOB */
3259 flag = *(blob + 1);
3260 if ((flag & GAIA_XML_LITTLE_ENDIAN) == GAIA_XML_LITTLE_ENDIAN)
3261 little_endian = 1;
3262 xml_len = gaiaImport32 (blob + 3, little_endian, endian_arch);
3263 return xml_len;
3264 }
3265
3266 GAIAGEO_DECLARE char *
gaiaXmlBlobGetSchemaURI(const unsigned char * blob,int blob_size)3267 gaiaXmlBlobGetSchemaURI (const unsigned char *blob, int blob_size)
3268 {
3269 /* Return the SchemaURI from a valid XmlBLOB buffer */
3270 int little_endian = 0;
3271 unsigned char flag;
3272 short uri_len;
3273 char *uri;
3274 int endian_arch = gaiaEndianArch ();
3275
3276 /* validity check */
3277 if (!gaiaIsValidXmlBlob (blob, blob_size))
3278 return NULL; /* cannot be an XmlBLOB */
3279 flag = *(blob + 1);
3280 if ((flag & GAIA_XML_LITTLE_ENDIAN) == GAIA_XML_LITTLE_ENDIAN)
3281 little_endian = 1;
3282 uri_len = gaiaImport16 (blob + 11, little_endian, endian_arch);
3283 if (!uri_len)
3284 return NULL;
3285
3286 uri = malloc (uri_len + 1);
3287 memcpy (uri, blob + 14, uri_len);
3288 *(uri + uri_len) = '\0';
3289 return uri;
3290 }
3291
3292 GAIAGEO_DECLARE char *
gaiaXmlGetInternalSchemaURI(const void * p_cache,const unsigned char * xml,int xml_len)3293 gaiaXmlGetInternalSchemaURI (const void *p_cache, const unsigned char *xml,
3294 int xml_len)
3295 {
3296 /* Return the internally defined SchemaURI from a valid XmlDocument */
3297 xmlDocPtr xml_doc;
3298 char *uri = NULL;
3299 xmlXPathContextPtr xpathCtx;
3300 xmlXPathObjectPtr xpathObj;
3301 xmlGenericErrorFunc silentError = (xmlGenericErrorFunc) spliteSilentError;
3302
3303 /* retrieving the XMLDocument internal SchemaURI (if any) */
3304 xmlSetGenericErrorFunc (NULL, silentError);
3305 xml_doc =
3306 xmlReadMemory ((const char *) xml, xml_len, "noname.xml", NULL, 0);
3307 if (xml_doc == NULL)
3308 {
3309 /* parsing error; not a well-formed XML */
3310 xmlSetGenericErrorFunc ((void *) stderr, NULL);
3311 return NULL;
3312 }
3313
3314 if (vxpath_eval_expr
3315 (p_cache, xml_doc, "/*/@xsi:schemaLocation", &xpathCtx, &xpathObj))
3316 {
3317 /* attempting first to extract xsi:schemaLocation */
3318 xmlNodeSetPtr nodeset = xpathObj->nodesetval;
3319 xmlNodePtr node;
3320 int num_nodes = (nodeset) ? nodeset->nodeNr : 0;
3321 if (num_nodes == 1)
3322 {
3323 node = nodeset->nodeTab[0];
3324 if (node->type == XML_ATTRIBUTE_NODE)
3325 {
3326 if (node->children != NULL)
3327 {
3328 if (node->children->content != NULL)
3329 {
3330 const char *str =
3331 (const char *) (node->children->content);
3332 const char *ptr = str;
3333 int i;
3334 int len = strlen (str);
3335 for (i = len - 1; i >= 0; i--)
3336 {
3337 if (*(str + i) == ' ')
3338 {
3339 /* last occurrence of SPACE [namespace/schema separator] */
3340 ptr = str + i + 1;
3341 break;
3342 }
3343 }
3344 len = strlen (ptr);
3345 uri = malloc (len + 1);
3346 strcpy (uri, ptr);
3347 }
3348 }
3349 }
3350 }
3351 if (uri != NULL)
3352 xmlXPathFreeContext (xpathCtx);
3353 xmlXPathFreeObject (xpathObj);
3354 }
3355 if (uri == NULL)
3356 {
3357 /* checking for xsi:noNamespaceSchemaLocation */
3358 if (vxpath_eval_expr
3359 (p_cache, xml_doc, "/*/@xsi:noNamespaceSchemaLocation", &xpathCtx,
3360 &xpathObj))
3361 {
3362 xmlNodeSetPtr nodeset = xpathObj->nodesetval;
3363 xmlNodePtr node;
3364 int num_nodes = (nodeset) ? nodeset->nodeNr : 0;
3365 if (num_nodes == 1)
3366 {
3367 node = nodeset->nodeTab[0];
3368 if (node->type == XML_ATTRIBUTE_NODE)
3369 {
3370 if (node->children != NULL)
3371 {
3372 if (node->children->content != NULL)
3373 {
3374 int len =
3375 strlen ((const char *)
3376 node->children->content);
3377 uri = malloc (len + 1);
3378 strcpy (uri,
3379 (const char *) node->
3380 children->content);
3381 }
3382 }
3383 }
3384 }
3385 xmlXPathFreeContext (xpathCtx);
3386 xmlXPathFreeObject (xpathObj);
3387 }
3388 }
3389
3390 xmlFreeDoc (xml_doc);
3391 xmlSetGenericErrorFunc ((void *) stderr, NULL);
3392 return uri;
3393 }
3394
3395 GAIAGEO_DECLARE char *
gaiaXmlBlobGetFileId(const unsigned char * blob,int blob_size)3396 gaiaXmlBlobGetFileId (const unsigned char *blob, int blob_size)
3397 {
3398 /* Return the FileIdentifier from a valid XmlBLOB buffer */
3399 int little_endian = 0;
3400 unsigned char flag;
3401 const unsigned char *ptr;
3402 short uri_len;
3403 short fileid_len;
3404 char *file_identifier;
3405 int endian_arch = gaiaEndianArch ();
3406
3407 /* validity check */
3408 if (!gaiaIsValidXmlBlob (blob, blob_size))
3409 return NULL; /* cannot be an XmlBLOB */
3410 flag = *(blob + 1);
3411 if ((flag & GAIA_XML_LITTLE_ENDIAN) == GAIA_XML_LITTLE_ENDIAN)
3412 little_endian = 1;
3413 ptr = blob + 11;
3414 uri_len = gaiaImport16 (ptr, little_endian, endian_arch);
3415 ptr += 3 + uri_len;
3416 fileid_len = gaiaImport16 (ptr, little_endian, endian_arch);
3417 if (!fileid_len)
3418 return NULL;
3419 ptr += 3;
3420
3421 file_identifier = malloc (fileid_len + 1);
3422 memcpy (file_identifier, ptr, fileid_len);
3423 *(file_identifier + fileid_len) = '\0';
3424 return file_identifier;
3425 }
3426
3427 GAIAGEO_DECLARE char *
gaiaXmlBlobGetParentId(const unsigned char * blob,int blob_size)3428 gaiaXmlBlobGetParentId (const unsigned char *blob, int blob_size)
3429 {
3430 /* Return the ParentIdentifier from a valid XmlBLOB buffer */
3431 int little_endian = 0;
3432 unsigned char flag;
3433 const unsigned char *ptr;
3434 short uri_len;
3435 short fileid_len;
3436 short parentid_len;
3437 char *parent_identifier;
3438 int endian_arch = gaiaEndianArch ();
3439
3440 /* validity check */
3441 if (!gaiaIsValidXmlBlob (blob, blob_size))
3442 return NULL; /* cannot be an XmlBLOB */
3443 flag = *(blob + 1);
3444 if ((flag & GAIA_XML_LITTLE_ENDIAN) == GAIA_XML_LITTLE_ENDIAN)
3445 little_endian = 1;
3446 ptr = blob + 11;
3447 uri_len = gaiaImport16 (ptr, little_endian, endian_arch);
3448 ptr += 3 + uri_len;
3449 fileid_len = gaiaImport16 (ptr, little_endian, endian_arch);
3450 ptr += 3 + fileid_len;
3451 parentid_len = gaiaImport16 (ptr, little_endian, endian_arch);
3452 if (!parentid_len)
3453 return NULL;
3454 ptr += 3;
3455
3456 parent_identifier = malloc (parentid_len + 1);
3457 memcpy (parent_identifier, ptr, parentid_len);
3458 *(parent_identifier + parentid_len) = '\0';
3459 return parent_identifier;
3460 }
3461
3462 static xmlNodePtr
find_iso_node(xmlNodePtr root,const char * name)3463 find_iso_node (xmlNodePtr root, const char *name)
3464 {
3465 /* scanning the Root node [fileIdentifier or parentIdentifier] */
3466 xmlNodePtr nodeId = NULL;
3467 xmlNodePtr node;
3468
3469 for (node = root->children; node; node = node->next)
3470 {
3471 if (node->type == XML_ELEMENT_NODE)
3472 {
3473 const char *xname = (const char *) (node->name);
3474 if (strcmp (xname, name) == 0)
3475 {
3476 nodeId = node;
3477 break;
3478 }
3479 }
3480 }
3481 if (nodeId == NULL)
3482 return NULL;
3483 for (node = nodeId->children; node; node = node->next)
3484 {
3485 if (node->type == XML_ELEMENT_NODE)
3486 {
3487 const char *xname = (const char *) (node->name);
3488 if (strcmp (xname, "CharacterString") == 0)
3489 return node;
3490 }
3491 }
3492 return NULL;
3493 }
3494
3495 static int
setIsoId(xmlDocPtr xml_doc,const char * node_name,const char * identifier,unsigned char ** out_blob,int * out_len)3496 setIsoId (xmlDocPtr xml_doc, const char *node_name, const char *identifier,
3497 unsigned char **out_blob, int *out_len)
3498 {
3499 /* attempting to change an ISO Id */
3500 xmlNodePtr node;
3501 xmlNodePtr new_node;
3502 xmlNodePtr text;
3503 xmlNodePtr old_node;
3504 xmlChar *buf;
3505 int len;
3506 *out_blob = NULL;
3507 *out_len = 0;
3508 node = find_iso_node (xmlDocGetRootElement (xml_doc), node_name);
3509 if (node == NULL)
3510 return 0;
3511 /* replacing the existing XML Node */
3512 new_node = xmlNewNode (node->ns, node->name);
3513 text = xmlNewText ((xmlChar *) identifier);
3514 xmlAddChild (new_node, text);
3515 old_node = xmlReplaceNode (node, new_node);
3516 xmlFreeNode (old_node);
3517 xmlDocDumpFormatMemory (xml_doc, &buf, &len, 0);
3518 if (buf == NULL)
3519 return 0;
3520 *out_blob = buf;
3521 *out_len = len;
3522 return 1;
3523 }
3524
3525 GAIAGEO_DECLARE int
gaiaXmlBlobSetFileId(const void * p_cache,const unsigned char * blob,int blob_size,const char * identifier,unsigned char ** new_blob,int * new_size)3526 gaiaXmlBlobSetFileId (const void *p_cache, const unsigned char *blob,
3527 int blob_size, const char *identifier,
3528 unsigned char **new_blob, int *new_size)
3529 {
3530 /* Return a new XmlBLOB buffer by replacing the FileId value */
3531 struct splite_internal_cache *cache =
3532 (struct splite_internal_cache *) p_cache;
3533 int compressed = 0;
3534 int little_endian = 0;
3535 unsigned char flag;
3536 const unsigned char *ptr;
3537 short uri_len;
3538 short fileid_len;
3539 short parentid_len;
3540 int xml_len;
3541 int zip_len;
3542 int name_len;
3543 short title_len;
3544 short abstract_len;
3545 short geometry_len;
3546 char *schemaURI = NULL;
3547 unsigned char *xml;
3548 xmlDocPtr xml_doc;
3549 unsigned char *out_blob;
3550 int out_len;
3551 int legacy_blob = 0;
3552 int endian_arch = gaiaEndianArch ();
3553 xmlGenericErrorFunc silentError = (xmlGenericErrorFunc) spliteSilentError;
3554
3555 *new_blob = NULL;
3556 *new_size = 0;
3557 /* validity check */
3558 if (!gaiaIsValidXmlBlob (blob, blob_size))
3559 return 0; /* cannot be an XmlBLOB */
3560 if (*(blob + 2) == GAIA_XML_LEGACY_HEADER)
3561 legacy_blob = 1;
3562 flag = *(blob + 1);
3563 if ((flag & GAIA_XML_ISO_METADATA) == GAIA_XML_ISO_METADATA)
3564 ;
3565 else
3566 return 0; /* not an ISO Metadata XmlBLOB */
3567 if ((flag & GAIA_XML_LITTLE_ENDIAN) == GAIA_XML_LITTLE_ENDIAN)
3568 little_endian = 1;
3569 if ((flag & GAIA_XML_COMPRESSED) == GAIA_XML_COMPRESSED)
3570 compressed = 1;
3571 xml_len = gaiaImport32 (blob + 3, little_endian, endian_arch);
3572 zip_len = gaiaImport32 (blob + 7, little_endian, endian_arch);
3573 ptr = blob + 11;
3574 uri_len = gaiaImport16 (ptr, little_endian, endian_arch);
3575 if (uri_len > 0)
3576 {
3577 schemaURI = malloc (uri_len + 1);
3578 memcpy (schemaURI, blob + 14, uri_len);
3579 *(schemaURI + uri_len) = '\0';
3580 }
3581 ptr += 3 + uri_len;
3582 fileid_len = gaiaImport16 (ptr, little_endian, endian_arch);
3583 ptr += 3 + fileid_len;
3584 parentid_len = gaiaImport16 (ptr, little_endian, endian_arch);
3585 ptr += 3 + parentid_len;
3586 if (!legacy_blob)
3587 {
3588 name_len = gaiaImport16 (ptr, little_endian, endian_arch);
3589 ptr += 3 + name_len;
3590 }
3591 title_len = gaiaImport16 (ptr, little_endian, endian_arch);
3592 ptr += 3 + title_len;
3593 abstract_len = gaiaImport16 (ptr, little_endian, endian_arch);
3594 ptr += 3 + abstract_len;
3595 geometry_len = gaiaImport16 (ptr, little_endian, endian_arch);
3596 ptr += 3 + geometry_len;
3597 ptr++;
3598
3599 if (compressed)
3600 {
3601 /* unzipping the XML payload */
3602 uLong refLen = xml_len;
3603 const Bytef *in = ptr;
3604 xml = malloc (xml_len + 1);
3605 if (uncompress (xml, &refLen, in, zip_len) != Z_OK)
3606 {
3607 /* uncompress error */
3608 spatialite_e ("XmlBLOB DEFLATE uncompress error\n");
3609 free (xml);
3610 return 0;
3611 }
3612 *(xml + xml_len) = '\0';
3613 }
3614 else
3615 {
3616 /* just copying the uncompressed XML payload */
3617 xml = malloc (xml_len + 1);
3618 memcpy (xml, ptr, xml_len);
3619 *(xml + xml_len) = '\0';
3620 }
3621 /* loading the XMLDocument */
3622 xmlSetGenericErrorFunc (NULL, silentError);
3623 xml_doc =
3624 xmlReadMemory ((const char *) xml, xml_len, "noname.xml", NULL, 0);
3625 if (xml_doc == NULL)
3626 {
3627 /* parsing error; not a well-formed XML */
3628 xmlSetGenericErrorFunc ((void *) stderr, NULL);
3629 return 0;
3630 }
3631 /* replacing the FileId value */
3632 setIsoId (xml_doc, "fileIdentifier", identifier, &out_blob, &out_len);
3633 free (xml);
3634 xmlFreeDoc (xml_doc);
3635 if (out_blob)
3636 {
3637 gaiaXmlToBlob (cache, out_blob, out_len, compressed, schemaURI,
3638 new_blob, new_size, NULL, NULL);
3639 #ifdef __MINGW32__
3640 /* MinGW is unable to statically link libxml2 if xmlFree() is declared */
3641 free (out_blob);
3642 #else
3643 xmlFree (out_blob);
3644 #endif
3645 xmlSetGenericErrorFunc ((void *) stderr, NULL);
3646 return 1;
3647 }
3648 xmlSetGenericErrorFunc ((void *) stderr, NULL);
3649 return 0;
3650 }
3651
3652 GAIAGEO_DECLARE int
gaiaXmlBlobSetParentId(const void * p_cache,const unsigned char * blob,int blob_size,const char * identifier,unsigned char ** new_blob,int * new_size)3653 gaiaXmlBlobSetParentId (const void *p_cache, const unsigned char *blob,
3654 int blob_size, const char *identifier,
3655 unsigned char **new_blob, int *new_size)
3656 {
3657 /* Return a new XmlBLOB buffer by replacing the ParentId value */
3658 struct splite_internal_cache *cache =
3659 (struct splite_internal_cache *) p_cache;
3660 int compressed = 0;
3661 int little_endian = 0;
3662 unsigned char flag;
3663 const unsigned char *ptr;
3664 short uri_len;
3665 short fileid_len;
3666 short parentid_len;
3667 int xml_len;
3668 int zip_len;
3669 short name_len;
3670 short title_len;
3671 short abstract_len;
3672 short geometry_len;
3673 char *schemaURI = NULL;
3674 unsigned char *xml;
3675 xmlDocPtr xml_doc;
3676 unsigned char *out_blob;
3677 int out_len;
3678 int legacy_blob = 0;
3679 int endian_arch = gaiaEndianArch ();
3680 xmlGenericErrorFunc silentError = (xmlGenericErrorFunc) spliteSilentError;
3681
3682 *new_blob = NULL;
3683 *new_size = 0;
3684 /* validity check */
3685 if (!gaiaIsValidXmlBlob (blob, blob_size))
3686 return 0; /* cannot be an XmlBLOB */
3687 if (*(blob + 2) == GAIA_XML_LEGACY_HEADER)
3688 legacy_blob = 1;
3689 flag = *(blob + 1);
3690 if ((flag & GAIA_XML_ISO_METADATA) == GAIA_XML_ISO_METADATA)
3691 ;
3692 else
3693 return 0; /* not an ISO Metadata XmlBLOB */
3694 if ((flag & GAIA_XML_LITTLE_ENDIAN) == GAIA_XML_LITTLE_ENDIAN)
3695 little_endian = 1;
3696 if ((flag & GAIA_XML_COMPRESSED) == GAIA_XML_COMPRESSED)
3697 compressed = 1;
3698 xml_len = gaiaImport32 (blob + 3, little_endian, endian_arch);
3699 zip_len = gaiaImport32 (blob + 7, little_endian, endian_arch);
3700 ptr = blob + 11;
3701 uri_len = gaiaImport16 (ptr, little_endian, endian_arch);
3702 if (uri_len > 0)
3703 {
3704 schemaURI = malloc (uri_len + 1);
3705 memcpy (schemaURI, blob + 14, uri_len);
3706 *(schemaURI + uri_len) = '\0';
3707 }
3708 ptr += 3 + uri_len;
3709 fileid_len = gaiaImport16 (ptr, little_endian, endian_arch);
3710 ptr += 3 + fileid_len;
3711 parentid_len = gaiaImport16 (ptr, little_endian, endian_arch);
3712 ptr += 3 + parentid_len;
3713 if (!legacy_blob)
3714 {
3715 name_len = gaiaImport16 (ptr, little_endian, endian_arch);
3716 ptr += 3 + name_len;
3717 }
3718 title_len = gaiaImport16 (ptr, little_endian, endian_arch);
3719 ptr += 3 + title_len;
3720 abstract_len = gaiaImport16 (ptr, little_endian, endian_arch);
3721 ptr += 3 + abstract_len;
3722 geometry_len = gaiaImport16 (ptr, little_endian, endian_arch);
3723 ptr += 3 + geometry_len;
3724 ptr++;
3725
3726 if (compressed)
3727 {
3728 /* unzipping the XML payload */
3729 uLong refLen = xml_len;
3730 const Bytef *in = ptr;
3731 xml = malloc (xml_len + 1);
3732 if (uncompress (xml, &refLen, in, zip_len) != Z_OK)
3733 {
3734 /* uncompress error */
3735 spatialite_e ("XmlBLOB DEFLATE uncompress error\n");
3736 free (xml);
3737 return 0;
3738 }
3739 *(xml + xml_len) = '\0';
3740 }
3741 else
3742 {
3743 /* just copying the uncompressed XML payload */
3744 xml = malloc (xml_len + 1);
3745 memcpy (xml, ptr, xml_len);
3746 *(xml + xml_len) = '\0';
3747 }
3748 /* loading the XMLDocument */
3749 xmlSetGenericErrorFunc (NULL, silentError);
3750 xml_doc =
3751 xmlReadMemory ((const char *) xml, xml_len, "noname.xml", NULL, 0);
3752 if (xml_doc == NULL)
3753 {
3754 /* parsing error; not a well-formed XML */
3755 xmlSetGenericErrorFunc ((void *) stderr, NULL);
3756 return 0;
3757 }
3758 /* replacing the ParentId value */
3759 setIsoId (xml_doc, "parentIdentifier", identifier, &out_blob, &out_len);
3760 free (xml);
3761 xmlFreeDoc (xml_doc);
3762 if (out_blob)
3763 {
3764 gaiaXmlToBlob (cache, out_blob, out_len, compressed, schemaURI,
3765 new_blob, new_size, NULL, NULL);
3766 #ifdef __MINGW32__
3767 /* MinGW is unable to statically link libxml2 if xmlFree() is declared */
3768 free (out_blob);
3769 #else
3770 xmlFree (out_blob);
3771 #endif
3772 xmlSetGenericErrorFunc ((void *) stderr, NULL);
3773 return 1;
3774 }
3775 xmlSetGenericErrorFunc ((void *) stderr, NULL);
3776 return 0;
3777 }
3778
3779 static xmlNodePtr
find_iso_sibling(xmlNodePtr root,const char * name)3780 find_iso_sibling (xmlNodePtr root, const char *name)
3781 {
3782 /* scanning the Root node [previous sibling] */
3783 xmlNodePtr node;
3784
3785 for (node = root->children; node; node = node->next)
3786 {
3787 if (node->type == XML_ELEMENT_NODE)
3788 {
3789 const char *xname = (const char *) (node->name);
3790 if (strcmp (xname, name) == 0)
3791 return node;
3792 }
3793 }
3794 return NULL;
3795 }
3796
3797 static int
addIsoId(xmlDocPtr xml_doc,const char * node_name,const char * identifier,const char * ns_id,const char * uri_id,const char * ns_charstr,const char * uri_charstr,unsigned char ** out_blob,int * out_len)3798 addIsoId (xmlDocPtr xml_doc, const char *node_name, const char *identifier,
3799 const char *ns_id, const char *uri_id, const char *ns_charstr,
3800 const char *uri_charstr, unsigned char **out_blob, int *out_len)
3801 {
3802 /* attempting to insert a new ISO Id */
3803 xmlNsPtr ns_id_ptr = NULL;
3804 xmlNsPtr ns_charstr_ptr = NULL;
3805 xmlNodePtr id_node;
3806 xmlNodePtr charstr_node;
3807 xmlNodePtr text;
3808 xmlNodePtr root = xmlDocGetRootElement (xml_doc);
3809 xmlNodePtr before = NULL;
3810 xmlChar *buf;
3811 int len;
3812 *out_blob = NULL;
3813 *out_len = 0;
3814 if (find_iso_node (root, node_name))
3815 return 0;
3816 /* retrieving the ID NameSpace */
3817 if (uri_id != NULL)
3818 ns_id_ptr = xmlSearchNsByHref (xml_doc, root, (xmlChar *) uri_id);
3819 if (ns_id_ptr == NULL)
3820 ns_id_ptr = xmlSearchNs (xml_doc, root, (xmlChar *) ns_id);
3821 /* inserting the "ID" XML Node */
3822 id_node = xmlNewNode (ns_id_ptr, (xmlChar *) node_name);
3823 if (strcmp (node_name, "parentIdentifier") == 0)
3824 {
3825 /* attempting to identify the previous sibling */
3826 before = find_iso_sibling (root, "characterSet");
3827 if (before == NULL)
3828 before = find_iso_sibling (root, "language");
3829 if (before == NULL)
3830 before = find_iso_sibling (root, "fileIdentifier");
3831 }
3832 if (before)
3833 xmlAddNextSibling (before, id_node);
3834 else
3835 {
3836 before = root->children;
3837 if (before)
3838 xmlAddPrevSibling (before, id_node);
3839 else
3840 xmlAddChild (root, id_node);
3841 }
3842 if (ns_id_ptr == NULL && ns_id != NULL && uri_id != NULL)
3843 {
3844 ns_id_ptr = xmlNewNs (root, (xmlChar *) uri_id, (xmlChar *) ns_id);
3845 xmlSetNs (id_node, ns_id_ptr);
3846 }
3847 /* retrieving the CharacterString NameSpace */
3848 if (uri_charstr != NULL)
3849 ns_charstr_ptr =
3850 xmlSearchNsByHref (xml_doc, root, (xmlChar *) uri_charstr);
3851 if (ns_charstr_ptr == NULL)
3852 ns_charstr_ptr = xmlSearchNs (xml_doc, root, (xmlChar *) ns_charstr);
3853 /* inserting the "CharacterString" XML Node */
3854 charstr_node = xmlNewNode (ns_charstr_ptr, (xmlChar *) "CharacterString");
3855 xmlAddChild (id_node, charstr_node);
3856 if (ns_charstr_ptr == NULL && ns_charstr != NULL && uri_charstr != NULL)
3857 {
3858 ns_charstr_ptr =
3859 xmlNewNs (root, (xmlChar *) uri_charstr, (xmlChar *) ns_charstr);
3860 xmlSetNs (charstr_node, ns_charstr_ptr);
3861 }
3862 text = xmlNewText ((xmlChar *) identifier);
3863 xmlAddChild (charstr_node, text);
3864 xmlDocDumpFormatMemory (xml_doc, &buf, &len, 0);
3865 if (buf == NULL)
3866 return 0;
3867 *out_blob = buf;
3868 *out_len = len;
3869 return 1;
3870 }
3871
3872 GAIAGEO_DECLARE int
gaiaXmlBlobAddFileId(const void * p_cache,const unsigned char * blob,int blob_size,const char * identifier,const char * ns_id,const char * uri_id,const char * ns_charstr,const char * uri_charstr,unsigned char ** new_blob,int * new_size)3873 gaiaXmlBlobAddFileId (const void *p_cache, const unsigned char *blob,
3874 int blob_size, const char *identifier, const char *ns_id,
3875 const char *uri_id, const char *ns_charstr,
3876 const char *uri_charstr, unsigned char **new_blob,
3877 int *new_size)
3878 {
3879 /* Return a new XmlBLOB buffer by inserting a FileId value */
3880 struct splite_internal_cache *cache =
3881 (struct splite_internal_cache *) p_cache;
3882 int compressed = 0;
3883 int little_endian = 0;
3884 unsigned char flag;
3885 const unsigned char *ptr;
3886 short uri_len;
3887 short fileid_len;
3888 short parentid_len;
3889 int xml_len;
3890 int zip_len;
3891 short name_len;
3892 short title_len;
3893 short abstract_len;
3894 short geometry_len;
3895 char *schemaURI = NULL;
3896 unsigned char *xml;
3897 xmlDocPtr xml_doc;
3898 unsigned char *out_blob;
3899 int out_len;
3900 int legacy_blob = 0;
3901 int endian_arch = gaiaEndianArch ();
3902 xmlGenericErrorFunc silentError = (xmlGenericErrorFunc) spliteSilentError;
3903
3904 *new_blob = NULL;
3905 *new_size = 0;
3906 /* validity check */
3907 if (!gaiaIsValidXmlBlob (blob, blob_size))
3908 return 0; /* cannot be an XmlBLOB */
3909 if (*(blob + 2) == GAIA_XML_LEGACY_HEADER)
3910 legacy_blob = 1;
3911 flag = *(blob + 1);
3912 if ((flag & GAIA_XML_ISO_METADATA) == GAIA_XML_ISO_METADATA)
3913 ;
3914 else
3915 return 0; /* not an ISO Metadata XmlBLOB */
3916 if ((flag & GAIA_XML_LITTLE_ENDIAN) == GAIA_XML_LITTLE_ENDIAN)
3917 little_endian = 1;
3918 if ((flag & GAIA_XML_COMPRESSED) == GAIA_XML_COMPRESSED)
3919 compressed = 1;
3920 xml_len = gaiaImport32 (blob + 3, little_endian, endian_arch);
3921 zip_len = gaiaImport32 (blob + 7, little_endian, endian_arch);
3922 ptr = blob + 11;
3923 uri_len = gaiaImport16 (ptr, little_endian, endian_arch);
3924 if (uri_len > 0)
3925 {
3926 schemaURI = malloc (uri_len + 1);
3927 memcpy (schemaURI, blob + 14, uri_len);
3928 *(schemaURI + uri_len) = '\0';
3929 }
3930 ptr += 3 + uri_len;
3931 fileid_len = gaiaImport16 (ptr, little_endian, endian_arch);
3932 ptr += 3 + fileid_len;
3933 parentid_len = gaiaImport16 (ptr, little_endian, endian_arch);
3934 ptr += 3 + parentid_len;
3935 if (!legacy_blob)
3936 {
3937 name_len = gaiaImport16 (ptr, little_endian, endian_arch);
3938 ptr += 3 + name_len;
3939 }
3940 title_len = gaiaImport16 (ptr, little_endian, endian_arch);
3941 ptr += 3 + title_len;
3942 abstract_len = gaiaImport16 (ptr, little_endian, endian_arch);
3943 ptr += 3 + abstract_len;
3944 geometry_len = gaiaImport16 (ptr, little_endian, endian_arch);
3945 ptr += 3 + geometry_len;
3946 ptr++;
3947
3948 if (compressed)
3949 {
3950 /* unzipping the XML payload */
3951 uLong refLen = xml_len;
3952 const Bytef *in = ptr;
3953 xml = malloc (xml_len + 1);
3954 if (uncompress (xml, &refLen, in, zip_len) != Z_OK)
3955 {
3956 /* uncompress error */
3957 spatialite_e ("XmlBLOB DEFLATE uncompress error\n");
3958 free (xml);
3959 return 0;
3960 }
3961 *(xml + xml_len) = '\0';
3962 }
3963 else
3964 {
3965 /* just copying the uncompressed XML payload */
3966 xml = malloc (xml_len + 1);
3967 memcpy (xml, ptr, xml_len);
3968 *(xml + xml_len) = '\0';
3969 }
3970 /* loading the XMLDocument */
3971 xmlSetGenericErrorFunc (NULL, silentError);
3972 xml_doc =
3973 xmlReadMemory ((const char *) xml, xml_len, "noname.xml", NULL, 0);
3974 if (xml_doc == NULL)
3975 {
3976 /* parsing error; not a well-formed XML */
3977 xmlSetGenericErrorFunc ((void *) stderr, NULL);
3978 return 0;
3979 }
3980 /* inserting the FileId value */
3981 addIsoId (xml_doc, "fileIdentifier", identifier, ns_id, uri_id, ns_charstr,
3982 uri_charstr, &out_blob, &out_len);
3983 free (xml);
3984 xmlFreeDoc (xml_doc);
3985 if (out_blob)
3986 {
3987 gaiaXmlToBlob (cache, out_blob, out_len, compressed, schemaURI,
3988 new_blob, new_size, NULL, NULL);
3989 #ifdef __MINGW32__
3990 /* MinGW is unable to statically link libxml2 if xmlFree() is declared */
3991 free (out_blob);
3992 #else
3993 xmlFree (out_blob);
3994 #endif
3995 xmlSetGenericErrorFunc ((void *) stderr, NULL);
3996 return 1;
3997 }
3998 xmlSetGenericErrorFunc ((void *) stderr, NULL);
3999 return 0;
4000 }
4001
4002 GAIAGEO_DECLARE int
gaiaXmlBlobAddParentId(const void * p_cache,const unsigned char * blob,int blob_size,const char * identifier,const char * ns_id,const char * uri_id,const char * ns_charstr,const char * uri_charstr,unsigned char ** new_blob,int * new_size)4003 gaiaXmlBlobAddParentId (const void *p_cache, const unsigned char *blob,
4004 int blob_size, const char *identifier,
4005 const char *ns_id, const char *uri_id,
4006 const char *ns_charstr, const char *uri_charstr,
4007 unsigned char **new_blob, int *new_size)
4008 {
4009 /* Return a new XmlBLOB buffer by inserting a ParentId value */
4010 struct splite_internal_cache *cache =
4011 (struct splite_internal_cache *) p_cache;
4012 int compressed = 0;
4013 int little_endian = 0;
4014 unsigned char flag;
4015 const unsigned char *ptr;
4016 short uri_len;
4017 short fileid_len;
4018 short parentid_len;
4019 int xml_len;
4020 int zip_len;
4021 short name_len;
4022 short title_len;
4023 short abstract_len;
4024 short geometry_len;
4025 char *schemaURI = NULL;
4026 unsigned char *xml;
4027 xmlDocPtr xml_doc;
4028 unsigned char *out_blob;
4029 int out_len;
4030 int legacy_blob = 0;
4031 int endian_arch = gaiaEndianArch ();
4032 xmlGenericErrorFunc silentError = (xmlGenericErrorFunc) spliteSilentError;
4033
4034 *new_blob = NULL;
4035 *new_size = 0;
4036 /* validity check */
4037 if (!gaiaIsValidXmlBlob (blob, blob_size))
4038 return 0; /* cannot be an XmlBLOB */
4039 if (*(blob + 2) == GAIA_XML_LEGACY_HEADER)
4040 legacy_blob = 1;
4041 flag = *(blob + 1);
4042 if ((flag & GAIA_XML_ISO_METADATA) == GAIA_XML_ISO_METADATA)
4043 ;
4044 else
4045 return 0; /* not an ISO Metadata XmlBLOB */
4046 if ((flag & GAIA_XML_LITTLE_ENDIAN) == GAIA_XML_LITTLE_ENDIAN)
4047 little_endian = 1;
4048 if ((flag & GAIA_XML_COMPRESSED) == GAIA_XML_COMPRESSED)
4049 compressed = 1;
4050 xml_len = gaiaImport32 (blob + 3, little_endian, endian_arch);
4051 zip_len = gaiaImport32 (blob + 7, little_endian, endian_arch);
4052 ptr = blob + 11;
4053 uri_len = gaiaImport16 (ptr, little_endian, endian_arch);
4054 if (uri_len > 0)
4055 {
4056 schemaURI = malloc (uri_len + 1);
4057 memcpy (schemaURI, blob + 14, uri_len);
4058 *(schemaURI + uri_len) = '\0';
4059 }
4060 ptr += 3 + uri_len;
4061 fileid_len = gaiaImport16 (ptr, little_endian, endian_arch);
4062 ptr += 3 + fileid_len;
4063 parentid_len = gaiaImport16 (ptr, little_endian, endian_arch);
4064 ptr += 3 + parentid_len;
4065 if (!legacy_blob)
4066 {
4067 name_len = gaiaImport16 (ptr, little_endian, endian_arch);
4068 ptr += 3 + name_len;
4069 }
4070 title_len = gaiaImport16 (ptr, little_endian, endian_arch);
4071 ptr += 3 + title_len;
4072 abstract_len = gaiaImport16 (ptr, little_endian, endian_arch);
4073 ptr += 3 + abstract_len;
4074 geometry_len = gaiaImport16 (ptr, little_endian, endian_arch);
4075 ptr += 3 + geometry_len;
4076 ptr++;
4077
4078 if (compressed)
4079 {
4080 /* unzipping the XML payload */
4081 uLong refLen = xml_len;
4082 const Bytef *in = ptr;
4083 xml = malloc (xml_len + 1);
4084 if (uncompress (xml, &refLen, in, zip_len) != Z_OK)
4085 {
4086 /* uncompress error */
4087 spatialite_e ("XmlBLOB DEFLATE uncompress error\n");
4088 free (xml);
4089 return 0;
4090 }
4091 *(xml + xml_len) = '\0';
4092 }
4093 else
4094 {
4095 /* just copying the uncompressed XML payload */
4096 xml = malloc (xml_len + 1);
4097 memcpy (xml, ptr, xml_len);
4098 *(xml + xml_len) = '\0';
4099 }
4100 /* loading the XMLDocument */
4101 xmlSetGenericErrorFunc (NULL, silentError);
4102 xml_doc =
4103 xmlReadMemory ((const char *) xml, xml_len, "noname.xml", NULL, 0);
4104 if (xml_doc == NULL)
4105 {
4106 /* parsing error; not a well-formed XML */
4107 xmlSetGenericErrorFunc ((void *) stderr, NULL);
4108 return 0;
4109 }
4110 /* inserting the ParentId value */
4111 addIsoId (xml_doc, "parentIdentifier", identifier, ns_id, uri_id,
4112 ns_charstr, uri_charstr, &out_blob, &out_len);
4113 free (xml);
4114 xmlFreeDoc (xml_doc);
4115 if (out_blob)
4116 {
4117 gaiaXmlToBlob (cache, out_blob, out_len, compressed, schemaURI,
4118 new_blob, new_size, NULL, NULL);
4119 #ifdef __MINGW32__
4120 /* MinGW is unable to statically link libxml2 if xmlFree() is declared */
4121 free (out_blob);
4122 #else
4123 xmlFree (out_blob);
4124 #endif
4125 xmlSetGenericErrorFunc ((void *) stderr, NULL);
4126 return 1;
4127 }
4128 xmlSetGenericErrorFunc ((void *) stderr, NULL);
4129 return 0;
4130 }
4131
4132 GAIAGEO_DECLARE char *
gaiaXmlBlobGetName(const unsigned char * blob,int blob_size)4133 gaiaXmlBlobGetName (const unsigned char *blob, int blob_size)
4134 {
4135 /* Return the Name from a valid XmlBLOB buffer */
4136 int little_endian = 0;
4137 unsigned char flag;
4138 const unsigned char *ptr;
4139 short uri_len;
4140 short fileid_len;
4141 short parentid_len;
4142 short name_len;
4143 char *name;
4144 int endian_arch = gaiaEndianArch ();
4145
4146 /* validity check */
4147 if (!gaiaIsValidXmlBlob (blob, blob_size))
4148 return NULL; /* cannot be an XmlBLOB */
4149 if (*(blob + 2) == GAIA_XML_LEGACY_HEADER)
4150 return NULL;
4151 flag = *(blob + 1);
4152 if ((flag & GAIA_XML_LITTLE_ENDIAN) == GAIA_XML_LITTLE_ENDIAN)
4153 little_endian = 1;
4154 ptr = blob + 11;
4155 uri_len = gaiaImport16 (ptr, little_endian, endian_arch);
4156 ptr += 3 + uri_len;
4157 fileid_len = gaiaImport16 (ptr, little_endian, endian_arch);
4158 ptr += 3 + fileid_len;
4159 parentid_len = gaiaImport16 (ptr, little_endian, endian_arch);
4160 ptr += 3 + parentid_len;
4161 name_len = gaiaImport16 (ptr, little_endian, endian_arch);
4162 if (!name_len)
4163 return NULL;
4164 ptr += 3;
4165
4166 name = malloc (name_len + 1);
4167 memcpy (name, ptr, name_len);
4168 *(name + name_len) = '\0';
4169 return name;
4170 }
4171
4172 GAIAGEO_DECLARE char *
gaiaXmlBlobGetTitle(const unsigned char * blob,int blob_size)4173 gaiaXmlBlobGetTitle (const unsigned char *blob, int blob_size)
4174 {
4175 /* Return the Title from a valid XmlBLOB buffer */
4176 int little_endian = 0;
4177 unsigned char flag;
4178 const unsigned char *ptr;
4179 short uri_len;
4180 short fileid_len;
4181 short parentid_len;
4182 short name_len;
4183 short title_len;
4184 char *title;
4185 int legacy_blob = 0;
4186 int endian_arch = gaiaEndianArch ();
4187
4188 /* validity check */
4189 if (!gaiaIsValidXmlBlob (blob, blob_size))
4190 return NULL; /* cannot be an XmlBLOB */
4191 if (*(blob + 2) == GAIA_XML_LEGACY_HEADER)
4192 legacy_blob = 1;
4193 flag = *(blob + 1);
4194 if ((flag & GAIA_XML_LITTLE_ENDIAN) == GAIA_XML_LITTLE_ENDIAN)
4195 little_endian = 1;
4196 ptr = blob + 11;
4197 uri_len = gaiaImport16 (ptr, little_endian, endian_arch);
4198 ptr += 3 + uri_len;
4199 fileid_len = gaiaImport16 (ptr, little_endian, endian_arch);
4200 ptr += 3 + fileid_len;
4201 parentid_len = gaiaImport16 (ptr, little_endian, endian_arch);
4202 ptr += 3 + parentid_len;
4203 if (!legacy_blob)
4204 {
4205 name_len = gaiaImport16 (ptr, little_endian, endian_arch);
4206 ptr += 3 + name_len;
4207 }
4208 title_len = gaiaImport16 (ptr, little_endian, endian_arch);
4209 if (!title_len)
4210 return NULL;
4211 ptr += 3;
4212
4213 title = malloc (title_len + 1);
4214 memcpy (title, ptr, title_len);
4215 *(title + title_len) = '\0';
4216 return title;
4217 }
4218
4219 GAIAGEO_DECLARE char *
gaiaXmlBlobGetAbstract(const unsigned char * blob,int blob_size)4220 gaiaXmlBlobGetAbstract (const unsigned char *blob, int blob_size)
4221 {
4222 /* Return the Abstract from a valid XmlBLOB buffer */
4223 int little_endian = 0;
4224 unsigned char flag;
4225 const unsigned char *ptr;
4226 short uri_len;
4227 short fileid_len;
4228 short parentid_len;
4229 short name_len;
4230 short title_len;
4231 short abstract_len;
4232 char *abstract;
4233 int legacy_blob = 0;
4234 int endian_arch = gaiaEndianArch ();
4235
4236 /* validity check */
4237 if (!gaiaIsValidXmlBlob (blob, blob_size))
4238 return NULL; /* cannot be an XmlBLOB */
4239 if (*(blob + 2) == GAIA_XML_LEGACY_HEADER)
4240 legacy_blob = 1;
4241 flag = *(blob + 1);
4242 if ((flag & GAIA_XML_LITTLE_ENDIAN) == GAIA_XML_LITTLE_ENDIAN)
4243 little_endian = 1;
4244 ptr = blob + 11;
4245 uri_len = gaiaImport16 (ptr, little_endian, endian_arch);
4246 ptr += 3 + uri_len;
4247 fileid_len = gaiaImport16 (ptr, little_endian, endian_arch);
4248 ptr += 3 + fileid_len;
4249 parentid_len = gaiaImport16 (ptr, little_endian, endian_arch);
4250 ptr += 3 + parentid_len;
4251 if (!legacy_blob)
4252 {
4253 name_len = gaiaImport16 (ptr, little_endian, endian_arch);
4254 ptr += 3 + name_len;
4255 }
4256 title_len = gaiaImport16 (ptr, little_endian, endian_arch);
4257 ptr += 3 + title_len;
4258 abstract_len = gaiaImport16 (ptr, little_endian, endian_arch);
4259 if (!abstract_len)
4260 return NULL;
4261 ptr += 3;
4262
4263 abstract = malloc (abstract_len + 1);
4264 memcpy (abstract, ptr, abstract_len);
4265 *(abstract + abstract_len) = '\0';
4266 return abstract;
4267 }
4268
4269 GAIAGEO_DECLARE void
gaiaXmlBlobGetGeometry(const unsigned char * blob,int blob_size,unsigned char ** blob_geom,int * geom_size)4270 gaiaXmlBlobGetGeometry (const unsigned char *blob, int blob_size,
4271 unsigned char **blob_geom, int *geom_size)
4272 {
4273 /* Return the Geometry from a valid XmlBLOB buffer */
4274 int little_endian = 0;
4275 unsigned char flag;
4276 const unsigned char *ptr;
4277 short uri_len;
4278 short fileid_len;
4279 short parentid_len;
4280 short name_len;
4281 short title_len;
4282 short abstract_len;
4283 short geometry_len;
4284 unsigned char *geometry;
4285 int legacy_blob = 0;
4286 int endian_arch = gaiaEndianArch ();
4287
4288 *blob_geom = NULL;
4289 *geom_size = 0;
4290
4291 /* validity check */
4292 if (!gaiaIsValidXmlBlob (blob, blob_size))
4293 return; /* cannot be an XmlBLOB */
4294 if (*(blob + 2) == GAIA_XML_LEGACY_HEADER)
4295 legacy_blob = 1;
4296 flag = *(blob + 1);
4297 if ((flag & GAIA_XML_LITTLE_ENDIAN) == GAIA_XML_LITTLE_ENDIAN)
4298 little_endian = 1;
4299 ptr = blob + 11;
4300 uri_len = gaiaImport16 (ptr, little_endian, endian_arch);
4301 ptr += 3 + uri_len;
4302 fileid_len = gaiaImport16 (ptr, little_endian, endian_arch);
4303 ptr += 3 + fileid_len;
4304 parentid_len = gaiaImport16 (ptr, little_endian, endian_arch);
4305 ptr += 3 + parentid_len;
4306 if (!legacy_blob)
4307 {
4308 name_len = gaiaImport16 (ptr, little_endian, endian_arch);
4309 ptr += 3 + name_len;
4310 }
4311 title_len = gaiaImport16 (ptr, little_endian, endian_arch);
4312 ptr += 3 + title_len;
4313 abstract_len = gaiaImport16 (ptr, little_endian, endian_arch);
4314 ptr += 3 + abstract_len;
4315 geometry_len = gaiaImport16 (ptr, little_endian, endian_arch);
4316 if (!geometry_len)
4317 return;
4318 ptr += 3;
4319
4320 geometry = malloc (geometry_len);
4321 memcpy (geometry, ptr, geometry_len);
4322 *blob_geom = geometry;
4323 *geom_size = geometry_len;
4324 }
4325
4326 GAIAGEO_DECLARE char *
gaiaXmlBlobGetEncoding(const unsigned char * blob,int blob_size)4327 gaiaXmlBlobGetEncoding (const unsigned char *blob, int blob_size)
4328 {
4329 /* Return the Charset Encoding from a valid XmlBLOB buffer */
4330 int compressed = 0;
4331 int little_endian = 0;
4332 unsigned char flag;
4333 const unsigned char *ptr;
4334 int xml_len;
4335 int zip_len;
4336 short uri_len;
4337 short fileid_len;
4338 short parentid_len;
4339 short name_len;
4340 short title_len;
4341 short abstract_len;
4342 short geometry_len;
4343 unsigned char *xml;
4344 xmlDocPtr xml_doc;
4345 char *encoding = NULL;
4346 int legacy_blob = 0;
4347 int endian_arch = gaiaEndianArch ();
4348 xmlGenericErrorFunc silentError = (xmlGenericErrorFunc) spliteSilentError;
4349
4350 /* validity check */
4351 if (!gaiaIsValidXmlBlob (blob, blob_size))
4352 return NULL; /* cannot be an XmlBLOB */
4353 if (*(blob + 2) == GAIA_XML_LEGACY_HEADER)
4354 legacy_blob = 1;
4355 flag = *(blob + 1);
4356 if ((flag & GAIA_XML_LITTLE_ENDIAN) == GAIA_XML_LITTLE_ENDIAN)
4357 little_endian = 1;
4358 if ((flag & GAIA_XML_COMPRESSED) == GAIA_XML_COMPRESSED)
4359 compressed = 1;
4360 xml_len = gaiaImport32 (blob + 3, little_endian, endian_arch);
4361 zip_len = gaiaImport32 (blob + 7, little_endian, endian_arch);
4362 ptr = blob + 11;
4363 uri_len = gaiaImport16 (ptr, little_endian, endian_arch);
4364 ptr += 3 + uri_len;
4365 fileid_len = gaiaImport16 (ptr, little_endian, endian_arch);
4366 ptr += 3 + fileid_len;
4367 parentid_len = gaiaImport16 (ptr, little_endian, endian_arch);
4368 ptr += 3 + parentid_len;
4369 if (!legacy_blob)
4370 {
4371 name_len = gaiaImport16 (ptr, little_endian, endian_arch);
4372 ptr += 3 + name_len;
4373 }
4374 title_len = gaiaImport16 (ptr, little_endian, endian_arch);
4375 ptr += 3 + title_len;
4376 abstract_len = gaiaImport16 (ptr, little_endian, endian_arch);
4377 ptr += 3 + abstract_len;
4378 geometry_len = gaiaImport16 (ptr, little_endian, endian_arch);
4379 ptr += 3 + geometry_len;
4380 ptr++;
4381 if (compressed)
4382 {
4383 /* unzipping the XML payload */
4384 uLong refLen = xml_len;
4385 const Bytef *in = ptr;
4386 xml = malloc (xml_len + 1);
4387 if (uncompress (xml, &refLen, in, zip_len) != Z_OK)
4388 {
4389 /* uncompress error */
4390 spatialite_e ("XmlBLOB DEFLATE uncompress error\n");
4391 free (xml);
4392 return NULL;
4393 }
4394 *(xml + xml_len) = '\0';
4395 }
4396 else
4397 {
4398 /* just copying the uncompressed XML payload */
4399 xml = malloc (xml_len + 1);
4400 memcpy (xml, ptr, xml_len);
4401 *(xml + xml_len) = '\0';
4402 }
4403 /* retrieving the XMLDocument encoding */
4404 xmlSetGenericErrorFunc (NULL, silentError);
4405 xml_doc =
4406 xmlReadMemory ((const char *) xml, xml_len, "noname.xml", NULL, 0);
4407 if (xml_doc == NULL)
4408 {
4409 /* parsing error; not a well-formed XML */
4410 xmlSetGenericErrorFunc ((void *) stderr, NULL);
4411 return NULL;
4412 }
4413 free (xml);
4414 if (xml_doc->encoding)
4415 {
4416 /* using the internal character enconding */
4417 int enclen = strlen ((const char *) xml_doc->encoding);
4418 encoding = malloc (enclen + 1);
4419 strcpy (encoding, (const char *) xml_doc->encoding);
4420 xmlFreeDoc (xml_doc);
4421 xmlSetGenericErrorFunc ((void *) stderr, NULL);
4422 return encoding;
4423 }
4424 xmlFreeDoc (xml_doc);
4425 xmlSetGenericErrorFunc ((void *) stderr, NULL);
4426 return NULL;
4427 }
4428
4429 static void
parse_gpx_trkpt_values(xmlNodePtr node,double * x,double * y)4430 parse_gpx_trkpt_values (xmlNodePtr node, double *x, double *y)
4431 {
4432 /* fetching values from a GPX <trkpt> tag */
4433 struct _xmlAttr *attr;
4434
4435 *x = 0.0;
4436 *y = 0.0;
4437
4438 attr = node->properties;
4439 while (attr != NULL)
4440 {
4441 /* attributes */
4442 if (attr->type == XML_ATTRIBUTE_NODE)
4443 {
4444 const char *name = (const char *) (attr->name);
4445 xmlNode *text = attr->children;
4446 if (strcmp (name, "lat") == 0 && text != NULL)
4447 *y = atof ((const char *) (text->content));
4448 if (strcmp (name, "lon") == 0 && text != NULL)
4449 *x = atof ((const char *) (text->content));
4450 }
4451 attr = attr->next;
4452 }
4453 }
4454
4455 static double
gpx_time2m(sqlite3_stmt * stmt,const char * timestamp)4456 gpx_time2m (sqlite3_stmt * stmt, const char *timestamp)
4457 {
4458 /* transforming a timestamp into an M-value */
4459 double m = 0.0;
4460 int ret;
4461
4462 sqlite3_reset (stmt);
4463 sqlite3_clear_bindings (stmt);
4464 sqlite3_bind_text (stmt, 1, timestamp, strlen (timestamp), SQLITE_STATIC);
4465 while (1)
4466 {
4467 /* scrolling the result set rows */
4468 ret = sqlite3_step (stmt);
4469 if (ret == SQLITE_DONE)
4470 break; /* end of result set */
4471 if (ret == SQLITE_ROW)
4472 {
4473 if (sqlite3_column_type (stmt, 0) == SQLITE_FLOAT)
4474 m = sqlite3_column_double (stmt, 0);
4475 }
4476 }
4477 return m;
4478 }
4479
4480 static void
parse_gpx_trkpt_children(xmlNodePtr node,sqlite3_stmt * stmt,double * z,double * m)4481 parse_gpx_trkpt_children (xmlNodePtr node, sqlite3_stmt * stmt, double *z,
4482 double *m)
4483 {
4484 /* parsing the children of a GPX <trkpt> tag */
4485 xmlNode *text;
4486 *z = 0.0;
4487 *m = 1721059.500000; /* 0000-01-01T00:00:00Z */
4488
4489 while (node)
4490 {
4491 if (node->type == XML_ELEMENT_NODE)
4492 {
4493 const char *name = (const char *) (node->name);
4494 if (strcmp (name, "ele") == 0)
4495 {
4496 text = node->children;
4497 if (text != NULL)
4498 *z = atof ((const char *) (text->content));
4499 }
4500 if (strcmp (name, "time") == 0)
4501 {
4502 text = node->children;
4503 if (text != NULL)
4504 *m = gpx_time2m (stmt,
4505 (const char *) (text->content));
4506 }
4507 }
4508 node = node->next;
4509 }
4510 }
4511
4512 static void
parse_gpx_trkpt_tag(xmlNodePtr node,sqlite3_stmt * stmt,gaiaDynamicLinePtr dyn)4513 parse_gpx_trkpt_tag (xmlNodePtr node, sqlite3_stmt * stmt,
4514 gaiaDynamicLinePtr dyn)
4515 {
4516 /* parsing a GPX <trkpt> tag */
4517
4518 while (node)
4519 {
4520 if (node->type == XML_ELEMENT_NODE)
4521 {
4522 const char *name = (const char *) (node->name);
4523 if (strcmp (name, "trkpt") == 0)
4524 {
4525 double x;
4526 double y;
4527 double z;
4528 double m;
4529 parse_gpx_trkpt_values (node, &x, &y);
4530 parse_gpx_trkpt_children (node->children, stmt, &z, &m);
4531 gaiaAppendPointZMToDynamicLine (dyn, x, y, z, m);
4532 }
4533 }
4534 node = node->next;
4535 }
4536 }
4537
4538 static void
gpx_copy_line(gaiaDynamicLinePtr dyn,gaiaGeomCollPtr geom)4539 gpx_copy_line (gaiaDynamicLinePtr dyn, gaiaGeomCollPtr geom)
4540 {
4541 /* copying a Linestring from a DynamicLine */
4542 gaiaPointPtr pt;
4543 int pts = 0;
4544 gaiaLinestringPtr ln;
4545 int iv;
4546
4547 pt = dyn->First;
4548 while (pt != NULL)
4549 {
4550 /* counting how many points */
4551 pts++;
4552 pt = pt->Next;
4553 }
4554 if (pts < 2)
4555 return;
4556
4557 ln = gaiaAddLinestringToGeomColl (geom, pts);
4558 iv = 0;
4559 pt = dyn->First;
4560 while (pt != NULL)
4561 {
4562 /* copying points */
4563 gaiaSetPointXYZM (ln->Coords, iv, pt->X, pt->Y, pt->Z, pt->M);
4564 iv++;
4565 pt = pt->Next;
4566 }
4567 }
4568
4569 static void
parse_gpx_trkseg_tag(xmlNodePtr node,sqlite3_stmt * stmt,gaiaGeomCollPtr geom)4570 parse_gpx_trkseg_tag (xmlNodePtr node, sqlite3_stmt * stmt,
4571 gaiaGeomCollPtr geom)
4572 {
4573 /* parsing a GPX <trkseg> tag */
4574
4575 while (node)
4576 {
4577 if (node->type == XML_ELEMENT_NODE)
4578 {
4579 const char *name = (const char *) (node->name);
4580 if (strcmp (name, "trkseg") == 0)
4581 {
4582 gaiaDynamicLinePtr dyn = gaiaAllocDynamicLine ();
4583 parse_gpx_trkpt_tag (node->children, stmt, dyn);
4584 gpx_copy_line (dyn, geom);
4585 gaiaFreeDynamicLine (dyn);
4586 }
4587 }
4588 node = node->next;
4589 }
4590 }
4591
4592 static void
parse_gpx_trk_tag(xmlNodePtr node,sqlite3_stmt * stmt,gaiaGeomCollPtr geom)4593 parse_gpx_trk_tag (xmlNodePtr node, sqlite3_stmt * stmt, gaiaGeomCollPtr geom)
4594 {
4595 /* parsing a GPX <trk> tag */
4596
4597 while (node)
4598 {
4599 if (node->type == XML_ELEMENT_NODE)
4600 {
4601 const char *name = (const char *) (node->name);
4602 if (strcmp (name, "trk") == 0)
4603 parse_gpx_trkseg_tag (node->children, stmt, geom);
4604 }
4605 node = node->next;
4606 }
4607 }
4608
4609 static void
parse_gpx_tag(xmlNodePtr node,sqlite3_stmt * stmt,gaiaGeomCollPtr geom)4610 parse_gpx_tag (xmlNodePtr node, sqlite3_stmt * stmt, gaiaGeomCollPtr geom)
4611 {
4612 /* parsing a GPX document */
4613
4614 while (node)
4615 {
4616 if (node->type == XML_ELEMENT_NODE)
4617 {
4618 const char *name = (const char *) (node->name);
4619 if (strcmp (name, "gpx") == 0)
4620 parse_gpx_trk_tag (node->children, stmt, geom);
4621 }
4622 node = node->next;
4623 }
4624 }
4625
4626 static void
parse_gpx(xmlDocPtr xml_doc,sqlite3_stmt * stmt,gaiaGeomCollPtr geom)4627 parse_gpx (xmlDocPtr xml_doc, sqlite3_stmt * stmt, gaiaGeomCollPtr geom)
4628 {
4629 /* attempting to parse a GPX document */
4630 xmlNodePtr root = xmlDocGetRootElement (xml_doc);
4631 parse_gpx_tag (root, stmt, geom);
4632 }
4633
4634 GAIAGEO_DECLARE gaiaGeomCollPtr
gaiaXmlBlobMLineFromGPX(const unsigned char * blob,int blob_size,sqlite3 * sqlite)4635 gaiaXmlBlobMLineFromGPX (const unsigned char *blob, int blob_size,
4636 sqlite3 * sqlite)
4637 {
4638 /* Return a MultiLinestring Geometry from a valid XmlBLOB buffer of the GPX type */
4639 int ret;
4640 const char *sql;
4641 sqlite3_stmt *stmt = NULL;
4642 int compressed = 0;
4643 int little_endian = 0;
4644 unsigned char flag;
4645 const unsigned char *ptr;
4646 int xml_len;
4647 int zip_len;
4648 short uri_len;
4649 short fileid_len;
4650 short parentid_len;
4651 short name_len;
4652 short title_len;
4653 short abstract_len;
4654 short geometry_len;
4655 unsigned char *xml;
4656 xmlDocPtr xml_doc;
4657 int legacy_blob = 0;
4658 int endian_arch = gaiaEndianArch ();
4659 xmlGenericErrorFunc silentError = (xmlGenericErrorFunc) spliteSilentError;
4660 gaiaGeomCollPtr geom = NULL;
4661
4662 /* validity check */
4663 if (!gaiaIsValidXmlBlob (blob, blob_size))
4664 return NULL; /* cannot be an XmlBLOB */
4665 if (!gaiaIsGpxXmlBlob (blob, blob_size))
4666 return NULL; /* not a GPX document */
4667 if (*(blob + 2) == GAIA_XML_LEGACY_HEADER)
4668 legacy_blob = 1;
4669 flag = *(blob + 1);
4670 if ((flag & GAIA_XML_LITTLE_ENDIAN) == GAIA_XML_LITTLE_ENDIAN)
4671 little_endian = 1;
4672 if ((flag & GAIA_XML_COMPRESSED) == GAIA_XML_COMPRESSED)
4673 compressed = 1;
4674 xml_len = gaiaImport32 (blob + 3, little_endian, endian_arch);
4675 zip_len = gaiaImport32 (blob + 7, little_endian, endian_arch);
4676 ptr = blob + 11;
4677 uri_len = gaiaImport16 (ptr, little_endian, endian_arch);
4678 ptr += 3 + uri_len;
4679 fileid_len = gaiaImport16 (ptr, little_endian, endian_arch);
4680 ptr += 3 + fileid_len;
4681 parentid_len = gaiaImport16 (ptr, little_endian, endian_arch);
4682 ptr += 3 + parentid_len;
4683 if (!legacy_blob)
4684 {
4685 name_len = gaiaImport16 (ptr, little_endian, endian_arch);
4686 ptr += 3 + name_len;
4687 }
4688 title_len = gaiaImport16 (ptr, little_endian, endian_arch);
4689 ptr += 3 + title_len;
4690 abstract_len = gaiaImport16 (ptr, little_endian, endian_arch);
4691 ptr += 3 + abstract_len;
4692 geometry_len = gaiaImport16 (ptr, little_endian, endian_arch);
4693 ptr += 3 + geometry_len;
4694 ptr++;
4695 if (compressed)
4696 {
4697 /* unzipping the XML payload */
4698 uLong refLen = xml_len;
4699 const Bytef *in = ptr;
4700 xml = malloc (xml_len + 1);
4701 if (uncompress (xml, &refLen, in, zip_len) != Z_OK)
4702 {
4703 /* uncompress error */
4704 spatialite_e ("XmlBLOB DEFLATE uncompress error\n");
4705 free (xml);
4706 return NULL;
4707 }
4708 *(xml + xml_len) = '\0';
4709 }
4710 else
4711 {
4712 /* just copying the uncompressed XML payload */
4713 xml = malloc (xml_len + 1);
4714 memcpy (xml, ptr, xml_len);
4715 *(xml + xml_len) = '\0';
4716 }
4717 /* attempting to parse the GPX document */
4718 xmlSetGenericErrorFunc (NULL, silentError);
4719 xml_doc =
4720 xmlReadMemory ((const char *) xml, xml_len, "noname.xml", NULL, 0);
4721 if (xml_doc == NULL)
4722 {
4723 /* parsing error; not a well-formed XML */
4724 xmlSetGenericErrorFunc ((void *) stderr, NULL);
4725 return NULL;
4726 }
4727 free (xml);
4728
4729 /* creating a prepared SQL statement transforming timestamps into M-values */
4730 sql = "SELECT julianday(?)";
4731 ret = sqlite3_prepare_v2 (sqlite, sql, strlen (sql), &stmt, NULL);
4732 if (ret != SQLITE_OK)
4733 goto end;
4734
4735 geom = gaiaAllocGeomCollXYZM ();
4736 geom->Srid = 4326;
4737 geom->DeclaredType = GAIA_MULTILINESTRING;
4738 parse_gpx (xml_doc, stmt, geom);
4739 sqlite3_finalize (stmt);
4740
4741 if (geom->FirstLinestring == NULL)
4742 {
4743 /* empty geometry: returning NULL */
4744 gaiaFreeGeomColl (geom);
4745 geom = NULL;
4746 }
4747
4748 end:
4749 xmlFreeDoc (xml_doc);
4750 xmlSetGenericErrorFunc ((void *) stderr, NULL);
4751 return geom;
4752 }
4753
4754 GAIAGEO_DECLARE char *
gaia_libxml2_version(void)4755 gaia_libxml2_version (void)
4756 {
4757 /* return the current LIBXML2 version */
4758 int len;
4759 char *version;
4760 const char *ver = LIBXML_DOTTED_VERSION;
4761 len = strlen (ver);
4762 version = malloc (len + 1);
4763 strcpy (version, ver);
4764 return version;
4765 }
4766
4767 #endif /* end LIBXML2: supporting XML documents */
4768