@@ -139,7 +139,7 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
139139 String headerName;
140140 String headerValue;
141141 bool isForm = false ;
142- bool isEncoded = false ;
142+ // bool isEncoded = false;
143143 uint32_t contentLength = 0 ;
144144 // parse headers
145145 while (1 ){
@@ -168,7 +168,7 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
168168 isForm = false ;
169169 } else if (headerValue.startsWith (F (" application/x-www-form-urlencoded" ))){
170170 isForm = false ;
171- isEncoded = true ;
171+ // isEncoded = true;
172172 } else if (headerValue.startsWith (F (" multipart/" ))){
173173 boundaryStr = headerValue.substring (headerValue.indexOf (' =' ) + 1 );
174174 boundaryStr.replace (" \" " ," " );
@@ -181,43 +181,34 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
181181 }
182182 }
183183
184- if (!isForm){
185- size_t plainLength;
186- char * plainBuf = readBytesWithTimeout (client, contentLength, plainLength, HTTP_MAX_POST_WAIT);
187- if (plainLength < contentLength) {
188- free (plainBuf);
189- return false ;
190- }
191- if (contentLength > 0 ) {
192- if (isEncoded){
193- // url encoded form
194- if (searchStr != " " ) searchStr += ' &' ;
195- searchStr += plainBuf;
196- }
197- _parseArguments (searchStr);
198- if (!isEncoded){
199- // plain post json or other data
200- RequestArgument& arg = _currentArgs[_currentArgCount++];
201- arg.key = F (" plain" );
202- arg.value = String (plainBuf);
184+ // always parse url for key/value pairs
185+ _parseArguments (searchStr);
186+
187+ if (!isForm) {
188+ if (contentLength) {
189+
190+ // add key=value: plain={body} (post json or other data)
191+
192+ size_t plainLength;
193+ char * plainBuf = readBytesWithTimeout (client, contentLength, plainLength, HTTP_MAX_POST_WAIT);
194+ if (plainLength < contentLength) {
195+ free (plainBuf);
196+ return false ;
203197 }
204198
205- # ifdef DEBUG_ESP_HTTP_SERVER
206- DEBUG_OUTPUT. print ( " Plain: " );
207- DEBUG_OUTPUT. println (plainBuf);
208- # endif
199+ RequestArgument& arg = _currentArgs[_currentArgCount++];
200+ arg. key = F ( " plain " );
201+ arg. value = String (plainBuf);
202+
209203 free (plainBuf);
210- } else {
211- // No content - but we can still have arguments in the URL.
212- _parseArguments (searchStr);
204+
213205 }
214- }
206+ } else { // isForm is true
215207
216- if (isForm){
217- _parseArguments (searchStr);
218208 if (!_parseForm (client, boundaryStr, contentLength)) {
219209 return false ;
220210 }
211+
221212 }
222213 } else {
223214 String headerName;
@@ -235,14 +226,14 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
235226 headerValue = req.substring (headerDiv + 2 );
236227 _collectHeader (headerName.c_str (),headerValue.c_str ());
237228
238- #ifdef DEBUG_ESP_HTTP_SERVER
239- DEBUG_OUTPUT.print (" headerName: " );
240- DEBUG_OUTPUT.println (headerName);
241- DEBUG_OUTPUT.print (" headerValue: " );
242- DEBUG_OUTPUT.println (headerValue);
243- #endif
229+ #ifdef DEBUG_ESP_HTTP_SERVER
230+ DEBUG_OUTPUT.print (F ( " headerName: " ) );
231+ DEBUG_OUTPUT.println (headerName);
232+ DEBUG_OUTPUT.print (F ( " headerValue: " ) );
233+ DEBUG_OUTPUT.println (headerValue);
234+ #endif
244235
245- if (headerName.equalsIgnoreCase (" Host" )){
236+ if (headerName.equalsIgnoreCase (" Host" )){
246237 _hostHeader = headerValue;
247238 }
248239 }
@@ -251,10 +242,16 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
251242 client.flush ();
252243
253244#ifdef DEBUG_ESP_HTTP_SERVER
254- DEBUG_OUTPUT.print (" Request: " );
245+ DEBUG_OUTPUT.print (F ( " Request: " ) );
255246 DEBUG_OUTPUT.println (url);
256- DEBUG_OUTPUT.print (" Arguments: " );
247+ DEBUG_OUTPUT.print (F ( " Arguments: " ) );
257248 DEBUG_OUTPUT.println (searchStr);
249+
250+ DEBUG_OUTPUT.println (F (" final list of key/value pairs:" ));
251+ for (int i = 0 ; i < _currentArgCount; i++)
252+ DEBUG_OUTPUT.printf (" key:'%s' value:'%s'\r\n " ,
253+ _currentArgs[i].key .c_str (),
254+ _currentArgs[i].value .c_str ());
258255#endif
259256
260257 return true ;
@@ -270,79 +267,85 @@ bool ESP8266WebServer::_collectHeader(const char* headerName, const char* header
270267 return false ;
271268}
272269
273- void ESP8266WebServer::_parseArguments (String data) {
274- #ifdef DEBUG_ESP_HTTP_SERVER
275- DEBUG_OUTPUT.print (" args: " );
276- DEBUG_OUTPUT.println (data);
277- #endif
278- if (_currentArgs)
279- delete[] _currentArgs;
280- _currentArgs = 0 ;
281- if (data.length () == 0 ) {
282- _currentArgCount = 0 ;
283- _currentArgs = new RequestArgument[1 ];
284- return ;
270+ struct storeArgHandler
271+ {
272+ void operator () (String& key, String& value, const String& data, int equal_index, int pos, int key_end_pos, int next_index)
273+ {
274+ key = ESP8266WebServer::urlDecode (data.substring (pos, key_end_pos));
275+ if ((equal_index != -1 ) && ((equal_index < next_index - 1 ) || (next_index == -1 )))
276+ value = ESP8266WebServer::urlDecode (data.substring (equal_index + 1 , next_index));
285277 }
286- _currentArgCount = 1 ;
278+ } ;
287279
288- for (int i = 0 ; i < (int )data.length (); ) {
289- i = data.indexOf (' &' , i);
290- if (i == -1 )
291- break ;
292- ++i;
293- ++_currentArgCount;
280+ struct nullArgHandler
281+ {
282+ void operator () (String& key, String& value, const String& data, int equal_index, int pos, int key_end_pos, int next_index) {
283+ (void )key; (void )value; (void )data; (void )equal_index; (void )pos; (void )key_end_pos; (void )next_index;
284+ // do nothing
294285 }
295- #ifdef DEBUG_ESP_HTTP_SERVER
296- DEBUG_OUTPUT.print (" args count: " );
297- DEBUG_OUTPUT.println (_currentArgCount);
298- #endif
286+ };
287+
288+ void ESP8266WebServer::_parseArguments (const String& data) {
289+ if (_currentArgs)
290+ delete[] _currentArgs;
291+
292+ _currentArgCount = _parseArgumentsPrivate (data, nullArgHandler ());
293+
294+ // allocate one more, this is needed because {"plain": plainBuf} is always added
295+ _currentArgs = new RequestArgument[_currentArgCount + 1 ];
296+
297+ (void )_parseArgumentsPrivate (data, storeArgHandler ());
298+ }
299+
300+ int ESP8266WebServer::_parseArgumentsPrivate (const String& data, std::function<void (String&,String&,const String&,int ,int ,int ,int )> handler) {
299301
300- _currentArgs = new RequestArgument[_currentArgCount+1 ];
301- int pos = 0 ;
302- int iarg;
303- for (iarg = 0 ; iarg < _currentArgCount;) {
304- int equal_sign_index = data.indexOf (' =' , pos);
305- int next_arg_index = data.indexOf (' &' , pos);
306- #ifdef DEBUG_ESP_HTTP_SERVER
307- DEBUG_OUTPUT.print (" pos " );
308- DEBUG_OUTPUT.print (pos);
309- DEBUG_OUTPUT.print (" =@ " );
310- DEBUG_OUTPUT.print (equal_sign_index);
311- DEBUG_OUTPUT.print (" &@ " );
312- DEBUG_OUTPUT.println (next_arg_index);
313- #endif
314- if ((equal_sign_index == -1 ) || ((equal_sign_index > next_arg_index) && (next_arg_index != -1 ))) {
315302#ifdef DEBUG_ESP_HTTP_SERVER
316- DEBUG_OUTPUT.print (" arg missing value : " );
317- DEBUG_OUTPUT.println (iarg );
303+ DEBUG_OUTPUT.print (" args : " );
304+ DEBUG_OUTPUT.println (data );
318305#endif
319- if (next_arg_index == -1 )
306+
307+ size_t pos = 0 ;
308+ int arg_total = 0 ;
309+
310+ while (true ) {
311+
312+ // skip empty expression
313+ while (data[pos] == ' &' || data[pos] == ' ;' )
314+ if (++pos >= data.length ())
320315 break ;
321- pos = next_arg_index + 1 ;
322- continue ;
316+
317+ // locate separators
318+ int equal_index = data.indexOf (' =' , pos);
319+ int key_end_pos = equal_index;
320+ int next_index = data.indexOf (' &' , pos);
321+ int next_index2 = data.indexOf (' ;' , pos);
322+ if ((next_index == -1 ) || (next_index2 != -1 && next_index2 < next_index))
323+ next_index = next_index2;
324+ if ((key_end_pos == -1 ) || ((key_end_pos > next_index) && (next_index != -1 )))
325+ key_end_pos = next_index;
326+ if (key_end_pos == -1 )
327+ key_end_pos = data.length ();
328+
329+ // handle key/value
330+ if ((int )pos < key_end_pos) {
331+
332+ RequestArgument& arg = _currentArgs[arg_total];
333+ handler (arg.key , arg.value , data, equal_index, pos, key_end_pos, next_index);
334+
335+ ++arg_total;
336+ pos = next_index + 1 ;
323337 }
324- RequestArgument& arg = _currentArgs[iarg];
325- arg.key = urlDecode (data.substring (pos, equal_sign_index));
326- arg.value = urlDecode (data.substring (equal_sign_index + 1 , next_arg_index));
327- #ifdef DEBUG_ESP_HTTP_SERVER
328- DEBUG_OUTPUT.print (" arg " );
329- DEBUG_OUTPUT.print (iarg);
330- DEBUG_OUTPUT.print (" key: " );
331- DEBUG_OUTPUT.print (arg.key );
332- DEBUG_OUTPUT.print (" value: " );
333- DEBUG_OUTPUT.println (arg.value );
334- #endif
335- ++iarg;
336- if (next_arg_index == -1 )
338+
339+ if (next_index == -1 )
337340 break ;
338- pos = next_arg_index + 1 ;
339341 }
340- _currentArgCount = iarg;
342+
341343#ifdef DEBUG_ESP_HTTP_SERVER
342344 DEBUG_OUTPUT.print (" args count: " );
343- DEBUG_OUTPUT.println (_currentArgCount );
345+ DEBUG_OUTPUT.println (arg_total );
344346#endif
345347
348+ return arg_total;
346349}
347350
348351void ESP8266WebServer::_uploadWriteByte (uint8_t b){
@@ -410,7 +413,7 @@ bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t
410413 DEBUG_OUTPUT.println (argFilename);
411414#endif
412415 // use GET to set the filename if uploading using blob
413- if (argFilename == F (" blob" ) && hasArg (FPSTR (filename)))
416+ if (argFilename == F (" blob" ) && hasArg (FPSTR (filename)))
414417 argFilename = arg (FPSTR (filename));
415418 }
416419#ifdef DEBUG_ESP_HTTP_SERVER
@@ -566,7 +569,7 @@ bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t
566569 arg.value = postArgs[iarg].value ;
567570 }
568571 _currentArgCount = iarg;
569- if (postArgs)
572+ if (postArgs)
570573 delete[] postArgs;
571574 return true ;
572575 }
@@ -579,33 +582,33 @@ bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t
579582
580583String ESP8266WebServer::urlDecode (const String& text)
581584{
582- String decoded = " " ;
583- char temp[] = " 0x00" ;
584- unsigned int len = text.length ();
585- unsigned int i = 0 ;
586- while (i < len)
587- {
588- char decodedChar;
589- char encodedChar = text.charAt (i++);
590- if ((encodedChar == ' %' ) && (i + 1 < len))
591- {
592- temp[2 ] = text.charAt (i++);
593- temp[3 ] = text.charAt (i++);
594-
595- decodedChar = strtol (temp, NULL , 16 );
596- }
597- else {
598- if (encodedChar == ' +' )
599- {
600- decodedChar = ' ' ;
601- }
602- else {
603- decodedChar = encodedChar; // normal ascii char
604- }
605- }
606- decoded += decodedChar;
607- }
608- return decoded;
585+ String decoded = " " ;
586+ char temp[] = " 0x00" ;
587+ unsigned int len = text.length ();
588+ unsigned int i = 0 ;
589+ while (i < len)
590+ {
591+ char decodedChar;
592+ char encodedChar = text.charAt (i++);
593+ if ((encodedChar == ' %' ) && (i + 1 < len))
594+ {
595+ temp[2 ] = text.charAt (i++);
596+ temp[3 ] = text.charAt (i++);
597+
598+ decodedChar = strtol (temp, NULL , 16 );
599+ }
600+ else {
601+ if (encodedChar == ' +' )
602+ {
603+ decodedChar = ' ' ;
604+ }
605+ else {
606+ decodedChar = encodedChar; // normal ascii char
607+ }
608+ }
609+ decoded += decodedChar;
610+ }
611+ return decoded;
609612}
610613
611614bool ESP8266WebServer::_parseFormUploadAborted (){
0 commit comments