Skip to content

Commit 6a83e8a

Browse files
Merge pull request #78 from bonitoo-io/fix/escaping
fix: proper invalid chars escaping
2 parents 66ed5d0 + efd2d26 commit 6a83e8a

File tree

4 files changed

+99
-67
lines changed

4 files changed

+99
-67
lines changed

src/InfluxDbClient.cpp

Lines changed: 1 addition & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ static const char UnitialisedMessage[] PROGMEM = "Unconfigured instance";
5050
static const char RetryAfter[] = "Retry-After";
5151
static const char TransferEnconding[] = "Transfer-Encoding";
5252

53-
static String escapeKey(String key);
54-
static String escapeValue(const char *value);
5553
static String escapeJSONString(String &value);
5654

5755
static String precisionToString(WritePrecision precision, uint8_t version = 2) {
@@ -70,7 +68,7 @@ static String precisionToString(WritePrecision precision, uint8_t version = 2) {
7068
}
7169

7270
Point::Point(String measurement):
73-
_measurement(measurement),
71+
_measurement(escapeKey(measurement, false)),
7472
_tags(""),
7573
_fields(""),
7674
_timestamp("")
@@ -651,63 +649,6 @@ void InfluxDBClient::postRequest(int expectedStatusCode) {
651649
}
652650
}
653651

654-
static String escapeKey(String key) {
655-
String ret;
656-
ret.reserve(key.length()+5); //5 is estimate of chars needs to escape,
657-
658-
for (char c: key)
659-
{
660-
switch (c)
661-
{
662-
case ' ':
663-
case ',':
664-
case '=':
665-
ret += '\\';
666-
break;
667-
}
668-
669-
ret += c;
670-
}
671-
return ret;
672-
}
673-
674-
static String escapeValue(const char *value) {
675-
String ret;
676-
int len = strlen_P(value);
677-
ret.reserve(len+5); //5 is estimate of max chars needs to escape,
678-
for(int i=0;i<len;i++)
679-
{
680-
switch (value[i])
681-
{
682-
case '\\':
683-
case '\"':
684-
ret += '\\';
685-
break;
686-
}
687-
688-
ret += value[i];
689-
}
690-
return ret;
691-
}
692-
static String escapeTagValue(const char *value) {
693-
String ret;
694-
int len = strlen_P(value);
695-
ret.reserve(len+5); //5 is estimate of max chars needs to escape,
696-
for(int i=0;i<len;i++)
697-
{
698-
switch (value[i])
699-
{
700-
case '\\':
701-
case '\"':
702-
ret += '\\';
703-
break;
704-
}
705-
706-
ret += value[i];
707-
}
708-
return ret;
709-
}
710-
711652
static String escapeJSONString(String &value) {
712653
String ret;
713654
int d = 0;

src/util/helpers.cpp

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,49 @@ void timeSync(const char *tzInfo, const char* ntpServer1, const char* ntpServer2
4545
time_t tnow = time(nullptr);
4646
Serial.print("Synchronized time: ");
4747
Serial.println(ctime(&tnow));
48-
}
48+
}
49+
50+
String escapeKey(String key, bool escapeEqual) {
51+
String ret;
52+
ret.reserve(key.length()+5); //5 is estimate of chars needs to escape,
53+
54+
for (char c: key)
55+
{
56+
switch (c)
57+
{
58+
case '\r':
59+
case '\n':
60+
case '\t':
61+
case ' ':
62+
case ',':
63+
ret += '\\';
64+
break;
65+
case '=':
66+
if(escapeEqual) {
67+
ret += '\\';
68+
}
69+
break;
70+
}
71+
ret += c;
72+
}
73+
return ret;
74+
}
75+
76+
String escapeValue(const char *value) {
77+
String ret;
78+
int len = strlen_P(value);
79+
ret.reserve(len+5); //5 is estimate of max chars needs to escape,
80+
for(int i=0;i<len;i++)
81+
{
82+
switch (value[i])
83+
{
84+
case '\\':
85+
case '\"':
86+
ret += '\\';
87+
break;
88+
}
89+
90+
ret += value[i];
91+
}
92+
return ret;
93+
}

src/util/helpers.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,10 @@
3434
// For the fastest time sync find NTP servers in your area: https://www.pool.ntp.org/zone/
3535
void timeSync(const char *tzInfo, const char* ntpServer1, const char* ntpServer2 = nullptr, const char* ntpServer3 = nullptr);
3636

37+
// Escape invalid chars in measurement, tag key, tag value and field key
38+
String escapeKey(String key, bool escapeEqual = true);
39+
// Escape invalid chars in field value
40+
String escapeValue(const char *value);
41+
42+
3743
#endif //_INFLUXDB_CLIENT_HELPERS_H

test/test.ino

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,13 @@ void setup() {
4545
Serial.println();
4646

4747
initInet();
48+
49+
Serial.printf("Using server: %s\n", INFLUXDB_CLIENT_TESTING_URL);
4850
}
4951

5052
void loop() {
5153
//tests
54+
testEcaping();
5255
testPoint();
5356
testFluxTypes();
5457
testFluxParserEmpty();
@@ -68,16 +71,42 @@ void loop() {
6871
testUserAgent();
6972
testFailedWrites();
7073
testTimestamp();
71-
// testRetryOnFailedConnection();
72-
// testBufferOverwriteBatchsize1();
73-
// testBufferOverwriteBatchsize5();
74-
// testServerTempDownBatchsize5();
75-
// testRetriesOnServerOverload();
74+
testRetryOnFailedConnection();
75+
testBufferOverwriteBatchsize1();
76+
testBufferOverwriteBatchsize5();
77+
testServerTempDownBatchsize5();
78+
testRetriesOnServerOverload();
7679

7780
Serial.printf("Test %s\n", failures ? "FAILED" : "SUCCEEDED");
7881
while(1) delay(1000);
7982
}
8083

84+
void testEcaping() {
85+
TEST_INIT("testEcaping");
86+
87+
Point p("t\re=s\nt\t_t e\"s,t");
88+
p.addTag("ta=g","val=ue");
89+
p.addTag("ta\tg","val\tue");
90+
p.addTag("ta\rg","val\rue");
91+
p.addTag("ta\ng","val\nue");
92+
p.addTag("ta g","valu e");
93+
p.addTag("ta,g","valu,e");
94+
p.addTag("tag","value");
95+
p.addTag("ta\"g","val\"ue");
96+
p.addField("fie=ld", "val=ue");
97+
p.addField("fie\tld", "val\tue");
98+
p.addField("fie\rld", "val\rue");
99+
p.addField("fie\nld", "val\nue");
100+
p.addField("fie ld", "val ue");
101+
p.addField("fie,ld", "val,ue");
102+
p.addField("fie\"ld", "val\"ue");
103+
104+
String line = p.toLineProtocol();
105+
TEST_ASSERTM(line == "t\\\re=s\\\nt\\\t_t\\ e\"s\\,t,ta\\=g=val\\=ue,ta\\\tg=val\\\tue,ta\\\rg=val\\\rue,ta\\\ng=val\\\nue,ta\\ g=valu\\ e,ta\\,g=valu\\,e,tag=value,ta\"g=val\"ue fie\\=ld=\"val=ue\",fie\\\tld=\"val\tue\",fie\\\rld=\"val\rue\",fie\\\nld=\"val\nue\",fie\\ ld=\"val ue\",fie\\,ld=\"val,ue\",fie\"ld=\"val\\\"ue\"", line);//
106+
TEST_END();
107+
}
108+
109+
81110
void testPoint() {
82111
TEST_INIT("testPoint");
83112

@@ -933,7 +962,7 @@ void testFluxTypes() {
933962
}
934963

935964
void testFluxParserEmpty() {
936-
TEST_INIT("testFluxParser");
965+
TEST_INIT("testFluxParserEmpty");
937966
FluxQueryResult flux("Error sss");
938967
TEST_ASSERTM(!flux.next(),"!flux.next()");
939968
TEST_ASSERTM(flux.getError() == "Error sss","flux.getError");
@@ -956,6 +985,7 @@ void testFluxParserEmpty() {
956985

957986
//test empty results set
958987
InfluxDBClient client2(INFLUXDB_CLIENT_TESTING_URL, INFLUXDB_CLIENT_TESTING_ORG, INFLUXDB_CLIENT_TESTING_BUC, INFLUXDB_CLIENT_TESTING_TOK);
988+
TEST_ASSERT(waitServer(client2, true));
959989
flux = client2.query("testquery-empty");
960990

961991
TEST_ASSERTM(!flux.next(),"flux.next()");
@@ -1052,6 +1082,7 @@ bool testTableColumns(FluxQueryResult flux, const char *columns[], int columnsC
10521082
void testFluxParserSingleTable() {
10531083
TEST_INIT("testFluxParserSingleTable");
10541084
InfluxDBClient client(INFLUXDB_CLIENT_TESTING_URL, INFLUXDB_CLIENT_TESTING_ORG, INFLUXDB_CLIENT_TESTING_BUC, INFLUXDB_CLIENT_TESTING_TOK);
1085+
TEST_ASSERT(waitServer(client, true));
10551086
FluxQueryResult flux = client.query("testquery-singleTable");
10561087
TEST_ASSERTM(flux.next(),"flux.next()");
10571088
TEST_ASSERTM(flux.hasTableChanged(),"flux.hasTableChanged()");
@@ -1108,6 +1139,7 @@ void testFluxParserSingleTable() {
11081139
void testFluxParserNilValue() {
11091140
TEST_INIT("testFluxParserNilValue");
11101141
InfluxDBClient client(INFLUXDB_CLIENT_TESTING_URL, INFLUXDB_CLIENT_TESTING_ORG, INFLUXDB_CLIENT_TESTING_BUC, INFLUXDB_CLIENT_TESTING_TOK);
1142+
TEST_ASSERT(waitServer(client, true));
11111143
FluxQueryResult flux = client.query("testquery-nil-value");
11121144
TEST_ASSERTM(flux.next(),"flux.next()");
11131145
TEST_ASSERTM(flux.hasTableChanged(),"flux.hasTableChanged()");
@@ -1158,6 +1190,7 @@ void testFluxParserNilValue() {
11581190
void testFluxParserMultiTables(bool chunked) {
11591191
TEST_INIT("testFluxParserMultiTables");
11601192
InfluxDBClient client(INFLUXDB_CLIENT_TESTING_URL, INFLUXDB_CLIENT_TESTING_ORG, INFLUXDB_CLIENT_TESTING_BUC, INFLUXDB_CLIENT_TESTING_TOK);
1193+
TEST_ASSERT(waitServer(client, true));
11611194
if(chunked) {
11621195
String record = "a,direction=chunked a=1";
11631196
client.writeRecord(record);
@@ -1344,6 +1377,7 @@ void testFluxParserMultiTables(bool chunked) {
13441377
void testFluxParserErrorDiffentColumnsNum() {
13451378
TEST_INIT("testFluxParserErrorDiffentColumnsNum");
13461379
InfluxDBClient client(INFLUXDB_CLIENT_TESTING_URL, INFLUXDB_CLIENT_TESTING_ORG, INFLUXDB_CLIENT_TESTING_BUC, INFLUXDB_CLIENT_TESTING_TOK);
1380+
TEST_ASSERT(waitServer(client, true));
13471381
FluxQueryResult flux = client.query("testquery-diffNum-data");
13481382

13491383
TEST_ASSERTM(!flux.next(),"!flux.next()");
@@ -1364,6 +1398,7 @@ void testFluxParserErrorDiffentColumnsNum() {
13641398
void testFluxParserFluxError() {
13651399
TEST_INIT("testFluxParserFluxError");
13661400
InfluxDBClient client(INFLUXDB_CLIENT_TESTING_URL, INFLUXDB_CLIENT_TESTING_ORG, INFLUXDB_CLIENT_TESTING_BUC, INFLUXDB_CLIENT_TESTING_TOK);
1401+
TEST_ASSERT(waitServer(client, true));
13671402
FluxQueryResult flux = client.query("testquery-flux-error");
13681403

13691404
TEST_ASSERTM(!flux.next(),"!flux.next()");
@@ -1377,6 +1412,7 @@ void testFluxParserFluxError() {
13771412
void testFluxParserInvalidDatatype() {
13781413
TEST_INIT("testFluxParserInvalidDatatype");
13791414
InfluxDBClient client(INFLUXDB_CLIENT_TESTING_URL, INFLUXDB_CLIENT_TESTING_ORG, INFLUXDB_CLIENT_TESTING_BUC, INFLUXDB_CLIENT_TESTING_TOK);
1415+
TEST_ASSERT(waitServer(client, true));
13801416
FluxQueryResult flux = client.query("testquery-invalid-datatype");
13811417

13821418
TEST_ASSERTM(!flux.next(),"!flux.next()");
@@ -1390,6 +1426,7 @@ void testFluxParserInvalidDatatype() {
13901426
void testFluxParserMissingDatatype() {
13911427
TEST_INIT("testFluxParserMissingDatatype");
13921428
InfluxDBClient client(INFLUXDB_CLIENT_TESTING_URL, INFLUXDB_CLIENT_TESTING_ORG, INFLUXDB_CLIENT_TESTING_BUC, INFLUXDB_CLIENT_TESTING_TOK);
1429+
TEST_ASSERT(waitServer(client, true));
13931430
FluxQueryResult flux = client.query("testquery-missing-datatype");
13941431

13951432
TEST_ASSERTM(!flux.next(),"!flux.next()");
@@ -1403,6 +1440,7 @@ void testFluxParserMissingDatatype() {
14031440
void testFluxParserErrorInRow() {
14041441
TEST_INIT("testFluxParserErrorInRow");
14051442
InfluxDBClient client(INFLUXDB_CLIENT_TESTING_URL, INFLUXDB_CLIENT_TESTING_ORG, INFLUXDB_CLIENT_TESTING_BUC, INFLUXDB_CLIENT_TESTING_TOK);
1443+
TEST_ASSERT(waitServer(client, true));
14061444
FluxQueryResult flux = client.query("testquery-error-it-row-full");
14071445

14081446
TEST_ASSERTM(!flux.next(),"!flux.next()");
@@ -1459,6 +1497,8 @@ void initInet() {
14591497
while (1) delay(100);
14601498
} else {
14611499
Serial.printf("Connected to: %s (%d)\n", WiFi.SSID().c_str(), WiFi.RSSI());
1500+
Serial.print("Ip: ");
1501+
Serial.println(WiFi.localIP());
14621502

14631503
timeSync("CET-1CEST,M3.5.0,M10.5.0/3", "pool.ntp.org", "0.cz.pool.ntp.org", "1.cz.pool.ntp.org");
14641504

0 commit comments

Comments
 (0)