openmohaa/code/gamespy/sake/sakeMain.c
2023-02-04 21:00:01 +01:00

428 lines
14 KiB
C

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#include "sakeMain.h"
#include "sakeRequest.h"
#include "../common/gsAvailable.h"
#include "../common/gsCore.h"
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// General
gsi_char gSakeUploadUrlOverride[SAKE_MAX_URL_LENGTH];
gsi_char gSakeDownloadUrlOverride[SAKE_MAX_URL_LENGTH];
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
SAKEStartupResult SAKE_CALL sakeStartup(SAKE * sakePtr)
{
SAKE sake;
GS_ASSERT(sakePtr);
// check for availability
if(__GSIACResult != GSIACAvailable)
return SAKEStartupResult_NOT_AVAILABLE;
// check that the core is initialized
if(gsCoreIsShutdown())
return SAKEStartupResult_CORE_SHUTDOWN;
// allocate the sake object
sake = (SAKE)gsimalloc(sizeof(SAKEInternal));
if(sake == NULL)
return SAKEStartupResult_OUT_OF_MEMORY;
// init the sake object
memset(sake, 0, sizeof(SAKEInternal));
// store the object in the user pointer
*sakePtr = sake;
return SAKEStartupResult_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void SAKE_CALL sakeShutdown(SAKE sake)
{
GS_ASSERT(sake);
//TODO: ensure that there are no pending operations
// that might reference this object
// free the struct
gsifree(sake);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Authentication
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void SAKE_CALL sakeSetGame(SAKE sake, const gsi_char * gameName, int gameId, const gsi_char *secretKey)
{
GS_ASSERT(sake);
GS_ASSERT(gameName && (_tcslen(gameName) <= SAKEI_GAME_NAME_LENGTH));
GS_ASSERT(gameId >= 0);
GS_ASSERT(secretKey && (_tcslen(secretKey) <= SAKEI_SECRET_KEY_LENGTH));
#ifdef GSI_UNICODE
// convert gamename and secretkey to ascii for executing requests
UCS2ToAsciiString(gameName, sake->mGameName);
UCS2ToAsciiString(secretKey, sake->mSecretKey);
#else
strcpy(sake->mGameName, gameName);
strcpy(sake->mSecretKey, secretKey);
#endif
sake->mGameId = gameId;
sake->mIsGameAuthenticated = gsi_true;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void SAKE_CALL sakeSetProfile(SAKE sake, int profileId, const char *loginTicket)
{
GS_ASSERT(sake);
GS_ASSERT(loginTicket);
GS_ASSERT(strlen(loginTicket) == SAKEI_LOGIN_TICKET_LENGTH);
sake->mProfileId = profileId;
memcpy(sake->mLoginTicket, loginTicket, SAKEI_LOGIN_TICKET_LENGTH + 1);
sake->mIsProfileAuthenticated = gsi_true;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Requests
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
SAKEStartRequestResult SAKE_CALL sakeGetStartRequestResult(SAKE sake)
{
GS_ASSERT(sake);
return sake->mStartRequestResult;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
static SAKERequest SAKE_CALL sakeiRunRequest(SAKE sake, void *input,
SAKERequestCallback callback, void *userData,
SAKEIRequestType type,
SAKEStartRequestResult (*startRequestFunc)(SAKERequest request))
{
SAKERequest request;
GS_ASSERT(sake);
request = sakeiInitRequest(sake, type, input, callback, userData);
if(!request)
return NULL;
sake->mStartRequestResult = startRequestFunc(request);
if(sake->mStartRequestResult != SAKEStartRequestResult_SUCCESS)
{
sakeiFreeRequest(request);
return NULL;
}
return request;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
SAKERequest SAKE_CALL sakeCreateRecord(SAKE sake, SAKECreateRecordInput *input, SAKERequestCallback callback, void *userData)
{
return sakeiRunRequest(sake, input, callback, userData, SAKEIRequestType_CREATE_RECORD, sakeiStartCreateRecordRequest);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
SAKERequest SAKE_CALL sakeUpdateRecord(SAKE sake, SAKEUpdateRecordInput *input, SAKERequestCallback callback, void *userData)
{
return sakeiRunRequest(sake, input, callback, userData, SAKEIRequestType_UPDATE_RECORD, sakeiStartUpdateRecordRequest);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
SAKERequest SAKE_CALL sakeDeleteRecord(SAKE sake, SAKEDeleteRecordInput *input, SAKERequestCallback callback, void *userData)
{
return sakeiRunRequest(sake, input, callback, userData, SAKEIRequestType_DELETE_RECORD, sakeiStartDeleteRecordRequest);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
SAKERequest SAKE_CALL sakeSearchForRecords(SAKE sake, SAKESearchForRecordsInput *input, SAKERequestCallback callback, void *userData)
{
return sakeiRunRequest(sake, input, callback, userData, SAKEIRequestType_SEARCH_FOR_RECORDS, sakeiStartSearchForRecordsRequest);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
SAKERequest SAKE_CALL sakeGetMyRecords(SAKE sake, SAKEGetMyRecordsInput *input, SAKERequestCallback callback, void *userData)
{
return sakeiRunRequest(sake, input, callback, userData, SAKEIRequestType_GET_MY_RECORDS, sakeiStartGetMyRecordsRequest);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
SAKERequest SAKE_CALL sakeGetSpecificRecords(SAKE sake, SAKEGetSpecificRecordsInput *input, SAKERequestCallback callback, void *userData)
{
return sakeiRunRequest(sake, input, callback, userData, SAKEIRequestType_GET_SPECIFIC_RECORDS, sakeiStartGetSpecificRecordsRequest);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
SAKERequest SAKE_CALL sakeGetRandomRecord(SAKE sake, SAKEGetRandomRecordInput *input, SAKERequestCallback callback, void *userData)
{
return sakeiRunRequest(sake, input, callback, userData, SAKEIRequestType_GET_RANDOM_RECORD, sakeiStartGetRandomRecordRequest);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
SAKERequest SAKE_CALL sakeRateRecord(SAKE sake, SAKERateRecordInput *input, SAKERequestCallback callback, void *userData)
{
return sakeiRunRequest(sake, input, callback, userData, SAKEIRequestType_RATE_RECORD, sakeiStartRateRecordRequest);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
SAKERequest SAKE_CALL sakeGetRecordLimit(SAKE sake, SAKEGetRecordLimitInput *input, SAKERequestCallback callback, void *userData)
{
return sakeiRunRequest(sake, input, callback, userData, SAKEIRequestType_GET_RECORD_LIMIT, sakeiStartGetRecordLimitRequest);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
SAKERequest SAKE_CALL sakeGetRecordCount(SAKE sake, SAKEGetRecordCountInput *input, SAKERequestCallback callback, void *userData)
{
return sakeiRunRequest(sake, input, callback, userData, SAKEIRequestType_GET_RECORD_COUNT, sakeiStartGetRecordCountRequest);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// read request utility
SAKEField * SAKE_CALL sakeGetFieldByName(const char *name, SAKEField *fields, int numFields)
{
int i;
GS_ASSERT(name);
GS_ASSERT(fields);
GS_ASSERT(numFields >= 0);
for(i = 0 ; i < numFields ; i++)
{
if(strcmp(fields[i].mName, name) == 0)
return &fields[i];
}
return NULL;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Files
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Set the URL format to be used by sakeGetFileDownloadUrl
gsi_bool SAKE_CALL sakeSetFileDownloadURL(SAKE sake, gsi_char url[SAKE_MAX_URL_LENGTH])
{
GS_ASSERT(sake);
GS_ASSERT(url);
if(!sake || !url)
return gsi_false;
_tcscpy(gSakeDownloadUrlOverride, url);
return gsi_true;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
gsi_bool SAKE_CALL sakeGetFileDownloadURL(SAKE sake, int fileId, gsi_char url[SAKE_MAX_URL_LENGTH])
{
int rcode;
GS_ASSERT(sake);
GS_ASSERT(fileId != 0);
GS_ASSERT(url);
GS_ASSERT(sake->mIsGameAuthenticated);
GS_ASSERT(sake->mIsProfileAuthenticated);
if(!sake || !url || !sake->mIsGameAuthenticated || !sake->mIsProfileAuthenticated)
return gsi_false;
if (gSakeDownloadUrlOverride[0] != '\0')
{
rcode = _tsnprintf(url, SAKE_MAX_URL_LENGTH, _T("%s?gameid=%d&pid=%d"),
gSakeDownloadUrlOverride, sake->mGameId, sake->mProfileId);
}
else
{
#ifdef GSI_UNICODE
{
// use capital %S to convert the gamename to a wide string
rcode = _tsnprintf(url, SAKE_MAX_URL_LENGTH, _T("http://%S.sake.%S/SakeFileServer/download.aspx?fileid=%d&gameid=%d&pid=%d"),
sake->mGameName, GSI_DOMAIN_NAME, fileId, sake->mGameId, sake->mProfileId);
}
#else
{
rcode = _tsnprintf(url, SAKE_MAX_URL_LENGTH, _T("http://%s.sake.%s/SakeFileServer/download.aspx?fileid=%d&gameid=%d&pid=%d"),
sake->mGameName, GSI_DOMAIN_NAME, fileId, sake->mGameId, sake->mProfileId);
}
#endif
}
if(rcode < 0)
return gsi_false;
return gsi_true;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
gsi_bool SAKE_CALL sakeSetFileUploadURL(SAKE sake, gsi_char url[SAKE_MAX_URL_LENGTH])
{
GS_ASSERT(sake);
GS_ASSERT(url);
if(!sake || !url)
return gsi_false;
_tcscpy(gSakeUploadUrlOverride, url);
return gsi_true;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
gsi_bool SAKE_CALL sakeGetFileUploadURL(SAKE sake, gsi_char url[SAKE_MAX_URL_LENGTH])
{
int rcode;
GS_ASSERT(sake);
GS_ASSERT(url);
GS_ASSERT(sake->mIsGameAuthenticated);
GS_ASSERT(sake->mIsProfileAuthenticated);
if(!sake || !url || !sake->mIsGameAuthenticated || !sake->mIsProfileAuthenticated)
return gsi_false;
if (gSakeUploadUrlOverride[0] != '\0')
{
rcode = _tsnprintf(url, SAKE_MAX_URL_LENGTH, _T("%s?gameid=%d&pid=%d"),
gSakeUploadUrlOverride, sake->mGameId, sake->mProfileId);
}
else
{
#ifdef GSI_UNICODE
{
// use capital %S to convert the gamename to a wide string
rcode = _tsnprintf(url, SAKE_MAX_URL_LENGTH, _T("http://%S.sake.%S/SakeFileServer/upload.aspx?gameid=%d&pid=%d"),
sake->mGameName, GSI_DOMAIN_NAME, sake->mGameId, sake->mProfileId);
}
#else
{
rcode = _tsnprintf(url, SAKE_MAX_URL_LENGTH, _T("http://%s.sake.%s/SakeFileServer/upload.aspx?gameid=%d&pid=%d"),
sake->mGameName, GSI_DOMAIN_NAME, sake->mGameId, sake->mProfileId);
}
#endif
}
if(rcode < 0)
return gsi_false;
return gsi_true;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
static SAKEFileResult SAKE_CALL sakeiParseFileResult(int resultCode)
{
if(resultCode >= SAKEFileResult_UNKNOWN_ERROR)
return SAKEFileResult_UNKNOWN_ERROR;
return (SAKEFileResult)resultCode;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
static gsi_bool SAKE_CALL sakeiGetHeaderValueInt(const char *headers, const char *headerName, int *value)
{
const char * header;
int rcode;
GS_ASSERT(headers);
GS_ASSERT(headerName);
GS_ASSERT(value);
#ifdef _DEBUG
// headerName must include the trailing colon
GS_ASSERT(headerName[strlen(headerName) - 1] == ':');
#endif
// find this header in the list of headers
header = strstr(headers, headerName);
if(header)
{
// skip the header name
header += strlen(headerName);
// scan in the result
rcode = sscanf(header, " %d", value);
if(rcode == 1)
return gsi_true;
}
return gsi_false;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
gsi_bool SAKE_CALL sakeGetFileResultFromHeaders(const char *headers, SAKEFileResult *result)
{
int resultCode;
gsi_bool foundResultCode;
foundResultCode = sakeiGetHeaderValueInt(headers, SAKE_FILE_RESULT_HEADER, &resultCode);
if(gsi_is_false(foundResultCode))
return gsi_false;
*result = sakeiParseFileResult(resultCode);
return gsi_true;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
gsi_bool SAKE_CALL sakeGetFileIdFromHeaders(const char *headers, int *fileId)
{
return sakeiGetHeaderValueInt(headers, SAKE_FILE_ID_HEADER, fileId);
}