WIZwiki-REST-io ver.2 Add POST Method

Dependencies:   MbedJSONValue_copy WIZnetInterface mbed

Fork of WIZwiki-REST_mc by Lawrence Lee

Files at this revision

API Documentation at this revision

Comitter:
joon874
Date:
Tue May 31 10:31:30 2016 +0000
Parent:
3:31ffbba7e8e9
Commit message:
WIZwiki-REST-io ver.2 ; Add POST Method

Changed in this revision

HTTPServer.cpp Show annotated file Show diff for this revision Revisions of this file
HTTPServer.h Show annotated file Show diff for this revision Revisions of this file
MbedJSONValue.lib Show annotated file Show diff for this revision Revisions of this file
RequestHandler.cpp Show annotated file Show diff for this revision Revisions of this file
RequestHandler.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 31ffbba7e8e9 -r 0b5a199e91f3 HTTPServer.cpp
--- a/HTTPServer.cpp	Tue May 03 02:21:56 2016 +0000
+++ b/HTTPServer.cpp	Tue May 31 10:31:30 2016 +0000
@@ -104,22 +104,22 @@
         printf("Type = %s\r\n", request_type);
 #endif        
             
-                if(request_type)
+        if(request_type)
         {
-                      request = strtok(NULL, "  \r\n");                                                 // corrested  " " -> " /"     : /Name -> Name
+            request = strtok(NULL, "  \r\n");                                                 // corrested  " " -> " /"     : /Name -> Name
             if(request)
             {
 #ifdef DEBUG_HTTP                                    
                     printf("URI = %s\r\n", request);
 #endif                    
-                        }
-                        else
-                        {
-              strcpy(rest_result, "Invaild URI");
+             }
+             else
+             {
+                    strcpy(rest_result, "Invaild URI");
 #ifdef DEBUG_HTTP                              
-                            printf("%s\r\n",rest_result);
+                    printf("%s\r\n",rest_result);
 #endif                            
-              return HTTP_INVALID_URI;
+                    return HTTP_INVALID_URI;
             }
         }
     }
@@ -133,7 +133,17 @@
     //if(itor != NULL)
         //itor->handle(request, rest_result.c_str());
     if(itor->second != NULL)
-        itor->second->handle(request, rest_result);
+    {
+        char* request_data = 0;
+        if(!strcmp(request_type,"POST"))
+        {
+            request_data = strstr(request+strlen(request)+1, "\r\n\r\n");
+#ifdef DEBUG_HTTP
+            printf("POST:request_data=%s\r\n",request_data+4);
+#endif
+        }
+        itor->second->handle(request, request_data, rest_result);
+    }
     else
     {
         strcpy(rest_result, "Invalid request handler");
diff -r 31ffbba7e8e9 -r 0b5a199e91f3 HTTPServer.h
--- a/HTTPServer.h	Tue May 03 02:21:56 2016 +0000
+++ b/HTTPServer.h	Tue May 31 10:31:30 2016 +0000
@@ -19,8 +19,8 @@
 }HTTP_RESULT;
 
 
-static  char HTTPBUF[512] ={0,};
-static  char rest_result[512] = {0,};
+static  char HTTPBUF[600] = {0,};
+static  char rest_result[532] = {0,};
 
 class HTTPServer
 {
diff -r 31ffbba7e8e9 -r 0b5a199e91f3 MbedJSONValue.lib
--- a/MbedJSONValue.lib	Tue May 03 02:21:56 2016 +0000
+++ b/MbedJSONValue.lib	Tue May 31 10:31:30 2016 +0000
@@ -1,1 +1,1 @@
-https://developer.mbed.org/users/joon874/code/MbedJSONValue1/#174bc7a49aa2
+https://developer.mbed.org/users/joon874/code/MbedJSONValue_copy/#fb820325a830
diff -r 31ffbba7e8e9 -r 0b5a199e91f3 RequestHandler.cpp
--- a/RequestHandler.cpp	Tue May 03 02:21:56 2016 +0000
+++ b/RequestHandler.cpp	Tue May 31 10:31:30 2016 +0000
@@ -6,7 +6,9 @@
 
 extern MbedJSONValue WIZwikiREST;
 
-void GetRequestHandler::handle(char* rest_uri, char *reply)
+MbedJSONValue*    pDataJson = 0;
+
+void GetRequestHandler::handle(char* rest_uri, char* request_data, char *reply)
 {
     MbedJSONValue* tmpJson;
 
@@ -16,55 +18,46 @@
 #ifdef DEBUG_HTTPREQ
     printf("GetRequestHandler():%s\r\n",rest_uri);
 #endif    
-    if(!strcmp(rest_uri, "/"))
-    {
+    if(!strcmp(rest_uri, "/")){
         tmpJson = &WIZwikiREST;     
     }
-    else
-    {
-        tok = strtok_r(rest_uri+1, "/", &last);             // 20160226
+    else{
+        tok = strtok_r(rest_uri+1, "/", &last);
         tmpJson = &WIZwikiREST;
         
-        char depth = 0;
         char* name = 0;
         while(tok)
         {
 #ifdef DEBUG_HTTPREQ            
-            printf("tok = %s \r\n", tok);               // Name
+            printf("tok = %s \r\n", tok);
 #endif            
-            if(tmpJson->hasMember(tok))
-            {
+            if(tmpJson->hasMember(tok)){
                 tmpJson = &((*tmpJson)[tok]);
                 name = tok;
                 tok = strtok_r(0, "/", &last);
-                depth++;
             }
-            else
-            {
+            else{
 #ifdef DEBUG_HTTPREQ                
                 printf("No Member\r\n");
 #endif                
                 break;
             }
         }
-        if(name)
-        {
-            if(tok)
-            {
-                if(tmpJson->accessible)
-                {
+        if(name){
+            if(tok){
+                if(tmpJson->accessible){
 #ifdef DEBUG_HTTPREQ                    
                     printf("accessible : tmpJson->size()=%d\r\n",tmpJson->size());
 #endif                    
                     
-                    if(tmpJson->size() > 0) {
+                    if(tmpJson->size() > 0){
                         *tmpJson = std::string(tok); 
                         tmpJson->cb_action((void*)tok); 
 #ifdef DEBUG_HTTPREQ                        
                         printf("set string:%s\r\n",tok);
 #endif
                     }
-                    else                    {
+                    else{
                         *tmpJson = atoi(tok); 
                         tmpJson->cb_action(&tmpJson->_value); 
 #ifdef DEBUG_HTTPREQ                        
@@ -72,8 +65,7 @@
 #endif                        
                     }
                 }
-                else
-                {
+                else{
                     strcpy (reply, "HTTP/1.1 403 OK\r\n");
                     strcat (reply, "Sever: WIZwiki-REST\r\n");
                     strcat (reply, "content-Type: text/json\r\n");
@@ -84,8 +76,7 @@
                 }
             }
         }
-        else
-        {
+        else{
             strcpy (reply, "HTTP/1.1 404 OK\r\n");
             strcat (reply, "Sever: WIZwiki-REST\r\n");
             strcat (reply, "content-Type: text/json\r\n");
@@ -106,10 +97,190 @@
     return;
 }
 
-void PutRequestHandler::handle(char* rest_uri, char *reply)
+void PostRequestHandler::handle(char* rest_uri, char* request_data, char *reply)
+{
+    MbedJSONValue* tmpJson;
+      char* tok;
+      char* last;
+      int errnum = 200;
+      
+#ifdef DEBUG_HTTPREQ
+    printf("PostRequestHandler():%s\r\n",request_data+4);
+#endif
+    if(!pDataJson){
+        pDataJson = new MbedJSONValue();  
+    }
+#ifdef DEBUG_HTTPREQ
+    printf("Before Parse\r\n");
+    debug_info();
+#endif
+    parse(*pDataJson,(const char*)request_data);
+#ifdef DEBUG_HTTPREQ
+    printf("After Parse\r\n");
+    debug_info();
+    printf("DataJson._type=%d\r\n",pDataJson->_type);
+    printf("DataJson=%s\r\n",pDataJson->serialize().c_str());
+    printf("DataJson.size()=%d\r\n",pDataJson->size());
+    printf("DataJason.type=%d\r\n",pDataJson->_type);
+#endif    
+
+    if(!strcmp(rest_uri, "/")){
+        tmpJson = &WIZwikiREST;     
+    }
+    else{
+        tok = strtok_r(rest_uri+1, "/", &last);
+        tmpJson = &WIZwikiREST;
+        
+        char* name = 0;
+        while(tok)
+        {
+#ifdef DEBUG_HTTPREQ            
+            printf("tok = %s \r\n", tok);
+#endif            
+            if(tmpJson->hasMember(tok)){
+                tmpJson = &((*tmpJson)[tok]);
+                name = tok;
+                tok = strtok_r(0, "/", &last);
+            }
+            else{
+#ifdef DEBUG_HTTPREQ                
+                printf("No Member\r\n");
+#endif                
+                break;
+            }
+        }
+        if(name){
+#ifdef DEBUG_HTTPREQ                            
+            printf("Token_name=%s\r\n",name);
+#endif
+            if(tok){
+#ifdef DEBUG_HTTPREQ                                            
+                printf("It should be no parameters : tok=%s\r\n",tok);
+#endif                
+                errnum = 403;
+            }
+        }
+        else{
+            errnum = 404;
+        }
+    }
+    if(errnum != 0){
+        switch(pDataJson->_type)
+        {
+            case MbedJSONValue::TypeInt:
+                if(tmpJson->accessible){
+                    *tmpJson = pDataJson->_value.asInt; 
+                    tmpJson->cb_action(&tmpJson->_value); 
+#ifdef DEBUG_HTTPREQ                        
+                    printf("set int:%d\r\n",atoi(tok));
+#endif                        
+                }
+                else{
+                    errnum = 403;
+                }
+                break;
+                
+            case MbedJSONValue::TypeString:
+                if(tmpJson->accessible){
+                    *tmpJson = pDataJson->_value.asString;
+                }
+                else{
+                    errnum = 403;
+                }
+                break;
+                
+            case MbedJSONValue::TypeObject:
+                for(int i = 0; i < pDataJson->index_token; i++)
+                {
+                    tok = (char*)pDataJson->token_name[i]->c_str();
+#ifdef DEBUG_HTTPREQ                                                
+                    printf("pDataJson.token_name[%d]->c_str()=%s\r\n",i,tok);
+#endif                    
+                    if(tmpJson->hasMember(tok)){
+                        if((*tmpJson)[tok].accessible){
+                            errnum = 200;
+                            if((*pDataJson)[i].size() > 0){
+                                (*tmpJson)[tok] = (*pDataJson)[i]._value.asString;
+#ifdef DEBUG_HTTPREQ                                                            
+                                printf("String Updated: %s : %s\r\n", tok,(*tmpJson)[tok].get<std::string>().c_str());
+#endif                                
+                            }
+                            else{
+                                (*tmpJson)[tok] = (*pDataJson)[i]._value.asInt;
+                                (*tmpJson)[tok].cb_action((void*)&((*pDataJson)[i]._value.asInt)); 
+#ifdef DEBUG_HTTPREQ
+                                printf("Int Updated: %s : %d\r\n", tok,(*tmpJson)[tok].get<int>());
+#endif                                
+                            }
+                        }
+                        else{
+                            errnum = 403; break;
+                        }
+                    }
+                    else{
+                        errnum = 404; break;
+                    }
+                }
+                break;
+                
+            default:
+                errnum = 403; break;
+        }    
+    }
+        
+    switch(errnum)
+    {
+        case 403:
+                strcpy (reply, "HTTP/1.1 403 OK\r\n");
+                strcat (reply, "Sever: WIZwiki-REST\r\n");
+                strcat (reply, "content-Type: text/json\r\n");
+                sprintf(reply + strlen(reply), "Content-Length: %d\r\n\r\n", 26+4);
+                strcat(reply, "{\"Result : No Accessible\"}");
+                strcat (reply, "\r\n\r\n");
+                break;
+            
+        case 404:
+                strcpy (reply, "HTTP/1.1 404 OK\r\n");
+                strcat (reply, "Sever: WIZwiki-REST\r\n");
+                strcat (reply, "content-Type: text/json\r\n");
+                sprintf(reply + strlen(reply), "Content-Length: %d\r\n\r\n", 33+4);
+                strcat(reply, "{\"Result\" : \"No defined Resource\"}");
+                strcat (reply, "\r\n\r\n");
+                break;
+            
+        case 200:
+                strcpy (reply, "HTTP/1.1 200 OK\r\n");
+                strcat (reply, "Sever: WIZwiki-REST\r\n");
+                strcat (reply, "content-Type: text/json\r\n");
+                sprintf(reply + strlen(reply), "Content-Length: %d\r\n\r\n", 15+4);
+                strcat (reply, "{\"Result\":\"OK\"}");
+                strcat (reply, "\r\n\r\n");
+                break;
+    }
+    
+#ifdef DEBUG_HTTPREQ
+    printf("Before Delete\r\n");
+    debug_info();
+#endif
+    if(pDataJson){
+#ifdef DEBUG_HTTPREQ
+        printf("type;%d, pDataJson->index_token=%d\r\n",pDataJson->_type,pDataJson->index_token);
+#endif
+        delete pDataJson;
+        pDataJson = 0;
+    }
+#ifdef DEBUG_HTTPREQ
+    printf("After Delete\r\n");
+    debug_info();
+#endif
+}
+
+/*
+void PutRequestHandler::handle(char* rest_uri, char* request_data, char *reply)
 {
 }
 
-void DeleteRequestHandler::handle(char* rest_uri, char *reply)
+void DeleteRequestHandler::handle(char* rest_uri, char* request_data, char *reply)
 {
 }
+*/
\ No newline at end of file
diff -r 31ffbba7e8e9 -r 0b5a199e91f3 RequestHandler.h
--- a/RequestHandler.h	Tue May 03 02:21:56 2016 +0000
+++ b/RequestHandler.h	Tue May 31 10:31:30 2016 +0000
@@ -3,34 +3,44 @@
 
 //#define DEBUG_HTTPREQ
 
+extern void debug_info();
+
 class RequestHandler
 {
     public :
-        
-        virtual void handle(char* rest_uri, char* reply) = 0;
+        virtual void handle(char* rest_uri, char* req_data, char* reply) = 0;
 };
 
 class GetRequestHandler : public RequestHandler
 {
     public :
-    
-        virtual void handle(char* rest_uri, char* reply);
+        virtual void handle(char* rest_uri, char* req_data, char* reply);        
+        
 };
 
+class PostRequestHandler : public RequestHandler
+{
+    public :
+        virtual void handle(char* rest_uri, char* req_data, char* reply);
+        
+};
+
+/* 
 class PutRequestHandler : public RequestHandler
 {
     public :
-        
-        virtual void handle(char* rest_uri, char* reply);
+        virtual void handle(char* rest_uri, char* req_data, char* reply);
 
 };
+*/
 
-
+/*
 class DeleteRequestHandler : public RequestHandler
 {
     public :
-            
-        virtual void handle(char* rest_uri, char* reply);
+        virtual void handle(char* rest_uri, char* req_data, char* reply);
 
 };
+*/
+
 #endif
diff -r 31ffbba7e8e9 -r 0b5a199e91f3 main.cpp
--- a/main.cpp	Tue May 03 02:21:56 2016 +0000
+++ b/main.cpp	Tue May 31 10:31:30 2016 +0000
@@ -8,6 +8,8 @@
 
 #define DHCP
 
+//#define DEBUG
+
 EthernetInterface eth;
 HTTPServer WIZwikiWebSvr;
 MbedJSONValue WIZwikiREST;
@@ -15,10 +17,13 @@
 // Enter a MAC address for your controller below.
 uint8_t mac_addr[6] = {0x00, 0x08, 0xDC, 0x00, 0x01, 0xFE};
 char mac_str[20];
-char ip_addr[] = "192.168.100.100";
-char subnet_mask[] = "255.255.255.0";
+char ip_addr[]      = "192.168.100.100";
+char subnet_mask[]  = "255.255.255.0";
 char gateway_addr[] = "192.168.100.1";
 
+GetRequestHandler myGetReq;
+PostRequestHandler myPostReq;
+
 DigitalOut LED_1(PA_1);
 DigitalOut LED_2(PA_2);
 
@@ -51,9 +56,42 @@
 DigitalInOut GP31(P31);
 DigitalInOut GP32(P32);
 
+
+bool gpio_all(void* param)
+{
+    if(!param) return false;
+    GP05.write(*(int*)param);
+    GP06.write(*(int*)param);
+    GP07.write(*(int*)param);
+    GP08.write(*(int*)param);
+    GP09.write(*(int*)param);
+    GP10.write(*(int*)param);                    
+    GP11.write(*(int*)param);
+    GP12.write(*(int*)param);
+    GP13.write(*(int*)param);
+    GP14.write(*(int*)param);
+    GP15.write(*(int*)param);
+    GP16.write(*(int*)param);                    
+    GP17.write(*(int*)param);
+    GP18.write(*(int*)param);
+    GP19.write(*(int*)param);
+    GP20.write(*(int*)param);                    
+    GP21.write(*(int*)param);
+    GP22.write(*(int*)param);
+    GP23.write(*(int*)param);
+    GP24.write(*(int*)param);
+    GP25.write(*(int*)param);
+    GP26.write(*(int*)param);                    
+    GP27.write(*(int*)param);
+    GP28.write(*(int*)param);
+    GP29.write(*(int*)param);
+    return true;
+}
+
+
 bool p5_set(void* param)
 {
-    if(!param) return false;
+     if(!param) return false;
     GP05.write(*(int*)param);
     return true;
 }
@@ -224,16 +262,21 @@
 {
     printf("SP:0x%X\r\n",__current_sp());
     __heapstats((__heapprt)fprintf,stderr);
+#ifdef DEBUG
+    __heapvalid((__heapprt)fprintf,stderr, 1);
+#endif
     printf("\r\n");
 }    
+
 void WIZwiki_REST_init();
 
 int main(void)
 {
-
-    sprintf(mac_str, "%02X:%02X:%02X:%02X:%02X:%02X",mac_addr[0],mac_addr[1],
-                                                     mac_addr[2],mac_addr[3], 
-                                                     mac_addr[4],mac_addr[5]);
+#ifdef DEBUG
+    debug_info();
+#endif
+    sprintf(mac_str, "%02X:%02X:%02X:%02X:%02X:%02X",mac_addr[0],mac_addr[1],mac_addr[2],mac_addr[3],mac_addr[4],mac_addr[5]);
+    
     //GPIO Set
     GP05.output();
     GP05.write(1);
@@ -286,28 +329,31 @@
     GP29.output();
     GP29.write(1);
 
-
     //LED Setbit
-    LED_1.write(0); // LED On
-    LED_2.write(1); // LED Off
+    //LED_1.write(0); // LED On
+    //LED_2.write(1); // LED Off
     printf("START \r\n");    
     printf("sizeof(MbedJSONValue)=%d\r\n",sizeof(MbedJSONValue));
     printf("sizeof(vector)=%d\r\n",sizeof(std::vector<string*>));
     printf("sizeof(string)=%d\r\n",sizeof(std::string));
+#ifdef DEBUG
     debug_info();
+#endif
 
     WIZwiki_REST_init();
 
+#ifdef DEBUG
     debug_info();
+#endif
                     
     // Serialize it into a JSON string
-    printf("\r\n");
     printf("-------------------------WIZwikiREST--------------------------- \r\n");
-    printf("%s\r\n", WIZwikiREST.serialize().c_str());
+    printf("\r\n%s\r\n", WIZwikiREST.serialize().c_str());
     printf("--------------------------------------------------------------- \r\n");
 
-    WIZwikiWebSvr.add_request_handler("GET", new GetRequestHandler());
-    //WIZwikiWebSvr.add_request_handler("DELETE", new DeleteRequestHandler());
+    WIZwikiWebSvr.add_request_handler("GET", &myGetReq);
+    WIZwikiWebSvr.add_request_handler("POST", &myPostReq);
+    //WIZwikiWebSvr.add_request_handler("DELETE", new PostRequestHandler());
     //WIZwikiWebSvr.add_request_handler("PUT", new PutRequestHandler());
     
     #ifdef DHCP
@@ -318,7 +364,7 @@
     
     
     printf("Check Ethernet Link\r\n");
-    //Add
+    
     do{
         printf("   Link - Wait... \r\n");
         wait(1);
@@ -334,15 +380,12 @@
         printf("   MASK : %s\r\n\r\n", eth.getNetworkMask());
         printf("   GW   : %s\r\n\r\n", eth.getGateway());
     }
-        
-    //while(1) //Wait link up
-    //{
-    //    if(eth.link() == true) 
-    //    break;
-    //}
     
     printf("Link up\r\n");
     printf("IP Address is %s\r\n", eth.getIPAddress());
+#ifdef DEBUG
+    debug_info();
+#endif
 
     if(!WIZwikiWebSvr.init(SERVER_PORT))
     {
@@ -361,30 +404,28 @@
     //Fill the object
     WIZwikiREST["Name"] = "WIZwiki-RESTful-01";
     WIZwikiREST["Name"].accessible = false;
+#ifdef DEBUG
     debug_info();
+#endif
     
     //Network
-
     WIZwikiREST["Network"]["MAC"] = mac_str;
-    debug_info();
     WIZwikiREST["Network"]["IP"] = ip_addr; 
     WIZwikiREST["Network"]["IP"].accessible = true; 
-    debug_info();
     WIZwikiREST["Network"]["SN"] = subnet_mask;  
     WIZwikiREST["Network"]["SN"].accessible = true;  
-    debug_info();
     WIZwikiREST["Network"]["GW"] = gateway_addr;
     WIZwikiREST["Network"]["GW"].accessible = true;
-    debug_info();
 
     //LEDs
-    WIZwikiREST["LED1"] = (LED_1.read() ? "Off" : "On");
-    WIZwikiREST["LED1"].accessible = true;
-    debug_info();    
-    WIZwikiREST["LED2"] = (LED_2.read() ? "Off" : "On");
-    WIZwikiREST["LED2"].accessible = true;
-    debug_info();
+    //WIZwikiREST["LED1"] = (LED_1.read() ? "Off" : "On");
+    //WIZwikiREST["LED1"].accessible = true;
+    //WIZwikiREST["LED2"] = (LED_2.read() ? "Off" : "On");
+    //WIZwikiREST["LED2"].accessible = true;
+    
     // GPIOs
+    WIZwikiREST["GPIOs"]["all"].accessible = true;
+    WIZwikiREST["GPIOs"]["all"].cb_action = gpio_all; 
     WIZwikiREST["GPIOs"]["P05"] = GP05.read();
     WIZwikiREST["GPIOs"]["P05"].accessible = true;
     WIZwikiREST["GPIOs"]["P05"].cb_action = p5_set;
@@ -439,7 +480,6 @@
     WIZwikiREST["GPIOs"]["P22"] = GP22.read();
     WIZwikiREST["GPIOs"]["P22"].accessible = true;
     WIZwikiREST["GPIOs"]["P22"].cb_action = p22_set;
-    
     WIZwikiREST["GPIOs"]["P23"] = GP23.read();
     WIZwikiREST["GPIOs"]["P23"].accessible = true;
     WIZwikiREST["GPIOs"]["P23"].cb_action = p23_set;
@@ -461,16 +501,8 @@
     WIZwikiREST["GPIOs"]["P29"] = GP29.read();
     WIZwikiREST["GPIOs"]["P29"].accessible = true;
     WIZwikiREST["GPIOs"]["P29"].cb_action = p29_set;
-/*    
-    WIZwikiREST["GPIOs"]["P30"] = GP30.read();
-    WIZwikiREST["GPIOs"]["P30"].accessible = true;
-    WIZwikiREST["GPIOs"]["P30"].cb_action = p30_set;
-    WIZwikiREST["GPIOs"]["P31"] = GP31.read();
-    WIZwikiREST["GPIOs"]["P31"].accessible = true;
-    WIZwikiREST["GPIOs"]["P31"].cb_action = p31_set;
-    WIZwikiREST["GPIOs"]["P32"] = GP32.read();
-    WIZwikiREST["GPIOs"]["P32"].accessible = true;
-    WIZwikiREST["GPIOs"]["P32"].cb_action = p32_set;
-*/
+
+#ifdef DEBUG
     debug_info();
+#endif
 }
diff -r 31ffbba7e8e9 -r 0b5a199e91f3 mbed.bld
--- a/mbed.bld	Tue May 03 02:21:56 2016 +0000
+++ b/mbed.bld	Tue May 31 10:31:30 2016 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/252557024ec3
\ No newline at end of file
+http://mbed.org/users/mbed_official/code/mbed/builds/6c34061e7c34
\ No newline at end of file