From 30b9e6c3227a968bd592c61b6a6451c3caf0bd05 Mon Sep 17 00:00:00 2001 From: Etienne Trimaille Date: Wed, 6 Nov 2024 14:37:09 +0100 Subject: [PATCH] Add a safety check about expressions and tokens --- lizmap_server/core.py | 16 ++++++++++++++++ lizmap_server/expression_service.py | 9 +++++---- lizmap_server/get_feature_info.py | 4 ++-- test/test_server_core.py | 7 +++++++ 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/lizmap_server/core.py b/lizmap_server/core.py index 67a04d34..cd2b0a43 100755 --- a/lizmap_server/core.py +++ b/lizmap_server/core.py @@ -392,3 +392,19 @@ def _server_feature_id_expression(feature_id: str, pk_attributes: list, fields: expression += QgsExpression.createFieldEqualityExpression(field_name, pk_values[i]) return expression + + +def qgis_expression(text: str, only_fields: bool = False) -> Tuple[QgsExpression, bool]: + """ Get the QGIS expression. """ + exp = QgsExpression(text) + if only_fields: + functions = exp.referencedFunctions() + if len(functions) >= 1: + logger = Logger() + logger.critical( + f"The expression below\n{text}\ncontains some functions : {','.join(functions)}\n" + f"Returning an empty expression." + ) + return QgsExpression(''), False + + return exp, True diff --git a/lizmap_server/expression_service.py b/lizmap_server/expression_service.py index ed84b5c3..c42756f6 100755 --- a/lizmap_server/expression_service.py +++ b/lizmap_server/expression_service.py @@ -34,6 +34,7 @@ get_lizmap_groups, get_lizmap_user_login, get_server_fid, + qgis_expression, write_json_response, ) from lizmap_server.exception import ExpressionServiceError @@ -187,7 +188,7 @@ def evaluate(params: Dict[str, str], response: QgsServerResponse, project: QgsPr elif isinstance(exp_json, dict): exp_items = exp_json.items() for k, e in exp_items: - exp = QgsExpression(e) + exp = qgis_expression(e)[0] exp.setGeomCalculator(da) exp.setDistanceUnits(project.distanceUnits()) exp.setAreaUnits(project.areaUnits()) @@ -716,7 +717,7 @@ def get_feature_with_form_scope( da.setEllipsoid(project.ellipsoid()) # Get filter expression - exp_f = QgsExpression(exp_filter) + exp_f = qgis_expression(exp_filter)[0] exp_f.setGeomCalculator(da) exp_f.setDistanceUnits(project.distanceUnits()) exp_f.setAreaUnits(project.areaUnits()) @@ -840,7 +841,7 @@ def virtualFields(params: Dict[str, str], response: QgsServerResponse, project: exp_map = {} exp_parser_errors = [] for k, e in vir_json.items(): - exp = QgsExpression(e) + exp = qgis_expression(e)[0] exp.setGeomCalculator(da) exp.setDistanceUnits(project.distanceUnits()) exp.setAreaUnits(project.areaUnits()) @@ -868,7 +869,7 @@ def virtualFields(params: Dict[str, str], response: QgsServerResponse, project: # get filter req_filter = params.get('FILTER', '') if req_filter: - req_exp = QgsExpression(req_filter) + req_exp = qgis_expression(req_filter)[0] req_exp.setGeomCalculator(da) req_exp.setDistanceUnits(project.distanceUnits()) req_exp.setAreaUnits(project.areaUnits()) diff --git a/lizmap_server/get_feature_info.py b/lizmap_server/get_feature_info.py index 3e534f4c..7c079f9f 100755 --- a/lizmap_server/get_feature_info.py +++ b/lizmap_server/get_feature_info.py @@ -24,7 +24,7 @@ ) from qgis.server import QgsServerFilter, QgsServerProjectUtils -from lizmap_server.core import find_vector_layer, server_feature_id_expression +from lizmap_server.core import find_vector_layer, server_feature_id_expression, qgis_expression from lizmap_server.logger import Logger, exception_handler from lizmap_server.tools import to_bool from lizmap_server.tooltip import Tooltip @@ -230,7 +230,7 @@ def responseComplete(self): expression = server_feature_id_expression(result.feature_id, result.layer.dataProvider()) if expression: - expression_request = QgsFeatureRequest(QgsExpression(expression)) + expression_request = QgsFeatureRequest(qgis_expression(expression)[0]) if not geometry_result: expression_request.setFlags(QgsFeatureRequest.NoGeometry) feature = QgsFeature() diff --git a/test/test_server_core.py b/test/test_server_core.py index 2d31f164..9ab59947 100755 --- a/test/test_server_core.py +++ b/test/test_server_core.py @@ -12,6 +12,7 @@ get_lizmap_config, get_lizmap_layer_login_filter, get_lizmap_layers_config, + qgis_expression, ) from lizmap_server.get_feature_info import GetFeatureInfoFilter from lizmap_server.tools import to_bool @@ -266,3 +267,9 @@ def test_feature_id_expression(self): "\"field_1\" = '1' AND \"field_2\" = '2'", _server_feature_id_expression("1@@2", ['field_1', 'field_2'], fields), ) + + def test_expression(self): + """ Test about expressions and tokens. """ + self.assertTrue(qgis_expression('"hi"')[1]) + self.assertTrue(qgis_expression('hi')[1]) + self.assertTrue(qgis_expression('lower("hi")')[1])