Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed issue #1621 #1664

Merged
merged 2 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES_NEXT_RELEASE
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
72 changes: 71 additions & 1 deletion src/lib/orionld/troe/pgAttributeBuild.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
*
* Author: Ken Zangelin
*/
#include <string.h> // strlen, strcspn

extern "C"
{
#include "kjson/KjNode.h" // KjNode
Expand All @@ -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 -
Expand Down Expand Up @@ -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)
{
Expand Down
116 changes: 116 additions & 0 deletions test/functionalTest/cases/0000_troe/troe_urlencode_attr_value.test
Original file line number Diff line number Diff line change
@@ -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
Loading