1
/**********************************************************************
2
* $Id: mapwfs11.c 9498 2009-10-20 13:38:46Z aboudreault $
5
* Purpose: OGC WFS 1.1.0 implementation. This file holds some WFS 1.1.0
6
* specific functions but other parts are still implemented in mapwfs.c.
7
* Author: Y. Assefa, DM Solutions Group (assefa@dmsolutions.ca)
9
**********************************************************************
10
* Copyright (c) 2008, Y. Assefa, DM Solutions Group Inc
12
* Permission is hereby granted, free of charge, to any person obtaining a
13
* copy of this software and associated documentation files (the "Software"),
14
* to deal in the Software without restriction, including without limitation
15
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
16
* and/or sell copies of the Software, and to permit persons to whom the
17
* Software is furnished to do so, subject to the following conditions:
19
* The above copyright notice and this permission notice shall be included in
20
* all copies of this Software or works derived from this Software.
22
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28
****************************************************************************/
30
#include "mapserver.h"
33
MS_CVSID("$Id: mapwfs11.c 9498 2009-10-20 13:38:46Z aboudreault $")
35
#if defined(USE_WFS_SVR) && defined(USE_LIBXML2)
36
#include "maplibxml2.h"
37
#include "mapowscommon.h"
38
#include "mapogcfilter.h"
41
int msWFSException11(mapObj *map, const char *locator,
42
const char *exceptionCode, const char *version)
45
char *errorString = NULL;
46
char *errorMessage = NULL;
47
char *schemasLocation = NULL;
50
xmlDocPtr psDoc = NULL;
51
xmlNodePtr psRootNode = NULL;
52
xmlNsPtr psNsOws = NULL;
53
xmlChar *buffer = NULL;
58
psNsOws = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/ows", BAD_CAST "ows");
60
encoding = msOWSLookupMetadata(&(map->web.metadata), "FO", "encoding");
62
errorString = msGetErrorString("\n");
63
errorMessage = msEncodeHTMLEntities(errorString);
64
schemasLocation = msEncodeHTMLEntities(msOWSGetSchemasLocation(map));
66
psDoc = xmlNewDoc(BAD_CAST "1.0");
68
psRootNode = msOWSCommonExceptionReport(psNsOws, OWS_1_0_0, schemasLocation, version, msOWSGetLanguage(map, "exception"), exceptionCode, locator, errorMessage);
70
xmlDocSetRootElement(psDoc, psRootNode);
72
psNsOws = xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/ows", BAD_CAST "ows");
75
msIO_printf("Content-type: text/xml; charset=%s%c%c", encoding,10,10);
77
msIO_printf("Content-type: text/xml%c%c",10,10);
79
xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, (encoding ? encoding : "ISO-8859-1"), 1);
81
msIO_printf("%s", buffer);
83
/*free buffer and the document */
86
free(schemasLocation);
90
/* clear error since we have already reported it */
97
/************************************************************************/
98
/* msWFSDumpLayer11 */
99
/************************************************************************/
100
static xmlNodePtr msWFSDumpLayer11(mapObj *map, layerObj *lp, xmlNsPtr psNsOws)
104
xmlNodePtr psRootNode, psNode;
105
const char *value = NULL;
107
psRootNode = xmlNewNode(NULL, BAD_CAST "FeatureType");
109
psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Name", BAD_CAST lp->name);
111
if (lp->name && strlen(lp->name) > 0 &&
112
(msIsXMLTagValid(lp->name) == MS_FALSE || isdigit(lp->name[0])))
113
xmlAddSibling(psNode,
114
xmlNewComment(BAD_CAST "WARNING: The layer name '%s' might contain spaces or "
115
"invalid characters or may start with a number. This could lead to potential problems"));
117
value = msOWSLookupMetadata(&(lp->metadata), "FO", "title");
119
psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Title", BAD_CAST value);
121
psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Title", BAD_CAST lp->name);
124
value = msOWSLookupMetadata(&(lp->metadata), "FO", "abstract");
126
psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Abstract", BAD_CAST value);
129
value = msOWSLookupMetadata(&(lp->metadata), "FO", "keywordlist");
132
msLibXml2GenerateList(
133
xmlNewChild(psRootNode, psNsOws, BAD_CAST "Keywords", NULL),
134
NULL, "Keyword", value, ',' );
136
/*srs only supposrt DefaultSRS with the same logic as for wfs1.0
137
TODO support OtherSRS*/
138
value = msOWSGetEPSGProj(&(map->projection),&(map->web.metadata),"FO",MS_TRUE);
140
value = msOWSGetEPSGProj(&(lp->projection), &(lp->metadata), "FO", MS_TRUE);
142
psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "DefaultSRS", BAD_CAST value);
144
xmlAddSibling(psNode,
145
xmlNewComment(BAD_CAST "WARNING: Mandatory mapfile parameter: (at least one of) MAP.PROJECTION, LAYER.PROJECTION or wfs/ows_srs metadata was missing in this context."));
147
/*TODO: adevertize only gml3?*/
148
psNode = xmlNewNode(NULL, BAD_CAST "OutputFormats");
149
xmlAddChild(psRootNode, psNode);
150
xmlNewChild(psNode, NULL, BAD_CAST "Format", BAD_CAST "text/xml; subtype=gml/3.1.1");
153
if (msOWSGetLayerExtent(map, lp, "FO", &ext) == MS_SUCCESS)
155
/*convert to latlong*/
156
if (lp->projection.numargs > 0)
158
if (!pj_is_latlong(&lp->projection.proj))
159
msProjectRect(&lp->projection, NULL, &ext);
161
else if (map->projection.numargs > 0 && !pj_is_latlong(&map->projection.proj))
162
msProjectRect(&map->projection, NULL, &ext);
164
xmlAddChild(psRootNode,
165
msOWSCommonWGS84BoundingBox( psNsOws, 2,
167
ext.maxx, ext.maxy));
171
xmlNewChild(psRootNode, psNsOws, BAD_CAST "WGS84BoundingBox", NULL);
172
xmlAddSibling(psNode,
173
xmlNewComment(BAD_CAST "WARNING: Optional WGS84BoundingBox could not be established for this layer. Consider setting the EXTENT in the LAYER object, or wfs_extent metadata. Also check that your data exists in the DATA statement"));
176
value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_href");
180
psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "MetadataURL", BAD_CAST value);
182
value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_format");
185
value = strdup("text/html"); /* default */
187
xmlNewProp(psNode, BAD_CAST "format", BAD_CAST value);
189
value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_type");
192
value = strdup("FGDC"); /* default */
194
xmlNewProp(psNode, BAD_CAST "type", BAD_CAST value);
200
/************************************************************************/
201
/* msWFSGetCapabilities11 */
203
/* Return the capabilities document for wfs 1.1.0 */
204
/************************************************************************/
205
int msWFSGetCapabilities11(mapObj *map, wfsParamsObj *params,
208
xmlDocPtr psDoc = NULL; /* document pointer */
209
xmlNodePtr psRootNode, psMainNode, psNode, psFtNode;
210
xmlNodePtr psTmpNode;
211
const char *updatesequence=NULL;
212
xmlNsPtr psNsOws, psNsXLink, psNsOgc;
213
char *schemalocation = NULL;
214
char *xsi_schemaLocation = NULL;
216
char *script_url=NULL, *script_url_encoded=NULL;
217
const char *value = NULL;
218
const char *encoding;
220
xmlChar *buffer = NULL;
222
msIOContext *context = NULL;
224
int ows_version = OWS_1_0_0;
226
/* -------------------------------------------------------------------- */
227
/* Handle updatesequence */
228
/* -------------------------------------------------------------------- */
230
updatesequence = msOWSLookupMetadata(&(map->web.metadata), "FO", "updatesequence");
232
encoding = msOWSLookupMetadata(&(map->web.metadata), "FO", "encoding");
234
if (params->pszUpdateSequence != NULL) {
235
i = msOWSNegotiateUpdateSequence(params->pszUpdateSequence, updatesequence);
236
if (i == 0) { /* current */
237
msSetError(MS_WFSERR, "UPDATESEQUENCE parameter (%s) is equal to server (%s)", "msWFSGetCapabilities11()", params->pszUpdateSequence, updatesequence);
238
return msWFSException11(map, "updatesequence", "CurrentUpdateSequence", params->pszVersion);
240
if (i > 0) { /* invalid */
241
msSetError(MS_WFSERR, "UPDATESEQUENCE parameter (%s) is higher than server (%s)", "msWFSGetCapabilities11()", params->pszUpdateSequence, updatesequence);
242
return msWFSException11(map, "updatesequence", "InvalidUpdateSequence", params->pszVersion);
247
/* -------------------------------------------------------------------- */
248
/* Create document. */
249
/* -------------------------------------------------------------------- */
250
psDoc = xmlNewDoc(BAD_CAST "1.0");
252
psRootNode = xmlNewNode(NULL, BAD_CAST "WFS_Capabilities");
254
xmlDocSetRootElement(psDoc, psRootNode);
256
/* -------------------------------------------------------------------- */
258
/* -------------------------------------------------------------------- */
259
/*default name space*/
260
xmlNewProp(psRootNode, BAD_CAST "xmlns", BAD_CAST "http://www.opengis.net/wfs");
262
xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml"));
263
xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/wfs", BAD_CAST "wfs"));
265
psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX);
266
psNsXLink = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_PREFIX);
267
xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_PREFIX);
268
xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_PREFIX );
270
xmlNewProp(psRootNode, BAD_CAST "version", BAD_CAST params->pszVersion );
272
updatesequence = msOWSLookupMetadata(&(map->web.metadata), "FO", "updatesequence");
275
xmlNewProp(psRootNode, BAD_CAST "updateSequence", BAD_CAST updatesequence);
278
schemalocation = msEncodeHTMLEntities( msOWSGetSchemasLocation(map) );
279
xsi_schemaLocation = strdup("http://www.opengis.net/wfs");
280
xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, " ");
281
xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, schemalocation);
282
xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/wfs/1.1.0/wfs.xsd");
283
xmlNewNsProp(psRootNode, NULL, BAD_CAST "xsi:schemaLocation", BAD_CAST xsi_schemaLocation);
285
/* -------------------------------------------------------------------- */
286
/* Service metadata. */
287
/* -------------------------------------------------------------------- */
289
psTmpNode = xmlAddChild(psRootNode,
290
msOWSCommonServiceIdentification(psNsOws, map, "OGC WFS", params->pszVersion, "FO"));
293
psTmpNode = xmlAddChild(psRootNode, msOWSCommonServiceProvider(
294
psNsOws, psNsXLink, map, "FO"));
296
/*operation metadata */
297
if ((script_url=msOWSGetOnlineResource(map, "FO", "onlineresource", req)) == NULL
298
|| (script_url_encoded = msEncodeHTMLEntities(script_url)) == NULL)
300
msSetError(MS_WFSERR, "Server URL not found", "msWFSGetCapabilities11()");
301
return msWFSException11(map, "mapserv", "NoApplicableCode", params->pszVersion);
304
/* -------------------------------------------------------------------- */
305
/* Operations metadata. */
306
/* -------------------------------------------------------------------- */
307
psMainNode= xmlAddChild(psRootNode,msOWSCommonOperationsMetadata(psNsOws));
309
/* -------------------------------------------------------------------- */
310
/* GetCapabilities */
311
/* -------------------------------------------------------------------- */
312
psNode = xmlAddChild(psMainNode,
313
msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"GetCapabilities",
314
OWS_METHOD_GETPOST, script_url_encoded));
316
xmlAddChild(psMainNode, psNode);
317
xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(
318
ows_version, psNsOws, "Parameter", "service", "WFS"));
320
xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,
321
"Parameter", "AcceptVersions",
324
xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,
325
"Parameter", "AcceptFormats",
329
/* -------------------------------------------------------------------- */
330
/* DescribeFeatureType */
331
/* -------------------------------------------------------------------- */
332
psNode = xmlAddChild(psMainNode,
333
msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"DescribeFeatureType",
334
OWS_METHOD_GETPOST, script_url_encoded));
335
xmlAddChild(psMainNode, psNode);
338
xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,
339
"Parameter", "outputFormat",
340
"XMLSCHEMA,text/xml; subtype=gml/2.1.2,text/xml; subtype=gml/3.1.1"));
342
/* -------------------------------------------------------------------- */
344
/* -------------------------------------------------------------------- */
345
psNode = xmlAddChild(psMainNode,
346
msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"GetFeature",
347
OWS_METHOD_GETPOST, script_url_encoded));
348
xmlAddChild(psMainNode, psNode);
350
/*resultType: TODO support hits*/
351
xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,
352
"Parameter", "resultType",
355
xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,
356
"Parameter", "resultType",
359
xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,
360
"Parameter", "outputFormat",
361
"text/xml; subtype=gml/3.1.1"));
363
value = msOWSLookupMetadata(&(map->web.metadata), "FO", "maxfeatures");
366
xmlAddChild(psMainNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,
367
"Constraint", "DefaultMaxFeatures",
371
/* -------------------------------------------------------------------- */
372
/* FeatureTypeList */
373
/* -------------------------------------------------------------------- */
375
psFtNode = xmlNewNode(NULL, BAD_CAST "FeatureTypeList");
376
xmlAddChild(psRootNode, psFtNode);
377
psNode = xmlNewChild(psFtNode, NULL, BAD_CAST "Operations", NULL);
378
xmlNewChild(psNode, NULL, BAD_CAST "Operation", BAD_CAST "Query");
380
for(i=0; i<map->numlayers; i++)
383
lp = GET_LAYER(map, i);
385
/* List only vector layers in which DUMP=TRUE */
386
if (msWFSIsLayerSupported(lp))
387
xmlAddChild(psFtNode, msWFSDumpLayer11(map, lp, psNsOws));
394
/* -------------------------------------------------------------------- */
395
/* Filter capabilities. */
396
/* -------------------------------------------------------------------- */
398
psNsOgc = xmlNewNs(NULL, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_PREFIX);
399
xmlAddChild(psRootNode, FLTGetCapabilities(psNsOgc, psNsOgc, MS_FALSE));
400
/* -------------------------------------------------------------------- */
401
/* Write out the document. */
402
/* -------------------------------------------------------------------- */
404
if( msIO_needBinaryStdout() == MS_FAILURE )
408
msIO_printf("Content-type: text/xml; charset=%s%c%c", encoding,10,10);
410
msIO_printf("Content-type: text/xml%c%c",10,10);
412
context = msIO_getHandler(stdout);
414
xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, (encoding ? encoding : "ISO-8859-1"), 1);
415
msIO_contextWrite(context, buffer, size);
418
/*free buffer and the document */
424
free(script_url_encoded);
425
free(xsi_schemaLocation);
426
free(schemalocation);
434
#endif /*defined(USE_WFS_SVR) && defined(USE_LIBXML2)*/
436
#if defined(USE_WFS_SVR) && !defined(USE_LIBXML2)
440
int msWFSGetCapabilities11(mapObj *map, wfsParamsObj *params,
444
msSetError( MS_WFSERR,
445
"WFS 1.1 request made, but mapserver requires libxml2 for WFS 1.1 services and this is not configured.",
446
"msWFSGetCapabilities11()", "NoApplicableCode" );
448
return msWFSException11(map, "mapserv", "NoApplicableCode", params->pszVersion);
451
int msWFSException11(mapObj *map, const char *locator, const char *exceptionCode, const char *version) {
452
/* fallback to reporting using 1.0 style exceptions. */
453
return msWFSException( map, locator, exceptionCode, "1.0.0" );
456
#endif /* defined(USE_WFS_SVR) && !defined(USE_LIBXML2) */
1
/**********************************************************************
2
* $Id: mapwfs11.c 11503 2011-04-07 19:56:16Z dmorissette $
5
* Purpose: OGC WFS 1.1.0 implementation. This file holds some WFS 1.1.0
6
* specific functions but other parts are still implemented in mapwfs.c.
7
* Author: Y. Assefa, DM Solutions Group (assefa@dmsolutions.ca)
9
**********************************************************************
10
* Copyright (c) 2008, Y. Assefa, DM Solutions Group Inc
12
* Permission is hereby granted, free of charge, to any person obtaining a
13
* copy of this software and associated documentation files (the "Software"),
14
* to deal in the Software without restriction, including without limitation
15
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
16
* and/or sell copies of the Software, and to permit persons to whom the
17
* Software is furnished to do so, subject to the following conditions:
19
* The above copyright notice and this permission notice shall be included in
20
* all copies of this Software or works derived from this Software.
22
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28
****************************************************************************/
30
#include "mapserver.h"
33
MS_CVSID("$Id: mapwfs11.c 11503 2011-04-07 19:56:16Z dmorissette $")
35
#if defined(USE_WFS_SVR) && defined(USE_LIBXML2)
36
#include "maplibxml2.h"
37
#include "mapowscommon.h"
38
#include "mapogcfilter.h"
40
/************************************************************************/
41
/* msWFSException11() */
42
/************************************************************************/
44
int msWFSException11(mapObj *map, const char *locator,
45
const char *exceptionCode, const char *version)
48
char *errorString = NULL;
49
char *errorMessage = NULL;
50
char *schemasLocation = NULL;
53
xmlDocPtr psDoc = NULL;
54
xmlNodePtr psRootNode = NULL;
55
xmlNsPtr psNsOws = NULL;
56
xmlChar *buffer = NULL;
61
psNsOws = xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/ows", BAD_CAST "ows");
63
encoding = msOWSLookupMetadata(&(map->web.metadata), "FO", "encoding");
65
errorString = msGetErrorString("\n");
66
errorMessage = msEncodeHTMLEntities(errorString);
67
schemasLocation = msEncodeHTMLEntities(msOWSGetSchemasLocation(map));
69
psDoc = xmlNewDoc(BAD_CAST "1.0");
71
psRootNode = msOWSCommonExceptionReport(psNsOws, OWS_1_0_0, schemasLocation, version, msOWSGetLanguage(map, "exception"), exceptionCode, locator, errorMessage);
73
xmlDocSetRootElement(psDoc, psRootNode);
75
xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/ows", BAD_CAST "ows");
78
msIO_printf("Content-type: text/xml; charset=%s%c%c", encoding,10,10);
80
msIO_printf("Content-type: text/xml%c%c",10,10);
82
xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, (encoding ? encoding : "ISO-8859-1"), 1);
84
msIO_printf("%s", buffer);
86
/*free buffer and the document */
89
free(schemasLocation);
94
/* clear error since we have already reported it */
101
/************************************************************************/
102
/* msWFSDumpLayer11 */
103
/************************************************************************/
104
static xmlNodePtr msWFSDumpLayer11(mapObj *map, layerObj *lp, xmlNsPtr psNsOws)
108
xmlNodePtr psRootNode, psNode;
109
const char *value = NULL;
110
const char *encoding = NULL;
116
encoding = msOWSLookupMetadata(&(map->web.metadata), "FO", "encoding");
118
encoding = "ISO-8859-1";
120
psRootNode = xmlNewNode(NULL, BAD_CAST "FeatureType");
122
/*if there is an encoding using it on some of the items*/
123
psNode = msOWSCommonxmlNewChildEncoded(psRootNode, NULL, "Name", lp->name, encoding);
126
if (lp->name && strlen(lp->name) > 0 &&
127
(msIsXMLTagValid(lp->name) == MS_FALSE || isdigit(lp->name[0])))
128
xmlAddSibling(psNode,
129
xmlNewComment(BAD_CAST "WARNING: The layer name '%s' might contain spaces or "
130
"invalid characters or may start with a number. This could lead to potential problems"));
132
value = msOWSLookupMetadata(&(lp->metadata), "FO", "title");
134
value =(const char*)lp->name;
136
psNode = msOWSCommonxmlNewChildEncoded(psRootNode, NULL, "Title", value, encoding);
139
value = msOWSLookupMetadata(&(lp->metadata), "FO", "abstract");
141
psNode = msOWSCommonxmlNewChildEncoded(psRootNode, NULL, "Abstract", value, encoding);
145
value = msOWSLookupMetadata(&(lp->metadata), "FO", "keywordlist");
150
encoded = msGetEncodedString(value, encoding);
152
encoded = msGetEncodedString(value, "ISO-8859-1");
154
msLibXml2GenerateList(
155
xmlNewChild(psRootNode, psNsOws, BAD_CAST "Keywords", NULL),
156
NULL, "Keyword", encoded, ',' );
159
/*support DefaultSRS and OtherSRS*/
160
valueToFree = msOWSGetProjURN(&(map->projection),&(map->web.metadata),"FO",MS_FALSE);
162
valueToFree = msOWSGetProjURN(&(lp->projection), &(lp->metadata), "FO", MS_FALSE);
166
tokens = msStringSplit(valueToFree, ' ', &n);
169
psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "DefaultSRS", BAD_CAST tokens[0]);
171
psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "OtherSRS", BAD_CAST tokens[i]);
173
msFreeCharArray(tokens, n);
177
xmlAddSibling(psNode,
178
xmlNewComment(BAD_CAST "WARNING: Mandatory mapfile parameter: (at least one of) MAP.PROJECTION, LAYER.PROJECTION or wfs/ows_srs metadata was missing in this context."));
183
/*TODO: adevertize only gml3?*/
184
psNode = xmlNewNode(NULL, BAD_CAST "OutputFormats");
185
xmlAddChild(psRootNode, psNode);
188
char *formats_list = msWFSGetOutputFormatList( map, lp, "1.1.0" );
193
tokens = msStringSplit(formats_list, ',', &n);
195
for( iformat = 0; iformat < n; iformat++ )
196
xmlNewChild(psNode, NULL, BAD_CAST "Format",
197
BAD_CAST tokens[iformat] );
198
msFree( formats_list );
199
msFreeCharArray( tokens, n );
203
if (msOWSGetLayerExtent(map, lp, "FO", &ext) == MS_SUCCESS)
205
/*convert to latlong*/
206
if (lp->projection.numargs > 0)
208
if (!pj_is_latlong(&lp->projection.proj))
209
msProjectRect(&lp->projection, NULL, &ext);
211
else if (map->projection.numargs > 0 && !pj_is_latlong(&map->projection.proj))
212
msProjectRect(&map->projection, NULL, &ext);
214
xmlAddChild(psRootNode,
215
msOWSCommonWGS84BoundingBox( psNsOws, 2,
217
ext.maxx, ext.maxy));
221
xmlNewChild(psRootNode, psNsOws, BAD_CAST "WGS84BoundingBox", NULL);
222
xmlAddSibling(psNode,
223
xmlNewComment(BAD_CAST "WARNING: Optional WGS84BoundingBox could not be established for this layer. Consider setting the EXTENT in the LAYER object, or wfs_extent metadata. Also check that your data exists in the DATA statement"));
226
value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_href");
230
psNode = xmlNewChild(psRootNode, NULL, BAD_CAST "MetadataURL", BAD_CAST value);
232
value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_format");
235
value = msStrdup("text/html"); /* default */
237
xmlNewProp(psNode, BAD_CAST "format", BAD_CAST value);
239
value = msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_type");
242
value = msStrdup("FGDC"); /* default */
244
xmlNewProp(psNode, BAD_CAST "type", BAD_CAST value);
250
/************************************************************************/
251
/* msWFSGetCapabilities11 */
253
/* Return the capabilities document for wfs 1.1.0 */
254
/************************************************************************/
255
int msWFSGetCapabilities11(mapObj *map, wfsParamsObj *params,
256
cgiRequestObj *req, owsRequestObj *ows_request)
258
xmlDocPtr psDoc = NULL; /* document pointer */
259
xmlNodePtr psRootNode, psMainNode, psNode, psFtNode;
260
xmlNodePtr psTmpNode;
261
const char *updatesequence=NULL;
262
xmlNsPtr psNsOws, psNsXLink, psNsOgc;
263
char *schemalocation = NULL;
264
char *xsi_schemaLocation = NULL;
266
char *script_url=NULL, *script_url_encoded=NULL, *formats_list;
267
const char *value = NULL;
268
const char *encoding;
270
xmlChar *buffer = NULL;
272
msIOContext *context = NULL;
274
int ows_version = OWS_1_0_0;
276
/* -------------------------------------------------------------------- */
277
/* Handle updatesequence */
278
/* -------------------------------------------------------------------- */
280
updatesequence = msOWSLookupMetadata(&(map->web.metadata), "FO", "updatesequence");
282
encoding = msOWSLookupMetadata(&(map->web.metadata), "FO", "encoding");
284
if (params->pszUpdateSequence != NULL) {
285
i = msOWSNegotiateUpdateSequence(params->pszUpdateSequence, updatesequence);
286
if (i == 0) { /* current */
287
msSetError(MS_WFSERR, "UPDATESEQUENCE parameter (%s) is equal to server (%s)", "msWFSGetCapabilities11()", params->pszUpdateSequence, updatesequence);
288
return msWFSException11(map, "updatesequence", "CurrentUpdateSequence", params->pszVersion);
290
if (i > 0) { /* invalid */
291
msSetError(MS_WFSERR, "UPDATESEQUENCE parameter (%s) is higher than server (%s)", "msWFSGetCapabilities11()", params->pszUpdateSequence, updatesequence);
292
return msWFSException11(map, "updatesequence", "InvalidUpdateSequence", params->pszVersion);
296
/* -------------------------------------------------------------------- */
297
/* Create document. */
298
/* -------------------------------------------------------------------- */
299
psDoc = xmlNewDoc(BAD_CAST "1.0");
301
psRootNode = xmlNewNode(NULL, BAD_CAST "WFS_Capabilities");
303
xmlDocSetRootElement(psDoc, psRootNode);
305
/* -------------------------------------------------------------------- */
307
/* -------------------------------------------------------------------- */
308
/*default name space*/
309
xmlNewProp(psRootNode, BAD_CAST "xmlns", BAD_CAST "http://www.opengis.net/wfs");
311
xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/gml", BAD_CAST "gml"));
312
xmlSetNs(psRootNode, xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/wfs", BAD_CAST "wfs"));
314
psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX);
315
psNsXLink = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_PREFIX);
316
xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_PREFIX);
317
xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_PREFIX );
319
xmlNewProp(psRootNode, BAD_CAST "version", BAD_CAST params->pszVersion );
321
updatesequence = msOWSLookupMetadata(&(map->web.metadata), "FO", "updatesequence");
324
xmlNewProp(psRootNode, BAD_CAST "updateSequence", BAD_CAST updatesequence);
327
schemalocation = msEncodeHTMLEntities( msOWSGetSchemasLocation(map) );
328
xsi_schemaLocation = msStrdup("http://www.opengis.net/wfs");
329
xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, " ");
330
xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, schemalocation);
331
xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/wfs/1.1.0/wfs.xsd");
332
xmlNewNsProp(psRootNode, NULL, BAD_CAST "xsi:schemaLocation", BAD_CAST xsi_schemaLocation);
334
/* -------------------------------------------------------------------- */
335
/* Service metadata. */
336
/* -------------------------------------------------------------------- */
338
psTmpNode = xmlAddChild(psRootNode,
339
msOWSCommonServiceIdentification(psNsOws, map, "OGC WFS", params->pszVersion, "FO"));
342
psTmpNode = xmlAddChild(psRootNode, msOWSCommonServiceProvider(
343
psNsOws, psNsXLink, map, "FO"));
345
/*operation metadata */
346
if ((script_url=msOWSGetOnlineResource(map, "FO", "onlineresource", req)) == NULL
347
|| (script_url_encoded = msEncodeHTMLEntities(script_url)) == NULL)
349
msSetError(MS_WFSERR, "Server URL not found", "msWFSGetCapabilities11()");
350
return msWFSException11(map, "mapserv", "NoApplicableCode", params->pszVersion);
353
/* -------------------------------------------------------------------- */
354
/* Operations metadata. */
355
/* -------------------------------------------------------------------- */
356
psMainNode= xmlAddChild(psRootNode,msOWSCommonOperationsMetadata(psNsOws));
358
/* -------------------------------------------------------------------- */
359
/* GetCapabilities */
360
/* -------------------------------------------------------------------- */
361
psNode = xmlAddChild(psMainNode,
362
msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"GetCapabilities",
363
OWS_METHOD_GETPOST, script_url_encoded));
365
xmlAddChild(psMainNode, psNode);
366
xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(
367
ows_version, psNsOws, "Parameter", "service", "WFS"));
369
xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,
370
"Parameter", "AcceptVersions",
373
xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,
374
"Parameter", "AcceptFormats",
378
/* -------------------------------------------------------------------- */
379
/* DescribeFeatureType */
380
/* -------------------------------------------------------------------- */
381
if (msOWSRequestIsEnabled(map, NULL, "F", "DescribeFeatureType", MS_TRUE))
383
psNode = xmlAddChild(psMainNode,
384
msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"DescribeFeatureType",
385
OWS_METHOD_GETPOST, script_url_encoded));
386
xmlAddChild(psMainNode, psNode);
389
xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,
390
"Parameter", "outputFormat",
391
"XMLSCHEMA,text/xml; subtype=gml/2.1.2,text/xml; subtype=gml/3.1.1"));
394
/* -------------------------------------------------------------------- */
396
/* -------------------------------------------------------------------- */
397
if (msOWSRequestIsEnabled(map, NULL, "F", "GetFeature", MS_TRUE))
400
psNode = xmlAddChild(psMainNode,
401
msOWSCommonOperationsMetadataOperation(psNsOws,psNsXLink,"GetFeature",
402
OWS_METHOD_GETPOST, script_url_encoded));
403
xmlAddChild(psMainNode, psNode);
405
xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,
406
"Parameter", "resultType",
409
formats_list = msWFSGetOutputFormatList( map, NULL, "1.1.0" );
410
xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,
411
"Parameter", "outputFormat",
413
msFree( formats_list );
415
value = msOWSLookupMetadata(&(map->web.metadata), "FO", "maxfeatures");
418
xmlAddChild(psMainNode, msOWSCommonOperationsMetadataDomainType(ows_version, psNsOws,
419
"Constraint", "DefaultMaxFeatures",
424
/* -------------------------------------------------------------------- */
425
/* FeatureTypeList */
426
/* -------------------------------------------------------------------- */
428
psFtNode = xmlNewNode(NULL, BAD_CAST "FeatureTypeList");
429
xmlAddChild(psRootNode, psFtNode);
430
psNode = xmlNewChild(psFtNode, NULL, BAD_CAST "Operations", NULL);
431
xmlNewChild(psNode, NULL, BAD_CAST "Operation", BAD_CAST "Query");
433
for(i=0; i<map->numlayers; i++)
436
lp = GET_LAYER(map, i);
438
if (!msIntegerInArray(lp->index, ows_request->enabled_layers, ows_request->numlayers))
441
/* List only vector layers in which DUMP=TRUE */
442
if (msWFSIsLayerSupported(lp))
443
xmlAddChild(psFtNode, msWFSDumpLayer11(map, lp, psNsOws));
450
/* -------------------------------------------------------------------- */
451
/* Filter capabilities. */
452
/* -------------------------------------------------------------------- */
454
psNsOgc = xmlNewNs(NULL, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_URI, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_PREFIX);
455
xmlAddChild(psRootNode, FLTGetCapabilities(psNsOgc, psNsOgc, MS_FALSE));
456
/* -------------------------------------------------------------------- */
457
/* Write out the document. */
458
/* -------------------------------------------------------------------- */
460
if( msIO_needBinaryStdout() == MS_FAILURE )
464
msIO_printf("Content-type: text/xml; charset=%s%c%c", encoding,10,10);
466
msIO_printf("Content-type: text/xml%c%c",10,10);
468
context = msIO_getHandler(stdout);
470
xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, (encoding ? encoding : "ISO-8859-1"), 1);
471
msIO_contextWrite(context, buffer, size);
474
/*free buffer and the document */
480
free(script_url_encoded);
481
free(xsi_schemaLocation);
482
free(schemalocation);
490
#endif /*defined(USE_WFS_SVR) && defined(USE_LIBXML2)*/
492
#if defined(USE_WFS_SVR) && !defined(USE_LIBXML2)
496
int msWFSGetCapabilities11(mapObj *map, wfsParamsObj *params,
500
msSetError( MS_WFSERR,
501
"WFS 1.1 request made, but mapserver requires libxml2 for WFS 1.1 services and this is not configured.",
502
"msWFSGetCapabilities11()", "NoApplicableCode" );
504
return msWFSException11(map, "mapserv", "NoApplicableCode", params->pszVersion);
507
int msWFSException11(mapObj *map, const char *locator, const char *exceptionCode, const char *version) {
508
/* fallback to reporting using 1.0 style exceptions. */
509
return msWFSException( map, locator, exceptionCode, "1.0.0" );
512
#endif /* defined(USE_WFS_SVR) && !defined(USE_LIBXML2) */