tinyows 1.2.2
wfs_request.c
Go to the documentation of this file.
1/*
2 Copyright (c) <2007-2012> <Barbara Philippot - Olivier Courtin>
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 IN THE SOFTWARE.
21*/
22
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <assert.h>
27#include <string.h>
28#include <ctype.h>
29
30#include "../ows/ows.h"
31
32
33/*
34 * Initialize wfs_request structure
35 */
37{
38 wfs_request *wr;
39
40 wr = malloc(sizeof(wfs_request));
41 assert(wr);
42
43 wr->request = WFS_REQUEST_UNKNOWN;
44 wr->format = WFS_FORMAT_UNKNOWN;
45 wr->typename = NULL;
46 wr->propertyname = NULL;
47 wr->bbox = NULL;
48 wr->srs = NULL;
49
50 wr->maxfeatures = -1;
51 wr->featureid = NULL;
52 wr->filter = NULL;
53 wr->operation = NULL;
54 wr->handle = NULL;
55 wr->resulttype = NULL;
56 wr->sortby = NULL;
57 wr->sections = NULL;
58 wr->callback = NULL;
59
60 wr->insert_results = NULL;
61 wr->delete_results = 0;
62 wr->update_results = 0;
63
64 return wr;
65}
66
67
68#ifdef OWS_DEBUG
69/*
70 * Print wfs_request structure
71 */
72void wfs_request_flush(wfs_request * wr, FILE * output)
73{
74 assert(wr && output);
75
76 fprintf(output, "[\n");
77
78 fprintf(output, " request -> %i\n", wr->request);
79 fprintf(output, " format -> %i\n", wr->format);
80 fprintf(output, " maxfeatures -> %i\n", wr->maxfeatures);
81
82 if (wr->typename) {
83 fprintf(output, " typename -> ");
84 list_flush(wr->typename, output);
85 fprintf(output, "\n");
86 }
87
88 if (wr->propertyname) {
89 fprintf(output, "propertyname -> ");
90 mlist_flush(wr->propertyname, output);
91 fprintf(output, "\n");
92 }
93
94 if (wr->bbox) {
95 fprintf(output, "bbox -> ");
96 ows_bbox_flush(wr->bbox, output);
97 fprintf(output, "\n");
98 }
99
100 if (wr->srs) {
101 fprintf(output, "srs -> ");
102 ows_srs_flush(wr->srs, output);
103 fprintf(output, "\n");
104 }
105
106 if (wr->featureid) {
107 fprintf(output, " featureid -> ");
108 mlist_flush(wr->featureid, output);
109 fprintf(output, "\n");
110 }
111
112 if (wr->filter) {
113 fprintf(output, " filter -> ");
114 list_flush(wr->filter, output);
115 fprintf(output, "\n");
116 }
117
118 if (wr->operation) {
119 fprintf(output, " operation -> ");
120 buffer_flush(wr->operation, output);
121 fprintf(output, "\n");
122 }
123
124 if (wr->handle) {
125 fprintf(output, " handle -> ");
126 list_flush(wr->handle, output);
127 fprintf(output, "\n");
128 }
129
130 if (wr->resulttype) {
131 fprintf(output, " resulttype -> ");
132 buffer_flush(wr->resulttype, output);
133 fprintf(output, "\n");
134 }
135
136 if (wr->sortby) {
137 fprintf(output, " sortby -> ");
138 buffer_flush(wr->sortby, output);
139 fprintf(output, "\n");
140 }
141
142 if (wr->sections) {
143 fprintf(output, " sections -> ");
144 list_flush(wr->sections, output);
145 fprintf(output, "\n");
146 }
147
148 if (wr->insert_results) {
149 fprintf(output, " insert_results -> ");
150 alist_flush(wr->insert_results, output);
151 fprintf(output, "\n");
152 }
153
154 if (wr->callback) {
155 fprintf(output, " callback -> ");
156 buffer_flush(wr->callback, output);
157 fprintf(output, "\n");
158 }
159
160 fprintf(output, "]\n");
161}
162#endif
163
164
165/*
166 * Release wfs_request structure
167 */
169{
170 assert(wr);
171
172 if (wr->typename) list_free(wr->typename);
173 if (wr->propertyname) mlist_free(wr->propertyname);
174 if (wr->bbox) ows_bbox_free(wr->bbox);
175 if (wr->srs) ows_srs_free(wr->srs);
176 if (wr->featureid) mlist_free(wr->featureid);
177 if (wr->filter) list_free(wr->filter);
178 if (wr->operation) buffer_free(wr->operation);
179 if (wr->handle) list_free(wr->handle);
180 if (wr->resulttype) buffer_free(wr->resulttype);
181 if (wr->sortby) buffer_free(wr->sortby);
182 if (wr->sections) list_free(wr->sections);
183 if (wr->insert_results) alist_free(wr->insert_results);
184 if (wr->callback) buffer_free(wr->callback);
185
186 free(wr);
187 wr = NULL;
188}
189
190
191/*
192 * Check if version is 1.0.0 or 1.1.0
193 */
194static void wfs_request_check_version(ows * o, wfs_request * wr, const array * cgi)
195{
196 assert(o && wr && cgi);
197
198 if (!array_is_key(cgi, "version"))
199 memcpy(o->request->version, o->wfs_default_version, sizeof(ows_version));
200
201 if (ows_version_get(o->request->version) != 100 && ows_version_get(o->request->version) != 110)
203 "VERSION parameter is not valid (use 1.0.0 or 1.1.0)", "version");
204}
205
206
207/*
208 * Check and fill typename parameter
209 * Return a list of layers' names
210 */
211static list *wfs_request_check_typename(ows * o, wfs_request * wr, list * layer_name)
212{
213 buffer *b, *n;
214 list_node *ln;
215
216 assert(o && wr && layer_name);
217
218 if (array_is_key(o->cgi, "typename")) {
219 b = array_get(o->cgi, "typename");
220 wr->typename = list_explode(',', b);
221
222 for (ln = wr->typename->first ; ln ; ln = ln->next) {
223
225 /* Check if layer exists and have storage */
226 if (!n || !ows_layer_match_table(o, n)) {
227 list_free(layer_name);
228 wfs_error(o, wr, WFS_ERROR_LAYER_NOT_DEFINED, "Unknown layer name", "typename");
229 return NULL;
230 }
231
232 /* Check if layer is retrievable */
233 if ((wr->request == WFS_GET_FEATURE || wr->request == WFS_DESCRIBE_FEATURE_TYPE)
234 && !ows_layer_retrievable(o->layers, n)) {
235 list_free(layer_name);
237 "Not retrievable layer(s), Forbidden operation.", "typename");
238 return NULL;
239 }
240
241 /* Check if layer is writable, if request is a transaction operation */
242 if (wr->operation && !ows_layer_writable(o->layers, n)) {
243 list_free(layer_name);
245 "Not writable layer(s), Forbidden Transaction Operation", "typename");
246 return NULL;
247 }
248
249 /* Fill the global layer name list */
250 list_add_by_copy(layer_name, n);
251 }
252 }
253
254 return layer_name;
255}
256
257
258/*
259 * Check and fill the featureid parameter
260 * Return a list of layers' names if typename parameter is not defined
261 */
262static list *wfs_request_check_fid(ows * o, wfs_request * wr, list * layer_name)
263{
264 list *fe, *ff;
265 mlist *f;
266 buffer *b, *layer;
267 list_node *ln, *ln_tpn;
268 mlist_node *mln = NULL;
269 ln = ln_tpn = NULL;
270
271 assert(o && wr && layer_name);
272
273 /* Featureid is not a mandatory parameter */
274 if (!array_is_key(o->cgi, "featureid")) return layer_name;
275
276 b = array_get(o->cgi, "featureid");
277 f = mlist_explode('(', ')', b);
278
279 if (wr->typename) {
280 /* Check if Typename and FeatureId size are similar */
281 if (f->size != wr->typename->size) {
282 mlist_free(f);
284 "featureid list and typename lists must have the same size", "");
285 return NULL;
286 }
287
288 ln_tpn = wr->typename->first;
289 }
290
291 for (mln = f->first ; mln ; mln = mln->next) {
292 for (ln = mln->value->first ; ln ; ln = ln->next) {
293 fe = list_split('.', ln->value, true);
294
295 /* Check the mapping between fid and typename */
296 if (wr->typename && !buffer_cmp(fe->last->value, ln_tpn->value->buf)) {
297 list_free(layer_name);
298 list_free(fe);
299 mlist_free(f);
300 wfs_error(o, wr, WFS_ERROR_NO_MATCHING, "featureid values and typename values don't match", "");
301 return NULL;
302 }
303
304 /* Check if featureid is well formed : layer.id */
305 if (!fe->first->next) {
306 list_free(layer_name);
307 list_free(fe);
308 mlist_free(f);
309 ows_error(o, OWS_ERROR_INVALID_PARAMETER_VALUE, "featureid must match layer.id", "GetFeature");
310 return NULL;
311 }
312
313 ff = list_split(':', fe->last->value, false);
314 layer = ows_layer_no_uri_to_uri(o->layers, ff->last->value);
315 list_free(ff);
316
317 /* If typename is NULL, fill the layer name list */
318 if (!wr->typename && !in_list(layer_name, layer))
319 list_add_by_copy(layer_name, layer);
320
321 /* Check if layer exists */
322 if (!ows_layer_in_list(o->layers, layer)) {
323 list_free(layer_name);
324 list_free(fe);
325 mlist_free(f);
326 wfs_error(o, wr, WFS_ERROR_LAYER_NOT_DEFINED, "Unknown layer name", "GetFeature");
327 return NULL;
328 }
329
330 /* Check if layer is retrievable if request is getFeature */
331 if (wr->request == WFS_GET_FEATURE && !ows_layer_retrievable(o->layers, layer)) {
332 list_free(layer_name);
333 list_free(fe);
334 mlist_free(f);
336 "Not-retrievable layer(s), GetFeature Operation not allowed",
337 "GetFeature");
338 return NULL;
339 }
340
341 /* Check if layer is writable if request is a transaction operation */
342 if (wr->operation && !ows_layer_writable(o->layers, layer)) {
343 list_free(layer_name);
344 list_free(fe);
345 mlist_free(f);
347 "Not-writable layer(s), Transaction Operation not allowed",
348 "Transaction");
349 return NULL;
350 }
351
352 list_free(fe);
353 }
354
355 if (wr->typename) ln_tpn = ln_tpn->next;
356 }
357
358 wr->featureid = f;
359
360 return layer_name;
361}
362
363
364/*
365 * Check and fill the bbox and srsName parameter
366 */
367static void wfs_request_check_srs(ows * o, wfs_request * wr, list * layer_name)
368{
369 buffer *b;
370 list_node *ln;
371 int srid, srid_tmp;
372
373 assert(o && wr && layer_name);
374
375 wr->srs = ows_srs_init();
376
377 /* srsName is not a mandatory parameter */
378 if (!array_is_key(o->cgi, "srsname")) {
379
380 /* We took the default SRS from the first requested layer */
381 srid = ows_srs_get_srid_from_layer(o, layer_name->first->value);
382
383 /* And check if all layers have the same SRS */
384 if (wr->typename && wr->typename->first->next) {
385 for (ln = layer_name->first->next ; ln ; ln = ln->next) {
386 srid_tmp = ows_srs_get_srid_from_layer(o, ln->value);
387
388 if (srid != srid_tmp) {
390 "Layers in TYPENAME must have the same SRS", "GetFeature");
391 return;
392 }
393 }
394 }
395
396 if(!ows_srs_set_from_srid(o, wr->srs, srid)) {
398 "The srsName value use an unsupported value, for requested layer(s)", "GetFeature");
399 return;
400 }
401
402 if (wr->format == WFS_GML311 || wr->format == WFS_GML321 ||
403 ows_version_get(o->request->version) == 110) {
404 wr->srs->honours_authority_axis_order = true;
405 wr->srs->is_long = true;
406 }
407
408 } else {
409 b = array_get(o->cgi, "srsname");
410 if (!ows_srs_set_from_srsname(o, wr->srs, b->buf)) {
412 "The srsName value use an unsupported value, for requested layer(s)", "GetFeature");
413 return;
414 }
415 }
416}
417
418
419/*
420 * Check and fill the bbox parameter
421 */
422static void wfs_request_check_bbox(ows * o, wfs_request * wr, list * layer_name)
423{
424 buffer *b;
425 int srid = 4326; /* Default srid if not srs is provided since WFS 1.1.0 */
426 bool honours_authority_axis_order_if_no_explicit_srs = false;
427
428 assert(o && wr && layer_name && wr->srs);
429
430 if (!array_is_key(o->cgi, "bbox")) return; /* BBOX is not mandatory */
431
432 b = array_get(o->cgi, "bbox");
433 wr->bbox = ows_bbox_init();
434
435 if (ows_version_get(o->request->version) == 100)
436 srid = wr->srs->srid;
437 else
438 honours_authority_axis_order_if_no_explicit_srs = true;
439
440 if (!ows_bbox_set_from_str(o, wr->bbox, b->buf, srid, honours_authority_axis_order_if_no_explicit_srs)) {
442 "Bad parameters for Bbox, must be Xmin,Ymin,Xmax,Ymax[,crsuri]", "NULL");
443 return;
444 }
445}
446
447
448/*
449 * Check and fill the output parameter
450 */
452{
453 assert(o && wr);
454
455 if (!array_is_key(o->cgi, "outputformat")) {
456 /* put the default values according to WFS version and request name */
457 if (ows_version_get(o->request->version) == 100) {
458 wr->format = WFS_GML212;
459 } else
460 wr->format = WFS_GML311;
461 } else {
462 if ( buffer_cmp(array_get(o->cgi, "outputformat"), "GML2")
463 || buffer_cmp(array_get(o->cgi, "outputformat"), "text/xml; subtype=gml/2.1.2"))
464 wr->format = WFS_GML212;
465 else if ( buffer_cmp(array_get(o->cgi, "outputformat"), "GML3")
466 || buffer_cmp(array_get(o->cgi, "outputformat"), "text/xml; subtype=gml/3.1.1"))
467 wr->format = WFS_GML311;
468 else if ( buffer_cmp(array_get(o->cgi, "outputformat"), "JSON")
469 || buffer_cmp(array_get(o->cgi, "outputformat"), "application/json"))
470 wr->format = WFS_GEOJSON;
471 else if ( buffer_cmp(array_get(o->cgi, "outputformat"), "JSONP")
472 || buffer_cmp(array_get(o->cgi, "outputformat"), "application/javascript"))
473 {
474 wr->format = WFS_JSONP;
475
476 wr->callback = buffer_init();
477 if (!array_is_key(o->cgi, "callback"))
478 buffer_add_str(wr->callback, "wfs_jsonp_callback");
479 else
480 buffer_copy(wr->callback, array_get(o->cgi, "callback"));
481 }
482 else if ( wr->request == WFS_DESCRIBE_FEATURE_TYPE
483 && buffer_cmp(array_get(o->cgi, "outputformat"), "XMLSCHEMA")) // FIXME: really ?
484 wr->format = WFS_XML_SCHEMA;
485 else
487 "OutputFormat is not supported", "GetFeature");
488 }
489
490
491
492}
493
494
495/*
496 * Check and fill the resultType parameter
497 */
499{
500 buffer *b;
501 assert(o && wr);
502
503 wr->resulttype = buffer_init();
504
505 /* default value is 'results' */
506 if (!array_is_key(o->cgi, "resulttype")) {
507 buffer_add_str(wr->resulttype, "results");
508 return;
509 }
510
511 b = array_get(o->cgi, "resulttype");
512
513 if (buffer_cmp(b, "results") || buffer_cmp(b, "hits"))
514 buffer_copy(wr->resulttype, b);
515 else
517 "ResultType isn't valid, must be results or hits", "resultType");
518}
519
520
521/*
522 * Check and fill the sortBy parameter
523 */
524static void wfs_request_check_sortby(ows * o, wfs_request * wr, list * layer_name)
525{
526 buffer *b;
527 list *l, *fe;
528 list_node *ln = NULL;
529
530 assert(o && wr);
531 /* sortBy is not a mandatory parameter */
532 if (!array_is_key(o->cgi, "sortby")) return;
533
534 b = array_get(o->cgi, "sortby");
535 wr->sortby = buffer_init();
536 l = list_explode(',', b);
537
538 for (ln = l->first ; ln ; ln = ln->next) {
539 fe = list_explode(' ', ln->value);
540 wfs_request_remove_prop_ns_prefix(o, fe->first->value, layer_name);
541
542 /* Add quotation marks */
543 buffer_add_head_str(fe->first->value, "\"");
544 buffer_add_str(fe->first->value, "\"");
545
546 /* SQL Order syntax */
547 if (fe->last->value && fe->last != fe->first) {
548 if (buffer_cmp(fe->last->value, "D") || buffer_cmp(fe->last->value, "DESC")) {
549 buffer_empty(fe->last->value);
550 buffer_add_str(fe->last->value, "DESC");
551 } else {
552 buffer_empty(fe->last->value);
553 buffer_add_str(fe->last->value, "ASC");
554 }
555 }
556
557 buffer_copy(wr->sortby, fe->first->value);
558 buffer_add_str(wr->sortby, " ");
559
560 if (fe->last->value && fe->last != fe->first)
561 buffer_copy(wr->sortby, fe->last->value);
562 else buffer_add_str(wr->sortby, "ASC");
563
564 if (ln->next) buffer_add_str(wr->sortby, ",");
565
566 list_free(fe);
567 }
568
569 list_free(l);
570}
571
572
573/*
574 * Check and fill the maxFeatures parameter
575 */
577{
578 int mf;
579 buffer *b;
580
581 assert(o && wr);
582
583 /* maxFeatures is not a mandatory parameter */
584 if (!array_is_key(o->cgi, "maxfeatures")) return;
585
586 b = array_get(o->cgi, "maxfeatures");
587 mf = atoi(b->buf);
588
589 if (mf > 0) wr->maxfeatures = mf;
591 "MaxFeatures isn't valid, must be > 0", "GetFeature");
592}
593
594
595/*
596 * TODO
597 */
599{
600 list * ns;
601 list_node * ln;
602
603 assert(o && prop && layer_name);
604
605 ns = ows_layer_list_ns_prefix(o->layers, layer_name);
606
607 for (ln = ns->first ; ln ; ln = ln->next) {
608 if (buffer_ncmp(ln->value, prop->buf, ln->value->use)) {
609 buffer_shift(prop, ln->value->use + 1); /* +1 for : separator */
610 list_free(ns);
611 return prop;
612 }
613 }
614
615 list_free(ns);
616 return prop; /* if ns_prefix don't match, just don't do anything */
617}
618
619
620/*
621 * Check and fill the propertyName parameter
622 */
623static void wfs_request_check_propertyname(ows * o, wfs_request * wr, list * layer_name)
624{
625 mlist *f;
626 buffer *b;
627 array *prop_table;
628 list_node *ln, *ln_tpn;
629 mlist_node *mln = NULL;
630
631 ln = ln_tpn = NULL;
632
633 assert(o && wr && layer_name);
634
635 /* propertyName is not a mandatory parameter */
636 if (!array_is_key(o->cgi, "propertyname")) return;
637
638 b = array_get(o->cgi, "propertyname");
639 f = mlist_explode('(', ')', b);
640
641 /*check if propertyname size and typename or fid size are similar */
642 if (f->size != layer_name->size) {
643 mlist_free(f);
645 "propertyname list size and typename list size must be similar", "GetFeature");
646 return;
647 }
648
649 for (mln = f->first, ln_tpn = layer_name->first ; mln ; mln = mln->next, ln_tpn = ln_tpn->next) {
650 prop_table = ows_psql_describe_table(o, ln_tpn->value);
651
652 for (ln = mln->value->first ; ln ; ln = ln->next) {
653
654 /* if propertyname is an Xpath expression */
655 if (check_regexp(ln->value->buf, "\\*\\["))
656 ln->value = fe_xpath_property_name(o, ln_tpn->value, ln->value);
657
658 /* check if propertyname values are correct */
659 ln->value = wfs_request_remove_prop_ns_prefix(o, ln->value, layer_name);
660 if (!buffer_cmp(ln->value, "*") && !array_is_key(prop_table, ln->value->buf)) {
661 mlist_free(f);
663 "PropertyName values not available", "GetFeature");
664 return;
665 }
666 }
667 }
668
669 wr->propertyname = f;
670}
671
672
673/*
674 * Check and fill the filter parameter
675 */
677{
678 buffer *b, *filter;
679 assert(o && wr);
680
681 if (!array_is_key(o->cgi, "filter")) return; /* Filter is not mandatory */
682
683 b = array_get(o->cgi, "filter");
684 filter = buffer_init();
685 buffer_copy(filter, b);
686 wr->filter = list_explode_start_end('(', ')', filter);
687
688 if (wr->filter->size != wr->typename->size)
690 "Filter list size and typename list size must be similar", "GetFeature");
691
692 buffer_free(filter);
693}
694
695
696/*
697 * Check and fill the operation parameter
698 * Only used for GET method and Delete Operation
699 */
701{
702 assert(o && wr);
703
704 /* OPERATION parameter is mandatory */
705 if (!array_is_key(o->cgi, "operation")) {
706 ows_error(o, OWS_ERROR_MISSING_PARAMETER_VALUE, "Operation (Delete) must be specified", "Operation");
707 return;
708 }
709
710 wr->operation = buffer_init();
711 buffer_copy(wr->operation, array_get(o->cgi, "operation"));
712
713 if (!buffer_cmp(wr->operation, "Delete")) {
715 "Only Delete operation is supported with GET method, use POST method for insert and update operations",
716 "Transaction");
717 return;
718 }
719}
720
721
722/*
723 * Check global parameters validity
724 */
726{
727 assert(o && wr);
728
729 if (!array_is_key(o->cgi, "typename") && !array_is_key(o->cgi, "featureid")) {
730 ows_error(o, OWS_ERROR_MISSING_PARAMETER_VALUE, "TYPENAME or FEATUREID must be set", "request");
731 return;
732 }
733
734 /* Test mutually exclusive parameters (FILTER, BBOX and FEATUREID) */
735 if ( (array_is_key(o->cgi, "filter") && array_is_key(o->cgi, "bbox"))
736 || (array_is_key(o->cgi, "filter") && array_is_key(o->cgi, "featureid"))
737 || (array_is_key(o->cgi, "bbox") && array_is_key(o->cgi, "featureid")))
739 "FILTER, BBOX and FEATUREID are mutually exclusive, just use one of these parameters", "request");
740}
741
742
743/*
744 * Check and fill all WFS get_capabilities parameter
745 */
746static void wfs_request_check_get_capabilities(ows * o, wfs_request * wr, const array * cgi)
747{
748 buffer *b;
749 list *l;
750 list_node *ln = NULL;
751 bool version = false;
752
753 assert(o && wr && cgi);
754
755 /* If key version is not set, version = higher version */
756 if (!array_is_key(cgi, "version")) {
757 ows_version_set(o->request->version, 1, 1, 0);
758 } else {
759 if (ows_version_get(o->request->version) < 110) ows_version_set(o->request->version, 1, 0, 0);
760 else if (ows_version_get(o->request->version) > 110) ows_version_set(o->request->version, 1, 1, 0);
761 }
762
763 /* 1.1.0 parameter : uses the first valid version */
764 if (array_is_key(cgi, "acceptversions")) {
765 b = array_get(cgi, "acceptversions");
766 l = list_explode(',', b);
767
768 for (ln = l->first ; ln ; ln = ln->next) {
769 if (version == false) {
770 if (buffer_cmp(ln->value, "1.0.0")) {
771 ows_version_set(o->request->version, 1, 0, 0);
772 version = true;
773 } else if (buffer_cmp(ln->value, "1.1.0")) {
774 ows_version_set(o->request->version, 1, 1, 0);
775 version = true;
776 }
777 }
778 }
779
780 list_free(l);
781 /* if versions weren't 1.0.0 or 1.1.0, raise an error */
782 if (version == false) {
784 "VERSION parameter is not valid (use 1.0.0 or 1.1.0)",
785 "AcceptVersions");
786 return;
787 }
788 }
789
790 /* FIXME updateSequence is not yet implemented */
791 if (array_is_key(cgi, "updatesequence")) {
792 b = array_get(cgi, "updatesequence");
793
794 if (!buffer_cmp(b, "0")) {
796 "UPDATESEQUENCE value must be omit or 0, function not (yet) implemented",
797 "updateSequence");
798 return;
799 }
800 }
801
802 /* Sections */
803 if (array_is_key(cgi, "sections")) {
804 b = array_get(cgi, "sections");
805 l = list_explode(',', b);
806 wr->sections = l;
807 }
808
809 /* AcceptFormats */
810 if (array_is_key(cgi, "acceptformats")) {
811 b = array_get(cgi, "acceptformats");
812
813 if (buffer_cmp(b, "text/xml")) wr->format = WFS_TEXT_XML;
814 else if (buffer_cmp(b, "application/xml")) wr->format = WFS_APPLICATION_XML;
816 "Not supported format : use text/xml or application/xml", "acceptFormats");
817 }
818}
819
820
821/*
822 * Check and fill all WFS describe_feature_type parameter
823 */
825{
826 list *layer_name;
827 ows_layer_node *ln = NULL;
828 assert(o && wr && cgi);
829
830 wfs_request_check_output(o, wr); /* OutputFormat */
831 if(o->exit) return;
832
833 /* Typename */
834 layer_name = list_init();
835 layer_name = wfs_request_check_typename(o, wr, layer_name);
836 if(o->exit) return;
837 list_free(layer_name);
838
839 /* if no Typename parameter is given, retrieve all layers defined in configuration file */
840 if (!array_is_key(cgi, "typename")) {
841 wr->typename = list_init();
842
843 for (ln = o->layers->first ; ln ; ln = ln->next)
844 if (ows_layer_match_table(o, ln->layer->name))
845 list_add_by_copy(wr->typename, ln->layer->name_prefix);
846 }
847}
848
849
850/*
851 * Check anf fill parameters of GetFeature request
852 */
853static void wfs_request_check_get_feature(ows * o, wfs_request * wr, const array * cgi)
854{
855 list *layer_name;
856 assert(o && wr && cgi);
857
858 wfs_request_check_parameters(o, wr); /* Check parameters validity */
859
860 layer_name = list_init();
861
862 /* TypeName (required except if there is a FeatureId parameter) */
863 if (!o->exit) layer_name = wfs_request_check_typename(o, wr, layer_name);
864
865 /* FeatureId, if no TypeName defined, list of layer_name must be extracted from FeatureId */
866 if (!o->exit) layer_name = wfs_request_check_fid(o, wr, layer_name);
867
868 if (!o->exit) wfs_request_check_srs(o, wr, layer_name); /* srsName */
869 if (!o->exit) wfs_request_check_bbox(o, wr, layer_name); /* BBOX=xmin,ymin,xmax,ymax[,srs] */
870 if (!o->exit) wfs_request_check_propertyname(o, wr, layer_name); /* PropertyName */
871 if (!o->exit) wfs_request_check_output(o, wr); /* outputFormat */
872 if (!o->exit) wfs_request_check_resulttype(o, wr); /* resultType */
873 if (!o->exit) wfs_request_check_sortby(o, wr, layer_name); /* sortBy */
874 if (!o->exit) wfs_request_check_maxfeatures(o, wr); /* maxFeatures */
875 if (!o->exit) wfs_request_check_filter(o, wr); /* Filter */
876
877 if (layer_name) list_free(layer_name);
878}
879
880
881/*
882 * Check anf fill parameters of Transaction request
883 */
884static void wfs_request_check_transaction(ows * o, wfs_request * wr, const array * cgi)
885{
886 list *layer_name;
887 assert(o && wr && cgi);
888
889 layer_name = list_init();
890
891 if (!o->exit) wfs_request_check_operation(o, wr); /* Operation */
892 if (!o->exit) wfs_request_check_parameters(o, wr); /* General checks */
893 if (!o->exit) layer_name = wfs_request_check_typename(o, wr, layer_name); /* Typename */
894 if (!o->exit) layer_name = wfs_request_check_fid(o, wr, layer_name); /* FeatureId */
895 if (!o->exit) wfs_request_check_bbox(o, wr, layer_name); /* Bbox */
896 if (!o->exit) wfs_request_check_filter(o, wr); /* Filter */
897
898 list_free(layer_name);
899}
900
901
902/*
903 * Check if wfs_request is valid
904 */
905void wfs_request_check(ows * o, wfs_request * wr, const array * cgi)
906{
907 buffer *b;
908 assert(o && wr && cgi);
909
910 b = array_get(cgi, "request");
911
912 /* Service */
913 if (o->request->service != WFS) {
914 ows_error(o, OWS_ERROR_INVALID_PARAMETER_VALUE, "bad service, should be WFS", "SERVICE");
915 return;
916 }
917
918 /* Version */
919 if (!buffer_case_cmp(b, "GetCapabilities")) {
920 wfs_request_check_version(o, wr, cgi);
921 if (o->exit) return;
922 }
923
924 /* Request */
925 if (buffer_case_cmp(b, "GetCapabilities")) {
926 wr->request = WFS_GET_CAPABILITIES;
928
929 } else if (buffer_case_cmp(b, "DescribeFeatureType")) {
930 wr->request = WFS_DESCRIBE_FEATURE_TYPE;
932
933 } else if (buffer_case_cmp(b, "GetFeature")) {
934 wr->request = WFS_GET_FEATURE;
936
937 } else if (buffer_case_cmp(b, "Transaction")) {
938 wr->request = WFS_TRANSACTION;
940
942 "REQUEST is not supported", "REQUEST");
943}
944
945
946/*
947 * Main function to call the right action's function
948 */
949void wfs(ows * o, wfs_request * wf)
950{
951 buffer *op;
952 assert(o && wf);
953
954 /* Run the request's execution */
955 switch (wf->request) {
958 break;
959
962 break;
963
964 case WFS_GET_FEATURE:
965 wfs_get_feature(o, wf);
966 break;
967
968 case WFS_TRANSACTION:
969
970 if (cgi_method_get()) {
971 if (buffer_cmp(wf->operation, "Delete"))
972 wfs_delete(o, wf);
973 else {
975 "Only Delete Operation is supported with GET method, use POST instead for Insert and Update.",
976 "Transaction");
977 return;
978 }
979
980 } else {
981 if (array_is_key(o->cgi, "operations")) {
982 op = array_get(o->cgi, "operations");
983 wfs_parse_operation(o, wf, op);
984 } else {
985 ows_error(o, OWS_ERROR_INVALID_PARAMETER_VALUE, "Operation parameter must be set", "Transaction");
986 return;
987 }
988 }
989
990 break;
991
992 default: assert(0); /* Should not happen */
993 }
994}
void wfs_get_capabilities(ows *o, wfs_request *wr)
void ows_bbox_free(ows_bbox *b)
Definition ows_bbox.c:58
void alist_free(alist *al)
Definition alist.c:56
int ows_version_get(ows_version *v)
bool ows_layer_in_list(const ows_layer_list *ll, buffer *name)
Definition ows_layer.c:193
void list_add_by_copy(list *l, buffer *value)
Definition list.c:187
void buffer_empty(buffer *buf)
Definition buffer.c:100
ows_bbox * ows_bbox_init()
Definition ows_bbox.c:37
list * list_explode_start_end(char separator_start, char separator_end, buffer *value)
Definition list.c:366
void buffer_copy(buffer *dest, const buffer *src)
Definition buffer.c:350
ows_srs * ows_srs_init()
Definition ows_srs.c:37
bool buffer_cmp(const buffer *buf, const char *str)
Definition buffer.c:290
buffer * fe_xpath_property_name(ows *o, buffer *typename, buffer *property)
Definition fe_filter.c:186
bool in_list(const list *l, const buffer *value)
Definition list.c:259
bool cgi_method_get()
Definition cgi_request.c:42
void list_free(list *l)
Definition list.c:54
void buffer_add_str(buffer *buf, const char *str)
Definition buffer.c:254
void list_flush(const list *l, FILE *output)
list * list_init()
Definition list.c:36
void buffer_flush(buffer *buf, FILE *output)
Definition buffer.c:112
void wfs_delete(ows *o, wfs_request *wr)
bool buffer_case_cmp(const buffer *buf, const char *str)
Definition buffer.c:330
bool ows_srs_set_from_srsname(ows *o, ows_srs *s, const char *srsname)
Definition ows_srs.c:303
bool ows_layer_match_table(const ows *o, const buffer *name)
Definition ows_layer.c:84
void ows_bbox_flush(const ows_bbox *b, FILE *output)
bool ows_srs_set_from_srid(ows *o, ows_srs *s, int srid)
Definition ows_srs.c:251
void wfs_describe_feature_type(ows *o, wfs_request *wr)
buffer * array_get(const array *a, const char *key)
Definition array.c:147
void alist_flush(const alist *al, FILE *output)
void wfs_error(ows *o, wfs_request *wf, enum wfs_error_code code, char *message, char *locator)
Definition wfs_error.c:124
void ows_error(ows *o, enum ows_error_code code, char *message, char *locator)
Definition ows_error.c:71
bool ows_bbox_set_from_str(ows *o, ows_bbox *bb, const char *str, int srid, bool honours_authority_axis_order_if_no_explicit_srs)
Definition ows_bbox.c:96
bool buffer_ncmp(const buffer *buf, const char *str, size_t n)
Definition buffer.c:310
mlist * mlist_explode(char separator_start, char separator_end, buffer *value)
Definition mlist.c:144
void wfs_parse_operation(ows *o, wfs_request *wr, buffer *op)
void buffer_add_head_str(buffer *buf, char *str)
Definition buffer.c:239
buffer * ows_layer_no_uri_to_uri(const ows_layer_list *ll, buffer *name_no_uri)
Definition ows_layer.c:392
bool array_is_key(const array *a, const char *key)
Definition array.c:105
void ows_srs_flush(ows_srs *c, FILE *output)
bool ows_layer_retrievable(const ows_layer_list *ll, const buffer *name)
Definition ows_layer.c:141
list * ows_layer_list_ns_prefix(ows_layer_list *ll, list *layer_name_prefix)
Definition ows_layer.c:281
array * ows_psql_describe_table(ows *o, buffer *layer_name)
Definition ows_psql.c:373
void buffer_free(buffer *buf)
Definition buffer.c:83
void mlist_flush(const mlist *ml, FILE *output)
void wfs_get_feature(ows *o, wfs_request *wr)
void buffer_shift(buffer *buf, size_t len)
Definition buffer.c:392
list * list_split(char separator, const buffer *value, bool reverse)
Definition list.c:324
int ows_srs_get_srid_from_layer(ows *o, buffer *layer_name)
Definition ows_srs.c:380
void wfs_request_flush(wfs_request *wr, FILE *output)
void ows_srs_free(ows_srs *c)
Definition ows_srs.c:76
void ows_version_set(ows_version *v, int major, int minor, int release)
Definition ows_version.c:51
buffer * buffer_init()
Definition buffer.c:61
bool ows_layer_writable(const ows_layer_list *ll, const buffer *name)
Definition ows_layer.c:175
list * list_explode(char separator, const buffer *value)
Definition list.c:296
bool check_regexp(const char *str_request, const char *str_regex)
Definition regexp.c:36
buffer * ows_layer_prefix_to_uri(ows_layer_list *ll, buffer *layer_name_prefix)
Definition ows_layer.c:343
void mlist_free(mlist *ml)
Definition mlist.c:54
struct List_node list_node
struct Ows_version ows_version
struct Ows_layer_node ows_layer_node
struct Buffer buffer
struct Mlist_node mlist_node
struct Ows ows
@ WFS_APPLICATION_XML
Definition ows_struct.h:286
@ WFS_FORMAT_UNKNOWN
Definition ows_struct.h:278
@ WFS_GEOJSON
Definition ows_struct.h:283
@ WFS_TEXT_XML
Definition ows_struct.h:285
@ WFS_XML_SCHEMA
Definition ows_struct.h:279
@ WFS_GML311
Definition ows_struct.h:281
@ WFS_GML321
Definition ows_struct.h:282
@ WFS_GML212
Definition ows_struct.h:280
@ WFS_JSONP
Definition ows_struct.h:284
struct Mlist mlist
@ WFS_ERROR_EXCLUSIVE_PARAMETERS
Definition ows_struct.h:262
@ WFS_ERROR_INCORRECT_SIZE_PARAMETER
Definition ows_struct.h:263
@ WFS_ERROR_NO_MATCHING
Definition ows_struct.h:264
@ WFS_ERROR_LAYER_NOT_WRITABLE
Definition ows_struct.h:261
@ WFS_ERROR_OUTPUT_FORMAT_NOT_SUPPORTED
Definition ows_struct.h:258
@ WFS_ERROR_LAYER_NOT_RETRIEVABLE
Definition ows_struct.h:260
@ WFS_ERROR_LAYER_NOT_DEFINED
Definition ows_struct.h:259
@ OWS_ERROR_OPERATION_NOT_SUPPORTED
Definition ows_struct.h:157
@ OWS_ERROR_VERSION_NEGOTIATION_FAILED
Definition ows_struct.h:160
@ OWS_ERROR_MISSING_PARAMETER_VALUE
Definition ows_struct.h:158
@ OWS_ERROR_INVALID_PARAMETER_VALUE
Definition ows_struct.h:159
@ OWS_ERROR_INVALID_UPDATE_SEQUENCE
Definition ows_struct.h:161
wfs_request
Definition ows_struct.h:269
@ WFS_TRANSACTION
Definition ows_struct.h:274
@ WFS_GET_CAPABILITIES
Definition ows_struct.h:271
@ WFS_REQUEST_UNKNOWN
Definition ows_struct.h:270
@ WFS_GET_FEATURE
Definition ows_struct.h:273
@ WFS_DESCRIBE_FEATURE_TYPE
Definition ows_struct.h:272
struct Array array
@ WFS
Definition ows_struct.h:242
struct List list
char * buf
size to next realloc
Definition ows_struct.h:39
size_t use
Definition ows_struct.h:36
struct List_node * next
Definition ows_struct.h:45
buffer * value
Definition ows_struct.h:44
unsigned int size
Definition ows_struct.h:52
list_node * last
Definition ows_struct.h:51
list_node * first
Definition ows_struct.h:50
struct Mlist_node * next
Definition ows_struct.h:58
list * value
Definition ows_struct.h:57
mlist_node * first
Definition ows_struct.h:63
unsigned int size
Definition ows_struct.h:65
ows_layer_node * first
Definition ows_struct.h:205
ows_layer * layer
Definition ows_struct.h:199
struct Ows_layer_node * next
Definition ows_struct.h:200
buffer * name
Definition ows_struct.h:177
buffer * name_prefix
Definition ows_struct.h:178
ows_version * version
Definition ows_struct.h:353
enum ows_service service
Definition ows_struct.h:355
ows_request * request
Definition ows_struct.h:403
ows_version * wfs_default_version
Definition ows_struct.h:404
array * cgi
Definition ows_struct.h:400
bool exit
Definition ows_struct.h:368
ows_layer_list * layers
Definition ows_struct.h:402
static list * wfs_request_check_fid(ows *o, wfs_request *wr, list *layer_name)
static void wfs_request_check_get_capabilities(ows *o, wfs_request *wr, const array *cgi)
static void wfs_request_check_propertyname(ows *o, wfs_request *wr, list *layer_name)
buffer * wfs_request_remove_prop_ns_prefix(ows *o, buffer *prop, list *layer_name)
static void wfs_request_check_operation(ows *o, wfs_request *wr)
void wfs_request_free(wfs_request *wr)
static void wfs_request_check_resulttype(ows *o, wfs_request *wr)
void wfs_request_check(ows *o, wfs_request *wr, const array *cgi)
static void wfs_request_check_maxfeatures(ows *o, wfs_request *wr)
wfs_request * wfs_request_init()
Definition wfs_request.c:36
static void wfs_request_check_output(ows *o, wfs_request *wr)
static list * wfs_request_check_typename(ows *o, wfs_request *wr, list *layer_name)
static void wfs_request_check_get_feature(ows *o, wfs_request *wr, const array *cgi)
static void wfs_request_check_describe_feature_type(ows *o, wfs_request *wr, const array *cgi)
static void wfs_request_check_filter(ows *o, wfs_request *wr)
static void wfs_request_check_srs(ows *o, wfs_request *wr, list *layer_name)
static void wfs_request_check_version(ows *o, wfs_request *wr, const array *cgi)
static void wfs_request_check_sortby(ows *o, wfs_request *wr, list *layer_name)
static void wfs_request_check_parameters(ows *o, wfs_request *wr)
static void wfs_request_check_bbox(ows *o, wfs_request *wr, list *layer_name)
void wfs(ows *o, wfs_request *wf)
static void wfs_request_check_transaction(ows *o, wfs_request *wr, const array *cgi)

Generated for tinyows by doxygen 1.13.2