|
|
//========= 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; }
|