Beispiel #1
0
CefRefPtr<CefResourceHandler> CCefApp::Create ( CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, const CefString& scheme_name, CefRefPtr<CefRequest> request )
{
    CWebCore* pWebCore = static_cast<CWebCore*> ( g_pCore->GetWebCore () );
    auto pWebView = pWebCore->FindWebView ( browser );
    if ( !pWebView || !pWebView->IsLocal () )
        return nullptr;

    CefURLParts urlParts;
    if ( !CefParseURL ( request->GetURL (), urlParts ) )
        return nullptr;

    if ( scheme_name == "mtalocal" ) // Backward compatibility
    {
        // Get full path
        SString path = UTF16ToMbUTF8 ( urlParts.path.str ).substr ( 2 );

        // Check if we're dealing with an external resource
        if ( path[0] == ':' )
        {
            size_t end = path.find_first_of ( '/' );
            if ( end != std::string::npos )
            {
                SString resourceName = path.substr ( 1, end-1 );
                SString resourcePath = path.substr ( end );

                // Call this function recursively and use the mta scheme instead
                request->SetURL ( "http://mta/local/" + resourceName + resourcePath );
                return Create ( browser, frame, "http", request );
            }
            return nullptr;
        }
        
        // Redirect mtalocal://* to http://mta/local/*, call recursively
        request->SetURL ( "http://mta/local/" + path );
        return Create ( browser, frame, "http", request );
    }
    
    SString host = UTF16ToMbUTF8 ( urlParts.host.str );
    if ( scheme_name == "http" && host == "mta" )
    {
        // Scheme format: http://mta/resourceName/file.html or http://mta/local/file.html for the current resource

        // Get resource name and path
        SString path = UTF16ToMbUTF8 ( urlParts.path.str ).substr ( 1 ); // Remove slash at the front
        size_t slashPos = path.find ( '/' );
        if ( slashPos == std::string::npos )
            return nullptr;

        SString resourceName = path.substr ( 0, slashPos );
        SString resourcePath = path.substr ( slashPos + 1 );

        if ( resourcePath.empty () )
            return nullptr;

        // Get mime type from extension
        CefString mimeType;
        size_t pos = resourcePath.find_last_of ( '.' );
        if ( pos != std::string::npos )
            mimeType = CefGetMimeType ( resourcePath.substr ( pos + 1 ) );

        // Make sure we provide a mime type, even 
        // when we cannot deduct it from the file extension
        if ( mimeType.empty () )
            mimeType = "application/octet-stream";

        if ( pWebView->HasAjaxHandler ( resourcePath ) )
        {
            std::vector<SString> vecGet;
            std::vector<SString> vecPost;

            if ( urlParts.query.str != nullptr )
            {
                SString strGet = UTF16ToMbUTF8 ( urlParts.query.str );
                std::vector<SString> vecTmp;
                strGet.Split ( "&", vecTmp );

                SString key; SString value;
                for ( auto&& param : vecTmp )
                {
                    param.Split ( "=", &key, &value );
                    vecGet.push_back ( key );
                    vecGet.push_back ( value );
                }
            }

            CefPostData::ElementVector vecPostElements;
            auto postData = request->GetPostData ();
            if ( postData.get () )
            {
                request->GetPostData ()->GetElements ( vecPostElements );

                SString key; SString value;
                for ( auto&& post : vecPostElements )
                {
                    // Limit to 5MiB and allow byte data only
                    size_t bytesCount = post->GetBytesCount ();
                    if ( bytesCount > 5*1024*1024 || post->GetType () != CefPostDataElement::Type::PDE_TYPE_BYTES )
                        continue;

                    // Make string from buffer
                    std::unique_ptr<char[]> buffer { new char[bytesCount] };
                    post->GetBytes ( bytesCount, buffer.get () );
                    SStringX param ( buffer.get (), bytesCount );

                    // Parse POST data into vector
                    std::vector<SString> vecTmp;
                    param.Split ( "&", vecTmp );
                    
                    for ( auto&& param : vecTmp )
                    {
                        param.Split ( "=", &key, &value );
                        vecPost.push_back ( key );
                        vecPost.push_back ( value );
                    }
                }
            }

            auto handler = new CAjaxResourceHandler ( vecGet, vecPost, mimeType );
            pWebView->HandleAjaxRequest ( resourcePath, handler );
            return handler;
        }
        else
        {
            // Calculate MTA resource path
            if ( resourceName != "local" )
                path = ":" + resourceName + "/" + resourcePath;
            else
                path = resourcePath;

            // Calculate absolute path
            if ( !pWebView->GetFullPathFromLocal ( path ) )
                return nullptr;
        
            // Finally, load the file stream
            auto stream = CefStreamReader::CreateForFile ( path );
            if ( stream.get () )
                return new CefStreamResourceHandler ( mimeType, stream );
        }

        return nullptr;
    }

    // Return null if there is no matching scheme
    return nullptr;
}
Beispiel #2
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 #3
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;
}
Beispiel #4
0
////////////////////////////////////////////////////////////////////
//                                                                //
// Implementation: CefDisplayHandler::OnTooltip                   //
// http://magpcss.org/ceforum/apidocs3/projects/(default)/CefDisplayHandler.html#OnTooltip(CefRefPtr%3CCefBrowser%3E,CefString&) //
//                                                                //
////////////////////////////////////////////////////////////////////
bool CWebView::OnTooltip ( CefRefPtr<CefBrowser> browser, CefString& title )
{
    // Queue event to run on the main thread
    auto func = std::bind ( &CWebBrowserEventsInterface::Events_OnTooltip, m_pEventsInterface, UTF16ToMbUTF8 ( title ) );
    g_pCore->GetWebCore ()->AddEventToEventQueue ( func, this, "OnTooltip" );
    
    return true;
}
Beispiel #5
0
////////////////////////////////////////////////////////////////////
//                                                                //
// Implementation: CefDisplayHandler::OnTitleChange               //
// http://magpcss.org/ceforum/apidocs3/projects/(default)/CefDisplayHandler.html#OnTitleChange(CefRefPtr%3CCefBrowser%3E,constCefString&) //
//                                                                //
////////////////////////////////////////////////////////////////////
void CWebView::OnTitleChange ( CefRefPtr<CefBrowser> browser, const CefString& title )
{
    m_CurrentTitle = UTF16ToMbUTF8 ( title );
}
Beispiel #6
0
////////////////////////////////////////////////////////////////////
//                                                                //
// Implementation: CefRequestHandler::OnBeforeResourceLoad        //
// http://magpcss.org/ceforum/apidocs3/projects/(default)/CefRequestHandler.html#OnBeforeResourceLoad(CefRefPtr%3CCefBrowser%3E,CefRefPtr%3CCefFrame%3E,CefRefPtr%3CCefRequest%3E) //
//                                                                //
////////////////////////////////////////////////////////////////////
CefRequestHandler::ReturnValue CWebView::OnBeforeResourceLoad ( CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, CefRefPtr<CefRequestCallback> callback )
{
    // Mostly the same as CWebView::OnBeforeBrowse
    CefURLParts urlParts;
    if ( !CefParseURL ( request->GetURL (), urlParts ) )
        return RV_CANCEL; // Cancel if invalid URL (this line will normally not be executed)

    // Add some information to the HTTP header
    {
        CefRequest::HeaderMap headerMap;
        request->GetHeaderMap ( headerMap );
        auto iter = headerMap.find ( "User-Agent" );

        if ( iter != headerMap.end () )
        {
            // Add MTA:SA "watermark"
            iter->second = iter->second.ToString () + "; " MTA_CEF_USERAGENT;

            // Add 'Android' to get the mobile version
            SString strPropertyValue;
            if ( GetProperty ( "mobile", strPropertyValue ) && strPropertyValue == "1" )
                iter->second = iter->second.ToString () + "; Mobile Android";

            request->SetHeaderMap ( headerMap );
        }
    }

    WString scheme = urlParts.scheme.str;
    if ( scheme == L"http" || scheme == L"https" )
    {
        SString domain = UTF16ToMbUTF8 ( urlParts.host.str );
        if ( domain != "mta" )
        {
            if ( IsLocal () )
                return RV_CANCEL; // Block remote requests in local mode generally

            eURLState urlState = g_pCore->GetWebCore ()->GetURLState ( domain, true );
            if ( urlState != eURLState::WEBPAGE_ALLOWED )
            {
                // Trigger onClientBrowserResourceBlocked event
                auto func = std::bind ( &CWebBrowserEventsInterface::Events_OnResourceBlocked, m_pEventsInterface,
                    SString ( request->GetURL () ), domain, urlState == eURLState::WEBPAGE_NOT_LISTED ? 0 : 1 );
                g_pCore->GetWebCore ()->AddEventToEventQueue ( func, this, "OnResourceBlocked" );

                return RV_CANCEL; // Block if explicitly forbidden
            }

            // Allow
            return RV_CONTINUE;
        }
        else
            return RV_CONTINUE;
    }
    else if ( scheme == L"mtalocal" )
    {
        // Allow :)
        return RV_CONTINUE;
    }

     // Trigger onClientBrowserResourceBlocked event
    auto func = std::bind ( &CWebBrowserEventsInterface::Events_OnResourceBlocked, m_pEventsInterface, SString ( request->GetURL () ), "", 2 ); // reason 1 := blocked protocol scheme
    g_pCore->GetWebCore ()->AddEventToEventQueue ( func, this, "OnResourceBlocked" );

    // Block everything else
    return RV_CANCEL;
}
int CLuaFunctionDefs::GetTok ( lua_State* luaVM )
{
    SString strInput = "";
    unsigned int uiToken = 0;
    unsigned int uiDelimiter = 0;
    SString strDelimiter;
    CScriptArgReader argStream ( luaVM );
    argStream.ReadString ( strInput );
    argStream.ReadNumber ( uiToken );

    if ( argStream.NextIsNumber ( ) )
    {
        argStream.ReadNumber ( uiDelimiter );
        wchar_t wUNICODE[2] = { uiDelimiter, '\0' };
        strDelimiter = UTF16ToMbUTF8(wUNICODE);
    }
    else  // It's already a string
        argStream.ReadString ( strDelimiter );

    if ( !argStream.HasErrors ( ) )
    {
        unsigned int uiCount = 0;

        if ( uiToken > 0 && uiToken < 1024 )
        {
            unsigned int uiCount = 1;
            char* szText = new char [ strInput.length ( ) + 1 ];
            strcpy ( szText, strInput );
            char* szToken = strtok ( szText, strDelimiter );

            // We're looking for the first part?
            if ( uiToken != 1 )
            {
                // strtok count number of times
                do
                {
                    uiCount++;
                    szToken = strtok ( NULL, strDelimiter );
                }
                while ( uiCount != uiToken );
            }

            // Found it?
            if ( szToken )
            {
                // Return it
                lua_pushstring ( luaVM, szToken );
                delete [] szText;
                return 1;
            }

            // Delete the text
            delete [] szText;
        }
        else
            m_pScriptDebugging->LogWarning ( luaVM, "Token parameter sent to split must be greater than 0 and smaller than 1024" );
    }
    else
        m_pScriptDebugging->LogCustom ( luaVM, argStream.GetFullErrorMessage() );

    lua_pushboolean ( luaVM, false );
    return 1;
}