1 /**********************************************************************
2 * $Id$
3 *
4 * Project: MapServer
5 * Purpose: OGC Web Map Context implementation
6 * Author: Julien-Samuel Lacroix, DM Solutions Group (lacroix@dmsolutions.ca)
7 *
8 **********************************************************************
9 * Copyright (c) 2002-2003, Julien-Samuel Lacroix, DM Solutions Group Inc
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies of this Software or works derived from this Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 ****************************************************************************/
28
29 #include "mapserver.h"
30 #include "mapows.h"
31
32 #include "cpl_vsi.h"
33
34
35 #if defined(USE_WMS_LYR)
36
37 /* There is a dependency to GDAL/OGR for the GML driver and MiniXML parser */
38 #include "cpl_minixml.h"
39
40 #endif
41
42 /* msGetMapContextFileText()
43 **
44 ** Read a file and return is content
45 **
46 ** Take the filename in argument
47 ** Return value must be freed by caller
48 */
msGetMapContextFileText(char * filename)49 char * msGetMapContextFileText(char *filename)
50 {
51 char *pszBuffer;
52 VSILFILE *stream;
53 int nLength;
54
55 /* open file */
56 if(filename != NULL && strlen(filename) > 0) {
57 stream = VSIFOpenL(filename, "rb");
58 if(!stream) {
59 msSetError(MS_IOERR, "(%s)", "msGetMapContextFileText()", filename);
60 return NULL;
61 }
62 } else {
63 msSetError(MS_IOERR, "(%s)", "msGetMapContextFileText()", filename);
64 return NULL;
65 }
66
67 VSIFSeekL( stream, 0, SEEK_END );
68 nLength = (int) VSIFTellL( stream );
69 VSIFSeekL( stream, 0, SEEK_SET );
70
71 pszBuffer = (char *) malloc(nLength+1);
72 if( pszBuffer == NULL ) {
73 msSetError(MS_MEMERR, "(%s)", "msGetMapContextFileText()", filename);
74 VSIFCloseL( stream );
75 return NULL;
76 }
77
78 if(VSIFReadL( pszBuffer, nLength, 1, stream ) == 0) {
79 free( pszBuffer );
80 VSIFCloseL( stream );
81 msSetError(MS_IOERR, "(%s)", "msGetMapContextFileText()", filename);
82 return NULL;
83 }
84 pszBuffer[nLength] = '\0';
85
86 VSIFCloseL( stream );
87
88 return pszBuffer;
89 }
90
91
92 #if defined(USE_WMS_LYR)
93
94 /*
95 **msGetMapContextXMLHashValue()
96 **
97 **Get the xml value and put it in the hash table
98 **
99 */
msGetMapContextXMLHashValue(CPLXMLNode * psRoot,const char * pszXMLPath,hashTableObj * metadata,char * pszMetadata)100 int msGetMapContextXMLHashValue( CPLXMLNode *psRoot, const char *pszXMLPath,
101 hashTableObj *metadata, char *pszMetadata )
102 {
103 char *pszValue;
104
105 pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL);
106 if(pszValue != NULL) {
107 if( metadata != NULL ) {
108 msInsertHashTable(metadata, pszMetadata, pszValue );
109 } else {
110 return MS_FAILURE;
111 }
112 } else {
113 return MS_FAILURE;
114 }
115
116 return MS_SUCCESS;
117 }
118
119 /*
120 **msGetMapContextXMLHashValue()
121 **
122 **Get the xml value and put it in the hash table
123 **
124 */
msGetMapContextXMLHashValueDecode(CPLXMLNode * psRoot,const char * pszXMLPath,hashTableObj * metadata,char * pszMetadata)125 int msGetMapContextXMLHashValueDecode( CPLXMLNode *psRoot,
126 const char *pszXMLPath,
127 hashTableObj *metadata,
128 char *pszMetadata )
129 {
130 char *pszValue;
131
132 pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL);
133 if(pszValue != NULL) {
134 if( metadata != NULL ) {
135 msDecodeHTMLEntities(pszValue);
136 msInsertHashTable(metadata, pszMetadata, pszValue );
137 } else {
138 return MS_FAILURE;
139 }
140 } else {
141 return MS_FAILURE;
142 }
143
144 return MS_SUCCESS;
145 }
146
147
148 /*
149 **msGetMapContextXMLStringValue()
150 **
151 **Get the xml value and put it in the string field
152 **
153 */
msGetMapContextXMLStringValue(CPLXMLNode * psRoot,char * pszXMLPath,char ** pszField)154 int msGetMapContextXMLStringValue( CPLXMLNode *psRoot, char *pszXMLPath,
155 char **pszField)
156 {
157 char *pszValue;
158
159 pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL);
160 if(pszValue != NULL) {
161 if( pszField != NULL ) {
162 *pszField = msStrdup(pszValue);
163 } else {
164 return MS_FAILURE;
165 }
166 } else {
167 return MS_FAILURE;
168 }
169
170 return MS_SUCCESS;
171 }
172
173
174 /*
175 **msGetMapContextXMLStringValue()
176 **
177 **Get the xml value and put it in the string field
178 **
179 */
msGetMapContextXMLStringValueDecode(CPLXMLNode * psRoot,char * pszXMLPath,char ** pszField)180 int msGetMapContextXMLStringValueDecode( CPLXMLNode *psRoot, char *pszXMLPath,
181 char **pszField)
182 {
183 char *pszValue;
184
185 pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL);
186 if(pszValue != NULL) {
187 if( pszField != NULL ) {
188 msDecodeHTMLEntities(pszValue);
189 *pszField = msStrdup(pszValue);
190 } else {
191 return MS_FAILURE;
192 }
193 } else {
194 return MS_FAILURE;
195 }
196
197 return MS_SUCCESS;
198 }
199
200
201 /*
202 **msGetMapContextXMLFloatValue()
203 **
204 **Get the xml value and put it in the string field
205 **
206 */
msGetMapContextXMLFloatValue(CPLXMLNode * psRoot,char * pszXMLPath,double * pszField)207 int msGetMapContextXMLFloatValue( CPLXMLNode *psRoot, char *pszXMLPath,
208 double *pszField)
209 {
210 char *pszValue;
211
212 pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL);
213 if(pszValue != NULL) {
214 if( pszField != NULL ) {
215 *pszField = atof(pszValue);
216 } else {
217 return MS_FAILURE;
218 }
219 } else {
220 return MS_FAILURE;
221 }
222
223 return MS_SUCCESS;
224 }
225
226 /*
227 ** msLoadMapContextURLELements
228 **
229 ** Take a Node and get the width, height, format and href from it.
230 ** Then put this info in metadatas.
231 */
msLoadMapContextURLELements(CPLXMLNode * psRoot,hashTableObj * metadata,const char * pszMetadataRoot)232 int msLoadMapContextURLELements( CPLXMLNode *psRoot, hashTableObj *metadata,
233 const char *pszMetadataRoot)
234 {
235 char *pszMetadataName;
236
237 if( psRoot == NULL || metadata == NULL || pszMetadataRoot == NULL )
238 return MS_FAILURE;
239
240 pszMetadataName = (char*) malloc( strlen(pszMetadataRoot) + 10 );
241
242 sprintf( pszMetadataName, "%s_width", pszMetadataRoot );
243 msGetMapContextXMLHashValue( psRoot, "width", metadata, pszMetadataName );
244
245 sprintf( pszMetadataName, "%s_height", pszMetadataRoot );
246 msGetMapContextXMLHashValue( psRoot, "height", metadata, pszMetadataName );
247
248 sprintf( pszMetadataName, "%s_format", pszMetadataRoot );
249 msGetMapContextXMLHashValue( psRoot, "format", metadata, pszMetadataName );
250
251 sprintf( pszMetadataName, "%s_href", pszMetadataRoot );
252 msGetMapContextXMLHashValue( psRoot, "OnlineResource.xlink:href", metadata,
253 pszMetadataName );
254
255 free(pszMetadataName);
256
257 return MS_SUCCESS;
258 }
259
260 /* msLoadMapContextKeyword
261 **
262 ** Put the keywords from a XML node and put them in a metadata.
263 ** psRoot should be set to keywordlist
264 */
msLoadMapContextListInMetadata(CPLXMLNode * psRoot,hashTableObj * metadata,char * pszXMLName,char * pszMetadataName,char * pszHashDelimiter)265 int msLoadMapContextListInMetadata( CPLXMLNode *psRoot, hashTableObj *metadata,
266 char *pszXMLName, char *pszMetadataName,
267 char *pszHashDelimiter)
268 {
269 const char *pszHash, *pszXMLValue;
270 char *pszMetadata;
271
272 if(psRoot == NULL || psRoot->psChild == NULL ||
273 metadata == NULL || pszMetadataName == NULL || pszXMLName == NULL)
274 return MS_FAILURE;
275
276 /* Pass from KeywordList to Keyword level */
277 psRoot = psRoot->psChild;
278
279 /* Loop on all elements and append keywords to the hash table */
280 while (psRoot) {
281 if (psRoot->psChild && strcasecmp(psRoot->pszValue, pszXMLName) == 0) {
282 pszXMLValue = psRoot->psChild->pszValue;
283 pszHash = msLookupHashTable(metadata, pszMetadataName);
284 if (pszHash != NULL) {
285 pszMetadata = (char*)malloc(strlen(pszHash)+
286 strlen(pszXMLValue)+2);
287 if(pszHashDelimiter == NULL)
288 sprintf( pszMetadata, "%s%s", pszHash, pszXMLValue );
289 else
290 sprintf( pszMetadata, "%s%s%s", pszHash, pszHashDelimiter,
291 pszXMLValue );
292 msInsertHashTable(metadata, pszMetadataName, pszMetadata);
293 free(pszMetadata);
294 } else
295 msInsertHashTable(metadata, pszMetadataName, pszXMLValue);
296 }
297 psRoot = psRoot->psNext;
298 }
299
300 return MS_SUCCESS;
301 }
302
303 /* msLoadMapContextContactInfo
304 **
305 ** Put the Contact informations from a XML node and put them in a metadata.
306 **
307 */
msLoadMapContextContactInfo(CPLXMLNode * psRoot,hashTableObj * metadata)308 int msLoadMapContextContactInfo( CPLXMLNode *psRoot, hashTableObj *metadata )
309 {
310 if(psRoot == NULL || metadata == NULL)
311 return MS_FAILURE;
312
313 /* Contact Person primary */
314 msGetMapContextXMLHashValue(psRoot,
315 "ContactPersonPrimary.ContactPerson",
316 metadata, "wms_contactperson");
317 msGetMapContextXMLHashValue(psRoot,
318 "ContactPersonPrimary.ContactOrganization",
319 metadata, "wms_contactorganization");
320 /* Contact Position */
321 msGetMapContextXMLHashValue(psRoot,
322 "ContactPosition",
323 metadata, "wms_contactposition");
324 /* Contact Address */
325 msGetMapContextXMLHashValue(psRoot, "ContactAddress.AddressType",
326 metadata, "wms_addresstype");
327 msGetMapContextXMLHashValue(psRoot, "ContactAddress.Address",
328 metadata, "wms_address");
329 msGetMapContextXMLHashValue(psRoot, "ContactAddress.City",
330 metadata, "wms_city");
331 msGetMapContextXMLHashValue(psRoot, "ContactAddress.StateOrProvince",
332 metadata, "wms_stateorprovince");
333 msGetMapContextXMLHashValue(psRoot, "ContactAddress.PostCode",
334 metadata, "wms_postcode");
335 msGetMapContextXMLHashValue(psRoot, "ContactAddress.Country",
336 metadata, "wms_country");
337
338 /* Others */
339 msGetMapContextXMLHashValue(psRoot, "ContactVoiceTelephone",
340 metadata, "wms_contactvoicetelephone");
341 msGetMapContextXMLHashValue(psRoot, "ContactFacsimileTelephone",
342 metadata, "wms_contactfacsimiletelephone");
343 msGetMapContextXMLHashValue(psRoot, "ContactElectronicMailAddress",
344 metadata, "wms_contactelectronicmailaddress");
345
346 return MS_SUCCESS;
347 }
348
349 /*
350 ** msLoadMapContextLayerFormat
351 **
352 **
353 */
msLoadMapContextLayerFormat(CPLXMLNode * psFormat,layerObj * layer)354 int msLoadMapContextLayerFormat(CPLXMLNode *psFormat, layerObj *layer)
355 {
356 const char *pszValue;
357 char *pszValue1;
358 const char* pszHash;
359
360 if(psFormat->psChild != NULL &&
361 strcasecmp(psFormat->pszValue, "Format") == 0 ) {
362 if(psFormat->psChild->psNext == NULL)
363 pszValue = psFormat->psChild->pszValue;
364 else
365 pszValue = psFormat->psChild->psNext->pszValue;
366 } else
367 pszValue = NULL;
368
369 if(pszValue != NULL && strcasecmp(pszValue, "") != 0) {
370 /* wms_format */
371 pszValue1 = (char*)CPLGetXMLValue(psFormat,
372 "current", NULL);
373 if(pszValue1 != NULL &&
374 (strcasecmp(pszValue1, "1") == 0 || strcasecmp(pszValue1, "true")==0))
375 msInsertHashTable(&(layer->metadata),
376 "wms_format", pszValue);
377 /* wms_formatlist */
378 pszHash = msLookupHashTable(&(layer->metadata),
379 "wms_formatlist");
380 if(pszHash != NULL) {
381 pszValue1 = (char*)malloc(strlen(pszHash)+
382 strlen(pszValue)+2);
383 sprintf(pszValue1, "%s,%s", pszHash, pszValue);
384 msInsertHashTable(&(layer->metadata),
385 "wms_formatlist", pszValue1);
386 free(pszValue1);
387 } else
388 msInsertHashTable(&(layer->metadata),
389 "wms_formatlist", pszValue);
390 }
391
392 /* Make sure selected format is supported or select another
393 * supported format. Note that we can efficiently do this
394 * only for GIF/PNG/JPEG, can't try to handle all GDAL
395 * formats.
396 */
397 pszValue = msLookupHashTable(&(layer->metadata), "wms_format");
398
399 if (
400 pszValue && (
401 #if !(defined USE_PNG)
402 strcasecmp(pszValue, "image/png") == 0 ||
403 strcasecmp(pszValue, "PNG") == 0 ||
404 #endif
405 #if !(defined USE_JPEG)
406 strcasecmp(pszValue, "image/jpeg") == 0 ||
407 strcasecmp(pszValue, "JPEG") == 0 ||
408 #endif
409 0 )) {
410 char **papszList=NULL;
411 int i, numformats=0;
412
413 pszValue = msLookupHashTable(&(layer->metadata),
414 "wms_formatlist");
415
416 papszList = msStringSplit(pszValue, ',', &numformats);
417 for(i=0; i < numformats; i++) {
418 if (
419 #if (defined USE_PNG)
420 strcasecmp(papszList[i], "image/png") == 0 ||
421 strcasecmp(papszList[i], "PNG") == 0 ||
422 #endif
423 #if (defined USE_JPEG)
424 strcasecmp(papszList[i], "image/jpeg") == 0 ||
425 strcasecmp(papszList[i], "JPEG") == 0 ||
426 #endif
427 #ifdef USE_GD_GIF
428 strcasecmp(papszList[i], "image/gif") == 0 ||
429 strcasecmp(papszList[i], "GIF") == 0 ||
430 #endif
431 0 ) {
432 /* Found a match */
433 msInsertHashTable(&(layer->metadata),
434 "wms_format", papszList[i]);
435 break;
436 }
437 }
438 if(papszList)
439 msFreeCharArray(papszList, numformats);
440
441 } /* end if unsupported format */
442
443 return MS_SUCCESS;
444 }
445
msLoadMapContextLayerStyle(CPLXMLNode * psStyle,layerObj * layer,int nStyle)446 int msLoadMapContextLayerStyle(CPLXMLNode *psStyle, layerObj *layer,
447 int nStyle)
448 {
449 char *pszValue, *pszValue1, *pszValue2;
450 const char *pszHash;
451 char* pszStyle=NULL;
452 char *pszStyleName;
453 CPLXMLNode *psStyleSLDBody;
454
455 pszStyleName =(char*)CPLGetXMLValue(psStyle,"Name",NULL);
456 if(pszStyleName == NULL) {
457 pszStyleName = (char*)malloc(20);
458 sprintf(pszStyleName, "Style{%d}", nStyle);
459 } else
460 pszStyleName = msStrdup(pszStyleName);
461
462 /* wms_style */
463 pszValue = (char*)CPLGetXMLValue(psStyle,"current",NULL);
464 if(pszValue != NULL &&
465 (strcasecmp(pszValue, "1") == 0 ||
466 strcasecmp(pszValue, "true") == 0))
467 msInsertHashTable(&(layer->metadata),
468 "wms_style", pszStyleName);
469 /* wms_stylelist */
470 pszHash = msLookupHashTable(&(layer->metadata),
471 "wms_stylelist");
472 if(pszHash != NULL) {
473 pszValue1 = (char*)malloc(strlen(pszHash)+
474 strlen(pszStyleName)+2);
475 sprintf(pszValue1, "%s,%s", pszHash, pszStyleName);
476 msInsertHashTable(&(layer->metadata),
477 "wms_stylelist", pszValue1);
478 free(pszValue1);
479 } else
480 msInsertHashTable(&(layer->metadata),
481 "wms_stylelist", pszStyleName);
482
483 /* Title */
484 pszStyle = (char*)malloc(strlen(pszStyleName)+20);
485 sprintf(pszStyle,"wms_style_%s_title",pszStyleName);
486
487 if( msGetMapContextXMLHashValue(psStyle, "Title", &(layer->metadata),
488 pszStyle) == MS_FAILURE )
489 msInsertHashTable(&(layer->metadata), pszStyle, layer->name);
490
491 free(pszStyle);
492
493 /* SLD */
494 pszStyle = (char*)malloc(strlen(pszStyleName)+15);
495 sprintf(pszStyle, "wms_style_%s_sld", pszStyleName);
496
497 msGetMapContextXMLHashValueDecode( psStyle, "SLD.OnlineResource.xlink:href",
498 &(layer->metadata), pszStyle );
499 free(pszStyle);
500
501 /* SLDBODY */
502 pszStyle = (char*)malloc(strlen(pszStyleName)+20);
503 sprintf(pszStyle, "wms_style_%s_sld_body", pszStyleName);
504
505 psStyleSLDBody = CPLGetXMLNode(psStyle, "SLD.StyledLayerDescriptor");
506 /*some clients such as OpenLayers add a name space, which I believe is wrong but
507 added this additional test for compatibility #3115*/
508 if (psStyleSLDBody == NULL)
509 psStyleSLDBody = CPLGetXMLNode(psStyle, "SLD.sld:StyledLayerDescriptor");
510
511 if(psStyleSLDBody != NULL && &(layer->metadata) != NULL) {
512 pszValue = CPLSerializeXMLTree(psStyleSLDBody);
513 if(pszValue != NULL) {
514 /* Before including SLDBody in the mapfile, we must replace the */
515 /* double quote for single quote. This is to prevent having this: */
516 /* "metadata" "<string attriute="ttt">" */
517 char *c;
518 for(c=pszValue; *c != '\0'; c++)
519 if(*c == '"')
520 *c = '\'';
521 msInsertHashTable(&(layer->metadata), pszStyle, pszValue );
522 msFree(pszValue);
523 }
524 }
525
526 free(pszStyle);
527
528 /* LegendURL */
529 pszStyle = (char*) malloc(strlen(pszStyleName) + 25);
530
531 sprintf( pszStyle, "wms_style_%s_legendurl",
532 pszStyleName);
533 msLoadMapContextURLELements( CPLGetXMLNode(psStyle, "LegendURL"),
534 &(layer->metadata), pszStyle );
535
536 free(pszStyle);
537
538 free(pszStyleName);
539
540 /* */
541 /* Add the stylelist to the layer connection */
542 /* */
543 if(msLookupHashTable(&(layer->metadata),
544 "wms_stylelist") == NULL) {
545 if(layer->connection)
546 pszValue = msStrdup(layer->connection);
547 else
548 pszValue = msStrdup( "" );
549 pszValue1 = strstr(pszValue, "STYLELIST=");
550 if(pszValue1 != NULL) {
551 pszValue1 += 10;
552 pszValue2 = strchr(pszValue, '&');
553 if(pszValue2 != NULL)
554 pszValue1[pszValue2-pszValue1] = '\0';
555 msInsertHashTable(&(layer->metadata), "wms_stylelist",
556 pszValue1);
557 }
558 free(pszValue);
559 }
560
561 /* */
562 /* Add the style to the layer connection */
563 /* */
564 if(msLookupHashTable(&(layer->metadata), "wms_style") == NULL) {
565 if(layer->connection)
566 pszValue = msStrdup(layer->connection);
567 else
568 pszValue = msStrdup( "" );
569 pszValue1 = strstr(pszValue, "STYLE=");
570 if(pszValue1 != NULL) {
571 pszValue1 += 6;
572 pszValue2 = strchr(pszValue, '&');
573 if(pszValue2 != NULL)
574 pszValue1[pszValue2-pszValue1] = '\0';
575 msInsertHashTable(&(layer->metadata), "wms_style",
576 pszValue1);
577 }
578 free(pszValue);
579 }
580
581 return MS_SUCCESS;
582 }
583
msLoadMapContextLayerDimension(CPLXMLNode * psDimension,layerObj * layer)584 int msLoadMapContextLayerDimension(CPLXMLNode *psDimension, layerObj *layer)
585 {
586 char *pszValue;
587 const char *pszHash;
588 char *pszDimension=NULL, *pszDimensionName=NULL;
589
590 pszDimensionName =(char*)CPLGetXMLValue(psDimension,"name",NULL);
591 if(pszDimensionName == NULL) {
592 return MS_FALSE;
593 } else
594 pszDimensionName = msStrdup(pszDimensionName);
595
596 pszDimension = (char*)malloc(strlen(pszDimensionName)+50);
597
598 /* wms_dimension: This is the current dimension */
599 pszValue = (char*)CPLGetXMLValue(psDimension, "current", NULL);
600 if(pszValue != NULL && (strcasecmp(pszValue, "1") == 0 ||
601 strcasecmp(pszValue, "true") == 0))
602 msInsertHashTable(&(layer->metadata),
603 "wms_dimension", pszDimensionName);
604 /* wms_dimensionlist */
605 pszHash = msLookupHashTable(&(layer->metadata),
606 "wms_dimensionlist");
607 if(pszHash != NULL) {
608 pszValue = (char*)malloc(strlen(pszHash)+
609 strlen(pszDimensionName)+2);
610 sprintf(pszValue, "%s,%s", pszHash, pszDimensionName);
611 msInsertHashTable(&(layer->metadata),
612 "wms_dimensionlist", pszValue);
613 free(pszValue);
614 } else
615 msInsertHashTable(&(layer->metadata),
616 "wms_dimensionlist", pszDimensionName);
617
618 /* Units */
619 sprintf(pszDimension, "wms_dimension_%s_units", pszDimensionName);
620 msGetMapContextXMLHashValue(psDimension, "units", &(layer->metadata),
621 pszDimension);
622
623 /* UnitSymbol */
624 sprintf(pszDimension, "wms_dimension_%s_unitsymbol", pszDimensionName);
625 msGetMapContextXMLHashValue(psDimension, "unitSymbol", &(layer->metadata),
626 pszDimension);
627
628 /* userValue */
629 sprintf(pszDimension, "wms_dimension_%s_uservalue", pszDimensionName);
630 msGetMapContextXMLHashValue(psDimension, "userValue", &(layer->metadata),
631 pszDimension);
632 if(strcasecmp(pszDimensionName, "time") == 0)
633 msGetMapContextXMLHashValue(psDimension, "userValue", &(layer->metadata),
634 "wms_time");
635
636 /* default */
637 sprintf(pszDimension, "wms_dimension_%s_default", pszDimensionName);
638 msGetMapContextXMLHashValue(psDimension, "default", &(layer->metadata),
639 pszDimension);
640
641 /* multipleValues */
642 sprintf(pszDimension, "wms_dimension_%s_multiplevalues", pszDimensionName);
643 msGetMapContextXMLHashValue(psDimension, "multipleValues",&(layer->metadata),
644 pszDimension);
645
646 /* nearestValue */
647 sprintf(pszDimension, "wms_dimension_%s_nearestvalue", pszDimensionName);
648 msGetMapContextXMLHashValue(psDimension, "nearestValue", &(layer->metadata),
649 pszDimension);
650
651 free(pszDimension);
652
653 free(pszDimensionName);
654
655 return MS_SUCCESS;
656 }
657
658
659
660 /*
661 ** msLoadMapContextGeneral
662 **
663 ** Load the General block of the mapcontext document
664 */
msLoadMapContextGeneral(mapObj * map,CPLXMLNode * psGeneral,CPLXMLNode * psMapContext,int nVersion,char * filename)665 int msLoadMapContextGeneral(mapObj *map, CPLXMLNode *psGeneral,
666 CPLXMLNode *psMapContext, int nVersion,
667 char *filename)
668 {
669
670 char *pszProj=NULL;
671 char *pszValue, *pszValue1, *pszValue2;
672 int nTmp;
673
674 /* Projection */
675 pszValue = (char*)CPLGetXMLValue(psGeneral,
676 "BoundingBox.SRS", NULL);
677 if(pszValue != NULL) {
678 if(strncasecmp(pszValue, "AUTO:", 5) == 0) {
679 pszProj = msStrdup(pszValue);
680 } else {
681 pszProj = (char*) malloc(sizeof(char)*(strlen(pszValue)+10));
682 sprintf(pszProj, "init=epsg:%s", pszValue+5);
683 }
684
685 msInitProjection(&map->projection);
686 map->projection.args[map->projection.numargs] = msStrdup(pszProj);
687 map->projection.numargs++;
688 msProcessProjection(&map->projection);
689
690 if( (nTmp = GetMapserverUnitUsingProj(&(map->projection))) == -1) {
691 free(pszProj);
692 msSetError( MS_MAPCONTEXTERR,
693 "Unable to set units for projection '%s'",
694 "msLoadMapContext()", pszProj );
695 return MS_FAILURE;
696 } else {
697 map->units = nTmp;
698 }
699 free(pszProj);
700 } else {
701 msDebug("Mandatory data General.BoundingBox.SRS missing in %s.",
702 filename);
703 }
704
705 /* Extent */
706 if( msGetMapContextXMLFloatValue(psGeneral, "BoundingBox.minx",
707 &(map->extent.minx)) == MS_FAILURE) {
708 msDebug("Mandatory data General.BoundingBox.minx missing in %s.",
709 filename);
710 }
711 if( msGetMapContextXMLFloatValue(psGeneral, "BoundingBox.miny",
712 &(map->extent.miny)) == MS_FAILURE) {
713 msDebug("Mandatory data General.BoundingBox.miny missing in %s.",
714 filename);
715 }
716 if( msGetMapContextXMLFloatValue(psGeneral, "BoundingBox.maxx",
717 &(map->extent.maxx)) == MS_FAILURE) {
718 msDebug("Mandatory data General.BoundingBox.maxx missing in %s.",
719 filename);
720 }
721 if( msGetMapContextXMLFloatValue(psGeneral, "BoundingBox.maxy",
722 &(map->extent.maxy)) == MS_FAILURE) {
723 msDebug("Mandatory data General.BoundingBox.maxy missing in %s.",
724 filename);
725 }
726
727 /* Title */
728 if( msGetMapContextXMLHashValue(psGeneral, "Title",
729 &(map->web.metadata), "wms_title") == MS_FAILURE) {
730 if ( nVersion >= OWS_1_0_0 )
731 msDebug("Mandatory data General.Title missing in %s.", filename);
732 else {
733 if( msGetMapContextXMLHashValue(psGeneral, "gml:name",
734 &(map->web.metadata), "wms_title") == MS_FAILURE ) {
735 if( nVersion < OWS_0_1_7 )
736 msDebug("Mandatory data General.Title missing in %s.", filename);
737 else
738 msDebug("Mandatory data General.gml:name missing in %s.",
739 filename);
740 }
741 }
742 }
743
744 /* Name */
745 if( nVersion >= OWS_1_0_0 ) {
746 pszValue = (char*)CPLGetXMLValue(psMapContext,
747 "id", NULL);
748 if (pszValue)
749 map->name = msStrdup(pszValue);
750 } else {
751 if(msGetMapContextXMLStringValue(psGeneral, "Name",
752 &(map->name)) == MS_FAILURE) {
753 msGetMapContextXMLStringValue(psGeneral, "gml:name",
754 &(map->name));
755 }
756 }
757 /* Keyword */
758 if( nVersion >= OWS_1_0_0 ) {
759 msLoadMapContextListInMetadata(
760 CPLGetXMLNode(psGeneral, "KeywordList"),
761 &(map->web.metadata), "KEYWORD", "wms_keywordlist", "," );
762 } else
763 msGetMapContextXMLHashValue(psGeneral, "Keywords",
764 &(map->web.metadata), "wms_keywordlist");
765
766 /* Window */
767 pszValue1 = (char*)CPLGetXMLValue(psGeneral,"Window.width",NULL);
768 pszValue2 = (char*)CPLGetXMLValue(psGeneral,"Window.height",NULL);
769 if(pszValue1 != NULL && pszValue2 != NULL) {
770 map->width = atoi(pszValue1);
771 map->height = atoi(pszValue2);
772 }
773
774 /* Abstract */
775 if( msGetMapContextXMLHashValue( psGeneral,
776 "Abstract", &(map->web.metadata),
777 "wms_abstract") == MS_FAILURE ) {
778 msGetMapContextXMLHashValue( psGeneral, "gml:description",
779 &(map->web.metadata), "wms_abstract");
780 }
781
782 /* DataURL */
783 msGetMapContextXMLHashValueDecode(psGeneral,
784 "DataURL.OnlineResource.xlink:href",
785 &(map->web.metadata), "wms_dataurl");
786
787 /* LogoURL */
788 /* The logourl have a width, height, format and an URL */
789 msLoadMapContextURLELements( CPLGetXMLNode(psGeneral, "LogoURL"),
790 &(map->web.metadata), "wms_logourl" );
791
792 /* DescriptionURL */
793 /* The descriptionurl have a width, height, format and an URL */
794 msLoadMapContextURLELements( CPLGetXMLNode(psGeneral,
795 "DescriptionURL"),
796 &(map->web.metadata), "wms_descriptionurl" );
797
798 /* Contact Info */
799 msLoadMapContextContactInfo(
800 CPLGetXMLNode(psGeneral, "ContactInformation"),
801 &(map->web.metadata) );
802
803 return MS_SUCCESS;
804 }
805
806 /*
807 ** msLoadMapContextLayer
808 **
809 ** Load a Layer block from a MapContext document
810 */
msLoadMapContextLayer(mapObj * map,CPLXMLNode * psLayer,int nVersion,char * filename,int unique_layer_names)811 int msLoadMapContextLayer(mapObj *map, CPLXMLNode *psLayer, int nVersion,
812 char *filename, int unique_layer_names)
813 {
814 char *pszValue;
815 const char *pszHash;
816 char *pszName=NULL;
817 CPLXMLNode *psFormatList, *psFormat, *psStyleList, *psStyle, *psExtension;
818 CPLXMLNode *psDimensionList, *psDimension;
819 int nStyle;
820 layerObj *layer;
821
822 /* Init new layer */
823 if(msGrowMapLayers(map) == NULL)
824 return MS_FAILURE;
825
826 layer = (GET_LAYER(map, map->numlayers));
827 initLayer(layer, map);
828 layer->map = (mapObj *)map;
829 layer->type = MS_LAYER_RASTER;
830 /* save the index */
831 GET_LAYER(map, map->numlayers)->index = map->numlayers;
832 map->layerorder[map->numlayers] = map->numlayers;
833 map->numlayers++;
834
835
836 /* Status */
837 pszValue = (char*)CPLGetXMLValue(psLayer, "hidden", "1");
838 if((pszValue != NULL) && (atoi(pszValue) == 0 &&
839 strcasecmp(pszValue, "true") != 0))
840 layer->status = MS_ON;
841 else
842 layer->status = MS_OFF;
843
844 /* Queryable */
845 pszValue = (char*)CPLGetXMLValue(psLayer, "queryable", "0");
846 if(pszValue !=NULL && (atoi(pszValue) == 1 ||
847 strcasecmp(pszValue, "true") == 0))
848 layer->template = msStrdup("ttt");
849
850 /* Name and Title */
851 pszValue = (char*)CPLGetXMLValue(psLayer, "Name", NULL);
852 if(pszValue != NULL) {
853 msInsertHashTable( &(layer->metadata), "wms_name", pszValue );
854
855 if (unique_layer_names) {
856 pszName = (char*)malloc(sizeof(char)*(strlen(pszValue)+15));
857 sprintf(pszName, "l%d:%s", layer->index, pszValue);
858 layer->name = msStrdup(pszName);
859 free(pszName);
860 } else
861 layer->name = msStrdup(pszValue);
862 } else {
863 pszName = (char*)malloc(sizeof(char)*15);
864 sprintf(pszName, "l%d:", layer->index);
865 layer->name = msStrdup(pszName);
866 free(pszName);
867 }
868
869 if(msGetMapContextXMLHashValue(psLayer, "Title", &(layer->metadata),
870 "wms_title") == MS_FAILURE) {
871 if(msGetMapContextXMLHashValue(psLayer, "Server.title",
872 &(layer->metadata), "wms_title") == MS_FAILURE) {
873 msDebug("Mandatory data Layer.Title missing in %s.", filename);
874 }
875 }
876
877 /* Server Title */
878 msGetMapContextXMLHashValue(psLayer, "Server.title", &(layer->metadata), "wms_server_title");
879
880 /* Abstract */
881 msGetMapContextXMLHashValue(psLayer, "Abstract", &(layer->metadata),
882 "wms_abstract");
883
884 /* DataURL */
885 if(nVersion <= OWS_0_1_4) {
886 msGetMapContextXMLHashValueDecode(psLayer,
887 "DataURL.OnlineResource.xlink:href",
888 &(layer->metadata), "wms_dataurl");
889 } else {
890 /* The DataURL have a width, height, format and an URL */
891 /* Width and height are not used, but they are included to */
892 /* be consistent with the spec. */
893 msLoadMapContextURLELements( CPLGetXMLNode(psLayer, "DataURL"),
894 &(layer->metadata), "wms_dataurl" );
895 }
896
897 /* The MetadataURL have a width, height, format and an URL */
898 /* Width and height are not used, but they are included to */
899 /* be consistent with the spec. */
900 msLoadMapContextURLELements( CPLGetXMLNode(psLayer, "MetadataURL"),
901 &(layer->metadata), "wms_metadataurl" );
902
903
904 /* MinScale && MaxScale */
905 pszValue = (char*)CPLGetXMLValue(psLayer, "sld:MinScaleDenominator", NULL);
906 if(pszValue != NULL) {
907 layer->minscaledenom = atof(pszValue);
908 }
909
910 pszValue = (char*)CPLGetXMLValue(psLayer, "sld:MaxScaleDenominator", NULL);
911 if(pszValue != NULL) {
912 layer->maxscaledenom = atof(pszValue);
913 }
914
915 /* */
916 /* Server */
917 /* */
918 if(nVersion >= OWS_0_1_4) {
919 if(msGetMapContextXMLStringValueDecode(psLayer,
920 "Server.OnlineResource.xlink:href",
921 &(layer->connection)) == MS_FAILURE) {
922 msSetError(MS_MAPCONTEXTERR,
923 "Mandatory data Server.OnlineResource.xlink:href missing in %s.",
924 "msLoadMapContext()", filename);
925 return MS_FAILURE;
926 } else {
927 msGetMapContextXMLHashValueDecode(psLayer,
928 "Server.OnlineResource.xlink:href",
929 &(layer->metadata), "wms_onlineresource");
930 layer->connectiontype = MS_WMS;
931 }
932 } else {
933 if(msGetMapContextXMLStringValueDecode(psLayer,
934 "Server.onlineResource",
935 &(layer->connection)) == MS_FAILURE) {
936 msSetError(MS_MAPCONTEXTERR,
937 "Mandatory data Server.onlineResource missing in %s.",
938 "msLoadMapContext()", filename);
939 return MS_FAILURE;
940 } else {
941 msGetMapContextXMLHashValueDecode(psLayer, "Server.onlineResource",
942 &(layer->metadata), "wms_onlineresource");
943 layer->connectiontype = MS_WMS;
944 }
945 }
946
947 if(nVersion >= OWS_0_1_4) {
948 if(msGetMapContextXMLHashValue(psLayer, "Server.version",
949 &(layer->metadata), "wms_server_version") == MS_FAILURE) {
950 msSetError(MS_MAPCONTEXTERR,
951 "Mandatory data Server.version missing in %s.",
952 "msLoadMapContext()", filename);
953 return MS_FAILURE;
954 }
955 } else {
956 if(msGetMapContextXMLHashValue(psLayer, "Server.wmtver",
957 &(layer->metadata), "wms_server_version") == MS_FAILURE) {
958 msSetError(MS_MAPCONTEXTERR,
959 "Mandatory data Server.wmtver missing in %s.",
960 "msLoadMapContext()", filename);
961 return MS_FAILURE;
962 }
963 }
964
965 /* Projection */
966 msLoadMapContextListInMetadata( psLayer, &(layer->metadata),
967 "SRS", "wms_srs", " " );
968
969 pszHash = msLookupHashTable(&(layer->metadata), "wms_srs");
970 if(((pszHash == NULL) || (strcasecmp(pszHash, "") == 0)) &&
971 map->projection.numargs != 0) {
972 char* pszProj = map->projection.args[map->projection.numargs-1];
973
974 if(pszProj != NULL) {
975 if(strncasecmp(pszProj, "AUTO:", 5) == 0) {
976 msInsertHashTable(&(layer->metadata),"wms_srs", pszProj);
977 } else {
978 if(strlen(pszProj) > 10) {
979 pszProj = (char*) malloc(sizeof(char) * (strlen(pszProj)));
980 sprintf( pszProj, "EPSG:%s",
981 map->projection.args[map->projection.numargs-1]+10);
982 msInsertHashTable(&(layer->metadata),"wms_srs", pszProj);
983 } else {
984 msDebug("Unable to set data for layer wms_srs from this"
985 " value %s.",
986 pszProj);
987 }
988 }
989 msFree(pszProj);
990 }
991 }
992
993 /* */
994 /* Format */
995 /* */
996 if( nVersion >= OWS_0_1_4 ) {
997 psFormatList = CPLGetXMLNode(psLayer, "FormatList");
998 } else {
999 psFormatList = psLayer;
1000 }
1001
1002 if(psFormatList != NULL) {
1003 for(psFormat = psFormatList->psChild;
1004 psFormat != NULL;
1005 psFormat = psFormat->psNext) {
1006 msLoadMapContextLayerFormat(psFormat, layer);
1007 }
1008
1009 } /* end FormatList parsing */
1010
1011 /* Style */
1012 if( nVersion >= OWS_0_1_4 ) {
1013 psStyleList = CPLGetXMLNode(psLayer, "StyleList");
1014 } else {
1015 psStyleList = psLayer;
1016 }
1017
1018 if(psStyleList != NULL) {
1019 nStyle = 0;
1020 for(psStyle = psStyleList->psChild;
1021 psStyle != NULL;
1022 psStyle = psStyle->psNext) {
1023 if(strcasecmp(psStyle->pszValue, "Style") == 0) {
1024 nStyle++;
1025 msLoadMapContextLayerStyle(psStyle, layer, nStyle);
1026 }
1027 }
1028 }
1029
1030 /* Dimension */
1031 psDimensionList = CPLGetXMLNode(psLayer, "DimensionList");
1032 if(psDimensionList != NULL) {
1033 for(psDimension = psDimensionList->psChild;
1034 psDimension != NULL;
1035 psDimension = psDimension->psNext) {
1036 if(strcasecmp(psDimension->pszValue, "Dimension") == 0) {
1037 msLoadMapContextLayerDimension(psDimension, layer);
1038 }
1039 }
1040 }
1041
1042 /* Extension */
1043 psExtension = CPLGetXMLNode(psLayer, "Extension");
1044 if (psExtension != NULL) {
1045 pszValue = (char*)CPLGetXMLValue(psExtension, "ol:opacity", NULL);
1046 if(pszValue != NULL) {
1047 if(!layer->compositer) {
1048 layer->compositer = msSmallMalloc(sizeof(LayerCompositer));
1049 initLayerCompositer(layer->compositer);
1050 }
1051 layer->compositer->opacity = atof(pszValue)*100;
1052 }
1053 }
1054
1055 return MS_SUCCESS;
1056 }
1057
1058 #endif
1059
1060
1061
1062 /* msLoadMapContextURL()
1063 **
1064 ** load an OGC Web Map Context format from an URL
1065 **
1066 ** Take a map object and a URL to a conect file in arguments
1067 */
1068
msLoadMapContextURL(mapObj * map,char * urlfilename,int unique_layer_names)1069 int msLoadMapContextURL(mapObj *map, char *urlfilename, int unique_layer_names)
1070 {
1071 #if defined(USE_WMS_LYR)
1072 char *pszTmpFile = NULL;
1073 int status = 0;
1074
1075 if (!map || !urlfilename) {
1076 msSetError(MS_MAPCONTEXTERR,
1077 "Invalid map or url given.",
1078 "msGetMapContextURL()");
1079 return MS_FAILURE;
1080 }
1081
1082 pszTmpFile = msTmpFile(map, map->mappath, NULL, "context.xml");
1083 if (msHTTPGetFile(urlfilename, pszTmpFile, &status,-1, 0, 0, 0) == MS_SUCCESS) {
1084 return msLoadMapContext(map, pszTmpFile, unique_layer_names);
1085 } else {
1086 msSetError(MS_MAPCONTEXTERR,
1087 "Could not open context file %s.",
1088 "msGetMapContextURL()", urlfilename);
1089 return MS_FAILURE;
1090 }
1091
1092 #else
1093 msSetError(MS_MAPCONTEXTERR,
1094 "Not implemented since Map Context is not enabled.",
1095 "msGetMapContextURL()");
1096 return MS_FAILURE;
1097 #endif
1098 }
1099 /* msLoadMapContext()
1100 **
1101 ** Get a mapfile from a OGC Web Map Context format
1102 **
1103 ** Take as first map object and a file in arguments
1104 ** If The 2nd aregument unique_layer_names is set to MS_TRUE, the layer
1105 ** name created would be unique and be prefixed with an l plus the layers's index
1106 ** (eg l:1:park. l:2:road ...). If It is set to MS_FALSE, the layer name
1107 ** would be the same name as the layer name in the context
1108 */
msLoadMapContext(mapObj * map,char * filename,int unique_layer_names)1109 int msLoadMapContext(mapObj *map, char *filename, int unique_layer_names)
1110 {
1111 #if defined(USE_WMS_LYR)
1112 char *pszWholeText, *pszValue;
1113 CPLXMLNode *psRoot, *psMapContext, *psLayer, *psLayerList, *psChild;
1114 char szPath[MS_MAXPATHLEN];
1115 int nVersion=-1;
1116 char szVersionBuf[OWS_VERSION_MAXLEN];
1117
1118 /* */
1119 /* Load the raw XML file */
1120 /* */
1121
1122 pszWholeText = msGetMapContextFileText(
1123 msBuildPath(szPath, map->mappath, filename));
1124 if(pszWholeText == NULL) {
1125 msSetError( MS_MAPCONTEXTERR, "Unable to read %s",
1126 "msLoadMapContext()", filename );
1127 return MS_FAILURE;
1128 }
1129
1130 if( ( strstr( pszWholeText, "<WMS_Viewer_Context" ) == NULL ) &&
1131 ( strstr( pszWholeText, "<View_Context" ) == NULL ) &&
1132 ( strstr( pszWholeText, "<ViewContext" ) == NULL ) )
1133
1134 {
1135 free( pszWholeText );
1136 msSetError( MS_MAPCONTEXTERR, "Not a Map Context file (%s)",
1137 "msLoadMapContext()", filename );
1138 return MS_FAILURE;
1139 }
1140
1141 /* */
1142 /* Convert to XML parse tree. */
1143 /* */
1144 psRoot = CPLParseXMLString( pszWholeText );
1145 free( pszWholeText );
1146
1147 /* We assume parser will report errors via CPL. */
1148 if( psRoot == NULL ) {
1149 msSetError( MS_MAPCONTEXTERR, "Invalid XML file (%s)",
1150 "msLoadMapContext()", filename );
1151 if(psRoot != NULL)
1152 CPLDestroyXMLNode(psRoot);
1153
1154 return MS_FAILURE;
1155 }
1156
1157 /* */
1158 /* Valid the MapContext file and get the root of the document */
1159 /* */
1160 psChild = psRoot;
1161 psMapContext = NULL;
1162 while( psChild != NULL ) {
1163 if( psChild->eType == CXT_Element &&
1164 (EQUAL(psChild->pszValue,"WMS_Viewer_Context") ||
1165 EQUAL(psChild->pszValue,"View_Context") ||
1166 EQUAL(psChild->pszValue,"ViewContext")) ) {
1167 psMapContext = psChild;
1168 break;
1169 } else {
1170 psChild = psChild->psNext;
1171 }
1172 }
1173
1174 if( psMapContext == NULL ) {
1175 CPLDestroyXMLNode(psRoot);
1176 msSetError( MS_MAPCONTEXTERR, "Invalid Map Context File (%s)",
1177 "msLoadMapContext()", filename );
1178 return MS_FAILURE;
1179 }
1180
1181 /* Fetch document version number */
1182 pszValue = (char*)CPLGetXMLValue(psMapContext,
1183 "version", NULL);
1184 if( !pszValue ) {
1185 msDebug( "msLoadMapContext(): Mandatory data version missing in %s, assuming 0.1.4.",
1186 filename );
1187 pszValue = "0.1.4";
1188 }
1189
1190 nVersion = msOWSParseVersionString(pszValue);
1191
1192 /* Make sure this is a supported version */
1193 switch (nVersion) {
1194 case OWS_0_1_2:
1195 case OWS_0_1_4:
1196 case OWS_0_1_7:
1197 case OWS_1_0_0:
1198 case OWS_1_1_0:
1199 /* All is good, this is a supported version. */
1200 break;
1201 default:
1202 /* Not a supported version */
1203 msSetError(MS_MAPCONTEXTERR,
1204 "This version of Map Context is not supported (%s).",
1205 "msLoadMapContext()", pszValue);
1206 CPLDestroyXMLNode(psRoot);
1207 return MS_FAILURE;
1208 }
1209
1210 /* Reformat and save Version in metadata */
1211 msInsertHashTable( &(map->web.metadata), "wms_context_version",
1212 msOWSGetVersionString(nVersion, szVersionBuf));
1213
1214 if( nVersion >= OWS_0_1_7 && nVersion < OWS_1_0_0) {
1215 if( msGetMapContextXMLHashValue(psMapContext, "fid",
1216 &(map->web.metadata), "wms_context_fid") == MS_FAILURE ) {
1217 msDebug("Mandatory data fid missing in %s.", filename);
1218 }
1219 }
1220
1221 /* */
1222 /* Load the General bloc */
1223 /* */
1224 psChild = CPLGetXMLNode( psMapContext, "General" );
1225 if( psChild == NULL ) {
1226 CPLDestroyXMLNode(psRoot);
1227 msSetError(MS_MAPCONTEXTERR,
1228 "The Map Context document provided (%s) does not contain any "
1229 "General elements.",
1230 "msLoadMapContext()", filename);
1231 return MS_FAILURE;
1232 }
1233
1234 if( msLoadMapContextGeneral(map, psChild, psMapContext,
1235 nVersion, filename) == MS_FAILURE ) {
1236 CPLDestroyXMLNode(psRoot);
1237 return MS_FAILURE;
1238 }
1239
1240 /* */
1241 /* Load the bloc LayerList */
1242 /* */
1243 psLayerList = CPLGetXMLNode(psMapContext, "LayerList");
1244 if( psLayerList != NULL ) {
1245 for(psLayer = psLayerList->psChild;
1246 psLayer != NULL;
1247 psLayer = psLayer->psNext) {
1248 if(EQUAL(psLayer->pszValue, "Layer")) {
1249 if( msLoadMapContextLayer(map, psLayer, nVersion,
1250 filename, unique_layer_names) == MS_FAILURE ) {
1251 CPLDestroyXMLNode(psRoot);
1252 return MS_FAILURE;
1253 }
1254 }/* end Layer parsing */
1255 }/* for */
1256 }
1257
1258 CPLDestroyXMLNode(psRoot);
1259
1260 return MS_SUCCESS;
1261
1262 #else
1263 msSetError(MS_MAPCONTEXTERR,
1264 "Not implemented since Map Context is not enabled.",
1265 "msGetMapContext()");
1266 return MS_FAILURE;
1267 #endif
1268 }
1269
1270
1271 /* msSaveMapContext()
1272 **
1273 ** Save a mapfile into the OGC Web Map Context format
1274 **
1275 ** Take a map object and a file in arguments
1276 */
msSaveMapContext(mapObj * map,char * filename)1277 int msSaveMapContext(mapObj *map, char *filename)
1278 {
1279 #if defined(USE_WMS_LYR)
1280 VSILFILE *stream;
1281 char szPath[MS_MAXPATHLEN];
1282 int nStatus;
1283
1284 /* open file */
1285 if(filename != NULL && strlen(filename) > 0) {
1286 stream = fopen(msBuildPath(szPath, map->mappath, filename), "wb");
1287 if(!stream) {
1288 msSetError(MS_IOERR, "(%s)", "msSaveMapContext()", filename);
1289 return(MS_FAILURE);
1290 }
1291 } else {
1292 msSetError(MS_IOERR, "Filename is undefined.", "msSaveMapContext()");
1293 return MS_FAILURE;
1294 }
1295
1296 nStatus = msWriteMapContext(map, stream);
1297
1298 fclose(stream);
1299
1300 return nStatus;
1301 #else
1302 msSetError(MS_MAPCONTEXTERR,
1303 "Not implemented since Map Context is not enabled.",
1304 "msSaveMapContext()");
1305 return MS_FAILURE;
1306 #endif
1307 }
1308
1309
1310
msWriteMapContext(mapObj * map,FILE * stream)1311 int msWriteMapContext(mapObj *map, FILE *stream)
1312 {
1313 #if defined(USE_WMS_LYR)
1314 const char * version;
1315 char *pszEPSG;
1316 char * tabspace=NULL, *pszChar,*pszSLD=NULL,*pszURL,*pszSLD2=NULL;
1317 char *pszStyle, *pszStyleItem, *pszSLDBody;
1318 char *pszEncodedVal;
1319 int i, nValue, nVersion=OWS_VERSION_NOTSET;
1320 /* Dimension element */
1321 char *pszDimension;
1322 const char *pszDimUserValue=NULL, *pszDimUnits=NULL, *pszDimDefault=NULL;
1323 const char *pszDimNearValue=NULL, *pszDimUnitSymbol=NULL;
1324 const char *pszDimMultiValue=NULL;
1325 int bDimensionList = 0;
1326
1327 /* Decide which version we're going to return... */
1328 version = msLookupHashTable(&(map->web.metadata), "wms_context_version");
1329 if(version == NULL)
1330 version = "1.1.0";
1331
1332 nVersion = msOWSParseVersionString(version);
1333 if (nVersion == OWS_VERSION_BADFORMAT)
1334 return MS_FAILURE; /* msSetError() already called. */
1335
1336 /* Make sure this is a supported version */
1337 /* Note that we don't write 0.1.2 even if we read it. */
1338 switch (nVersion) {
1339 case OWS_0_1_4:
1340 case OWS_0_1_7:
1341 case OWS_1_0_0:
1342 case OWS_1_1_0:
1343 /* All is good, this is a supported version. */
1344 break;
1345 default:
1346 /* Not a supported version */
1347 msSetError(MS_MAPCONTEXTERR,
1348 "This version of Map Context is not supported (%s).",
1349 "msSaveMapContext()", version);
1350 return MS_FAILURE;
1351 }
1352
1353 /* file header */
1354 msIO_fprintf( stream, "<?xml version='1.0' encoding=\"UTF-8\" standalone=\"no\" ?>\n");
1355
1356 /* set the WMS_Viewer_Context information */
1357 pszEncodedVal = msEncodeHTMLEntities(version);
1358 if(nVersion >= OWS_1_0_0) {
1359 msIO_fprintf( stream, "<ViewContext version=\"%s\"", pszEncodedVal );
1360 } else if(nVersion >= OWS_0_1_7) {
1361 msIO_fprintf( stream, "<View_Context version=\"%s\"", pszEncodedVal );
1362
1363 } else { /* 0.1.4 */
1364 msIO_fprintf( stream, "<WMS_Viewer_Context version=\"%s\"", pszEncodedVal );
1365 }
1366 msFree(pszEncodedVal);
1367
1368 if ( nVersion >= OWS_0_1_7 && nVersion < OWS_1_0_0 ) {
1369 msOWSPrintEncodeMetadata(stream, &(map->web.metadata), NULL,
1370 "wms_context_fid", OWS_NOERR," fid=\"%s\"","0");
1371 }
1372 if ( nVersion >= OWS_1_0_0 )
1373 msOWSPrintEncodeParam(stream, "MAP.NAME", map->name, OWS_NOERR,
1374 " id=\"%s\"", NULL);
1375
1376 msIO_fprintf( stream, " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
1377 msIO_fprintf( stream, " xmlns:ogc=\"http://www.opengis.net/ogc\"");
1378
1379 if( nVersion >= OWS_0_1_7 && nVersion < OWS_1_0_0 ) {
1380 msIO_fprintf( stream, " xmlns:gml=\"http://www.opengis.net/gml\"");
1381 }
1382 if( nVersion >= OWS_1_0_0 ) {
1383 msIO_fprintf( stream, " xmlns:xlink=\"http://www.w3.org/1999/xlink\"");
1384 msIO_fprintf( stream, " xmlns=\"http://www.opengis.net/context\"");
1385 msIO_fprintf( stream, " xmlns:sld=\"http://www.opengis.net/sld\"");
1386 pszEncodedVal = msEncodeHTMLEntities(msOWSGetSchemasLocation(map));
1387 if( nVersion >= OWS_1_1_0 )
1388 msIO_fprintf( stream,
1389 " xsi:schemaLocation=\"http://www.opengis.net/context %s/context/1.1.0/context.xsd\">\n",
1390 pszEncodedVal);
1391 else
1392 msIO_fprintf( stream,
1393 " xsi:schemaLocation=\"http://www.opengis.net/context %s/context/1.0.0/context.xsd\">\n",
1394 pszEncodedVal);
1395 msFree(pszEncodedVal);
1396 } else {
1397 msIO_fprintf( stream, " xmlns:xlink=\"http://www.w3.org/TR/xlink\"");
1398
1399 pszEncodedVal = msEncodeHTMLEntities(msOWSGetSchemasLocation(map));
1400 msIO_fprintf( stream, " xsi:noNamespaceSchemaLocation=\"%s/contexts/",
1401 pszEncodedVal );
1402 msFree(pszEncodedVal);
1403 pszEncodedVal = msEncodeHTMLEntities(msOWSGetSchemasLocation(map));
1404 msIO_fprintf( stream, "%s/context.xsd\">\n", pszEncodedVal);
1405 msFree(pszEncodedVal);
1406 }
1407
1408 /* set the General information */
1409 msIO_fprintf( stream, " <General>\n" );
1410
1411 /* Window */
1412 if( map->width != -1 || map->height != -1 )
1413 msIO_fprintf( stream, " <Window width=\"%d\" height=\"%d\"/>\n",
1414 map->width, map->height );
1415
1416 /* Bounding box corners and spatial reference system */
1417 if(tabspace)
1418 free(tabspace);
1419 tabspace = msStrdup(" ");
1420 msOWSGetEPSGProj(&(map->projection), &(map->web.metadata), "MO", MS_TRUE, &pszEPSG);
1421 msIO_fprintf( stream,
1422 "%s<!-- Bounding box corners and spatial reference system -->\n",
1423 tabspace );
1424 if(!pszEPSG || (strcasecmp(pszEPSG, "(null)") == 0))
1425 msIO_fprintf(stream, "<!-- WARNING: Mandatory data 'projection' was missing in this context. -->\n");
1426
1427 pszEncodedVal = msEncodeHTMLEntities(pszEPSG);
1428 msIO_fprintf( stream, "%s<BoundingBox SRS=\"%s\" minx=\"%f\" miny=\"%f\" maxx=\"%f\" maxy=\"%f\"/>\n",
1429 tabspace, pszEncodedVal, map->extent.minx, map->extent.miny,
1430 map->extent.maxx, map->extent.maxy );
1431 msFree(pszEncodedVal);
1432 msFree(pszEPSG);
1433
1434 /* Title, name */
1435 if( nVersion >= OWS_0_1_7 && nVersion < OWS_1_0_0 ) {
1436 msOWSPrintEncodeParam(stream, "MAP.NAME", map->name, OWS_NOERR,
1437 " <gml:name>%s</gml:name>\n", NULL);
1438 } else {
1439 if (nVersion < OWS_0_1_7)
1440 msOWSPrintEncodeParam(stream, "MAP.NAME", map->name, OWS_NOERR,
1441 " <Name>%s</Name>\n", NULL);
1442
1443 msIO_fprintf( stream, "%s<!-- Title of Context -->\n", tabspace );
1444 msOWSPrintEncodeMetadata(stream, &(map->web.metadata),
1445 NULL, "wms_title", OWS_WARN,
1446 " <Title>%s</Title>\n", map->name);
1447 }
1448
1449 /* keyword */
1450 if (nVersion >= OWS_1_0_0) {
1451 if (msLookupHashTable(&(map->web.metadata),"wms_keywordlist")!=NULL) {
1452 char **papszKeywords;
1453 int nKeywords, iKey;
1454
1455 const char* pszValue = msLookupHashTable(&(map->web.metadata),
1456 "wms_keywordlist");
1457 papszKeywords = msStringSplit(pszValue, ',', &nKeywords);
1458 if(nKeywords > 0 && papszKeywords) {
1459 msIO_fprintf( stream, " <KeywordList>\n");
1460 for(iKey=0; iKey<nKeywords; iKey++) {
1461 pszEncodedVal = msEncodeHTMLEntities(papszKeywords[iKey]);
1462 msIO_fprintf( stream, " <Keyword>%s</Keyword>\n",
1463 pszEncodedVal);
1464 msFree(pszEncodedVal);
1465 }
1466 msIO_fprintf( stream, " </KeywordList>\n");
1467 }
1468 }
1469 } else
1470 msOWSPrintEncodeMetadataList(stream, &(map->web.metadata), NULL,
1471 "wms_keywordlist",
1472 " <Keywords>\n", " </Keywords>\n",
1473 " %s\n", NULL);
1474
1475 /* abstract */
1476 if( nVersion >= OWS_0_1_7 && nVersion < OWS_1_0_0 ) {
1477 msOWSPrintEncodeMetadata(stream, &(map->web.metadata),
1478 NULL, "wms_abstract", OWS_NOERR,
1479 " <gml:description>%s</gml:description>\n", NULL);
1480 } else {
1481 msOWSPrintEncodeMetadata(stream, &(map->web.metadata),
1482 NULL, "wms_abstract", OWS_NOERR,
1483 " <Abstract>%s</Abstract>\n", NULL);
1484 }
1485
1486 /* LogoURL */
1487 /* The LogoURL have a width, height, format and an URL */
1488 msOWSPrintURLType(stream, &(map->web.metadata), "MO", "logourl",
1489 OWS_NOERR, NULL, "LogoURL", NULL, " width=\"%s\"",
1490 " height=\"%s\""," format=\"%s\"",
1491 " <OnlineResource xlink:type=\"simple\" xlink:href=\"%s\"/>\n",
1492 MS_FALSE, MS_FALSE, MS_FALSE, MS_FALSE, MS_TRUE,
1493 NULL, NULL, NULL, NULL, NULL, " ");
1494
1495 /* DataURL */
1496 msOWSPrintEncodeMetadata(stream, &(map->web.metadata),
1497 NULL, "wms_dataurl", OWS_NOERR,
1498 " <DataURL>\n <OnlineResource xlink:type=\"simple\" xlink:href=\"%s\"/>\n </DataURL>\n", NULL);
1499
1500 /* DescriptionURL */
1501 /* The DescriptionURL have a width, height, format and an URL */
1502 /* The metadata is structured like this: "width height format url" */
1503 msOWSPrintURLType(stream, &(map->web.metadata), "MO", "descriptionurl",
1504 OWS_NOERR, NULL, "DescriptionURL", NULL, " width=\"%s\"",
1505 " height=\"%s\""," format=\"%s\"",
1506 " <OnlineResource xlink:type=\"simple\" xlink:href=\"%s\"/>\n",
1507 MS_FALSE, MS_FALSE, MS_FALSE, MS_FALSE, MS_TRUE,
1508 NULL, NULL, NULL, NULL, NULL, " ");
1509
1510 /* Contact Info */
1511 msOWSPrintContactInfo( stream, tabspace, OWS_1_1_0, &(map->web.metadata), "MO" );
1512
1513 /* Close General */
1514 msIO_fprintf( stream, " </General>\n" );
1515 free(tabspace);
1516
1517 /* Set the layer list */
1518 msIO_fprintf(stream, " <LayerList>\n");
1519
1520 /* Loop on all layer */
1521 for(i=0; i<map->numlayers; i++) {
1522 if(GET_LAYER(map, i)->status != MS_DELETE && GET_LAYER(map, i)->connectiontype == MS_WMS) {
1523 const char* pszValue;
1524 char* pszValueMod;
1525 const char* pszCurrent;
1526 if(GET_LAYER(map, i)->status == MS_OFF)
1527 nValue = 1;
1528 else
1529 nValue = 0;
1530 msIO_fprintf(stream, " <Layer queryable=\"%d\" hidden=\"%d\">\n",
1531 msIsLayerQueryable(GET_LAYER(map, i)), nValue);
1532
1533 /* */
1534 /* Server definition */
1535 /* */
1536 if(nVersion < OWS_1_0_0 )
1537 msOWSPrintEncodeMetadata(stream, &(GET_LAYER(map, i)->metadata),
1538 NULL, "wms_server_version", OWS_WARN,
1539 " <Server service=\"WMS\" version=\"%s\" ",
1540 "1.0.0");
1541 else
1542 msOWSPrintEncodeMetadata(stream, &(GET_LAYER(map, i)->metadata),
1543 NULL, "wms_server_version", OWS_WARN,
1544 " <Server service=\"OGC:WMS\" version=\"%s\" ",
1545 "1.0.0");
1546
1547 if(msOWSLookupMetadata(&(GET_LAYER(map, i)->metadata), "MO", "server_title"))
1548 msOWSPrintEncodeMetadata(stream, &(GET_LAYER(map, i)->metadata),
1549 NULL, "wms_server_title", OWS_NOERR,
1550 "title=\"%s\">\n", "");
1551
1552 else if(GET_LAYER(map, i)->name)
1553 msOWSPrintEncodeMetadata(stream, &(GET_LAYER(map, i)->metadata),
1554 NULL, "wms_title", OWS_NOERR,
1555 "title=\"%s\">\n", GET_LAYER(map, i)->name);
1556 else {
1557 msOWSPrintEncodeMetadata(stream, &(GET_LAYER(map, i)->metadata),
1558 NULL, "wms_title", OWS_NOERR,
1559 "title=\"%s\">\n", "");
1560 }
1561
1562 /* Get base url of the online resource to be the default value */
1563 if(GET_LAYER(map, i)->connection)
1564 pszValueMod = msStrdup( GET_LAYER(map, i)->connection );
1565 else
1566 pszValueMod = msStrdup( "" );
1567 pszChar = strchr(pszValueMod, '?');
1568 if( pszChar )
1569 pszValueMod[pszChar - pszValueMod] = '\0';
1570 if(msOWSPrintEncodeMetadata(stream, &(GET_LAYER(map, i)->metadata),
1571 NULL, "wms_onlineresource", OWS_WARN,
1572 " <OnlineResource xlink:type=\"simple\" xlink:href=\"%s\"/>\n",
1573 pszValueMod) == OWS_WARN)
1574 msIO_fprintf(stream, "<!-- wms_onlineresource not set, using base URL"
1575 " , but probably not what you want -->\n");
1576 msIO_fprintf(stream, " </Server>\n");
1577 if(pszValueMod)
1578 free(pszValueMod);
1579
1580 /* */
1581 /* Layer information */
1582 /* */
1583 msOWSPrintEncodeMetadata(stream, &(GET_LAYER(map, i)->metadata),
1584 NULL, "wms_name", OWS_WARN,
1585 " <Name>%s</Name>\n",
1586 GET_LAYER(map, i)->name);
1587 msOWSPrintEncodeMetadata(stream, &(GET_LAYER(map, i)->metadata),
1588 NULL, "wms_title", OWS_WARN,
1589 " <Title>%s</Title>\n",
1590 GET_LAYER(map, i)->name);
1591 msOWSPrintEncodeMetadata(stream, &(GET_LAYER(map, i)->metadata),
1592 NULL, "wms_abstract", OWS_NOERR,
1593 " <Abstract>%s</Abstract>\n",
1594 NULL);
1595
1596 /* DataURL */
1597 if(nVersion <= OWS_0_1_4) {
1598 msOWSPrintEncodeMetadata(stream, &(GET_LAYER(map, i)->metadata),
1599 NULL, "wms_dataurl", OWS_NOERR,
1600 " <DataURL>%s</DataURL>\n",
1601 NULL);
1602 } else {
1603 /* The DataURL have a width, height, format and an URL */
1604 /* The metadata will be structured like this: */
1605 /* "width height format url" */
1606 /* Note: in version 0.1.7 the width and height are not included */
1607 /* in the Context file, but they are included in the metadata for */
1608 /* for consistency with the URLType. */
1609 msOWSPrintURLType(stream, &(GET_LAYER(map, i)->metadata), "MO",
1610 "dataurl", OWS_NOERR, NULL, "DataURL", NULL,
1611 " width=\"%s\"", " height=\"%s\"",
1612 " format=\"%s\"",
1613 " <OnlineResource xlink:type=\"simple\""
1614 " xlink:href=\"%s\"/>\n",
1615 MS_FALSE, MS_FALSE, MS_FALSE, MS_FALSE,
1616 MS_TRUE, NULL, NULL, NULL,NULL,NULL, " ");
1617 }
1618
1619 /* MetadataURL */
1620 /* The MetadataURL have a width, height, format and an URL */
1621 /* The metadata will be structured like this: */
1622 /* "width height format url" */
1623 msOWSPrintURLType(stream, &(GET_LAYER(map, i)->metadata), "MO",
1624 "metadataurl", OWS_NOERR, NULL, "MetadataURL",NULL,
1625 " width=\"%s\"", " height=\"%s\""," format=\"%s\"",
1626 " <OnlineResource xlink:type=\"simple\""
1627 " xlink:href=\"%s\"/>\n",
1628 MS_FALSE, MS_FALSE, MS_FALSE, MS_FALSE,
1629 MS_TRUE, NULL, NULL, NULL, NULL, NULL, " ");
1630
1631 /* MinScale && MaxScale */
1632 if(nVersion >= OWS_1_1_0 && GET_LAYER(map, i)->minscaledenom > 0)
1633 msIO_fprintf(stream,
1634 " <sld:MinScaleDenominator>%g</sld:MinScaleDenominator>\n",
1635 GET_LAYER(map, i)->minscaledenom);
1636 if(nVersion >= OWS_1_1_0 && GET_LAYER(map, i)->maxscaledenom > 0)
1637 msIO_fprintf(stream,
1638 " <sld:MaxScaleDenominator>%g</sld:MaxScaleDenominator>\n",
1639 GET_LAYER(map, i)->maxscaledenom);
1640
1641 /* Layer SRS */
1642 msOWSGetEPSGProj(&(GET_LAYER(map, i)->projection),
1643 &(GET_LAYER(map, i)->metadata),
1644 "MO", MS_FALSE, &pszEPSG);
1645 if(pszEPSG && (strcasecmp(pszEPSG, "(null)") != 0)) {
1646 pszEncodedVal = msEncodeHTMLEntities(pszEPSG);
1647 msIO_fprintf(stream, " <SRS>%s</SRS>\n", pszEncodedVal);
1648 msFree(pszEncodedVal);
1649 }
1650 msFree(pszEPSG);
1651
1652 /* Format */
1653 if(msLookupHashTable(&(GET_LAYER(map, i)->metadata),"wms_formatlist")==NULL &&
1654 msLookupHashTable(&(GET_LAYER(map, i)->metadata),"wms_format")==NULL) {
1655 pszURL = NULL;
1656 if(GET_LAYER(map, i)->connection)
1657 pszURL = msStrdup( GET_LAYER(map, i)->connection );
1658 else
1659 pszURL = msStrdup( "" );
1660 pszValueMod = pszURL;
1661 pszValueMod = strstr( pszValueMod, "FORMAT=" );
1662 if( pszValueMod ) {
1663 pszValueMod += 7;
1664 pszChar = strchr(pszValueMod, '&');
1665 if( pszChar )
1666 pszValueMod[pszChar - pszValueMod] = '\0';
1667 if(strcasecmp(pszValueMod, "") != 0) {
1668 pszEncodedVal = msEncodeHTMLEntities(pszValueMod);
1669 msIO_fprintf( stream, " <FormatList>\n");
1670 msIO_fprintf(stream," <Format>%s</Format>\n",pszValueMod);
1671 msIO_fprintf( stream, " </FormatList>\n");
1672 msFree(pszEncodedVal);
1673 }
1674 }
1675 if(pszURL)
1676 free(pszURL);
1677 } else {
1678 char **papszFormats;
1679 int numFormats, nForm;
1680
1681 pszValue = msLookupHashTable(&(GET_LAYER(map, i)->metadata),
1682 "wms_formatlist");
1683 if(!pszValue)
1684 pszValue = msLookupHashTable(&(GET_LAYER(map, i)->metadata),
1685 "wms_format");
1686 pszCurrent = msLookupHashTable(&(GET_LAYER(map, i)->metadata),
1687 "wms_format");
1688
1689 papszFormats = msStringSplit(pszValue, ',', &numFormats);
1690 if(numFormats > 0 && papszFormats) {
1691 msIO_fprintf( stream, " <FormatList>\n");
1692 for(nForm=0; nForm<numFormats; nForm++) {
1693 pszEncodedVal =msEncodeHTMLEntities(papszFormats[nForm]);
1694 if(pszCurrent && (strcasecmp(papszFormats[nForm],
1695 pszCurrent) == 0))
1696 msIO_fprintf( stream,
1697 " <Format current=\"1\">%s</Format>\n",
1698 pszEncodedVal);
1699 else
1700 msIO_fprintf( stream, " <Format>%s</Format>\n",
1701 pszEncodedVal);
1702 msFree(pszEncodedVal);
1703 }
1704 msIO_fprintf( stream, " </FormatList>\n");
1705 }
1706 if(papszFormats)
1707 msFreeCharArray(papszFormats, numFormats);
1708 }
1709 /* Style */
1710 /* First check the stylelist */
1711 pszValue = msLookupHashTable(&(GET_LAYER(map, i)->metadata),
1712 "wms_stylelist");
1713 while( pszValue && *pszValue == ' ' )
1714 pszValue ++;
1715 if(pszValue == NULL || strlen(pszValue) < 1) {
1716 /* Check if the style is in the connection URL */
1717 pszURL = "";
1718 if(GET_LAYER(map, i)->connection)
1719 pszURL = msStrdup( GET_LAYER(map, i)->connection );
1720 else
1721 pszURL = msStrdup( "" );
1722 pszValueMod = pszURL;
1723 /* Grab the STYLES in the URL */
1724 pszValueMod = strstr( pszValueMod, "STYLES=" );
1725 if( pszValueMod ) {
1726 pszValueMod += 7;
1727 pszChar = strchr(pszValueMod, '&');
1728 if( pszChar )
1729 pszValueMod[pszChar - pszValueMod] = '\0';
1730
1731 /* Check the SLD string from the URL */
1732 if(GET_LAYER(map, i)->connection)
1733 pszSLD2 = msStrdup(GET_LAYER(map, i)->connection);
1734 else
1735 pszSLD2 = msStrdup( "" );
1736 if(pszSLD2) {
1737 pszSLD = strstr(pszSLD2, "SLD=");
1738 pszSLDBody = strstr(pszSLD2, "SLD_BODY=");
1739 } else {
1740 pszSLD = NULL;
1741 pszSLDBody = NULL;
1742 }
1743 /* Check SLD */
1744 if( pszSLD ) {
1745 pszChar = strchr(pszSLD, '&');
1746 if( pszChar )
1747 pszSLD[pszChar - pszSLD] = '\0';
1748 pszSLD += 4;
1749 }
1750 /* Check SLDBody */
1751 if( pszSLDBody ) {
1752 pszChar = strchr(pszSLDBody, '&');
1753 if( pszChar )
1754 pszSLDBody[pszChar - pszSLDBody] = '\0';
1755 pszSLDBody += 9;
1756 }
1757 if( (pszValueMod && (strcasecmp(pszValueMod, "") != 0)) ||
1758 (pszSLD && (strcasecmp(pszSLD, "") != 0)) ||
1759 (pszSLDBody && (strcasecmp(pszSLDBody, "") != 0))) {
1760 /* Write Name and Title */
1761 msIO_fprintf( stream, " <StyleList>\n");
1762 msIO_fprintf( stream, " <Style current=\"1\">\n");
1763 if( pszValueMod && (strcasecmp(pszValueMod, "") != 0)) {
1764 pszEncodedVal = msEncodeHTMLEntities(pszValueMod);
1765 msIO_fprintf(stream, " <Name>%s</Name>\n",
1766 pszEncodedVal);
1767 msIO_fprintf(stream," <Title>%s</Title>\n",
1768 pszEncodedVal);
1769 msFree(pszEncodedVal);
1770 }
1771 /* Write the SLD string from the URL */
1772 if( pszSLD && (strcasecmp(pszSLD, "") != 0)) {
1773 pszEncodedVal = msEncodeHTMLEntities(pszSLD);
1774 msIO_fprintf( stream, " <SLD>\n" );
1775 msIO_fprintf( stream,
1776 " <OnlineResource xlink:type=\"simple\" ");
1777 msIO_fprintf(stream,"xlink:href=\"%s\"/>",
1778 pszEncodedVal);
1779 msIO_fprintf( stream, " </SLD>\n" );
1780 free(pszEncodedVal);
1781 } else if(pszSLDBody && (strcasecmp(pszSLDBody, "") != 0)) {
1782 msIO_fprintf( stream, " <SLD>\n" );
1783 msIO_fprintf( stream, " %s\n",pszSLDBody);
1784 msIO_fprintf( stream, " </SLD>\n" );
1785 }
1786 msIO_fprintf( stream, " </Style>\n");
1787 msIO_fprintf( stream, " </StyleList>\n");
1788 }
1789 if(pszSLD2) {
1790 free(pszSLD2);
1791 pszSLD2 = NULL;
1792 }
1793 }
1794 if(pszURL) {
1795 free(pszURL);
1796 pszURL = NULL;
1797 }
1798 } else {
1799 const char* pszCurrent;
1800 /* If the style information is not in the connection URL, */
1801 /* read the metadata. */
1802 pszValue = msLookupHashTable(&(GET_LAYER(map, i)->metadata),
1803 "wms_stylelist");
1804 pszCurrent = msLookupHashTable(&(GET_LAYER(map, i)->metadata),
1805 "wms_style");
1806 msIO_fprintf( stream, " <StyleList>\n");
1807 /* Loop in each style in the style list */
1808 while(pszValue != NULL) {
1809 pszStyle = msStrdup(pszValue);
1810 pszChar = strchr(pszStyle, ',');
1811 if(pszChar != NULL)
1812 pszStyle[pszChar - pszStyle] = '\0';
1813 if(strcasecmp(pszStyle, "") == 0)
1814 continue;
1815
1816 if(pszCurrent && (strcasecmp(pszStyle, pszCurrent) == 0))
1817 msIO_fprintf( stream," <Style current=\"1\">\n" );
1818 else
1819 msIO_fprintf( stream, " <Style>\n" );
1820
1821 /* Write SLDURL if it is in the metadata */
1822 pszStyleItem = (char*)malloc(strlen(pszStyle)+10+10);
1823 sprintf(pszStyleItem, "wms_style_%s_sld", pszStyle);
1824 if(msLookupHashTable(&(GET_LAYER(map, i)->metadata),
1825 pszStyleItem) != NULL) {
1826 msIO_fprintf(stream, " <SLD>\n");
1827 msOWSPrintEncodeMetadata(stream,
1828 &(GET_LAYER(map, i)->metadata),
1829 NULL, pszStyleItem,
1830 OWS_NOERR,
1831 " <OnlineResource xlink:type=\"simple\" xlink:href=\"%s\"/>\n",
1832 NULL);
1833 msIO_fprintf(stream, " </SLD>\n");
1834 free(pszStyleItem);
1835 } else {
1836 /* If the URL is not there, check for SLDBody */
1837 sprintf(pszStyleItem, "wms_style_%s_sld_body", pszStyle);
1838 if(msLookupHashTable(&(GET_LAYER(map, i)->metadata),
1839 pszStyleItem) != NULL) {
1840 msIO_fprintf(stream, " <SLD>\n");
1841 msOWSPrintMetadata(stream,&(GET_LAYER(map, i)->metadata),
1842 NULL, pszStyleItem, OWS_NOERR,
1843 " %s\n", NULL);
1844 msIO_fprintf(stream, " </SLD>\n");
1845 free(pszStyleItem);
1846 } else {
1847 /* If the SLD is not specified, then write the */
1848 /* name, Title and LegendURL */
1849 free(pszStyleItem);
1850 /* Name */
1851 pszEncodedVal = msEncodeHTMLEntities(pszStyle);
1852 msIO_fprintf(stream, " <Name>%s</Name>\n",
1853 pszEncodedVal);
1854 msFree(pszEncodedVal);
1855 pszStyleItem = (char*)malloc(strlen(pszStyle)+10+8);
1856 sprintf(pszStyleItem, "wms_style_%s_title",pszStyle);
1857 /* Title */
1858 msOWSPrintEncodeMetadata(stream,
1859 &(GET_LAYER(map, i)->metadata),
1860 NULL, pszStyleItem,
1861 OWS_NOERR,
1862 " <Title>%s</Title>\n",
1863 NULL);
1864 free(pszStyleItem);
1865
1866 /* LegendURL */
1867 pszStyleItem = (char*)malloc(strlen(pszStyle)+10+20);
1868 sprintf(pszStyleItem, "style_%s_legendurl",
1869 pszStyle);
1870 msOWSPrintURLType(stream, &(GET_LAYER(map, i)->metadata),
1871 "M", pszStyleItem, OWS_NOERR, NULL,
1872 "LegendURL", NULL, " width=\"%s\"",
1873 " height=\"%s\""," format=\"%s\"",
1874 " <OnlineResource "
1875 "xlink:type=\"simple\""
1876 " xlink:href=\"%s\"/>\n ",
1877 MS_FALSE, MS_FALSE, MS_FALSE,
1878 MS_FALSE, MS_TRUE, NULL, NULL,
1879 NULL, NULL, NULL, " ");
1880 free(pszStyleItem);
1881 }
1882 }
1883
1884 msIO_fprintf( stream," </Style>\n" );
1885
1886 free(pszStyle);
1887 pszValue = strchr(pszValue, ',');
1888 if(pszValue)
1889 pszValue++;
1890 }
1891 msIO_fprintf( stream, " </StyleList>\n");
1892 }
1893
1894 /* Dimension element */;
1895 pszCurrent = NULL;
1896
1897 pszValue = msLookupHashTable(&(GET_LAYER(map, i)->metadata),
1898 "wms_dimensionlist");
1899 pszCurrent = msLookupHashTable(&(GET_LAYER(map, i)->metadata),
1900 "wms_dimension");
1901 while(pszValue != NULL) {
1902 /* Extract the dimension name from the list */
1903 pszDimension = msStrdup(pszValue);
1904 pszChar = strchr(pszDimension, ',');
1905 if(pszChar != NULL)
1906 pszDimension[pszChar - pszDimension] = '\0';
1907 if(strcasecmp(pszDimension, "") == 0) {
1908 free(pszDimension);
1909 pszValue = strchr(pszValue, ',');
1910 if(pszValue)
1911 pszValue++;
1912 continue;
1913 }
1914
1915 /* From the dimension list, extract the required dimension */
1916 msOWSGetDimensionInfo(GET_LAYER(map, i), pszDimension,
1917 &pszDimUserValue, &pszDimUnits,
1918 &pszDimDefault, &pszDimNearValue,
1919 &pszDimUnitSymbol, &pszDimMultiValue);
1920
1921 if(pszDimUserValue == NULL || pszDimUnits == NULL ||
1922 pszDimUnitSymbol == NULL) {
1923 free(pszDimension);
1924 pszValue = strchr(pszValue, ',');
1925 if(pszValue)
1926 pszValue++;
1927 continue;
1928 }
1929
1930 if(!bDimensionList) {
1931 bDimensionList = 1;
1932 msIO_fprintf( stream, " <DimensionList>\n");
1933 }
1934
1935 /* name */
1936 msIO_fprintf( stream, " <Dimension name=\"%s\"",
1937 pszDimension);
1938 /* units */
1939 msIO_fprintf( stream, " units=\"%s\"", pszDimUnits);
1940 /* unitSymbol */
1941 msIO_fprintf( stream, " unitSymbol=\"%s\"", pszDimUnitSymbol);
1942 /* userValue */
1943 msIO_fprintf( stream, " userValue=\"%s\"", pszDimUserValue);
1944 /* default */
1945 if(pszDimDefault)
1946 msIO_fprintf( stream, " default=\"%s\"", pszDimDefault);
1947 /* multipleValues */
1948 if(pszDimMultiValue)
1949 msIO_fprintf(stream, " multipleValues=\"%s\"",
1950 pszDimMultiValue);
1951 /* nearestValue */
1952 if(pszDimNearValue)
1953 msIO_fprintf( stream," nearestValue=\"%s\"",pszDimNearValue);
1954
1955 if(pszCurrent && strcasecmp(pszDimension, pszCurrent) == 0)
1956 msIO_fprintf( stream, " current=\"1\"");
1957
1958 msIO_fprintf( stream, "/>\n");
1959
1960 free(pszDimension);
1961 pszValue = strchr(pszValue, ',');
1962 if(pszValue)
1963 pszValue++;
1964 }
1965
1966 if(bDimensionList) {
1967 msIO_fprintf( stream, " </DimensionList>\n");
1968 bDimensionList = 0;
1969 }
1970
1971 msIO_fprintf(stream, " </Layer>\n");
1972 }
1973 }
1974
1975 /* Close layer list */
1976 msIO_fprintf(stream, " </LayerList>\n");
1977 /* Close Map Context */
1978
1979 if(nVersion >= OWS_1_0_0) {
1980 msIO_fprintf(stream, "</ViewContext>\n");
1981 } else if(nVersion >= OWS_0_1_7) {
1982 msIO_fprintf(stream, "</View_Context>\n");
1983 } else { /* 0.1.4 */
1984 msIO_fprintf(stream, "</WMS_Viewer_Context>\n");
1985 }
1986
1987 return MS_SUCCESS;
1988 #else
1989 msSetError(MS_MAPCONTEXTERR,
1990 "Not implemented since Map Context is not enabled.",
1991 "msWriteMapContext()");
1992 return MS_FAILURE;
1993 #endif
1994 }
1995
1996
1997