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

geographika / mapserver / 11366259730

16 Oct 2024 01:04PM UTC coverage: 40.285%. Remained the same
11366259730

push

github

geographika
Remove Python 3.8 and add Python 3.13

58212 of 144501 relevant lines covered (40.28%)

25421.16 hits per line

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

76.95
/src/mapowscommon.c
1
/******************************************************************************
2
 * $Id$
3
 *
4
 * Project:  MapServer
5
 * Purpose:  OGC OWS Common Implementation for use by MapServer OGC code
6
 *           versions:
7
 *           1.0.0 (OGC Document 05-008c1)
8
 *           1.1.0 (OGC document 06-121r3)
9
 *
10
 * Author:   Tom Kralidis (tomkralidis@gmail.com)
11
 *
12
 ******************************************************************************
13
 * Copyright (c) 2006, Tom Kralidis
14
 *
15
 * Permission is hereby granted, free of charge, to any person obtaining a
16
 * copy of this software and associated documentation files (the "Software"),
17
 * to deal in the Software without restriction, including without limitation
18
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
19
 * and/or sell copies of the Software, and to permit persons to whom the
20
 * Software is furnished to do so, subject to the following conditions:
21
 *
22
 * The above copyright notice and this permission notice shall be included in
23
 * all copies of this Software or works derived from this Software.
24
 *
25
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
26
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
30
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
31
 * DEALINGS IN THE SOFTWARE.
32
 ****************************************************************************/
33

34
#include "mapserver.h"
35
#include "mapows.h"
36

37
#ifdef USE_LIBXML2
38

39
#include <libxml/parser.h>
40
#include <libxml/tree.h>
41

42
#include "mapowscommon.h"
43
#include "maplibxml2.h"
44

45
/**
46
 * msOWSCommonServiceIdentification()
47
 *
48
 * returns an object of ServiceIdentification as per:
49
 *
50
 * 1.0.0 subclause 7.4.3
51
 * 1.1.1 subclause 7.4.4
52
 *
53
 * @param map mapObj used to fetch WEB/METADATA
54
 * @param servicetype the OWS type
55
 * @param supported_versions the supported version(s) of the OWS
56
 *
57
 * @return psRootNode xmlNodePtr of XML construct
58
 *
59
 */
60

61
xmlNodePtr msOWSCommonServiceIdentification(xmlNsPtr psNsOws, mapObj *map,
99✔
62
                                            const char *servicetype,
63
                                            const char *supported_versions,
64
                                            const char *namespaces,
65
                                            const char *validated_language) {
66
  const char *value = NULL;
67

68
  xmlNodePtr psRootNode = NULL;
69
  xmlNodePtr psNode = NULL;
70

71
  if (_validateNamespace(psNsOws) == MS_FAILURE)
99✔
72
    psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI,
×
73
                       BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX);
74

75
  /* create element name */
76
  psRootNode = xmlNewNode(psNsOws, BAD_CAST "ServiceIdentification");
99✔
77

78
  /* add child elements */
79

80
  value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces,
99✔
81
                                          "title", validated_language);
82

83
  psNode =
84
      xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "Title", BAD_CAST value);
99✔
85

86
  if (!value) {
99✔
87
    xmlAddSibling(
1✔
88
        psNode,
89
        xmlNewComment(
90
            BAD_CAST
91
            "WARNING: Optional metadata \"ows_title\" missing for ows:Title"));
92
  }
93

94
  value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces,
99✔
95
                                          "abstract", validated_language);
96

97
  psNode =
98
      xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "Abstract", BAD_CAST value);
99✔
99

100
  if (!value) {
99✔
101
    xmlAddSibling(psNode,
4✔
102
                  xmlNewComment(BAD_CAST
103
                                "WARNING: Optional metadata \"ows_abstract\" "
104
                                "was missing for ows:Abstract"));
105
  }
106

107
  value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces,
99✔
108
                                          "keywordlist", validated_language);
109

110
  if (value) {
99✔
111
    psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "Keywords", NULL);
95✔
112
    msLibXml2GenerateList(psNode, psNsOws, "Keyword", value, ',');
95✔
113
  }
114

115
  else {
116
    xmlAddSibling(
4✔
117
        psNode,
118
        xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_keywordlist\" "
119
                               "was missing for ows:KeywordList"));
120
  }
121

122
  psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "ServiceType",
99✔
123
                           BAD_CAST servicetype);
124

125
  xmlNewProp(psNode, BAD_CAST "codeSpace", BAD_CAST MS_OWSCOMMON_OGC_CODESPACE);
99✔
126

127
  msLibXml2GenerateList(psRootNode, psNsOws, "ServiceTypeVersion",
99✔
128
                        supported_versions, ',');
129

130
  value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces,
99✔
131
                                          "fees", validated_language);
132

133
  psNode =
134
      xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "Fees", BAD_CAST value);
99✔
135

136
  if (!value) {
99✔
137
    xmlAddSibling(psNode,
4✔
138
                  xmlNewComment(BAD_CAST
139
                                "WARNING: Optional metadata \"ows_fees\" was "
140
                                "missing for ows:Fees"));
141
  }
142

143
  value =
144
      msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces,
99✔
145
                                      "accessconstraints", validated_language);
146

147
  psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "AccessConstraints",
99✔
148
                           BAD_CAST value);
149

150
  if (!value) {
99✔
151
    xmlAddSibling(
4✔
152
        psNode,
153
        xmlNewComment(BAD_CAST
154
                      "WARNING: Optional metadata \"ows_accessconstraints\" "
155
                      "was missing for ows:AccessConstraints"));
156
  }
157

158
  return psRootNode;
99✔
159
}
160

161
/**
162
 * msOWSCommonServiceProvider()
163
 *
164
 * returns an object of ServiceProvider as per:
165
 *
166
 *
167
 * 1.0.0 subclause 7.4.4
168
 * 1.1.0 subclause 7.4.5
169
 *
170
 * @param map mapObj to fetch MAP/WEB/METADATA
171
 *
172
 * @return psRootNode xmlNodePtr pointer of XML construct
173
 *
174
 */
175

176
xmlNodePtr msOWSCommonServiceProvider(xmlNsPtr psNsOws, xmlNsPtr psNsXLink,
98✔
177
                                      mapObj *map, const char *namespaces,
178
                                      const char *validated_language) {
179
  const char *value = NULL;
180

181
  xmlNodePtr psNode = NULL;
182
  xmlNodePtr psRootNode = NULL;
183
  xmlNodePtr psSubNode = NULL;
184
  xmlNodePtr psSubSubNode = NULL;
185
  xmlNodePtr psSubSubSubNode = NULL;
186

187
  if (_validateNamespace(psNsOws) == MS_FAILURE)
98✔
188
    psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI,
×
189
                       BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX);
190

191
  psRootNode = xmlNewNode(psNsOws, BAD_CAST "ServiceProvider");
98✔
192

193
  /* add child elements */
194

195
  value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces,
98✔
196
                                          "contactorganization",
197
                                          validated_language);
198

199
  psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "ProviderName",
98✔
200
                           BAD_CAST value);
201

202
  if (!value) {
98✔
203
    xmlAddSibling(
4✔
204
        psNode,
205
        xmlNewComment(BAD_CAST
206
                      "WARNING: Mandatory metadata \"ows_contactorganization\" "
207
                      "was missing for ows:ProviderName"));
208
  }
209

210
  psNode = xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "ProviderSite", NULL);
98✔
211

212
  xmlNewNsProp(psNode, psNsXLink, BAD_CAST "type", BAD_CAST "simple");
98✔
213

214
  value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces,
98✔
215
                                          "service_onlineresource",
216
                                          validated_language);
217

218
  xmlNewNsProp(psNode, psNsXLink, BAD_CAST "href", BAD_CAST value);
98✔
219

220
  if (!value) {
98✔
221
    xmlAddSibling(
1✔
222
        psNode, xmlNewComment(
223
                    BAD_CAST
224
                    "WARNING: Optional metadata \"ows_service_onlineresource\" "
225
                    "was missing for ows:ProviderSite/@xlink:href"));
226
  }
227

228
  psNode =
229
      xmlNewTextChild(psRootNode, psNsOws, BAD_CAST "ServiceContact", NULL);
98✔
230

231
  value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces,
98✔
232
                                          "contactperson", validated_language);
233

234
  psSubNode = xmlNewTextChild(psNode, psNsOws, BAD_CAST "IndividualName",
98✔
235
                              BAD_CAST value);
236

237
  if (!value) {
98✔
238
    xmlAddSibling(
4✔
239
        psSubNode,
240
        xmlNewComment(BAD_CAST
241
                      "WARNING: Optional metadata \"ows_contactperson\" was "
242
                      "missing for ows:IndividualName"));
243
  }
244

245
  value = msOWSLookupMetadataWithLanguage(
98✔
246
      &(map->web.metadata), namespaces, "contactposition", validated_language);
247

248
  psSubNode =
249
      xmlNewTextChild(psNode, psNsOws, BAD_CAST "PositionName", BAD_CAST value);
98✔
250

251
  if (!value) {
98✔
252
    xmlAddSibling(
4✔
253
        psSubNode,
254
        xmlNewComment(BAD_CAST
255
                      "WARNING: Optional metadata \"ows_contactposition\" was "
256
                      "missing for ows:PositionName"));
257
  }
258

259
  psSubNode = xmlNewTextChild(psNode, psNsOws, BAD_CAST "ContactInfo", NULL);
98✔
260

261
  psSubSubNode = xmlNewTextChild(psSubNode, psNsOws, BAD_CAST "Phone", NULL);
98✔
262

263
  value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces,
98✔
264
                                          "contactvoicetelephone",
265
                                          validated_language);
266

267
  psSubSubSubNode =
268
      xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "Voice", BAD_CAST value);
98✔
269

270
  if (!value) {
98✔
271
    xmlAddSibling(
4✔
272
        psSubSubSubNode,
273
        xmlNewComment(
274
            BAD_CAST "WARNING: Optional metadata \"ows_contactvoicetelephone\" "
275
                     "was missing for ows:Voice"));
276
  }
277

278
  value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces,
98✔
279
                                          "contactfacsimiletelephone",
280
                                          validated_language);
281

282
  psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "Facsimile",
98✔
283
                                    BAD_CAST value);
284

285
  if (!value) {
98✔
286
    xmlAddSibling(
4✔
287
        psSubSubSubNode,
288
        xmlNewComment(
289
            BAD_CAST
290
            "WARNING: Optional metadata \"ows_contactfacsimiletelephone\" was "
291
            "missing for ows:Facsimile"));
292
  }
293

294
  psSubSubNode = xmlNewTextChild(psSubNode, psNsOws, BAD_CAST "Address", NULL);
98✔
295

296
  value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces,
98✔
297
                                          "address", validated_language);
298

299
  psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws,
98✔
300
                                    BAD_CAST "DeliveryPoint", BAD_CAST value);
301

302
  if (!value) {
98✔
303
    xmlAddSibling(
4✔
304
        psSubSubSubNode,
305
        xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_address\" was "
306
                               "missing for ows:DeliveryPoint"));
307
  }
308

309
  value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces,
98✔
310
                                          "city", validated_language);
311

312
  psSubSubSubNode =
313
      xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "City", BAD_CAST value);
98✔
314

315
  if (!value) {
98✔
316
    xmlAddSibling(psSubSubSubNode,
4✔
317
                  xmlNewComment(BAD_CAST
318
                                "WARNING: Optional metadata \"ows_city\" was "
319
                                "missing for ows:City"));
320
  }
321

322
  value = msOWSLookupMetadataWithLanguage(
98✔
323
      &(map->web.metadata), namespaces, "stateorprovince", validated_language);
324

325
  psSubSubSubNode = xmlNewTextChild(
98✔
326
      psSubSubNode, psNsOws, BAD_CAST "AdministrativeArea", BAD_CAST value);
327

328
  if (!value) {
98✔
329
    xmlAddSibling(
4✔
330
        psSubSubSubNode,
331
        xmlNewComment(BAD_CAST
332
                      "WARNING: Optional metadata \"ows_stateorprovince\" was "
333
                      "missing for ows:AdministrativeArea"));
334
  }
335

336
  value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces,
98✔
337
                                          "postcode", validated_language);
338

339
  psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws,
98✔
340
                                    BAD_CAST "PostalCode", BAD_CAST value);
341

342
  if (!value) {
98✔
343
    xmlAddSibling(psSubSubSubNode,
4✔
344
                  xmlNewComment(BAD_CAST
345
                                "WARNING: Optional metadata \"ows_postcode\" "
346
                                "was missing for ows:PostalCode"));
347
  }
348

349
  value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces,
98✔
350
                                          "country", validated_language);
351

352
  psSubSubSubNode = xmlNewTextChild(psSubSubNode, psNsOws, BAD_CAST "Country",
98✔
353
                                    BAD_CAST value);
354

355
  if (!value) {
98✔
356
    xmlAddSibling(
4✔
357
        psSubSubSubNode,
358
        xmlNewComment(BAD_CAST "WARNING: Optional metadata \"ows_country\" was "
359
                               "missing for ows:Country"));
360
  }
361

362
  value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces,
98✔
363
                                          "contactelectronicmailaddress",
364
                                          validated_language);
365

366
  psSubSubSubNode = xmlNewTextChild(
98✔
367
      psSubSubNode, psNsOws, BAD_CAST "ElectronicMailAddress", BAD_CAST value);
368

369
  if (!value) {
98✔
370
    xmlAddSibling(
4✔
371
        psSubSubSubNode,
372
        xmlNewComment(
373
            BAD_CAST
374
            "WARNING: Optional metadata \"ows_contactelectronicmailaddress\" "
375
            "was missing for ows:ElectronicMailAddress"));
376
  }
377

378
  psSubSubNode =
379
      xmlNewTextChild(psSubNode, psNsOws, BAD_CAST "OnlineResource", NULL);
98✔
380

381
  xmlNewNsProp(psSubSubNode, psNsXLink, BAD_CAST "type", BAD_CAST "simple");
98✔
382

383
  value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces,
98✔
384
                                          "service_onlineresource",
385
                                          validated_language);
386

387
  xmlNewNsProp(psSubSubNode, psNsXLink, BAD_CAST "href", BAD_CAST value);
98✔
388

389
  if (!value) {
98✔
390
    xmlAddSibling(
1✔
391
        psSubSubNode,
392
        xmlNewComment(
393
            BAD_CAST
394
            "WARNING: Optional metadata \"ows_service_onlineresource\" was "
395
            "missing for ows:OnlineResource/@xlink:href"));
396
  }
397

398
  value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces,
98✔
399
                                          "hoursofservice", validated_language);
400

401
  psSubSubNode = xmlNewTextChild(psSubNode, psNsOws, BAD_CAST "HoursOfService",
98✔
402
                                 BAD_CAST value);
403

404
  if (!value) {
98✔
405
    xmlAddSibling(
4✔
406
        psSubSubNode,
407
        xmlNewComment(BAD_CAST
408
                      "WARNING: Optional metadata \"ows_hoursofservice\" was "
409
                      "missing for ows:HoursOfService"));
410
  }
411

412
  value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces,
98✔
413
                                          "contactinstructions",
414
                                          validated_language);
415

416
  psSubSubNode = xmlNewTextChild(
98✔
417
      psSubNode, psNsOws, BAD_CAST "ContactInstructions", BAD_CAST value);
418

419
  if (!value) {
98✔
420
    xmlAddSibling(
4✔
421
        psSubSubNode,
422
        xmlNewComment(BAD_CAST
423
                      "WARNING: Optional metadata \"ows_contactinstructions\" "
424
                      "was missing for ows:ContactInstructions"));
425
  }
426

427
  value = msOWSLookupMetadataWithLanguage(&(map->web.metadata), namespaces,
98✔
428
                                          "role", validated_language);
429

430
  psSubNode = xmlNewTextChild(psNode, psNsOws, BAD_CAST "Role", BAD_CAST value);
98✔
431

432
  if (!value) {
98✔
433
    xmlAddSibling(psSubNode,
4✔
434
                  xmlNewComment(BAD_CAST
435
                                "WARNING: Optional metadata \"ows_role\" was "
436
                                "missing for ows:Role"));
437
  }
438

439
  return psRootNode;
98✔
440
}
441

442
/**
443
 * msOWSCommonOperationsMetadata()
444
 *
445
 * returns the root element of OperationsMetadata as per:
446
 *
447
 * 1.0.0 subclause 7.4.5
448
 * 1.1.0 subclause 7.4.6
449
 *
450
 * @return psRootNode xmlNodePtr pointer of XML construct
451
 *
452
 */
453

454
xmlNodePtr msOWSCommonOperationsMetadata(xmlNsPtr psNsOws) {
98✔
455
  xmlNodePtr psRootNode = NULL;
456

457
  if (_validateNamespace(psNsOws) == MS_FAILURE)
98✔
458
    psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI,
×
459
                       BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX);
460

461
  psRootNode = xmlNewNode(psNsOws, BAD_CAST "OperationsMetadata");
98✔
462
  return psRootNode;
98✔
463
}
464

465
/**
466
 * msOWSCommonOperationsMetadataOperation()
467
 *
468
 * returns an Operation element of OperationsMetadata as per:
469
 *
470
 * 1.0.0 subclause 7.4.5
471
 * 1.1.0 subclause 7.4.6
472
 *
473
 * @param name name of the Operation
474
 * @param method HTTP method: OWS_METHOD_GET, OWS_METHOD_POST or
475
 * OWS_METHOD_GETPOST)
476
 * @param url online resource URL
477
 *
478
 * @return psRootNode xmlNodePtr pointer of XML construct
479
 */
480

481
xmlNodePtr msOWSCommonOperationsMetadataOperation(xmlNsPtr psNsOws,
382✔
482
                                                  xmlNsPtr psXLinkNs,
483
                                                  const char *name, int method,
484
                                                  const char *url) {
485
  if (_validateNamespace(psNsOws) == MS_FAILURE)
382✔
486
    psNsOws = xmlNewNs(NULL, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI,
×
487
                       BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX);
488

489
  xmlNodePtr psRootNode = xmlNewNode(psNsOws, BAD_CAST "Operation");
382✔
490

491
  xmlNewProp(psRootNode, BAD_CAST "name", BAD_CAST name);
382✔
492

493
  xmlNodePtr psNode = xmlNewChild(psRootNode, psNsOws, BAD_CAST "DCP", NULL);
382✔
494

495
  xmlNodePtr psSubNode = xmlNewChild(psNode, psNsOws, BAD_CAST "HTTP", NULL);
382✔
496

497
  if (method == OWS_METHOD_GET || method == OWS_METHOD_GETPOST) {
382✔
498
    xmlNodePtr psSubSubNode =
499
        xmlNewChild(psSubNode, psNsOws, BAD_CAST "Get", NULL);
382✔
500
    xmlNewNsProp(psSubSubNode, psXLinkNs, BAD_CAST "type", BAD_CAST "simple");
382✔
501
    xmlNewNsProp(psSubSubNode, psXLinkNs, BAD_CAST "href", BAD_CAST url);
382✔
502
  }
503

504
  if (method == OWS_METHOD_POST || method == OWS_METHOD_GETPOST) {
382✔
505
    xmlNodePtr psSubSubNode =
506
        xmlNewChild(psSubNode, psNsOws, BAD_CAST "Post", NULL);
382✔
507
    xmlNewNsProp(psSubSubNode, psXLinkNs, BAD_CAST "type", BAD_CAST "simple");
382✔
508
    xmlNewNsProp(psSubSubNode, psXLinkNs, BAD_CAST "href", BAD_CAST url);
382✔
509
  }
510

511
  return psRootNode;
382✔
512
}
513

514
/**
515
 * msOWSCommonOperationsMetadataDomainType()
516
 *
517
 * returns a Parameter or Constraint element (which are of type ows:DomainType)
518
 * of OperationsMetadata as per:
519
 *
520
 * 1.0.0 subclause 7.4.5
521
 * 1.1.0 subclause 7.4.6
522
 *
523
 * @param version the integerized x.y.z version of OWS Common to use
524
 * @param elname name of the element (Parameter | Constraint)
525
 * @param name name of the Parameter
526
 * @param values list of values (comma separated list) or NULL if none
527
 *
528
 * @return psRootNode xmlNodePtr pointer of XML construct
529
 *
530
 */
531

532
xmlNodePtr msOWSCommonOperationsMetadataDomainType(int version,
675✔
533
                                                   xmlNsPtr psNsOws,
534
                                                   const char *elname,
535
                                                   const char *name,
536
                                                   const char *values) {
537
  if (_validateNamespace(psNsOws) == MS_FAILURE)
675✔
538
    psNsOws = xmlNewNs(NULL, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI,
×
539
                       BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX);
540

541
  xmlNodePtr psRootNode = xmlNewNode(psNsOws, BAD_CAST elname);
675✔
542

543
  xmlNewProp(psRootNode, BAD_CAST "name", BAD_CAST name);
675✔
544

545
  if (version == OWS_1_0_0) {
675✔
546
    msLibXml2GenerateList(psRootNode, psNsOws, "Value", values, ',');
122✔
547
  }
548
  if (version == OWS_1_1_0 || version == OWS_2_0_0) {
675✔
549
    xmlNodePtr psNode =
550
        xmlNewChild(psRootNode, psNsOws, BAD_CAST "AllowedValues", NULL);
553✔
551
    msLibXml2GenerateList(psNode, psNsOws, "Value", values, ',');
553✔
552
  }
553

554
  return psRootNode;
675✔
555
}
556

557
/**
558
 * msOWSCommonExceptionReport()
559
 *
560
 * returns an object of ExceptionReport as per clause 8
561
 *
562
 * @param ows_version the version of OWS Common to use
563
 * @param schemas_location URL to OGC Schemas Location base
564
 * @param version the version of the calling specification
565
 * @param language ISO3166 code of language
566
 * @param exceptionCode a code from the calling specification's list of
567
 * exceptions, or from OWS Common
568
 * @param locator where the exception was encountered (i.e. "layers" keyword)
569
 * @param ExceptionText the actual error message
570
 *
571
 * @return psRootNode xmlNodePtr pointer of XML construct
572
 *
573
 */
574

575
xmlNodePtr msOWSCommonExceptionReport(xmlNsPtr psNsOws, int ows_version,
105✔
576
                                      const char *schemas_location,
577
                                      const char *version, const char *language,
578
                                      const char *exceptionCode,
579
                                      const char *locator,
580
                                      const char *ExceptionText) {
581
  char *xsi_schemaLocation = NULL;
582
  char szVersionBuf[OWS_VERSION_MAXLEN];
583

584
  xmlNsPtr psNsXsi = NULL;
585
  xmlNodePtr psRootNode = NULL;
586
  xmlNodePtr psMainNode = NULL;
587

588
  psRootNode = xmlNewNode(psNsOws, BAD_CAST "ExceptionReport");
105✔
589

590
  psNsXsi = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_URI,
105✔
591
                     BAD_CAST MS_OWSCOMMON_W3C_XSI_NAMESPACE_PREFIX);
592

593
  /* add attributes to root element */
594
  xmlNewProp(psRootNode, BAD_CAST "version", BAD_CAST version);
105✔
595

596
  if (ows_version == OWS_1_0_0) {
105✔
597
    xmlNewProp(psRootNode, BAD_CAST "language", BAD_CAST language);
13✔
598
  }
599
  if (ows_version == OWS_1_1_0) {
105✔
600
    xmlNewProp(psRootNode, BAD_CAST "xml:lang", BAD_CAST language);
92✔
601
  }
602

603
  xsi_schemaLocation = msStrdup((char *)psNsOws->href);
105✔
604
  xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, " ");
105✔
605
  xsi_schemaLocation =
606
      msStringConcatenate(xsi_schemaLocation, (char *)schemas_location);
105✔
607
  xsi_schemaLocation = msStringConcatenate(xsi_schemaLocation, "/ows/");
105✔
608
  xsi_schemaLocation = msStringConcatenate(
105✔
609
      xsi_schemaLocation,
610
      (char *)msOWSGetVersionString(ows_version, szVersionBuf));
611
  xsi_schemaLocation =
612
      msStringConcatenate(xsi_schemaLocation, "/owsExceptionReport.xsd");
105✔
613

614
  /* add namespace'd attributes to root element */
615
  xmlNewNsProp(psRootNode, psNsXsi, BAD_CAST "schemaLocation",
105✔
616
               BAD_CAST xsi_schemaLocation);
617

618
  /* add child element */
619
  psMainNode = xmlNewChild(psRootNode, NULL, BAD_CAST "Exception", NULL);
105✔
620

621
  /* add attributes to child */
622
  xmlNewProp(psMainNode, BAD_CAST "exceptionCode", BAD_CAST exceptionCode);
105✔
623

624
  if (locator != NULL) {
105✔
625
    xmlNewProp(psMainNode, BAD_CAST "locator", BAD_CAST locator);
98✔
626
  }
627

628
  if (ExceptionText != NULL) {
105✔
629
    xmlNewTextChild(psMainNode, NULL, BAD_CAST "ExceptionText",
102✔
630
                    BAD_CAST ExceptionText);
631
  }
632

633
  free(xsi_schemaLocation);
105✔
634
  return psRootNode;
105✔
635
}
636

637
/**
638
 * msOWSCommonBoundingBox()
639
 *
640
 * returns an object of BoundingBox as per subclause 10.2.1
641
 *
642
 * If necessary (ie. an EPSG URN GCS such as 4326) the tuple axes will be
643
 * reoriented to match the EPSG coordinate system expectations.
644
 *
645
 * @param psNsOws OWS namespace object
646
 * @param crs the CRS / EPSG code
647
 * @param dimensions number of dimensions of the coordinates
648
 * @param minx minx
649
 * @param miny miny
650
 * @param maxx maxx
651
 * @param maxy maxy
652
 *
653
 * @return psRootNode xmlNodePtr pointer of XML construct
654
 */
655

656
xmlNodePtr msOWSCommonBoundingBox(xmlNsPtr psNsOws, const char *crs,
4✔
657
                                  int dimensions, double minx, double miny,
658
                                  double maxx, double maxy) {
659
  char LowerCorner[100];
660
  char UpperCorner[100];
661
  char dim_string[100];
662
  xmlNodePtr psRootNode = NULL;
663

664
  /* Do we need to reorient tuple axes? */
665
  if (crs && strstr(crs, "imageCRS") == NULL) {
4✔
666
    projectionObj proj;
667

668
    msInitProjection(&proj);
2✔
669
    if (msLoadProjectionString(&proj, (char *)crs) == 0) {
2✔
670
      msAxisNormalizePoints(&proj, 1, &minx, &miny);
2✔
671
      msAxisNormalizePoints(&proj, 1, &maxx, &maxy);
2✔
672
    }
673
    msFreeProjection(&proj);
2✔
674
  }
675

676
  if (_validateNamespace(psNsOws) == MS_FAILURE)
4✔
677
    psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI,
×
678
                       BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX);
679

680
  /* create element name */
681
  psRootNode = xmlNewNode(psNsOws, BAD_CAST "BoundingBox");
4✔
682

683
  /* add attributes to the root element */
684
  xmlNewProp(psRootNode, BAD_CAST "crs", BAD_CAST crs);
4✔
685

686
  snprintf(dim_string, sizeof(dim_string), "%d", dimensions);
687
  xmlNewProp(psRootNode, BAD_CAST "dimensions", BAD_CAST dim_string);
4✔
688

689
  snprintf(LowerCorner, sizeof(LowerCorner), "%.15g %.15g", minx, miny);
4✔
690
  snprintf(UpperCorner, sizeof(UpperCorner), "%.15g %.15g", maxx, maxy);
4✔
691

692
  /* add child elements */
693
  xmlNewChild(psRootNode, psNsOws, BAD_CAST "LowerCorner",
4✔
694
              BAD_CAST LowerCorner);
695
  xmlNewChild(psRootNode, psNsOws, BAD_CAST "UpperCorner",
4✔
696
              BAD_CAST UpperCorner);
697

698
  return psRootNode;
4✔
699
}
700

701
/**
702
 * msOWSCommonWGS84BoundingBox()
703
 *
704
 * returns an object of WGS84BoundingBox as per subclause 10.2.2
705
 *
706
 * @param psNsOws OWS namespace object
707
 * @param dimensions number of dimensions of the coordinates
708
 * @param minx minx
709
 * @param miny miny
710
 * @param maxx maxx
711
 * @param maxy maxy
712
 *
713
 * @return psRootNode xmlNodePtr pointer of XML construct
714
 */
715

716
xmlNodePtr msOWSCommonWGS84BoundingBox(xmlNsPtr psNsOws, int dimensions,
70✔
717
                                       double minx, double miny, double maxx,
718
                                       double maxy) {
719
  char LowerCorner[100];
720
  char UpperCorner[100];
721
  char dim_string[100];
722

723
  xmlNodePtr psRootNode = NULL;
724

725
  if (_validateNamespace(psNsOws) == MS_FAILURE)
70✔
726
    psNsOws = xmlNewNs(psRootNode, BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_URI,
×
727
                       BAD_CAST MS_OWSCOMMON_OWS_NAMESPACE_PREFIX);
728

729
  /* create element name */
730
  psRootNode = xmlNewNode(psNsOws, BAD_CAST "WGS84BoundingBox");
70✔
731

732
  snprintf(dim_string, sizeof(dim_string), "%d", dimensions);
733
  xmlNewProp(psRootNode, BAD_CAST "dimensions", BAD_CAST dim_string);
70✔
734

735
  snprintf(LowerCorner, sizeof(LowerCorner), "%.6f %.6f", minx, miny);
736
  snprintf(UpperCorner, sizeof(UpperCorner), "%.6f %.6f", maxx, maxy);
737

738
  /* add child elements */
739
  xmlNewChild(psRootNode, psNsOws, BAD_CAST "LowerCorner",
70✔
740
              BAD_CAST LowerCorner);
741
  xmlNewChild(psRootNode, psNsOws, BAD_CAST "UpperCorner",
70✔
742
              BAD_CAST UpperCorner);
743

744
  return psRootNode;
70✔
745
}
746

747
/**
748
 * _validateNamespace()
749
 *
750
 * validates the namespace passed to this module's functions
751
 *
752
 * @param psNsOws namespace object
753
 *
754
 * @return MS_SUCCESS or MS_FAILURE
755
 *
756
 */
757

758
int _validateNamespace(xmlNsPtr psNsOws) {
1,426✔
759
  char namespace_prefix[10];
760
  snprintf(namespace_prefix, sizeof(namespace_prefix), "%s", psNsOws->prefix);
1,426✔
761
  if (strcmp(namespace_prefix, MS_OWSCOMMON_OWS_NAMESPACE_PREFIX) == 0)
1,426✔
762
    return MS_SUCCESS;
763
  else
764
    return MS_FAILURE;
×
765
}
766

767
/*
768
 * Valid an xml string against an XML schema
769
 * Inpired from:
770
 * http://xml.developpez.com/sources/?page=validation#validate_XSD_CppCLI_2
771
 * taken from tinyows.org
772
 */
773
int msOWSSchemaValidation(const char *xml_schema, const char *xml) {
×
774
  xmlSchemaPtr schema;
775
  xmlSchemaParserCtxtPtr ctxt;
776
  xmlSchemaValidCtxtPtr validctxt;
777
  int ret;
778
  xmlDocPtr doc;
779

780
  if (!xml_schema || !xml)
×
781
    return MS_FAILURE;
782

783
  xmlInitParser();
×
784
  schema = NULL;
785
  ret = -1;
786

787
  /* To valid WFS 2.0 requests, we might need to explicitly import */
788
  /* GML and FES 2.0 */
789
  if (strlen(xml_schema) > strlen(MS_OWSCOMMON_WFS_20_SCHEMA_LOCATION) &&
×
790
      strcmp(xml_schema + strlen(xml_schema) -
×
791
                 strlen(MS_OWSCOMMON_WFS_20_SCHEMA_LOCATION),
792
             MS_OWSCOMMON_WFS_20_SCHEMA_LOCATION) == 0) {
×
793
    const size_t nLenBaseLocation =
794
        strlen(xml_schema) - strlen(MS_OWSCOMMON_WFS_20_SCHEMA_LOCATION);
795
    char *pszInMemSchema = NULL;
796
    char *pszBaseLocation = (char *)msSmallMalloc(nLenBaseLocation + 1);
×
797
    memcpy(pszBaseLocation, xml_schema, nLenBaseLocation);
798
    pszBaseLocation[nLenBaseLocation] = '\0';
×
799

800
    pszInMemSchema = msStringConcatenate(
×
801
        pszInMemSchema,
802
        "<schema elementFormDefault=\"qualified\" version=\"1.0.0\" "
803
        "xmlns=\"http://www.w3.org/2001/XMLSchema\">\n");
804

805
    pszInMemSchema = msStringConcatenate(
×
806
        pszInMemSchema, "<import namespace=\"" MS_OWSCOMMON_WFS_20_NAMESPACE_URI
807
                        "\" schemaLocation=\"");
808
    pszInMemSchema = msStringConcatenate(pszInMemSchema, xml_schema);
×
809
    pszInMemSchema = msStringConcatenate(pszInMemSchema, "\" />\n");
×
810

811
    if (strstr(xml, MS_OWSCOMMON_FES_20_NAMESPACE_URI) != NULL) {
×
812
      pszInMemSchema = msStringConcatenate(
×
813
          pszInMemSchema,
814
          "<import namespace=\"" MS_OWSCOMMON_FES_20_NAMESPACE_URI
815
          "\" schemaLocation=\"");
816
      pszInMemSchema = msStringConcatenate(pszInMemSchema, pszBaseLocation);
×
817
      pszInMemSchema = msStringConcatenate(
×
818
          pszInMemSchema, MS_OWSCOMMON_FES_20_SCHEMA_LOCATION "\" />\n");
819
    }
820

821
    if (strstr(xml, MS_OWSCOMMON_GML_32_NAMESPACE_URI) != NULL) {
×
822
      pszInMemSchema = msStringConcatenate(
×
823
          pszInMemSchema,
824
          "<import namespace=\"" MS_OWSCOMMON_GML_32_NAMESPACE_URI
825
          "\" schemaLocation=\"");
826
      pszInMemSchema = msStringConcatenate(pszInMemSchema, pszBaseLocation);
×
827
      pszInMemSchema = msStringConcatenate(
×
828
          pszInMemSchema, MS_OWSCOMMON_GML_321_SCHEMA_LOCATION "\" />\n");
829

830
    } else if (strstr(xml, MS_OWSCOMMON_GML_NAMESPACE_URI) != NULL) {
×
831
      if (strstr(xml, MS_OWSCOMMON_GML_212_SCHEMA_LOCATION) != NULL) {
×
832
        pszInMemSchema = msStringConcatenate(
×
833
            pszInMemSchema,
834
            "<import namespace=\"" MS_OWSCOMMON_GML_NAMESPACE_URI
835
            "\" schemaLocation=\"");
836
        pszInMemSchema = msStringConcatenate(pszInMemSchema, pszBaseLocation);
×
837
        pszInMemSchema = msStringConcatenate(
×
838
            pszInMemSchema, MS_OWSCOMMON_GML_212_SCHEMA_LOCATION "\" />\n");
839
      } else if (strstr(xml, MS_OWSCOMMON_GML_311_SCHEMA_LOCATION) != NULL) {
×
840
        pszInMemSchema = msStringConcatenate(
×
841
            pszInMemSchema,
842
            "<import namespace=\"" MS_OWSCOMMON_GML_NAMESPACE_URI
843
            "\" schemaLocation=\"");
844
        pszInMemSchema = msStringConcatenate(pszInMemSchema, pszBaseLocation);
×
845
        pszInMemSchema = msStringConcatenate(
×
846
            pszInMemSchema, MS_OWSCOMMON_GML_311_SCHEMA_LOCATION "\" />\n");
847
      }
848
    }
849

850
    pszInMemSchema = msStringConcatenate(pszInMemSchema, "</schema>\n");
×
851

852
    ctxt = xmlSchemaNewMemParserCtxt(pszInMemSchema, strlen(pszInMemSchema));
×
853
    msFree(pszInMemSchema);
×
854
    msFree(pszBaseLocation);
×
855
  } else {
856
    /* Open XML Schema File */
857
    ctxt = xmlSchemaNewParserCtxt(xml_schema);
×
858
  }
859

860
  /*
861
  xmlSchemaSetParserErrors(ctxt,
862
                           (xmlSchemaValidityErrorFunc) libxml2_callback,
863
                           (xmlSchemaValidityWarningFunc) libxml2_callback,
864
  stderr);
865
  */
866

867
  schema = xmlSchemaParse(ctxt);
×
868
  xmlSchemaFreeParserCtxt(ctxt);
×
869

870
  /* If XML Schema hasn't been rightly loaded */
871
  if (schema == NULL) {
×
872
    xmlCleanupParser();
×
873
    return ret;
×
874
  }
875

876
  doc = xmlParseDoc((xmlChar *)xml);
×
877

878
  if (doc != NULL) {
×
879
    /* Loading XML Schema content */
880
    validctxt = xmlSchemaNewValidCtxt(schema);
×
881
    /*
882
    xmlSchemaSetValidErrors(validctxt,
883
                            (xmlSchemaValidityErrorFunc) libxml2_callback,
884
                            (xmlSchemaValidityWarningFunc) libxml2_callback,
885
    stderr);
886
    */
887
    /* validation */
888
    ret = xmlSchemaValidateDoc(validctxt, doc);
×
889
    xmlSchemaFreeValidCtxt(validctxt);
×
890
  }
891

892
  xmlSchemaFree(schema);
×
893
  xmlFreeDoc(doc);
×
894
  xmlCleanupParser();
×
895

896
  return ret;
×
897
}
898

899
#endif /* defined(USE_LIBXML2) */
900

901
/**
902
 * msOWSCommonNegotiateVersion()
903
 *
904
 * returns a supported version as per subclause 7.3.2
905
 *
906
 * @param requested_version the version passed by the client
907
 * @param supported_versions an array of supported versions
908
 * @param num_supported_versions size of supported_versions
909
 *
910
 * @return supported version integer, or -1 on error
911
 *
912
 */
913

914
int msOWSCommonNegotiateVersion(int requested_version,
85✔
915
                                const int supported_versions[],
916
                                int num_supported_versions) {
917
  int i;
918

919
  /* if version is not set return error */
920
  if (!requested_version)
85✔
921
    return -1;
922

923
  /* return the first entry that's equal to the requested version */
924
  for (i = 0; i < num_supported_versions; i++) {
162✔
925
    if (supported_versions[i] == requested_version)
152✔
926
      return supported_versions[i];
73✔
927
  }
928

929
  /* no match; calling code should throw an exception */
930
  return -1;
931
}
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