/* Connector to let httpd use the espfs filesystem to serve the files in it. */ /* * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * Jeroen Domburg wrote this file. As long as you retain * this notice you can do whatever you want with this stuff. If we meet some day, * and you think this stuff is worth it, you can buy me a beer in return. * ---------------------------------------------------------------------------- */ #include "espmissingincludes.h" #include #include #include "c_types.h" #include "user_interface.h" #include "espconn.h" #include "mem.h" #include "httpd.h" #include "espfs.h" #include "httpdespfs.h" //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) { EspFsFile *file=connData->cgiData; int len; char buff[1024]; #ifdef GZIP_COMPRESSION const char *gzipSendResult = NULL; #endif if (connData->conn==NULL) { //Connection aborted. Clean up. espFsClose(file); return HTTPD_CGI_DONE; } if (file==NULL) { //First call to this cgi. Open the file so we can read it. file=espFsOpen(connData->url); if (file==NULL) { return HTTPD_CGI_NOTFOUND; } connData->cgiData=file; httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", httpdGetMimetype(connData->url)); #ifdef GZIP_COMPRESSION gzipSendResult = sendGZIPEncodingIfNeeded(connData); if (gzipSendResult != NULL) { httpdEndHeaders(connData); httpdSend(connData, gzipSendResult, os_strlen(gzipSendResult)); return HTTPD_CGI_DONE; } #endif httpdHeader(connData, "Cache-Control", "max-age=3600, must-revalidate"); httpdEndHeaders(connData); return HTTPD_CGI_MORE; } len=espFsRead(file, buff, 1024); if (len>0) espconn_sent(connData->conn, (uint8 *)buff, len); if (len!=1024) { //We're done. espFsClose(file); return HTTPD_CGI_DONE; } else { //Ok, till next time. return HTTPD_CGI_MORE; } } //cgiEspFsTemplate can be used as a template. typedef struct { EspFsFile *file; void *tplArg; char token[64]; int tokenPos; } TplData; typedef void (* TplCallback)(HttpdConnData *connData, char *token, void **arg); int ICACHE_FLASH_ATTR cgiEspFsTemplate(HttpdConnData *connData) { TplData *tpd=connData->cgiData; int len; int x, sp=0; char *e=NULL; char buff[1025]; if (connData->conn==NULL) { //Connection aborted. Clean up. ((TplCallback)(connData->cgiArg))(connData, NULL, &tpd->tplArg); espFsClose(tpd->file); os_free(tpd); return HTTPD_CGI_DONE; } if (tpd==NULL) { //First call to this cgi. Open the file so we can read it. tpd=(TplData *)os_malloc(sizeof(TplData)); tpd->file=espFsOpen(connData->url); tpd->tplArg=NULL; tpd->tokenPos=-1; if (tpd->file==NULL) { return HTTPD_CGI_NOTFOUND; } connData->cgiData=tpd; httpdStartResponse(connData, 200); httpdHeader(connData, "Content-Type", httpdGetMimetype(connData->url)); httpdEndHeaders(connData); return HTTPD_CGI_MORE; } len=espFsRead(tpd->file, buff, 1024); if (len>0) { sp=0; e=buff; for (x=0; xtokenPos==-1) { //Inside ordinary text. if (buff[x]=='%') { //Send raw data up to now if (sp!=0) httpdSend(connData, e, sp); sp=0; //Go collect token chars. tpd->tokenPos=0; } else { sp++; } } else { if (buff[x]=='%') { if (tpd->tokenPos==0) { //This is the second % of a %% escape string. //Send a single % and resume with the normal program flow. httpdSend(connData, "%", 1); } else { //This is an actual token. tpd->token[tpd->tokenPos++]=0; //zero-terminate token ((TplCallback)(connData->cgiArg))(connData, tpd->token, &tpd->tplArg); } //Go collect normal chars again. e=&buff[x+1]; tpd->tokenPos=-1; } else { if (tpd->tokenPos<(sizeof(tpd->token)-1)) tpd->token[tpd->tokenPos++]=buff[x]; } } } } //Send remaining bit. if (sp!=0) httpdSend(connData, e, sp); if (len!=1024) { //We're done. ((TplCallback)(connData->cgiArg))(connData, NULL, &tpd->tplArg); espFsClose(tpd->file); return HTTPD_CGI_DONE; } else { //Ok, till next time. return HTTPD_CGI_MORE; } }