improvements in template engine and routes
This commit is contained in:
+10
-2
@@ -7,8 +7,8 @@ THISDIR:=$(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
|
||||
#Default options. If you want to change them, please create ../esphttpdconfig.mk with the options you want in it.
|
||||
GZIP_COMPRESSION ?= no
|
||||
COMPRESS_W_YUI ?= no
|
||||
GZIP_COMPRESSION ?= yes
|
||||
COMPRESS_W_YUI ?= yes
|
||||
YUI-COMPRESSOR ?= /usr/bin/yui-compressor
|
||||
USE_HEATSHRINK ?= yes
|
||||
HTTPD_WEBSOCKETS ?= yes
|
||||
@@ -18,6 +18,11 @@ HTTPD_MAX_CONNECTIONS ?= 4
|
||||
#For FreeRTOS
|
||||
HTTPD_STACKSIZE ?= 2048
|
||||
|
||||
# this works only if you also enable YUI-COMPRESSOR
|
||||
HTML-MINIFIER ?= html-minifier -c html-minifier-conf.json
|
||||
COMPRESS_W_HTMLMINIFIER ?= yes
|
||||
|
||||
|
||||
# Output directors to store intermediate compiled files
|
||||
# relative to the project directory
|
||||
BUILD_BASE = build
|
||||
@@ -162,6 +167,9 @@ ifeq ("$(COMPRESS_W_YUI)","yes")
|
||||
$(Q) echo "Compression assets with yui-compressor. This may take a while..."
|
||||
$(Q) for file in `find html_compressed -type f -name "*.js"`; do $(YUI-COMPRESSOR) --type js $$file -o $$file; done
|
||||
$(Q) for file in `find html_compressed -type f -name "*.css"`; do $(YUI-COMPRESSOR) --type css $$file -o $$file; done
|
||||
ifeq ("$(COMPRESS_W_HTMLMINIFIER)","yes")
|
||||
$(Q) for file in `find html_compressed -type f -name "*.html" -o -name "*.htm" -o -name "*.tpl"`; do $(HTML-MINIFIER) $$file -o $$file; done
|
||||
endif
|
||||
$(Q) awk "BEGIN {printf \"YUI compression ratio was: %.2f%%\\n\", (`du -b -s html_compressed/ | sed 's/\([0-9]*\).*/\1/'`/`du -b -s ../html/ | sed 's/\([0-9]*\).*/\1/'`)*100}"
|
||||
# mkespfsimage will compress html, css, svg and js files with gzip by default if enabled
|
||||
# override with -g cmdline parameter
|
||||
|
||||
@@ -86,10 +86,10 @@ static const ICACHE_RODATA_ATTR MimeMap mimeTypes[]={
|
||||
};
|
||||
|
||||
//Returns a static char* to a mime type for a given url to a file.
|
||||
const char ICACHE_FLASH_ATTR *httpdGetMimetype(char *url) {
|
||||
const char ICACHE_FLASH_ATTR *httpdGetMimetype(const char *url) {
|
||||
int i=0;
|
||||
//Go find the extension
|
||||
char *ext=url+(strlen(url)-1);
|
||||
const char *ext=url+(strlen(url)-1);
|
||||
while (ext!=url && *ext!='.') ext--;
|
||||
if (*ext=='.') ext++;
|
||||
|
||||
@@ -99,7 +99,7 @@ const char ICACHE_FLASH_ATTR *httpdGetMimetype(char *url) {
|
||||
}
|
||||
|
||||
//Looks up the connData info for a specific connection
|
||||
static HttpdConnData ICACHE_FLASH_ATTR *httpdFindConnData(ConnTypePtr conn, char *remIp, int remPort) {
|
||||
static HttpdConnData ICACHE_FLASH_ATTR *httpdFindConnData(ConnTypePtr conn, const char *remIp, int remPort) {
|
||||
for (int i=0; i<HTTPD_MAX_CONNECTIONS; i++) {
|
||||
if (connData[i] && connData[i]->remote_port == remPort &&
|
||||
memcmp(connData[i]->remote_ip, remIp, 4) == 0) {
|
||||
@@ -154,7 +154,7 @@ int ICACHE_FLASH_ATTR httpdUrlDecode(char *val, int valLen, char *ret, int retLe
|
||||
esced=2;
|
||||
} else if (esced==2) {
|
||||
escVal+=httpdHexVal(val[s]);
|
||||
ret[d++]=escVal;
|
||||
ret[d++]=(char)escVal;
|
||||
esced=0;
|
||||
} else if (val[s]=='%') {
|
||||
esced=1;
|
||||
@@ -481,7 +481,7 @@ void ICACHE_FLASH_ATTR httpdSentCb(ConnTypePtr rconn, char *remIp, int remPort)
|
||||
httpdCgiIsDone(conn);
|
||||
}
|
||||
if (r==HTTPD_CGI_NOTFOUND || r==HTTPD_CGI_AUTHENTICATED) {
|
||||
httpd_printf("ERROR! CGI fn returns code %d after sending data! Bad CGI!\n", r);
|
||||
error("ERROR! CGI fn returns code %d after sending data! Bad CGI!", r);
|
||||
httpdCgiIsDone(conn);
|
||||
}
|
||||
httpdFlushSendBuffer(conn);
|
||||
@@ -514,6 +514,7 @@ static void ICACHE_FLASH_ATTR httpdProcessRequest(HttpdConnData *conn) {
|
||||
conn->cgiData=NULL;
|
||||
conn->cgi=builtInUrls[i].cgiCb;
|
||||
conn->cgiArg=builtInUrls[i].cgiArg;
|
||||
conn->cgiArg2=builtInUrls[i].cgiArg2;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
|
||||
@@ -27,7 +27,8 @@ static const char *gzipNonSupportedMessage = "HTTP/1.0 501 Not implemented\r\n"
|
||||
"Your browser does not accept gzip-compressed data.\r\n";
|
||||
|
||||
|
||||
EspFsFile *tryOpenIndex(const char *path)
|
||||
|
||||
static EspFsFile *tryOpenIndex_do(const char *path, const char *indexname)
|
||||
{
|
||||
// Try appending index.tpl
|
||||
char fname[100];
|
||||
@@ -41,17 +42,38 @@ EspFsFile *tryOpenIndex(const char *path)
|
||||
}
|
||||
|
||||
// add index
|
||||
strcpy(fname + url_len, "index.tpl");
|
||||
strcpy(fname + url_len, indexname);
|
||||
|
||||
return espFsOpen(fname);
|
||||
}
|
||||
|
||||
|
||||
EspFsFile *tryOpenIndex(const char *path)
|
||||
{
|
||||
EspFsFile * file;
|
||||
|
||||
//This is a catch-all cgi function. It takes the url passed to it, looks up the corresponding
|
||||
//path in the filesystem and if it exists, passes the file through. This simulates what a normal
|
||||
//webserver would do with static files.
|
||||
int ICACHE_FLASH_ATTR cgiEspFsHook(HttpdConnData *connData)
|
||||
// if there is a dot in the file, assume it's an extension
|
||||
// no point in trying to find index in this case, abort.
|
||||
if (strchr(path, '.') != NULL) return NULL;
|
||||
|
||||
|
||||
// try index.html
|
||||
file = tryOpenIndex_do(path, "index.html");
|
||||
if (file != NULL) return file;
|
||||
|
||||
// try index.htm
|
||||
file = tryOpenIndex_do(path, "index.htm");
|
||||
if (file != NULL) return file;
|
||||
|
||||
// try index.tpl
|
||||
file = tryOpenIndex_do(path, "index.tpl");
|
||||
if (file != NULL) return file;
|
||||
|
||||
return NULL; // failed to guess the right name
|
||||
}
|
||||
|
||||
|
||||
int ICACHE_FLASH_ATTR serveStaticFile(HttpdConnData *connData, const char* filepath)
|
||||
{
|
||||
EspFsFile *file = connData->cgiData;
|
||||
int len;
|
||||
@@ -65,18 +87,21 @@ int ICACHE_FLASH_ATTR cgiEspFsHook(HttpdConnData *connData)
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
|
||||
// invalid call.
|
||||
if (filepath == NULL) {
|
||||
printf("serveStaticFile called with NULL path!\n");
|
||||
return HTTPD_CGI_NOTFOUND;
|
||||
}
|
||||
|
||||
if (file == NULL) {
|
||||
//First call to this cgi. Open the file so we can read it.
|
||||
file = espFsOpen(connData->url);
|
||||
file = espFsOpen(filepath);
|
||||
if (file == NULL) {
|
||||
|
||||
// file not found
|
||||
file = tryOpenIndex(connData->url);
|
||||
|
||||
if (file == NULL) {
|
||||
return HTTPD_CGI_NOTFOUND;
|
||||
}
|
||||
|
||||
// If this is a folder, look for index file
|
||||
file = tryOpenIndex(filepath);
|
||||
if (file == NULL) return HTTPD_CGI_NOTFOUND;
|
||||
}
|
||||
|
||||
// The gzip checking code is intentionally without #ifdefs because checking
|
||||
@@ -100,7 +125,7 @@ int ICACHE_FLASH_ATTR cgiEspFsHook(HttpdConnData *connData)
|
||||
|
||||
connData->cgiData = file;
|
||||
httpdStartResponse(connData, 200);
|
||||
httpdHeader(connData, "Content-Type", httpdGetMimetype(connData->url));
|
||||
httpdHeader(connData, "Content-Type", httpdGetMimetype(filepath));
|
||||
if (isGzip) {
|
||||
httpdHeader(connData, "Content-Encoding", "gzip");
|
||||
}
|
||||
@@ -122,6 +147,21 @@ int ICACHE_FLASH_ATTR cgiEspFsHook(HttpdConnData *connData)
|
||||
}
|
||||
|
||||
|
||||
|
||||
//This is a catch-all cgi function. It takes the url passed to it, looks up the corresponding
|
||||
//path in the filesystem and if it exists, passes the file through. This simulates what a normal
|
||||
//webserver would do with static files.
|
||||
int ICACHE_FLASH_ATTR cgiEspFsHook(HttpdConnData *connData)
|
||||
{
|
||||
return serveStaticFile(connData, connData->url);
|
||||
}
|
||||
|
||||
|
||||
int ICACHE_FLASH_ATTR cgiEspFsFile(HttpdConnData *connData)
|
||||
{
|
||||
return serveStaticFile(connData, connData->cgiArg);
|
||||
}
|
||||
|
||||
//cgiEspFsTemplate can be used as a template.
|
||||
|
||||
#define TEMPLATE_CHUNK 1024
|
||||
@@ -164,18 +204,25 @@ int ICACHE_FLASH_ATTR cgiEspFsTemplate(HttpdConnData *connData)
|
||||
|
||||
tpd->chunk_resume = false;
|
||||
|
||||
tpd->file = espFsOpen(connData->url);
|
||||
|
||||
const char *filepath = connData->url;
|
||||
|
||||
// check for custom template URL
|
||||
if (connData->cgiArg2 != NULL) {
|
||||
filepath = connData->cgiArg2;
|
||||
printf("Using filepath %s\n", filepath);
|
||||
}
|
||||
|
||||
tpd->file = espFsOpen(filepath);
|
||||
if (tpd->file == NULL) {
|
||||
|
||||
// file not found
|
||||
tpd->file = tryOpenIndex(connData->url);
|
||||
|
||||
// If this is a folder, look for index file
|
||||
tpd->file = tryOpenIndex(filepath);
|
||||
if (tpd->file == NULL) {
|
||||
espFsClose(tpd->file);
|
||||
free(tpd);
|
||||
return HTTPD_CGI_NOTFOUND;
|
||||
}
|
||||
}
|
||||
|
||||
tpd->tplArg = NULL;
|
||||
tpd->tokenPos = -1;
|
||||
if (espFsFlags(tpd->file) & FLAG_GZIP) {
|
||||
@@ -186,7 +233,7 @@ int ICACHE_FLASH_ATTR cgiEspFsTemplate(HttpdConnData *connData)
|
||||
}
|
||||
connData->cgiData = tpd;
|
||||
httpdStartResponse(connData, 200);
|
||||
httpdHeader(connData, "Content-Type", httpdGetMimetype(connData->url));
|
||||
httpdHeader(connData, "Content-Type", httpdGetMimetype(filepath));
|
||||
httpdEndHeaders(connData);
|
||||
return HTTPD_CGI_MORE;
|
||||
}
|
||||
|
||||
+83
-75
@@ -39,15 +39,15 @@ It's written for use with httpd, but doesn't need to be used as such.
|
||||
#include "heatshrink_decoder.h"
|
||||
#endif
|
||||
|
||||
static char* espFsData = NULL;
|
||||
static const char* espFsData = NULL;
|
||||
|
||||
|
||||
struct EspFsFile {
|
||||
EspFsHeader *header;
|
||||
const EspFsHeader *header;
|
||||
char decompressor;
|
||||
int32_t posDecomp;
|
||||
char *posStart;
|
||||
char *posComp;
|
||||
const char *posStart;
|
||||
const char *posComp;
|
||||
void *decompData;
|
||||
};
|
||||
|
||||
@@ -67,9 +67,10 @@ Accessing the flash through the mem emulation at 0x40200000 is a bit hairy: All
|
||||
a memory exception, crashing the program.
|
||||
*/
|
||||
|
||||
EspFsInitResult ICACHE_FLASH_ATTR espFsInit(void *flashAddress) {
|
||||
if((uint32_t)flashAddress > 0x40200000) {
|
||||
flashAddress = (void*)((uint32_t)flashAddress-0x40200000);
|
||||
EspFsInitResult ICACHE_FLASH_ATTR espFsInit(const void *flashAddress)
|
||||
{
|
||||
if ((uint32_t)flashAddress > 0x40200000) {
|
||||
flashAddress = (void*)((uint32_t)flashAddress - 0x40200000);
|
||||
}
|
||||
|
||||
// base address must be aligned to 4 bytes
|
||||
@@ -84,7 +85,7 @@ EspFsInitResult ICACHE_FLASH_ATTR espFsInit(void *flashAddress) {
|
||||
return ESPFS_INIT_RESULT_NO_IMAGE;
|
||||
}
|
||||
|
||||
espFsData = (char *)flashAddress;
|
||||
espFsData = (const char *)flashAddress;
|
||||
return ESPFS_INIT_RESULT_OK;
|
||||
}
|
||||
|
||||
@@ -93,20 +94,22 @@ EspFsInitResult ICACHE_FLASH_ATTR espFsInit(void *flashAddress) {
|
||||
|
||||
//ToDo: perhaps memcpy also does unaligned accesses?
|
||||
#ifdef __ets__
|
||||
void ICACHE_FLASH_ATTR readFlashUnaligned(char *dst, char *src, int len) {
|
||||
void ICACHE_FLASH_ATTR readFlashUnaligned(char *dst, char *src, int len)
|
||||
{
|
||||
uint8_t src_offset = ((uint32_t)src) & 3;
|
||||
uint32_t src_address = ((uint32_t)src) - src_offset;
|
||||
|
||||
uint32_t tmp_buf[len/4 + 2];
|
||||
spi_flash_read((uint32)src_address, (uint32*)tmp_buf, len+src_offset);
|
||||
memcpy(dst, ((uint8_t*)tmp_buf)+src_offset, len);
|
||||
uint32_t tmp_buf[len / 4 + 2];
|
||||
spi_flash_read((uint32)src_address, (uint32*)tmp_buf, len + src_offset);
|
||||
memcpy(dst, ((uint8_t*)tmp_buf) + src_offset, len);
|
||||
}
|
||||
#else
|
||||
#define readFlashUnaligned memcpy
|
||||
#endif
|
||||
|
||||
// Returns flags of opened file.
|
||||
int ICACHE_FLASH_ATTR espFsFlags(EspFsFile *fh) {
|
||||
int ICACHE_FLASH_ATTR espFsFlags(EspFsFile *fh)
|
||||
{
|
||||
if (fh == NULL) {
|
||||
httpd_printf("File handle not ready\n");
|
||||
return -1;
|
||||
@@ -118,61 +121,64 @@ int ICACHE_FLASH_ATTR espFsFlags(EspFsFile *fh) {
|
||||
}
|
||||
|
||||
//Open a file and return a pointer to the file desc struct.
|
||||
EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
|
||||
EspFsFile ICACHE_FLASH_ATTR *espFsOpen(const char *fileName)
|
||||
{
|
||||
printf("Open file %s\n", fileName);
|
||||
|
||||
if (espFsData == NULL) {
|
||||
httpd_printf("Call espFsInit first!\n");
|
||||
return NULL;
|
||||
}
|
||||
char *p=espFsData;
|
||||
char *hpos;
|
||||
const char *p = espFsData;
|
||||
const char *hpos;
|
||||
char namebuf[256];
|
||||
EspFsHeader h;
|
||||
EspFsFile *r;
|
||||
//Strip initial slashes
|
||||
while(fileName[0]=='/') fileName++;
|
||||
while (fileName[0] == '/') fileName++;
|
||||
//Go find that file!
|
||||
while(1) {
|
||||
hpos=p;
|
||||
while (1) {
|
||||
hpos = p;
|
||||
//Grab the next file header.
|
||||
spi_flash_read((uint32)p, (uint32*)&h, sizeof(EspFsHeader));
|
||||
|
||||
if (h.magic!=ESPFS_MAGIC) {
|
||||
if (h.magic != ESPFS_MAGIC) {
|
||||
httpd_printf("Magic mismatch. EspFS image broken.\n");
|
||||
return NULL;
|
||||
}
|
||||
if (h.flags&FLAG_LASTFILE) {
|
||||
httpd_printf("End of image.\n");
|
||||
if (h.flags & FLAG_LASTFILE) {
|
||||
httpd_printf("File %s not found in EspFS.\n", fileName);
|
||||
return NULL;
|
||||
}
|
||||
//Grab the name of the file.
|
||||
p+=sizeof(EspFsHeader);
|
||||
p += sizeof(EspFsHeader);
|
||||
spi_flash_read((uint32)p, (uint32*)&namebuf, sizeof(namebuf));
|
||||
// httpd_printf("Found file '%s'. Namelen=%x fileLenComp=%x, compr=%d flags=%d\n",
|
||||
// namebuf, (unsigned int)h.nameLen, (unsigned int)h.fileLenComp, h.compression, h.flags);
|
||||
if (strcmp(namebuf, fileName)==0) {
|
||||
// httpd_printf("Found file '%s'. Namelen=%x fileLenComp=%x, compr=%d flags=%d\n",
|
||||
// namebuf, (unsigned int)h.nameLen, (unsigned int)h.fileLenComp, h.compression, h.flags);
|
||||
if (strcmp(namebuf, fileName) == 0) {
|
||||
//Yay, this is the file we need!
|
||||
p+=h.nameLen; //Skip to content.
|
||||
r=(EspFsFile *)malloc(sizeof(EspFsFile)); //Alloc file desc mem
|
||||
// httpd_printf("Alloc %p\n", r);
|
||||
if (r==NULL) return NULL;
|
||||
r->header=(EspFsHeader *)hpos;
|
||||
r->decompressor=h.compression;
|
||||
r->posComp=p;
|
||||
r->posStart=p;
|
||||
r->posDecomp=0;
|
||||
if (h.compression==COMPRESS_NONE) {
|
||||
r->decompData=NULL;
|
||||
p += h.nameLen; //Skip to content.
|
||||
r = (EspFsFile *)malloc(sizeof(EspFsFile)); //Alloc file desc mem
|
||||
// httpd_printf("Alloc %p\n", r);
|
||||
if (r == NULL) return NULL;
|
||||
r->header = (const EspFsHeader *)hpos;
|
||||
r->decompressor = h.compression;
|
||||
r->posComp = p;
|
||||
r->posStart = p;
|
||||
r->posDecomp = 0;
|
||||
if (h.compression == COMPRESS_NONE) {
|
||||
r->decompData = NULL;
|
||||
#ifdef ESPFS_HEATSHRINK
|
||||
} else if (h.compression==COMPRESS_HEATSHRINK) {
|
||||
} else if (h.compression == COMPRESS_HEATSHRINK) {
|
||||
//File is compressed with Heatshrink.
|
||||
char parm;
|
||||
heatshrink_decoder *dec;
|
||||
//Decoder params are stored in 1st byte.
|
||||
readFlashUnaligned(&parm, r->posComp, 1);
|
||||
readFlashUnaligned(&parm, (char*)r->posComp, 1);
|
||||
r->posComp++;
|
||||
httpd_printf("Heatshrink compressed file; decode parms = %x\n", parm);
|
||||
dec=heatshrink_decoder_alloc(16, (parm>>4)&0xf, parm&0xf);
|
||||
r->decompData=dec;
|
||||
dec = heatshrink_decoder_alloc(16, (parm >> 4) & 0xf, parm & 0xf);
|
||||
r->decompData = dec;
|
||||
#endif
|
||||
} else {
|
||||
httpd_printf("Invalid compression: %d\n", h.compression);
|
||||
@@ -181,37 +187,38 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
|
||||
return r;
|
||||
}
|
||||
//We don't need this file. Skip name and file
|
||||
p+=h.nameLen+h.fileLenComp;
|
||||
if ((int)p&3) p+=4-((int)p&3); //align to next 32bit val
|
||||
p += h.nameLen + h.fileLenComp;
|
||||
if ((int)p & 3) p += 4 - ((int)p & 3); //align to next 32bit val
|
||||
}
|
||||
}
|
||||
|
||||
//Read len bytes from the given file into buff. Returns the actual amount of bytes read.
|
||||
int ICACHE_FLASH_ATTR espFsRead(EspFsFile *fh, char *buff, int len) {
|
||||
int ICACHE_FLASH_ATTR espFsRead(EspFsFile *fh, char *buff, int len)
|
||||
{
|
||||
int flen, fdlen;
|
||||
if (fh==NULL) return 0;
|
||||
if (fh == NULL) return 0;
|
||||
|
||||
readFlashUnaligned((char*)&flen, (char*)&fh->header->fileLenComp, 4);
|
||||
//Cache file length.
|
||||
//Do stuff depending on the way the file is compressed.
|
||||
if (fh->decompressor==COMPRESS_NONE) {
|
||||
if (fh->decompressor == COMPRESS_NONE) {
|
||||
int toRead;
|
||||
toRead=flen-(fh->posComp-fh->posStart);
|
||||
if (len>toRead) len=toRead;
|
||||
// httpd_printf("Reading %d bytes from %x\n", len, (unsigned int)fh->posComp);
|
||||
readFlashUnaligned(buff, fh->posComp, len);
|
||||
fh->posDecomp+=len;
|
||||
fh->posComp+=len;
|
||||
// httpd_printf("Done reading %d bytes, pos=%x\n", len, fh->posComp);
|
||||
toRead = flen - (fh->posComp - fh->posStart);
|
||||
if (len > toRead) len = toRead;
|
||||
// httpd_printf("Reading %d bytes from %x\n", len, (unsigned int)fh->posComp);
|
||||
readFlashUnaligned(buff, (char*)fh->posComp, len);
|
||||
fh->posDecomp += len;
|
||||
fh->posComp += len;
|
||||
// httpd_printf("Done reading %d bytes, pos=%x\n", len, fh->posComp);
|
||||
return len;
|
||||
#ifdef ESPFS_HEATSHRINK
|
||||
} else if (fh->decompressor==COMPRESS_HEATSHRINK) {
|
||||
} else if (fh->decompressor == COMPRESS_HEATSHRINK) {
|
||||
readFlashUnaligned((char*)&fdlen, (char*)&fh->header->fileLenDecomp, 4);
|
||||
int decoded=0;
|
||||
int decoded = 0;
|
||||
size_t elen, rlen;
|
||||
char ebuff[16];
|
||||
heatshrink_decoder *dec=(heatshrink_decoder *)fh->decompData;
|
||||
// httpd_printf("Alloc %p\n", dec);
|
||||
heatshrink_decoder *dec = (heatshrink_decoder *)fh->decompData;
|
||||
// httpd_printf("Alloc %p\n", dec);
|
||||
if (fh->posDecomp == fdlen) {
|
||||
return 0;
|
||||
}
|
||||
@@ -220,26 +227,26 @@ int ICACHE_FLASH_ATTR espFsRead(EspFsFile *fh, char *buff, int len) {
|
||||
// This means even when there is no input data (elen==0) try to poll decoder until
|
||||
// posDecomp equals decompressed file length
|
||||
|
||||
while(decoded<len) {
|
||||
while (decoded < len) {
|
||||
//Feed data into the decompressor
|
||||
//ToDo: Check ret val of heatshrink fns for errors
|
||||
elen=flen-(fh->posComp - fh->posStart);
|
||||
if (elen>0) {
|
||||
readFlashUnaligned(ebuff, fh->posComp, 16);
|
||||
heatshrink_decoder_sink(dec, (uint8_t *)ebuff, (elen>16)?16:elen, &rlen);
|
||||
fh->posComp+=rlen;
|
||||
elen = flen - (fh->posComp - fh->posStart);
|
||||
if (elen > 0) {
|
||||
readFlashUnaligned(ebuff, (char*)fh->posComp, 16);
|
||||
heatshrink_decoder_sink(dec, (uint8_t *)ebuff, (elen > 16) ? 16 : elen, &rlen);
|
||||
fh->posComp += rlen;
|
||||
}
|
||||
//Grab decompressed data and put into buff
|
||||
heatshrink_decoder_poll(dec, (uint8_t *)buff, len-decoded, &rlen);
|
||||
fh->posDecomp+=rlen;
|
||||
buff+=rlen;
|
||||
decoded+=rlen;
|
||||
heatshrink_decoder_poll(dec, (uint8_t *)buff, len - decoded, &rlen);
|
||||
fh->posDecomp += rlen;
|
||||
buff += rlen;
|
||||
decoded += rlen;
|
||||
|
||||
// httpd_printf("Elen %d rlen %d d %d pd %ld fdl %d\n",elen,rlen,decoded, fh->posDecomp, fdlen);
|
||||
// httpd_printf("Elen %d rlen %d d %d pd %ld fdl %d\n",elen,rlen,decoded, fh->posDecomp, fdlen);
|
||||
|
||||
if (elen == 0) {
|
||||
if (fh->posDecomp == fdlen) {
|
||||
// httpd_printf("Decoder finish\n");
|
||||
// httpd_printf("Decoder finish\n");
|
||||
heatshrink_decoder_finish(dec);
|
||||
}
|
||||
return decoded;
|
||||
@@ -252,16 +259,17 @@ int ICACHE_FLASH_ATTR espFsRead(EspFsFile *fh, char *buff, int len) {
|
||||
}
|
||||
|
||||
//Close the file.
|
||||
void ICACHE_FLASH_ATTR espFsClose(EspFsFile *fh) {
|
||||
if (fh==NULL) return;
|
||||
void ICACHE_FLASH_ATTR espFsClose(EspFsFile *fh)
|
||||
{
|
||||
if (fh == NULL) return;
|
||||
#ifdef ESPFS_HEATSHRINK
|
||||
if (fh->decompressor==COMPRESS_HEATSHRINK) {
|
||||
heatshrink_decoder *dec=(heatshrink_decoder *)fh->decompData;
|
||||
if (fh->decompressor == COMPRESS_HEATSHRINK) {
|
||||
heatshrink_decoder *dec = (heatshrink_decoder *)fh->decompData;
|
||||
heatshrink_decoder_free(dec);
|
||||
// httpd_printf("Freed %p\n", dec);
|
||||
// httpd_printf("Freed %p\n", dec);
|
||||
}
|
||||
#endif
|
||||
// httpd_printf("Freed %p\n", fh);
|
||||
// httpd_printf("Freed %p\n", fh);
|
||||
free(fh);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#ifndef ESPROFSFORMAT_H
|
||||
#define ESPROFSFORMAT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
Stupid cpio-like tool to make read-only 'filesystems' that live on the flash SPI chip of the module.
|
||||
Can (will) use lzf compression (when I come around to it) to make shit quicker. Aligns names, files,
|
||||
headers on 4-byte boundaries so the SPI abstraction hardware in the ESP8266 doesn't crap on itself
|
||||
headers on 4-byte boundaries so the SPI abstraction hardware in the ESP8266 doesn't crap on itself
|
||||
when trying to do a <4byte or unaligned read.
|
||||
*/
|
||||
|
||||
@@ -30,4 +32,4 @@ typedef struct {
|
||||
int32_t fileLenDecomp;
|
||||
} __attribute__((packed)) EspFsHeader;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"removeComments": true,
|
||||
"removeCommentsFromCDATA": true,
|
||||
"removeCDATASectionsFromCDATA": true,
|
||||
"collapseWhitespace": true,
|
||||
"conservativeCollapse": false,
|
||||
"collapseBooleanAttributes": true,
|
||||
"removeTagWhitespace": true,
|
||||
"removeAttributeQuotes": true,
|
||||
"removeRedundantAttributes": true,
|
||||
"useShortDoctype": true,
|
||||
"removeEmptyAttributes": true,
|
||||
"removeScriptTypeAttributes": true,
|
||||
"removeStyleLinkTypeAttributes": true,
|
||||
"removeOptionalTags": false,
|
||||
"removeEmptyElements": false,
|
||||
"lint": false,
|
||||
"keepClosingSlash": false,
|
||||
"caseSensitive": false,
|
||||
"minifyJS": true,
|
||||
"minifyCSS": true,
|
||||
"includeAutoGeneratedTags": false,
|
||||
"ignoreCustomComments": [],
|
||||
"processScripts": []
|
||||
}
|
||||
@@ -13,11 +13,11 @@ typedef enum {
|
||||
|
||||
typedef struct EspFsFile EspFsFile;
|
||||
|
||||
EspFsInitResult espFsInit(void *flashAddress);
|
||||
EspFsFile *espFsOpen(char *fileName);
|
||||
EspFsInitResult espFsInit(const void *flashAddress);
|
||||
EspFsFile *espFsOpen(const char *fileName);
|
||||
int espFsFlags(EspFsFile *fh);
|
||||
int espFsRead(EspFsFile *fh, char *buff, int len);
|
||||
void espFsClose(EspFsFile *fh);
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -26,9 +26,15 @@ struct HttpdConnData {
|
||||
char requestType; // One of the HTTPD_METHOD_* values
|
||||
char *url; // The URL requested, without hostname or GET arguments
|
||||
char *getArgs; // The GET arguments for this request, if any.
|
||||
|
||||
const void *cgiArg; // Argument to the CGI function, as stated as the 3rd argument of
|
||||
// the builtInUrls entry that referred to the CGI function.
|
||||
|
||||
const void *cgiArg2; // Argument to the CGI function, as stated as the 4th argument of
|
||||
// the builtInUrls entry that referred to the CGI function.
|
||||
|
||||
void *cgiData; // Opaque data pointer for the CGI function
|
||||
|
||||
char *hostName; // Host name field of request
|
||||
HttpdPriv *priv; // Opaque pointer to data for internal httpd housekeeping
|
||||
cgiSendCallback cgi; // CGI function pointer
|
||||
@@ -55,8 +61,33 @@ typedef struct {
|
||||
const char *url;
|
||||
cgiSendCallback cgiCb;
|
||||
const void *cgiArg;
|
||||
const void *cgiArg2;
|
||||
} HttpdBuiltInUrl;
|
||||
|
||||
|
||||
// macros for defining HttpdBuiltInUrl's
|
||||
|
||||
#define ROUTE_CGI_ARG2(path, handler, arg1, arg2) {path, handler, (void *)arg1, (void *)arg2}
|
||||
|
||||
#define ROUTE_CGI_ARG(path, handler, arg1) ROUTE_CGI_ARG2(path, handler, arg1, NULL)
|
||||
#define ROUTE_CGI(path, handler) ROUTE_CGI_ARG2(path, handler, NULL, NULL)
|
||||
|
||||
#define ROUTE_FILE(path, filepath) ROUTE_CGI_ARG(path, cgiEspFsStaticFile, filepath)
|
||||
|
||||
// the argument of a template route is accessible as cgiArg2 on the connData struct.
|
||||
#define ROUTE_TPL(path, replacer) ROUTE_CGI_ARG(path, cgiEspFsTemplate, replacer)
|
||||
#define ROUTE_TPL_FILE(path, replacer, filepath) ROUTE_CGI_ARG2(path, cgiEspFsTemplate, replacer, filepath)
|
||||
|
||||
#define ROUTE_REDIRECT(path, target) ROUTE_CGI_ARG(path, cgiRedirect, target)
|
||||
#define ROUTE_AUTH(path, passwdFunc) ROUTE_CGI_ARG(path, authBasic, passwdFunc)
|
||||
|
||||
// catch-all route
|
||||
#define ROUTE_FS(path) ROUTE_CGI(path, cgiEspFsHook)
|
||||
|
||||
#define ROUTE_END() {NULL, NULL, NULL, NULL}
|
||||
|
||||
|
||||
|
||||
int cgiRedirect(HttpdConnData *connData);
|
||||
int cgiRedirectToHostname(HttpdConnData *connData);
|
||||
int cgiRedirectApClientToHostname(HttpdConnData *connData);
|
||||
@@ -64,7 +95,7 @@ void httpdRedirect(HttpdConnData *conn, char *newUrl);
|
||||
int httpdUrlDecode(char *val, int valLen, char *ret, int retLen);
|
||||
int httpdFindArg(char *line, char *arg, char *buff, int buffLen);
|
||||
void httpdInit(HttpdBuiltInUrl *fixedUrls, int port);
|
||||
const char *httpdGetMimetype(char *url);
|
||||
const char *httpdGetMimetype(const char *url);
|
||||
void httpdDisableTransferEncoding(HttpdConnData *conn);
|
||||
void httpdStartResponse(HttpdConnData *conn, int code);
|
||||
void httpdHeader(HttpdConnData *conn, const char *field, const char *val);
|
||||
@@ -80,4 +111,11 @@ void httpdDisconCb(ConnTypePtr conn, char *remIp, int remPort);
|
||||
int httpdConnectCb(ConnTypePtr conn, char *remIp, int remPort);
|
||||
|
||||
|
||||
// debugging
|
||||
|
||||
#define LOG_EOL "\n"
|
||||
#define dbg(fmt, ...) httpd_printf(fmt LOG_EOL, ##__VA_ARGS__);
|
||||
#define error(fmt, ...) httpd_printf("\x1b[31;1m"fmt"\x1b[0m"LOG_EOL, ##__VA_ARGS__);
|
||||
#define info(fmt, ...) httpd_printf("\x1b[32;1m"fmt"\x1b[0m"LOG_EOL, ##__VA_ARGS__);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,7 +3,13 @@
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
/** Catch-all, use in '*' routes */
|
||||
int cgiEspFsHook(HttpdConnData *connData);
|
||||
|
||||
/** Template route */
|
||||
int ICACHE_FLASH_ATTR cgiEspFsTemplate(HttpdConnData *connData);
|
||||
|
||||
#endif
|
||||
/** Static file route with the file as the first arg. */
|
||||
int ICACHE_FLASH_ATTR cgiEspFsFile(HttpdConnData *connData);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user