extensions/clientprefs/cookie.cpp
author Kyle Sanderson <kyle.leet@gmail.com>
Tue May 06 18:40:35 2014 -0700 (2014-05-06)
changeset 4344 c445c3266192
parent 4077 01e607ae37f0
child 4348 2cb93df2515e
permissions -rw-r--r--
Unify Maximum supported clients, raised SDKTools limit (bug 5964, r=psychonic).
pred@2009
     1
/**
dvander@4029
     2
 * vim: set ts=4 sw=4 tw=99 noet:
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
{
kyle@4344
    40
	for (int i=0; i<=SM_MAXPLAYERS; 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
			OnClientDisconnecting(i);
pred@2009
    59
	}
pred@2009
    60
pred@2009
    61
	/* Find all cookies and delete them */
kyle@3804
    62
	for (SourceHook::List<Cookie *>::iterator _iter = cookieList.begin(); _iter != cookieList.end(); _iter++)
dvander@4029
    63
		delete (*_iter);
kyle@3804
    64
	
kyle@3804
    65
	cookieList.clear();
pred@2009
    66
}
pred@2009
    67
pred@2009
    68
Cookie *CookieManager::FindCookie(const char *name)
pred@2009
    69
{
dvander@4077
    70
	Cookie *cookie;
dvander@4077
    71
	if (!cookieFinder.retrieve(name, &cookie))
pred@2009
    72
		return NULL;
dvander@4077
    73
	return cookie;
pred@2009
    74
}
pred@2009
    75
pred@2048
    76
Cookie *CookieManager::CreateCookie(const char *name, const char *description, CookieAccess access)
pred@2009
    77
{
pred@2009
    78
	Cookie *pCookie = FindCookie(name);
pred@2009
    79
pred@2009
    80
	/* Check if cookie already exists */
pred@2009
    81
	if (pCookie != NULL)
pred@2009
    82
	{
pred@2048
    83
		/* Update data fields to the provided values */
kyle@3804
    84
		UTIL_strncpy(pCookie->description, description, MAX_DESC_LENGTH);
pred@2048
    85
		pCookie->access = access;
pred@2048
    86
pred@2009
    87
		return pCookie;
pred@2009
    88
	}
pred@2009
    89
pred@2009
    90
	/* First time cookie - Create from scratch */
pred@2048
    91
	pCookie = new Cookie(name, description, access);
kyle@3804
    92
	
kyle@3804
    93
	/* Attempt to insert cookie into the db and get its ID num */
kyle@3804
    94
	TQueryOp *op = new TQueryOp(Query_InsertCookie, pCookie);
kyle@3804
    95
	op->m_params.cookie = pCookie;
kyle@3804
    96
	
dvander@4077
    97
	cookieFinder.insert(name, pCookie);
pred@2009
    98
	cookieList.push_back(pCookie);
pred@2009
    99
pred@2207
   100
	g_ClientPrefs.AddQueryToQueue(op);
pred@2009
   101
pred@2009
   102
	return pCookie;
pred@2009
   103
}
pred@2009
   104
pred@2009
   105
bool CookieManager::GetCookieValue(Cookie *pCookie, int client, char **value)
pred@2009
   106
{
pred@2009
   107
	CookieData *data = pCookie->data[client];
pred@2009
   108
pred@2009
   109
	/* Check if a value has been set before */
pred@2009
   110
	if (data == NULL)
pred@2009
   111
	{
pred@2009
   112
		data = new CookieData("");
pred@2009
   113
		data->parent = pCookie;
pred@2009
   114
		clientData[client].push_back(data);
pred@2009
   115
		pCookie->data[client] = data;
kyle@3804
   116
		data->changed = false;
kyle@3804
   117
		data->timestamp = 0;
pred@2009
   118
	}
pred@2009
   119
pred@2009
   120
	*value = &data->value[0];
pred@2009
   121
pred@2009
   122
	return true;
pred@2009
   123
}
pred@2009
   124
fyrenmoo@2982
   125
bool CookieManager::SetCookieValue(Cookie *pCookie, int client, const char *value)
pred@2009
   126
{
pred@2009
   127
	CookieData *data = pCookie->data[client];
pred@2009
   128
pred@2009
   129
	if (data == NULL)
pred@2009
   130
	{
pred@2009
   131
		data = new CookieData(value);
pred@2009
   132
		data->parent = pCookie;
pred@2009
   133
		clientData[client].push_back(data);
pred@2009
   134
		pCookie->data[client] = data;
pred@2009
   135
	}
pred@2009
   136
	else
pred@2009
   137
	{
kyle@3804
   138
		UTIL_strncpy(data->value, value, MAX_VALUE_LENGTH);
pred@2009
   139
	}
pred@2009
   140
pred@2009
   141
	data->changed = true;
pred@2668
   142
	data->timestamp = time(NULL);
pred@2009
   143
pred@2009
   144
	return true;
pred@2009
   145
}
pred@2009
   146
pred@2009
   147
void CookieManager::OnClientAuthorized(int client, const char *authstring)
pred@2009
   148
{
dvander@2380
   149
	IGamePlayer *player = playerhelpers->GetGamePlayer(client);
dvander@2380
   150
dvander@2380
   151
	if (player == NULL)
dvander@2380
   152
	{
dvander@2380
   153
		return;
dvander@2380
   154
	}
dvander@2380
   155
pred@2009
   156
	connected[client] = true;
kyle@3804
   157
	statsPending[client] = true;
pred@2009
   158
kyle@3804
   159
	g_ClientPrefs.AttemptReconnection();
kyle@3804
   160
	
pred@2592
   161
	TQueryOp *op = new TQueryOp(Query_SelectData, player->GetSerial());
kyle@3804
   162
	UTIL_strncpy(op->m_params.steamId, authstring, MAX_NAME_LENGTH);
pred@2207
   163
pred@2207
   164
	g_ClientPrefs.AddQueryToQueue(op);
pred@2009
   165
}
pred@2009
   166
pred@2009
   167
void CookieManager::OnClientDisconnecting(int client)
pred@2009
   168
{
pred@2009
   169
	connected[client] = false;
pred@2009
   170
	statsLoaded[client] = false;
kyle@3804
   171
	statsPending[client] = false;
pred@2009
   172
kyle@3829
   173
	CookieData *current = NULL;
pred@2009
   174
kyle@3804
   175
	g_ClientPrefs.AttemptReconnection();
kyle@3804
   176
	
kyle@3804
   177
	/* Save this cookie to the database */
kyle@3804
   178
	IGamePlayer *player = playerhelpers->GetGamePlayer(client);
kyle@3804
   179
	const char *pAuth = NULL;
kyle@3804
   180
	int dbId;
kyle@3804
   181
	
kyle@3804
   182
	if (player)
pred@2009
   183
	{
kyle@3804
   184
		pAuth = player->GetAuthString();
kyle@3829
   185
		g_ClientPrefs.ClearQueryCache(player->GetSerial());
kyle@3804
   186
	}
kyle@3829
   187
		
kyle@3804
   188
	for (SourceHook::List<CookieData *>::iterator _iter = clientData[client].begin();\
kyle@3804
   189
	_iter != clientData[client].end(); _iter++)
kyle@3804
   190
	{
pred@2009
   191
		current = (CookieData *)*_iter;
kyle@3804
   192
		dbId = current->parent->dbid;
kyle@3804
   193
		
kyle@3829
   194
		if (player == NULL || pAuth == NULL || !current->changed || dbId == -1)
pred@2009
   195
		{
pred@2131
   196
			current->parent->data[client] = NULL;
pred@2131
   197
			delete current;
pred@2009
   198
			continue;
pred@2009
   199
		}
pred@2009
   200
pred@2207
   201
		TQueryOp *op = new TQueryOp(Query_InsertData, client);
pred@2009
   202
kyle@3804
   203
		UTIL_strncpy(op->m_params.steamId, pAuth, MAX_NAME_LENGTH);
pred@2207
   204
		op->m_params.cookieId = dbId;
pred@2207
   205
		op->m_params.data = current;
pred@2207
   206
pred@2207
   207
		g_ClientPrefs.AddQueryToQueue(op);
pred@2009
   208
pred@2009
   209
		current->parent->data[client] = NULL;
pred@2009
   210
	}
kyle@3804
   211
	
kyle@3804
   212
	clientData[client].clear();
pred@2009
   213
}
pred@2009
   214
pred@2592
   215
void CookieManager::ClientConnectCallback(int serial, IQuery *data)
pred@2009
   216
{
dvander@2380
   217
	int client;
dvander@2373
   218
dvander@2380
   219
	/* Check validity of client */
pred@2592
   220
	if ((client = playerhelpers->GetClientFromSerial(serial)) == 0)
dvander@2380
   221
	{
dvander@2380
   222
		return;
dvander@2380
   223
	}
kyle@3804
   224
	statsPending[client] = false;
kyle@3804
   225
	
kyle@3804
   226
	IResultSet *results;
dvander@2380
   227
	/* Check validity of results */
dvander@2373
   228
	if (data == NULL || (results = data->GetResultSet()) == NULL)
pred@2009
   229
	{
pred@2009
   230
		return;
pred@2009
   231
	}
pred@2009
   232
kyle@3804
   233
	CookieData *pData;
dvander@2373
   234
	IResultRow *row;
kyle@3804
   235
	unsigned int timestamp;
kyle@3804
   236
	CookieAccess access;
kyle@3804
   237
	
kyle@3804
   238
	while (results->MoreRows() && ((row = results->FetchRow()) != NULL))
pred@2009
   239
	{
kyle@3804
   240
		const char *name = "";
pred@2009
   241
		row->GetString(0, &name, NULL);
kyle@3804
   242
		
kyle@3804
   243
		const char *value = "";
pred@2009
   244
		row->GetString(1, &value, NULL);
pred@2009
   245
kyle@3804
   246
		pData = new CookieData(value);
pred@2009
   247
		pData->changed = false;
pred@2009
   248
kyle@3804
   249
		pData->timestamp = (row->GetInt(4, (int *)&timestamp) == DBVal_Data) ? timestamp : 0;
pred@2668
   250
pred@2009
   251
		Cookie *parent = FindCookie(name);
pred@2009
   252
pred@2009
   253
		if (parent == NULL)
pred@2009
   254
		{
kyle@3804
   255
			const char *desc = "";
pred@2009
   256
			row->GetString(2, &desc, NULL);
pred@2009
   257
kyle@3804
   258
			access = CookieAccess_Public;
pred@2048
   259
			row->GetInt(3, (int *)&access);
pred@2048
   260
pred@2048
   261
			parent = CreateCookie(name, desc, access);
pred@2009
   262
		}
pred@2009
   263
pred@2009
   264
		pData->parent = parent;
pred@2009
   265
		parent->data[client] = pData;
pred@2009
   266
		clientData[client].push_back(pData);
kyle@3804
   267
	}
pred@2009
   268
pred@2009
   269
	statsLoaded[client] = true;
pred@2009
   270
pred@2048
   271
	cookieDataLoadedForward->PushCell(client);
pred@2048
   272
	cookieDataLoadedForward->Execute(NULL);
pred@2009
   273
}
pred@2009
   274
pred@2009
   275
void CookieManager::InsertCookieCallback(Cookie *pCookie, int dbId)
pred@2009
   276
{
pred@2048
   277
	if (dbId > 0)
pred@2048
   278
	{
pred@2048
   279
		pCookie->dbid = dbId;
pred@2048
   280
		return;
pred@2048
   281
	}
pred@2048
   282
pred@2207
   283
	TQueryOp *op = new TQueryOp(Query_SelectId, pCookie);
pred@2207
   284
	/* Put the cookie name into the steamId field to save space - Make sure we remember that it's there */
kyle@3804
   285
	UTIL_strncpy(op->m_params.steamId, pCookie->name, MAX_NAME_LENGTH);
pred@2207
   286
	g_ClientPrefs.AddQueryToQueue(op);
pred@2048
   287
}
pred@2048
   288
pred@2048
   289
void CookieManager::SelectIdCallback(Cookie *pCookie, IQuery *data)
pred@2048
   290
{
dvander@2373
   291
	IResultSet *results;
dvander@2373
   292
	
dvander@2373
   293
	if (data == NULL || (results = data->GetResultSet()) == NULL)
pred@2048
   294
	{
pred@2048
   295
		return;
pred@2048
   296
	}
pred@2048
   297
pred@2048
   298
	IResultRow *row = results->FetchRow();
pred@2048
   299
pred@2048
   300
	if (row == NULL)
pred@2048
   301
	{
pred@2048
   302
		return;
pred@2048
   303
	}
pred@2048
   304
pred@2048
   305
	row->GetInt(0, &pCookie->dbid);
pred@2009
   306
}
pred@2009
   307
pred@2009
   308
bool CookieManager::AreClientCookiesCached(int client)
pred@2009
   309
{
pred@2009
   310
	return statsLoaded[client];
pred@2009
   311
}
pred@2009
   312
kyle@3804
   313
bool CookieManager::AreClientCookiesPening(int client)
kyle@3804
   314
{
kyle@3804
   315
	return statsPending[client];
kyle@3804
   316
}
kyle@3804
   317
pred@2048
   318
void CookieManager::OnPluginDestroyed(IPlugin *plugin)
pred@2048
   319
{
pred@2048
   320
	SourceHook::List<char *> *pList;
pred@2048
   321
pred@2048
   322
	if (plugin->GetProperty("SettingsMenuItems", (void **)&pList, true))
pred@2048
   323
	{
pred@2048
   324
		char *name;
kyle@3804
   325
		ItemDrawInfo draw;
kyle@3804
   326
		const char *info;
kyle@3804
   327
		AutoMenuData * data;
kyle@3804
   328
		unsigned itemcount;
kyle@3804
   329
		
kyle@3804
   330
		for (SourceHook::List<char *>::iterator p_iter = pList->begin(); p_iter != pList->end(); p_iter++)
pred@2048
   331
		{
pred@2048
   332
			name = (char *)*p_iter;
kyle@3804
   333
			itemcount = clientMenu->GetItemCount();
kyle@3804
   334
			//remove from this plugins list
kyle@3804
   335
			for (unsigned int i=0; i < itemcount; i++)
pred@2048
   336
			{
kyle@3804
   337
				info = clientMenu->GetItemInfo(i, &draw);
pred@2048
   338
pred@2048
   339
				if (info == NULL)
pred@2048
   340
				{
pred@2048
   341
					continue;
pred@2048
   342
				}
pred@2048
   343
pred@2048
   344
				if (strcmp(draw.display, name) == 0)
pred@2048
   345
				{
kyle@3804
   346
					data = (AutoMenuData *)strtoul(info, NULL, 16);
pred@2048
   347
pred@2048
   348
					if (data->handler->forward != NULL)
pred@2048
   349
					{
pred@2048
   350
						forwards->ReleaseForward(data->handler->forward);
pred@2048
   351
					}
pred@2048
   352
					delete data->handler;
pred@2048
   353
					delete data;
pred@2048
   354
pred@2048
   355
					clientMenu->RemoveItem(i);
pred@2048
   356
					break;
pred@2048
   357
				}
pred@2048
   358
			}
pred@2048
   359
kyle@3804
   360
			delete [] name;
kyle@3804
   361
		}
kyle@3804
   362
		
kyle@3804
   363
		pList->clear();
pred@2048
   364
	}
pred@2048
   365
}
dvander@2373
   366
pred@2668
   367
bool CookieManager::GetCookieTime(Cookie *pCookie, int client, time_t *value)
pred@2668
   368
{
pred@2668
   369
	CookieData *data = pCookie->data[client];
pred@2668
   370
pred@2668
   371
	/* Check if a value has been set before */
pred@2668
   372
	if (data == NULL)
pred@2668
   373
	{
pred@2668
   374
		return false;
pred@2668
   375
	}
pred@2668
   376
pred@2668
   377
	*value = data->timestamp;
pred@2668
   378
pred@2668
   379
	return true;
pred@2668
   380
}