openmohaa/code/gamespy/pt/ptMain.c

682 lines
15 KiB
C
Raw Permalink Normal View History

2023-02-04 21:00:01 +01:00
/*
GameSpy PT SDK
Dan "Mr. Pants" Schoenblum
dan@gamespy.com
Copyright 2000 GameSpy Industries, Inc
*/
#include <stdio.h>
#include "pt.h"
#include "../ghttp/ghttp.h"
#include "../common/gsStringUtil.h"
#include "../common/gsAvailable.h"
/************
** DEFINES **
************/
#define PTA_DEFAULT_VERCHECK_URL "http://motd." GSI_DOMAIN_NAME "/motd/vercheck.asp"
#define PTA_DEFAULT_MOTD_URL "http://motd." GSI_DOMAIN_NAME "/motd/motd.asp"
#define PTA_DEFAULT_FILEPLANET_URL "http://www.fileplanet.com/dlfileraw.asp"
#define MAX_MIRRORS 32
#define PTA_MAX_STRING_SIZE 2048
char gPTAVercheckURL[PTA_MAX_STRING_SIZE];
char gPTAMOTDURL[PTA_MAX_STRING_SIZE];
char gPTAFilePlanetURL[PTA_MAX_STRING_SIZE];
/**********
** TYPES **
**********/
typedef struct ptaPatchData
{
ptPatchCallback callback;
void * param;
} ptaPatchData;
typedef struct ptaFilePlanetInfoData
{
int fileID;
ptFilePlanetInfoCallback callback;
void * param;
} ptaFilePlanetInfoData;
/************
** GLOBALS **
************/
//static char URL[PTA_MAX_STRING_SIZE];
/**************
** FUNCTIONS **
**************/
static const char * ptaGetKeyValue
(
const char * buffer,
const char * key
)
{
static char value[PTA_MAX_STRING_SIZE];
const char * str;
int len;
str = strstr(buffer, key);
if(!str)
return NULL;
str += strlen(key);
len = (int)strcspn(str, "\\");
len = min(len, (int)sizeof(value) - 1);
memcpy(value, str, (unsigned int)len);
value[len] = '\0';
return value;
}
static char Line[PTA_MAX_STRING_SIZE];
static int ptaFillLine
(
const char * buffer
)
{
char * str = Line;
int i;
// Skip white space.
////////////////////
for(i = 0 ; isspace(*buffer) ; i++)
buffer++;
// Check for EOF.
/////////////////
if(*buffer == '\0')
return EOF;
// Copy off the line.
/////////////////////
for( ; *buffer && ((*buffer != 0x0A) && (*buffer != 0x0D)) ; i++)
{
if(i == sizeof(Line) - 1)
{
// This line is too big for our buffer.
///////////////////////////////////////
assert(0);
return EOF;
}
*str++ = *buffer++;
}
*str = '\0';
return i;
}
static void ptaCallPatchCallback
(
ptaPatchData * data,
PTBool available,
PTBool mandatory,
const char * versionName,
int fileID,
const char * downloadURL
)
{
if(data->callback)
{
#ifndef GSI_UNICODE
data->callback(available, mandatory, versionName, fileID, downloadURL, data->param);
#else
unsigned short versionName_W[255];
unsigned short downloadURL_W[PTA_MAX_STRING_SIZE*2];
UTF8ToUCS2String(versionName, versionName_W);
AsciiToUCS2String(downloadURL, downloadURL_W);
data->callback(available, mandatory, versionName_W, fileID, downloadURL_W, data->param);
#endif
}
gsifree(data);
}
// already returns ghttptrue
static GHTTPBool ptaPatchFailed
(
ptaPatchData * data
)
{
ptaCallPatchCallback(data, PTFalse, PTFalse, "", 0, "");
return GHTTPTrue;
}
static void ptaCallFilePlanetInfoCallback
(
ptaFilePlanetInfoData * data,
PTBool found,
const char * description,
const char * size,
int numMirrors,
char ** mirrorNames,
char ** mirrorURLs
)
{
int i;
if(data->callback)
{
if (!found)
data->callback(data->fileID, PTFalse, NULL, NULL, 0, NULL, NULL, data->param);
else
{
#ifndef GSI_UNICODE
data->callback(data->fileID, found, description, size, numMirrors, (const char**)mirrorNames, (const char**)mirrorURLs, data->param);
#else
unsigned short description_W[255];
unsigned short size_W[1024];
unsigned short** mirrorNames_W;
unsigned short** mirrorURLs_W;
int i;
UTF8ToUCS2String(description, description_W);
AsciiToUCS2String(size, size_W);
mirrorNames_W = UTF8ToUCS2StringArrayAlloc((const UTF8String *)mirrorNames, numMirrors);
mirrorURLs_W = UTF8ToUCS2StringArrayAlloc((const UTF8String *)mirrorURLs, numMirrors);
data->callback(data->fileID, found, description_W, size_W, numMirrors, (const unsigned short**)mirrorNames_W, (const unsigned short**)mirrorURLs_W, data->param);
for (i=0; i < numMirrors; i++)
{
gsifree(mirrorNames[i]);
gsifree(mirrorURLs[i]);
}
gsifree(mirrorNames);
gsifree(mirrorURLs);
#endif
}
}
for(i = 0 ; i < numMirrors ; i++)
{
gsifree(mirrorNames[i]);
gsifree(mirrorURLs[i]);
}
gsifree(data);
}
// already returns ghttptrue
static GHTTPBool ptaFilePlanetInfoFailed
(
ptaFilePlanetInfoData * data
)
{
ptaCallFilePlanetInfoCallback(data, PTFalse, NULL, NULL, 0, NULL, NULL);
return GHTTPTrue;
}
static GHTTPBool ptaPatchCompletedCallback
(
GHTTPRequest request,
GHTTPResult result,
char * buffer,
GHTTPByteCount bufferLen,
void * param
)
{
ptaPatchData * data = (ptaPatchData *)param;
const char * value;
PTBool mandatory;
int fileID;
char versionName[PTA_MAX_STRING_SIZE];
char downloadURL[PTA_MAX_STRING_SIZE];
GSI_UNUSED(bufferLen);
GSI_UNUSED(request);
// Check for success.
/////////////////////
if(result != GHTTPSuccess)
return ptaPatchFailed(data);
// Check for a patch.
/////////////////////
value = ptaGetKeyValue(buffer, "\\newver\\");
if(!value || !atoi(value))
return ptaPatchFailed(data);
// Check the mandatory flag.
////////////////////////////
value = ptaGetKeyValue(buffer, "\\lockout\\");
mandatory = (value && atoi(value));
// Get the file id.
///////////////////
value = ptaGetKeyValue(buffer, "\\fpfileid\\");
if(value)
fileID = atoi(value);
else
fileID = 0;
// Get the name.
////////////////
value = ptaGetKeyValue(buffer, "\\newvername\\");
if(value)
{
strncpy(versionName, value, sizeof(versionName));
versionName[sizeof(versionName) - 1] = '\0';
}
else
versionName[0] = '\0';
// Get the URL.
///////////////
value = ptaGetKeyValue(buffer, "\\dlurl\\");
if(value)
{
strncpy(downloadURL, value, sizeof(downloadURL));
downloadURL[sizeof(downloadURL) - 1] = '\0';
}
else
downloadURL[0] = '\0';
// Call the callback.
/////////////////////
ptaCallPatchCallback(data, PTTrue, mandatory, versionName, fileID, downloadURL);
return GHTTPTrue;
}
PTBool ptCheckForPatchA
(
int productID,
const char * versionUniqueID,
int distributionID,
ptPatchCallback callback,
PTBool blocking,
void * param
)
{
int charsWritten;
char aURL[PTA_MAX_STRING_SIZE];
ptaPatchData * data;
// check if the backend is available
if(__GSIACResult != GSIACAvailable)
return PTFalse;
// Check the arguments.
///////////////////////
assert(versionUniqueID);
if(!versionUniqueID)
return PTFalse;
assert(callback);
if(!callback)
return PTFalse;
// override hostname?
if (gPTAVercheckURL[0] == '\0')
sprintf(gPTAVercheckURL, PTA_DEFAULT_VERCHECK_URL);
// Store some data.
///////////////////
data = (ptaPatchData *)gsimalloc(sizeof(ptaPatchData));
if(!data)
return PTFalse;
memset(data, 0, sizeof(ptaPatchData));
data->callback = callback;
data->param = param;
// Build the URL.
/////////////////
charsWritten =
snprintf(aURL, PTA_MAX_STRING_SIZE,
"%s?productid=%d&versionuniqueid=%s&distid=%d&gamename=%s",
gPTAVercheckURL, productID, versionUniqueID, distributionID,
__GSIACGamename);
assert(charsWritten >= 0);
if (charsWritten < 0)
return PTFalse;
// Send the request.
////////////////////
if((ghttpGetFileA(aURL, (GHTTPBool)blocking, ptaPatchCompletedCallback, data) == (unsigned char)(-1)) && !blocking)
return PTFalse;
return PTTrue;
}
#ifdef GSI_UNICODE
PTBool ptCheckForPatchW
(
int productID,
const unsigned short* versionUniqueID,
int distributionID,
ptPatchCallback callback,
PTBool blocking,
void * param
)
{
char versionUniqueID_A[255];
UCS2ToUTF8String(versionUniqueID, versionUniqueID_A);
return ptCheckForPatchA(productID, versionUniqueID_A, distributionID, callback, blocking, param);
}
#endif
PTBool ptTrackUsageA
(
int userID,
int productID,
const char * versionUniqueID,
int distributionID,
PTBool blocking
)
{
int charsWritten;
char aURL[PTA_MAX_STRING_SIZE];
// check if the backend is available
if(__GSIACResult != GSIACAvailable)
return PTFalse;
// Check the arguments.
///////////////////////
assert(versionUniqueID);
if(!versionUniqueID)
return PTFalse;
// override hostname?
if (gPTAMOTDURL[0] == '\0')
sprintf(gPTAMOTDURL, PTA_DEFAULT_MOTD_URL);
// Build the URL.
/////////////////
charsWritten = snprintf(aURL, PTA_MAX_STRING_SIZE,
"%s?userid=%d&productid=%d&versionuniqueid=%s&distid=%d&uniqueid=%s&gamename=%s",
gPTAMOTDURL, userID, productID, versionUniqueID, distributionID, GOAGetUniqueID(),
__GSIACGamename);
assert(charsWritten >= 0);
if (charsWritten < 0)
return PTFalse;
// Send the info.
/////////////////
if(ghttpGetFileA(aURL, (GHTTPBool)blocking, NULL, NULL) == -1)
return PTFalse;
return PTTrue;
}
#ifdef GSI_UNICODE
PTBool ptTrackUsageW
(
int userID,
int productID,
const unsigned short* versionUniqueID,
int distributionID,
PTBool blocking
)
{
char versionUniqueID_A[255];
UCS2ToUTF8String(versionUniqueID, versionUniqueID_A);
return ptTrackUsageA(userID, productID, versionUniqueID_A, distributionID, blocking);
}
#endif
PTBool ptCreateCheckPatchTrackUsageReqA
(
int userID,
int productID,
const char * versionUniqueID,
int distributionID,
ptPatchCallback callback,
PTBool blocking,
int *request,
void * param
)
{
int charsWritten;
char aURL[PTA_MAX_STRING_SIZE];
ptaPatchData * data;
// check if the backend is available
if(__GSIACResult != GSIACAvailable)
return PTFalse;
// Check the arguments.
///////////////////////
assert(versionUniqueID);
if(!versionUniqueID)
return PTFalse;
assert(callback);
if(!callback)
return PTFalse;
// Store some data.
///////////////////
data = (ptaPatchData *)gsimalloc(sizeof(ptaPatchData));
if(!data)
return PTFalse;
memset(data, 0, sizeof(ptaPatchData));
data->callback = callback;
data->param = param;
// override hostname?
if (gPTAVercheckURL[0] == '\0')
sprintf(gPTAVercheckURL, PTA_DEFAULT_VERCHECK_URL);
// Build the URL.
/////////////////
charsWritten = snprintf(aURL, PTA_MAX_STRING_SIZE,
"%s?userid=%d&productid=%d&versionuniqueid=%s&distid=%d&uniqueid=%s&gamename=%s",
gPTAVercheckURL, userID, productID, versionUniqueID, distributionID, GOAGetUniqueID(),
__GSIACGamename);
assert(charsWritten >= 0);
if (charsWritten < 0)
return PTFalse;
// Send the request.
////////////////////
*request = ghttpGetFileA(aURL, (GHTTPBool)blocking, ptaPatchCompletedCallback, data);
if (*request == -1)
return PTFalse;
return PTTrue;
}
#ifdef GSI_UNICODE
PTBool ptCreateCheckPatchTrackUsageReqW
(
int userID,
int productID,
const unsigned short * versionUniqueID,
int distributionID,
ptPatchCallback callback,
PTBool blocking,
int *request,
void * param
)
{
char versionUniqueID_A[255];
UCS2ToUTF8String(versionUniqueID, versionUniqueID_A);
return ptCreateCheckPatchTrackUsageReqA(userID, productID, versionUniqueID_A, distributionID, callback, blocking, request, param);
}
#endif
PTBool ptCheckForPatchAndTrackUsageA
(
int userID,
int productID,
const char * versionUniqueID,
int distributionID,
ptPatchCallback callback,
PTBool blocking,
void * param
)
{
GHTTPRequest aRequest;
// create the request and send it.
///////////////////////////////////
return ptCreateCheckPatchTrackUsageReqA(userID, productID, versionUniqueID, distributionID, callback, blocking, &aRequest, param);
}
#ifdef GSI_UNICODE
PTBool ptCheckForPatchAndTrackUsageW
(
int userID,
int productID,
const unsigned short * versionUniqueID,
int distributionID,
ptPatchCallback callback,
PTBool blocking,
void * param
)
{
char versionUniqueID_A[255];
UCS2ToUTF8String(versionUniqueID, versionUniqueID_A);
return ptCheckForPatchAndTrackUsageA(userID, productID, versionUniqueID_A, distributionID, callback, blocking, param);
}
#endif
static GHTTPBool ptaFilePlanetCompletedCallback
(
GHTTPRequest request,
GHTTPResult result,
char * buffer,
GHTTPByteCount bufferLen,
void * param
)
{
ptaFilePlanetInfoData * data = (ptaFilePlanetInfoData *)param;
int len;
char description[256];
char size[64];
char * mirrorNames[MAX_MIRRORS];
char * mirrorURLs[MAX_MIRRORS];
int i;
char * str;
// check if the backend is available
if(__GSIACResult != GSIACAvailable)
return GHTTPFalse;
GSI_UNUSED(request);
GSI_UNUSED(bufferLen);
// Check for success.
/////////////////////
if(result != GHTTPSuccess)
return ptaFilePlanetInfoFailed(data);
// Get the description.
///////////////////////
len = ptaFillLine(buffer);
if(len == EOF)
return ptaFilePlanetInfoFailed(data);
buffer += len;
strncpy(description, Line, sizeof(description));
description[sizeof(description) - 1] = '\0';
// Get the size.
////////////////
len = ptaFillLine(buffer);
if(len == EOF)
return ptaFilePlanetInfoFailed(data);
buffer += len;
strncpy(size, Line, sizeof(size));
size[sizeof(size) - 1] = '\0';
// Get the mirrors.
///////////////////
for(i = 0 ; (i < MAX_MIRRORS) && ((len = ptaFillLine(buffer)) != EOF) ; )
{
// Adjust the buffer.
/////////////////////
buffer += len;
// Find the tab.
////////////////
str = strchr(Line, '\t');
if(!str)
continue;
// Copy off the name.
/////////////////////
len = (str - Line);
mirrorNames[i] = (char *)gsimalloc((unsigned int)len + 1);
if(!mirrorNames[i])
break;
memcpy(mirrorNames[i], Line, (unsigned int)len);
mirrorNames[i][len] = '\0';
// Copy off the URL.
////////////////////
str++;
len = (int)strlen(str);
mirrorURLs[i] = (char *)gsimalloc((unsigned int)len + 1);
if(!mirrorURLs[i])
{
gsifree(mirrorNames[i]);
break;
}
strcpy(mirrorURLs[i], str);
// One more mirror.
///////////////////
i++;
}
// Call the callback.
/////////////////////
ptaCallFilePlanetInfoCallback(data, PTTrue, description, size, i, mirrorNames, mirrorURLs);
return GHTTPTrue;
}
// 9/7/2004 (xgd) ptLookupFilePlanetInfo() deprecated; per case 2724.
//
PTBool ptLookupFilePlanetInfo
(
int fileID,
ptFilePlanetInfoCallback callback,
PTBool blocking,
void * param
)
{
char aURL[PTA_MAX_STRING_SIZE];
ptaFilePlanetInfoData * data;
// Check the arguments.
///////////////////////
assert(callback);
if(!callback)
return PTFalse;
// override hostname?
if (gPTAFilePlanetURL[0] == '\0')
sprintf(gPTAFilePlanetURL, PTA_DEFAULT_FILEPLANET_URL);
// Store some data.
///////////////////
data = (ptaFilePlanetInfoData *)gsimalloc(sizeof(ptaFilePlanetInfoData));
if(!data)
return PTFalse;
memset(data, 0, sizeof(ptaFilePlanetInfoData));
data->callback = callback;
data->param = param;
data->fileID = fileID;
// Build the URL.
/////////////////
// 11/24/2004 - Added By Saad Nader
// Now using string size as limit for printing
// also null terminate string automatically
///////////////////////////////////////////////
snprintf(aURL, PTA_MAX_STRING_SIZE,
"%s?file=%d&gamename=%s", gPTAFilePlanetURL, fileID, __GSIACGamename);
// Send the request.
////////////////////
if((ghttpGetFileA(aURL, (GHTTPBool)blocking, ptaFilePlanetCompletedCallback, data) == -1) && !blocking)
return PTFalse;
return PTTrue;
}