This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088

Fork of libMiMic by Ryo Iizuka

Files at this revision

API Documentation at this revision

Comitter:
nyatla
Date:
Mon Mar 16 14:19:16 2015 +0000
Parent:
110:257739f9b31e
Child:
112:1853d747fcdf
Commit message:
ModLocalfilesystem; ; Add virtual directory option.

Changed in this revision

mbed/mod/ModBaseClass.cpp Show annotated file Show diff for this revision Revisions of this file
mbed/mod/ModBaseClass.h Show annotated file Show diff for this revision Revisions of this file
mbed/mod/ModLocalFileSystem.cpp Show annotated file Show diff for this revision Revisions of this file
mbed/mod/ModLocalFileSystem.h Show annotated file Show diff for this revision Revisions of this file
--- a/mbed/mod/ModBaseClass.cpp	Sun Mar 15 09:33:38 2015 +0000
+++ b/mbed/mod/ModBaseClass.cpp	Mon Mar 16 14:19:16 2015 +0000
@@ -52,5 +52,5 @@
             return false;
         }
         return true;
-    }        
+    }
 }
--- a/mbed/mod/ModBaseClass.h	Sun Mar 15 09:33:38 2015 +0000
+++ b/mbed/mod/ModBaseClass.h	Mon Mar 16 14:19:16 2015 +0000
@@ -34,6 +34,10 @@
          * </pre>
          */
         void setParam(const char* i_path);
+        /**
+         * URLとパスプレフィクスi_pathを比較して、処理対象のURLかを計算します。
+         * URLに'/i_path/'を含むパスを処理対象とみなします。
+         */
         virtual bool canHandle(HttpdConnection& i_connection);
     };
 }
\ No newline at end of file
--- a/mbed/mod/ModLocalFileSystem.cpp	Sun Mar 15 09:33:38 2015 +0000
+++ b/mbed/mod/ModLocalFileSystem.cpp	Mon Mar 16 14:19:16 2015 +0000
@@ -12,7 +12,17 @@
 
 
 using namespace MiMic;
-static void retDirJson(UrlReader& url,char* buf,HttpdConnection& i_connection,unsigned char i_fs_type)
+
+static void write_path(HttpdConnection& i_connection,const char* i_buf,const char* i_root_alias,const char* i_f_path)
+{
+    if(i_root_alias==NULL){
+        i_connection.sendBodyF("%s",i_buf);
+    }else{
+        i_connection.sendBodyF("%.*s%s",strlen(i_root_alias)-1,i_root_alias,i_buf+strlen(i_f_path)+1);
+    }
+}
+
+void ModLocalFileSystem::retDirJson(const char* i_buf,HttpdConnection& i_connection,unsigned char i_fs_type)
 {
    //assert(HEAD or GET)
    //directory-list json
@@ -22,24 +32,21 @@
     if(!i_connection.isMethodType(Http::MT_GET)){
         return;
     }
-    const char* t;
-    int l;
-    url.getPath(t,l);
-    buf[l]='\0';//split path
-    //remove '/'
-    if(buf[l-1]=='/'){
-        buf[l-1]='\0';
-    }        
-    DIR* d=opendir(buf);
+      
+    DIR* d=opendir(i_buf);
     if ( d == NULL )
     {
-        i_connection.sendBodyF("{\"dir\":\"%s\",\"status\":404,\"list\":[]}",buf);
+        i_connection.sendBodyF("{\"dir\":\"");
+        write_path(i_connection,i_buf,this->_root_alias,this->_path);
+        i_connection.sendBodyF("\",\"status\":404,\"list\":[]}");
         return;
     }
     if(!i_connection.isMethodType(Http::MT_GET)){
         //nothing to do
     }else{
-        i_connection.sendBodyF("{\"dir\":\"%s\",\"status\":200,\"list\":[",buf);
+        i_connection.sendBodyF("{\"dir\":\"");
+        write_path(i_connection,i_buf,this->_root_alias,this->_path);
+        i_connection.sendBodyF("\",\"status\":200,\"list\":[");
         switch(i_fs_type){
         case ModLocalFileSystem::FST_DEFAULT:
             for(struct dirent *p= readdir(d);;)
@@ -74,17 +81,12 @@
     }
     closedir(d);
 }
-static void retDirHtml(UrlReader& url,char* buf,HttpdConnection& i_connection,unsigned char i_fs_type)
+void ModLocalFileSystem::retDirHtml(const char* i_buf,HttpdConnection& i_connection,unsigned char i_fs_type)
 {
     //assert(HEAD or GET)
-    buf[strlen(buf)-1]='\0';//convert to dir path
-    DIR* d=opendir(buf);
+    DIR* d=opendir(i_buf);
     if(d==NULL){
         i_connection.sendError(403);
-        if(!i_connection.isMethodType(Http::MT_GET)){
-            return;
-        }
-        i_connection.sendBodyF("<!DOCTYPE html><html><body><h1>403 Forbidden</h1><hr/>'%s'</body></html>",buf);
         return;
     }        
     if(!i_connection.sendHeader(200,"text/html",NULL)){
@@ -94,9 +96,10 @@
             //nothing to do.
         }else{
             i_connection.sendBodyF(
-                "<!DOCTYPE html><html><body><h1>Index of %s</h1><hr/>\n"
-                "<ul>\n"
-                ,buf);
+                "<!DOCTYPE html><html><body><h1>Index of ");
+            write_path(i_connection,i_buf,this->_root_alias,this->_path);
+            i_connection.sendBodyF("</h1><hr/>\n"
+                "<ul>\n");
             switch(i_fs_type){
             case ModLocalFileSystem::FST_DEFAULT:
                 for(struct dirent *p = readdir(d);p!=NULL;p = readdir(d))
@@ -120,49 +123,39 @@
             default:
                 break;
             }
-            i_connection.sendBodyF("</ul></body></html>",buf);
+            i_connection.sendBodyF("</ul></body></html>");
         }
     }
     closedir(d);
 }
-static void retFile(UrlReader& url,char* buf,HttpdConnection& i_connection)
+/**
+ * @param i_path
+ * i_pathにはnull終端ファイルパスを入れてください。
+ */
+void ModLocalFileSystem::retFile(char* i_buf,HttpdConnection& i_connection)
 {
-    //file contents
-    {//split URL path and query
-        const char* t;
-        int l;
-        url.getPath(t,l);
-        buf[l]='\0';
-    }
     //return content
-    FILE *fp;
-    size_t sz;
-    //size
-    fp = fopen(buf, "r"); 
+    FILE *fp = fopen(i_buf, "r"); 
     if(fp==NULL){
         i_connection.sendError(404);
-        if(!i_connection.isMethodType(Http::MT_GET)){
-            return;
-        }
-        i_connection.sendBodyF("<!DOCTYPE html><html><body>'%s' not found.</body></html>",buf);
         return;
     }
     
     fseek(fp, 0, SEEK_END); // seek to end of file
-    sz = ftell(fp);       // get current file pointer
+    size_t sz = ftell(fp);       // get current file pointer
     fseek(fp, 0, SEEK_SET); // seek back to beginning of file
-    if(i_connection.sendHeader(200,NyLPC_cMiMeType_getFileName2MimeType(buf),NULL,sz)){
+    if(i_connection.sendHeader(200,NyLPC_cMiMeType_getFileName2MimeType(i_buf),NULL,sz)){
         if(!i_connection.isMethodType(Http::MT_GET)){
             //nothing to do
         }else{
             Timer t;
             t.start();
             for(;;){
-                sz=fread(buf,1,Httpd::SIZE_OF_HTTP_BUF,fp);
+                sz=fread(i_buf,1,Httpd::SIZE_OF_HTTP_BUF,fp);
                 if(sz<1){
                     break;
                 }
-                if(!i_connection.sendBody(buf,sz)){
+                if(!i_connection.sendBody(i_buf,sz)){
                     break;
                 }
                 //switch other session
@@ -179,25 +172,67 @@
     fclose(fp);
 }    
 
+NyLPC_TBool flip_url_prefix(char* buf, int buf_len, const char* url_prefix, const char* file_path)
+{
+    size_t bl = strlen(url_prefix);
+    size_t al = strlen(file_path)+2;
+    if (al - bl + strlen(buf) + 1 > buf_len){
+        return NyLPC_TBool_FALSE;
+    }
+    if (strncmp(buf, url_prefix, bl) == 0){
+        memmove(buf + al, buf + bl, strlen(buf) - bl + 1);
+        memcpy(buf + 1, file_path, al - 1);
+        *(buf + al - 1) = '/';
+    }
+    return NyLPC_TBool_TRUE;
+}
 
 namespace MiMic
 {
-    ModLocalFileSystem::ModLocalFileSystem(const char* i_path,unsigned char i_fs_type):ModBaseClass(i_path)
+    ModLocalFileSystem::ModLocalFileSystem(const char* i_path,const char* i_root_alias,unsigned char i_fs_type):ModBaseClass()
     {
-        this->_fs_type=i_fs_type;
+        this->setParam(i_path,i_root_alias,i_fs_type);
+    }
+    ModLocalFileSystem::ModLocalFileSystem(const char* i_path,unsigned char i_fs_type):ModBaseClass()
+    {
+        this->setParam(i_path,NULL,i_fs_type);
     }
     ModLocalFileSystem::ModLocalFileSystem():ModBaseClass()
     {
+        this->_root_alias=NULL;
     }
     ModLocalFileSystem::~ModLocalFileSystem()
     {
     }
+    void ModLocalFileSystem::setParam(const char* i_path,const char* i_root_alias,unsigned char i_fs_type)
+    {
+        NyLPC_Assert(strlen(i_root_alias)>0);
+        ModBaseClass::setParam(i_path);
+        this->_root_alias=i_root_alias;
+        this->_fs_type=i_fs_type;
+    }
     void ModLocalFileSystem::setParam(const char* i_path,unsigned char i_fs_type)
     {
-        ModBaseClass::setParam(i_path);
-        this->_fs_type=i_fs_type;
+        this->setParam(i_path,NULL,i_fs_type);
     }
-  
+    bool ModLocalFileSystem::canHandle(HttpdConnection& i_connection)
+    {
+        if(this->_root_alias==NULL){
+            return ModBaseClass::canHandle(i_connection);
+        }
+        //root alias指定がある場合
+        if(!NyLPC_cHttpdConnection_getReqStatus(i_connection._ref_inst)==NyLPC_cHttpdConnection_ReqStatus_REQPARSE)
+        {
+            return NyLPC_TBool_FALSE;
+        }        
+        const NyLPC_TChar* in_url;
+        in_url=NyLPC_cHttpdConnection_getUrlPrefix(i_connection._ref_inst);
+        size_t base_url_len=strlen(this->_root_alias);
+        if(strncmp(this->_root_alias,in_url,base_url_len)!=0){
+            return false;
+        }
+        return true;
+    }  
     bool ModLocalFileSystem::execute(HttpdConnection& i_connection)
     {
         //check platform
@@ -233,15 +268,33 @@
             }
             NyLPC_cModUrl_finalize(&mod);
         }
+        //パスのエイリアスがあるときはここで編集
+        if(this->_root_alias!=NULL){
+            flip_url_prefix(buf,Httpd::SIZE_OF_HTTP_BUF,this->_root_alias,this->_path);
+        }
         UrlReader url(buf);
         if(url.hasQueryKey("list")){
             // if path has '/?list' query key,return directory information
-            retDirJson(url,buf,i_connection,this->_fs_type);
+            const char* t;
+            int l;
+            url.getPath(t,l);
+            buf[l]='\0';//split path
+            //remove '/'
+            if(buf[l-1]=='/'){
+                buf[l-1]='\0';
+            }
+            retDirJson(buf,i_connection,this->_fs_type);
         }else if(strchr(buf,'?')==NULL && strchr(buf,'#')==NULL && buf[strlen(buf)-1]=='/'){
             //return directory html when URL has not bookmark and URL query and terminated by '/'.
-            retDirHtml(url,buf,i_connection,this->_fs_type);
+            buf[strlen(buf)-1]='\0';//convert to dir path
+            retDirHtml(buf,i_connection,this->_fs_type);
         }else{
-            retFile(url,buf,i_connection);
+            //split URL path and query
+            const char* t;
+            int l;
+            url.getPath(t,l);
+            buf[l]='\0';
+            retFile(buf,i_connection);
         }
         //Httpd unlock
         i_connection.unlockHttpd();
--- a/mbed/mod/ModLocalFileSystem.h	Sun Mar 15 09:33:38 2015 +0000
+++ b/mbed/mod/ModLocalFileSystem.h	Mon Mar 16 14:19:16 2015 +0000
@@ -28,11 +28,19 @@
     private:
         /** file system type*/
         unsigned char _fs_type;
+        /** ルートディレクトリのプレフィクス "/pathname/" 表記*/        
+        const char* _root_alias;
+    private:
+        void retFile(char* i_buf,HttpdConnection& i_connection);
+        void retDirHtml(const char* i_buf,HttpdConnection& i_connection,unsigned char i_fs_type);
+        void retDirJson(const char* buf,HttpdConnection& i_connection,unsigned char i_fs_type);
+        
     public:
         const static unsigned char FST_DEFAULT=0x00;
         const static unsigned char FST_SDFATFS=0x01;
     public:
         /**
+         * Create filesistem responder.
          * @param i_fs_type
          * Filesystem type.
          * This value should match the file system type of mount point.
@@ -42,9 +50,23 @@
          * </ul>
          */
         ModLocalFileSystem(const char* i_path,unsigned char i_fs_type=FST_DEFAULT);
+        /**
+         * 2nd constructor.
+         * @param i_root_alias
+         * Root path string. Handler replaces the accepted URL prefix in the root path.
+         * ex. '/' or '/virtual_path/',
+         */
+        ModLocalFileSystem(const char* i_path,const char* i_root_alias,unsigned char i_fs_type=FST_DEFAULT);
+        /**
+         * 3rd donstructor.
+         * Must be call setParam method before call execute.
+         */
         ModLocalFileSystem();
         virtual ~ModLocalFileSystem();
         void setParam(const char* i_path,unsigned char i_fs_type=FST_DEFAULT);
+        void setParam(const char* i_path,const char* i_root_alias,unsigned char i_fs_type=FST_DEFAULT);
+        virtual bool canHandle(HttpdConnection& i_connection);
+       
         bool execute(HttpdConnection& i_connection);
     };