Exemplo n.º 1
0
//
// Process next BrowseToSolution
//
void SharedUtil::ProcessPendingBrowseToSolution ( void )
{
    SString strType, strMessageBoxMessage;
    int bAskQuestion;

    // Get args from the registry
    CArgMap argMap;
    argMap.SetFromString ( GetApplicationSetting ( "pending-browse-to-solution" ) );
    argMap.Get ( "type", strType );
    argMap.Get ( "message", strMessageBoxMessage );
    argMap.Get ( "bAskQuestion", bAskQuestion );

    // Check if anything to do
    if ( strType.empty () )
        return;

    ClearPendingBrowseToSolution ();

    // Show message box if required
    if ( !strMessageBoxMessage.empty () )
        MessageBox ( 0, strMessageBoxMessage, "Error", MB_OK|MB_ICONEXCLAMATION );

    // Ask question if required, and then launch URL
    if ( !bAskQuestion || IDYES == MessageBox( 0, "Do you want to see some on-line help about this problem ?", "MTA: San Andreas", MB_ICONQUESTION|MB_YESNO ) )
    {
        SString strQueryURL = GetApplicationSetting ( "trouble-url" );
        if ( strQueryURL == "" )
            strQueryURL = TROUBLE_URL1;
        strQueryURL = strQueryURL.Replace ( "%VERSION%", GetApplicationSetting ( "mta-version-ext" ) );
        strQueryURL = strQueryURL.Replace ( "%ID%", GetApplicationSetting ( "serial" ) );
        strQueryURL = strQueryURL.Replace ( "%TROUBLE%", strType );
        ShellExecuteNonBlocking ( "open", strQueryURL.c_str () );
    }
}
Exemplo n.º 2
0
bool CClientDFF::ReplaceModel(unsigned short usModel, bool bAlphaTransparency)
{
    // Record attempt in case it all goes wrong
    CArgMap argMap;
    argMap.Set("id", usModel);
    argMap.Set("reason", "ReplaceModel");
    SetApplicationSetting("diagnostics", "gta-model-fail", argMap.ToString());

    bool bResult = DoReplaceModel(usModel, bAlphaTransparency);

    SetApplicationSetting("diagnostics", "gta-model-fail", "");
    return bResult;
}
////////////////////////////////////////////////////////////////////////////////////////////////
// Check for invalid RpHAnimHierarchy*
void _cdecl OnGetAnimHierarchyFromSkinClump(RpClump* pRpClump, void* pRpHAnimHierarchyResult)
{
    if (pRpHAnimHierarchyResult == nullptr)
    {
        // Crash will occur at offset 003C51A8
        uint uiModelId = pGameInterface->GetPools()->GetModelIdFromClump(pRpClump);
        LogEvent(818, "Model bad anim hierarchy", "GetAnimHierarchyFromSkinClump", SString("Corrupt model:%d", uiModelId), 5418);
        CArgMap argMap;
        argMap.Set("id", uiModelId);
        argMap.Set("reason", "anim_hierarchy");
        SetApplicationSetting("diagnostics", "gta-model-fail", argMap.ToString());
    }
}
Exemplo n.º 4
0
//////////////////////////////////////////////////////////
//
// CInstallManager::_InstallNewsItems
//
//
//
//////////////////////////////////////////////////////////
SString CInstallManager::_InstallNewsItems ( void )
{
    // Get install news queue
    CArgMap queue;
    queue.SetFromString ( GetApplicationSetting ( "news-install" ) );
    SetApplicationSetting ( "news-install", "" );

    std::vector < SString > keyList;
    queue.GetKeys ( keyList );
    for ( uint i = 0 ; i < keyList.size () ; i++ )
    {
        // Install each file
        SString strDate = keyList[i];
        SString strFileLocation = queue.Get ( strDate );

        // Save cwd
        SString strSavedDir = GetSystemCurrentDirectory ();

        // Calc and make target dir
        SString strTargetDir = PathJoin ( GetMTADataPath (), "news", strDate );
        MkDir ( strTargetDir );

        // Extract into target dir
        SetCurrentDirectory ( strTargetDir );

        // Try to extract the files
        if ( !ExtractFiles ( strFileLocation ) )
        {
            // If extract failed and update file is an exe, try to run it
            if ( ExtractExtension ( strFileLocation ).CompareI ( "exe" ) )
                ShellExecuteBlocking ( "open", strFileLocation, "-s" );
        }

        // Restore cwd
        SetCurrentDirectory ( strSavedDir );

        // Check result
        if ( FileExists ( PathJoin ( strTargetDir, "files.xml" ) ) )
        {
            SetApplicationSettingInt ( "news-updated", 1 );
            AddReportLog ( 2051, SString ( "InstallNewsItems ok for '%s'", *strDate ) );
        }
        else
        {
            AddReportLog ( 4048, SString ( "InstallNewsItems failed with '%s' '%s' '%s'", *strDate, *strFileLocation, *strTargetDir ) );
        }
    }
    return "ok";
}
Exemplo n.º 5
0
//
// Direct players to info about trouble
//
void SharedUtil::BrowseToSolution ( const SString& strType, bool bAskQuestion, bool bTerminateProcess, bool bDoOnExit, const SString& strMessageBoxMessage )
{
    AddReportLog ( 3200, SString ( "Trouble %s", *strType ) );

    // Put args into a string and save in the registry
    CArgMap argMap;
    argMap.Set ( "type", strType.SplitLeft ( ";" ) );
    argMap.Set ( "bAskQuestion", bAskQuestion );
    argMap.Set ( "message", strMessageBoxMessage );
    SetApplicationSetting ( "pending-browse-to-solution", argMap.ToString () );

    // Do it now if required
    if ( !bDoOnExit )
        ProcessPendingBrowseToSolution ();

    // Exit if required
    if ( bTerminateProcess )
        TerminateProcess ( GetCurrentProcess (), 1 );
}
///////////////////////////////////////////////////////////////
//
// CDatabaseConnectionMySql::CDatabaseConnectionMySql
//
//
//
///////////////////////////////////////////////////////////////
CDatabaseConnectionMySql::CDatabaseConnectionMySql ( CDatabaseType* pManager, const SString& strHost, const SString& strUsername, const SString& strPassword, const SString& strOptions )
    : m_iRefCount ( 1 )
    , m_pManager ( pManager )
{
    // Parse options string
    CArgMap optionsMap ( "=", ";" );
    optionsMap.SetFromString ( strOptions );
    optionsMap.Get ( "autoreconnect", m_bAutomaticReconnect, 1 );
    optionsMap.Get ( "batch", m_bAutomaticTransactionsEnabled, 1 );

    SString strHostname;
    SString strDatabaseName;
    int iPort = 0;
    SString strUnixSocket;
    ulong ulClientFlags = 0;

    // Parse host string
    CArgMap argMap ( "=", ";" );
    argMap.SetFromString ( strHost );
    argMap.Get ( "dbname", strDatabaseName, "" );
    argMap.Get ( "host", strHostname, "localhost" );
    argMap.Get ( "port", iPort, 0 );
    argMap.Get ( "unix_socket", strUnixSocket, "" );

    m_handle = mysql_init ( NULL );
    if ( m_handle )
    {
        my_bool reconnect = m_bAutomaticReconnect;
        mysql_options ( m_handle, MYSQL_OPT_RECONNECT, &reconnect );

        if ( mysql_real_connect ( m_handle, strHostname, strUsername, strPassword, strDatabaseName, iPort, strUnixSocket, ulClientFlags ) )
            m_bOpened = true;
        else
        {
            SetLastError ( mysql_errno( m_handle ), mysql_error ( m_handle ) );
        }
    }
}
Exemplo n.º 7
0
bool CMainConfig::Load ( void )
{
    // Eventually destroy the previously loaded xml
    if ( m_pFile )
    {
        delete m_pFile;
        m_pFile = NULL;
    }

    // Load the XML
    m_pFile = g_pServerInterface->GetXML ()->CreateXML ( GetFileName ().c_str () );
    if ( !m_pFile )
    {
        CLogger::ErrorPrintf ( "Error loading config file\n" );
        return false;
    }

    // Parse it
    if ( !m_pFile->Parse () )
    {
        CLogger::ErrorPrintf ( "Error parsing config file\n" );
        return false;
    }

    // Grab the XML root node
    m_pRootNode = m_pFile->GetRootNode ();
    if ( !m_pRootNode )
    {
        CLogger::ErrorPrintf ( "Missing root node ('config')\n" );
        return false;
    }

    // Name
    int iResult = GetString ( m_pRootNode, "servername", m_strServerName, 1, 96 );
    if ( iResult == DOESNT_EXIST )
    {
        CLogger::ErrorPrintf ( "Server name not specified in config\n" );
        return false;
    }
    else if ( iResult == INVALID_VALUE )
    {
        CLogger::ErrorPrintf ( "Server name must be between 1 and 96 characters\n" );
        return false;
    }

    // Grab the script debuglog
    GetString ( m_pRootNode, "serverip", m_strServerIP, 1 );

    // Grab the port
    int iTemp;
    iResult = GetInteger ( m_pRootNode, "serverport", iTemp, 1, 65535 );
    if ( iResult == IS_SUCCESS )
    {
        m_usServerPort = static_cast < unsigned short > ( iTemp );
    }
    else
    {
        if ( iResult == DOESNT_EXIST )
            CLogger::ErrorPrintf ( "Server port not specified in config\n" );
        else
            CLogger::ErrorPrintf ( "Server port must be between 1 and 65535\n" );

        return false;
    }

    // Grab the max players
    iResult = GetInteger ( m_pRootNode, "maxplayers", iTemp, 1, MAX_PLAYER_COUNT );
    if ( iResult == IS_SUCCESS )
    {
        m_uiHardMaxPlayers = iTemp;
        m_uiSoftMaxPlayers = iTemp;
    }
    else
    {
        if ( iResult == DOESNT_EXIST )
            CLogger::ErrorPrintf ( "Max players not specified in config\n" );
        else
            CLogger::ErrorPrintf ( "Max players must be between 1 and %u\n", MAX_PLAYER_COUNT );

        return false;
    }

    // httpserver
    iResult = GetBoolean ( m_pRootNode, "httpserver", m_bHTTPEnabled );
    if ( iResult == INVALID_VALUE )
    {
        CLogger::LogPrint ( "WARNING: Invalid value specified in \"httpserver\" tag; defaulting to 1\n" );
        m_bHTTPEnabled = true;
    }
    else if ( iResult == DOESNT_EXIST )
    {
        m_bHTTPEnabled = false;
    }

    // HTTPD port
    iResult = GetInteger ( m_pRootNode, "httpport", iTemp, 1, 65535 );
    if ( iResult == IS_SUCCESS )
    {
        m_usHTTPPort = static_cast < unsigned short > ( iTemp );
    }
    else
    {
        if ( iResult == DOESNT_EXIST )
            CLogger::ErrorPrintf ( "HTTP port is not specified in config\n" );
        else
            CLogger::ErrorPrintf ( "HTTP server port must be between 1 and 65535\n" );

        return false;
    }

    // HTTPD Download URL (if we want to host externally)
    if ( GetString ( m_pRootNode, "httpdownloadurl", m_strHTTPDownloadURL, 5 ) == IS_SUCCESS )
    {
        m_ucHTTPDownloadType = HTTP_DOWNLOAD_ENABLED_URL;
        m_strHTTPDownloadURL = SString ( m_strHTTPDownloadURL ).TrimEnd ( "/" );
    }
    else
    {
        m_ucHTTPDownloadType = HTTP_DOWNLOAD_ENABLED_PORT;
        m_strHTTPDownloadURL = "";
    }

    // httpmaxconnectionsperclient
    GetInteger ( m_pRootNode, "httpmaxconnectionsperclient", m_iHTTPMaxConnectionsPerClient, 1, 8 );
    m_iHTTPMaxConnectionsPerClient = Clamp ( 1, m_iHTTPMaxConnectionsPerClient, 8 );

    // httpthreadcount
    GetInteger ( m_pRootNode, "httpthreadcount", m_iHTTPThreadCount, 1, 20 );
    m_iHTTPThreadCount = Clamp ( 1, m_iHTTPThreadCount, 20 );

    // httpdosthreshold
    GetInteger ( m_pRootNode, "httpdosthreshold", m_iHTTPDosThreshold, 1, 10000 );
    m_iHTTPDosThreshold = Clamp ( 1, m_iHTTPDosThreshold, 10000 );

    // verifyclientsettings
    GetInteger ( m_pRootNode, "verifyclientsettings", m_iEnableClientChecks );

    // Handle the <client_file> nodes
    CXMLNode* pNode = NULL;
    unsigned int uiCurrentIndex = 0;
    do
    {
        // Grab the current script node
        pNode = m_pRootNode->FindSubNode ( "client_file", uiCurrentIndex++ );
        if ( pNode )
        {
            // Grab its "name" attribute
            CXMLAttribute* pAttribute = pNode->GetAttributes ().Find ( "name" );
            SString strName = pAttribute ? pAttribute->GetValue () : "";
            strName = strName.Replace ( "\\", "/" ).ToLower ();

            // Grab its "verify" attribute
            pAttribute = pNode->GetAttributes ().Find ( "verify" );
            SString strVerify = pAttribute ? pAttribute->GetValue () : "";
            bool bVerify = strVerify == "true" || strVerify == "yes" || strVerify == "1";

            // Find bitnumber
            bool bFound = false;
            for ( uint i = 0 ; i < NUMELMS( gtaDataFiles ) ; i++ )
            {
                if ( strName == gtaDataFiles[i].szRealFilename )
                {
                    if ( bVerify )
                        m_iEnableClientChecks |= 1 << gtaDataFiles[i].iBitNumber;
                    else
                        m_iEnableClientChecks &= ~( 1 << gtaDataFiles[i].iBitNumber );
                    bFound = true;
                    break;
                }
            }

            if ( !bFound )
                CLogger::ErrorPrintf ( "Unknown client_file '%s'\n", *strName );
        }
    }
    while ( pNode );


    // hideac
    int iHideAC = 0;
    GetInteger ( m_pRootNode, "hideac", iHideAC );

    {
        std::set < SString > disableACMap;
        std::set < SString > enableSDMap;

        {
            SString strDisableAC;
            GetString ( m_pRootNode, "disableac", strDisableAC );
            std::vector < SString > tagACList;
            strDisableAC.Split ( ",", tagACList );
            for ( std::vector < SString >::iterator it = tagACList.begin () ; it != tagACList.end () ; ++it )
                if ( isdigit((uchar)***it) )
                {
                    MapInsert ( disableACMap, *it );
                    MapInsert ( m_DisableComboACMap, *it );
                }
        }

        // Add support for SD #12, #14, #15, #16, #20, #22 and #28 (defaults to disabled)
        MapInsert ( m_DisableComboACMap, "12" );
        MapInsert ( m_DisableComboACMap, "14" );
        MapInsert ( m_DisableComboACMap, "15" );
        MapInsert ( m_DisableComboACMap, "16" );
        MapInsert ( m_DisableComboACMap, "20" );
        MapInsert ( m_DisableComboACMap, "22" );
        MapInsert ( m_DisableComboACMap, "28" );

        {
            SString strEnableSD;
            GetString ( m_pRootNode, "enablesd", strEnableSD );
            std::vector < SString > tagSDList;
            strEnableSD.Split ( ",", tagSDList );
            for ( std::vector < SString >::iterator it = tagSDList.begin () ; it != tagSDList.end () ; ++it )
                if ( isdigit((uchar)***it) )
                {
                    MapInsert ( enableSDMap, *it );
                    MapRemove ( m_DisableComboACMap, *it );
                }

            // Also save initial value in transient settings, so we can update the config without anyone knowing
            MapSet ( m_TransientSettings, "enablesd", strEnableSD );
        }

        CArgMap argMap;
        for ( std::set < SString >::iterator it = m_DisableComboACMap.begin () ; it != m_DisableComboACMap.end () ; ++it )
            argMap.Set ( *it, "" );
        SString strDisableComboACMap = argMap.ToString ();

        argMap = CArgMap ();
        for ( std::set < SString >::iterator it = disableACMap.begin () ; it != disableACMap.end () ; ++it )
            argMap.Set ( *it, "" );
        SString strDisableACMap = argMap.ToString ();

        argMap = CArgMap ();
        for ( std::set < SString >::iterator it = enableSDMap.begin () ; it != enableSDMap.end () ; ++it )
            argMap.Set ( *it, "" );
        SString strEnableSDMap = argMap.ToString ();

        g_pNetServer->SetChecks ( strDisableComboACMap, strDisableACMap, strEnableSDMap, m_iEnableClientChecks, iHideAC != 0 );
    }

    {
        SString strEnable;
        GetString ( m_pRootNode, "enablediagnostic", strEnable );
        std::vector < SString > tagList;
        strEnable.Split ( ",", tagList );
        for ( std::vector < SString >::iterator it = tagList.begin () ; it != tagList.end () ; ++it )
            if ( (*it).length () )
                MapInsert ( m_EnableDiagnosticMap, *it );
    }

    // Grab the server password
    iResult = GetString ( m_pRootNode, "password", m_strPassword, 1, 32 );

    // Grab the server fps limit
    int iFPSTemp = 0;
    iResult = GetInteger ( m_pRootNode, "fpslimit", iFPSTemp, 0, 100 );
    if ( iResult == IS_SUCCESS )
    {
        if ( iFPSTemp == 0 || iFPSTemp >= 25 )
        {
             m_usFPSLimit = (unsigned short)iFPSTemp;
             SetInteger ( m_pRootNode, "fpslimit", (int)m_usFPSLimit );
        }
    }

    // Grab whether or not voice is enabled
    iResult = GetInteger ( m_pRootNode, "voice", iTemp, 0, 1 );
    if ( iResult == IS_SUCCESS )
    {
        m_bVoiceEnabled = iTemp ? true : false;
    }

    // Grab the Sample Rate for Voice
    iTemp = m_uiVoiceSampleRate;
    iResult = GetInteger ( m_pRootNode, "voice_samplerate", iTemp, 0, 2 );
    m_uiVoiceSampleRate = Clamp ( 0, iTemp, 2 );

    // Grab the Quality for Voice
    iTemp = m_ucVoiceQuality;
    iResult = GetInteger ( m_pRootNode, "voice_quality", iTemp, 0, 10 );
    m_ucVoiceQuality = Clamp ( 0, iTemp, 10 );

    // Grab the bitrate for Voice [optional]
    iResult = GetInteger ( m_pRootNode, "voice_bitrate", iTemp );
    if ( iResult == IS_SUCCESS )
    {
        m_uiVoiceBitrate = iTemp;
    }


    // Grab the serial verification
    /** ACHTUNG: Unsupported for release 1.0 (#4090)
    iResult = GetBoolean ( m_pRootNode, "verifyserials", m_bVerifySerials );
    if ( iResult == INVALID_VALUE )
    {
        m_bVerifySerials = true;
    }
    else if ( iResult == DOESNT_EXIST )
    */
    {
        m_bVerifySerials = false;
    }

    // Grab the server-id filename
    SString strIdFile = "server-id.keys";
    GetString ( m_pRootNode, "idfile", strIdFile, 1 );
    m_strIdFile = g_pServerInterface->GetModManager ()->GetAbsolutePath ( strIdFile );

    // Grab the server logfiles
    std::string strBuffer;
    if ( GetString ( m_pRootNode, "logfile", strBuffer, 1 ) == IS_SUCCESS )
        m_strLogFile = g_pServerInterface->GetModManager ()->GetAbsolutePath ( strBuffer.c_str () );

    if ( GetString ( m_pRootNode, "authfile", strBuffer, 1 ) == IS_SUCCESS )
        m_strAuthFile = g_pServerInterface->GetModManager ()->GetAbsolutePath ( strBuffer.c_str () );

    if ( GetString ( m_pRootNode, "dbfile", strBuffer, 1 ) == IS_SUCCESS )
        m_strDbLogFilename = g_pServerInterface->GetModManager ()->GetAbsolutePath ( strBuffer.c_str () );
    else
        m_strDbLogFilename = g_pServerInterface->GetModManager ()->GetAbsolutePath ( "logs/db.log" );

    if ( GetString ( m_pRootNode, "loadstringfile", strBuffer, 1 ) == IS_SUCCESS )
        m_strLoadstringLogFilename = g_pServerInterface->GetModManager ()->GetAbsolutePath ( strBuffer.c_str () );

    // Grab the server access control list
    if ( GetString ( m_pRootNode, "acl", strBuffer, 1, 255 ) == IS_SUCCESS )
    {
        m_strAccessControlListFile = g_pServerInterface->GetModManager ()->GetAbsolutePath ( strBuffer.c_str () );
    }
    else
    {
        m_strAccessControlListFile = g_pServerInterface->GetModManager ()->GetAbsolutePath ( "acl.xml" );
    }

    // Grab the global databases path
    if ( GetString ( m_pRootNode, "global_databases_path", strBuffer, 1, 255 ) != IS_SUCCESS )
        strBuffer = "databases/global";
    if ( !IsValidFilePath ( strBuffer.c_str () ) || strBuffer.empty () )
    {
        CLogger::ErrorPrintf ( "global_databases_path is not valid. Defaulting to 'databases/global'\n" );
        strBuffer = "databases/global";
    }
    m_strGlobalDatabasesPath = g_pServerInterface->GetModManager ()->GetAbsolutePath ( strBuffer.c_str () );

    // Grab the system databases path
    if ( GetString ( m_pRootNode, "system_databases_path", strBuffer, 1, 255 ) != IS_SUCCESS )
        strBuffer = "databases/system";
    if ( !IsValidFilePath ( strBuffer.c_str () ) || strBuffer.empty () )
    {
        CLogger::ErrorPrintf ( "system_databases_path is not valid. Defaulting to 'databases/system'\n" );
        strBuffer = "databases/system";
    }
    m_strSystemDatabasesPath = g_pServerInterface->GetModManager ()->GetAbsolutePath ( strBuffer.c_str () );

    // Grab the backup path
    if ( GetString ( m_pRootNode, "backup_path", strBuffer, 1, 255 ) != IS_SUCCESS )
        strBuffer = "backups";
    if ( !IsValidFilePath ( strBuffer.c_str () ) || strBuffer.empty () )
    {
        CLogger::ErrorPrintf ( "backup_path is not valid. Defaulting to 'backups'\n" );
        strBuffer = "backups";
    }
    m_strBackupPath = g_pServerInterface->GetModManager ()->GetAbsolutePath ( strBuffer.c_str () );

    // Grab the backup interval
    GetInteger ( m_pRootNode, "backup_interval", m_iBackupInterval );
    m_iBackupInterval = Clamp ( 0, m_iBackupInterval, 30 );

    // Grab the backup count
    GetInteger ( m_pRootNode, "backup_copies", m_iBackupAmount );
    m_iBackupAmount = Clamp ( 0, m_iBackupAmount, 100 );

    GetBoolean ( m_pRootNode, "autologin", m_bAutoLogin );

    // networkencryption - Encryption for Server <-> client communications
    GetBoolean ( m_pRootNode, "networkencryption", m_bNetworkEncryptionEnabled );

    // bandwidth_reduction
    GetString ( m_pRootNode, "bandwidth_reduction", m_strBandwidthReductionMode );
    ApplyBandwidthReductionMode ();

    // busy_sleep_time
    GetInteger ( m_pRootNode, "busy_sleep_time", m_iPendingWorkToDoSleepTime );
    m_iPendingWorkToDoSleepTime = Clamp ( -1, m_iPendingWorkToDoSleepTime, 50 );

    // idle_sleep_time
    GetInteger ( m_pRootNode, "idle_sleep_time", m_iNoWorkToDoSleepTime );
    m_iNoWorkToDoSleepTime = Clamp ( -1, m_iNoWorkToDoSleepTime, 50 );

    // threadnet - Default to on at startup
    m_bThreadNetEnabled = true;
    ApplyThreadNetEnabled ();

    // Check settings in this list here
    const std::vector < SIntSetting >& settingList = GetIntSettingList ();
    for ( uint i = 0 ; i < settingList.size () ; i++ )
    {
        const SIntSetting& item = settingList[i];
        int iValue = item.iDefault;
        GetInteger ( m_pRootNode, item.szName, iValue );
        *item.pVariable = Clamp ( item.iMin, iValue, item.iMax );
    }

    // Handle recently retired lightsync_rate
    if ( m_pRootNode->FindSubNode ( "lightweight_sync_interval" ) == NULL )
    {
        GetInteger ( m_pRootNode, "lightsync_rate", g_TickRateSettings.iLightSync );
        g_TickRateSettings.iLightSync = Clamp ( 200, g_TickRateSettings.iLightSync, 4000 );
    }

    ApplyNetOptions ();

    return true;
}
Exemplo n.º 8
0
//
// Extract and map data from a shoutcast meta string
//
void CBassAudio::ParseShoutcastMeta ( const SString& strMeta )
{
    // Get title
    int startPos = strMeta.find ( "=" );
    SString strStreamTitle = strMeta.SubStr ( startPos + 2, strMeta.find ( ";" ) - startPos - 3 );

    if ( !strStreamTitle.empty () )
        m_strStreamTitle = strStreamTitle;

    // Get url
    startPos = strMeta.find ( "=" , startPos + 1 );
    SString strStreamUrl = strMeta.SubStr ( startPos + 2, strMeta.find ( ";", startPos ) - startPos - 3 );

    // Extract info from url
    CArgMap shoutcastInfo;
    shoutcastInfo.SetEscapeCharacter ( '%' );
    shoutcastInfo.SetFromString ( strStreamUrl );

    // Convert from shoutcast identifiers to map of tags
    static const char* convList[] = {
                        // Mapable
                        "%ARTI", "artist",
                        "%TITL", "title",
                        "%ALBM", "album",

                        // Mapable, but possibly don't exist
                        "%GNRE", "genre",
                        "%YEAR", "year",
                        "%CMNT", "comment",
                        "%TRCK", "track",
                        "%COMP", "composer",
                        "%COPY", "copyright",
                        "%SUBT", "subtitle",
                        "%AART", "albumartist",

                        // Not mapabale
                        "%DURATION", "duration",
                        "%SONGTYPE", "songtype",
                        "%OVERLAY", "overlay",
                        "%BUYCD", "buycd",
                        "%WEBSITE", "website",
                        "%PICTURE", "picture",
                   };

    std::vector < SString > shoutcastKeyList;
    shoutcastInfo.GetKeys ( shoutcastKeyList );

    // For each shoutcast pair
    for ( std::vector < SString >::iterator iter = shoutcastKeyList.begin () ; iter != shoutcastKeyList.end () ; ++iter )
    {
        const SString& strKey = *iter;
        SString strValue = shoutcastInfo.Get ( strKey );

        // Find %TAG match
        for ( uint i = 0 ; i < NUMELMS( convList ) - 1 ; i += 2 )
        {
            if ( strKey == convList[ i + 1 ] )
            {
                MapSet ( m_ConvertedTagMap, convList[ i ], strValue );
                break;
            }
        }
    }
}
Exemplo n.º 9
0
 void CArgMap::Merge ( const CArgMap& other, bool bAllowMultiValues )
 {
     MergeFromString ( other.ToString (), bAllowMultiValues );
 }