;
- close(IF);
- my $cnt = join("", @fc);
-
- if( $name =~ /\.html$/ )
- {
- if( ! ( $flags & 2 ) )
- {
- $cnt = "$head$cnt";
- }
- else
- {
- printf("TODO: prepend headers to GZipped HTML content!\n");
- }
- }
-
- $name .= chr(0);
- $name .= chr(0) while( (length($name) & 3) != 0 );
-
- my $size = length($cnt);
-
- $espfs .= "ESfs";
- $espfs .= chr($flags);
- $espfs .= chr($compression);
- $espfs .= chr( length($name) & 255 );
- $espfs .= chr( length($name) / 256 );
- $espfs .= chr( $size & 255 );
- $espfs .= chr( ( $size / 0x100 ) & 255 );
- $espfs .= chr( ( $size / 0x10000 ) & 255 );
- $espfs .= chr( ( $size / 0x1000000 ) & 255 );
- $espfs .= chr( $size & 255 );
- $espfs .= chr( ( $size / 0x100 ) & 255 );
- $espfs .= chr( ( $size / 0x10000 ) & 255 );
- $espfs .= chr( ( $size / 0x1000000 ) & 255 );
-
- $espfs .= $name;
-
-
-
- $cnt .= chr(0) while( (length($cnt) & 3) != 0 );
- $espfs .= $cnt;
-}
-
-$espfs .= "ESfs";
-$espfs .= chr(1);
-for(my $i=0; $i < 11; $i++)
-{
- $espfs .= chr(0);
-}
-
-open FH, ">", $out or die "Can't open file for write, $!";
-print FH $espfs;
-close(FH);
-
-
-exit(0);
-
-sub read_dir_structure
-{
- my ($dir, $base) = @_;
-
- my @files;
-
- opendir my $dh, $dir or die "Could not open '$dir' for reading: $!\n";
-
- while (my $file = readdir $dh) {
- if ($file eq '.' or $file eq '..') {
- next;
- }
-
- my $path = "$dir/$file";
- if( -d "$path" )
- {
- my @sd = read_dir_structure($path, "$base/$file");
- push @files, @sd ;
- }
- else
- {
- push @files, "$base/$file";
- }
- }
-
- close( $dh );
-
- $_ =~ s/^\/// for(@files);
- return @files;
-}
diff --git a/esp-link/cgiwebserversetup.c b/esp-link/cgiwebserversetup.c
index 2a25950..1d1d2e6 100644
--- a/esp-link/cgiwebserversetup.c
+++ b/esp-link/cgiwebserversetup.c
@@ -9,8 +9,9 @@
#include "config.h"
#include "web-server.h"
-int upload_offset = 0; // flash offset where to store page upload
-int html_header_len = 0; // HTML header length (for uploading HTML files)
+int header_position = 0; // flash offset of the file header
+int upload_position = 0; // flash offset where to store page upload
+int html_header_len = 0; // length of the HTML header added to the file
// this is the header to add if user uploads HTML file
const char * HTML_HEADER = "esp-link"
@@ -18,127 +19,157 @@ const char * HTML_HEADER = "esp-link
" ";
+// this method is for flash writing and erasing the page
+// write is incremental, so whenever a page border is reached, the next page will be erased
+int ICACHE_FLASH_ATTR webServerSetupWriteFlash( int addr, void * data, int length )
+{
+ int end_addr = addr + length;
+ if( end_addr >= getUserPageSectionEnd() )
+ {
+ os_printf("No more space in the flash!\n");
+ return 1;
+ }
+
+ void * free_ptr = 0;
+ if(( length & 3 ) != 0 ) // ESP8266 always writes 4 bytes, so the remaining ones should be oxFF-ed out
+ {
+ free_ptr = os_malloc(length + 4);
+ os_memset(free_ptr, 0xFF, length + 4);
+ os_memcpy(free_ptr, data, length);
+ data = free_ptr;
+ }
+
+ int ptr = 0;
+ while( addr < end_addr )
+ {
+ if (addr % SPI_FLASH_SEC_SIZE == 0){
+ spi_flash_erase_sector(addr/SPI_FLASH_SEC_SIZE);
+ }
+
+ int max = (addr | (SPI_FLASH_SEC_SIZE - 1)) + 1;
+ int len = end_addr - addr;
+ if( end_addr > max )
+ len = max - addr;
+
+ spi_flash_write( addr, (uint32_t *)((char *)data + ptr), len );
+ ptr += len;
+ addr += len;
+ }
+ if( free_ptr != 0 )
+ os_free(free_ptr);
+ return 0;
+}
+
+// debug code
+void ICACHE_FLASH_ATTR dumpFlash( int end )
+{
+ int dump = getUserPageSectionStart();
+ while( dump < end )
+ {
+ char buffer[16];
+ spi_flash_read(dump, (uint32_t *)buffer, sizeof(buffer));
+ char dmpstr[sizeof(buffer)*3];
+ os_sprintf(dmpstr, "%06X: ", dump);
+ for(int i=0; i < sizeof(buffer); i++ )
+ os_sprintf(dmpstr + os_strlen(dmpstr), "%02X ", buffer[i]);
+ os_printf("%s\n", dmpstr);
+ dump += sizeof(buffer);
+ }
+}
+
// multipart callback for uploading user defined pages
int ICACHE_FLASH_ATTR webServerSetupMultipartCallback(MultipartCmd cmd, char *data, int dataLen, int position)
{
switch(cmd)
{
+ case FILE_UPLOAD_START:
+ upload_position = getUserPageSectionStart();
+ header_position = upload_position;
+ break;
case FILE_START:
- upload_offset = 0;
- html_header_len = 0;
- // simple HTML file
- if( ( dataLen > 5 ) && ( os_strcmp(data + dataLen - 5, ".html") == 0 ) ) // if the file ends with .html, wrap into an espfs image
{
- // write the start block on esp-fs
- int spi_flash_addr = getUserPageSectionStart();
- spi_flash_erase_sector(spi_flash_addr/SPI_FLASH_SEC_SIZE);
+ html_header_len = 0;
+
+ // write the starting block on esp-fs
EspFsHeader hdr;
hdr.magic = 0xFFFFFFFF; // espfs magic is invalid during upload
hdr.flags = 0;
hdr.compression = 0;
-
+
int len = dataLen + 1;
while(( len & 3 ) != 0 )
len++;
-
+
hdr.nameLen = len;
hdr.fileLenComp = hdr.fileLenDecomp = 0xFFFFFFFF;
- spi_flash_write( spi_flash_addr + upload_offset, (uint32_t *)(&hdr), sizeof(EspFsHeader) );
- upload_offset += sizeof(EspFsHeader);
-
+ header_position = upload_position;
+ if( webServerSetupWriteFlash( upload_position, (uint32_t *)(&hdr), sizeof(EspFsHeader) ) )
+ return 1;
+ upload_position += sizeof(EspFsHeader);
+
char nameBuf[len];
os_memset(nameBuf, 0, len);
os_memcpy(nameBuf, data, dataLen);
- spi_flash_write( spi_flash_addr + upload_offset, (uint32_t *)(nameBuf), len );
- upload_offset += len;
-
- html_header_len = os_strlen(HTML_HEADER) & ~3; // upload only 4 byte aligned part
- char buf[html_header_len];
- os_memcpy(buf, HTML_HEADER, html_header_len);
- spi_flash_write( spi_flash_addr + upload_offset, (uint32_t *)(buf), html_header_len );
- upload_offset += html_header_len;
- }
- break;
- case FILE_DATA:
- if(( position < 4 ) && (upload_offset == 0)) // for espfs images check the magic number
- {
- for(int p = position; p < 4; p++ )
+ if( webServerSetupWriteFlash( upload_position, (uint32_t *)(nameBuf), len ) )
+ return 1;
+ upload_position += len;
+
+ // add header to HTML files
+ if( ( dataLen > 5 ) && ( os_strcmp(data + dataLen - 5, ".html") == 0 ) ) // if the file ends with .html, wrap into an espfs image
{
- if( data[p - position] != ((ESPFS_MAGIC >> (p * 8) ) & 255 ) )
- {
- os_printf("Not an espfs image!\n");
+ html_header_len = os_strlen(HTML_HEADER) & ~3; // upload only 4 byte aligned part
+ char buf[html_header_len];
+ os_memcpy(buf, HTML_HEADER, html_header_len);
+ if( webServerSetupWriteFlash( upload_position, (uint32_t *)(buf), html_header_len ) )
return 1;
- }
- data[p - position] = 0xFF; // espfs magic is invalid during upload
+ upload_position += html_header_len;
}
}
-
- int spi_flash_addr = getUserPageSectionStart() + upload_offset + position;
- int spi_flash_end_addr = spi_flash_addr + dataLen;
- if( spi_flash_end_addr + dataLen >= getUserPageSectionEnd() )
- {
- os_printf("No more space in the flash!\n");
+ break;
+ case FILE_DATA:
+ if( webServerSetupWriteFlash( upload_position, data, dataLen ) )
return 1;
- }
-
- int ptr = 0;
- while( spi_flash_addr < spi_flash_end_addr )
+ upload_position += dataLen;
+ break;
+ case FILE_DONE:
{
- if (spi_flash_addr % SPI_FLASH_SEC_SIZE == 0){
- spi_flash_erase_sector(spi_flash_addr/SPI_FLASH_SEC_SIZE);
+ // write padding after the file
+ uint8_t pad_cnt = (4 - position) & 3;
+ if( pad_cnt ) {
+ uint32_t pad = 0;
+ if( webServerSetupWriteFlash( upload_position, &pad, pad_cnt ) )
+ return 1;
+ upload_position += pad_cnt;
}
-
- int max = (spi_flash_addr | (SPI_FLASH_SEC_SIZE - 1)) + 1;
- int len = spi_flash_end_addr - spi_flash_addr;
- if( spi_flash_end_addr > max )
- len = max - spi_flash_addr;
-
- spi_flash_write( spi_flash_addr, (uint32_t *)(data + ptr), len );
- ptr += len;
- spi_flash_addr += len;
+
+ EspFsHeader hdr;
+ hdr.magic = ESPFS_MAGIC;
+ hdr.fileLenComp = hdr.fileLenDecomp = position + html_header_len;
+
+ // restore ESPFS magic
+ spi_flash_write( header_position + ((char *)&hdr.magic - (char*)&hdr), (uint32_t *)&hdr.magic, sizeof(uint32_t) );
+ // set file size
+ spi_flash_write( header_position + ((char *)&hdr.fileLenComp - (char*)&hdr), (uint32_t *)&hdr.fileLenComp, sizeof(uint32_t) );
+ spi_flash_write( header_position + ((char *)&hdr.fileLenDecomp - (char*)&hdr), (uint32_t *)&hdr.fileLenDecomp, sizeof(uint32_t) );
}
-
break;
- case FILE_DONE:
+ case FILE_UPLOAD_DONE:
{
- if( html_header_len != 0 )
- {
- // write the terminating block on esp-fs
- int spi_flash_addr = getUserPageSectionStart() + upload_offset + position;
+ // write the termination block
+
+ EspFsHeader hdr;
+ hdr.magic = ESPFS_MAGIC;
+ hdr.flags = 1;
+ hdr.compression = 0;
+ hdr.nameLen = 0;
+ hdr.fileLenComp = hdr.fileLenDecomp = 0;
+
+ if( webServerSetupWriteFlash( upload_position, (uint32_t *)(&hdr), sizeof(EspFsHeader) ) )
+ return 1;
+ upload_position += sizeof(EspFsHeader);
- uint32_t pad = 0;
- uint8_t pad_cnt = (4 - position) & 3;
- if( pad_cnt )
- spi_flash_write( spi_flash_addr, &pad, pad_cnt );
-
- spi_flash_addr += pad_cnt;
-
- // create ESPFS image
- EspFsHeader hdr;
- hdr.magic = ESPFS_MAGIC;
- hdr.flags = 1;
- hdr.compression = 0;
- hdr.nameLen = 0;
- hdr.fileLenComp = hdr.fileLenDecomp = 0;
-
- spi_flash_write( spi_flash_addr, (uint32_t *)(&hdr), sizeof(EspFsHeader) );
-
- uint32_t totallen = html_header_len + position;
-
- // restore ESPFS magic
- spi_flash_write( (int)getUserPageSectionStart(), (uint32_t *)&hdr.magic, sizeof(uint32_t) );
- // set file size
- spi_flash_write( (int)getUserPageSectionStart() + 8, &totallen, sizeof(uint32_t) );
- spi_flash_write( (int)getUserPageSectionStart() + 12, &totallen, sizeof(uint32_t) );
- }
- else
- {
- // set espfs magic (set it valid)
- uint32_t magic = ESPFS_MAGIC;
- spi_flash_write( (int)getUserPageSectionStart(), (uint32_t *)&magic, sizeof(uint32_t) );
- }
WEB_Init(); // reload the content
}
break;
diff --git a/html/web-server.html b/html/web-server.html
index a5a1d41..8d60ee9 100644
--- a/html/web-server.html
+++ b/html/web-server.html
@@ -8,7 +8,7 @@
the measurement data.
diff --git a/httpd/multipart.c b/httpd/multipart.c
index d709798..427bc70 100644
--- a/httpd/multipart.c
+++ b/httpd/multipart.c
@@ -4,7 +4,7 @@
#include "multipart.h"
#include "cgi.h"
-#define BOUNDARY_SIZE 100
+#define BOUNDARY_SIZE 128
typedef enum {
STATE_SEARCH_BOUNDARY = 0, // state: searching multipart boundary
@@ -227,6 +227,7 @@ int ICACHE_FLASH_ATTR multipartProcessData(MultipartCtx * context, char * bounda
context->boundaryBufferPtr -= dataSize;
os_memcpy(context->boundaryBuffer, context->boundaryBuffer + dataSize, context->boundaryBufferPtr);
}
+
return 0;
}
@@ -253,6 +254,9 @@ int ICACHE_FLASH_ATTR multipartProcess(MultipartCtx * context, HttpdConnData * c
context->state = STATE_SEARCH_BOUNDARY;
multipartAllocBoundaryBuffer(context);
+
+ if( context->callBack( FILE_UPLOAD_START, NULL, 0, context->position ) ) // start uploading files
+ context->state = STATE_ERROR;
}
if( context->state != STATE_ERROR )
@@ -281,6 +285,8 @@ int ICACHE_FLASH_ATTR multipartProcess(MultipartCtx * context, HttpdConnData * c
// this is the last package, process the remaining data
if( multipartProcessData(context, post->multipartBoundary, NULL, 0, 1) )
context->state = STATE_ERROR;
+ else if( context->callBack( FILE_UPLOAD_DONE, NULL, 0, context->position ) ) // done with files
+ context->state = STATE_ERROR;
}
multipartFreeBoundaryBuffer( context );
diff --git a/httpd/multipart.h b/httpd/multipart.h
index 87a4bb2..a1205cd 100644
--- a/httpd/multipart.h
+++ b/httpd/multipart.h
@@ -4,9 +4,11 @@
#include
typedef enum {
- FILE_START, // multipart: the start of a new file
- FILE_DATA, // multipart: file data
- FILE_DONE, // multipart: file end
+ FILE_UPLOAD_START, // multipart: uploading files started
+ FILE_START, // multipart: the start of a new file (can be more)
+ FILE_DATA, // multipart: file data
+ FILE_DONE, // multipart: file end
+ FILE_UPLOAD_DONE, // multipart: finished for all files
} MultipartCmd;
// multipart callback