From 9845ea9dd2b1afc9b6cde34b9ea2c864033ad9ab Mon Sep 17 00:00:00 2001 From: devyte Date: Fri, 12 Jan 2018 01:56:09 -0300 Subject: [PATCH 1/5] add begin(port) to esp8266webserver, move some strings to flash, some refactoring --- .../ESP8266WebServer/src/ESP8266WebServer.cpp | 56 ++++++++++--------- .../ESP8266WebServer/src/ESP8266WebServer.h | 3 +- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp index 6950012217..340ffef773 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp @@ -88,13 +88,16 @@ ESP8266WebServer::~ESP8266WebServer() { } void ESP8266WebServer::begin() { - _currentStatus = HC_NONE; + close(); _server.begin(); - if(!_headerKeysCount) - collectHeaders(0, 0); } -String ESP8266WebServer::_exractParam(String& authReq,const String& param,const char delimit){ +void ESP8266WebServer::begin(uint16_t port) { + close(); + _server.begin(port); +} + +String ESP8266WebServer::_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())); @@ -132,17 +135,17 @@ bool ESP8266WebServer::authenticate(const char * username, const char * password #ifdef DEBUG_ESP_HTTP_SERVER DEBUG_OUTPUT.println(authReq); #endif - String _username = _exractParam(authReq,"username=\""); + String _username = _extractParam(authReq,"username=\""); if((!_username.length())||_username!=String(username)){ authReq = String(); return false; } // extracting required parameters for RFC 2069 simpler Digest - String _realm = _exractParam(authReq,"realm=\""); - String _nonce = _exractParam(authReq,"nonce=\""); - String _uri = _exractParam(authReq,"uri=\""); - String _response = _exractParam(authReq,"response=\""); - String _opaque = _exractParam(authReq,"opaque=\""); + String _realm = _extractParam(authReq,"realm=\""); + String _nonce = _extractParam(authReq,"nonce=\""); + String _uri = _extractParam(authReq,"uri=\""); + String _response = _extractParam(authReq,"response=\""); + String _opaque = _extractParam(authReq,"opaque=\""); if((!_realm.length())||(!_nonce.length())||(!_uri.length())||(!_response.length())||(!_opaque.length())){ authReq = String(); @@ -155,8 +158,8 @@ bool ESP8266WebServer::authenticate(const char * username, const char * password // parameters for the RFC 2617 newer Digest String _nc,_cnonce; if(authReq.indexOf("qop=auth") != -1){ - _nc = _exractParam(authReq,"nc=",','); - _cnonce = _exractParam(authReq,"cnonce=\""); + _nc = _extractParam(authReq,"nc=",','); + _cnonce = _extractParam(authReq,"cnonce=\""); } MD5Builder md5; md5.begin(); @@ -215,16 +218,16 @@ String ESP8266WebServer::_getRandomHexString(){ void ESP8266WebServer::requestAuthentication(HTTPAuthMethod mode, const char* realm, const String& authFailMsg){ if(realm==NULL){ - _srealm = "Login Required"; + _srealm = String(F("Login Required")); }else{ _srealm = String(realm); } if(mode==BASIC_AUTH){ - sendHeader("WWW-Authenticate", "Basic realm=\"" + _srealm + "\""); + sendHeader(String(F("WWW-Authenticate")), String(F("Basic realm=\"")) + _srealm + String(F("\""))); }else{ _snonce=_getRandomHexString(); _sopaque=_getRandomHexString(); - sendHeader("WWW-Authenticate", "Digest realm=\"" +_srealm + "\", qop=\"auth\", nonce=\""+_snonce+"\", opaque=\""+_sopaque+"\""); + sendHeader(String(F("WWW-Authenticate")), String(F("Digest realm=\"")) +_srealm + String(F("\", qop=\"auth\", nonce=\"")) + _snonce + String(F("\", opaque=\"")) + _sopaque + String(F("\""))); } send(401,"text/html",authFailMsg); } @@ -327,6 +330,9 @@ void ESP8266WebServer::handleClient() { void ESP8266WebServer::close() { _server.close(); + _currentStatus = HC_NONE; + if(!_headerKeysCount) + collectHeaders(0, 0); } void ESP8266WebServer::stop() { @@ -352,27 +358,27 @@ void ESP8266WebServer::setContentLength(size_t contentLength) { } void ESP8266WebServer::_prepareHeader(String& response, int code, const char* content_type, size_t contentLength) { - response = "HTTP/1."+String(_currentVersion)+" "; + response = String(F("HTTP/1.")) + String(_currentVersion) + " "; response += String(code); response += " "; response += _responseCodeToString(code); - response += "\r\n"; + response += String(F("\r\n")); if (!content_type) content_type = "text/html"; - sendHeader("Content-Type", content_type, true); + sendHeader(String(F("Content-Type")), content_type, true); if (_contentLength == CONTENT_LENGTH_NOT_SET) { - sendHeader("Content-Length", String(contentLength)); + sendHeader(String(F("Content-Length")), String(contentLength)); } else if (_contentLength != CONTENT_LENGTH_UNKNOWN) { - sendHeader("Content-Length", String(_contentLength)); + sendHeader(String(F("Content-Length")), String(_contentLength)); } else if(_contentLength == CONTENT_LENGTH_UNKNOWN && _currentVersion){ //HTTP/1.1 or above client //let's do chunked _chunked = true; - sendHeader("Accept-Ranges","none"); - sendHeader("Transfer-Encoding","chunked"); + sendHeader(String(F("Accept-Ranges")),String(F("none"))); + sendHeader(String(F("Transfer-Encoding")),String(F("chunked"))); } - sendHeader("Connection", "close"); + sendHeader(String(F("Connection")), String(F("close"))); response += _responseHeaders; response += "\r\n"; @@ -574,7 +580,7 @@ void ESP8266WebServer::_handleRequest() { handled = true; } if (!handled) { - send(404, "text/plain", String("Not found: ") + _currentUri); + send(404, "text/plain", String(F("Not found: ")) + _currentUri); handled = true; } if (handled) { @@ -632,6 +638,6 @@ String ESP8266WebServer::_responseCodeToString(int code) { case 503: return F("Service Unavailable"); case 504: return F("Gateway Time-out"); case 505: return F("HTTP Version not supported"); - default: return ""; + default: return F(""); } } diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h index 6de40e07b7..22bc23ab8e 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h @@ -74,6 +74,7 @@ class ESP8266WebServer virtual ~ESP8266WebServer(); virtual void begin(); + virtual void begin(uint16_t port); virtual void handleClient(); virtual void close(); @@ -157,7 +158,7 @@ template size_t streamFile(T &file, const String& contentType){ String _getRandomHexString(); // for extracting Auth parameters - String _exractParam(String& authReq,const String& param,const char delimit = '"'); + String _extractParam(String& authReq,const String& param,const char delimit = '"'); struct RequestArgument { String key; From 0ddebeabde4bb0d4eec47e7efcb02bc976832bde Mon Sep 17 00:00:00 2001 From: devyte Date: Sat, 3 Feb 2018 22:27:13 -0300 Subject: [PATCH 2/5] Moved more strings to flash, unified some strings --- .../ESP8266WebServer/src/ESP8266WebServer.cpp | 50 ++++++++++--------- .../src/detail/RequestHandlersImpl.h | 33 ++---------- 2 files changed, 31 insertions(+), 52 deletions(-) diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp index 340ffef773..29309e5cb3 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp @@ -36,7 +36,9 @@ #define DEBUG_OUTPUT Serial #endif -const char * AUTHORIZATION_HEADER = "Authorization"; +//const char * AUTHORIZATION_HEADER = "Authorization"; +static const char AUTHORIZATION_HEADER[] PROGMEM = "Authorization"; +static const char qop_auth[] PROGMEM = "qop=auth"; ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port) : _server(addr, port) @@ -44,13 +46,13 @@ ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port) , _currentVersion(0) , _currentStatus(HC_NONE) , _statusChange(0) -, _currentHandler(0) -, _firstHandler(0) -, _lastHandler(0) +, _currentHandler(nullptr) +, _firstHandler(nullptr) +, _lastHandler(nullptr) , _currentArgCount(0) -, _currentArgs(0) +, _currentArgs(nullptr) , _headerKeysCount(0) -, _currentHeaders(0) +, _currentHeaders(nullptr) , _contentLength(0) , _chunked(false) { @@ -62,13 +64,13 @@ ESP8266WebServer::ESP8266WebServer(int port) , _currentVersion(0) , _currentStatus(HC_NONE) , _statusChange(0) -, _currentHandler(0) -, _firstHandler(0) -, _lastHandler(0) +, _currentHandler(nullptr) +, _firstHandler(nullptr) +, _lastHandler(nullptr) , _currentArgCount(0) -, _currentArgs(0) +, _currentArgs(nullptr) , _headerKeysCount(0) -, _currentHeaders(0) +, _currentHeaders(nullptr) , _contentLength(0) , _chunked(false) { @@ -104,9 +106,9 @@ String ESP8266WebServer::_extractParam(String& authReq,const String& param,const } bool ESP8266WebServer::authenticate(const char * username, const char * password){ - if(hasHeader(AUTHORIZATION_HEADER)){ - String authReq = header(AUTHORIZATION_HEADER); - if(authReq.startsWith("Basic")){ + 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; @@ -130,22 +132,22 @@ bool ESP8266WebServer::authenticate(const char * username, const char * password } delete[] toencode; delete[] encoded; - }else if(authReq.startsWith("Digest")){ + }else if(authReq.startsWith(F("Digest"))){ authReq = authReq.substring(7); #ifdef DEBUG_ESP_HTTP_SERVER DEBUG_OUTPUT.println(authReq); #endif - String _username = _extractParam(authReq,"username=\""); + String _username = _extractParam(authReq,F("username=\"")); if((!_username.length())||_username!=String(username)){ authReq = String(); return false; } // extracting required parameters for RFC 2069 simpler Digest - String _realm = _extractParam(authReq,"realm=\""); - String _nonce = _extractParam(authReq,"nonce=\""); - String _uri = _extractParam(authReq,"uri=\""); - String _response = _extractParam(authReq,"response=\""); - String _opaque = _extractParam(authReq,"opaque=\""); + 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 = String(); @@ -157,7 +159,7 @@ bool ESP8266WebServer::authenticate(const char * username, const char * password } // parameters for the RFC 2617 newer Digest String _nc,_cnonce; - if(authReq.indexOf("qop=auth") != -1){ + if(authReq.indexOf(FPSTR(qop=auth)) != -1){ _nc = _extractParam(authReq,"nc=",','); _cnonce = _extractParam(authReq,"cnonce=\""); } @@ -187,7 +189,7 @@ bool ESP8266WebServer::authenticate(const char * username, const char * password DEBUG_OUTPUT.println("Hash of GET:uri=" + _H2); #endif md5.begin(); - if(authReq.indexOf("qop=auth") != -1){ + if(authReq.indexOf(FPSTR(qop_auth)) != -1){ md5.add(_H1+":"+_nonce+":"+_nc+":"+_cnonce+":auth:"+_H2); }else{ md5.add(_H1+":"+_nonce+":"+_H2); @@ -518,7 +520,7 @@ void ESP8266WebServer::collectHeaders(const char* headerKeys[], const size_t hea if (_currentHeaders) delete[]_currentHeaders; _currentHeaders = new RequestArgument[_headerKeysCount]; - _currentHeaders[0].key = AUTHORIZATION_HEADER; + _currentHeaders[0].key = FPSTR(AUTHORIZATION_HEADER); for (int i = 1; i < _headerKeysCount; i++){ _currentHeaders[i].key = headerKeys[i-1]; } diff --git a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h index 692052359d..b1de4a6005 100644 --- a/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h +++ b/libraries/ESP8266WebServer/src/detail/RequestHandlersImpl.h @@ -2,32 +2,9 @@ #define REQUESTHANDLERSIMPL_H #include "RequestHandler.h" +#include "mimetable.h" -// Table of extension->MIME strings stored in PROGMEM, needs to be global due to GCC section typing rules -static const struct {const char endsWith[16]; const char mimeType[32];} mimeTable[] ICACHE_RODATA_ATTR = { - { ".html", "text/html" }, - { ".htm", "text/html" }, - { ".css", "text/css" }, - { ".txt", "text/plain" }, - { ".js", "application/javascript" }, - { ".json", "application/json" }, - { ".png", "image/png" }, - { ".gif", "image/gif" }, - { ".jpg", "image/jpeg" }, - { ".ico", "image/x-icon" }, - { ".svg", "image/svg+xml" }, - { ".ttf", "application/x-font-ttf" }, - { ".otf", "application/x-font-opentype" }, - { ".woff", "application/font-woff" }, - { ".woff2", "application/font-woff2" }, - { ".eot", "application/vnd.ms-fontobject" }, - { ".sfnt", "application/font-sfnt" }, - { ".xml", "text/xml" }, - { ".pdf", "application/pdf" }, - { ".zip", "application/zip" }, - { ".gz", "application/x-gzip" }, - { ".appcache", "text/cache-manifest" }, - { "", "application/octet-stream" } }; +using namespace mime; class FunctionRequestHandler : public RequestHandler { public: @@ -124,10 +101,10 @@ class StaticRequestHandler : public RequestHandler { // look for gz file, only if the original specified path is not a gz. So part only works to send gzip via content encoding when a non compressed is asked for // if you point the the path to gzip you will serve the gzip as content type "application/x-gzip", not text or javascript etc... - if (!path.endsWith(".gz") && !_fs.exists(path)) { - String pathWithGz = path + ".gz"; + if (!path.endsWith(mimeTable[gz].endsWith) && !_fs.exists(path)) { + String pathWithGz = path + mimeTable[gz].endsWith; if(_fs.exists(pathWithGz)) - path += ".gz"; + path += mimeTable[gz].endsWith; } File f = _fs.open(path, "r"); From f8a784e8ce93b03469d479dd1e7f725de39f3877 Mon Sep 17 00:00:00 2001 From: devyte Date: Mon, 5 Feb 2018 01:37:28 -0300 Subject: [PATCH 3/5] move mimetable strings into a standalone file --- .../ESP8266WebServer/src/detail/mimetable.cpp | 35 ++++++++++++++ .../ESP8266WebServer/src/detail/mimetable.h | 47 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 libraries/ESP8266WebServer/src/detail/mimetable.cpp create mode 100644 libraries/ESP8266WebServer/src/detail/mimetable.h diff --git a/libraries/ESP8266WebServer/src/detail/mimetable.cpp b/libraries/ESP8266WebServer/src/detail/mimetable.cpp new file mode 100644 index 0000000000..51a1f60bc7 --- /dev/null +++ b/libraries/ESP8266WebServer/src/detail/mimetable.cpp @@ -0,0 +1,35 @@ +#include "mimetable.h" +#include "pgmspace.h" + +namespace mime +{ + +// Table of extension->MIME strings stored in PROGMEM, needs to be global due to GCC section typing rules +const Entry mimeTable[maxType] ICACHE_RODATA_ATTR = +{ + { ".html", "text/html" }, + { ".htm", "text/html" }, + { ".css", "text/css" }, + { ".txt", "text/plain" }, + { ".js", "application/javascript" }, + { ".json", "application/json" }, + { ".png", "image/png" }, + { ".gif", "image/gif" }, + { ".jpg", "image/jpeg" }, + { ".ico", "image/x-icon" }, + { ".svg", "image/svg+xml" }, + { ".ttf", "application/x-font-ttf" }, + { ".otf", "application/x-font-opentype" }, + { ".woff", "application/font-woff" }, + { ".woff2", "application/font-woff2" }, + { ".eot", "application/vnd.ms-fontobject" }, + { ".sfnt", "application/font-sfnt" }, + { ".xml", "text/xml" }, + { ".pdf", "application/pdf" }, + { ".zip", "application/zip" }, + { ".gz", "application/x-gzip" }, + { ".appcache", "text/cache-manifest" }, + { "", "application/octet-stream" } +}; + +} diff --git a/libraries/ESP8266WebServer/src/detail/mimetable.h b/libraries/ESP8266WebServer/src/detail/mimetable.h new file mode 100644 index 0000000000..12513d2b27 --- /dev/null +++ b/libraries/ESP8266WebServer/src/detail/mimetable.h @@ -0,0 +1,47 @@ +#ifndef __MIMETABLE_H__ +#define __MIMETABLE_H__ + + +namespace mime +{ + +enum type +{ + html, + htm, + css, + txt, + js, + json, + png, + gif, + jpg, + ico, + svg, + ttf, + otf, + woff, + woff2, + eot, + sfnt, + xml, + pdf, + zip, + gz, + appcache, + none, + maxType +}; + +struct Entry +{ + const char endsWith[16]; + const char mimeType[32]; +}; + + +} + +extern const mime::Entry mimeTable[mime::maxType]; + +#endif From e744e60ff96088b4a7501444a4fe9466c1c844d4 Mon Sep 17 00:00:00 2001 From: devyte Date: Mon, 5 Feb 2018 03:20:17 -0300 Subject: [PATCH 4/5] more string moves to flash, remove duplicates, refactor of template method, minor styling --- .../ESP8266WebServer/src/ESP8266WebServer.cpp | 109 +++++++++++------- .../ESP8266WebServer/src/ESP8266WebServer.h | 21 ++-- .../ESP8266WebServer/src/detail/mimetable.h | 2 +- 3 files changed, 75 insertions(+), 57 deletions(-) diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp index 29309e5cb3..96eed9ba71 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp @@ -39,6 +39,10 @@ //const char * AUTHORIZATION_HEADER = "Authorization"; static const char AUTHORIZATION_HEADER[] PROGMEM = "Authorization"; static const char qop_auth[] PROGMEM = "qop=auth"; +static const char WWW_Authenticate[] PROGMEM = "WWW-Authenticate"; +static const char colon[] PROGMEM = ":"; +static const char Content_Length[] PROGMEM = "Content-Length"; + ESP8266WebServer::ESP8266WebServer(IPAddress addr, int port) : _server(addr, port) @@ -101,7 +105,8 @@ void ESP8266WebServer::begin(uint16_t port) { String ESP8266WebServer::_extractParam(String& authReq,const String& param,const char delimit){ int _begin = authReq.indexOf(param); - if (_begin==-1) return ""; + if (_begin==-1) + return String(); return authReq.substring(_begin+param.length(),authReq.indexOf(delimit,_begin+param.length())); } @@ -132,40 +137,40 @@ bool ESP8266WebServer::authenticate(const char * username, const char * password } delete[] toencode; delete[] encoded; - }else if(authReq.startsWith(F("Digest"))){ + } else if(authReq.startsWith(F("Digest"))) { authReq = authReq.substring(7); #ifdef DEBUG_ESP_HTTP_SERVER DEBUG_OUTPUT.println(authReq); #endif String _username = _extractParam(authReq,F("username=\"")); - if((!_username.length())||_username!=String(username)){ + if(!_username.length() || _username != String(username)) { authReq = String(); 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=\"")); + 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())){ + if((!_realm.length()) || (!_nonce.length()) || (!_uri.length()) || (!_response.length()) || (!_opaque.length())) { authReq = String(); return false; } - if((_opaque!=_sopaque)||(_nonce!=_snonce)||(_realm!=_srealm)){ + if((_opaque != _sopaque) || (_nonce != _snonce) || (_realm != _srealm)) { authReq = String(); return false; } // parameters for the RFC 2617 newer Digest String _nc,_cnonce; - if(authReq.indexOf(FPSTR(qop=auth)) != -1){ - _nc = _extractParam(authReq,"nc=",','); - _cnonce = _extractParam(authReq,"cnonce=\""); + if(authReq.indexOf(FPSTR(qop_auth)) != -1) { + _nc = _extractParam(authReq, F("nc="), ','); + _cnonce = _extractParam(authReq, F("cnonce=\"")); } MD5Builder md5; md5.begin(); - md5.add(String(username)+":"+_realm+":"+String(password)); // md5 of the user:realm:user + md5.add(String(username) + ':' + _realm + ':' + String(password)); // md5 of the user:realm:user md5.calculate(); String _H1 = md5.toString(); #ifdef DEBUG_ESP_HTTP_SERVER @@ -173,15 +178,15 @@ bool ESP8266WebServer::authenticate(const char * username, const char * password #endif md5.begin(); if(_currentMethod == HTTP_GET){ - md5.add("GET:"+_uri); + md5.add(String(F("GET:")) + _uri); }else if(_currentMethod == HTTP_POST){ - md5.add("POST:"+_uri); + md5.add(String(F("POST:")) + _uri); }else if(_currentMethod == HTTP_PUT){ - md5.add("PUT:"+_uri); + md5.add(String(F("PUT:")) + _uri); }else if(_currentMethod == HTTP_DELETE){ - md5.add("DELETE:"+_uri); + md5.add(String(F("DELETE:")) + _uri); }else{ - md5.add("GET:"+_uri); + md5.add(String(F("GET:")) + _uri); } md5.calculate(); String _H2 = md5.toString(); @@ -189,17 +194,17 @@ bool ESP8266WebServer::authenticate(const char * username, const char * password DEBUG_OUTPUT.println("Hash of GET:uri=" + _H2); #endif md5.begin(); - if(authReq.indexOf(FPSTR(qop_auth)) != -1){ - md5.add(_H1+":"+_nonce+":"+_nc+":"+_cnonce+":auth:"+_H2); + if(authReq.indexOf(FPSTR(qop_auth)) != -1) { + md5.add(_H1 + FPSTR(colon) + _nonce + FPSTR(colon) + _nc + FPSTR(colon) + _cnonce + ':auth:' + _H2); }else{ - md5.add(_H1+":"+_nonce+":"+_H2); + md5.add(_H1 + FPSTR(colon) + _nonce + FPSTR(colon) + _H2); } md5.calculate(); String _responsecheck = md5.toString(); #ifdef DEBUG_ESP_HTTP_SERVER DEBUG_OUTPUT.println("The Proper response=" +_responsecheck); #endif - if(_response==_responsecheck){ + if(_response == _responsecheck){ authReq = String(); return true; } @@ -209,29 +214,30 @@ bool ESP8266WebServer::authenticate(const char * username, const char * password return false; } -String ESP8266WebServer::_getRandomHexString(){ +String ESP8266WebServer::_getRandomHexString() { char buffer[33]; // buffer to hold 32 Hex Digit + /0 int i; - for(i=0;i<4;i++){ - sprintf (buffer+(i*8), "%08x", RANDOM_REG32); + for(i = 0; i < 4; i++) { + sprintf (buffer + (i*8), "%08x", RANDOM_REG32); } return String(buffer); } -void ESP8266WebServer::requestAuthentication(HTTPAuthMethod mode, const char* realm, const String& authFailMsg){ - if(realm==NULL){ +void ESP8266WebServer::requestAuthentication(HTTPAuthMethod mode, const char* realm, const String& authFailMsg) { + if(realm == NULL) { _srealm = String(F("Login Required")); - }else{ + } else { _srealm = String(realm); } - if(mode==BASIC_AUTH){ - sendHeader(String(F("WWW-Authenticate")), String(F("Basic realm=\"")) + _srealm + String(F("\""))); - }else{ + if(mode == BASIC_AUTH) { + sendHeader(String(FPSTR(WWW_Authenticate)), String(F("Basic realm=\"")) + _srealm + String(F("\""))); + } else { _snonce=_getRandomHexString(); _sopaque=_getRandomHexString(); - sendHeader(String(F("WWW-Authenticate")), String(F("Digest realm=\"")) +_srealm + String(F("\", qop=\"auth\", nonce=\"")) + _snonce + String(F("\", opaque=\"")) + _sopaque + String(F("\""))); + sendHeader(String(FPSTR(WWW_Authenticate)), String(F("Digest realm=\"")) +_srealm + String(F("\", qop=\"auth\", nonce=\"")) + _snonce + String(F("\", opaque=\"")) + _sopaque + String(F("\""))); } - send(401,"text/html",authFailMsg); + using namespace mime; + send(401, mimeTable[html].mimeType, authFailMsg); } void ESP8266WebServer::on(const String &uri, ESP8266WebServer::THandlerFunction handler) { @@ -343,9 +349,9 @@ void ESP8266WebServer::stop() { void ESP8266WebServer::sendHeader(const String& name, const String& value, bool first) { String headerLine = name; - headerLine += ": "; + headerLine += F(": "); headerLine += value; - headerLine += "\r\n"; + headerLine += F("\r\n"); if (first) { _responseHeaders = headerLine + _responseHeaders; @@ -355,25 +361,26 @@ void ESP8266WebServer::sendHeader(const String& name, const String& value, bool } } -void ESP8266WebServer::setContentLength(size_t contentLength) { +void ESP8266WebServer::setContentLength(const size_t contentLength) { _contentLength = contentLength; } void ESP8266WebServer::_prepareHeader(String& response, int code, const char* content_type, size_t contentLength) { - response = String(F("HTTP/1.")) + String(_currentVersion) + " "; + response = String(F("HTTP/1.")) + String(_currentVersion) + ' '; response += String(code); - response += " "; + response += ' '; response += _responseCodeToString(code); response += String(F("\r\n")); + using namespace mime; if (!content_type) - content_type = "text/html"; + content_type = mimeTable[html].mimeType; sendHeader(String(F("Content-Type")), content_type, true); if (_contentLength == CONTENT_LENGTH_NOT_SET) { - sendHeader(String(F("Content-Length")), String(contentLength)); + sendHeader(String(FPSTR(Content_Length)), String(contentLength)); } else if (_contentLength != CONTENT_LENGTH_UNKNOWN) { - sendHeader(String(F("Content-Length")), String(_contentLength)); + 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; @@ -474,6 +481,19 @@ void ESP8266WebServer::sendContent_P(PGM_P content, size_t size) { } +void ESP8266WebServer::_streamFileCore(const size_t fileSize, const String & fileName, const String & contentType) +{ + using namespace mime; + setContentLength(fileSize); + if (fileName.endsWith(mimeTable[gz].endsWith) && + contentType != mimeTable[gz].mimeType && + contentType != mimeTable[none].mimeType) { + sendHeader(F("Content-Encoding"), F("gzip")); + } + send(200, contentType, ""); +} + + String ESP8266WebServer::arg(String name) { for (int i = 0; i < _currentArgCount; ++i) { if ( _currentArgs[i].key == name ) @@ -582,7 +602,8 @@ void ESP8266WebServer::_handleRequest() { handled = true; } if (!handled) { - send(404, "text/plain", String(F("Not found: ")) + _currentUri); + using namespace mime; + send(404, mimeTable[html].mimeType, String(F("Not found: ")) + _currentUri); handled = true; } if (handled) { @@ -594,7 +615,7 @@ void ESP8266WebServer::_handleRequest() { void ESP8266WebServer::_finalizeResponse() { if (_chunked) { - sendContent(""); + sendContent(String()); } } diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h index 22bc23ab8e..0bfa302a4c 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h @@ -121,7 +121,7 @@ class ESP8266WebServer void send_P(int code, PGM_P content_type, PGM_P content); void send_P(int code, PGM_P content_type, PGM_P content, size_t contentLength); - void setContentLength(size_t contentLength); + void setContentLength(const size_t contentLength); void sendHeader(const String& name, const String& value, bool first = false); void sendContent(const String& content); void sendContent_P(PGM_P content); @@ -129,17 +129,12 @@ class ESP8266WebServer static String urlDecode(const String& text); -template size_t streamFile(T &file, const String& contentType){ - setContentLength(file.size()); - if (String(file.name()).endsWith(".gz") && - contentType != "application/x-gzip" && - contentType != "application/octet-stream"){ - sendHeader("Content-Encoding", "gzip"); + template + size_t streamFile(T &file, const String& contentType) { + _streamFileCore(file.size(), file.name(), contentType); + return _currentClient.write(file); } - send(200, contentType, ""); - return _currentClient.write(file); -} - + protected: virtual size_t _currentClientWrite(const char* b, size_t l) { return _currentClient.write( b, l ); } virtual size_t _currentClientWrite_P(PGM_P b, size_t l) { return _currentClient.write_P( b, l ); } @@ -155,7 +150,9 @@ template size_t streamFile(T &file, const String& contentType){ uint8_t _uploadReadByte(WiFiClient& client); void _prepareHeader(String& response, int code, const char* content_type, size_t contentLength); bool _collectHeader(const char* headerName, const char* headerValue); - + + void _streamFileCore(const size_t fileSize, const String & fileName, const String & contentType); + String _getRandomHexString(); // for extracting Auth parameters String _extractParam(String& authReq,const String& param,const char delimit = '"'); diff --git a/libraries/ESP8266WebServer/src/detail/mimetable.h b/libraries/ESP8266WebServer/src/detail/mimetable.h index 12513d2b27..191356c489 100644 --- a/libraries/ESP8266WebServer/src/detail/mimetable.h +++ b/libraries/ESP8266WebServer/src/detail/mimetable.h @@ -40,8 +40,8 @@ struct Entry }; +extern const Entry mimeTable[maxType]; } -extern const mime::Entry mimeTable[mime::maxType]; #endif From 3b25df7ede3184bfea55732fd6fcda6f1fe42b30 Mon Sep 17 00:00:00 2001 From: devyte Date: Tue, 6 Feb 2018 21:12:33 -0300 Subject: [PATCH 5/5] Reverted moving small string to flash (no heap advantage, reduces bin size) --- .../ESP8266WebServer/src/ESP8266WebServer.cpp | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp index 96eed9ba71..4eef8725a6 100644 --- a/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp +++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp @@ -106,7 +106,7 @@ void ESP8266WebServer::begin(uint16_t port) { String ESP8266WebServer::_extractParam(String& authReq,const String& param,const char delimit){ int _begin = authReq.indexOf(param); if (_begin==-1) - return String(); + return ""; return authReq.substring(_begin+param.length(),authReq.indexOf(delimit,_begin+param.length())); } @@ -119,18 +119,18 @@ bool ESP8266WebServer::authenticate(const char * username, const char * password char toencodeLen = strlen(username)+strlen(password)+1; char *toencode = new char[toencodeLen + 1]; if(toencode == NULL){ - authReq = String(); + authReq = ""; return false; } char *encoded = new char[base64_encode_expected_len(toencodeLen)+1]; if(encoded == NULL){ - authReq = String(); + authReq = ""; delete[] toencode; return false; } sprintf(toencode, "%s:%s", username, password); if(base64_encode_chars(toencode, toencodeLen, encoded) > 0 && authReq.equalsConstantTime(encoded)) { - authReq = String(); + authReq = ""; delete[] toencode; delete[] encoded; return true; @@ -144,7 +144,7 @@ bool ESP8266WebServer::authenticate(const char * username, const char * password #endif String _username = _extractParam(authReq,F("username=\"")); if(!_username.length() || _username != String(username)) { - authReq = String(); + authReq = ""; return false; } // extracting required parameters for RFC 2069 simpler Digest @@ -155,11 +155,11 @@ bool ESP8266WebServer::authenticate(const char * username, const char * password String _opaque = _extractParam(authReq, F("opaque=\"")); if((!_realm.length()) || (!_nonce.length()) || (!_uri.length()) || (!_response.length()) || (!_opaque.length())) { - authReq = String(); + authReq = ""; return false; } if((_opaque != _sopaque) || (_nonce != _snonce) || (_realm != _srealm)) { - authReq = String(); + authReq = ""; return false; } // parameters for the RFC 2617 newer Digest @@ -205,11 +205,11 @@ bool ESP8266WebServer::authenticate(const char * username, const char * password DEBUG_OUTPUT.println("The Proper response=" +_responsecheck); #endif if(_response == _responsecheck){ - authReq = String(); + authReq = ""; return true; } } - authReq = String(); + authReq = ""; } return false; } @@ -351,7 +351,7 @@ void ESP8266WebServer::sendHeader(const String& name, const String& value, bool String headerLine = name; headerLine += F(": "); headerLine += value; - headerLine += F("\r\n"); + headerLine += "\r\n"; if (first) { _responseHeaders = headerLine + _responseHeaders; @@ -370,7 +370,7 @@ void ESP8266WebServer::_prepareHeader(String& response, int code, const char* co response += String(code); response += ' '; response += _responseCodeToString(code); - response += String(F("\r\n")); + response += "\r\n"; using namespace mime; if (!content_type) @@ -391,7 +391,7 @@ void ESP8266WebServer::_prepareHeader(String& response, int code, const char* co response += _responseHeaders; response += "\r\n"; - _responseHeaders = String(); + _responseHeaders = ""; } void ESP8266WebServer::send(int code, const char* content_type, const String& content) { @@ -499,19 +499,19 @@ String ESP8266WebServer::arg(String name) { if ( _currentArgs[i].key == name ) return _currentArgs[i].value; } - return String(); + return ""; } String ESP8266WebServer::arg(int i) { if (i < _currentArgCount) return _currentArgs[i].value; - return String(); + return ""; } String ESP8266WebServer::argName(int i) { if (i < _currentArgCount) return _currentArgs[i].key; - return String(); + return ""; } int ESP8266WebServer::args() { @@ -532,7 +532,7 @@ String ESP8266WebServer::header(String name) { if (_currentHeaders[i].key.equalsIgnoreCase(name)) return _currentHeaders[i].value; } - return String(); + return ""; } void ESP8266WebServer::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) { @@ -549,13 +549,13 @@ void ESP8266WebServer::collectHeaders(const char* headerKeys[], const size_t hea String ESP8266WebServer::header(int i) { if (i < _headerKeysCount) return _currentHeaders[i].value; - return String(); + return ""; } String ESP8266WebServer::headerName(int i) { if (i < _headerKeysCount) return _currentHeaders[i].key; - return String(); + return ""; } int ESP8266WebServer::headers() { @@ -609,13 +609,13 @@ void ESP8266WebServer::_handleRequest() { if (handled) { _finalizeResponse(); } - _currentUri = String(); + _currentUri = ""; } void ESP8266WebServer::_finalizeResponse() { if (_chunked) { - sendContent(String()); + sendContent(""); } }