From 82b583b5ef4e729ad2c3c74b26adce16a145605a Mon Sep 17 00:00:00 2001 From: shennetsind Date: Sat, 11 Jan 2014 14:02:59 -0200 Subject: Hercules 1st 2014 MegaPatch http://hercules.ws/board/topic/3886-hercules-1st-2014-megapatch/ Signed-off-by: shennetsind --- src/login/account.h | 10 +- src/login/account_sql.c | 271 +++++++++++++++++++++++++++++++++++++----------- src/login/login.c | 51 +-------- src/login/login.h | 5 +- 4 files changed, 225 insertions(+), 112 deletions(-) (limited to 'src/login') diff --git a/src/login/account.h b/src/login/account.h index f55e38b0c..74a9e9626 100644 --- a/src/login/account.h +++ b/src/login/account.h @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena Dev Teams #ifndef __ACCOUNT_H_INCLUDED__ #define __ACCOUNT_H_INCLUDED__ @@ -32,8 +33,6 @@ struct mmo_account char lastlogin[24]; // date+time of last successful login char last_ip[16]; // save of last IP of connection char birthdate[10+1]; // assigned birth date (format: YYYY-MM-DD, default: 0000-00-00) - int account_reg2_num; - struct global_reg account_reg2[ACCOUNT_REG2_NUM]; // account script variables (stored on login server) }; @@ -137,4 +136,7 @@ struct AccountDB Sql *account_db_sql_up(AccountDB* self); +void mmo_send_accreg2(AccountDB* self, int fd, int account_id, int char_id); +void mmo_save_accreg2(AccountDB* self, int fd, int account_id, int char_id); + #endif // __ACCOUNT_H_INCLUDED__ diff --git a/src/login/account_sql.c b/src/login/account_sql.c index 283eb3a0d..1483196ab 100644 --- a/src/login/account_sql.c +++ b/src/login/account_sql.c @@ -9,6 +9,7 @@ #include "../common/strlib.h" #include "../common/timer.h" #include "../common/console.h" +#include "../common/socket.h" #include "account.h" #include #include @@ -40,7 +41,9 @@ typedef struct AccountDB_SQL // other settings bool case_sensitive; char account_db[32]; - char accreg_db[32]; + char global_acc_reg_num_db[32]; + char global_acc_reg_str_db[32]; + } AccountDB_SQL; @@ -106,7 +109,8 @@ AccountDB* account_db_sql(void) // other settings db->case_sensitive = false; safestrncpy(db->account_db, "login", sizeof(db->account_db)); - safestrncpy(db->accreg_db, "global_reg_value", sizeof(db->accreg_db)); + safestrncpy(db->global_acc_reg_num_db, "global_acc_reg_num_db", sizeof(db->global_acc_reg_num_db)); + safestrncpy(db->global_acc_reg_str_db, "global_acc_reg_str_db", sizeof(db->global_acc_reg_str_db)); return &db->vtable; } @@ -250,8 +254,11 @@ static bool account_db_sql_get_property(AccountDB* self, const char* key, char* if( strcmpi(key, "account_db") == 0 ) safesnprintf(buf, buflen, "%s", db->account_db); else - if( strcmpi(key, "accreg_db") == 0 ) - safesnprintf(buf, buflen, "%s", db->accreg_db); + if( strcmpi(key, "global_acc_reg_str_db") == 0 ) + safesnprintf(buf, buflen, "%s", db->global_acc_reg_str_db); + else + if( strcmpi(key, "global_acc_reg_num_db") == 0 ) + safesnprintf(buf, buflen, "%s", db->global_acc_reg_num_db); else return false;// not found return true; @@ -321,8 +328,11 @@ static bool account_db_sql_set_property(AccountDB* self, const char* key, const if( strcmpi(key, "account_db") == 0 ) safestrncpy(db->account_db, value, sizeof(db->account_db)); else - if( strcmpi(key, "accreg_db") == 0 ) - safestrncpy(db->accreg_db, value, sizeof(db->accreg_db)); + if( strcmpi(key, "global_acc_reg_str_db") == 0 ) + safestrncpy(db->global_acc_reg_str_db, value, sizeof(db->global_acc_reg_str_db)); + else + if( strcmpi(key, "global_acc_reg_num_db") == 0 ) + safestrncpy(db->global_acc_reg_num_db, value, sizeof(db->global_acc_reg_num_db)); else return false;// not found return true; @@ -393,7 +403,9 @@ static bool account_db_sql_remove(AccountDB* self, const int account_id) if( SQL_SUCCESS != SQL->QueryStr(sql_handle, "START TRANSACTION") || SQL_SUCCESS != SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = %d", db->account_db, account_id) - || SQL_SUCCESS != SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = %d", db->accreg_db, account_id) ) + || SQL_SUCCESS != SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = %d", db->global_acc_reg_num_db, account_id) + || SQL_SUCCESS != SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = %d", db->global_acc_reg_str_db, account_id) + ) Sql_ShowDebug(sql_handle); else result = true; @@ -520,7 +532,6 @@ static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int acc { Sql* sql_handle = db->accounts; char* data; - int i = 0; // retrieve login entry for the specified account if( SQL_ERROR == SQL->Query(sql_handle, @@ -556,27 +567,6 @@ static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int acc SQL->FreeResult(sql_handle); - - // retrieve account regs for the specified user - 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) ) - { - Sql_ShowDebug(sql_handle); - return false; - } - - acc->account_reg2_num = (int)SQL->NumRows(sql_handle); - - while( SQL_SUCCESS == SQL->NextRow(sql_handle) ) - { - SQL->GetData(sql_handle, 0, &data, NULL); safestrncpy(acc->account_reg2[i].str, data, sizeof(acc->account_reg2[i].str)); - SQL->GetData(sql_handle, 1, &data, NULL); safestrncpy(acc->account_reg2[i].value, data, sizeof(acc->account_reg2[i].value)); - ++i; - } - SQL->FreeResult(sql_handle); - - if( i != acc->account_reg2_num ) - return false; - return true; } @@ -585,7 +575,6 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo Sql* sql_handle = db->accounts; SqlStmt* stmt = SQL->StmtMalloc(sql_handle); bool result = false; - int i; // try do @@ -647,34 +636,6 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo } } - // remove old account regs - if( SQL_SUCCESS != SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `type`='1' AND `account_id`='%d'", db->accreg_db, acc->account_id) ) - { - Sql_ShowDebug(sql_handle); - break; - } - // insert new account regs - if( SQL_SUCCESS != SQL->StmtPrepare(stmt, "INSERT INTO `%s` (`type`, `account_id`, `str`, `value`) VALUES ( 1 , '%d' , ? , ? );", db->accreg_db, acc->account_id) ) - { - SqlStmt_ShowDebug(stmt); - break; - } - for( i = 0; i < acc->account_reg2_num; ++i ) - { - if( SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_STRING, (void*)acc->account_reg2[i].str, strlen(acc->account_reg2[i].str)) - || SQL_SUCCESS != SQL->StmtBindParam(stmt, 1, SQLDT_STRING, (void*)acc->account_reg2[i].value, strlen(acc->account_reg2[i].value)) - || SQL_SUCCESS != SQL->StmtExecute(stmt) - ) { - SqlStmt_ShowDebug(stmt); - break; - } - } - if( i < acc->account_reg2_num ) - { - result = false; - break; - } - // if we got this far, everything was successful result = true; @@ -686,6 +647,7 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo return result; } + Sql* account_db_sql_up(AccountDB* self) { AccountDB_SQL* db = (AccountDB_SQL*)self; Sql_HerculesUpdateCheck(db->accounts); @@ -694,3 +656,196 @@ Sql* account_db_sql_up(AccountDB* self) { #endif return db->accounts; } +void mmo_save_accreg2(AccountDB* self, int fd, int account_id, int char_id) { + Sql* sql_handle = ((AccountDB_SQL*)self)->accounts; + AccountDB_SQL* db = (AccountDB_SQL*)self; + int count = RFIFOW(fd, 12); + + if( count ) { + int cursor = 14, i; + char key[32], sval[254]; + unsigned int index; + + for(i = 0; i < count; i++) { + safestrncpy(key, (char*)RFIFOP(fd, cursor + 1), RFIFOB(fd, cursor)); + cursor += RFIFOB(fd, cursor) + 1; + + index = RFIFOL(fd, cursor); + cursor += 4; + + switch (RFIFOB(fd, cursor++)) { + /* int */ + case 0: + if( SQL_ERROR == SQL->Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`key`,`index`,`value`) VALUES ('%d','%s','%u','%d')", db->global_acc_reg_num_db, account_id, key, index, RFIFOL(fd, cursor)) ) + Sql_ShowDebug(sql_handle); + cursor += 4; + break; + case 1: + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `key` = '%s' AND `index` = '%u' LIMIT 1", db->global_acc_reg_num_db, account_id, key, index) ) + Sql_ShowDebug(sql_handle); + break; + /* str */ + case 2: + safestrncpy(sval, (char*)RFIFOP(fd, cursor + 1), RFIFOB(fd, cursor)); + cursor += RFIFOB(fd, cursor) + 1; + if( SQL_ERROR == SQL->Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`key`,`index`,`value`) VALUES ('%d','%s','%u','%s')", db->global_acc_reg_str_db, account_id, key, index, sval) ) + Sql_ShowDebug(sql_handle); + break; + case 3: + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `key` = '%s' AND `index` = '%u' LIMIT 1", db->global_acc_reg_str_db, account_id, key, index) ) + Sql_ShowDebug(sql_handle); + break; + + default: + ShowError("mmo_save_accreg2: DA HOO UNKNOWN TYPE %d\n",RFIFOB(fd, cursor - 1)); + return; + } + + } + + } + +} +void mmo_send_accreg2(AccountDB* self, int fd, int account_id, int char_id) { + Sql* sql_handle = ((AccountDB_SQL*)self)->accounts; + AccountDB_SQL* db = (AccountDB_SQL*)self; + char* data; + int plen = 0; + size_t len; + + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `account_id`='%d'", db->global_acc_reg_str_db, account_id) ) + Sql_ShowDebug(sql_handle); + + WFIFOHEAD(fd, 60000 + 300); + WFIFOW(fd, 0) = 0x3804; + /* 0x2 = length, set prior to being sent */ + WFIFOL(fd, 4) = account_id; + WFIFOL(fd, 8) = char_id; + WFIFOB(fd, 12) = 0;/* var type (only set when all vars have been sent, regardless of type) */ + WFIFOB(fd, 13) = 1;/* is string type */ + WFIFOW(fd, 14) = 0;/* count */ + plen = 16; + + /** + * Vessel! + * + * str type + * { keyLength(B), key(), index(L), valLength(B), val() } + **/ + while ( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { + + SQL->GetData(sql_handle, 0, &data, NULL); + len = strlen(data)+1; + + WFIFOB(fd, plen) = (unsigned char)len;/* won't be higher; the column size is 32 */ + plen += 1; + + safestrncpy((char*)WFIFOP(fd,plen), data, len); + plen += len; + + SQL->GetData(sql_handle, 1, &data, NULL); + + WFIFOL(fd, plen) = (unsigned int)atol(data); + plen += 4; + + SQL->GetData(sql_handle, 2, &data, NULL); + len = strlen(data)+1; + + WFIFOB(fd, plen) = (unsigned char)len;/* won't be higher; the column size is 254 */ + plen += 1; + + safestrncpy((char*)WFIFOP(fd,plen), data, len); + plen += len; + + WFIFOW(fd, 14) += 1; + + if( plen > 60000 ) { + WFIFOW(fd, 2) = plen; + WFIFOSET(fd, plen); + + /* prepare follow up */ + WFIFOHEAD(fd, 60000 + 300); + WFIFOW(fd, 0) = 0x3804; + /* 0x2 = length, set prior to being sent */ + WFIFOL(fd, 4) = account_id; + WFIFOL(fd, 8) = char_id; + WFIFOB(fd, 12) = 0;/* var type (only set when all vars have been sent, regardless of type) */ + WFIFOB(fd, 13) = 1;/* is string type */ + WFIFOW(fd, 14) = 0;/* count */ + plen = 16; + } + } + + /* mark & go. */ + WFIFOW(fd, 2) = plen; + WFIFOSET(fd, plen); + + SQL->FreeResult(sql_handle); + + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `account_id`='%d'", db->global_acc_reg_num_db, account_id) ) + Sql_ShowDebug(sql_handle); + + WFIFOHEAD(fd, 60000 + 300); + WFIFOW(fd, 0) = 0x3804; + /* 0x2 = length, set prior to being sent */ + WFIFOL(fd, 4) = account_id; + WFIFOL(fd, 8) = char_id; + WFIFOB(fd, 12) = 0;/* var type (only set when all vars have been sent, regardless of type) */ + WFIFOB(fd, 13) = 0;/* is int type */ + WFIFOW(fd, 14) = 0;/* count */ + plen = 16; + + /** + * Vessel! + * + * int type + * { keyLength(B), key(), index(L), value(L) } + **/ + while ( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { + + SQL->GetData(sql_handle, 0, &data, NULL); + len = strlen(data)+1; + + WFIFOB(fd, plen) = (unsigned char)len;/* won't be higher; the column size is 32 */ + plen += 1; + + safestrncpy((char*)WFIFOP(fd,plen), data, len); + plen += len; + + SQL->GetData(sql_handle, 1, &data, NULL); + + WFIFOL(fd, plen) = (unsigned int)atol(data); + plen += 4; + + SQL->GetData(sql_handle, 2, &data, NULL); + + WFIFOL(fd, plen) = atoi(data); + plen += 4; + + WFIFOW(fd, 14) += 1; + + if( plen > 60000 ) { + WFIFOW(fd, 2) = plen; + WFIFOSET(fd, plen); + + /* prepare follow up */ + WFIFOHEAD(fd, 60000 + 300); + WFIFOW(fd, 0) = 0x3804; + /* 0x2 = length, set prior to being sent */ + WFIFOL(fd, 4) = account_id; + WFIFOL(fd, 8) = char_id; + WFIFOB(fd, 12) = 0;/* var type (only set when all vars have been sent, regardless of type) */ + WFIFOB(fd, 13) = 0;/* is int type */ + WFIFOW(fd, 14) = 0;/* count */ + + plen = 16; + } + } + + /* mark as complete & go. */ + WFIFOB(fd, 12) = 1; + WFIFOW(fd, 2) = plen; + WFIFOSET(fd, plen); + + SQL->FreeResult(sql_handle); +} diff --git a/src/login/login.c b/src/login/login.c index 57a2d0b74..e9d0eac9d 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -704,30 +704,8 @@ int parse_fromchar(int fd) if( !accounts->load_num(accounts, &acc, account_id) ) ShowStatus("Char-server '%s': receiving (from the char-server) of account_reg2 (account: %d not found, ip: %s).\n", server[id].name, account_id, ip); - else - { - int len; - int p; - ShowNotice("char-server '%s': receiving (from the char-server) of account_reg2 (account: %d, ip: %s).\n", server[id].name, account_id, ip); - for( j = 0, p = 13; j < ACCOUNT_REG2_NUM && p < RFIFOW(fd,2); ++j ) - { - sscanf((char*)RFIFOP(fd,p), "%31c%n", acc.account_reg2[j].str, &len); - acc.account_reg2[j].str[len]='\0'; - p +=len+1; //+1 to skip the '\0' between strings. - sscanf((char*)RFIFOP(fd,p), "%255c%n", acc.account_reg2[j].value, &len); - acc.account_reg2[j].value[len]='\0'; - p +=len+1; - remove_control_chars(acc.account_reg2[j].str); - remove_control_chars(acc.account_reg2[j].value); - } - acc.account_reg2_num = j; - - // Save - accounts->save(accounts, &acc); - - // Sending information towards the other char-servers. - RFIFOW(fd,0) = 0x2729;// reusing read buffer - charif_sendallwos(fd, RFIFOP(fd,0), RFIFOW(fd,2)); + else { + mmo_save_accreg2(accounts,fd,account_id,RFIFOL(fd, 8)); } RFIFOSKIP(fd,RFIFOW(fd,2)); } @@ -797,34 +775,11 @@ int parse_fromchar(int fd) if (RFIFOREST(fd) < 10) return 0; { - struct mmo_account acc; - size_t off; - int account_id = RFIFOL(fd,2); int char_id = RFIFOL(fd,6); RFIFOSKIP(fd,10); - WFIFOHEAD(fd,ACCOUNT_REG2_NUM*sizeof(struct global_reg)); - WFIFOW(fd,0) = 0x2729; - WFIFOL(fd,4) = account_id; - WFIFOL(fd,8) = char_id; - WFIFOB(fd,12) = 1; //Type 1 for Account2 registry - - off = 13; - if( accounts->load_num(accounts, &acc, account_id) ) - { - for( j = 0; j < acc.account_reg2_num; j++ ) - { - if( acc.account_reg2[j].str[0] != '\0' ) - { - off += sprintf((char*)WFIFOP(fd,off), "%s", acc.account_reg2[j].str)+1; //We add 1 to consider the '\0' in place. - off += sprintf((char*)WFIFOP(fd,off), "%s", acc.account_reg2[j].value)+1; - } - } - } - - WFIFOW(fd,2) = (uint16)off; - WFIFOSET(fd,WFIFOW(fd,2)); + mmo_send_accreg2(accounts,fd,account_id,char_id); } break; diff --git a/src/login/login.h b/src/login/login.h index 80cbee74b..d6a021125 100644 --- a/src/login/login.h +++ b/src/login/login.h @@ -1,5 +1,6 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena Dev Teams #ifndef _LOGIN_H_ #define _LOGIN_H_ -- cgit v1.2.3-70-g09d2