1 /*
2
3 rl2wms -- WMS related functions
4
5 version 0.1, 2013 July 28
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 RasterLite2 library
24
25 The Initial Developer of the Original Code is Alessandro Furieri
26
27 Portions created by the Initial Developer are Copyright (C) 2013
28 the Initial Developer. All Rights Reserved.
29
30 Alternatively, the contents of this file may be used under the terms of
31 either the GNU General Public License Version 2 or later (the "GPL"), or
32 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 in which case the provisions of the GPL or the LGPL are applicable instead
34 of those above. If you wish to allow use of your version of this file only
35 under the terms of either the GPL or the LGPL, and not to allow others to
36 use your version of this file under the terms of the MPL, indicate your
37 decision by deleting the provisions above and replace them with the notice
38 and other provisions required by the GPL or the LGPL. If you do not delete
39 the provisions above, a recipient may use your version of this file under
40 the terms of any one of the MPL, the GPL or the LGPL.
41
42 */
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <float.h>
46 #include <math.h>
47 #include <string.h>
48 #include <time.h>
49
50 #include <curl/curl.h>
51 #include <libxml/parser.h>
52
53 #include "rasterlite2/sqlite.h"
54
55 #include "rasterlite2/rasterlite2.h"
56 #include "rasterlite2/rl2wms.h"
57
58 #define WMS_FORMAT_UNKNOWN 0
59 #define WMS_FORMAT_GIF 1
60 #define WMS_FORMAT_PNG 2
61 #define WMS_FORMAT_PNG8 3
62 #define WMS_FORMAT_PNG24 4
63 #define WMS_FORMAT_PNG32 5
64 #define WMS_FORMAT_JPEG 6
65 #define WMS_FORMAT_TIFF 7
66
67 typedef struct wmsMemBufferStruct
68 {
69 /* a struct handling a dynamically growing output buffer */
70 unsigned char *Buffer;
71 size_t WriteOffset;
72 size_t BufferSize;
73 int Error;
74 } wmsMemBuffer;
75 typedef wmsMemBuffer *wmsMemBufferPtr;
76
77 typedef struct wmsCachedCapabilitiesStruct
78 {
79 /* a WMS Cached GetCapabilities response */
80 char *Url;
81 unsigned char *Response;
82 struct wmsCachedCapabilitiesStruct *Next;
83 } wmsCachedCapabilities;
84 typedef wmsCachedCapabilities *wmsCachedCapabilitiesPtr;
85
86 typedef struct wmsCachedItemStruct
87 {
88 /* a WMS Cached Item */
89 char *Url;
90 time_t Time;
91 int Size;
92 unsigned char *Item;
93 int ImageFormat;
94 struct wmsCachedItemStruct *Prev;
95 struct wmsCachedItemStruct *Next;
96 } wmsCachedItem;
97 typedef wmsCachedItem *wmsCachedItemPtr;
98
99 typedef struct wmsCacheStruct
100 {
101 /* a struct implementing a WMS image cache */
102 int MaxSize;
103 int CurrentSize;
104 wmsCachedCapabilitiesPtr FirstCapab;
105 wmsCachedCapabilitiesPtr LastCapab;
106 wmsCachedItemPtr First;
107 wmsCachedItemPtr Last;
108 int NumCachedItems;
109 wmsCachedItemPtr *SortedByUrl;
110 wmsCachedItemPtr *SortedByTime;
111 int HitCount;
112 int MissCount;
113 int FlushedCount;
114 double TotalDownload;
115 } wmsCache;
116 typedef wmsCache *wmsCachePtr;
117
118 typedef struct wmsFormatStruct
119 {
120 /* a struct wrapping a WMS Format */
121 int FormatCode;
122 char *Format;
123 struct wmsFormatStruct *next;
124 } wmsFormat;
125 typedef wmsFormat *wmsFormatPtr;
126
127 typedef struct wmsCrsStruct
128 {
129 /* a struct wrapping a WMS CRS */
130 char *Crs;
131 struct wmsCrsStruct *next;
132 } wmsCrs;
133 typedef wmsCrs *wmsCrsPtr;
134
135 typedef struct wmsBBoxStruct
136 {
137 /* a struct wrapping a WMS Bounding Box */
138 char *Crs;
139 double MinX;
140 double MaxX;
141 double MinY;
142 double MaxY;
143 struct wmsBBoxStruct *next;
144 } wmsBBox;
145 typedef wmsBBox *wmsBBoxPtr;
146
147 typedef struct wmsStyleStruct
148 {
149 /* a struct wrapping a WMS Style */
150 char *Name;
151 char *Title;
152 char *Abstract;
153 struct wmsStyleStruct *next;
154 } wmsStyle;
155 typedef wmsStyle *wmsStylePtr;
156
157 typedef struct wmsUrlArgumentStruct
158 {
159 /* struct wrapping a WMS URL argument */
160 char *argName;
161 char *argValue;
162 struct wmsUrlArgumentStruct *next;
163 } wmsUrlArgument;
164 typedef wmsUrlArgument *wmsUrlArgumentPtr;
165
166 typedef struct wmsTilePatternStruct
167 {
168 /* struct wrapping a WMS TilePattern */
169 char *Pattern;
170 char *Format;
171 char *SRS;
172 char *Style;
173 int TileWidth;
174 int TileHeight;
175 double TileBaseX;
176 double TileBaseY;
177 double TileExtentX;
178 double TileExtentY;
179 wmsUrlArgumentPtr first;
180 wmsUrlArgumentPtr last;
181 struct wmsTilePatternStruct *next;
182 } wmsTilePattern;
183 typedef wmsTilePattern *wmsTilePatternPtr;
184
185 typedef struct wmsTiledLayerStruct
186 {
187 /* a struct wrapping a WMS Tiled Layer */
188 char *Name;
189 char *Title;
190 char *Abstract;
191 double MinLat;
192 double MaxLat;
193 double MinLong;
194 double MaxLong;
195 char *Pad;
196 char *Bands;
197 char *DataType;
198 wmsTilePatternPtr firstPattern;
199 wmsTilePatternPtr lastPattern;
200 struct wmsTiledLayerStruct *firstChild;
201 struct wmsTiledLayerStruct *lastChild;
202 struct wmsTiledLayerStruct *next;
203 } wmsTiledLayer;
204 typedef wmsTiledLayer *wmsTiledLayerPtr;
205
206 typedef struct wmsLayerStruct
207 {
208 /* a struct wrapping a WMS Layer */
209 int Queryable;
210 int Opaque;
211 char *Name;
212 char *Title;
213 char *Abstract;
214 double MinScaleDenominator;
215 double MaxScaleDenominator;
216 double MinLat;
217 double MaxLat;
218 double MinLong;
219 double MaxLong;
220 wmsBBoxPtr firstBBox;
221 wmsBBoxPtr lastBBox;
222 wmsCrsPtr firstCrs;
223 wmsCrsPtr lastCrs;
224 wmsStylePtr firstStyle;
225 wmsStylePtr lastStyle;
226 struct wmsLayerStruct *Parent;
227 struct wmsLayerStruct *firstLayer;
228 struct wmsLayerStruct *lastLayer;
229 struct wmsLayerStruct *next;
230 } wmsLayer;
231 typedef wmsLayer *wmsLayerPtr;
232
233 typedef struct wmsCapabilitiesStruct
234 {
235 /* a struct wrapping a WMS Capabilities answer */
236 char *Version;
237 char *Name;
238 char *Title;
239 char *Abstract;
240 char *GetMapURLGet;
241 char *GetMapURLPost;
242 char *GetFeatureInfoURLGet;
243 char *GetFeatureInfoURLPost;
244 char *GetTileServiceURLGet;
245 char *GetTileServiceURLPost;
246 char *GmlMimeType;
247 char *XmlMimeType;
248 char *ContactPerson;
249 char *ContactOrganization;
250 char *ContactPosition;
251 char *PostalAddress;
252 char *City;
253 char *StateProvince;
254 char *PostCode;
255 char *Country;
256 char *VoiceTelephone;
257 char *FaxTelephone;
258 char *EMailAddress;
259 char *Fees;
260 char *AccessConstraints;
261 int LayerLimit;
262 int MaxWidth;
263 int MaxHeight;
264 wmsFormatPtr firstFormat;
265 wmsFormatPtr lastFormat;
266 wmsLayerPtr firstLayer;
267 wmsLayerPtr lastLayer;
268 char *TileServiceName;
269 char *TileServiceTitle;
270 char *TileServiceAbstract;
271 wmsTiledLayerPtr firstTiled;
272 wmsTiledLayerPtr lastTiled;
273 } wmsCapabilities;
274 typedef wmsCapabilities *wmsCapabilitiesPtr;
275
276 typedef struct wmsFeatureAttributeStruct
277 {
278 /* a struct wrapping a GML FeatureAtrribute */
279 char *name;
280 char *value;
281 gaiaGeomCollPtr geometry;
282 struct wmsFeatureAttributeStruct *next;
283 } wmsFeatureAttribute;
284 typedef wmsFeatureAttribute *wmsFeatureAttributePtr;
285
286 typedef struct wmsFeatureMemberStruct
287 {
288 /* a struct wrapping a GML FeatureMember */
289 char *layer_name;
290 wmsFeatureAttributePtr first;
291 wmsFeatureAttributePtr last;
292 struct wmsFeatureMemberStruct *next;
293 } wmsFeatureMember;
294 typedef wmsFeatureMember *wmsFeatureMemberPtr;
295
296 typedef struct wmsFeatureCollectionStruct
297 {
298 /* a struct wrapping a WMS FeatureInfo answer */
299 wmsFeatureMemberPtr first;
300 wmsFeatureMemberPtr last;
301 } wmsFeatureCollection;
302 typedef wmsFeatureCollection *wmsFeatureCollectionPtr;
303
304 typedef struct wmsSinglePartResponseStruct
305 {
306 /* a struct wrapping a single part body response */
307 char *body;
308 struct wmsSinglePartResponseStruct *next;
309 } wmsSinglePartResponse;
310 typedef wmsSinglePartResponse *wmsSinglePartResponsePtr;
311
312 typedef struct wmsMultipartCollectionStruct
313 {
314 /* a struct wrapping a Multipart HTTP response */
315 wmsSinglePartResponse *first;
316 wmsSinglePartResponse *last;
317 } wmsMultipartCollection;
318 typedef wmsMultipartCollection *wmsMultipartCollectionPtr;
319
320 static wmsCachedItemPtr
wmsAllocCachedItem(const char * url,const unsigned char * item,int size,const char * image_format)321 wmsAllocCachedItem (const char *url, const unsigned char *item, int size,
322 const char *image_format)
323 {
324 /* creating a WMS Cached Item */
325 int len;
326 time_t xtime;
327 wmsCachedItemPtr ptr = malloc (sizeof (wmsCachedItem));
328 len = strlen (url);
329 ptr->Url = malloc (len + 1);
330 strcpy (ptr->Url, url);
331 time (&xtime);
332 ptr->Time = xtime;
333 ptr->Size = size;
334 ptr->Item = malloc (size);
335 memcpy (ptr->Item, item, size);
336 ptr->ImageFormat = WMS_FORMAT_UNKNOWN;
337 if (strcmp (image_format, "image/gif") == 0)
338 ptr->ImageFormat = WMS_FORMAT_GIF;
339 if (strcmp (image_format, "image/png") == 0)
340 ptr->ImageFormat = WMS_FORMAT_PNG;
341 if (strcmp (image_format, "image/jpeg") == 0)
342 ptr->ImageFormat = WMS_FORMAT_JPEG;
343 if (strcmp (image_format, "image/tiff") == 0)
344 ptr->ImageFormat = WMS_FORMAT_TIFF;
345 ptr->Prev = NULL;
346 ptr->Next = NULL;
347 return ptr;
348 }
349
350 static void
wmsFreeCachedItem(wmsCachedItemPtr ptr)351 wmsFreeCachedItem (wmsCachedItemPtr ptr)
352 {
353 /* memory cleanup - destroying a WMS Cached Item */
354 if (ptr == NULL)
355 return;
356 if (ptr->Url != NULL)
357 free (ptr->Url);
358 if (ptr->Item != NULL)
359 free (ptr->Item);
360 free (ptr);
361 }
362
363 static wmsCachedCapabilitiesPtr
wmsAllocCachedCapabilities(const char * url,const unsigned char * response,int size)364 wmsAllocCachedCapabilities (const char *url, const unsigned char *response,
365 int size)
366 {
367 /* creating a WMS Cached GetCapabilities response */
368 wmsCachedCapabilitiesPtr ptr = malloc (sizeof (wmsCachedCapabilities));
369 int len = strlen (url);
370 ptr->Url = malloc (len + 1);
371 strcpy (ptr->Url, url);
372 ptr->Response = malloc (size + 1);
373 memcpy (ptr->Response, response, size);
374 *(ptr->Response + size) = '\0';
375 ptr->Next = NULL;
376 return ptr;
377 }
378
379 static void
wmsFreeCachedCapabilities(wmsCachedCapabilitiesPtr ptr)380 wmsFreeCachedCapabilities (wmsCachedCapabilitiesPtr ptr)
381 {
382 /* memory cleanup - destroying a WMS Cached GetCapabilities Response */
383 if (ptr == NULL)
384 return;
385 if (ptr->Url != NULL)
386 free (ptr->Url);
387 if (ptr->Response != NULL)
388 free (ptr->Response);
389 free (ptr);
390 }
391
392 static wmsCachePtr
wmsAllocCache(void)393 wmsAllocCache (void)
394 {
395 /* creating a WMS Cache */
396 wmsCachePtr cache = malloc (sizeof (wmsCache));
397 cache->MaxSize = 64 * 1024 * 1024;
398 cache->CurrentSize = 0;
399 cache->FirstCapab = NULL;
400 cache->LastCapab = NULL;
401 cache->First = NULL;
402 cache->Last = NULL;
403 cache->NumCachedItems = 0;
404 cache->SortedByUrl = NULL;
405 cache->SortedByTime = NULL;
406 cache->HitCount = 0;
407 cache->MissCount = 0;
408 cache->FlushedCount = 0;
409 cache->TotalDownload = 0 - 0;
410 return cache;
411 }
412
413 static void
wmsCacheReset(wmsCachePtr cache)414 wmsCacheReset (wmsCachePtr cache)
415 {
416 /* memory cleanup: flushing/resetting a WMS-Cache object */
417 wmsCachedItemPtr pI;
418 wmsCachedItemPtr pIn;
419 wmsCachedCapabilitiesPtr pC;
420 wmsCachedCapabilitiesPtr pCn;
421 if (cache == NULL)
422 return;
423
424 pC = cache->FirstCapab;
425 while (pC != NULL)
426 {
427 pCn = pC->Next;
428 wmsFreeCachedCapabilities (pC);
429 pC = pCn;
430 }
431 pI = cache->First;
432 while (pI != NULL)
433 {
434 pIn = pI->Next;
435 wmsFreeCachedItem (pI);
436 pI = pIn;
437 }
438 if (cache->SortedByUrl != NULL)
439 free (cache->SortedByUrl);
440 if (cache->SortedByTime != NULL)
441 free (cache->SortedByTime);
442 cache->CurrentSize = 0;
443 cache->First = NULL;
444 cache->Last = NULL;
445 cache->FirstCapab = NULL;
446 cache->LastCapab = NULL;
447 cache->NumCachedItems = 0;
448 cache->HitCount = 0;
449 cache->MissCount = 0;
450 cache->FlushedCount = 0;
451 cache->TotalDownload = 0.0;
452 cache->SortedByUrl = NULL;
453 cache->SortedByTime = NULL;
454 }
455
456 static void
wmsFreeCache(wmsCachePtr cache)457 wmsFreeCache (wmsCachePtr cache)
458 {
459 /* memory cleanup: freeing a WMS-Cache object */
460 if (cache == NULL)
461 return;
462
463 wmsCacheReset (cache);
464 free (cache);
465 }
466
467 static int
compare_time(const void * p1,const void * p2)468 compare_time (const void *p1, const void *p2)
469 {
470 /* comparison function for QSort [Time] */
471 wmsCachedItemPtr pI1 = *((wmsCachedItemPtr *) p1);
472 wmsCachedItemPtr pI2 = *((wmsCachedItemPtr *) p2);
473 if (pI1->Time == pI2->Time)
474 return 0;
475 if (pI1->Time > pI2->Time)
476 return 1;
477 return -1;
478 }
479
480 static void
wmsCacheUpdateTime(wmsCachePtr cache)481 wmsCacheUpdateTime (wmsCachePtr cache)
482 {
483 /* updating the SortedByTime array */
484 wmsCachedItemPtr pI;
485 int pos = 0;
486 if (cache == NULL)
487 return;
488 if (cache->SortedByTime != NULL)
489 free (cache->SortedByTime);
490 cache->SortedByTime = NULL;
491 if (cache->NumCachedItems <= 0)
492 return;
493 cache->SortedByTime =
494 malloc (sizeof (wmsCachedItemPtr) * cache->NumCachedItems);
495 pI = cache->First;
496 while (pI != NULL)
497 {
498 /* populating the array */
499 *(cache->SortedByTime + pos) = pI;
500 pos++;
501 pI = pI->Next;
502 }
503 qsort (cache->SortedByTime, cache->NumCachedItems,
504 sizeof (wmsCachedItemPtr), compare_time);
505 }
506
507 static int
compare_url(const void * p1,const void * p2)508 compare_url (const void *p1, const void *p2)
509 {
510 /* comparison function for QSort [Time] */
511 wmsCachedItemPtr pI1 = *((wmsCachedItemPtr *) p1);
512 wmsCachedItemPtr pI2 = *((wmsCachedItemPtr *) p2);
513 return strcmp (pI1->Url, pI2->Url);
514 }
515
516 static void
wmsCacheUpdate(wmsCachePtr cache)517 wmsCacheUpdate (wmsCachePtr cache)
518 {
519 /* updating the SortedByUrl array */
520 wmsCachedItemPtr pI;
521 int pos = 0;
522 if (cache == NULL)
523 return;
524 if (cache->SortedByUrl != NULL)
525 free (cache->SortedByUrl);
526 cache->SortedByUrl = NULL;
527 if (cache->NumCachedItems <= 0)
528 return;
529 cache->SortedByUrl =
530 malloc (sizeof (wmsCachedItemPtr) * cache->NumCachedItems);
531 pI = cache->First;
532 while (pI != NULL)
533 {
534 /* populating the array */
535 *(cache->SortedByUrl + pos) = pI;
536 pos++;
537 pI = pI->Next;
538 }
539 qsort (cache->SortedByUrl, cache->NumCachedItems, sizeof (wmsCachedItemPtr),
540 compare_url);
541 }
542
543 static void
wmsCacheSqueeze(wmsCachePtr cache,int limit)544 wmsCacheSqueeze (wmsCachePtr cache, int limit)
545 {
546 /* squeezing the WMS Cache */
547 int i;
548 int max;
549 if (cache == NULL)
550 return;
551 if (cache->CurrentSize < limit)
552 return;
553 wmsCacheUpdateTime (cache);
554 max = cache->NumCachedItems;
555 for (i = 0; i < max; i++)
556 {
557 wmsCachedItemPtr pI = *(cache->SortedByTime + i);
558 if (pI->Prev != NULL)
559 pI->Prev->Next = pI->Next;
560 if (pI->Next != NULL)
561 pI->Next->Prev = pI->Prev;
562 if (cache->First == pI)
563 cache->First = pI->Next;
564 if (cache->Last == pI)
565 cache->Last = pI->Prev;
566 wmsFreeCachedItem (pI);
567 cache->NumCachedItems -= 1;
568 cache->CurrentSize -= pI->Size;
569 cache->FlushedCount += 1;
570 if (cache->CurrentSize < limit)
571 break;
572 }
573 if (cache->SortedByTime != NULL)
574 free (cache->SortedByTime);
575 cache->SortedByTime = NULL;
576 }
577
578 static void
wmsAddCachedCapabilities(wmsCachePtr cache,const char * url,const unsigned char * response,int size)579 wmsAddCachedCapabilities (wmsCachePtr cache, const char *url,
580 const unsigned char *response, int size)
581 {
582 /* adding a new WMS Cached GetCapabilitiesItem */
583 wmsCachedCapabilitiesPtr ptr;
584 if (cache == NULL)
585 return;
586 ptr = wmsAllocCachedCapabilities (url, response, size);
587 if (cache->FirstCapab == NULL)
588 cache->FirstCapab = ptr;
589 if (cache->LastCapab != NULL)
590 cache->LastCapab->Next = ptr;
591 cache->LastCapab = ptr;
592 cache->TotalDownload += (double) size;
593 }
594
595
596 static void
wmsAddCachedItem(wmsCachePtr cache,const char * url,const unsigned char * item,int size,const char * image_format)597 wmsAddCachedItem (wmsCachePtr cache, const char *url, const unsigned char *item,
598 int size, const char *image_format)
599 {
600 /* adding a new WMS Cached Item */
601 wmsCachedItemPtr ptr;
602 if (cache == NULL)
603 return;
604 if (cache->CurrentSize + size > cache->MaxSize)
605 wmsCacheSqueeze (cache, cache->MaxSize - size);
606 ptr = wmsAllocCachedItem (url, item, size, image_format);
607 ptr->Prev = cache->Last;
608 if (cache->First == NULL)
609 cache->First = ptr;
610 if (cache->Last != NULL)
611 cache->Last->Next = ptr;
612 cache->Last = ptr;
613 cache->NumCachedItems += 1;
614 cache->CurrentSize += size;
615 cache->TotalDownload += (double) size;
616 wmsCacheUpdate (cache);
617 }
618
619 static wmsCachedCapabilitiesPtr
getWmsCachedCapabilities(wmsCachePtr cache,const char * url)620 getWmsCachedCapabilities (wmsCachePtr cache, const char *url)
621 {
622 /* attempting to retrieve a cached GetCapabilities Response by URL */
623 wmsCachedCapabilitiesPtr capab;
624 if (cache == NULL)
625 return NULL;
626 capab = cache->FirstCapab;
627 while (capab != NULL)
628 {
629 if (strcmp (capab->Url, url) == 0)
630 return capab;
631 capab = capab->Next;
632 }
633 return NULL;
634 }
635
636 static wmsCachedItemPtr
getWmsCachedItem(wmsCachePtr cache,const char * url)637 getWmsCachedItem (wmsCachePtr cache, const char *url)
638 {
639 /* attempting to retrieve a cached item by URL */
640 wmsCachedItem item;
641 wmsCachedItemPtr p_item = &item;
642 wmsCachedItemPtr found;
643 void *x;
644 item.Url = (char *) url;
645 if (cache == NULL)
646 return NULL;
647 if (cache->NumCachedItems <= 0)
648 return NULL;
649 if (cache->SortedByUrl == NULL)
650 return NULL;
651 x = bsearch (&p_item, cache->SortedByUrl, cache->NumCachedItems,
652 sizeof (wmsCachedItemPtr), compare_url);
653 if (x == NULL)
654 {
655 cache->MissCount += 1;
656 return NULL;
657 }
658 found = *((wmsCachedItemPtr *) x);
659 cache->HitCount += 1;
660 return found;
661 }
662
663 RL2_DECLARE rl2WmsCachePtr
create_wms_cache(void)664 create_wms_cache (void)
665 {
666 /* creating a WMS Cache */
667 wmsCachePtr cache = wmsAllocCache ();
668 return (rl2WmsCachePtr) cache;
669 }
670
671 RL2_DECLARE void
destroy_wms_cache(rl2WmsCachePtr handle)672 destroy_wms_cache (rl2WmsCachePtr handle)
673 {
674 /* memory cleanup: freeing a WMS-Cache object */
675 wmsCachePtr ptr = (wmsCachePtr) handle;
676 if (ptr == NULL)
677 return;
678 wmsFreeCache (ptr);
679 }
680
681 RL2_DECLARE void
reset_wms_cache(rl2WmsCachePtr handle)682 reset_wms_cache (rl2WmsCachePtr handle)
683 {
684 /* memory cleanup: flushing/resetting a WMS-Cache object */
685 wmsCachePtr ptr = (wmsCachePtr) handle;
686 if (ptr == NULL)
687 return;
688 wmsCacheReset (ptr);
689 }
690
691 RL2_DECLARE int
get_wms_cache_max_size(rl2WmsCachePtr handle)692 get_wms_cache_max_size (rl2WmsCachePtr handle)
693 {
694 /* returns the MAX-SIZE from a WMS-Cache object */
695 wmsCachePtr ptr = (wmsCachePtr) handle;
696 if (ptr == NULL)
697 return -1;
698 return ptr->MaxSize;
699 }
700
701 RL2_DECLARE void
set_wms_cache_max_size(rl2WmsCachePtr handle,int size)702 set_wms_cache_max_size (rl2WmsCachePtr handle, int size)
703 {
704 /* changes the MAX-SIZE for a WMS-Cache object */
705 int min = 4 * 1024 * 1024;
706 int max = 256 * 1024 * 1024;
707 wmsCachePtr ptr = (wmsCachePtr) handle;
708 if (ptr == NULL)
709 return;
710 ptr->MaxSize = size;
711 if (ptr->MaxSize < min)
712 ptr->MaxSize = min;
713 if (ptr->MaxSize > max)
714 ptr->MaxSize = max;
715 if (ptr->CurrentSize > ptr->MaxSize)
716 {
717 wmsCacheSqueeze (ptr, ptr->MaxSize);
718 wmsCacheUpdate (ptr);
719 }
720 }
721
722 RL2_DECLARE int
get_wms_cache_items_count(rl2WmsCachePtr handle)723 get_wms_cache_items_count (rl2WmsCachePtr handle)
724 {
725 /* returns the CURRENT-SIZE from a WMS-Cache object */
726 wmsCachePtr ptr = (wmsCachePtr) handle;
727 if (ptr == NULL)
728 return -1;
729 return ptr->NumCachedItems;
730 }
731
732 RL2_DECLARE int
get_wms_cache_current_size(rl2WmsCachePtr handle)733 get_wms_cache_current_size (rl2WmsCachePtr handle)
734 {
735 /* returns the CURRENT-SIZE from a WMS-Cache object */
736 wmsCachePtr ptr = (wmsCachePtr) handle;
737 if (ptr == NULL)
738 return -1;
739 return ptr->CurrentSize;
740 }
741
742 RL2_DECLARE int
get_wms_cache_hit_count(rl2WmsCachePtr handle)743 get_wms_cache_hit_count (rl2WmsCachePtr handle)
744 {
745 /* returns the HIT-COUNT from a WMS-Cache object */
746 wmsCachePtr ptr = (wmsCachePtr) handle;
747 if (ptr == NULL)
748 return -1;
749 return ptr->HitCount;
750 }
751
752 RL2_DECLARE int
get_wms_cache_miss_count(rl2WmsCachePtr handle)753 get_wms_cache_miss_count (rl2WmsCachePtr handle)
754 {
755 /* returns the MISS-COUNT from a WMS-Cache object */
756 wmsCachePtr ptr = (wmsCachePtr) handle;
757 if (ptr == NULL)
758 return -1;
759 return ptr->MissCount;
760 }
761
762 RL2_DECLARE int
get_wms_cache_flushed_count(rl2WmsCachePtr handle)763 get_wms_cache_flushed_count (rl2WmsCachePtr handle)
764 {
765 /* returns the FLUSHED-COUNT from a WMS-Cache object */
766 wmsCachePtr ptr = (wmsCachePtr) handle;
767 if (ptr == NULL)
768 return -1;
769 return ptr->FlushedCount;
770 }
771
772 RL2_DECLARE double
get_wms_total_download_size(rl2WmsCachePtr handle)773 get_wms_total_download_size (rl2WmsCachePtr handle)
774 {
775 /* returns the TOTAL-DOWNLOAD size from a WMS-Cache object */
776 wmsCachePtr ptr = (wmsCachePtr) handle;
777 if (ptr == NULL)
778 return -1;
779 return ptr->TotalDownload;
780 }
781
782 static wmsFormatPtr
wmsAllocFormat(const char * format)783 wmsAllocFormat (const char *format)
784 {
785 /* allocating an empty WMS Format object */
786 int len;
787 wmsFormatPtr fmt = malloc (sizeof (wmsFormat));
788 fmt->FormatCode = WMS_FORMAT_UNKNOWN;
789 if (strcmp (format, "image/jpeg") == 0)
790 fmt->FormatCode = WMS_FORMAT_JPEG;
791 if (strcmp (format, "image/tiff") == 0)
792 fmt->FormatCode = WMS_FORMAT_TIFF;
793 if (strcmp (format, "image/gif") == 0)
794 fmt->FormatCode = WMS_FORMAT_GIF;
795 if (strcmp (format, "image/png") == 0)
796 fmt->FormatCode = WMS_FORMAT_PNG;
797 if (strcmp (format, "image/png8") == 0)
798 fmt->FormatCode = WMS_FORMAT_PNG8;
799 if (strcmp (format, "image/png; mode=8bit") == 0)
800 fmt->FormatCode = WMS_FORMAT_PNG8;
801 if (strcmp (format, "image/png24") == 0)
802 fmt->FormatCode = WMS_FORMAT_PNG24;
803 if (strcmp (format, "image/png; mode=24bit") == 0)
804 fmt->FormatCode = WMS_FORMAT_PNG24;
805 if (strcmp (format, "image/png32") == 0)
806 fmt->FormatCode = WMS_FORMAT_PNG32;
807 if (strcmp (format, "image/png; mode=32bit") == 0)
808 fmt->FormatCode = WMS_FORMAT_PNG32;
809 len = strlen (format);
810 fmt->Format = malloc (len + 1);
811 strcpy (fmt->Format, format);
812 fmt->next = NULL;
813 return fmt;
814 }
815
816 static void
wmsFreeFormat(wmsFormatPtr fmt)817 wmsFreeFormat (wmsFormatPtr fmt)
818 {
819 /* memory cleanup - destroying a WMS Format object */
820 if (fmt == NULL)
821 return;
822 if (fmt->Format != NULL)
823 free (fmt->Format);
824 free (fmt);
825 }
826
827 static wmsCrsPtr
wmsAllocCrs(const char * crs_str)828 wmsAllocCrs (const char *crs_str)
829 {
830 /* allocating a WMS CRS object */
831 int len;
832 wmsCrsPtr crs = malloc (sizeof (wmsCrs));
833 crs->Crs = NULL;
834 if (crs != NULL)
835 {
836 len = strlen (crs_str);
837 crs->Crs = malloc (len + 1);
838 strcpy (crs->Crs, crs_str);
839 }
840 crs->next = NULL;
841 return crs;
842 }
843
844 static void
wmsFreeCrs(wmsCrsPtr crs)845 wmsFreeCrs (wmsCrsPtr crs)
846 {
847 /* memory cleanup - destroying a WMS CRS object */
848 if (crs == NULL)
849 return;
850 if (crs->Crs != NULL)
851 free (crs->Crs);
852 free (crs);
853 }
854
855 static wmsBBoxPtr
wmsAllocBBox(const char * crs_str,double minx,double maxx,double miny,double maxy)856 wmsAllocBBox (const char *crs_str, double minx, double maxx, double miny,
857 double maxy)
858 {
859 /* allocating a WMS Bounding Box object */
860 int len;
861 wmsBBoxPtr bbox = malloc (sizeof (wmsBBox));
862 bbox->Crs = NULL;
863 if (bbox != NULL)
864 {
865 len = strlen (crs_str);
866 bbox->Crs = malloc (len + 1);
867 strcpy (bbox->Crs, crs_str);
868 }
869 bbox->MinX = minx;
870 bbox->MaxX = maxx;
871 bbox->MinY = miny;
872 bbox->MaxY = maxy;
873 bbox->next = NULL;
874 return bbox;
875 }
876
877 static void
wmsFreeBBox(wmsBBoxPtr bbox)878 wmsFreeBBox (wmsBBoxPtr bbox)
879 {
880 /* memory cleanup - destroying a WMS BBOX object */
881 if (bbox == NULL)
882 return;
883 if (bbox->Crs != NULL)
884 free (bbox->Crs);
885 free (bbox);
886 }
887
888 static wmsStylePtr
wmsAllocStyle(const char * name,const char * title,const char * abstract)889 wmsAllocStyle (const char *name, const char *title, const char *abstract)
890 {
891 /* allocating a WMS Style object */
892 int len;
893 wmsStylePtr stl = malloc (sizeof (wmsStyle));
894 stl->Name = NULL;
895 stl->Title = NULL;
896 stl->Abstract = NULL;
897 if (name != NULL)
898 {
899 len = strlen (name);
900 stl->Name = malloc (len + 1);
901 strcpy (stl->Name, name);
902 }
903 if (title != NULL)
904 {
905 len = strlen (title);
906 stl->Title = malloc (len + 1);
907 strcpy (stl->Title, title);
908 }
909 if (abstract != NULL)
910 {
911 len = strlen (abstract);
912 stl->Abstract = malloc (len + 1);
913 strcpy (stl->Abstract, abstract);
914 }
915 stl->next = NULL;
916 return stl;
917 }
918
919 static void
wmsFreeStyle(wmsStylePtr stl)920 wmsFreeStyle (wmsStylePtr stl)
921 {
922 /* memory cleanup - destroying a WMS Style object */
923 if (stl == NULL)
924 return;
925 if (stl->Name != NULL)
926 free (stl->Name);
927 if (stl->Title != NULL)
928 free (stl->Title);
929 if (stl->Abstract != NULL)
930 free (stl->Abstract);
931 free (stl);
932 }
933
934 static wmsLayerPtr
wmsAllocLayer(const char * name,const char * title,const char * abstract,wmsLayerPtr parent)935 wmsAllocLayer (const char *name, const char *title, const char *abstract,
936 wmsLayerPtr parent)
937 {
938 /* allocating a WMS Layer object */
939 int len;
940 wmsLayerPtr lyr = malloc (sizeof (wmsLayer));
941 lyr->Queryable = -1;
942 lyr->Opaque = -1;
943 lyr->Name = NULL;
944 lyr->Title = NULL;
945 lyr->Abstract = NULL;
946 if (name != NULL)
947 {
948 len = strlen (name);
949 lyr->Name = malloc (len + 1);
950 strcpy (lyr->Name, name);
951 }
952 if (title != NULL)
953 {
954 len = strlen (title);
955 lyr->Title = malloc (len + 1);
956 strcpy (lyr->Title, title);
957 }
958 if (abstract != NULL)
959 {
960 len = strlen (abstract);
961 lyr->Abstract = malloc (len + 1);
962 strcpy (lyr->Abstract, abstract);
963 }
964 lyr->Parent = parent;
965 lyr->MinScaleDenominator = DBL_MAX;
966 lyr->MaxScaleDenominator = DBL_MAX;
967 lyr->MinLat = DBL_MAX;
968 lyr->MaxLat = DBL_MAX;
969 lyr->MinLong = DBL_MAX;
970 lyr->MaxLong = DBL_MAX;
971 lyr->firstBBox = NULL;
972 lyr->lastBBox = NULL;
973 lyr->firstCrs = NULL;
974 lyr->lastCrs = NULL;
975 lyr->firstStyle = NULL;
976 lyr->lastStyle = NULL;
977 lyr->firstLayer = NULL;
978 lyr->lastLayer = NULL;
979 lyr->next = NULL;
980 return lyr;
981 }
982
983 static void
wmsFreeLayer(wmsLayerPtr lyr)984 wmsFreeLayer (wmsLayerPtr lyr)
985 {
986 /* memory cleanup - destroying a WMS Layer object */
987 wmsCrsPtr pc;
988 wmsCrsPtr pcn;
989 wmsBBoxPtr pbb;
990 wmsBBoxPtr pbbn;
991 wmsStylePtr ps;
992 wmsStylePtr psn;
993 wmsLayerPtr pl;
994 wmsLayerPtr pln;
995 if (lyr == NULL)
996 return;
997 if (lyr->Name != NULL)
998 free (lyr->Name);
999 if (lyr->Title != NULL)
1000 free (lyr->Title);
1001 if (lyr->Abstract != NULL)
1002 free (lyr->Abstract);
1003 pc = lyr->firstCrs;
1004 while (pc != NULL)
1005 {
1006 pcn = pc->next;
1007 wmsFreeCrs (pc);
1008 pc = pcn;
1009 }
1010 pbb = lyr->firstBBox;
1011 while (pbb != NULL)
1012 {
1013 pbbn = pbb->next;
1014 wmsFreeBBox (pbb);
1015 pbb = pbbn;
1016 }
1017 ps = lyr->firstStyle;
1018 while (ps != NULL)
1019 {
1020 psn = ps->next;
1021 wmsFreeStyle (ps);
1022 ps = psn;
1023 }
1024 pl = lyr->firstLayer;
1025 while (pl != NULL)
1026 {
1027 pln = pl->next;
1028 wmsFreeLayer (pl);
1029 pl = pln;
1030 }
1031 free (lyr);
1032 }
1033
1034 static wmsUrlArgumentPtr
wmsAllocUrlArgument(char * arg_name,char * arg_value)1035 wmsAllocUrlArgument (char *arg_name, char *arg_value)
1036 {
1037 /* allocating a WMS URL Argument object */
1038 wmsUrlArgumentPtr arg = malloc (sizeof (wmsUrlArgument));
1039 arg->argName = arg_name;
1040 arg->argValue = arg_value;
1041 arg->next = NULL;
1042 return arg;
1043 }
1044
1045 static void
wmsFreeUrlArgument(wmsUrlArgumentPtr arg)1046 wmsFreeUrlArgument (wmsUrlArgumentPtr arg)
1047 {
1048 /* memory cleanup - destroying a WMS URL Argument object */
1049 if (arg == NULL)
1050 return;
1051 if (arg->argName != NULL)
1052 free (arg->argName);
1053 if (arg->argValue != NULL)
1054 free (arg->argValue);
1055 free (arg);
1056 }
1057
1058 static void
add_url_argument(wmsTilePatternPtr ptr,const char * pattern)1059 add_url_argument (wmsTilePatternPtr ptr, const char *pattern)
1060 {
1061 /* adding an URL argument */
1062 char *name = NULL;
1063 char *value = NULL;
1064 const char *p = pattern;
1065 const char *p_eq = pattern;
1066 wmsUrlArgumentPtr arg;
1067 int len;
1068
1069 /* splitting arg Name and Value */
1070 while (1)
1071 {
1072 if (*p == '=')
1073 p_eq = p;
1074 if (*p == '\0')
1075 break;
1076 p++;
1077 }
1078
1079 len = p_eq - pattern;
1080 if (len > 0)
1081 {
1082 /* arg Name */
1083 name = malloc (len + 1);
1084 memcpy (name, pattern, len);
1085 *(name + len) = '\0';
1086 }
1087 len = strlen (p_eq + 1);
1088 if (len > 0)
1089 {
1090 /* arg Value */
1091 value = malloc (len + 1);
1092 strcpy (value, p_eq + 1);
1093 }
1094
1095 arg = wmsAllocUrlArgument (name, value);
1096 if (ptr->first == NULL)
1097 ptr->first = arg;
1098 if (ptr->last != NULL)
1099 ptr->last->next = arg;
1100 ptr->last = arg;
1101 }
1102
1103 static void
parse_pattern_bbox(const char * value,double * minx,double * miny,double * maxx,double * maxy)1104 parse_pattern_bbox (const char *value, double *minx, double *miny, double *maxx,
1105 double *maxy)
1106 {
1107 /* parsing a BBOX arg [minx,miny,maxx,maxy] */
1108 int step = 0;
1109 const char *p_start = value;
1110 const char *p_end = value;
1111 *minx = DBL_MAX;
1112 *miny = DBL_MAX;
1113 *maxx = DBL_MAX;
1114 *maxy = DBL_MAX;
1115
1116 while (1)
1117 {
1118 if (*p_end == ',' || *p_end == '\0')
1119 {
1120 int len = p_end - p_start;
1121 char *str = malloc (len + 1);
1122 memcpy (str, p_start, len);
1123 *(str + len) = '\0';
1124 if (step == 0)
1125 *minx = atof (str);
1126 if (step == 1)
1127 *miny = atof (str);
1128 if (step == 2)
1129 *maxx = atof (str);
1130 if (step == 3)
1131 *maxy = atof (str);
1132 step++;
1133 free (str);
1134 p_start = p_end + 1;
1135 }
1136 if (*p_end == '\0')
1137 break;
1138 p_end++;
1139 }
1140 }
1141
1142 static void
parse_url_arguments(wmsTilePatternPtr ptr,const char * pattern)1143 parse_url_arguments (wmsTilePatternPtr ptr, const char *pattern)
1144 {
1145 /* parsing URL arguments */
1146 const char *p_start = pattern;
1147 const char *p_end = pattern;
1148 while (1)
1149 {
1150 if (*p_end == '&' || *p_end == '\0')
1151 {
1152 int len = p_end - p_start;
1153 char *arg = malloc (len + 1);
1154 memcpy (arg, p_start, len);
1155 *(arg + len) = '\0';
1156 add_url_argument (ptr, arg);
1157 free (arg);
1158 p_start = p_end + 1;
1159 }
1160 if (*p_end == '\0')
1161 break;
1162 p_end++;
1163 }
1164 }
1165
1166 static wmsTilePatternPtr
wmsAllocTilePattern(char * pattern)1167 wmsAllocTilePattern (char *pattern)
1168 {
1169 /* allocating a WMS TilePattern object */
1170 double minx;
1171 double miny;
1172 double maxx;
1173 double maxy;
1174 wmsUrlArgumentPtr pa;
1175 wmsTilePatternPtr ptr = malloc (sizeof (wmsTilePattern));
1176 ptr->Pattern = pattern;
1177 ptr->Format = NULL;
1178 ptr->SRS = NULL;
1179 ptr->Style = NULL;
1180 ptr->TileWidth = 0;
1181 ptr->TileHeight = 0;
1182 ptr->TileBaseX = DBL_MAX;
1183 ptr->TileBaseY = DBL_MAX;
1184 ptr->TileExtentX = DBL_MAX;
1185 ptr->TileExtentY = DBL_MAX;
1186 ptr->first = NULL;
1187 ptr->last = NULL;
1188 parse_url_arguments (ptr, pattern);
1189 ptr->next = NULL;
1190 /* setting explicit values */
1191 pa = ptr->first;
1192 while (pa != NULL)
1193 {
1194 if (strcasecmp (pa->argName, "format") == 0)
1195 ptr->Format = pa->argValue;
1196 if (strcasecmp (pa->argName, "srs") == 0)
1197 ptr->SRS = pa->argValue;
1198 if (strcasecmp (pa->argName, "styles") == 0)
1199 ptr->Style = pa->argValue;
1200 if (strcasecmp (pa->argName, "width") == 0)
1201 ptr->TileWidth = atoi (pa->argValue);
1202 if (strcasecmp (pa->argName, "width") == 0)
1203 ptr->TileHeight = atoi (pa->argValue);
1204 if (strcasecmp (pa->argName, "bbox") == 0)
1205 {
1206 parse_pattern_bbox (pa->argValue, &minx, &miny, &maxx, &maxy);
1207 ptr->TileBaseX = minx; /* leftmost coord */
1208 ptr->TileBaseY = maxy; /* topmost coord */
1209 ptr->TileExtentX = maxx - minx;
1210 ptr->TileExtentY = maxy - miny;
1211 }
1212 pa = pa->next;
1213 }
1214 return ptr;
1215 }
1216
1217 static void
wmsFreeTilePattern(wmsTilePatternPtr pattern)1218 wmsFreeTilePattern (wmsTilePatternPtr pattern)
1219 {
1220 /* memory cleanup - destroying a WMS TilePattern object */
1221 wmsUrlArgumentPtr pa;
1222 wmsUrlArgumentPtr pan;
1223 if (pattern == NULL)
1224 return;
1225 if (pattern->Pattern != NULL)
1226 free (pattern->Pattern);
1227 pa = pattern->first;
1228 while (pa != NULL)
1229 {
1230 pan = pa->next;
1231 wmsFreeUrlArgument (pa);
1232 pa = pan;
1233 }
1234 free (pattern);
1235 }
1236
1237 static wmsTiledLayerPtr
wmsAllocTiledLayer(const char * name,const char * title,const char * abstract)1238 wmsAllocTiledLayer (const char *name, const char *title, const char *abstract)
1239 {
1240 /* allocating a WMS TiledLayer object */
1241 int len;
1242 wmsTiledLayerPtr lyr = malloc (sizeof (wmsTiledLayer));
1243 lyr->Name = NULL;
1244 lyr->Title = NULL;
1245 lyr->Abstract = NULL;
1246 if (name != NULL)
1247 {
1248 len = strlen (name);
1249 lyr->Name = malloc (len + 1);
1250 strcpy (lyr->Name, name);
1251 }
1252 if (title != NULL)
1253 {
1254 len = strlen (title);
1255 lyr->Title = malloc (len + 1);
1256 strcpy (lyr->Title, title);
1257 }
1258 if (abstract != NULL)
1259 {
1260 len = strlen (abstract);
1261 lyr->Abstract = malloc (len + 1);
1262 strcpy (lyr->Abstract, abstract);
1263 }
1264 lyr->MinLat = DBL_MAX;
1265 lyr->MaxLat = DBL_MAX;
1266 lyr->MinLong = DBL_MAX;
1267 lyr->MaxLong = DBL_MAX;
1268 lyr->Pad = NULL;
1269 lyr->Bands = NULL;
1270 lyr->DataType = NULL;
1271 lyr->firstPattern = NULL;
1272 lyr->lastPattern = NULL;
1273 lyr->firstChild = NULL;
1274 lyr->lastChild = NULL;
1275 lyr->next = NULL;
1276 return lyr;
1277 }
1278
1279 static void
wmsFreeTiledLayer(wmsTiledLayerPtr lyr)1280 wmsFreeTiledLayer (wmsTiledLayerPtr lyr)
1281 {
1282 /* memory cleanup - destroying a WMS TiledLayer object */
1283 wmsTilePatternPtr pp;
1284 wmsTilePatternPtr ppn;
1285 wmsTiledLayerPtr pt;
1286 wmsTiledLayerPtr ptn;
1287 if (lyr == NULL)
1288 return;
1289 if (lyr->Name != NULL)
1290 free (lyr->Name);
1291 if (lyr->Title != NULL)
1292 free (lyr->Title);
1293 if (lyr->Abstract != NULL)
1294 free (lyr->Abstract);
1295 if (lyr->Pad != NULL)
1296 free (lyr->Pad);
1297 if (lyr->Bands != NULL)
1298 free (lyr->Bands);
1299 if (lyr->DataType != NULL)
1300 free (lyr->DataType);
1301 pp = lyr->firstPattern;
1302 while (pp != NULL)
1303 {
1304 ppn = pp->next;
1305 wmsFreeTilePattern (pp);
1306 pp = ppn;
1307 }
1308 pt = lyr->firstChild;
1309 while (pt != NULL)
1310 {
1311 ptn = pt->next;
1312 wmsFreeTiledLayer (pt);
1313 pt = ptn;
1314 }
1315 free (lyr);
1316 }
1317
1318 static wmsCapabilitiesPtr
wmsAllocCapabilities()1319 wmsAllocCapabilities ()
1320 {
1321 /* allocating an empty WMS GetCapabilities object */
1322 wmsCapabilitiesPtr cap = malloc (sizeof (wmsCapabilities));
1323 cap->Version = NULL;
1324 cap->Name = NULL;
1325 cap->Title = NULL;
1326 cap->Abstract = NULL;
1327 cap->GetMapURLGet = NULL;
1328 cap->GetMapURLPost = NULL;
1329 cap->GetFeatureInfoURLGet = NULL;
1330 cap->GetFeatureInfoURLPost = NULL;
1331 cap->GetTileServiceURLGet = NULL;
1332 cap->GetTileServiceURLPost = NULL;
1333 cap->GmlMimeType = NULL;
1334 cap->XmlMimeType = NULL;
1335 cap->ContactPerson = NULL;
1336 cap->ContactOrganization = NULL;
1337 cap->ContactPosition = NULL;
1338 cap->PostalAddress = NULL;
1339 cap->City = NULL;
1340 cap->StateProvince = NULL;
1341 cap->PostCode = NULL;
1342 cap->Country = NULL;
1343 cap->VoiceTelephone = NULL;
1344 cap->FaxTelephone = NULL;
1345 cap->EMailAddress = NULL;
1346 cap->Fees = NULL;
1347 cap->AccessConstraints = NULL;
1348 cap->LayerLimit = -1;
1349 cap->MaxWidth = -1;
1350 cap->MaxHeight = -1;
1351 cap->firstFormat = NULL;
1352 cap->lastFormat = NULL;
1353 cap->firstLayer = NULL;
1354 cap->lastLayer = NULL;
1355 cap->TileServiceName = NULL;
1356 cap->TileServiceTitle = NULL;
1357 cap->TileServiceAbstract = NULL;
1358 cap->firstTiled = NULL;
1359 cap->lastTiled = NULL;
1360 return cap;
1361 }
1362
1363 static void
wmsFreeCapabilities(wmsCapabilitiesPtr cap)1364 wmsFreeCapabilities (wmsCapabilitiesPtr cap)
1365 {
1366 /* memory cleanup - freeing a WMS Capabilities object */
1367 wmsFormatPtr pf;
1368 wmsFormatPtr pfn;
1369 wmsLayerPtr pl;
1370 wmsLayerPtr pln;
1371 wmsTiledLayerPtr pt;
1372 wmsTiledLayerPtr ptn;
1373 if (cap == NULL)
1374 return;
1375 if (cap->Version)
1376 free (cap->Version);
1377 if (cap->Name)
1378 free (cap->Name);
1379 if (cap->Title)
1380 free (cap->Title);
1381 if (cap->Abstract)
1382 free (cap->Abstract);
1383 if (cap->GetMapURLGet)
1384 free (cap->GetMapURLGet);
1385 if (cap->GetMapURLPost)
1386 free (cap->GetMapURLPost);
1387 if (cap->GetFeatureInfoURLGet)
1388 free (cap->GetFeatureInfoURLGet);
1389 if (cap->GetFeatureInfoURLPost)
1390 free (cap->GetFeatureInfoURLPost);
1391 if (cap->GetTileServiceURLGet)
1392 free (cap->GetTileServiceURLGet);
1393 if (cap->GetTileServiceURLPost)
1394 free (cap->GetTileServiceURLPost);
1395 if (cap->GmlMimeType)
1396 free (cap->GmlMimeType);
1397 if (cap->XmlMimeType)
1398 free (cap->XmlMimeType);
1399 if (cap->ContactPerson)
1400 free (cap->ContactPerson);
1401 if (cap->ContactOrganization)
1402 free (cap->ContactOrganization);
1403 if (cap->ContactPosition)
1404 free (cap->ContactPosition);
1405 if (cap->PostalAddress)
1406 free (cap->PostalAddress);
1407 if (cap->City)
1408 free (cap->City);
1409 if (cap->StateProvince)
1410 free (cap->StateProvince);
1411 if (cap->PostCode)
1412 free (cap->PostCode);
1413 if (cap->Country)
1414 free (cap->Country);
1415 if (cap->VoiceTelephone)
1416 free (cap->VoiceTelephone);
1417 if (cap->FaxTelephone)
1418 free (cap->FaxTelephone);
1419 if (cap->EMailAddress)
1420 free (cap->EMailAddress);
1421 if (cap->Fees)
1422 free (cap->Fees);
1423 if (cap->AccessConstraints)
1424 free (cap->AccessConstraints);
1425 if (cap->TileServiceName)
1426 free (cap->TileServiceName);
1427 if (cap->TileServiceTitle)
1428 free (cap->TileServiceTitle);
1429 if (cap->TileServiceAbstract)
1430 free (cap->TileServiceAbstract);
1431 pf = cap->firstFormat;
1432 while (pf != NULL)
1433 {
1434 pfn = pf->next;
1435 wmsFreeFormat (pf);
1436 pf = pfn;
1437 }
1438 pl = cap->firstLayer;
1439 while (pl != NULL)
1440 {
1441 pln = pl->next;
1442 wmsFreeLayer (pl);
1443 pl = pln;
1444 }
1445 pt = cap->firstTiled;
1446 while (pt != NULL)
1447 {
1448 ptn = pt->next;
1449 wmsFreeTiledLayer (pt);
1450 pt = ptn;
1451 }
1452 free (cap);
1453 }
1454
1455 static wmsFeatureAttributePtr
wmsAllocFeatureAttribute(const char * name,char * value)1456 wmsAllocFeatureAttribute (const char *name, char *value)
1457 {
1458 /* allocating and initializing a GML Feature Attribute object */
1459 int len;
1460 wmsFeatureAttributePtr attr = malloc (sizeof (wmsFeatureAttribute));
1461 len = strlen (name);
1462 attr->name = malloc (len + 1);
1463 strcpy (attr->name, name);
1464 attr->value = value;
1465 attr->geometry = NULL;
1466 attr->next = NULL;
1467 return attr;
1468 }
1469
1470 static void
wmsFreeFeatureAttribute(wmsFeatureAttributePtr attr)1471 wmsFreeFeatureAttribute (wmsFeatureAttributePtr attr)
1472 {
1473 /* memory cleanup - freeing a GML Feature Attribute object */
1474 if (attr == NULL)
1475 return;
1476 if (attr->name != NULL)
1477 free (attr->name);
1478 if (attr->value != NULL)
1479 free (attr->value);
1480 if (attr->geometry != NULL)
1481 gaiaFreeGeomColl (attr->geometry);
1482 free (attr);
1483 }
1484
1485 static wmsFeatureMemberPtr
wmsAllocFeatureMember(const char * name)1486 wmsAllocFeatureMember (const char *name)
1487 {
1488 /* allocating an empty GML Feature Member object */
1489 int len;
1490 wmsFeatureMemberPtr member = malloc (sizeof (wmsFeatureMember));
1491 len = strlen (name);
1492 member->layer_name = malloc (len + 1);
1493 strcpy (member->layer_name, name);
1494 member->first = NULL;
1495 member->last = NULL;
1496 member->next = NULL;
1497 return member;
1498 }
1499
1500 static void
wmsFreeFeatureMember(wmsFeatureMemberPtr member)1501 wmsFreeFeatureMember (wmsFeatureMemberPtr member)
1502 {
1503 /* memory cleanup - freeing a GML Feature Member object */
1504 wmsFeatureAttributePtr pa;
1505 wmsFeatureAttributePtr pan;
1506 if (member == NULL)
1507 return;
1508 if (member->layer_name != NULL)
1509 free (member->layer_name);
1510 pa = member->first;
1511 while (pa != NULL)
1512 {
1513 pan = pa->next;
1514 wmsFreeFeatureAttribute (pa);
1515 pa = pan;
1516 }
1517 free (member);
1518 }
1519
1520 static void
wmsAddFeatureMemberAttribute(wmsFeatureMemberPtr member,const char * name,char * value)1521 wmsAddFeatureMemberAttribute (wmsFeatureMemberPtr member, const char *name,
1522 char *value)
1523 {
1524 /* adding an attribute+value to some GML Feature Member */
1525 wmsFeatureAttributePtr attr;
1526 if (member == NULL)
1527 return;
1528 attr = wmsAllocFeatureAttribute (name, value);
1529 if (member->first == NULL)
1530 member->first = attr;
1531 if (member->last != NULL)
1532 member->last->next = attr;
1533 member->last = attr;
1534 }
1535
1536 static wmsFeatureCollectionPtr
wmsAllocFeatureCollection()1537 wmsAllocFeatureCollection ()
1538 {
1539 /* allocating an empty GML Feature Collection object */
1540 wmsFeatureCollectionPtr coll = malloc (sizeof (wmsFeatureCollection));
1541 coll->first = NULL;
1542 coll->last = NULL;
1543 return coll;
1544 }
1545
1546 static void
wmsFreeFeatureCollection(wmsFeatureCollectionPtr coll)1547 wmsFreeFeatureCollection (wmsFeatureCollectionPtr coll)
1548 {
1549 /* memory cleanup - freeing a GML Feature Collection object */
1550 wmsFeatureMemberPtr pm;
1551 wmsFeatureMemberPtr pmn;
1552 if (coll == NULL)
1553 return;
1554 pm = coll->first;
1555 while (pm != NULL)
1556 {
1557 pmn = pm->next;
1558 wmsFreeFeatureMember (pm);
1559 pm = pmn;
1560 }
1561 free (coll);
1562 }
1563
1564 static wmsSinglePartResponsePtr
wmsAllocSinglePartResponse(char * body)1565 wmsAllocSinglePartResponse (char *body)
1566 {
1567 /* allocating and initializing a SinglePart Response */
1568 wmsSinglePartResponsePtr single = malloc (sizeof (wmsSinglePartResponse));
1569 single->body = body;
1570 single->next = NULL;
1571 return single;
1572 }
1573
1574 static void
wmsFreeSinglePartResponse(wmsSinglePartResponsePtr single)1575 wmsFreeSinglePartResponse (wmsSinglePartResponsePtr single)
1576 {
1577 /* memory cleanup - freeing a HTTP SinglePart Response object */
1578 if (single == NULL)
1579 return;
1580 if (single->body != NULL)
1581 free (single->body);
1582 free (single);
1583 }
1584
1585 static wmsMultipartCollectionPtr
wmsAllocMultipartCollection()1586 wmsAllocMultipartCollection ()
1587 {
1588 /* allocating an empty HTTP Multipart response object */
1589 wmsMultipartCollectionPtr coll = malloc (sizeof (wmsMultipartCollection));
1590 coll->first = NULL;
1591 coll->last = NULL;
1592 return coll;
1593 }
1594
1595 static void
wmsFreeMultipartCollection(wmsMultipartCollectionPtr coll)1596 wmsFreeMultipartCollection (wmsMultipartCollectionPtr coll)
1597 {
1598 /* memory cleanup - freeing a HTTP Multipart Collection object */
1599 wmsSinglePartResponsePtr ps;
1600 wmsSinglePartResponsePtr psn;
1601 if (coll == NULL)
1602 return;
1603 ps = coll->first;
1604 while (ps != NULL)
1605 {
1606 psn = ps->next;
1607 wmsFreeSinglePartResponse (ps);
1608 ps = psn;
1609 }
1610 free (coll);
1611 }
1612
1613 static void
wmsAddPartToMultipart(wmsMultipartCollectionPtr coll,char * body)1614 wmsAddPartToMultipart (wmsMultipartCollectionPtr coll, char *body)
1615 {
1616 /* adding a SinglePart Response to the Collection */
1617 wmsSinglePartResponsePtr single = wmsAllocSinglePartResponse (body);
1618 if (coll->first == NULL)
1619 coll->first = single;
1620 if (coll->last != NULL)
1621 coll->last->next = single;
1622 coll->last = single;
1623 }
1624
1625 static void
wmsMemBufferInitialize(wmsMemBufferPtr buf)1626 wmsMemBufferInitialize (wmsMemBufferPtr buf)
1627 {
1628 /* initializing a dynamically growing output buffer */
1629 buf->Buffer = NULL;
1630 buf->WriteOffset = 0;
1631 buf->BufferSize = 0;
1632 buf->Error = 0;
1633 }
1634
1635 static void
wmsMemBufferReset(wmsMemBufferPtr buf)1636 wmsMemBufferReset (wmsMemBufferPtr buf)
1637 {
1638 /* cleaning a dynamically growing output buffer */
1639 if (buf->Buffer)
1640 free (buf->Buffer);
1641 buf->Buffer = NULL;
1642 buf->WriteOffset = 0;
1643 buf->BufferSize = 0;
1644 buf->Error = 0;
1645 }
1646
1647 static void
wmsMemBufferAppend(wmsMemBufferPtr buf,const unsigned char * payload,size_t size)1648 wmsMemBufferAppend (wmsMemBufferPtr buf, const unsigned char *payload,
1649 size_t size)
1650 {
1651 /* appending into the buffer */
1652 size_t free_size = buf->BufferSize - buf->WriteOffset;
1653 if (size > free_size)
1654 {
1655 /* we must allocate a bigger buffer */
1656 size_t new_size;
1657 unsigned char *new_buf;
1658 if (buf->BufferSize == 0)
1659 new_size = size + 1024;
1660 else if (buf->BufferSize <= 4196)
1661 new_size = buf->BufferSize + size + 4196;
1662 else if (buf->BufferSize <= 65536)
1663 new_size = buf->BufferSize + size + 65536;
1664 else
1665 new_size = buf->BufferSize + size + (1024 * 1024);
1666 new_buf = malloc (new_size);
1667 if (!new_buf)
1668 {
1669 buf->Error = 1;
1670 return;
1671 }
1672 if (buf->Buffer)
1673 {
1674 memcpy (new_buf, buf->Buffer, buf->WriteOffset);
1675 free (buf->Buffer);
1676 }
1677 buf->Buffer = new_buf;
1678 buf->BufferSize = new_size;
1679 }
1680 memcpy (buf->Buffer + buf->WriteOffset, payload, size);
1681 buf->WriteOffset += size;
1682 }
1683
1684 static wmsMultipartCollectionPtr
parse_multipart_body(wmsMemBufferPtr buf,const char * multipart_boundary)1685 parse_multipart_body (wmsMemBufferPtr buf, const char *multipart_boundary)
1686 {
1687 /* attempting to split a Multipart Response in its single parts */
1688 const char *p_in;
1689 char *marker = sqlite3_mprintf ("--%s\r\n", multipart_boundary);
1690 char *marker_end = sqlite3_mprintf ("--%s--\r\n", multipart_boundary);
1691 wmsMultipartCollectionPtr coll = wmsAllocMultipartCollection ();
1692 /* ensuring a NULL terminated string */
1693 if (buf->BufferSize > buf->WriteOffset)
1694 *(buf->Buffer + buf->WriteOffset) = '\0';
1695 else
1696 wmsMemBufferAppend (buf, (const unsigned char *) " ", 2);
1697 p_in = (const char *) buf->Buffer;
1698 while (p_in != NULL)
1699 {
1700 int len;
1701 const char *start_body;
1702 const char *stop;
1703 const char *start = strstr (p_in, marker);
1704 if (start == NULL)
1705 break;
1706 start_body = strstr (start, "\r\n\r\n");
1707 if (start_body == NULL)
1708 break;
1709 start_body += 4;
1710 stop = strstr (start_body, marker);
1711 if (stop != NULL)
1712 p_in = stop;
1713 else
1714 {
1715 stop = strstr (start_body, marker_end);
1716 if (stop == NULL)
1717 break;
1718 p_in = NULL;
1719 }
1720 stop -= 1;
1721 len = stop - start_body + 1;
1722 if (len > 0)
1723 {
1724 char *body;
1725 body = malloc (len + 1);
1726 memcpy (body, start_body, len);
1727 *(body + len) = '\0';
1728 wmsAddPartToMultipart (coll, body);
1729 }
1730 }
1731 sqlite3_free (marker);
1732 sqlite3_free (marker_end);
1733 if (coll->first == NULL)
1734 {
1735 wmsFreeMultipartCollection (coll);
1736 return NULL;
1737 }
1738 return coll;
1739 }
1740
1741 static size_t
store_data(char * ptr,size_t size,size_t nmemb,void * userdata)1742 store_data (char *ptr, size_t size, size_t nmemb, void *userdata)
1743 {
1744 /* updating the dynamic buffer */
1745 size_t total = size * nmemb;
1746 wmsMemBufferAppend (userdata, (unsigned char *) ptr, total);
1747 return total;
1748 }
1749
1750 static char *
parse_http_format(wmsMemBufferPtr buf)1751 parse_http_format (wmsMemBufferPtr buf)
1752 {
1753 /* parsing the Content-Type from the HTTP header */
1754 int i;
1755 unsigned char *p_in = NULL;
1756 unsigned char *base;
1757 int size = 0;
1758 char *tmp;
1759
1760 if (buf->Buffer == NULL)
1761 return NULL;
1762 for (i = 0; i < (int) (buf->WriteOffset) - 15; i++)
1763 {
1764 if (memcmp (buf->Buffer + i, "Content-Type: ", 14) == 0)
1765 {
1766 p_in = buf->Buffer + i + 14;
1767 break;
1768 }
1769 }
1770 if (p_in == NULL)
1771 return NULL;
1772
1773 /* attempting to retrieve the Content-Type */
1774 base = p_in;
1775 while ((size_t) (p_in - buf->Buffer) < buf->WriteOffset)
1776 {
1777 if (*p_in == '\r')
1778 break;
1779 size++;
1780 p_in++;
1781 }
1782 if (size <= 0)
1783 return NULL;
1784 tmp = malloc (size + 1);
1785 memcpy (tmp, base, size);
1786 *(tmp + size) = '\0';
1787 return tmp;
1788 }
1789
1790 static char *
parse_http_redirect(wmsMemBufferPtr buf)1791 parse_http_redirect (wmsMemBufferPtr buf)
1792 {
1793 /* parsing a redirect location from the HTTP header */
1794 int i;
1795 unsigned char *p_in = NULL;
1796 unsigned char *base;
1797 int size = 0;
1798 char *tmp;
1799
1800 if (buf->Buffer == NULL)
1801 return NULL;
1802 for (i = 0; i < (int) (buf->WriteOffset) - 11; i++)
1803 {
1804 if (memcmp (buf->Buffer + i, "Location: ", 10) == 0)
1805 {
1806 p_in = buf->Buffer + i + 10;
1807 break;
1808 }
1809 }
1810 if (p_in == NULL)
1811 return NULL;
1812
1813 /* attempting to retrieve the new HTTP location */
1814 base = p_in;
1815 while ((size_t) (p_in - buf->Buffer) < buf->WriteOffset)
1816 {
1817 if (*p_in == '\r')
1818 break;
1819 size++;
1820 p_in++;
1821 }
1822 if (size <= 0)
1823 return NULL;
1824 tmp = malloc (size + 1);
1825 memcpy (tmp, base, size);
1826 *(tmp + size) = '\0';
1827 return tmp;
1828 }
1829
1830 static void
check_http_header(wmsMemBufferPtr buf,int * http_status,char ** http_code)1831 check_http_header (wmsMemBufferPtr buf, int *http_status, char **http_code)
1832 {
1833 /* checking the HTTP header */
1834 unsigned char *p_in;
1835 unsigned char *base_status;
1836 unsigned char *base_code;
1837 int size_status = 0;
1838 int size_code = 0;
1839 char *tmp;
1840
1841 *http_status = -1;
1842 *http_code = NULL;
1843 if (buf->Buffer == NULL)
1844 return;
1845 if (buf->WriteOffset < 10)
1846 return;
1847 if (memcmp (buf->Buffer, "HTTP/1.1 ", 9) != 0
1848 && memcmp (buf->Buffer, "HTTP/1.0 ", 9) != 0)
1849 return;
1850
1851 /* attempting to retrieve the HTTP status */
1852 p_in = buf->Buffer + 9;
1853 base_status = p_in;
1854 while ((size_t) (p_in - buf->Buffer) < buf->WriteOffset)
1855 {
1856 if (*p_in == ' ')
1857 break;
1858 size_status++;
1859 p_in++;
1860 }
1861 if (size_status <= 0)
1862 return;
1863 tmp = malloc (size_status + 1);
1864 memcpy (tmp, base_status, size_status);
1865 *(tmp + size_status) = '\0';
1866 *http_status = atoi (tmp);
1867 free (tmp);
1868
1869 /* attempting to retrieve the HTTP code */
1870 p_in = buf->Buffer + 10 + size_status;
1871 base_code = p_in;
1872 while ((size_t) (p_in - buf->Buffer) < buf->WriteOffset)
1873 {
1874 if (*p_in == '\r')
1875 break;
1876 size_code++;
1877 p_in++;
1878 }
1879 if (size_code <= 0)
1880 return;
1881 tmp = malloc (size_code + 1);
1882 memcpy (tmp, base_code, size_code);
1883 *(tmp + size_code) = '\0';
1884 *http_code = tmp;
1885 }
1886
1887 static char *
check_http_multipart_response(wmsMemBufferPtr buf)1888 check_http_multipart_response (wmsMemBufferPtr buf)
1889 {
1890 /* testing for a Content-Type: multipart returning an eventual Boundary delimiter */
1891 int i;
1892 unsigned char *p_in = NULL;
1893 unsigned char *base;
1894 int size = 0;
1895 char *mime;
1896 const char *boundary;
1897 char *tmp;
1898
1899 if (buf->Buffer == NULL)
1900 return NULL;
1901 for (i = 0; i < (int) (buf->WriteOffset) - 15; i++)
1902 {
1903 if (memcmp (buf->Buffer + i, "Content-Type: ", 14) == 0)
1904 {
1905 p_in = buf->Buffer + i + 14;
1906 break;
1907 }
1908 }
1909 if (p_in == NULL)
1910 return NULL;
1911
1912 /* attempting to retrieve the Content-Type */
1913 base = p_in;
1914 while ((size_t) (p_in - buf->Buffer) < buf->WriteOffset)
1915 {
1916 if (*p_in == '\r')
1917 break;
1918 size++;
1919 p_in++;
1920 }
1921 if (size <= 0)
1922 return NULL;
1923 mime = malloc (size + 1);
1924 memcpy (mime, base, size);
1925 *(mime + size) = '\0';
1926 if (strncmp (mime, "multipart/", 10) != 0)
1927 goto not_found;
1928 boundary = strstr (mime, "boundary=");
1929 if (boundary == NULL)
1930 goto not_found;
1931 /* attempting to retrieve the Boundary */
1932 size = strlen (boundary + 9);
1933 if (size <= 0)
1934 goto not_found;
1935 tmp = malloc (size + 1);
1936 strcpy (tmp, boundary + 9);
1937 free (mime);
1938 return tmp;
1939 not_found:
1940 free (mime);
1941 return NULL;
1942 }
1943
1944 static int
start_cdata(const char * p_in,int i,int max)1945 start_cdata (const char *p_in, int i, int max)
1946 {
1947 /* testing for "<!CDATA[" - CDATA start marker */
1948 if (i + 9 >= max)
1949 return 0;
1950 if (*(p_in + i) == '<' && *(p_in + i + 1) == '!' && *(p_in + i + 2) == '['
1951 && *(p_in + i + 3) == 'C' && *(p_in + i + 4) == 'D'
1952 && *(p_in + i + 5) == 'A' && *(p_in + i + 6) == 'T'
1953 && *(p_in + i + 7) == 'A' && *(p_in + i + 8) == '[')
1954 return 1;
1955 return 0;
1956 }
1957
1958 static int
end_cdata(const char * p_in,int i)1959 end_cdata (const char *p_in, int i)
1960 {
1961 /* testing for "]]>" - CDATA end marker */
1962 if (i < 2)
1963 return 0;
1964 if (*(p_in + i - 2) == ']' && *(p_in + i - 1) == ']' && *(p_in + i) == '>')
1965 return 1;
1966 return 0;
1967 }
1968
1969 static char *
clean_xml(wmsMemBuffer * in)1970 clean_xml (wmsMemBuffer * in)
1971 {
1972 /* cleaning the XML payload by removing useless whitespaces */
1973 wmsMemBuffer outbuf;
1974 char *out;
1975 const char *p_in;
1976 int i;
1977 int j;
1978 int cdata = 0;
1979 int ignore = 0;
1980 if (in->WriteOffset <= 0)
1981 return NULL;
1982 wmsMemBufferInitialize (&outbuf);
1983
1984 p_in = (const char *) (in->Buffer);
1985 for (i = 0; i < (int) (in->WriteOffset); i++)
1986 {
1987 if (*(p_in + i) == '<')
1988 {
1989 if (!cdata)
1990 {
1991 if (start_cdata (p_in, i, in->WriteOffset))
1992 {
1993 i += 8;
1994 cdata = 1;
1995 continue;
1996 }
1997 for (j = outbuf.WriteOffset - 1; j > 0; j--)
1998 {
1999 /* consuming trailing whitespaces */
2000 if (*(outbuf.Buffer + j) == ' '
2001 || *(outbuf.Buffer + j) == '\t'
2002 || *(outbuf.Buffer + j) == '\r'
2003 || *(outbuf.Buffer + j) == '\n')
2004 {
2005 outbuf.WriteOffset -= 1;
2006 continue;
2007 }
2008 break;
2009 }
2010 ignore = 0;
2011 }
2012 }
2013 if (ignore)
2014 {
2015 if (*(p_in + i) == ' ' || *(p_in + i) == '\t'
2016 || *(p_in + i) == '\r' || *(p_in + i) == '\n')
2017 continue;
2018 else
2019 ignore = 0;
2020 }
2021 if (*(p_in + i) == '>' && cdata && end_cdata (p_in, i))
2022 {
2023 cdata = 0;
2024 outbuf.WriteOffset -= 2;
2025 continue;
2026 }
2027 if (cdata)
2028 {
2029 /* masking XML special characters */
2030 if (*(p_in + i) == '<')
2031 wmsMemBufferAppend (&outbuf, (const unsigned char *) "<",
2032 4);
2033 else if (*(p_in + i) == '>')
2034 wmsMemBufferAppend (&outbuf, (const unsigned char *) ">",
2035 4);
2036 else if (*(p_in + i) == '&')
2037 wmsMemBufferAppend (&outbuf,
2038 (const unsigned char *) "&", 5);
2039 else if (*(p_in + i) == '>')
2040 wmsMemBufferAppend (&outbuf,
2041 (const unsigned char *) """, 6);
2042 else
2043 wmsMemBufferAppend (&outbuf,
2044 (const unsigned char *) (p_in + i), 1);
2045 }
2046 else
2047 wmsMemBufferAppend (&outbuf, (const unsigned char *) (p_in + i),
2048 1);
2049 if (*(p_in + i) == '>')
2050 {
2051 if (!cdata)
2052 ignore = 1;
2053 }
2054 }
2055 out = malloc (outbuf.WriteOffset + 1);
2056 memcpy (out, outbuf.Buffer, outbuf.WriteOffset);
2057 *(out + outbuf.WriteOffset) = '\0';
2058 wmsMemBufferReset (&outbuf);
2059 return out;
2060 }
2061
2062 static char *
clean_xml_str(const char * p_in)2063 clean_xml_str (const char *p_in)
2064 {
2065 /* cleaning the XML payload by removing useless whitespaces */
2066 wmsMemBuffer outbuf;
2067 char *out;
2068 int i;
2069 int j;
2070 int cdata = 0;
2071 int ignore = 0;
2072 int len = strlen (p_in);
2073 if (len <= 0)
2074 return NULL;
2075 wmsMemBufferInitialize (&outbuf);
2076
2077 for (i = 0; i < len; i++)
2078 {
2079 if (*(p_in + i) == '<')
2080 {
2081 if (!cdata)
2082 {
2083 if (start_cdata (p_in, i, len))
2084 {
2085 i += 8;
2086 cdata = 1;
2087 continue;
2088 }
2089 for (j = outbuf.WriteOffset - 1; j > 0; j--)
2090 {
2091 /* consuming trailing whitespaces */
2092 if (*(outbuf.Buffer + j) == ' '
2093 || *(outbuf.Buffer + j) == '\t'
2094 || *(outbuf.Buffer + j) == '\r'
2095 || *(outbuf.Buffer + j) == '\n')
2096 {
2097 outbuf.WriteOffset -= 1;
2098 continue;
2099 }
2100 break;
2101 }
2102 ignore = 0;
2103 }
2104 }
2105 if (ignore)
2106 {
2107 if (*(p_in + i) == ' ' || *(p_in + i) == '\t'
2108 || *(p_in + i) == '\r' || *(p_in + i) == '\n')
2109 continue;
2110 else
2111 ignore = 0;
2112 }
2113 if (*(p_in + i) == '>' && cdata && end_cdata (p_in, i))
2114 {
2115 cdata = 0;
2116 outbuf.WriteOffset -= 2;
2117 continue;
2118 }
2119 if (cdata)
2120 {
2121 /* masking XML special characters */
2122 if (*(p_in + i) == '<')
2123 wmsMemBufferAppend (&outbuf, (const unsigned char *) "<",
2124 4);
2125 else if (*(p_in + i) == '>')
2126 wmsMemBufferAppend (&outbuf, (const unsigned char *) ">",
2127 4);
2128 else if (*(p_in + i) == '&')
2129 wmsMemBufferAppend (&outbuf,
2130 (const unsigned char *) "&", 5);
2131 else if (*(p_in + i) == '>')
2132 wmsMemBufferAppend (&outbuf,
2133 (const unsigned char *) """, 6);
2134 else
2135 wmsMemBufferAppend (&outbuf,
2136 (const unsigned char *) (p_in + i), 1);
2137 }
2138 else
2139 wmsMemBufferAppend (&outbuf, (const unsigned char *) (p_in + i),
2140 1);
2141 if (*(p_in + i) == '>')
2142 {
2143 if (!cdata)
2144 ignore = 1;
2145 }
2146 }
2147 out = malloc (outbuf.WriteOffset + 1);
2148 memcpy (out, outbuf.Buffer, outbuf.WriteOffset);
2149 *(out + outbuf.WriteOffset) = '\0';
2150 wmsMemBufferReset (&outbuf);
2151 return out;
2152 }
2153
2154 static void
wmsParsingError(void * ctx,const char * msg,...)2155 wmsParsingError (void *ctx, const char *msg, ...)
2156 {
2157 /* appending to the current Parsing Error buffer */
2158 wmsMemBufferPtr buf = (wmsMemBufferPtr) ctx;
2159 char out[65536];
2160 va_list args;
2161
2162 if (ctx != NULL)
2163 ctx = NULL; /* suppressing stupid compiler warnings (unused args) */
2164
2165 va_start (args, msg);
2166 vsnprintf (out, 65536, msg, args);
2167 wmsMemBufferAppend (buf, (unsigned char *) out, strlen (out));
2168 va_end (args);
2169 }
2170
2171 static void
parse_wms_EX_geoBBox(xmlNodePtr node,wmsLayerPtr lyr)2172 parse_wms_EX_geoBBox (xmlNodePtr node, wmsLayerPtr lyr)
2173 {
2174 /* parsing a WMS Layer/EX_GeographicBoundingBox */
2175 xmlNodePtr cur_node = NULL;
2176 xmlNodePtr child_node = NULL;
2177
2178 for (cur_node = node; cur_node; cur_node = cur_node->next)
2179 {
2180 if (cur_node->type == XML_ELEMENT_NODE)
2181 {
2182 if (strcmp
2183 ((const char *) (cur_node->name),
2184 "southBoundLatitude") == 0)
2185 {
2186 child_node = cur_node->children;
2187 if (child_node != NULL)
2188 {
2189 if (child_node->type == XML_TEXT_NODE)
2190 lyr->MinLat =
2191 atof ((const char *) (child_node->content));
2192 }
2193 }
2194 if (strcmp
2195 ((const char *) (cur_node->name),
2196 "northBoundLatitude") == 0)
2197 {
2198 child_node = cur_node->children;
2199 if (child_node != NULL)
2200 {
2201 if (child_node->type == XML_TEXT_NODE)
2202 lyr->MaxLat =
2203 atof ((const char *) (child_node->content));
2204 }
2205 }
2206 if (strcmp
2207 ((const char *) (cur_node->name),
2208 "westBoundLongitude") == 0)
2209 {
2210 child_node = cur_node->children;
2211 if (child_node != NULL)
2212 {
2213 if (child_node->type == XML_TEXT_NODE)
2214 lyr->MinLong =
2215 atof ((const char *) (child_node->content));
2216 }
2217 }
2218 if (strcmp
2219 ((const char *) (cur_node->name),
2220 "eastBoundLongitude") == 0)
2221 {
2222 child_node = cur_node->children;
2223 if (child_node != NULL)
2224 {
2225 if (child_node->type == XML_TEXT_NODE)
2226 lyr->MaxLong =
2227 atof ((const char *) (child_node->content));
2228 }
2229 }
2230 }
2231 }
2232 }
2233
2234 static void
parse_wms_geoBBox(struct _xmlAttr * properties,wmsLayerPtr lyr)2235 parse_wms_geoBBox (struct _xmlAttr *properties, wmsLayerPtr lyr)
2236 {
2237 /* parsing a WMS Layer/LatLonBoundingBox */
2238 struct _xmlAttr *attr = properties;
2239
2240 while (attr != NULL)
2241 {
2242 if (attr->name != NULL)
2243 {
2244 xmlNodePtr text;
2245 if (strcmp ((const char *) (attr->name), "miny") == 0)
2246 {
2247 text = attr->children;
2248 if (text->type == XML_TEXT_NODE)
2249 lyr->MinLat = atof ((const char *) (text->content));
2250 }
2251 if (strcmp ((const char *) (attr->name), "maxy") == 0)
2252 {
2253 text = attr->children;
2254 if (text->type == XML_TEXT_NODE)
2255 lyr->MaxLat = atof ((const char *) (text->content));
2256 }
2257 if (strcmp ((const char *) (attr->name), "minx") == 0)
2258 {
2259 text = attr->children;
2260 if (text->type == XML_TEXT_NODE)
2261 lyr->MinLong = atof ((const char *) (text->content));
2262 }
2263 if (strcmp ((const char *) (attr->name), "maxx") == 0)
2264 {
2265 text = attr->children;
2266 if (text->type == XML_TEXT_NODE)
2267 lyr->MaxLong = atof ((const char *) (text->content));
2268 }
2269 }
2270 attr = attr->next;
2271 }
2272 }
2273
2274 static void
parse_wms_BBox(struct _xmlAttr * properties,wmsLayerPtr lyr)2275 parse_wms_BBox (struct _xmlAttr *properties, wmsLayerPtr lyr)
2276 {
2277 /* parsing a WMS Layer/BoundingBox */
2278 struct _xmlAttr *attr = properties;
2279 const char *crs = NULL;
2280 double minx = DBL_MAX;
2281 double maxx = DBL_MAX;
2282 double miny = DBL_MAX;
2283 double maxy = DBL_MAX;
2284 wmsBBoxPtr bbox;
2285
2286 while (attr != NULL)
2287 {
2288 if (attr->name != NULL)
2289 {
2290 xmlNodePtr text;
2291 if (strcmp ((const char *) (attr->name), "CRS") == 0
2292 || strcmp ((const char *) (attr->name), "SRS") == 0)
2293 {
2294 text = attr->children;
2295 if (text->type == XML_TEXT_NODE)
2296 crs = (const char *) (text->content);
2297 }
2298 if (strcmp ((const char *) (attr->name), "miny") == 0)
2299 {
2300 text = attr->children;
2301 if (text->type == XML_TEXT_NODE)
2302 miny = atof ((const char *) (text->content));
2303 }
2304 if (strcmp ((const char *) (attr->name), "maxy") == 0)
2305 {
2306 text = attr->children;
2307 if (text->type == XML_TEXT_NODE)
2308 maxy = atof ((const char *) (text->content));
2309 }
2310 if (strcmp ((const char *) (attr->name), "minx") == 0)
2311 {
2312 text = attr->children;
2313 if (text->type == XML_TEXT_NODE)
2314 minx = atof ((const char *) (text->content));
2315 }
2316 if (strcmp ((const char *) (attr->name), "maxx") == 0)
2317 {
2318 text = attr->children;
2319 if (text->type == XML_TEXT_NODE)
2320 maxx = atof ((const char *) (text->content));
2321 }
2322 }
2323 attr = attr->next;
2324 }
2325 bbox = wmsAllocBBox (crs, minx, maxx, miny, maxy);
2326 if (lyr->firstBBox == NULL)
2327 lyr->firstBBox = bbox;
2328 if (lyr->lastBBox != NULL)
2329 lyr->lastBBox->next = bbox;
2330 lyr->lastBBox = bbox;
2331 }
2332
2333 static void
parse_wms_style(xmlNodePtr node,wmsLayerPtr lyr)2334 parse_wms_style (xmlNodePtr node, wmsLayerPtr lyr)
2335 {
2336 /* parsing a WMS Style definition */
2337 xmlNodePtr cur_node = NULL;
2338 xmlNodePtr child_node = NULL;
2339 const char *name = NULL;
2340 const char *title = NULL;
2341 const char *abstract = NULL;
2342 wmsStylePtr stl;
2343
2344 for (cur_node = node; cur_node; cur_node = cur_node->next)
2345 {
2346 if (cur_node->type == XML_ELEMENT_NODE)
2347 {
2348 if (strcmp ((const char *) (cur_node->name), "Name") == 0)
2349 {
2350 child_node = cur_node->children;
2351 if (child_node != NULL)
2352 {
2353 if (child_node->type == XML_TEXT_NODE)
2354 name = (const char *) (child_node->content);
2355 }
2356 }
2357 if (strcmp ((const char *) (cur_node->name), "Title") == 0)
2358 {
2359 child_node = cur_node->children;
2360 if (child_node != NULL)
2361 {
2362 if (child_node->type == XML_TEXT_NODE)
2363 title = (const char *) (child_node->content);
2364 }
2365 }
2366 if (strcmp ((const char *) (cur_node->name), "Abstract") == 0)
2367 {
2368 child_node = cur_node->children;
2369 if (child_node != NULL)
2370 {
2371 if (child_node->type == XML_TEXT_NODE)
2372 abstract = (const char *) (child_node->content);
2373 }
2374 }
2375 }
2376 }
2377
2378 stl = wmsAllocStyle (name, title, abstract);
2379 if (lyr->firstStyle == NULL)
2380 lyr->firstStyle = stl;
2381 if (lyr->lastStyle != NULL)
2382 lyr->lastStyle->next = stl;
2383 lyr->lastStyle = stl;
2384 }
2385
2386 static void
parse_wms_layer_in_layer(xmlNodePtr node,struct _xmlAttr * properties,wmsLayerPtr group,int level)2387 parse_wms_layer_in_layer (xmlNodePtr node, struct _xmlAttr *properties,
2388 wmsLayerPtr group, int level)
2389 {
2390 /* recursively parsing a WMS Layer definition (2nd level) */
2391 xmlNodePtr cur_node = NULL;
2392 xmlNodePtr child_node = NULL;
2393 const char *name = NULL;
2394 const char *title = NULL;
2395 const char *abstract = NULL;
2396 wmsLayerPtr lyr;
2397 struct _xmlAttr *attr;
2398
2399 for (cur_node = node; cur_node; cur_node = cur_node->next)
2400 {
2401 if (cur_node->type == XML_ELEMENT_NODE)
2402 {
2403 if (strcmp ((const char *) (cur_node->name), "Name") == 0)
2404 {
2405 child_node = cur_node->children;
2406 if (child_node != NULL)
2407 {
2408 if (child_node->type == XML_TEXT_NODE)
2409 name = (const char *) (child_node->content);
2410 }
2411 }
2412 if (strcmp ((const char *) (cur_node->name), "Title") == 0)
2413 {
2414 child_node = cur_node->children;
2415 if (child_node != NULL)
2416 {
2417 if (child_node->type == XML_TEXT_NODE)
2418 title = (const char *) (child_node->content);
2419 }
2420 }
2421 if (strcmp ((const char *) (cur_node->name), "Abstract") == 0)
2422 {
2423 child_node = cur_node->children;
2424 if (child_node != NULL)
2425 {
2426 if (child_node->type == XML_TEXT_NODE)
2427 abstract = (const char *) (child_node->content);
2428 }
2429 }
2430 }
2431 }
2432 lyr = wmsAllocLayer (name, title, abstract, group);
2433 if (group->firstLayer == NULL)
2434 group->firstLayer = lyr;
2435 if (group->lastLayer != NULL)
2436 group->lastLayer->next = lyr;
2437 group->lastLayer = lyr;
2438
2439 attr = properties;
2440 while (attr != NULL)
2441 {
2442 if (attr->name != NULL)
2443 {
2444 xmlNodePtr text;
2445 if (strcmp ((const char *) (attr->name), "queryable") == 0)
2446 {
2447 text = attr->children;
2448 if (text->type == XML_TEXT_NODE)
2449 lyr->Queryable =
2450 atoi ((const char *) (text->content));
2451 }
2452 if (strcmp ((const char *) (attr->name), "opaque") == 0)
2453 {
2454 text = attr->children;
2455 if (text->type == XML_TEXT_NODE)
2456 lyr->Opaque = atoi ((const char *) (text->content));
2457 }
2458 }
2459 attr = attr->next;
2460 }
2461
2462 for (cur_node = node; cur_node; cur_node = cur_node->next)
2463 {
2464 if (cur_node->type == XML_ELEMENT_NODE)
2465 {
2466 if (strcmp ((const char *) (cur_node->name), "CRS") == 0
2467 || strcmp ((const char *) (cur_node->name), "SRS") == 0)
2468 {
2469 xmlNodePtr child_node = cur_node->children;
2470 if (child_node != NULL)
2471 {
2472 if (child_node->type == XML_TEXT_NODE)
2473 {
2474 wmsCrsPtr crs;
2475 const char *crs_string =
2476 (const char *) (child_node->content);
2477 crs = wmsAllocCrs (crs_string);
2478 if (lyr->firstCrs == NULL)
2479 lyr->firstCrs = crs;
2480 if (lyr->lastCrs != NULL)
2481 lyr->lastCrs->next = crs;
2482 lyr->lastCrs = crs;
2483 }
2484 }
2485 }
2486 if (strcmp
2487 ((const char *) (cur_node->name),
2488 "EX_GeographicBoundingBox") == 0)
2489 parse_wms_EX_geoBBox (cur_node->children, lyr);
2490 if (strcmp
2491 ((const char *) (cur_node->name), "LatLonBoundingBox") == 0)
2492 parse_wms_geoBBox (cur_node->properties, lyr);
2493 if (strcmp ((const char *) (cur_node->name), "BoundingBox") ==
2494 0)
2495 parse_wms_BBox (cur_node->properties, lyr);
2496 if (strcmp ((const char *) (cur_node->name), "Style") == 0)
2497 parse_wms_style (cur_node->children, lyr);
2498 if (strcmp
2499 ((const char *) (cur_node->name),
2500 "MinScaleDenominator") == 0)
2501 {
2502 xmlNodePtr child_node = cur_node->children;
2503 if (child_node != NULL)
2504 {
2505 if (child_node->type == XML_TEXT_NODE)
2506 {
2507 const char *str =
2508 (const char *) (child_node->content);
2509 lyr->MinScaleDenominator = atof (str);
2510 }
2511 }
2512 }
2513 if (strcmp
2514 ((const char *) (cur_node->name),
2515 "MaxScaleDenominator") == 0)
2516 {
2517 xmlNodePtr child_node = cur_node->children;
2518 if (child_node != NULL)
2519 {
2520 if (child_node->type == XML_TEXT_NODE)
2521 {
2522 const char *str =
2523 (const char *) (child_node->content);
2524 lyr->MaxScaleDenominator = atof (str);
2525 }
2526 }
2527 }
2528 if (strcmp ((const char *) (cur_node->name), "Layer") == 0)
2529 parse_wms_layer_in_layer (cur_node->children,
2530 cur_node->properties, lyr,
2531 level + 1);
2532 }
2533 }
2534 }
2535
2536 static void
parse_wms_layer(xmlNodePtr node,struct _xmlAttr * properties,wmsCapabilitiesPtr cap)2537 parse_wms_layer (xmlNodePtr node, struct _xmlAttr *properties,
2538 wmsCapabilitiesPtr cap)
2539 {
2540 /* parsing a WMS Layer definition */
2541 xmlNodePtr cur_node = NULL;
2542 xmlNodePtr child_node = NULL;
2543 const char *name = NULL;
2544 const char *title = NULL;
2545 const char *abstract = NULL;
2546 wmsLayerPtr lyr;
2547 struct _xmlAttr *attr;
2548
2549 for (cur_node = node; cur_node; cur_node = cur_node->next)
2550 {
2551 if (cur_node->type == XML_ELEMENT_NODE)
2552 {
2553 if (strcmp ((const char *) (cur_node->name), "Name") == 0)
2554 {
2555 child_node = cur_node->children;
2556 if (child_node != NULL)
2557 {
2558 if (child_node->type == XML_TEXT_NODE)
2559 name = (const char *) (child_node->content);
2560 }
2561 }
2562 if (strcmp ((const char *) (cur_node->name), "Title") == 0)
2563 {
2564 child_node = cur_node->children;
2565 if (child_node != NULL)
2566 {
2567 if (child_node->type == XML_TEXT_NODE)
2568 title = (const char *) (child_node->content);
2569 }
2570 }
2571 if (strcmp ((const char *) (cur_node->name), "Abstract") == 0)
2572 {
2573 child_node = cur_node->children;
2574 if (child_node != NULL)
2575 {
2576 if (child_node->type == XML_TEXT_NODE)
2577 abstract = (const char *) (child_node->content);
2578 }
2579 }
2580 }
2581 }
2582 lyr = wmsAllocLayer (name, title, abstract, NULL);
2583 if (cap->firstLayer == NULL)
2584 cap->firstLayer = lyr;
2585 if (cap->lastLayer != NULL)
2586 cap->lastLayer->next = lyr;
2587 cap->lastLayer = lyr;
2588
2589 attr = properties;
2590 while (attr != NULL)
2591 {
2592 if (attr->name != NULL)
2593 {
2594 xmlNodePtr text;
2595 if (strcmp ((const char *) (attr->name), "queryable") == 0)
2596 {
2597 text = attr->children;
2598 if (text->type == XML_TEXT_NODE)
2599 lyr->Queryable =
2600 atoi ((const char *) (text->content));
2601 }
2602 if (strcmp ((const char *) (attr->name), "opaque") == 0)
2603 {
2604 text = attr->children;
2605 if (text->type == XML_TEXT_NODE)
2606 lyr->Opaque = atoi ((const char *) (text->content));
2607 }
2608 }
2609 attr = attr->next;
2610 }
2611
2612 for (cur_node = node; cur_node; cur_node = cur_node->next)
2613 {
2614 if (cur_node->type == XML_ELEMENT_NODE)
2615 {
2616 if (strcmp ((const char *) (cur_node->name), "CRS") == 0
2617 || strcmp ((const char *) (cur_node->name), "SRS") == 0)
2618 {
2619 xmlNodePtr child_node = cur_node->children;
2620 if (child_node != NULL)
2621 {
2622 if (child_node->type == XML_TEXT_NODE)
2623 {
2624 wmsCrsPtr crs;
2625 const char *crs_string =
2626 (const char *) (child_node->content);
2627 crs = wmsAllocCrs (crs_string);
2628 if (lyr->firstCrs == NULL)
2629 lyr->firstCrs = crs;
2630 if (lyr->lastCrs != NULL)
2631 lyr->lastCrs->next = crs;
2632 lyr->lastCrs = crs;
2633 }
2634 }
2635 }
2636 if (strcmp
2637 ((const char *) (cur_node->name),
2638 "EX_GeographicBoundingBox") == 0)
2639 parse_wms_EX_geoBBox (cur_node->children, lyr);
2640 if (strcmp
2641 ((const char *) (cur_node->name), "LatLonBoundingBox") == 0)
2642 parse_wms_geoBBox (cur_node->properties, lyr);
2643 if (strcmp ((const char *) (cur_node->name), "BoundingBox") ==
2644 0)
2645 parse_wms_BBox (cur_node->properties, lyr);
2646 if (strcmp ((const char *) (cur_node->name), "Style") == 0)
2647 parse_wms_style (cur_node->children, lyr);
2648 if (strcmp
2649 ((const char *) (cur_node->name),
2650 "MinScaleDenominator") == 0)
2651 {
2652 xmlNodePtr child_node = cur_node->children;
2653 if (child_node != NULL)
2654 {
2655 if (child_node->type == XML_TEXT_NODE)
2656 {
2657 const char *str =
2658 (const char *) (child_node->content);
2659 lyr->MinScaleDenominator = atof (str);
2660 }
2661 }
2662 }
2663 if (strcmp
2664 ((const char *) (cur_node->name),
2665 "MaxScaleDenominator") == 0)
2666 {
2667 xmlNodePtr child_node = cur_node->children;
2668 if (child_node != NULL)
2669 {
2670 if (child_node->type == XML_TEXT_NODE)
2671 {
2672 const char *str =
2673 (const char *) (child_node->content);
2674 lyr->MaxScaleDenominator = atof (str);
2675 }
2676 }
2677 }
2678 if (strcmp ((const char *) (cur_node->name), "Layer") == 0)
2679 parse_wms_layer_in_layer (cur_node->children,
2680 cur_node->properties, lyr, 0);
2681 }
2682 }
2683 }
2684
2685 static void
parse_wms_contact_person(xmlNodePtr node,const char ** contact_person,const char ** contact_organization)2686 parse_wms_contact_person (xmlNodePtr node, const char **contact_person,
2687 const char **contact_organization)
2688 {
2689 /* parsing a WMS ContactPersonPrimary definition */
2690 xmlNodePtr cur_node = NULL;
2691 xmlNodePtr child_node = NULL;
2692
2693 for (cur_node = node; cur_node; cur_node = cur_node->next)
2694 {
2695 if (cur_node->type == XML_ELEMENT_NODE)
2696 {
2697 if (strcmp
2698 ((const char *) (cur_node->name),
2699 "ContactOrganization") == 0)
2700 {
2701 child_node = cur_node->children;
2702 if (child_node != NULL)
2703 {
2704 if (child_node->type == XML_TEXT_NODE)
2705 *contact_organization =
2706 (const char *) (child_node->content);
2707 }
2708 }
2709 if (strcmp ((const char *) (cur_node->name), "ContactPerson") ==
2710 0)
2711 {
2712 child_node = cur_node->children;
2713 if (child_node != NULL)
2714 {
2715 if (child_node->type == XML_TEXT_NODE)
2716 *contact_person =
2717 (const char *) (child_node->content);
2718 }
2719 }
2720 }
2721 }
2722 }
2723
2724 static void
parse_wms_contact_address(xmlNodePtr node,const char ** postal_address,const char ** city,const char ** state_province,const char ** post_code,const char ** country)2725 parse_wms_contact_address (xmlNodePtr node, const char **postal_address,
2726 const char **city, const char **state_province,
2727 const char **post_code, const char **country)
2728 {
2729 /* parsing a WMS ContactAddress definition */
2730 xmlNodePtr cur_node = NULL;
2731 xmlNodePtr child_node = NULL;
2732
2733 for (cur_node = node; cur_node; cur_node = cur_node->next)
2734 {
2735 if (cur_node->type == XML_ELEMENT_NODE)
2736 {
2737 if (strcmp ((const char *) (cur_node->name), "Address") == 0)
2738 {
2739 child_node = cur_node->children;
2740 if (child_node != NULL)
2741 {
2742 if (child_node->type == XML_TEXT_NODE)
2743 *postal_address =
2744 (const char *) (child_node->content);
2745 }
2746 }
2747 if (strcmp ((const char *) (cur_node->name), "City") == 0)
2748 {
2749 child_node = cur_node->children;
2750 if (child_node != NULL)
2751 {
2752 if (child_node->type == XML_TEXT_NODE)
2753 *city = (const char *) (child_node->content);
2754 }
2755 }
2756 if (strcmp ((const char *) (cur_node->name), "StateOrProvince")
2757 == 0)
2758 {
2759 child_node = cur_node->children;
2760 if (child_node != NULL)
2761 {
2762 if (child_node->type == XML_TEXT_NODE)
2763 *state_province =
2764 (const char *) (child_node->content);
2765 }
2766 }
2767 if (strcmp ((const char *) (cur_node->name), "PostCode") == 0)
2768 {
2769 child_node = cur_node->children;
2770 if (child_node != NULL)
2771 {
2772 if (child_node->type == XML_TEXT_NODE)
2773 *post_code =
2774 (const char *) (child_node->content);
2775 }
2776 }
2777 if (strcmp ((const char *) (cur_node->name), "Country") == 0)
2778 {
2779 child_node = cur_node->children;
2780 if (child_node != NULL)
2781 {
2782 if (child_node->type == XML_TEXT_NODE)
2783 *country = (const char *) (child_node->content);
2784 }
2785 }
2786 }
2787 }
2788 }
2789
2790 static void
parse_wms_contact_information(xmlNodePtr node,const char ** contact_person,const char ** contact_organization,const char ** contact_position,const char ** postal_address,const char ** city,const char ** state_province,const char ** post_code,const char ** country,const char ** voice_telephone,const char ** fax_telephone,const char ** email_address)2791 parse_wms_contact_information (xmlNodePtr node, const char **contact_person,
2792 const char **contact_organization,
2793 const char **contact_position,
2794 const char **postal_address, const char **city,
2795 const char **state_province,
2796 const char **post_code, const char **country,
2797 const char **voice_telephone,
2798 const char **fax_telephone,
2799 const char **email_address)
2800 {
2801 /* parsing a WMS ContactInformation definition */
2802 xmlNodePtr cur_node = NULL;
2803 xmlNodePtr child_node = NULL;
2804
2805 for (cur_node = node; cur_node; cur_node = cur_node->next)
2806 {
2807 if (cur_node->type == XML_ELEMENT_NODE)
2808 {
2809 if (strcmp ((const char *) (cur_node->name), "ContactPosition")
2810 == 0)
2811 {
2812 child_node = cur_node->children;
2813 if (child_node != NULL)
2814 {
2815 if (child_node->type == XML_TEXT_NODE)
2816 *contact_position =
2817 (const char *) (child_node->content);
2818 }
2819 }
2820 if (strcmp
2821 ((const char *) (cur_node->name),
2822 "ContactPersonPrimary") == 0)
2823 parse_wms_contact_person (cur_node->children,
2824 contact_person,
2825 contact_organization);
2826 if (strcmp ((const char *) (cur_node->name), "ContactAddress")
2827 == 0)
2828 parse_wms_contact_address (cur_node->children,
2829 postal_address, city,
2830 state_province, post_code,
2831 country);
2832 if (strcmp
2833 ((const char *) (cur_node->name),
2834 "ContactVoiceTelephone") == 0)
2835 {
2836 child_node = cur_node->children;
2837 if (child_node != NULL)
2838 {
2839 if (child_node->type == XML_TEXT_NODE)
2840 *voice_telephone =
2841 (const char *) (child_node->content);
2842 }
2843 }
2844 if (strcmp
2845 ((const char *) (cur_node->name),
2846 "ContactFacsimileTelephone") == 0)
2847 {
2848 child_node = cur_node->children;
2849 if (child_node != NULL)
2850 {
2851 if (child_node->type == XML_TEXT_NODE)
2852 *fax_telephone =
2853 (const char *) (child_node->content);
2854 }
2855 }
2856 if (strcmp
2857 ((const char *) (cur_node->name),
2858 "ContactElectronicMailAddress") == 0)
2859 {
2860 child_node = cur_node->children;
2861 if (child_node != NULL)
2862 {
2863 if (child_node->type == XML_TEXT_NODE)
2864 *email_address =
2865 (const char *) (child_node->content);
2866 }
2867 }
2868 }
2869 }
2870 }
2871
2872 static void
parse_wms_service(xmlNodePtr node,wmsCapabilitiesPtr cap)2873 parse_wms_service (xmlNodePtr node, wmsCapabilitiesPtr cap)
2874 {
2875 /* parsing a WMS Service definition */
2876 xmlNodePtr cur_node = NULL;
2877 xmlNodePtr child_node = NULL;
2878 const char *name = NULL;
2879 const char *title = NULL;
2880 const char *abstract = NULL;
2881 const char *contact_person = NULL;
2882 const char *contact_organization = NULL;
2883 const char *contact_position = NULL;
2884 const char *postal_address = NULL;
2885 const char *city = NULL;
2886 const char *state_province = NULL;
2887 const char *post_code = NULL;
2888 const char *country = NULL;
2889 const char *voice_telephone = NULL;
2890 const char *fax_telephone = NULL;
2891 const char *email_address = NULL;
2892 const char *fees = NULL;
2893 const char *access_constraints = NULL;
2894 int layer_limit = -1;
2895 int maxWidth = -1;
2896 int maxHeight = -1;
2897 int len;
2898
2899 for (cur_node = node; cur_node; cur_node = cur_node->next)
2900 {
2901 if (cur_node->type == XML_ELEMENT_NODE)
2902 {
2903 if (strcmp ((const char *) (cur_node->name), "Name") == 0)
2904 {
2905 child_node = cur_node->children;
2906 if (child_node != NULL)
2907 {
2908 if (child_node->type == XML_TEXT_NODE)
2909 name = (const char *) (child_node->content);
2910 }
2911 }
2912 if (strcmp ((const char *) (cur_node->name), "Title") == 0)
2913 {
2914 child_node = cur_node->children;
2915 if (child_node != NULL)
2916 {
2917 if (child_node->type == XML_TEXT_NODE)
2918 title = (const char *) (child_node->content);
2919 }
2920 }
2921 if (strcmp ((const char *) (cur_node->name), "Abstract") == 0)
2922 {
2923 child_node = cur_node->children;
2924 if (child_node != NULL)
2925 {
2926 if (child_node->type == XML_TEXT_NODE)
2927 abstract = (const char *) (child_node->content);
2928 }
2929 }
2930 if (strcmp
2931 ((const char *) (cur_node->name),
2932 "ContactInformation") == 0)
2933 parse_wms_contact_information (cur_node->children,
2934 &contact_person,
2935 &contact_organization,
2936 &contact_position,
2937 &postal_address, &city,
2938 &state_province, &post_code,
2939 &country, &voice_telephone,
2940 &fax_telephone,
2941 &email_address);
2942 if (strcmp ((const char *) (cur_node->name), "Fees") == 0)
2943 {
2944 child_node = cur_node->children;
2945 if (child_node != NULL)
2946 {
2947 if (child_node->type == XML_TEXT_NODE)
2948 fees = (const char *) (child_node->content);
2949 }
2950 }
2951 if (strcmp
2952 ((const char *) (cur_node->name), "AccessConstraints") == 0)
2953 {
2954 child_node = cur_node->children;
2955 if (child_node != NULL)
2956 {
2957 if (child_node->type == XML_TEXT_NODE)
2958 access_constraints =
2959 (const char *) (child_node->content);
2960 }
2961 }
2962 if (strcmp ((const char *) (cur_node->name), "LayerLimit") == 0)
2963 {
2964 child_node = cur_node->children;
2965 if (child_node != NULL)
2966 {
2967 if (child_node->type == XML_TEXT_NODE)
2968 layer_limit =
2969 atoi ((const char *) (child_node->content));
2970 }
2971 }
2972 if (strcmp ((const char *) (cur_node->name), "MaxWidth") == 0)
2973 {
2974 child_node = cur_node->children;
2975 if (child_node != NULL)
2976 {
2977 if (child_node->type == XML_TEXT_NODE)
2978 maxWidth =
2979 atoi ((const char *) (child_node->content));
2980 }
2981 }
2982 if (strcmp ((const char *) (cur_node->name), "MaxHeight") == 0)
2983 {
2984 child_node = cur_node->children;
2985 if (child_node != NULL)
2986 {
2987 if (child_node->type == XML_TEXT_NODE)
2988 maxHeight =
2989 atoi ((const char *) (child_node->content));
2990 }
2991 }
2992 }
2993 }
2994
2995 if (cap->Name != NULL)
2996 {
2997 free (cap->Name);
2998 cap->Name = NULL;
2999 }
3000 if (name != NULL)
3001 {
3002 len = strlen (name);
3003 cap->Name = malloc (len + 1);
3004 strcpy (cap->Name, name);
3005 }
3006 if (cap->Title != NULL)
3007 {
3008 free (cap->Title);
3009 cap->Title = NULL;
3010 }
3011 if (title != NULL)
3012 {
3013 len = strlen (title);
3014 cap->Title = malloc (len + 1);
3015 strcpy (cap->Title, title);
3016 }
3017 if (cap->Abstract != NULL)
3018 {
3019 free (cap->Abstract);
3020 cap->Abstract = NULL;
3021 }
3022 if (abstract != NULL)
3023 {
3024 len = strlen (abstract);
3025 cap->Abstract = malloc (len + 1);
3026 strcpy (cap->Abstract, abstract);
3027 }
3028 if (contact_person != NULL)
3029 {
3030 len = strlen (contact_person);
3031 cap->ContactPerson = malloc (len + 1);
3032 strcpy (cap->ContactPerson, contact_person);
3033 }
3034 if (contact_organization != NULL)
3035 {
3036 len = strlen (contact_organization);
3037 cap->ContactOrganization = malloc (len + 1);
3038 strcpy (cap->ContactOrganization, contact_organization);
3039 }
3040 if (contact_position != NULL)
3041 {
3042 len = strlen (contact_position);
3043 cap->ContactPosition = malloc (len + 1);
3044 strcpy (cap->ContactPosition, contact_position);
3045 }
3046 if (postal_address != NULL)
3047 {
3048 len = strlen (postal_address);
3049 cap->PostalAddress = malloc (len + 1);
3050 strcpy (cap->PostalAddress, postal_address);
3051 }
3052 if (city != NULL)
3053 {
3054 len = strlen (city);
3055 cap->City = malloc (len + 1);
3056 strcpy (cap->City, city);
3057 }
3058 if (state_province != NULL)
3059 {
3060 len = strlen (state_province);
3061 cap->StateProvince = malloc (len + 1);
3062 strcpy (cap->StateProvince, state_province);
3063 }
3064 if (post_code != NULL)
3065 {
3066 len = strlen (post_code);
3067 cap->PostCode = malloc (len + 1);
3068 strcpy (cap->PostCode, post_code);
3069 }
3070 if (country != NULL)
3071 {
3072 len = strlen (country);
3073 cap->Country = malloc (len + 1);
3074 strcpy (cap->Country, country);
3075 }
3076 if (voice_telephone != NULL)
3077 {
3078 len = strlen (voice_telephone);
3079 cap->VoiceTelephone = malloc (len + 1);
3080 strcpy (cap->VoiceTelephone, voice_telephone);
3081 }
3082 if (fax_telephone != NULL)
3083 {
3084 len = strlen (fax_telephone);
3085 cap->FaxTelephone = malloc (len + 1);
3086 strcpy (cap->FaxTelephone, fax_telephone);
3087 }
3088 if (email_address != NULL)
3089 {
3090 len = strlen (email_address);
3091 cap->EMailAddress = malloc (len + 1);
3092 strcpy (cap->EMailAddress, email_address);
3093 }
3094 if (fees != NULL)
3095 {
3096 len = strlen (fees);
3097 cap->Fees = malloc (len + 1);
3098 strcpy (cap->Fees, fees);
3099 }
3100 if (access_constraints != NULL)
3101 {
3102 len = strlen (access_constraints);
3103 cap->AccessConstraints = malloc (len + 1);
3104 strcpy (cap->AccessConstraints, access_constraints);
3105 }
3106 if (layer_limit > 0)
3107 cap->LayerLimit = layer_limit;
3108 if (maxWidth > 0)
3109 cap->MaxWidth = maxWidth;
3110 if (maxHeight > 0)
3111 cap->MaxHeight = maxHeight;
3112 }
3113
3114 static void
parse_wms_GetMap_HTTP_Get(xmlNodePtr node,wmsCapabilitiesPtr cap)3115 parse_wms_GetMap_HTTP_Get (xmlNodePtr node, wmsCapabilitiesPtr cap)
3116 {
3117 /* recursively parsing the GetCapabilities/Capability/Request/GetMap/DCPType/HTTP/Get node */
3118 xmlNodePtr cur_node = NULL;
3119 int len;
3120 const char *p;
3121
3122 for (cur_node = node; cur_node; cur_node = cur_node->next)
3123 {
3124 if (cur_node->type == XML_ELEMENT_NODE)
3125 {
3126 if (strcmp ((const char *) (cur_node->name), "OnlineResource")
3127 == 0)
3128 {
3129 struct _xmlAttr *attr = cur_node->properties;
3130 while (attr != NULL)
3131 {
3132 if (attr->name != NULL)
3133 {
3134 if (strcmp
3135 ((const char *) (attr->name),
3136 "href") == 0)
3137 {
3138 xmlNodePtr text = attr->children;
3139 if (text->type == XML_TEXT_NODE)
3140 {
3141 if (cap->GetMapURLGet != NULL)
3142 {
3143 free (cap->GetMapURLGet);
3144 cap->GetMapURLGet = NULL;
3145 }
3146 p = (const char
3147 *) (text->content);
3148 len = strlen (p);
3149 cap->GetMapURLGet =
3150 malloc (len + 1);
3151 strcpy (cap->GetMapURLGet, p);
3152 }
3153 }
3154 }
3155 attr = attr->next;
3156 }
3157 }
3158 }
3159 }
3160 }
3161
3162 static void
parse_wms_GetMap_HTTP_Post(xmlNodePtr node,wmsCapabilitiesPtr cap)3163 parse_wms_GetMap_HTTP_Post (xmlNodePtr node, wmsCapabilitiesPtr cap)
3164 {
3165 /* recursively parsing the GetCapabilities/Capability/Request/GetMap/DCPType/HTTP/Post node */
3166 xmlNodePtr cur_node = NULL;
3167 int len;
3168 const char *p;
3169
3170 for (cur_node = node; cur_node; cur_node = cur_node->next)
3171 {
3172 if (cur_node->type == XML_ELEMENT_NODE)
3173 {
3174 if (strcmp ((const char *) (cur_node->name), "OnlineResource")
3175 == 0)
3176 {
3177 struct _xmlAttr *attr = cur_node->properties;
3178 while (attr != NULL)
3179 {
3180 if (attr->name != NULL)
3181 {
3182 if (strcmp
3183 ((const char *) (attr->name),
3184 "href") == 0)
3185 {
3186 xmlNodePtr text = attr->children;
3187 if (text->type == XML_TEXT_NODE)
3188 {
3189 if (cap->GetMapURLPost != NULL)
3190 {
3191 free (cap->GetMapURLPost);
3192 cap->GetMapURLPost = NULL;
3193 }
3194 p = (const char
3195 *) (text->content);
3196 len = strlen (p);
3197 cap->GetMapURLPost =
3198 malloc (len + 1);
3199 strcpy (cap->GetMapURLPost, p);
3200 }
3201 }
3202 }
3203 attr = attr->next;
3204 }
3205 }
3206 }
3207 }
3208 }
3209
3210 static void
parse_wms_GetTileService_HTTP_Get(xmlNodePtr node,wmsCapabilitiesPtr cap)3211 parse_wms_GetTileService_HTTP_Get (xmlNodePtr node, wmsCapabilitiesPtr cap)
3212 {
3213 /* recursively parsing the GetCapabilities/Capability/Request/GetTileService/DCPType/HTTP/Get node */
3214 xmlNodePtr cur_node = NULL;
3215 int len;
3216 const char *p;
3217
3218 for (cur_node = node; cur_node; cur_node = cur_node->next)
3219 {
3220 if (cur_node->type == XML_ELEMENT_NODE)
3221 {
3222 if (strcmp ((const char *) (cur_node->name), "OnlineResource")
3223 == 0)
3224 {
3225 struct _xmlAttr *attr = cur_node->properties;
3226 while (attr != NULL)
3227 {
3228 if (attr->name != NULL)
3229 {
3230 if (strcmp
3231 ((const char *) (attr->name),
3232 "href") == 0)
3233 {
3234 xmlNodePtr text = attr->children;
3235 if (text->type == XML_TEXT_NODE)
3236 {
3237 if (cap->GetTileServiceURLGet !=
3238 NULL)
3239 {
3240 free (cap->
3241 GetTileServiceURLGet);
3242 cap->GetMapURLGet = NULL;
3243 }
3244 p = (const char
3245 *) (text->content);
3246 len = strlen (p);
3247 cap->GetTileServiceURLGet =
3248 malloc (len + 1);
3249 strcpy (cap->GetTileServiceURLGet,
3250 p);
3251 }
3252 }
3253 }
3254 attr = attr->next;
3255 }
3256 }
3257 }
3258 }
3259 }
3260
3261 static void
parse_wms_GetTileService_HTTP_Post(xmlNodePtr node,wmsCapabilitiesPtr cap)3262 parse_wms_GetTileService_HTTP_Post (xmlNodePtr node, wmsCapabilitiesPtr cap)
3263 {
3264 /* recursively parsing the GetCapabilities/Capability/Request/GetTileService/DCPType/HTTP/Post node */
3265 xmlNodePtr cur_node = NULL;
3266 int len;
3267 const char *p;
3268
3269 for (cur_node = node; cur_node; cur_node = cur_node->next)
3270 {
3271 if (cur_node->type == XML_ELEMENT_NODE)
3272 {
3273 if (strcmp ((const char *) (cur_node->name), "OnlineResource")
3274 == 0)
3275 {
3276 struct _xmlAttr *attr = cur_node->properties;
3277 while (attr != NULL)
3278 {
3279 if (attr->name != NULL)
3280 {
3281 if (strcmp
3282 ((const char *) (attr->name),
3283 "href") == 0)
3284 {
3285 xmlNodePtr text = attr->children;
3286 if (text->type == XML_TEXT_NODE)
3287 {
3288 if (cap->GetTileServiceURLPost !=
3289 NULL)
3290 {
3291 free (cap->
3292 GetTileServiceURLPost);
3293 cap->GetTileServiceURLPost =
3294 NULL;
3295 }
3296 p = (const char
3297 *) (text->content);
3298 len = strlen (p);
3299 cap->GetTileServiceURLPost =
3300 malloc (len + 1);
3301 strcpy
3302 (cap->GetTileServiceURLPost,
3303 p);
3304 }
3305 }
3306 }
3307 attr = attr->next;
3308 }
3309 }
3310 }
3311 }
3312 }
3313
3314 static void
parse_wms_GetInfo_HTTP_Get(xmlNodePtr node,wmsCapabilitiesPtr cap)3315 parse_wms_GetInfo_HTTP_Get (xmlNodePtr node, wmsCapabilitiesPtr cap)
3316 {
3317 /* recursively parsing the GetCapabilities/Capability/Request/GetFeatureInfo/DCPType/HTTP/Get node */
3318 xmlNodePtr cur_node = NULL;
3319 int len;
3320 const char *p;
3321
3322 for (cur_node = node; cur_node; cur_node = cur_node->next)
3323 {
3324 if (cur_node->type == XML_ELEMENT_NODE)
3325 {
3326 if (strcmp ((const char *) (cur_node->name), "OnlineResource")
3327 == 0)
3328 {
3329 struct _xmlAttr *attr = cur_node->properties;
3330 while (attr != NULL)
3331 {
3332 if (attr->name != NULL)
3333 {
3334 if (strcmp
3335 ((const char *) (attr->name),
3336 "href") == 0)
3337 {
3338 xmlNodePtr text = attr->children;
3339 if (text->type == XML_TEXT_NODE)
3340 {
3341 if (cap->GetFeatureInfoURLGet !=
3342 NULL)
3343 {
3344 free (cap->GetFeatureInfoURLGet);
3345 cap->GetFeatureInfoURLGet =
3346 NULL;
3347 }
3348 p = (const char
3349 *) (text->content);
3350 len = strlen (p);
3351 cap->GetFeatureInfoURLGet =
3352 malloc (len + 1);
3353 strcpy (cap->GetFeatureInfoURLGet,
3354 p);
3355 }
3356 }
3357 }
3358 attr = attr->next;
3359 }
3360 }
3361 }
3362 }
3363 }
3364
3365 static void
parse_wms_GetInfo_HTTP_Post(xmlNodePtr node,wmsCapabilitiesPtr cap)3366 parse_wms_GetInfo_HTTP_Post (xmlNodePtr node, wmsCapabilitiesPtr cap)
3367 {
3368 /* recursively parsing the GetCapabilities/Capability/Request/GetFeatureInfo/DCPType/HTTP/Post node */
3369 xmlNodePtr cur_node = NULL;
3370 int len;
3371 const char *p;
3372
3373 for (cur_node = node; cur_node; cur_node = cur_node->next)
3374 {
3375 if (cur_node->type == XML_ELEMENT_NODE)
3376 {
3377 if (strcmp ((const char *) (cur_node->name), "OnlineResource")
3378 == 0)
3379 {
3380 struct _xmlAttr *attr = cur_node->properties;
3381 while (attr != NULL)
3382 {
3383 if (attr->name != NULL)
3384 {
3385 if (strcmp
3386 ((const char *) (attr->name),
3387 "href") == 0)
3388 {
3389 xmlNodePtr text = attr->children;
3390 if (text->type == XML_TEXT_NODE)
3391 {
3392 if (cap->GetFeatureInfoURLPost !=
3393 NULL)
3394 {
3395 free (cap->GetFeatureInfoURLPost);
3396 cap->GetFeatureInfoURLPost =
3397 NULL;
3398 }
3399 p = (const char
3400 *) (text->content);
3401 len = strlen (p);
3402 cap->GetFeatureInfoURLPost =
3403 malloc (len + 1);
3404 strcpy
3405 (cap->GetFeatureInfoURLPost,
3406 p);
3407 }
3408 }
3409 }
3410 attr = attr->next;
3411 }
3412 }
3413 }
3414 }
3415 }
3416
3417 static void
parse_wms_GetMap_HTTP(xmlNodePtr node,wmsCapabilitiesPtr cap)3418 parse_wms_GetMap_HTTP (xmlNodePtr node, wmsCapabilitiesPtr cap)
3419 {
3420 /* recursively parsing the GetCapabilities/Capability/Request/GetMap/DCPType node */
3421 xmlNodePtr cur_node = NULL;
3422
3423 for (cur_node = node; cur_node; cur_node = cur_node->next)
3424 {
3425 if (cur_node->type == XML_ELEMENT_NODE)
3426 {
3427 if (strcmp ((const char *) (cur_node->name), "Get") == 0)
3428 parse_wms_GetMap_HTTP_Get (cur_node->children, cap);
3429 if (strcmp ((const char *) (cur_node->name), "Post") == 0)
3430 parse_wms_GetMap_HTTP_Post (cur_node->children, cap);
3431 }
3432 }
3433 }
3434
3435 static void
parse_wms_GetTileService_HTTP(xmlNodePtr node,wmsCapabilitiesPtr cap)3436 parse_wms_GetTileService_HTTP (xmlNodePtr node, wmsCapabilitiesPtr cap)
3437 {
3438 /* recursively parsing the GetCapabilities/Capability/Request/GetTileService/DCPType node */
3439 xmlNodePtr cur_node = NULL;
3440
3441 for (cur_node = node; cur_node; cur_node = cur_node->next)
3442 {
3443 if (cur_node->type == XML_ELEMENT_NODE)
3444 {
3445 if (strcmp ((const char *) (cur_node->name), "Get") == 0)
3446 parse_wms_GetTileService_HTTP_Get (cur_node->children, cap);
3447 if (strcmp ((const char *) (cur_node->name), "Post") == 0)
3448 parse_wms_GetTileService_HTTP_Post (cur_node->children,
3449 cap);
3450 }
3451 }
3452 }
3453
3454 static void
parse_wms_GetInfo_HTTP(xmlNodePtr node,wmsCapabilitiesPtr cap)3455 parse_wms_GetInfo_HTTP (xmlNodePtr node, wmsCapabilitiesPtr cap)
3456 {
3457 /* recursively parsing the GetCapabilities/Capability/Request/GetFeatureInfo/DCPType node */
3458 xmlNodePtr cur_node = NULL;
3459
3460 for (cur_node = node; cur_node; cur_node = cur_node->next)
3461 {
3462 if (cur_node->type == XML_ELEMENT_NODE)
3463 {
3464 if (strcmp ((const char *) (cur_node->name), "Get") == 0)
3465 parse_wms_GetInfo_HTTP_Get (cur_node->children, cap);
3466 if (strcmp ((const char *) (cur_node->name), "Post") == 0)
3467 parse_wms_GetInfo_HTTP_Post (cur_node->children, cap);
3468 }
3469 }
3470 }
3471
3472 static void
parse_wms_GetMap_DCPType(xmlNodePtr node,wmsCapabilitiesPtr cap)3473 parse_wms_GetMap_DCPType (xmlNodePtr node, wmsCapabilitiesPtr cap)
3474 {
3475 /* recursively parsing the GetCapabilities/Capability/Request/GetMap/DCPType node */
3476 xmlNodePtr cur_node = NULL;
3477
3478 for (cur_node = node; cur_node; cur_node = cur_node->next)
3479 {
3480 if (cur_node->type == XML_ELEMENT_NODE)
3481 {
3482 if (strcmp ((const char *) (cur_node->name), "HTTP") == 0)
3483 parse_wms_GetMap_HTTP (cur_node->children, cap);
3484 }
3485 }
3486 }
3487
3488 static void
parse_wms_GetInfo_DCPType(xmlNodePtr node,wmsCapabilitiesPtr cap)3489 parse_wms_GetInfo_DCPType (xmlNodePtr node, wmsCapabilitiesPtr cap)
3490 {
3491 /* recursively parsing the GetCapabilities/Capability/Request/GetFeatureInfo/DCPType node */
3492 xmlNodePtr cur_node = NULL;
3493
3494 for (cur_node = node; cur_node; cur_node = cur_node->next)
3495 {
3496 if (cur_node->type == XML_ELEMENT_NODE)
3497 {
3498 if (strcmp ((const char *) (cur_node->name), "HTTP") == 0)
3499 parse_wms_GetInfo_HTTP (cur_node->children, cap);
3500 }
3501 }
3502 }
3503
3504 static void
parse_wms_GetTileService_DCPType(xmlNodePtr node,wmsCapabilitiesPtr cap)3505 parse_wms_GetTileService_DCPType (xmlNodePtr node, wmsCapabilitiesPtr cap)
3506 {
3507 /* recursively parsing the GetCapabilities/Capability/Request/GetTileService/DCPType node */
3508 xmlNodePtr cur_node = NULL;
3509
3510 for (cur_node = node; cur_node; cur_node = cur_node->next)
3511 {
3512 if (cur_node->type == XML_ELEMENT_NODE)
3513 {
3514 if (strcmp ((const char *) (cur_node->name), "HTTP") == 0)
3515 parse_wms_GetTileService_HTTP (cur_node->children, cap);
3516 }
3517 }
3518 }
3519
3520 static void
parse_wms_getMap(xmlNodePtr node,wmsCapabilitiesPtr cap)3521 parse_wms_getMap (xmlNodePtr node, wmsCapabilitiesPtr cap)
3522 {
3523 /* recursively parsing the GetCapabilities/Capability/Request/GetMap node */
3524 xmlNodePtr cur_node = NULL;
3525
3526 for (cur_node = node; cur_node; cur_node = cur_node->next)
3527 {
3528 if (cur_node->type == XML_ELEMENT_NODE)
3529 {
3530 if (strcmp ((const char *) (cur_node->name), "Format") == 0)
3531 {
3532 xmlNodePtr child_node = cur_node->children;
3533 if (child_node != NULL)
3534 {
3535 if (child_node->type == XML_TEXT_NODE)
3536 {
3537 wmsFormatPtr fmt;
3538 const char *format =
3539 (const char *) (child_node->content);
3540 fmt = wmsAllocFormat (format);
3541 if (cap->firstFormat == NULL)
3542 cap->firstFormat = fmt;
3543 if (cap->lastFormat != NULL)
3544 cap->lastFormat->next = fmt;
3545 cap->lastFormat = fmt;
3546 }
3547 }
3548 }
3549 if (strcmp ((const char *) (cur_node->name), "DCPType") == 0)
3550 parse_wms_GetMap_DCPType (cur_node->children, cap);
3551 }
3552 }
3553 }
3554
3555 static void
parse_wms_getInfo(xmlNodePtr node,wmsCapabilitiesPtr cap)3556 parse_wms_getInfo (xmlNodePtr node, wmsCapabilitiesPtr cap)
3557 {
3558 /* recursively parsing the GetCapabilities/Capability/Request/GetFeatureInfo node */
3559 xmlNodePtr cur_node = NULL;
3560
3561 for (cur_node = node; cur_node; cur_node = cur_node->next)
3562 {
3563 if (cur_node->type == XML_ELEMENT_NODE)
3564 {
3565 if (strcmp ((const char *) (cur_node->name), "Format") == 0)
3566 {
3567 xmlNodePtr child_node = cur_node->children;
3568 if (child_node != NULL)
3569 {
3570 if (child_node->type == XML_TEXT_NODE)
3571 {
3572 if (cap->GmlMimeType == NULL)
3573 {
3574 int ok = 0;
3575 const char *format =
3576 (const char
3577 *) (child_node->content);
3578 if (strcmp (format, "text/gml") == 0)
3579 ok = 1;
3580 if (strcmp
3581 (format,
3582 "application/vnd.ogc.gml") == 0)
3583 ok = 1;
3584 if (strcmp
3585 (format,
3586 "application/vnd.ogc.gml/3.1.1") ==
3587 0)
3588 ok = 1;
3589 if (ok)
3590 {
3591 int len = strlen (format);
3592 cap->GmlMimeType =
3593 malloc (len + 1);
3594 strcpy (cap->GmlMimeType, format);
3595 }
3596 }
3597 if (cap->XmlMimeType == NULL)
3598 {
3599 int ok = 0;
3600 const char *format =
3601 (const char
3602 *) (child_node->content);
3603 if (strcmp (format, "text/xml") == 0)
3604 ok = 1;
3605 if (ok)
3606 {
3607 int len = strlen (format);
3608 cap->XmlMimeType =
3609 malloc (len + 1);
3610 strcpy (cap->XmlMimeType, format);
3611 }
3612 }
3613 }
3614 }
3615 }
3616 if (strcmp ((const char *) (cur_node->name), "DCPType") == 0)
3617 parse_wms_GetInfo_DCPType (cur_node->children, cap);
3618 }
3619 }
3620 }
3621
3622 static void
parse_wms_getTileService(xmlNodePtr node,wmsCapabilitiesPtr cap)3623 parse_wms_getTileService (xmlNodePtr node, wmsCapabilitiesPtr cap)
3624 {
3625 /* recursively parsing the GetCapabilities/Capability/Request/GetTileService node */
3626 xmlNodePtr cur_node = NULL;
3627
3628 for (cur_node = node; cur_node; cur_node = cur_node->next)
3629 {
3630 if (strcmp ((const char *) (cur_node->name), "DCPType") == 0)
3631 parse_wms_GetTileService_DCPType (cur_node->children, cap);
3632 }
3633 }
3634
3635 static void
parse_wms_request(xmlNodePtr node,wmsCapabilitiesPtr cap)3636 parse_wms_request (xmlNodePtr node, wmsCapabilitiesPtr cap)
3637 {
3638 /* recursively parsing the GetCapabilities/Capability/Request node */
3639 xmlNodePtr cur_node = NULL;
3640
3641 for (cur_node = node; cur_node; cur_node = cur_node->next)
3642 {
3643 if (cur_node->type == XML_ELEMENT_NODE)
3644 {
3645 if (strcmp ((const char *) (cur_node->name), "GetMap") == 0)
3646 parse_wms_getMap (cur_node->children, cap);
3647 if (strcmp ((const char *) (cur_node->name), "GetTileService")
3648 == 0)
3649 parse_wms_getTileService (cur_node->children, cap);
3650 if (strcmp ((const char *) (cur_node->name), "GetFeatureInfo")
3651 == 0)
3652 parse_wms_getInfo (cur_node->children, cap);
3653 }
3654 }
3655 }
3656
3657 static void
parse_wms_capability(xmlNodePtr node,wmsCapabilitiesPtr cap)3658 parse_wms_capability (xmlNodePtr node, wmsCapabilitiesPtr cap)
3659 {
3660 /* recursively parsing the GetCapabilities/Capability node */
3661 xmlNodePtr cur_node = NULL;
3662
3663 for (cur_node = node; cur_node; cur_node = cur_node->next)
3664 {
3665 if (cur_node->type == XML_ELEMENT_NODE)
3666 {
3667 if (strcmp ((const char *) (cur_node->name), "Request") == 0)
3668 parse_wms_request (cur_node->children, cap);
3669 if (strcmp ((const char *) (cur_node->name), "Layer") == 0)
3670 parse_wms_layer (cur_node->children, cur_node->properties,
3671 cap);
3672 }
3673 }
3674 }
3675
3676 static void
parse_capabilities(xmlNodePtr node,wmsCapabilitiesPtr cap)3677 parse_capabilities (xmlNodePtr node, wmsCapabilitiesPtr cap)
3678 {
3679 /* recursively parsing the GetCapabilities payload */
3680 xmlNodePtr cur_node = NULL;
3681
3682 if (node)
3683 cur_node = node->children;
3684 else
3685 return;
3686
3687 for (; cur_node; cur_node = cur_node->next)
3688 {
3689 if (cur_node->type == XML_ELEMENT_NODE)
3690 {
3691 if (strcmp ((const char *) (cur_node->name), "Service") == 0)
3692 parse_wms_service (cur_node->children, cap);
3693 if (strcmp ((const char *) (cur_node->name), "Capability") == 0)
3694 parse_wms_capability (cur_node->children, cap);
3695 }
3696 }
3697 }
3698
3699 static void
parse_version(xmlNodePtr node,wmsCapabilitiesPtr cap)3700 parse_version (xmlNodePtr node, wmsCapabilitiesPtr cap)
3701 {
3702 /* attempting to extract the Version String */
3703 const char *version = NULL;
3704 struct _xmlAttr *attr = node->properties;
3705
3706 while (attr != NULL)
3707 {
3708 if (attr->name != NULL)
3709 {
3710 xmlNodePtr text;
3711 if (strcmp ((const char *) (attr->name), "version") == 0)
3712 {
3713 text = attr->children;
3714 if (text->type == XML_TEXT_NODE)
3715 version = (const char *) (text->content);
3716 }
3717 }
3718 attr = attr->next;
3719 }
3720 if (version != NULL)
3721 {
3722 int len = strlen (version);
3723 if (cap->Version != NULL)
3724 free (cap->Version);
3725 cap->Version = malloc (len + 1);
3726 strcpy (cap->Version, version);
3727 }
3728 }
3729
3730 static wmsCapabilitiesPtr
parse_wms_capabilities(const char * buf)3731 parse_wms_capabilities (const char *buf)
3732 {
3733 /* attempting to parse a WMS GetCapabilities answer */
3734 xmlDocPtr xml_doc;
3735 xmlNodePtr root;
3736 wmsMemBuffer xmlErr;
3737 wmsCapabilitiesPtr cap = NULL;
3738
3739 /* testing if the XMLDocument is well-formed */
3740 wmsMemBufferInitialize (&xmlErr);
3741 xmlSetGenericErrorFunc (&xmlErr, wmsParsingError);
3742 xml_doc = xmlReadMemory (buf, strlen (buf), "GetCapabilities.xml", NULL, 0);
3743 if (xml_doc == NULL)
3744 {
3745 /* parsing error; not a well-formed XML */
3746 char *err = NULL;
3747 const char *p_err = "error unknown";
3748 if (xmlErr.Buffer != NULL)
3749 {
3750 err = malloc (xmlErr.WriteOffset + 1);
3751 memcpy (err, xmlErr.Buffer, xmlErr.WriteOffset);
3752 *(err + xmlErr.WriteOffset) = '\0';
3753 p_err = err;
3754 }
3755 fprintf (stderr, "XML parsing error: %s\n", p_err);
3756 if (err)
3757 free (err);
3758 wmsMemBufferReset (&xmlErr);
3759 xmlSetGenericErrorFunc ((void *) stderr, NULL);
3760 return NULL;
3761 }
3762 if (xmlErr.Buffer != NULL)
3763 {
3764 /* reporting some XML warning */
3765 char *err = malloc (xmlErr.WriteOffset + 1);
3766 memcpy (err, xmlErr.Buffer, xmlErr.WriteOffset);
3767 *(err + xmlErr.WriteOffset) = '\0';
3768 fprintf (stderr, "XML parsing warning: %s\n", err);
3769 free (err);
3770 }
3771 wmsMemBufferReset (&xmlErr);
3772
3773 /* parsing XML nodes */
3774 cap = wmsAllocCapabilities ();
3775 root = xmlDocGetRootElement (xml_doc);
3776 parse_version (root, cap);
3777 parse_capabilities (root, cap);
3778 xmlFreeDoc (xml_doc);
3779
3780 return cap;
3781 }
3782
3783 static void
parse_wms_tiled_geoBBox(struct _xmlAttr * properties,wmsTiledLayerPtr lyr)3784 parse_wms_tiled_geoBBox (struct _xmlAttr *properties, wmsTiledLayerPtr lyr)
3785 {
3786 /* parsing a WMS TiledLayer/LatLonBoundingBox */
3787 struct _xmlAttr *attr = properties;
3788
3789 while (attr != NULL)
3790 {
3791 if (attr->name != NULL)
3792 {
3793 xmlNodePtr text;
3794 if (strcmp ((const char *) (attr->name), "miny") == 0)
3795 {
3796 text = attr->children;
3797 if (text->type == XML_TEXT_NODE)
3798 lyr->MinLat = atof ((const char *) (text->content));
3799 }
3800 if (strcmp ((const char *) (attr->name), "maxy") == 0)
3801 {
3802 text = attr->children;
3803 if (text->type == XML_TEXT_NODE)
3804 lyr->MaxLat = atof ((const char *) (text->content));
3805 }
3806 if (strcmp ((const char *) (attr->name), "minx") == 0)
3807 {
3808 text = attr->children;
3809 if (text->type == XML_TEXT_NODE)
3810 lyr->MinLong = atof ((const char *) (text->content));
3811 }
3812 if (strcmp ((const char *) (attr->name), "maxx") == 0)
3813 {
3814 text = attr->children;
3815 if (text->type == XML_TEXT_NODE)
3816 lyr->MaxLong = atof ((const char *) (text->content));
3817 }
3818 }
3819 attr = attr->next;
3820 }
3821 }
3822
3823 static char *
normalize_pattern(const char * pattern)3824 normalize_pattern (const char *pattern)
3825 {
3826 /* normalizing a tile pattern */
3827 char *out;
3828 int len;
3829 const char *p_end = pattern;
3830 while (1)
3831 {
3832 if (*p_end == ' ' || *p_end == '\0' || *p_end == '\t'
3833 || *p_end == '\r' || *p_end == '\n')
3834 break;
3835 p_end++;
3836 }
3837 len = p_end - pattern;
3838 if (len <= 0)
3839 return NULL;
3840 out = malloc (len + 1);
3841 memcpy (out, pattern, len);
3842 *(out + len) = '\0';
3843 return out;
3844 }
3845
3846 static void
parse_wms_tiled_group_child(xmlNodePtr node,wmsTiledLayerPtr parent)3847 parse_wms_tiled_group_child (xmlNodePtr node, wmsTiledLayerPtr parent)
3848 {
3849 /* parsing a WMS Tiled Layer (child) definition */
3850 xmlNodePtr cur_node = NULL;
3851 xmlNodePtr child_node = NULL;
3852 const char *name = NULL;
3853 const char *title = NULL;
3854 const char *abstract = NULL;
3855 wmsTiledLayerPtr lyr;
3856
3857 for (cur_node = node; cur_node; cur_node = cur_node->next)
3858 {
3859 if (cur_node->type == XML_ELEMENT_NODE)
3860 {
3861 if (strcmp ((const char *) (cur_node->name), "Name") == 0)
3862 {
3863 child_node = cur_node->children;
3864 if (child_node != NULL)
3865 {
3866 if (child_node->type == XML_TEXT_NODE)
3867 name = (const char *) (child_node->content);
3868 }
3869 }
3870 if (strcmp ((const char *) (cur_node->name), "Title") == 0)
3871 {
3872 child_node = cur_node->children;
3873 if (child_node != NULL)
3874 {
3875 if (child_node->type == XML_TEXT_NODE)
3876 title = (const char *) (child_node->content);
3877 }
3878 }
3879 if (strcmp ((const char *) (cur_node->name), "Abstract") == 0)
3880 {
3881 child_node = cur_node->children;
3882 if (child_node != NULL)
3883 {
3884 if (child_node->type == XML_TEXT_NODE)
3885 abstract = (const char *) (child_node->content);
3886 }
3887 }
3888 }
3889 }
3890 lyr = wmsAllocTiledLayer (name, title, abstract);
3891 if (parent->firstChild == NULL)
3892 parent->firstChild = lyr;
3893 if (parent->lastChild != NULL)
3894 parent->lastChild->next = lyr;
3895 parent->lastChild = lyr;
3896
3897 for (cur_node = node; cur_node; cur_node = cur_node->next)
3898 {
3899 if (cur_node->type == XML_ELEMENT_NODE)
3900 {
3901 int len;
3902 if (strcmp
3903 ((const char *) (cur_node->name), "LatLonBoundingBox") == 0)
3904 parse_wms_tiled_geoBBox (cur_node->properties, lyr);
3905 if (strcmp ((const char *) (cur_node->name), "Pad") == 0)
3906 {
3907 child_node = cur_node->children;
3908 if (child_node != NULL)
3909 {
3910 if (child_node->type == XML_TEXT_NODE)
3911 {
3912 if (lyr->Pad != NULL)
3913 free (lyr->Pad);
3914 lyr->Pad = NULL;
3915 len =
3916 strlen ((const char
3917 *) (child_node->content));
3918 lyr->Pad = malloc (len + 1);
3919 strcpy (lyr->Pad,
3920 (const char *) (child_node->content));
3921 }
3922 }
3923 }
3924 if (strcmp ((const char *) (cur_node->name), "Bands") == 0)
3925 {
3926 child_node = cur_node->children;
3927 if (child_node != NULL)
3928 {
3929 if (child_node->type == XML_TEXT_NODE)
3930 {
3931 if (lyr->Bands != NULL)
3932 free (lyr->Bands);
3933 lyr->Bands = NULL;
3934 len =
3935 strlen ((const char
3936 *) (child_node->content));
3937 lyr->Bands = malloc (len + 1);
3938 strcpy (lyr->Bands,
3939 (const char *) (child_node->content));
3940 }
3941 }
3942 }
3943 if (strcmp ((const char *) (cur_node->name), "DataType") == 0)
3944 {
3945 child_node = cur_node->children;
3946 if (child_node != NULL)
3947 {
3948 if (child_node->type == XML_TEXT_NODE)
3949 {
3950 if (lyr->DataType != NULL)
3951 free (lyr->DataType);
3952 lyr->DataType = NULL;
3953 len =
3954 strlen ((const char
3955 *) (child_node->content));
3956 lyr->DataType = malloc (len + 1);
3957 strcpy (lyr->DataType,
3958 (const char *) (child_node->content));
3959 }
3960 }
3961 }
3962 if (strcmp ((const char *) (cur_node->name), "TilePattern") ==
3963 0)
3964 {
3965 child_node = cur_node->children;
3966 if (child_node != NULL)
3967 {
3968 if (child_node->type == XML_TEXT_NODE)
3969 {
3970 const char *pattern =
3971 (const char *) (child_node->content);
3972 char *norm_pattern =
3973 normalize_pattern (pattern);
3974 if (norm_pattern != NULL)
3975 {
3976 wmsTilePatternPtr pattern =
3977 wmsAllocTilePattern (norm_pattern);
3978 if (lyr->firstPattern == NULL)
3979 lyr->firstPattern = pattern;
3980 if (lyr->lastPattern != NULL)
3981 lyr->lastPattern->next = pattern;
3982 lyr->lastPattern = pattern;
3983 }
3984 }
3985 }
3986 }
3987 }
3988 }
3989 }
3990
3991 static void
parse_wms_tiled_groups_child(xmlNodePtr node,wmsTiledLayerPtr parent)3992 parse_wms_tiled_groups_child (xmlNodePtr node, wmsTiledLayerPtr parent)
3993 {
3994 /* parsing a WMS Tiled (Group) Layer definition */
3995 xmlNodePtr cur_node = NULL;
3996 xmlNodePtr child_node = NULL;
3997 const char *name = NULL;
3998 const char *title = NULL;
3999 const char *abstract = NULL;
4000 wmsTiledLayerPtr lyr;
4001
4002 for (cur_node = node; cur_node; cur_node = cur_node->next)
4003 {
4004 if (cur_node->type == XML_ELEMENT_NODE)
4005 {
4006 if (strcmp ((const char *) (cur_node->name), "Name") == 0)
4007 {
4008 child_node = cur_node->children;
4009 if (child_node != NULL)
4010 {
4011 if (child_node->type == XML_TEXT_NODE)
4012 name = (const char *) (child_node->content);
4013 }
4014 }
4015 if (strcmp ((const char *) (cur_node->name), "Title") == 0)
4016 {
4017 child_node = cur_node->children;
4018 if (child_node != NULL)
4019 {
4020 if (child_node->type == XML_TEXT_NODE)
4021 title = (const char *) (child_node->content);
4022 }
4023 }
4024 if (strcmp ((const char *) (cur_node->name), "Abstract") == 0)
4025 {
4026 child_node = cur_node->children;
4027 if (child_node != NULL)
4028 {
4029 if (child_node->type == XML_TEXT_NODE)
4030 abstract = (const char *) (child_node->content);
4031 }
4032 }
4033 }
4034 }
4035 lyr = wmsAllocTiledLayer (name, title, abstract);
4036 if (parent->firstChild == NULL)
4037 parent->firstChild = lyr;
4038 if (parent->lastChild != NULL)
4039 parent->lastChild->next = lyr;
4040 parent->lastChild = lyr;
4041
4042 for (cur_node = node; cur_node; cur_node = cur_node->next)
4043 {
4044 if (cur_node->type == XML_ELEMENT_NODE)
4045 {
4046 if (strcmp ((const char *) (cur_node->name), "TiledGroup") == 0)
4047 parse_wms_tiled_group_child (cur_node->children, lyr);
4048 if (strcmp ((const char *) (cur_node->name), "TiledGroups") ==
4049 0)
4050 parse_wms_tiled_groups_child (cur_node->children, lyr);
4051 }
4052 }
4053 }
4054
4055 static void
parse_wms_tiled_group(xmlNodePtr node,wmsCapabilitiesPtr cap)4056 parse_wms_tiled_group (xmlNodePtr node, wmsCapabilitiesPtr cap)
4057 {
4058 /* parsing a WMS Tiled Layer definition */
4059 xmlNodePtr cur_node = NULL;
4060 xmlNodePtr child_node = NULL;
4061 const char *name = NULL;
4062 const char *title = NULL;
4063 const char *abstract = NULL;
4064 wmsTiledLayerPtr lyr;
4065
4066 for (cur_node = node; cur_node; cur_node = cur_node->next)
4067 {
4068 if (cur_node->type == XML_ELEMENT_NODE)
4069 {
4070 if (strcmp ((const char *) (cur_node->name), "Name") == 0)
4071 {
4072 child_node = cur_node->children;
4073 if (child_node != NULL)
4074 {
4075 if (child_node->type == XML_TEXT_NODE)
4076 name = (const char *) (child_node->content);
4077 }
4078 }
4079 if (strcmp ((const char *) (cur_node->name), "Title") == 0)
4080 {
4081 child_node = cur_node->children;
4082 if (child_node != NULL)
4083 {
4084 if (child_node->type == XML_TEXT_NODE)
4085 title = (const char *) (child_node->content);
4086 }
4087 }
4088 if (strcmp ((const char *) (cur_node->name), "Abstract") == 0)
4089 {
4090 child_node = cur_node->children;
4091 if (child_node != NULL)
4092 {
4093 if (child_node->type == XML_TEXT_NODE)
4094 abstract = (const char *) (child_node->content);
4095 }
4096 }
4097 }
4098 }
4099 lyr = wmsAllocTiledLayer (name, title, abstract);
4100 if (cap->firstTiled == NULL)
4101 cap->firstTiled = lyr;
4102 if (cap->lastTiled != NULL)
4103 cap->lastTiled->next = lyr;
4104 cap->lastTiled = lyr;
4105
4106 for (cur_node = node; cur_node; cur_node = cur_node->next)
4107 {
4108 if (cur_node->type == XML_ELEMENT_NODE)
4109 {
4110 int len;
4111 if (strcmp
4112 ((const char *) (cur_node->name), "LatLonBoundingBox") == 0)
4113 parse_wms_tiled_geoBBox (cur_node->properties, lyr);
4114 if (strcmp ((const char *) (cur_node->name), "Pad") == 0)
4115 {
4116 child_node = cur_node->children;
4117 if (child_node != NULL)
4118 {
4119 if (child_node->type == XML_TEXT_NODE)
4120 {
4121 if (lyr->Pad != NULL)
4122 free (lyr->Pad);
4123 lyr->Pad = NULL;
4124 len =
4125 strlen ((const char
4126 *) (child_node->content));
4127 lyr->Pad = malloc (len + 1);
4128 strcpy (lyr->Pad,
4129 (const char *) (child_node->content));
4130 }
4131 }
4132 }
4133 if (strcmp ((const char *) (cur_node->name), "Bands") == 0)
4134 {
4135 child_node = cur_node->children;
4136 if (child_node != NULL)
4137 {
4138 if (child_node->type == XML_TEXT_NODE)
4139 {
4140 if (lyr->Bands != NULL)
4141 free (lyr->Bands);
4142 lyr->Bands = NULL;
4143 len =
4144 strlen ((const char
4145 *) (child_node->content));
4146 lyr->Bands = malloc (len + 1);
4147 strcpy (lyr->Bands,
4148 (const char *) (child_node->content));
4149 }
4150 }
4151 }
4152 if (strcmp ((const char *) (cur_node->name), "DataType") == 0)
4153 {
4154 child_node = cur_node->children;
4155 if (child_node != NULL)
4156 {
4157 if (child_node->type == XML_TEXT_NODE)
4158 {
4159 if (lyr->DataType != NULL)
4160 free (lyr->DataType);
4161 lyr->DataType = NULL;
4162 len =
4163 strlen ((const char
4164 *) (child_node->content));
4165 lyr->DataType = malloc (len + 1);
4166 strcpy (lyr->DataType,
4167 (const char *) (child_node->content));
4168 }
4169 }
4170 }
4171 if (strcmp ((const char *) (cur_node->name), "TilePattern") ==
4172 0)
4173 {
4174 child_node = cur_node->children;
4175 if (child_node != NULL)
4176 {
4177 if (child_node->type == XML_TEXT_NODE)
4178 {
4179 const char *pattern =
4180 (const char *) (child_node->content);
4181 char *norm_pattern =
4182 normalize_pattern (pattern);
4183 if (norm_pattern != NULL)
4184 {
4185 wmsTilePatternPtr pattern =
4186 wmsAllocTilePattern (norm_pattern);
4187 if (lyr->firstPattern == NULL)
4188 lyr->firstPattern = pattern;
4189 if (lyr->lastPattern != NULL)
4190 lyr->lastPattern->next = pattern;
4191 lyr->lastPattern = pattern;
4192 }
4193 }
4194 }
4195 }
4196 }
4197 }
4198 }
4199
4200 static void
parse_wms_tiled_groups(xmlNodePtr node,wmsCapabilitiesPtr cap)4201 parse_wms_tiled_groups (xmlNodePtr node, wmsCapabilitiesPtr cap)
4202 {
4203 /* parsing a WMS Tiled (Group) Layer definition */
4204 xmlNodePtr cur_node = NULL;
4205 xmlNodePtr child_node = NULL;
4206 const char *name = NULL;
4207 const char *title = NULL;
4208 const char *abstract = NULL;
4209 wmsTiledLayerPtr lyr;
4210
4211 for (cur_node = node; cur_node; cur_node = cur_node->next)
4212 {
4213 if (cur_node->type == XML_ELEMENT_NODE)
4214 {
4215 if (strcmp ((const char *) (cur_node->name), "Name") == 0)
4216 {
4217 child_node = cur_node->children;
4218 if (child_node != NULL)
4219 {
4220 if (child_node->type == XML_TEXT_NODE)
4221 name = (const char *) (child_node->content);
4222 }
4223 }
4224 if (strcmp ((const char *) (cur_node->name), "Title") == 0)
4225 {
4226 child_node = cur_node->children;
4227 if (child_node != NULL)
4228 {
4229 if (child_node->type == XML_TEXT_NODE)
4230 title = (const char *) (child_node->content);
4231 }
4232 }
4233 if (strcmp ((const char *) (cur_node->name), "Abstract") == 0)
4234 {
4235 child_node = cur_node->children;
4236 if (child_node != NULL)
4237 {
4238 if (child_node->type == XML_TEXT_NODE)
4239 abstract = (const char *) (child_node->content);
4240 }
4241 }
4242 }
4243 }
4244 lyr = wmsAllocTiledLayer (name, title, abstract);
4245 if (cap->firstTiled == NULL)
4246 cap->firstTiled = lyr;
4247 if (cap->lastTiled != NULL)
4248 cap->lastTiled->next = lyr;
4249 cap->lastTiled = lyr;
4250
4251 for (cur_node = node; cur_node; cur_node = cur_node->next)
4252 {
4253 if (cur_node->type == XML_ELEMENT_NODE)
4254 {
4255 if (strcmp ((const char *) (cur_node->name), "TiledGroup") == 0)
4256 parse_wms_tiled_group_child (cur_node->children, lyr);
4257 if (strcmp ((const char *) (cur_node->name), "TiledGroups") ==
4258 0)
4259 parse_wms_tiled_groups_child (cur_node->children, lyr);
4260 }
4261 }
4262 }
4263
4264 static void
parse_tile_service_info(xmlNodePtr node,wmsCapabilitiesPtr cap)4265 parse_tile_service_info (xmlNodePtr node, wmsCapabilitiesPtr cap)
4266 {
4267 /* recursively parsing the GetTileService/Service payload */
4268 xmlNodePtr cur_node = NULL;
4269
4270 if (node)
4271 cur_node = node->children;
4272 else
4273 return;
4274
4275 for (; cur_node; cur_node = cur_node->next)
4276 {
4277 if (cur_node->type == XML_ELEMENT_NODE)
4278 {
4279 int len;
4280 xmlNodePtr child_node;
4281 const char *value;
4282 if (strcmp ((const char *) (cur_node->name), "Name") == 0)
4283 {
4284 if (cap->TileServiceName != NULL)
4285 free (cap->TileServiceName);
4286 cap->TileServiceName = NULL;
4287 child_node = cur_node->children;
4288 if (child_node != NULL)
4289 {
4290 if (child_node->type == XML_TEXT_NODE)
4291 value = (const char *) (child_node->content);
4292 if (value != NULL)
4293 {
4294 len = strlen (value);
4295 cap->TileServiceName = malloc (len + 1);
4296 strcpy (cap->TileServiceName, value);
4297 }
4298 }
4299 }
4300 if (strcmp ((const char *) (cur_node->name), "Title") == 0)
4301 {
4302 if (cap->TileServiceTitle != NULL)
4303 free (cap->TileServiceTitle);
4304 cap->TileServiceTitle = NULL;
4305 child_node = cur_node->children;
4306 if (child_node != NULL)
4307 {
4308 if (child_node->type == XML_TEXT_NODE)
4309 value = (const char *) (child_node->content);
4310 if (value != NULL)
4311 {
4312 len = strlen (value);
4313 cap->TileServiceTitle = malloc (len + 1);
4314 strcpy (cap->TileServiceTitle, value);
4315 }
4316 }
4317 }
4318 if (strcmp ((const char *) (cur_node->name), "Abstract") == 0)
4319 {
4320 if (cap->TileServiceAbstract != NULL)
4321 free (cap->TileServiceAbstract);
4322 cap->TileServiceAbstract = NULL;
4323 child_node = cur_node->children;
4324 if (child_node != NULL)
4325 {
4326 if (child_node->type == XML_TEXT_NODE)
4327 value = (const char *) (child_node->content);
4328 if (value != NULL)
4329 {
4330 len = strlen (value);
4331 cap->TileServiceAbstract = malloc (len + 1);
4332 strcpy (cap->TileServiceAbstract, value);
4333 }
4334 }
4335 }
4336 }
4337 }
4338 }
4339
4340 static void
parse_tiled_patterns(xmlNodePtr node,wmsCapabilitiesPtr cap)4341 parse_tiled_patterns (xmlNodePtr node, wmsCapabilitiesPtr cap)
4342 {
4343 /* recursively parsing the GetTileService/TiledPatterns payload */
4344 xmlNodePtr cur_node = NULL;
4345
4346 if (node)
4347 cur_node = node->children;
4348 else
4349 return;
4350
4351 for (; cur_node; cur_node = cur_node->next)
4352 {
4353 if (cur_node->type == XML_ELEMENT_NODE)
4354 {
4355 if (strcmp ((const char *) (cur_node->name), "TiledGroup") == 0)
4356 parse_wms_tiled_group (cur_node->children, cap);
4357 if (strcmp ((const char *) (cur_node->name), "TiledGroups") ==
4358 0)
4359 parse_wms_tiled_groups (cur_node->children, cap);
4360 }
4361 }
4362 }
4363
4364 static void
parse_tile_service(xmlNodePtr node,wmsCapabilitiesPtr cap)4365 parse_tile_service (xmlNodePtr node, wmsCapabilitiesPtr cap)
4366 {
4367 /* recursively parsing the GetTileService payload */
4368 xmlNodePtr cur_node = NULL;
4369
4370 if (node)
4371 cur_node = node->children;
4372 else
4373 return;
4374
4375 for (; cur_node; cur_node = cur_node->next)
4376 {
4377 if (cur_node->type == XML_ELEMENT_NODE)
4378 {
4379 if (strcmp ((const char *) (cur_node->name), "Service") == 0)
4380 parse_tile_service_info (cur_node, cap);
4381 if (strcmp ((const char *) (cur_node->name), "TiledPatterns") ==
4382 0)
4383 parse_tiled_patterns (cur_node, cap);
4384 }
4385 }
4386 }
4387
4388 static void
parse_wms_get_tile_service(wmsCapabilitiesPtr capabilities,const char * buf)4389 parse_wms_get_tile_service (wmsCapabilitiesPtr capabilities, const char *buf)
4390 {
4391 /* attempting to parse a WMS GetTileService answer */
4392 xmlDocPtr xml_doc;
4393 xmlNodePtr root;
4394 wmsMemBuffer xmlErr;
4395
4396 /* testing if the XMLDocument is well-formed */
4397 wmsMemBufferInitialize (&xmlErr);
4398 xmlSetGenericErrorFunc (&xmlErr, wmsParsingError);
4399 xml_doc = xmlReadMemory (buf, strlen (buf), "GetTileService.xml", NULL, 0);
4400 if (xml_doc == NULL)
4401 {
4402 /* parsing error; not a well-formed XML */
4403 char *err = NULL;
4404 const char *p_err = "error unknown";
4405 if (xmlErr.Buffer != NULL)
4406 {
4407 err = malloc (xmlErr.WriteOffset + 1);
4408 memcpy (err, xmlErr.Buffer, xmlErr.WriteOffset);
4409 *(err + xmlErr.WriteOffset) = '\0';
4410 p_err = err;
4411 }
4412 fprintf (stderr, "XML parsing error: %s\n", p_err);
4413 if (err)
4414 free (err);
4415 wmsMemBufferReset (&xmlErr);
4416 xmlSetGenericErrorFunc ((void *) stderr, NULL);
4417 return;
4418 }
4419 if (xmlErr.Buffer != NULL)
4420 {
4421 /* reporting some XML warning */
4422 char *err = malloc (xmlErr.WriteOffset + 1);
4423 memcpy (err, xmlErr.Buffer, xmlErr.WriteOffset);
4424 *(err + xmlErr.WriteOffset) = '\0';
4425 fprintf (stderr, "XML parsing warning: %s\n", err);
4426 free (err);
4427 }
4428 wmsMemBufferReset (&xmlErr);
4429
4430 /* parsing XML nodes */
4431 root = xmlDocGetRootElement (xml_doc);
4432 parse_tile_service (root, capabilities);
4433 xmlFreeDoc (xml_doc);
4434 }
4435
4436 static void
parse_wms_gml_geom(wmsMemBufferPtr gmlBuf,xmlNodePtr node)4437 parse_wms_gml_geom (wmsMemBufferPtr gmlBuf, xmlNodePtr node)
4438 {
4439 /* recursively reassembling the GML Geometry */
4440 xmlNodePtr cur_node = NULL;
4441
4442 for (cur_node = node; cur_node; cur_node = cur_node->next)
4443 {
4444 if (cur_node->type == XML_ELEMENT_NODE)
4445 {
4446 /* found some internal GML Geometry Tag */
4447 struct _xmlAttr *attr;
4448 char *tag_name;
4449 if (cur_node->ns == NULL)
4450 tag_name = sqlite3_mprintf ("<%s", cur_node->name);
4451 else
4452 tag_name =
4453 sqlite3_mprintf ("<%s:%s", cur_node->ns->prefix,
4454 cur_node->name);
4455 wmsMemBufferAppend (gmlBuf, (unsigned char *) tag_name,
4456 strlen (tag_name));
4457 sqlite3_free (tag_name);
4458 attr = cur_node->properties;
4459 while (attr != NULL)
4460 {
4461 /* eventual node attributes */
4462 if (attr->type == XML_ATTRIBUTE_NODE)
4463 {
4464 const char *value = "";
4465 xmlNodePtr text = attr->children;
4466 if (text != NULL)
4467 {
4468 if (text->type == XML_TEXT_NODE)
4469 value = (const char *) (text->content);
4470 }
4471 if (attr->ns == NULL)
4472 tag_name =
4473 sqlite3_mprintf (" %s=\"%s\"", attr->name,
4474 value);
4475 else
4476 tag_name =
4477 sqlite3_mprintf (" %s:%s=\"%s\"",
4478 attr->ns->prefix,
4479 attr->name, value);
4480 wmsMemBufferAppend (gmlBuf,
4481 (unsigned char *) tag_name,
4482 strlen (tag_name));
4483 sqlite3_free (tag_name);
4484 }
4485 attr = attr->next;
4486 }
4487 wmsMemBufferAppend (gmlBuf, (unsigned char *) ">", 1);
4488 parse_wms_gml_geom (gmlBuf, cur_node->children);
4489 if (cur_node->ns == NULL)
4490 tag_name = sqlite3_mprintf ("</%s>", cur_node->name);
4491 else
4492 tag_name =
4493 sqlite3_mprintf ("</%s:%s>", cur_node->ns->prefix,
4494 cur_node->name);
4495 wmsMemBufferAppend (gmlBuf, (unsigned char *) tag_name,
4496 strlen (tag_name));
4497 sqlite3_free (tag_name);
4498 }
4499 if (cur_node->type == XML_TEXT_NODE)
4500 {
4501 /* found a Text item */
4502 wmsMemBufferAppend (gmlBuf,
4503 (unsigned char *) (cur_node->content),
4504 strlen ((const char
4505 *) (cur_node->content)));
4506 }
4507 }
4508 }
4509
4510 static void
parse_wms_feature_attribute(xmlNodePtr node,wmsFeatureMemberPtr member)4511 parse_wms_feature_attribute (xmlNodePtr node, wmsFeatureMemberPtr member)
4512 {
4513 /* parsing the GetFeatureInfo/featureAttribute node */
4514 xmlNodePtr cur_node = NULL;
4515
4516 for (cur_node = node; cur_node; cur_node = cur_node->next)
4517 {
4518 if (cur_node->type == XML_ELEMENT_NODE)
4519 {
4520 xmlNodePtr text = cur_node->children;
4521 if (text == NULL)
4522 continue;
4523 if (text->type == XML_TEXT_NODE)
4524 {
4525 /* found an attribute */
4526 {
4527 char *value = NULL;
4528 if (text->content != NULL)
4529 {
4530 int len =
4531 strlen ((const char *) (text->content));
4532 value = malloc (len + 1);
4533 strcpy (value, (const char *) (text->content));
4534 }
4535 wmsAddFeatureMemberAttribute (member,
4536 (const char
4537 *) (cur_node->name),
4538 value);
4539 }
4540 }
4541 if (text->type == XML_ELEMENT_NODE)
4542 {
4543 /* probably found the GML Geometry - attempting to reassemble */
4544 char *gml = NULL;
4545 wmsMemBuffer gmlBuf;
4546 wmsMemBufferInitialize (&gmlBuf);
4547 parse_wms_gml_geom (&gmlBuf, text);
4548 if (gmlBuf.WriteOffset > 0)
4549 {
4550 gml = malloc (gmlBuf.WriteOffset + 1);
4551 memcpy (gml, gmlBuf.Buffer, gmlBuf.WriteOffset);
4552 *(gml + gmlBuf.WriteOffset) = '\0';
4553 }
4554 wmsMemBufferReset (&gmlBuf);
4555 wmsAddFeatureMemberAttribute (member,
4556 (const char
4557 *) (cur_node->name), gml);
4558 }
4559 }
4560 }
4561 }
4562
4563
4564 static void
parse_wms_feature_member(xmlNodePtr node,wmsFeatureCollectionPtr coll)4565 parse_wms_feature_member (xmlNodePtr node, wmsFeatureCollectionPtr coll)
4566 {
4567 /* parsing the GetFeatureInfo/featureMember node */
4568 xmlNodePtr cur_node = NULL;
4569
4570 for (cur_node = node; cur_node; cur_node = cur_node->next)
4571 {
4572 if (cur_node->type == XML_ELEMENT_NODE)
4573 {
4574
4575 wmsFeatureMemberPtr member =
4576 wmsAllocFeatureMember ((const char *) (cur_node->name));
4577 parse_wms_feature_attribute (cur_node->children, member);
4578 if (member->first == NULL)
4579 {
4580 /* empty feature */
4581 wmsFreeFeatureMember (member);
4582 }
4583 /* appending the feature to the collection */
4584 if (coll->first == NULL)
4585 coll->first = member;
4586 if (coll->last != NULL)
4587 coll->last->next = member;
4588 coll->last = member;
4589 }
4590 }
4591 }
4592
4593 static void
parse_ms_layer(xmlNodePtr node,wmsFeatureCollectionPtr coll,const char * feature_name)4594 parse_ms_layer (xmlNodePtr node, wmsFeatureCollectionPtr coll,
4595 const char *feature_name)
4596 {
4597 /* recursively parsing msGMLOutput features from a layer */
4598 xmlNodePtr cur_node = NULL;
4599
4600 for (cur_node = node; cur_node; cur_node = cur_node->next)
4601 {
4602 if (cur_node->type == XML_ELEMENT_NODE)
4603 {
4604 if (strcmp ((const char *) (cur_node->name), feature_name) == 0)
4605 parse_wms_feature_member (cur_node, coll);
4606 else
4607 parse_ms_layer (cur_node->children, coll, feature_name);
4608 }
4609 }
4610 }
4611
4612 static char *
make_feature_name(const char * layer_name)4613 make_feature_name (const char *layer_name)
4614 {
4615 /* building the expected feature name */
4616 char *name;
4617 int len = strlen (layer_name);
4618 if (len <= 6)
4619 return NULL;
4620 if (strcmp (layer_name + len - 6, "_layer") != 0)
4621 return NULL;
4622 name = malloc (len - 6 + 9);
4623 strncpy (name, layer_name, len - 6);
4624 name[len - 6] = '\0';
4625 strcat (name, "_feature");
4626 return name;
4627 }
4628
4629 static void
parse_ms_gml_output(xmlNodePtr node,wmsFeatureCollectionPtr coll)4630 parse_ms_gml_output (xmlNodePtr node, wmsFeatureCollectionPtr coll)
4631 {
4632 /* parsing the msGMLOutput payload */
4633 xmlNodePtr cur_node = NULL;
4634 char *feature_name = NULL;
4635 if (strcmp ((const char *) (node->name), "msGMLOutput") != 0)
4636 return;
4637
4638 if (node)
4639 cur_node = node->children;
4640 else
4641 return;
4642
4643 for (; cur_node; cur_node = cur_node->next)
4644 {
4645 if (cur_node->type == XML_ELEMENT_NODE)
4646 {
4647 if (feature_name == NULL)
4648 feature_name =
4649 make_feature_name ((const char *) (cur_node->name));
4650 if (feature_name == NULL)
4651 continue;
4652 parse_ms_layer (cur_node->children, coll, feature_name);
4653 }
4654 }
4655 if (feature_name != NULL)
4656 free (feature_name);
4657 }
4658
4659 static void
parse_esri_xml_field(struct _xmlAttr * properties,wmsFeatureMemberPtr member)4660 parse_esri_xml_field (struct _xmlAttr *properties, wmsFeatureMemberPtr member)
4661 {
4662 /* parsing an ESRI <Fields> based on XML attributes */
4663 struct _xmlAttr *attr = properties;
4664
4665 while (attr != NULL)
4666 {
4667 if (attr->name != NULL)
4668 {
4669 char *value = NULL;
4670 xmlNodePtr text = attr->children;
4671 if (text != NULL)
4672 {
4673 if (text->type == XML_TEXT_NODE)
4674 {
4675 if (text->content != NULL)
4676 {
4677 int len =
4678 strlen ((const char *) (text->content));
4679 value = malloc (len + 1);
4680 strcpy (value,
4681 (const char *) (text->content));
4682 }
4683 }
4684 }
4685 else
4686 {
4687 value = malloc (1);
4688 *value = '\0';
4689 }
4690 wmsAddFeatureMemberAttribute (member,
4691 (const char *) (attr->name),
4692 value);
4693 }
4694 attr = attr->next;
4695 }
4696 }
4697
4698 static void
parse_esri_xml_output(xmlNodePtr node,wmsFeatureCollectionPtr coll)4699 parse_esri_xml_output (xmlNodePtr node, wmsFeatureCollectionPtr coll)
4700 {
4701 /* parsing the ESRI-like XML payload */
4702 xmlNodePtr cur_node = NULL;
4703 if (strcmp ((const char *) (node->name), "FeatureInfoResponse") != 0)
4704 return;
4705
4706 if (node)
4707 cur_node = node->children;
4708 else
4709 return;
4710
4711 for (; cur_node; cur_node = cur_node->next)
4712 {
4713 if (cur_node->type == XML_ELEMENT_NODE)
4714 {
4715 if (strcmp ((const char *) (cur_node->name), "Fields") != 0)
4716 {
4717 struct _xmlAttr *attr = cur_node->properties;
4718 if (attr != NULL)
4719 {
4720 wmsFeatureMemberPtr member =
4721 wmsAllocFeatureMember ((const char
4722 *) (cur_node->name));
4723 parse_esri_xml_field (attr, member);
4724 /* appending the feature to the collection */
4725 if (coll->first == NULL)
4726 coll->first = member;
4727 if (coll->last != NULL)
4728 coll->last->next = member;
4729 coll->last = member;
4730 }
4731 }
4732 }
4733 }
4734 }
4735
4736 static void
parse_feature_collection(xmlNodePtr node,wmsFeatureCollectionPtr coll)4737 parse_feature_collection (xmlNodePtr node, wmsFeatureCollectionPtr coll)
4738 {
4739 /* parsing the GetFeatureInfo payload */
4740 xmlNodePtr cur_node = NULL;
4741 if (strcmp ((const char *) (node->name), "FeatureInfoResponse") == 0)
4742 {
4743 parse_esri_xml_output (node, coll);
4744 return;
4745 }
4746 if (strcmp ((const char *) (node->name), "msGMLOutput") == 0)
4747 {
4748 parse_ms_gml_output (node, coll);
4749 return;
4750 }
4751 if (strcmp ((const char *) (node->name), "FeatureCollection") != 0)
4752 return;
4753
4754 if (node)
4755 cur_node = node->children;
4756 else
4757 return;
4758
4759 for (; cur_node; cur_node = cur_node->next)
4760 {
4761 if (cur_node->type == XML_ELEMENT_NODE)
4762 {
4763 if (strcmp ((const char *) (cur_node->name), "featureMember") ==
4764 0)
4765 parse_wms_feature_member (cur_node->children, coll);
4766 }
4767 }
4768 }
4769
4770 static wmsFeatureCollectionPtr
parse_wms_feature_collection(const char * buf)4771 parse_wms_feature_collection (const char *buf)
4772 {
4773 /* attempting to parse a WMS GetFeatureInfo answer */
4774 xmlDocPtr xml_doc;
4775 xmlNodePtr root;
4776 wmsMemBuffer xmlErr;
4777 wmsFeatureCollectionPtr coll = NULL;
4778
4779 /* testing if the XMLDocument is well-formed */
4780 wmsMemBufferInitialize (&xmlErr);
4781 xmlSetGenericErrorFunc (&xmlErr, wmsParsingError);
4782 xml_doc = xmlReadMemory (buf, strlen (buf), "GetFeatureInfo.xml", NULL, 0);
4783 if (xml_doc == NULL)
4784 {
4785 /* parsing error; not a well-formed XML */
4786 char *err = NULL;
4787 const char *p_err = "error unknown";
4788 if (xmlErr.Buffer != NULL)
4789 {
4790 err = malloc (xmlErr.WriteOffset + 1);
4791 memcpy (err, xmlErr.Buffer, xmlErr.WriteOffset);
4792 *(err + xmlErr.WriteOffset) = '\0';
4793 p_err = err;
4794 }
4795 fprintf (stderr, "XML parsing error: %s\n", p_err);
4796 if (err)
4797 free (err);
4798 wmsMemBufferReset (&xmlErr);
4799 xmlSetGenericErrorFunc ((void *) stderr, NULL);
4800 return NULL;
4801 }
4802 if (xmlErr.Buffer != NULL)
4803 {
4804 /* reporting some XML warning */
4805 char *err = malloc (xmlErr.WriteOffset + 1);
4806 memcpy (err, xmlErr.Buffer, xmlErr.WriteOffset);
4807 *(err + xmlErr.WriteOffset) = '\0';
4808 fprintf (stderr, "XML parsing warning: %s\n", err);
4809 free (err);
4810 }
4811 wmsMemBufferReset (&xmlErr);
4812
4813 /* parsing XML nodes */
4814 coll = wmsAllocFeatureCollection ();
4815 root = xmlDocGetRootElement (xml_doc);
4816 parse_feature_collection (root, coll);
4817 xmlFreeDoc (xml_doc);
4818
4819 if (coll != NULL)
4820 {
4821 if (coll->first == NULL)
4822 {
4823 /* empty collection */
4824 wmsFreeFeatureCollection (coll);
4825 coll = NULL;
4826 }
4827 }
4828
4829 return coll;
4830 }
4831
4832 static int
query_TileService(rl2WmsCachePtr cache_handle,wmsCapabilitiesPtr capabilities,const char * proxy)4833 query_TileService (rl2WmsCachePtr cache_handle, wmsCapabilitiesPtr capabilities,
4834 const char *proxy)
4835 {
4836 /* attempting to get and parse a WMS GetTileService request */
4837 CURL *curl = NULL;
4838 CURLcode res;
4839 wmsMemBuffer headerBuf;
4840 wmsMemBuffer bodyBuf;
4841 int http_status;
4842 char *http_code;
4843 char *xml_buf;
4844 char *url;
4845 wmsCachePtr cache = (wmsCachePtr) cache_handle;
4846 int already_cached = 0;
4847 int retcode = 0;
4848
4849 /* initializes the dynamically growing buffers */
4850 wmsMemBufferInitialize (&headerBuf);
4851 wmsMemBufferInitialize (&bodyBuf);
4852 url =
4853 sqlite3_mprintf ("%srequest=GetTileService",
4854 capabilities->GetTileServiceURLGet);
4855
4856 if (cache != NULL)
4857 {
4858 /* checks if it's already stored into the WMS Cache */
4859 wmsCachedCapabilitiesPtr cachedCapab =
4860 getWmsCachedCapabilities (cache, url);
4861 if (cachedCapab != NULL)
4862 {
4863 /* ok, found from WMS Cache */
4864 xml_buf =
4865 clean_xml_str ((const char *) (cachedCapab->Response));
4866 already_cached = 1;
4867 goto do_tile_service;
4868 }
4869 }
4870
4871 curl = curl_easy_init ();
4872 if (curl)
4873 {
4874 /* setting the URL */
4875 curl_easy_setopt (curl, CURLOPT_URL, url);
4876
4877 if (proxy != NULL)
4878 {
4879 /* setting up the required proxy */
4880 curl_easy_setopt (curl, CURLOPT_PROXY, proxy);
4881 }
4882
4883 /* no progress meter please */
4884 curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 1L);
4885 /* setting the output callback function */
4886 curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, store_data);
4887 curl_easy_setopt (curl, CURLOPT_WRITEHEADER, &headerBuf);
4888 curl_easy_setopt (curl, CURLOPT_WRITEDATA, &bodyBuf);
4889
4890 /* Perform the request, res will get the return code */
4891 res = curl_easy_perform (curl);
4892 /* Check for errors */
4893 if (res != CURLE_OK)
4894 {
4895 fprintf (stderr, "CURL error: %s\n", curl_easy_strerror (res));
4896 goto stop;
4897 }
4898
4899 /* verifying the HTTP status code */
4900 check_http_header (&headerBuf, &http_status, &http_code);
4901 if (http_status != 200)
4902 {
4903 fprintf (stderr, "Invalid HTTP status code: %d %s\n",
4904 http_status, http_code);
4905 if (http_code != NULL)
4906 free (http_code);
4907 goto stop;
4908 }
4909 if (http_code != NULL)
4910 free (http_code);
4911 }
4912
4913 /* attempting to parse the GetCapabilities answer */
4914 xml_buf = clean_xml (&bodyBuf);
4915 do_tile_service:
4916 if (xml_buf != NULL)
4917 {
4918 parse_wms_get_tile_service (capabilities, xml_buf);
4919 free (xml_buf);
4920 retcode = 1;
4921 }
4922 if (!already_cached)
4923 {
4924 /* saving into the WMS Cache */
4925 wmsAddCachedCapabilities (cache, url, bodyBuf.Buffer,
4926 bodyBuf.WriteOffset);
4927 }
4928
4929 /* memory cleanup */
4930 stop:
4931 wmsMemBufferReset (&headerBuf);
4932 wmsMemBufferReset (&bodyBuf);
4933 sqlite3_free (url);
4934 if (curl != NULL)
4935 curl_easy_cleanup (curl);
4936 return retcode;
4937 }
4938
4939 RL2_DECLARE rl2WmsCatalogPtr
create_wms_catalog(rl2WmsCachePtr cache_handle,const char * url,const char * proxy,char ** err_msg)4940 create_wms_catalog (rl2WmsCachePtr cache_handle, const char *url,
4941 const char *proxy, char **err_msg)
4942 {
4943 /* attempting to get and parse a WMS GetCapabilities request */
4944 CURL *curl = NULL;
4945 CURLcode res;
4946 wmsMemBuffer headerBuf;
4947 wmsMemBuffer bodyBuf;
4948 int http_status;
4949 char *http_code;
4950 wmsCapabilitiesPtr capabilities = NULL;
4951 char *xml_buf;
4952 wmsCachePtr cache = (wmsCachePtr) cache_handle;
4953 int already_cached = 0;
4954
4955 /* initializes the dynamically growing buffers */
4956 wmsMemBufferInitialize (&headerBuf);
4957 wmsMemBufferInitialize (&bodyBuf);
4958
4959 if (cache != NULL)
4960 {
4961 /* checks if it's already stored into the WMS Cache */
4962 wmsCachedCapabilitiesPtr cachedCapab =
4963 getWmsCachedCapabilities (cache, url);
4964 if (cachedCapab != NULL)
4965 {
4966 /* ok, found from WMS Cache */
4967 xml_buf =
4968 clean_xml_str ((const char *) (cachedCapab->Response));
4969 already_cached = 1;
4970 goto do_capabilities;
4971 }
4972 }
4973
4974 *err_msg = NULL;
4975 curl = curl_easy_init ();
4976 if (curl)
4977 {
4978 /* setting the URL */
4979 curl_easy_setopt (curl, CURLOPT_URL, url);
4980
4981 if (proxy != NULL)
4982 {
4983 /* setting up the required proxy */
4984 curl_easy_setopt (curl, CURLOPT_PROXY, proxy);
4985 }
4986
4987 /* no progress meter please */
4988 curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 1L);
4989 /* setting the output callback function */
4990 curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, store_data);
4991 curl_easy_setopt (curl, CURLOPT_WRITEHEADER, &headerBuf);
4992 curl_easy_setopt (curl, CURLOPT_WRITEDATA, &bodyBuf);
4993
4994 /* Perform the request, res will get the return code */
4995 res = curl_easy_perform (curl);
4996 /* Check for errors */
4997 if (res != CURLE_OK)
4998 {
4999 fprintf (stderr, "CURL error: %s\n", curl_easy_strerror (res));
5000 goto stop;
5001 }
5002
5003 /* verifying the HTTP status code */
5004 check_http_header (&headerBuf, &http_status, &http_code);
5005 if (http_status != 200)
5006 {
5007 fprintf (stderr, "Invalid HTTP status code: %d %s\n",
5008 http_status, http_code);
5009 if (http_code != NULL)
5010 free (http_code);
5011 goto stop;
5012 }
5013 if (http_code != NULL)
5014 free (http_code);
5015
5016 /* attempting to parse the GetCapabilities answer */
5017 xml_buf = clean_xml (&bodyBuf);
5018 do_capabilities:
5019 if (xml_buf != NULL)
5020 {
5021 capabilities = parse_wms_capabilities (xml_buf);
5022 free (xml_buf);
5023 }
5024
5025 if (capabilities != NULL)
5026 {
5027 if (capabilities->GetTileServiceURLGet != NULL)
5028 {
5029 /* attempting to resolve WMS GetTileService */
5030 int retry = 0;
5031 /* first attempt */
5032 if (!query_TileService
5033 (cache_handle, capabilities, proxy))
5034 retry = 1;
5035 if (retry)
5036 {
5037 /* second attempt */
5038 retry = 0;
5039 if (!query_TileService
5040 (cache_handle, capabilities, proxy))
5041 retry = 1;
5042 }
5043 if (retry)
5044 {
5045 /* third attempt */
5046 retry = 0;
5047 if (!query_TileService
5048 (cache_handle, capabilities, proxy))
5049 retry = 1;
5050 }
5051 if (retry)
5052 {
5053 /* fourth attempt */
5054 retry = 0;
5055 if (!query_TileService
5056 (cache_handle, capabilities, proxy))
5057 retry = 1;
5058 }
5059 if (retry)
5060 {
5061 /* fifth attempt */
5062 if (!query_TileService
5063 (cache_handle, capabilities, proxy))
5064 {
5065 /* giving up */
5066 wmsFreeCapabilities (capabilities);
5067 capabilities = NULL;
5068 goto stop;
5069 }
5070 }
5071 }
5072 if (!already_cached)
5073 {
5074 /* saving into the WMS Cache */
5075 wmsAddCachedCapabilities (cache, url, bodyBuf.Buffer,
5076 bodyBuf.WriteOffset);
5077 }
5078 }
5079 }
5080
5081 stop:
5082 if (curl != NULL)
5083 curl_easy_cleanup (curl);
5084 wmsMemBufferReset (&headerBuf);
5085 wmsMemBufferReset (&bodyBuf);
5086 return (rl2WmsCatalogPtr) capabilities;
5087 }
5088
5089 RL2_DECLARE void
destroy_wms_catalog(rl2WmsCatalogPtr handle)5090 destroy_wms_catalog (rl2WmsCatalogPtr handle)
5091 {
5092 /* memory cleanup: freeing a WMS-Catalog object */
5093 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5094 if (ptr == NULL)
5095 return;
5096 wmsFreeCapabilities (ptr);
5097 }
5098
5099 RL2_DECLARE int
get_wms_format_count(rl2WmsCatalogPtr handle,int mode)5100 get_wms_format_count (rl2WmsCatalogPtr handle, int mode)
5101 {
5102 /* counting how many Formats are supported by a WMS-Catalog */
5103 int count = 0;
5104 wmsFormatPtr fmt;
5105 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5106 if (ptr == NULL)
5107 return -1;
5108
5109 fmt = ptr->firstFormat;
5110 while (fmt != NULL)
5111 {
5112 if (mode)
5113 {
5114 if (fmt->FormatCode != WMS_FORMAT_UNKNOWN)
5115 count++;
5116 }
5117 else
5118 count++;
5119 fmt = fmt->next;
5120 }
5121 return count;
5122 }
5123
5124 RL2_DECLARE const char *
get_wms_format(rl2WmsCatalogPtr handle,int index,int mode)5125 get_wms_format (rl2WmsCatalogPtr handle, int index, int mode)
5126 {
5127 /* attempting to get the Nth Format supported by some WMS-Catalog object */
5128 int count = 0;
5129 wmsFormatPtr fmt;
5130 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5131 if (ptr == NULL)
5132 return NULL;
5133
5134 fmt = ptr->firstFormat;
5135 while (fmt != NULL)
5136 {
5137 if (mode)
5138 {
5139 if (fmt->FormatCode == WMS_FORMAT_UNKNOWN)
5140 {
5141 fmt = fmt->next;
5142 continue;
5143 }
5144 }
5145 if (count == index)
5146 return fmt->Format;
5147 count++;
5148 fmt = fmt->next;
5149 }
5150 return NULL;
5151 }
5152
5153 RL2_DECLARE const char *
get_wms_contact_person(rl2WmsCatalogPtr handle)5154 get_wms_contact_person (rl2WmsCatalogPtr handle)
5155 {
5156 /* attempting to get the Contact Person defined by some WMS-Catalog object */
5157 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5158 if (ptr == NULL)
5159 return NULL;
5160
5161 return ptr->ContactPerson;
5162 }
5163
5164 RL2_DECLARE const char *
get_wms_contact_organization(rl2WmsCatalogPtr handle)5165 get_wms_contact_organization (rl2WmsCatalogPtr handle)
5166 {
5167 /* attempting to get the Contact Organization defined by some WMS-Catalog object */
5168 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5169 if (ptr == NULL)
5170 return NULL;
5171
5172 return ptr->ContactOrganization;
5173 }
5174
5175 RL2_DECLARE const char *
get_wms_contact_position(rl2WmsCatalogPtr handle)5176 get_wms_contact_position (rl2WmsCatalogPtr handle)
5177 {
5178 /* attempting to get the Contact Position defined by some WMS-Catalog object */
5179 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5180 if (ptr == NULL)
5181 return NULL;
5182
5183 return ptr->ContactPosition;
5184 }
5185
5186 RL2_DECLARE const char *
get_wms_contact_postal_address(rl2WmsCatalogPtr handle)5187 get_wms_contact_postal_address (rl2WmsCatalogPtr handle)
5188 {
5189 /* attempting to get the Postal Address defined by some WMS-Catalog object */
5190 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5191 if (ptr == NULL)
5192 return NULL;
5193
5194 return ptr->PostalAddress;
5195 }
5196
5197 RL2_DECLARE const char *
get_wms_contact_city(rl2WmsCatalogPtr handle)5198 get_wms_contact_city (rl2WmsCatalogPtr handle)
5199 {
5200 /* attempting to get the City (Postal Address) defined by some WMS-Catalog object */
5201 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5202 if (ptr == NULL)
5203 return NULL;
5204
5205 return ptr->City;
5206 }
5207
5208 RL2_DECLARE const char *
get_wms_contact_state_province(rl2WmsCatalogPtr handle)5209 get_wms_contact_state_province (rl2WmsCatalogPtr handle)
5210 {
5211 /* attempting to get the State or Province (Postal Address) defined by some WMS-Catalog object */
5212 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5213 if (ptr == NULL)
5214 return NULL;
5215
5216 return ptr->StateProvince;
5217 }
5218
5219 RL2_DECLARE const char *
get_wms_contact_post_code(rl2WmsCatalogPtr handle)5220 get_wms_contact_post_code (rl2WmsCatalogPtr handle)
5221 {
5222 /* attempting to get the Post Code (Postal Address) defined by some WMS-Catalog object */
5223 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5224 if (ptr == NULL)
5225 return NULL;
5226
5227 return ptr->PostCode;
5228 }
5229
5230 RL2_DECLARE const char *
get_wms_contact_country(rl2WmsCatalogPtr handle)5231 get_wms_contact_country (rl2WmsCatalogPtr handle)
5232 {
5233 /* attempting to get the Country (Postal Address) defined by some WMS-Catalog object */
5234 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5235 if (ptr == NULL)
5236 return NULL;
5237
5238 return ptr->Country;
5239 }
5240
5241 RL2_DECLARE const char *
get_wms_contact_voice_telephone(rl2WmsCatalogPtr handle)5242 get_wms_contact_voice_telephone (rl2WmsCatalogPtr handle)
5243 {
5244 /* attempting to get the Voice Telephone defined by some WMS-Catalog object */
5245 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5246 if (ptr == NULL)
5247 return NULL;
5248
5249 return ptr->VoiceTelephone;
5250 }
5251
5252 RL2_DECLARE const char *
get_wms_contact_fax_telephone(rl2WmsCatalogPtr handle)5253 get_wms_contact_fax_telephone (rl2WmsCatalogPtr handle)
5254 {
5255 /* attempting to get the FAX Telephone defined by some WMS-Catalog object */
5256 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5257 if (ptr == NULL)
5258 return NULL;
5259
5260 return ptr->FaxTelephone;
5261 }
5262
5263 RL2_DECLARE const char *
get_wms_contact_email_address(rl2WmsCatalogPtr handle)5264 get_wms_contact_email_address (rl2WmsCatalogPtr handle)
5265 {
5266 /* attempting to get the e-mail Address defined by some WMS-Catalog object */
5267 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5268 if (ptr == NULL)
5269 return NULL;
5270
5271 return ptr->EMailAddress;
5272 }
5273
5274 RL2_DECLARE const char *
get_wms_fees(rl2WmsCatalogPtr handle)5275 get_wms_fees (rl2WmsCatalogPtr handle)
5276 {
5277 /* attempting to get the Fees required by some WMS-Catalog object */
5278 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5279 if (ptr == NULL)
5280 return NULL;
5281
5282 return ptr->Fees;
5283 }
5284
5285 RL2_DECLARE const char *
get_wms_access_constraints(rl2WmsCatalogPtr handle)5286 get_wms_access_constraints (rl2WmsCatalogPtr handle)
5287 {
5288 /* attempting to get the Access Constraints imposed by some WMS-Catalog object */
5289 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5290 if (ptr == NULL)
5291 return NULL;
5292
5293 return ptr->AccessConstraints;
5294 }
5295
5296 RL2_DECLARE int
get_wms_layer_limit(rl2WmsCatalogPtr handle)5297 get_wms_layer_limit (rl2WmsCatalogPtr handle)
5298 {
5299 /* attempting to get the LayerLimit supported by some WMS-Catalog object */
5300 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5301 if (ptr == NULL)
5302 return -1;
5303
5304 return ptr->LayerLimit;
5305 }
5306
5307 RL2_DECLARE int
get_wms_max_width(rl2WmsCatalogPtr handle)5308 get_wms_max_width (rl2WmsCatalogPtr handle)
5309 {
5310 /* attempting to get the MaxWidth supported by some WMS-Catalog object */
5311 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5312 if (ptr == NULL)
5313 return -1;
5314
5315 return ptr->MaxWidth;
5316 }
5317
5318 RL2_DECLARE int
get_wms_max_height(rl2WmsCatalogPtr handle)5319 get_wms_max_height (rl2WmsCatalogPtr handle)
5320 {
5321 /* attempting to get the MaxHeight supported by some WMS-Catalog object */
5322 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5323 if (ptr == NULL)
5324 return -1;
5325
5326 return ptr->MaxHeight;
5327 }
5328
5329 RL2_DECLARE const char *
get_wms_version(rl2WmsCatalogPtr handle)5330 get_wms_version (rl2WmsCatalogPtr handle)
5331 {
5332 /* attempting to get the Version String from some WMS-Catalog object */
5333 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5334 if (ptr == NULL)
5335 return NULL;
5336
5337 return ptr->Version;
5338 }
5339
5340 RL2_DECLARE const char *
get_wms_name(rl2WmsCatalogPtr handle)5341 get_wms_name (rl2WmsCatalogPtr handle)
5342 {
5343 /* attempting to get the Name from some WMS-Catalog object */
5344 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5345 if (ptr == NULL)
5346 return NULL;
5347
5348 return ptr->Name;
5349 }
5350
5351 RL2_DECLARE const char *
get_wms_title(rl2WmsCatalogPtr handle)5352 get_wms_title (rl2WmsCatalogPtr handle)
5353 {
5354 /* attempting to get the Title from some WMS-Catalog object */
5355 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5356 if (ptr == NULL)
5357 return NULL;
5358
5359 return ptr->Title;
5360 }
5361
5362 RL2_DECLARE const char *
get_wms_abstract(rl2WmsCatalogPtr handle)5363 get_wms_abstract (rl2WmsCatalogPtr handle)
5364 {
5365 /* attempting to get the Abstract from some WMS-Catalog object */
5366 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5367 if (ptr == NULL)
5368 return NULL;
5369
5370 return ptr->Abstract;
5371 }
5372
5373 RL2_DECLARE const char *
get_wms_url_GetMap_get(rl2WmsCatalogPtr handle)5374 get_wms_url_GetMap_get (rl2WmsCatalogPtr handle)
5375 {
5376 /* attempting to get the GetMap URL (method GET) from some WMS-Catalog object */
5377 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5378 if (ptr == NULL)
5379 return NULL;
5380
5381 return ptr->GetMapURLGet;
5382 }
5383
5384 RL2_DECLARE const char *
get_wms_url_GetMap_post(rl2WmsCatalogPtr handle)5385 get_wms_url_GetMap_post (rl2WmsCatalogPtr handle)
5386 {
5387 /* attempting to get the GetMap URL (method POST) from some WMS-Catalog object */
5388 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5389 if (ptr == NULL)
5390 return NULL;
5391
5392 return ptr->GetMapURLPost;
5393 }
5394
5395 RL2_DECLARE const char *
get_wms_url_GetTileService_get(rl2WmsCatalogPtr handle)5396 get_wms_url_GetTileService_get (rl2WmsCatalogPtr handle)
5397 {
5398 /* attempting to get the GetTileService URL (method GET) from some WMS-Catalog object */
5399 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5400 if (ptr == NULL)
5401 return NULL;
5402
5403 return ptr->GetTileServiceURLGet;
5404 }
5405
5406 RL2_DECLARE const char *
get_wms_url_GetTileService_post(rl2WmsCatalogPtr handle)5407 get_wms_url_GetTileService_post (rl2WmsCatalogPtr handle)
5408 {
5409 /* attempting to get the GetTileService URL (method POST) from some WMS-Catalog object */
5410 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5411 if (ptr == NULL)
5412 return NULL;
5413
5414 return ptr->GetTileServiceURLPost;
5415 }
5416
5417 RL2_DECLARE const char *
get_wms_url_GetFeatureInfo_get(rl2WmsCatalogPtr handle)5418 get_wms_url_GetFeatureInfo_get (rl2WmsCatalogPtr handle)
5419 {
5420 /* attempting to get the GetFeatureInfo URL (method GET) from some WMS-Catalog object */
5421 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5422 if (ptr == NULL)
5423 return NULL;
5424
5425 return ptr->GetFeatureInfoURLGet;
5426 }
5427
5428 RL2_DECLARE const char *
get_wms_url_GetFeatureInfo_post(rl2WmsCatalogPtr handle)5429 get_wms_url_GetFeatureInfo_post (rl2WmsCatalogPtr handle)
5430 {
5431 /* attempting to get the GetFeatureInfo URL (method POST) from some WMS-Catalog object */
5432 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5433 if (ptr == NULL)
5434 return NULL;
5435
5436 return ptr->GetFeatureInfoURLPost;
5437 }
5438
5439 RL2_DECLARE const char *
get_wms_gml_mime_type(rl2WmsCatalogPtr handle)5440 get_wms_gml_mime_type (rl2WmsCatalogPtr handle)
5441 {
5442 /* attempting to get the GML MIME type from some WMS-Catalog object */
5443 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5444 if (ptr == NULL)
5445 return NULL;
5446
5447 return ptr->GmlMimeType;
5448 }
5449
5450 RL2_DECLARE const char *
get_wms_xml_mime_type(rl2WmsCatalogPtr handle)5451 get_wms_xml_mime_type (rl2WmsCatalogPtr handle)
5452 {
5453 /* attempting to get the XML MIME type from some WMS-Catalog object */
5454 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5455 if (ptr == NULL)
5456 return NULL;
5457
5458 return ptr->XmlMimeType;
5459 }
5460
5461 RL2_DECLARE int
is_wms_tile_service(rl2WmsCatalogPtr handle)5462 is_wms_tile_service (rl2WmsCatalogPtr handle)
5463 {
5464 /* testing if a WMS-Catalog actually is a TileService */
5465 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5466 if (ptr == NULL)
5467 return -1;
5468
5469 if (ptr->firstTiled != NULL)
5470 return 1;
5471 return 0;
5472 }
5473
5474 RL2_DECLARE const char *
get_wms_tile_service_name(rl2WmsCatalogPtr handle)5475 get_wms_tile_service_name (rl2WmsCatalogPtr handle)
5476 {
5477 /* return the TileService name */
5478 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5479 if (ptr == NULL)
5480 return NULL;
5481
5482 return ptr->TileServiceName;
5483 }
5484
5485 RL2_DECLARE const char *
get_wms_tile_service_title(rl2WmsCatalogPtr handle)5486 get_wms_tile_service_title (rl2WmsCatalogPtr handle)
5487 {
5488 /* return the TileService title */
5489 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5490 if (ptr == NULL)
5491 return NULL;
5492
5493 return ptr->TileServiceTitle;
5494 }
5495
5496 RL2_DECLARE const char *
get_wms_tile_service_abstract(rl2WmsCatalogPtr handle)5497 get_wms_tile_service_abstract (rl2WmsCatalogPtr handle)
5498 {
5499 /* return the TileService abstract */
5500 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5501 if (ptr == NULL)
5502 return NULL;
5503
5504 return ptr->TileServiceAbstract;
5505 }
5506
5507 RL2_DECLARE int
get_wms_tile_service_count(rl2WmsCatalogPtr handle)5508 get_wms_tile_service_count (rl2WmsCatalogPtr handle)
5509 {
5510 /* counting how many first-level tiled layers are defined within a WMS-Catalog */
5511 int count = 0;
5512 wmsTiledLayerPtr lyr;
5513 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5514 if (ptr == NULL)
5515 return -1;
5516
5517 lyr = ptr->firstTiled;
5518 while (lyr != NULL)
5519 {
5520 count++;
5521 lyr = lyr->next;
5522 }
5523 return count;
5524 }
5525
5526 RL2_DECLARE rl2WmsTiledLayerPtr
get_wms_catalog_tiled_layer(rl2WmsCatalogPtr handle,int index)5527 get_wms_catalog_tiled_layer (rl2WmsCatalogPtr handle, int index)
5528 {
5529 /* attempting to get a reference to some WMS-TiledLayer object */
5530 int count = 0;
5531 wmsTiledLayerPtr lyr;
5532 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
5533 if (ptr == NULL)
5534 return NULL;
5535
5536 lyr = ptr->firstTiled;
5537 while (lyr != NULL)
5538 {
5539 if (count == index)
5540 return (rl2WmsTiledLayerPtr) lyr;
5541 count++;
5542 lyr = lyr->next;
5543 }
5544 return NULL;
5545 }
5546
5547 RL2_DECLARE int
wms_tiled_layer_has_children(rl2WmsTiledLayerPtr handle)5548 wms_tiled_layer_has_children (rl2WmsTiledLayerPtr handle)
5549 {
5550 /* testing if a WMS-TiledLayer object has TiledLayer children */
5551 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5552 if (ptr == NULL)
5553 return 0;
5554 if (ptr->firstChild == NULL)
5555 return 0;
5556 return 1;
5557 }
5558
5559 RL2_DECLARE int
get_wms_tiled_layer_children_count(rl2WmsTiledLayerPtr handle)5560 get_wms_tiled_layer_children_count (rl2WmsTiledLayerPtr handle)
5561 {
5562 /* counting how many children tiled layers are defined within a WMS-TiledLayer */
5563 int count = 0;
5564 wmsTiledLayerPtr lyr;
5565 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5566 if (ptr == NULL)
5567 return -1;
5568
5569 lyr = ptr->firstChild;
5570 while (lyr != NULL)
5571 {
5572 count++;
5573 lyr = lyr->next;
5574 }
5575 return count;
5576 }
5577
5578 RL2_DECLARE rl2WmsTiledLayerPtr
get_wms_child_tiled_layer(rl2WmsTiledLayerPtr handle,int index)5579 get_wms_child_tiled_layer (rl2WmsTiledLayerPtr handle, int index)
5580 {
5581 /* attempting to get a reference to some child WMS-TiledLayer object */
5582 int count = 0;
5583 wmsTiledLayerPtr lyr;
5584 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5585 if (ptr == NULL)
5586 return NULL;
5587
5588 lyr = ptr->firstChild;
5589 while (lyr != NULL)
5590 {
5591 if (count == index)
5592 return (rl2WmsTiledLayerPtr) lyr;
5593 count++;
5594 lyr = lyr->next;
5595 }
5596 return NULL;
5597 }
5598
5599 RL2_DECLARE const char *
get_wms_tiled_layer_name(rl2WmsTiledLayerPtr handle)5600 get_wms_tiled_layer_name (rl2WmsTiledLayerPtr handle)
5601 {
5602 /* return the name corresponding to a WMS-TiledLayer object */
5603 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5604 if (ptr == NULL)
5605 return NULL;
5606 return ptr->Name;
5607 }
5608
5609 RL2_DECLARE const char *
get_wms_tiled_layer_title(rl2WmsTiledLayerPtr handle)5610 get_wms_tiled_layer_title (rl2WmsTiledLayerPtr handle)
5611 {
5612 /* return the title corresponding to a WMS-TiledLayer object */
5613 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5614 if (ptr == NULL)
5615 return NULL;
5616 return ptr->Title;
5617 }
5618
5619 RL2_DECLARE const char *
get_wms_tiled_layer_abstract(rl2WmsTiledLayerPtr handle)5620 get_wms_tiled_layer_abstract (rl2WmsTiledLayerPtr handle)
5621 {
5622 /* return the abstract corresponding to a WMS-TiledLayer object */
5623 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5624 if (ptr == NULL)
5625 return NULL;
5626 return ptr->Abstract;
5627 }
5628
5629 RL2_DECLARE const char *
get_wms_tiled_layer_pad(rl2WmsTiledLayerPtr handle)5630 get_wms_tiled_layer_pad (rl2WmsTiledLayerPtr handle)
5631 {
5632 /* return the Pad corresponding to a WMS-TiledLayer object */
5633 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5634 if (ptr == NULL)
5635 return NULL;
5636 return ptr->Pad;
5637 }
5638
5639 RL2_DECLARE const char *
get_wms_tiled_layer_bands(rl2WmsTiledLayerPtr handle)5640 get_wms_tiled_layer_bands (rl2WmsTiledLayerPtr handle)
5641 {
5642 /* return the Bands corresponding to a WMS-TiledLayer object */
5643 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5644 if (ptr == NULL)
5645 return NULL;
5646 return ptr->Bands;
5647 }
5648
5649 RL2_DECLARE const char *
get_wms_tiled_layer_data_type(rl2WmsTiledLayerPtr handle)5650 get_wms_tiled_layer_data_type (rl2WmsTiledLayerPtr handle)
5651 {
5652 /* return the Bands corresponding to a WMS-TiledLayer object */
5653 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5654 if (ptr == NULL)
5655 return NULL;
5656 return ptr->DataType;
5657 }
5658
5659 RL2_DECLARE int
get_wms_tiled_layer_bbox(rl2WmsTiledLayerPtr handle,double * minx,double * miny,double * maxx,double * maxy)5660 get_wms_tiled_layer_bbox (rl2WmsTiledLayerPtr handle, double *minx,
5661 double *miny, double *maxx, double *maxy)
5662 {
5663 /* return the BBox corresponding to a WMS-TiledLayer object */
5664 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5665 if (ptr == NULL)
5666 return 0;
5667 *minx = ptr->MinLong;
5668 *miny = ptr->MinLat;
5669 *maxx = ptr->MaxLong;
5670 *maxy = ptr->MaxLat;
5671 return 1;
5672 }
5673
5674 RL2_DECLARE int
get_wms_tiled_layer_tile_size(rl2WmsTiledLayerPtr handle,int * width,int * height)5675 get_wms_tiled_layer_tile_size (rl2WmsTiledLayerPtr handle, int *width,
5676 int *height)
5677 {
5678 /* return the Tile Size corresponding to a WMS-TiledLayer object */
5679 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5680 if (ptr == NULL)
5681 return 0;
5682 if (ptr->firstPattern == NULL)
5683 return 0;
5684 *width = ptr->firstPattern->TileWidth;
5685 *height = ptr->firstPattern->TileHeight;
5686 return 1;
5687 }
5688
5689 RL2_DECLARE const char *
get_wms_tiled_layer_crs(rl2WmsTiledLayerPtr handle)5690 get_wms_tiled_layer_crs (rl2WmsTiledLayerPtr handle)
5691 {
5692 /* return the CRS corresponding to a WMS-TiledLayer object */
5693 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5694 if (ptr == NULL)
5695 return NULL;
5696 if (ptr->firstPattern == NULL)
5697 return NULL;
5698 return ptr->firstPattern->SRS;
5699 }
5700
5701 RL2_DECLARE const char *
get_wms_tiled_layer_format(rl2WmsTiledLayerPtr handle)5702 get_wms_tiled_layer_format (rl2WmsTiledLayerPtr handle)
5703 {
5704 /* return the Format corresponding to a WMS-TiledLayer object */
5705 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5706 if (ptr == NULL)
5707 return NULL;
5708 if (ptr->firstPattern == NULL)
5709 return NULL;
5710 return ptr->firstPattern->Format;
5711 }
5712
5713 RL2_DECLARE const char *
get_wms_tiled_layer_style(rl2WmsTiledLayerPtr handle)5714 get_wms_tiled_layer_style (rl2WmsTiledLayerPtr handle)
5715 {
5716 /* return the Style corresponding to a WMS-TiledLayer object */
5717 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5718 if (ptr == NULL)
5719 return NULL;
5720 if (ptr->firstPattern == NULL)
5721 return NULL;
5722 return ptr->firstPattern->Style;
5723 }
5724
5725 RL2_DECLARE int
get_wms_tile_pattern_count(rl2WmsTiledLayerPtr handle)5726 get_wms_tile_pattern_count (rl2WmsTiledLayerPtr handle)
5727 {
5728 /* counting how many TilePatterns are defined within a WMS-TiledLayer object */
5729 int count = 0;
5730 wmsTilePatternPtr pattern;
5731 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5732 if (ptr == NULL)
5733 return -1;
5734
5735 pattern = ptr->firstPattern;
5736 while (pattern != NULL)
5737 {
5738 count++;
5739 pattern = pattern->next;
5740 }
5741 return count;
5742 }
5743
5744 RL2_DECLARE rl2WmsTilePatternPtr
get_wms_tile_pattern_handle(rl2WmsTiledLayerPtr handle,int index)5745 get_wms_tile_pattern_handle (rl2WmsTiledLayerPtr handle, int index)
5746 {
5747 /* return the Handle from a TilePattern (identified by its index) */
5748 int count = 0;
5749 wmsTilePatternPtr pattern;
5750 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5751 if (ptr == NULL)
5752 return NULL;
5753
5754 pattern = ptr->firstPattern;
5755 while (pattern != NULL)
5756 {
5757 if (count == index)
5758 return (rl2WmsTilePatternPtr) pattern;
5759 count++;
5760 pattern = pattern->next;
5761 }
5762 return NULL;
5763 }
5764
5765 RL2_DECLARE rl2WmsTilePatternPtr
clone_wms_tile_pattern(rl2WmsTilePatternPtr handle)5766 clone_wms_tile_pattern (rl2WmsTilePatternPtr handle)
5767 {
5768 /* clones a WMS TilePattern object */
5769 char *str;
5770 int len;
5771 wmsTilePatternPtr clone;
5772 wmsTilePatternPtr pattern = (wmsTilePatternPtr) handle;
5773 if (pattern == NULL)
5774 return NULL;
5775
5776 len = strlen (pattern->Pattern);
5777 str = malloc (len + 1);
5778 strcpy (str, pattern->Pattern);
5779 clone = wmsAllocTilePattern (str);
5780 return (rl2WmsTilePatternPtr) clone;
5781 }
5782
5783 RL2_DECLARE void
destroy_wms_tile_pattern(rl2WmsTilePatternPtr handle)5784 destroy_wms_tile_pattern (rl2WmsTilePatternPtr handle)
5785 {
5786 /* memory cleanup - finalizes a WMS-TilePattern object */
5787 wmsTilePatternPtr pattern = (wmsTilePatternPtr) handle;
5788 if (pattern == NULL)
5789 return;
5790 wmsFreeTilePattern (pattern);
5791 }
5792
5793 RL2_DECLARE const char *
get_wms_tile_pattern_srs(rl2WmsTiledLayerPtr handle,int index)5794 get_wms_tile_pattern_srs (rl2WmsTiledLayerPtr handle, int index)
5795 {
5796 /* return the SRS from a TilePattern (identified by its index) */
5797 int count = 0;
5798 wmsTilePatternPtr pattern;
5799 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5800 if (ptr == NULL)
5801 return NULL;
5802
5803 pattern = ptr->firstPattern;
5804 while (pattern != NULL)
5805 {
5806 if (count == index)
5807 return pattern->SRS;
5808 count++;
5809 pattern = pattern->next;
5810 }
5811 return NULL;
5812 }
5813
5814 RL2_DECLARE int
get_wms_tile_pattern_tile_width(rl2WmsTiledLayerPtr handle,int index)5815 get_wms_tile_pattern_tile_width (rl2WmsTiledLayerPtr handle, int index)
5816 {
5817 /* return the TileWidth from a TilePattern (identified by its index) */
5818 int count = 0;
5819 wmsTilePatternPtr pattern;
5820 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5821 if (ptr == NULL)
5822 return -1;
5823
5824 pattern = ptr->firstPattern;
5825 while (pattern != NULL)
5826 {
5827 if (count == index)
5828 return pattern->TileWidth;
5829 count++;
5830 pattern = pattern->next;
5831 }
5832 return -1;
5833 }
5834
5835 RL2_DECLARE int
get_wms_tile_pattern_tile_height(rl2WmsTiledLayerPtr handle,int index)5836 get_wms_tile_pattern_tile_height (rl2WmsTiledLayerPtr handle, int index)
5837 {
5838 /* return the TileHeight from a TilePattern (identified by its index) */
5839 int count = 0;
5840 wmsTilePatternPtr pattern;
5841 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5842 if (ptr == NULL)
5843 return -1;
5844
5845 pattern = ptr->firstPattern;
5846 while (pattern != NULL)
5847 {
5848 if (count == index)
5849 return pattern->TileHeight;
5850 count++;
5851 pattern = pattern->next;
5852 }
5853 return -1;
5854 }
5855
5856 RL2_DECLARE double
get_wms_tile_pattern_base_x(rl2WmsTiledLayerPtr handle,int index)5857 get_wms_tile_pattern_base_x (rl2WmsTiledLayerPtr handle, int index)
5858 {
5859 /* return the TileBaseX (leftmost coord) from a TilePattern (identified by its index) */
5860 int count = 0;
5861 wmsTilePatternPtr pattern;
5862 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5863 if (ptr == NULL)
5864 return DBL_MAX;
5865
5866 pattern = ptr->firstPattern;
5867 while (pattern != NULL)
5868 {
5869 if (count == index)
5870 return pattern->TileBaseX;
5871 count++;
5872 pattern = pattern->next;
5873 }
5874 return DBL_MAX;
5875 }
5876
5877 RL2_DECLARE double
get_wms_tile_pattern_base_y(rl2WmsTiledLayerPtr handle,int index)5878 get_wms_tile_pattern_base_y (rl2WmsTiledLayerPtr handle, int index)
5879 {
5880 /* return the TileBaseY (topmost coord) from a TilePattern (identified by its index) */
5881 int count = 0;
5882 wmsTilePatternPtr pattern;
5883 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5884 if (ptr == NULL)
5885 return DBL_MAX;
5886
5887 pattern = ptr->firstPattern;
5888 while (pattern != NULL)
5889 {
5890 if (count == index)
5891 return pattern->TileBaseY;
5892 count++;
5893 pattern = pattern->next;
5894 }
5895 return DBL_MAX;
5896 }
5897
5898 RL2_DECLARE double
get_wms_tile_pattern_extent_x(rl2WmsTiledLayerPtr handle,int index)5899 get_wms_tile_pattern_extent_x (rl2WmsTiledLayerPtr handle, int index)
5900 {
5901 /* return the TileExtentX from a TilePattern (identified by its index) */
5902 int count = 0;
5903 wmsTilePatternPtr pattern;
5904 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5905 if (ptr == NULL)
5906 return DBL_MAX;
5907
5908 pattern = ptr->firstPattern;
5909 while (pattern != NULL)
5910 {
5911 if (count == index)
5912 return pattern->TileExtentX;
5913 count++;
5914 pattern = pattern->next;
5915 }
5916 return DBL_MAX;
5917 }
5918
5919 RL2_DECLARE double
get_wms_tile_pattern_extent_y(rl2WmsTiledLayerPtr handle,int index)5920 get_wms_tile_pattern_extent_y (rl2WmsTiledLayerPtr handle, int index)
5921 {
5922 /* return the TileExtentY from a TilePattern (identified by its index) */
5923 int count = 0;
5924 wmsTilePatternPtr pattern;
5925 wmsTiledLayerPtr ptr = (wmsTiledLayerPtr) handle;
5926 if (ptr == NULL)
5927 return DBL_MAX;
5928
5929 pattern = ptr->firstPattern;
5930 while (pattern != NULL)
5931 {
5932 if (count == index)
5933 return pattern->TileExtentY;
5934 count++;
5935 pattern = pattern->next;
5936 }
5937 return DBL_MAX;
5938 }
5939
5940 RL2_DECLARE char *
get_wms_tile_pattern_sample_url(rl2WmsTilePatternPtr handle)5941 get_wms_tile_pattern_sample_url (rl2WmsTilePatternPtr handle)
5942 {
5943 /* return the sample URL for some TilePattern */
5944 char *url = NULL;
5945 wmsUrlArgumentPtr arg;
5946 wmsTilePatternPtr ptr = (wmsTilePatternPtr) handle;
5947 if (ptr == NULL)
5948 return NULL;
5949
5950 arg = ptr->first;
5951 while (arg != NULL)
5952 {
5953 if (url != NULL)
5954 {
5955 char *str;
5956 if (arg->argValue == NULL)
5957 str = sqlite3_mprintf ("%s&%s=", url, arg->argName);
5958 else
5959 str =
5960 sqlite3_mprintf ("%s&%s=%s", url,
5961 arg->argName, arg->argValue);
5962 sqlite3_free (url);
5963 url = str;
5964 }
5965 else
5966 {
5967 if (arg->argValue == NULL)
5968 url = sqlite3_mprintf ("%s=", arg->argName);
5969 else
5970 url =
5971 sqlite3_mprintf ("%s=%s", arg->argName, arg->argValue);
5972 }
5973 arg = arg->next;
5974 }
5975 return url;
5976 }
5977
5978 RL2_DECLARE char *
get_wms_tile_pattern_request_url(rl2WmsTilePatternPtr handle,const char * base_url,double min_x,double min_y)5979 get_wms_tile_pattern_request_url (rl2WmsTilePatternPtr
5980 handle,
5981 const char *base_url,
5982 double min_x, double min_y)
5983 {
5984 /* return a full GetMap request URL for some TilePattern */
5985 char *url = NULL;
5986 wmsUrlArgumentPtr arg;
5987 wmsTilePatternPtr ptr = (wmsTilePatternPtr) handle;
5988 if (ptr == NULL)
5989 return NULL;
5990
5991 url = sqlite3_mprintf ("%s", base_url);
5992 arg = ptr->first;
5993 while (arg != NULL)
5994 {
5995 char *str;
5996 if (strcasecmp (arg->argName, "bbox") == 0)
5997 {
5998 char *bbox =
5999 sqlite3_mprintf ("%1.6f,%1.6f,%1.6f,%1.6f", min_x, min_y,
6000 min_x + ptr->TileExtentX,
6001 min_y + ptr->TileExtentY);
6002 if (arg != ptr->first)
6003 {
6004 str = sqlite3_mprintf ("%s&%s=%s", url,
6005 arg->argName, bbox);
6006 }
6007 else
6008 {
6009 str =
6010 sqlite3_mprintf ("%s%s=%s", url, arg->argName, bbox);
6011 }
6012 sqlite3_free (bbox);
6013 }
6014 else
6015 {
6016 if (arg != ptr->first)
6017 {
6018 if (arg->argValue == NULL)
6019 str = sqlite3_mprintf ("%s&%s=", url, arg->argName);
6020 else
6021 str =
6022 sqlite3_mprintf ("%s&%s=%s", url,
6023 arg->argName, arg->argValue);
6024 }
6025 else
6026 {
6027 if (arg->argValue == NULL)
6028 str = sqlite3_mprintf ("%s%s=", url, arg->argName);
6029 else
6030 str =
6031 sqlite3_mprintf ("%s%s=%s", url, arg->argName,
6032 arg->argValue);
6033 }
6034 }
6035 sqlite3_free (url);
6036 url = str;
6037 arg = arg->next;
6038 }
6039 return url;
6040 }
6041
6042 RL2_DECLARE int
get_wms_catalog_count(rl2WmsCatalogPtr handle)6043 get_wms_catalog_count (rl2WmsCatalogPtr handle)
6044 {
6045 /* counting how many first-level layers are defined within a WMS-Catalog */
6046 int count = 0;
6047 wmsLayerPtr lyr;
6048 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
6049 if (ptr == NULL)
6050 return -1;
6051
6052 lyr = ptr->firstLayer;
6053 while (lyr != NULL)
6054 {
6055 count++;
6056 lyr = lyr->next;
6057 }
6058 return count;
6059 }
6060
6061 RL2_DECLARE rl2WmsLayerPtr
get_wms_catalog_layer(rl2WmsCatalogPtr handle,int index)6062 get_wms_catalog_layer (rl2WmsCatalogPtr handle, int index)
6063 {
6064 /* attempting to get a reference to some WMS-Layer object */
6065 int count = 0;
6066 wmsLayerPtr lyr;
6067 wmsCapabilitiesPtr ptr = (wmsCapabilitiesPtr) handle;
6068 if (ptr == NULL)
6069 return NULL;
6070
6071 lyr = ptr->firstLayer;
6072 while (lyr != NULL)
6073 {
6074 if (count == index)
6075 return (rl2WmsLayerPtr) lyr;
6076 count++;
6077 lyr = lyr->next;
6078 }
6079 return NULL;
6080 }
6081
6082 RL2_DECLARE int
wms_layer_has_children(rl2WmsLayerPtr handle)6083 wms_layer_has_children (rl2WmsLayerPtr handle)
6084 {
6085 /* testing if a WMS-Layer object has Layer children */
6086 wmsLayerPtr ptr = (wmsLayerPtr) handle;
6087 if (ptr == NULL)
6088 return 0;
6089 if (ptr->firstLayer == NULL)
6090 return 0;
6091 return 1;
6092 }
6093
6094 RL2_DECLARE int
get_wms_layer_children_count(rl2WmsLayerPtr handle)6095 get_wms_layer_children_count (rl2WmsLayerPtr handle)
6096 {
6097 /* counting how many children layers are defined within a WMS-Layer */
6098 int count = 0;
6099 wmsLayerPtr lyr;
6100 wmsLayerPtr ptr = (wmsLayerPtr) handle;
6101 if (ptr == NULL)
6102 return -1;
6103
6104 lyr = ptr->firstLayer;
6105 while (lyr != NULL)
6106 {
6107 count++;
6108 lyr = lyr->next;
6109 }
6110 return count;
6111 }
6112
6113 RL2_DECLARE rl2WmsLayerPtr
get_wms_child_layer(rl2WmsLayerPtr handle,int index)6114 get_wms_child_layer (rl2WmsLayerPtr handle, int index)
6115 {
6116 /* attempting to get a reference to some child WMS-Layer object */
6117 int count = 0;
6118 wmsLayerPtr lyr;
6119 wmsLayerPtr ptr = (wmsLayerPtr) handle;
6120 if (ptr == NULL)
6121 return NULL;
6122
6123 lyr = ptr->firstLayer;
6124 while (lyr != NULL)
6125 {
6126 if (count == index)
6127 return (rl2WmsLayerPtr) lyr;
6128 count++;
6129 lyr = lyr->next;
6130 }
6131 return NULL;
6132 }
6133
6134 RL2_DECLARE const char *
get_wms_layer_name(rl2WmsLayerPtr handle)6135 get_wms_layer_name (rl2WmsLayerPtr handle)
6136 {
6137 /* return the name corresponding to a WMS-Layer object */
6138 wmsLayerPtr ptr = (wmsLayerPtr) handle;
6139 if (ptr == NULL)
6140 return NULL;
6141 return ptr->Name;
6142 }
6143
6144 RL2_DECLARE const char *
get_wms_layer_title(rl2WmsLayerPtr handle)6145 get_wms_layer_title (rl2WmsLayerPtr handle)
6146 {
6147 /* return the title corresponding to a WMS-Layer object */
6148 wmsLayerPtr ptr = (wmsLayerPtr) handle;
6149 if (ptr == NULL)
6150 return NULL;
6151 return ptr->Title;
6152 }
6153
6154 RL2_DECLARE const char *
get_wms_layer_abstract(rl2WmsLayerPtr handle)6155 get_wms_layer_abstract (rl2WmsLayerPtr handle)
6156 {
6157 /* return the abstract corresponding to a WMS-Layer object */
6158 wmsLayerPtr ptr = (wmsLayerPtr) handle;
6159 if (ptr == NULL)
6160 return NULL;
6161 return ptr->Abstract;
6162 }
6163
6164 static int
wms_parent_crs_count(wmsLayerPtr lyr)6165 wms_parent_crs_count (wmsLayerPtr lyr)
6166 {
6167 /* recursively counting how many CRSs are supported by a parent Layer (inheritance) */
6168 int count = 0;
6169 wmsCrsPtr crs;
6170 if (lyr == NULL)
6171 return 0;
6172
6173 crs = lyr->firstCrs;
6174 while (crs != NULL)
6175 {
6176 count++;
6177 crs = crs->next;
6178 }
6179 count += wms_parent_crs_count (lyr->Parent);
6180 return count;
6181 }
6182
6183 RL2_DECLARE int
get_wms_layer_crs_count(rl2WmsLayerPtr handle)6184 get_wms_layer_crs_count (rl2WmsLayerPtr handle)
6185 {
6186 /* counting how many CRSs are supported by a WMS-Layer */
6187 int count = 0;
6188 wmsCrsPtr crs;
6189 wmsLayerPtr ptr = (wmsLayerPtr) handle;
6190 if (ptr == NULL)
6191 return -1;
6192
6193 crs = ptr->firstCrs;
6194 while (crs != NULL)
6195 {
6196 count++;
6197 crs = crs->next;
6198 }
6199 count += wms_parent_crs_count (ptr->Parent);
6200 return count;
6201 }
6202
6203 static wmsCrsPtr
wms_parent_crs(wmsLayerPtr lyr,int * cnt,int index)6204 wms_parent_crs (wmsLayerPtr lyr, int *cnt, int index)
6205 {
6206 /* recursively finding a CRS by index (inheritance) */
6207 int count = *cnt;
6208 wmsCrsPtr crs;
6209 if (lyr == NULL)
6210 return 0;
6211
6212 crs = lyr->firstCrs;
6213 while (crs != NULL)
6214 {
6215 if (count == index)
6216 return crs;
6217 count++;
6218 crs = crs->next;
6219 }
6220 *cnt = count;
6221 crs = wms_parent_crs (lyr->Parent, cnt, index);
6222 return crs;
6223 }
6224
6225 RL2_DECLARE const char *
get_wms_layer_crs(rl2WmsLayerPtr handle,int index)6226 get_wms_layer_crs (rl2WmsLayerPtr handle, int index)
6227 {
6228 /* attempting to get the Nth CRS supported by some WMS-Layer object */
6229 int count = 0;
6230 wmsCrsPtr crs;
6231 wmsLayerPtr ptr = (wmsLayerPtr) handle;
6232 if (ptr == NULL)
6233 return NULL;
6234
6235 crs = ptr->firstCrs;
6236 while (crs != NULL)
6237 {
6238 if (count == index)
6239 return crs->Crs;
6240 count++;
6241 crs = crs->next;
6242 }
6243 crs = wms_parent_crs (ptr->Parent, &count, index);
6244 if (crs != NULL)
6245 return crs->Crs;
6246 return NULL;
6247 }
6248
6249 RL2_DECLARE int
get_wms_layer_style_count(rl2WmsLayerPtr handle)6250 get_wms_layer_style_count (rl2WmsLayerPtr handle)
6251 {
6252 /* counting how many Styles are supported by a WMS-Layer */
6253 int count = 0;
6254 wmsStylePtr stl;
6255 wmsLayerPtr ptr = (wmsLayerPtr) handle;
6256 if (ptr == NULL)
6257 return -1;
6258
6259 stl = ptr->firstStyle;
6260 while (stl != NULL)
6261 {
6262 count++;
6263 stl = stl->next;
6264 }
6265 return count;
6266 }
6267
6268 RL2_DECLARE const char *
get_wms_layer_style_name(rl2WmsLayerPtr handle,int index)6269 get_wms_layer_style_name (rl2WmsLayerPtr handle, int index)
6270 {
6271 /* attempting to get the Name of the Nth Style supported by some WMS-Layer object */
6272 int count = 0;
6273 wmsStylePtr stl;
6274 wmsLayerPtr ptr = (wmsLayerPtr) handle;
6275 if (ptr == NULL)
6276 return NULL;
6277
6278 stl = ptr->firstStyle;
6279 while (stl != NULL)
6280 {
6281 if (count == index)
6282 return stl->Name;
6283 count++;
6284 stl = stl->next;
6285 }
6286 return NULL;
6287 }
6288
6289 RL2_DECLARE const char *
get_wms_layer_style_title(rl2WmsLayerPtr handle,int index)6290 get_wms_layer_style_title (rl2WmsLayerPtr handle, int index)
6291 {
6292 /* attempting to get the Title of the Nth Style supported by some WMS-Layer object */
6293 int count = 0;
6294 wmsStylePtr stl;
6295 wmsLayerPtr ptr = (wmsLayerPtr) handle;
6296 if (ptr == NULL)
6297 return NULL;
6298
6299 stl = ptr->firstStyle;
6300 while (stl != NULL)
6301 {
6302 if (count == index)
6303 return stl->Title;
6304 count++;
6305 stl = stl->next;
6306 }
6307 return NULL;
6308 }
6309
6310 RL2_DECLARE const char *
get_wms_layer_style_abstract(rl2WmsLayerPtr handle,int index)6311 get_wms_layer_style_abstract (rl2WmsLayerPtr handle, int index)
6312 {
6313 /* attempting to get the Abstract of the Nth Style supported by some WMS-Layer object */
6314 int count = 0;
6315 wmsStylePtr stl;
6316 wmsLayerPtr ptr = (wmsLayerPtr) handle;
6317 if (ptr == NULL)
6318 return NULL;
6319
6320 stl = ptr->firstStyle;
6321 while (stl != NULL)
6322 {
6323 if (count == index)
6324 return stl->Abstract;
6325 count++;
6326 stl = stl->next;
6327 }
6328 return NULL;
6329 }
6330
6331 static void
wms_parent_opaque(wmsLayerPtr lyr,int * opaque)6332 wms_parent_opaque (wmsLayerPtr lyr, int *opaque)
6333 {
6334 /* recursively testing the Opaque property from a parent Layer (inheritance) */
6335 if (lyr == NULL)
6336 return;
6337
6338 if (lyr->Opaque >= 0)
6339 {
6340 *opaque = lyr->Opaque;
6341 return;
6342 }
6343 wms_parent_opaque (lyr->Parent, opaque);
6344 }
6345
6346 RL2_DECLARE int
is_wms_layer_opaque(rl2WmsLayerPtr handle)6347 is_wms_layer_opaque (rl2WmsLayerPtr handle)
6348 {
6349 /* Tests if some WMS-Layer object declares the Opaque property */
6350 int opaque = -1;
6351 wmsLayerPtr ptr = (wmsLayerPtr) handle;
6352 if (ptr == NULL)
6353 return -1;
6354
6355 if (ptr->Opaque >= 0)
6356 return ptr->Opaque;
6357 wms_parent_opaque (ptr->Parent, &opaque);
6358 return opaque;
6359 }
6360
6361 static void
wms_parent_queryable(wmsLayerPtr lyr,int * queryable)6362 wms_parent_queryable (wmsLayerPtr lyr, int *queryable)
6363 {
6364 /* recursively testing the Queryable property from a parent Layer (inheritance) */
6365 if (lyr == NULL)
6366 return;
6367
6368 if (lyr->Queryable >= 0)
6369 {
6370 *queryable = lyr->Queryable;
6371 return;
6372 }
6373 wms_parent_opaque (lyr->Parent, queryable);
6374 }
6375
6376 RL2_DECLARE int
is_wms_layer_queryable(rl2WmsLayerPtr handle)6377 is_wms_layer_queryable (rl2WmsLayerPtr handle)
6378 {
6379 /* Tests if some WMS-Layer object declares the Queryable property */
6380 int queryable = -1;
6381 wmsLayerPtr ptr = (wmsLayerPtr) handle;
6382 if (ptr == NULL)
6383 return -1;
6384
6385 if (ptr->Queryable >= 0)
6386 return ptr->Queryable;
6387 wms_parent_queryable (ptr->Parent, &queryable);
6388 return queryable;
6389 }
6390
6391 RL2_DECLARE double
get_wms_layer_min_scale_denominator(rl2WmsLayerPtr handle)6392 get_wms_layer_min_scale_denominator (rl2WmsLayerPtr handle)
6393 {
6394 /* Return the MinScaleDenominator from some WMS-Layer object */
6395 wmsLayerPtr ptr = (wmsLayerPtr) handle;
6396 if (ptr == NULL)
6397 return DBL_MAX;
6398
6399 return ptr->MinScaleDenominator;
6400 }
6401
6402 RL2_DECLARE double
get_wms_layer_max_scale_denominator(rl2WmsLayerPtr handle)6403 get_wms_layer_max_scale_denominator (rl2WmsLayerPtr handle)
6404 {
6405 /* Return the MaxScaleDenominator from some WMS-Layer object */
6406 wmsLayerPtr ptr = (wmsLayerPtr) handle;
6407 if (ptr == NULL)
6408 return DBL_MAX;
6409
6410 return ptr->MaxScaleDenominator;
6411 }
6412
6413 RL2_DECLARE int
get_wms_layer_geo_bbox(rl2WmsLayerPtr handle,double * minx,double * maxx,double * miny,double * maxy)6414 get_wms_layer_geo_bbox (rl2WmsLayerPtr handle, double *minx, double *maxx,
6415 double *miny, double *maxy)
6416 {
6417 /* Return the Geographic Bounding Box from some WMS-Layer object */
6418 wmsLayerPtr ptr = (wmsLayerPtr) handle;
6419 *minx = DBL_MAX;
6420 *maxx = DBL_MAX;
6421 *miny = DBL_MAX;
6422 *maxx = DBL_MAX;
6423 if (ptr == NULL)
6424 return 0;
6425
6426 if (ptr->MinLat == DBL_MAX && ptr->MaxLat == DBL_MAX
6427 && ptr->MinLong == DBL_MAX && ptr->MaxLong == DBL_MAX)
6428 {
6429 /* undefined: iteratively searching its Parents */
6430 wmsLayerPtr parent = ptr->Parent;
6431 while (parent != NULL)
6432 {
6433 if (parent->MinLat == DBL_MAX && parent->MaxLat == DBL_MAX
6434 && parent->MinLong == DBL_MAX && parent->MaxLong == DBL_MAX)
6435 {
6436 parent = parent->Parent;
6437 continue;
6438 }
6439 *miny = parent->MinLat;
6440 *maxy = parent->MaxLat;
6441 *minx = parent->MinLong;
6442 *maxx = parent->MaxLong;
6443 return 1;
6444 }
6445 }
6446 *miny = ptr->MinLat;
6447 *maxy = ptr->MaxLat;
6448 *minx = ptr->MinLong;
6449 *maxx = ptr->MaxLong;
6450 return 1;
6451 }
6452
6453 RL2_DECLARE int
get_wms_layer_bbox(rl2WmsLayerPtr handle,const char * crs,double * minx,double * maxx,double * miny,double * maxy)6454 get_wms_layer_bbox (rl2WmsLayerPtr handle, const char *crs, double *minx,
6455 double *maxx, double *miny, double *maxy)
6456 {
6457 /* Return the Bounding Box corresponding to given CRS from some WMS-Layer object */
6458 wmsBBoxPtr bbox;
6459 wmsLayerPtr ptr = (wmsLayerPtr) handle;
6460 wmsLayerPtr parent;
6461 *minx = DBL_MAX;
6462 *maxx = DBL_MAX;
6463 *miny = DBL_MAX;
6464 *maxx = DBL_MAX;
6465 if (ptr == NULL)
6466 return 0;
6467
6468 bbox = ptr->firstBBox;
6469 while (bbox != NULL)
6470 {
6471 if (strcmp (bbox->Crs, crs) == 0)
6472 {
6473 *miny = bbox->MinY;
6474 *maxy = bbox->MaxY;
6475 *minx = bbox->MinX;
6476 *maxx = bbox->MaxX;
6477 return 1;
6478 }
6479 bbox = bbox->next;
6480 }
6481
6482 /* not found: iteratively searching its Parents */
6483 parent = ptr->Parent;
6484 while (parent != NULL)
6485 {
6486 bbox = parent->firstBBox;
6487 while (bbox != NULL)
6488 {
6489 if (strcmp (bbox->Crs, crs) == 0)
6490 {
6491 *miny = bbox->MinY;
6492 *maxy = bbox->MaxY;
6493 *minx = bbox->MinX;
6494 *maxx = bbox->MaxX;
6495 return 1;
6496 }
6497 bbox = bbox->next;
6498 }
6499 parent = parent->Parent;
6500 }
6501 return 0;
6502 }
6503
6504 RL2_DECLARE void
destroy_wms_feature_collection(rl2WmsFeatureCollectionPtr handle)6505 destroy_wms_feature_collection (rl2WmsFeatureCollectionPtr handle)
6506 {
6507 /* memory cleanup: freeing a GML Feature Collection object */
6508 wmsFeatureCollectionPtr ptr = (wmsFeatureCollectionPtr) handle;
6509 if (ptr == NULL)
6510 return;
6511 wmsFreeFeatureCollection (ptr);
6512 }
6513
6514 static int
check_swap(gaiaGeomCollPtr geom,double point_x,double point_y)6515 check_swap (gaiaGeomCollPtr geom, double point_x, double point_y)
6516 {
6517 /* checking if X and Y axes should be flipped */
6518 double x;
6519 double y;
6520 double z;
6521 double m;
6522 double dist;
6523 double dist_flip;
6524 gaiaPointPtr pt;
6525 gaiaLinestringPtr ln;
6526 gaiaPolygonPtr pg;
6527 pt = geom->FirstPoint;
6528 if (pt != NULL)
6529 {
6530 x = pt->X;
6531 y = pt->Y;
6532 goto eval;
6533 }
6534 ln = geom->FirstLinestring;
6535 if (ln != NULL)
6536 {
6537 if (ln->DimensionModel == GAIA_XY_Z)
6538 {
6539 gaiaGetPointXYZ (ln->Coords, 0, &x, &y, &z);
6540 }
6541 else if (ln->DimensionModel == GAIA_XY_M)
6542 {
6543 gaiaGetPointXYM (ln->Coords, 0, &x, &y, &m);
6544 }
6545 else if (ln->DimensionModel == GAIA_XY_Z_M)
6546 {
6547 gaiaGetPointXYZM (ln->Coords, 0, &x, &y, &z, &m);
6548 }
6549 else
6550 {
6551 gaiaGetPoint (ln->Coords, 0, &x, &y);
6552 }
6553 goto eval;
6554 }
6555 pg = geom->FirstPolygon;
6556 if (pg != NULL)
6557 {
6558 gaiaRingPtr ring = pg->Exterior;
6559 if (ring->DimensionModel == GAIA_XY_Z)
6560 {
6561 gaiaGetPointXYZ (ring->Coords, 0, &x, &y, &z);
6562 }
6563 else if (ring->DimensionModel == GAIA_XY_M)
6564 {
6565 gaiaGetPointXYM (ring->Coords, 0, &x, &y, &m);
6566 }
6567 else if (ring->DimensionModel == GAIA_XY_Z_M)
6568 {
6569 gaiaGetPointXYZM (ring->Coords, 0, &x, &y, &z, &m);
6570 }
6571 else
6572 {
6573 gaiaGetPoint (ring->Coords, 0, &x, &y);
6574 }
6575 goto eval;
6576 }
6577 return 0;
6578 eval:
6579 dist =
6580 sqrt (((x - point_x) * (x - point_x)) +
6581 ((y - point_y) * (y - point_y)));
6582 dist_flip =
6583 sqrt (((x - point_y) * (x - point_y)) +
6584 ((y - point_x) * (y - point_x)));
6585 if (dist_flip < dist)
6586 return 1;
6587 return 0;
6588 }
6589
6590 static void
getProjParams(void * p_sqlite,int srid,char ** proj_params)6591 getProjParams (void *p_sqlite, int srid, char **proj_params)
6592 {
6593 /* retrieves the PROJ params from SPATIAL_SYS_REF table, if possible */
6594 sqlite3 *sqlite = (sqlite3 *) p_sqlite;
6595 char *sql;
6596 char **results;
6597 int rows;
6598 int columns;
6599 int i;
6600 int ret;
6601 int len;
6602 const char *proj4text;
6603 char *errMsg = NULL;
6604 *proj_params = NULL;
6605 sql = sqlite3_mprintf
6606 ("SELECT proj4text FROM spatial_ref_sys WHERE srid = %d", srid);
6607 ret = sqlite3_get_table (sqlite, sql, &results, &rows, &columns, &errMsg);
6608 sqlite3_free (sql);
6609 if (ret != SQLITE_OK)
6610 {
6611 fprintf (stderr, "unknown SRID: %d\t<%s>\n", srid, errMsg);
6612 sqlite3_free (errMsg);
6613 return;
6614 }
6615 for (i = 1; i <= rows; i++)
6616 {
6617 proj4text = results[(i * columns)];
6618 if (proj4text != NULL)
6619 {
6620 len = strlen (proj4text);
6621 *proj_params = malloc (len + 1);
6622 strcpy (*proj_params, proj4text);
6623 }
6624 }
6625 if (*proj_params == NULL)
6626 fprintf (stderr, "unknown SRID: %d\n", srid);
6627 sqlite3_free_table (results);
6628 }
6629
6630 static gaiaGeomCollPtr
reproject(gaiaGeomCollPtr geom,int srid,sqlite3 * sqlite)6631 reproject (gaiaGeomCollPtr geom, int srid, sqlite3 * sqlite)
6632 {
6633 /* attempting to reproject into a different CRS */
6634 char *proj_from;
6635 char *proj_to;
6636 gaiaGeomCollPtr g2 = NULL;
6637 getProjParams (sqlite, geom->Srid, &proj_from);
6638 getProjParams (sqlite, srid, &proj_to);
6639 if (proj_to == NULL || proj_from == NULL)
6640 ;
6641 else
6642 g2 = gaiaTransform (geom, proj_from, proj_to);
6643 if (proj_from)
6644 free (proj_from);
6645 if (proj_to)
6646 free (proj_to);
6647 return g2;
6648 }
6649
6650 RL2_DECLARE void
wms_feature_collection_parse_geometries(rl2WmsFeatureCollectionPtr handle,int srid,double point_x,double point_y,sqlite3 * sqlite)6651 wms_feature_collection_parse_geometries (rl2WmsFeatureCollectionPtr
6652 handle, int srid, double point_x,
6653 double point_y, sqlite3 * sqlite)
6654 {
6655 /* attempting to parse any GML Geometry contained within a Feature Collection object */
6656 wmsFeatureMemberPtr member;
6657 wmsFeatureCollectionPtr ptr = (wmsFeatureCollectionPtr) handle;
6658 if (ptr == NULL)
6659 return;
6660
6661 member = ptr->first;
6662 while (member != NULL)
6663 {
6664 /* looping on FeatureMembers */
6665 wmsFeatureAttributePtr attr;
6666 attr = member->first;
6667 while (attr != NULL)
6668 {
6669 /* looping on FeatureAttributes */
6670 if (attr->value != NULL)
6671 {
6672 /* attempting to parse a possible GML Geometry */
6673 gaiaGeomCollPtr geom =
6674 gaiaParseGml ((const unsigned char *) (attr->value),
6675 sqlite);
6676 if (geom != NULL)
6677 {
6678 if (geom->Srid > 0 && srid > 0
6679 && geom->Srid != srid)
6680 {
6681 /* attempting to reproject into the Map CRS */
6682 gaiaGeomCollPtr g2 =
6683 reproject (geom, srid, sqlite);
6684 if (g2 != NULL)
6685 {
6686 if (check_swap (g2, point_x, point_y))
6687 {
6688 gaiaFreeGeomColl (g2);
6689 gaiaSwapCoords (geom);
6690 g2 = reproject (geom, srid,
6691 sqlite);
6692 attr->geometry = g2;
6693 gaiaFreeGeomColl (geom);
6694 }
6695 else
6696 {
6697 attr->geometry = g2;
6698 gaiaFreeGeomColl (geom);
6699 }
6700 }
6701 }
6702 else
6703 {
6704 if (check_swap (geom, point_x, point_y))
6705 gaiaSwapCoords (geom);
6706 attr->geometry = geom;
6707 }
6708 }
6709 }
6710 attr = attr->next;
6711 }
6712 member = member->next;
6713 }
6714 }
6715
6716 RL2_DECLARE int
get_wms_feature_members_count(rl2WmsFeatureCollectionPtr handle)6717 get_wms_feature_members_count (rl2WmsFeatureCollectionPtr handle)
6718 {
6719 /* counting how many Feature Members are contained within a WMS-FeatureCollection */
6720 int count = 0;
6721 wmsFeatureMemberPtr member;
6722 wmsFeatureCollectionPtr ptr = (wmsFeatureCollectionPtr) handle;
6723 if (ptr == NULL)
6724 return -1;
6725
6726 member = ptr->first;
6727 while (member != NULL)
6728 {
6729 count++;
6730 member = member->next;
6731 }
6732 return count;
6733 }
6734
6735 RL2_DECLARE rl2WmsFeatureMemberPtr
get_wms_feature_member(rl2WmsFeatureCollectionPtr handle,int index)6736 get_wms_feature_member (rl2WmsFeatureCollectionPtr handle, int index)
6737 {
6738 /* attempting to get the Nth FeatureMember from some WMS-FeatureCollection object */
6739 int count = 0;
6740 wmsFeatureMemberPtr member;
6741 wmsFeatureCollectionPtr ptr = (wmsFeatureCollectionPtr) handle;
6742 if (ptr == NULL)
6743 return NULL;
6744
6745 member = ptr->first;
6746 while (member != NULL)
6747 {
6748 if (count == index)
6749 return (rl2WmsFeatureMemberPtr) member;
6750 count++;
6751 member = member->next;
6752 }
6753 return NULL;
6754 }
6755
6756 RL2_DECLARE int
get_wms_feature_attributes_count(rl2WmsFeatureMemberPtr handle)6757 get_wms_feature_attributes_count (rl2WmsFeatureMemberPtr handle)
6758 {
6759 /* counting how many Feature Attributes are contained within a WMS-FeatureMember */
6760 int count = 0;
6761 wmsFeatureAttributePtr attr;
6762 wmsFeatureMemberPtr ptr = (wmsFeatureMemberPtr) handle;
6763 if (ptr == NULL)
6764 return -1;
6765
6766 attr = ptr->first;
6767 while (attr != NULL)
6768 {
6769 count++;
6770 attr = attr->next;
6771 }
6772 return count;
6773 }
6774
6775 RL2_DECLARE const char *
get_wms_feature_attribute_name(rl2WmsFeatureMemberPtr handle,int index)6776 get_wms_feature_attribute_name (rl2WmsFeatureMemberPtr handle, int index)
6777 {
6778 /* attempting to get the Nth FeatureAttribute (Name) from some WMS-FeatureMember object */
6779 int count = 0;
6780 wmsFeatureAttributePtr attr;
6781 wmsFeatureMemberPtr ptr = (wmsFeatureMemberPtr) handle;
6782 if (ptr == NULL)
6783 return NULL;
6784
6785 attr = ptr->first;
6786 while (attr != NULL)
6787 {
6788 if (count == index)
6789 return attr->name;
6790 count++;
6791 attr = attr->next;
6792 }
6793 return NULL;
6794 }
6795
6796 RL2_DECLARE gaiaGeomCollPtr
get_wms_feature_attribute_geometry(rl2WmsFeatureMemberPtr handle,int index)6797 get_wms_feature_attribute_geometry (rl2WmsFeatureMemberPtr handle, int index)
6798 {
6799 /* attempting to get the Nth FeatureAttribute (Geometry) from some WMS-FeatureMember object */
6800 int count = 0;
6801 wmsFeatureAttributePtr attr;
6802 wmsFeatureMemberPtr ptr = (wmsFeatureMemberPtr) handle;
6803 if (ptr == NULL)
6804 return NULL;
6805
6806 attr = ptr->first;
6807 while (attr != NULL)
6808 {
6809 if (count == index)
6810 return attr->geometry;
6811 count++;
6812 attr = attr->next;
6813 }
6814 return NULL;
6815 }
6816
6817 RL2_DECLARE const char *
get_wms_feature_attribute_value(rl2WmsFeatureMemberPtr handle,int index)6818 get_wms_feature_attribute_value (rl2WmsFeatureMemberPtr handle, int index)
6819 {
6820 /* attempting to get the Nth FeatureAttribute (Value) from some WMS-FeatureMember object */
6821 int count = 0;
6822 wmsFeatureAttributePtr attr;
6823 wmsFeatureMemberPtr ptr = (wmsFeatureMemberPtr) handle;
6824 if (ptr == NULL)
6825 return NULL;
6826
6827 attr = ptr->first;
6828 while (attr != NULL)
6829 {
6830 if (count == index)
6831 return attr->value;
6832 count++;
6833 attr = attr->next;
6834 }
6835 return NULL;
6836 }
6837
6838 static int
check_marker(const char * url)6839 check_marker (const char *url)
6840 {
6841 /* testing if some "?" marker is already defined */
6842 int i;
6843 int force_marker = 1;
6844 for (i = 0; i < (int) strlen (url); i++)
6845 {
6846 if (*(url + i) == '?')
6847 force_marker = 0;
6848 }
6849 return force_marker;
6850 }
6851
6852 RL2_DECLARE unsigned char *
do_wms_GetMap_get(rl2WmsCachePtr cache_handle,const char * url,const char * proxy,const char * version,const char * layer,const char * crs,int swap_xy,double minx,double miny,double maxx,double maxy,int width,int height,const char * style,const char * format,int opaque,int from_cache,char ** err_msg)6853 do_wms_GetMap_get (rl2WmsCachePtr cache_handle, const char *url,
6854 const char *proxy, const char *version, const char *layer,
6855 const char *crs, int swap_xy, double minx, double miny,
6856 double maxx, double maxy, int width, int height,
6857 const char *style, const char *format, int opaque,
6858 int from_cache, char **err_msg)
6859 {
6860 /* attempting to execute a WMS GepMap request [method GET] */
6861 CURL *curl = NULL;
6862 CURLcode res;
6863 wmsMemBuffer headerBuf;
6864 wmsMemBuffer bodyBuf;
6865 int http_status;
6866 char *http_code;
6867 char *request;
6868 char *image_format;
6869 unsigned char *rgba = NULL;
6870 int force_marker = check_marker (url);
6871 const char *crs_prefix = "CRS";
6872 rl2RasterPtr raster = NULL;
6873 wmsCachePtr cache = (wmsCachePtr) cache_handle;
6874
6875 *err_msg = NULL;
6876 if (from_cache && cache == NULL)
6877 return NULL;
6878
6879 /* masking NULL arguments */
6880 if (url == NULL)
6881 url = "";
6882 if (version == NULL)
6883 version = "";
6884 if (layer == NULL)
6885 layer = "";
6886 if (crs == NULL)
6887 crs = "";
6888 if (style == NULL)
6889 style = "";
6890 if (format == NULL)
6891 format = "";
6892
6893 /* preparing the request URL */
6894 if (strcmp (version, "1.3.0") < 0)
6895 {
6896 /* earlier versions of the protocol require SRS instead of CRS */
6897 crs_prefix = "SRS";
6898 }
6899 if (force_marker)
6900 {
6901 /* "?" marker not declared */
6902 if (swap_xy)
6903 request =
6904 sqlite3_mprintf ("%s?SERVICE=WMS&REQUEST=GetMap&VERSION=%s"
6905 "&LAYERS=%s&%s=%s&BBOX=%1.6f,%1.6f,%1.6f,%1.6f"
6906 "&WIDTH=%d&HEIGHT=%d&STYLES=%s&FORMAT=%s"
6907 "&TRANSPARENT=%s&BGCOLOR=0xFFFFFF", url,
6908 version, layer, crs_prefix, crs, miny, minx,
6909 maxy, maxx, width, height, style, format,
6910 (opaque == 0) ? "TRUE" : "FALSE");
6911 else
6912 request =
6913 sqlite3_mprintf ("%s?SERVICE=WMS&REQUEST=GetMap&VERSION=%s"
6914 "&LAYERS=%s&%s=%s&BBOX=%1.6f,%1.6f,%1.6f,%1.6f"
6915 "&WIDTH=%d&HEIGHT=%d&STYLES=%s&FORMAT=%s"
6916 "&TRANSPARENT=%s&BGCOLOR=0xFFFFFF", url,
6917 version, layer, crs_prefix, crs, minx, miny,
6918 maxx, maxy, width, height, style, format,
6919 (opaque == 0) ? "TRUE" : "FALSE");
6920 }
6921 else
6922 {
6923 /* "?" marker already defined */
6924 if (swap_xy)
6925 request =
6926 sqlite3_mprintf ("%sSERVICE=WMS&REQUEST=GetMap&VERSION=%s"
6927 "&LAYERS=%s&%s=%s&BBOX=%1.6f,%1.6f,%1.6f,%1.6f"
6928 "&WIDTH=%d&HEIGHT=%d&STYLES=%s&FORMAT=%s"
6929 "&TRANSPARENT=%s&BGCOLOR=0xFFFFFF", url,
6930 version, layer, crs_prefix, crs, miny, minx,
6931 maxy, maxx, width, height, style, format,
6932 (opaque == 0) ? "TRUE" : "FALSE");
6933 else
6934 request =
6935 sqlite3_mprintf ("%sSERVICE=WMS&REQUEST=GetMap&VERSION=%s"
6936 "&LAYERS=%s&%s=%s&BBOX=%1.6f,%1.6f,%1.6f,%1.6f"
6937 "&WIDTH=%d&HEIGHT=%d&STYLES=%s&FORMAT=%s"
6938 "&TRANSPARENT=%s&BGCOLOR=0xFFFFFF", url,
6939 version, layer, crs_prefix, crs, minx, miny,
6940 maxx, maxy, width, height, style, format,
6941 (opaque == 0) ? "TRUE" : "FALSE");
6942 }
6943
6944 if (cache != NULL)
6945 {
6946 /* checks if it's already stored into the WMS Cache */
6947 wmsCachedItemPtr cachedItem = getWmsCachedItem (cache, request);
6948 if (cachedItem != NULL)
6949 {
6950 /* ok, found from WMS Cache */
6951 time_t xtime;
6952 time (&xtime);
6953 cachedItem->Time = xtime;
6954 /* attempting to decode an RGBA image */
6955 if (cachedItem->ImageFormat == WMS_FORMAT_GIF)
6956 raster =
6957 rl2_raster_from_gif (cachedItem->Item,
6958 cachedItem->Size);
6959 if (cachedItem->ImageFormat == WMS_FORMAT_PNG)
6960 raster =
6961 rl2_raster_from_png (cachedItem->Item,
6962 cachedItem->Size);
6963 if (cachedItem->ImageFormat == WMS_FORMAT_JPEG)
6964 raster =
6965 rl2_raster_from_jpeg (cachedItem->Item,
6966 cachedItem->Size);
6967 if (cachedItem->ImageFormat == WMS_FORMAT_TIFF)
6968 raster =
6969 rl2_raster_from_tiff (cachedItem->Item,
6970 cachedItem->Size);
6971 goto image_ready;
6972 }
6973 }
6974 if (from_cache)
6975 {
6976 sqlite3_free (request);
6977 return NULL;
6978 }
6979
6980 curl = curl_easy_init ();
6981 if (curl)
6982 {
6983 /* setting the URL */
6984 curl_easy_setopt (curl, CURLOPT_URL, request);
6985
6986 if (proxy != NULL)
6987 {
6988 /* setting up the required proxy */
6989 curl_easy_setopt (curl, CURLOPT_PROXY, proxy);
6990 }
6991
6992 /* no progress meter please */
6993 curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 1L);
6994 /* setting the output callback function */
6995 curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, store_data);
6996
6997 /* initializes the dynamically growing buffers */
6998 wmsMemBufferInitialize (&headerBuf);
6999 wmsMemBufferInitialize (&bodyBuf);
7000 curl_easy_setopt (curl, CURLOPT_WRITEHEADER, &headerBuf);
7001 curl_easy_setopt (curl, CURLOPT_WRITEDATA, &bodyBuf);
7002
7003 /* Perform the request, res will get the return code */
7004 res = curl_easy_perform (curl);
7005 /* Check for errors */
7006 if (res != CURLE_OK)
7007 {
7008 fprintf (stderr, "CURL error: %s\n", curl_easy_strerror (res));
7009 goto stop;
7010 }
7011
7012 /* verifying the HTTP status code */
7013 check_http_header (&headerBuf, &http_status, &http_code);
7014 if (http_status == 302)
7015 {
7016 while (1)
7017 {
7018 /* following a redirect */
7019 char *redir = parse_http_redirect (&headerBuf);
7020 if (redir == NULL)
7021 break;
7022 /* resetting all buffers */
7023 if (http_code != NULL)
7024 free (http_code);
7025 wmsMemBufferReset (&headerBuf);
7026 wmsMemBufferReset (&bodyBuf);
7027 curl_easy_setopt (curl, CURLOPT_URL, redir);
7028 if (proxy != NULL)
7029 curl_easy_setopt (curl, CURLOPT_PROXY, proxy);
7030 res = curl_easy_perform (curl);
7031 if (res != CURLE_OK)
7032 {
7033 fprintf (stderr, "CURL error: %s\n",
7034 curl_easy_strerror (res));
7035 goto stop;
7036 }
7037 free (redir);
7038 check_http_header (&headerBuf, &http_status, &http_code);
7039 if (http_status == 302)
7040 continue;
7041 break;
7042 }
7043
7044 }
7045 if (http_status != 200)
7046 {
7047 fprintf (stderr, "Invalid HTTP status code: %d %s\n",
7048 http_status, http_code);
7049 if (http_code != NULL)
7050 free (http_code);
7051 goto stop;
7052 }
7053 if (http_code != NULL)
7054 free (http_code);
7055
7056 /* attempting to decode an RGBA image */
7057 image_format = parse_http_format (&headerBuf);
7058 if (strcmp (image_format, "image/gif") == 0)
7059 raster =
7060 rl2_raster_from_gif (bodyBuf.Buffer, bodyBuf.WriteOffset);
7061 if (strcmp (image_format, "image/png") == 0)
7062 raster =
7063 rl2_raster_from_png (bodyBuf.Buffer, bodyBuf.WriteOffset);
7064 if (strcmp (image_format, "image/jpeg") == 0)
7065 raster =
7066 rl2_raster_from_jpeg (bodyBuf.Buffer, bodyBuf.WriteOffset);
7067 if (strcmp (image_format, "image/tiff") == 0)
7068 raster =
7069 rl2_raster_from_tiff (bodyBuf.Buffer, bodyBuf.WriteOffset);
7070
7071 if (raster != NULL)
7072 {
7073 /* saving into the WMS Cache */
7074 wmsAddCachedItem (cache, request, bodyBuf.Buffer,
7075 bodyBuf.WriteOffset, image_format);
7076 }
7077
7078 if (image_format != NULL)
7079 free (image_format);
7080
7081 stop:
7082 wmsMemBufferReset (&headerBuf);
7083 wmsMemBufferReset (&bodyBuf);
7084 curl_easy_cleanup (curl);
7085 }
7086
7087 image_ready:
7088 sqlite3_free (request);
7089
7090 if (raster != NULL)
7091 {
7092 /* exporting the image into an RGBA pix-buffer */
7093 int size;
7094 int ret = rl2_raster_data_to_RGBA (raster, &rgba, &size);
7095 rl2_destroy_raster (raster);
7096 if (ret == RL2_OK && rgba != NULL && size == (width * height * 4))
7097 return rgba;
7098 if (rgba != NULL)
7099 free (rgba);
7100 rgba = NULL;
7101 }
7102 return rgba;
7103 }
7104
7105 RL2_DECLARE unsigned char *
do_wms_GetMap_post(rl2WmsCachePtr cache_handle,const char * url,const char * proxy,const char * version,const char * layer,const char * crs,int swap_xy,double minx,double miny,double maxx,double maxy,int width,int height,const char * style,const char * format,int opaque,int from_cache,char ** err_msg)7106 do_wms_GetMap_post (rl2WmsCachePtr cache_handle, const char *url,
7107 const char *proxy, const char *version, const char *layer,
7108 const char *crs, int swap_xy, double minx, double miny,
7109 double maxx, double maxy, int width, int height,
7110 const char *style, const char *format, int opaque,
7111 int from_cache, char **err_msg)
7112 {
7113 /* attempting to execute a WMS GepMap request [method POST] */
7114
7115 /* not yet implemented: just a stupid placeholder always returning NULL */
7116 if (cache_handle == NULL || url == NULL || proxy == NULL || version == NULL
7117 || layer == NULL || crs == NULL)
7118 return NULL;
7119 if (minx == miny || maxx == maxy || width == height || opaque == from_cache
7120 || width == swap_xy)
7121 return NULL;
7122 if (style == NULL || format == NULL || err_msg == NULL)
7123 return NULL;
7124 return NULL;
7125 }
7126
7127 RL2_DECLARE unsigned char *
do_wms_GetMap_TileService_get(rl2WmsCachePtr cache_handle,const char * url,const char * proxy,int width,int height,int from_cache,char ** err_msg)7128 do_wms_GetMap_TileService_get (rl2WmsCachePtr cache_handle, const char *url,
7129 const char *proxy, int width, int height,
7130 int from_cache, char **err_msg)
7131 {
7132 /* attempting to execute a WMS GepMap TileService request [method GET] */
7133 CURL *curl = NULL;
7134 CURLcode res;
7135 wmsMemBuffer headerBuf;
7136 wmsMemBuffer bodyBuf;
7137 int http_status;
7138 char *http_code;
7139 char *image_format;
7140 unsigned char *rgba = NULL;
7141 rl2RasterPtr raster = NULL;
7142 wmsCachePtr cache = (wmsCachePtr) cache_handle;
7143
7144 *err_msg = NULL;
7145 if (from_cache && cache == NULL)
7146 return NULL;
7147
7148 /* masking NULL arguments */
7149 if (url == NULL)
7150 url = "";
7151
7152 if (cache != NULL)
7153 {
7154 /* checks if it's already stored into the WMS Cache */
7155 wmsCachedItemPtr cachedItem = getWmsCachedItem (cache, url);
7156 if (cachedItem != NULL)
7157 {
7158 /* ok, found from WMS Cache */
7159 time_t xtime;
7160 time (&xtime);
7161 cachedItem->Time = xtime;
7162 /* attempting to decode an RGBA image */
7163 if (cachedItem->ImageFormat == WMS_FORMAT_GIF)
7164 raster =
7165 rl2_raster_from_gif (cachedItem->Item,
7166 cachedItem->Size);
7167 if (cachedItem->ImageFormat == WMS_FORMAT_PNG)
7168 raster =
7169 rl2_raster_from_png (cachedItem->Item,
7170 cachedItem->Size);
7171 if (cachedItem->ImageFormat == WMS_FORMAT_JPEG)
7172 raster =
7173 rl2_raster_from_jpeg (cachedItem->Item,
7174 cachedItem->Size);
7175 if (cachedItem->ImageFormat == WMS_FORMAT_TIFF)
7176 raster =
7177 rl2_raster_from_tiff (cachedItem->Item,
7178 cachedItem->Size);
7179 goto image_ready;
7180 }
7181 }
7182 if (from_cache)
7183 return NULL;
7184
7185 curl = curl_easy_init ();
7186 if (curl)
7187 {
7188 /* setting the URL */
7189 curl_easy_setopt (curl, CURLOPT_URL, url);
7190
7191 if (proxy != NULL)
7192 {
7193 /* setting up the required proxy */
7194 curl_easy_setopt (curl, CURLOPT_PROXY, proxy);
7195 }
7196
7197 /* no progress meter please */
7198 curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 1L);
7199 /* setting the output callback function */
7200 curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, store_data);
7201
7202 /* initializes the dynamically growing buffers */
7203 wmsMemBufferInitialize (&headerBuf);
7204 wmsMemBufferInitialize (&bodyBuf);
7205 curl_easy_setopt (curl, CURLOPT_WRITEHEADER, &headerBuf);
7206 curl_easy_setopt (curl, CURLOPT_WRITEDATA, &bodyBuf);
7207
7208 /* Perform the request, res will get the return code */
7209 res = curl_easy_perform (curl);
7210 /* Check for errors */
7211 if (res != CURLE_OK)
7212 {
7213 fprintf (stderr, "CURL error: %s\n", curl_easy_strerror (res));
7214 goto stop;
7215 }
7216
7217 /* verifying the HTTP status code */
7218 check_http_header (&headerBuf, &http_status, &http_code);
7219 if (http_status == 302)
7220 {
7221 while (1)
7222 {
7223 /* following a redirect */
7224 char *redir = parse_http_redirect (&headerBuf);
7225 if (redir == NULL)
7226 break;
7227 /* resetting all buffers */
7228 if (http_code != NULL)
7229 free (http_code);
7230 wmsMemBufferReset (&headerBuf);
7231 wmsMemBufferReset (&bodyBuf);
7232 curl_easy_setopt (curl, CURLOPT_URL, redir);
7233 if (proxy != NULL)
7234 curl_easy_setopt (curl, CURLOPT_PROXY, proxy);
7235 res = curl_easy_perform (curl);
7236 if (res != CURLE_OK)
7237 {
7238 fprintf (stderr, "CURL error: %s\n",
7239 curl_easy_strerror (res));
7240 goto stop;
7241 }
7242 free (redir);
7243 check_http_header (&headerBuf, &http_status, &http_code);
7244 if (http_status == 302)
7245 continue;
7246 break;
7247 }
7248
7249 }
7250 if (http_status != 200)
7251 {
7252 fprintf (stderr, "Invalid HTTP status code: %d %s\n",
7253 http_status, http_code);
7254 if (http_code != NULL)
7255 free (http_code);
7256 goto stop;
7257 }
7258 if (http_code != NULL)
7259 free (http_code);
7260
7261 /* attempting to decode an RGBA image */
7262 image_format = parse_http_format (&headerBuf);
7263 if (strcmp (image_format, "image/gif") == 0)
7264 raster =
7265 rl2_raster_from_gif (bodyBuf.Buffer, bodyBuf.WriteOffset);
7266 if (strcmp (image_format, "image/png") == 0)
7267 raster =
7268 rl2_raster_from_png (bodyBuf.Buffer, bodyBuf.WriteOffset);
7269 if (strcmp (image_format, "image/jpeg") == 0)
7270 raster =
7271 rl2_raster_from_jpeg (bodyBuf.Buffer, bodyBuf.WriteOffset);
7272 if (strcmp (image_format, "image/tiff") == 0)
7273 raster =
7274 rl2_raster_from_tiff (bodyBuf.Buffer, bodyBuf.WriteOffset);
7275
7276 if (raster != NULL)
7277 {
7278 /* saving into the WMS Cache */
7279 wmsAddCachedItem (cache, url, bodyBuf.Buffer,
7280 bodyBuf.WriteOffset, image_format);
7281 }
7282
7283 if (image_format != NULL)
7284 free (image_format);
7285
7286 stop:
7287 wmsMemBufferReset (&headerBuf);
7288 wmsMemBufferReset (&bodyBuf);
7289 curl_easy_cleanup (curl);
7290 }
7291
7292 image_ready:
7293
7294 if (raster != NULL)
7295 {
7296 /* exporting the image into an RGBA pix-buffer */
7297 int size;
7298 int ret = rl2_raster_data_to_RGBA (raster, &rgba, &size);
7299 rl2_destroy_raster (raster);
7300 if (ret == RL2_OK && rgba != NULL && size == (width * height * 4))
7301 return rgba;
7302 if (rgba != NULL)
7303 free (rgba);
7304 rgba = NULL;
7305 }
7306 return rgba;
7307 }
7308
7309 RL2_DECLARE unsigned char *
do_wms_GetMap_TileService_post(rl2WmsCachePtr cache_handle,const char * url,const char * proxy,int width,int height,int from_cache,char ** err_msg)7310 do_wms_GetMap_TileService_post (rl2WmsCachePtr cache_handle, const char *url,
7311 const char *proxy, int width, int height,
7312 int from_cache, char **err_msg)
7313 {
7314 /* attempting to execute a WMS GepMap TileService request [method POST] */
7315
7316 /* not yet implemented: just a stupid placeholder always returning NULL */
7317 if (cache_handle == NULL || url == NULL || proxy == NULL || err_msg == NULL)
7318 return NULL;
7319 if (width == height || width == from_cache)
7320 return NULL;
7321 return NULL;
7322 }
7323
7324 RL2_DECLARE rl2WmsFeatureCollectionPtr
do_wms_GetFeatureInfo_get(const char * url,const char * proxy,const char * version,const char * format,const char * layer,const char * crs,int swap_xy,double minx,double miny,double maxx,double maxy,int width,int height,int mouse_x,int mouse_y,char ** err_msg)7325 do_wms_GetFeatureInfo_get (const char *url, const char *proxy,
7326 const char *version, const char *format,
7327 const char *layer, const char *crs, int swap_xy,
7328 double minx, double miny, double maxx, double maxy,
7329 int width, int height, int mouse_x, int mouse_y,
7330 char **err_msg)
7331 {
7332 /* attempting to execute a WMS GepFeatureInfo request [method GET] */
7333 CURL *curl = NULL;
7334 CURLcode res;
7335 wmsMemBuffer headerBuf;
7336 wmsMemBuffer bodyBuf;
7337 wmsFeatureCollectionPtr coll = NULL;
7338 int http_status;
7339 char *http_code;
7340 char *request;
7341 char *multipart_boundary;
7342 const char *crs_prefix = "CRS";
7343 char *xml_buf;
7344 int force_marker = check_marker (url);
7345
7346 *err_msg = NULL;
7347
7348 /* masking NULL arguments */
7349 if (url == NULL)
7350 url = "";
7351 if (version == NULL)
7352 version = "";
7353 if (format == NULL)
7354 format = "";
7355 if (layer == NULL)
7356 layer = "";
7357 if (crs == NULL)
7358 crs = "";
7359
7360 /* preparing the request URL */
7361 if (strcmp (version, "1.3.0") < 0)
7362 {
7363 /* earlier versions of the protocol require SRS instead of CRS */
7364 crs_prefix = "SRS";
7365 }
7366 if (force_marker)
7367 {
7368 if (swap_xy)
7369 request =
7370 sqlite3_mprintf
7371 ("%s?SERVICE=WMS&REQUEST=GetFeatureInfo&VERSION=%s&LAYERS=%s"
7372 "&QUERY_LAYERS=%s&%s=%s&BBOX=%1.6f,%1.6f,%1.6f,%1.6f"
7373 "&WIDTH=%d&HEIGHT=%d&X=%d&Y=%d&INFO_FORMAT=%s"
7374 "&FEATURE_COUNT=50", url, version, layer, layer, crs_prefix,
7375 crs, miny, minx, maxy, maxx, width, height, mouse_x,
7376 mouse_y, format);
7377 else
7378 request =
7379 sqlite3_mprintf
7380 ("%s?SERVICE=WMS&REQUEST=GetFeatureInfo&VERSION=%s&LAYERS=%s"
7381 "&QUERY_LAYERS=%s&%s=%s&BBOX=%1.6f,%1.6f,%1.6f,%1.6f"
7382 "&WIDTH=%d&HEIGHT=%d&X=%d&Y=%d&INFO_FORMAT=%s"
7383 "&FEATURE_COUNT=50", url, version, layer, layer, crs_prefix,
7384 crs, minx, miny, maxx, maxy, width, height, mouse_x,
7385 mouse_y, format);
7386 }
7387 else
7388 {
7389 if (swap_xy)
7390 request =
7391 sqlite3_mprintf
7392 ("%sSERVICE=WMS&REQUEST=GetFeatureInfo&VERSION=%s&LAYERS=%s"
7393 "&QUERY_LAYERS=%s&%s=%s&BBOX=%1.6f,%1.6f,%1.6f,%1.6f"
7394 "&WIDTH=%d&HEIGHT=%d&X=%d&Y=%d&INFO_FORMAT=%s"
7395 "&FEATURE_COUNT=50", url, version, layer, layer, crs_prefix,
7396 crs, miny, minx, maxy, maxx, width, height, mouse_x,
7397 mouse_y, format);
7398 else
7399 request =
7400 sqlite3_mprintf
7401 ("%sSERVICE=WMS&REQUEST=GetFeatureInfo&VERSION=%s&LAYERS=%s"
7402 "&QUERY_LAYERS=%s&%s=%s&BBOX=%1.6f,%1.6f,%1.6f,%1.6f"
7403 "&WIDTH=%d&HEIGHT=%d&X=%d&Y=%d&INFO_FORMAT=%s"
7404 "&FEATURE_COUNT=50", url, version, layer, layer, crs_prefix,
7405 crs, minx, miny, maxx, maxy, width, height, mouse_x,
7406 mouse_y, format);
7407 }
7408
7409 curl = curl_easy_init ();
7410 if (curl)
7411 {
7412 /* setting the URL */
7413 curl_easy_setopt (curl, CURLOPT_URL, request);
7414
7415 if (proxy != NULL)
7416 {
7417 /* setting up the required proxy */
7418 curl_easy_setopt (curl, CURLOPT_PROXY, proxy);
7419 }
7420
7421 /* no progress meter please */
7422 curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 1L);
7423 /* setting the output callback function */
7424 curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, store_data);
7425
7426 /* initializes the dynamically growing buffers */
7427 wmsMemBufferInitialize (&headerBuf);
7428 wmsMemBufferInitialize (&bodyBuf);
7429 curl_easy_setopt (curl, CURLOPT_WRITEHEADER, &headerBuf);
7430 curl_easy_setopt (curl, CURLOPT_WRITEDATA, &bodyBuf);
7431
7432 /* Perform the request, res will get the return code */
7433 res = curl_easy_perform (curl);
7434 /* Check for errors */
7435 if (res != CURLE_OK)
7436 {
7437 fprintf (stderr, "CURL error: %s\n", curl_easy_strerror (res));
7438 goto stop;
7439 }
7440
7441 /* verifying the HTTP status code */
7442 check_http_header (&headerBuf, &http_status, &http_code);
7443 if (http_status == 302)
7444 {
7445 while (1)
7446 {
7447 /* following a redirect */
7448 char *redir = parse_http_redirect (&headerBuf);
7449 if (redir == NULL)
7450 break;
7451 /* resetting all buffers */
7452 if (http_code != NULL)
7453 free (http_code);
7454 wmsMemBufferReset (&headerBuf);
7455 wmsMemBufferReset (&bodyBuf);
7456 curl_easy_setopt (curl, CURLOPT_URL, redir);
7457 if (proxy != NULL)
7458 curl_easy_setopt (curl, CURLOPT_PROXY, proxy);
7459 res = curl_easy_perform (curl);
7460 if (res != CURLE_OK)
7461 {
7462 fprintf (stderr, "CURL error: %s\n",
7463 curl_easy_strerror (res));
7464 goto stop;
7465 }
7466 free (redir);
7467 check_http_header (&headerBuf, &http_status, &http_code);
7468 if (http_status == 302)
7469 continue;
7470 break;
7471 }
7472
7473 }
7474 if (http_status != 200)
7475 {
7476 fprintf (stderr, "Invalid HTTP status code: %d %s\n",
7477 http_status, http_code);
7478 if (http_code != NULL)
7479 free (http_code);
7480 goto stop;
7481 }
7482 if (http_code != NULL)
7483 free (http_code);
7484
7485 multipart_boundary = check_http_multipart_response (&headerBuf);
7486 if (multipart_boundary != NULL)
7487 {
7488 wmsMultipartCollectionPtr multi =
7489 parse_multipart_body (&bodyBuf, multipart_boundary);
7490 free (multipart_boundary);
7491 if (multi != NULL)
7492 {
7493 wmsSinglePartResponsePtr single = multi->first;
7494 while (single != NULL)
7495 {
7496 xml_buf = clean_xml_str (single->body);
7497 if (xml_buf != NULL)
7498 {
7499 coll = parse_wms_feature_collection (xml_buf);
7500 free (xml_buf);
7501 }
7502 if (coll != NULL)
7503 {
7504 wmsFreeMultipartCollection (multi);
7505 goto stop;
7506 }
7507 single = single->next;
7508 }
7509 wmsFreeMultipartCollection (multi);
7510 }
7511 }
7512 else
7513 {
7514 xml_buf = clean_xml (&bodyBuf);
7515 if (xml_buf != NULL)
7516 {
7517 coll = parse_wms_feature_collection (xml_buf);
7518 free (xml_buf);
7519 }
7520 }
7521
7522 stop:
7523 wmsMemBufferReset (&headerBuf);
7524 wmsMemBufferReset (&bodyBuf);
7525 curl_easy_cleanup (curl);
7526 }
7527
7528 sqlite3_free (request);
7529 if (coll != NULL)
7530 {
7531 if (coll->first == NULL)
7532 {
7533 wmsFreeFeatureCollection (coll);
7534 coll = NULL;
7535 }
7536 }
7537 return (rl2WmsFeatureCollectionPtr) coll;
7538 }
7539
7540 RL2_DECLARE rl2WmsFeatureCollectionPtr
do_wms_GetFeatureInfo_post(const char * url,const char * proxy,const char * version,const char * format,const char * layer,const char * crs,int swap_xy,double minx,double miny,double maxx,double maxy,int width,int height,int mouse_x,int mouse_y,char ** err_msg)7541 do_wms_GetFeatureInfo_post (const char *url, const char *proxy,
7542 const char *version, const char *format,
7543 const char *layer, const char *crs, int swap_xy,
7544 double minx, double miny, double maxx, double maxy,
7545 int width, int height, int mouse_x, int mouse_y,
7546 char **err_msg)
7547 {
7548 /* attempting to execute a WMS GepFeatureInfo request [method POST] */
7549
7550 /* not yet implemented: just a stupid placeholder always returning NULL */
7551 if (url == NULL || proxy == NULL || version == NULL || format == NULL
7552 || layer == NULL || crs == NULL)
7553 return NULL;
7554 if (minx == miny || maxx == maxy || width == height || mouse_x == mouse_y
7555 || swap_xy == mouse_x)
7556 return NULL;
7557 if (err_msg == NULL)
7558 return NULL;
7559 return NULL;
7560 }
7561