diff options
Diffstat (limited to 'utils/bugreporter/bugreporter.cpp')
| -rw-r--r-- | utils/bugreporter/bugreporter.cpp | 1180 |
1 files changed, 1180 insertions, 0 deletions
diff --git a/utils/bugreporter/bugreporter.cpp b/utils/bugreporter/bugreporter.cpp new file mode 100644 index 0000000..6002107 --- /dev/null +++ b/utils/bugreporter/bugreporter.cpp @@ -0,0 +1,1180 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// +#define PROTECTED_THINGS_DISABLE +#undef PROTECT_FILEIO_FUNCTIONS +#undef fopen +#include <windows.h> +#include "basetypes.h" + +#include "utlvector.h" +#include "utlsymbol.h" +#include "utldict.h" +#include "utlbuffer.h" + +#include "bugreporter/bugreporter.h" +#include "trktool.h" +#include "filesystem_tools.h" +#include "KeyValues.h" + +#define SCR_TYPE 1 + +#define TRACKER_SETTINGS "resource/bugreporter.res" +#define TRACKER_LOGIN "cfg/bugreporter_login.res" + +#define DEFAULT_DBMS "tracker" +#define DEFAULT_PROJECT "Half-Life 2" +#define DEFAULT_USERNAME "" +#define DEFAULT_PASSWORD DEFAULT_USERNAME + +IBaseFileSystem *g_pFileSystem = NULL; + +class CBug +{ +public: + CBug() + { + Clear(); + } + + void Clear() + { + Q_memset( title, 0, sizeof( title ) ); + Q_memset( desc, 0, sizeof( desc ) ); + Q_memset( submitter, 0, sizeof( submitter ) ); + Q_memset( owner, 0, sizeof( owner ) ); + Q_memset( severity, 0, sizeof( severity ) ); + Q_memset( priority, 0, sizeof( priority ) ); + Q_memset( area, 0, sizeof( area ) ); + Q_memset( mapnumber, 0, sizeof( mapnumber) ); + Q_memset( reporttype, 0, sizeof( reporttype ) ); + Q_memset( level, 0, sizeof( level ) ); + Q_memset( build, 0, sizeof( build ) ); + Q_memset( position, 0, sizeof( position ) ); + Q_memset( orientation, 0, sizeof( orientation ) ); + Q_memset( screenshot_unc, 0, sizeof( screenshot_unc ) ); + Q_memset( savegame_unc, 0, sizeof( savegame_unc ) ); + Q_memset( bsp_unc, 0, sizeof( bsp_unc ) ); + Q_memset( vmf_unc, 0, sizeof( vmf_unc ) ); + Q_memset( driverinfo, 0, sizeof( driverinfo ) ); + Q_memset( misc, 0, sizeof( misc ) ); + + includedfiles.Purge(); + } + + char title[ 256 ]; + char desc[ 8192 ]; + char owner[ 256 ]; + char submitter[ 256 ]; + char severity[ 256 ]; + char priority[ 256 ]; + char area[ 256 ]; + char mapnumber[ 256 ]; + char reporttype[ 256 ]; + char level[ 256 ]; + char build[ 256 ]; + char position[ 256 ]; + char orientation[ 256 ]; + char screenshot_unc[ 256 ]; + char savegame_unc[ 256 ]; + char bsp_unc[ 256 ]; + char vmf_unc[ 256 ]; + char driverinfo[ 2048 ]; + char misc[ 1024 ]; + + struct incfile + { + char name[ 256 ]; + }; + + CUtlVector< incfile > includedfiles; +}; + +class CBugReporter : public IBugReporter +{ +public: + + CBugReporter(); + virtual ~CBugReporter(); + + // Initialize and login with default username/password for this computer (from resource/bugreporter.res) + virtual bool Init( CreateInterfaceFn engineFactory ); + virtual void Shutdown(); + + virtual bool IsPublicUI() { return false; } + + virtual char const *GetUserName(); + virtual char const *GetUserName_Display(); + + virtual int GetNameCount(); + virtual char const *GetName( int index ); + + virtual int GetDisplayNameCount(); + virtual char const *GetDisplayName( int index ); + + virtual char const *GetDisplayNameForUserName( char const *username ); + virtual char const *GetUserNameForDisplayName( char const *display ); + + virtual int GetSeverityCount(); + virtual char const *GetSeverity( int index ); + + virtual int GetPriorityCount(); + virtual char const *GetPriority( int index ); + + virtual int GetAreaCount(); + virtual char const *GetArea( int index ); + + virtual int GetAreaMapCount(); + virtual char const *GetAreaMap( int index ); + + virtual int GetMapNumberCount(); + virtual char const *GetMapNumber( int index ); + + virtual int GetReportTypeCount(); + virtual char const *GetReportType( int index ); + + virtual char const *GetRepositoryURL( void ) { return NULL; } + virtual char const *GetSubmissionURL( void ) { return NULL; } + + virtual int GetLevelCount(int area) { return 0; } + virtual char const *GetLevel(int area, int index ) { return ""; } + +// Submission API + virtual void StartNewBugReport(); + virtual void CancelNewBugReport(); + virtual bool CommitBugReport( int& bugSubmissionId ); + + virtual void SetTitle( char const *title ); + virtual void SetDescription( char const *description ); + + // NULL for current user + virtual void SetSubmitter( char const *username = 0 ); + virtual void SetOwner( char const *username ); + virtual void SetSeverity( char const *severity ); + virtual void SetPriority( char const *priority ); + virtual void SetArea( char const *area ); + virtual void SetMapNumber ( char const *mapnumber ); + virtual void SetReportType( char const *reporttype ); + + virtual void SetLevel( char const *levelnamne ); + virtual void SetPosition( char const *position ); + virtual void SetOrientation( char const *pitch_yaw_roll ); + virtual void SetBuildNumber( char const *build_num ); + + virtual void SetScreenShot( char const *screenshot_unc_address ); + virtual void SetSaveGame( char const *savegame_unc_address ); + + virtual void SetBSPName( char const *bsp_unc_address ); + virtual void SetVMFName( char const *vmf_unc_address ); + + virtual void AddIncludedFile( char const *filename ); + virtual void ResetIncludedFiles(); + + virtual void SetZipAttachmentName( char const *zipfilename ) {} // only used by public bug reporter + + virtual void SetDriverInfo( char const *info ); + + virtual void SetMiscInfo( char const *info ); + + // These are stubbed here, but are used by the public version... + virtual void SetCSERAddress( const struct netadr_s& adr ) {} + virtual void SetExeName( char const *exename ) {} + virtual void SetGameDirectory( char const *gamedir ) {} + virtual void SetRAM( int ram ) {} + virtual void SetCPU( int cpu ) {} + virtual void SetProcessor( char const *processor ) {} + virtual void SetDXVersion( unsigned int high, unsigned int low, unsigned int vendor, unsigned int device ) {} + virtual void SetOSVersion( char const *osversion ) {} + virtual void SetSteamUserID( void *steamid, int idsize ) {}; +private: + + void ReportError(TRK_UINT rc, char const *func, char const *msg ); + TRK_UINT Login(TRK_HANDLE* pTrkHandle); + bool PopulateLists(); + + bool PopulateChoiceList( char const *listname, CUtlVector< CUtlSymbol >& list ); + + void SubstituteBugId( int bugid, char *out, int outlen, CUtlBuffer& src ); + + CUtlSymbolTable m_BugStrings; + + CUtlVector< CUtlSymbol > m_Severity; + CUtlVector< CUtlSymbol > m_Names; + CUtlVector< CUtlSymbol > m_SortedDisplayNames; + CUtlDict< CUtlSymbol, int > m_InternalNameMapping; + CUtlVector< CUtlSymbol > m_Priority; + CUtlVector< CUtlSymbol > m_Area; + CUtlVector< CUtlSymbol > m_AreaMap; + CUtlVector< CUtlSymbol > m_MapNumber; + CUtlVector< CUtlSymbol > m_ReportType; + + TRK_HANDLE trkHandle; + TRK_RECORD_HANDLE trkRecHandle; + + CUtlSymbol m_UserName; + + CBug *m_pBug; +}; + +CBugReporter::CBugReporter() +{ + m_pBug = NULL; + + trkHandle = (TRK_HANDLE)0; + trkRecHandle = (TRK_RECORD_HANDLE)0; +} + +CBugReporter::~CBugReporter() +{ + m_BugStrings.RemoveAll(); + m_Severity.Purge(); + m_Names.Purge(); + m_SortedDisplayNames.Purge(); + m_InternalNameMapping.Purge(); + m_Priority.Purge(); + m_Area.Purge(); + m_MapNumber.Purge(); + m_ReportType.Purge(); + + delete m_pBug; +} + +struct TRKELookup +{ + unsigned int id; + char const *str; +}; + +#define TRKERROR( id ) { id, #id } + +static TRKELookup g_Lookup[] = +{ + TRKERROR( TRK_SUCCESS ), + TRKERROR( TRK_E_VERSION_MISMATCH ), + TRKERROR( TRK_E_OUT_OF_MEMORY ), + TRKERROR( TRK_E_BAD_HANDLE ), + TRKERROR( TRK_E_BAD_INPUT_POINTER ), + TRKERROR( TRK_E_BAD_INPUT_VALUE ), + TRKERROR( TRK_E_DATA_TRUNCATED ), + TRKERROR( TRK_E_NO_MORE_DATA ), + TRKERROR( TRK_E_LIST_NOT_INITIALIZED ), + TRKERROR( TRK_E_END_OF_LIST ), + TRKERROR( TRK_E_NOT_LOGGED_IN ), + TRKERROR( TRK_E_SERVER_NOT_PREPARED ), + TRKERROR( TRK_E_BAD_DATABASE_VERSION ), + TRKERROR( TRK_E_UNABLE_TO_CONNECT ), + TRKERROR( TRK_E_UNABLE_TO_DISCONNECT ), + TRKERROR( TRK_E_UNABLE_TO_START_TIMER ), + TRKERROR( TRK_E_NO_DATA_SOURCES ), + TRKERROR( TRK_E_NO_PROJECTS ), + TRKERROR( TRK_E_WRITE_FAILED ), + TRKERROR( TRK_E_PERMISSION_DENIED ), + TRKERROR( TRK_E_SET_FIELD_DENIED ), + TRKERROR( TRK_E_ITEM_NOT_FOUND ), + TRKERROR( TRK_E_CANNOT_ACCESS_DATABASE ), + TRKERROR( TRK_E_CANNOT_ACCESS_QUERY ), + TRKERROR( TRK_E_CANNOT_ACCESS_INTRAY ), + TRKERROR( TRK_E_CANNOT_OPEN_FILE ), + TRKERROR( TRK_E_INVALID_DBMS_TYPE ), + TRKERROR( TRK_E_INVALID_RECORD_TYPE ), + TRKERROR( TRK_E_INVALID_FIELD ), + TRKERROR( TRK_E_INVALID_CHOICE ), + TRKERROR( TRK_E_INVALID_USER ), + TRKERROR( TRK_E_INVALID_SUBMITTER ), + TRKERROR( TRK_E_INVALID_OWNER ), + TRKERROR( TRK_E_INVALID_DATE ), + TRKERROR( TRK_E_INVALID_STORED_QUERY ), + TRKERROR( TRK_E_INVALID_MODE ), + TRKERROR( TRK_E_INVALID_MESSAGE ), + TRKERROR( TRK_E_VALUE_OUT_OF_RANGE ), + TRKERROR( TRK_E_WRONG_FIELD_TYPE ), + TRKERROR( TRK_E_NO_CURRENT_RECORD ), + TRKERROR( TRK_E_NO_CURRENT_NOTE ), + TRKERROR( TRK_E_NO_CURRENT_ATTACHED_FILE ), + TRKERROR( TRK_E_NO_CURRENT_ASSOCIATION ), + TRKERROR( TRK_E_NO_RECORD_BEGIN ), + TRKERROR( TRK_E_NO_MODULE ), + TRKERROR( TRK_E_USER_CANCELLED ), + TRKERROR( TRK_E_SEMAPHORE_TIMEOUT ), + TRKERROR( TRK_E_SEMAPHORE_ERROR ), + TRKERROR( TRK_E_INVALID_SERVER_NAME ), + TRKERROR( TRK_E_NOT_LICENSED ) +}; + +void CBugReporter::ReportError(TRK_UINT rc, char const *func, char const *msg ) +{ + if ( rc != TRK_SUCCESS ) + { + switch (rc) + { + case TRK_E_ITEM_NOT_FOUND: + Msg( "%s %s was not found!\n", func, msg ); + break; + case TRK_E_INVALID_FIELD: + Msg( "%s %s Invalid field!\n", func, msg ); + break; + default: + int i = 0; + for ( i; i < ARRAYSIZE( g_Lookup ) ; ++i ) + { + if ( g_Lookup[ i ].id == rc ) + { + Msg( "%s returned %i - %s!\n", func, rc, g_Lookup[ i ].str ); + break; + } + } + + if ( i >= ARRAYSIZE( g_Lookup ) ) + { + Msg( "%s returned %i - %s!\n", func, rc, "???" ); + } + break; + } + } +} + +TRK_UINT CBugReporter::Login(TRK_HANDLE* pTrkHandle) +{ + char dbms[50] = DEFAULT_DBMS; + char proj[50] = DEFAULT_PROJECT; + + char username[ 50 ]; + char password[ 50 ]; + + GetPrivateProfileStringA( + "login", + "userid1", + DEFAULT_USERNAME, // default + username, + sizeof( username ), + "PVCSTRK.ini" ); + + if ( !Q_stricmp( username, DEFAULT_USERNAME) || !Q_stricmp( username, "BELMAPNTKY" ) ) // if userid1 didn't have a valid name in it try userid0 + { + GetPrivateProfileStringA( + "login", + "userid0", + DEFAULT_USERNAME, // default + username, + sizeof( username ), + "PVCSTRK.ini" ); + } + + Q_strncpy( password, username, sizeof( password ) ); + + if ( g_pFileSystem ) + { + KeyValues *kv = new KeyValues( "tracker_login" ); + Assert( kv ); + if ( kv ) + { + if ( kv->LoadFromFile( g_pFileSystem, TRACKER_SETTINGS ) ) + { + Q_strncpy( dbms, kv->GetString( "database_server", DEFAULT_DBMS ), sizeof( dbms ) ); + Q_strncpy( proj, kv->GetString( "project_name", DEFAULT_PROJECT ), sizeof( proj ) ); + } + + kv->Clear(); + + // Load optional login info + if ( g_pFileSystem->FileExists( TRACKER_LOGIN, "GAME" ) ) + { + if ( kv->LoadFromFile( g_pFileSystem, TRACKER_LOGIN ) ) + { + Q_strncpy( username, kv->GetString( "username", username ), sizeof( username ) ); + Q_strncpy( password, kv->GetString( "password", password ), sizeof( password ) ); + } + } + + kv->deleteThis(); + } + } + + bool maybeNoPVCSInstalled = false; + + // We still don't know the username. . try to get it from the environment + if( username[0] == '\0' ) + { + if( getenv( "username" ) ) + { + Q_strncpy( username, getenv( "username" ), sizeof( username ) ); + maybeNoPVCSInstalled = true; + } + } + + + m_UserName = m_BugStrings.AddString( username ); + + TRK_UINT rc = TrkProjectLogin(*pTrkHandle, + username, + password, + proj, + NULL, + NULL, + NULL, + NULL, + TRK_USE_INI_FILE_DBMS_LOGIN); + + if (rc != TRK_SUCCESS) + { + rc = TrkProjectLogin(*pTrkHandle, + username, + "", + proj, + NULL, + NULL, + NULL, + NULL, + TRK_USE_INI_FILE_DBMS_LOGIN); + if (rc != TRK_SUCCESS) + { + if ( maybeNoPVCSInstalled ) + { + Msg("Bug reporter failed: Make sure you have PVCS installed and that you have logged into it successfully at least once.\n"); + } + else + { + Msg("Bug reporter init failed: Your tracker password must be your user name or blank.\n"); + } + return rc; + } + } + + TrkGetLoginDBMSName(*pTrkHandle, sizeof(dbms), dbms ); + TrkGetLoginProjectName(*pTrkHandle, sizeof(proj), proj ); + + Msg( "Project: %s\n", proj ); + Msg( "Server: %s\n", dbms ); + + return rc; +} + +//----------------------------------------------------------------------------- +// Purpose: Initialize and login with default username/password for this computer (from resource/bugreporter.res) +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CBugReporter::Init( CreateInterfaceFn engineFactory ) +{ + if ( engineFactory ) + { + g_pFileSystem = (IFileSystem *)engineFactory( FILESYSTEM_INTERFACE_VERSION, NULL ); + if ( !g_pFileSystem ) + { + AssertMsg( 0, "Failed to create/get IFileSystem" ); + return false; + } + } + + TRK_UINT rc; + rc = TrkHandleAlloc( TRK_VERSION_ID, &trkHandle); + if ( rc != TRK_SUCCESS ) + { + ReportError(rc, "TrkHandleAlloc", "Failed to Allocate Tracker Handle!"); + return false; + } + + // Login to default project out of INI file. + rc = Login( &trkHandle ); + if (rc != TRK_SUCCESS) + { + return false; + } + + rc = TrkRecordHandleAlloc(trkHandle, &trkRecHandle); + if (rc != TRK_SUCCESS) + { + ReportError(rc, "TrkRecordHandleAlloc", + "Failed to Allocate Tracker Record Handle!"); + return false; + } + + PopulateLists(); + + return true; +} + +void CBugReporter::Shutdown() +{ + TRK_UINT rc; + + if ( trkRecHandle ) + { + rc = TrkRecordHandleFree(&trkRecHandle); + if (rc != TRK_SUCCESS) + { + ReportError(rc, "TrkRecordHandleFree", "Failed to Free Tracker Record Handle!"); + } + } + + if ( trkHandle ) + { + rc = TrkProjectLogout(trkHandle); + if (rc != TRK_SUCCESS) + { + ReportError(rc, "TrkProjectLogout", "Failed to Logout of Project!"); + } + else + { + rc = TrkHandleFree(&trkHandle); + if (rc != TRK_SUCCESS) + { + ReportError(rc, "TrkHandleFree", "Failed to Free Tracker Handle!"); + } + } + } +} + +char const *CBugReporter::GetUserName() +{ + return m_BugStrings.String( m_UserName ); +} + +char const *CBugReporter::GetUserName_Display() +{ + return GetDisplayNameForUserName( GetUserName() ); +} + +int CBugReporter::GetNameCount() +{ + return m_Names.Count(); +} + +char const *CBugReporter::GetName( int index ) +{ + if ( index < 0 || index >= m_Names.Count() ) + return "<<Invalid>>"; + + return m_BugStrings.String( m_Names[ index ] ); +} + +int CBugReporter::GetDisplayNameCount() +{ + return m_SortedDisplayNames.Count(); +} + +char const *CBugReporter::GetDisplayName( int index ) +{ + if ( index < 0 || index >= (int)m_SortedDisplayNames.Count() ) + return "<<Invalid>>"; + + return m_BugStrings.String( m_SortedDisplayNames[ index ] ); +} + +char const *CBugReporter::GetDisplayNameForUserName( char const *username ) +{ + int c = GetDisplayNameCount(); + for ( int i = 0; i < c ; i++ ) + { + CUtlSymbol sym = m_InternalNameMapping[ i ]; + char const *testname = m_BugStrings.String( sym ); + if ( !Q_stricmp( testname, username ) ) + { + return m_InternalNameMapping.GetElementName( i ); + } + } + + return "<<Invalid>>"; +} + +char const *CBugReporter::GetUserNameForDisplayName( char const *display ) +{ + int idx = m_InternalNameMapping.Find( display ); + if ( idx == m_InternalNameMapping.InvalidIndex() ) + return "<<Invalid>>"; + + CUtlSymbol sym; + sym = m_InternalNameMapping[ idx ]; + return m_BugStrings.String( sym ); +} + +int CBugReporter::GetSeverityCount() +{ + return m_Severity.Count() ; +} + +char const *CBugReporter::GetSeverity( int index ) +{ + if ( index < 0 || index >= m_Severity.Count() ) + return "<<Invalid>>"; + + return m_BugStrings.String( m_Severity[ index ] ); +} + +int CBugReporter::GetPriorityCount() +{ + return m_Priority.Count(); +} + +char const *CBugReporter::GetPriority( int index ) +{ + if ( index < 0 || index >= m_Priority.Count() ) + return "<<Invalid>>"; + + return m_BugStrings.String( m_Priority[ index ] ); +} + +int CBugReporter::GetAreaCount() +{ + return m_Area.Count(); +} + +char const *CBugReporter::GetArea( int index ) +{ + if ( index < 0 || index >= m_Area.Count() ) + return "<<Invalid>>"; + + return m_BugStrings.String( m_Area[ index ] ); +} + +int CBugReporter::GetAreaMapCount() +{ + return m_AreaMap.Count(); +} + +char const *CBugReporter::GetAreaMap( int index ) +{ + if ( index < 0 || index >= m_AreaMap.Count() ) + return "<<Invalid>>"; + + return m_BugStrings.String( m_AreaMap[ index ] ); +} + +int CBugReporter::GetMapNumberCount() +{ + return m_MapNumber.Count(); +} + +char const *CBugReporter::GetMapNumber( int index ) +{ + if ( index < 0 || index >= m_MapNumber.Count() ) + return "<<Invalid>>"; + + return m_BugStrings.String( m_MapNumber[ index ] ); +} + +int CBugReporter::GetReportTypeCount() +{ + return m_ReportType.Count(); +} + +char const *CBugReporter::GetReportType( int index ) +{ + if ( index < 0 || index >= m_ReportType.Count() ) + return "<<Invalid>>"; + + return m_BugStrings.String( m_ReportType[ index ] ); +} + +void CBugReporter::StartNewBugReport() +{ + if ( !m_pBug ) + { + m_pBug = new CBug(); + } + else + { + m_pBug->Clear(); + } +} + +void CBugReporter::CancelNewBugReport() +{ + if ( !m_pBug ) + return; + + m_pBug->Clear(); +} + +void CBugReporter::SubstituteBugId( int bugid, char *out, int outlen, CUtlBuffer& src ) +{ + out[ 0 ] = 0; + + char *dest = out; + + src.SeekGet( CUtlBuffer::SEEK_HEAD, 0 ); + + char const *replace = "\\BugId\\"; + int replace_len = Q_strlen( replace ); + + for ( int pos = 0; pos <= src.TellPut() && ( ( dest - out ) < outlen ); ) + { + char const *str = ( char const * )src.PeekGet( pos ); + if ( !Q_strnicmp( str, replace, replace_len ) ) + { + *dest++ = '\\'; + + char num[ 32 ]; + Q_snprintf( num, sizeof( num ), "%i", bugid ); + char *pnum = num; + while ( *pnum ) + { + *dest++ = *pnum++; + } + + *dest++ = '\\'; + pos += replace_len; + continue; + } + + *dest++ = *str; + ++pos; + } + *dest = 0; +} + +bool CBugReporter::CommitBugReport( int& bugSubmissionId ) +{ + bugSubmissionId = -1; + + if ( !m_pBug ) + return false; + + TRK_UINT rc = 0; + rc = TrkNewRecordBegin( trkRecHandle, SCR_TYPE ); + if ( rc != TRK_SUCCESS ) + { + ReportError(rc, "TrkNewRecordBegin", + "Failed to TrkNewRecordBegin!"); + return false; + } + + // Populate fields + rc = TrkSetStringFieldValue( trkRecHandle, + "Title", + m_pBug->title ); + if ( rc != TRK_SUCCESS ) + { + ReportError(rc, "TrkSetStringFieldValue", + "Failed to add title!"); + return false; + } + rc = TrkSetStringFieldValue( trkRecHandle, + "Submitter", + m_pBug->submitter ); + if ( rc != TRK_SUCCESS ) + { + ReportError(rc, "TrkSetStringFieldValue", + "Failed to set submitter!"); + return false; + } + rc = TrkSetStringFieldValue( trkRecHandle, + "Owner", + m_pBug->owner ); + if ( rc != TRK_SUCCESS ) + { + ReportError(rc, "TrkSetStringFieldValue", + "Failed to set owner!"); + return false; + } + rc = TrkSetStringFieldValue( trkRecHandle, + "Severity", + m_pBug->severity ); + if ( rc != TRK_SUCCESS ) + { + ReportError(rc, "TrkSetStringFieldValue", + "Failed to set severity!"); + //return false; + } + rc = TrkSetStringFieldValue( trkRecHandle, + "Report Type", + m_pBug->reporttype ); + if ( rc != TRK_SUCCESS ) + { + ReportError(rc, "TrkSetStringFieldValue", + "Failed to set report type!"); + //return false; + } + rc = TrkSetStringFieldValue( trkRecHandle, + "Priority", + m_pBug->priority ); + if ( rc != TRK_SUCCESS ) + { + ReportError(rc, "TrkSetStringFieldValue", + "Failed to set priority!"); + //return false; + } + rc = TrkSetStringFieldValue( trkRecHandle, + "Area", + m_pBug->area ); + if ( rc != TRK_SUCCESS ) + { + ReportError(rc, "TrkSetStringFieldValue", + "Failed to set area!"); + //return false; + } + rc = TrkSetStringFieldValue( trkRecHandle, + "Map Number", + m_pBug->mapnumber ); + if ( rc != TRK_SUCCESS ) + { + ReportError(rc, "TrkSetStringFieldValue", + "Failed to set map area!"); + //return false; + } + + + CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); + + buf.Printf( "%s\n\n", m_pBug->desc ); + + buf.Printf( "level: %s\nbuild: %s\nposition: setpos %s; setang %s\n", + m_pBug->level, + m_pBug->build, + m_pBug->position, + m_pBug->orientation ); + + if ( m_pBug->screenshot_unc[ 0 ] ) + { + buf.Printf( "screenshot: %s\n", m_pBug->screenshot_unc ); + } + if ( m_pBug->savegame_unc[ 0 ] ) + { + buf.Printf( "savegame: %s\n", m_pBug->savegame_unc ); + } + if ( m_pBug->bsp_unc[ 0 ] ) + { + buf.Printf( "bsp: %s\n", m_pBug->bsp_unc ); + } + if ( m_pBug->vmf_unc[ 0 ] ) + { + buf.Printf( "vmf: %s\n", m_pBug->vmf_unc ); + } + if ( m_pBug->includedfiles.Count() > 0 ) + { + int c = m_pBug->includedfiles.Count(); + for ( int i = 0 ; i < c; ++i ) + { + buf.Printf( "include: %s\n", m_pBug->includedfiles[ i ].name ); + } + } + if ( m_pBug->driverinfo[ 0 ] ) + { + buf.Printf( "%s\n", m_pBug->driverinfo ); + } + if ( m_pBug->misc[ 0 ] ) + { + buf.Printf( "%s\n", m_pBug->misc ); + } + + buf.PutChar( 0 ); + + rc = TrkSetDescriptionData( trkRecHandle, + buf.TellPut(), + (const char * )buf.Base(), + 0 ); + if ( rc != TRK_SUCCESS ) + { + ReportError(rc, "TrkSetDescriptionData", + "Failed to set description data!"); + return false; + } + + TRK_TRANSACTION_ID id; + rc = TrkNewRecordCommit( trkRecHandle, &id ); + if ( rc != TRK_SUCCESS ) + { + ReportError(rc, "TrkNewRecordCommit", + "Failed to TrkNewRecordCommit!"); + return false; + } + + TRK_UINT bugId; + rc = TrkGetNumericFieldValue( trkRecHandle, "Id", &bugId ); + if ( rc != TRK_SUCCESS ) + { + ReportError(rc, "TrkGetNumericFieldValue", + "Failed to TrkGetNumericFieldValue for bug Id #!"); + } + else + { + bugSubmissionId = (int)bugId; + } + + rc = TrkGetSingleRecord( trkRecHandle, bugId, SCR_TYPE ); + if ( rc != TRK_SUCCESS ) + { + ReportError( rc, "TrkGetSingleRecord", + "Failed to open bug id for update" ); + return false; + } + + rc = TrkUpdateRecordBegin( trkRecHandle ); + if ( rc != TRK_SUCCESS ) + { + ReportError( rc, "TrkUpdateRecordBegin", + "Failed to open bug id for update" ); + return false; + } + else + { + int textbuflen = 2 * buf.TellPut() + 1; + + char *textbuf = new char [ textbuflen ]; + Q_memset( textbuf, 0, textbuflen ); + + SubstituteBugId( (int)bugId, textbuf, textbuflen, buf ); + + // Update the description with the substituted text!!! + rc = TrkSetDescriptionData( trkRecHandle, + Q_strlen( textbuf ) + 1, + (const char * )textbuf, + 0 ); + + delete[] textbuf; + + if ( rc != TRK_SUCCESS ) + { + ReportError(rc, "TrkSetDescriptionData(update)", + "Failed to set description data!"); + return false; + } + + rc = TrkUpdateRecordCommit( trkRecHandle, &id ); + if ( rc != TRK_SUCCESS ) + { + ReportError(rc, "TrkUpdateRecordCommit", + "Failed to TrkUpdateRecordCommit for bug Id #!"); + return false; + } + } + + m_pBug->Clear(); + + return true; +} + +void CBugReporter::SetTitle( char const *title ) +{ + Assert( m_pBug ); + Q_strncpy( m_pBug->title, title, sizeof( m_pBug->title ) ); +} + +void CBugReporter::SetDescription( char const *description ) +{ + Assert( m_pBug ); + Q_strncpy( m_pBug->desc, description, sizeof( m_pBug->desc ) ); +} + +void CBugReporter::SetSubmitter( char const *username /*= 0*/ ) +{ + if ( !username ) + { + username = GetUserName(); + } + + Assert( m_pBug ); + Q_strncpy( m_pBug->submitter, username, sizeof( m_pBug->submitter ) ); +} + +void CBugReporter::SetOwner( char const *username ) +{ + Assert( m_pBug ); + Q_strncpy( m_pBug->owner, username, sizeof( m_pBug->owner ) ); +} + +void CBugReporter::SetSeverity( char const *severity ) +{ + Assert( m_pBug ); + Q_strncpy( m_pBug->severity, severity, sizeof( m_pBug->severity ) ); +} + +void CBugReporter::SetPriority( char const *priority ) +{ + Assert( m_pBug ); + Q_strncpy( m_pBug->priority, priority, sizeof( m_pBug->priority ) ); +} + +void CBugReporter::SetArea( char const *area ) +{ + Assert( m_pBug ); + Q_strncpy( m_pBug->area, area, sizeof( m_pBug->area ) ); +} + +void CBugReporter::SetMapNumber( char const *mapnumber ) +{ + Assert( m_pBug); + Q_strncpy( m_pBug->mapnumber, mapnumber, sizeof( m_pBug->mapnumber ) ); +} + +void CBugReporter::SetReportType( char const *reporttype ) +{ + Assert( m_pBug ); + Q_strncpy( m_pBug->reporttype, reporttype, sizeof( m_pBug->reporttype ) ); +} + +void CBugReporter::SetLevel( char const *levelnamne ) +{ + Assert( m_pBug ); + Q_strncpy( m_pBug->level, levelnamne, sizeof( m_pBug->level ) ); +} + +void CBugReporter::SetDriverInfo( char const *info ) +{ + Assert( m_pBug ); + Q_strncpy( m_pBug->driverinfo, info, sizeof( m_pBug->driverinfo ) ); +} + +void CBugReporter::SetMiscInfo( char const *info ) +{ + Assert( m_pBug ); + Q_strncpy( m_pBug->misc, info, sizeof( m_pBug->misc ) ); +} + +void CBugReporter::SetPosition( char const *position ) +{ + Assert( m_pBug ); + Q_strncpy( m_pBug->position, position, sizeof( m_pBug->position ) ); +} + +void CBugReporter::SetOrientation( char const *pitch_yaw_roll ) +{ + Assert( m_pBug ); + Q_strncpy( m_pBug->orientation, pitch_yaw_roll, sizeof( m_pBug->orientation ) ); +} + +void CBugReporter::SetBuildNumber( char const *build_num ) +{ + Assert( m_pBug ); + Q_strncpy( m_pBug->build, build_num, sizeof( m_pBug->build ) ); +} + +void CBugReporter::SetScreenShot( char const *screenshot_unc_address ) +{ + Assert( m_pBug ); + Q_strncpy( m_pBug->screenshot_unc, screenshot_unc_address, sizeof( m_pBug->screenshot_unc ) ); +} + +void CBugReporter::SetSaveGame( char const *savegame_unc_address ) +{ + Assert( m_pBug ); + Q_strncpy( m_pBug->savegame_unc, savegame_unc_address, sizeof( m_pBug->savegame_unc ) ); +} + +void CBugReporter::SetBSPName( char const *bsp_unc_address ) +{ + Assert( m_pBug ); + Q_strncpy( m_pBug->bsp_unc, bsp_unc_address, sizeof( m_pBug->bsp_unc ) ); +} + +void CBugReporter::SetVMFName( char const *vmf_unc_address ) +{ + Assert( m_pBug ); + Q_strncpy( m_pBug->vmf_unc, vmf_unc_address, sizeof( m_pBug->vmf_unc ) ); +} + +void CBugReporter::AddIncludedFile( char const *filename ) +{ + CBug::incfile includedfile; + Q_strncpy( includedfile.name, filename, sizeof( includedfile.name ) ); + m_pBug->includedfiles.AddToTail( includedfile ); +} + +void CBugReporter::ResetIncludedFiles() +{ + m_pBug->includedfiles.Purge(); +} + +bool CBugReporter::PopulateChoiceList( char const *listname, CUtlVector< CUtlSymbol >& list ) +{ + TRK_UINT rc; + + rc = TrkInitChoiceList( trkHandle, listname, SCR_TYPE ); + if ( TRK_SUCCESS != rc ) + { + ReportError( rc, "TrkInitChoiceList", listname ); + return false; + } + else + { + char sz[ 256 ]; + + while ( TrkGetNextChoice( trkHandle, sizeof( sz ), sz ) != TRK_E_END_OF_LIST ) + { + CUtlSymbol sym = m_BugStrings.AddString( sz ); + list.AddToTail( sym ); + } + } + + return true; +} + +// owner, not required <<Unassigned>> +// area <<None>> + +bool CBugReporter::PopulateLists() +{ + CUtlSymbol unassigned = m_BugStrings.AddString( "<<Unassigned>>" ); + CUtlSymbol none = m_BugStrings.AddString( "<<None>>" ); + + m_Area.AddToTail( none ); + m_MapNumber.AddToTail( none ); + m_Names.AddToTail( unassigned ); + m_InternalNameMapping.Insert( "<<Unassigned>>", unassigned ); + m_SortedDisplayNames.AddToTail( unassigned ); + + PopulateChoiceList( "Severity", m_Severity ); + PopulateChoiceList( "Report Type", m_ReportType ); + PopulateChoiceList( "Area", m_Area ); + PopulateChoiceList( "Area@Dir%Map", m_AreaMap ); + PopulateChoiceList( "Map Number", m_MapNumber ); + PopulateChoiceList( "Priority", m_Priority ); + + // Need to gather names, too + TRK_UINT rc; + + rc = TrkInitUserList( trkHandle ); + if ( TRK_SUCCESS != rc ) + { + ReportError( rc, "TrkInitUserList", "Couldn't get userlist" ); + return false; + } + else + { + char sz[ 256 ]; + + while ( TrkGetNextUser( trkHandle, sizeof( sz ), sz ) != TRK_E_END_OF_LIST ) + { + // Now lookup display name for user + char displayname[ 256 ]; + + rc = TrkGetUserFullName( trkHandle, sz, sizeof( displayname ), displayname ); + if ( TRK_SUCCESS == rc ) + { + // Fill in lookup table + CUtlSymbol internal_name_sym = m_BugStrings.AddString( sz ); + CUtlSymbol display_name_sym = m_BugStrings.AddString( displayname ); + + m_Names.AddToTail( internal_name_sym ); + + m_InternalNameMapping.Insert( displayname, internal_name_sym ); + + m_SortedDisplayNames.AddToTail( display_name_sym ); + } + } + + // Now sort display names + int c = m_SortedDisplayNames.Count(); + for ( int i = 1 ; i < c; i++ ) + { + for ( int j = i + 1; j < c; j++ ) + { + char const *p1 = m_BugStrings.String( m_SortedDisplayNames[ i ] ); + char const *p2 = m_BugStrings.String( m_SortedDisplayNames[ j ] ); + + int cmp = Q_stricmp( p1, p2 ); + if ( cmp > 0 ) + { + CUtlSymbol t = m_SortedDisplayNames[ i ]; + m_SortedDisplayNames[ i ] = m_SortedDisplayNames[ j ]; + m_SortedDisplayNames[ j ] = t; + } + } + } + } + + return true; +} + +EXPOSE_SINGLE_INTERFACE( CBugReporter, IBugReporter, INTERFACEVERSION_BUGREPORTER );
\ No newline at end of file |