/* * Add a given buffer to the end of an alist entry * if key exist, value is add to the list * if not new key entry is created */ void alist_add(alist * al, buffer * key, buffer * value) { alist_node *an; assert(al); assert(key); assert(value); if (!alist_is_key(al, key->buf)) { an = malloc(sizeof(alist_node)); assert(an); an->key = key; an->value = list_init(); if (!al->first) al->first = an; else al->last->next = an; al->last = an; al->last->next = NULL; } else { for (an = al->first ; an ; an = an->next) if (buffer_case_cmp(an->key, key->buf)) break; } list_add(an->value, value); }
/* * Check if a given key string is or not in the alist */ bool alist_is_key(const alist * al, const char *key) { alist_node *an; size_t ks; assert(al); assert(key); for (ks = strlen(key), an = al->first ; an ; an = an->next) if (ks == an->key->use) if (buffer_case_cmp(an->key, key)) return true; return false; }
/* * Return a value buffer from an alist (from key value) * You must be sure key is defined for this array, see is_key() above * Carreful return a reference on the alist buf itself ! */ list *alist_get(const alist * al, const char *key) { alist_node *an; size_t ks; assert(al); assert(key); for (ks = strlen(key), an = al->first ; an ; an = an->next) { if (ks == an->key->use) if (buffer_case_cmp(an->key, key)) break; } assert(an); return an->value; }
/* * Convert a PostgreSql type to a valid * OGC XMLSchema's type */ char *ows_psql_to_xsd(buffer * type, ows_version *version) { int wfs_version; assert(type); assert(version); wfs_version = ows_version_get(version); if (buffer_case_cmp(type, "geometry")) return "gml:GeometryPropertyType"; if (buffer_cmp(type, "geography")) return "gml:GeometryPropertyType"; if (buffer_cmp(type, "int2")) return "short"; if (buffer_cmp(type, "int4")) return "int"; if (buffer_cmp(type, "int8")) return "long"; if (buffer_cmp(type, "float4")) return "float"; if (buffer_cmp(type, "float8")) return "double"; if (buffer_cmp(type, "bool")) return "boolean"; if (buffer_cmp(type, "bytea")) return "byte"; if (buffer_cmp(type, "date")) return "date"; if (buffer_cmp(type, "time")) return "time"; if (buffer_ncmp(type, "numeric", 7)) return "decimal"; if (buffer_ncmp(type, "timestamp", 9)) return "dateTime"; /* Could be also timestamptz */ if (buffer_cmp(type, "POINT")) return "gml:PointPropertyType"; if (buffer_cmp(type, "LINESTRING") && wfs_version == 100) return "gml:LineStringPropertyType"; if (buffer_cmp(type, "LINESTRING") && wfs_version == 110) return "gml:CurvePropertyType"; if (buffer_cmp(type, "POLYGON") && wfs_version == 100) return "gml:PolygonPropertyType"; if (buffer_cmp(type, "POLYGON") && wfs_version == 110) return "gml:SurfacePropertyType"; if (buffer_cmp(type, "MULTIPOINT")) return "gml:MultiPointPropertyType"; if (buffer_cmp(type, "MULTILINESTRING") && wfs_version == 100) return "gml:MultiLineStringPropertyType"; if (buffer_cmp(type, "MULTILINESTRING") && wfs_version == 110) return "gml:MultiCurvePropertyType"; if (buffer_cmp(type, "MULTIPOLYGON") && wfs_version == 100) return "gml:MultiPolygonPropertyType"; if (buffer_cmp(type, "MULTIPOLYGON") && wfs_version == 110) return "gml:MultiSurfacePropertyType"; if (buffer_cmp(type, "GEOMETRYCOLLECTION")) return "gml:MultiGeometryPropertyType"; return "string"; }
/* * Parse char by char QUERY_STRING request and return an array key/value * (key are all lowercase) */ array *cgi_parse_kvp(ows * o, char *query) { int i; bool in_key; buffer *key; buffer *val; array *arr; char string[2]; assert(o); assert(query); key = buffer_init(); val = buffer_init(); arr = array_init(); in_key = true; cgi_unescape_url(query); cgi_remove_crlf(query); cgi_plustospace(query); for (i = 0; i < CGI_QUERY_MAX && query[i] ; i++) { if (query[i] == '&') { in_key = true; array_add(arr, key, val); key = buffer_init(); val = buffer_init(); } else if (query[i] == '=') { /* char '=' inside filter key mustn't be taken into account */ if ((!buffer_case_cmp(key, "filter") || !buffer_case_cmp(key, "outputformat")) && buffer_cmp(val, "")) in_key = false; else buffer_add(val, query[i]); } /* Check characters'CGI request */ else { /* to check the regular expression, argument must be a string, not a char */ string[0] = query[i]; string[1] = '\0'; if (in_key) { /* if word is key, only letters are allowed */ if (check_regexp(string, "[A-Za-zà-ÿ]")) buffer_add(key, tolower(query[i])); else { buffer_free(key); buffer_free(val); array_free(arr); ows_error(o, OWS_ERROR_MISSING_PARAMETER_VALUE, "QUERY_STRING contains forbidden characters", "request"); return NULL; } } else { /* if word is filter key, more characters are allowed */ if ( check_regexp(string, "[A-Za-zà-ÿ0-9.\\=;,():/\\*_ \\-]") || (buffer_cmp(key, "filter") && check_regexp(string, "[A-Za-zà-ÿ0-9.#\\,():/_<> %\"\'=\\*!\\-]|\\[|\\]"))) buffer_add(val, query[i]); else { buffer_free(key); buffer_free(val); array_free(arr); ows_error(o, OWS_ERROR_MISSING_PARAMETER_VALUE, "QUERY_STRING contains forbidden characters", "request"); return NULL; } } } } if (i == CGI_QUERY_MAX) { buffer_free(key); buffer_free(val); array_free(arr); ows_error(o, OWS_ERROR_REQUEST_HTTP, "QUERY_STRING too long", "request"); return NULL; } array_add(arr, key, val); return arr; }
/* * Execute the wfs get capabilities 1.1.0 request */ static void wfs_get_capabilities_110(ows * o, wfs_request * wr) { buffer *name; assert(o); assert(wr); if (wr->format == WFS_TEXT_XML) fprintf(o->output, "Content-Type: text/xml\n\n"); else fprintf(o->output, "Content-Type: application/xml\n\n"); fprintf(o->output, "<?xml version='1.0' encoding='%s'?>\n", o->encoding->buf); fprintf(o->output, "<WFS_Capabilities"); fprintf(o->output, " version='1.1.0' updateSequence='0'\n"); fprintf(o->output, " xmlns='http://www.opengis.net/wfs'\n"); fprintf(o->output, " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'\n"); fprintf(o->output, " xmlns:ogc='http://www.opengis.net/ogc'\n"); fprintf(o->output, " xmlns:gml='http://www.opengis.net/gml'\n"); fprintf(o->output, " xmlns:ows='http://www.opengis.net/ows'\n"); fprintf(o->output, " xmlns:xlink='http://www.w3.org/1999/xlink'\n"); fprintf(o->output, " xsi:schemaLocation='http://www.opengis.net/wfs\n"); fprintf(o->output, " http://schemas.opengis.net/wfs/1.1.0/wfs.xsd' >\n"); name = buffer_init(); /* Service Identification Section : provides information about the WFS service iself */ buffer_add_str(name, "ServiceIdentification"); if (wr->sections) { if (in_list(wr->sections, name) || buffer_case_cmp(wr->sections->first->value, "all")) ows_service_identification(o); } else ows_service_identification(o); /* Service Provider Section : provides metadata about the organization operating the WFS server */ buffer_empty(name); buffer_add_str(name, "ServiceProvider"); if (wr->sections) { if (in_list(wr->sections, name) || buffer_case_cmp(wr->sections->first->value, "all")) ows_service_provider(o); } else ows_service_provider(o); /* Operation Metadata Section : specifies the list of requests that the WFS can handle */ buffer_empty(name); buffer_add_str(name, "OperationsMetadata"); if (wr->sections) { if (in_list(wr->sections, name) || buffer_case_cmp(wr->sections->first->value, "all")) wfs_operations_metadata(o); } else wfs_operations_metadata(o); /* FeatureType list Section : specifies the list of feature types available from the wfs */ buffer_empty(name); buffer_add_str(name, "FeatureTypeList"); if (wr->sections) { if (in_list(wr->sections, name) || buffer_case_cmp(wr->sections->first->value, "all")) wfs_feature_type_list(o); } else wfs_feature_type_list(o); /* No ServesGMLObjectType list Section since there isn't any supported GML Object types not derived from gml:AbstractFeatureType */ /* SupportsGMLObjectType list Section : defines the list of GML Object types that the WFS server would be capable of serving */ buffer_empty(name); buffer_add_str(name, "SupportsGMLObjectTypeList"); if (wr->sections) { if (in_list(wr->sections, name) || buffer_case_cmp(wr->sections->first->value, "all")) wfs_gml_object_type_list(o); } else wfs_gml_object_type_list(o); /* Filter Capabilities Section : describe what specific filter capabilties are supported by the wfs */ fe_filter_capabilities_110(o); fprintf(o->output, "</WFS_Capabilities>\n"); fclose(o->output); buffer_free(name); }