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;
}
Ejemplo n.º 2
0
Archivo: main.cpp Proyecto: yagi/satori
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;
}