From 0919eef81baf57f8adbe6dc4fb66d5f58d1e873c Mon Sep 17 00:00:00 2001 From: Khoi Hoang <57012152+khoih-prog@users.noreply.github.com> Date: Tue, 23 Nov 2021 02:08:47 -0500 Subject: [PATCH] Delete WebServer.cpp --- esp32s2_WebServer_Patch/WebServer.cpp | 705 -------------------------- 1 file changed, 705 deletions(-) delete mode 100644 esp32s2_WebServer_Patch/WebServer.cpp diff --git a/esp32s2_WebServer_Patch/WebServer.cpp b/esp32s2_WebServer_Patch/WebServer.cpp deleted file mode 100644 index 5d8f313..0000000 --- a/esp32s2_WebServer_Patch/WebServer.cpp +++ /dev/null @@ -1,705 +0,0 @@ -/* - WebServer.cpp - Dead simple web-server. - Supports only one simultaneous client, knows how to handle GET and POST. - - Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling) -*/ - -// KH, Using "WebServer.handleClient delay" (https://github.com/espressif/arduino-esp32/pull/4350) - -#include -#include -#include -#include "WiFiServer.h" -#include "WiFiClient.h" -#include "WebServer.h" -#include "FS.h" -#include "detail/RequestHandlersImpl.h" -#include "mbedtls/md5.h" - - -static const char AUTHORIZATION_HEADER[] = "Authorization"; -static const char qop_auth[] = "qop=\"auth\""; -static const char WWW_Authenticate[] = "WWW-Authenticate"; -static const char Content_Length[] = "Content-Length"; - - -WebServer::WebServer(IPAddress addr, int port) -: _corsEnabled(false) -, _server(addr, port) -, _currentMethod(HTTP_ANY) -, _currentVersion(0) -, _currentStatus(HC_NONE) -, _statusChange(0) -, _nullDelay(true) -, _currentHandler(nullptr) -, _firstHandler(nullptr) -, _lastHandler(nullptr) -, _currentArgCount(0) -, _currentArgs(nullptr) -, _postArgsLen(0) -, _postArgs(nullptr) -, _headerKeysCount(0) -, _currentHeaders(nullptr) -, _contentLength(0) -, _chunked(false) -{ -} - -WebServer::WebServer(int port) -: _corsEnabled(false) -, _server(port) -, _currentMethod(HTTP_ANY) -, _currentVersion(0) -, _currentStatus(HC_NONE) -, _statusChange(0) -, _nullDelay(true) -, _currentHandler(nullptr) -, _firstHandler(nullptr) -, _lastHandler(nullptr) -, _currentArgCount(0) -, _currentArgs(nullptr) -, _postArgsLen(0) -, _postArgs(nullptr) -, _headerKeysCount(0) -, _currentHeaders(nullptr) -, _contentLength(0) -, _chunked(false) -{ -} - -WebServer::~WebServer() { - _server.close(); - if (_currentHeaders) - delete[]_currentHeaders; - RequestHandler* handler = _firstHandler; - while (handler) { - RequestHandler* next = handler->next(); - delete handler; - handler = next; - } -} - -void WebServer::begin() { - close(); - _server.begin(); - _server.setNoDelay(true); -} - -void WebServer::begin(uint16_t port) { - close(); - _server.begin(port); - _server.setNoDelay(true); -} - -String WebServer::_extractParam(String& authReq,const String& param,const char delimit){ - int _begin = authReq.indexOf(param); - if (_begin == -1) - return ""; - return authReq.substring(_begin+param.length(),authReq.indexOf(delimit,_begin+param.length())); -} - -static String md5str(String &in){ - char out[33] = {0}; - mbedtls_md5_context _ctx; - uint8_t i; - uint8_t * _buf = (uint8_t*)malloc(16); - if(_buf == NULL) - return String(out); - memset(_buf, 0x00, 16); - mbedtls_md5_init(&_ctx); - mbedtls_md5_starts(&_ctx); - mbedtls_md5_update(&_ctx, (const uint8_t *)in.c_str(), in.length()); - mbedtls_md5_finish(&_ctx, _buf); - for(i = 0; i < 16; i++) { - sprintf(out + (i * 2), "%02x", _buf[i]); - } - out[32] = 0; - free(_buf); - return String(out); -} - -bool WebServer::authenticate(const char * username, const char * password){ - if(hasHeader(FPSTR(AUTHORIZATION_HEADER))) { - String authReq = header(FPSTR(AUTHORIZATION_HEADER)); - if(authReq.startsWith(F("Basic"))){ - authReq = authReq.substring(6); - authReq.trim(); - char toencodeLen = strlen(username)+strlen(password)+1; - char *toencode = new char[toencodeLen + 1]; - if(toencode == NULL){ - authReq = ""; - return false; - } - char *encoded = new char[base64_encode_expected_len(toencodeLen)+1]; - if(encoded == NULL){ - authReq = ""; - delete[] toencode; - return false; - } - sprintf(toencode, "%s:%s", username, password); - if(base64_encode_chars(toencode, toencodeLen, encoded) > 0 && authReq.equalsConstantTime(encoded)) { - authReq = ""; - delete[] toencode; - delete[] encoded; - return true; - } - delete[] toencode; - delete[] encoded; - } else if(authReq.startsWith(F("Digest"))) { - authReq = authReq.substring(7); - log_v("%s", authReq.c_str()); - String _username = _extractParam(authReq,F("username=\""),'\"'); - if(!_username.length() || _username != String(username)) { - authReq = ""; - return false; - } - // extracting required parameters for RFC 2069 simpler Digest - String _realm = _extractParam(authReq, F("realm=\""),'\"'); - String _nonce = _extractParam(authReq, F("nonce=\""),'\"'); - String _uri = _extractParam(authReq, F("uri=\""),'\"'); - String _response = _extractParam(authReq, F("response=\""),'\"'); - String _opaque = _extractParam(authReq, F("opaque=\""),'\"'); - - if((!_realm.length()) || (!_nonce.length()) || (!_uri.length()) || (!_response.length()) || (!_opaque.length())) { - authReq = ""; - return false; - } - if((_opaque != _sopaque) || (_nonce != _snonce) || (_realm != _srealm)) { - authReq = ""; - return false; - } - // parameters for the RFC 2617 newer Digest - String _nc,_cnonce; - if(authReq.indexOf(FPSTR(qop_auth)) != -1) { - _nc = _extractParam(authReq, F("nc="), ','); - _cnonce = _extractParam(authReq, F("cnonce=\""),'\"'); - } - String _H1 = md5str(String(username) + ':' + _realm + ':' + String(password)); - log_v("Hash of user:realm:pass=%s", _H1.c_str()); - String _H2 = ""; - if(_currentMethod == HTTP_GET){ - _H2 = md5str(String(F("GET:")) + _uri); - }else if(_currentMethod == HTTP_POST){ - _H2 = md5str(String(F("POST:")) + _uri); - }else if(_currentMethod == HTTP_PUT){ - _H2 = md5str(String(F("PUT:")) + _uri); - }else if(_currentMethod == HTTP_DELETE){ - _H2 = md5str(String(F("DELETE:")) + _uri); - }else{ - _H2 = md5str(String(F("GET:")) + _uri); - } - log_v("Hash of GET:uri=%s", _H2.c_str()); - String _responsecheck = ""; - if(authReq.indexOf(FPSTR(qop_auth)) != -1) { - _responsecheck = md5str(_H1 + ':' + _nonce + ':' + _nc + ':' + _cnonce + F(":auth:") + _H2); - } else { - _responsecheck = md5str(_H1 + ':' + _nonce + ':' + _H2); - } - log_v("The Proper response=%s", _responsecheck.c_str()); - if(_response == _responsecheck){ - authReq = ""; - return true; - } - } - authReq = ""; - } - return false; -} - -String WebServer::_getRandomHexString() { - char buffer[33]; // buffer to hold 32 Hex Digit + /0 - int i; - for(i = 0; i < 4; i++) { - sprintf (buffer + (i*8), "%08x", esp_random()); - } - return String(buffer); -} - -void WebServer::requestAuthentication(HTTPAuthMethod mode, const char* realm, const String& authFailMsg) { - if(realm == NULL) { - _srealm = String(F("Login Required")); - } else { - _srealm = String(realm); - } - if(mode == BASIC_AUTH) { - sendHeader(String(FPSTR(WWW_Authenticate)), String(F("Basic realm=\"")) + _srealm + String(F("\""))); - } else { - _snonce=_getRandomHexString(); - _sopaque=_getRandomHexString(); - sendHeader(String(FPSTR(WWW_Authenticate)), String(F("Digest realm=\"")) +_srealm + String(F("\", qop=\"auth\", nonce=\"")) + _snonce + String(F("\", opaque=\"")) + _sopaque + String(F("\""))); - } - using namespace mime; - send(401, String(FPSTR(mimeTable[html].mimeType)), authFailMsg); -} - -void WebServer::on(const Uri &uri, WebServer::THandlerFunction handler) { - on(uri, HTTP_ANY, handler); -} - -void WebServer::on(const Uri &uri, HTTPMethod method, WebServer::THandlerFunction fn) { - on(uri, method, fn, _fileUploadHandler); -} - -void WebServer::on(const Uri &uri, HTTPMethod method, WebServer::THandlerFunction fn, WebServer::THandlerFunction ufn) { - _addRequestHandler(new FunctionRequestHandler(fn, ufn, uri, method)); -} - -void WebServer::addHandler(RequestHandler* handler) { - _addRequestHandler(handler); -} - -void WebServer::_addRequestHandler(RequestHandler* handler) { - if (!_lastHandler) { - _firstHandler = handler; - _lastHandler = handler; - } - else { - _lastHandler->next(handler); - _lastHandler = handler; - } -} - -void WebServer::serveStatic(const char* uri, FS& fs, const char* path, const char* cache_header) { - _addRequestHandler(new StaticRequestHandler(fs, path, uri, cache_header)); -} - -void WebServer::handleClient() { - if (_currentStatus == HC_NONE) { - WiFiClient client = _server.available(); - if (!client) { - if (_nullDelay) { - delay(1); - } - return; - } - - log_v("New client"); - - _currentClient = client; - _currentStatus = HC_WAIT_READ; - _statusChange = millis(); - } - - bool keepCurrentClient = false; - bool callYield = false; - - if (_currentClient.connected()) { - switch (_currentStatus) { - case HC_NONE: - // No-op to avoid C++ compiler warning - break; - case HC_WAIT_READ: - // Wait for data from client to become available - if (_currentClient.available()) { - if (_parseRequest(_currentClient)) { - // because HTTP_MAX_SEND_WAIT is expressed in milliseconds, - // it must be divided by 1000 - _currentClient.setTimeout(HTTP_MAX_SEND_WAIT / 1000); - _contentLength = CONTENT_LENGTH_NOT_SET; - _handleRequest(); - -// Fix for issue with Chrome based browsers: https://github.com/espressif/arduino-esp32/issues/3652 -// if (_currentClient.connected()) { -// _currentStatus = HC_WAIT_CLOSE; -// _statusChange = millis(); -// keepCurrentClient = true; -// } - } - } else { // !_currentClient.available() - if (millis() - _statusChange <= HTTP_MAX_DATA_WAIT) { - keepCurrentClient = true; - } - callYield = true; - } - break; - case HC_WAIT_CLOSE: - // Wait for client to close the connection - if (millis() - _statusChange <= HTTP_MAX_CLOSE_WAIT) { - keepCurrentClient = true; - callYield = true; - } - } - } - - if (!keepCurrentClient) { - _currentClient = WiFiClient(); - _currentStatus = HC_NONE; - _currentUpload.reset(); - } - - if (callYield) { - yield(); - } -} - -void WebServer::close() { - _server.close(); - _currentStatus = HC_NONE; - if(!_headerKeysCount) - collectHeaders(0, 0); -} - -void WebServer::stop() { - close(); -} - -void WebServer::sendHeader(const String& name, const String& value, bool first) { - String headerLine = name; - headerLine += F(": "); - headerLine += value; - headerLine += "\r\n"; - - if (first) { - _responseHeaders = headerLine + _responseHeaders; - } - else { - _responseHeaders += headerLine; - } -} - -void WebServer::setContentLength(const size_t contentLength) { - _contentLength = contentLength; -} - -void WebServer::enableDelay(boolean value) { - _nullDelay = value; -} - -void WebServer::enableCORS(boolean value) { - _corsEnabled = value; -} - -void WebServer::enableCrossOrigin(boolean value) { - enableCORS(value); -} - -void WebServer::_prepareHeader(String& response, int code, const char* content_type, size_t contentLength) { - response = String(F("HTTP/1.")) + String(_currentVersion) + ' '; - response += String(code); - response += ' '; - response += _responseCodeToString(code); - response += "\r\n"; - - using namespace mime; - if (!content_type) - content_type = mimeTable[html].mimeType; - - sendHeader(String(F("Content-Type")), String(FPSTR(content_type)), true); - if (_contentLength == CONTENT_LENGTH_NOT_SET) { - sendHeader(String(FPSTR(Content_Length)), String(contentLength)); - } else if (_contentLength != CONTENT_LENGTH_UNKNOWN) { - sendHeader(String(FPSTR(Content_Length)), String(_contentLength)); - } else if(_contentLength == CONTENT_LENGTH_UNKNOWN && _currentVersion){ //HTTP/1.1 or above client - //let's do chunked - _chunked = true; - sendHeader(String(F("Accept-Ranges")),String(F("none"))); - sendHeader(String(F("Transfer-Encoding")),String(F("chunked"))); - } - if (_corsEnabled) { - sendHeader(String(FPSTR("Access-Control-Allow-Origin")), String("*")); - } - sendHeader(String(F("Connection")), String(F("close"))); - - response += _responseHeaders; - response += "\r\n"; - _responseHeaders = ""; -} - -void WebServer::send(int code, const char* content_type, const String& content) { - String header; - // Can we asume the following? - //if(code == 200 && content.length() == 0 && _contentLength == CONTENT_LENGTH_NOT_SET) - // _contentLength = CONTENT_LENGTH_UNKNOWN; - _prepareHeader(header, code, content_type, content.length()); - _currentClientWrite(header.c_str(), header.length()); - if(content.length()) - sendContent(content); -} - -void WebServer::send_P(int code, PGM_P content_type, PGM_P content) { - size_t contentLength = 0; - - if (content != NULL) { - contentLength = strlen_P(content); - } - - String header; - char type[64]; - memccpy_P((void*)type, (PGM_VOID_P)content_type, 0, sizeof(type)); - _prepareHeader(header, code, (const char* )type, contentLength); - _currentClientWrite(header.c_str(), header.length()); - sendContent_P(content); -} - -void WebServer::send_P(int code, PGM_P content_type, PGM_P content, size_t contentLength) { - String header; - char type[64]; - memccpy_P((void*)type, (PGM_VOID_P)content_type, 0, sizeof(type)); - _prepareHeader(header, code, (const char* )type, contentLength); - sendContent(header); - sendContent_P(content, contentLength); -} - -void WebServer::send(int code, char* content_type, const String& content) { - send(code, (const char*)content_type, content); -} - -void WebServer::send(int code, const String& content_type, const String& content) { - send(code, (const char*)content_type.c_str(), content); -} - -void WebServer::sendContent(const String& content) { - sendContent(content.c_str(), content.length()); -} - -void WebServer::sendContent(const char* content, size_t contentLength) { - const char * footer = "\r\n"; - if(_chunked) { - char * chunkSize = (char *)malloc(11); - if(chunkSize){ - sprintf(chunkSize, "%x%s", contentLength, footer); - _currentClientWrite(chunkSize, strlen(chunkSize)); - free(chunkSize); - } - } - _currentClientWrite(content, contentLength); - if(_chunked){ - _currentClient.write(footer, 2); - if (contentLength == 0) { - _chunked = false; - } - } -} - -void WebServer::sendContent_P(PGM_P content) { - sendContent_P(content, strlen_P(content)); -} - -void WebServer::sendContent_P(PGM_P content, size_t size) { - const char * footer = "\r\n"; - if(_chunked) { - char * chunkSize = (char *)malloc(11); - if(chunkSize){ - sprintf(chunkSize, "%x%s", size, footer); - _currentClientWrite(chunkSize, strlen(chunkSize)); - free(chunkSize); - } - } - _currentClientWrite_P(content, size); - if(_chunked){ - _currentClient.write(footer, 2); - if (size == 0) { - _chunked = false; - } - } -} - - -void WebServer::_streamFileCore(const size_t fileSize, const String & fileName, const String & contentType) -{ - using namespace mime; - setContentLength(fileSize); - if (fileName.endsWith(String(FPSTR(mimeTable[gz].endsWith))) && - contentType != String(FPSTR(mimeTable[gz].mimeType)) && - contentType != String(FPSTR(mimeTable[none].mimeType))) { - sendHeader(F("Content-Encoding"), F("gzip")); - } - send(200, contentType, ""); -} - -String WebServer::pathArg(unsigned int i) { - if (_currentHandler != nullptr) - return _currentHandler->pathArg(i); - return ""; -} - -String WebServer::arg(String name) { - for (int j = 0; j < _postArgsLen; ++j) { - if ( _postArgs[j].key == name ) - return _postArgs[j].value; - } - for (int i = 0; i < _currentArgCount; ++i) { - if ( _currentArgs[i].key == name ) - return _currentArgs[i].value; - } - return ""; -} - -String WebServer::arg(int i) { - if (i < _currentArgCount) - return _currentArgs[i].value; - return ""; -} - -String WebServer::argName(int i) { - if (i < _currentArgCount) - return _currentArgs[i].key; - return ""; -} - -int WebServer::args() { - return _currentArgCount; -} - -bool WebServer::hasArg(String name) { - for (int j = 0; j < _postArgsLen; ++j) { - if (_postArgs[j].key == name) - return true; - } - for (int i = 0; i < _currentArgCount; ++i) { - if (_currentArgs[i].key == name) - return true; - } - return false; -} - - -String WebServer::header(String name) { - for (int i = 0; i < _headerKeysCount; ++i) { - if (_currentHeaders[i].key.equalsIgnoreCase(name)) - return _currentHeaders[i].value; - } - return ""; -} - -void WebServer::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) { - _headerKeysCount = headerKeysCount + 1; - if (_currentHeaders) - delete[]_currentHeaders; - _currentHeaders = new RequestArgument[_headerKeysCount]; - _currentHeaders[0].key = FPSTR(AUTHORIZATION_HEADER); - for (int i = 1; i < _headerKeysCount; i++){ - _currentHeaders[i].key = headerKeys[i-1]; - } -} - -String WebServer::header(int i) { - if (i < _headerKeysCount) - return _currentHeaders[i].value; - return ""; -} - -String WebServer::headerName(int i) { - if (i < _headerKeysCount) - return _currentHeaders[i].key; - return ""; -} - -int WebServer::headers() { - return _headerKeysCount; -} - -bool WebServer::hasHeader(String name) { - for (int i = 0; i < _headerKeysCount; ++i) { - if ((_currentHeaders[i].key.equalsIgnoreCase(name)) && (_currentHeaders[i].value.length() > 0)) - return true; - } - return false; -} - -String WebServer::hostHeader() { - return _hostHeader; -} - -void WebServer::onFileUpload(THandlerFunction fn) { - _fileUploadHandler = fn; -} - -void WebServer::onNotFound(THandlerFunction fn) { - _notFoundHandler = fn; -} - -void WebServer::_handleRequest() { - bool handled = false; - if (!_currentHandler){ - log_e("request handler not found"); - } - else { - handled = _currentHandler->handle(*this, _currentMethod, _currentUri); - if (!handled) { - log_e("request handler failed to handle request"); - } - } - if (!handled && _notFoundHandler) { - _notFoundHandler(); - handled = true; - } - if (!handled) { - using namespace mime; - send(404, String(FPSTR(mimeTable[html].mimeType)), String(F("Not found: ")) + _currentUri); - handled = true; - } - if (handled) { - _finalizeResponse(); - } - _currentUri = ""; -} - - -void WebServer::_finalizeResponse() { - if (_chunked) { - sendContent(""); - } -} - -String WebServer::_responseCodeToString(int code) { - switch (code) { - case 100: return F("Continue"); - case 101: return F("Switching Protocols"); - case 200: return F("OK"); - case 201: return F("Created"); - case 202: return F("Accepted"); - case 203: return F("Non-Authoritative Information"); - case 204: return F("No Content"); - case 205: return F("Reset Content"); - case 206: return F("Partial Content"); - case 300: return F("Multiple Choices"); - case 301: return F("Moved Permanently"); - case 302: return F("Found"); - case 303: return F("See Other"); - case 304: return F("Not Modified"); - case 305: return F("Use Proxy"); - case 307: return F("Temporary Redirect"); - case 400: return F("Bad Request"); - case 401: return F("Unauthorized"); - case 402: return F("Payment Required"); - case 403: return F("Forbidden"); - case 404: return F("Not Found"); - case 405: return F("Method Not Allowed"); - case 406: return F("Not Acceptable"); - case 407: return F("Proxy Authentication Required"); - case 408: return F("Request Time-out"); - case 409: return F("Conflict"); - case 410: return F("Gone"); - case 411: return F("Length Required"); - case 412: return F("Precondition Failed"); - case 413: return F("Request Entity Too Large"); - case 414: return F("Request-URI Too Large"); - case 415: return F("Unsupported Media Type"); - case 416: return F("Requested range not satisfiable"); - case 417: return F("Expectation Failed"); - case 500: return F("Internal Server Error"); - case 501: return F("Not Implemented"); - case 502: return F("Bad Gateway"); - case 503: return F("Service Unavailable"); - case 504: return F("Gateway Time-out"); - case 505: return F("HTTP Version not supported"); - default: return F(""); - } -}