Advertisement
Guest User

Untitled

a guest
Dec 7th, 2016
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.96 KB | None | 0 0
  1. // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3.  
  4. #include "../common/malloc.h"
  5. #include "../common/mmo.h"
  6. #include "../common/showmsg.h"
  7. #include "../common/sql.h"
  8. #include "../common/strlib.h"
  9. #include "../common/timer.h"
  10. #include "account.h"
  11. #include <stdlib.h>
  12. #include <string.h>
  13.  
  14. /// global defines
  15. #define ACCOUNT_SQL_DB_VERSION 20080417
  16.  
  17. /// internal structure
  18. typedef struct AccountDB_SQL
  19. {
  20. AccountDB vtable; // public interface
  21.  
  22. Sql* accounts; // SQL accounts storage
  23.  
  24. // global sql settings
  25. char global_db_hostname[32];
  26. uint16 global_db_port;
  27. char global_db_username[32];
  28. char global_db_password[32];
  29. char global_db_database[32];
  30. char global_codepage[32];
  31. // local sql settings
  32. char db_hostname[32];
  33. uint16 db_port;
  34. char db_username[32];
  35. char db_password[32];
  36. char db_database[32];
  37. char codepage[32];
  38. // other settings
  39. bool case_sensitive;
  40. char account_db[32];
  41. char accreg_db[32];
  42.  
  43. } AccountDB_SQL;
  44.  
  45. /// internal structure
  46. typedef struct AccountDBIterator_SQL
  47. {
  48. AccountDBIterator vtable; // public interface
  49.  
  50. AccountDB_SQL* db;
  51. int last_account_id;
  52. } AccountDBIterator_SQL;
  53.  
  54. /// internal functions
  55. static bool account_db_sql_init(AccountDB* self);
  56. static void account_db_sql_destroy(AccountDB* self);
  57. static bool account_db_sql_get_property(AccountDB* self, const char* key, char* buf, size_t buflen);
  58. static bool account_db_sql_set_property(AccountDB* self, const char* option, const char* value);
  59. static bool account_db_sql_create(AccountDB* self, struct mmo_account* acc);
  60. static bool account_db_sql_remove(AccountDB* self, const int account_id);
  61. static bool account_db_sql_save(AccountDB* self, const struct mmo_account* acc);
  62. static bool account_db_sql_load_num(AccountDB* self, struct mmo_account* acc, const int account_id);
  63. static bool account_db_sql_load_str(AccountDB* self, struct mmo_account* acc, const char* userid);
  64. static AccountDBIterator* account_db_sql_iterator(AccountDB* self);
  65. static void account_db_sql_iter_destroy(AccountDBIterator* self);
  66. static bool account_db_sql_iter_next(AccountDBIterator* self, struct mmo_account* acc);
  67.  
  68. static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int account_id);
  69. static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, bool is_new);
  70.  
  71. /// public constructor
  72. AccountDB* account_db_sql(void)
  73. {
  74. AccountDB_SQL* db = (AccountDB_SQL*)aCalloc(1, sizeof(AccountDB_SQL));
  75.  
  76. // set up the vtable
  77. db->vtable.init = &account_db_sql_init;
  78. db->vtable.destroy = &account_db_sql_destroy;
  79. db->vtable.get_property = &account_db_sql_get_property;
  80. db->vtable.set_property = &account_db_sql_set_property;
  81. db->vtable.save = &account_db_sql_save;
  82. db->vtable.create = &account_db_sql_create;
  83. db->vtable.remove = &account_db_sql_remove;
  84. db->vtable.load_num = &account_db_sql_load_num;
  85. db->vtable.load_str = &account_db_sql_load_str;
  86. db->vtable.iterator = &account_db_sql_iterator;
  87.  
  88. // initialize to default values
  89. db->accounts = NULL;
  90. // global sql settings
  91. safestrncpy(db->global_db_hostname, "127.0.0.1", sizeof(db->global_db_hostname));
  92. db->global_db_port = 3306;
  93. safestrncpy(db->global_db_username, "ragnarok", sizeof(db->global_db_username));
  94. safestrncpy(db->global_db_password, "ragnarok", sizeof(db->global_db_password));
  95. safestrncpy(db->global_db_database, "ragnarok", sizeof(db->global_db_database));
  96. safestrncpy(db->global_codepage, "", sizeof(db->global_codepage));
  97. // local sql settings
  98. safestrncpy(db->db_hostname, "", sizeof(db->db_hostname));
  99. db->db_port = 3306;
  100. safestrncpy(db->db_username, "", sizeof(db->db_username));
  101. safestrncpy(db->db_password, "", sizeof(db->db_password));
  102. safestrncpy(db->db_database, "", sizeof(db->db_database));
  103. safestrncpy(db->codepage, "", sizeof(db->codepage));
  104. // other settings
  105. db->case_sensitive = false;
  106. safestrncpy(db->account_db, "login", sizeof(db->account_db));
  107. safestrncpy(db->accreg_db, "global_reg_value", sizeof(db->accreg_db));
  108.  
  109. return &db->vtable;
  110. }
  111.  
  112.  
  113. /* ------------------------------------------------------------------------- */
  114.  
  115.  
  116. /// establishes database connection
  117. static bool account_db_sql_init(AccountDB* self)
  118. {
  119. AccountDB_SQL* db = (AccountDB_SQL*)self;
  120. Sql* sql_handle;
  121. const char* username;
  122. const char* password;
  123. const char* hostname;
  124. uint16 port;
  125. const char* database;
  126. const char* codepage;
  127.  
  128. db->accounts = Sql_Malloc();
  129. sql_handle = db->accounts;
  130.  
  131. if( db->db_hostname[0] != '\0' )
  132. {// local settings
  133. username = db->db_username;
  134. password = db->db_password;
  135. hostname = db->db_hostname;
  136. port = db->db_port;
  137. database = db->db_database;
  138. codepage = db->codepage;
  139. }
  140. else
  141. {// global settings
  142. username = db->global_db_username;
  143. password = db->global_db_password;
  144. hostname = db->global_db_hostname;
  145. port = db->global_db_port;
  146. database = db->global_db_database;
  147. codepage = db->global_codepage;
  148. }
  149.  
  150. if( SQL_ERROR == Sql_Connect(sql_handle, username, password, hostname, port, database) )
  151. {
  152. Sql_ShowDebug(sql_handle);
  153. Sql_Free(db->accounts);
  154. db->accounts = NULL;
  155. return false;
  156. }
  157.  
  158. if( codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, codepage) )
  159. Sql_ShowDebug(sql_handle);
  160.  
  161. return true;
  162. }
  163.  
  164. /// disconnects from database
  165. static void account_db_sql_destroy(AccountDB* self)
  166. {
  167. AccountDB_SQL* db = (AccountDB_SQL*)self;
  168.  
  169. Sql_Free(db->accounts);
  170. db->accounts = NULL;
  171. aFree(db);
  172. }
  173.  
  174. /// Gets a property from this database.
  175. static bool account_db_sql_get_property(AccountDB* self, const char* key, char* buf, size_t buflen)
  176. {
  177. AccountDB_SQL* db = (AccountDB_SQL*)self;
  178. const char* signature;
  179.  
  180. signature = "engine.";
  181. if( strncmpi(key, signature, strlen(signature)) == 0 )
  182. {
  183. key += strlen(signature);
  184. if( strcmpi(key, "name") == 0 )
  185. safesnprintf(buf, buflen, "sql");
  186. else
  187. if( strcmpi(key, "version") == 0 )
  188. safesnprintf(buf, buflen, "%d", ACCOUNT_SQL_DB_VERSION);
  189. else
  190. if( strcmpi(key, "comment") == 0 )
  191. safesnprintf(buf, buflen, "SQL Account Database");
  192. else
  193. return false;// not found
  194. return true;
  195. }
  196.  
  197. signature = "sql.";
  198. if( strncmpi(key, signature, strlen(signature)) == 0 )
  199. {
  200. key += strlen(signature);
  201. if( strcmpi(key, "db_hostname") == 0 )
  202. safesnprintf(buf, buflen, "%s", db->global_db_hostname);
  203. else
  204. if( strcmpi(key, "db_port") == 0 )
  205. safesnprintf(buf, buflen, "%d", db->global_db_port);
  206. else
  207. if( strcmpi(key, "db_username") == 0 )
  208. safesnprintf(buf, buflen, "%s", db->global_db_username);
  209. else
  210. if( strcmpi(key, "db_password") == 0 )
  211. safesnprintf(buf, buflen, "%s", db->global_db_password);
  212. else
  213. if( strcmpi(key, "db_database") == 0 )
  214. safesnprintf(buf, buflen, "%s", db->global_db_database);
  215. else
  216. if( strcmpi(key, "codepage") == 0 )
  217. safesnprintf(buf, buflen, "%s", db->global_codepage);
  218. else
  219. return false;// not found
  220. return true;
  221. }
  222.  
  223. signature = "account.sql.";
  224. if( strncmpi(key, signature, strlen(signature)) == 0 )
  225. {
  226. key += strlen(signature);
  227. if( strcmpi(key, "db_hostname") == 0 )
  228. safesnprintf(buf, buflen, "%s", db->db_hostname);
  229. else
  230. if( strcmpi(key, "db_port") == 0 )
  231. safesnprintf(buf, buflen, "%d", db->db_port);
  232. else
  233. if( strcmpi(key, "db_username") == 0 )
  234. safesnprintf(buf, buflen, "%s", db->db_username);
  235. else
  236. if( strcmpi(key, "db_password") == 0 )
  237. safesnprintf(buf, buflen, "%s", db->db_password);
  238. else
  239. if( strcmpi(key, "db_database") == 0 )
  240. safesnprintf(buf, buflen, "%s", db->db_database);
  241. else
  242. if( strcmpi(key, "codepage") == 0 )
  243. safesnprintf(buf, buflen, "%s", db->codepage);
  244. else
  245. if( strcmpi(key, "case_sensitive") == 0 )
  246. safesnprintf(buf, buflen, "%d", (db->case_sensitive ? 1 : 0));
  247. else
  248. if( strcmpi(key, "account_db") == 0 )
  249. safesnprintf(buf, buflen, "%s", db->account_db);
  250. else
  251. if( strcmpi(key, "accreg_db") == 0 )
  252. safesnprintf(buf, buflen, "%s", db->accreg_db);
  253. else
  254. return false;// not found
  255. return true;
  256. }
  257.  
  258. return false;// not found
  259. }
  260.  
  261. /// if the option is supported, adjusts the internal state
  262. static bool account_db_sql_set_property(AccountDB* self, const char* key, const char* value)
  263. {
  264. AccountDB_SQL* db = (AccountDB_SQL*)self;
  265. const char* signature;
  266.  
  267.  
  268. signature = "sql.";
  269. if( strncmp(key, signature, strlen(signature)) == 0 )
  270. {
  271. key += strlen(signature);
  272. if( strcmpi(key, "db_hostname") == 0 )
  273. safestrncpy(db->global_db_hostname, value, sizeof(db->global_db_hostname));
  274. else
  275. if( strcmpi(key, "db_port") == 0 )
  276. db->global_db_port = (uint16)strtoul(value, NULL, 10);
  277. else
  278. if( strcmpi(key, "db_username") == 0 )
  279. safestrncpy(db->global_db_username, value, sizeof(db->global_db_username));
  280. else
  281. if( strcmpi(key, "db_password") == 0 )
  282. safestrncpy(db->global_db_password, value, sizeof(db->global_db_password));
  283. else
  284. if( strcmpi(key, "db_database") == 0 )
  285. safestrncpy(db->global_db_database, value, sizeof(db->global_db_database));
  286. else
  287. if( strcmpi(key, "codepage") == 0 )
  288. safestrncpy(db->global_codepage, value, sizeof(db->global_codepage));
  289. else
  290. return false;// not found
  291. return true;
  292. }
  293.  
  294. signature = "account.sql.";
  295. if( strncmp(key, signature, strlen(signature)) == 0 )
  296. {
  297. key += strlen(signature);
  298. if( strcmpi(key, "db_hostname") == 0 )
  299. safestrncpy(db->db_hostname, value, sizeof(db->db_hostname));
  300. else
  301. if( strcmpi(key, "db_port") == 0 )
  302. db->db_port = (uint16)strtoul(value, NULL, 10);
  303. else
  304. if( strcmpi(key, "db_username") == 0 )
  305. safestrncpy(db->db_username, value, sizeof(db->db_username));
  306. else
  307. if( strcmpi(key, "db_password") == 0 )
  308. safestrncpy(db->db_password, value, sizeof(db->db_password));
  309. else
  310. if( strcmpi(key, "db_database") == 0 )
  311. safestrncpy(db->db_database, value, sizeof(db->db_database));
  312. else
  313. if( strcmpi(key, "codepage") == 0 )
  314. safestrncpy(db->codepage, value, sizeof(db->codepage));
  315. else
  316. if( strcmpi(key, "case_sensitive") == 0 )
  317. db->case_sensitive = config_switch(value);
  318. else
  319. if( strcmpi(key, "account_db") == 0 )
  320. safestrncpy(db->account_db, value, sizeof(db->account_db));
  321. else
  322. if( strcmpi(key, "accreg_db") == 0 )
  323. safestrncpy(db->accreg_db, value, sizeof(db->accreg_db));
  324. else
  325. return false;// not found
  326. return true;
  327. }
  328.  
  329. return false;// not found
  330. }
  331.  
  332. /// create a new account entry
  333. /// If acc->account_id is -1, the account id will be auto-generated,
  334. /// and its value will be written to acc->account_id if everything succeeds.
  335. static bool account_db_sql_create(AccountDB* self, struct mmo_account* acc)
  336. {
  337. AccountDB_SQL* db = (AccountDB_SQL*)self;
  338. Sql* sql_handle = db->accounts;
  339.  
  340. // decide on the account id to assign
  341. int account_id;
  342. if( acc->account_id != -1 )
  343. {// caller specifies it manually
  344. account_id = acc->account_id;
  345. }
  346. else
  347. {// ask the database
  348. char* data;
  349. size_t len;
  350.  
  351. if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT MAX(`account_id`)+1 FROM `%s`", db->account_db) )
  352. {
  353. Sql_ShowDebug(sql_handle);
  354. return false;
  355. }
  356. if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
  357. {
  358. Sql_ShowDebug(sql_handle);
  359. Sql_FreeResult(sql_handle);
  360. return false;
  361. }
  362.  
  363. Sql_GetData(sql_handle, 0, &data, &len);
  364. account_id = ( data != NULL ) ? atoi(data) : 0;
  365. Sql_FreeResult(sql_handle);
  366.  
  367. if( account_id < START_ACCOUNT_NUM )
  368. account_id = START_ACCOUNT_NUM;
  369.  
  370. }
  371.  
  372. // zero value is prohibited
  373. if( account_id == 0 )
  374. return false;
  375.  
  376. // absolute maximum
  377. if( account_id > END_ACCOUNT_NUM )
  378. return false;
  379.  
  380. // insert the data into the database
  381. acc->account_id = account_id;
  382. return mmo_auth_tosql(db, acc, true);
  383. }
  384.  
  385. /// delete an existing account entry + its regs
  386. static bool account_db_sql_remove(AccountDB* self, const int account_id)
  387. {
  388. AccountDB_SQL* db = (AccountDB_SQL*)self;
  389. Sql* sql_handle = db->accounts;
  390. bool result = false;
  391.  
  392. if( SQL_SUCCESS != Sql_QueryStr(sql_handle, "START TRANSACTION")
  393. || SQL_SUCCESS != Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = %d", db->account_db, account_id)
  394. || SQL_SUCCESS != Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = %d", db->accreg_db, account_id) )
  395. Sql_ShowDebug(sql_handle);
  396. else
  397. result = true;
  398.  
  399. result &= ( SQL_SUCCESS == Sql_QueryStr(sql_handle, (result == true) ? "COMMIT" : "ROLLBACK") );
  400.  
  401. return result;
  402. }
  403.  
  404. /// update an existing account with the provided new data (both account and regs)
  405. static bool account_db_sql_save(AccountDB* self, const struct mmo_account* acc)
  406. {
  407. AccountDB_SQL* db = (AccountDB_SQL*)self;
  408. return mmo_auth_tosql(db, acc, false);
  409. }
  410.  
  411. /// retrieve data from db and store it in the provided data structure
  412. static bool account_db_sql_load_num(AccountDB* self, struct mmo_account* acc, const int account_id)
  413. {
  414. AccountDB_SQL* db = (AccountDB_SQL*)self;
  415. return mmo_auth_fromsql(db, acc, account_id);
  416. }
  417.  
  418. /// retrieve data from db and store it in the provided data structure
  419. static bool account_db_sql_load_str(AccountDB* self, struct mmo_account* acc, const char* userid)
  420. {
  421. AccountDB_SQL* db = (AccountDB_SQL*)self;
  422. Sql* sql_handle = db->accounts;
  423. char esc_userid[2*NAME_LENGTH+1];
  424. int account_id;
  425. char* data;
  426.  
  427. Sql_EscapeString(sql_handle, esc_userid, userid);
  428.  
  429. // get the list of account IDs for this user ID
  430. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id` FROM `%s` WHERE `userid`= %s '%s'",
  431. db->account_db, (db->case_sensitive ? "BINARY" : ""), esc_userid) )
  432. {
  433. Sql_ShowDebug(sql_handle);
  434. return false;
  435. }
  436.  
  437. if( Sql_NumRows(sql_handle) > 1 )
  438. {// serious problem - duplicit account
  439. ShowError("account_db_sql_load_str: multiple accounts found when retrieving data for account '%s'!\n", userid);
  440. Sql_FreeResult(sql_handle);
  441. return false;
  442. }
  443.  
  444. if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
  445. {// no such entry
  446. Sql_FreeResult(sql_handle);
  447. return false;
  448. }
  449.  
  450. Sql_GetData(sql_handle, 0, &data, NULL);
  451. account_id = atoi(data);
  452.  
  453. return account_db_sql_load_num(self, acc, account_id);
  454. }
  455.  
  456.  
  457. /// Returns a new forward iterator.
  458. static AccountDBIterator* account_db_sql_iterator(AccountDB* self)
  459. {
  460. AccountDB_SQL* db = (AccountDB_SQL*)self;
  461. AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)aCalloc(1, sizeof(AccountDBIterator_SQL));
  462.  
  463. // set up the vtable
  464. iter->vtable.destroy = &account_db_sql_iter_destroy;
  465. iter->vtable.next = &account_db_sql_iter_next;
  466.  
  467. // fill data
  468. iter->db = db;
  469. iter->last_account_id = -1;
  470.  
  471. return &iter->vtable;
  472. }
  473.  
  474.  
  475. /// Destroys this iterator, releasing all allocated memory (including itself).
  476. static void account_db_sql_iter_destroy(AccountDBIterator* self)
  477. {
  478. AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)self;
  479. aFree(iter);
  480. }
  481.  
  482.  
  483. /// Fetches the next account in the database.
  484. static bool account_db_sql_iter_next(AccountDBIterator* self, struct mmo_account* acc)
  485. {
  486. AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)self;
  487. AccountDB_SQL* db = (AccountDB_SQL*)iter->db;
  488. Sql* sql_handle = db->accounts;
  489. int account_id;
  490. char* data;
  491.  
  492. // get next account ID
  493. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id` FROM `%s` WHERE `account_id` > '%d' ORDER BY `account_id` ASC LIMIT 1",
  494. db->account_db, iter->last_account_id) )
  495. {
  496. Sql_ShowDebug(sql_handle);
  497. return false;
  498. }
  499.  
  500. if( SQL_SUCCESS == Sql_NextRow(sql_handle) &&
  501. SQL_SUCCESS == Sql_GetData(sql_handle, 0, &data, NULL) &&
  502. data != NULL )
  503. {// get account data
  504. account_id = atoi(data);
  505. if( mmo_auth_fromsql(db, acc, account_id) )
  506. {
  507. iter->last_account_id = account_id;
  508. Sql_FreeResult(sql_handle);
  509. return true;
  510. }
  511. }
  512. Sql_FreeResult(sql_handle);
  513. return false;
  514. }
  515.  
  516.  
  517. static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int account_id)
  518. {
  519. Sql* sql_handle = db->accounts;
  520. char* data;
  521. int i = 0;
  522.  
  523. // retrieve login entry for the specified account
  524. if( SQL_ERROR == Sql_Query(sql_handle,
  525. "SELECT `account_id`,`userid`,`user_pass`,`sex`,`email`,`level`,`state`,`unban_time`,`expiration_time`,`logincount`,`lastlogin`,`last_ip` FROM `%s` WHERE `account_id` = %d",
  526. db->account_db, account_id )
  527. ) {
  528. Sql_ShowDebug(sql_handle);
  529. return false;
  530. }
  531.  
  532. if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
  533. {// no such entry
  534. Sql_FreeResult(sql_handle);
  535. return false;
  536. }
  537.  
  538. Sql_GetData(sql_handle, 0, &data, NULL); acc->account_id = atoi(data);
  539. Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(acc->userid, data, sizeof(acc->userid));
  540. Sql_GetData(sql_handle, 2, &data, NULL); safestrncpy(acc->pass, data, sizeof(acc->pass));
  541. Sql_GetData(sql_handle, 3, &data, NULL); acc->sex = data[0];
  542. Sql_GetData(sql_handle, 4, &data, NULL); safestrncpy(acc->email, data, sizeof(acc->email));
  543. Sql_GetData(sql_handle, 5, &data, NULL); acc->level = atoi(data);
  544. Sql_GetData(sql_handle, 6, &data, NULL); acc->state = strtoul(data, NULL, 10);
  545. Sql_GetData(sql_handle, 7, &data, NULL); acc->unban_time = atol(data);
  546. Sql_GetData(sql_handle, 8, &data, NULL); acc->expiration_time = atol(data);
  547. Sql_GetData(sql_handle, 9, &data, NULL); acc->logincount = strtoul(data, NULL, 10);
  548. Sql_GetData(sql_handle, 10, &data, NULL); safestrncpy(acc->lastlogin, data, sizeof(acc->lastlogin));
  549. Sql_GetData(sql_handle, 11, &data, NULL); safestrncpy(acc->last_ip, data, sizeof(acc->last_ip));
  550.  
  551. Sql_FreeResult(sql_handle);
  552.  
  553.  
  554. // retrieve account regs for the specified user
  555. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`,`value` FROM `%s` WHERE `type`='1' AND `account_id`='%d'", db->accreg_db, acc->account_id) )
  556. {
  557. Sql_ShowDebug(sql_handle);
  558. return false;
  559. }
  560.  
  561. acc->account_reg2_num = (int)Sql_NumRows(sql_handle);
  562.  
  563. while( SQL_SUCCESS == Sql_NextRow(sql_handle) )
  564. {
  565. char* data;
  566. Sql_GetData(sql_handle, 0, &data, NULL); safestrncpy(acc->account_reg2[i].str, data, sizeof(acc->account_reg2[i].str));
  567. Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(acc->account_reg2[i].value, data, sizeof(acc->account_reg2[i].value));
  568. ++i;
  569. }
  570. Sql_FreeResult(sql_handle);
  571.  
  572. if( i != acc->account_reg2_num )
  573. return false;
  574.  
  575. return true;
  576. }
  577.  
  578. static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, bool is_new)
  579. {
  580. Sql* sql_handle = db->accounts;
  581. SqlStmt* stmt = SqlStmt_Malloc(sql_handle);
  582. bool result = false;
  583. int i;
  584.  
  585. // try
  586. do
  587. {
  588.  
  589. if( SQL_SUCCESS != Sql_QueryStr(sql_handle, "START TRANSACTION") )
  590. {
  591. Sql_ShowDebug(sql_handle);
  592. break;
  593. }
  594.  
  595. if( is_new )
  596. {// insert into account table
  597. if( SQL_SUCCESS != SqlStmt_Prepare(stmt,
  598. "INSERT INTO `%s` (`account_id`, `userid`, `user_pass`, `sex`, `email`, `level`, `state`, `unban_time`, `expiration_time`, `logincount`, `lastlogin`, `last_ip`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
  599. db->account_db)
  600. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_INT, (void*)&acc->account_id, sizeof(acc->account_id))
  601. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->userid, strlen(acc->userid))
  602. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_STRING, (void*)acc->pass, strlen(acc->pass))
  603. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 3, SQLDT_ENUM, (void*)&acc->sex, sizeof(acc->sex))
  604. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 4, SQLDT_STRING, (void*)&acc->email, strlen(acc->email))
  605. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 5, SQLDT_INT, (void*)&acc->level, sizeof(acc->level))
  606. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 6, SQLDT_UINT, (void*)&acc->state, sizeof(acc->state))
  607. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 7, SQLDT_LONG, (void*)&acc->unban_time, sizeof(acc->unban_time))
  608. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 8, SQLDT_INT, (void*)&acc->expiration_time, sizeof(acc->expiration_time))
  609. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 9, SQLDT_UINT, (void*)&acc->logincount, sizeof(acc->logincount))
  610. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 10, SQLDT_STRING, (void*)&acc->lastlogin, strlen(acc->lastlogin))
  611. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 11, SQLDT_STRING, (void*)&acc->last_ip, strlen(acc->last_ip))
  612. || SQL_SUCCESS != SqlStmt_Execute(stmt)
  613. ) {
  614. SqlStmt_ShowDebug(stmt);
  615. break;
  616. }
  617. }
  618. else
  619. {// update account table
  620. if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "UPDATE `%s` SET `userid`=?,`user_pass`=?,`sex`=?,`email`=?,`level`=?,`state`=?,`unban_time`=?,`expiration_time`=?,`logincount`=?,`lastlogin`=?,`last_ip`=? WHERE `account_id` = '%d'", db->account_db, acc->account_id)
  621. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (void*)acc->userid, strlen(acc->userid))
  622. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->pass, strlen(acc->pass))
  623. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_ENUM, (void*)&acc->sex, sizeof(acc->sex))
  624. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 3, SQLDT_STRING, (void*)acc->email, strlen(acc->email))
  625. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 4, SQLDT_INT, (void*)&acc->level, sizeof(acc->level))
  626. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 5, SQLDT_UINT, (void*)&acc->state, sizeof(acc->state))
  627. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 6, SQLDT_LONG, (void*)&acc->unban_time, sizeof(acc->unban_time))
  628. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 7, SQLDT_LONG, (void*)&acc->expiration_time, sizeof(acc->expiration_time))
  629. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 8, SQLDT_UINT, (void*)&acc->logincount, sizeof(acc->logincount))
  630. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 9, SQLDT_STRING, (void*)&acc->lastlogin, strlen(acc->lastlogin))
  631. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 10, SQLDT_STRING, (void*)&acc->last_ip, strlen(acc->last_ip))
  632. || SQL_SUCCESS != SqlStmt_Execute(stmt)
  633. ) {
  634. SqlStmt_ShowDebug(stmt);
  635. break;
  636. }
  637. }
  638.  
  639. // remove old account regs
  640. if( SQL_SUCCESS != Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`='1' AND `account_id`='%d'", db->accreg_db, acc->account_id) )
  641. {
  642. Sql_ShowDebug(sql_handle);
  643. break;
  644. }
  645. // insert new account regs
  646. if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "INSERT INTO `%s` (`type`, `account_id`, `str`, `value`) VALUES ( 1 , '%d' , ? , ? );", db->accreg_db, acc->account_id) )
  647. {
  648. SqlStmt_ShowDebug(stmt);
  649. break;
  650. }
  651. for( i = 0; i < acc->account_reg2_num; ++i )
  652. {
  653. if( SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (void*)acc->account_reg2[i].str, strlen(acc->account_reg2[i].str))
  654. || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->account_reg2[i].value, strlen(acc->account_reg2[i].value))
  655. || SQL_SUCCESS != SqlStmt_Execute(stmt)
  656. ) {
  657. SqlStmt_ShowDebug(stmt);
  658. break;
  659. }
  660. }
  661. if( i < acc->account_reg2_num )
  662. {
  663. result = false;
  664. break;
  665. }
  666.  
  667. // if we got this far, everything was successful
  668. result = true;
  669.  
  670. } while(0);
  671. // finally
  672.  
  673. result &= ( SQL_SUCCESS == Sql_QueryStr(sql_handle, (result == true) ? "COMMIT" : "ROLLBACK") );
  674. SqlStmt_Free(stmt);
  675.  
  676. return result;
  677. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement