From 1b682d3564ef56b2406cf8fd83f44dc2600f224e Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Sun, 10 May 2020 15:24:10 +0200 Subject: [PATCH] Add rule length, truncates rules too long and add escape JSON --- tasmota/support.ino | 59 +++++++++++++++++++++++++++++++++++++++ tasmota/xdrv_10_rules.ino | 13 +++++++-- 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/tasmota/support.ino b/tasmota/support.ino index 45c6b0e7a..5d7d06624 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1863,3 +1863,62 @@ void AddLogBufferSize(uint32_t loglevel, uint8_t *buffer, uint32_t count, uint32 } AddLog(loglevel); } + +/*********************************************************************************************\ + * JSON parsing +\*********************************************************************************************/ + +// does the character needs to be escaped, and if so with which character +char escapeJSONChar(char c) { + if ((c == '\"') || (c == '\\')) { + return c; + } + if (c == '\n') { return 'n'; } + if (c == '\t') { return 't'; } + if (c == '\r') { return 'r'; } + if (c == '\f') { return 'f'; } + if (c == '\b') { return 'b'; } + return 0; +} + +String escapeJSONString(const char *str) { + String r(""); + if (nullptr == str) { return r; } + + bool needs_escape = false; + size_t len_out = 1; + const char * c = str; + + while (*c) { + if (escapeJSONChar(*c)) { + len_out++; + needs_escape = true; + } + c++; + len_out++; + } + + if (needs_escape) { + // we need to escape some chars + // allocate target buffer + r.reserve(len_out); + c = str; + char *d = r.begin(); + while (*c) { + char c2 = escapeJSONChar(*c); + if (c2) { + c++; + *d++ = '\\'; + *d++ = c2; + } else { + *d++ = *c++; + } + } + *d = 0; // add NULL terminator + r = (char*) r.begin(); // assign the buffer to the string + } else { + r = str; + } + + return r; +} \ No newline at end of file diff --git a/tasmota/xdrv_10_rules.ino b/tasmota/xdrv_10_rules.ino index 33f61a68c..922014e49 100644 --- a/tasmota/xdrv_10_rules.ino +++ b/tasmota/xdrv_10_rules.ino @@ -1992,12 +1992,21 @@ void CmndRule(void) } Rules.triggers[index -1] = 0; // Reset once flag } + String rule = GetRule(index - 1); + size_t rule_len = rule.length(); + if (rule_len >= MAX_RULE_SIZE) { + // we need to split the rule in chunks + rule = rule.substring(0, MAX_RULE_SIZE); + rule += F("..."); + } // snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s\",\"Once\":\"%s\",\"StopOnError\":\"%s\",\"Free\":%d,\"Rules\":\"%s\"}"), // XdrvMailbox.command, index, GetStateText(bitRead(Settings.rule_enabled, index -1)), GetStateText(bitRead(Settings.rule_once, index -1)), // GetStateText(bitRead(Settings.rule_stop, index -1)), sizeof(Settings.rules[index -1]) - strlen(Settings.rules[index -1]) -1, Settings.rules[index -1]); - snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s\",\"Once\":\"%s\",\"StopOnError\":\"%s\",\"Free\":%d,\"Rules\":\"%s\"}"), + snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s\",\"Once\":\"%s\",\"StopOnError\":\"%s\",\"Length\":%d,\"Free\":%d,\"Rules\":\"%s\"}"), XdrvMailbox.command, index, GetStateText(bitRead(Settings.rule_enabled, index -1)), GetStateText(bitRead(Settings.rule_once, index -1)), - GetStateText(bitRead(Settings.rule_stop, index -1)), sizeof(Settings.rules[0]) - GetRuleLenStorage(index - 1), GetRule(index - 1).c_str()); + GetStateText(bitRead(Settings.rule_stop, index -1)), + rule_len, MAX_RULE_SIZE - GetRuleLenStorage(index - 1), + escapeJSONString(rule.c_str()).c_str()); } }