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