From 5668927160aa1e88a072ebb2c8046adcc0b76929 Mon Sep 17 00:00:00 2001
From: Jeroen88 <info@el-mago.nl>
Date: Wed, 5 Dec 2018 13:59:53 +0100
Subject: [PATCH 1/5] Fix error in PR #2048: if ::available() is called before
 ::connect() _rxBuffer is not initialised

---
 libraries/WiFi/src/WiFiClient.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/libraries/WiFi/src/WiFiClient.cpp b/libraries/WiFi/src/WiFiClient.cpp
index 6669ef59baf..5c42cc9da1b 100644
--- a/libraries/WiFi/src/WiFiClient.cpp
+++ b/libraries/WiFi/src/WiFiClient.cpp
@@ -398,6 +398,10 @@ int WiFiClient::peek()
 
 int WiFiClient::available()
 {
+    if(!_rxBuffer)
+    {
+        return 0;
+    }
     int res = _rxBuffer->available();
     if(_rxBuffer->failed()) {
         log_e("%d", errno);

From ea4493774e795c68ab2dcb53b6ffe749a8d247b8 Mon Sep 17 00:00:00 2001
From: Jeroen88 <info@el-mago.nl>
Date: Wed, 5 Dec 2018 14:27:54 +0100
Subject: [PATCH 2/5] Abort update if http.begin() returns false. Fix a typo in
 httpUpdate.ino

---
 .../HTTPUpdate/examples/httpUpdate/httpUpdate.ino |  2 +-
 libraries/HTTPUpdate/src/HTTPUpdate.cpp           | 15 ++++++++++++---
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/libraries/HTTPUpdate/examples/httpUpdate/httpUpdate.ino b/libraries/HTTPUpdate/examples/httpUpdate/httpUpdate.ino
index c9018cd43be..f646be04583 100644
--- a/libraries/HTTPUpdate/examples/httpUpdate/httpUpdate.ino
+++ b/libraries/HTTPUpdate/examples/httpUpdate/httpUpdate.ino
@@ -56,7 +56,7 @@ void loop() {
 
     switch (ret) {
       case HTTP_UPDATE_FAILED:
-        Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s\n", httpUpdate.getLastError(), httpUpdate.getLastErrorString().c_str());
+        Serial.printf("HTTP_UPDATE_FAILED Error (%d): %s\n", httpUpdate.getLastError(), httpUpdate.getLastErrorString().c_str());
         break;
 
       case HTTP_UPDATE_NO_UPDATES:
diff --git a/libraries/HTTPUpdate/src/HTTPUpdate.cpp b/libraries/HTTPUpdate/src/HTTPUpdate.cpp
index c3a04cc8913..af263936f8e 100644
--- a/libraries/HTTPUpdate/src/HTTPUpdate.cpp
+++ b/libraries/HTTPUpdate/src/HTTPUpdate.cpp
@@ -49,14 +49,20 @@ HTTPUpdate::~HTTPUpdate(void)
 HTTPUpdateResult HTTPUpdate::update(WiFiClient& client, const String& url, const String& currentVersion)
 {
     HTTPClient http;
-    http.begin(client, url);
+    if(!http.begin(client, url))
+    {
+        return HTTP_UPDATE_FAILED;
+    }
     return handleUpdate(http, currentVersion, false);
 }
 
 HTTPUpdateResult HTTPUpdate::updateSpiffs(WiFiClient& client, const String& url, const String& currentVersion)
 {
     HTTPClient http;
-    http.begin(client, url);
+    if(!http.begin(client, url))
+    {
+        return HTTP_UPDATE_FAILED;
+    }
     return handleUpdate(http, currentVersion, true);
 }
 
@@ -64,7 +70,10 @@ HTTPUpdateResult HTTPUpdate::update(WiFiClient& client, const String& host, uint
         const String& currentVersion)
 {
     HTTPClient http;
-    http.begin(client, host, port, uri);
+    if(!http.begin(client, host, port, uri))
+    {
+        return HTTP_UPDATE_FAILED;
+    }
     return handleUpdate(http, currentVersion, false);
 }
 

From cf9175b58f5884241fc507fdd34f1c839ff0c094 Mon Sep 17 00:00:00 2001
From: Jeroen88 <info@el-mago.nl>
Date: Wed, 5 Dec 2018 23:08:23 +0100
Subject: [PATCH 3/5] Fixed flash size check and added SPIFFS size check

---
 libraries/HTTPUpdate/src/HTTPUpdate.cpp | 31 +++++++++++++++++++------
 libraries/HTTPUpdate/src/HTTPUpdate.h   |  1 +
 2 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/libraries/HTTPUpdate/src/HTTPUpdate.cpp b/libraries/HTTPUpdate/src/HTTPUpdate.cpp
index c3a04cc8913..b03ecaedc48 100644
--- a/libraries/HTTPUpdate/src/HTTPUpdate.cpp
+++ b/libraries/HTTPUpdate/src/HTTPUpdate.cpp
@@ -118,6 +118,8 @@ String HTTPUpdate::getLastErrorString(void)
         return "Verify Bin Header Failed";
     case HTTP_UE_BIN_FOR_WRONG_FLASH:
         return "New Binary Does Not Fit Flash Size";
+    case HTTP_UE_NO_PARTITION:
+        return "Partition Could Not be Found";
     }
 
     return String();
@@ -229,14 +231,25 @@ HTTPUpdateResult HTTPUpdate::handleUpdate(HTTPClient& http, const String& curren
         if(len > 0) {
             bool startUpdate = true;
             if(spiffs) {
-// To do                size_t spiffsSize = ((size_t) &_SPIFFS_end - (size_t) &_SPIFFS_start);
-// To do                if(len > (int) spiffsSize) {
-// To do                    log_e("spiffsSize to low (%d) needed: %d\n", spiffsSize, len);
-// To do                    startUpdate = false;
-// To do                }
+                const esp_partition_t* _partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, NULL);
+                if(!_partition){
+                    _lastError = HTTP_UE_NO_PARTITION;
+                    return HTTP_UPDATE_FAILED;
+                }
+
+                if(len > _partition->size) {
+                    log_e("spiffsSize to low (%d) needed: %d\n", _partition->size, len);
+                    startUpdate = false;
+                }
             } else {
-                if(len > (int) ESP.getFreeSketchSpace()) {
-                    log_e("FreeSketchSpace to low (%d) needed: %d\n", ESP.getFreeSketchSpace(), len);
+                const esp_partition_t* _partition = esp_ota_get_next_update_partition(NULL);
+                if(!_partition){
+                    _lastError = HTTP_UE_NO_PARTITION;
+                    return HTTP_UPDATE_FAILED;
+                }
+
+                if(len > _partition->size) {
+                    log_e("FreeSketchSpace to low (%d) needed: %d\n", _partition->size, len);
                     startUpdate = false;
                 }
             }
@@ -366,6 +379,10 @@ bool HTTPUpdate::runUpdate(Stream& in, uint32_t size, String md5, int command)
         }
     }
 
+// To do: the SHA256 could be checked if the server sends it
+
+    delay(0);
+
     if(Update.writeStream(in) != size) {
         _lastError = Update.getError();
         Update.printError(error);
diff --git a/libraries/HTTPUpdate/src/HTTPUpdate.h b/libraries/HTTPUpdate/src/HTTPUpdate.h
index 33b77840110..f126cba0639 100644
--- a/libraries/HTTPUpdate/src/HTTPUpdate.h
+++ b/libraries/HTTPUpdate/src/HTTPUpdate.h
@@ -42,6 +42,7 @@
 #define HTTP_UE_SERVER_FAULTY_MD5           (-105)
 #define HTTP_UE_BIN_VERIFY_HEADER_FAILED    (-106)
 #define HTTP_UE_BIN_FOR_WRONG_FLASH         (-107)
+#define HTTP_UE_NO_PARTITION                (-108)
 
 enum HTTPUpdateResult {
     HTTP_UPDATE_FAILED,

From 9e629e733122d6cf474076179edacf2c29ef42b6 Mon Sep 17 00:00:00 2001
From: Jeroen88 <info@el-mago.nl>
Date: Thu, 6 Dec 2018 19:28:14 +0100
Subject: [PATCH 4/5] Rewriting ESP.getFreeSketchSpace(), moving code from
 HTTPUpdate.cpp

---
 cores/esp32/Esp.cpp                     |  7 ++++++-
 libraries/HTTPUpdate/src/HTTPUpdate.cpp | 10 ++++------
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/cores/esp32/Esp.cpp b/cores/esp32/Esp.cpp
index 7f57973ea66..9e5dbc25254 100644
--- a/cores/esp32/Esp.cpp
+++ b/cores/esp32/Esp.cpp
@@ -169,7 +169,12 @@ uint32_t EspClass::getSketchSize () {
 }
 
 uint32_t EspClass::getFreeSketchSpace () {
-    return sketchSize(SKETCH_SIZE_FREE);
+    const esp_partition_t* _partition = esp_ota_get_next_update_partition(NULL);
+    if(!_partition){
+        return 0;
+    }
+
+    return _partition->size;
 }
 
 uint8_t EspClass::getChipRevision(void)
diff --git a/libraries/HTTPUpdate/src/HTTPUpdate.cpp b/libraries/HTTPUpdate/src/HTTPUpdate.cpp
index e27b0d58d23..dd4f8623689 100644
--- a/libraries/HTTPUpdate/src/HTTPUpdate.cpp
+++ b/libraries/HTTPUpdate/src/HTTPUpdate.cpp
@@ -251,14 +251,14 @@ HTTPUpdateResult HTTPUpdate::handleUpdate(HTTPClient& http, const String& curren
                     startUpdate = false;
                 }
             } else {
-                const esp_partition_t* _partition = esp_ota_get_next_update_partition(NULL);
-                if(!_partition){
+                int sketchFreeSpace = ESP.getFreeSketchSpace();
+                if(!sketchFreeSpace){
                     _lastError = HTTP_UE_NO_PARTITION;
                     return HTTP_UPDATE_FAILED;
                 }
 
-                if(len > _partition->size) {
-                    log_e("FreeSketchSpace to low (%d) needed: %d\n", _partition->size, len);
+                if(len > sketchFreeSpace) {
+                    log_e("FreeSketchSpace to low (%d) needed: %d\n", sketchFreeSpace, len);
                     startUpdate = false;
                 }
             }
@@ -390,8 +390,6 @@ bool HTTPUpdate::runUpdate(Stream& in, uint32_t size, String md5, int command)
 
 // To do: the SHA256 could be checked if the server sends it
 
-    delay(0);
-
     if(Update.writeStream(in) != size) {
         _lastError = Update.getError();
         Update.printError(error);

From 0902ffaba6e8c3c7143d7f5f9c00bc4cd5322d22 Mon Sep 17 00:00:00 2001
From: Jeroen88 <info@el-mago.nl>
Date: Fri, 7 Dec 2018 17:42:42 +0100
Subject: [PATCH 5/5] Add getSketchMD5() to ESP.h and ESP.cpp

---
 cores/esp32/Esp.cpp | 37 +++++++++++++++++++++++++++++++++++--
 cores/esp32/Esp.h   |  1 +
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/cores/esp32/Esp.cpp b/cores/esp32/Esp.cpp
index 9e5dbc25254..60e4490d72e 100644
--- a/cores/esp32/Esp.cpp
+++ b/cores/esp32/Esp.cpp
@@ -30,6 +30,7 @@
 extern "C" {
 #include <esp_image_format.h>
 }
+#include <MD5Builder.h>
 
 /**
  * User-defined Literals
@@ -158,9 +159,9 @@ static uint32_t sketchSize(sketchSize_t response) {
     data.start_addr = running_pos.offset;
     esp_image_verify(ESP_IMAGE_VERIFY, &running_pos, &data);
     if (response) {
-    return running_pos.size - data.image_len;
+        return running_pos.size - data.image_len;
     } else {
-    return data.image_len;
+        return data.image_len;
     }
 }
     
@@ -168,6 +169,38 @@ uint32_t EspClass::getSketchSize () {
     return sketchSize(SKETCH_SIZE_TOTAL);
 }
 
+String EspClass::getSketchMD5()
+{
+    static String result;
+    if (result.length()) {
+        return result;
+    }
+    uint32_t lengthLeft = getSketchSize();
+
+    const esp_partition_t *running = esp_ota_get_running_partition();
+    if (!running) return String();
+    const size_t bufSize = SPI_FLASH_SEC_SIZE;
+    std::unique_ptr<uint8_t[]> buf(new uint8_t[bufSize]);
+    uint32_t offset = 0;
+    if(!buf.get()) {
+        return String();
+    }
+    MD5Builder md5;
+    md5.begin();
+    while( lengthLeft > 0) {
+        size_t readBytes = (lengthLeft < bufSize) ? lengthLeft : bufSize;
+        if (!ESP.flashRead(running->address + offset, reinterpret_cast<uint32_t*>(buf.get()), (readBytes + 3) & ~3)) {
+            return String();
+        }
+        md5.add(buf.get(), readBytes);
+        lengthLeft -= readBytes;
+        offset += readBytes;
+    }
+    md5.calculate();
+    result = md5.toString();
+    return result;
+}
+
 uint32_t EspClass::getFreeSketchSpace () {
     const esp_partition_t* _partition = esp_ota_get_next_update_partition(NULL);
     if(!_partition){
diff --git a/cores/esp32/Esp.h b/cores/esp32/Esp.h
index 385bcbb4b1f..f8e7b9cfe70 100644
--- a/cores/esp32/Esp.h
+++ b/cores/esp32/Esp.h
@@ -90,6 +90,7 @@ class EspClass
     FlashMode_t magicFlashChipMode(uint8_t byte);
 
     uint32_t getSketchSize();
+    String getSketchMD5();
     uint32_t getFreeSketchSpace();
 
     bool flashEraseSector(uint32_t sector);