Beispiel #1
0
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;
}
Beispiel #2
0
///////////////////////////////////////////////////////////////
//
// 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;
}