From 5183018bf48b8b3cf6af3554dfc08168f999716e Mon Sep 17 00:00:00 2001 From: Ken Zangelin Date: Wed, 4 Sep 2024 17:54:07 +0200 Subject: [PATCH 1/2] Fixed issue #1621 --- CHANGES_NEXT_RELEASE | 1 + src/lib/orionld/troe/pgAttributeBuild.cpp | 72 ++++++++++- .../ngsild_subscription_count.test | 91 ++++++++++++++ .../0000_troe/troe_urlencode_attr_value.test | 116 ++++++++++++++++++ 4 files changed, 279 insertions(+), 1 deletion(-) create mode 100644 test/functionalTest/cases/0000_ngsild/ngsild_subscription_count.test create mode 100644 test/functionalTest/cases/0000_troe/troe_urlencode_attr_value.test diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index 3458b6cb56..82e1bb5c9b 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -1,4 +1,5 @@ ## Fixed Issues: + #1621: URL-Encoding single quote in attribute values in TRoE DB ## New Features: * Distributed subscriptions: subordinate subscriptions are DELETED when their "father" is deleted. diff --git a/src/lib/orionld/troe/pgAttributeBuild.cpp b/src/lib/orionld/troe/pgAttributeBuild.cpp index f403e1cbce..8c21f43002 100644 --- a/src/lib/orionld/troe/pgAttributeBuild.cpp +++ b/src/lib/orionld/troe/pgAttributeBuild.cpp @@ -22,6 +22,8 @@ * * Author: Ken Zangelin */ +#include // strlen, strcspn + extern "C" { #include "kjson/KjNode.h" // KjNode @@ -41,6 +43,68 @@ extern "C" +// ---------------------------------------------------------------------------- +// +// kjStringValueEncode - +// +static char* urlencode(const char* s, int sLen, int acceptedLen) +{ + int maxLen = (sLen - acceptedLen) * 3 + acceptedLen + 1; + char* sOut = kaAlloc(&orionldState.kalloc, maxLen); + + if (sOut == NULL) + return (char*) "too long string value"; + + int sIx = acceptedLen; + int sOutIx = acceptedLen; + + strncpy(sOut, s, acceptedLen); + + while (s[sIx] != 0) + { + if (s[sIx] == '\'') + { + sOut[sOutIx++] = '%'; + sOut[sOutIx++] = '2'; + sOut[sOutIx++] = '7'; + } + else + sOut[sOutIx++] = s[sIx]; + + ++sIx; + } + + return sOut; +} + + + +// ---------------------------------------------------------------------------- +// +// kjStringValueEncode - +// +void kjStringValueEncode(KjNode* nodeP) +{ + if (nodeP->type == KjString) + { + size_t len = strlen(nodeP->value.s); + size_t acceptedLen = strcspn(nodeP->value.s, "\'"); + + if (acceptedLen != len) + nodeP->value.s = urlencode(nodeP->value.s, len, acceptedLen); + } + else if ((nodeP->type == KjObject) || (nodeP->type == KjArray)) + { + for (KjNode* nP = nodeP->value.firstChildP; nP != NULL; nP = nP->next) + { + if ((nodeP->type == KjObject) || (nodeP->type == KjArray) || (nodeP->type == KjString)) + kjStringValueEncode(nP); + } + } +} + + + // ---------------------------------------------------------------------------- // // pgAttributeBuild - @@ -82,7 +146,13 @@ bool pgAttributeBuild else if (strcmp(nodeP->name, "unitCode") == 0) unitCode = nodeP->value.s; else if (strcmp(nodeP->name, "type") == 0) type = nodeP->value.s; else if (strcmp(nodeP->name, "datasetId") == 0) datasetId = nodeP->value.s; - else if (strcmp(nodeP->name, "value") == 0) valueNodeP = nodeP; + else if (strcmp(nodeP->name, "value") == 0) + { + if ((nodeP->type == KjObject) || (nodeP->type == KjArray) || (nodeP->type == KjString)) + kjStringValueEncode(nodeP); + + valueNodeP = nodeP; + } else if (strcmp(nodeP->name, "json") == 0) valueNodeP = nodeP; else if (strcmp(nodeP->name, "object") == 0) { diff --git a/test/functionalTest/cases/0000_ngsild/ngsild_subscription_count.test b/test/functionalTest/cases/0000_ngsild/ngsild_subscription_count.test new file mode 100644 index 0000000000..8168c42b66 --- /dev/null +++ b/test/functionalTest/cases/0000_ngsild/ngsild_subscription_count.test @@ -0,0 +1,91 @@ +# Copyright 2024 FIWARE Foundation e.V. +# +# This file is part of Orion-LD Context Broker. +# +# Orion-LD Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion-LD Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion-LD Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# orionld at fiware dot org + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +GET Subscriptions with count - issue #1647 + +--SHELL-INIT-- +dbInit CB +orionldStart CB -experimental + +--SHELL-- + +# +# 01. GET all subscriptions, with count set - see 0 and [] +# 02. Create subscription urn:S1 +# 03. GET all subscriptions, with count set - see 1 and urn:S1 +# 04. GET all subscriptions, with count set and limit=0- see 1 and [] +# + +echo "01. GET all subscriptions, with count set - see 0 and []" +echo "========================================================" +orionCurl --url /ngsi-ld/v1/subscriptions?count=true +echo +echo + + +echo "02. Create subscription urn:S1" +echo "==============================" +payload='{ + "id": "urn:S1", + "type": "Subscription", + "entities": [ + { + "idPattern": "urn:WeatherObserved", + "type": "WeatherObserved" + } + ], + "watchedAttributes": [ + "dateObserved" + ], + "isActive": true, + "notification": { + "format": "normalized", + "endpoint": { + "uri": "http://localhost:'$LISTENER_PORT'/notify", + "accept": "application/json" + } + } +}' +orionCurl --url /ngsi-ld/v1/subscriptions --payload "$payload" +echo +echo + + +echo "03. GET all subscriptions, with count set - see 1 and urn:S1" +echo "============================================================" +orionCurl --url /ngsi-ld/v1/subscriptions?count=true +echo +echo + + +echo "04. GET all subscriptions, with count set and limit=0- see 1 and []" +echo "===================================================================" +orionCurl --url '/ngsi-ld/v1/subscriptions?count=true&limit=0' +echo +echo + + +--REGEXPECT-- +--TEARDOWN-- +brokerStop CB +dbDrop CB diff --git a/test/functionalTest/cases/0000_troe/troe_urlencode_attr_value.test b/test/functionalTest/cases/0000_troe/troe_urlencode_attr_value.test new file mode 100644 index 0000000000..7d99d2bd57 --- /dev/null +++ b/test/functionalTest/cases/0000_troe/troe_urlencode_attr_value.test @@ -0,0 +1,116 @@ +# Copyright 2024 FIWARE Foundation e.V. +# +# This file is part of Orion-LD Context Broker. +# +# Orion-LD Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion-LD Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion-LD Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# orionld at fiware dot org + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +Attribute with strange chars in attribute value + +--SHELL-INIT-- +export BROKER=orionld +dbInit CB +pgInit $CB_DB_NAME +orionldStart CB -experimental -troe + +--SHELL-- + +# +# 01. Create an entity E1 with an attribute P1 with a string value with 'strange' characters +# 02. See all entities in TRoE DB +# 03. See all attributes in TRoE DB +# 04. See all sub-attributes in TRoE DB - there aren't any +# + +echo "01. Create an entity E1 with an attribute P1 with a string value with 'strange' characters" +echo "==========================================================================================" +payload='{ + "id": "urn:ngsi-ld:entity:E1", + "type": "Device", + "P1": "'\'0\''", + "P2": { + "value": { + "a": "1" + } + }, + "P3": { + "value": { + "a": "'\'2\''" + } + } +}' +orionCurl --url /ngsi-ld/v1/entities --payload "$payload" +echo +echo + + +echo "02. See all entities in TRoE DB" +echo "===============================" +postgresCmd -sql "SELECT opMode,id,type,ts FROM entities" +echo +echo + + +echo "03. See all attributes in TRoE DB" +echo "=================================" +postgresCmd -sql "SELECT opMode,id,valueType,entityId,subProperties,unitcode,datasetid,text,number,boolean,compound,observedAt,ts FROM attributes" +echo +echo + + +echo "04. See all sub-attributes in TRoE DB - there aren't any" +echo "========================================================" +postgresCmd -sql "SELECT id,valueType,entityId,attrInstanceId,unitcode,text,number,boolean FROM subAttributes" +echo +echo + + +--REGEXPECT-- +01. Create an entity E1 with an attribute P1 with a string value with 'strange' characters +========================================================================================== +HTTP/1.1 201 Created +Content-Length: 0 +Date: REGEX(.*) +Location: /ngsi-ld/v1/entities/urn:ngsi-ld:entity:E1 + + + +02. See all entities in TRoE DB +=============================== +opmode,id,type,ts +Create,urn:ngsi-ld:entity:E1,https://uri.etsi.org/ngsi-ld/default-context/Device,202REGEX(.*) + + +03. See all attributes in TRoE DB +================================= +opmode,id,valuetype,entityid,subproperties,unitcode,datasetid,text,number,boolean,compound,observedat,ts +Create,https://uri.etsi.org/ngsi-ld/default-context/P1,String,urn:ngsi-ld:entity:E1,f,,None,%270%27,,,,,202REGEX(.*) +Create,https://uri.etsi.org/ngsi-ld/default-context/P2,Compound,urn:ngsi-ld:entity:E1,f,,None,,,,"{""a"": ""1""}",,202REGEX(.*) +Create,https://uri.etsi.org/ngsi-ld/default-context/P3,Compound,urn:ngsi-ld:entity:E1,f,,None,,,,"{""a"": ""%272%27""}",,202REGEX(.*) + + +04. See all sub-attributes in TRoE DB - there aren't any +======================================================== +id,valuetype,entityid,attrinstanceid,unitcode,text,number,boolean + + +--TEARDOWN-- +brokerStop CB +dbDrop CB +pgDrop $CB_DB_NAME From 8686b55b6c1b66811b67f405d7803875cad703c0 Mon Sep 17 00:00:00 2001 From: Ken Zangelin Date: Thu, 5 Sep 2024 09:05:34 +0200 Subject: [PATCH 2/2] Removed an unfinished functest meant for another issue --- .../ngsild_subscription_count.test | 91 ------------------- 1 file changed, 91 deletions(-) delete mode 100644 test/functionalTest/cases/0000_ngsild/ngsild_subscription_count.test diff --git a/test/functionalTest/cases/0000_ngsild/ngsild_subscription_count.test b/test/functionalTest/cases/0000_ngsild/ngsild_subscription_count.test deleted file mode 100644 index 8168c42b66..0000000000 --- a/test/functionalTest/cases/0000_ngsild/ngsild_subscription_count.test +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright 2024 FIWARE Foundation e.V. -# -# This file is part of Orion-LD Context Broker. -# -# Orion-LD Context Broker is free software: you can redistribute it and/or -# modify it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Orion-LD Context Broker is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero -# General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Orion-LD Context Broker. If not, see http://www.gnu.org/licenses/. -# -# For those usages not covered by this license please contact with -# orionld at fiware dot org - -# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh - ---NAME-- -GET Subscriptions with count - issue #1647 - ---SHELL-INIT-- -dbInit CB -orionldStart CB -experimental - ---SHELL-- - -# -# 01. GET all subscriptions, with count set - see 0 and [] -# 02. Create subscription urn:S1 -# 03. GET all subscriptions, with count set - see 1 and urn:S1 -# 04. GET all subscriptions, with count set and limit=0- see 1 and [] -# - -echo "01. GET all subscriptions, with count set - see 0 and []" -echo "========================================================" -orionCurl --url /ngsi-ld/v1/subscriptions?count=true -echo -echo - - -echo "02. Create subscription urn:S1" -echo "==============================" -payload='{ - "id": "urn:S1", - "type": "Subscription", - "entities": [ - { - "idPattern": "urn:WeatherObserved", - "type": "WeatherObserved" - } - ], - "watchedAttributes": [ - "dateObserved" - ], - "isActive": true, - "notification": { - "format": "normalized", - "endpoint": { - "uri": "http://localhost:'$LISTENER_PORT'/notify", - "accept": "application/json" - } - } -}' -orionCurl --url /ngsi-ld/v1/subscriptions --payload "$payload" -echo -echo - - -echo "03. GET all subscriptions, with count set - see 1 and urn:S1" -echo "============================================================" -orionCurl --url /ngsi-ld/v1/subscriptions?count=true -echo -echo - - -echo "04. GET all subscriptions, with count set and limit=0- see 1 and []" -echo "===================================================================" -orionCurl --url '/ngsi-ld/v1/subscriptions?count=true&limit=0' -echo -echo - - ---REGEXPECT-- ---TEARDOWN-- -brokerStop CB -dbDrop CB