PageRenderTime 54ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/mani_admin_plugin/mani_mysql.cpp

http://maniadminplugin.googlecode.com/
C++ | 384 lines | 279 code | 51 blank | 54 comment | 53 complexity | 79ed6d715395b602e4e7e845a8f3feba MD5 | raw file
Possible License(s): GPL-3.0
  1. //
  2. // Mani Admin Plugin
  3. //
  4. // Copyright Š 2009-2014 Giles Millward (Mani). All rights reserved.
  5. //
  6. // This file is part of ManiAdminPlugin.
  7. //
  8. // Mani Admin Plugin is free software: you can redistribute it and/or modify
  9. // it under the terms of the GNU General Public License as published by
  10. // the Free Software Foundation, either version 3 of the License, or
  11. // (at your option) any later version.
  12. //
  13. // Mani Admin Plugin is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. // GNU General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU General Public License
  19. // along with Mani Admin Plugin. If not, see <http://www.gnu.org/licenses/>.
  20. //
  21. //
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <math.h>
  26. #include <time.h>
  27. #ifndef __linux__
  28. #include <winsock.h>
  29. #else
  30. #include <pthread.h>
  31. #include <errno.h>
  32. #endif
  33. #include <mysql.h>
  34. #include <mysqld_error.h>
  35. #include "interface.h"
  36. #include "filesystem.h"
  37. #include "engine/iserverplugin.h"
  38. #include "iplayerinfo.h"
  39. #include "eiface.h"
  40. #include "igameevents.h"
  41. #include "mrecipientfilter.h"
  42. #include "bitbuf.h"
  43. #include "engine/IEngineSound.h"
  44. #include "inetchannelinfo.h"
  45. #include "networkstringtabledefs.h"
  46. #include "mani_timers.h"
  47. #include "mani_main.h"
  48. #include "mani_convar.h"
  49. #include "mani_memory.h"
  50. #include "mani_output.h"
  51. #include "mani_database.h"
  52. #include "mani_mysql.h"
  53. #include "KeyValues.h"
  54. #include "cbaseentity.h"
  55. extern IVEngineServer *engine; // helper functions (messaging clients, loading content, making entities, running commands, etc)
  56. extern IFileSystem *filesystem;
  57. extern IServerGameDLL *serverdll;
  58. extern CGlobalVars *gpGlobals;
  59. extern int max_players;
  60. extern bool war_mode;
  61. inline bool FStruEq(const char *sz1, const char *sz2)
  62. {
  63. return(Q_strcmp(sz1, sz2) == 0);
  64. }
  65. ManiMySQL::ManiMySQL()
  66. {
  67. // Init
  68. my_data = NULL;
  69. res_ptr = NULL;
  70. fd = NULL;
  71. row = NULL;
  72. strcpy(sql_server_version, "");
  73. major = minor = issue = 0;
  74. }
  75. ManiMySQL::~ManiMySQL()
  76. {
  77. // Cleanup
  78. if (res_ptr) mysql_free_result( res_ptr ) ;
  79. if (my_data) mysql_close( my_data ) ;
  80. my_data = NULL;
  81. res_ptr = NULL;
  82. }
  83. //---------------------------------------------------------------------------------
  84. // Purpose: Create a connection to a database
  85. //---------------------------------------------------------------------------------
  86. bool ManiMySQL::Init(player_t *player_ptr)
  87. {
  88. static unsigned int timeout;
  89. bool connection_failed = false;
  90. bool tried_connection = false;
  91. timeout = gpManiDatabase->GetDBTimeout();
  92. if (res_ptr)
  93. {
  94. mysql_free_result( res_ptr ) ;
  95. res_ptr = NULL;
  96. }
  97. if (my_data)
  98. {
  99. mysql_close( my_data ) ;
  100. my_data = NULL;
  101. }
  102. if ((my_data = mysql_init((MYSQL*) 0)) == NULL)
  103. {
  104. OutputHelpText(ORANGE_CHAT, player_ptr, "Failed to init database!");
  105. return false;
  106. }
  107. if (mysql_options(my_data, MYSQL_OPT_CONNECT_TIMEOUT, (char *) &timeout))
  108. {
  109. OutputHelpText(ORANGE_CHAT, player_ptr, "mysql_options failed!");
  110. OutputHelpText(ORANGE_CHAT, player_ptr, "%s", mysql_error(my_data));
  111. }
  112. // Linux only !!
  113. #ifdef __linux__
  114. if (FStrEq(gpManiDatabase->GetDBHost(), "localhost") ||
  115. FStrEq(gpManiDatabase->GetDBHost(), "127.0.0.1"))
  116. {
  117. if (gpManiDatabase->GetDBSocketPath() &&
  118. !FStrEq(gpManiDatabase->GetDBSocketPath(), ""))
  119. {
  120. tried_connection = true;
  121. if (mysql_real_connect
  122. (
  123. my_data,
  124. gpManiDatabase->GetDBHost(),
  125. gpManiDatabase->GetDBUser(),
  126. gpManiDatabase->GetDBPassword(),
  127. gpManiDatabase->GetDBName(),
  128. gpManiDatabase->GetDBPort(),
  129. gpManiDatabase->GetDBSocketPath(),
  130. 0 ) == NULL)
  131. {
  132. connection_failed = true;
  133. }
  134. }
  135. }
  136. #endif
  137. // Only if not tried connection yet !!
  138. if (!tried_connection)
  139. {
  140. if (mysql_real_connect
  141. (
  142. my_data,
  143. gpManiDatabase->GetDBHost(),
  144. gpManiDatabase->GetDBUser(),
  145. gpManiDatabase->GetDBPassword(),
  146. gpManiDatabase->GetDBName(),
  147. gpManiDatabase->GetDBPort(),
  148. NULL,
  149. 0 ) == NULL)
  150. {
  151. connection_failed = true;
  152. }
  153. }
  154. if (connection_failed)
  155. {
  156. error_code = mysql_errno(my_data);
  157. OutputHelpText(ORANGE_CHAT, player_ptr, "mysql_real_connect failed!") ;
  158. OutputHelpText(ORANGE_CHAT, player_ptr, "%s", mysql_error(my_data));
  159. mysql_close( my_data ) ;
  160. my_data = NULL;
  161. return false;
  162. }
  163. if ( mysql_select_db( my_data, gpManiDatabase->GetDBName()) != 0 )
  164. {
  165. error_code = mysql_errno(my_data);
  166. OutputHelpText(ORANGE_CHAT, player_ptr, "Can't select the %s database!", gpManiDatabase->GetDBName() ) ;
  167. OutputHelpText(ORANGE_CHAT, player_ptr, "%s", mysql_error(my_data));
  168. mysql_close( my_data ) ;
  169. my_data = NULL;
  170. return false;
  171. }
  172. return true;
  173. }
  174. //---------------------------------------------------------------------------------
  175. // Purpose: Execute a query
  176. //---------------------------------------------------------------------------------
  177. bool ManiMySQL::ExecuteQuery
  178. (
  179. player_t *player_ptr,
  180. int *row_count,
  181. char *sql_query,
  182. ...
  183. )
  184. {
  185. *row_count = 0;
  186. if (res_ptr)
  187. {
  188. mysql_free_result( res_ptr ) ;
  189. res_ptr = NULL;
  190. }
  191. va_list argptr;
  192. char temp_string[4096];
  193. va_start ( argptr, sql_query );
  194. vsnprintf( temp_string, sizeof(temp_string), sql_query, argptr );
  195. va_end ( argptr );
  196. if (mysql_query( my_data, temp_string ) != 0)
  197. {
  198. error_code = mysql_errno(my_data);
  199. OutputHelpText(ORANGE_CHAT, player_ptr, "sql [%s] failed", temp_string ) ;
  200. OutputHelpText(ORANGE_CHAT, player_ptr, "error %i", mysql_errno(my_data));
  201. OutputHelpText(ORANGE_CHAT, player_ptr, "%s", mysql_error(my_data));
  202. mysql_close( my_data ) ;
  203. my_data = NULL;
  204. return false;
  205. }
  206. res_ptr = mysql_store_result( my_data );
  207. if (res_ptr)
  208. {
  209. *row_count = (int) mysql_num_rows( res_ptr );
  210. }
  211. else
  212. {
  213. *row_count = -1;
  214. }
  215. return true;
  216. }
  217. //---------------------------------------------------------------------------------
  218. // Purpose: Execute a query
  219. //---------------------------------------------------------------------------------
  220. bool ManiMySQL::ExecuteQuery
  221. (
  222. player_t *player_ptr,
  223. char *sql_query,
  224. ...
  225. )
  226. {
  227. if (res_ptr)
  228. {
  229. mysql_free_result( res_ptr ) ;
  230. res_ptr = NULL;
  231. }
  232. va_list argptr;
  233. char temp_string[4096];
  234. va_start ( argptr, sql_query );
  235. vsnprintf( temp_string, sizeof(temp_string), sql_query, argptr );
  236. va_end ( argptr );
  237. if (mysql_query( my_data, temp_string ) != 0)
  238. {
  239. error_code = mysql_errno(my_data);
  240. OutputHelpText(ORANGE_CHAT, player_ptr, "sql [%s] failed", temp_string ) ;
  241. OutputHelpText(ORANGE_CHAT, player_ptr, "error %i", mysql_errno(my_data));
  242. OutputHelpText(ORANGE_CHAT, player_ptr, "%s", mysql_error(my_data));
  243. mysql_close( my_data ) ;
  244. my_data = NULL;
  245. return false;
  246. }
  247. res_ptr = mysql_store_result( my_data );
  248. return true;
  249. }
  250. //---------------------------------------------------------------------------------
  251. // Purpose: Fetch row into row (char **)
  252. //---------------------------------------------------------------------------------
  253. bool ManiMySQL::FetchRow(void)
  254. {
  255. row = mysql_fetch_row(res_ptr);
  256. if (row == NULL) return false;
  257. return true;
  258. }
  259. //---------------------------------------------------------------------------------
  260. // Purpose: Get row id (after auto increment insert
  261. //---------------------------------------------------------------------------------
  262. int ManiMySQL::GetRowID(void)
  263. {
  264. return (int) mysql_insert_id(my_data);
  265. }
  266. //---------------------------------------------------------------------------------
  267. // Purpose: Get sql server version
  268. //---------------------------------------------------------------------------------
  269. char *ManiMySQL::GetServerVersion(void)
  270. {
  271. if (strcmp(sql_server_version,"") == 0)
  272. {
  273. Q_strcpy(sql_server_version, mysql_get_server_info(my_data));
  274. if (strcmp(sql_server_version, "") != 0)
  275. {
  276. int i = 0;
  277. int j = 0;
  278. char buffer[32];
  279. while (sql_server_version[i] != '.')
  280. {
  281. buffer[j++] = sql_server_version[i++];
  282. }
  283. buffer[j] = '\0';
  284. i++;
  285. major = atoi(buffer);
  286. j = 0;
  287. while (sql_server_version[i] != '.')
  288. {
  289. buffer[j++] = sql_server_version[i++];
  290. }
  291. buffer[j] = '\0';
  292. i++;
  293. minor = atoi(buffer);
  294. j = 0;
  295. // We add isdigit here because sometimes they like to do things like
  296. // '5.0.24-standard'
  297. while (sql_server_version[i] != '\0' && isdigit(sql_server_version[i]) != 0)
  298. {
  299. buffer[j++] = sql_server_version[i++];
  300. }
  301. buffer[j] = '\0';
  302. issue = atoi(buffer);
  303. }
  304. }
  305. return sql_server_version;
  306. }
  307. //---------------------------------------------------------------------------------
  308. // Purpose: Check if version higher than passed in version
  309. //---------------------------------------------------------------------------------
  310. bool ManiMySQL::IsHigherVer(int maj, int min, int iss)
  311. {
  312. if (major > maj) return true;
  313. if (major == maj && minor > min) return true;
  314. if (major == maj && minor == min && issue > iss) return true;
  315. return false;
  316. }
  317. //---------------------------------------------------------------------------------
  318. // Purpose: Check if version higher than passed in version
  319. //---------------------------------------------------------------------------------
  320. bool ManiMySQL::IsHigherVer(int maj, int min)
  321. {
  322. if (major > maj) return true;
  323. if (major == maj && minor > min) return true;
  324. return false;
  325. }
  326. //---------------------------------------------------------------------------------
  327. // Purpose: Check if version higher than passed in version
  328. //---------------------------------------------------------------------------------
  329. bool ManiMySQL::IsHigherVer(int maj)
  330. {
  331. if (major > maj) return true;
  332. return false;
  333. }