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
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 16:22:58 by
