Replaced the multipart espfs flashing with the version from @billprozac and tweaked a little (untested)

v0.9.0
Ben Pirt 10 years ago
parent 4ee2d75977
commit c2a02f28ea
  1. 3
      include/httpdconfig.h
  2. 166
      user/cgi.c
  3. 2
      user/cgi.h
  4. 2
      user/user_main.c

@ -3,7 +3,8 @@
#define EFS_HEATSHRINK #define EFS_HEATSHRINK
//Pos of esp fs in flash //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. //If you want, you can define a realm for the authentication system.
//#define HTTP_AUTH_REALM "MyRealm" //#define HTTP_AUTH_REALM "MyRealm"

@ -22,6 +22,7 @@ flash as a binary. Also handles the hit counter on the main page.
#include "io.h" #include "io.h"
#include <ip_addr.h> #include <ip_addr.h>
#include "espmissingincludes.h" #include "espmissingincludes.h"
#include "../include/httpdconfig.h"
//cause I can't be bothered to write an ioGetLed() //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; if (*pos>=0x40200000+(512*1024)) return HTTPD_CGI_DONE; else return HTTPD_CGI_MORE;
} }
#define LOOKING_FOR_SECTION 1 uint32_t postCounter = 0;
#define CHECKING_HEADERS 2
#define IN_DATA 3
typedef struct updateState_t { int ICACHE_FLASH_ATTR cgiUploadEspfs(HttpdConnData *connData) {
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;
if (connData->conn==NULL) { if (connData->conn==NULL) {
//Connection aborted. Clean up. //Connection aborted. Clean up.
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }
if(connData->requestType == GET){ SpiFlashOpResult ret;
httpdStartResponse(connData, 200); int x;
httpdHeader(connData, "Content-Length", "135"); uint32_t flashOff = ESPFS_POS;
httpdEndHeaders(connData); uint32_t flashSize = ESPFS_SIZE;
httpdSend(connData, "<html><body><form method=\"POST\" enctype=\"multipart/form-data\"><input type=\"file\" name=\"file\"><input type=\"submit\"></form></body></html>", 135);
}else if(connData->requestType == POST){ //If this is the first time, erase the flash sector
if(connData->postReceived == connData->postBuffLen){ if (postCounter == 0){
//it's the first time this handler has been called for this request os_printf("Erasing flash at 0x%x...\n", flashOff);
connData->cgiPrivData = (int*)os_malloc(sizeof(updateState_t)); // Which segment are we flashing?
state = connData->cgiPrivData; for (x=0; x<flashSize; x+=4096){
state->step = LOOKING_FOR_SECTION; spi_flash_erase_sector((flashOff+x)/0x1000);
}else{
state = connData->cgiPrivData;
} }
os_printf("Done erasing.\n");
}
char *b; // Because we get sent 1k chunks until the end, if data is less than 1k, we pad it as it must be the end...right???
char *p; if (connData->postBuffSize==1024){
char * end = connData->postBuff + connData->postBuffLen; ret=spi_flash_write((flashOff + postCounter), (uint32 *)connData->postBuff, 1024);
for(b = connData->postBuff; b < end; b++){ os_printf("Flash return %d\n", ret);
if(state->step == LOOKING_FOR_SECTION){ } else {
if((p = bin_strstr(b, connData->multipartBoundary, connData->postBuffLen - (b - connData->postBuff), -1)) != NULL){ // 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
os_printf("Found section\r\n"); char *postBuff = (char*)os_zalloc(1024);
// We've found one of the sections, now make sure it's the file os_printf("Mallocced buffer of 1024 bytes of last chunk.\n");
b = p + strlen(connData->multipartBoundary) + 2; os_memcpy(postBuff, connData->postBuff, connData->postBuffSize);
state->step = CHECKING_HEADERS; ret=spi_flash_write((flashOff + postCounter), (uint32 *)postBuff, 1024);
}else{ os_printf("Flash return %d\n", ret);
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;
}
} }
return HTTPD_CGI_DONE;
}
// 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));
if (postCounter == connData->postLen){
httpdSend(connData, "Finished uploading", -1);
postCounter=0;
return HTTPD_CGI_DONE;
} else {
return HTTPD_CGI_MORE;
}
}

@ -7,6 +7,6 @@ int cgiLed(HttpdConnData *connData);
int tplLed(HttpdConnData *connData, char *token, void **arg); int tplLed(HttpdConnData *connData, char *token, void **arg);
int cgiReadFlash(HttpdConnData *connData); int cgiReadFlash(HttpdConnData *connData);
int tplCounter(HttpdConnData *connData, char *token, void **arg); int tplCounter(HttpdConnData *connData, char *token, void **arg);
int updateWeb(HttpdConnData *connData); int cgiUploadEspfs(HttpdConnData *connData);
#endif #endif

@ -55,7 +55,7 @@ HttpdBuiltInUrl builtInUrls[]={
{"/led.tpl", cgiEspFsTemplate, tplLed}, {"/led.tpl", cgiEspFsTemplate, tplLed},
{"/index.tpl", cgiEspFsTemplate, tplCounter}, {"/index.tpl", cgiEspFsTemplate, tplCounter},
{"/led.cgi", cgiLed, NULL}, {"/led.cgi", cgiLed, NULL},
{"/updateweb.cgi", updateWeb, NULL}, {"/updateweb.cgi", cgiUploadEspfs, NULL},
//Routines to make the /wifi URL and everything beneath it work. //Routines to make the /wifi URL and everything beneath it work.

Loading…
Cancel
Save