@@ -309,42 +309,14 @@ void WebServer::_uploadWriteByte(uint8_t b){
309309 _currentUpload->buf [_currentUpload->currentSize ++] = b;
310310}
311311
312- int WebServer::_uploadReadByte (WiFiClient& client){
312+ int WebServer::_uploadReadByte (WiFiClient& client) {
313313 int res = client.read ();
314- if (res < 0 ) {
315- // keep trying until you either read a valid byte or timeout
316- unsigned long startMillis = millis ();
317- long timeoutIntervalMillis = client.getTimeout ();
318- boolean timedOut = false ;
319- for (;;) {
320- if (!client.connected ()) return -1 ;
321- // loosely modeled after blinkWithoutDelay pattern
322- while (!timedOut && !client.available () && client.connected ()){
323- delay (2 );
324- timedOut = millis () - startMillis >= timeoutIntervalMillis;
325- }
326314
327- res = client.read ();
328- if (res >= 0 ) {
329- return res; // exit on a valid read
330- }
331- // NOTE: it is possible to get here and have all of the following
332- // assertions hold true
333- //
334- // -- client.available() > 0
335- // -- client.connected == true
336- // -- res == -1
337- //
338- // a simple retry strategy overcomes this which is to say the
339- // assertion is not permanent, but the reason that this works
340- // is elusive, and possibly indicative of a more subtle underlying
341- // issue
342-
343- timedOut = millis () - startMillis >= timeoutIntervalMillis;
344- if (timedOut) {
345- return res; // exit on a timeout
346- }
347- }
315+ if (res < 0 ) {
316+ while (!client.available () && client.connected ())
317+ delay (2 );
318+
319+ res = client.read ();
348320 }
349321
350322 return res;
@@ -436,88 +408,59 @@ bool WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t len){
436408 if (_currentHandler && _currentHandler->canUpload (_currentUri))
437409 _currentHandler->upload (*this , _currentUri, *_currentUpload);
438410 _currentUpload->status = UPLOAD_FILE_WRITE;
439- int argByte = _uploadReadByte (client);
440- readfile:
441411
442- while (argByte != 0x0D ){
443- if (argByte < 0 ) return _parseFormUploadAborted ();
444- _uploadWriteByte (argByte);
445- argByte = _uploadReadByte (client);
446- }
447-
448- argByte = _uploadReadByte (client);
449- if (argByte < 0 ) return _parseFormUploadAborted ();
450- if (argByte == 0x0A ){
451- argByte = _uploadReadByte (client);
452- if (argByte < 0 ) return _parseFormUploadAborted ();
453- if ((char )argByte != ' -' ){
454- // continue reading the file
455- _uploadWriteByte (0x0D );
456- _uploadWriteByte (0x0A );
457- goto readfile;
458- } else {
459- argByte = _uploadReadByte (client);
460- if (argByte < 0 ) return _parseFormUploadAborted ();
461- if ((char )argByte != ' -' ){
462- // continue reading the file
463- _uploadWriteByte (0x0D );
464- _uploadWriteByte (0x0A );
465- _uploadWriteByte ((uint8_t )(' -' ));
466- goto readfile;
467- }
468- }
469-
470- uint8_t endBuf[boundary.length ()];
471- uint32_t i = 0 ;
472- while (i < boundary.length ()){
473- argByte = _uploadReadByte (client);
474- if (argByte < 0 ) return _parseFormUploadAborted ();
475- if ((char )argByte == 0x0D ){
476- _uploadWriteByte (0x0D );
477- _uploadWriteByte (0x0A );
478- _uploadWriteByte ((uint8_t )(' -' ));
479- _uploadWriteByte ((uint8_t )(' -' ));
480- uint32_t j = 0 ;
481- while (j < i){
482- _uploadWriteByte (endBuf[j++]);
483- }
484- goto readfile;
485- }
486- endBuf[i++] = (uint8_t )argByte;
487- }
488-
489- if (strstr ((const char *)endBuf, boundary.c_str ()) != NULL ){
490- if (_currentHandler && _currentHandler->canUpload (_currentUri))
491- _currentHandler->upload (*this , _currentUri, *_currentUpload);
492- _currentUpload->totalSize += _currentUpload->currentSize ;
493- _currentUpload->status = UPLOAD_FILE_END;
494- if (_currentHandler && _currentHandler->canUpload (_currentUri))
495- _currentHandler->upload (*this , _currentUri, *_currentUpload);
496- log_v (" End File: %s Type: %s Size: %d" , _currentUpload->filename .c_str (), _currentUpload->type .c_str (), _currentUpload->totalSize );
497- line = client.readStringUntil (0x0D );
498- client.readStringUntil (0x0A );
499- if (line == " --" ){
500- log_v (" Done Parsing POST" );
501- break ;
412+ int fastBoundaryLen = 4 /* \r\n-- */ + boundary.length () + 1 /* \0 */ ;
413+ char fastBoundary[ fastBoundaryLen ];
414+ snprintf (fastBoundary, fastBoundaryLen, " \r\n --%s" , boundary.c_str ());
415+ int boundaryPtr = 0 ;
416+ while ( true ) {
417+ int ret = _uploadReadByte (client);
418+ if (ret < 0 ) {
419+ // Unexpected, we should have had data available per above
420+ return _parseFormUploadAborted ();
502421 }
503- continue ;
504- } else {
505- _uploadWriteByte (0x0D );
506- _uploadWriteByte (0x0A );
507- _uploadWriteByte ((uint8_t )(' -' ));
508- _uploadWriteByte ((uint8_t )(' -' ));
509- uint32_t i = 0 ;
510- while (i < boundary.length ()){
511- _uploadWriteByte (endBuf[i++]);
422+ char in = (char ) ret;
423+ if (in == fastBoundary[ boundaryPtr ]) {
424+ // The input matched the current expected character, advance and possibly exit this file
425+ boundaryPtr++;
426+ if (boundaryPtr == fastBoundaryLen - 1 ) {
427+ // We read the whole boundary line, we're done here!
428+ break ;
429+ }
430+ } else {
431+ // The char doesn't match what we want, so dump whatever matches we had, the read in char, and reset ptr to start
432+ for (int i = 0 ; i < boundaryPtr; i++) {
433+ _uploadWriteByte ( fastBoundary[ i ] );
434+ }
435+ if (in == fastBoundary[ 0 ]) {
436+ // This could be the start of the real end, mark it so and don't emit/skip it
437+ boundaryPtr = 1 ;
438+ } else {
439+ // Not the 1st char of our pattern, so emit and ignore
440+ _uploadWriteByte ( in );
441+ boundaryPtr = 0 ;
442+ }
512443 }
513- argByte = _uploadReadByte (client);
514- goto readfile;
515- }
516- } else {
517- _uploadWriteByte (0x0D );
518- goto readfile;
519444 }
520- break ;
445+ // Found the boundary string, finish processing this file upload
446+ if (_currentHandler && _currentHandler->canUpload (_currentUri))
447+ _currentHandler->upload (*this , _currentUri, *_currentUpload);
448+ _currentUpload->totalSize += _currentUpload->currentSize ;
449+ _currentUpload->status = UPLOAD_FILE_END;
450+ if (_currentHandler && _currentHandler->canUpload (_currentUri))
451+ _currentHandler->upload (*this , _currentUri, *_currentUpload);
452+ log_v (" End File: %s Type: %s Size: %d" ,
453+ _currentUpload->filename .c_str (),
454+ _currentUpload->type .c_str (),
455+ (int )_currentUpload->totalSize );
456+ if (!client.connected ()) return _parseFormUploadAborted ();
457+ line = client.readStringUntil (' \r ' );
458+ client.readStringUntil (' \n ' );
459+ if (line == " --" ) { // extra two dashes mean we reached the end of all form fields
460+ log_v (" Done Parsing POST" );
461+ break ;
462+ }
463+ continue ;
521464 }
522465 }
523466 }
0 commit comments