Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of libMiMic by
ModLocalFileSystem.cpp
00001 #include "ModLocalFileSystem.h" 00002 #include "HttpdConnection.h" 00003 #include "UrlReader.h" 00004 #include "Http.h" 00005 #include "Httpd.h" 00006 #include "NyLPC_net.h" 00007 #include <stdio.h> 00008 #include <stdlib.h> 00009 #include <typeinfo> 00010 #include "mbed.h" 00011 #include "FATDirHandle.h" 00012 00013 00014 using namespace MiMic; 00015 00016 static void write_path(HttpdConnection& i_connection,const char* i_buf,const char* i_root_alias,const char* i_f_path) 00017 { 00018 if(i_root_alias==NULL){ 00019 i_connection.sendBodyF("%s",i_buf); 00020 }else{ 00021 i_connection.sendBodyF("%.*s%s",strlen(i_root_alias)-1,i_root_alias,i_buf+strlen(i_f_path)+1); 00022 } 00023 } 00024 00025 void ModLocalFileSystem::retDirJson(const char* i_buf,HttpdConnection& i_connection,unsigned char i_fs_type) 00026 { 00027 //assert(HEAD or GET) 00028 //directory-list json 00029 if(!NyLPC_cHttpdUtils_sendJsonHeader((i_connection._ref_inst))){ 00030 return; 00031 } 00032 if(!i_connection.isMethodType(Http::MT_GET)){ 00033 return; 00034 } 00035 00036 DIR* d=opendir(i_buf); 00037 if ( d == NULL ) 00038 { 00039 i_connection.sendBodyF("{\"dir\":\""); 00040 write_path(i_connection,i_buf,this->_root_alias,this->_path); 00041 i_connection.sendBodyF("\",\"status\":404,\"list\":[]}"); 00042 return; 00043 } 00044 if(!i_connection.isMethodType(Http::MT_GET)){ 00045 //nothing to do 00046 }else{ 00047 i_connection.sendBodyF("{\"dir\":\""); 00048 write_path(i_connection,i_buf,this->_root_alias,this->_path); 00049 i_connection.sendBodyF("\",\"status\":200,\"list\":["); 00050 switch(i_fs_type){ 00051 case ModLocalFileSystem::FST_DEFAULT: 00052 for(struct dirent *p= readdir(d);;) 00053 { 00054 i_connection.sendBodyF("{\"name\":\"%s\",\"mtype\":\"%s\",\"size\":undefined}", 00055 p->d_name,NyLPC_cMiMeType_getFileName2MimeType(p->d_name)); 00056 p = readdir(d); 00057 if(p==NULL){ 00058 break; 00059 } 00060 i_connection.sendBodyF(","); 00061 } 00062 break; 00063 case ModLocalFileSystem::FST_SDFATFS: 00064 for(struct dirent *p= readdir(d);;) 00065 { 00066 bool isdir=(((struct direntFAT*)(p))->fattrib & AM_DIR)!=0; 00067 i_connection.sendBodyF("{\"name\":\"%s\",\"mtype\":\"%s\",\"size\":%u}", 00068 p->d_name,isdir?"directory":NyLPC_cMiMeType_getFileName2MimeType(p->d_name), 00069 isdir?0:((struct direntFAT*)(p))->fsize); 00070 p = readdir(d); 00071 if(p==NULL){ 00072 break; 00073 } 00074 i_connection.sendBodyF(","); 00075 } 00076 break; 00077 default: 00078 break; 00079 } 00080 i_connection.sendBodyF("]}"); 00081 } 00082 closedir(d); 00083 } 00084 void ModLocalFileSystem::retDirHtml(const char* i_buf,HttpdConnection& i_connection,unsigned char i_fs_type) 00085 { 00086 //assert(HEAD or GET) 00087 DIR* d=opendir(i_buf); 00088 if(d==NULL){ 00089 i_connection.sendError(403); 00090 return; 00091 } 00092 if(!i_connection.sendHeader(200,"text/html",NULL)){ 00093 //nothing to do 00094 }else{ 00095 if(!i_connection.isMethodType(Http::MT_GET)){ 00096 //nothing to do. 00097 }else{ 00098 i_connection.sendBodyF( 00099 "<!DOCTYPE html><html><body><h1>Index of "); 00100 write_path(i_connection,i_buf,this->_root_alias,this->_path); 00101 i_connection.sendBodyF("</h1><hr/>\n" 00102 "<ul>\n"); 00103 switch(i_fs_type){ 00104 case ModLocalFileSystem::FST_DEFAULT: 00105 for(struct dirent *p = readdir(d);p!=NULL;p = readdir(d)) 00106 { 00107 i_connection.sendBodyF("<li><a href=\"./%s\">%s</a></li>\n", 00108 p->d_name,p->d_name); 00109 } 00110 break; 00111 case ModLocalFileSystem::FST_SDFATFS: 00112 for(struct dirent *p = readdir(d);p!=NULL;p = readdir(d)) 00113 { 00114 if((((struct direntFAT*)(p))->fattrib & AM_DIR)!=0){ 00115 //dir 00116 i_connection.sendBodyF("<li><a href=\"./%s/\">[DIR]%s</a></li>\n",p->d_name,p->d_name); 00117 }else{ 00118 //file 00119 i_connection.sendBodyF("<li><a href=\"./%s\">%s</a></li>\n",p->d_name,p->d_name); 00120 } 00121 } 00122 break; 00123 default: 00124 break; 00125 } 00126 i_connection.sendBodyF("</ul></body></html>"); 00127 } 00128 } 00129 closedir(d); 00130 } 00131 /** 00132 * @param i_path 00133 * i_pathにはnull終端ファイルパスを入れてください。 00134 */ 00135 void ModLocalFileSystem::retFile(char* i_buf,HttpdConnection& i_connection) 00136 { 00137 //return content 00138 FILE *fp = fopen(i_buf, "r"); 00139 if(fp==NULL){ 00140 i_connection.sendError(404); 00141 return; 00142 } 00143 00144 fseek(fp, 0, SEEK_END); // seek to end of file 00145 size_t sz = ftell(fp); // get current file pointer 00146 fseek(fp, 0, SEEK_SET); // seek back to beginning of file 00147 if(i_connection.sendHeader(200,NyLPC_cMiMeType_getFileName2MimeType(i_buf),NULL,sz)){ 00148 if(!i_connection.isMethodType(Http::MT_GET)){ 00149 //nothing to do 00150 }else{ 00151 Timer t; 00152 t.start(); 00153 for(;;){ 00154 sz=fread(i_buf,1,Httpd::SIZE_OF_HTTP_BUF,fp); 00155 if(sz<1){ 00156 break; 00157 } 00158 if(!i_connection.sendBody(i_buf,sz)){ 00159 break; 00160 } 00161 //switch other session 00162 if(t.read_ms()>500){ 00163 //switch transport thread 00164 i_connection.unlockHttpd(); 00165 NyLPC_cThread_sleep(50); 00166 i_connection.lockHttpd(); 00167 t.reset(); 00168 } 00169 } 00170 } 00171 } 00172 fclose(fp); 00173 } 00174 00175 NyLPC_TBool flip_url_prefix(char* buf, int buf_len, const char* url_prefix, const char* file_path) 00176 { 00177 size_t bl = strlen(url_prefix); 00178 size_t al = strlen(file_path)+2; 00179 if (al - bl + strlen(buf) + 1 > buf_len){ 00180 return NyLPC_TBool_FALSE; 00181 } 00182 if (strncmp(buf, url_prefix, bl) == 0){ 00183 memmove(buf + al, buf + bl, strlen(buf) - bl + 1); 00184 memcpy(buf + 1, file_path, al - 1); 00185 *(buf + al - 1) = '/'; 00186 } 00187 return NyLPC_TBool_TRUE; 00188 } 00189 00190 namespace MiMic 00191 { 00192 ModLocalFileSystem::ModLocalFileSystem(const char* i_path,const char* i_root_alias,unsigned char i_fs_type):ModBaseClass() 00193 { 00194 this->setParam(i_path,i_root_alias,i_fs_type); 00195 } 00196 ModLocalFileSystem::ModLocalFileSystem(const char* i_path,unsigned char i_fs_type):ModBaseClass() 00197 { 00198 this->setParam(i_path,NULL,i_fs_type); 00199 } 00200 ModLocalFileSystem::ModLocalFileSystem():ModBaseClass() 00201 { 00202 this->_root_alias=NULL; 00203 } 00204 ModLocalFileSystem::~ModLocalFileSystem() 00205 { 00206 } 00207 void ModLocalFileSystem::setParam(const char* i_path,const char* i_root_alias,unsigned char i_fs_type) 00208 { 00209 NyLPC_Assert(strlen(i_root_alias)>0); 00210 ModBaseClass::setParam(i_path); 00211 this->_root_alias=i_root_alias; 00212 this->_fs_type=i_fs_type; 00213 } 00214 void ModLocalFileSystem::setParam(const char* i_path,unsigned char i_fs_type) 00215 { 00216 this->setParam(i_path,NULL,i_fs_type); 00217 } 00218 bool ModLocalFileSystem::canHandle(HttpdConnection& i_connection) 00219 { 00220 if(this->_root_alias==NULL){ 00221 return ModBaseClass::canHandle(i_connection); 00222 } 00223 //root alias指定がある場合 00224 if(!NyLPC_cHttpdConnection_getReqStatus(i_connection._ref_inst)==NyLPC_cHttpdConnection_ReqStatus_REQPARSE) 00225 { 00226 return NyLPC_TBool_FALSE; 00227 } 00228 const NyLPC_TChar* in_url; 00229 in_url=NyLPC_cHttpdConnection_getUrlPrefix(i_connection._ref_inst); 00230 size_t base_url_len=strlen(this->_root_alias); 00231 if(strncmp(this->_root_alias,in_url,base_url_len)!=0){ 00232 return false; 00233 } 00234 return true; 00235 } 00236 bool ModLocalFileSystem::execute(HttpdConnection& i_connection) 00237 { 00238 //check platform 00239 //<write here! /> 00240 00241 //check prefix 00242 if(!this->canHandle(i_connection)){ 00243 return false; 00244 } 00245 00246 //check Method type 00247 { 00248 int mt=i_connection.getMethodType(); 00249 if(mt!=Http::MT_GET && mt!=Http::MT_HEAD){ 00250 //method not allowed. 00251 i_connection.sendError(405); 00252 return true; 00253 } 00254 } 00255 //Httpd lock 00256 i_connection.lockHttpd(); 00257 char* buf=Httpd::_shared_buf; 00258 00259 //set file path 00260 { 00261 //call ModUrl 00262 NyLPC_TcModUrl_t mod; 00263 NyLPC_cModUrl_initialize(&mod); 00264 if(!NyLPC_cModUrl_execute2(&mod,i_connection._ref_inst,buf,Httpd::SIZE_OF_HTTP_BUF,0,NyLPC_cModUrl_ParseMode_ALL)){ 00265 NyLPC_cModUrl_finalize(&mod); 00266 i_connection.unlockHttpd(); 00267 return true; 00268 } 00269 NyLPC_cModUrl_finalize(&mod); 00270 } 00271 //パスのエイリアスがあるときはここで編集 00272 if(this->_root_alias!=NULL){ 00273 flip_url_prefix(buf,Httpd::SIZE_OF_HTTP_BUF,this->_root_alias,this->_path); 00274 } 00275 UrlReader url(buf); 00276 if(url.hasQueryKey("list")){ 00277 // if path has '/?list' query key,return directory information 00278 const char* t; 00279 int l; 00280 url.getPath(t,l); 00281 buf[l]='\0';//split path 00282 //remove '/' 00283 if(buf[l-1]=='/'){ 00284 buf[l-1]='\0'; 00285 } 00286 retDirJson(buf,i_connection,this->_fs_type); 00287 }else if(strchr(buf,'?')==NULL && strchr(buf,'#')==NULL && buf[strlen(buf)-1]=='/'){ 00288 //return directory html when URL has not bookmark and URL query and terminated by '/'. 00289 buf[strlen(buf)-1]='\0';//convert to dir path 00290 retDirHtml(buf,i_connection,this->_fs_type); 00291 }else{ 00292 //split URL path and query 00293 const char* t; 00294 int l; 00295 url.getPath(t,l); 00296 buf[l]='\0'; 00297 retFile(buf,i_connection); 00298 } 00299 //Httpd unlock 00300 i_connection.unlockHttpd(); 00301 return true; 00302 00303 } 00304 }
Generated on Tue Jul 12 2022 16:22:56 by
1.7.2
