Overhaul of ClientPrefs extension (bug 5538, r=asherkin).
authorKyle Sanderson <kyle.leet@gmail.com>
Thu Feb 28 21:51:49 2013 +0000 (2013-02-28)
changeset 380490159516acd3
parent 3803 b809e6808d9d
child 3805 5f1ee51320d0
Overhaul of ClientPrefs extension (bug 5538, r=asherkin).
extensions/clientprefs/cookie.cpp
extensions/clientprefs/cookie.h
extensions/clientprefs/extension.cpp
extensions/clientprefs/extension.h
extensions/clientprefs/menus.cpp
extensions/clientprefs/menus.h
extensions/clientprefs/natives.cpp
extensions/clientprefs/query.cpp
extensions/clientprefs/query.h
     1.1 --- a/extensions/clientprefs/cookie.cpp	Mon Feb 25 20:44:16 2013 -0600
     1.2 +++ b/extensions/clientprefs/cookie.cpp	Thu Feb 28 21:51:49 2013 +0000
     1.3 @@ -41,6 +41,7 @@
     1.4  	{
     1.5  		connected[i] = false;
     1.6  		statsLoaded[i] = false;
     1.7 +		statsPending[i] = false;
     1.8  	}
     1.9  
    1.10  	cookieDataLoadedForward = NULL;
    1.11 @@ -51,10 +52,7 @@
    1.12  void CookieManager::Unload()
    1.13  {
    1.14  	/* If clients are connected we should try save their data */
    1.15 -
    1.16 -	int maxclients = playerhelpers->GetMaxClients();
    1.17 -
    1.18 -	for (int i=1; i<=maxclients; i++)
    1.19 +	for (int i = playerhelpers->GetMaxClients()+1; --i > 0;)
    1.20  	{
    1.21  		if (connected[i])
    1.22  		{
    1.23 @@ -63,20 +61,14 @@
    1.24  	}
    1.25  
    1.26  	/* Find all cookies and delete them */
    1.27 -	
    1.28 -	SourceHook::List<Cookie *>::iterator _iter;
    1.29 -
    1.30  	Cookie *current;
    1.31  
    1.32 -	_iter = cookieList.begin();
    1.33 -
    1.34 -	while (_iter != cookieList.end())
    1.35 +	for (SourceHook::List<Cookie *>::iterator _iter = cookieList.begin(); _iter != cookieList.end(); _iter++)
    1.36  	{
    1.37  		current = (Cookie *)*_iter;
    1.38  
    1.39  		if (current == NULL)
    1.40  		{
    1.41 -			_iter++;
    1.42  			continue;
    1.43  		}
    1.44  
    1.45 @@ -91,9 +83,9 @@
    1.46  			g_ClientPrefs.cookieMutex->Unlock();
    1.47  			delete current;
    1.48  		}
    1.49 -
    1.50 -		_iter = cookieList.erase(_iter);
    1.51  	}
    1.52 +	
    1.53 +	cookieList.clear();
    1.54  }
    1.55  
    1.56  Cookie *CookieManager::FindCookie(const char *name)
    1.57 @@ -116,9 +108,7 @@
    1.58  	if (pCookie != NULL)
    1.59  	{
    1.60  		/* Update data fields to the provided values */
    1.61 -		strncpy(pCookie->description, description, MAX_DESC_LENGTH);
    1.62 -		pCookie->description[MAX_DESC_LENGTH-1] = '\0';
    1.63 -
    1.64 +		UTIL_strncpy(pCookie->description, description, MAX_DESC_LENGTH);
    1.65  		pCookie->access = access;
    1.66  
    1.67  		return pCookie;
    1.68 @@ -126,18 +116,15 @@
    1.69  
    1.70  	/* First time cookie - Create from scratch */
    1.71  	pCookie = new Cookie(name, description, access);
    1.72 +	pCookie->usedInQuery++;
    1.73 +	
    1.74 +	/* Attempt to insert cookie into the db and get its ID num */
    1.75 +	TQueryOp *op = new TQueryOp(Query_InsertCookie, pCookie);
    1.76 +	op->m_params.cookie = pCookie;
    1.77 +	
    1.78  	cookieTrie.insert(name, pCookie);
    1.79  	cookieList.push_back(pCookie);
    1.80  
    1.81 -	/* Attempt to insert cookie into the db and get its ID num */
    1.82 -
    1.83 -	TQueryOp *op = new TQueryOp(Query_InsertCookie, pCookie);
    1.84 -
    1.85 -	g_ClientPrefs.cookieMutex->Lock();
    1.86 -	op->m_params.cookie = pCookie;
    1.87 -	pCookie->usedInQuery++;
    1.88 -	g_ClientPrefs.cookieMutex->Unlock();
    1.89 -
    1.90  	g_ClientPrefs.AddQueryToQueue(op);
    1.91  
    1.92  	return pCookie;
    1.93 @@ -145,8 +132,6 @@
    1.94  
    1.95  bool CookieManager::GetCookieValue(Cookie *pCookie, int client, char **value)
    1.96  {
    1.97 -	assert(pCookie);
    1.98 -
    1.99  	CookieData *data = pCookie->data[client];
   1.100  
   1.101  	/* Check if a value has been set before */
   1.102 @@ -156,8 +141,8 @@
   1.103  		data->parent = pCookie;
   1.104  		clientData[client].push_back(data);
   1.105  		pCookie->data[client] = data;
   1.106 -		data->changed = true;
   1.107 -		data->timestamp = time(NULL);
   1.108 +		data->changed = false;
   1.109 +		data->timestamp = 0;
   1.110  	}
   1.111  
   1.112  	*value = &data->value[0];
   1.113 @@ -167,8 +152,6 @@
   1.114  
   1.115  bool CookieManager::SetCookieValue(Cookie *pCookie, int client, const char *value)
   1.116  {
   1.117 -	assert(pCookie);
   1.118 -
   1.119  	CookieData *data = pCookie->data[client];
   1.120  
   1.121  	if (data == NULL)
   1.122 @@ -180,8 +163,7 @@
   1.123  	}
   1.124  	else
   1.125  	{
   1.126 -		strncpy(data->value, value, MAX_VALUE_LENGTH);
   1.127 -		data->value[MAX_VALUE_LENGTH-1] = '\0';
   1.128 +		UTIL_strncpy(data->value, value, MAX_VALUE_LENGTH);
   1.129  	}
   1.130  
   1.131  	data->changed = true;
   1.132 @@ -200,9 +182,12 @@
   1.133  	}
   1.134  
   1.135  	connected[client] = true;
   1.136 +	statsPending[client] = true;
   1.137  
   1.138 +	g_ClientPrefs.AttemptReconnection();
   1.139 +	
   1.140  	TQueryOp *op = new TQueryOp(Query_SelectData, player->GetSerial());
   1.141 -	strcpy(op->m_params.steamId, authstring);
   1.142 +	UTIL_strncpy(op->m_params.steamId, authstring, MAX_NAME_LENGTH);
   1.143  
   1.144  	g_ClientPrefs.AddQueryToQueue(op);
   1.145  }
   1.146 @@ -211,105 +196,103 @@
   1.147  {
   1.148  	connected[client] = false;
   1.149  	statsLoaded[client] = false;
   1.150 -
   1.151 -	SourceHook::List<CookieData *>::iterator _iter;
   1.152 +	statsPending[client] = false;
   1.153  
   1.154  	CookieData *current;
   1.155  
   1.156 -	_iter = clientData[client].begin();
   1.157 -
   1.158 -	while (_iter != clientData[client].end())
   1.159 +	g_ClientPrefs.AttemptReconnection();
   1.160 +	
   1.161 +	/* Save this cookie to the database */
   1.162 +	IGamePlayer *player = playerhelpers->GetGamePlayer(client);
   1.163 +	const char *pAuth = NULL;
   1.164 +	int dbId;
   1.165 +	
   1.166 +	if (player)
   1.167  	{
   1.168 +		pAuth = player->GetAuthString();
   1.169 +	}
   1.170 +	
   1.171 +	g_ClientPrefs.ClearQueryCache(player->GetSerial());
   1.172 +	
   1.173 +	for (SourceHook::List<CookieData *>::iterator _iter = clientData[client].begin();\
   1.174 +	_iter != clientData[client].end(); _iter++)
   1.175 +	{
   1.176 +		if (player == NULL || pAuth == NULL)
   1.177 +		{
   1.178 +			/* panic! */
   1.179 +			current->parent->data[client] = NULL;
   1.180 +			delete current;
   1.181 +			continue;
   1.182 +		}
   1.183 +	
   1.184  		current = (CookieData *)*_iter;
   1.185 -
   1.186 -		if (!current->changed)
   1.187 +		dbId = current->parent->dbid;
   1.188 +		
   1.189 +		if (!current->changed || dbId == -1)
   1.190  		{
   1.191  			current->parent->data[client] = NULL;
   1.192  			delete current;
   1.193 -			_iter = clientData[client].erase(_iter);
   1.194  			continue;
   1.195  		}
   1.196  
   1.197 -		/* Save this cookie to the database */
   1.198 -		IGamePlayer *player = playerhelpers->GetGamePlayer(client);
   1.199 -
   1.200 -		if (player == NULL)
   1.201 -		{
   1.202 -			/* panic! */
   1.203 -			return;
   1.204 -		}
   1.205 -
   1.206 -		int dbId = current->parent->dbid;
   1.207 -
   1.208 -		if (dbId == -1)
   1.209 -		{
   1.210 -			/* Insert/Find Query must be still running or failed. */
   1.211 -			return;
   1.212 -		}
   1.213 -
   1.214  		TQueryOp *op = new TQueryOp(Query_InsertData, client);
   1.215  
   1.216 -		strcpy(op->m_params.steamId, player->GetAuthString());
   1.217 +		UTIL_strncpy(op->m_params.steamId, pAuth, MAX_NAME_LENGTH);
   1.218  		op->m_params.cookieId = dbId;
   1.219  		op->m_params.data = current;
   1.220  
   1.221  		g_ClientPrefs.AddQueryToQueue(op);
   1.222  
   1.223  		current->parent->data[client] = NULL;
   1.224 -		
   1.225 -
   1.226 -		/* We don't delete here, it will be removed when the query is completed */
   1.227 -
   1.228 -		_iter = clientData[client].erase(_iter);
   1.229  	}
   1.230 +	
   1.231 +	clientData[client].clear();
   1.232  }
   1.233  
   1.234  void CookieManager::ClientConnectCallback(int serial, IQuery *data)
   1.235  {
   1.236  	int client;
   1.237 -	IResultSet *results;
   1.238  
   1.239  	/* Check validity of client */
   1.240  	if ((client = playerhelpers->GetClientFromSerial(serial)) == 0)
   1.241  	{
   1.242  		return;
   1.243  	}
   1.244 -
   1.245 +	statsPending[client] = false;
   1.246 +	
   1.247 +	IResultSet *results;
   1.248  	/* Check validity of results */
   1.249  	if (data == NULL || (results = data->GetResultSet()) == NULL)
   1.250  	{
   1.251  		return;
   1.252  	}
   1.253  
   1.254 +	CookieData *pData;
   1.255  	IResultRow *row;
   1.256 -	do
   1.257 +	unsigned int timestamp;
   1.258 +	CookieAccess access;
   1.259 +	
   1.260 +	while (results->MoreRows() && ((row = results->FetchRow()) != NULL))
   1.261  	{
   1.262 -		if ((row = results->FetchRow()) == NULL)
   1.263 -		{
   1.264 -			break;
   1.265 -		}
   1.266 -
   1.267 -		const char *name;
   1.268 +		const char *name = "";
   1.269  		row->GetString(0, &name, NULL);
   1.270 -
   1.271 -		const char *value;
   1.272 +		
   1.273 +		const char *value = "";
   1.274  		row->GetString(1, &value, NULL);
   1.275  
   1.276 -		CookieData *pData = new CookieData(value);
   1.277 +		pData = new CookieData(value);
   1.278  		pData->changed = false;
   1.279  
   1.280 -		unsigned int timestamp = 0;
   1.281 -		row->GetInt(4, (int *)&timestamp);
   1.282 -		pData->timestamp = timestamp;
   1.283 +		pData->timestamp = (row->GetInt(4, (int *)&timestamp) == DBVal_Data) ? timestamp : 0;
   1.284  
   1.285  		Cookie *parent = FindCookie(name);
   1.286  
   1.287  		if (parent == NULL)
   1.288  		{
   1.289 -			const char *desc;
   1.290 +			const char *desc = "";
   1.291  			row->GetString(2, &desc, NULL);
   1.292  
   1.293 -			CookieAccess access = CookieAccess_Public;
   1.294 +			access = CookieAccess_Public;
   1.295  			row->GetInt(3, (int *)&access);
   1.296  
   1.297  			parent = CreateCookie(name, desc, access);
   1.298 @@ -317,10 +300,8 @@
   1.299  
   1.300  		pData->parent = parent;
   1.301  		parent->data[client] = pData;
   1.302 -
   1.303  		clientData[client].push_back(pData);
   1.304 -
   1.305 -	} while (results->MoreRows());
   1.306 +	}
   1.307  
   1.308  	statsLoaded[client] = true;
   1.309  
   1.310 @@ -338,7 +319,7 @@
   1.311  
   1.312  	TQueryOp *op = new TQueryOp(Query_SelectId, pCookie);
   1.313  	/* Put the cookie name into the steamId field to save space - Make sure we remember that it's there */
   1.314 -	strcpy(op->m_params.steamId, pCookie->name);
   1.315 +	UTIL_strncpy(op->m_params.steamId, pCookie->name, MAX_NAME_LENGTH);
   1.316  	g_ClientPrefs.AddQueryToQueue(op);
   1.317  }
   1.318  
   1.319 @@ -366,26 +347,31 @@
   1.320  	return statsLoaded[client];
   1.321  }
   1.322  
   1.323 +bool CookieManager::AreClientCookiesPening(int client)
   1.324 +{
   1.325 +	return statsPending[client];
   1.326 +}
   1.327 +
   1.328  void CookieManager::OnPluginDestroyed(IPlugin *plugin)
   1.329  {
   1.330  	SourceHook::List<char *> *pList;
   1.331  
   1.332  	if (plugin->GetProperty("SettingsMenuItems", (void **)&pList, true))
   1.333  	{
   1.334 -		SourceHook::List<char *>::iterator p_iter = pList->begin();
   1.335  		char *name;
   1.336 -
   1.337 -		while (p_iter != pList->end())
   1.338 +		ItemDrawInfo draw;
   1.339 +		const char *info;
   1.340 +		AutoMenuData * data;
   1.341 +		unsigned itemcount;
   1.342 +		
   1.343 +		for (SourceHook::List<char *>::iterator p_iter = pList->begin(); p_iter != pList->end(); p_iter++)
   1.344  		{
   1.345  			name = (char *)*p_iter;
   1.346 -		
   1.347 -			p_iter = pList->erase(p_iter); //remove from this plugins list
   1.348 -
   1.349 -			ItemDrawInfo draw;
   1.350 -			
   1.351 -			for (unsigned int i=0; i<clientMenu->GetItemCount(); i++)
   1.352 +			itemcount = clientMenu->GetItemCount();
   1.353 +			//remove from this plugins list
   1.354 +			for (unsigned int i=0; i < itemcount; i++)
   1.355  			{
   1.356 -				const char *info = clientMenu->GetItemInfo(i, &draw);
   1.357 +				info = clientMenu->GetItemInfo(i, &draw);
   1.358  
   1.359  				if (info == NULL)
   1.360  				{
   1.361 @@ -394,9 +380,7 @@
   1.362  
   1.363  				if (strcmp(draw.display, name) == 0)
   1.364  				{
   1.365 -					ItemDrawInfo draw;
   1.366 -					const char *info = clientMenu->GetItemInfo(i, &draw);
   1.367 -					AutoMenuData *data = (AutoMenuData *)strtoul(info, NULL, 16);
   1.368 +					data = (AutoMenuData *)strtoul(info, NULL, 16);
   1.369  
   1.370  					if (data->handler->forward != NULL)
   1.371  					{
   1.372 @@ -410,15 +394,15 @@
   1.373  				}
   1.374  			}
   1.375  
   1.376 -			delete name;
   1.377 -		}		
   1.378 +			delete [] name;
   1.379 +		}
   1.380 +		
   1.381 +		pList->clear();
   1.382  	}
   1.383  }
   1.384  
   1.385  bool CookieManager::GetCookieTime(Cookie *pCookie, int client, time_t *value)
   1.386  {
   1.387 -	assert(pCookie);
   1.388 -
   1.389  	CookieData *data = pCookie->data[client];
   1.390  
   1.391  	/* Check if a value has been set before */
     2.1 --- a/extensions/clientprefs/cookie.h	Mon Feb 25 20:44:16 2013 -0600
     2.2 +++ b/extensions/clientprefs/cookie.h	Thu Feb 28 21:51:49 2013 +0000
     2.3 @@ -54,11 +54,10 @@
     2.4  {
     2.5  	CookieData(const char *value)
     2.6  	{
     2.7 -		strncpy(this->value, value, MAX_VALUE_LENGTH);
     2.8 -		this->value[MAX_VALUE_LENGTH-1] = '\0';
     2.9 +		UTIL_strncpy(this->value, value, MAX_VALUE_LENGTH);
    2.10  	}
    2.11  
    2.12 -	char value[MAX_VALUE_LENGTH];
    2.13 +	char value[MAX_VALUE_LENGTH+1];
    2.14  	bool changed;
    2.15  	time_t timestamp;
    2.16  	Cookie *parent;
    2.17 @@ -68,10 +67,8 @@
    2.18  {
    2.19  	Cookie(const char *name, const char *description, CookieAccess access)
    2.20  	{
    2.21 -		strncpy(this->name, name, MAX_NAME_LENGTH);
    2.22 -		this->name[MAX_NAME_LENGTH-1] = '\0';
    2.23 -		strncpy(this->description, description, MAX_DESC_LENGTH);
    2.24 -		this->description[MAX_DESC_LENGTH-1] = '\0';
    2.25 +		UTIL_strncpy(this->name, name, MAX_NAME_LENGTH);
    2.26 +		UTIL_strncpy(this->description, description, MAX_DESC_LENGTH);
    2.27  
    2.28  		this->access = access;
    2.29  
    2.30 @@ -97,8 +94,8 @@
    2.31  		}
    2.32  	}
    2.33  
    2.34 -	char name[MAX_NAME_LENGTH];
    2.35 -	char description[MAX_DESC_LENGTH];
    2.36 +	char name[MAX_NAME_LENGTH+1];
    2.37 +	char description[MAX_DESC_LENGTH+1];
    2.38  	int dbid;
    2.39  	CookieData *data[MAXCLIENTS+1];
    2.40  	CookieAccess access;
    2.41 @@ -133,6 +130,8 @@
    2.42  	bool AreClientCookiesCached(int client);
    2.43  
    2.44  	void OnPluginDestroyed(IPlugin *plugin);
    2.45 +	
    2.46 +	bool AreClientCookiesPening(int client);
    2.47  
    2.48  public:
    2.49  	IForward *cookieDataLoadedForward;
    2.50 @@ -145,6 +144,7 @@
    2.51  
    2.52  	bool connected[MAXCLIENTS+1];
    2.53  	bool statsLoaded[MAXCLIENTS+1];
    2.54 +	bool statsPending[MAXCLIENTS+1];
    2.55  };
    2.56  
    2.57  extern CookieManager g_CookieManager;
     3.1 --- a/extensions/clientprefs/extension.cpp	Mon Feb 25 20:44:16 2013 -0600
     3.2 +++ b/extensions/clientprefs/extension.cpp	Thu Feb 28 21:51:49 2013 +0000
     3.3 @@ -47,7 +47,6 @@
     3.4  HandleType_t g_CookieIterator = 0;
     3.5  CookieIteratorHandler g_CookieIteratorHandler;
     3.6  DbDriver g_DriverType;
     3.7 -static const DatabaseInfo *storage_local = NULL;
     3.8  
     3.9  bool ClientPrefs::SDK_OnLoad(char *error, size_t maxlength, bool late)
    3.10  {
    3.11 @@ -60,28 +59,19 @@
    3.12  	{
    3.13  		DBInfo = dbi->FindDatabaseConf("default");
    3.14  
    3.15 -		if (DBInfo == NULL ||
    3.16 -			(strcmp(DBInfo->host, "localhost") == 0 &&
    3.17 -			 strcmp(DBInfo->database, "sourcemod") == 0 && 
    3.18 -			 strcmp(DBInfo->user, "root") == 0 &&
    3.19 -			 strcmp(DBInfo->pass, "") == 0 &&
    3.20 -			 strcmp(DBInfo->driver, "") == 0))
    3.21 -		{
    3.22 -			storage_local = dbi->FindDatabaseConf("storage-local");
    3.23 -			if (DBInfo == NULL)
    3.24 -			{
    3.25 -				DBInfo = storage_local;
    3.26 -			}
    3.27 -		}
    3.28 -
    3.29  		if (DBInfo == NULL)
    3.30  		{
    3.31 -			snprintf(error, maxlength, "Could not find \"clientprefs\" or \"default\" database configs");
    3.32 -			return false;
    3.33 +			DBInfo = dbi->FindDatabaseConf("storage-local");
    3.34  		}
    3.35  	}
    3.36 +	
    3.37 +	if (DBInfo == NULL)
    3.38 +	{
    3.39 +		snprintf(error, maxlength, "Could not find any suitable database configs");
    3.40 +		return false;
    3.41 +	}
    3.42  
    3.43 -	if (DBInfo->driver[0] != '\0')
    3.44 +	if (DBInfo->driver && DBInfo->driver[0] != '\0')
    3.45  	{
    3.46  		Driver = dbi->FindOrLoadDriver(DBInfo->driver);
    3.47  	}
    3.48 @@ -96,7 +86,6 @@
    3.49  		return false;
    3.50  	}
    3.51  
    3.52 -	Database = NULL;
    3.53  	databaseLoading = true;
    3.54  	TQueryOp *op = new TQueryOp(Query_Connect, 0);
    3.55  	dbi->AddToThreadQueue(op, PrioQueue_High);
    3.56 @@ -136,19 +125,7 @@
    3.57  
    3.58  	if (late)
    3.59  	{
    3.60 -		int maxclients = playerhelpers->GetMaxClients();
    3.61 -
    3.62 -		for (int i = 1; i <= maxclients; i++)
    3.63 -		{
    3.64 -			IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(i);
    3.65 -
    3.66 -			if (!pPlayer || !pPlayer->IsAuthorized())
    3.67 -			{
    3.68 -				continue;
    3.69 -			}
    3.70 -
    3.71 -			g_CookieManager.OnClientAuthorized(i, pPlayer->GetAuthString());
    3.72 -		}
    3.73 +		this->CatchLateLoadClients();
    3.74  	}
    3.75  
    3.76  	return true;
    3.77 @@ -188,20 +165,37 @@
    3.78  	if (Database != NULL)
    3.79  	{
    3.80  		Database->Close();
    3.81 +		Database = NULL;
    3.82 +	}
    3.83 +
    3.84 +	if (g_CookieManager.cookieDataLoadedForward != NULL)
    3.85 +	{
    3.86 +		forwards->ReleaseForward(g_CookieManager.cookieDataLoadedForward);
    3.87 +		g_CookieManager.cookieDataLoadedForward = NULL;
    3.88  	}
    3.89  
    3.90 -	forwards->ReleaseForward(g_CookieManager.cookieDataLoadedForward);
    3.91 -
    3.92 -	HandleSecurity sec = HandleSecurity(identity, identity);
    3.93 -	HandleError err = handlesys->FreeHandle(g_CookieManager.clientMenu->GetHandle(), &sec);
    3.94 -	if (HandleError_None != err)
    3.95 +	if (g_CookieManager.clientMenu != NULL)
    3.96  	{
    3.97 -		g_pSM->LogError(myself, "Error %d when attempting to free client menu handle", err);
    3.98 +		Handle_t menuHandle = g_CookieManager.clientMenu->GetHandle();
    3.99 +		
   3.100 +		if (menuHandle != BAD_HANDLE)
   3.101 +		{
   3.102 +			HandleSecurity sec = HandleSecurity(identity, identity);
   3.103 +			HandleError err = handlesys->FreeHandle(menuHandle, &sec);
   3.104 +			if (HandleError_None != err)
   3.105 +			{
   3.106 +				g_pSM->LogError(myself, "Error %d when attempting to free client menu handle", err);
   3.107 +			}
   3.108 +		}
   3.109 +		
   3.110 +		g_CookieManager.clientMenu = NULL;
   3.111  	}
   3.112  
   3.113 -	phrases->Destroy();
   3.114 -
   3.115 -	sharesys->DestroyIdentity( identity );
   3.116 +	if (phrases != NULL)
   3.117 +	{
   3.118 +		phrases->Destroy();
   3.119 +		phrases = NULL;
   3.120 +	}
   3.121  
   3.122  	plsys->RemovePluginsListener(&g_CookieManager);
   3.123  	playerhelpers->RemoveClientListener(&g_CookieManager);
   3.124 @@ -212,15 +206,23 @@
   3.125  
   3.126  void ClientPrefs::OnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax)
   3.127  {
   3.128 -	if (Database == NULL && !databaseLoading)
   3.129 +	this->AttemptReconnection();
   3.130 +}
   3.131 +
   3.132 +void ClientPrefs::AttemptReconnection()
   3.133 +{
   3.134 +	if (Database || databaseLoading)
   3.135  	{
   3.136 -		g_pSM->LogMessage(myself, "Attempting to reconnect to database...");
   3.137 -		
   3.138 -		databaseLoading = true;
   3.139 -		
   3.140 -		TQueryOp *op = new TQueryOp(Query_Connect, 0);
   3.141 -		dbi->AddToThreadQueue(op, PrioQueue_High);
   3.142 +		return; /* We're already loading, or have loaded. */
   3.143  	}
   3.144 +	
   3.145 +	g_pSM->LogMessage(myself, "Attempting to reconnect to database...");
   3.146 +	databaseLoading = true;
   3.147 +	
   3.148 +	TQueryOp *op = new TQueryOp(Query_Connect, 0);
   3.149 +	dbi->AddToThreadQueue(op, PrioQueue_High);
   3.150 +	
   3.151 +	this->CatchLateLoadClients(); /* DB reconnection, we should check if we missed anyone... */
   3.152  }
   3.153  
   3.154  void ClientPrefs::DatabaseConnect()
   3.155 @@ -230,19 +232,10 @@
   3.156  
   3.157  	Database = Driver->Connect(DBInfo, true, error, sizeof(error));
   3.158  
   3.159 -	if (Database == NULL &&
   3.160 -		DBInfo != storage_local &&
   3.161 -		storage_local != NULL)
   3.162 -	{
   3.163 -		DBInfo = storage_local;
   3.164 -		Database = Driver->Connect(DBInfo, true, error, sizeof(error));
   3.165 -	}
   3.166 -
   3.167  	if (Database == NULL)
   3.168  	{
   3.169  		g_pSM->LogError(myself, error);
   3.170  		databaseLoading = false;
   3.171 -		ProcessQueryCache();
   3.172  		return;
   3.173  	}
   3.174  
   3.175 @@ -319,87 +312,76 @@
   3.176  
   3.177  	databaseLoading = false;
   3.178  
   3.179 -	ProcessQueryCache();
   3.180 -
   3.181 +	this->ProcessQueryCache();	
   3.182  	return;
   3.183  
   3.184  fatal_fail:
   3.185  	Database->Close();
   3.186  	Database = NULL;
   3.187  	databaseLoading = false;
   3.188 -	ProcessQueryCache();
   3.189  }
   3.190  
   3.191  bool ClientPrefs::AddQueryToQueue( TQueryOp *query )
   3.192  {
   3.193  	queryMutex->Lock();
   3.194 -
   3.195 -	if (Database == NULL && databaseLoading)
   3.196 +	if (Database == NULL)
   3.197  	{
   3.198  		cachedQueries.push_back(query);
   3.199  		queryMutex->Unlock();
   3.200 -		return true;
   3.201 +		return false;
   3.202 +	}
   3.203 +	
   3.204 +	if (!cachedQueries.empty())
   3.205 +	{
   3.206 +		queryMutex->Unlock();
   3.207 +		this->ProcessQueryCache();
   3.208 +	}
   3.209 +	else
   3.210 +	{
   3.211 +		queryMutex->Unlock();
   3.212  	}
   3.213  
   3.214 -	queryMutex->Unlock();
   3.215 -
   3.216 -	if (Database)
   3.217 -	{
   3.218 -		query->SetDatabase(Database);
   3.219 -		dbi->AddToThreadQueue(query, PrioQueue_Normal);
   3.220 -		return true;
   3.221 -	}
   3.222 -
   3.223 -	query->Destroy();
   3.224 -
   3.225 -	/* If Database is NULL and we're not in the loading phase it must have failed - Can't do much */
   3.226 -	return false;
   3.227 +	query->SetDatabase(Database);
   3.228 +	dbi->AddToThreadQueue(query, PrioQueue_Normal);
   3.229 +	return true;
   3.230  }
   3.231  
   3.232  void ClientPrefs::ProcessQueryCache()
   3.233  {
   3.234 -	SourceHook::List<TQueryOp *>::iterator iter;
   3.235 +	if (Database == NULL)
   3.236 +	{
   3.237 +		return;
   3.238 +	}
   3.239  
   3.240  	queryMutex->Lock();
   3.241 -
   3.242 -	iter = cachedQueries.begin();
   3.243 -	
   3.244 -	while (iter != cachedQueries.end())
   3.245 +	TQueryOp *op;
   3.246 +	for (SourceHook::List<TQueryOp *>::iterator iter = cachedQueries.begin(); iter != cachedQueries.end(); iter++)
   3.247  	{
   3.248 -		TQueryOp *op = *iter;
   3.249 -
   3.250 -		if (Database != NULL)
   3.251 -		{
   3.252 -			op->SetDatabase(Database);
   3.253 -			dbi->AddToThreadQueue(op, PrioQueue_Normal);
   3.254 -		}
   3.255 -		else
   3.256 -		{
   3.257 -			op->Destroy();
   3.258 -		}
   3.259 -
   3.260 -		iter++;
   3.261 +		op = *iter;
   3.262 +		op->SetDatabase(Database);
   3.263 +		dbi->AddToThreadQueue(op, PrioQueue_Normal);
   3.264  	}
   3.265  
   3.266  	cachedQueries.clear();
   3.267 -
   3.268  	queryMutex->Unlock();
   3.269  }
   3.270  
   3.271  size_t IsAuthIdConnected(char *authID)
   3.272  {
   3.273  	IGamePlayer *player;
   3.274 -	int maxPlayers = playerhelpers->GetMaxClients();
   3.275 -
   3.276 -	for (int playerIndex = 1; playerIndex <= maxPlayers; playerIndex++)
   3.277 +	const char *authString;
   3.278 +	
   3.279 +	for (int playerIndex = playerhelpers->GetMaxClients()+1; --playerIndex > 0;)
   3.280  	{
   3.281  		player = playerhelpers->GetGamePlayer(playerIndex);
   3.282 -		if (!player || !player->IsConnected())
   3.283 +		if (player == NULL || !player->IsConnected())
   3.284  		{
   3.285  			continue;
   3.286  		}
   3.287 -		const char *authString = player->GetAuthString();
   3.288 -		if (!authString || authString[0] == '\0')
   3.289 +		
   3.290 +		authString = player->GetAuthString();
   3.291 +		
   3.292 +		if (authString == NULL || authString[0] == '\0')
   3.293  		{
   3.294  			continue;
   3.295  		}
   3.296 @@ -412,22 +394,45 @@
   3.297  	return 0;
   3.298  }
   3.299  
   3.300 -size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
   3.301 +void ClientPrefs::CatchLateLoadClients()
   3.302  {
   3.303 -	va_list ap;
   3.304 -	va_start(ap, fmt);
   3.305 -	size_t len = vsnprintf(buffer, maxlength, fmt, ap);
   3.306 -	va_end(ap);
   3.307 +	IGamePlayer *pPlayer;
   3.308 +	for (int i = playerhelpers->GetMaxClients()+1; --i > 0;)
   3.309 +	{
   3.310 +		if (g_CookieManager.AreClientCookiesPening(i) || g_CookieManager.AreClientCookiesCached(i))
   3.311 +		{
   3.312 +			continue;
   3.313 +		}
   3.314 +	
   3.315 +		pPlayer = playerhelpers->GetGamePlayer(i);
   3.316 +
   3.317 +		if (!pPlayer || !pPlayer->IsAuthorized())
   3.318 +		{
   3.319 +			continue;
   3.320 +		}
   3.321  
   3.322 -	if (len >= maxlength)
   3.323 -	{
   3.324 -		buffer[maxlength - 1] = '\0';
   3.325 -		return (maxlength - 1);
   3.326 +		g_CookieManager.OnClientAuthorized(i, pPlayer->GetAuthString());
   3.327  	}
   3.328 -	else
   3.329 +}
   3.330 +
   3.331 +void ClientPrefs::ClearQueryCache(int serial)
   3.332 +{
   3.333 +	queryMutex->Lock();
   3.334 +
   3.335 +	for (SourceHook::List<TQueryOp *>::iterator iter = cachedQueries.begin(); iter != cachedQueries.end();)
   3.336  	{
   3.337 -		return len;
   3.338 -	}
   3.339 +		TQueryOp *op = *iter;
   3.340 +		if (op && op->PullQueryType() == Query_SelectData && op->PullQuerySerial() == serial)
   3.341 + 		{
   3.342 +			op->Destroy();
   3.343 +			iter = cachedQueries.erase(iter);
   3.344 + 		}
   3.345 + 		else
   3.346 + 		{
   3.347 +			iter++;
   3.348 + 		}
   3.349 + 	}
   3.350 +	queryMutex->Unlock();
   3.351  }
   3.352  
   3.353  bool Translate(char *buffer, 
   3.354 @@ -478,6 +483,30 @@
   3.355  	return true;
   3.356  }
   3.357  
   3.358 +char * UTIL_strncpy(char * destination, const char * source, size_t num)
   3.359 +{
   3.360 +	if (source == NULL)
   3.361 +	{
   3.362 +		destination[0] = '\0';
   3.363 +		return destination;
   3.364 +	}
   3.365 +	
   3.366 +	size_t req = strlen(source);
   3.367 +	if (!req)
   3.368 +	{
   3.369 +		destination[0] = '\0';
   3.370 +		return destination;
   3.371 +	}
   3.372 +	else if (req >= num)
   3.373 +	{
   3.374 +		req = num-1;
   3.375 +	}
   3.376 +	
   3.377 +	strncpy(destination, source, req);
   3.378 +	destination[req] = '\0';
   3.379 +	return destination;
   3.380 +}
   3.381 +
   3.382  IdentityToken_t *ClientPrefs::GetIdentity() const
   3.383  {
   3.384  	return identity;
   3.385 @@ -493,3 +522,15 @@
   3.386  	return SM_BUILD_TIMESTAMP;
   3.387  }
   3.388  
   3.389 +ClientPrefs::ClientPrefs()
   3.390 +{
   3.391 +	Driver = NULL;
   3.392 +	Database = NULL;
   3.393 +	databaseLoading = false;
   3.394 +	phrases = NULL;
   3.395 +	DBInfo = NULL;
   3.396 +
   3.397 +	cookieMutex = NULL;
   3.398 +	queryMutex = NULL;
   3.399 +	identity = NULL;
   3.400 +}
     4.1 --- a/extensions/clientprefs/extension.h	Mon Feb 25 20:44:16 2013 -0600
     4.2 +++ b/extensions/clientprefs/extension.h	Thu Feb 28 21:51:49 2013 +0000
     4.3 @@ -38,6 +38,9 @@
     4.4  #include <stdarg.h>
     4.5  #include "smsdk_ext.h"
     4.6  #include "sh_list.h"
     4.7 +
     4.8 +char * UTIL_strncpy(char * destination, const char * source, size_t num);
     4.9 +
    4.10  #include "cookie.h"
    4.11  #include "menus.h"
    4.12  #include "query.h"
    4.13 @@ -59,6 +62,8 @@
    4.14  class ClientPrefs : public SDKExtension
    4.15  {
    4.16  public:
    4.17 +	ClientPrefs();
    4.18 +public:
    4.19  	/**
    4.20  	 * @brief This is called after the initial loading sequence has been processed.
    4.21  	 *
    4.22 @@ -93,6 +98,10 @@
    4.23  
    4.24  	bool AddQueryToQueue(TQueryOp *query);
    4.25  	void ProcessQueryCache();
    4.26 +	
    4.27 +	void AttemptReconnection();
    4.28 +	void CatchLateLoadClients();
    4.29 +	void ClearQueryCache(int serial);
    4.30  
    4.31  	/**
    4.32  	 * @brief Called when the pause state is changed.
    4.33 @@ -145,11 +154,11 @@
    4.34  public:
    4.35  	IDBDriver *Driver;
    4.36  	IDatabase *Database;
    4.37 -	bool databaseLoading;
    4.38  	IPhraseCollection *phrases;
    4.39  	const DatabaseInfo *DBInfo;
    4.40  
    4.41  	IMutex *cookieMutex;
    4.42 +	bool databaseLoading;
    4.43  
    4.44  private:
    4.45  	SourceHook::List<TQueryOp *> cachedQueries;
    4.46 @@ -177,8 +186,6 @@
    4.47  
    4.48  size_t IsAuthIdConnected(char *authID);
    4.49  
    4.50 -size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...);
    4.51 -
    4.52  extern sp_nativeinfo_t g_ClientPrefNatives[];
    4.53  
    4.54  extern ClientPrefs g_ClientPrefs;
     5.1 --- a/extensions/clientprefs/menus.cpp	Mon Feb 25 20:44:16 2013 -0600
     5.2 +++ b/extensions/clientprefs/menus.cpp	Thu Feb 28 21:51:49 2013 +0000
     5.3 @@ -99,7 +99,7 @@
     5.4  	if (data->handler->forward != NULL)
     5.5  	{
     5.6  		char buffer[100];
     5.7 -		UTIL_Format(buffer, sizeof(buffer), "%s", dr.display);
     5.8 +		g_pSM->Format(buffer, sizeof(buffer), "%s", dr.display);
     5.9  
    5.10  		data->handler->forward->PushCell(client);
    5.11  		data->handler->forward->PushCell(CookieMenuAction_DisplayOption);
    5.12 @@ -118,53 +118,15 @@
    5.13  
    5.14  void AutoMenuHandler::OnMenuSelect(SourceMod::IBaseMenu *menu, int client, unsigned int item)
    5.15  {
    5.16 +	static const char settings[CookieMenu_Elements][2][4] = { {"yes", "no"}, {"1", "0"}, {"on", "off"}, {"1", "0"} };
    5.17  	ItemDrawInfo draw;
    5.18  
    5.19  	const char *info = menu->GetItemInfo(item, &draw);
    5.20  
    5.21  	AutoMenuData *data = (AutoMenuData *)strtoul(info, NULL, 16);
    5.22  
    5.23 -	switch (data->type)
    5.24 -	{
    5.25 -	case CookieMenu_YesNo:
    5.26 -		{
    5.27 -			if (item == 0)
    5.28 -			{
    5.29 -				g_CookieManager.SetCookieValue(data->pCookie, client, "yes");
    5.30 -			}
    5.31 -			else
    5.32 -			{
    5.33 -				g_CookieManager.SetCookieValue(data->pCookie, client, "no");
    5.34 -			}
    5.35 -			break;
    5.36 -		}
    5.37 -	case CookieMenu_YesNo_Int:
    5.38 -	case CookieMenu_OnOff_Int:
    5.39 -		{
    5.40 -			if (item == 0)
    5.41 -			{
    5.42 -				g_CookieManager.SetCookieValue(data->pCookie, client, "1");
    5.43 -			}
    5.44 -			else
    5.45 -			{
    5.46 -				g_CookieManager.SetCookieValue(data->pCookie, client, "0");
    5.47 -			}
    5.48 -			break;
    5.49 -		}
    5.50 -	case CookieMenu_OnOff:
    5.51 -		{
    5.52 -			if (item == 0)
    5.53 -			{
    5.54 -				g_CookieManager.SetCookieValue(data->pCookie, client, "on");
    5.55 -			}
    5.56 -			else
    5.57 -			{
    5.58 -				g_CookieManager.SetCookieValue(data->pCookie, client, "off");
    5.59 -			}
    5.60 -			break;
    5.61 -		}
    5.62 -	}
    5.63 -
    5.64 +	g_CookieManager.SetCookieValue(data->pCookie, client, settings[data->type][item]);
    5.65 +	
    5.66  	char message[255];
    5.67  	char *value;
    5.68  	g_CookieManager.GetCookieValue(data->pCookie, client, &value);
     6.1 --- a/extensions/clientprefs/menus.h	Mon Feb 25 20:44:16 2013 -0600
     6.2 +++ b/extensions/clientprefs/menus.h	Thu Feb 28 21:51:49 2013 +0000
     6.3 @@ -59,13 +59,14 @@
     6.4  	CookieMenu_YesNo_Int,		/**< Yes/No menu with 1/0 saved into the cookie */
     6.5  	CookieMenu_OnOff,			/**< On/Off menu with "on"/"off" results saved into the cookie */
     6.6  	CookieMenu_OnOff_Int,		/**< On/Off menu with 1/0 saved into the cookie */
     6.7 +	CookieMenu_Elements
     6.8  };
     6.9  
    6.10  struct ItemHandler
    6.11  {
    6.12 -	bool isAutoMenu;
    6.13  	IChangeableForward *forward;
    6.14  	CookieMenu autoMenuType;
    6.15 +	bool isAutoMenu;
    6.16  };
    6.17  
    6.18  class ClientMenuHandler : public IMenuHandler
    6.19 @@ -96,8 +97,8 @@
    6.20  {
    6.21  	ItemHandler *handler;
    6.22  	Cookie *pCookie;
    6.23 +	cell_t datavalue;
    6.24  	CookieMenu type;
    6.25 -	cell_t datavalue;
    6.26  };
    6.27  
    6.28  #endif // _INCLUDE_SOURCEMOD_CLIENTPREFS_MENUS_H_
     7.1 --- a/extensions/clientprefs/natives.cpp	Mon Feb 25 20:44:16 2013 -0600
     7.2 +++ b/extensions/clientprefs/natives.cpp	Thu Feb 28 21:51:49 2013 +0000
     7.3 @@ -35,10 +35,7 @@
     7.4  
     7.5  cell_t RegClientPrefCookie(IPluginContext *pContext, const cell_t *params)
     7.6  {
     7.7 -	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
     7.8 -	{
     7.9 -		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
    7.10 -	}
    7.11 +	g_ClientPrefs.AttemptReconnection();
    7.12  
    7.13  	char *name;
    7.14  	pContext->LocalToString(params[1], &name);
    7.15 @@ -67,10 +64,7 @@
    7.16  
    7.17  cell_t FindClientPrefCookie(IPluginContext *pContext, const cell_t *params)
    7.18  {
    7.19 -	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
    7.20 -	{
    7.21 -		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
    7.22 -	}
    7.23 +	g_ClientPrefs.AttemptReconnection();
    7.24  
    7.25  	char *name;
    7.26  	pContext->LocalToString(params[1], &name);
    7.27 @@ -91,10 +85,7 @@
    7.28  
    7.29  cell_t SetAuthIdCookie(IPluginContext *pContext, const cell_t *params)
    7.30  {
    7.31 -	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
    7.32 -	{
    7.33 -		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
    7.34 -	}
    7.35 +	g_ClientPrefs.AttemptReconnection();
    7.36  
    7.37  	char *steamID;
    7.38  	pContext->LocalToString(params[1], &steamID);
    7.39 @@ -136,8 +127,7 @@
    7.40  	// edit database table
    7.41  	TQueryOp *op = new TQueryOp(Query_InsertData, pCookie);
    7.42  	// limit player auth length which doubles for cookie name length
    7.43 -	strncpy(op->m_params.steamId, steamID, MAX_NAME_LENGTH);
    7.44 -	op->m_params.steamId[MAX_NAME_LENGTH-1] = '\0';
    7.45 +	UTIL_strncpy(op->m_params.steamId, steamID, MAX_NAME_LENGTH);
    7.46  	op->m_params.cookieId = i_dbId;
    7.47  	op->m_params.data = payload;
    7.48  
    7.49 @@ -148,10 +138,7 @@
    7.50  
    7.51  cell_t SetClientPrefCookie(IPluginContext *pContext, const cell_t *params)
    7.52  {
    7.53 -	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
    7.54 -	{
    7.55 -		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
    7.56 -	}
    7.57 +	g_ClientPrefs.AttemptReconnection();
    7.58  
    7.59  	int client = params[1];
    7.60  
    7.61 @@ -183,10 +170,7 @@
    7.62  
    7.63  cell_t GetClientPrefCookie(IPluginContext *pContext, const cell_t *params)
    7.64  {
    7.65 -	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
    7.66 -	{
    7.67 -		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
    7.68 -	}
    7.69 +	g_ClientPrefs.AttemptReconnection();
    7.70  
    7.71  	int client = params[1];
    7.72  
    7.73 @@ -221,10 +205,7 @@
    7.74  
    7.75  cell_t AreClientCookiesCached(IPluginContext *pContext, const cell_t *params)
    7.76  {
    7.77 -	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
    7.78 -	{
    7.79 -		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
    7.80 -	}
    7.81 +	g_ClientPrefs.AttemptReconnection();
    7.82  
    7.83  	int client = params[1];
    7.84  
    7.85 @@ -238,10 +219,7 @@
    7.86  
    7.87  cell_t GetCookieAccess(IPluginContext *pContext, const cell_t *params)
    7.88  {
    7.89 -	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
    7.90 -	{
    7.91 -		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
    7.92 -	}
    7.93 +	g_ClientPrefs.AttemptReconnection();
    7.94  
    7.95  	Handle_t hndl = static_cast<Handle_t>(params[1]);
    7.96  	HandleError err;
    7.97 @@ -263,10 +241,7 @@
    7.98  
    7.99  static cell_t GetCookieIterator(IPluginContext *pContext, const cell_t *params)
   7.100  {
   7.101 -	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
   7.102 -	{
   7.103 -		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
   7.104 -	}
   7.105 +	g_ClientPrefs.AttemptReconnection();
   7.106  
   7.107  	SourceHook::List<Cookie *>::iterator *iter = new SourceHook::List<Cookie *>::iterator;
   7.108  	*iter = g_CookieManager.cookieList.begin();
   7.109 @@ -282,10 +257,7 @@
   7.110  
   7.111  static cell_t ReadCookieIterator(IPluginContext *pContext, const cell_t *params)
   7.112  {
   7.113 -	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
   7.114 -	{
   7.115 -		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
   7.116 -	}
   7.117 +	g_ClientPrefs.AttemptReconnection();
   7.118  
   7.119  	SourceHook::List<Cookie *>::iterator *iter;
   7.120  
   7.121 @@ -323,10 +295,7 @@
   7.122  
   7.123  cell_t ShowSettingsMenu(IPluginContext *pContext, const cell_t *params)
   7.124  {
   7.125 -	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
   7.126 -	{
   7.127 -		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
   7.128 -	}
   7.129 +	g_ClientPrefs.AttemptReconnection();
   7.130  
   7.131  	char message[256];
   7.132  	Translate(message, sizeof(message), "%T:", 2, NULL, "Client Settings", &params[1]);
   7.133 @@ -339,10 +308,7 @@
   7.134  
   7.135  cell_t AddSettingsMenuItem(IPluginContext *pContext, const cell_t *params)
   7.136  {
   7.137 -	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
   7.138 -	{
   7.139 -		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
   7.140 -	}
   7.141 +	g_ClientPrefs.AttemptReconnection();
   7.142  
   7.143  	char *display;
   7.144  	pContext->LocalToString(params[3], &display);
   7.145 @@ -358,7 +324,7 @@
   7.146  	AutoMenuData *data = new AutoMenuData;
   7.147  	data->datavalue = params[2];
   7.148  	data->handler = pItem;
   7.149 -	UTIL_Format(info, sizeof(info), "%x", data);
   7.150 +	g_pSM->Format(info, sizeof(info), "%x", data);
   7.151  
   7.152  	ItemDrawInfo draw(display, 0);
   7.153  
   7.154 @@ -376,7 +342,7 @@
   7.155  	}
   7.156  
   7.157  	char *copyarray = new char[strlen(display)+1];
   7.158 -	UTIL_Format(copyarray, strlen(display)+1, "%s", display);
   7.159 +	g_pSM->Format(copyarray, strlen(display)+1, "%s", display);
   7.160  
   7.161  	pList->push_back(copyarray);
   7.162  
   7.163 @@ -385,10 +351,7 @@
   7.164  
   7.165  cell_t AddSettingsPrefabMenuItem(IPluginContext *pContext, const cell_t *params)
   7.166  {
   7.167 -	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
   7.168 -	{
   7.169 -		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
   7.170 -	}
   7.171 +	g_ClientPrefs.AttemptReconnection();
   7.172  
   7.173  	Handle_t hndl = static_cast<Handle_t>(params[1]);
   7.174  	HandleError err;
   7.175 @@ -433,7 +396,7 @@
   7.176  	data->pCookie = pCookie;
   7.177  	data->type = (CookieMenu)params[2];
   7.178  	data->handler = pItem;
   7.179 -	UTIL_Format(info, sizeof(info), "%x", data);
   7.180 +	g_pSM->Format(info, sizeof(info), "%x", data);
   7.181  
   7.182  	g_CookieManager.clientMenu->AppendItem(info, draw);
   7.183  
   7.184 @@ -449,7 +412,7 @@
   7.185  	}
   7.186  
   7.187  	char *copyarray = new char[strlen(display)+1];
   7.188 -	UTIL_Format(copyarray, strlen(display)+1, "%s", display);
   7.189 +	g_pSM->Format(copyarray, strlen(display)+1, "%s", display);
   7.190  
   7.191  	pList->push_back(copyarray);
   7.192  
   7.193 @@ -458,10 +421,7 @@
   7.194  
   7.195  cell_t GetClientCookieTime(IPluginContext *pContext, const cell_t *params)
   7.196  {
   7.197 -	if (g_ClientPrefs.Database == NULL && !g_ClientPrefs.databaseLoading)
   7.198 -	{
   7.199 -		return pContext->ThrowNativeError("Clientprefs is disabled due to a failed database connection");
   7.200 -	}
   7.201 +	g_ClientPrefs.AttemptReconnection();
   7.202  
   7.203  	Handle_t hndl = static_cast<Handle_t>(params[2]);
   7.204  	HandleError err;
     8.1 --- a/extensions/clientprefs/query.cpp	Mon Feb 25 20:44:16 2013 -0600
     8.2 +++ b/extensions/clientprefs/query.cpp	Thu Feb 28 21:51:49 2013 +0000
     8.3 @@ -35,12 +35,6 @@
     8.4  void TQueryOp::RunThinkPart()
     8.5  {
     8.6  	//handler for threaded sql queries
     8.7 -
     8.8 -	if (m_type == Query_Connect)
     8.9 -	{
    8.10 -		return;
    8.11 -	}
    8.12 -
    8.13  	switch (m_type)
    8.14  	{
    8.15  		case Query_InsertCookie:
    8.16 @@ -61,6 +55,11 @@
    8.17  			break;
    8.18  		}
    8.19  
    8.20 +		case Query_Connect:
    8.21 +		{
    8.22 +			return;
    8.23 +		}
    8.24 +		
    8.25  		default:
    8.26  		{
    8.27  			break;
    8.28 @@ -73,31 +72,26 @@
    8.29  	if (m_type == Query_Connect)
    8.30  	{
    8.31  		g_ClientPrefs.DatabaseConnect();
    8.32 +		return;
    8.33  	}
    8.34 -	else
    8.35 -	{
    8.36 -		assert(m_database != NULL);
    8.37 -
    8.38 -		/* I don't think this is needed anymore... keeping for now. */
    8.39 -		m_database->LockForFullAtomicOperation();
    8.40 -
    8.41 +	
    8.42 +	assert(m_database != NULL);
    8.43 +	/* I don't think this is needed anymore... keeping for now. */
    8.44 +	m_database->LockForFullAtomicOperation();
    8.45  		if (!BindParamsAndRun())
    8.46 -		{
    8.47 -			g_pSM->LogError(myself, 
    8.48 -							"Failed SQL Query, Error: \"%s\" (Query id %i - serial %i)", 
    8.49 -							m_database->GetError(),
    8.50 -							m_type, 
    8.51 -							m_serial);
    8.52 -		}
    8.53 +	{
    8.54 +		g_pSM->LogError(myself, 
    8.55 +						"Failed SQL Query, Error: \"%s\" (Query id %i - serial %i)", 
    8.56 +						m_database->GetError(),
    8.57 +						m_type, 
    8.58 +						m_serial);
    8.59 +	}
    8.60  
    8.61 -		m_database->UnlockFromFullAtomicOperation();
    8.62 -	}
    8.63 +	m_database->UnlockFromFullAtomicOperation();
    8.64  }
    8.65  
    8.66  IDBDriver *TQueryOp::GetDriver()
    8.67  {
    8.68 -	assert(m_database != NULL);
    8.69 -
    8.70  	return m_database->GetDriver();
    8.71  }
    8.72  
    8.73 @@ -131,6 +125,7 @@
    8.74  	m_database = NULL;
    8.75  	m_insertId = -1;
    8.76  	m_pResult = NULL;
    8.77 +	m_serial = 0;
    8.78  }
    8.79  
    8.80  void TQueryOp::SetDatabase(IDatabase *db)
    8.81 @@ -162,7 +157,7 @@
    8.82  
    8.83  			if (g_DriverType == Driver_MySQL)
    8.84  			{
    8.85 -				UTIL_Format(query,
    8.86 +				g_pSM->Format(query,
    8.87  					sizeof(query),
    8.88  					"INSERT IGNORE INTO sm_cookies (name, description, access) \
    8.89  					 VALUES (\"%s\", \"%s\", %d)",
    8.90 @@ -172,7 +167,7 @@
    8.91  			}
    8.92  			else if (g_DriverType == Driver_SQLite)
    8.93  			{
    8.94 -				UTIL_Format(query,
    8.95 +				g_pSM->Format(query,
    8.96  					sizeof(query),
    8.97  					"INSERT OR IGNORE INTO sm_cookies (name, description, access) \
    8.98  					 VALUES ('%s', '%s', %d)",
    8.99 @@ -197,7 +192,7 @@
   8.100  
   8.101  			m_database->QuoteString(m_params.steamId, safe_str, sizeof(safe_str), &ignore);
   8.102  
   8.103 -			UTIL_Format(query,
   8.104 +			g_pSM->Format(query,
   8.105  				sizeof(query),
   8.106  				"SELECT sm_cookies.name, sm_cookie_cache.value, sm_cookies.description, \
   8.107  						sm_cookies.access, sm_cookie_cache.timestamp 	\
   8.108 @@ -228,7 +223,7 @@
   8.109  
   8.110  			if (g_DriverType == Driver_MySQL)
   8.111  			{
   8.112 -				UTIL_Format(query, 
   8.113 +				g_pSM->Format(query, 
   8.114  					sizeof(query),
   8.115  					"INSERT INTO sm_cookie_cache (player, cookie_id, value, timestamp) 	\
   8.116  					 VALUES (\"%s\", %d, \"%s\", %d)									\
   8.117 @@ -243,7 +238,7 @@
   8.118  			}
   8.119  			else if (g_DriverType == Driver_SQLite)
   8.120  			{
   8.121 -				UTIL_Format(query,
   8.122 +				g_pSM->Format(query,
   8.123  					sizeof(query),
   8.124  					"INSERT OR REPLACE INTO sm_cookie_cache						\
   8.125  					 (player, cookie_id, value, timestamp)						\
   8.126 @@ -274,7 +269,7 @@
   8.127  				sizeof(safe_name),
   8.128  				&ignore);
   8.129  
   8.130 -			UTIL_Format(query, 
   8.131 +			g_pSM->Format(query, 
   8.132  				sizeof(query),
   8.133  				"SELECT id FROM sm_cookies WHERE name = '%s'",
   8.134  				safe_name);
   8.135 @@ -296,6 +291,16 @@
   8.136  	return false;
   8.137  }
   8.138  
   8.139 +querytype TQueryOp::PullQueryType()
   8.140 +{
   8.141 +	return m_type;
   8.142 +}
   8.143 +
   8.144 +int TQueryOp::PullQuerySerial()
   8.145 +{
   8.146 +	return m_serial;
   8.147 +}
   8.148 +
   8.149  ParamData::~ParamData()
   8.150  {
   8.151  	if (cookie)
   8.152 @@ -309,8 +314,10 @@
   8.153  			delete cookie;
   8.154  			cookie = NULL;
   8.155  		}
   8.156 -
   8.157 -		g_ClientPrefs.cookieMutex->Unlock();	
   8.158 +		else
   8.159 +		{
   8.160 +			g_ClientPrefs.cookieMutex->Unlock();
   8.161 +		}
   8.162  	}
   8.163  
   8.164  	if (data)
     9.1 --- a/extensions/clientprefs/query.h	Mon Feb 25 20:44:16 2013 -0600
     9.2 +++ b/extensions/clientprefs/query.h	Thu Feb 28 21:51:49 2013 +0000
     9.3 @@ -93,6 +93,10 @@
     9.4  	{
     9.5  		return m_database;
     9.6  	}
     9.7 +	
     9.8 +public:
     9.9 +	querytype PullQueryType();
    9.10 +	int PullQuerySerial();
    9.11  
    9.12  private:
    9.13  	IDatabase *m_database;