@@ -139,7 +139,7 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
139
139
String headerName;
140
140
String headerValue;
141
141
bool isForm = false ;
142
- bool isEncoded = false ;
142
+ // bool isEncoded = false;
143
143
uint32_t contentLength = 0 ;
144
144
// parse headers
145
145
while (1 ){
@@ -168,7 +168,7 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
168
168
isForm = false ;
169
169
} else if (headerValue.startsWith (F (" application/x-www-form-urlencoded" ))){
170
170
isForm = false ;
171
- isEncoded = true ;
171
+ // isEncoded = true;
172
172
} else if (headerValue.startsWith (F (" multipart/" ))){
173
173
boundaryStr = headerValue.substring (headerValue.indexOf (' =' ) + 1 );
174
174
boundaryStr.replace (" \" " ," " );
@@ -181,43 +181,34 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
181
181
}
182
182
}
183
183
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 ;
203
197
}
204
198
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
+
209
203
free (plainBuf);
210
- } else {
211
- // No content - but we can still have arguments in the URL.
212
- _parseArguments (searchStr);
204
+
213
205
}
214
- }
206
+ } else { // isForm is true
215
207
216
- if (isForm){
217
- _parseArguments (searchStr);
218
208
if (!_parseForm (client, boundaryStr, contentLength)) {
219
209
return false ;
220
210
}
211
+
221
212
}
222
213
} else {
223
214
String headerName;
@@ -235,14 +226,14 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
235
226
headerValue = req.substring (headerDiv + 2 );
236
227
_collectHeader (headerName.c_str (),headerValue.c_str ());
237
228
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
244
235
245
- if (headerName.equalsIgnoreCase (" Host" )){
236
+ if (headerName.equalsIgnoreCase (" Host" )){
246
237
_hostHeader = headerValue;
247
238
}
248
239
}
@@ -251,10 +242,16 @@ bool ESP8266WebServer::_parseRequest(WiFiClient& client) {
251
242
client.flush ();
252
243
253
244
#ifdef DEBUG_ESP_HTTP_SERVER
254
- DEBUG_OUTPUT.print (" Request: " );
245
+ DEBUG_OUTPUT.print (F ( " Request: " ) );
255
246
DEBUG_OUTPUT.println (url);
256
- DEBUG_OUTPUT.print (" Arguments: " );
247
+ DEBUG_OUTPUT.print (F ( " Arguments: " ) );
257
248
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 ());
258
255
#endif
259
256
260
257
return true ;
@@ -270,79 +267,85 @@ bool ESP8266WebServer::_collectHeader(const char* headerName, const char* header
270
267
return false ;
271
268
}
272
269
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));
285
277
}
286
- _currentArgCount = 1 ;
278
+ } ;
287
279
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
294
285
}
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) {
299
301
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 ))) {
315
302
#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 );
318
305
#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 ())
320
315
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 ;
323
337
}
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 )
337
340
break ;
338
- pos = next_arg_index + 1 ;
339
341
}
340
- _currentArgCount = iarg;
342
+
341
343
#ifdef DEBUG_ESP_HTTP_SERVER
342
344
DEBUG_OUTPUT.print (" args count: " );
343
- DEBUG_OUTPUT.println (_currentArgCount );
345
+ DEBUG_OUTPUT.println (arg_total );
344
346
#endif
345
347
348
+ return arg_total;
346
349
}
347
350
348
351
void ESP8266WebServer::_uploadWriteByte (uint8_t b){
@@ -410,7 +413,7 @@ bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t
410
413
DEBUG_OUTPUT.println (argFilename);
411
414
#endif
412
415
// 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)))
414
417
argFilename = arg (FPSTR (filename));
415
418
}
416
419
#ifdef DEBUG_ESP_HTTP_SERVER
@@ -566,7 +569,7 @@ bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t
566
569
arg.value = postArgs[iarg].value ;
567
570
}
568
571
_currentArgCount = iarg;
569
- if (postArgs)
572
+ if (postArgs)
570
573
delete[] postArgs;
571
574
return true ;
572
575
}
@@ -579,33 +582,33 @@ bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t
579
582
580
583
String ESP8266WebServer::urlDecode (const String& text)
581
584
{
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;
609
612
}
610
613
611
614
bool ESP8266WebServer::_parseFormUploadAborted (){
0 commit comments