• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

MapServer / MapServer / 24101978785

07 Apr 2026 08:07PM UTC coverage: 42.423% (+0.09%) from 42.336%
24101978785

push

github

web-flow
Add support for non-EPSG projections for WCS and WFS protocols (#7457)

* Support AUTH:CODE projections

* Remove duplicate param

* Allow additional authority codes in the wfs_srs list

* Handle custom init files

* Move parameter and make static

* Add back legacy support for urn:EPSG:geographicCRS:CODE

* Tests updated due to new projection handling

* Test updates

* Add new line

* Handle custom projection files and new style proj codes

* EOL fix

* Handle projections in the form urn:ogc:def:crs:ESRI::53009

* Add WCS tests

* Update authorities based on proj.db

* Add projection string tests

* EOL fixes

* Add test data

* Copy custom projection file

* Remove extent

* Add WFS tests

* Update encodings

* Add custom projection tests for WCS

* Remove DATA

* Test fixes

* Switch result to ASCII

* Use backslashes

* Add test for IGNF:ATIGBONNE.BOURD and update IAU_2015

* Appveyor fix

* EOL fix

* Avoid adding + to AUTH:CODE projection strings

* Always assume PROJ_VERSION_MAJOR >= 6

* Use std::string and avoid strlcpy

102 of 120 new or added lines in 5 files covered. (85.0%)

15 existing lines in 5 files now uncovered.

64591 of 152256 relevant lines covered (42.42%)

27322.32 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.63
/src/mapwfs11.cpp
1
/**********************************************************************
2
 * $Id$
3
 *
4
 * Project:  MapServer
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
7
 *mapwfs.c. Author:   Y. Assefa, DM Solutions Group (assefa@dmsolutions.ca)
8
 *
9
 **********************************************************************
10
 * Copyright (c) 2008, Y. Assefa, DM Solutions Group Inc
11
 *
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:
18
 *
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.
21
 *
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
 ****************************************************************************/
29

30
#include "mapserver.h"
31
#include "mapows.h"
32

33
#if defined(USE_WFS_SVR) && defined(USE_LIBXML2)
34
#include "maplibxml2.h"
35
#include "mapowscommon.h"
36
#include "mapogcfilter.h"
37

38
#include <string>
39

40
template <class T> inline void IGNORE_RET_VAL(T) {}
41

42
/************************************************************************/
43
/*                          msWFSException11()                          */
44
/************************************************************************/
45

46
int msWFSException11(mapObj *map, const char *locator,
13✔
47
                     const char *exceptionCode, const char *version) {
48
  int size = 0;
13✔
49
  char *errorString = NULL;
50
  char *schemasLocation = NULL;
51

52
  xmlDocPtr psDoc = NULL;
53
  xmlNodePtr psRootNode = NULL;
54
  xmlNsPtr psNsOws = NULL;
55
  xmlChar *buffer = NULL;
13✔
56

57
  if (version == NULL)
13✔
58
    version = "1.1.0";
59

60
  psNsOws =
61
      xmlNewNs(NULL, BAD_CAST "http://www.opengis.net/ows", BAD_CAST "ows");
13✔
62

63
  errorString = msGetErrorString("\n");
13✔
64
  schemasLocation = msEncodeHTMLEntities(msOWSGetSchemasLocation(map));
13✔
65

66
  psDoc = xmlNewDoc(BAD_CAST "1.0");
13✔
67

68
  psRootNode = msOWSCommonExceptionReport(
13✔
69
      psNsOws, OWS_1_0_0, schemasLocation, version,
70
      msOWSGetLanguage(map, "exception"), exceptionCode, locator, errorString);
71

72
  xmlDocSetRootElement(psDoc, psRootNode);
13✔
73

74
  xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/ows", BAD_CAST "ows");
13✔
75

76
  msIO_setHeader("Content-Type", "text/xml; charset=UTF-8");
13✔
77
  msIO_sendHeaders();
13✔
78

79
  xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, ("UTF-8"), 1);
13✔
80

81
  msIO_printf("%s", buffer);
13✔
82

83
  /*free buffer and the document */
84
  free(errorString);
13✔
85
  free(schemasLocation);
13✔
86
  xmlFree(buffer);
13✔
87
  xmlFreeDoc(psDoc);
13✔
88
  xmlFreeNs(psNsOws);
13✔
89

90
  /* clear error since we have already reported it */
91
  msResetErrorList();
13✔
92

93
  return MS_FAILURE;
13✔
94
}
95

96
/************************************************************************/
97
/*                       msWFSAddMetadataURL                            */
98
/************************************************************************/
99

100
static void msWFSAddMetadataURL(layerObj *lp, int nWFSVersion,
62✔
101
                                const std::string &radix,
102
                                xmlNodePtr psRootNode) {
103
  const char *value =
104
      msOWSLookupMetadata(&(lp->metadata), "FO", (radix + "_href").c_str());
62✔
105

106
  if (value) {
62✔
107
    if (nWFSVersion >= OWS_2_0_0) {
62✔
108
      xmlNodePtr psNode =
109
          xmlNewChild(psRootNode, NULL, BAD_CAST "MetadataURL", NULL);
35✔
110
      xmlNewProp(psNode, BAD_CAST "xlink:href", BAD_CAST value);
35✔
111

112
      value = msOWSLookupMetadata(&(lp->metadata), "FO",
35✔
113
                                  (radix + "_about").c_str());
35✔
114
      if (value != NULL)
35✔
115
        xmlNewProp(psNode, BAD_CAST "about", BAD_CAST value);
4✔
116
    } else {
117
      xmlNodePtr psNode = xmlNewTextChild(
27✔
118
          psRootNode, NULL, BAD_CAST "MetadataURL", BAD_CAST value);
119

120
      value = msOWSLookupMetadata(&(lp->metadata), "FO",
27✔
121
                                  (radix + "_format").c_str());
27✔
122

123
      if (!value)
27✔
124
        value = "text/html"; /* default */
125

126
      xmlNewProp(psNode, BAD_CAST "format", BAD_CAST value);
27✔
127

128
      value =
129
          msOWSLookupMetadata(&(lp->metadata), "FO", (radix + "_type").c_str());
27✔
130

131
      if (!value)
27✔
132
        value = "FGDC"; /* default */
133

134
      xmlNewProp(psNode, BAD_CAST "type", BAD_CAST value);
27✔
135
    }
136
  }
137
}
62✔
138

139
/************************************************************************/
140
/*                            msWFSDumpLayer11                          */
141
/************************************************************************/
142
xmlNodePtr msWFSDumpLayer11(mapObj *map, layerObj *lp, xmlNsPtr psNsOws,
60✔
143
                            int nWFSVersion, const char *validate_language,
144
                            char *script_url) {
145
  rectObj ext;
146

147
  xmlNodePtr psRootNode, psNode;
148
  const char *value = NULL;
149
  char *valueToFree;
150
  int i = 0;
151

152
  psRootNode = xmlNewNode(NULL, BAD_CAST "FeatureType");
60✔
153

154
  /* add namespace to layer name */
155
  value = msOWSLookupMetadata(&(map->web.metadata), "FO", "namespace_prefix");
60✔
156

157
  /* FIXME? Should probably be applied to WFS 1.1 as well, but the addition */
158
  /* of the prefix can be disruptive for clients */
159
  if (value == NULL && nWFSVersion >= OWS_2_0_0)
60✔
160
    value = MS_DEFAULT_NAMESPACE_PREFIX;
161

162
  if (value) {
26✔
163
    int n = strlen(value) + strlen(lp->name) + 1 + 1;
34✔
164
    valueToFree = (char *)msSmallMalloc(n);
34✔
165
    snprintf(valueToFree, n, "%s:%s", value, lp->name);
34✔
166

167
    psNode = xmlNewTextChild(psRootNode, NULL, BAD_CAST "Name",
34✔
168
                             BAD_CAST valueToFree);
169
    msFree(valueToFree);
34✔
170
  } else {
171
    psNode =
172
        xmlNewTextChild(psRootNode, NULL, BAD_CAST "Name", BAD_CAST lp->name);
26✔
173
  }
174

175
  if (lp->name && strlen(lp->name) > 0 &&
120✔
176
      (msIsXMLTagValid(lp->name) == MS_FALSE || isdigit(lp->name[0]))) {
120✔
177
    char szTmp[512];
178
    snprintf(szTmp, sizeof(szTmp),
×
179
             "WARNING: The layer name '%s' might contain spaces or "
180
             "invalid characters or may start with a number. This could lead "
181
             "to potential problems",
182
             lp->name);
183
    xmlAddSibling(psNode, xmlNewComment(BAD_CAST szTmp));
×
184
  }
185

186
  value = msOWSLookupMetadataWithLanguage(&(lp->metadata), "FO", "title",
60✔
187
                                          validate_language);
188
  if (!value)
60✔
189
    value = (const char *)lp->name;
3✔
190

191
  psNode = xmlNewTextChild(psRootNode, NULL, BAD_CAST "Title", BAD_CAST value);
60✔
192

193
  value = msOWSLookupMetadataWithLanguage(&(lp->metadata), "FO", "abstract",
60✔
194
                                          validate_language);
195
  if (value)
60✔
196
    psNode =
197
        xmlNewTextChild(psRootNode, NULL, BAD_CAST "Abstract", BAD_CAST value);
13✔
198

199
  value = msOWSLookupMetadataWithLanguage(&(lp->metadata), "FO", "keywordlist",
60✔
200
                                          validate_language);
201

202
  if (value)
60✔
203
    msLibXml2GenerateList(
5✔
204
        xmlNewChild(psRootNode, psNsOws, BAD_CAST "Keywords", NULL), NULL,
205
        "Keyword", value, ',');
206

207
  /*support DefaultSRS and OtherSRS*/
208
  valueToFree =
209
      msOWSGetProjURN(&(map->projection), &(map->web.metadata), "FO", MS_FALSE);
60✔
210
  if (!valueToFree)
60✔
211
    valueToFree =
212
        msOWSGetProjURN(&(lp->projection), &(lp->metadata), "FO", MS_FALSE);
6✔
213

214
  if (valueToFree) {
6✔
215
    int n = 0;
60✔
216
    char **tokens = msStringSplit(valueToFree, ' ', &n);
60✔
217
    if (tokens && n > 0) {
60✔
218
      if (nWFSVersion == OWS_1_1_0)
60✔
219
        IGNORE_RET_VAL(xmlNewTextChild(psRootNode, NULL, BAD_CAST "DefaultSRS",
26✔
220
                                       BAD_CAST tokens[0]));
221
      else
222
        IGNORE_RET_VAL(xmlNewTextChild(psRootNode, NULL, BAD_CAST "DefaultCRS",
34✔
223
                                       BAD_CAST tokens[0]));
224
      for (i = 1; i < n; i++) {
110✔
225
        if (nWFSVersion == OWS_1_1_0)
50✔
226
          IGNORE_RET_VAL(xmlNewTextChild(psRootNode, NULL, BAD_CAST "OtherSRS",
21✔
227
                                         BAD_CAST tokens[i]));
21✔
228
        else
229
          IGNORE_RET_VAL(xmlNewTextChild(psRootNode, NULL, BAD_CAST "OtherCRS",
29✔
230
                                         BAD_CAST tokens[i]));
29✔
231
      }
232
    }
233
    msFreeCharArray(tokens, n);
60✔
234
  } else
UNCOV
235
    xmlAddSibling(
×
236
        psNode,
237
        xmlNewComment(BAD_CAST
238
                      "WARNING: Mandatory mapfile parameter: (at least one of) "
239
                      "MAP.PROJECTION, LAYER.PROJECTION or wfs/ows_srs "
240
                      "metadata was missing in this context."));
241

242
  free(valueToFree);
60✔
243
  valueToFree = NULL;
244

245
  /*TODO: adevertize only gml3?*/
246
  psNode = xmlNewNode(NULL, BAD_CAST "OutputFormats");
60✔
247
  xmlAddChild(psRootNode, psNode);
60✔
248

249
  {
250
    char *formats_list = msWFSGetOutputFormatList(map, lp, nWFSVersion);
60✔
251
    int iformat;
252
    int n = 0;
60✔
253
    char **tokens = msStringSplit(formats_list, ',', &n);
60✔
254

255
    for (iformat = 0; iformat < n; iformat++)
263✔
256
      xmlNewTextChild(psNode, NULL, BAD_CAST "Format",
203✔
257
                      BAD_CAST tokens[iformat]);
203✔
258
    msFree(formats_list);
60✔
259
    msFreeCharArray(tokens, n);
60✔
260
  }
261

262
  /*bbox*/
263
  if (msOWSGetLayerExtent(map, lp, "FO", &ext) == MS_SUCCESS) {
60✔
264
    /*convert to latlong*/
265
    if (lp->projection.numargs > 0)
60✔
266
      msOWSProjectToWGS84(&lp->projection, &ext);
59✔
267
    else
268
      msOWSProjectToWGS84(&map->projection, &ext);
1✔
269

270
    xmlAddChild(psRootNode,
60✔
271
                msOWSCommonWGS84BoundingBox(psNsOws, 2, ext.minx, ext.miny,
272
                                            ext.maxx, ext.maxy));
273
  } else {
274
    xmlAddSibling(
×
275
        psNode,
276
        xmlNewComment(
277
            BAD_CAST "WARNING: Optional WGS84BoundingBox could not be "
278
                     "established for this layer.  Consider setting the EXTENT "
279
                     "in the LAYER object, or wfs_extent metadata. Also check "
280
                     "that your data exists in the DATA statement"));
281
  }
282

283
  const char *metadataurl_list =
284
      msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_list");
60✔
285
  if (metadataurl_list) {
60✔
286
    int ntokens = 0;
2✔
287
    char **tokens = msStringSplit(metadataurl_list, ' ', &ntokens);
2✔
288
    for (int i = 0; i < ntokens; i++) {
6✔
289
      std::string key("metadataurl_");
4✔
290
      key += tokens[i];
4✔
291
      msWFSAddMetadataURL(lp, nWFSVersion, key, psRootNode);
4✔
292
    }
293
    msFreeCharArray(tokens, ntokens);
2✔
294
  } else {
295
    if (!msOWSLookupMetadata(&(lp->metadata), "FO", "metadataurl_href"))
58✔
296
      msMetadataSetGetMetadataURL(lp, script_url);
50✔
297

298
    msWFSAddMetadataURL(lp, nWFSVersion, "metadataurl", psRootNode);
116✔
299
  }
300

301
  return psRootNode;
60✔
302
}
303

304
/************************************************************************/
305
/*                          msWFSGetCapabilities11                      */
306
/*                                                                      */
307
/*      Return the capabilities document for wfs 1.1.0                  */
308
/************************************************************************/
309
int msWFSGetCapabilities11(mapObj *map, wfsParamsObj *params,
24✔
310
                           cgiRequestObj *req, owsRequestObj *ows_request) {
311
  xmlDocPtr psDoc = NULL; /* document pointer */
312
  xmlNodePtr psRootNode, psMainNode, psNode, psFtNode;
313
  const char *updatesequence = NULL;
314
  xmlNsPtr psNsOws, psNsXLink, psNsOgc;
315
  char *schemalocation = NULL;
316
  char *xsi_schemaLocation = NULL;
317
  const char *user_namespace_prefix = NULL;
318
  const char *user_namespace_uri = NULL;
319
  gmlNamespaceListObj *namespaceList =
320
      NULL; /* for external application schema support */
321

322
  char *script_url = NULL, *formats_list;
323
  const char *value = NULL;
324

325
  xmlChar *buffer = NULL;
24✔
326
  int size = 0, i;
24✔
327
  msIOContext *context = NULL;
328

329
  int ows_version = OWS_1_0_0;
330
  int ret;
331

332
  /* -------------------------------------------------------------------- */
333
  /*      Handle updatesequence                                           */
334
  /* -------------------------------------------------------------------- */
335
  ret = msWFSHandleUpdateSequence(map, params, "msWFSGetCapabilities11()");
24✔
336
  if (ret != MS_SUCCESS)
24✔
337
    return ret;
338

339
  /* -------------------------------------------------------------------- */
340
  /*      Create document.                                                */
341
  /* -------------------------------------------------------------------- */
342
  psDoc = xmlNewDoc(BAD_CAST "1.0");
20✔
343

344
  psRootNode = xmlNewNode(NULL, BAD_CAST "WFS_Capabilities");
20✔
345

346
  xmlDocSetRootElement(psDoc, psRootNode);
20✔
347

348
  /* -------------------------------------------------------------------- */
349
  /*      Name spaces                                                     */
350
  /* -------------------------------------------------------------------- */
351
  /*default name space*/
352
  xmlNewProp(psRootNode, BAD_CAST "xmlns",
20✔
353
             BAD_CAST "http://www.opengis.net/wfs");
354

355
  xmlSetNs(psRootNode,
20✔
356
           xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/gml",
357
                    BAD_CAST "gml"));
358
  xmlSetNs(psRootNode,
20✔
359
           xmlNewNs(psRootNode, BAD_CAST "http://www.opengis.net/wfs",
360
                    BAD_CAST "wfs"));
361

362
  psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI,
20✔
363
                     BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX);
364
  psNsXLink =
365
      xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_URI,
20✔
366
               BAD_CAST MS_OWSCOMMON_W3C_XLINK_NAMESPACE_PREFIX);
367
  xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_URI,
20✔
368
           BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_PREFIX);
369
  xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_URI,
20✔
370
           BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_PREFIX);
371

372
  value = msOWSLookupMetadata(&(map->web.metadata), "FO", "namespace_uri");
20✔
373
  if (value)
374
    user_namespace_uri = value;
375

376
  value = msOWSLookupMetadata(&(map->web.metadata), "FO", "namespace_prefix");
20✔
377
  if (value)
20✔
378
    user_namespace_prefix = value;
379
  if (user_namespace_prefix != NULL &&
×
380
      msIsXMLTagValid(user_namespace_prefix) == MS_FALSE)
×
381
    msIO_printf(
×
382
        "<!-- WARNING: The value '%s' is not valid XML namespace. -->\n",
383
        user_namespace_prefix);
384
  else
385
    xmlNewNs(psRootNode, BAD_CAST user_namespace_uri,
20✔
386
             BAD_CAST user_namespace_prefix);
387

388
  /* any additional namespaces */
389
  namespaceList = msGMLGetNamespaces(&(map->web), "G");
20✔
390
  for (i = 0; i < namespaceList->numnamespaces; i++) {
20✔
391
    if (namespaceList->namespaces[i].uri) {
×
392
      xmlNewNs(psRootNode, BAD_CAST namespaceList->namespaces[i].uri,
×
393
               BAD_CAST namespaceList->namespaces[i].prefix);
×
394
    }
395
  }
396
  msGMLFreeNamespaces(namespaceList);
20✔
397

398
  xmlNewProp(psRootNode, BAD_CAST "version", BAD_CAST params->pszVersion);
20✔
399

400
  updatesequence =
401
      msOWSLookupMetadata(&(map->web.metadata), "FO", "updatesequence");
20✔
402

403
  if (updatesequence)
20✔
404
    xmlNewProp(psRootNode, BAD_CAST "updateSequence", BAD_CAST updatesequence);
19✔
405

406
  /*schema*/
407
  schemalocation = msEncodeHTMLEntities(msOWSGetSchemasLocation(map));
20✔
408
  xsi_schemaLocation = msStrdup("http://www.opengis.net/wfs");
20✔
409
  xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, " ");
20✔
410
  xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, schemalocation);
20✔
411
  xsi_schemaLocation =
412
      msStringConcatenate(xsi_schemaLocation, "/wfs/1.1.0/wfs.xsd");
20✔
413
  xmlNewNsProp(psRootNode, NULL, BAD_CAST "xsi:schemaLocation",
20✔
414
               BAD_CAST xsi_schemaLocation);
415

416
  /* -------------------------------------------------------------------- */
417
  /*      Service metadata.                                               */
418
  /* -------------------------------------------------------------------- */
419

420
  xmlAddChild(psRootNode,
20✔
421
              msOWSCommonServiceIdentification(psNsOws, map, "OGC WFS",
422
                                               params->pszVersion, "FO", NULL));
20✔
423

424
  /*service provider*/
425
  xmlAddChild(psRootNode,
20✔
426
              msOWSCommonServiceProvider(psNsOws, psNsXLink, map, "FO", NULL));
427

428
  /*operation metadata */
429
  if ((script_url = msOWSGetOnlineResource(map, "FO", "onlineresource", req)) ==
20✔
430
      NULL) {
431
    msSetError(MS_WFSERR, "Server URL not found", "msWFSGetCapabilities11()");
×
432
    return msWFSException11(map, "mapserv", MS_OWS_ERROR_NO_APPLICABLE_CODE,
×
433
                            params->pszVersion);
×
434
  }
435

436
  /* -------------------------------------------------------------------- */
437
  /*      Operations metadata.                                            */
438
  /* -------------------------------------------------------------------- */
439
  psMainNode = xmlAddChild(psRootNode, msOWSCommonOperationsMetadata(psNsOws));
20✔
440

441
  /* -------------------------------------------------------------------- */
442
  /*      GetCapabilities                                                 */
443
  /* -------------------------------------------------------------------- */
444
  psNode = xmlAddChild(psMainNode, msOWSCommonOperationsMetadataOperation(
20✔
445
                                       psNsOws, psNsXLink, "GetCapabilities",
446
                                       OWS_METHOD_GETPOST, script_url));
447

448
  xmlAddChild(psMainNode, psNode);
20✔
449
  xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(
20✔
450
                          ows_version, psNsOws, "Parameter", "service", "WFS"));
451
  /*accept version*/
452
  xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(
20✔
453
                          ows_version, psNsOws, "Parameter", "AcceptVersions",
454
                          "1.0.0,1.1.0"));
455
  /*format*/
456
  xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(
20✔
457
                          ows_version, psNsOws, "Parameter", "AcceptFormats",
458
                          "text/xml"));
459

460
  /* -------------------------------------------------------------------- */
461
  /*      DescribeFeatureType                                             */
462
  /* -------------------------------------------------------------------- */
463
  if (msOWSRequestIsEnabled(map, NULL, "F", "DescribeFeatureType", MS_TRUE)) {
20✔
464
    psNode =
465
        xmlAddChild(psMainNode, msOWSCommonOperationsMetadataOperation(
20✔
466
                                    psNsOws, psNsXLink, "DescribeFeatureType",
467
                                    OWS_METHOD_GETPOST, script_url));
468
    xmlAddChild(psMainNode, psNode);
20✔
469

470
    /*output format*/
471
    xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(
20✔
472
                            ows_version, psNsOws, "Parameter", "outputFormat",
473
                            "XMLSCHEMA,text/xml; subtype=gml/2.1.2,text/xml; "
474
                            "subtype=gml/3.1.1"));
475
  }
476

477
  /* -------------------------------------------------------------------- */
478
  /*      GetFeature                                                      */
479
  /* -------------------------------------------------------------------- */
480
  if (msOWSRequestIsEnabled(map, NULL, "F", "GetFeature", MS_TRUE)) {
20✔
481

482
    psNode = xmlAddChild(psMainNode, msOWSCommonOperationsMetadataOperation(
20✔
483
                                         psNsOws, psNsXLink, "GetFeature",
484
                                         OWS_METHOD_GETPOST, script_url));
485
    xmlAddChild(psMainNode, psNode);
20✔
486

487
    xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(
20✔
488
                            ows_version, psNsOws, "Parameter", "resultType",
489
                            "results,hits"));
490

491
    formats_list = msWFSGetOutputFormatList(map, NULL, OWS_1_1_0);
20✔
492
    xmlAddChild(psNode, msOWSCommonOperationsMetadataDomainType(
20✔
493
                            ows_version, psNsOws, "Parameter", "outputFormat",
494
                            formats_list));
495
    msFree(formats_list);
20✔
496

497
    value = msOWSLookupMetadata(&(map->web.metadata), "FO", "maxfeatures");
20✔
498

499
    if (value) {
20✔
500
      xmlAddChild(psMainNode, msOWSCommonOperationsMetadataDomainType(
9✔
501
                                  ows_version, psNsOws, "Constraint",
502
                                  "DefaultMaxFeatures", (char *)value));
503
    }
504
  }
505

506
  /* -------------------------------------------------------------------- */
507
  /*      FeatureTypeList                                                 */
508
  /* -------------------------------------------------------------------- */
509

510
  psFtNode = xmlNewNode(NULL, BAD_CAST "FeatureTypeList");
20✔
511
  xmlAddChild(psRootNode, psFtNode);
20✔
512
  psNode = xmlNewChild(psFtNode, NULL, BAD_CAST "Operations", NULL);
20✔
513
  xmlNewChild(psNode, NULL, BAD_CAST "Operation", BAD_CAST "Query");
20✔
514

515
  for (i = 0; i < map->numlayers; i++) {
55✔
516
    layerObj *lp;
517
    lp = GET_LAYER(map, i);
35✔
518

519
    if (!msIntegerInArray(lp->index, ows_request->enabled_layers,
35✔
520
                          ows_request->numlayers))
521
      continue;
8✔
522

523
    if (msIsLayerSupportedForWFSOrOAPIF(lp))
27✔
524
      xmlAddChild(psFtNode, msWFSDumpLayer11(map, lp, psNsOws, OWS_1_1_0, NULL,
26✔
525
                                             script_url));
526
  }
527

528
  /* -------------------------------------------------------------------- */
529
  /*      Filter capabilities.                                            */
530
  /* -------------------------------------------------------------------- */
531

532
  psNsOgc = xmlNewNs(NULL, BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_URI,
20✔
533
                     BAD_CAST MS_OWSCOMMON_OGC_NAMESPACE_PREFIX);
534
  xmlAddChild(psRootNode, FLTGetCapabilities(psNsOgc, psNsOgc, MS_FALSE));
20✔
535
  /* -------------------------------------------------------------------- */
536
  /*      Write out the document.                                         */
537
  /* -------------------------------------------------------------------- */
538

539
  if (msIO_needBinaryStdout() == MS_FAILURE)
20✔
540
    return MS_FAILURE;
541

542
  msIO_setHeader("Content-Type", "text/xml; charset=UTF-8");
20✔
543
  msIO_sendHeaders();
20✔
544

545
  context = msIO_getHandler(stdout);
20✔
546

547
  xmlDocDumpFormatMemoryEnc(psDoc, &buffer, &size, ("UTF-8"), 1);
20✔
548
  msIO_contextWrite(context, buffer, size);
20✔
549
  xmlFree(buffer);
20✔
550

551
  /*free buffer and the document */
552
  /*xmlFree(buffer);*/
553
  xmlFreeDoc(psDoc);
20✔
554
  xmlFreeNs(psNsOgc);
20✔
555

556
  free(script_url);
20✔
557
  free(xsi_schemaLocation);
20✔
558
  free(schemalocation);
20✔
559

560
  xmlCleanupParser();
20✔
561

562
  return (MS_SUCCESS);
563
}
564

565
#endif /*defined(USE_WFS_SVR) && defined(USE_LIBXML2)*/
566

567
#if defined(USE_WFS_SVR) && !defined(USE_LIBXML2)
568

569
int msWFSGetCapabilities11(mapObj *map, wfsParamsObj *params,
570
                           cgiRequestObj *req, owsRequestObj *ows_request)
571

572
{
573
  msSetError(MS_WFSERR,
574
             "WFS 1.1 request made, but mapserver requires libxml2 for WFS 1.1 "
575
             "services and this is not configured.",
576
             "msWFSGetCapabilities11()");
577

578
  return msWFSException11(map, "mapserv", MS_OWS_ERROR_NO_APPLICABLE_CODE,
579
                          params->pszVersion);
580
}
581

582
int msWFSException11(mapObj *map, const char *locator,
583
                     const char *exceptionCode, const char *version) {
584
  /* fallback to reporting using 1.0 style exceptions. */
585
  return msWFSException(map, locator, exceptionCode, "1.0.0");
586
}
587

588
#endif /* defined(USE_WFS_SVR) && !defined(USE_LIBXML2) */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc