extensions/clientprefs/cookie.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Thu Apr 25 11:41:49 2013 -0400 (2013-04-25)
changeset 3901 dfad9b7c68ae
parent 3829 2d31287c982f
child 4029 cf8bdfcf6503
permissions -rw-r--r--
Triggering build.
pred@2009
     1
/**
pred@2009
     2
 * vim: set ts=4 :
pred@2009
     3
 * =============================================================================
pred@2009
     4
 * SourceMod Client Preferences Extension
pred@2009
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
pred@2009
     6
 * =============================================================================
pred@2009
     7
 *
pred@2009
     8
 * This program is free software; you can redistribute it and/or modify it under
pred@2009
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
pred@2009
    10
 * Free Software Foundation.
pred@2009
    11
 * 
pred@2009
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
pred@2009
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
pred@2009
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
pred@2009
    15
 * details.
pred@2009
    16
 *
pred@2009
    17
 * You should have received a copy of the GNU General Public License along with
pred@2009
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
pred@2009
    19
 *
pred@2009
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
pred@2009
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
pred@2009
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
pred@2009
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
pred@2009
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
pred@2009
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
pred@2009
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
pred@2009
    27
 * or <http://www.sourcemod.net/license.php>.
pred@2009
    28
 *
pred@2009
    29
 * Version: $Id$
pred@2009
    30
 */
pred@2009
    31
pred@2009
    32
#include "cookie.h"
pred@2048
    33
#include "menus.h"
pred@2009
    34
#include "query.h"
pred@2009
    35
pred@2009
    36
CookieManager g_CookieManager;
pred@2009
    37
pred@2009
    38
CookieManager::CookieManager()
pred@2009
    39
{
pred@2009
    40
	for (int i=0; i<=MAXCLIENTS; i++)
pred@2009
    41
	{
pred@2009
    42
		connected[i] = false;
pred@2009
    43
		statsLoaded[i] = false;
kyle@3804
    44
		statsPending[i] = false;
pred@2009
    45
	}
pred@2009
    46
pred@2048
    47
	cookieDataLoadedForward = NULL;
pred@2048
    48
	clientMenu = NULL;
pred@2009
    49
}
pred@2009
    50
CookieManager::~CookieManager(){}
pred@2009
    51
pred@2009
    52
void CookieManager::Unload()
pred@2009
    53
{
pred@2009
    54
	/* If clients are connected we should try save their data */
kyle@3804
    55
	for (int i = playerhelpers->GetMaxClients()+1; --i > 0;)
pred@2009
    56
	{
pred@2009
    57
		if (connected[i])
pred@2009
    58
		{
pred@2009
    59
			OnClientDisconnecting(i);
pred@2009
    60
		}
pred@2009
    61
	}
pred@2009
    62
pred@2009
    63
	/* Find all cookies and delete them */
pred@2009
    64
	Cookie *current;
pred@2009
    65
kyle@3804
    66
	for (SourceHook::List<Cookie *>::iterator _iter = cookieList.begin(); _iter != cookieList.end(); _iter++)
pred@2009
    67
	{
pred@2009
    68
		current = (Cookie *)*_iter;
pred@2009
    69
pred@2009
    70
		if (current == NULL)
pred@2009
    71
		{
pred@2009
    72
			continue;
pred@2009
    73
		}
pred@2009
    74
pred@2207
    75
		g_ClientPrefs.cookieMutex->Lock();
pred@2207
    76
		if (current->usedInQuery)
pred@2207
    77
		{
pred@2207
    78
			current->shouldDelete = true;
pred@2207
    79
			g_ClientPrefs.cookieMutex->Unlock();
pred@2207
    80
		}
pred@2207
    81
		else
pred@2207
    82
		{
pred@2207
    83
			g_ClientPrefs.cookieMutex->Unlock();
pred@2207
    84
			delete current;
pred@2207
    85
		}
pred@2009
    86
	}
kyle@3804
    87
	
kyle@3804
    88
	cookieList.clear();
pred@2009
    89
}
pred@2009
    90
pred@2009
    91
Cookie *CookieManager::FindCookie(const char *name)
pred@2009
    92
{
pred@2009
    93
	Cookie **pCookie = cookieTrie.retrieve(name);
pred@2009
    94
pred@2009
    95
	if (pCookie == NULL)
pred@2009
    96
	{
pred@2009
    97
		return NULL;
pred@2009
    98
	}
pred@2009
    99
pred@2009
   100
	return *pCookie;
pred@2009
   101
}
pred@2009
   102
pred@2048
   103
Cookie *CookieManager::CreateCookie(const char *name, const char *description, CookieAccess access)
pred@2009
   104
{
pred@2009
   105
	Cookie *pCookie = FindCookie(name);
pred@2009
   106
pred@2009
   107
	/* Check if cookie already exists */
pred@2009
   108
	if (pCookie != NULL)
pred@2009
   109
	{
pred@2048
   110
		/* Update data fields to the provided values */
kyle@3804
   111
		UTIL_strncpy(pCookie->description, description, MAX_DESC_LENGTH);
pred@2048
   112
		pCookie->access = access;
pred@2048
   113
pred@2009
   114
		return pCookie;
pred@2009
   115
	}
pred@2009
   116
pred@2009
   117
	/* First time cookie - Create from scratch */
pred@2048
   118
	pCookie = new Cookie(name, description, access);
kyle@3804
   119
	pCookie->usedInQuery++;
kyle@3804
   120
	
kyle@3804
   121
	/* Attempt to insert cookie into the db and get its ID num */
kyle@3804
   122
	TQueryOp *op = new TQueryOp(Query_InsertCookie, pCookie);
kyle@3804
   123
	op->m_params.cookie = pCookie;
kyle@3804
   124
	
pred@2009
   125
	cookieTrie.insert(name, pCookie);
pred@2009
   126
	cookieList.push_back(pCookie);
pred@2009
   127
pred@2207
   128
	g_ClientPrefs.AddQueryToQueue(op);
pred@2009
   129
pred@2009
   130
	return pCookie;
pred@2009
   131
}
pred@2009
   132
pred@2009
   133
bool CookieManager::GetCookieValue(Cookie *pCookie, int client, char **value)
pred@2009
   134
{
pred@2009
   135
	CookieData *data = pCookie->data[client];
pred@2009
   136
pred@2009
   137
	/* Check if a value has been set before */
pred@2009
   138
	if (data == NULL)
pred@2009
   139
	{
pred@2009
   140
		data = new CookieData("");
pred@2009
   141
		data->parent = pCookie;
pred@2009
   142
		clientData[client].push_back(data);
pred@2009
   143
		pCookie->data[client] = data;
kyle@3804
   144
		data->changed = false;
kyle@3804
   145
		data->timestamp = 0;
pred@2009
   146
	}
pred@2009
   147
pred@2009
   148
	*value = &data->value[0];
pred@2009
   149
pred@2009
   150
	return true;
pred@2009
   151
}
pred@2009
   152
fyrenmoo@2982
   153
bool CookieManager::SetCookieValue(Cookie *pCookie, int client, const char *value)
pred@2009
   154
{
pred@2009
   155
	CookieData *data = pCookie->data[client];
pred@2009
   156
pred@2009
   157
	if (data == NULL)
pred@2009
   158
	{
pred@2009
   159
		data = new CookieData(value);
pred@2009
   160
		data->parent = pCookie;
pred@2009
   161
		clientData[client].push_back(data);
pred@2009
   162
		pCookie->data[client] = data;
pred@2009
   163
	}
pred@2009
   164
	else
pred@2009
   165
	{
kyle@3804
   166
		UTIL_strncpy(data->value, value, MAX_VALUE_LENGTH);
pred@2009
   167
	}
pred@2009
   168
pred@2009
   169
	data->changed = true;
pred@2668
   170
	data->timestamp = time(NULL);
pred@2009
   171
pred@2009
   172
	return true;
pred@2009
   173
}
pred@2009
   174
pred@2009
   175
void CookieManager::OnClientAuthorized(int client, const char *authstring)
pred@2009
   176
{
dvander@2380
   177
	IGamePlayer *player = playerhelpers->GetGamePlayer(client);
dvander@2380
   178
dvander@2380
   179
	if (player == NULL)
dvander@2380
   180
	{
dvander@2380
   181
		return;
dvander@2380
   182
	}
dvander@2380
   183
pred@2009
   184
	connected[client] = true;
kyle@3804
   185
	statsPending[client] = true;
pred@2009
   186
kyle@3804
   187
	g_ClientPrefs.AttemptReconnection();
kyle@3804
   188
	
pred@2592
   189
	TQueryOp *op = new TQueryOp(Query_SelectData, player->GetSerial());
kyle@3804
   190
	UTIL_strncpy(op->m_params.steamId, authstring, MAX_NAME_LENGTH);
pred@2207
   191
pred@2207
   192
	g_ClientPrefs.AddQueryToQueue(op);
pred@2009
   193
}
pred@2009
   194
pred@2009
   195
void CookieManager::OnClientDisconnecting(int client)
pred@2009
   196
{
pred@2009
   197
	connected[client] = false;
pred@2009
   198
	statsLoaded[client] = false;
kyle@3804
   199
	statsPending[client] = false;
pred@2009
   200
kyle@3829
   201
	CookieData *current = NULL;
pred@2009
   202
kyle@3804
   203
	g_ClientPrefs.AttemptReconnection();
kyle@3804
   204
	
kyle@3804
   205
	/* Save this cookie to the database */
kyle@3804
   206
	IGamePlayer *player = playerhelpers->GetGamePlayer(client);
kyle@3804
   207
	const char *pAuth = NULL;
kyle@3804
   208
	int dbId;
kyle@3804
   209
	
kyle@3804
   210
	if (player)
pred@2009
   211
	{
kyle@3804
   212
		pAuth = player->GetAuthString();
kyle@3829
   213
		g_ClientPrefs.ClearQueryCache(player->GetSerial());
kyle@3804
   214
	}
kyle@3829
   215
		
kyle@3804
   216
	for (SourceHook::List<CookieData *>::iterator _iter = clientData[client].begin();\
kyle@3804
   217
	_iter != clientData[client].end(); _iter++)
kyle@3804
   218
	{
pred@2009
   219
		current = (CookieData *)*_iter;
kyle@3804
   220
		dbId = current->parent->dbid;
kyle@3804
   221
		
kyle@3829
   222
		if (player == NULL || pAuth == NULL || !current->changed || dbId == -1)
pred@2009
   223
		{
pred@2131
   224
			current->parent->data[client] = NULL;
pred@2131
   225
			delete current;
pred@2009
   226
			continue;
pred@2009
   227
		}
pred@2009
   228
pred@2207
   229
		TQueryOp *op = new TQueryOp(Query_InsertData, client);
pred@2009
   230
kyle@3804
   231
		UTIL_strncpy(op->m_params.steamId, pAuth, MAX_NAME_LENGTH);
pred@2207
   232
		op->m_params.cookieId = dbId;
pred@2207
   233
		op->m_params.data = current;
pred@2207
   234
pred@2207
   235
		g_ClientPrefs.AddQueryToQueue(op);
pred@2009
   236
pred@2009
   237
		current->parent->data[client] = NULL;
pred@2009
   238
	}
kyle@3804
   239
	
kyle@3804
   240
	clientData[client].clear();
pred@2009
   241
}
pred@2009
   242
pred@2592
   243
void CookieManager::ClientConnectCallback(int serial, IQuery *data)
pred@2009
   244
{
dvander@2380
   245
	int client;
dvander@2373
   246
dvander@2380
   247
	/* Check validity of client */
pred@2592
   248
	if ((client = playerhelpers->GetClientFromSerial(serial)) == 0)
dvander@2380
   249
	{
dvander@2380
   250
		return;
dvander@2380
   251
	}
kyle@3804
   252
	statsPending[client] = false;
kyle@3804
   253
	
kyle@3804
   254
	IResultSet *results;
dvander@2380
   255
	/* Check validity of results */
dvander@2373
   256
	if (data == NULL || (results = data->GetResultSet()) == NULL)
pred@2009
   257
	{
pred@2009
   258
		return;
pred@2009
   259
	}
pred@2009
   260
kyle@3804
   261
	CookieData *pData;
dvander@2373
   262
	IResultRow *row;
kyle@3804
   263
	unsigned int timestamp;
kyle@3804
   264
	CookieAccess access;
kyle@3804
   265
	
kyle@3804
   266
	while (results->MoreRows() && ((row = results->FetchRow()) != NULL))
pred@2009
   267
	{
kyle@3804
   268
		const char *name = "";
pred@2009
   269
		row->GetString(0, &name, NULL);
kyle@3804
   270
		
kyle@3804
   271
		const char *value = "";
pred@2009
   272
		row->GetString(1, &value, NULL);
pred@2009
   273
kyle@3804
   274
		pData = new CookieData(value);
pred@2009
   275
		pData->changed = false;
pred@2009
   276
kyle@3804
   277
		pData->timestamp = (row->GetInt(4, (int *)&timestamp) == DBVal_Data) ? timestamp : 0;
pred@2668
   278
pred@2009
   279
		Cookie *parent = FindCookie(name);
pred@2009
   280
pred@2009
   281
		if (parent == NULL)
pred@2009
   282
		{
kyle@3804
   283
			const char *desc = "";
pred@2009
   284
			row->GetString(2, &desc, NULL);
pred@2009
   285
kyle@3804
   286
			access = CookieAccess_Public;
pred@2048
   287
			row->GetInt(3, (int *)&access);
pred@2048
   288
pred@2048
   289
			parent = CreateCookie(name, desc, access);
pred@2009
   290
		}
pred@2009
   291
pred@2009
   292
		pData->parent = parent;
pred@2009
   293
		parent->data[client] = pData;
pred@2009
   294
		clientData[client].push_back(pData);
kyle@3804
   295
	}
pred@2009
   296
pred@2009
   297
	statsLoaded[client] = true;
pred@2009
   298
pred@2048
   299
	cookieDataLoadedForward->PushCell(client);
pred@2048
   300
	cookieDataLoadedForward->Execute(NULL);
pred@2009
   301
}
pred@2009
   302
pred@2009
   303
void CookieManager::InsertCookieCallback(Cookie *pCookie, int dbId)
pred@2009
   304
{
pred@2048
   305
	if (dbId > 0)
pred@2048
   306
	{
pred@2048
   307
		pCookie->dbid = dbId;
pred@2048
   308
		return;
pred@2048
   309
	}
pred@2048
   310
pred@2207
   311
	TQueryOp *op = new TQueryOp(Query_SelectId, pCookie);
pred@2207
   312
	/* Put the cookie name into the steamId field to save space - Make sure we remember that it's there */
kyle@3804
   313
	UTIL_strncpy(op->m_params.steamId, pCookie->name, MAX_NAME_LENGTH);
pred@2207
   314
	g_ClientPrefs.AddQueryToQueue(op);
pred@2048
   315
}
pred@2048
   316
pred@2048
   317
void CookieManager::SelectIdCallback(Cookie *pCookie, IQuery *data)
pred@2048
   318
{
dvander@2373
   319
	IResultSet *results;
dvander@2373
   320
	
dvander@2373
   321
	if (data == NULL || (results = data->GetResultSet()) == NULL)
pred@2048
   322
	{
pred@2048
   323
		return;
pred@2048
   324
	}
pred@2048
   325
pred@2048
   326
	IResultRow *row = results->FetchRow();
pred@2048
   327
pred@2048
   328
	if (row == NULL)
pred@2048
   329
	{
pred@2048
   330
		return;
pred@2048
   331
	}
pred@2048
   332
pred@2048
   333
	row->GetInt(0, &pCookie->dbid);
pred@2009
   334
}
pred@2009
   335
pred@2009
   336
bool CookieManager::AreClientCookiesCached(int client)
pred@2009
   337
{
pred@2009
   338
	return statsLoaded[client];
pred@2009
   339
}
pred@2009
   340
kyle@3804
   341
bool CookieManager::AreClientCookiesPening(int client)
kyle@3804
   342
{
kyle@3804
   343
	return statsPending[client];
kyle@3804
   344
}
kyle@3804
   345
pred@2048
   346
void CookieManager::OnPluginDestroyed(IPlugin *plugin)
pred@2048
   347
{
pred@2048
   348
	SourceHook::List<char *> *pList;
pred@2048
   349
pred@2048
   350
	if (plugin->GetProperty("SettingsMenuItems", (void **)&pList, true))
pred@2048
   351
	{
pred@2048
   352
		char *name;
kyle@3804
   353
		ItemDrawInfo draw;
kyle@3804
   354
		const char *info;
kyle@3804
   355
		AutoMenuData * data;
kyle@3804
   356
		unsigned itemcount;
kyle@3804
   357
		
kyle@3804
   358
		for (SourceHook::List<char *>::iterator p_iter = pList->begin(); p_iter != pList->end(); p_iter++)
pred@2048
   359
		{
pred@2048
   360
			name = (char *)*p_iter;
kyle@3804
   361
			itemcount = clientMenu->GetItemCount();
kyle@3804
   362
			//remove from this plugins list
kyle@3804
   363
			for (unsigned int i=0; i < itemcount; i++)
pred@2048
   364
			{
kyle@3804
   365
				info = clientMenu->GetItemInfo(i, &draw);
pred@2048
   366
pred@2048
   367
				if (info == NULL)
pred@2048
   368
				{
pred@2048
   369
					continue;
pred@2048
   370
				}
pred@2048
   371
pred@2048
   372
				if (strcmp(draw.display, name) == 0)
pred@2048
   373
				{
kyle@3804
   374
					data = (AutoMenuData *)strtoul(info, NULL, 16);
pred@2048
   375
pred@2048
   376
					if (data->handler->forward != NULL)
pred@2048
   377
					{
pred@2048
   378
						forwards->ReleaseForward(data->handler->forward);
pred@2048
   379
					}
pred@2048
   380
					delete data->handler;
pred@2048
   381
					delete data;
pred@2048
   382
pred@2048
   383
					clientMenu->RemoveItem(i);
pred@2048
   384
					break;
pred@2048
   385
				}
pred@2048
   386
			}
pred@2048
   387
kyle@3804
   388
			delete [] name;
kyle@3804
   389
		}
kyle@3804
   390
		
kyle@3804
   391
		pList->clear();
pred@2048
   392
	}
pred@2048
   393
}
dvander@2373
   394
pred@2668
   395
bool CookieManager::GetCookieTime(Cookie *pCookie, int client, time_t *value)
pred@2668
   396
{
pred@2668
   397
	CookieData *data = pCookie->data[client];
pred@2668
   398
pred@2668
   399
	/* Check if a value has been set before */
pred@2668
   400
	if (data == NULL)
pred@2668
   401
	{
pred@2668
   402
		return false;
pred@2668
   403
	}
pred@2668
   404
pred@2668
   405
	*value = data->timestamp;
pred@2668
   406
pred@2668
   407
	return true;
pred@2668
   408
}