Overhaul of ClientPrefs extension (bug 5538, r=asherkin).

This commit is contained in:
Kyle Sanderson 2013-02-28 21:51:49 +00:00
parent 6b07625192
commit 5d942265f9
9 changed files with 325 additions and 359 deletions

View File

@ -41,6 +41,7 @@ CookieManager::CookieManager()
{ {
connected[i] = false; connected[i] = false;
statsLoaded[i] = false; statsLoaded[i] = false;
statsPending[i] = false;
} }
cookieDataLoadedForward = NULL; cookieDataLoadedForward = NULL;
@ -51,10 +52,7 @@ CookieManager::~CookieManager(){}
void CookieManager::Unload() void CookieManager::Unload()
{ {
/* If clients are connected we should try save their data */ /* If clients are connected we should try save their data */
for (int i = playerhelpers->GetMaxClients()+1; --i > 0;)
int maxclients = playerhelpers->GetMaxClients();
for (int i=1; i<=maxclients; i++)
{ {
if (connected[i]) if (connected[i])
{ {
@ -63,20 +61,14 @@ void CookieManager::Unload()
} }
/* Find all cookies and delete them */ /* Find all cookies and delete them */
SourceHook::List<Cookie *>::iterator _iter;
Cookie *current; Cookie *current;
_iter = cookieList.begin(); for (SourceHook::List<Cookie *>::iterator _iter = cookieList.begin(); _iter != cookieList.end(); _iter++)
while (_iter != cookieList.end())
{ {
current = (Cookie *)*_iter; current = (Cookie *)*_iter;
if (current == NULL) if (current == NULL)
{ {
_iter++;
continue; continue;
} }
@ -91,9 +83,9 @@ void CookieManager::Unload()
g_ClientPrefs.cookieMutex->Unlock(); g_ClientPrefs.cookieMutex->Unlock();
delete current; delete current;
} }
_iter = cookieList.erase(_iter);
} }
cookieList.clear();
} }
Cookie *CookieManager::FindCookie(const char *name) Cookie *CookieManager::FindCookie(const char *name)
@ -116,9 +108,7 @@ Cookie *CookieManager::CreateCookie(const char *name, const char *description, C
if (pCookie != NULL) if (pCookie != NULL)
{ {
/* Update data fields to the provided values */ /* Update data fields to the provided values */
strncpy(pCookie->description, description, MAX_DESC_LENGTH); UTIL_strncpy(pCookie->description, description, MAX_DESC_LENGTH);
pCookie->description[MAX_DESC_LENGTH-1] = '\0';
pCookie->access = access; pCookie->access = access;
return pCookie; return pCookie;
@ -126,17 +116,14 @@ Cookie *CookieManager::CreateCookie(const char *name, const char *description, C
/* First time cookie - Create from scratch */ /* First time cookie - Create from scratch */
pCookie = new Cookie(name, description, access); pCookie = new Cookie(name, description, access);
cookieTrie.insert(name, pCookie); pCookie->usedInQuery++;
cookieList.push_back(pCookie);
/* Attempt to insert cookie into the db and get its ID num */ /* Attempt to insert cookie into the db and get its ID num */
TQueryOp *op = new TQueryOp(Query_InsertCookie, pCookie); TQueryOp *op = new TQueryOp(Query_InsertCookie, pCookie);
g_ClientPrefs.cookieMutex->Lock();
op->m_params.cookie = pCookie; op->m_params.cookie = pCookie;
pCookie->usedInQuery++;
g_ClientPrefs.cookieMutex->Unlock(); cookieTrie.insert(name, pCookie);
cookieList.push_back(pCookie);
g_ClientPrefs.AddQueryToQueue(op); g_ClientPrefs.AddQueryToQueue(op);
@ -145,8 +132,6 @@ Cookie *CookieManager::CreateCookie(const char *name, const char *description, C
bool CookieManager::GetCookieValue(Cookie *pCookie, int client, char **value) bool CookieManager::GetCookieValue(Cookie *pCookie, int client, char **value)
{ {
assert(pCookie);
CookieData *data = pCookie->data[client]; CookieData *data = pCookie->data[client];
/* Check if a value has been set before */ /* Check if a value has been set before */
@ -156,8 +141,8 @@ bool CookieManager::GetCookieValue(Cookie *pCookie, int client, char **value)
data->parent = pCookie; data->parent = pCookie;
clientData[client].push_back(data); clientData[client].push_back(data);
pCookie->data[client] = data; pCookie->data[client] = data;
data->changed = true; data->changed = false;
data->timestamp = time(NULL); data->timestamp = 0;
} }
*value = &data->value[0]; *value = &data->value[0];
@ -167,8 +152,6 @@ bool CookieManager::GetCookieValue(Cookie *pCookie, int client, char **value)
bool CookieManager::SetCookieValue(Cookie *pCookie, int client, const char *value) bool CookieManager::SetCookieValue(Cookie *pCookie, int client, const char *value)
{ {
assert(pCookie);
CookieData *data = pCookie->data[client]; CookieData *data = pCookie->data[client];
if (data == NULL) if (data == NULL)
@ -180,8 +163,7 @@ bool CookieManager::SetCookieValue(Cookie *pCookie, int client, const char *valu
} }
else else
{ {
strncpy(data->value, value, MAX_VALUE_LENGTH); UTIL_strncpy(data->value, value, MAX_VALUE_LENGTH);
data->value[MAX_VALUE_LENGTH-1] = '\0';
} }
data->changed = true; data->changed = true;
@ -200,9 +182,12 @@ void CookieManager::OnClientAuthorized(int client, const char *authstring)
} }
connected[client] = true; connected[client] = true;
statsPending[client] = true;
g_ClientPrefs.AttemptReconnection();
TQueryOp *op = new TQueryOp(Query_SelectData, player->GetSerial()); TQueryOp *op = new TQueryOp(Query_SelectData, player->GetSerial());
strcpy(op->m_params.steamId, authstring); UTIL_strncpy(op->m_params.steamId, authstring, MAX_NAME_LENGTH);
g_ClientPrefs.AddQueryToQueue(op); g_ClientPrefs.AddQueryToQueue(op);
} }
@ -211,105 +196,103 @@ void CookieManager::OnClientDisconnecting(int client)
{ {
connected[client] = false; connected[client] = false;
statsLoaded[client] = false; statsLoaded[client] = false;
statsPending[client] = false;
SourceHook::List<CookieData *>::iterator _iter;
CookieData *current; CookieData *current;
_iter = clientData[client].begin(); g_ClientPrefs.AttemptReconnection();
while (_iter != clientData[client].end())
{
current = (CookieData *)*_iter;
if (!current->changed)
{
current->parent->data[client] = NULL;
delete current;
_iter = clientData[client].erase(_iter);
continue;
}
/* Save this cookie to the database */ /* Save this cookie to the database */
IGamePlayer *player = playerhelpers->GetGamePlayer(client); IGamePlayer *player = playerhelpers->GetGamePlayer(client);
const char *pAuth = NULL;
int dbId;
if (player == NULL) if (player)
{ {
/* panic! */ pAuth = player->GetAuthString();
return;
} }
int dbId = current->parent->dbid; g_ClientPrefs.ClearQueryCache(player->GetSerial());
if (dbId == -1) for (SourceHook::List<CookieData *>::iterator _iter = clientData[client].begin();\
_iter != clientData[client].end(); _iter++)
{ {
/* Insert/Find Query must be still running or failed. */ if (player == NULL || pAuth == NULL)
return; {
/* panic! */
current->parent->data[client] = NULL;
delete current;
continue;
}
current = (CookieData *)*_iter;
dbId = current->parent->dbid;
if (!current->changed || dbId == -1)
{
current->parent->data[client] = NULL;
delete current;
continue;
} }
TQueryOp *op = new TQueryOp(Query_InsertData, client); TQueryOp *op = new TQueryOp(Query_InsertData, client);
strcpy(op->m_params.steamId, player->GetAuthString()); UTIL_strncpy(op->m_params.steamId, pAuth, MAX_NAME_LENGTH);
op->m_params.cookieId = dbId; op->m_params.cookieId = dbId;
op->m_params.data = current; op->m_params.data = current;
g_ClientPrefs.AddQueryToQueue(op); g_ClientPrefs.AddQueryToQueue(op);
current->parent->data[client] = NULL; current->parent->data[client] = NULL;
/* We don't delete here, it will be removed when the query is completed */
_iter = clientData[client].erase(_iter);
} }
clientData[client].clear();
} }
void CookieManager::ClientConnectCallback(int serial, IQuery *data) void CookieManager::ClientConnectCallback(int serial, IQuery *data)
{ {
int client; int client;
IResultSet *results;
/* Check validity of client */ /* Check validity of client */
if ((client = playerhelpers->GetClientFromSerial(serial)) == 0) if ((client = playerhelpers->GetClientFromSerial(serial)) == 0)
{ {
return; return;
} }
statsPending[client] = false;
IResultSet *results;
/* Check validity of results */ /* Check validity of results */
if (data == NULL || (results = data->GetResultSet()) == NULL) if (data == NULL || (results = data->GetResultSet()) == NULL)
{ {
return; return;
} }
CookieData *pData;
IResultRow *row; IResultRow *row;
do unsigned int timestamp;
{ CookieAccess access;
if ((row = results->FetchRow()) == NULL)
{
break;
}
const char *name; while (results->MoreRows() && ((row = results->FetchRow()) != NULL))
{
const char *name = "";
row->GetString(0, &name, NULL); row->GetString(0, &name, NULL);
const char *value; const char *value = "";
row->GetString(1, &value, NULL); row->GetString(1, &value, NULL);
CookieData *pData = new CookieData(value); pData = new CookieData(value);
pData->changed = false; pData->changed = false;
unsigned int timestamp = 0; pData->timestamp = (row->GetInt(4, (int *)&timestamp) == DBVal_Data) ? timestamp : 0;
row->GetInt(4, (int *)&timestamp);
pData->timestamp = timestamp;
Cookie *parent = FindCookie(name); Cookie *parent = FindCookie(name);
if (parent == NULL) if (parent == NULL)
{ {
const char *desc; const char *desc = "";
row->GetString(2, &desc, NULL); row->GetString(2, &desc, NULL);
CookieAccess access = CookieAccess_Public; access = CookieAccess_Public;
row->GetInt(3, (int *)&access); row->GetInt(3, (int *)&access);
parent = CreateCookie(name, desc, access); parent = CreateCookie(name, desc, access);
@ -317,10 +300,8 @@ void CookieManager::ClientConnectCallback(int serial, IQuery *data)
pData->parent = parent; pData->parent = parent;
parent->data[client] = pData; parent->data[client] = pData;
clientData[client].push_back(pData); clientData[client].push_back(pData);
}
} while (results->MoreRows());
statsLoaded[client] = true; statsLoaded[client] = true;
@ -338,7 +319,7 @@ void CookieManager::InsertCookieCallback(Cookie *pCookie, int dbId)
TQueryOp *op = new TQueryOp(Query_SelectId, pCookie); TQueryOp *op = new TQueryOp(Query_SelectId, pCookie);
/* Put the cookie name into the steamId field to save space - Make sure we remember that it's there */ /* Put the cookie name into the steamId field to save space - Make sure we remember that it's there */
strcpy(op->m_params.steamId, pCookie->name); UTIL_strncpy(op->m_params.steamId, pCookie->name, MAX_NAME_LENGTH);
g_ClientPrefs.AddQueryToQueue(op); g_ClientPrefs.AddQueryToQueue(op);
} }
@ -366,26 +347,31 @@ bool CookieManager::AreClientCookiesCached(int client)
return statsLoaded[client]; return statsLoaded[client];
} }
bool CookieManager::AreClientCookiesPening(int client)
{
return statsPending[client];
}
void CookieManager::OnPluginDestroyed(IPlugin *plugin) void CookieManager::OnPluginDestroyed(IPlugin *plugin)
{ {
SourceHook::List<char *> *pList; SourceHook::List<char *> *pList;
if (plugin->GetProperty("SettingsMenuItems", (void **)&pList, true)) if (plugin->GetProperty("SettingsMenuItems", (void **)&pList, true))
{ {
SourceHook::List<char *>::iterator p_iter = pList->begin();
char *name; char *name;
ItemDrawInfo draw;
const char *info;
AutoMenuData * data;
unsigned itemcount;
while (p_iter != pList->end()) for (SourceHook::List<char *>::iterator p_iter = pList->begin(); p_iter != pList->end(); p_iter++)
{ {
name = (char *)*p_iter; name = (char *)*p_iter;
itemcount = clientMenu->GetItemCount();
p_iter = pList->erase(p_iter); //remove from this plugins list //remove from this plugins list
for (unsigned int i=0; i < itemcount; i++)
ItemDrawInfo draw;
for (unsigned int i=0; i<clientMenu->GetItemCount(); i++)
{ {
const char *info = clientMenu->GetItemInfo(i, &draw); info = clientMenu->GetItemInfo(i, &draw);
if (info == NULL) if (info == NULL)
{ {
@ -394,9 +380,7 @@ void CookieManager::OnPluginDestroyed(IPlugin *plugin)
if (strcmp(draw.display, name) == 0) if (strcmp(draw.display, name) == 0)
{ {
ItemDrawInfo draw; data = (AutoMenuData *)strtoul(info, NULL, 16);
const char *info = clientMenu->GetItemInfo(i, &draw);
AutoMenuData *data = (AutoMenuData *)strtoul(info, NULL, 16);
if (data->handler->forward != NULL) if (data->handler->forward != NULL)
{ {
@ -410,15 +394,15 @@ void CookieManager::OnPluginDestroyed(IPlugin *plugin)
} }
} }
delete name; delete [] name;
} }
pList->clear();
} }
} }
bool CookieManager::GetCookieTime(Cookie *pCookie, int client, time_t *value) bool CookieManager::GetCookieTime(Cookie *pCookie, int client, time_t *value)
{ {
assert(pCookie);
CookieData *data = pCookie->data[client]; CookieData *data = pCookie->data[client];
/* Check if a value has been set before */ /* Check if a value has been set before */

View File

@ -54,11 +54,10 @@ struct CookieData
{ {
CookieData(const char *value) CookieData(const char *value)
{ {
strncpy(this->value, value, MAX_VALUE_LENGTH); UTIL_strncpy(this->value, value, MAX_VALUE_LENGTH);
this->value[MAX_VALUE_LENGTH-1] = '\0';
} }
char value[MAX_VALUE_LENGTH]; char value[MAX_VALUE_LENGTH+1];
bool changed; bool changed;
time_t timestamp; time_t timestamp;
Cookie *parent; Cookie *parent;
@ -68,10 +67,8 @@ struct Cookie
{ {
Cookie(const char *name, const char *description, CookieAccess access) Cookie(const char *name, const char *description, CookieAccess access)
{ {
strncpy(this->name, name, MAX_NAME_LENGTH); UTIL_strncpy(this->name, name, MAX_NAME_LENGTH);
this->name[MAX_NAME_LENGTH-1] = '\0'; UTIL_strncpy(this->description, description, MAX_DESC_LENGTH);
strncpy(this->description, description, MAX_DESC_LENGTH);
this->description[MAX_DESC_LENGTH-1] = '\0';
this->access = access; this->access = access;
@ -97,8 +94,8 @@ struct Cookie
} }
} }
char name[MAX_NAME_LENGTH]; char name[MAX_NAME_LENGTH+1];
char description[MAX_DESC_LENGTH]; char description[MAX_DESC_LENGTH+1];
int dbid; int dbid;
CookieData *data[MAXCLIENTS+1]; CookieData *data[MAXCLIENTS+1];
CookieAccess access; CookieAccess access;
@ -134,6 +131,8 @@ public:
void OnPluginDestroyed(IPlugin *plugin); void OnPluginDestroyed(IPlugin *plugin);
bool AreClientCookiesPening(int client);
public: public:
IForward *cookieDataLoadedForward; IForward *cookieDataLoadedForward;
SourceHook::List<Cookie *> cookieList; SourceHook::List<Cookie *> cookieList;
@ -145,6 +144,7 @@ private:
bool connected[MAXCLIENTS+1]; bool connected[MAXCLIENTS+1];
bool statsLoaded[MAXCLIENTS+1]; bool statsLoaded[MAXCLIENTS+1];
bool statsPending[MAXCLIENTS+1];
}; };
extern CookieManager g_CookieManager; extern CookieManager g_CookieManager;

View File

@ -47,7 +47,6 @@ CookieTypeHandler g_CookieTypeHandler;
HandleType_t g_CookieIterator = 0; HandleType_t g_CookieIterator = 0;
CookieIteratorHandler g_CookieIteratorHandler; CookieIteratorHandler g_CookieIteratorHandler;
DbDriver g_DriverType; DbDriver g_DriverType;
static const DatabaseInfo *storage_local = NULL;
bool ClientPrefs::SDK_OnLoad(char *error, size_t maxlength, bool late) bool ClientPrefs::SDK_OnLoad(char *error, size_t maxlength, bool late)
{ {
@ -60,28 +59,19 @@ bool ClientPrefs::SDK_OnLoad(char *error, size_t maxlength, bool late)
{ {
DBInfo = dbi->FindDatabaseConf("default"); DBInfo = dbi->FindDatabaseConf("default");
if (DBInfo == NULL ||
(strcmp(DBInfo->host, "localhost") == 0 &&
strcmp(DBInfo->database, "sourcemod") == 0 &&
strcmp(DBInfo->user, "root") == 0 &&
strcmp(DBInfo->pass, "") == 0 &&
strcmp(DBInfo->driver, "") == 0))
{
storage_local = dbi->FindDatabaseConf("storage-local");
if (DBInfo == NULL) if (DBInfo == NULL)
{ {
DBInfo = storage_local; DBInfo = dbi->FindDatabaseConf("storage-local");
} }
} }
if (DBInfo == NULL) if (DBInfo == NULL)
{ {
snprintf(error, maxlength, "Could not find \"clientprefs\" or \"default\" database configs"); snprintf(error, maxlength, "Could not find any suitable database configs");
return false; return false;
} }
}
if (DBInfo->driver[0] != '\0') if (DBInfo->driver && DBInfo->driver[0] != '\0')
{ {
Driver = dbi->FindOrLoadDriver(DBInfo->driver); Driver = dbi->FindOrLoadDriver(DBInfo->driver);
} }
@ -96,7 +86,6 @@ bool ClientPrefs::SDK_OnLoad(char *error, size_t maxlength, bool late)
return false; return false;
} }
Database = NULL;
databaseLoading = true; databaseLoading = true;
TQueryOp *op = new TQueryOp(Query_Connect, 0); TQueryOp *op = new TQueryOp(Query_Connect, 0);
dbi->AddToThreadQueue(op, PrioQueue_High); dbi->AddToThreadQueue(op, PrioQueue_High);
@ -136,19 +125,7 @@ bool ClientPrefs::SDK_OnLoad(char *error, size_t maxlength, bool late)
if (late) if (late)
{ {
int maxclients = playerhelpers->GetMaxClients(); this->CatchLateLoadClients();
for (int i = 1; i <= maxclients; i++)
{
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(i);
if (!pPlayer || !pPlayer->IsAuthorized())
{
continue;
}
g_CookieManager.OnClientAuthorized(i, pPlayer->GetAuthString());
}
} }
return true; return true;
@ -188,20 +165,37 @@ void ClientPrefs::SDK_OnUnload()
if (Database != NULL) if (Database != NULL)
{ {
Database->Close(); Database->Close();
Database = NULL;
} }
if (g_CookieManager.cookieDataLoadedForward != NULL)
{
forwards->ReleaseForward(g_CookieManager.cookieDataLoadedForward); forwards->ReleaseForward(g_CookieManager.cookieDataLoadedForward);
g_CookieManager.cookieDataLoadedForward = NULL;
}
if (g_CookieManager.clientMenu != NULL)
{
Handle_t menuHandle = g_CookieManager.clientMenu->GetHandle();
if (menuHandle != BAD_HANDLE)
{
HandleSecurity sec = HandleSecurity(identity, identity); HandleSecurity sec = HandleSecurity(identity, identity);
HandleError err = handlesys->FreeHandle(g_CookieManager.clientMenu->GetHandle(), &sec); HandleError err = handlesys->FreeHandle(menuHandle, &sec);
if (HandleError_None != err) if (HandleError_None != err)
{ {
g_pSM->LogError(myself, "Error %d when attempting to free client menu handle", err); g_pSM->LogError(myself, "Error %d when attempting to free client menu handle", err);
} }
}
g_CookieManager.clientMenu = NULL;
}
if (phrases != NULL)
{
phrases->Destroy(); phrases->Destroy();
phrases = NULL;
sharesys->DestroyIdentity( identity ); }
plsys->RemovePluginsListener(&g_CookieManager); plsys->RemovePluginsListener(&g_CookieManager);
playerhelpers->RemoveClientListener(&g_CookieManager); playerhelpers->RemoveClientListener(&g_CookieManager);
@ -212,15 +206,23 @@ void ClientPrefs::SDK_OnUnload()
void ClientPrefs::OnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax) void ClientPrefs::OnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax)
{ {
if (Database == NULL && !databaseLoading) this->AttemptReconnection();
{ }
g_pSM->LogMessage(myself, "Attempting to reconnect to database...");
void ClientPrefs::AttemptReconnection()
{
if (Database || databaseLoading)
{
return; /* We're already loading, or have loaded. */
}
g_pSM->LogMessage(myself, "Attempting to reconnect to database...");
databaseLoading = true; databaseLoading = true;
TQueryOp *op = new TQueryOp(Query_Connect, 0); TQueryOp *op = new TQueryOp(Query_Connect, 0);
dbi->AddToThreadQueue(op, PrioQueue_High); dbi->AddToThreadQueue(op, PrioQueue_High);
}
this->CatchLateLoadClients(); /* DB reconnection, we should check if we missed anyone... */
} }
void ClientPrefs::DatabaseConnect() void ClientPrefs::DatabaseConnect()
@ -230,19 +232,10 @@ void ClientPrefs::DatabaseConnect()
Database = Driver->Connect(DBInfo, true, error, sizeof(error)); Database = Driver->Connect(DBInfo, true, error, sizeof(error));
if (Database == NULL &&
DBInfo != storage_local &&
storage_local != NULL)
{
DBInfo = storage_local;
Database = Driver->Connect(DBInfo, true, error, sizeof(error));
}
if (Database == NULL) if (Database == NULL)
{ {
g_pSM->LogError(myself, error); g_pSM->LogError(myself, error);
databaseLoading = false; databaseLoading = false;
ProcessQueryCache();
return; return;
} }
@ -319,87 +312,76 @@ void ClientPrefs::DatabaseConnect()
databaseLoading = false; databaseLoading = false;
ProcessQueryCache(); this->ProcessQueryCache();
return; return;
fatal_fail: fatal_fail:
Database->Close(); Database->Close();
Database = NULL; Database = NULL;
databaseLoading = false; databaseLoading = false;
ProcessQueryCache();
} }
bool ClientPrefs::AddQueryToQueue( TQueryOp *query ) bool ClientPrefs::AddQueryToQueue( TQueryOp *query )
{ {
queryMutex->Lock(); queryMutex->Lock();
if (Database == NULL)
if (Database == NULL && databaseLoading)
{ {
cachedQueries.push_back(query); cachedQueries.push_back(query);
queryMutex->Unlock(); queryMutex->Unlock();
return true; return false;
} }
queryMutex->Unlock(); if (!cachedQueries.empty())
if (Database)
{ {
queryMutex->Unlock();
this->ProcessQueryCache();
}
else
{
queryMutex->Unlock();
}
query->SetDatabase(Database); query->SetDatabase(Database);
dbi->AddToThreadQueue(query, PrioQueue_Normal); dbi->AddToThreadQueue(query, PrioQueue_Normal);
return true; return true;
} }
query->Destroy();
/* If Database is NULL and we're not in the loading phase it must have failed - Can't do much */
return false;
}
void ClientPrefs::ProcessQueryCache() void ClientPrefs::ProcessQueryCache()
{ {
SourceHook::List<TQueryOp *>::iterator iter; if (Database == NULL)
{
return;
}
queryMutex->Lock(); queryMutex->Lock();
TQueryOp *op;
iter = cachedQueries.begin(); for (SourceHook::List<TQueryOp *>::iterator iter = cachedQueries.begin(); iter != cachedQueries.end(); iter++)
while (iter != cachedQueries.end())
{
TQueryOp *op = *iter;
if (Database != NULL)
{ {
op = *iter;
op->SetDatabase(Database); op->SetDatabase(Database);
dbi->AddToThreadQueue(op, PrioQueue_Normal); dbi->AddToThreadQueue(op, PrioQueue_Normal);
} }
else
{
op->Destroy();
}
iter++;
}
cachedQueries.clear(); cachedQueries.clear();
queryMutex->Unlock(); queryMutex->Unlock();
} }
size_t IsAuthIdConnected(char *authID) size_t IsAuthIdConnected(char *authID)
{ {
IGamePlayer *player; IGamePlayer *player;
int maxPlayers = playerhelpers->GetMaxClients(); const char *authString;
for (int playerIndex = 1; playerIndex <= maxPlayers; playerIndex++) for (int playerIndex = playerhelpers->GetMaxClients()+1; --playerIndex > 0;)
{ {
player = playerhelpers->GetGamePlayer(playerIndex); player = playerhelpers->GetGamePlayer(playerIndex);
if (!player || !player->IsConnected()) if (player == NULL || !player->IsConnected())
{ {
continue; continue;
} }
const char *authString = player->GetAuthString();
if (!authString || authString[0] == '\0') authString = player->GetAuthString();
if (authString == NULL || authString[0] == '\0')
{ {
continue; continue;
} }
@ -412,23 +394,46 @@ size_t IsAuthIdConnected(char *authID)
return 0; return 0;
} }
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...) void ClientPrefs::CatchLateLoadClients()
{ {
va_list ap; IGamePlayer *pPlayer;
va_start(ap, fmt); for (int i = playerhelpers->GetMaxClients()+1; --i > 0;)
size_t len = vsnprintf(buffer, maxlength, fmt, ap); {
va_end(ap); if (g_CookieManager.AreClientCookiesPening(i) || g_CookieManager.AreClientCookiesCached(i))
{
continue;
}
if (len >= maxlength) pPlayer = playerhelpers->GetGamePlayer(i);
if (!pPlayer || !pPlayer->IsAuthorized())
{ {
buffer[maxlength - 1] = '\0'; continue;
return (maxlength - 1); }
g_CookieManager.OnClientAuthorized(i, pPlayer->GetAuthString());
}
}
void ClientPrefs::ClearQueryCache(int serial)
{
queryMutex->Lock();
for (SourceHook::List<TQueryOp *>::iterator iter = cachedQueries.begin(); iter != cachedQueries.end();)
{
TQueryOp *op = *iter;
if (op && op->PullQueryType() == Query_SelectData && op->PullQuerySerial() == serial)
{
op->Destroy();
iter = cachedQueries.erase(iter);
} }
else else
{ {
return len; iter++;
} }
} }
queryMutex->Unlock();
}
bool Translate(char *buffer, bool Translate(char *buffer,
size_t maxlength, size_t maxlength,
@ -478,6 +483,30 @@ bool Translate(char *buffer,
return true; return true;
} }
char * UTIL_strncpy(char * destination, const char * source, size_t num)
{
if (source == NULL)
{
destination[0] = '\0';
return destination;
}
size_t req = strlen(source);
if (!req)
{
destination[0] = '\0';
return destination;
}
else if (req >= num)
{
req = num-1;
}
strncpy(destination, source, req);
destination[req] = '\0';
return destination;
}
IdentityToken_t *ClientPrefs::GetIdentity() const IdentityToken_t *ClientPrefs::GetIdentity() const
{ {
return identity; return identity;
@ -493,3 +522,15 @@ const char *ClientPrefs::GetExtensionDateString()
return SM_BUILD_TIMESTAMP; return SM_BUILD_TIMESTAMP;
} }
ClientPrefs::ClientPrefs()
{
Driver = NULL;
Database = NULL;
databaseLoading = false;
phrases = NULL;
DBInfo = NULL;
cookieMutex = NULL;
queryMutex = NULL;
identity = NULL;
}

View File

@ -38,6 +38,9 @@
#include <stdarg.h> #include <stdarg.h>
#include "smsdk_ext.h" #include "smsdk_ext.h"
#include "sh_list.h" #include "sh_list.h"
char * UTIL_strncpy(char * destination, const char * source, size_t num);
#include "cookie.h" #include "cookie.h"
#include "menus.h" #include "menus.h"
#include "query.h" #include "query.h"
@ -58,6 +61,8 @@ class TQueryOp;
*/ */
class ClientPrefs : public SDKExtension class ClientPrefs : public SDKExtension
{ {
public:
ClientPrefs();
public: public:
/** /**
* @brief This is called after the initial loading sequence has been processed. * @brief This is called after the initial loading sequence has been processed.
@ -94,6 +99,10 @@ public:
bool AddQueryToQueue(TQueryOp *query); bool AddQueryToQueue(TQueryOp *query);
void ProcessQueryCache(); void ProcessQueryCache();
void AttemptReconnection();
void CatchLateLoadClients();
void ClearQueryCache(int serial);
/** /**
* @brief Called when the pause state is changed. * @brief Called when the pause state is changed.
*/ */
@ -145,11 +154,11 @@ public:
public: public:
IDBDriver *Driver; IDBDriver *Driver;
IDatabase *Database; IDatabase *Database;
bool databaseLoading;
IPhraseCollection *phrases; IPhraseCollection *phrases;
const DatabaseInfo *DBInfo; const DatabaseInfo *DBInfo;
IMutex *cookieMutex; IMutex *cookieMutex;
bool databaseLoading;
private: private:
SourceHook::List<TQueryOp *> cachedQueries; SourceHook::List<TQueryOp *> cachedQueries;
@ -177,8 +186,6 @@ public:
size_t IsAuthIdConnected(char *authID); size_t IsAuthIdConnected(char *authID);
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...);
extern sp_nativeinfo_t g_ClientPrefNatives[]; extern sp_nativeinfo_t g_ClientPrefNatives[];
extern ClientPrefs g_ClientPrefs; extern ClientPrefs g_ClientPrefs;

View File

@ -99,7 +99,7 @@ unsigned int ClientMenuHandler::OnMenuDisplayItem(IBaseMenu *menu,
if (data->handler->forward != NULL) if (data->handler->forward != NULL)
{ {
char buffer[100]; char buffer[100];
UTIL_Format(buffer, sizeof(buffer), "%s", dr.display); g_pSM->Format(buffer, sizeof(buffer), "%s", dr.display);
data->handler->forward->PushCell(client); data->handler->forward->PushCell(client);
data->handler->forward->PushCell(CookieMenuAction_DisplayOption); data->handler->forward->PushCell(CookieMenuAction_DisplayOption);
@ -118,52 +118,14 @@ unsigned int ClientMenuHandler::OnMenuDisplayItem(IBaseMenu *menu,
void AutoMenuHandler::OnMenuSelect(SourceMod::IBaseMenu *menu, int client, unsigned int item) void AutoMenuHandler::OnMenuSelect(SourceMod::IBaseMenu *menu, int client, unsigned int item)
{ {
static const char settings[CookieMenu_Elements][2][4] = { {"yes", "no"}, {"1", "0"}, {"on", "off"}, {"1", "0"} };
ItemDrawInfo draw; ItemDrawInfo draw;
const char *info = menu->GetItemInfo(item, &draw); const char *info = menu->GetItemInfo(item, &draw);
AutoMenuData *data = (AutoMenuData *)strtoul(info, NULL, 16); AutoMenuData *data = (AutoMenuData *)strtoul(info, NULL, 16);
switch (data->type) g_CookieManager.SetCookieValue(data->pCookie, client, settings[data->type][item]);
{
case CookieMenu_YesNo:
{
if (item == 0)
{
g_CookieManager.SetCookieValue(data->pCookie, client, "yes");
}
else
{
g_CookieManager.SetCookieValue(data->pCookie, client, "no");
}
break;
}
case CookieMenu_YesNo_Int:
case CookieMenu_OnOff_Int:
{
if (item == 0)
{
g_CookieManager.SetCookieValue(data->pCookie, client, "1");
}
else
{
g_CookieManager.SetCookieValue(data->pCookie, client, "0");
}
break;
}
case CookieMenu_OnOff:
{
if (item == 0)
{
g_CookieManager.SetCookieValue(data->pCookie, client, "on");
}
else
{
g_CookieManager.SetCookieValue(data->pCookie, client, "off");
}
break;
}
}
char message[255]; char message[255];
char *value; char *value;

View File

@ -59,13 +59,14 @@ enum CookieMenu
CookieMenu_YesNo_Int, /**< Yes/No menu with 1/0 saved into the cookie */ CookieMenu_YesNo_Int, /**< Yes/No menu with 1/0 saved into the cookie */
CookieMenu_OnOff, /**< On/Off menu with "on"/"off" results saved into the cookie */ CookieMenu_OnOff, /**< On/Off menu with "on"/"off" results saved into the cookie */
CookieMenu_OnOff_Int, /**< On/Off menu with 1/0 saved into the cookie */ CookieMenu_OnOff_Int, /**< On/Off menu with 1/0 saved into the cookie */
CookieMenu_Elements
}; };
struct ItemHandler struct ItemHandler
{ {
bool isAutoMenu;
IChangeableForward *forward; IChangeableForward *forward;
CookieMenu autoMenuType; CookieMenu autoMenuType;
bool isAutoMenu;
}; };
class ClientMenuHandler : public IMenuHandler class ClientMenuHandler : public IMenuHandler
@ -96,8 +97,8 @@ struct AutoMenuData
{ {
ItemHandler *handler; ItemHandler *handler;
Cookie *pCookie; Cookie *pCookie;
CookieMenu type;
cell_t datavalue; cell_t datavalue;
CookieMenu type;
}; };
#endif // _INCLUDE_SOURCEMOD_CLIENTPREFS_MENUS_H_ #endif // _INCLUDE_SOURCEMOD_CLIENTPREFS_MENUS_H_

View File

@ -35,10 +35,7 @@
cell_t RegClientPrefCookie(IPluginContext *pContext, const cell_t *params) cell_t RegClientPrefCookie(IPluginContext *pContext, const cell_t *params)
{ {
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading) g_ClientPrefs.AttemptReconnection();
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
char *name; char *name;
pContext->LocalToString(params[1], &name); pContext->LocalToString(params[1], &name);
@ -67,10 +64,7 @@ cell_t RegClientPrefCookie(IPluginContext *pContext, const cell_t *params)
cell_t FindClientPrefCookie(IPluginContext *pContext, const cell_t *params) cell_t FindClientPrefCookie(IPluginContext *pContext, const cell_t *params)
{ {
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading) g_ClientPrefs.AttemptReconnection();
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
char *name; char *name;
pContext->LocalToString(params[1], &name); pContext->LocalToString(params[1], &name);
@ -91,10 +85,7 @@ cell_t FindClientPrefCookie(IPluginContext *pContext, const cell_t *params)
cell_t SetAuthIdCookie(IPluginContext *pContext, const cell_t *params) cell_t SetAuthIdCookie(IPluginContext *pContext, const cell_t *params)
{ {
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading) g_ClientPrefs.AttemptReconnection();
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
char *steamID; char *steamID;
pContext->LocalToString(params[1], &steamID); pContext->LocalToString(params[1], &steamID);
@ -136,8 +127,7 @@ cell_t SetAuthIdCookie(IPluginContext *pContext, const cell_t *params)
// edit database table // edit database table
TQueryOp *op = new TQueryOp(Query_InsertData, pCookie); TQueryOp *op = new TQueryOp(Query_InsertData, pCookie);
// limit player auth length which doubles for cookie name length // limit player auth length which doubles for cookie name length
strncpy(op->m_params.steamId, steamID, MAX_NAME_LENGTH); UTIL_strncpy(op->m_params.steamId, steamID, MAX_NAME_LENGTH);
op->m_params.steamId[MAX_NAME_LENGTH-1] = '\0';
op->m_params.cookieId = i_dbId; op->m_params.cookieId = i_dbId;
op->m_params.data = payload; op->m_params.data = payload;
@ -148,10 +138,7 @@ cell_t SetAuthIdCookie(IPluginContext *pContext, const cell_t *params)
cell_t SetClientPrefCookie(IPluginContext *pContext, const cell_t *params) cell_t SetClientPrefCookie(IPluginContext *pContext, const cell_t *params)
{ {
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading) g_ClientPrefs.AttemptReconnection();
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
int client = params[1]; int client = params[1];
@ -183,10 +170,7 @@ cell_t SetClientPrefCookie(IPluginContext *pContext, const cell_t *params)
cell_t GetClientPrefCookie(IPluginContext *pContext, const cell_t *params) cell_t GetClientPrefCookie(IPluginContext *pContext, const cell_t *params)
{ {
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading) g_ClientPrefs.AttemptReconnection();
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
int client = params[1]; int client = params[1];
@ -221,10 +205,7 @@ cell_t GetClientPrefCookie(IPluginContext *pContext, const cell_t *params)
cell_t AreClientCookiesCached(IPluginContext *pContext, const cell_t *params) cell_t AreClientCookiesCached(IPluginContext *pContext, const cell_t *params)
{ {
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading) g_ClientPrefs.AttemptReconnection();
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
int client = params[1]; int client = params[1];
@ -238,10 +219,7 @@ cell_t AreClientCookiesCached(IPluginContext *pContext, const cell_t *params)
cell_t GetCookieAccess(IPluginContext *pContext, const cell_t *params) cell_t GetCookieAccess(IPluginContext *pContext, const cell_t *params)
{ {
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading) g_ClientPrefs.AttemptReconnection();
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
Handle_t hndl = static_cast<Handle_t>(params[1]); Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err; HandleError err;
@ -263,10 +241,7 @@ cell_t GetCookieAccess(IPluginContext *pContext, const cell_t *params)
static cell_t GetCookieIterator(IPluginContext *pContext, const cell_t *params) static cell_t GetCookieIterator(IPluginContext *pContext, const cell_t *params)
{ {
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading) g_ClientPrefs.AttemptReconnection();
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
SourceHook::List<Cookie *>::iterator *iter = new SourceHook::List<Cookie *>::iterator; SourceHook::List<Cookie *>::iterator *iter = new SourceHook::List<Cookie *>::iterator;
*iter = g_CookieManager.cookieList.begin(); *iter = g_CookieManager.cookieList.begin();
@ -282,10 +257,7 @@ static cell_t GetCookieIterator(IPluginContext *pContext, const cell_t *params)
static cell_t ReadCookieIterator(IPluginContext *pContext, const cell_t *params) static cell_t ReadCookieIterator(IPluginContext *pContext, const cell_t *params)
{ {
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading) g_ClientPrefs.AttemptReconnection();
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
SourceHook::List<Cookie *>::iterator *iter; SourceHook::List<Cookie *>::iterator *iter;
@ -323,10 +295,7 @@ static cell_t ReadCookieIterator(IPluginContext *pContext, const cell_t *params)
cell_t ShowSettingsMenu(IPluginContext *pContext, const cell_t *params) cell_t ShowSettingsMenu(IPluginContext *pContext, const cell_t *params)
{ {
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading) g_ClientPrefs.AttemptReconnection();
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
char message[256]; char message[256];
Translate(message, sizeof(message), "%T:", 2, NULL, "Client Settings", &params[1]); Translate(message, sizeof(message), "%T:", 2, NULL, "Client Settings", &params[1]);
@ -339,10 +308,7 @@ cell_t ShowSettingsMenu(IPluginContext *pContext, const cell_t *params)
cell_t AddSettingsMenuItem(IPluginContext *pContext, const cell_t *params) cell_t AddSettingsMenuItem(IPluginContext *pContext, const cell_t *params)
{ {
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading) g_ClientPrefs.AttemptReconnection();
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
char *display; char *display;
pContext->LocalToString(params[3], &display); pContext->LocalToString(params[3], &display);
@ -358,7 +324,7 @@ cell_t AddSettingsMenuItem(IPluginContext *pContext, const cell_t *params)
AutoMenuData *data = new AutoMenuData; AutoMenuData *data = new AutoMenuData;
data->datavalue = params[2]; data->datavalue = params[2];
data->handler = pItem; data->handler = pItem;
UTIL_Format(info, sizeof(info), "%x", data); g_pSM->Format(info, sizeof(info), "%x", data);
ItemDrawInfo draw(display, 0); ItemDrawInfo draw(display, 0);
@ -376,7 +342,7 @@ cell_t AddSettingsMenuItem(IPluginContext *pContext, const cell_t *params)
} }
char *copyarray = new char[strlen(display)+1]; char *copyarray = new char[strlen(display)+1];
UTIL_Format(copyarray, strlen(display)+1, "%s", display); g_pSM->Format(copyarray, strlen(display)+1, "%s", display);
pList->push_back(copyarray); pList->push_back(copyarray);
@ -385,10 +351,7 @@ cell_t AddSettingsMenuItem(IPluginContext *pContext, const cell_t *params)
cell_t AddSettingsPrefabMenuItem(IPluginContext *pContext, const cell_t *params) cell_t AddSettingsPrefabMenuItem(IPluginContext *pContext, const cell_t *params)
{ {
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading) g_ClientPrefs.AttemptReconnection();
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
Handle_t hndl = static_cast<Handle_t>(params[1]); Handle_t hndl = static_cast<Handle_t>(params[1]);
HandleError err; HandleError err;
@ -433,7 +396,7 @@ cell_t AddSettingsPrefabMenuItem(IPluginContext *pContext, const cell_t *params)
data->pCookie = pCookie; data->pCookie = pCookie;
data->type = (CookieMenu)params[2]; data->type = (CookieMenu)params[2];
data->handler = pItem; data->handler = pItem;
UTIL_Format(info, sizeof(info), "%x", data); g_pSM->Format(info, sizeof(info), "%x", data);
g_CookieManager.clientMenu->AppendItem(info, draw); g_CookieManager.clientMenu->AppendItem(info, draw);
@ -449,7 +412,7 @@ cell_t AddSettingsPrefabMenuItem(IPluginContext *pContext, const cell_t *params)
} }
char *copyarray = new char[strlen(display)+1]; char *copyarray = new char[strlen(display)+1];
UTIL_Format(copyarray, strlen(display)+1, "%s", display); g_pSM->Format(copyarray, strlen(display)+1, "%s", display);
pList->push_back(copyarray); pList->push_back(copyarray);
@ -458,10 +421,7 @@ cell_t AddSettingsPrefabMenuItem(IPluginContext *pContext, const cell_t *params)
cell_t GetClientCookieTime(IPluginContext *pContext, const cell_t *params) cell_t GetClientCookieTime(IPluginContext *pContext, const cell_t *params)
{ {
if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading) g_ClientPrefs.AttemptReconnection();
{
return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
}
Handle_t hndl = static_cast<Handle_t>(params[2]); Handle_t hndl = static_cast<Handle_t>(params[2]);
HandleError err; HandleError err;

View File

@ -35,12 +35,6 @@
void TQueryOp::RunThinkPart() void TQueryOp::RunThinkPart()
{ {
//handler for threaded sql queries //handler for threaded sql queries
if (m_type == Query_Connect)
{
return;
}
switch (m_type) switch (m_type)
{ {
case Query_InsertCookie: case Query_InsertCookie:
@ -61,6 +55,11 @@ void TQueryOp::RunThinkPart()
break; break;
} }
case Query_Connect:
{
return;
}
default: default:
{ {
break; break;
@ -73,14 +72,12 @@ void TQueryOp::RunThreadPart()
if (m_type == Query_Connect) if (m_type == Query_Connect)
{ {
g_ClientPrefs.DatabaseConnect(); g_ClientPrefs.DatabaseConnect();
return;
} }
else
{
assert(m_database != NULL);
assert(m_database != NULL);
/* I don't think this is needed anymore... keeping for now. */ /* I don't think this is needed anymore... keeping for now. */
m_database->LockForFullAtomicOperation(); m_database->LockForFullAtomicOperation();
if (!BindParamsAndRun()) if (!BindParamsAndRun())
{ {
g_pSM->LogError(myself, g_pSM->LogError(myself,
@ -92,12 +89,9 @@ void TQueryOp::RunThreadPart()
m_database->UnlockFromFullAtomicOperation(); m_database->UnlockFromFullAtomicOperation();
} }
}
IDBDriver *TQueryOp::GetDriver() IDBDriver *TQueryOp::GetDriver()
{ {
assert(m_database != NULL);
return m_database->GetDriver(); return m_database->GetDriver();
} }
@ -131,6 +125,7 @@ TQueryOp::TQueryOp(enum querytype type, Cookie *cookie)
m_database = NULL; m_database = NULL;
m_insertId = -1; m_insertId = -1;
m_pResult = NULL; m_pResult = NULL;
m_serial = 0;
} }
void TQueryOp::SetDatabase(IDatabase *db) void TQueryOp::SetDatabase(IDatabase *db)
@ -162,7 +157,7 @@ bool TQueryOp::BindParamsAndRun()
if (g_DriverType == Driver_MySQL) if (g_DriverType == Driver_MySQL)
{ {
UTIL_Format(query, g_pSM->Format(query,
sizeof(query), sizeof(query),
"INSERT IGNORE INTO sm_cookies (name, description, access) \ "INSERT IGNORE INTO sm_cookies (name, description, access) \
VALUES (\"%s\", \"%s\", %d)", VALUES (\"%s\", \"%s\", %d)",
@ -172,7 +167,7 @@ bool TQueryOp::BindParamsAndRun()
} }
else if (g_DriverType == Driver_SQLite) else if (g_DriverType == Driver_SQLite)
{ {
UTIL_Format(query, g_pSM->Format(query,
sizeof(query), sizeof(query),
"INSERT OR IGNORE INTO sm_cookies (name, description, access) \ "INSERT OR IGNORE INTO sm_cookies (name, description, access) \
VALUES ('%s', '%s', %d)", VALUES ('%s', '%s', %d)",
@ -197,7 +192,7 @@ bool TQueryOp::BindParamsAndRun()
m_database->QuoteString(m_params.steamId, safe_str, sizeof(safe_str), &ignore); m_database->QuoteString(m_params.steamId, safe_str, sizeof(safe_str), &ignore);
UTIL_Format(query, g_pSM->Format(query,
sizeof(query), sizeof(query),
"SELECT sm_cookies.name, sm_cookie_cache.value, sm_cookies.description, \ "SELECT sm_cookies.name, sm_cookie_cache.value, sm_cookies.description, \
sm_cookies.access, sm_cookie_cache.timestamp \ sm_cookies.access, sm_cookie_cache.timestamp \
@ -228,7 +223,7 @@ bool TQueryOp::BindParamsAndRun()
if (g_DriverType == Driver_MySQL) if (g_DriverType == Driver_MySQL)
{ {
UTIL_Format(query, g_pSM->Format(query,
sizeof(query), sizeof(query),
"INSERT INTO sm_cookie_cache (player, cookie_id, value, timestamp) \ "INSERT INTO sm_cookie_cache (player, cookie_id, value, timestamp) \
VALUES (\"%s\", %d, \"%s\", %d) \ VALUES (\"%s\", %d, \"%s\", %d) \
@ -243,7 +238,7 @@ bool TQueryOp::BindParamsAndRun()
} }
else if (g_DriverType == Driver_SQLite) else if (g_DriverType == Driver_SQLite)
{ {
UTIL_Format(query, g_pSM->Format(query,
sizeof(query), sizeof(query),
"INSERT OR REPLACE INTO sm_cookie_cache \ "INSERT OR REPLACE INTO sm_cookie_cache \
(player, cookie_id, value, timestamp) \ (player, cookie_id, value, timestamp) \
@ -274,7 +269,7 @@ bool TQueryOp::BindParamsAndRun()
sizeof(safe_name), sizeof(safe_name),
&ignore); &ignore);
UTIL_Format(query, g_pSM->Format(query,
sizeof(query), sizeof(query),
"SELECT id FROM sm_cookies WHERE name = '%s'", "SELECT id FROM sm_cookies WHERE name = '%s'",
safe_name); safe_name);
@ -296,6 +291,16 @@ bool TQueryOp::BindParamsAndRun()
return false; return false;
} }
querytype TQueryOp::PullQueryType()
{
return m_type;
}
int TQueryOp::PullQuerySerial()
{
return m_serial;
}
ParamData::~ParamData() ParamData::~ParamData()
{ {
if (cookie) if (cookie)
@ -309,9 +314,11 @@ ParamData::~ParamData()
delete cookie; delete cookie;
cookie = NULL; cookie = NULL;
} }
else
{
g_ClientPrefs.cookieMutex->Unlock(); g_ClientPrefs.cookieMutex->Unlock();
} }
}
if (data) if (data)
{ {

View File

@ -94,6 +94,10 @@ public:
return m_database; return m_database;
} }
public:
querytype PullQueryType();
int PullQuerySerial();
private: private:
IDatabase *m_database; IDatabase *m_database;
IQuery *m_pResult; IQuery *m_pResult;