root/tags/rel-5-0-2/mapserver/mapcontext.c

Revision 6983, 72.9 kB (checked in by assefa, 9 months ago)

Fixed crash when loading a context file (#2372)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /**********************************************************************
2  * $Id$
3  *
4  * Name:     mapcontext.c
5  * Project:  MapServer
6  * Language: C
7  * Purpose:  OGC Web Map Context implementation
8  * Author:   Julien-Samuel Lacroix, DM Solutions Group (lacroix@dmsolutions.ca)
9  *
10  **********************************************************************
11  * Copyright (c) 2002-2003, Julien-Samuel Lacroix, DM Solutions Group Inc
12  *
13  * Permission is hereby granted, free of charge, to any person obtaining a
14  * copy of this software and associated documentation files (the "Software"),
15  * to deal in the Software without restriction, including without limitation
16  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17  * and/or sell copies of the Software, and to permit persons to whom the
18  * Software is furnished to do so, subject to the following conditions:
19  *
20  * The above copyright notice and this permission notice shall be included in
21  * all copies of this Software or works derived from this Software.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
26  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29  ****************************************************************************/
30
31 #include "mapserver.h"
32
33 MS_CVSID("$Id$")
34
35 #if defined(USE_WMS_LYR) && defined(USE_OGR)
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 */
49 char * msGetMapContextFileText(char *filename)
50 {
51   char *pszBuffer;
52   FILE *stream;
53   int    nLength;
54  
55   /* open file */
56   if(filename != NULL && strlen(filename) > 0) {
57       stream = fopen(filename, "rb");
58       if(!stream) {
59           msSetError(MS_IOERR, "(%s)", "msGetMapContextFileText()", filename);
60           return NULL;
61       }
62   }
63   else
64   {
65       msSetError(MS_IOERR, "(%s)", "msGetMapContextFileText()", filename);
66       return NULL;
67   }
68
69   fseek( stream, 0, SEEK_END );
70   nLength = ftell( stream );
71   fseek( stream, 0, SEEK_SET );
72
73   pszBuffer = (char *) malloc(nLength+1);
74   if( pszBuffer == NULL )
75   {
76       msSetError(MS_MEMERR, "(%s)", "msGetMapContextFileText()", filename);
77       fclose( stream );
78       return NULL;
79   }
80  
81   if(fread( pszBuffer, nLength, 1, stream ) == 0 &&  !feof(stream))
82   {
83       free( pszBuffer );
84       fclose( stream );
85       msSetError(MS_IOERR, "(%s)", "msGetMapContextFileText()", filename);
86       return NULL;
87   }
88   pszBuffer[nLength] = '\0';
89
90   fclose( stream );
91
92   return pszBuffer;
93 }
94
95
96 #if defined(USE_WMS_LYR) && defined(USE_OGR)
97
98 /*
99 **msGetMapContextXMLHashValue()
100 **
101 **Get the xml value and put it in the hash table
102 **
103 */
104 int msGetMapContextXMLHashValue( CPLXMLNode *psRoot, const char *pszXMLPath,
105                                  hashTableObj *metadata, char *pszMetadata )
106 {
107   char *pszValue;
108
109   pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL);
110   if(pszValue != NULL)
111   {
112       if( metadata != NULL )
113       {
114           msInsertHashTable(metadata, pszMetadata, pszValue );
115       }
116       else
117       {
118           return MS_FAILURE;
119       }
120   }
121   else
122   {
123       return MS_FAILURE;
124   }
125
126   return MS_SUCCESS;
127 }
128
129 /*
130 **msGetMapContextXMLHashValue()
131 **
132 **Get the xml value and put it in the hash table
133 **
134 */
135 int msGetMapContextXMLHashValueDecode( CPLXMLNode *psRoot,
136                                        const char *pszXMLPath,
137                                        hashTableObj *metadata,
138                                        char *pszMetadata )
139 {
140   char *pszValue;
141
142   pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL);
143   if(pszValue != NULL)
144   {
145       if( metadata != NULL )
146       {
147           msDecodeHTMLEntities(pszValue);
148           msInsertHashTable(metadata, pszMetadata, pszValue );
149       }
150       else
151       {
152           return MS_FAILURE;
153       }
154   }
155   else
156   {
157       return MS_FAILURE;
158   }
159
160   return MS_SUCCESS;
161 }
162
163
164 /*
165 **msGetMapContextXMLStringValue()
166 **
167 **Get the xml value and put it in the string field
168 **
169 */
170 int msGetMapContextXMLStringValue( CPLXMLNode *psRoot, char *pszXMLPath,
171                                    char **pszField)
172 {
173   char *pszValue;
174
175   pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL);
176   if(pszValue != NULL)
177   {
178       if( pszField != NULL )
179       {
180            *pszField = strdup(pszValue);
181       }
182       else
183       {
184           return MS_FAILURE;
185       }
186   }
187   else
188   {
189       return MS_FAILURE;
190   }
191
192   return MS_SUCCESS;
193 }
194
195
196 /*
197 **msGetMapContextXMLStringValue()
198 **
199 **Get the xml value and put it in the string field
200 **
201 */
202 int msGetMapContextXMLStringValueDecode( CPLXMLNode *psRoot, char *pszXMLPath,
203                                          char **pszField)
204 {
205   char *pszValue;
206
207   pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL);
208   if(pszValue != NULL)
209   {
210       if( pszField != NULL )
211       {
212           msDecodeHTMLEntities(pszValue);
213           *pszField = strdup(pszValue);
214       }
215       else
216       {
217           return MS_FAILURE;
218       }
219   }
220   else
221   {
222       return MS_FAILURE;
223   }
224
225   return MS_SUCCESS;
226 }
227
228
229 /*
230 **msGetMapContextXMLFloatValue()
231 **
232 **Get the xml value and put it in the string field
233 **
234 */
235 int msGetMapContextXMLFloatValue( CPLXMLNode *psRoot, char *pszXMLPath,
236                                         double *pszField)
237 {
238   char *pszValue;
239
240   pszValue = (char*)CPLGetXMLValue( psRoot, pszXMLPath, NULL);
241   if(pszValue != NULL)
242   {
243       if( pszField != NULL )
244       {
245           *pszField = atof(pszValue);
246       }
247       else
248       {
249           return MS_FAILURE;
250       }
251   }
252   else
253   {
254       return MS_FAILURE;
255   }
256
257   return MS_SUCCESS;
258 }
259
260 /*
261 ** msLoadMapContextURLELements
262 **
263 ** Take a Node and get the width, height, format and href from it.
264 ** Then put this info in metadatas.
265 */
266 int msLoadMapContextURLELements( CPLXMLNode *psRoot, hashTableObj *metadata,
267                                  const char *pszMetadataRoot)
268 {
269   char *pszMetadataName;
270
271   if( psRoot == NULL || metadata == NULL || pszMetadataRoot == NULL )
272       return MS_FAILURE;
273
274   pszMetadataName = (char*) malloc( strlen(pszMetadataRoot) + 10 );
275
276   sprintf( pszMetadataName, "%s_width", pszMetadataRoot );
277   msGetMapContextXMLHashValue( psRoot, "width", metadata, pszMetadataName );
278
279   sprintf( pszMetadataName, "%s_height", pszMetadataRoot );
280   msGetMapContextXMLHashValue( psRoot, "height", metadata, pszMetadataName );
281
282   sprintf( pszMetadataName, "%s_format", pszMetadataRoot );
283   msGetMapContextXMLHashValue( psRoot, "format", metadata, pszMetadataName );
284
285   sprintf( pszMetadataName, "%s_href", pszMetadataRoot );
286   msGetMapContextXMLHashValue( psRoot, "OnlineResource.xlink:href", metadata,
287                                pszMetadataName );
288
289   free(pszMetadataName);
290
291   return MS_SUCCESS;
292 }
293
294 /* msLoadMapContextKeyword
295 **
296 ** Put the keywords from a XML node and put them in a metadata.
297 ** psRoot should be set to keywordlist
298 */
299 int msLoadMapContextListInMetadata( CPLXMLNode *psRoot, hashTableObj *metadata,
300                                     char *pszXMLName, char *pszMetadataName,
301                                     char *pszHashDelimiter)
302 {
303   char *pszHash, *pszXMLValue, *pszMetadata;
304
305   if(psRoot == NULL || psRoot->psChild == NULL ||
306      metadata == NULL || pszMetadataName == NULL || pszXMLName == NULL)
307       return MS_FAILURE;
308
309   /* Pass from KeywordList to Keyword level */
310   psRoot = psRoot->psChild;
311
312   /* Loop on all elements and append keywords to the hash table */
313   while (psRoot)
314   {
315       if (psRoot->psChild && strcasecmp(psRoot->pszValue, pszXMLName) == 0)
316       {
317           pszXMLValue = psRoot->psChild->pszValue;
318           pszHash = msLookupHashTable(metadata, pszMetadataName);
319           if (pszHash != NULL)
320           {
321               pszMetadata = (char*)malloc(strlen(pszHash)+
322                                           strlen(pszXMLValue)+2);
323               if(pszHashDelimiter == NULL)
324                   sprintf( pszMetadata, "%s%s", pszHash, pszXMLValue );
325               else
326                   sprintf( pszMetadata, "%s%s%s", pszHash, pszHashDelimiter,
327                            pszXMLValue );
328               msInsertHashTable(metadata, pszMetadataName, pszMetadata);
329               free(pszMetadata);
330           }
331           else
332               msInsertHashTable(metadata, pszMetadataName, pszXMLValue);
333       }
334       psRoot = psRoot->psNext;   
335   }
336
337   return MS_SUCCESS;
338 }
339
340 /* msLoadMapContextContactInfo
341 **
342 ** Put the Contact informations from a XML node and put them in a metadata.
343 **
344 */
345 int msLoadMapContextContactInfo( CPLXMLNode *psRoot, hashTableObj *metadata )
346 {
347     if(psRoot == NULL || metadata == NULL)
348         return MS_FAILURE;
349
350     /* Contact Person primary */
351     msGetMapContextXMLHashValue(psRoot,
352                               "ContactPersonPrimary.ContactPerson",
353                               metadata, "wms_contactperson");
354   msGetMapContextXMLHashValue(psRoot,
355                               "ContactPersonPrimary.ContactOrganization",
356                               metadata, "wms_contactorganization");
357   /* Contact Position */
358   msGetMapContextXMLHashValue(psRoot,
359                               "ContactPosition",
360                               metadata, "wms_contactposition");
361   /* Contact Address */
362   msGetMapContextXMLHashValue(psRoot, "ContactAddress.AddressType",
363                               metadata, "wms_addresstype");
364   msGetMapContextXMLHashValue(psRoot, "ContactAddress.Address",
365                               metadata, "wms_address");
366   msGetMapContextXMLHashValue(psRoot, "ContactAddress.City",
367                               metadata, "wms_city");
368   msGetMapContextXMLHashValue(psRoot, "ContactAddress.StateOrProvince",
369                               metadata, "wms_stateorprovince");
370   msGetMapContextXMLHashValue(psRoot, "ContactAddress.PostCode",
371                               metadata, "wms_postcode");
372   msGetMapContextXMLHashValue(psRoot, "ContactAddress.Country",
373                               metadata, "wms_country");
374
375   /* Others */
376   msGetMapContextXMLHashValue(psRoot, "ContactVoiceTelephone",
377                               metadata, "wms_contactvoicetelephone");
378   msGetMapContextXMLHashValue(psRoot, "ContactFacsimileTelephone",
379                               metadata, "wms_contactfacsimiletelephone");
380   msGetMapContextXMLHashValue(psRoot, "ContactElectronicMailAddress",
381                               metadata, "wms_contactelectronicmailaddress");
382
383   return MS_SUCCESS;
384 }
385
386 /*
387 ** msLoadMapContextLayerFormat
388 **
389 **
390 */
391 int msLoadMapContextLayerFormat(CPLXMLNode *psFormat, layerObj *layer)
392 {
393   char *pszValue, *pszValue1, *pszHash;
394
395   if(psFormat->psChild != NULL &&
396      strcasecmp(psFormat->pszValue, "Format") == 0 )
397   {
398       if(psFormat->psChild->psNext == NULL)
399           pszValue = psFormat->psChild->pszValue;
400       else
401           pszValue = psFormat->psChild->psNext->pszValue;
402   }
403   else
404       pszValue = NULL;
405
406   if(pszValue != NULL && strcasecmp(pszValue, "") != 0)
407   {
408       /* wms_format */
409       pszValue1 = (char*)CPLGetXMLValue(psFormat,
410                                         "current", NULL);
411       if(pszValue1 != NULL &&
412          (strcasecmp(pszValue1, "1") == 0 || strcasecmp(pszValue1, "true")==0))
413           msInsertHashTable(&(layer->metadata),
414                             "wms_format", pszValue);
415       /* wms_formatlist */
416       pszHash = msLookupHashTable(&(layer->metadata),
417                                   "wms_formatlist");
418       if(pszHash != NULL)
419       {
420           pszValue1 = (char*)malloc(strlen(pszHash)+
421                                     strlen(pszValue)+2);
422           sprintf(pszValue1, "%s,%s", pszHash, pszValue);
423           msInsertHashTable(&(layer->metadata),
424                             "wms_formatlist", pszValue1);
425           free(pszValue1);
426       }
427       else
428           msInsertHashTable(&(layer->metadata),
429                             "wms_formatlist", pszValue);
430   }
431
432   /* Make sure selected format is supported or select another
433    * supported format.  Note that we can efficiently do this
434    * only for GIF/PNG/JPEG, can't try to handle all GDAL
435    * formats.
436    */
437   pszValue = msLookupHashTable(&(layer->metadata), "wms_format");
438
439   if (
440 #ifndef USE_GD_PNG
441       strcasecmp(pszValue, "image/png") == 0 ||
442       strcasecmp(pszValue, "PNG") == 0 ||
443 #endif
444 #ifndef USE_GD_JPEG
445       strcasecmp(pszValue, "image/jpeg") == 0 ||
446       strcasecmp(pszValue, "JPEG") == 0 ||
447 #endif
448 #ifndef USE_GD_GIF
449       strcasecmp(pszValue, "image/gif") == 0 ||
450       strcasecmp(pszValue, "GIF") == 0 ||
451 #endif
452       0 )
453   {
454       char **papszList=NULL;
455       int i, numformats=0;
456
457       pszValue = msLookupHashTable(&(layer->metadata),
458                                    "wms_formatlist");
459
460       papszList = msStringSplit(pszValue, ',', &numformats);
461       for(i=0; i < numformats; i++)
462       {
463           if (
464 #ifdef USE_GD_PNG
465               strcasecmp(papszList[i], "image/png") == 0 ||
466               strcasecmp(papszList[i], "PNG") == 0 ||
467 #endif
468 #ifdef USE_GD_JPEG
469               strcasecmp(papszList[i], "image/jpeg") == 0 ||
470               strcasecmp(papszList[i], "JPEG") == 0 ||
471 #endif
472 #ifdef USE_GD_GIF
473               strcasecmp(papszList[i], "image/gif") == 0 ||
474               strcasecmp(papszList[i], "GIF") == 0 ||
475 #endif
476               0 )
477           {
478               /* Found a match */
479               msInsertHashTable(&(layer->metadata),
480                                 "wms_format", papszList[i]);
481               break;
482           }
483       }
484       if(papszList)
485           msFreeCharArray(papszList, numformats);
486
487   } /* end if unsupported format */
488
489   return MS_SUCCESS;
490 }
491
492 int msLoadMapContextLayerStyle(CPLXMLNode *psStyle, layerObj *layer,
493                                int nStyle)
494 {
495   char *pszValue, *pszValue1, *pszValue2;
496   char *pszHash, *pszStyle=NULL, *pszStyleName;
497   CPLXMLNode *psStyleSLDBody;
498
499   pszStyleName =(char*)CPLGetXMLValue(psStyle,"Name",NULL);
500   if(pszStyleName == NULL)
501   {
502        pszStyleName = (char*)malloc(15);
503        sprintf(pszStyleName, "Style{%d}", nStyle);
504   }
505   else
506       pszStyleName = strdup(pszStyleName);
507
508   /* wms_style */
509   pszValue = (char*)CPLGetXMLValue(psStyle,"current",NULL);
510   if(pszValue != NULL &&
511      (strcasecmp(pszValue, "1") == 0 ||
512       strcasecmp(pszValue, "true") == 0))
513       msInsertHashTable(&(layer->metadata),
514                         "wms_style", pszStyleName);
515   /* wms_stylelist */
516   pszHash = msLookupHashTable(&(layer->metadata),
517                               "wms_stylelist");
518   if(pszHash != NULL)
519   {
520       pszValue1 = (char*)malloc(strlen(pszHash)+
521                                 strlen(pszStyleName)+2);
522       sprintf(pszValue1, "%s,%s", pszHash, pszStyleName);
523       msInsertHashTable(&(layer->metadata),
524                         "wms_stylelist", pszValue1);
525       free(pszValue1);
526   }
527   else
528       msInsertHashTable(&(layer->metadata),
529                         "wms_stylelist", pszStyleName);
530
531   /* Title */
532   pszStyle = (char*)malloc(strlen(pszStyleName)+20);
533   sprintf(pszStyle,"wms_style_%s_title",pszStyleName);
534
535   if( msGetMapContextXMLHashValue(psStyle, "Title", &(layer->metadata),
536                                   pszStyle) == MS_FAILURE )
537       msInsertHashTable(&(layer->metadata), pszStyle, layer->name);
538
539   free(pszStyle);
540
541   /* SLD */
542   pszStyle = (char*)malloc(strlen(pszStyleName)+15);
543   sprintf(pszStyle, "wms_style_%s_sld", pszStyleName);
544  
545   msGetMapContextXMLHashValueDecode( psStyle, "SLD.OnlineResource.xlink:href",
546                                      &(layer->metadata), pszStyle );
547   free(pszStyle);
548
549   /* SLDBODY */
550   pszStyle = (char*)malloc(strlen(pszStyleName)+20);
551   sprintf(pszStyle, "wms_style_%s_sld_body", pszStyleName);
552
553   psStyleSLDBody = CPLGetXMLNode(psStyle, "SLD.StyledLayerDescriptor");
554   if(psStyleSLDBody != NULL && &(layer->metadata) != NULL)
555   {
556       pszValue = CPLSerializeXMLTree(psStyleSLDBody);
557       if(pszValue != NULL)
558       {
559           /* Before including SLDBody in the mapfile, we must replace the */
560           /* double quote for single quote. This is to prevent having this: */
561           /* "metadata" "<string attriute="ttt">" */
562           char *c;
563           for(c=pszValue; *c != '\0'; c++)
564               if(*c == '"')
565                   *c = '\'';
566           msInsertHashTable(&(layer->metadata), pszStyle, pszValue );
567           msFree(pszValue);
568       }
569   }
570
571   free(pszStyle);
572
573   /* LegendURL */
574   pszStyle = (char*) malloc(strlen(pszStyleName) + 25);
575
576   sprintf( pszStyle, "wms_style_%s_legendurl",
577            pszStyleName);
578   msLoadMapContextURLELements( CPLGetXMLNode(psStyle, "LegendURL"),
579                                &(layer->metadata), pszStyle );
580
581   free(pszStyle);
582
583   free(pszStyleName);
584
585   /*  */
586   /* Add the stylelist to the layer connection */
587   /*  */
588   if(msLookupHashTable(&(layer->metadata),
589                        "wms_stylelist") == NULL)
590   {
591       if(layer->connection)
592           pszValue = strdup(layer->connection);
593       else
594           pszValue = strdup( "" );
595       pszValue1 = strstr(pszValue, "STYLELIST=");
596       if(pszValue1 != NULL)
597       {                         
598           pszValue1 += 10;
599           pszValue2 = strchr(pszValue, '&');
600           if(pszValue2 != NULL)
601               pszValue1[pszValue2-pszValue1] = '\0';
602           msInsertHashTable(&(layer->metadata), "wms_stylelist",
603                             pszValue1);
604       }
605       free(pszValue);
606   }
607
608   /*  */
609   /* Add the style to the layer connection */
610   /*  */
611   if(msLookupHashTable(&(layer->metadata), "wms_style") == NULL)
612   {
613       if(layer->connection)
614           pszValue = strdup(layer->connection);
615       else
616           pszValue = strdup( "" );
617       pszValue1 = strstr(pszValue, "STYLE=");
618       if(pszValue1 != NULL)
619       {                         
620           pszValue1 += 6;
621           pszValue2 = strchr(pszValue, '&');
622           if(pszValue2 != NULL)
623               pszValue1[pszValue2-pszValue1] = '\0';
624           msInsertHashTable(&(layer->metadata), "wms_style",
625                             pszValue1);
626       }
627       free(pszValue);
628   }
629
630   return MS_SUCCESS;
631 }
632
633 int msLoadMapContextLayerDimension(CPLXMLNode *psDimension, layerObj *layer)
634 {
635     char *pszValue, *pszHash;
636   char *pszDimension=NULL, *pszDimensionName=NULL;
637
638   pszDimensionName =(char*)CPLGetXMLValue(psDimension,"name",NULL);
639   if(pszDimensionName == NULL)
640   {
641       return MS_FALSE;
642   }
643   else
644       pszDimensionName = strdup(pszDimensionName);
645
646   pszDimension = (char*)malloc(strlen(pszDimensionName)+50);
647
648   /* wms_dimension: This is the current dimension */
649   pszValue = (char*)CPLGetXMLValue(psDimension, "current", NULL);
650   if(pszValue != NULL && (strcasecmp(pszValue, "1") == 0 ||
651                           strcasecmp(pszValue, "true") == 0))
652       msInsertHashTable(&(layer->metadata),
653                         "wms_dimension", pszDimensionName);
654   /* wms_dimensionlist */
655   pszHash = msLookupHashTable(&(layer->metadata),
656                               "wms_dimensionlist");
657   if(pszHash != NULL)
658   {
659       pszValue = (char*)malloc(strlen(pszHash)+
660                                 strlen(pszDimensionName)+2);
661       sprintf(pszValue, "%s,%s", pszHash, pszDimensionName);
662       msInsertHashTable(&(layer->metadata),
663                         "wms_dimensionlist", pszValue);
664       free(pszValue);
665   }
666   else
667       msInsertHashTable(&(layer->metadata),
668                         "wms_dimensionlist", pszDimensionName);
669
670   /* Units */
671   sprintf(pszDimension, "wms_dimension_%s_units", pszDimensionName);
672   msGetMapContextXMLHashValue(psDimension, "units", &(layer->metadata),
673                               pszDimension);
674
675   /* UnitSymbol */
676   sprintf(pszDimension, "wms_dimension_%s_unitsymbol", pszDimensionName);
677   msGetMapContextXMLHashValue(psDimension, "unitSymbol", &(layer->metadata),
678                               pszDimension);
679
680   /* userValue */
681   sprintf(pszDimension, "wms_dimension_%s_uservalue", pszDimensionName);
682   msGetMapContextXMLHashValue(psDimension, "userValue", &(layer->metadata),
683                               pszDimension);
684   if(strcasecmp(pszDimensionName, "time") == 0)
685       msGetMapContextXMLHashValue(psDimension, "userValue", &(layer->metadata),
686                                   "wms_time");
687
688   /* default */
689   sprintf(pszDimension, "wms_dimension_%s_default", pszDimensionName);
690   msGetMapContextXMLHashValue(psDimension, "default", &(layer->metadata),
691                               pszDimension);
692
693   /* multipleValues */
694   sprintf(pszDimension, "wms_dimension_%s_multiplevalues", pszDimensionName);
695   msGetMapContextXMLHashValue(psDimension, "multipleValues",&(layer->metadata),
696                               pszDimension);
697
698   /* nearestValue */
699   sprintf(pszDimension, "wms_dimension_%s_nearestvalue", pszDimensionName);
700   msGetMapContextXMLHashValue(psDimension, "nearestValue", &(layer->metadata),
701                               pszDimension);
702
703   free(pszDimension);
704
705   free(pszDimensionName);
706
707   return MS_SUCCESS;
708 }
709
710
711
712 /*
713 ** msLoadMapContextGeneral
714 **
715 ** Load the General block of the mapcontext document
716 */
717 int msLoadMapContextGeneral(mapObj *map, CPLXMLNode *psGeneral,
718                             CPLXMLNode *psMapContext, int nVersion,
719                             char *filename)
720 {
721
722   char *pszProj=NULL;
723   char *pszValue, *pszValue1, *pszValue2;
724
725   /* Projection */
726   pszValue = (char*)CPLGetXMLValue(psGeneral,
727                                    "BoundingBox.SRS", NULL);
728   if(pszValue != NULL)
729   {
730       if(strncasecmp(pszValue, "AUTO:", 5) == 0)
731       {
732           pszProj = strdup(pszValue);
733       }
734       else
735       {
736           pszProj = (char*) malloc(sizeof(char)*(strlen(pszValue)+10));
737           sprintf(pszProj, "init=epsg:%s", pszValue+5);
738       }
739
740       msInitProjection(&map->projection);
741       map->projection.args[map->projection.numargs] = strdup(pszProj);
742       map->projection.numargs++;
743       msProcessProjection(&map->projection);
744
745       if( (map->units = GetMapserverUnitUsingProj(&(map->projection))) == -1)
746       {
747           free(pszProj);
748           msSetError( MS_MAPCONTEXTERR,
749                       "Unable to set units for projection '%s'",
750                       "msLoadMapContext()", pszProj );
751           return MS_FAILURE;
752       }
753       free(pszProj);
754   }
755   else
756   {
757       msDebug("Mandatory data General.BoundingBox.SRS missing in %s.",
758               filename);
759   }
760
761   /* Extent */
762   if( msGetMapContextXMLFloatValue(psGeneral, "BoundingBox.minx",
763                                    &(map->extent.minx)) == MS_FAILURE)
764   {
765       msDebug("Mandatory data General.BoundingBox.minx missing in %s.",
766               filename);
767   }
768   if( msGetMapContextXMLFloatValue(psGeneral, "BoundingBox.miny",
769                                &(map->extent.miny)) == MS_FAILURE)
770   {
771       msDebug("Mandatory data General.BoundingBox.miny missing in %s.",
772               filename);
773   }
774   if( msGetMapContextXMLFloatValue(psGeneral, "BoundingBox.maxx",
775                                &(map->extent.maxx)) == MS_FAILURE)
776   {
777       msDebug("Mandatory data General.BoundingBox.maxx missing in %s.",
778               filename);
779   }
780   if( msGetMapContextXMLFloatValue(psGeneral, "BoundingBox.maxy",
781                                &(map->extent.maxy)) == MS_FAILURE)
782   {
783       msDebug("Mandatory data General.BoundingBox.maxy missing in %s.",
784               filename);
785   }
786
787   /* Title */
788   if( msGetMapContextXMLHashValue(psGeneral, "Title",
789                               &(map->web.metadata), "wms_title") == MS_FAILURE)
790   {
791       if ( nVersion >= OWS_1_0_0 )
792          msDebug("Mandatory data General.Title missing in %s.", filename);
793       else
794       {
795           if( msGetMapContextXMLHashValue(psGeneral, "gml:name",
796                              &(map->web.metadata), "wms_title") == MS_FAILURE )
797           {
798               if( nVersion < OWS_0_1_7 )
799                 msDebug("Mandatory data General.Title missing in %s.", filename);
800               else
801                 msDebug("Mandatory data General.gml:name missing in %s.",
802                         filename);
803           }
804       }
805   }
806
807   /* Name */
808   if( nVersion >= OWS_1_0_0 )
809   {
810       pszValue = (char*)CPLGetXMLValue(psMapContext,
811                                        "id", NULL);
812       if (pszValue)
813         map->name = strdup(pszValue);
814   }
815   else
816   {
817       if(msGetMapContextXMLStringValue(psGeneral, "Name",
818                                        &(map->name)) == MS_FAILURE)
819       {
820           msGetMapContextXMLStringValue(psGeneral, "gml:name",
821                                         &(map->name));
822       }
823   }
824   /* Keyword */
825   if( nVersion >= OWS_1_0_0 )
826   {
827       msLoadMapContextListInMetadata(
828           CPLGetXMLNode(psGeneral, "KeywordList"),
829           &(map->web.metadata), "KEYWORD", "wms_keywordlist", "," );
830   }
831   else
832     msGetMapContextXMLHashValue(psGeneral, "Keywords",
833                                 &(map->web.metadata), "wms_keywordlist");
834
835   /* Window */
836   pszValue1 = (char*)CPLGetXMLValue(psGeneral,"Window.width",NULL);
837   pszValue2 = (char*)CPLGetXMLValue(psGeneral,"Window.height",NULL);
838   if(pszValue1 != NULL && pszValue2 != NULL)
839   {
840       map->width = atoi(pszValue1);
841       map->height = atoi(pszValue2);
842   }
843
844   /* Abstract */
845   if( msGetMapContextXMLHashValue( psGeneral,
846                                    "Abstract", &(map->web.metadata),
847                                    "wms_abstract") == MS_FAILURE )
848   {
849       msGetMapContextXMLHashValue( psGeneral, "gml:description",
850                                    &(map->web.metadata), "wms_abstract");
851   }
852
853   /* DataURL */
854   msGetMapContextXMLHashValueDecode(psGeneral,
855                                    "DataURL.OnlineResource.xlink:href",
856                                    &(map->web.metadata), "wms_dataurl");
857
858   /* LogoURL */
859   /* The logourl have a width, height, format and an URL */
860   msLoadMapContextURLELements( CPLGetXMLNode(psGeneral, "LogoURL"),
861                                &(map->web.metadata), "wms_logourl" );
862
863   /* DescriptionURL */
864   /* The descriptionurl have a width, height, format and an URL */
865   msLoadMapContextURLELements( CPLGetXMLNode(psGeneral,
866                                              "DescriptionURL"),
867                                &(map->web.metadata), "wms_descriptionurl" );
868
869   /* Contact Info */
870   msLoadMapContextContactInfo(
871       CPLGetXMLNode(psGeneral, "ContactInformation"),
872       &(map->web.metadata) );
873
874   return MS_SUCCESS;
875 }
876
877 /*
878 ** msLoadMapContextLayer
879 **
880 ** Load a Layer block from a MapContext document
881 */
882 int msLoadMapContextLayer(mapObj *map, CPLXMLNode *psLayer, int nVersion,
883                           char *filename, int unique_layer_names)
884 {
885   char *pszProj=NULL;
886   char *pszValue;
887   char *pszHash, *pszName=NULL;
888   CPLXMLNode *psFormatList, *psFormat, *psStyleList, *psStyle;
889   CPLXMLNode *psDimensionList, *psDimension;
890   int nStyle;
891   layerObj *layer;
892
893   /* Init new layer */
894   if(msGrowMapLayers(map) == NULL)
895     return MS_FAILURE;
896   layer = (GET_LAYER(map, map->numlayers));
897   initLayer(layer, map);
898   layer->map = (mapObj *)map;
899   layer->type = MS_LAYER_RASTER;
900   /* save the index */
901   GET_LAYER(map, map->numlayers)->index = map->numlayers;
902   map->layerorder[map->numlayers] = map->numlayers;
903   map->numlayers++;
904  
905  
906   /* Status */
907   pszValue = (char*)CPLGetXMLValue(psLayer, "hidden", "1");
908   if((pszValue != NULL) && (atoi(pszValue) == 0 &&
909                             !strcasecmp(pszValue, "true") == 0))
910       layer->status = MS_ON;
911   else
912       layer->status = MS_OFF;
913
914   /* Queryable */
915   pszValue = (char*)CPLGetXMLValue(psLayer, "queryable", "0");
916   if(pszValue !=NULL && (atoi(pszValue) == 1  ||
917                          strcasecmp(pszValue, "true") == 0))
918       layer->template = strdup("ttt");
919
920   /* Name and Title */
921   pszValue = (char*)CPLGetXMLValue(psLayer, "Name", NULL);
922   if(pszValue != NULL)
923   {
924       msInsertHashTable( &(layer->metadata), "wms_name", pszValue );
925
926       if (unique_layer_names)
927       {
928           pszName = (char*)malloc(sizeof(char)*(strlen(pszValue)+10));
929           sprintf(pszName, "l%d:%s", layer->index, pszValue);
930           layer->name = strdup(pszName);
931           free(pszName);
932       }
933       else
934         layer->name  = strdup(pszValue);
935   }
936   else