// バス名からフォルダ名と拡張子を削除する。 void ToOnlyFileName( LPSTR buf ) { LPSTR ptr; // フォルダ名 if ( (ptr = FindFinalChar( buf, '\\' )) != NULL ) ::lstrcpy( buf, ptr+1 ); // 拡張子 if ( (ptr = FindFinalChar( buf, '.' )) != NULL ) *ptr = '\0'; }
// パス文字列の拡張子部を取得する LPCTSTR GetExtention( LPCTSTR szPath ) { LPCTSTR ext = FindFinalChar( szPath, '.' ); if ( ext == NULL ) return NULL; else return ext+1; }
// パス文字列の拡張子を変更する void SetExtention( LPTSTR szPath, LPCTSTR szNewExtention ) { LPTSTR ext = FindFinalChar( szPath, '.' ); if ( ext == NULL ) { ext = szPath + ::lstrlen(szPath); sprintf( ext, ".%s", szNewExtention ); } else strcpy( ext+1, szNewExtention ); }
// パス文字列のファイル名部分を取得する。 // 文字列中に \ 記号がない場合は、与えられた文字列をそのまま返す。 LPCTSTR GetFileName( LPCTSTR szPath ) { LPCTSTR ext = FindFinalChar( szPath, '\\' ); return ( ext == NULL ) ? szPath : ext+1 ; }
bool Satori::load(const string& iBaseFolder) { GetSender().next_event(); setlocale(LC_ALL, "Japanese"); #ifdef _WINDOWS _setmbcp(_MB_CP_LOCALE); #endif mBaseFolder = iBaseFolder; GetSender().sender() << "■SATORI::Load on " << mBaseFolder << "" << std::endl; #if POSIX // 「/」で終わっていなければ付ける。 if (mBaseFolder[mBaseFolder.size() - 1] != '/') { mBaseFolder += '/'; } #else // 「\」で終わっていなければ付ける。 if (mBaseFolder[mBaseFolder.size() - 1] != '\\') { mBaseFolder += '\\'; } #endif #ifdef _MSC_VER // 本体のあるフォルダをサーチ { TCHAR buf[MAX_PATH+1]; ::GetModuleFileName(NULL, buf, MAX_PATH); char* p = FindFinalChar(buf, DIR_CHAR); if ( p==NULL ) mExeFolder = ""; else { *(++p) = '\0'; mExeFolder = buf; } } GetSender().sender() << "本体の所在: " << mExeFolder << "" << std::endl; #endif // _MSC_VER // メンバ初期化 InitMembers(); #ifdef _MSC_VER // システムの設定を読んでおく OSVERSIONINFO ovi; ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); ::GetVersionEx(&ovi); string os; if ( ovi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) { if ( ovi.dwMinorVersion == 0 ) { mOSType=SATORI_OS_WIN95; os="Windows 95"; } else if ( ovi.dwMinorVersion == 10 ) { mOSType=SATORI_OS_WIN98; os="Windows 98"; } else if ( ovi.dwMinorVersion == 90 ) { mOSType=SATORI_OS_WINME; os="Windows Me"; } else { mOSType = SATORI_OS_UNDEFINED; os="undefined"; } } else { if ( ovi.dwMinorVersion == 0 ) { if ( ovi.dwMajorVersion == 4 ) { mOSType=SATORI_OS_WINNT; os="Windows NT"; } else if ( ovi.dwMajorVersion == 5 ) { mOSType=SATORI_OS_WIN2K; os="Windows 2000"; } } else { mOSType = SATORI_OS_WINXP; os="Windows XP or later"; } } GetSender().sender() << "OS種別: " << os << std::endl; if ( mOSType==SATORI_OS_WIN95 ) { is_single_monitor = true; } else { BOOL (WINAPI* pEnumDisplayMonitors)(HDC,LPRECT,MONITORENUMPROC,LPARAM); (FARPROC&)pEnumDisplayMonitors = ::GetProcAddress(::GetModuleHandle("user32.dll"), "EnumDisplayMonitors"); if ( pEnumDisplayMonitors==NULL ) { is_single_monitor = true; } else { RECT rectData[2]; memset(rectData,0,sizeof(rectData)); (*pEnumDisplayMonitors)(NULL,NULL,(MONITORENUMPROC)MonitorEnumFunc,(LPARAM)(rectData)); max_screen_rect = rectData[0]; desktop_rect = rectData[1]; RECT* rect; rect = &desktop_rect; GetSender().sender() << "プライマリデスクトップ: (" << rect->left << "," << rect->top << "," << rect->right << "," << rect->bottom << ")" << std::endl; rect = &max_screen_rect; GetSender().sender() << "仮想デスクトップ: (" << rect->left << "," << rect->top << "," << rect->right << "," << rect->bottom << ")" << std::endl; is_single_monitor = ( ::EqualRect(&max_screen_rect, &desktop_rect)!=FALSE ); GetSender().sender() << (is_single_monitor ? "モニタは一つだけと判断、見切れ判定を呼び出し元に任せます。" : "複数のモニタが接続されていると判断、見切れ判定は里々が行います。") << std::endl; } } #endif // _MSC_VER // 置換辞書読み取り strmap_from_file(replace_before_dic, mBaseFolder+"replace.txt", "\t"); strmap_from_file(replace_after_dic, mBaseFolder+"replace_after.txt", "\t"); // キャラデータ読み込み mCharacters.load(mBaseFolder + "characters.ini"); for ( inimap::const_iterator i=mCharacters.begin() ; i!=mCharacters.end() ; ++i ) { const strmap& m = i->second; strmap::const_iterator j; // 置換辞書に追加 j = m.find("popular-name"); if ( j != m.end() && j->second.size()>0 ) replace_before_dic[j->second + ":"] = string("\xff\x01") + zen2han(i->first); //0xff0x01はあとで変換 j = m.find("initial-letter"); if ( j != m.end() && j->second.size()>0 ) replace_before_dic[j->second + ":"] = string("\xff\x01") + zen2han(i->first); //0xff0x01はあとで変換 j = m.find("base-surface"); if ( j != m.end() && j->second.size()>0 ) system_variable_operation( string("サーフェス加算値") + i->first, j->second); } //for ( strmap::const_iterator j=replace_before_dic.begin() ; j!=replace_before_dic.end() ; ++j ) // cout << j->first << ": " << j->second << endl; // ランダマイズ randomize(); //------------------------------------------ // コンフィグ読み込み LoadDictionary(mBaseFolder + "satori_conf.txt", false); // 変数初期化実行 GetSentence("初期化"); // SAORI読み込み Family<Word>* f = words.get_family("SAORI"); mShioriPlugins->load(mBaseFolder); if ( f != NULL ) { std::vector<const Word*> els; f->get_elements_pointers(els); for (std::vector<const Word*>::const_iterator i=els.begin(); i!=els.end() ; ++i) { if ( (*i)->size()>0 && !mShioriPlugins->load_a_plugin(**i) ) { GetSender().sender() << "SAORI読み込み中にエラーが発生: " << **i << std::endl; } } } mShioriPlugins->load_default_entry(); talks.clear(); words.clear(); //------------------------------------------ // セーブデータ読み込み //bool oldConf = fEncodeSavedata; bool loadResult = LoadDictionary(mBaseFolder + "satori_savedata." + (fEncodeSavedata?"sat":"txt"), false); GetSentence("セーブデータ"); bool execResult = talks.get_family("セーブデータ") != NULL; if ( ! loadResult || ! execResult ) { loadResult = LoadDictionary(mBaseFolder + "satori_savebackup." + (fEncodeSavedata?"sat":"txt"), false); GetSentence("セーブデータ"); execResult = talks.get_family("セーブデータ") != NULL; } talks.clear(); reload_flag = false; if ( variables.find("ゴースト起動時間累計秒") != variables.end() ) { sec_count_total = zen2ul(variables["ゴースト起動時間累計秒"]); } else if ( variables.find("ゴースト起動時間累計ミリ秒") != variables.end() ) { sec_count_total = zen2ul(variables["ゴースト起動時間累計ミリ秒"]) / 1000; } else { sec_count_total = zen2ul(variables["ゴースト起動時間累計(ms)"]) / 1000; } variables["起動回数"] = itos( zen2int(variables["起動回数"])+1 ); // 「単語の追加」で登録された単語を覚えておく const std::map< string, Family<Word> >& m = words.compatible(); for (std::map< string, Family<Word> >::const_iterator it = m.begin() ; it != m.end() ; ++it ) { std::vector<const Word*> v; it->second.get_elements_pointers(v); for (std::vector<const Word*>::const_iterator itx = v.begin() ; itx < v.end() ; ++itx ) { mAppendedWords[it->first].push_back(**itx); } } //------------------------------------------ // 指定フォルダの辞書を読み込み int loadcount = 0; strvec::iterator i = dic_folder.begin(); if ( i==dic_folder.end() ) { loadcount += LoadDicFolder(mBaseFolder); // ルートフォルダの辞書 } else { for ( ; i!=dic_folder.end() ; ++i ) loadcount += LoadDicFolder(mBaseFolder + *i + DIR_CHAR); // サブフォルダの辞書 } is_dic_loaded = loadcount != 0; //------------------------------------------ secure_flag = true; system_variable_operation("単語群「*」の重複回避", "有効、トーク中"); system_variable_operation("文「*」の重複回避", "有効"); //system_variable_operation("単語群「季節の食べ物」の重複回避", "有効、トーク中"); GetSentence("OnSatoriLoad"); on_loaded_script = GetSentence("OnSatoriBoot"); diet_script(on_loaded_script); GetSender().sender() << "loaded." << std::endl; GetSender().flush(); return true; }
int main( int argc, char *argv[ ], char *envp[ ] ) { // 実行ファイルのあるフォルダ名を取得 TCHAR szPath[MAX_PATH]=""; ::GetModuleFileName(NULL, szPath, MAX_PATH); char* p = FindFinalChar(szPath, '\\'); if ( *p == NULL ) return 1; *p='\0'; base_folder = szPath; sender << "[sodate]" << endl; sender << "ディスク上の対象フォルダは " << base_folder << "です。" << endl; ::SetCurrentDirectory(base_folder.c_str()); // 設置場所の確認 if ( !isExistFolder( (base_folder+"\\ghost\\master").c_str() ) ) { error("ghost/masterが見つかりません。設置位置を確認してください。"); return false; } if ( !isExistFolder( (base_folder+"\\shell\\master").c_str() ) ) { error("shell/masterが見つかりません。設置位置を確認してください。"); return false; } // 設定ファイルの読み込み sender << "設定ファイル sodate.dat を読み込みます。" << endl; if ( !strmap_from_file(conf, base_folder+"\\sodate.dat", byte_value_1) ) { error("先に sodate_setup.exe を実行してください。"); return false; } // 暗号保存されたパスワードをデコード string str = decode(conf["password"]); int len = str.size()/2; byte* buf = new byte[len+1]; buf[len]='\0'; string_to_binary(str, buf); xor_filter(buf, len, 186); conf["password"] = decode( (char*)buf ); // 古いupdates2.dauを削除 ::DeleteFile( (base_folder+"\\updates2.dau").c_str() ); ::DeleteFile( (base_folder+"\\ghost\\master\\updates2.dau").c_str() ); // 対象ファイル選定 cout << "対象ファイルを選定中" << endl; strvec allow_files_vec, deny_files_vec; stringset deny_files_set; split(conf["allow_files"], byte_value_2, allow_files_vec); split(conf["deny_files"], byte_value_2, deny_files_vec); // 除外ファイルが(存在すれば)set化 for (strvec::iterator i=deny_files_vec.begin() ; i!=deny_files_vec.end() ; ++i) { string full_path = base_folder+"\\"+*i; replace(full_path, "/", "\\"); string folder_name = get_folder_name(full_path); WIN32_FIND_DATA fd; HANDLE h = ::FindFirstFile(full_path.c_str(), &fd); if ( h == INVALID_HANDLE_VALUE ) continue; do { if ( fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY ) continue; deny_files_set.insert(folder_name+"\\"+fd.cFileName); } while ( ::FindNextFile(h, &fd) ); ::FindClose(h); } // 対象ファイルを、除外対象に一致しないことを確認しつつfiles化 for (strvec::iterator i=allow_files_vec.begin() ; i!=allow_files_vec.end() ; ++i) { string full_path = base_folder+"\\"+*i; replace(full_path, "/", "\\"); string folder_name = get_folder_name(full_path); WIN32_FIND_DATA fd; HANDLE h = ::FindFirstFile(full_path.c_str(), &fd); if ( h == INVALID_HANDLE_VALUE ) { sender << *i << "に該当するファイルがありません。" << endl; continue; } int n=0; do { if ( fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY ) continue; string filename=folder_name+"\\"+fd.cFileName; if ( deny_files_set.find(filename) == deny_files_set.end() ) { files.push_back(filename); ++n; } } while ( ::FindNextFile(h, &fd) ); ::FindClose(h); if ( n==0 ) { sender << *i << "に該当するファイルがありません。" << endl; continue; } } if ( files.size()==0 ) { error("対象となるファイルが存在しません。"); return 1; } else { // 本家のupdates2.dauに構造を合わせるためのリストのソート list<string> OLD = files; // 複製を作る files.clear(); list<string>& NEW = files; // 空っぽのほう // まずは単なるアルファベットソート files.sort(); // まずはshellフォルダの中身を移行 list<string>::iterator i;; for (i=OLD.begin(); i!=OLD.end() ;) { if ( compare_head(get_folder_name(*i), base_folder+"\\shell\\") ) { NEW.push_back(*i); i=OLD.erase(i); } else ++i; } // 続いてghostフォルダの中身を移行 for (i=OLD.begin(); i!=OLD.end() ;) { if ( compare_head(get_folder_name(*i), base_folder+"\\ghost\\") ) { NEW.insert(NEW.begin(), *i); // 反転しないように i=OLD.erase(i); } else ++i; } // ghost, shell,ルート以外のフォルダの中身を移行(あるのか?) for (i=OLD.begin(); i!=OLD.end() ;) { if ( !compare_head(get_folder_name(*i), base_folder) ) { NEW.push_back(*i); i=OLD.erase(i); } else ++i; } // 残り。ルートフォルダの中身を移行 NEW.insert(NEW.end(), OLD.begin(), OLD.end()); OLD.clear(); } sender << "updates2.dauを作成中" << endl; bool makeUpdates2(string base_folder, const list<string>& files); if ( !makeUpdates2(szPath, files) ) { error("updates2.dauが作成できませんでした。"); return 1; } sender << "updates2.dauを作成完了" << endl; // 同じものをコピー ::CopyFile( (base_folder+"\\updates2.dau").c_str(), (base_folder+"\\ghost\\master\\updates2.dau").c_str(), FALSE ); if ( conf["is_create_archive"]!="0") { sender << "zip/narアーカイブを作成中" << endl; if ( !is_exist_file(base_folder+"\\install.txt") ) { error("zip/narアーカイブを作成するためには、ゴーストのルートフォルダにinstall.txtが必要です。"); return false; } SYSTEMTIME st; char buf[10]; ::GetLocalTime(&st); sprintf(buf, "%02d", st.wYear%100); replace(conf["archive_filename"], "%year", buf); sprintf(buf, "%04d", st.wYear); replace(conf["archive_filename"], "%year4", buf); sprintf(buf, "%02d", st.wMonth); replace(conf["archive_filename"], "%month", buf); sprintf(buf, "%02d", st.wDay); replace(conf["archive_filename"], "%day", buf); sprintf(buf, "%02d", st.wHour); replace(conf["archive_filename"], "%hour", buf); sprintf(buf, "%02d", st.wMinute); replace(conf["archive_filename"], "%minute", buf); sprintf(buf, "%02d", st.wSecond); replace(conf["archive_filename"], "%second", buf); if ( (conf["archive_local_folder"])[ conf["archive_local_folder"].size()-1 ] != '\\' ) conf["archive_local_folder"] += "\\"; string archive_filename = conf["archive_local_folder"]+conf["archive_filename"]; // 既にあるなら削除しておく ::DeleteFile(archive_filename.c_str()); /* string cmd = "zip.exe"; string opt = "-r " + archive_filename; for (list<string>::const_iterator i=files.begin(); i!=files.end() ; ++i ) { string filename(*i); opt += string(" ") + (filename.c_str()+base_folder.size()+1); } opt += " ghost\\master\\updates2.dau"; if ( opt.find(" install.txt")==string::npos ) opt += " install.txt"; // nar時には必須なので。 opt += " > nul"; */ //system((cmd+" "+opt).c_str()); //::ShellExecute(NULL, NULL, (cmd+" "+opt).c_str(), NULL, NULL, SW_SHOW); //if ( !is_exist_file(archive_filename) ) { list<string> zip_files; bool exist_install_txt=false; for (list<string>::const_iterator i=files.begin(); i!=files.end() ; ++i ) { zip_files.push_back(i->c_str()+base_folder.size()+1); if ( zip_files.back()=="install.txt" ) exist_install_txt = true; } zip_files.push_back("ghost\\master\\updates2.dau"); if ( !exist_install_txt ) zip_files.push_back("install.txt"); if ( !makeZip(archive_filename, zip_files) ) { error("アーカイブファイル'"+archive_filename+"'が作成できませんでした。"); } else { sender << "zip/narアーカイブ '" << archive_filename << "' を作成完了" << endl; } } files.push_back(base_folder+"\\updates2.dau"); // フォルダ別に分離格納 as global // map<string, set<string> > files_on_dir; // dirname : filenames { for (list<string>::iterator i=files.begin(); i!=files.end() ; ++i) { string rel_path = (i->c_str()+base_folder.size()+1); files_on_dir[ get_folder_name(rel_path) ].insert( get_file_name(rel_path) ); } } bool uploadFiles(const string&, list<string>&); if ( conf["is_upload"]!="0") uploadFiles(szPath, files); // ルートのupdates2.dauはアップロードした後に削除。 ::DeleteFile( (base_folder+"\\updates2.dau").c_str() ); return 0; }