extensions/clientprefs/query.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Thu Jul 04 11:28:32 2013 -0400 (2013-07-04)
changeset 3931 576fa42454dc
parent 3804 90159516acd3
child 4029 cf8bdfcf6503
permissions -rw-r--r--
Fixed build for real.
     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 "query.h"
    33 
    34 
    35 void TQueryOp::RunThinkPart()
    36 {
    37 	//handler for threaded sql queries
    38 	switch (m_type)
    39 	{
    40 		case Query_InsertCookie:
    41 		{
    42 			g_CookieManager.InsertCookieCallback(m_pCookie, m_insertId);
    43 			break;
    44 		}
    45 
    46 		case Query_SelectData:
    47 		{
    48 			g_CookieManager.ClientConnectCallback(m_serial, m_pResult);
    49 			break;
    50 		}
    51 
    52 		case Query_SelectId:
    53 		{
    54 			g_CookieManager.SelectIdCallback(m_pCookie, m_pResult);
    55 			break;
    56 		}
    57 
    58 		case Query_Connect:
    59 		{
    60 			return;
    61 		}
    62 		
    63 		default:
    64 		{
    65 			break;
    66 		}
    67 	}
    68 }
    69 
    70 void TQueryOp::RunThreadPart()
    71 {
    72 	if (m_type == Query_Connect)
    73 	{
    74 		g_ClientPrefs.DatabaseConnect();
    75 		return;
    76 	}
    77 	
    78 	assert(m_database != NULL);
    79 	/* I don't think this is needed anymore... keeping for now. */
    80 	m_database->LockForFullAtomicOperation();
    81 		if (!BindParamsAndRun())
    82 	{
    83 		g_pSM->LogError(myself, 
    84 						"Failed SQL Query, Error: \"%s\" (Query id %i - serial %i)", 
    85 						m_database->GetError(),
    86 						m_type, 
    87 						m_serial);
    88 	}
    89 
    90 	m_database->UnlockFromFullAtomicOperation();
    91 }
    92 
    93 IDBDriver *TQueryOp::GetDriver()
    94 {
    95 	return m_database->GetDriver();
    96 }
    97 
    98 IdentityToken_t *TQueryOp::GetOwner()
    99 {
   100 	return myself->GetIdentity();
   101 }
   102 
   103 void TQueryOp::Destroy()
   104 {
   105 	if (m_pResult != NULL)
   106 	{
   107 		m_pResult->Destroy();
   108 	}
   109 	delete this;
   110 }
   111 
   112 TQueryOp::TQueryOp(enum querytype type, int serial)
   113 {
   114 	m_type = type;
   115 	m_serial = serial;
   116 	m_database = NULL;
   117 	m_insertId = -1;
   118 	m_pResult = NULL;
   119 }
   120 
   121 TQueryOp::TQueryOp(enum querytype type, Cookie *cookie)
   122 {
   123 	m_type = type;
   124 	m_pCookie = cookie;
   125 	m_database = NULL;
   126 	m_insertId = -1;
   127 	m_pResult = NULL;
   128 	m_serial = 0;
   129 }
   130 
   131 void TQueryOp::SetDatabase(IDatabase *db)
   132 {
   133 	m_database = db;
   134 	m_database->IncReferenceCount();
   135 }
   136 
   137 bool TQueryOp::BindParamsAndRun()
   138 {
   139 	size_t ignore;
   140 	char query[2048];
   141 
   142 	switch (m_type)
   143 	{
   144 		case Query_InsertCookie:
   145 		{
   146 			char safe_name[MAX_NAME_LENGTH*2 + 1];
   147 			char safe_desc[MAX_DESC_LENGTH*2 + 1];
   148 			
   149 			m_database->QuoteString(m_params.cookie->name, 
   150 				safe_name, 
   151 				sizeof(safe_name),
   152 				&ignore);
   153 			m_database->QuoteString(m_params.cookie->description,
   154 				safe_desc,
   155 				sizeof(safe_desc),
   156 				&ignore);
   157 
   158 			if (g_DriverType == Driver_MySQL)
   159 			{
   160 				g_pSM->Format(query,
   161 					sizeof(query),
   162 					"INSERT IGNORE INTO sm_cookies (name, description, access) \
   163 					 VALUES (\"%s\", \"%s\", %d)",
   164 					safe_name,
   165 					safe_desc,
   166 					m_params.cookie->access);
   167 			}
   168 			else if (g_DriverType == Driver_SQLite)
   169 			{
   170 				g_pSM->Format(query,
   171 					sizeof(query),
   172 					"INSERT OR IGNORE INTO sm_cookies (name, description, access) \
   173 					 VALUES ('%s', '%s', %d)",
   174 					 safe_name,
   175 					 safe_desc,
   176 					 m_params.cookie->access);
   177 			}
   178 
   179 			if (!m_database->DoSimpleQuery(query))
   180 			{
   181 				return false;
   182 			}
   183 
   184 			m_insertId = m_database->GetInsertID();
   185 
   186 			return true;
   187 		}
   188 
   189 		case Query_SelectData:
   190 		{
   191 			char safe_str[128];
   192 
   193 			m_database->QuoteString(m_params.steamId, safe_str, sizeof(safe_str), &ignore);
   194 
   195 			g_pSM->Format(query,
   196 				sizeof(query),
   197 				"SELECT sm_cookies.name, sm_cookie_cache.value, sm_cookies.description, \
   198 						sm_cookies.access, sm_cookie_cache.timestamp 	\
   199 				FROM sm_cookies				\
   200 				JOIN sm_cookie_cache		\
   201 				ON sm_cookies.id = sm_cookie_cache.cookie_id \
   202 				WHERE player = '%s'",
   203 				safe_str);
   204 
   205 			m_pResult = m_database->DoQuery(query);
   206 
   207 			return (m_pResult != NULL);
   208 		}
   209 
   210 		case Query_InsertData:
   211 		{
   212 			char safe_id[128];
   213 			char safe_val[MAX_VALUE_LENGTH*2 + 1];
   214 
   215 			m_database->QuoteString(m_params.steamId,
   216 				safe_id,
   217 				sizeof(safe_id),
   218 				&ignore);
   219 			m_database->QuoteString(m_params.data->value,
   220 				safe_val,
   221 				sizeof(safe_val),
   222 				&ignore);
   223 
   224 			if (g_DriverType == Driver_MySQL)
   225 			{
   226 				g_pSM->Format(query, 
   227 					sizeof(query),
   228 					"INSERT INTO sm_cookie_cache (player, cookie_id, value, timestamp) 	\
   229 					 VALUES (\"%s\", %d, \"%s\", %d)									\
   230 					 ON DUPLICATE KEY UPDATE											\
   231 					 value = \"%s\", timestamp = %d",
   232 					safe_id,
   233 					m_params.cookieId,
   234 					safe_val,
   235 					(unsigned int)m_params.data->timestamp,
   236 					safe_val,
   237 					(unsigned int)m_params.data->timestamp);
   238 			}
   239 			else if (g_DriverType == Driver_SQLite)
   240 			{
   241 				g_pSM->Format(query,
   242 					sizeof(query),
   243 					"INSERT OR REPLACE INTO sm_cookie_cache						\
   244 					 (player, cookie_id, value, timestamp)						\
   245 					 VALUES ('%s', %d, '%s', %d)",
   246 					safe_id,
   247 					m_params.cookieId,
   248 					safe_val,
   249 					(unsigned int)m_params.data->timestamp);
   250 			}
   251 
   252 			if (!m_database->DoSimpleQuery(query))
   253 			{
   254 				return false;
   255 			}
   256 
   257 			m_insertId = m_database->GetInsertID();
   258 
   259 			return true;
   260 		}
   261 
   262 		case Query_SelectId:
   263 		{
   264 			char safe_name[MAX_NAME_LENGTH*2 + 1];
   265 
   266 			/* the steamId var was actually used to store the name of the cookie - Save duplicating vars */
   267 			m_database->QuoteString(m_params.steamId, 
   268 				safe_name,
   269 				sizeof(safe_name),
   270 				&ignore);
   271 
   272 			g_pSM->Format(query, 
   273 				sizeof(query),
   274 				"SELECT id FROM sm_cookies WHERE name = '%s'",
   275 				safe_name);
   276 
   277 			m_pResult = m_database->DoQuery(query);
   278 
   279 			return (m_pResult != NULL);
   280 		}
   281 
   282 		default:
   283 		{
   284 			break;
   285 		}
   286 			
   287 	}
   288 
   289 	assert(false);
   290 
   291 	return false;
   292 }
   293 
   294 querytype TQueryOp::PullQueryType()
   295 {
   296 	return m_type;
   297 }
   298 
   299 int TQueryOp::PullQuerySerial()
   300 {
   301 	return m_serial;
   302 }
   303 
   304 ParamData::~ParamData()
   305 {
   306 	if (cookie)
   307 	{
   308 		g_ClientPrefs.cookieMutex->Lock();
   309 		cookie->usedInQuery--;
   310 
   311 		if (cookie->shouldDelete && cookie->usedInQuery <= 0)
   312 		{
   313 			g_ClientPrefs.cookieMutex->Unlock();
   314 			delete cookie;
   315 			cookie = NULL;
   316 		}
   317 		else
   318 		{
   319 			g_ClientPrefs.cookieMutex->Unlock();
   320 		}
   321 	}
   322 
   323 	if (data)
   324 	{
   325 		/* Data is only ever passed in a client disconnect query and always needs to be deleted */
   326 		delete data;
   327 		data = NULL;
   328 	}
   329 }
   330 
   331 ParamData::ParamData()
   332 {
   333 	cookie = NULL;
   334 	data = NULL;
   335 	steamId[0] = '\0';
   336 	cookieId = 0;
   337 }
   338