This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088
Dependents: MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more
NyLPC_cModFileIoBaseClass.c
00001 /********************************************************************************* 00002 * PROJECT: MiMic 00003 * -------------------------------------------------------------------------------- 00004 * 00005 * This file is part of MiMic 00006 * Copyright (C)2011 Ryo Iizuka 00007 * 00008 * MiMic is free software: you can redistribute it and/or modify 00009 * it under the terms of the GNU Lesser General Public License as published 00010 * by the Free Software Foundation, either version 3 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public License 00019 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00020 * 00021 * For further information please contact. 00022 * http://nyatla.jp/ 00023 * <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp> 00024 * 00025 *********************************************************************************/ 00026 #include "NyLPC_cModFileIoBaseClass.h" 00027 #include "NyLPC_stdlib.h" 00028 #include "NyLPC_http.h" 00029 #include "../NyLPC_cHttpdConnection_protected.h" 00030 #include "../NyLPC_cHttpdUtils.h" 00031 #include "NyLPC_net.h" 00032 00033 #define FNAME_MAX 48 00034 #define STRBUF_MAX 48 00035 00036 struct TModFileIoHeader 00037 { 00038 struct NyLPC_THttpBasicHeader super; 00039 NyLPC_TcUrlEncode_t urlencode; 00040 NyLPC_TUInt8 _content_id; 00041 //解析用 00042 NyLPC_TUInt8 _qery_name_id; 00043 NyLPC_TUInt8 _astate; 00044 NyLPC_TInt16 _prefix_len; 00045 NyLPC_TcStr_t _tstr; 00046 NyLPC_TChar _tstr_buf[STRBUF_MAX]; 00047 /** 文字列のパーサ*/ 00048 char fname[FNAME_MAX];//対象ファイル名の格納先 00049 }; 00050 00051 #define ST_PARSE_PATH 1 00052 #define ST_PARSE_QUERY_NAME 2 00053 #define ST_PARSE_QUERY_VALUE 3 //Query読み出し中 00054 #define ST_PARSE_QUERY_VALUE_NAME 4 00055 /** 00056 * コンテンツID定義(コンテンツ名に対応) 00057 */ 00058 #define CONTENT_ID_UPLOAD 2 00059 #define CONTENT_ID_CREATE 3 00060 #define CONTENT_ID_REMOVE 4 00061 #define CONTENT_ID_UNKNOWN 0 00062 00063 00064 #define QNAME_ID_NAME 1 00065 #define QNAME_ID_UNKNOWN 0 00066 00067 00068 static const struct NyLPC_TTextIdTbl url_tbl[]= 00069 { 00070 {"upload.api",CONTENT_ID_UPLOAD}, 00071 {"create.api",CONTENT_ID_CREATE}, 00072 {"remove.api",CONTENT_ID_REMOVE}, 00073 {NULL,CONTENT_ID_UNKNOWN} 00074 }; 00075 00076 static const struct NyLPC_TTextIdTbl qname_id_table[]= 00077 { 00078 {"name",QNAME_ID_NAME}, 00079 {NULL,QNAME_ID_UNKNOWN} 00080 }; 00081 00082 00083 00084 static NyLPC_TBool urlHandler(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out) 00085 { 00086 struct TModFileIoHeader* out=(struct TModFileIoHeader*)o_out; 00087 NyLPC_TChar c; 00088 //読み飛ばし 00089 if(out->_prefix_len<0){ 00090 out->_prefix_len++; 00091 return NyLPC_TBool_TRUE;//読み飛ばし 00092 } 00093 //Path解析 00094 if(out->_astate==ST_PARSE_PATH){ 00095 if(i_c!='\0' && i_c!='?'){ 00096 if(!NyLPC_cStr_put(&(out->_tstr),i_c)){ 00097 //ERROR 00098 NyLPC_OnErrorGoto(ERROR); 00099 } 00100 }else{ 00101 out->_content_id=NyLPC_TTextIdTbl_getMatchId(NyLPC_cStr_str(&(out->_tstr)),url_tbl); 00102 switch(out->_content_id) 00103 { 00104 case CONTENT_ID_UPLOAD: 00105 case CONTENT_ID_CREATE: 00106 case CONTENT_ID_REMOVE: 00107 break; 00108 default: 00109 NyLPC_OnErrorGoto(ERROR); 00110 } 00111 NyLPC_cStr_clear(&(out->_tstr)); 00112 out->_astate=ST_PARSE_QUERY_NAME;//クエリ名解析へ 00113 } 00114 return NyLPC_TBool_TRUE; 00115 } 00116 switch(out->_content_id) 00117 { 00118 case CONTENT_ID_UPLOAD: 00119 case CONTENT_ID_CREATE: 00120 case CONTENT_ID_REMOVE: 00121 switch(out->_astate){ 00122 case ST_PARSE_QUERY_NAME: 00123 if(i_c!='\0' && i_c!='&' && i_c!='='){ 00124 if(!NyLPC_cStr_put(&(out->_tstr),i_c)){ 00125 NyLPC_OnErrorGoto(ERROR); 00126 } 00127 }else{ 00128 //Query確定。 00129 out->_qery_name_id=NyLPC_TTextIdTbl_getMatchId(NyLPC_cStr_str(&(out->_tstr)),qname_id_table); 00130 NyLPC_cStr_clear(&(out->_tstr)); 00131 //クエリ値がある場合 00132 switch(out->_qery_name_id){ 00133 case QNAME_ID_NAME: 00134 NyLPC_cUrlEncode_reset(&out->urlencode); 00135 out->_astate=ST_PARSE_QUERY_VALUE_NAME; 00136 break; 00137 default: 00138 out->_astate=ST_PARSE_QUERY_VALUE; 00139 break; 00140 } 00141 } 00142 return NyLPC_TBool_TRUE; 00143 case ST_PARSE_QUERY_VALUE: 00144 //未知のクエリは無視 00145 if(i_c!='\0' && i_c!='&'){ 00146 }else{ 00147 //クエリ値解析完了 00148 out->_astate=ST_PARSE_QUERY_NAME; 00149 } 00150 return NyLPC_TBool_TRUE; 00151 case ST_PARSE_QUERY_VALUE_NAME: 00152 if(i_c!='\0' && i_c!='&'){ 00153 //URLデコードしながら蓄積 00154 switch(NyLPC_cUrlEncode_decode(&out->urlencode,i_c,&c)){ 00155 case NyLPC_TcUrlEncode_ST_NEXT: 00156 break; 00157 case NyLPC_TcUrlEncode_ST_DONE: 00158 if(!NyLPC_cStr_put(&(out->_tstr),c)){ 00159 NyLPC_OnErrorGoto(ERROR); 00160 } 00161 break; 00162 default: 00163 NyLPC_OnErrorGoto(ERROR); 00164 } 00165 return NyLPC_TBool_TRUE; 00166 }else{ 00167 if(NyLPC_cStr_len(&out->_tstr)<1){ 00168 //ファイル名短すぎ 00169 NyLPC_OnErrorGoto(ERROR); 00170 } 00171 //ファイル名を保存 00172 strcpy(out->fname,(const char*)NyLPC_cStr_str(&out->_tstr)); 00173 //終端しているなら、次のクエリへ 00174 out->_astate=ST_PARSE_QUERY_NAME; 00175 } 00176 return NyLPC_TBool_TRUE; 00177 default: 00178 break; 00179 } 00180 NyLPC_OnErrorGoto(ERROR); 00181 default: 00182 NyLPC_OnErrorGoto(ERROR); 00183 } 00184 return NyLPC_TBool_TRUE; 00185 ERROR: 00186 return NyLPC_TBool_FALSE; 00187 } 00188 /** 00189 * デフォルトハンドラ 00190 */ 00191 static const struct NyLPC_TcHttpBasicHeaderParser_Handler handler= 00192 { 00193 NULL, 00194 urlHandler 00195 }; 00196 00197 00198 /** 00199 * コンストラクタ。 00200 */ 00201 void NyLPC_cModFileIoBaseClass_initialize(NyLPC_TcModFileIoBaseClass_t* i_inst,const NyLPC_TChar* i_ref_root_path) 00202 { 00203 NyLPC_cModRomFiles_initialize(&i_inst->super,i_ref_root_path,NULL,0); 00204 } 00205 void NyLPC_cModFileIoBaseClass_finalize(NyLPC_TcModFileIoBaseClass_t* i_inst) 00206 { 00207 NyLPC_cModRomFiles_finalize(&i_inst->super); 00208 } 00209 /** 00210 * モジュールがコネクションをハンドリングできるかを返します。 00211 */ 00212 NyLPC_TBool NyLPC_cModFileIoBaseClass_canHandle(NyLPC_TcModFileIoBaseClass_t* i_inst,NyLPC_TcHttpdConnection_t* i_connection) 00213 { 00214 return NyLPC_cModRomFiles_canHandle(&i_inst->super,i_connection); 00215 } 00216 00217 static struct TModFileIoHeader single_header; 00218 00219 00220 /** 00221 * モジュールを実行します。 00222 */ 00223 NyLPC_TBool NyLPC_cModFileIoBaseClass_execute(NyLPC_TcModFileIoBaseClass_t* i_inst,NyLPC_TcHttpdConnection_t* i_connection) 00224 { 00225 union{ 00226 NyLPC_TcHttpBasicHeaderParser_t parser; 00227 NyLPC_TcHttpBodyParser_t body_parser; 00228 }sh; 00229 NyLPC_TUInt8 method_type; 00230 //リクエストParse済へ遷移(この関数の後はModが責任を持ってリクエストを返却) 00231 NyLPC_cHttpdConnection_setReqStatusParsed(i_connection); 00232 00233 //排他ロック 00234 NyLPC_cHttpdConnection_lock(i_connection); 00235 {//parser 00236 00237 //URL解析の準備 00238 single_header._prefix_len=-((NyLPC_TInt16)strlen(i_inst->super._ref_root_path)+2); 00239 single_header._astate=ST_PARSE_PATH; 00240 single_header.fname[0]='\0'; 00241 NyLPC_cUrlEncode_initialize(&single_header.urlencode); 00242 NyLPC_cStr_initialize(&single_header._tstr,single_header._tstr_buf,STRBUF_MAX); 00243 00244 NyLPC_cHttpBasicHeaderParser_initialize(&sh.parser,&handler); 00245 00246 //プリフェッチしたデータを流す 00247 NyLPC_cHttpBasicHeaderParser_parseInit(&sh.parser,&(single_header.super)); 00248 NyLPC_cHttpdConnection_pushPrefetchInfo(i_connection,&sh.parser,&single_header.super); 00249 //後続をストリームから取り込む 00250 if(!NyLPC_cHttpBasicHeaderParser_parseStream(&sh.parser,NyLPC_cHttpdConnection_refStream(i_connection),&(single_header.super))){ 00251 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,500); 00252 NyLPC_OnErrorGoto(Error1); 00253 } 00254 if(!NyLPC_cHttpBasicHeaderParser_parseFinish(&sh.parser,&(single_header.super))){ 00255 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,500); 00256 NyLPC_OnErrorGoto(Error1); 00257 } 00258 //HeaderParserはここで破棄(URLEncode,cSTRも) 00259 NyLPC_cHttpBasicHeaderParser_finalize(&sh.parser); 00260 NyLPC_cUrlEncode_finalize(&single_header.urlencode); 00261 NyLPC_cStr_finalize(&single_header._tstr); 00262 } 00263 //Request::ConnectionがClose設定,又はHTTP1.1では無い場合,CLOSE 00264 if(single_header.super.connection==NyLPC_THttpMessgeHeader_Connection_CLOSE || single_header.super.startline.req.version!=NyLPC_THttpVersion_11) 00265 { 00266 NyLPC_cHttpdConnection_setConnectionMode(i_connection,NyLPC_TcHttpdConnection_CONNECTION_MODE_CLOSE); 00267 } 00268 //返答フェーズ 00269 { 00270 method_type=NyLPC_cHttpdConnection_getMethod(i_connection); 00271 00272 //CGIの実行 00273 switch(single_header._content_id) 00274 { 00275 case CONTENT_ID_UPLOAD: 00276 //ファイル名とBodyParserを通知 00277 if(method_type==NyLPC_THttpMethodType_POST) 00278 { 00279 NyLPC_cHttpdConnection_send100Continue(i_connection); 00280 NyLPC_cHttpBodyParser_initialize(&sh.body_parser); 00281 NyLPC_cHttpBodyParser_parseInit(&sh.body_parser,&single_header.super); 00282 //ハンドラ内ではparseStreamのみ実行 00283 if(!i_inst->_abstruct_function.upload(i_connection,single_header.fname,&sh.body_parser)){ 00284 NyLPC_cHttpdConnection_setConnectionMode(i_connection,NyLPC_TcHttpdConnection_CONNECTION_MODE_CLOSE); 00285 } 00286 if(NyLPC_cHttpBodyParser_parseFinish(&sh.body_parser)){ 00287 NyLPC_cHttpBodyParser_finalize(&sh.body_parser); 00288 NyLPC_OnErrorGoto(Error2);//エラーメッセージはハンドラ内で送られていると仮定する。 00289 } 00290 NyLPC_cHttpBodyParser_finalize(&sh.body_parser); 00291 }else{ 00292 NyLPC_OnErrorGoto(Error2); 00293 } 00294 break; 00295 case CONTENT_ID_CREATE: 00296 if(method_type==NyLPC_THttpMethodType_GET || method_type==NyLPC_THttpMethodType_HEAD) 00297 { 00298 //イベント起動 00299 if(!i_inst->_abstruct_function.create(i_connection,single_header.fname)){ 00300 NyLPC_cHttpdConnection_setConnectionMode(i_connection,NyLPC_TcHttpdConnection_CONNECTION_MODE_CLOSE); 00301 } 00302 break; 00303 } 00304 NyLPC_OnErrorGoto(Error2_405); 00305 case CONTENT_ID_REMOVE: 00306 //ファイル名を通知 00307 if(method_type==NyLPC_THttpMethodType_GET || method_type==NyLPC_THttpMethodType_HEAD) 00308 { 00309 //イベント起動 00310 if(!i_inst->_abstruct_function.remove(i_connection,single_header.fname)){ 00311 NyLPC_cHttpdConnection_setConnectionMode(i_connection,NyLPC_TcHttpdConnection_CONNECTION_MODE_CLOSE); 00312 } 00313 break; 00314 } 00315 NyLPC_OnErrorGoto(Error2_405); 00316 default: 00317 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,400); 00318 NyLPC_OnErrorGoto(Error2); 00319 } 00320 } 00321 //占有解除 00322 NyLPC_cHttpdConnection_unlock(i_connection); 00323 return NyLPC_TBool_TRUE; 00324 Error2_405: 00325 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,405); 00326 Error2: 00327 //VM排他ロックの解除 00328 NyLPC_cHttpdConnection_unlock(i_connection); 00329 return NyLPC_TBool_FALSE; 00330 Error1: 00331 NyLPC_cHttpBasicHeaderParser_finalize(&parser); 00332 NyLPC_cStr_finalize(&single_header._tstr); 00333 NyLPC_cUrlEncode_finalize(&single_header.urlencode); 00334 //VM排他ロックの解除 00335 NyLPC_cHttpdConnection_unlock(i_connection); 00336 return NyLPC_TBool_FALSE; 00337 } 00338 00339
Generated on Tue Jul 12 2022 15:46:16 by 1.7.2