// Remove base path from the start of abs path SString SharedUtil::PathMakeRelative ( const SString& strInBasePath, const SString& strInAbsPath ) { SString strBasePath = PathConform ( strInBasePath ); SString strAbsPath = PathConform ( strInAbsPath ); if ( strAbsPath.BeginsWithI ( strBasePath ) ) { return strAbsPath.SubStr ( strBasePath.length () ).TrimStart ( PATH_SEPERATOR ); } return strAbsPath; }
std::vector<SString> SharedUtil::FindFiles(const SString& strMatch, bool bFiles, bool bDirectories, bool bSortByDate) { std::vector<SString> strResult; std::multimap<uint64, SString> sortMap; DIR* Dir; struct dirent* DirEntry; // Extract any filename matching characters SString strFileMatch; SString strSearchDirectory = PathJoin(PathConform(strMatch).SplitLeft("/", &strFileMatch, -1), "/"); if ((Dir = opendir(strSearchDirectory))) { while ((DirEntry = readdir(Dir)) != NULL) { // Skip dotted entries if (strcmp(DirEntry->d_name, ".") && strcmp(DirEntry->d_name, "..")) { struct stat Info; bool bIsDir = false; // Do wildcard matching if required if (!strFileMatch.empty() && !WildcardMatch(strFileMatch, DirEntry->d_name)) { continue; } SString strPath = PathJoin(strSearchDirectory, DirEntry->d_name); // Determine the file stats if (lstat(strPath, &Info) != -1) bIsDir = S_ISDIR(Info.st_mode); if (bIsDir ? bDirectories : bFiles) { if (bSortByDate) { SString strAbsPath = strSearchDirectory + DirEntry->d_name; struct stat attrib; stat(strAbsPath, &attrib); MapInsert(sortMap, (uint64)attrib.st_mtime, SStringX(DirEntry->d_name)); } else strResult.push_back(DirEntry->d_name); } } } closedir(Dir); } // Resolve sorted map if required if (!sortMap.empty()) { for (std::multimap<uint64, SString>::iterator iter = sortMap.begin(); iter != sortMap.end(); ++iter) strResult.push_back(iter->second); } return strResult; }
void SharedUtil::ExtractFilename ( const SString& strInPathFilename, SString* strPath, SString* strFilename ) { const SString strPathFilename = PathConform ( strInPathFilename ); if ( !strPathFilename.Split ( PATH_SEPERATOR, strPath, strFilename, -1 ) ) if ( strFilename ) *strFilename = strPathFilename; }
SString SharedUtil::MakeUniquePath ( const SString& strInPathFilename ) { const SString strPathFilename = PathConform ( strInPathFilename ); SString strBeforeUniqueChar, strAfterUniqueChar; SString strPath, strFilename; ExtractFilename ( strPathFilename, &strPath, &strFilename ); SString strMain, strExt; if ( ExtractExtension ( strFilename, &strMain, &strExt ) ) { strBeforeUniqueChar = PathJoin ( strPath, strMain ); strAfterUniqueChar = "." + strExt; } else { strBeforeUniqueChar = strPathFilename; strAfterUniqueChar = ""; } SString strTest = strPathFilename; int iCount = 1; #ifdef WIN32 while ( GetFileAttributes ( strTest ) != INVALID_FILE_ATTRIBUTES ) #else while ( DirectoryExists ( strTest ) || FileExists ( strTest ) ) #endif { strTest = SString ( "%s_%d%s", strBeforeUniqueChar.c_str (), iCount++, strAfterUniqueChar.c_str () ); } return strTest; }
// // Ensure all directories exist to the file // void SharedUtil::MakeSureDirExists ( const SString& strPath ) { std::vector < SString > parts; PathConform ( strPath ).Split ( PATH_SEPERATOR, parts ); // Find first dir that already exists int idx = parts.size () - 1; for ( ; idx >= 0 ; idx-- ) { SString strTemp = SString::Join ( PATH_SEPERATOR, parts, 0, idx ); if ( DirectoryExists ( strTemp ) ) break; } // Make non existing dirs only idx++; for ( ; idx < (int)parts.size () ; idx++ ) { SString strTemp = SString::Join ( PATH_SEPERATOR, parts, 0, idx ); // Call mkdir on this path #ifdef WIN32 mkdir ( strTemp ); #else mkdir ( strTemp ,0775 ); #endif } }
SString SharedUtil::PathJoin ( const SString& str1, const SString& str2, const SString& str3, const SString& str4, const SString& str5 ) { SString strResult = str1 + PATH_SEPERATOR + str2 + PATH_SEPERATOR + str3; if ( str4.length () ) strResult += PATH_SEPERATOR + str4; if ( str5.length () ) strResult += PATH_SEPERATOR + str5; return PathConform ( strResult ); }
void DefaultResourceProvider::loadRawDataContainer(const String& filename, RawDataContainer& output, const String& resourceGroup) { if (filename.empty() || (filename == (utf8*)"")) { throw InvalidRequestException((utf8*) "DefaultResourceProvider::load - Filename supplied for data loading must be valid"); } std::wstring strFilename1 = filename.c_wstring (); std::wstring strFilename2 = System::getSingleton ().GetGuiWorkingDirectory().c_wstring () + strFilename1; // If supplied filename looks like it is absolute, try that first bool bIsAbsolutePath = false; { SString strTemp = PathConform ( filename.c_str () ); if ( strTemp.Contains ( ":" ) || strTemp.BeginsWith ( "\\" ) ) std::swap ( strFilename1, strFilename2 ); } std::ifstream dataFile; dataFile.open(strFilename2.c_str (), std::ios::binary|std::ios::ate); if( dataFile.fail()) { dataFile.clear(); dataFile.open(strFilename1.c_str (), std::ios::binary|std::ios::ate); if( dataFile.fail()) { throw InvalidRequestException((utf8*) "DefaultResourceProvider::load - " + filename + " does not exist"); } } std::streampos size = dataFile.tellg(); dataFile.seekg (0, std::ios::beg); unsigned char* buffer = new unsigned char [(uint)size]; try { dataFile.read(reinterpret_cast<char*>(buffer), size); } catch(std::ifstream::failure e) { delete [] buffer; throw GenericException((utf8*) "DefaultResourceProvider::loadRawDataContainer - Problem reading " + filename); } dataFile.close(); //memcpy(container->getDataPtr(), buffer, size); output.setData(buffer); output.setSize((size_t)size); //delete [] buffer; }
// Return true if path is not relative bool SharedUtil::IsAbsolutePath ( const SString& strInPath ) { const SString strPath = PathConform ( strInPath ); if ( strPath.BeginsWith( PATH_SEPERATOR ) ) return true; #ifdef WIN32 if ( strPath.length() > 0 && strPath[1] == ':' ) return true; #endif return false; }
void CAccountManager::ReconnectToDatabase(void) { if (m_hDbConnection != INVALID_DB_HANDLE) { m_pDatabaseManager->Disconnect(m_hDbConnection); } //Load internal.db SString strOptions; #ifdef WITH_ACCOUNT_QUERY_LOGGING g_pGame->GetDatabaseManager ()->SetLogLevel ( EJobLogLevel::ALL, g_pGame->GetConfig ()->GetDbLogFilename () ); SetOption < CDbOptionsMap > ( strOptions, "log", 1 ); SetOption < CDbOptionsMap > ( strOptions, "tag", "accounts" ); #endif SetOption < CDbOptionsMap > ( strOptions, "queue", DB_SQLITE_QUEUE_NAME_INTERNAL ); m_hDbConnection = m_pDatabaseManager->Connect ( "sqlite", PathConform ( m_strDbPathFilename ), "", "", strOptions ); }
/////////////////////////////////////////////////////////////// // // FindFiles // // Find all files or directories at a path // If sorted by date, returns last modified last // /////////////////////////////////////////////////////////////// std::vector < SString > SharedUtil::FindFiles ( const SString& strInMatch, bool bFiles, bool bDirectories, bool bSortByDate ) { std::vector < SString > strResult; std::multimap < uint64, SString > sortMap; SString strMatch = PathConform ( strInMatch ); if ( strMatch.Right ( 1 ) == PATH_SEPERATOR ) strMatch += "*"; WIN32_FIND_DATAW findData; HANDLE hFind = FindFirstFileW ( FromUTF8( strMatch ), &findData ); if( hFind != INVALID_HANDLE_VALUE ) { do { if ( ( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) ? bDirectories : bFiles ) if ( wcscmp ( findData.cFileName, L"." ) && wcscmp ( findData.cFileName, L".." ) ) { if ( bSortByDate ) MapInsert( sortMap, (uint64&)findData.ftLastWriteTime, ToUTF8( findData.cFileName ) ); else strResult.push_back ( ToUTF8( findData.cFileName ) ); } } while( FindNextFileW( hFind, &findData ) ); FindClose( hFind ); } // Resolve sorted map if required if ( !sortMap.empty() ) { for ( std::multimap < uint64, SString >::iterator iter = sortMap.begin() ; iter != sortMap.end() ; ++iter ) strResult.push_back ( iter->second ); } return strResult; }
// Conform a path string for sorting SString SharedUtil::ConformPathForSorting ( const SString& strPathFilename ) { return PathConform ( strPathFilename ).ToLower (); }
void CCrashDumpWriter::DumpMiniDump ( _EXCEPTION_POINTERS* pException, CExceptionInformation* pExceptionInformation ) { WriteDebugEvent ( "CCrashDumpWriter::DumpMiniDump" ); // Try to load the DLL in our directory HMODULE hDll = NULL; char szDbgHelpPath [MAX_PATH]; if ( GetModuleFileNameA ( NULL, szDbgHelpPath, MAX_PATH ) ) { char* pSlash = _tcsrchr ( szDbgHelpPath, '\\' ); if ( pSlash ) { _tcscpy ( pSlash + 1, "DBGHELP.DLL" ); hDll = LoadLibrary ( szDbgHelpPath ); } } // If we couldn't load the one in our dir, load any version available if ( !hDll ) { hDll = LoadLibrary( "DBGHELP.DLL" ); } if ( !hDll ) AddReportLog( 9201, "CCrashDumpWriter::DumpMiniDump - Could not load DBGHELP.DLL" ); // We could load a dll? if ( hDll ) { // Grab the MiniDumpWriteDump proc address MINIDUMPWRITEDUMP pDump = reinterpret_cast < MINIDUMPWRITEDUMP > ( GetProcAddress( hDll, "MiniDumpWriteDump" ) ); if ( !pDump ) AddReportLog( 9202, "CCrashDumpWriter::DumpMiniDump - Could not find MiniDumpWriteDump" ); if ( pDump ) { // Create the file HANDLE hFile = CreateFile ( CalcMTASAPath ( "mta\\core.dmp" ), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if ( hFile == INVALID_HANDLE_VALUE ) AddReportLog( 9203, SString( "CCrashDumpWriter::DumpMiniDump - Could not create '%s'", *CalcMTASAPath ( "mta\\core.dmp" ) ) ); if ( hFile != INVALID_HANDLE_VALUE ) { // Create an exception information struct _MINIDUMP_EXCEPTION_INFORMATION ExInfo; ExInfo.ThreadId = GetCurrentThreadId (); ExInfo.ExceptionPointers = pException; ExInfo.ClientPointers = FALSE; // Write the dump BOOL bResult = pDump ( GetCurrentProcess(), GetCurrentProcessId(), hFile, (MINIDUMP_TYPE)( MiniDumpNormal | MiniDumpWithIndirectlyReferencedMemory ), &ExInfo, NULL, NULL ); if ( !bResult ) AddReportLog( 9204, SString( "CCrashDumpWriter::DumpMiniDump - MiniDumpWriteDump failed (%08x)", GetLastError() ) ); else WriteDebugEvent ( "CCrashDumpWriter::DumpMiniDump - MiniDumpWriteDump succeeded" ); // Close the dumpfile CloseHandle ( hFile ); // Grab the current time // Ask windows for the system time. SYSTEMTIME SystemTime; GetLocalTime ( &SystemTime ); // Create the dump directory CreateDirectory ( CalcMTASAPath ( "mta\\dumps" ), 0 ); CreateDirectory ( CalcMTASAPath ( "mta\\dumps\\private" ), 0 ); SString strModuleName = pExceptionInformation->GetModuleBaseName (); strModuleName = strModuleName.ReplaceI ( ".dll", "" ).Replace ( ".exe", "" ).Replace ( "_", "" ).Replace ( ".", "" ).Replace ( "-", "" ); if ( strModuleName.length () == 0 ) strModuleName = "unknown"; SString strMTAVersionFull = SString ( "%s.%s", MTA_DM_BUILDTAG_LONG, *GetApplicationSetting ( "mta-version-ext" ).SplitRight ( ".", NULL, -2 ) ); SString strSerialPart = GetApplicationSetting ( "serial" ).substr ( 0, 5 ); uint uiServerIP = GetApplicationSettingInt ( "last-server-ip" ); uint uiServerPort = GetApplicationSettingInt ( "last-server-port" ); int uiServerTime = GetApplicationSettingInt ( "last-server-time" ); int uiServerDuration = _time32 ( NULL ) - uiServerTime; uiServerDuration = Clamp ( 0, uiServerDuration + 1, 0xfff ); // Get path to mta dir SString strPathCode; { std::vector < SString > parts; PathConform ( CalcMTASAPath ( "" ) ).Split ( PATH_SEPERATOR, parts ); for ( uint i = 0 ; i < parts.size () ; i++ ) { if ( parts[i].CompareI ( "Program Files" ) ) strPathCode += "Pr"; else if ( parts[i].CompareI ( "Program Files (x86)" ) ) strPathCode += "Px"; else if ( parts[i].CompareI ( "MTA San Andreas" ) ) strPathCode += "Mt"; else if ( parts[i].BeginsWithI ( "MTA San Andreas" ) ) strPathCode += "Mb"; else strPathCode += parts[i].Left ( 1 ).ToUpper (); } } // Ensure filename parts match up with EDumpFileNameParts SString strFilename ( "mta\\dumps\\private\\client_%s_%s_%08x_%x_%s_%08X_%04X_%03X_%s_%04d%02d%02d_%02d%02d.dmp", strMTAVersionFull.c_str (), strModuleName.c_str (), pExceptionInformation->GetAddressModuleOffset (), pExceptionInformation->GetCode () & 0xffff, strPathCode.c_str (), uiServerIP, uiServerPort, uiServerDuration, strSerialPart.c_str (), SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute ); SString strPathFilename = CalcMTASAPath ( strFilename ); // Copy the file CopyFile ( CalcMTASAPath ( "mta\\core.dmp" ), strPathFilename, false ); // For the dump uploader SetApplicationSetting ( "diagnostics", "last-dump-extra", "none" ); SetApplicationSetting ( "diagnostics", "last-dump-save", strPathFilename ); // Try to append pool sizes info to dump file SetApplicationSetting ( "diagnostics", "last-dump-extra", "try-pools" ); CBuffer poolInfo; GetPoolInfo ( poolInfo ); AppendToDumpFile ( strPathFilename, poolInfo, 'POLs', 'POLe' ); SetApplicationSetting ( "diagnostics", "last-dump-extra", "added-pools" ); // Try to append d3d state info to dump file SetApplicationSetting ( "diagnostics", "last-dump-extra", "try-d3d" ); CBuffer d3dInfo; GetD3DInfo ( d3dInfo ); AppendToDumpFile ( strPathFilename, d3dInfo, 'D3Ds', 'D3De' ); SetApplicationSetting ( "diagnostics", "last-dump-extra", "added-d3d" ); // Try to append crash averted stats to dump file SetApplicationSetting ( "diagnostics", "last-dump-extra", "try-crash-averted" ); CBuffer crashAvertedStats; GetCrashAvertedStats ( crashAvertedStats ); AppendToDumpFile ( strPathFilename, crashAvertedStats, 'CASs', 'CASe' ); SetApplicationSetting ( "diagnostics", "last-dump-extra", "added-crash-averted" ); // Try to append log info to dump file SetApplicationSetting ( "diagnostics", "last-dump-extra", "try-log" ); CBuffer logInfo; GetLogInfo ( logInfo ); AppendToDumpFile ( strPathFilename, logInfo, 'LOGs', 'LOGe' ); SetApplicationSetting ( "diagnostics", "last-dump-extra", "added-log" ); // Try to append dx info to dump file SetApplicationSetting ( "diagnostics", "last-dump-extra", "try-misc" ); CBuffer dxInfo; GetDxInfo ( dxInfo ); AppendToDumpFile ( strPathFilename, dxInfo, 'DXIs', 'DXIe' ); SetApplicationSetting ( "diagnostics", "last-dump-extra", "added-misc" ); // Try to append misc info to dump file SetApplicationSetting ( "diagnostics", "last-dump-extra", "try-misc" ); CBuffer miscInfo; GetMiscInfo ( miscInfo ); AppendToDumpFile ( strPathFilename, miscInfo, 'MSCs', 'MSCe' ); SetApplicationSetting ( "diagnostics", "last-dump-extra", "added-misc" ); // Try to append memory info to dump file SetApplicationSetting ( "diagnostics", "last-dump-extra", "try-mem" ); CBuffer memInfo; GetMemoryInfo ( memInfo ); AppendToDumpFile ( strPathFilename, memInfo, 'MEMs', 'MEMe' ); SetApplicationSetting ( "diagnostics", "last-dump-extra", "added-mem" ); // Try to logfile.txt to dump file SetApplicationSetting ( "diagnostics", "last-dump-extra", "try-logfile" ); CBuffer logfileContent; logfileContent.LoadFromFile( CalcMTASAPath( PathJoin( "mta", "logs", "logfile.txt" ) ) ); AppendToDumpFile ( strPathFilename, logfileContent, 'LOGs', 'LOGe' ); SetApplicationSetting ( "diagnostics", "last-dump-extra", "added-logfile" ); // Try to report.log to dump file SetApplicationSetting ( "diagnostics", "last-dump-extra", "try-report" ); CBuffer reportLogContent; reportLogContent.LoadFromFile( PathJoin( GetMTADataPath(), "report.log" ) ); AppendToDumpFile ( strPathFilename, reportLogContent, 'REPs', 'REPe' ); SetApplicationSetting ( "diagnostics", "last-dump-extra", "added-report" ); } } // Free the DLL again FreeLibrary ( hDll ); } // Auto-fixes // Check if crash was in volumetric shadow code if ( ms_uiInCrashZone == 1 || ms_uiInCrashZone == 2 ) { CVARS_SET( "volumetric_shadows", false ); CCore::GetSingleton().SaveConfig(); AddReportLog( 9205, "Disabled volumetric shadows" ); } CNet* pNet = CCore::GetSingleton().GetNetwork(); if ( pNet ) pNet->PostCrash(); }
bool CAccountManager::IntegrityCheck () { // Check database integrity { CRegistryResult result; bool bOk = m_pDatabaseManager->QueryWithResultf ( m_hDbConnection, &result, "PRAGMA integrity_check" ); // Get result as a string SString strResult; if ( result->nRows && result->nColumns ) { CRegistryResultCell& cell = result->Data.front()[0]; if ( cell.nType == SQLITE_TEXT ) strResult = std::string ( (const char *)cell.pVal, cell.nLength - 1 ); } // Process result if ( !bOk || !strResult.BeginsWithI ( "ok" ) ) { CLogger::ErrorPrintf ( "%s", *strResult ); CLogger::ErrorPrintf ( "%s\n", *m_pDatabaseManager->GetLastErrorMessage () ); CLogger::ErrorPrintf ( "Errors were encountered loading '%s' database\n", *ExtractFilename ( PathConform ( "internal.db" ) ) ); CLogger::ErrorPrintf ( "Maybe now is the perfect time to panic.\n" ); CLogger::ErrorPrintf ( "See - http://wiki.multitheftauto.com/wiki/fixdb\n" ); CLogger::ErrorPrintf ( "************************\n" ); // Allow server to continue } } // Check can update file { m_pDatabaseManager->Execf ( m_hDbConnection, "DROP TABLE IF EXISTS write_test" ); m_pDatabaseManager->Execf ( m_hDbConnection, "CREATE TABLE IF NOT EXISTS write_test (id INTEGER PRIMARY KEY, value INTEGER)" ); m_pDatabaseManager->Execf ( m_hDbConnection, "INSERT OR IGNORE INTO write_test (id, value) VALUES(1,2)" ) ; bool bOk = m_pDatabaseManager->QueryWithResultf ( m_hDbConnection, NULL, "UPDATE write_test SET value=3 WHERE id=1" ); if ( !bOk ) { CLogger::ErrorPrintf ( "%s\n", *m_pDatabaseManager->GetLastErrorMessage () ); CLogger::ErrorPrintf ( "Errors were encountered updating '%s' database\n", *ExtractFilename ( PathConform ( "internal.db" ) ) ); CLogger::ErrorPrintf ( "Database might have incorrect file permissions, or locked by another process, or damaged.\n" ); CLogger::ErrorPrintf ( "See - http://wiki.multitheftauto.com/wiki/fixdb\n" ); CLogger::ErrorPrintf ( "************************\n" ); return false; } m_pDatabaseManager->Execf ( m_hDbConnection, "DROP TABLE write_test" ); } // Do compact if required if ( g_pGame->GetConfig()->ShouldCompactInternalDatabases() ) { CLogger::LogPrintf ( "Compacting accounts database '%s' ...\n", *ExtractFilename ( PathConform ( "internal.db" ) ) ); CRegistryResult result; bool bOk = m_pDatabaseManager->QueryWithResultf ( m_hDbConnection, &result, "VACUUM" ); // Get result as a string SString strResult; if ( result->nRows && result->nColumns ) { CRegistryResultCell& cell = result->Data.front()[0]; if ( cell.nType == SQLITE_TEXT ) strResult = std::string ( (const char *)cell.pVal, cell.nLength - 1 ); } // Process result if ( !bOk ) { CLogger::ErrorPrintf ( "%s", *strResult ); CLogger::ErrorPrintf ( "%s\n", *m_pDatabaseManager->GetLastErrorMessage () ); CLogger::ErrorPrintf ( "Errors were encountered compacting '%s' database\n", *ExtractFilename ( PathConform ( "internal.db" ) ) ); CLogger::ErrorPrintf ( "Maybe now is the perfect time to panic.\n" ); CLogger::ErrorPrintf ( "See - http://wiki.multitheftauto.com/wiki/fixdb\n" ); CLogger::ErrorPrintf ( "************************\n" ); // Allow server to continue } } return true; }
/////////////////////////////////////////////////////////////// // // DoInstallFiles // // Copy directory tree at current dirctory to GetMTASAPath () // /////////////////////////////////////////////////////////////// bool DoInstallFiles ( void ) { SString strCurrentDir = PathConform ( GetSystemCurrentDirectory () ); const SString strMTASAPath = PathConform ( GetMTASAPath () ); SString path1, path2; strCurrentDir.Split ( "\\", &path1, &path2, -1 ); SString strDestRoot = strMTASAPath; SString strSrcRoot = strCurrentDir; SString strBakRoot = MakeUniquePath ( strCurrentDir + "_bak_" ); // Clean backup dir if ( !MkDir ( strBakRoot ) ) { AddReportLog ( 5020, SString ( "InstallFiles: Couldn't make dir '%s'", strBakRoot.c_str () ) ); return false; } // Get list of files to install std::vector < SFileItem > itemList; { std::vector < SString > fileList; FindFilesRecursive ( PathJoin ( strCurrentDir, "*" ), fileList ); for ( unsigned int i = 0 ; i < fileList.size () ; i++ ) { SFileItem item; item.strSrcPathFilename = PathConform ( fileList[i] ); item.strDestPathFilename = PathConform ( fileList[i].Replace ( strSrcRoot, strDestRoot ) ); item.strBackupPathFilename = PathConform ( fileList[i].Replace ( strSrcRoot, strBakRoot ) ); itemList.push_back ( item ); } } // See if any files to be updated are running. // If so, terminate them for ( unsigned int i = 0 ; i < itemList.size () ; i++ ) { SString strFile = itemList[i].strDestPathFilename; if ( strFile.EndsWithI( ".exe" ) ) TerminateProcessFromPathFilename ( strFile ); } // Copy current(old) files into backup location for ( unsigned int i = 0 ; i < itemList.size () ; i++ ) { const SFileItem& item = itemList[i]; if ( !FileCopy ( item.strDestPathFilename, item.strBackupPathFilename ) ) { if ( FileExists ( item.strDestPathFilename ) ) { AddReportLog ( 5021, SString ( "InstallFiles: Couldn't backup '%s' to '%s'", *item.strDestPathFilename, *item.strBackupPathFilename ) ); return false; } AddReportLog ( 4023, SString ( "InstallFiles: Couldn't backup '%s' as it does not exist", *item.strDestPathFilename ) ); } } // Try copy new files bool bOk = true; std::vector < SFileItem > fileListSuccess; for ( unsigned int i = 0 ; i < itemList.size () ; i++ ) { const SFileItem& item = itemList[i]; if ( !FileCopy ( item.strSrcPathFilename, item.strDestPathFilename ) ) { // If copy failed, check if we really need to copy the file if ( GenerateSha256HexStringFromFile( item.strSrcPathFilename ) != GenerateSha256HexStringFromFile( item.strDestPathFilename ) ) { AddReportLog ( 5022, SString ( "InstallFiles: Couldn't copy '%s' to '%s'", *item.strSrcPathFilename, *item.strDestPathFilename ) ); bOk = false; break; } } fileListSuccess.push_back ( item ); } // If fail, copy back old files if ( !bOk ) { bool bPossibleDisaster = false; for ( unsigned int i = 0 ; i < fileListSuccess.size () ; i++ ) { const SFileItem& item = fileListSuccess[i]; int iRetryCount = 3; while ( true ) { if ( FileCopy ( item.strBackupPathFilename, item.strDestPathFilename ) ) break; // If copy failed, check if we really need to copy the file if ( GenerateSha256HexStringFromFile( item.strBackupPathFilename ) != GenerateSha256HexStringFromFile( item.strDestPathFilename ) ) break; if ( !--iRetryCount ) { AddReportLog ( 5023, SString ( "InstallFiles: Possible disaster restoring '%s' to '%s'", *item.strBackupPathFilename, *item.strDestPathFilename ) ); bPossibleDisaster = true; break; } } } //if ( bPossibleDisaster ) // MessageBox ( NULL, _("Installation may be corrupt. Please redownload from www.mtasa.com"), _("Error"), MB_OK | MB_ICONERROR ); //else // MessageBox ( NULL, _("Could not update due to file conflicts."), _("Error"), MB_OK | MB_ICONERROR ); } // Launch MTA_EXE_NAME return bOk; }
CAccountManager::CAccountManager ( const SString& strDbPathFilename ) : m_AccountProtect( 6, 30000, 60000 * 1 ) // Max of 6 attempts per 30 seconds, then 1 minute ignore { m_llLastTimeSaved = GetTickCount64_ (); m_bChangedSinceSaved = false; m_iAccounts = 1; m_pDatabaseManager = g_pGame->GetDatabaseManager (); //Load internal.db SString strOptions; #ifdef WITH_ACCOUNT_QUERY_LOGGING g_pGame->GetDatabaseManager ()->SetLogLevel ( EJobLogLevel::ALL, g_pGame->GetConfig ()->GetDbLogFilename () ); SetOption < CDbOptionsMap > ( strOptions, "log", 1 ); SetOption < CDbOptionsMap > ( strOptions, "tag", "accounts" ); #endif SetOption < CDbOptionsMap > ( strOptions, "queue", DB_SQLITE_QUEUE_NAME_INTERNAL ); m_hDbConnection = m_pDatabaseManager->Connect ( "sqlite", PathConform ( strDbPathFilename ), "", "", strOptions ); // Check if new installation CRegistryResult result; m_pDatabaseManager->QueryWithResultf ( m_hDbConnection, &result, "SELECT name FROM sqlite_master WHERE type='table' AND name='accounts'" ); bool bNewInstallation = ( result->nRows == 0 ); //Create all our tables (Don't echo the results) m_pDatabaseManager->Execf ( m_hDbConnection, "CREATE TABLE IF NOT EXISTS accounts (id INTEGER PRIMARY KEY, name TEXT, password TEXT, ip TEXT, serial TEXT)" ); m_pDatabaseManager->Execf ( m_hDbConnection, "CREATE TABLE IF NOT EXISTS userdata (id INTEGER PRIMARY KEY, userid INTEGER, key TEXT, value TEXT, type INTEGER)" ); m_pDatabaseManager->Execf ( m_hDbConnection, "CREATE TABLE IF NOT EXISTS serialusage (id INTEGER PRIMARY KEY, userid INTEGER, " "serial TEXT, " "added_ip TEXT, " "added_date INTEGER, " "auth_who INTEGER, " "auth_date INTEGER, " "last_login_ip TEXT, " "last_login_date INTEGER, " "last_login_http_date INTEGER )" ); m_pDatabaseManager->Execf ( m_hDbConnection, "CREATE INDEX IF NOT EXISTS IDX_SERIALUSAGE_USERID on serialusage(userid)" ); m_pDatabaseManager->Execf ( m_hDbConnection, "CREATE UNIQUE INDEX IF NOT EXISTS IDX_SERIALUSAGE_USERID_SERIAL_U on serialusage(userid,serial)" ); // Check if unique index on accounts exists m_pDatabaseManager->QueryWithResultf ( m_hDbConnection, &result, "SELECT name FROM sqlite_master WHERE type='index' AND name='IDX_ACCOUNTS_NAME_U'" ); if ( result->nRows == 0 ) { // Need to add unique index on accounts if ( !bNewInstallation ) CLogger::LogPrintNoStamp ( "Updating accounts table...\n" ); // Make sure we have a non-unique index to speed up the duplication removal m_pDatabaseManager->Execf ( m_hDbConnection, "CREATE INDEX IF NOT EXISTS IDX_ACCOUNTS_NAME on accounts(name)" ); // Remove any duplicate name entries m_pDatabaseManager->Execf ( m_hDbConnection, "DELETE FROM accounts WHERE rowid in " " (SELECT A.rowid" " FROM accounts A, accounts B" " WHERE A.rowid > B.rowid AND A.name = B.name)" ); // Remove non-unique index m_pDatabaseManager->Execf ( m_hDbConnection, "DROP INDEX IF EXISTS IDX_ACCOUNTS_NAME" ); // Add unique index m_pDatabaseManager->Execf ( m_hDbConnection, "CREATE UNIQUE INDEX IF NOT EXISTS IDX_ACCOUNTS_NAME_U on accounts(name)" ); } // Check if unique index on userdata exists m_pDatabaseManager->QueryWithResultf ( m_hDbConnection, &result, "SELECT name FROM sqlite_master WHERE type='index' AND name='IDX_USERDATA_USERID_KEY_U'" ); if ( result->nRows == 0 ) { // Need to add unique index on userdata if ( !bNewInstallation ) CLogger::LogPrintNoStamp ( "Updating userdata table...\n" ); // Make sure we have a non-unique index to speed up the duplication removal m_pDatabaseManager->Execf ( m_hDbConnection, "CREATE INDEX IF NOT EXISTS IDX_USERDATA_USERID_KEY on userdata(userid,key)" ); // Remove any duplicate userid+key entries m_pDatabaseManager->Execf ( m_hDbConnection, "DELETE FROM userdata WHERE rowid in " " (SELECT A.rowid" " FROM userdata A, userdata B" " WHERE A.rowid > B.rowid AND A.userid = B.userid AND A.key = B.key)" ); // Remove non-unique index m_pDatabaseManager->Execf ( m_hDbConnection, "DROP INDEX IF EXISTS IDX_USERDATA_USERID_KEY" ); // Add unique index m_pDatabaseManager->Execf ( m_hDbConnection, "CREATE UNIQUE INDEX IF NOT EXISTS IDX_USERDATA_USERID_KEY_U on userdata(userid,key)" ); } // Ensure old indexes are removed m_pDatabaseManager->Execf ( m_hDbConnection, "DROP INDEX IF EXISTS IDX_ACCOUNTS_NAME" ); m_pDatabaseManager->Execf ( m_hDbConnection, "DROP INDEX IF EXISTS IDX_USERDATA_USERID" ); m_pDatabaseManager->Execf ( m_hDbConnection, "DROP INDEX IF EXISTS IDX_USERDATA_USERID_KEY" ); }
/////////////////////////////////////////////////////////////// // // MkDir // // Returns true if the directory is created or already exists // TODO: Make bTree off option work // /////////////////////////////////////////////////////////////// bool SharedUtil::MkDir ( const SString& strInPath, bool bTree ) { SString strPath = PathConform ( strInPath ); MakeSureDirExists ( strPath + PATH_SEPERATOR ); return DirectoryExists ( strPath ); }
bool CRegistry::IntegrityCheck ( void ) { // Check database integrity { CRegistryResult result; bool bOk = Query( &result, "PRAGMA integrity_check" ); // Get result as a string SString strResult; if ( result->nRows && result->nColumns ) { CRegistryResultCell& cell = result->Data.front()[0]; if ( cell.nType == SQLITE_TEXT ) strResult = std::string ( (const char *)cell.pVal, cell.nLength - 1 ); } // Process result if ( !bOk || !strResult.BeginsWithI ( "ok" ) ) { CLogger::ErrorPrintf ( "%s", *strResult ); CLogger::ErrorPrintf ( "%s\n", GetLastError ().c_str() ); CLogger::ErrorPrintf ( "Errors were encountered loading '%s' database\n", *ExtractFilename ( PathConform ( m_strFileName ) ) ); CLogger::ErrorPrintf ( "Maybe now is the perfect time to panic.\n" ); CLogger::ErrorPrintf ( "See - http://wiki.multitheftauto.com/wiki/fixdb\n" ); CLogger::ErrorPrintf ( "************************\n" ); return false; } } // Do compact if required if ( g_pGame->GetConfig()->ShouldCompactInternalDatabases() ) { CLogger::LogPrintf ( "Compacting database '%s' ...\n", *ExtractFilename ( PathConform ( m_strFileName ) ) ); CRegistryResult result; bool bOk = Query( &result, "VACUUM" ); // Get result as a string SString strResult; if ( result->nRows && result->nColumns ) { CRegistryResultCell& cell = result->Data.front()[0]; if ( cell.nType == SQLITE_TEXT ) strResult = std::string ( (const char *)cell.pVal, cell.nLength - 1 ); } // Process result if ( !bOk ) { CLogger::ErrorPrintf ( "%s", *strResult ); CLogger::ErrorPrintf ( "%s\n", GetLastError ().c_str() ); CLogger::ErrorPrintf ( "Errors were encountered compacting '%s' database\n", *ExtractFilename ( PathConform ( m_strFileName ) ) ); CLogger::ErrorPrintf ( "Maybe now is the perfect time to panic.\n" ); CLogger::ErrorPrintf ( "See - http://wiki.multitheftauto.com/wiki/fixdb\n" ); CLogger::ErrorPrintf ( "************************\n" ); // Allow server to continue } } return true; }
CAccountManager::CAccountManager ( const char* szFileName, SString strBuffer ): CXMLConfig ( szFileName ) , m_AccountProtect( 6, 30000, 60000 * 1 ) // Max of 6 attempts per 30 seconds, then 1 minute ignore { m_bAutoLogin = false; m_llLastTimeSaved = GetTickCount64_ (); m_bChangedSinceSaved = false; //set loadXML to false m_bLoadXML = false; m_iAccounts = 1; //Load internal.db m_pDatabaseManager = g_pGame->GetDatabaseManager (); m_hDbConnection = m_pDatabaseManager->Connect ( "sqlite", PathConform ( strBuffer ) ); // Check if new installation CRegistryResult result; m_pDatabaseManager->QueryWithResultf ( m_hDbConnection, &result, "SELECT name FROM sqlite_master WHERE type='table' AND name='accounts'" ); bool bNewInstallation = ( result->nRows == 0 ); //Create all our tables (Don't echo the results) m_pDatabaseManager->Execf ( m_hDbConnection, "CREATE TABLE IF NOT EXISTS accounts (id INTEGER PRIMARY KEY, name TEXT, password TEXT, ip TEXT, serial TEXT)" ); m_pDatabaseManager->Execf ( m_hDbConnection, "CREATE TABLE IF NOT EXISTS userdata (id INTEGER PRIMARY KEY, userid INTEGER, key TEXT, value TEXT, type INTEGER)" ); m_pDatabaseManager->Execf ( m_hDbConnection, "CREATE TABLE IF NOT EXISTS settings (id INTEGER PRIMARY KEY, key TEXT, value INTEGER)" ); // Check if unique index on accounts exists m_pDatabaseManager->QueryWithResultf ( m_hDbConnection, &result, "SELECT name FROM sqlite_master WHERE type='index' AND name='IDX_ACCOUNTS_NAME_U'" ); if ( result->nRows == 0 ) { // Need to add unique index on accounts if ( !bNewInstallation ) CLogger::LogPrintNoStamp ( "Updating accounts table...\n" ); // Make sure we have a non-unique index to speed up the duplication removal m_pDatabaseManager->Execf ( m_hDbConnection, "CREATE INDEX IF NOT EXISTS IDX_ACCOUNTS_NAME on accounts(name)" ); // Remove any duplicate name entries m_pDatabaseManager->Execf ( m_hDbConnection, "DELETE FROM accounts WHERE rowid in " " (SELECT A.rowid" " FROM accounts A, accounts B" " WHERE A.rowid > B.rowid AND A.name = B.name)" ); // Remove non-unique index m_pDatabaseManager->Execf ( m_hDbConnection, "DROP INDEX IF EXISTS IDX_ACCOUNTS_NAME" ); // Add unique index m_pDatabaseManager->Execf ( m_hDbConnection, "CREATE UNIQUE INDEX IF NOT EXISTS IDX_ACCOUNTS_NAME_U on accounts(name)" ); } // Check if unique index on userdata exists m_pDatabaseManager->QueryWithResultf ( m_hDbConnection, &result, "SELECT name FROM sqlite_master WHERE type='index' AND name='IDX_USERDATA_USERID_KEY_U'" ); if ( result->nRows == 0 ) { // Need to add unique index on userdata if ( !bNewInstallation ) CLogger::LogPrintNoStamp ( "Updating userdata table...\n" ); // Make sure we have a non-unique index to speed up the duplication removal m_pDatabaseManager->Execf ( m_hDbConnection, "CREATE INDEX IF NOT EXISTS IDX_USERDATA_USERID_KEY on userdata(userid,key)" ); // Remove any duplicate userid+key entries m_pDatabaseManager->Execf ( m_hDbConnection, "DELETE FROM userdata WHERE rowid in " " (SELECT A.rowid" " FROM userdata A, userdata B" " WHERE A.rowid > B.rowid AND A.userid = B.userid AND A.key = B.key)" ); // Remove non-unique index m_pDatabaseManager->Execf ( m_hDbConnection, "DROP INDEX IF EXISTS IDX_USERDATA_USERID_KEY" ); // Add unique index m_pDatabaseManager->Execf ( m_hDbConnection, "CREATE UNIQUE INDEX IF NOT EXISTS IDX_USERDATA_USERID_KEY_U on userdata(userid,key)" ); } // Ensure old indexes are removed m_pDatabaseManager->Execf ( m_hDbConnection, "DROP INDEX IF EXISTS IDX_ACCOUNTS_NAME" ); m_pDatabaseManager->Execf ( m_hDbConnection, "DROP INDEX IF EXISTS IDX_USERDATA_USERID" ); m_pDatabaseManager->Execf ( m_hDbConnection, "DROP INDEX IF EXISTS IDX_USERDATA_USERID_KEY" ); //Pull our settings m_pDatabaseManager->QueryWithResultf ( m_hDbConnection, &result, "SELECT key, value from settings" ); //Did we get any results if ( result->nRows == 0 ) { //Set our settings and clear the accounts/userdata tables just in case m_pDatabaseManager->Execf ( m_hDbConnection, "INSERT INTO settings (key, value) VALUES(?,?)", SQLITE_TEXT, "XMLParsed", SQLITE_INTEGER, 0 ); //Tell the Server to load the xml file rather than the SQL m_bLoadXML = true; } else { bool bLoadXMLMissing = true; for ( CRegistryResultIterator iter = result->begin() ; iter != result->end() ; ++iter ) { const CRegistryResultRow& row = *iter; SString strSetting = (const char *)row[0].pVal; //Do we have a result for XMLParsed if ( strSetting == "XMLParsed" ) { //Is XMLParsed zero if ( row[1].nVal == 0 ) { //Tell the Server to load the xml file rather than the SQL m_bLoadXML = true; } bLoadXMLMissing = false; } } //if we didn't load the XMLParsed variable if ( bLoadXMLMissing ) { //Insert it m_pDatabaseManager->Execf ( m_hDbConnection, "INSERT INTO settings (key, value) VALUES(?,?)", SQLITE_TEXT, "XMLParsed", SQLITE_INTEGER, 0 ); //Tell the Server to load the xml file rather than the SQL m_bLoadXML = true; } } //Check whether autologin was enabled in the main config m_bAutoLogin = g_pGame->GetConfig()->IsAutoLoginEnabled(); }
SString SharedUtil::PathJoin ( const SString& str1, const SString& str2 ) { return PathConform ( str1 + PATH_SEPERATOR + str2 ); }