From 7126f2498543a90a54c1c90d8495972c41ad4e92 Mon Sep 17 00:00:00 2001 From: Francesco Boccacci Date: Wed, 7 Feb 2024 08:48:10 +0100 Subject: [PATCH] Prevent `RequestNotWellFormed` error for invalid characters in BBOX requests (ref: layer names with spaces, colons or slashes) (#566) * :bug: Use regex that substitute only blanck space with underscore * :bug: Use regex that substitute only blanck space with underscore and replace / with no space * :bug: Fix filter SELECTED layers. Fix bug on query bypolygon. It returned features of selected layer. Wrong * In case of wfs request, need to take in account replace of / and : on layer Name * make use of `has(filter.SELECTED)` * inline replacer * variable name * wrong param * micro perf opts * variable name * Remove layerName. Not translate. useless * Take in account drawpolygon query type * Update src/app/core/layers/imagelayer.js replace all : with - using replaceAll string method Co-authored-by: Raruto * Remove plus regex. * Sanitize also / slash * remove console.log --------- Co-authored-by: Raruto --- src/app/core/layers/imagelayer.js | 4 +- src/app/core/layers/layersstore.js | 40 +++++++++---------- .../controls/querybydrawpolygoncontrol.js | 3 +- .../gui/queryresults/queryresultsservice.js | 3 +- src/components/QueryResults.vue | 1 + src/utils/parsers/index.js | 15 ++++--- 6 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/app/core/layers/imagelayer.js b/src/app/core/layers/imagelayer.js index 78b53f020..bcd1ddcd7 100644 --- a/src/app/core/layers/imagelayer.js +++ b/src/app/core/layers/imagelayer.js @@ -171,8 +171,8 @@ proto.getWmsUrl = function({ type = 'map' } = {}) { return this.config.wmsUrl; }; -proto.getWFSLayerName = function(){ - return this.getQueryLayerName().replace(/[/\s]/g, '_') +proto.getWFSLayerName = function() { + return this.getQueryLayerName().replace(/\s/g, '_').replaceAll( ':', '-' ); }; proto.useProxy = function(){ diff --git a/src/app/core/layers/layersstore.js b/src/app/core/layers/layersstore.js index 256a7c74b..91a0090d6 100644 --- a/src/app/core/layers/layersstore.js +++ b/src/app/core/layers/layersstore.js @@ -90,7 +90,7 @@ proto.getLayersDict = function(filter = {}, options = {}) { filter.FILTERABLE, filter.EDITABLE, filter.VISIBLE, - // filter.SELECTED, + filter.SELECTED, filter.CACHED, filter.SELECTED_OR_ALL, filter.SERVERTYPE, @@ -109,33 +109,31 @@ proto.getLayersDict = function(filter = {}, options = {}) { if (filter.IDS) { const ids = [].concat(filter.IDS); - layers = layers.filter(layer => -1 !== ids.indexOf(layer.getId())); + layers = layers.filter(l => -1 !== ids.indexOf(l.getId())); } - // return only selected if some one are selected + // check if there are `selected` layers otherwise get all `layers` if (filter.SELECTED_OR_ALL) { - let _layers = layers; - layers = layers.filter(layer => layer.isSelected()); - layers = layers.length ? layers : _layers; - } else if (false === filter.SELECTED_OR_ALL) { - layers = layers.filter(layer => filter.SELECTED === layer.isSelected()); + const selected = layers.filter(l => l.isSelected()); + layers = selected.length > 0 ? selected : layers; } // checks if a boolean filter is setted const has = f => 'boolean' === typeof f; - - if (has(filter.QUERYABLE)) layers = layers.filter(layer => filter.QUERYABLE === layer.isQueryable()); - if (has(filter.FILTERABLE)) layers = layers.filter(layer => filter.FILTERABLE === layer.isFilterable(options.filtrable || null)); - if (has(filter.EDITABLE)) layers = layers.filter(layer => filter.EDITABLE === layer.isEditable()); - if (has(filter.VISIBLE)) layers = layers.filter(layer => filter.VISIBLE === layer.isVisible()); - if (has(filter.CACHED)) layers = layers.filter(layer => filter.CACHED === layer.isCached()); - if (has(filter.BASELAYER)) layers = layers.filter(layer => filter.BASELAYER === layer.isBaseLayer()); - if (has(filter.GEOLAYER)) layers = layers.filter(layer => filter.GEOLAYER === layer.state.geolayer); - if (has(filter.VECTORLAYER)) layers = layers.filter(layer => filter.VECTORLAYER === layer.isType('vector')); - if (has(filter.HIDDEN)) layers = layers.filter(layer => filter.HIDDEN == layer.isHidden()); - if (has(filter.DISABLED)) layers = layers.filter(layer => filter.DISABLED === layer.isDisabled()); - if ('string' === typeof filter.SERVERTYPE && filter.SERVERTYPE.length) layers = layers.filter(layer => filter.SERVERTYPE === layer.getServerType()); - if (filter.PRINTABLE) layers = layers.filter(layer => layer.state.geolayer && layer.isPrintable({ scale: filter.PRINTABLE.scale })); + + if (has(filter.SELECTED) && !filter.SELECTED_OR_ALL) layers = layers.filter(l => filter.SELECTED === l.isSelected()); + if (has(filter.QUERYABLE)) layers = layers.filter(l => filter.QUERYABLE === l.isQueryable()); + if (has(filter.FILTERABLE)) layers = layers.filter(l => filter.FILTERABLE === l.isFilterable(options.filtrable || null)); + if (has(filter.EDITABLE)) layers = layers.filter(l => filter.EDITABLE === l.isEditable()); + if (has(filter.VISIBLE)) layers = layers.filter(l => filter.VISIBLE === l.isVisible()); + if (has(filter.CACHED)) layers = layers.filter(l => filter.CACHED === l.isCached()); + if (has(filter.BASELAYER)) layers = layers.filter(l => filter.BASELAYER === l.isBaseLayer()); + if (has(filter.GEOLAYER)) layers = layers.filter(l => filter.GEOLAYER === l.state.geolayer); + if (has(filter.VECTORLAYER)) layers = layers.filter(l => filter.VECTORLAYER === l.isType('vector')); + if (has(filter.HIDDEN)) layers = layers.filter(l => filter.HIDDEN == l.isHidden()); + if (has(filter.DISABLED)) layers = layers.filter(l => filter.DISABLED === l.isDisabled()); + if ('string' === typeof filter.SERVERTYPE && filter.SERVERTYPE.length) layers = layers.filter(l => filter.SERVERTYPE === l.getServerType()); + if (filter.PRINTABLE) layers = layers.filter(l => l.state.geolayer && l.isPrintable({ scale: filter.PRINTABLE.scale })); return layers; }; diff --git a/src/app/g3w-ol/controls/querybydrawpolygoncontrol.js b/src/app/g3w-ol/controls/querybydrawpolygoncontrol.js index 6e6e714cd..025f20da3 100644 --- a/src/app/g3w-ol/controls/querybydrawpolygoncontrol.js +++ b/src/app/g3w-ol/controls/querybydrawpolygoncontrol.js @@ -153,7 +153,6 @@ proto.runSpatialQuery = async function() { try { await DataRouterService.getData('query:polygon', { inputs: { - layerName: 'Draw', feature: this.feature, excludeSelected: (null === this.getSelectedLayer()), external: { @@ -177,7 +176,7 @@ proto.runSpatialQuery = async function() { } }); - } catch(err){ + } catch(err) { console.warn(err) } }; diff --git a/src/app/gui/queryresults/queryresultsservice.js b/src/app/gui/queryresults/queryresultsservice.js index efe449870..27b0fd626 100644 --- a/src/app/gui/queryresults/queryresultsservice.js +++ b/src/app/gui/queryresults/queryresultsservice.js @@ -2316,7 +2316,8 @@ QueryResultsService.prototype.setters = { switch (this.state.query.type) { case 'coordinates': this.showCoordinates(this.state.query.coordinates); break; case 'bbox': this.showBBOX(this.state.query.bbox); break; - case 'polygon': this.showGeometry(this.state.query.geometry); break; + case 'polygon': + case 'drawpolygon': this.showGeometry(this.state.query.geometry); break; } } diff --git a/src/components/QueryResults.vue b/src/components/QueryResults.vue index b977052a9..947dacbb4 100644 --- a/src/components/QueryResults.vue +++ b/src/components/QueryResults.vue @@ -469,6 +469,7 @@ message: ` [${query.bbox.join(' , ')}]` }; case 'polygon': + case 'drawpolygon': return { icon: 'draw', message: (query.layerName) ? diff --git a/src/utils/parsers/index.js b/src/utils/parsers/index.js index 1c99edc66..f3f7b0ba8 100644 --- a/src/utils/parsers/index.js +++ b/src/utils/parsers/index.js @@ -161,15 +161,20 @@ const utils = { }, handleXMLStringResponseBeforeConvertToJSON({response, layers, wms}={}) { if (!response) return; // return undefined if no response - if (!(typeof response === 'string'|| response instanceof String)) + if (!(typeof response === 'string'|| response instanceof String)) { response = new XMLSerializer().serializeToString(response); + } for (let i=0; i < layers.length; i++) { const layer = layers[i]; let originalName = (wms && layer.isWmsUseLayerIds()) ? layer.getId(): layer.getName(); - let sanitizeLayerName = wms ? originalName.replace(/[/\s]/g, '') : originalName.replace(/[/\s]/g, '_'); - sanitizeLayerName = sanitizeLayerName.replace(/(\'+)/, ''); - sanitizeLayerName = sanitizeLayerName.replace(/(\)+)/, ''); - sanitizeLayerName = sanitizeLayerName.replace(/(\(+)/, ''); + let sanitizeLayerName = wms ? originalName.replace(/[/\s]/g, '') : originalName.replace(/\s/g, '_'); + sanitizeLayerName = sanitizeLayerName.replace(/(\'+)/, ''); + sanitizeLayerName = sanitizeLayerName.replace(/(\)+)/, ''); + sanitizeLayerName = sanitizeLayerName.replace(/(\(+)/, ''); + sanitizeLayerName = wms ? sanitizeLayerName : sanitizeLayerName.replace(/\//g, ''); + sanitizeLayerName = wms ? sanitizeLayerName : sanitizeLayerName.replace(/\\/g, ''); + sanitizeLayerName = wms ? sanitizeLayerName : sanitizeLayerName.replace(/\:/g, '-'); + const reg = new RegExp(`qgs:${sanitizeLayerName}`, "g"); response = response.replace(reg, `qgs:layer${i}`); }