void chlogif_send_global_accreg(const char *key, unsigned int index, intptr_t val, bool is_string) { int nlen = WFIFOW(login_fd, 2); size_t len; if (!chlogif_isconnected()) return; len = strlen(key)+1; WFIFOB(login_fd, nlen) = (unsigned char)len; // won't be higher; the column size is 32 nlen += 1; safestrncpy(WFIFOCP(login_fd,nlen), key, len); nlen += len; WFIFOL(login_fd, nlen) = index; nlen += 4; if( is_string ) { WFIFOB(login_fd, nlen) = val ? 2 : 3; nlen += 1; if( val ) { char *sval = (char*)val; len = strlen(sval)+1; WFIFOB(login_fd, nlen) = (unsigned char)len; // won't be higher; the column size is 254 nlen += 1; safestrncpy(WFIFOCP(login_fd,nlen), sval, len); nlen += len; } } else { WFIFOB(login_fd, nlen) = val ? 0 : 1; nlen += 1; if( val ) { WFIFOL(login_fd, nlen) = (int)val; nlen += 4; } } WFIFOW(login_fd,12) += 1; WFIFOW(login_fd, 2) = nlen; if( WFIFOW(login_fd, 2) > 60000 ) { int account_id = WFIFOL(login_fd,4), char_id = WFIFOL(login_fd,8); chlogif_prepsend_global_accreg(); chlogif_upd_global_accreg(account_id, char_id); // prepare next } }
/** * Inform client that auth has failed. * @param sd: player session * @param result: nb (msg define in conf) 0 = Unregistered ID 1 = Incorrect Password 2 = This ID is expired 3 = Rejected from Server 4 = You have been blocked by the GM Team 5 = Your Game's EXE file is not the latest version 6 = Your are Prohibited to log in until %s 7 = Server is jammed due to over populated 8 = No more accounts may be connected from this company 9 = MSI_REFUSE_BAN_BY_DBA 10 = MSI_REFUSE_EMAIL_NOT_CONFIRMED 11 = MSI_REFUSE_BAN_BY_GM 12 = MSI_REFUSE_TEMP_BAN_FOR_DBWORK 13 = MSI_REFUSE_SELF_LOCK 14 = MSI_REFUSE_NOT_PERMITTED_GROUP 15 = MSI_REFUSE_NOT_PERMITTED_GROUP 99 = This ID has been totally erased 100 = Login information remains at %s 101 = Account has been locked for a hacking investigation. Please contact the GM Team for more information 102 = This account has been temporarily prohibited from login due to a bug-related investigation 103 = This character is being deleted. Login is temporarily unavailable for the time being 104 = This character is being deleted. Login is temporarily unavailable for the time being default = Unknown Error. */ static void logclif_auth_failed(struct login_session_data* sd, int result) { int fd = sd->fd; uint32 ip = session[fd]->client_addr; if (login_config.log_login) { if(result >= 0 && result <= 15) login_log(ip, sd->userid, result, msg_txt(result)); else if(result >= 99 && result <= 104) login_log(ip, sd->userid, result, msg_txt(result-83)); //-83 offset else login_log(ip, sd->userid, result, msg_txt(22)); //unknow error } if( (result == 0 || result == 1) && login_config.dynamic_pass_failure_ban ) ipban_log(ip); // log failed password attempt //#if PACKETVER >= 20120000 /* not sure when this started */ if( sd->version >= date2version(20120000) ){ /* not sure when this started */ WFIFOHEAD(fd,26); WFIFOW(fd,0) = 0x83e; WFIFOL(fd,2) = result; if( result != 6 ) memset(WFIFOP(fd,6), '\0', 20); else { // 6 = Your are Prohibited to log in until %s struct mmo_account acc; AccountDB* accounts = login_get_accounts_db(); time_t unban_time = ( accounts->load_str(accounts, &acc, sd->userid) ) ? acc.unban_time : 0; timestamp2string(WFIFOCP(fd,6), 20, unban_time, login_config.date_format); } WFIFOSET(fd,26); } //#else else { WFIFOHEAD(fd,23); WFIFOW(fd,0) = 0x6a; WFIFOB(fd,2) = (uint8)result; if( result != 6 ) memset(WFIFOP(fd,3), '\0', 20); else { // 6 = Your are Prohibited to log in until %s struct mmo_account acc; AccountDB* accounts = login_get_accounts_db(); time_t unban_time = ( accounts->load_str(accounts, &acc, sd->userid) ) ? acc.unban_time : 0; timestamp2string(WFIFOCP(fd,3), 20, unban_time, login_config.date_format); } WFIFOSET(fd,23); } //#endif }
/** * Transmit account data to char_server * S 2717 aid.W email.40B exp_time.L group_id.B char_slot.B birthdate.11B pincode.5B pincode_change.L * isvip.1B char_vip.1B max_billing.1B (tot 75) * @return -1 : account not found, 1:sucess */ int logchrif_send_accdata(int fd, uint32 aid) { struct mmo_account acc; time_t expiration_time = 0; char email[40] = ""; int group_id = 0; char birthdate[10+1] = ""; char pincode[PINCODE_LENGTH+1]; char isvip = false; uint8 char_slots = MIN_CHARS, char_vip = 0, char_billing = 0; AccountDB* accounts = login_get_accounts_db(); memset(pincode,0,PINCODE_LENGTH+1); if( !accounts->load_num(accounts, &acc, aid) ) return -1; else { safestrncpy(email, acc.email, sizeof(email)); expiration_time = acc.expiration_time; group_id = acc.group_id; safestrncpy(birthdate, acc.birthdate, sizeof(birthdate)); safestrncpy(pincode, acc.pincode, sizeof(pincode)); #ifdef VIP_ENABLE char_vip = login_config.vip_sys.char_increase; if( acc.vip_time > time(NULL) ) { isvip = true; char_slots = login_config.char_per_account + char_vip; } else char_slots = login_config.char_per_account; char_billing = MAX_CHAR_BILLING; //TODO create a config for this #endif } WFIFOHEAD(fd,75); WFIFOW(fd,0) = 0x2717; WFIFOL(fd,2) = aid; safestrncpy(WFIFOCP(fd,6), email, 40); WFIFOL(fd,46) = (uint32)expiration_time; WFIFOB(fd,50) = (unsigned char)group_id; WFIFOB(fd,51) = char_slots; safestrncpy(WFIFOCP(fd,52), birthdate, 10+1); safestrncpy(WFIFOCP(fd,63), pincode, 4+1 ); WFIFOL(fd,68) = (uint32)acc.pincode_change; WFIFOB(fd,72) = isvip; WFIFOB(fd,73) = char_vip; WFIFOB(fd,74) = char_billing; WFIFOSET(fd,75); return 1; }
/** * Transmit the result of a account_information request from map-serv, with type 1 * @param fd : map-serv link * @param u_fd : player fd to send info to * @param acc_id : id of player found * @param acc_name : name of player found */ void mapif_acc_info_ack(int fd, int u_fd, int acc_id, const char* acc_name){ WFIFOHEAD(fd,10 + NAME_LENGTH); WFIFOW(fd,0) = 0x3808; WFIFOL(fd,2) = u_fd; WFIFOL(fd,6) = acc_id; safestrncpy(WFIFOCP(fd,10),acc_name,NAME_LENGTH); WFIFOSET(fd,10 + NAME_LENGTH); }
/** * IA 0x2720 * Get account info that asked by inter/char-server */ int logchrif_parse_accinfo(int fd) { if( RFIFOREST(fd) < 23 ) return 0; else { int map_fd = RFIFOL(fd, 2), u_fd = RFIFOL(fd, 6), u_aid = RFIFOL(fd, 10), account_id = RFIFOL(fd, 14); int8 type = RFIFOB(fd, 18); AccountDB* accounts = login_get_accounts_db(); struct mmo_account acc; RFIFOSKIP(fd,19); // Send back the result to char-server if (accounts->load_num(accounts, &acc, account_id)) { int len = 122 + NAME_LENGTH; //ShowInfo("Found account info for %d, requested by %d\n", account_id, u_aid); WFIFOHEAD(fd, len); WFIFOW(fd, 0) = 0x2721; WFIFOL(fd, 2) = map_fd; WFIFOL(fd, 6) = u_fd; WFIFOL(fd, 10) = u_aid; WFIFOL(fd, 14) = account_id; WFIFOB(fd, 18) = (1<<type); // success WFIFOL(fd, 19) = acc.group_id; WFIFOL(fd, 23) = acc.logincount; WFIFOL(fd, 27) = acc.state; safestrncpy(WFIFOCP(fd, 31), acc.email, 40); safestrncpy(WFIFOCP(fd, 71), acc.last_ip, 16); safestrncpy(WFIFOCP(fd, 87), acc.lastlogin, 24); safestrncpy(WFIFOCP(fd, 111), acc.birthdate, 11); safestrncpy(WFIFOCP(fd, 122), acc.userid, NAME_LENGTH); WFIFOSET(fd, len); } else { //ShowInfo("Cannot found account info for %d, requested by %d\n", account_id, u_aid); WFIFOHEAD(fd, 19); WFIFOW(fd, 0) = 0x2721; WFIFOL(fd, 2) = map_fd; WFIFOL(fd, 6) = u_fd; WFIFOL(fd, 10) = u_aid; WFIFOL(fd, 14) = account_id; WFIFOB(fd, 18) = 0; // failed WFIFOSET(fd, 19); } } return 1; }
void mapif_Mail_receiver_send( int fd, int requesting_char_id, int char_id, int class_, int base_level, const char* name ){ WFIFOHEAD(fd,38); WFIFOW(fd,0) = 0x384e; WFIFOL(fd,2) = requesting_char_id; WFIFOL(fd,6) = char_id; WFIFOW(fd,10) = class_; WFIFOW(fd,12) = base_level; strncpy(WFIFOCP(fd, 14), name, NAME_LENGTH); WFIFOSET(fd,38); }
void chlogif_pincode_notifyLoginPinUpdate( uint32 account_id, char* pin ){ if ( chlogif_isconnected() ){ int size = 8 + PINCODE_LENGTH+1; WFIFOHEAD(login_fd,size); WFIFOW(login_fd,0) = 0x2738; WFIFOW(login_fd,2) = size; WFIFOL(login_fd,4) = account_id; strncpy( WFIFOCP(login_fd,8), pin, PINCODE_LENGTH+1 ); WFIFOSET(login_fd,size); } }
/* extremely handy I believe it will serve other uses in the near future */ void inter_to_fd(int fd, int u_fd, int aid, char* msg, ...) { char msg_out[512]; va_list ap; int len = 1;/* yes we start at 1 */ va_start(ap,msg); len += vsnprintf(msg_out, 512, msg, ap); va_end(ap); WFIFOHEAD(fd,12 + len); WFIFOW(fd,0) = 0x3807; WFIFOW(fd,2) = 12 + (unsigned short)len; WFIFOL(fd,4) = u_fd; WFIFOL(fd,8) = aid; safestrncpy(WFIFOCP(fd,12), msg_out, len); WFIFOSET(fd,12 + len); return; }
// Load account_reg from sql (type=2) int inter_accreg_fromsql(uint32 account_id, uint32 char_id, int fd, int type) { char* data; size_t len; unsigned int plen = 0; switch( type ) { case 3: //char reg if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `char_id`='%d'", schema_config.char_reg_str_table, char_id) ) Sql_ShowDebug(sql_handle); break; case 2: //account reg if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `account_id`='%d'", schema_config.acc_reg_str_table, account_id) ) Sql_ShowDebug(sql_handle); break; case 1: //account2 reg ShowError("inter_accreg_fromsql: Char server shouldn't handle type 1 registry values (##). That is the login server's job!\n"); return 0; default: ShowError("inter_accreg_fromsql: Invalid type %d\n", type); return 0; } 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(<keyLength>), index(L), valLength(B), val(<valLength>) } **/ 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(WFIFOCP(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(WFIFOCP(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; } } WFIFOW(fd, 2) = plen; WFIFOSET(fd, plen); Sql_FreeResult(sql_handle); switch( type ) { case 3: //char reg if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `char_id`='%d'", schema_config.char_reg_num_table, char_id)) Sql_ShowDebug(sql_handle); break; case 2: //account reg if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `account_id`='%d'", schema_config.acc_reg_num_table, account_id)) Sql_ShowDebug(sql_handle); break; #if 0 // This is already checked above. case 1: //account2 reg ShowError("inter_accreg_fromsql: Char server shouldn't handle type 1 registry values (##). That is the login server's work!\n"); return 0; #endif // 0 } 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(<keyLength>), 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(WFIFOCP(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; } } WFIFOB(fd, 12) = type; WFIFOW(fd, 2) = plen; WFIFOSET(fd, plen); Sql_FreeResult(sql_handle); return 1; }
void mmo_send_global_accreg(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_table, account_id) ) Sql_ShowDebug(sql_handle); WFIFOHEAD(fd, 60000 + 300); WFIFOW(fd, 0) = 0x2726; // 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(<keyLength>), index(L), valLength(B), val(<valLength>) } **/ 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(WFIFOCP(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(WFIFOCP(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) = 0x2726; // 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; } } 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_table, account_id) ) Sql_ShowDebug(sql_handle); WFIFOHEAD(fd, 60000 + 300); WFIFOW(fd, 0) = 0x2726; // 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(<keyLength>), 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(WFIFOCP(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) = 0x2726; // 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; } } WFIFOB(fd, 12) = 1; WFIFOW(fd, 2) = plen; WFIFOSET(fd, plen); Sql_FreeResult(sql_handle); }