int SaoriClient::request( const vector<string>& i_argument, bool i_is_secure, string& o_result, vector<string>& o_value) { //--------------------- // リクエスト作成 strpairvec data; int idx=0; for ( vector<string>::const_iterator i=i_argument.begin() ; i!=i_argument.end() ; ++i,++idx ) { data.push_back( strpair(string("Argument")+itos(idx), *i) ); } data.push_back( strpair("SecurityLevel", (i_is_secure ? "Local" : "External") ) ); //--------------------- // リクエスト実行 strpairvec r_data; int return_code = this->SakuraDLLClient::request("EXECUTE", data, r_data); //--------------------- // 返答を解析 string result; for ( strpairvec::const_iterator i = r_data.begin() ; i != r_data.end() ; ++i ) { const string& key = i->first; const string& value = i->second; if ( compare_head(key, "Value") && isdigit(key[strlen("Value")]) ) { const int pos = atoi(key.c_str() + strlen("Value")); if ( pos<0 || pos>65536 ) { continue; } if ( o_value.size() <= pos ) { o_value.resize(pos+1); } o_value[pos] = value; } else if ( key=="Result" ) { o_result = value; } } return return_code; }
// リクエストを送り、レスポンスを受け取る。戻り値はリターンコード。 int SakuraClient::request( const string& i_protocol, const string& i_protocol_version, const string& i_command, const strpairvec& i_data, string& o_protocol, string& o_protocol_version, strpairvec& o_data) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // リクエスト文字列を作成 string request = i_command + " " + i_protocol + "/" + i_protocol_version + CRLF; for ( strpairvec::const_iterator it = i_data.begin() ; it != i_data.end() ; ++it ) { request += it->first + ": " + it->second + CRLF; } request += CRLF; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // リクエスト実行 string response = this->request(request); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // お返事を解析 // 一行目を切り出し o_protocol = cut_token(response, "/"); o_protocol_version = cut_token(response, " "); int return_code = atoi( cut_token(response, " ").c_str() ); string return_string = cut_token(response, CRLF); // 以降のデータ行を切り出し while ( response.size() > 0 ) { string value = cut_token(response, CRLF); string key = cut_token(value, ": "); o_data.push_back( strpair(key, value) ); } return return_code; }
int Satori::request( const string& i_protocol, const string& i_protocol_version, const string& i_command, const strpairvec& i_data, string& o_protocol, string& o_protocol_version, strpairvec& o_data) { SenderEnableBuffering seb(GetSender()); //------------------------------------------------- // リクエスト単位のクラスメンバを初期化 mRequestMap.clear(); mRequestID = ""; mReferences.clear(); mReferences.reserve(8); // 最小値 // 引数をクラスメンバに設定 mRequestCommand = i_command; mRequestType = i_protocol; mRequestVersion = i_protocol_version; mStatusLine = i_command + " " + i_protocol + "/" + i_protocol_version; // 返すプロトコルのデフォルト値 o_protocol = "SHIORI"; o_protocol_version = "3.0"; // 喋るごとに初期化する変数 return_empty = false; surface_restore_at_talk_onetime = SR_INVALID; auto_anchor_enable_onetime = auto_anchor_enable; is_quick_section = false; // スクリプトヘッダ header_script = ""; // プロトコルを判別 if ( i_protocol=="SAORI" && i_protocol_version[0]>='1' ) { o_protocol = i_protocol; o_protocol_version = "1.0"; mRequestMode = SAORI; } else if ( i_protocol=="SHIORI" && i_protocol_version[0]>='3' ) { mRequestMode = SHIORI3; } else if ( i_protocol=="SHIORI" && i_protocol_version[0]=='2' ) { mRequestMode = SHIORI2; // 2.xにもバージョンとしては3.0を返す } else if ( i_protocol=="MAKOTO" && i_protocol_version[0]>='2' ) { o_protocol = i_protocol; o_protocol_version = "2.0"; mRequestMode = MAKOTO2; } else if ( i_protocol=="UNKNOWN" ) { mRequestMode = UNKNOWN; } else { // 未対応のプロトコルだった。 return 400; } // データ部をmRequestMapに格納。 // SHOIRI/3.0以外のプロトコルの場合、SHOIRI/3.0に変換を行う。 for ( strpairvec::const_iterator it = i_data.begin() ; it != i_data.end() ; ++it ) { string key = it->first; const string& value = it->second; switch ( mRequestMode ) { case SAORI: if ( compare_head(key, "Argument") ) { int n = stoi_internal(key.c_str()+8); if ( n==0 ) key = "ID"; else key = "Reference" + itos(n-1); } break; case SHIORI2: // こっちはてきとー if ( key=="Event" ) key="ID"; break; case MAKOTO2: if ( key=="String" ) key="Reference0"; break; default: break; } mRequestMap[key] = value; if ( compare_head(key, "Reference") ) { int n = stoi_internal(key.c_str()+9); if ( n>=0 && n<65536 ) { if ( n>=mReferences.size() ) mReferences.resize(n+1); mReferences[n]=value; } } } if ( mRequestMode == MAKOTO2 ) { mRequestMap["ID"] = "OnMakoto"; } mRequestID = mRequestMap["ID"]; mIsMateria = ( mRequestMap["Sender"] == "embryo" ); mIsStatusHeaderExist = ( mRequestMap["Sender"] == "SSP" ); //------------------------------------------------- // リクエストを解釈 if ( mRequestCommand=="GET Version" ) { if ( mRequestMode == SHIORI2 ) { o_data.push_back( strpair("ID", gSatoriName) ); o_data.push_back( strpair("Craftman", gSatoriCraftman) ); o_data.push_back( strpair("Version", gSatoriVersion) ); } return 200; } // 選択分岐記録を変数に代入。ref0を元に戻す。 if ( compare_head(mRequestID, "OnChoice") ) // OnChoiceSelect/OnChoiceEnterの両方 { strvec vec; int ref_no = ( mRequestID=="OnChoiceEnter" || mRequestID=="OnChoiceSelectEx" )?1:0; string& info = mRequestMap[string("Reference")+itos(ref_no)]; if ( split(info, byte1_dlmt, vec)==3 ) // \1区切りの3文字列であるならば { info=mReferences[ref_no]=variables["選択ID"]=vec[0]; variables["選択ラベル"]=vec[1]; variables["選択番号"]=vec[2]; } } // ログについて色々 bool log_disable_soft = ( mRequestID=="OnSurfaceChange" || mRequestID=="OnSecondChange" || mRequestID=="OnMinuteChange" || mRequestID=="OnMouseMove" || mRequestID=="OnTranslate"); bool log_disable_hard = ( /*compare_tail(mRequestID, "caption") || */compare_tail(mRequestID, "visible") || compare_head(mRequestID, "menu.") || mRequestID.find(".color.")!=string::npos ); GetSender().next_event(); if(fRequestLog) { GetSender().sender() << "--- Request ---" << std::endl << mStatusLine <<std::endl; // << iRequest <<std::endl; for(strmap::const_iterator i=mRequestMap.begin() ; i!=mRequestMap.end() ; ++i) if ( !i->first.empty() && !i->second.empty() && i->first!="SecurityLevel" && i->first!="Sender" && i->first!="Charset" ) { GetSender().sender() << i->first << ": " << i->second <<std::endl; } } // せきゅあ? strmap::const_iterator it = mRequestMap.find("SecurityLevel"); secure_flag = ( it!=mRequestMap.end() && stricmp(it->second.c_str(), "local")==0 ); // メイン処理 GetSender().sender() << "--- Operation ---" << std::endl; int status_code = 500; if ( mRequestID=="enable_log" || mRequestID=="enable_debug" ) { if ( secure_flag ) { bool flag = false; if ( mReferences.size() > 0 ) { flag = atoi(mReferences[0].c_str()) != 0; } if ( mRequestID=="enable_debug" ) { fDebugMode = flag; } else { GetSender().validate(flag); } status_code = 200; } else { GetSender().sender() << "local/Localでないので蹴りました: ShioriEcho" <<std::endl; status_code = 403; } } else if ( mRequestID=="ShioriEcho" ) { // ShioriEcho実装 if ( fDebugMode && secure_flag ) { string result = SentenceToSakuraScriptExec_with_PreProcess(mReferences); if ( result.length() ) { static const char* const dangerous_tag[] = {"\\![updatebymyself]", "\\![vanishbymyself]", "\\![enter,passivemode]", "\\![enter,inductionmode]", "\\![leave,passivemode]", "\\![leave,inductionmode]", "\\![lock,repaint]", "\\![unlock,repaint]", "\\![biff]", "\\![open,browser", "\\![open,mailer", "\\![raise", "\\j["}; std::string replace_to; for ( int i = 0 ; i < (sizeof(dangerous_tag)/sizeof(dangerous_tag[0])) ; ++i ) { replace_to = "¥["; replace_to += dangerous_tag[i]+2; //\をヌキ replace(result,dangerous_tag[i],replace_to); } //Translate(result); - Translateは後でかかる mResponseMap["Value"] = result; status_code = 200; } else { status_code = 204; } } else { if ( fDebugMode ) { GetSender().sender() << "local/Localでないので蹴りました: ShioriEcho" <<std::endl; status_code = 403; } else { static const std::string dbgmsg = "デバッグモードが無効です。使用するためには$デバッグ=有効にしてください。: ShioriEcho"; GetSender().sender() << dbgmsg <<std::endl; mResponseMap["Value"] = "\\0" + dbgmsg + "\\e"; status_code = 200; } } } else if (mRequestID == "SatolistEcho"){ #ifndef POSIX // さとりすとデバッガ実装 if (fDebugMode && secure_flag) { //R0は除去される strvec customRef; for (int i = 1; i < mReferences.size(); i++){ customRef.push_back(mReferences[i]); } string result = SentenceToSakuraScriptExec_with_PreProcess(customRef); if (result.length()) { result = string("SSTP 200 OK\r\nCharset: Shift_JIS\r\nResult: ") + result + "\r\n\r\n"; } else{ //情報なし result = string("SSTP 204 No Content\r\nCharset: Shift_JIS\r\n\r\n"); } char* copyData = new char[result.length() + 1]; strcpy(copyData, result.c_str()); COPYDATASTRUCT cds; cds.dwData = 0; cds.cbData = result.length() + 1; cds.lpData = copyData; DWORD ret; SendMessageTimeout((HWND)stoi_internal(mReferences[0]), WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds, 0, 1000, &ret); //ここで204を返すと非対応時のエラーを出すので200で通知メッセージを表示する status_code = 200; mResponseMap["Value"] = "\\0\\_q■情報を送信しました。\\e"; } else { if (fDebugMode) { GetSender().sender() << "local/Localでないので蹴りました: SatolistEcho" <<std::endl; status_code = 403; } else { static const std::string dbgmsg = "デバッグモードが無効です。使用するためには$デバッグ=有効にしてください。: SatolistEcho"; GetSender().sender() << dbgmsg <<std::endl; mResponseMap["Value"] = "\\0" + dbgmsg + "\\e"; status_code = 200; } } #endif // POSIX } else { status_code = CreateResponse(mResponseMap); } // 後処理1 default_surface = next_default_surface; //-------------------------------------------------------------------- // Valueに対する最終処理 if ( status_code==200 ) { // && compare_head(mRequestID, "On") strmap::iterator i = mResponseMap.find("Value"); if ( i!=mResponseMap.end() ) { if ( return_empty ) { status_code = 204; mResponseMap.erase(i); } else { if ( !Translate(i->second) ) { status_code = 204; mResponseMap.erase(i); } else { second_from_last_talk = 0; if ( compare_head(mRequestID, "On") ) { mResponseHistory.push_front(i->second); if ( mResponseHistory.size() >= RESPONSE_HISTORY_SIZE ) mResponseHistory.pop_back(); } } } } } GetSender().sender() << "status code : " << itos(status_code) <<std::endl; //-------------------------------------------------------------------- for(strmap::const_iterator i=mResponseMap.begin() ; i!=mResponseMap.end() ; ++i) { string key=i->first, value=i->second; switch ( mRequestMode ) { case SAORI: if ( key=="Value" ) { key = "Result"; value = header_script + value; } else if ( compare_head(key, "Reference") ) { key = string() + "Value" + (key.c_str()+9); } break; case SHIORI2: if ( key=="Value" ) { key = "Sentence"; value = header_script + value; } break; case MAKOTO2: if ( key=="Value" ) { key = "String"; value = header_script + value; } break; default: if ( key=="Value" ) { value = header_script + value; } break; } o_data.push_back( strpair(key, value) ); } if ( GetSender().errsender().get_log_mode() ) { const std::vector<string> &errlog = GetSender().errsender().get_log(); std::string errmsg; std::string errlevel; for ( std::vector<string>::const_iterator itr = errlog.begin() ; itr != errlog.end(); ++itr ) { errmsg += "SATORI - "; errmsg += mRequestID; errmsg += " > "; errmsg += *itr; errmsg += "\1"; errlevel += "critical\1"; } if ( errmsg.length() ) { errmsg.erase(errmsg.end()-1,errmsg.end()); errlevel.erase(errlevel.end()-1,errlevel.end()); o_data.push_back( strpair("ErrorLevel",errlevel) ); o_data.push_back( strpair("ErrorDescription",errmsg) ); } GetSender().errsender().clear_log(); } GetSender().validate(); if(fResponseLog) { GetSender().sender() << "--- Response ---" <<std::endl << mResponseMap <<std::endl; } mResponseMap.clear(); if ( log_disable_hard ) { GetSender().delete_last_request(); } else if ( log_disable_soft ) { if ( status_code != 200 ) { GetSender().delete_last_request(); } } GetSender().flush(); //-------------------------------------------------------------------- // リロード処理 if ( reload_flag ) { reload_flag = false; string tmp = mBaseFolder; GetSender().sender() << "■■reloading." <<std::endl; unload(); load(tmp); GetSender().sender() << "■■reloaded." <<std::endl; GetSender().flush(); } return status_code; }
string SakuraDLLHost::request(const string& i_request_string) { //GetSender().sender() << "--- Request ---" << endl << i_request_string << endl; // HTTPもどき形式の要求文字列を解析する // restには未解釈の「残り」が入っている string rest = i_request_string; // 一行目を切り出し string command = cut_token(rest, CRLF); // 後ろから ' ' を探し、見つかればそれ以降をプロトコル部分として認識する string protocol, protocol_version; for ( int n = command.size()-1 ; n >= 0 ; --n ) { if ( command[n] == ' ' ) { protocol_version = command.substr(n+1); // いったん全部を預けて…… protocol = cut_token(protocol_version, "/"); // /より前を取り出す。 /が無ければ全部貰い受ける command = command.substr(0, n); break; } } // 以降のデータ行を切り出し strpairvec data; while ( rest.size() > 0 ) { string value = cut_token(rest, CRLF); string key = cut_token(value, ": "); data.push_back( strpair(key, value) ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // リクエストを実行する // 戻り値格納用オブジェクト string r_protocol, r_protocol_version; strpairvec r_data; int r_return_code = request( protocol, protocol_version, command, data, r_protocol, r_protocol_version, r_data); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // 返答をHTTPもどき文字列形式として構築し、返す。 string response; response += r_protocol + "/" + r_protocol_version + " "; switch ( r_return_code ) { case 200: response += "200 OK"; break; case 204: response += "204 No Content"; break; case 400: response += "400 Bad Request"; break; default: response += "500 Internal Server Error"; break; } response += CRLF; // Charsetが無ければ付ける。 bool charset_exists = false; for (strpairvec::const_iterator ite = r_data.begin(); ite != r_data.end(); ite++) { if (ite->first == "Charset") { charset_exists = true; break; } } if (!charset_exists) { r_data.push_back(strpair("Charset", "Shift_JIS")); } for ( strpairvec::const_iterator i = r_data.begin() ; i != r_data.end() ; ++i ) { response += i->first + ": " + i->second + CRLF; } response += CRLF; //GetSender().sender() << "--- Response ---" << endl << response << endl; return response; }
int CodeWriter::initStyle(std::string stylefile) { const unsigned int BUFFERSIZE = 300; char buf[BUFFERSIZE]; // 버퍼 초기화 memset(buf, BUFFERSIZE, 0); char delim[] = "\n"; char *ptr; bool flag = false; //std::string stylefileFullname = m_homeDir + "/" + stylefile; std::string stylefileFullname = stylefile; m_file_style = fopen(stylefileFullname.c_str(), "r"); if(m_file_style == NULL) return -1; //패턴파일을 한줄씩 읽으면서 while(fgets(buf, BUFFERSIZE, m_file_style) != NULL) { // 문자열 분리하여 출력하기 ptr = (char*)strtok(buf, delim); if(ptr==NULL){ //printf("\n"); } else{ //printf("%s\n", ptr); std::string line = Estring::trim(std::string(ptr)); if(line=="$start_inline"){ flag = true; } else if(line=="$end_inline") break; else if(line==""){ //공백라인인 경우 } else if(flag){ std::vector<std::string> sline = Estring::split(line, "@"); std::string key = Estring::trim(sline[0]); std::string elem = sline[1]; if(key!="" && elem != "") //블록인 경우 if(Estring::trim(elem) == "$start_block"){ elem = ""; std::string end = "$end_block"; while(1){ fgets(buf, BUFFERSIZE, m_file_style); ptr = (char*)strtok(buf, delim); if(ptr != NULL){ if(end.compare( Estring::trim(ptr))==0) break; elem.append(ptr); } elem.append("\n"); } } //삽입 m_ptable.insert(strpair(key, elem)); } } memset(buf, BUFFERSIZE, 0); } fclose(m_file_style); return 0; }