This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088
Dependents: MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more
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 15:46:14 by 1.7.2