From 478775388ce221f11f30c8dc23b9a28663b11ff8 Mon Sep 17 00:00:00 2001 From: David Gauchard Date: Thu, 11 Oct 2018 17:12:34 +0200 Subject: [PATCH 01/10] fix parseArgument --- .../ESP8266WebServer/src/ESP8266WebServer.h | 2 +- libraries/ESP8266WebServer/src/Parsing.cpp | 120 ++++++++++-------- 2 files changed, 65 insertions(+), 57 deletions(-) diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h index 0bfa302a4c..a055d35492 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h @@ -142,7 +142,7 @@ class ESP8266WebServer void _handleRequest(); void _finalizeResponse(); bool _parseRequest(WiFiClient& client); - void _parseArguments(String data); + int _parseArguments(const String& data, bool store = true); static String _responseCodeToString(int code); bool _parseForm(WiFiClient& client, String boundary, uint32_t len); bool _parseFormUploadAborted(); diff --git a/libraries/ESP8266WebServer/src/Parsing.cpp b/libraries/ESP8266WebServer/src/Parsing.cpp index 25bf6acec0..5e0aff58ae 100644 --- a/libraries/ESP8266WebServer/src/Parsing.cpp +++ b/libraries/ESP8266WebServer/src/Parsing.cpp @@ -270,79 +270,87 @@ bool ESP8266WebServer::_collectHeader(const char* headerName, const char* header return false; } -void ESP8266WebServer::_parseArguments(String data) { +int ESP8266WebServer::_parseArguments(const String& data, bool store) { + // when store is true, a recursive call + // with store=false is recursively called first + // to evaluate the number of arguments + // should we use a vector instead? + #ifdef DEBUG_ESP_HTTP_SERVER DEBUG_OUTPUT.print("args: "); DEBUG_OUTPUT.println(data); #endif - if (_currentArgs) - delete[] _currentArgs; - _currentArgs = 0; - if (data.length() == 0) { - _currentArgCount = 0; - _currentArgs = new RequestArgument[1]; - return; + + if (store) { + if (_currentArgs) + delete[] _currentArgs; + _currentArgs = 0; } - _currentArgCount = 1; - for (int i = 0; i < (int)data.length(); ) { - i = data.indexOf('&', i); - if (i == -1) - break; - ++i; - ++_currentArgCount; + if (store) { + _currentArgCount = _parseArguments(data, false); + _currentArgs = new RequestArgument[_currentArgCount+1]; } -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("args count: "); - DEBUG_OUTPUT.println(_currentArgCount); -#endif - _currentArgs = new RequestArgument[_currentArgCount+1]; - int pos = 0; - int iarg; - for (iarg = 0; iarg < _currentArgCount;) { - int equal_sign_index = data.indexOf('=', pos); - int next_arg_index = data.indexOf('&', pos); -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("pos "); - DEBUG_OUTPUT.print(pos); - DEBUG_OUTPUT.print("=@ "); - DEBUG_OUTPUT.print(equal_sign_index); - DEBUG_OUTPUT.print(" &@ "); - DEBUG_OUTPUT.println(next_arg_index); -#endif - if ((equal_sign_index == -1) || ((equal_sign_index > next_arg_index) && (next_arg_index != -1))) { -#ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("arg missing value: "); - DEBUG_OUTPUT.println(iarg); -#endif - if (next_arg_index == -1) + size_t pos = 0; + int arg_total = 0; + + while (true) { + + // skip empty expression + while (data[pos] == '&' || data[pos] == ';') + if (++pos >= data.length()) break; - pos = next_arg_index + 1; - continue; - } - RequestArgument& arg = _currentArgs[iarg]; - arg.key = urlDecode(data.substring(pos, equal_sign_index)); - arg.value = urlDecode(data.substring(equal_sign_index + 1, next_arg_index)); + + // locate separators + int equal_index = data.indexOf('=', pos); + int keyEndPos = equal_index; + int next_index = data.indexOf('&', pos); + int next_index2 = data.indexOf(';', pos); + if ((next_index == -1) || (next_index2 != -1 && next_index2 < next_index)) + next_index = next_index2; + if ((keyEndPos == -1) || ((keyEndPos > next_index) && (next_index != -1))) + keyEndPos = next_index; + if (keyEndPos == -1) + keyEndPos = data.length(); + keyEndPos--; + + // handle key/value + if (keyEndPos >= (int)pos) { + // do not store or count empty ending key ("url?x=y;") + + if (store) { + RequestArgument& arg = _currentArgs[arg_total]; + arg.key = urlDecode(data.substring(pos, keyEndPos)); + if ((equal_index != -1) && ((equal_index < next_index - 1) || (next_index == -1))) + arg.value = urlDecode(data.substring(equal_index + 1, next_index - 1)); #ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("arg "); - DEBUG_OUTPUT.print(iarg); - DEBUG_OUTPUT.print(" key: "); - DEBUG_OUTPUT.print(arg.key); - DEBUG_OUTPUT.print(" value: "); - DEBUG_OUTPUT.println(arg.value); + DEBUG_OUTPUT.print("arg "); + DEBUG_OUTPUT.print(arg_total); + DEBUG_OUTPUT.print(" key: "); + DEBUG_OUTPUT.print(arg.key); + DEBUG_OUTPUT.print(" value: "); + DEBUG_OUTPUT.println(arg.value); #endif - ++iarg; - if (next_arg_index == -1) + } + + ++arg_total; + pos = next_index + 1; + } + + if (next_index == -1) break; - pos = next_arg_index + 1; } - _currentArgCount = iarg; + #ifdef DEBUG_ESP_HTTP_SERVER DEBUG_OUTPUT.print("args count: "); - DEBUG_OUTPUT.println(_currentArgCount); + DEBUG_OUTPUT.println(arg_total); #endif + if (store) + _currentArgCount = arg_total; + + return arg_total; } void ESP8266WebServer::_uploadWriteByte(uint8_t b){ From aa4dac986ef316629d541f3128986be4b2a2f709 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Thu, 11 Oct 2018 22:00:11 +0200 Subject: [PATCH 02/10] remove recursion --- .../ESP8266WebServer/src/ESP8266WebServer.h | 3 ++- libraries/ESP8266WebServer/src/Parsing.cpp | 25 ++++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h index a055d35492..1c2fb97862 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h @@ -142,7 +142,8 @@ class ESP8266WebServer void _handleRequest(); void _finalizeResponse(); bool _parseRequest(WiFiClient& client); - int _parseArguments(const String& data, bool store = true); + void _parseArguments(const String& data); + int _parseArgumentsPrivate(const String& data, int counted); static String _responseCodeToString(int code); bool _parseForm(WiFiClient& client, String boundary, uint32_t len); bool _parseFormUploadAborted(); diff --git a/libraries/ESP8266WebServer/src/Parsing.cpp b/libraries/ESP8266WebServer/src/Parsing.cpp index 5e0aff58ae..9200844116 100644 --- a/libraries/ESP8266WebServer/src/Parsing.cpp +++ b/libraries/ESP8266WebServer/src/Parsing.cpp @@ -270,26 +270,27 @@ bool ESP8266WebServer::_collectHeader(const char* headerName, const char* header return false; } -int ESP8266WebServer::_parseArguments(const String& data, bool store) { - // when store is true, a recursive call - // with store=false is recursively called first - // to evaluate the number of arguments - // should we use a vector instead? +void ESP8266WebServer::_parseArguments(const String& data) { + int counted = _parseArgumentsPrivate(data, 0); + (void)_parseArgumentsPrivate(data, counted); +} + +int ESP8266WebServer::_parseArgumentsPrivate(const String& data, int counted) { +// counted==0: parsing only, return counted arguments +// counted!=0: parsing and storing "counted" arguments #ifdef DEBUG_ESP_HTTP_SERVER DEBUG_OUTPUT.print("args: "); DEBUG_OUTPUT.println(data); #endif - if (store) { + if (counted > 0) { if (_currentArgs) delete[] _currentArgs; _currentArgs = 0; - } - if (store) { - _currentArgCount = _parseArguments(data, false); - _currentArgs = new RequestArgument[_currentArgCount+1]; + // allocate one more, this is needed (search "plainBuf" in this file) + _currentArgs = new RequestArgument[(_currentArgCount = counted) + 1]; } size_t pos = 0; @@ -319,7 +320,7 @@ int ESP8266WebServer::_parseArguments(const String& data, bool store) { if (keyEndPos >= (int)pos) { // do not store or count empty ending key ("url?x=y;") - if (store) { + if (counted > 0) { RequestArgument& arg = _currentArgs[arg_total]; arg.key = urlDecode(data.substring(pos, keyEndPos)); if ((equal_index != -1) && ((equal_index < next_index - 1) || (next_index == -1))) @@ -347,7 +348,7 @@ int ESP8266WebServer::_parseArguments(const String& data, bool store) { DEBUG_OUTPUT.println(arg_total); #endif - if (store) + if (counted > 0) _currentArgCount = arg_total; return arg_total; From db0cd7d789687184880a745e1df4f70e1838a2ff Mon Sep 17 00:00:00 2001 From: david gauchard Date: Thu, 11 Oct 2018 22:13:55 +0200 Subject: [PATCH 03/10] keep variable naming style consistent --- libraries/ESP8266WebServer/src/Parsing.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/ESP8266WebServer/src/Parsing.cpp b/libraries/ESP8266WebServer/src/Parsing.cpp index 9200844116..1f463d62e7 100644 --- a/libraries/ESP8266WebServer/src/Parsing.cpp +++ b/libraries/ESP8266WebServer/src/Parsing.cpp @@ -305,24 +305,24 @@ int ESP8266WebServer::_parseArgumentsPrivate(const String& data, int counted) { // locate separators int equal_index = data.indexOf('=', pos); - int keyEndPos = equal_index; + int key_end_pos = equal_index; int next_index = data.indexOf('&', pos); int next_index2 = data.indexOf(';', pos); if ((next_index == -1) || (next_index2 != -1 && next_index2 < next_index)) next_index = next_index2; - if ((keyEndPos == -1) || ((keyEndPos > next_index) && (next_index != -1))) - keyEndPos = next_index; - if (keyEndPos == -1) - keyEndPos = data.length(); - keyEndPos--; + if ((key_end_pos == -1) || ((key_end_pos > next_index) && (next_index != -1))) + key_end_pos = next_index; + if (key_end_pos == -1) + key_end_pos = data.length(); + key_end_pos--; // handle key/value - if (keyEndPos >= (int)pos) { + if (key_end_pos >= (int)pos) { // do not store or count empty ending key ("url?x=y;") if (counted > 0) { RequestArgument& arg = _currentArgs[arg_total]; - arg.key = urlDecode(data.substring(pos, keyEndPos)); + arg.key = urlDecode(data.substring(pos, key_end_pos)); if ((equal_index != -1) && ((equal_index < next_index - 1) || (next_index == -1))) arg.value = urlDecode(data.substring(equal_index + 1, next_index - 1)); #ifdef DEBUG_ESP_HTTP_SERVER From ac47a03d619e49235de7bcc3534943e11410d4af Mon Sep 17 00:00:00 2001 From: david gauchard Date: Fri, 12 Oct 2018 00:47:05 +0200 Subject: [PATCH 04/10] inviting Alexa --- libraries/ESP8266WebServer/src/Parsing.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/ESP8266WebServer/src/Parsing.cpp b/libraries/ESP8266WebServer/src/Parsing.cpp index 1f463d62e7..ddd212b225 100644 --- a/libraries/ESP8266WebServer/src/Parsing.cpp +++ b/libraries/ESP8266WebServer/src/Parsing.cpp @@ -195,7 +195,9 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) { searchStr += plainBuf; } _parseArguments(searchStr); - if(!isEncoded){ + if ( !isEncoded + || (0 == _currentArgCount) // Alexa fix https://github.com/arendst/Sonoff-Tasmota/issues/1639#issuecomment-359253011 + ) { //plain post json or other data RequestArgument& arg = _currentArgs[_currentArgCount++]; arg.key = F("plain"); From bdf2aceba4e318d73051e1a32a5633baedd1e5f3 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Fri, 12 Oct 2018 23:40:24 +0200 Subject: [PATCH 05/10] fix alexa fix (well, trying...) --- libraries/ESP8266WebServer/src/Parsing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266WebServer/src/Parsing.cpp b/libraries/ESP8266WebServer/src/Parsing.cpp index ddd212b225..6f9d2920c6 100644 --- a/libraries/ESP8266WebServer/src/Parsing.cpp +++ b/libraries/ESP8266WebServer/src/Parsing.cpp @@ -196,7 +196,7 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) { } _parseArguments(searchStr); if ( !isEncoded - || (0 == _currentArgCount) // Alexa fix https://github.com/arendst/Sonoff-Tasmota/issues/1639#issuecomment-359253011 + || (hasSearch == -1) // Alexa fix (malformed header with form content) ) { //plain post json or other data RequestArgument& arg = _currentArgs[_currentArgCount++]; From 1ba0cfc758c35278e78ca59e21775522d7987e01 Mon Sep 17 00:00:00 2001 From: reloxx13 Date: Sat, 13 Oct 2018 02:34:50 +0200 Subject: [PATCH 06/10] fix pos substrings key_end_pos--; dont count down here, it will cut of every key by -1 ("save" will be "sav") (substring (end = up to, but not including, so no need to -1) Parsing cpp L329 arg.value = urlDecode(data.substring(equal_index + 1, next_index - 1)); => -1 is too less for substring (substring (end = up to, but not including, so no need to -1) --- libraries/ESP8266WebServer/src/Parsing.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/ESP8266WebServer/src/Parsing.cpp b/libraries/ESP8266WebServer/src/Parsing.cpp index 6f9d2920c6..874ca2cc85 100644 --- a/libraries/ESP8266WebServer/src/Parsing.cpp +++ b/libraries/ESP8266WebServer/src/Parsing.cpp @@ -316,17 +316,16 @@ int ESP8266WebServer::_parseArgumentsPrivate(const String& data, int counted) { key_end_pos = next_index; if (key_end_pos == -1) key_end_pos = data.length(); - key_end_pos--; // handle key/value - if (key_end_pos >= (int)pos) { + if ( (int)pos <= key_end_pos) { // do not store or count empty ending key ("url?x=y;") if (counted > 0) { RequestArgument& arg = _currentArgs[arg_total]; arg.key = urlDecode(data.substring(pos, key_end_pos)); if ((equal_index != -1) && ((equal_index < next_index - 1) || (next_index == -1))) - arg.value = urlDecode(data.substring(equal_index + 1, next_index - 1)); + arg.value = urlDecode(data.substring(equal_index + 1, next_index)); #ifdef DEBUG_ESP_HTTP_SERVER DEBUG_OUTPUT.print("arg "); DEBUG_OUTPUT.print(arg_total); From 0d62a41bec6cb40c99331db5b060ae075295835d Mon Sep 17 00:00:00 2001 From: david gauchard Date: Sun, 14 Oct 2018 01:41:09 +0200 Subject: [PATCH 07/10] alexa invite: add workaround for malformed x-www-form-urlencoded --- libraries/ESP8266WebServer/src/Parsing.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/libraries/ESP8266WebServer/src/Parsing.cpp b/libraries/ESP8266WebServer/src/Parsing.cpp index 6f9d2920c6..21e6dbd662 100644 --- a/libraries/ESP8266WebServer/src/Parsing.cpp +++ b/libraries/ESP8266WebServer/src/Parsing.cpp @@ -191,13 +191,15 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) { if (contentLength > 0) { if(isEncoded){ //url encoded form - if (searchStr != "") searchStr += '&'; + if (searchStr.length()) + searchStr += '&'; + else + // workaround: x-www-form-urlencoded without data + searchStr = F("plain="); searchStr += plainBuf; } _parseArguments(searchStr); - if ( !isEncoded - || (hasSearch == -1) // Alexa fix (malformed header with form content) - ) { + if (!isEncoded) { //plain post json or other data RequestArgument& arg = _currentArgs[_currentArgCount++]; arg.key = F("plain"); @@ -328,12 +330,7 @@ int ESP8266WebServer::_parseArgumentsPrivate(const String& data, int counted) { if ((equal_index != -1) && ((equal_index < next_index - 1) || (next_index == -1))) arg.value = urlDecode(data.substring(equal_index + 1, next_index - 1)); #ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("arg "); - DEBUG_OUTPUT.print(arg_total); - DEBUG_OUTPUT.print(" key: "); - DEBUG_OUTPUT.print(arg.key); - DEBUG_OUTPUT.print(" value: "); - DEBUG_OUTPUT.println(arg.value); + DEBUG_OUTPUT.printf("arg %d key: '%s' value: '%s'\r\n", arg_total, arg.key.c_str(), arg.value.c_str()); #endif } From cf2299fab1813488fd2c8a8ae82621f94639e559 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Sun, 14 Oct 2018 02:45:33 +0200 Subject: [PATCH 08/10] when !form, alway add content in key "plain" --- libraries/ESP8266WebServer/src/Parsing.cpp | 145 ++++++++++----------- 1 file changed, 69 insertions(+), 76 deletions(-) diff --git a/libraries/ESP8266WebServer/src/Parsing.cpp b/libraries/ESP8266WebServer/src/Parsing.cpp index faaf2bffde..07cfd5de26 100644 --- a/libraries/ESP8266WebServer/src/Parsing.cpp +++ b/libraries/ESP8266WebServer/src/Parsing.cpp @@ -139,7 +139,7 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) { String headerName; String headerValue; bool isForm = false; - bool isEncoded = false; + //bool isEncoded = false; uint32_t contentLength = 0; //parse headers while(1){ @@ -168,7 +168,7 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) { isForm = false; } else if (headerValue.startsWith(F("application/x-www-form-urlencoded"))){ isForm = false; - isEncoded = true; + //isEncoded = true; } else if (headerValue.startsWith(F("multipart/"))){ boundaryStr = headerValue.substring(headerValue.indexOf('=') + 1); boundaryStr.replace("\"",""); @@ -181,47 +181,34 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) { } } - if (!isForm){ - size_t plainLength; - char* plainBuf = readBytesWithTimeout(client, contentLength, plainLength, HTTP_MAX_POST_WAIT); - if (plainLength < contentLength) { - free(plainBuf); - return false; - } - if (contentLength > 0) { - if(isEncoded){ - //url encoded form - if (searchStr.length()) - searchStr += '&'; - else - // workaround: x-www-form-urlencoded without data - searchStr = F("plain="); - searchStr += plainBuf; - } - _parseArguments(searchStr); - if (!isEncoded) { - //plain post json or other data - RequestArgument& arg = _currentArgs[_currentArgCount++]; - arg.key = F("plain"); - arg.value = String(plainBuf); + // always parse url for key/value pairs + _parseArguments(searchStr); + + if (!isForm) { + if (contentLength) { + + // add key=value: plain={body} (post json or other data) + + size_t plainLength; + char* plainBuf = readBytesWithTimeout(client, contentLength, plainLength, HTTP_MAX_POST_WAIT); + if (plainLength < contentLength) { + free(plainBuf); + return false; } - #ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("Plain: "); - DEBUG_OUTPUT.println(plainBuf); - #endif + RequestArgument& arg = _currentArgs[_currentArgCount++]; + arg.key = F("plain"); + arg.value = String(plainBuf); + free(plainBuf); - } else { - // No content - but we can still have arguments in the URL. - _parseArguments(searchStr); + } - } + } else { // isForm is true - if (isForm){ - _parseArguments(searchStr); if (!_parseForm(client, boundaryStr, contentLength)) { return false; } + } } else { String headerName; @@ -239,14 +226,14 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) { headerValue = req.substring(headerDiv + 2); _collectHeader(headerName.c_str(),headerValue.c_str()); - #ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("headerName: "); - DEBUG_OUTPUT.println(headerName); - DEBUG_OUTPUT.print("headerValue: "); - DEBUG_OUTPUT.println(headerValue); - #endif +#ifdef DEBUG_ESP_HTTP_SERVER + DEBUG_OUTPUT.print(F("headerName: ")); + DEBUG_OUTPUT.println(headerName); + DEBUG_OUTPUT.print(F("headerValue: ")); + DEBUG_OUTPUT.println(headerValue); +#endif - if (headerName.equalsIgnoreCase("Host")){ + if (headerName.equalsIgnoreCase("Host")){ _hostHeader = headerValue; } } @@ -255,10 +242,16 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) { client.flush(); #ifdef DEBUG_ESP_HTTP_SERVER - DEBUG_OUTPUT.print("Request: "); + DEBUG_OUTPUT.print(F("Request: ")); DEBUG_OUTPUT.println(url); - DEBUG_OUTPUT.print(" Arguments: "); + DEBUG_OUTPUT.print(F("Arguments: ")); DEBUG_OUTPUT.println(searchStr); + + DEBUG_OUTPUT.println(F("final list of key/value pairs:")); + for (int i = 0; i < _currentArgCount; i++) + DEBUG_OUTPUT.printf(" key:'%s' value:'%s'\r\n", + _currentArgs[i].key.c_str(), + _currentArgs[i].value.c_str()); #endif return true; @@ -292,11 +285,12 @@ int ESP8266WebServer::_parseArgumentsPrivate(const String& data, int counted) { if (_currentArgs) delete[] _currentArgs; _currentArgs = 0; - - // allocate one more, this is needed (search "plainBuf" in this file) - _currentArgs = new RequestArgument[(_currentArgCount = counted) + 1]; } + // allocate one more (even if counted==0) + // this is needed because {"plain": plainBuf} is always added + _currentArgs = new RequestArgument[(_currentArgCount = counted) + 1]; + size_t pos = 0; int arg_total = 0; @@ -320,9 +314,8 @@ int ESP8266WebServer::_parseArgumentsPrivate(const String& data, int counted) { key_end_pos = data.length(); // handle key/value - if ( (int)pos <= key_end_pos) { + if ((int)pos < key_end_pos) { // do not store or count empty ending key ("url?x=y;") - if (counted > 0) { RequestArgument& arg = _currentArgs[arg_total]; arg.key = urlDecode(data.substring(pos, key_end_pos)); @@ -586,33 +579,33 @@ bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t String ESP8266WebServer::urlDecode(const String& text) { - String decoded = ""; - char temp[] = "0x00"; - unsigned int len = text.length(); - unsigned int i = 0; - while (i < len) - { - char decodedChar; - char encodedChar = text.charAt(i++); - if ((encodedChar == '%') && (i + 1 < len)) - { - temp[2] = text.charAt(i++); - temp[3] = text.charAt(i++); - - decodedChar = strtol(temp, NULL, 16); - } - else { - if (encodedChar == '+') - { - decodedChar = ' '; - } - else { - decodedChar = encodedChar; // normal ascii char - } - } - decoded += decodedChar; - } - return decoded; + String decoded = ""; + char temp[] = "0x00"; + unsigned int len = text.length(); + unsigned int i = 0; + while (i < len) + { + char decodedChar; + char encodedChar = text.charAt(i++); + if ((encodedChar == '%') && (i + 1 < len)) + { + temp[2] = text.charAt(i++); + temp[3] = text.charAt(i++); + + decodedChar = strtol(temp, NULL, 16); + } + else { + if (encodedChar == '+') + { + decodedChar = ' '; + } + else { + decodedChar = encodedChar; // normal ascii char + } + } + decoded += decodedChar; + } + return decoded; } bool ESP8266WebServer::_parseFormUploadAborted(){ From 9d1e411adb8ba21ebfafe0b8db6411a32f711c5c Mon Sep 17 00:00:00 2001 From: david gauchard Date: Tue, 16 Oct 2018 11:12:52 +0200 Subject: [PATCH 09/10] fix memleak --- libraries/ESP8266WebServer/src/Parsing.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/libraries/ESP8266WebServer/src/Parsing.cpp b/libraries/ESP8266WebServer/src/Parsing.cpp index 07cfd5de26..67ee18e345 100644 --- a/libraries/ESP8266WebServer/src/Parsing.cpp +++ b/libraries/ESP8266WebServer/src/Parsing.cpp @@ -268,28 +268,29 @@ bool ESP8266WebServer::_collectHeader(const char* headerName, const char* header } void ESP8266WebServer::_parseArguments(const String& data) { - int counted = _parseArgumentsPrivate(data, 0); + int counted = _parseArgumentsPrivate(data, -1); (void)_parseArgumentsPrivate(data, counted); } int ESP8266WebServer::_parseArgumentsPrivate(const String& data, int counted) { -// counted==0: parsing only, return counted arguments -// counted!=0: parsing and storing "counted" arguments +// counted<0: parse only, return counted arguments +// counted>=0: allocate counted+1, parse and store "counted" arguments #ifdef DEBUG_ESP_HTTP_SERVER DEBUG_OUTPUT.print("args: "); DEBUG_OUTPUT.println(data); #endif - if (counted > 0) { + if (counted >= 0) { if (_currentArgs) delete[] _currentArgs; _currentArgs = 0; - } + _currentArgCount = counted; - // allocate one more (even if counted==0) - // this is needed because {"plain": plainBuf} is always added - _currentArgs = new RequestArgument[(_currentArgCount = counted) + 1]; + // allocate one more (even if counted==0) + // this is needed because {"plain": plainBuf} is always added + _currentArgs = new RequestArgument[_currentArgCount + 1]; + } size_t pos = 0; int arg_total = 0; @@ -316,7 +317,7 @@ int ESP8266WebServer::_parseArgumentsPrivate(const String& data, int counted) { // handle key/value if ((int)pos < key_end_pos) { // do not store or count empty ending key ("url?x=y;") - if (counted > 0) { + if (counted >= 0) { RequestArgument& arg = _currentArgs[arg_total]; arg.key = urlDecode(data.substring(pos, key_end_pos)); if ((equal_index != -1) && ((equal_index < next_index - 1) || (next_index == -1))) @@ -339,9 +340,6 @@ int ESP8266WebServer::_parseArgumentsPrivate(const String& data, int counted) { DEBUG_OUTPUT.println(arg_total); #endif - if (counted > 0) - _currentArgCount = arg_total; - return arg_total; } From 8abf98d6c8f1989a0f4ada6b3b9a3051c854ea2b Mon Sep 17 00:00:00 2001 From: david gauchard Date: Wed, 17 Oct 2018 01:25:24 +0200 Subject: [PATCH 10/10] +simplify +readability --- .../ESP8266WebServer/src/ESP8266WebServer.h | 2 +- libraries/ESP8266WebServer/src/Parsing.cpp | 37 +++++++++---------- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h index 1c2fb97862..551e601fe6 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h @@ -143,7 +143,7 @@ class ESP8266WebServer void _finalizeResponse(); bool _parseRequest(WiFiClient& client); void _parseArguments(const String& data); - int _parseArgumentsPrivate(const String& data, int counted); + int _parseArgumentsPrivate(const String& data, bool store); static String _responseCodeToString(int code); bool _parseForm(WiFiClient& client, String boundary, uint32_t len); bool _parseFormUploadAborted(); diff --git a/libraries/ESP8266WebServer/src/Parsing.cpp b/libraries/ESP8266WebServer/src/Parsing.cpp index 67ee18e345..1fc1536ad5 100644 --- a/libraries/ESP8266WebServer/src/Parsing.cpp +++ b/libraries/ESP8266WebServer/src/Parsing.cpp @@ -268,30 +268,27 @@ bool ESP8266WebServer::_collectHeader(const char* headerName, const char* header } void ESP8266WebServer::_parseArguments(const String& data) { - int counted = _parseArgumentsPrivate(data, -1); - (void)_parseArgumentsPrivate(data, counted); + + if (_currentArgs) + delete[] _currentArgs; + _currentArgCount = _parseArgumentsPrivate(data, false); + + // allocate one more (even if counted==0) + // this is needed because {"plain": plainBuf} is always added (later) + _currentArgs = new RequestArgument[_currentArgCount + 1]; + + (void)_parseArgumentsPrivate(data, true); } -int ESP8266WebServer::_parseArgumentsPrivate(const String& data, int counted) { -// counted<0: parse only, return counted arguments -// counted>=0: allocate counted+1, parse and store "counted" arguments +int ESP8266WebServer::_parseArgumentsPrivate(const String& data, bool store) { +// !store: parse only, return counted arguments +// store: parse and store arguments #ifdef DEBUG_ESP_HTTP_SERVER DEBUG_OUTPUT.print("args: "); DEBUG_OUTPUT.println(data); #endif - if (counted >= 0) { - if (_currentArgs) - delete[] _currentArgs; - _currentArgs = 0; - _currentArgCount = counted; - - // allocate one more (even if counted==0) - // this is needed because {"plain": plainBuf} is always added - _currentArgs = new RequestArgument[_currentArgCount + 1]; - } - size_t pos = 0; int arg_total = 0; @@ -316,8 +313,8 @@ int ESP8266WebServer::_parseArgumentsPrivate(const String& data, int counted) { // handle key/value if ((int)pos < key_end_pos) { - // do not store or count empty ending key ("url?x=y;") - if (counted >= 0) { + + if (store) { RequestArgument& arg = _currentArgs[arg_total]; arg.key = urlDecode(data.substring(pos, key_end_pos)); if ((equal_index != -1) && ((equal_index < next_index - 1) || (next_index == -1))) @@ -408,7 +405,7 @@ bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t DEBUG_OUTPUT.println(argFilename); #endif //use GET to set the filename if uploading using blob - if (argFilename == F("blob") && hasArg(FPSTR(filename))) + if (argFilename == F("blob") && hasArg(FPSTR(filename))) argFilename = arg(FPSTR(filename)); } #ifdef DEBUG_ESP_HTTP_SERVER @@ -564,7 +561,7 @@ bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t arg.value = postArgs[iarg].value; } _currentArgCount = iarg; - if (postArgs) + if (postArgs) delete[] postArgs; return true; }