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