3 * =============================================================================
4 * SourceMod Client Preferences Extension
5 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
6 * =============================================================================
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.
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
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/>.
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>.
36 CookieManager g_CookieManager;
38 CookieManager::CookieManager()
40 for (int i=0; i<=MAXCLIENTS; i++)
43 statsLoaded[i] = false;
46 cookieDataLoadedForward = NULL;
49 CookieManager::~CookieManager(){}
51 void CookieManager::Unload()
53 /* If clients are connected we should try save their data */
55 int maxclients = playerhelpers->GetMaxClients();
57 for (int i=1; i<=maxclients; i++)
61 OnClientDisconnecting(i);
65 /* Find all cookies and delete them */
67 SourceHook::List<Cookie *>::iterator _iter;
71 _iter = cookieList.begin();
73 while (_iter != cookieList.end())
75 current = (Cookie *)*_iter;
83 g_ClientPrefs.cookieMutex->Lock();
84 if (current->usedInQuery)
86 current->shouldDelete = true;
87 g_ClientPrefs.cookieMutex->Unlock();
91 g_ClientPrefs.cookieMutex->Unlock();
95 _iter = cookieList.erase(_iter);
99 Cookie *CookieManager::FindCookie(const char *name)
101 Cookie **pCookie = cookieTrie.retrieve(name);
111 Cookie *CookieManager::CreateCookie(const char *name, const char *description, CookieAccess access)
113 Cookie *pCookie = FindCookie(name);
115 /* Check if cookie already exists */
118 /* Update data fields to the provided values */
119 strncpy(pCookie->description, description, MAX_DESC_LENGTH);
120 pCookie->description[MAX_DESC_LENGTH-1] = '\0';
122 pCookie->access = access;
127 /* First time cookie - Create from scratch */
128 pCookie = new Cookie(name, description, access);
129 cookieTrie.insert(name, pCookie);
130 cookieList.push_back(pCookie);
132 /* Attempt to insert cookie into the db and get its ID num */
134 TQueryOp *op = new TQueryOp(Query_InsertCookie, pCookie);
136 g_ClientPrefs.cookieMutex->Lock();
137 op->m_params.cookie = pCookie;
138 pCookie->usedInQuery++;
139 g_ClientPrefs.cookieMutex->Unlock();
141 g_ClientPrefs.AddQueryToQueue(op);
146 bool CookieManager::GetCookieValue(Cookie *pCookie, int client, char **value)
150 CookieData *data = pCookie->data[client];
152 /* Check if a value has been set before */
155 data = new CookieData("");
156 data->parent = pCookie;
157 clientData[client].push_back(data);
158 pCookie->data[client] = data;
159 data->changed = true;
160 data->timestamp = time(NULL);
163 *value = &data->value[0];
168 bool CookieManager::SetCookieValue(Cookie *pCookie, int client, char *value)
172 CookieData *data = pCookie->data[client];
176 data = new CookieData(value);
177 data->parent = pCookie;
178 clientData[client].push_back(data);
179 pCookie->data[client] = data;
183 strncpy(data->value, value, MAX_VALUE_LENGTH);
184 data->value[MAX_VALUE_LENGTH-1] = '\0';
187 data->changed = true;
188 data->timestamp = time(NULL);
193 void CookieManager::OnClientAuthorized(int client, const char *authstring)
195 IGamePlayer *player = playerhelpers->GetGamePlayer(client);
202 connected[client] = true;
204 TQueryOp *op = new TQueryOp(Query_SelectData, player->GetSerial());
205 strcpy(op->m_params.steamId, authstring);
207 g_ClientPrefs.AddQueryToQueue(op);
210 void CookieManager::OnClientDisconnecting(int client)
212 connected[client] = false;
213 statsLoaded[client] = false;
215 SourceHook::List<CookieData *>::iterator _iter;
219 _iter = clientData[client].begin();
221 while (_iter != clientData[client].end())
223 current = (CookieData *)*_iter;
225 if (!current->changed)
227 current->parent->data[client] = NULL;
229 _iter = clientData[client].erase(_iter);
233 /* Save this cookie to the database */
234 IGamePlayer *player = playerhelpers->GetGamePlayer(client);
242 int dbId = current->parent->dbid;
246 /* Insert/Find Query must be still running or failed. */
250 TQueryOp *op = new TQueryOp(Query_InsertData, client);
252 strcpy(op->m_params.steamId, player->GetAuthString());
253 op->m_params.cookieId = dbId;
254 op->m_params.data = current;
256 g_ClientPrefs.AddQueryToQueue(op);
258 current->parent->data[client] = NULL;
261 /* We don't delete here, it will be removed when the query is completed */
263 _iter = clientData[client].erase(_iter);
267 void CookieManager::ClientConnectCallback(int serial, IQuery *data)
272 /* Check validity of client */
273 if ((client = playerhelpers->GetClientFromSerial(serial)) == 0)
278 /* Check validity of results */
279 if (data == NULL || (results = data->GetResultSet()) == NULL)
287 if ((row = results->FetchRow()) == NULL)
293 row->GetString(0, &name, NULL);
296 row->GetString(1, &value, NULL);
298 CookieData *pData = new CookieData(value);
299 pData->changed = false;
301 unsigned int timestamp = 0;
302 row->GetInt(4, (int *)×tamp);
303 pData->timestamp = timestamp;
305 Cookie *parent = FindCookie(name);
310 row->GetString(2, &desc, NULL);
312 CookieAccess access = CookieAccess_Public;
313 row->GetInt(3, (int *)&access);
315 parent = CreateCookie(name, desc, access);
316 cookieTrie.insert(name, parent);
317 cookieList.push_back(parent);
320 pData->parent = parent;
321 parent->data[client] = pData;
323 clientData[client].push_back(pData);
325 } while (results->MoreRows());
327 statsLoaded[client] = true;
329 cookieDataLoadedForward->PushCell(client);
330 cookieDataLoadedForward->Execute(NULL);
333 void CookieManager::InsertCookieCallback(Cookie *pCookie, int dbId)
337 pCookie->dbid = dbId;
341 TQueryOp *op = new TQueryOp(Query_SelectId, pCookie);
342 /* Put the cookie name into the steamId field to save space - Make sure we remember that it's there */
343 strcpy(op->m_params.steamId, pCookie->name);
344 g_ClientPrefs.AddQueryToQueue(op);
347 void CookieManager::SelectIdCallback(Cookie *pCookie, IQuery *data)
351 if (data == NULL || (results = data->GetResultSet()) == NULL)
356 IResultRow *row = results->FetchRow();
363 row->GetInt(0, &pCookie->dbid);
366 bool CookieManager::AreClientCookiesCached(int client)
368 return statsLoaded[client];
371 void CookieManager::OnPluginDestroyed(IPlugin *plugin)
373 SourceHook::List<char *> *pList;
375 if (plugin->GetProperty("SettingsMenuItems", (void **)&pList, true))
377 SourceHook::List<char *>::iterator p_iter = pList->begin();
380 while (p_iter != pList->end())
382 name = (char *)*p_iter;
384 p_iter = pList->erase(p_iter); //remove from this plugins list
388 for (unsigned int i=0; i<clientMenu->GetItemCount(); i++)
390 const char *info = clientMenu->GetItemInfo(i, &draw);
397 if (strcmp(draw.display, name) == 0)
400 const char *info = clientMenu->GetItemInfo(i, &draw);
401 AutoMenuData *data = (AutoMenuData *)strtol(info, NULL, 16);
403 if (data->handler->forward != NULL)
405 forwards->ReleaseForward(data->handler->forward);
407 delete data->handler;
410 clientMenu->RemoveItem(i);
420 bool CookieManager::GetCookieTime(Cookie *pCookie, int client, time_t *value)
424 CookieData *data = pCookie->data[client];
426 /* Check if a value has been set before */
432 *value = data->timestamp;