bool CLuaMain::LoadScriptFromBuffer ( const char* cpInBuffer, unsigned int uiInSize, const char* szFileName ) { SString strNiceFilename = ConformResourcePath( szFileName ); // Decrypt if required const char* cpBuffer; uint uiSize; if ( !g_pRealNetServer->DecryptScript( cpInBuffer, uiInSize, &cpBuffer, &uiSize, strNiceFilename ) ) { SString strMessage( "%s is invalid. Please re-compile at http://luac.mtasa.com/", *strNiceFilename ); g_pGame->GetScriptDebugging()->LogError ( m_luaVM, "Loading script failed: %s", *strMessage ); return false; } bool bUTF8; // UTF-8 BOM? Compare by checking the standard UTF-8 BOM if ( IsUTF8BOM( cpBuffer, uiSize ) == false ) { // Maybe not UTF-8, if we have a >80% heuristic detection confidence, assume it is bUTF8 = ( GetUTF8Confidence ( (const unsigned char*)cpBuffer, uiSize ) >= 80 ); } else { // If there's a BOM, load ignoring the first 3 bytes bUTF8 = true; cpBuffer += 3; uiSize -= 3; } // If compiled script, make sure correct chunkname is embedded EmbedChunkName( strNiceFilename, &cpBuffer, &uiSize ); if ( m_luaVM ) { // Are we not marked as UTF-8 already, and not precompiled? std::string strUTFScript; if ( !bUTF8 && !IsLuaCompiledScript( cpBuffer, uiSize ) ) { std::string strBuffer = std::string(cpBuffer, uiSize); #ifdef WIN32 std::setlocale(LC_CTYPE,""); // Temporarilly use locales to read the script strUTFScript = UTF16ToMbUTF8(ANSIToUTF16( strBuffer )); std::setlocale(LC_CTYPE,"C"); #else strUTFScript = UTF16ToMbUTF8(ANSIToUTF16( strBuffer )); #endif if ( uiSize != strUTFScript.size() ) { uiSize = strUTFScript.size(); g_pGame->GetScriptDebugging()->LogWarning ( m_luaVM, "Script '%s' is not encoded in UTF-8. Loading as ANSI...", strNiceFilename.c_str() ); } } else strUTFScript = std::string(cpBuffer, uiSize); // Run the script if ( CLuaMain::LuaLoadBuffer ( m_luaVM, bUTF8 ? cpBuffer : strUTFScript.c_str(), uiSize, SString ( "@%s", *strNiceFilename ) ) ) { // Print the error std::string strRes = lua_tostring( m_luaVM, -1 ); if ( strRes.length () ) { CLogger::LogPrintf ( "SCRIPT ERROR: %s\n", strRes.c_str () ); g_pGame->GetScriptDebugging()->LogError ( m_luaVM, "Loading script failed: %s", strRes.c_str () ); } else { CLogger::LogPrint ( "SCRIPT ERROR: Unknown\n" ); g_pGame->GetScriptDebugging()->LogError ( m_luaVM, "Loading script failed for unknown reason" ); } } else { ResetInstructionCount (); int luaSavedTop = lua_gettop ( m_luaVM ); int iret = this->PCall ( m_luaVM, 0, LUA_MULTRET, 0 ) ; if ( iret == LUA_ERRRUN || iret == LUA_ERRMEM ) { SString strRes = lua_tostring( m_luaVM, -1 ); g_pGame->GetScriptDebugging()->LogPCallError( m_luaVM, strRes, true ); } // Cleanup any return values if ( lua_gettop ( m_luaVM ) > luaSavedTop ) lua_settop( m_luaVM, luaSavedTop ); return true; } } return false; }
/////////////////////////////////////////////////////////////// // // CResourceChecker::CheckLuaSourceForIssues // // Look for function names not in comment blocks // Note: Ignores quotes // /////////////////////////////////////////////////////////////// void CResourceChecker::CheckLuaSourceForIssues ( string strLuaSource, const string& strFileName, const string& strResourceName, bool bClientScript, bool bCompiledScript, ECheckerModeType checkerMode, string* pstrOutResult ) { CHashMap < SString, long > doneWarningMap; long lLineNumber = 1; // Check if this is a UTF-8 script bool bUTF8 = IsUTF8BOM( strLuaSource.c_str(), strLuaSource.length() ); // If it's not a UTF8 script, does it contain foreign language characters that should be upgraded? if ( !bCompiledScript && !bUTF8 && GetUTF8Confidence ( (const unsigned char*)&strLuaSource.at ( 0 ), strLuaSource.length() ) < 80 ) { std::wstring strUTF16Script = ANSIToUTF16 ( strLuaSource ); #ifdef WIN32 std::setlocale(LC_CTYPE,""); // Temporarilly use locales to read the script std::string strUTFScript = UTF16ToMbUTF8 ( strUTF16Script ); std::setlocale(LC_CTYPE,"C"); #else std::string strUTFScript = UTF16ToMbUTF8 ( strUTF16Script ); #endif if ( strLuaSource.length () != strUTFScript.size() ) { // In-place upgrade... if ( checkerMode == ECheckerMode::UPGRADE ) { // Upgrade only if there is no problem ( setlocale() issue? ) if ( strUTF16Script != L"?" ) { // Convert our script to ANSI, appending a BOM at the beginning strLuaSource = "\xEF\xBB\xBF" + strUTFScript; } } if ( checkerMode == ECheckerMode::WARNINGS ) { m_ulDeprecatedWarningCount++; CLogger::LogPrintf ( "WARNING: %s/%s [%s] is encoded in ANSI instead of UTF-8. Please convert your file to UTF-8.\n", strResourceName.c_str (), strFileName.c_str (), bClientScript ? "Client" : "Server" ); } } } // Step through each identifier in the file. for ( long lPos = 0 ; lPos < (long)strLuaSource.length () ; lPos++ ) { long lNameLength; long lNameOffset = FindLuaIdentifier ( strLuaSource.c_str () + lPos, &lNameLength, &lLineNumber ); if ( lNameOffset == - 1 ) break; lNameOffset += lPos; // Make offset absolute from the start of the file lPos = lNameOffset + lNameLength; // Adjust so the next pass starts from just after this identifier string strIdentifierName( strLuaSource.c_str () + lNameOffset, lNameLength ); // In-place upgrade... if ( checkerMode == ECheckerMode::UPGRADE ) { assert ( !bCompiledScript ); string strUpgraded; if ( UpgradeLuaFunctionName( strIdentifierName, bClientScript, strUpgraded ) ) { // Old head string strHead( strLuaSource.c_str (), lNameOffset ); // Old tail string strTail( strLuaSource.c_str () + lNameOffset + lNameLength ); // New source strLuaSource = strHead + strUpgraded + strTail; lPos += -lNameLength + strUpgraded.length (); } CheckVersionRequirements ( strIdentifierName, bClientScript ); } // Log warnings... if ( checkerMode == ECheckerMode::WARNINGS ) { // Only do the identifier once per file if ( doneWarningMap.find ( strIdentifierName ) == doneWarningMap.end () ) { doneWarningMap[strIdentifierName] = 1; if ( !bCompiledScript ) // Don't issue deprecated function warnings if the script is compiled, because we can't upgrade it IssueLuaFunctionNameWarnings ( strIdentifierName, strFileName, strResourceName, bClientScript, lLineNumber ); CheckVersionRequirements ( strIdentifierName, bClientScript ); } } } if ( pstrOutResult ) *pstrOutResult = strLuaSource; }