diff --git a/include/httpdconfig.h b/include/httpdconfig.h index 56e02e4..193b12f 100644 --- a/include/httpdconfig.h +++ b/include/httpdconfig.h @@ -3,7 +3,8 @@ #define EFS_HEATSHRINK //Pos of esp fs in flash -#define ESPFS_POS 0x12000 +#define ESPFS_POS 0x12000 +#define ESPFS_SIZE 0x2E000 //If you want, you can define a realm for the authentication system. //#define HTTP_AUTH_REALM "MyRealm" \ No newline at end of file diff --git a/user/cgi.c b/user/cgi.c index 753ea84..0b7e8ce 100644 --- a/user/cgi.c +++ b/user/cgi.c @@ -22,6 +22,7 @@ flash as a binary. Also handles the hit counter on the main page. #include "io.h" #include #include "espmissingincludes.h" +#include "../include/httpdconfig.h" //cause I can't be bothered to write an ioGetLed() @@ -104,139 +105,50 @@ int ICACHE_FLASH_ATTR cgiReadFlash(HttpdConnData *connData) { if (*pos>=0x40200000+(512*1024)) return HTTPD_CGI_DONE; else return HTTPD_CGI_MORE; } -#define LOOKING_FOR_SECTION 1 -#define CHECKING_HEADERS 2 -#define IN_DATA 3 +uint32_t postCounter = 0; -typedef struct updateState_t { - char delimiter[61]; - int step; -} updateState_t; - -char* bin_strstr(char *haystack, char *needle, int haystackLen, int needleLen){ - if(needleLen < 0){ - needleLen = strlen(needle); - } - char * end = haystack + haystackLen; - for(; haystack < end; haystack++){ - if(*haystack == *needle){ - int match = true; - for(int i = 1; i< needleLen; i++){ - if(*(needle + i) != *(haystack + i)){ - match = false; - break; - } - } - if(match){ - return haystack; - } - } - } - return NULL; -} - - -//Cgi to allow user to upload a new espfs image -int ICACHE_FLASH_ATTR updateWeb(HttpdConnData *connData) { - os_printf("data size : %d\r\n", connData->postBuffLen); - updateState_t *state; +int ICACHE_FLASH_ATTR cgiUploadEspfs(HttpdConnData *connData) { if (connData->conn==NULL) { //Connection aborted. Clean up. return HTTPD_CGI_DONE; } - if(connData->requestType == GET){ - httpdStartResponse(connData, 200); - httpdHeader(connData, "Content-Length", "135"); - httpdEndHeaders(connData); - httpdSend(connData, "
", 135); - }else if(connData->requestType == POST){ - if(connData->postReceived == connData->postBuffLen){ - //it's the first time this handler has been called for this request - connData->cgiPrivData = (int*)os_malloc(sizeof(updateState_t)); - state = connData->cgiPrivData; - state->step = LOOKING_FOR_SECTION; - }else{ - state = connData->cgiPrivData; + SpiFlashOpResult ret; + int x; + uint32_t flashOff = ESPFS_POS; + uint32_t flashSize = ESPFS_SIZE; + + //If this is the first time, erase the flash sector + if (postCounter == 0){ + os_printf("Erasing flash at 0x%x...\n", flashOff); + // Which segment are we flashing? + for (x=0; xpostBuffSize==1024){ + ret=spi_flash_write((flashOff + postCounter), (uint32 *)connData->postBuff, 1024); + os_printf("Flash return %d\n", ret); + } else { + // Think we can probably use postReceived to check if it's the last chunk and then pad the original postBuff to avoid allocating another 1k of memory + char *postBuff = (char*)os_zalloc(1024); + os_printf("Mallocced buffer of 1024 bytes of last chunk.\n"); + os_memcpy(postBuff, connData->postBuff, connData->postBuffSize); + ret=spi_flash_write((flashOff + postCounter), (uint32 *)postBuff, 1024); + os_printf("Flash return %d\n", ret); + } + + // Count bytes for data + postCounter = postCounter + connData->postBuffSize;//connData->postBuff); + os_printf("Wrote %d bytes (%dB of %d)\n", connData->postBuffSize, postCounter, connData->postLen);//&connData->postBuff)); - char *b; - char *p; - char * end = connData->postBuff + connData->postBuffLen; - for(b = connData->postBuff; b < end; b++){ - if(state->step == LOOKING_FOR_SECTION){ - if((p = bin_strstr(b, connData->multipartBoundary, connData->postBuffLen - (b - connData->postBuff), -1)) != NULL){ - os_printf("Found section\r\n"); - // We've found one of the sections, now make sure it's the file - b = p + strlen(connData->multipartBoundary) + 2; - state->step = CHECKING_HEADERS; - }else{ - os_printf("Not Found section\r\n"); - break; - } - } - - if(state->step == CHECKING_HEADERS){ - //os_printf("next data: %s\n", b); - if(!os_strncmp(b, "Content-Disposition: form-data", 30)){ - os_printf("Correct header\r\n"); - // It's the Content-Disposition header - // Find the end of the line - p = os_strstr(b, "\r\n"); - // turn the end of the line into a string end so we can search within the line - *p = 0; - if(os_strstr(b, "name=\"file\"") != NULL){ - os_printf("Correct file\r\n"); - b = p + 2; - // it's the correct section, skip to the data - if((p = os_strstr(b, "\r\n\r\n")) != NULL){ - os_printf("Skipping to data\r\n"); - b = p + 4; - state->step = IN_DATA; - }else{ - os_printf("Couldn't find line endings\r\n"); - os_printf("data: %s\n", b); - return HTTPD_CGI_DONE; - } - }else{ - // it's the wrong section, skip to the next boundary - b = p + 1; - state->step = LOOKING_FOR_SECTION; - } - }else{ - // Skip to the next header - p = os_strstr(b, "\r\n"); - b = p + 2; - } - } - - if(state->step == IN_DATA){ - //os_printf("In data\r\n"); - // Make sure it doesn't contain the boundary, but we can't rely on there being no zeroes so can't use strstr - if((p = bin_strstr(b, connData->multipartBoundary, connData->postBuffLen - (b - connData->postBuff), -1)) == NULL){ - // all of the data is file data - }else{ - if(b < (p - 2)){ // -2 bytes for the \r\n - // This is a byte that's part of the file - os_printf("%c", *b); - }else{ - os_printf("\r\nComplete\r\n"); - } - } - } - } - /* - os_printf("postReceived: %d\r\n", connData->postReceived); - os_printf("postLen : %d\r\n", connData->postLen); - os_printf("data size : %d\r\n", connData->postBuffLen); - */ - if(connData->postReceived >= connData->postLen){ - httpdStartResponse(connData, 204); - if (connData->cgiPrivData!=NULL) os_free(connData->cgiPrivData); - return HTTPD_CGI_DONE; - }else{ - return HTTPD_CGI_MORE; - } + if (postCounter == connData->postLen){ + httpdSend(connData, "Finished uploading", -1); + postCounter=0; + return HTTPD_CGI_DONE; + } else { + return HTTPD_CGI_MORE; } - return HTTPD_CGI_DONE; } - diff --git a/user/cgi.h b/user/cgi.h index 8b3c8b2..a1cc7a3 100644 --- a/user/cgi.h +++ b/user/cgi.h @@ -7,6 +7,6 @@ int cgiLed(HttpdConnData *connData); int tplLed(HttpdConnData *connData, char *token, void **arg); int cgiReadFlash(HttpdConnData *connData); int tplCounter(HttpdConnData *connData, char *token, void **arg); -int updateWeb(HttpdConnData *connData); +int cgiUploadEspfs(HttpdConnData *connData); #endif \ No newline at end of file diff --git a/user/user_main.c b/user/user_main.c index 3ce7d77..433ccbd 100644 --- a/user/user_main.c +++ b/user/user_main.c @@ -55,7 +55,7 @@ HttpdBuiltInUrl builtInUrls[]={ {"/led.tpl", cgiEspFsTemplate, tplLed}, {"/index.tpl", cgiEspFsTemplate, tplCounter}, {"/led.cgi", cgiLed, NULL}, - {"/updateweb.cgi", updateWeb, NULL}, + {"/updateweb.cgi", cgiUploadEspfs, NULL}, //Routines to make the /wifi URL and everything beneath it work.