diff options
Diffstat (limited to 'utils/getbugs/getbugs.cpp')
| -rw-r--r-- | utils/getbugs/getbugs.cpp | 1005 |
1 files changed, 1005 insertions, 0 deletions
diff --git a/utils/getbugs/getbugs.cpp b/utils/getbugs/getbugs.cpp new file mode 100644 index 0000000..2ce5b5d --- /dev/null +++ b/utils/getbugs/getbugs.cpp @@ -0,0 +1,1005 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#include <stdio.h> +#include <windows.h> +#include "tier0/dbg.h" +#include "utldict.h" +#include "filesystem.h" +#include "KeyValues.h" +#include "cmdlib.h" +#include "interface.h" +#include "imysqlwrapper.h" +#include "../bugreporter/trktool.h" +#include "utlbuffer.h" +#include <sys/types.h> +#include <sys/stat.h> +#include <direct.h> + +bool uselogfile = false; + +static bool spewed = false; + +static char workingdir[ 256 ]; + +#define SCR_TYPE 1 + +#define DEFAULT_DBMS "tracker" +#define DEFAULT_USERNAME "PublicUser" +#define DEFAULT_PASSWORD DEFAULT_USERNAME + +#define BUG_REPOSITORY_FMT "\\\\fileserver\\bugs\\public\\%s\\%s\\%s.zip" + +struct BugField_t +{ + BugField_t() + { + value[ 0 ] = 0; + numvalue = 0; + trkfield[ 0 ] = 0; + isdesc = false; + isnumeric = false; + } + + char value[ 8192 ]; + int numvalue; + char trkfield[ 256 ]; + bool isdesc; + bool isnumeric; +}; + +#define SQL_SETVALUE( fieldname, sqlcolumn ) Q_strncpy( bug.m_pBug->fieldname, sqlcolumn.String(), sizeof( bug.m_pBug->fieldname ) ); +#define SQL_SETVALUESTRING( fieldname, str ) Q_strncpy( bug.m_pBug->fieldname, str, sizeof( bug.m_pBug->fieldname ) ); + + +class CBugReporter +{ +public: + + CBugReporter(); + virtual ~CBugReporter(); + + // Initialize and login with default username/password for this computer (from resource/bugreporter.res) + virtual bool Init( char const *projectname ); + virtual void Shutdown(); + + virtual bool IsPublicUI() { return false; } + +// Submission API + virtual void StartNewBugReport(); + virtual void CancelNewBugReport(); + virtual bool CommitBugReport( int& bugSubmissionId ); + + virtual void AddField( char const *fieldname, char const *value, bool isdesc = false ); + virtual void AddNumericField( char const *fieldname, int value ); + +private: + + void ReportError(TRK_UINT rc, char const *func, char const *msg ); + TRK_UINT Login(TRK_HANDLE* pTrkHandle, char const *projectname ); + + void SubstituteBugId( int bugid, char *out, int outlen, CUtlBuffer& src ); + + TRK_HANDLE trkHandle; + TRK_RECORD_HANDLE trkRecHandle; + +public: + CUtlVector< BugField_t > m_Fields; +}; + +void CBugReporter::AddField( char const *fieldname, char const *value, bool isdesc /*=false*/ ) +{ + BugField_t fld; + Q_strncpy( fld.value, value, sizeof( fld.value ) ); + fld.isnumeric = false; + Q_strncpy( fld.trkfield, fieldname, sizeof( fld.trkfield ) ); + fld.isdesc = isdesc; + + m_Fields.AddToTail( fld ); +} + +void CBugReporter::AddNumericField( char const *fieldname, int value ) +{ + BugField_t fld; + fld.numvalue = value; + fld.isnumeric = true; + Q_strncpy( fld.trkfield, fieldname, sizeof( fld.trkfield ) ); + fld.isdesc = false; + + m_Fields.AddToTail( fld ); +} + +CBugReporter::CBugReporter() +{ + trkHandle = (TRK_HANDLE)0; + trkRecHandle = (TRK_RECORD_HANDLE)0; +} + +CBugReporter::~CBugReporter() +{ + m_Fields.RemoveAll(); +} + +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 (%s)!\n", func, rc, g_Lookup[ i ].str, msg ); + break; + } + } + + if ( i >= ARRAYSIZE( g_Lookup ) ) + { + Msg( "%s returned %i - %s! (%s)\n", func, rc, "???", msg ); + } + break; + } + } +} + +TRK_UINT CBugReporter::Login(TRK_HANDLE* pTrkHandle, char const *projectname ) +{ + char dbms[50] = DEFAULT_DBMS; + + char username[ 50 ]; + char password[ 50 ]; + + Q_strncpy( username, DEFAULT_USERNAME, sizeof( username ) ); + Q_strncpy( password, DEFAULT_PASSWORD, sizeof( password ) ); + + TRK_UINT rc = TrkProjectLogin(*pTrkHandle, + username, + password, + projectname, + NULL, + NULL, + NULL, + NULL, + TRK_USE_INI_FILE_DBMS_LOGIN); + + if (rc != TRK_SUCCESS) + { + rc = TrkProjectLogin(*pTrkHandle, + username, + "", + projectname, + NULL, + NULL, + NULL, + NULL, + TRK_USE_INI_FILE_DBMS_LOGIN); + if (rc != TRK_SUCCESS) + { + Msg("Bug reporter init failed: Your tracker password must be your user name or blank.\n"); + return rc; + } + } + + TrkGetLoginDBMSName(*pTrkHandle, sizeof(dbms), dbms ); + + char projout[ 256 ]; + + TrkGetLoginProjectName(*pTrkHandle, sizeof( projout ), projout ); + + Msg( "Project: %s\n", projout ); + 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( char const *projectname ) +{ + 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, projectname ); + 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; + } + + 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!"); + } + } + } +} + +void CBugReporter::StartNewBugReport() +{ + m_Fields.RemoveAll(); +} + +void CBugReporter::CancelNewBugReport() +{ + m_Fields.RemoveAll(); +} + +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; + + int fieldCount = m_Fields.Count(); + if ( fieldCount == 0 ) + return false; + + TRK_UINT rc = 0; + rc = TrkNewRecordBegin( trkRecHandle, SCR_TYPE ); + if ( rc != TRK_SUCCESS ) + { + ReportError(rc, "TrkNewRecordBegin", + "Failed to TrkNewRecordBegin!"); + return false; + } + + CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); + + for ( int i = 0; i < fieldCount; ++i ) + { + BugField_t& fld = m_Fields[ i ]; + + if ( !fld.isdesc ) + { + // Populate fields + if ( !fld.isnumeric ) + { + rc = TrkSetStringFieldValue( + trkRecHandle, + fld.trkfield, + fld.value ); + } + else + { + rc = TrkSetNumericFieldValue( + trkRecHandle, + fld.trkfield, + fld.numvalue ); + } + if ( rc != TRK_SUCCESS ) + { + char es[ 256 ]; + Q_snprintf( es, sizeof( es ), "Failed to add '%s'", fld.trkfield ); + + ReportError( rc, "TrkSetStringFieldValue", es ); + return false; + } + } + else + { + buf.Printf( "%s\n", fld.value ); + + 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_Fields.RemoveAll(); + + return true; +} + +SpewRetval_t SpewFunc( SpewType_t type, char const *pMsg ) +{ + spewed = true; + + printf( "%s", pMsg ); + OutputDebugString( pMsg ); + + if ( type == SPEW_ERROR ) + { + printf( "\n" ); + OutputDebugString( "\n" ); + } + + return SPEW_CONTINUE; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : depth - +// *fmt - +// ... - +//----------------------------------------------------------------------------- +void vprint( int depth, const char *fmt, ... ) +{ + char string[ 8192 ]; + va_list va; + va_start( va, fmt ); + vsprintf( string, fmt, va ); + va_end( va ); + + FILE *fp = NULL; + + if ( uselogfile ) + { + fp = fopen( "log.txt", "ab" ); + } + + while ( depth-- > 0 ) + { + printf( " " ); + OutputDebugString( " " ); + if ( fp ) + { + fprintf( fp, " " ); + } + } + + ::printf( "%s", string ); + OutputDebugString( string ); + + if ( fp ) + { + char *p = string; + while ( *p ) + { + if ( *p == '\n' ) + { + fputc( '\r', fp ); + } + fputc( *p, fp ); + p++; + } + fclose( fp ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void printusage( void ) +{ + vprint( 0, "usage: getbugs pvcsproject hostname database username password contentadminexe <startbug endbug>\n\ + \ne.g.: getbugs \"Steam Beta\" steamweb cserr username password \"u:/p4clients/yahn_steam_work/projects/gazelleproto/tools/contentadmin/vc70_debug_static/contentadmin.exe\" 1 10\n" ); + + // Exit app + exit( 1 ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CheckLogFile( void ) +{ + if ( uselogfile ) + { + _unlink( "log.txt" ); + vprint( 0, " Outputting to log.txt\n" ); + } +} + +void PrintHeader() +{ + vprint( 0, "Valve Software - getbugs.exe (%s)\n", __DATE__ ); + vprint( 0, "--- Pulls public bugreporter bugs into PVCS tracker ---\n" ); +} + +bool GetBugZip( int bugnum, char const *admin ) +{ + bool retval = false; + + char commandline[ 512 ]; + char directory[ 512 ]; + + Q_strncpy( directory, admin, sizeof( directory ) ); + Q_StripFilename( directory ); + + + // sprintf( commandline, "msdev engdll.dsw /MAKE \"quiver - Win32 GL Debug\" /OUT log.txt" ); + + // Builds the default configuration + sprintf( commandline, "\"%s\" bugreport %i", admin, bugnum ); + + PROCESS_INFORMATION pi; + memset( &pi, 0, sizeof( pi ) ); + + STARTUPINFO si; + memset( &si, 0, sizeof( si ) ); + si.cb = sizeof( si ); + + if ( !CreateProcess( NULL, commandline, NULL, NULL, TRUE, 0, NULL, directory, &si, &pi ) ) + { + LPVOID lpMsgBuf; + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + // Process any inserts in lpMsgBuf. + // ... + // Display the string. + MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION ); + // Free the buffer. + LocalFree( lpMsgBuf ); + return retval; + } + + // Wait until child process exits. + WaitForSingleObject( pi.hProcess, INFINITE ); + + DWORD exitCode = (DWORD)-1; + if ( GetExitCodeProcess( pi.hProcess, &exitCode ) ) + { + if ( exitCode == 0 ) + { + retval = true; + } + } + + // Close process and thread handles. + CloseHandle( pi.hProcess ); + CloseHandle( pi.hThread ); + + return retval; +} + +void CreateDirHierarchy(const char *path) +{ + char temppath[512]; + Q_strncpy( temppath, path, sizeof(temppath) ); + + for (char *ofs = temppath+1 ; *ofs ; ofs++) + { + if (*ofs == '/' || *ofs == '\\') + { // create the directory + char old = *ofs; + *ofs = 0; + _mkdir (temppath); + *ofs = old; + } + } +} + + +void GetBugInfo( CBugReporter& bug, char const *host, char const *database, char const *username, char const *password, char const *admin, int startbug, int endbug ) +{ + // Now connect to steamweb and update the engineaccess table + CSysModule *sql = Sys_LoadModule( "mysql_wrapper" ); + if ( sql ) + { + CreateInterfaceFn factory = Sys_GetFactory( sql ); + if ( factory ) + { + IMySQL *mysql = ( IMySQL * )factory( MYSQL_WRAPPER_VERSION_NAME, NULL ); + if ( mysql ) + { + if ( mysql->InitMySQL( database, host, username, password ) ) + { + char q[ 512 ]; + + /* + Q_snprintf( q, sizeof( q ), "insert into engineaccess (BuildIdentifier,AllowAccess) values (\"%s\",1);", + argv[2] ); + + int retcode = mysql->Execute( q ); + if ( retcode != 0 ) + { + printf( "Query %s failed\n", q ); + } + else + { + printf( "Successfully added buildidentifier '%s' to %s:%s\n", + argv[ 2 ], argv[ 3 ], argv[ 4 ] ); + } + */ + + char where[ 256 ]; + where[ 0 ] = 0; + if ( startbug != -1 && endbug != -1 ) + { + Q_snprintf( where, sizeof( where ), "BugId>=%i and BugId<=%i and ", startbug, endbug ); + } + + Q_snprintf( q, sizeof( q ), "select BugId, Time, BuildNumber, ExeName, GameDirectory, MapName, Title, Description, IP," + "BaseIP, RAM, CPU, ProcessorVendor, DXVersionHighPart, DXVersionLowPart, DXVendorID, DXDeviceID, OSVersion, " + "BugReportFilePath, ReportType, EMail, AccountName, SteamID, Processed, Important from bugreports where %s ( Processed is NULL or Processed = 0 );", where ); + + + int retcode = mysql->Execute( q ); + if ( retcode != 0 ) + { + vprint( 0, "Query %s failed\n", q ); + } + else + { + IMySQLRowSet *rows = mysql->DuplicateRowSet(); + + CUtlVector< int > processed; + + if ( rows && rows->NumFields() > 0 ) + { + while ( rows->NextRow() ) + { + CColumnValue BugId = rows->GetColumnValue( "BugId" ); + CColumnValue Time = rows->GetColumnValue( "Time" ); + CColumnValue BuildNumber = rows->GetColumnValue( "BuildNumber" ); + CColumnValue ExeName = rows->GetColumnValue( "ExeName" ); + CColumnValue GameDirectory = rows->GetColumnValue( "GameDirectory" ); + CColumnValue MapName = rows->GetColumnValue( "MapName" ); + CColumnValue Title = rows->GetColumnValue( "Title" ); + CColumnValue Description = rows->GetColumnValue( "Description" ); + CColumnValue IP = rows->GetColumnValue( "IP" ); + CColumnValue BaseIP = rows->GetColumnValue( "BaseIP" ); + CColumnValue RAM = rows->GetColumnValue( "RAM" ); + CColumnValue CPU = rows->GetColumnValue( "CPU" ); + CColumnValue ProcessorVendor = rows->GetColumnValue( "ProcessorVendor" ); + CColumnValue DXVersionHighPart = rows->GetColumnValue( "DXVersionHighPart" ); + CColumnValue DXVersionLowPart = rows->GetColumnValue( "DXVersionLowPart" ); + CColumnValue DXVendorID = rows->GetColumnValue( "DXVendorID" ); + CColumnValue DXDeviceID = rows->GetColumnValue( "DXDeviceID" ); + CColumnValue OSVersion = rows->GetColumnValue( "OSVersion" ); + CColumnValue BugReportFilePath = rows->GetColumnValue( "BugReportFilePath" ); + CColumnValue ReportType = rows->GetColumnValue( "ReportType" ); + CColumnValue EMail = rows->GetColumnValue( "EMail" ); + CColumnValue Accountname = rows->GetColumnValue( "Accountname" ); + CColumnValue SteamID = rows->GetColumnValue( "SteamID" ); + CColumnValue Processed = rows->GetColumnValue( "Processed" ); + CColumnValue Important = rows->GetColumnValue( "Important" ); + + bug.StartNewBugReport(); + + vprint( 1, "Processing bug %i\n", BugId.Int32() ); + + bug.AddField( "Owner", "PublicUser" ); + bug.AddField( "Submitter", "PublicUser" ); + bug.AddField( "Title", Title.String() ); + + + bug.AddNumericField( "BugId", BugId.Int32() ); + bug.AddNumericField( "Build", BuildNumber.Int32() ); + bug.AddField( "Exe", ExeName.String() ); + bug.AddField( "Gamedir", GameDirectory.String() ); + bug.AddField( "Map", MapName.String() ); + bug.AddField( "Operating System", OSVersion.String() ); + bug.AddField( "Processor", ProcessorVendor.String() ); + bug.AddNumericField( "Memory", RAM.Int32() ); + bug.AddField( "SteamID", SteamID.String() ); + bug.AddNumericField( "CPU", CPU.Int32() ); + + bug.AddField( "Time", Time.String() ); + + char dxversion[ 512 ]; + int vhigh = DXVersionHighPart.Int32(); + int vlow = DXVersionLowPart.Int32(); + + Q_snprintf( dxversion, sizeof( dxversion ), "%u.%u.%u.%u", ( vhigh >> 16 ) , vhigh & 0xffff, ( vlow >> 16 ), vlow & 0xffff ); + + bug.AddField( "DXVersion", dxversion); + + bug.AddNumericField( "DXDevice", DXDeviceID.Int32() ); + bug.AddNumericField( "DXVendor", DXVendorID.Int32() ); + + bug.AddField( "BugType", ReportType.String() ); + bug.AddField( "E-Mail Address", EMail.String() ); + bug.AddField( "Account Name", Accountname.String() ); + + char zipurl[ 512 ]; + zipurl[ 0 ] = 0; + + char basepath[ 512 ]; + Q_FileBase( BugReportFilePath.String(), basepath, sizeof( basepath ) ); + + char desc[ 8192 ]; + + if ( BugReportFilePath.String()[ 0 ] ) + { + Q_snprintf( zipurl, sizeof( zipurl ), BUG_REPOSITORY_FMT, database, "BugId", basepath ); + + Q_snprintf( desc, sizeof( desc ), "%s\n\nzip url: %s\n", Description.String(), zipurl ); + } + else + { + Q_strncpy( desc, Description.String(), sizeof( desc ) ); + } + + bug.AddField( "Description", desc, true ); + + int trackerBugId = -1; + + bool success = bug.CommitBugReport( trackerBugId ); + if ( success ) + { + // The public UI handles uploading on it's own... + // Fixup URL + if ( zipurl[ 0 ] ) + { + char zipurlfixed[ 512 ]; + char id[ 32 ]; + Q_snprintf( id, sizeof( id ), "%i", trackerBugId ); + + // The upload destination + Q_snprintf( zipurlfixed, sizeof( zipurlfixed ), BUG_REPOSITORY_FMT, database, id, basepath ); + Q_strlower( zipurlfixed ); + Q_FixSlashes( zipurlfixed ); + + char admindir[ 512 ]; + Q_strncpy( admindir, admin, sizeof( admindir ) ); + Q_StripFilename( admindir ); + Q_strlower( admindir ); + Q_FixSlashes( admindir ); + + + char zipurllocal[ 512 ]; + Q_snprintf( zipurllocal, sizeof( zipurllocal ), "%s\\%s.zip", admindir, basepath ); + Q_strlower( zipurllocal ); + Q_FixSlashes( zipurllocal ); + + // Get local copy of .zip file + + if ( GetBugZip( BugId.Int32(), admin ) ) + { + struct _stat statbuf; + + if ( _stat( zipurllocal, &statbuf ) == 0 ) + { + CreateDirHierarchy( zipurlfixed ); + + MoveFile( zipurllocal, zipurlfixed ); + + // Mark processed + processed.AddToTail( BugId.Int32() ); + } + } + else + { + Warning( "Unable to retrieve bug file for %i\n", BugId.Int32() ); + } + } + else + { + processed.AddToTail( BugId.Int32() ); + } + + } + else + { + Warning( "Unable to post bug report to database\n" ); + } + } + + // Discard memory + rows->Release(); + + int c = processed.Count(); + for ( int i = 0; i < c; ++i ) + { + Q_snprintf( q, sizeof( q ), "update bugreports set Processed=1 where BugId=%i;", processed[ i ] ); + + retcode = mysql->Execute( q ); + if ( retcode != 0 ) + { + Msg( "Query failed '%s'\n", q ); + } + } + } + } + } + else + { + vprint( 0, "InitMySQL failed\n" ); + } + + mysql->Release(); + } + else + { + vprint( 0, "Unable to connect via mysql_wrapper\n"); + } + } + else + { + vprint( 0, "Unable to get factory from mysql_wrapper.dll, not updating access mysql table!!!" ); + } + + Sys_UnloadModule( sql ); + } + else + { + vprint( 0, "Unable to load mysql_wrapper.dll, not updating access mysql table!!!" ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : argc - +// argv[] - +// Output : int +//----------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + SpewOutputFunc( SpewFunc ); + SpewActivate( "getbugs", 2 ); + + uselogfile = true; + verbose = true; + + if ( argc != 7 && argc != 9 ) + { + PrintHeader(); + printusage(); + } + + CheckLogFile(); + + PrintHeader(); + + vprint( 0, " Getting bugs...\n" ); + + workingdir[0] = 0; + Q_getwd( workingdir, sizeof( workingdir ) ); + + // If they didn't specify -game on the command line, use VPROJECT. + CmdLib_InitFileSystem( workingdir ); + + + CBugReporter bugreporter; + if ( !bugreporter.Init( argv[ 1 ] ) ) + { + vprint( 0, "Couldn't init bug reporter\n" ); + return 0; + } + + if ( argc == 9 ) + { + GetBugInfo( bugreporter, argv[2], argv[3], argv[4], argv[5], argv[ 6 ], atoi( argv[ 7 ] ), atoi( argv[ 8 ] ) ); + } + else + { + GetBugInfo( bugreporter, argv[2], argv[3], argv[4], argv[5], argv[ 6 ], -1, -1 ); + } + + + bugreporter.Shutdown(); + CmdLib_TermFileSystem(); + + return 0; +} |