Exemplo n.º 1
0
// パーティ作成可否
int mapif_party_created(int fd,int account_id,int char_id,struct party *p)
{
	WFIFOHEAD(fd, 39);
	WFIFOW(fd,0)=0x3820;
	WFIFOL(fd,2)=account_id;
	WFIFOL(fd,6)=char_id;
	if(p!=NULL){
		WFIFOB(fd,10)=0;
		WFIFOL(fd,11)=p->party_id;
		memcpy(WFIFOP(fd,15),p->name,NAME_LENGTH);
		ShowInfo("int_party: Party created (%d - %s)\n",p->party_id,p->name);
	}else{
		WFIFOB(fd,10)=1;
		WFIFOL(fd,11)=0;
		memset(WFIFOP(fd,15),0,NAME_LENGTH);
	}
	WFIFOSET(fd,39);

	return 0;
}
Exemplo n.º 2
0
/*==========================================
 * Request auth confirmation
 *------------------------------------------*/
void chrif_authreq(struct map_session_data *sd)
{
	struct auth_node *node= chrif_search(sd->bl.id);

	if( node != NULL )
	{
		set_eof(sd->fd);
		return;
	}

	WFIFOHEAD(char_fd,19);
	WFIFOW(char_fd,0) = 0x2b26;
	WFIFOL(char_fd,2) = sd->status.account_id;
	WFIFOL(char_fd,6) = sd->status.char_id;
	WFIFOL(char_fd,10) = sd->login_id1;
	WFIFOB(char_fd,14) = sd->status.sex;
	WFIFOL(char_fd,15) = htonl(session[sd->fd]->client_addr);
	WFIFOSET(char_fd,19);
	chrif_sd_to_auth(sd, ST_LOGIN);
}
Exemplo n.º 3
0
/*==========================================
 * S 2b0e <accid>.l <name>.24B <type>.w { <year>.w <month>.w <day>.w <hour>.w <minute>.w <second>.w }
 * Send an account modification request to the login server (via char server).
 * type of operation:
 *   1: block, 2: ban, 3: unblock, 4: unban, 5: changesex (use next function for 5)
 *------------------------------------------*/
int chrif_char_ask_name(int acc, const char* character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second) {
	
	chrif_check(-1);

	WFIFOHEAD(char_fd,44);
	WFIFOW(char_fd,0) = 0x2b0e;
	WFIFOL(char_fd,2) = acc;
	safestrncpy((char*)WFIFOP(char_fd,6), character_name, NAME_LENGTH);
	WFIFOW(char_fd,30) = operation_type;
	
	if ( operation_type == 2 ) {
		WFIFOW(char_fd,32) = year;
		WFIFOW(char_fd,34) = month;
		WFIFOW(char_fd,36) = day;
		WFIFOW(char_fd,38) = hour;
		WFIFOW(char_fd,40) = minute;
		WFIFOW(char_fd,42) = second;
	}
	
	WFIFOSET(char_fd,44);
	return 0;
}
Exemplo n.º 4
0
// pet
int intif_create_pet(int account_id,int char_id,short pet_class,short pet_lv,short pet_egg_id,
	short pet_equip,short intimate,short hungry,char rename_flag,char incuvate,char *pet_name)
{
	WFIFOW(inter_fd,0) = 0x3080;
	WFIFOL(inter_fd,2) = account_id;
	WFIFOL(inter_fd,6) = char_id;
	WFIFOW(inter_fd,10) = pet_class;
	WFIFOW(inter_fd,12) = pet_lv;
	WFIFOW(inter_fd,14) = pet_egg_id;
	WFIFOW(inter_fd,16) = pet_equip;
	WFIFOW(inter_fd,18) = intimate;
	WFIFOW(inter_fd,20) = hungry;
	WFIFOB(inter_fd,22) = rename_flag;
	WFIFOB(inter_fd,23) = incuvate;
	memcpy(WFIFOP(inter_fd,24),pet_name,24);
	WFIFOSET(inter_fd,48);

	return 0;
}
Exemplo n.º 5
0
/*==========================================
 * Return Mail
 *------------------------------------------*/
static void mapif_Mail_return(int fd, int char_id, int mail_id)
{
	struct mail_message msg;
	int new_mail = 0;

	if( mail_loadmessage(mail_id, &msg) )
	{
		if( msg.dest_id != char_id)
			return;
		else if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_db, mail_id) )
			Sql_ShowDebug(sql_handle);
		else
		{
			char temp_[MAIL_TITLE_LENGTH];

			// swap sender and receiver
			swap(msg.send_id, msg.dest_id);
			safestrncpy(temp_, msg.send_name, NAME_LENGTH);
			safestrncpy(msg.send_name, msg.dest_name, NAME_LENGTH);
			safestrncpy(msg.dest_name, temp_, NAME_LENGTH);

			// set reply message title
			snprintf(temp_, MAIL_TITLE_LENGTH, "RE:%s", msg.title);
			safestrncpy(msg.title, temp_, MAIL_TITLE_LENGTH);

			msg.status = MAIL_NEW;
			msg.timestamp = time(NULL);

			new_mail = mail_savemessage(&msg);
			mapif_Mail_new(&msg);
		}
	}

	WFIFOHEAD(fd,11);
	WFIFOW(fd,0) = 0x384c;
	WFIFOL(fd,2) = char_id;
	WFIFOL(fd,6) = mail_id;
	WFIFOB(fd,10) = (new_mail == 0);
	WFIFOSET(fd,11);
}
Exemplo n.º 6
0
int chlogif_parse_ackaccreq(int fd, struct char_session_data* sd){
	if (RFIFOREST(fd) < 25)
		return 0;
	{
		int account_id = RFIFOL(fd,2);
		uint32 login_id1 = RFIFOL(fd,6);
		uint32 login_id2 = RFIFOL(fd,10);
		uint8 sex = RFIFOB(fd,14);
		uint8 result = RFIFOB(fd,15);
		int request_id = RFIFOL(fd,16);
		uint32 version = RFIFOL(fd,20);
		uint8 clienttype = RFIFOB(fd,24);
		RFIFOSKIP(fd,25);

		if( session_isActive(request_id) && (sd=(struct char_session_data*)session[request_id]->session_data) &&
			!sd->auth && sd->account_id == account_id && sd->login_id1 == login_id1 && sd->login_id2 == login_id2 && sd->sex == sex )
		{
			int client_fd = request_id;
			sd->version = version;
			sd->clienttype = clienttype;
			if(sd->version != date2version(PACKETVER))
				ShowWarning("s aid=%d has an incorect version=%d in clientinfo. Server compiled for %d\n",
					sd->account_id,sd->version,date2version(PACKETVER));

			switch( result )
			{
			case 0:// ok
				char_auth_ok(client_fd, sd);
				break;
			case 1:// auth failed
				WFIFOHEAD(client_fd,3);
				WFIFOW(client_fd,0) = 0x6c;
				WFIFOB(client_fd,2) = 0;// rejected from server
				WFIFOSET(client_fd,3);
				break;
			}
		}
	}
	return 1;
}
Exemplo n.º 7
0
/**
 * Map-serv request to save mmo_char_status in sql
 * Receive character data from map-server for saving
 * @param fd: wich fd to parse from
 * @param id: wich map_serv id
 * @return : 0 not enough data received, 1 success
 */
int chmapif_parse_reqsavechar(int fd, int id){
	if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
		return 0;
	{
		int aid = RFIFOL(fd,4), cid = RFIFOL(fd,8), size = RFIFOW(fd,2);
		struct online_char_data* character;
		DBMap* online_char_db = char_get_onlinedb();

		if (size - 13 != sizeof(struct mmo_charstatus))
		{
			ShowError("parse_from_map (save-char): Size mismatch! %d != %d\n", size-13, sizeof(struct mmo_charstatus));
			RFIFOSKIP(fd,size);
			return 1;
		}
		//Check account only if this ain't final save. Final-save goes through because of the char-map reconnect
		if (RFIFOB(fd,12) || RFIFOB(fd,13) || (
			(character = (struct online_char_data*)idb_get(online_char_db, aid)) != NULL &&
			character->char_id == cid))
		{
			struct mmo_charstatus char_dat;
			memcpy(&char_dat, RFIFOP(fd,13), sizeof(struct mmo_charstatus));
			char_mmo_char_tosql(cid, &char_dat);
		} else {	//This may be valid on char-server reconnection, when re-sending characters that already logged off.
			ShowError("parse_from_map (save-char): Received data for non-existant/offline character (%d:%d).\n", aid, cid);
			char_set_char_online(id, cid, aid);
		}

		if (RFIFOB(fd,12))
		{	//Flag, set character offline after saving. [Skotlex]
			char_set_char_offline(cid, aid);
			WFIFOHEAD(fd,10);
			WFIFOW(fd,0) = 0x2b21; //Save ack only needed on final save.
			WFIFOL(fd,2) = aid;
			WFIFOL(fd,6) = cid;
			WFIFOSET(fd,10);
		}
		RFIFOSKIP(fd,size);
	}
	return 1;
}
Exemplo n.º 8
0
/*! 
 *  \brief     Set a character to offline mode
 *  
 *  \author    Fimbulwinter Development Team
 *  \author    GreenBox
 *  \date      08/12/11
 *
 **/
void CharServer::set_char_offline(int account_id, char char_id)
{
	if (char_id > 0)
	{
		statement s = (database->prepare << "UPDATE `char` SET `online` = 0 WHERE `char_id` = :c", use(char_id));
		s.execute();
	}
	else
	{
		statement s = (database->prepare << "UPDATE `char` SET `online` = 0 WHERE `account_id` = :a", use(account_id));
		s.execute();
	}

	if (online_chars.count(account_id))
	{
		if (online_chars[account_id].server > -1)
		{
			if (servers[online_chars[account_id].server].users > 0)
				servers[online_chars[account_id].server].users--;
		}

		if (online_chars[account_id].disconnect_timer)
			TimerManager::FreeTimer(online_chars[account_id].disconnect_timer);

		if (online_chars[account_id].char_id == char_id)
		{
			online_chars[account_id].char_id = -1;
			online_chars[account_id].server = -1;
		}
	}

	if (auth_conn_ok && (char_id == -1 || !online_chars.count(account_id) || online_chars[account_id].cl->flags.eof))
	{
		WFIFOHEAD(auth_conn,6);
		WFIFOW(auth_conn,0) = INTER_CA_SET_ACC_OFF;
		WFIFOL(auth_conn,2) = account_id;
		auth_conn->send_buffer(6);
	}
}
Exemplo n.º 9
0
/*==========================================
 * Request/Receive top 10 Fame character list
 *------------------------------------------*/
int chrif_updatefamelist(struct map_session_data* sd) {
	char type;
	
	chrif_check(-1);

	switch(sd->class_ & MAPID_UPPERMASK) {
		case MAPID_BLACKSMITH: type = 1; break;
		case MAPID_ALCHEMIST:  type = 2; break;
		case MAPID_TAEKWON:    type = 3; break;
		default:
			return 0;
	}

	WFIFOHEAD(char_fd, 11);
	WFIFOW(char_fd,0) = 0x2b10;
	WFIFOL(char_fd,2) = sd->status.char_id;
	WFIFOL(char_fd,6) = sd->status.fame;
	WFIFOB(char_fd,10) = type;
	WFIFOSET(char_fd,11);

	return 0;
}
Exemplo n.º 10
0
/*==========================================
 * Delete Mail
 *------------------------------------------*/
static void mapif_Mail_delete(int fd, uint32 char_id, int mail_id, bool deleted)
{
	bool failed = false;

	if( !deleted ) {
		if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_db, mail_id)
		||  SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_attachment_db, mail_id) ) {
			Sql_ShowDebug(sql_handle);
			failed = true;
		}
	}

	if( fd <= 0 )
		return; // Only if the request came from a map-server and was not timer triggered for an offline character

	WFIFOHEAD(fd,11);
	WFIFOW(fd,0) = 0x384b;
	WFIFOL(fd,2) = char_id;
	WFIFOL(fd,6) = mail_id;
	WFIFOB(fd,10) = failed;
	WFIFOSET(fd,11);
}
Exemplo n.º 11
0
static void mapif_elemental_deleted(int fd, unsigned char flag) {
    WFIFOHEAD(fd,3);
    WFIFOW(fd,0) = 0x387d;
    WFIFOB(fd,2) = flag;
    WFIFOSET(fd,3);
}
Exemplo n.º 12
0
void mapif_elemental_saved(int fd, unsigned char flag) {
	WFIFOHEAD(fd,3);
	WFIFOW(fd,0) = 0x387e;
	WFIFOB(fd,2) = flag;
	WFIFOSET(fd,3);
}
Exemplo n.º 13
0
void chlogif_prepsend_global_accreg(void) {
	if ( chlogif_isconnected() ){
		WFIFOSET(login_fd, WFIFOW(login_fd,2));
	}
}
Exemplo n.º 14
0
/**
 * Auth successful, inform client and create a temp auth_node.
 * @param sd: player session
 */
static void logclif_auth_ok(struct login_session_data* sd) {
	int fd = sd->fd;
	uint32 ip = session[fd]->client_addr;

	uint8 server_num, n;
	uint32 subnet_char_ip;
	struct auth_node* node;
	int i;

#if PACKETVER < 20170315
	int cmd = 0x69; // AC_ACCEPT_LOGIN
	int header = 47;
	int size = 32;
#else
	int cmd = 0xac4; // AC_ACCEPT_LOGIN3
	int header = 64;
	int size = 160;
#endif

	if( runflag != LOGINSERVER_ST_RUNNING ){
		// players can only login while running
		logclif_sent_auth_result(fd,1); // server closed
		return;
	}

	if( login_config.group_id_to_connect >= 0 && sd->group_id != login_config.group_id_to_connect ) {
		ShowStatus("Connection refused: the required group id for connection is %d (account: %s, group: %d).\n", login_config.group_id_to_connect, sd->userid, sd->group_id);
		logclif_sent_auth_result(fd,1); // server closed
		return;
	} else if( login_config.min_group_id_to_connect >= 0 && login_config.group_id_to_connect == -1 && sd->group_id < login_config.min_group_id_to_connect ) {
		ShowStatus("Connection refused: the minimum group id required for connection is %d (account: %s, group: %d).\n", login_config.min_group_id_to_connect, sd->userid, sd->group_id);
		logclif_sent_auth_result(fd,1); // server closed
		return;
	}

	server_num = 0;
	for( i = 0; i < ARRAYLENGTH(ch_server); ++i )
		if( session_isActive(ch_server[i].fd) )
			server_num++;

	if( server_num == 0 )
	{// if no char-server, don't send void list of servers, just disconnect the player with proper message
		ShowStatus("Connection refused: there is no char-server online (account: %s).\n", sd->userid);
		logclif_sent_auth_result(fd,1); // server closed
		return;
	}

	{
		struct online_login_data* data = (struct online_login_data*)idb_get(online_db, sd->account_id);
		if( data )
		{// account is already marked as online!
			if( data->char_server > -1 )
			{// Request char servers to kick this account out. [Skotlex]
				uint8 buf[6];
				ShowNotice("User '%s' is already online - Rejected.\n", sd->userid);
				WBUFW(buf,0) = 0x2734;
				WBUFL(buf,2) = sd->account_id;
				logchrif_sendallwos(-1, buf, 6);
				if( data->waiting_disconnect == INVALID_TIMER )
					data->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, login_waiting_disconnect_timer, sd->account_id, 0);
				logclif_sent_auth_result(fd,8); // 08 = Server still recognizes your last login
				return;
			}
			else
			if( data->char_server == -1 )
			{// client has authed but did not access char-server yet
				// wipe previous session
				idb_remove(auth_db, sd->account_id);
				login_remove_online_user(sd->account_id);
				data = NULL;
			}
		}
	}

	login_log(ip, sd->userid, 100, "login ok");
	ShowStatus("Connection of the account '%s' accepted.\n", sd->userid);

	WFIFOHEAD(fd,header+size*server_num);
	WFIFOW(fd,0) = cmd;
	WFIFOW(fd,2) = header+size*server_num;
	WFIFOL(fd,4) = sd->login_id1;
	WFIFOL(fd,8) = sd->account_id;
	WFIFOL(fd,12) = sd->login_id2;
	WFIFOL(fd,16) = 0; // in old version, that was for ip (not more used)
	//memcpy(WFIFOP(fd,20), sd->lastlogin, 24); // in old version, that was for name (not more used)
	memset(WFIFOP(fd,20), 0, 24);
	WFIFOW(fd,44) = 0; // unknown
	WFIFOB(fd,46) = sex_str2num(sd->sex);
#if PACKETVER >= 20170315
	memset(WFIFOP(fd,47),0,17); // Unknown
#endif
	for( i = 0, n = 0; i < ARRAYLENGTH(ch_server); ++i ) {
		if( !session_isValid(ch_server[i].fd) )
			continue;
		subnet_char_ip = lan_subnetcheck(ip); // Advanced subnet check [LuzZza]
		WFIFOL(fd,header+n*size) = htonl((subnet_char_ip) ? subnet_char_ip : ch_server[i].ip);
		WFIFOW(fd,header+n*size+4) = ntows(htons(ch_server[i].port)); // [!] LE byte order here [!]
		memcpy(WFIFOP(fd,header+n*size+6), ch_server[i].name, 20);
		WFIFOW(fd,header+n*size+26) = ch_server[i].users;
		WFIFOW(fd,header+n*size+28) = ch_server[i].type;
		WFIFOW(fd,header+n*size+30) = ch_server[i].new_;
#if PACKETVER >= 20170315
		memset(WFIFOP(fd, header+n*size+32), 0, 128); // Unknown
#endif
		n++;
	}
	WFIFOSET(fd,header+size*server_num);

	// create temporary auth entry
	CREATE(node, struct auth_node, 1);
	node->account_id = sd->account_id;
	node->login_id1 = sd->login_id1;
	node->login_id2 = sd->login_id2;
	node->sex = sd->sex;
	node->ip = ip;
	node->clienttype = sd->clienttype;
	idb_put(auth_db, sd->account_id, node);
	{
		struct online_login_data* data;
		// mark client as 'online'
		data = login_add_online_user(-1, sd->account_id);
		// schedule deletion of this node
		data->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, login_waiting_disconnect_timer, sd->account_id, 0);
	}
}
Exemplo n.º 15
0
// 0x7944 - request account id lookup by name (response: 0x7945)
// 0x7946 - request account name lookup by id (response: 0x7947)
// 0x7952 - request account information lookup by name (response: 0x7953)
// 0x7954 - request account information lookup by id (response: 0x7953)
//---------------------------------------
int parse_admin(int fd)
{
	unsigned int i, j;
	char* account_name;
	struct mmo_account acc;

	uint32 ipl = session[fd]->client_addr;
	char ip[16];
	ip2str(ipl, ip);

	if( session[fd]->flag.eof )
	{
		do_close(fd);
		ShowInfo("Remote administration has disconnected (session #%d).\n", fd);
		return 0;
	}

	while( RFIFOREST(fd) >= 2 )
	{
		uint16 command = RFIFOW(fd,0);

		switch( command )
		{
		
		case 0x7530:	// Request of the server version
			ShowStatus("'ladmin': Sending of the server version (ip: %s)\n", ip);
			WFIFOHEAD(fd,10);
			WFIFOW(fd,0) = 0x7531;
			WFIFOB(fd,2) = ATHENA_MAJOR_VERSION;
			WFIFOB(fd,3) = ATHENA_MINOR_VERSION;
			WFIFOB(fd,4) = ATHENA_REVISION;
			WFIFOB(fd,5) = ATHENA_RELEASE_FLAG;
			WFIFOB(fd,6) = ATHENA_OFFICIAL_FLAG;
			WFIFOB(fd,7) = ATHENA_SERVER_LOGIN;
			WFIFOW(fd,8) = ATHENA_MOD_VERSION;
			WFIFOSET(fd,10);
			RFIFOSKIP(fd,2);
			break;
/*
		case 0x7920:	// Request of an accounts list
			if (RFIFOREST(fd) < 10)
				return 0;
			{
				int st, ed;
				uint16 len;
				CREATE_BUFFER(id, int, auth_num);
				st = RFIFOL(fd,2);
				ed = RFIFOL(fd,6);
				RFIFOSKIP(fd,10);
				WFIFOW(fd,0) = 0x7921;
				if (st < 0)
					st = 0;
				if (ed > END_ACCOUNT_NUM || ed < st || ed <= 0)
					ed = END_ACCOUNT_NUM;
				ShowStatus("'ladmin': Sending an accounts list (ask: from %d to %d, ip: %s)\n", st, ed, ip);
				// Sort before send
				for(i = 0; i < auth_num; i++) {
					unsigned int k;
					id[i] = i;
					for(j = 0; j < i; j++) {
						if (auth_dat[id[i]].account_id < auth_dat[id[j]].account_id) {
							for(k = i; k > j; k--) {
								id[k] = id[k-1];
							}
							id[j] = i; // id[i]
							break;
						}
					}
				}
				// Sending accounts information
				len = 4;
				for(i = 0; i < auth_num && len < 30000; i++) {
					int account_id = auth_dat[id[i]].account_id; // use sorted index
					if (account_id >= st && account_id <= ed) {
						j = id[i];
						WFIFOL(fd,len) = account_id;
						WFIFOB(fd,len+4) = (unsigned char)isGM(account_id);
						memcpy(WFIFOP(fd,len+5), auth_dat[j].userid, 24);
						WFIFOB(fd,len+29) = auth_dat[j].sex;
						WFIFOL(fd,len+30) = auth_dat[j].logincount;
						if (auth_dat[j].state == 0 && auth_dat[j].unban_time != 0) // if no state and banished
							WFIFOL(fd,len+34) = 7; // 6 = Your are Prohibited to log in until %s
						else
							WFIFOL(fd,len+34) = auth_dat[j].state;
						len += 38;
					}
				}
				WFIFOW(fd,2) = len;
				WFIFOSET(fd,len);
				//if (id) free(id);
				DELETE_BUFFER(id);
			}
			break;
*/
		case 0x7930:	// Request for an account creation
			if (RFIFOREST(fd) < 91)
				return 0;
		{
			struct mmo_account ma;
			safestrncpy(ma.userid, (char*)RFIFOP(fd, 2), sizeof(ma.userid));
			safestrncpy(ma.pass, (char*)RFIFOP(fd,26), sizeof(ma.pass));
			ma.sex = RFIFOB(fd,50);
			safestrncpy(ma.email, (char*)RFIFOP(fd,51), sizeof(ma.email));
			safestrncpy(ma.lastlogin, "-", sizeof(ma.lastlogin));

			ShowNotice("'ladmin': Account creation request (account: %s pass: %s, sex: %c, email: %s, ip: %s)\n", ma.userid, ma.pass, ma.sex, ma.email, ip);

			WFIFOW(fd,0) = 0x7931;
			WFIFOL(fd,2) = mmo_auth_new(ma.userid, ma.pass, ma.sex, ip);
			safestrncpy((char*)WFIFOP(fd,6), ma.userid, 24);
			WFIFOSET(fd,30);
		}
			RFIFOSKIP(fd,91);
			break;
/*
		case 0x7932:	// Request for an account deletion
			if (RFIFOREST(fd) < 26)
				return 0;
		{
			struct mmo_account acc;

			char* account_name = (char*)RFIFOP(fd,2);
			account_name[23] = '\0';

			WFIFOW(fd,0) = 0x7933;

			if( accounts->load_str(accounts, &acc, account_name) )
			{
				// Char-server is notified of deletion (for characters deletion).
				unsigned char buf[65535];
				WBUFW(buf,0) = 0x2730;
				WBUFL(buf,2) = acc.account_id;
				charif_sendallwos(-1, buf, 6);

				// send answer
				memcpy(WFIFOP(fd,6), acc.userid, 24);
				WFIFOL(fd,2) = acc.account_id;

				// delete account
				memset(acc.userid, '\0', sizeof(acc.userid));
				auth_dat[i].account_id = -1;
				mmo_auth_sync();
			} else {
				WFIFOL(fd,2) = -1;
				memcpy(WFIFOP(fd,6), account_name, 24);
				ShowNotice("'ladmin': Attempt to delete an unknown account (account: %s, ip: %s)\n", account_name, ip);
			}
			WFIFOSET(fd,30);
		}
			RFIFOSKIP(fd,26);
			break;
*/
		case 0x7934:	// Request to change a password
			if (RFIFOREST(fd) < 50)
				return 0;
		{
			struct mmo_account acc;

			char* account_name = (char*)RFIFOP(fd,2);
			account_name[23] = '\0';

			WFIFOW(fd,0) = 0x7935;

			if( accounts->load_str(accounts, &acc, account_name) )
			{
				WFIFOL(fd,2) = acc.account_id;
				safestrncpy((char*)WFIFOP(fd,6), acc.userid, 24);
				safestrncpy(acc.pass, (char*)RFIFOP(fd,26), 24);
				ShowNotice("'ladmin': Modification of a password (account: %s, new password: %s, ip: %s)\n", acc.userid, acc.pass, ip);

				accounts->save(accounts, &acc);
			}
			else
			{
				WFIFOL(fd,2) = -1;
				safestrncpy((char*)WFIFOP(fd,6), account_name, 24);
				ShowNotice("'ladmin': Attempt to modify the password of an unknown account (account: %s, ip: %s)\n", account_name, ip);
			}

			WFIFOSET(fd,30);
		}
			RFIFOSKIP(fd,50);
			break;

		case 0x7936:	// Request to modify a state
			if (RFIFOREST(fd) < 50)
				return 0;
		{
			struct mmo_account acc;

			char* account_name = (char*)RFIFOP(fd,2);
			uint32 state = RFIFOL(fd,26);
			account_name[23] = '\0';

			WFIFOW(fd,0) = 0x7937;

			if( accounts->load_str(accounts, &acc, account_name) )
			{
				memcpy(WFIFOP(fd,6), acc.userid, 24);
				WFIFOL(fd,2) = acc.account_id;

				if (acc.state == state)
					ShowNotice("'ladmin': Modification of a state, but the state of the account already has this value (account: %s, received state: %d, ip: %s)\n", account_name, state, ip);
				else
				{
					ShowNotice("'ladmin': Modification of a state (account: %s, new state: %d, ip: %s)\n", acc.userid, state, ip);

					if (acc.state == 0) {
						unsigned char buf[16];
						WBUFW(buf,0) = 0x2731;
						WBUFL(buf,2) = acc.account_id;
						WBUFB(buf,6) = 0; // 0: change of statut, 1: ban
						WBUFL(buf,7) = state; // status or final date of a banishment
						charif_sendallwos(-1, buf, 11);
					}
					acc.state = state;
					accounts->save(accounts, &acc);
				}
			}
			else
			{
				ShowNotice("'ladmin': Attempt to modify the state of an unknown account (account: %s, received state: %d, ip: %s)\n", account_name, state, ip);
				WFIFOL(fd,2) = -1;
				memcpy(WFIFOP(fd,6), account_name, 24);
			}

			WFIFOL(fd,30) = state;
			WFIFOSET(fd,34);
		}
			RFIFOSKIP(fd,50);
			break;
/*
		case 0x7938:	// Request for servers list and # of online players
		{		
			uint8 server_num = 0;
			ShowStatus("'ladmin': Sending of servers list (ip: %s)\n", ip);
			for(i = 0; i < MAX_SERVERS; i++) {
				if (server[i].fd >= 0) {
					WFIFOL(fd,4+server_num*32) = htonl(server[i].ip);
					WFIFOW(fd,4+server_num*32+4) = htons(server[i].port);
					memcpy(WFIFOP(fd,4+server_num*32+6), server[i].name, 20);
					WFIFOW(fd,4+server_num*32+26) = server[i].users;
					WFIFOW(fd,4+server_num*32+28) = server[i].maintenance;
					WFIFOW(fd,4+server_num*32+30) = server[i].new_;
					server_num++;
				}
			}
			WFIFOW(fd,0) = 0x7939;
			WFIFOW(fd,2) = 4 + 32 * server_num;
			WFIFOSET(fd,4+32*server_num);
			RFIFOSKIP(fd,2);
			break;
		}

		case 0x793a:	// Request to password check
			if (RFIFOREST(fd) < 50)
				return 0;
			WFIFOW(fd,0) = 0x793b;
			WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
			account_name = (char*)RFIFOP(fd,2);
			account_name[23] = '\0';
			remove_control_chars(account_name);
			if( accounts->load_str(accounts, &acc, account_name) )
			{
				char pass[25];
				memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
				memcpy(pass, RFIFOP(fd,26), 24);
				pass[24] = '\0';
				remove_control_chars(pass);
				if (strcmp(acc.pass, pass) == 0) {
					WFIFOL(fd,2) = acc.account_id;
					ShowNotice("'ladmin': Check of password OK (account: %s, password: %s, ip: %s)\n", acc.userid, acc.pass, ip);
				} else {
					ShowNotice("'ladmin': Failure of password check (account: %s, proposed pass: %s, ip: %s)\n", acc.userid, pass, ip);
				}
			} else {
				memcpy(WFIFOP(fd,6), account_name, 24);
				ShowNotice("'ladmin': Attempt to check the password of an unknown account (account: %s, ip: %s)\n", account_name, ip);
			}
			WFIFOSET(fd,30);
			RFIFOSKIP(fd,50);
			break;

		case 0x793c:	// Request to modify sex
			if (RFIFOREST(fd) < 27)
				return 0;
			WFIFOW(fd,0) = 0x793d;
			WFIFOL(fd,2) = 0xFFFFFFFF; // -1
			account_name = (char*)RFIFOP(fd,2);
			account_name[23] = '\0';
			remove_control_chars(account_name);
			memcpy(WFIFOP(fd,6), account_name, 24);
			{
				char sex;
				sex = RFIFOB(fd,26);
				if (sex != 'F' && sex != 'M') {
					if (sex > 31)
						ShowNotice("'ladmin': Attempt to give an invalid sex (account: %s, received sex: %c, ip: %s)\n", account_name, sex, ip);
					else
						ShowNotice("'ladmin': Attempt to give an invalid sex (account: %s, received sex: 'control char', ip: %s)\n", account_name, ip);
				} else {
					if( accounts->load_str(accounts, &acc, account_name) )
					{
						memcpy(WFIFOP(fd,6), acc.userid, 24);
						if (acc.sex != sex)
						{
							unsigned char buf[16];
							ShowNotice("'ladmin': Modification of a sex (account: %s, new sex: %c, ip: %s)\n", acc.userid, sex, ip);

							WFIFOL(fd,2) = acc.account_id;
							acc.sex = sex;
							accounts->save(accounts, &acc);

							// send to all char-server the change
							WBUFW(buf,0) = 0x2723;
							WBUFL(buf,2) = acc.account_id;
							WBUFB(buf,6) = acc.sex;
							charif_sendallwos(-1, buf, 7);
						} else {
							ShowNotice("'ladmin': Modification of a sex, but the sex is already the good sex (account: %s, sex: %c, ip: %s)\n", acc.userid, sex, ip);
						}
					} else {
						ShowNotice("'ladmin': Attempt to modify the sex of an unknown account (account: %s, received sex: %c, ip: %s)\n", account_name, sex, ip);
					}
				}
			}
			WFIFOSET(fd,30);
			RFIFOSKIP(fd,27);
			break;

		case 0x793e:	// Request to modify GM level
			if (RFIFOREST(fd) < 27)
				return 0;
			WFIFOW(fd,0) = 0x793f;
			WFIFOL(fd,2) = 0xFFFFFFFF; // -1
			account_name = (char*)RFIFOP(fd,2);
			account_name[23] = '\0';
			remove_control_chars(account_name);
			memcpy(WFIFOP(fd,6), account_name, 24);
		{
			char new_gm_level;
			new_gm_level = RFIFOB(fd,26);
			if( new_gm_level < 0 || new_gm_level > 99 )
				ShowNotice("'ladmin': Attempt to give an invalid GM level (account: %s, received GM level: %d, ip: %s)\n", account_name, (int)new_gm_level, ip);
			else
			if( !accounts->load_str(accounts, &acc, account_name) )
				ShowNotice("'ladmin': Attempt to modify the GM level of an unknown account (account: %s, received GM level: %d, ip: %s)\n", account_name, (int)new_gm_level, ip);
			else
			{
				memcpy(WFIFOP(fd,6), acc.userid, 24);

				if (isGM(acc.account_id) == new_gm_level)
					ShowNotice("'ladmin': Attempt to modify of a GM level, but the GM level is already the good GM level (account: %s (%d), GM level: %d, ip: %s)\n", acc.userid, acc.account_id, (int)new_gm_level, ip);
				else
				{
					//TODO: change level
				}
			}
		}
			WFIFOSET(fd,30);
			RFIFOSKIP(fd,27);
			break;

		case 0x7940:	// Request to modify e-mail
			if (RFIFOREST(fd) < 66)
				return 0;
			WFIFOW(fd,0) = 0x7941;
			WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
			account_name = (char*)RFIFOP(fd,2);
			account_name[23] = '\0';
			remove_control_chars(account_name);
			memcpy(WFIFOP(fd,6), account_name, 24);
			{
				char email[40];
				memcpy(email, RFIFOP(fd,26), 40);
				if (e_mail_check(email) == 0) {
					ShowNotice("'ladmin': Attempt to give an invalid e-mail (account: %s, ip: %s)\n", account_name, ip);
				} else {
					remove_control_chars(email);
					i = search_account_index(account_name);
					if (i != -1) {
						memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
						memcpy(auth_dat[i].email, email, 40);
						WFIFOL(fd,2) = auth_dat[i].account_id;
						ShowNotice("'ladmin': Modification of an email (account: %s, new e-mail: %s, ip: %s)\n", auth_dat[i].userid, email, ip);
						mmo_auth_sync();
					} else {
						ShowNotice("'ladmin': Attempt to modify the e-mail of an unknown account (account: %s, received e-mail: %s, ip: %s)\n", account_name, email, ip);
					}
				}
			}
			WFIFOSET(fd,30);
			RFIFOSKIP(fd,66);
			break;

		case 0x7942:	// Request to modify memo field
			if ((int)RFIFOREST(fd) < 28 || (int)RFIFOREST(fd) < (28 + RFIFOW(fd,26)))
				return 0;
			WFIFOW(fd,0) = 0x7943;
			WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
			account_name = (char*)RFIFOP(fd,2);
			account_name[23] = '\0';
			remove_control_chars(account_name);
			i = search_account_index(account_name);
			if (i != -1) {
				int size_of_memo = sizeof(auth_dat[i].memo);
				memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
				memset(auth_dat[i].memo, '\0', size_of_memo);
				if (RFIFOW(fd,26) == 0) {
					strncpy(auth_dat[i].memo, "-", size_of_memo);
				} else if (RFIFOW(fd,26) > size_of_memo - 1) {
					memcpy(auth_dat[i].memo, RFIFOP(fd,28), size_of_memo - 1);
				} else {
					memcpy(auth_dat[i].memo, RFIFOP(fd,28), RFIFOW(fd,26));
				}
				auth_dat[i].memo[size_of_memo - 1] = '\0';
				remove_control_chars(auth_dat[i].memo);
				WFIFOL(fd,2) = auth_dat[i].account_id;
				ShowNotice("'ladmin': Modification of a memo field (account: %s, new memo: %s, ip: %s)\n", auth_dat[i].userid, auth_dat[i].memo, ip);
				mmo_auth_sync();
			} else {
				memcpy(WFIFOP(fd,6), account_name, 24);
				ShowNotice("'ladmin': Attempt to modify the memo field of an unknown account (account: %s, ip: %s)\n", account_name, ip);
			}
			WFIFOSET(fd,30);
			RFIFOSKIP(fd,28 + RFIFOW(fd,26));
			break;

		case 0x7944:	// Request to found an account id
			if (RFIFOREST(fd) < 26)
				return 0;
			WFIFOW(fd,0) = 0x7945;
			WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
			account_name = (char*)RFIFOP(fd,2);
			account_name[23] = '\0';
			remove_control_chars(account_name);
			i = search_account_index(account_name);
			if (i != -1) {
				memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
				WFIFOL(fd,2) = auth_dat[i].account_id;
				ShowNotice("'ladmin': Request (by the name) of an account id (account: %s, id: %d, ip: %s)\n", auth_dat[i].userid, auth_dat[i].account_id, ip);
			} else {
				memcpy(WFIFOP(fd,6), account_name, 24);
				ShowNotice("'ladmin': ID request (by the name) of an unknown account (account: %s, ip: %s)\n", account_name, ip);
			}
			WFIFOSET(fd,30);
			RFIFOSKIP(fd,26);
			break;

		case 0x7946:	// Request to found an account name
			if (RFIFOREST(fd) < 6)
				return 0;
			WFIFOW(fd,0) = 0x7947;
			WFIFOL(fd,2) = RFIFOL(fd,2);
			memset(WFIFOP(fd,6), '\0', 24);
			for(i = 0; i < auth_num; i++) {
				if (auth_dat[i].account_id == (int)RFIFOL(fd,2)) {
					strncpy((char*)WFIFOP(fd,6), auth_dat[i].userid, 24);
					ShowNotice("'ladmin': Request (by id) of an account name (account: %s, id: %d, ip: %s)\n", auth_dat[i].userid, RFIFOL(fd,2), ip);
					break;
				}
			}
			if (i == auth_num) {
				ShowNotice("'ladmin': Name request (by id) of an unknown account (id: %d, ip: %s)\n", RFIFOL(fd,2), ip);
				strncpy((char*)WFIFOP(fd,6), "", 24);
			}
			WFIFOSET(fd,30);
			RFIFOSKIP(fd,6);
			break;

		case 0x7948:	// Request to change the validity limit (timestamp) (absolute value)
			if (RFIFOREST(fd) < 30)
				return 0;
			{
				time_t timestamp;
				char tmpstr[2048];
				WFIFOW(fd,0) = 0x7949;
				WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
				account_name = (char*)RFIFOP(fd,2);
				account_name[23] = '\0';
				remove_control_chars(account_name);
				timestamp = (time_t)RFIFOL(fd,26);
				strftime(tmpstr, 24, login_config.date_format, localtime(&timestamp));
				i = search_account_index(account_name);
				if (i != -1) {
					memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
					ShowNotice("'ladmin': Change of a validity limit (account: %s, new validity: %d (%s), ip: %s)\n", auth_dat[i].userid, timestamp, (timestamp == 0 ? "unlimited" : tmpstr), ip);
					auth_dat[i].expiration_time = timestamp;
					WFIFOL(fd,2) = auth_dat[i].account_id;
					mmo_auth_sync();
				} else {
					memcpy(WFIFOP(fd,6), account_name, 24);
					ShowNotice("'ladmin': Attempt to change the validity limit of an unknown account (account: %s, received validity: %d (%s), ip: %s)\n", account_name, timestamp, (timestamp == 0 ? "unlimited" : tmpstr), ip);
				}
				WFIFOL(fd,30) = (unsigned int)timestamp;
			}
			WFIFOSET(fd,34);
			RFIFOSKIP(fd,30);
			break;

		case 0x794a:	// Request to change the final date of a banishment (timestamp) (absolute value)
			if (RFIFOREST(fd) < 30)
				return 0;
			{
				time_t timestamp;
				char tmpstr[2048];
				WFIFOW(fd,0) = 0x794b;
				WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
				account_name = (char*)RFIFOP(fd,2);
				account_name[23] = '\0';
				remove_control_chars(account_name);
				timestamp = (time_t)RFIFOL(fd,26);
				if (timestamp <= time(NULL))
					timestamp = 0;
				strftime(tmpstr, 24, login_config.date_format, localtime(&timestamp));
				i = search_account_index(account_name);
				if (i != -1) {
					memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
					WFIFOL(fd,2) = auth_dat[i].account_id;
					ShowNotice("'ladmin': Change of the final date of a banishment (account: %s, new final date of banishment: %d (%s), ip: %s)\n", auth_dat[i].userid, timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip);
					if (auth_dat[i].unban_time != timestamp) {
						if (timestamp != 0) {
							unsigned char buf[16];
							WBUFW(buf,0) = 0x2731;
							WBUFL(buf,2) = auth_dat[i].account_id;
							WBUFB(buf,6) = 1; // 0: change of statut, 1: ban
							WBUFL(buf,7) = (unsigned int)timestamp; // status or final date of a banishment
							charif_sendallwos(-1, buf, 11);
						}
						auth_dat[i].unban_time = timestamp;
						mmo_auth_sync();
					}
				} else {
					memcpy(WFIFOP(fd,6), account_name, 24);
					ShowNotice("'ladmin': Attempt to change the final date of a banishment of an unknown account (account: %s, received final date of banishment: %d (%s), ip: %s)\n", account_name, timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip);
				}
				WFIFOL(fd,30) = (unsigned int)timestamp;
			}
			WFIFOSET(fd,34);
			RFIFOSKIP(fd,30);
			break;

		case 0x794c:	// Request to change the final date of a banishment (timestamp) (relative change)
			if (RFIFOREST(fd) < 38)
				return 0;
			{
				time_t timestamp;
				struct tm *tmtime;
				char tmpstr[2048];
				WFIFOW(fd,0) = 0x794d;
				WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
				account_name = (char*)RFIFOP(fd,2);
				account_name[23] = '\0';
				remove_control_chars(account_name);
				i = search_account_index(account_name);
				if (i != -1) {
					WFIFOL(fd,2) = auth_dat[i].account_id;
					memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
					if (auth_dat[i].unban_time == 0 || auth_dat[i].unban_time < time(NULL))
						timestamp = time(NULL);
					else
						timestamp = auth_dat[i].unban_time;
					tmtime = localtime(&timestamp);
					tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,26);
					tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,28);
					tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,30);
					tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,32);
					tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,34);
					tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,36);
					timestamp = mktime(tmtime);
					if (timestamp != -1) {
						if (timestamp <= time(NULL))
							timestamp = 0;
						strftime(tmpstr, 24, login_config.date_format, localtime(&timestamp));
						ShowNotice("'ladmin': Adjustment of a final date of a banishment (account: %s, (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %d (%s), ip: %s)\n", auth_dat[i].userid, (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip);
						if (auth_dat[i].unban_time != timestamp) {
							if (timestamp != 0) {
								unsigned char buf[16];
								WBUFW(buf,0) = 0x2731;
								WBUFL(buf,2) = auth_dat[i].account_id;
								WBUFB(buf,6) = 1; // 0: change of statut, 1: ban
								WBUFL(buf,7) = (unsigned int)timestamp; // status or final date of a banishment
								charif_sendallwos(-1, buf, 11);
							}
							auth_dat[i].unban_time = timestamp;
							mmo_auth_sync();
						}
					} else {
						strftime(tmpstr, 24, login_config.date_format, localtime(&auth_dat[i].unban_time));
						ShowNotice("'ladmin': Impossible to adjust the final date of a banishment (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n", auth_dat[i].userid, auth_dat[i].unban_time, (auth_dat[i].unban_time == 0 ? "no banishment" : tmpstr), (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), ip);
					}
					WFIFOL(fd,30) = (unsigned long)auth_dat[i].unban_time;
				} else {
					memcpy(WFIFOP(fd,6), account_name, 24);
					ShowNotice("'ladmin': Attempt to adjust the final date of a banishment of an unknown account (account: %s, ip: %s)\n", account_name, ip);
					WFIFOL(fd,30) = 0;
				}
			}
			WFIFOSET(fd,34);
			RFIFOSKIP(fd,38);
			break;

		case 0x794e:	// Request to send a broadcast message
			if (RFIFOREST(fd) < 8 || RFIFOREST(fd) < (8 + RFIFOL(fd,4)))
				return 0;
			WFIFOW(fd,0) = 0x794f;
			WFIFOW(fd,2) = 0xFFFF; // WTF???
			if (RFIFOL(fd,4) < 1) {
				ShowNotice("'ladmin': Receiving a message for broadcast, but message is void (ip: %s)\n", ip);
			} else {
				// at least 1 char-server
				for(i = 0; i < MAX_SERVERS; i++)
					if (server[i].fd >= 0)
						break;
				if (i == MAX_SERVERS) {
					ShowNotice("'ladmin': Receiving a message for broadcast, but no char-server is online (ip: %s)\n", ip);
				} else {
					unsigned char buf[32000];
					char message[32000];
					WFIFOW(fd,2) = 0;
					memset(message, '\0', sizeof(message));
					memcpy(message, RFIFOP(fd,8), RFIFOL(fd,4));
					message[sizeof(message)-1] = '\0';
					remove_control_chars(message);
					if (RFIFOW(fd,2) == 0)
						ShowNotice("'ladmin': Receiving a message for broadcast (message (in yellow): %s, ip: %s)\n", message, ip);
					else
						ShowNotice("'ladmin': Receiving a message for broadcast (message (in blue): %s, ip: %s)\n", message, ip);
					// send same message to all char-servers (no answer)
					memcpy(WBUFP(buf,0), RFIFOP(fd,0), 8 + RFIFOL(fd,4));
					WBUFW(buf,0) = 0x2726;
					charif_sendallwos(-1, buf, 8 + RFIFOL(fd,4));
				}
			}
			WFIFOSET(fd,4);
			RFIFOSKIP(fd,8 + RFIFOL(fd,4));
			break;

		case 0x7950:	// Request to change the validity limite (timestamp) (relative change)
			if (RFIFOREST(fd) < 38)
				return 0;
		{
			time_t timestamp;
			struct tm *tmtime;
			char tmpstr[2048];
			char tmpstr2[2048];
			WFIFOW(fd,0) = 0x7951;
			WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
			account_name = (char*)RFIFOP(fd,2);
			account_name[23] = '\0';
			remove_control_chars(account_name);
			i = search_account_index(account_name);
			if (i != -1) {
				WFIFOL(fd,2) = auth_dat[i].account_id;
				memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
				timestamp = auth_dat[i].expiration_time;
				if (timestamp == 0 || timestamp < time(NULL))
					timestamp = time(NULL);
				tmtime = localtime(&timestamp);
				tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,26);
				tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,28);
				tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,30);
				tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,32);
				tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,34);
				tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,36);
				timestamp = mktime(tmtime);
				if (timestamp != -1) {
					strftime(tmpstr, 24, login_config.date_format, localtime(&auth_dat[i].expiration_time));
					strftime(tmpstr2, 24, login_config.date_format, localtime(&timestamp));
					ShowNotice("'ladmin': Adjustment of a validity limit (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %d (%s), ip: %s)\n", auth_dat[i].userid, auth_dat[i].expiration_time, (auth_dat[i].expiration_time == 0 ? "unlimited" : tmpstr), (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), timestamp, (timestamp == 0 ? "unlimited" : tmpstr2), ip);
					auth_dat[i].expiration_time = timestamp;
					mmo_auth_sync();
					WFIFOL(fd,30) = (unsigned long)auth_dat[i].expiration_time;
				} else {
					strftime(tmpstr, 24, login_config.date_format, localtime(&auth_dat[i].expiration_time));
					ShowNotice("'ladmin': Impossible to adjust a validity limit (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n", auth_dat[i].userid, auth_dat[i].expiration_time, (auth_dat[i].expiration_time == 0 ? "unlimited" : tmpstr), (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), ip);
					WFIFOL(fd,30) = 0;
				}
			} else {
				memcpy(WFIFOP(fd,6), account_name, 24);
				ShowNotice("'ladmin': Attempt to adjust the validity limit of an unknown account (account: %s, ip: %s)\n", account_name, ip);
				WFIFOL(fd,30) = 0;
			}

			WFIFOSET(fd,34);
		}
			RFIFOSKIP(fd,38);
			break;
*/
		case 0x7952:	// Request about informations of an account (by account name)
			if (RFIFOREST(fd) < 26)
				return 0;
		{
			struct mmo_account acc;

			WFIFOW(fd,0) = 0x7953;

			account_name = (char*)RFIFOP(fd,2);
			account_name[23] = '\0';

			if( accounts->load_str(accounts, &acc, account_name) )
			{
				ShowNotice("'ladmin': Sending information of an account (request by the name; account: %s, id: %d, ip: %s)\n", acc.userid, acc.account_id, ip);
				WFIFOL(fd,2) = acc.account_id;
				WFIFOB(fd,6) = acc.level;
				safestrncpy((char*)WFIFOP(fd,7), acc.userid, 24);
				WFIFOB(fd,31) = acc.sex;
				WFIFOL(fd,32) = acc.logincount;
				WFIFOL(fd,36) = acc.state;
				safestrncpy((char*)WFIFOP(fd,40), "-", 20); // error message (removed)
				safestrncpy((char*)WFIFOP(fd,60), acc.lastlogin, 24);
				safestrncpy((char*)WFIFOP(fd,84), acc.last_ip, 16);
				safestrncpy((char*)WFIFOP(fd,100), acc.email, 40);
				WFIFOL(fd,140) = (unsigned long)acc.expiration_time;
				WFIFOL(fd,144) = (unsigned long)acc.unban_time;
				WFIFOW(fd,148) = 0; // previously, this was strlen(memo), and memo went afterwards
			}
			else
			{
				ShowNotice("'ladmin': Attempt to obtain information (by the name) of an unknown account (account: %s, ip: %s)\n", account_name, ip);
				WFIFOL(fd,2) = -1;
				safestrncpy((char*)WFIFOP(fd,7), account_name, 24); // not found
			}

			WFIFOSET(fd,150);
		}
			RFIFOSKIP(fd,26);
			break;

		case 0x7954:	// Request about information of an account (by account id)
			if (RFIFOREST(fd) < 6)
				return 0;
		{
			struct mmo_account acc;

			int account_id = RFIFOL(fd,2);

			WFIFOHEAD(fd,150);
			WFIFOW(fd,0) = 0x7953;
			WFIFOL(fd,2) = account_id;

			if( accounts->load_num(accounts, &acc, account_id) )
			{
				ShowNotice("'ladmin': Sending information of an account (request by the id; account: %s, id: %d, ip: %s)\n", acc.userid, account_id, ip);
				WFIFOB(fd,6) = acc.level;
				safestrncpy((char*)WFIFOP(fd,7), acc.userid, 24);
				WFIFOB(fd,31) = acc.sex;
				WFIFOL(fd,32) = acc.logincount;
				WFIFOL(fd,36) = acc.state;
				safestrncpy((char*)WFIFOP(fd,40), "-", 20); // error message (removed)
				safestrncpy((char*)WFIFOP(fd,60), acc.lastlogin, 24);
				safestrncpy((char*)WFIFOP(fd,84), acc.last_ip, 16);
				safestrncpy((char*)WFIFOP(fd,100), acc.email, 40);
				WFIFOL(fd,140) = (unsigned long)acc.expiration_time;
				WFIFOL(fd,144) = (unsigned long)acc.unban_time;
				WFIFOW(fd,148) = 0; // previously, this was strlen(memo), and memo went afterwards
			}
			else
			{
				ShowNotice("'ladmin': Attempt to obtain information (by the id) of an unknown account (id: %d, ip: %s)\n", account_id, ip);
				safestrncpy((char*)WFIFOP(fd,7), "", 24); // not found
			}

			WFIFOSET(fd,150);
		}
			RFIFOSKIP(fd,6);
			break;

		default:
			ShowStatus("'ladmin': End of connection, unknown packet (ip: %s)\n", ip);
			set_eof(fd);
			return 0;
		}
	}
	RFIFOSKIP(fd,RFIFOREST(fd));
	return 0;
}
Exemplo n.º 16
0
/*
 * Transmit auth result to client
 * <result>.B ()
 * result :
 *  1 : Server closed
 *  2 : Someone has already logged in with this id
 *  8 : already online
 */
void chclif_send_auth_result(int fd,char result){
	WFIFOHEAD(fd,3);
	WFIFOW(fd,0) = 0x81;
	WFIFOB(fd,2) = result;
	WFIFOSET(fd,3);
}
Exemplo n.º 17
0
/**
 * Entry point from client to log-server.
 * Function that checks incoming command, then splits it to the correct handler.
 * @param fd: file descriptor to parse, (link to client)
 * @return 0=invalid session,marked for disconnection,unknow packet, banned..; 1=success
 */
int logclif_parse(int fd) {
	struct login_session_data* sd = (struct login_session_data*)session[fd]->session_data;

	char ip[16];
	uint32 ipl = session[fd]->client_addr;
	ip2str(ipl, ip);

	if( session[fd]->flag.eof )
	{
		ShowInfo("Closed connection from '" CL_WHITE "%s" CL_RESET "'.\n", ip);
		do_close(fd);
		return 0;
	}

	if( sd == NULL )
	{
		// Perform ip-ban check
		if( login_config.ipban && ipban_check(ipl) )
		{
			ShowStatus("Connection refused: IP isn't authorised (deny/allow, ip: %s).\n", ip);
			login_log(ipl, "unknown", -3, "ip banned");
			WFIFOHEAD(fd,23);
			WFIFOW(fd,0) = 0x6a;
			WFIFOB(fd,2) = 3; // 3 = Rejected from Server
			WFIFOSET(fd,23);
			set_eof(fd);
			return 0;
		}
		// create a session for this new connection
		CREATE(session[fd]->session_data, struct login_session_data, 1);
		sd = (struct login_session_data*)session[fd]->session_data;
		sd->fd = fd;
	}

	while( RFIFOREST(fd) >= 2 )
	{
		uint16 command = RFIFOW(fd,0);
		int next=1;

		switch( command )
		{
		// New alive packet: used to verify if client is always alive.
		case 0x0200: next = logclif_parse_keepalive(fd); break;
		// client md5 hash (binary)
		case 0x0204: next = logclif_parse_updclhash(fd,sd); break;
		// request client login (raw password)
		case 0x0064: // S 0064 <version>.L <username>.24B <password>.24B <clienttype>.B
		case 0x0277: // S 0277 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B
		case 0x02b0: // S 02b0 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B <g_isGravityID>.B
		// request client login (md5-hashed password)
		case 0x01dd: // S 01dd <version>.L <username>.24B <password hash>.16B <clienttype>.B
		case 0x01fa: // S 01fa <version>.L <username>.24B <password hash>.16B <clienttype>.B <?>.B(index of the connection in the clientinfo file (+10 if the command-line contains "pc"))
		case 0x027c: // S 027c <version>.L <username>.24B <password hash>.16B <clienttype>.B <?>.13B(junk)
		case 0x0825: // S 0825 <packetsize>.W <version>.L <clienttype>.B <userid>.24B <password>.27B <mac>.17B <ip>.15B <token>.(packetsize - 0x5C)B
			next = logclif_parse_reqauth(fd,  sd, command, ip); 
			break;
		// Sending request of the coding key
		case 0x01db: next = logclif_parse_reqkey(fd, sd); break;
		// Connection request of a char-server
		case 0x2710: logclif_parse_reqcharconnec(fd,sd, ip); return 0; // processing will continue elsewhere
		default:
			ShowNotice("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, command);
			set_eof(fd);
			return 0;
		}
		if(next==0) return 0; // avoid processing of followup packets (prev was probably incomplete)
	}

	return 0;
}
Exemplo n.º 18
0
void mapif_Mail_getattach(int fd, uint32 char_id, int mail_id, int type)
{
	struct mail_message msg;

	if( ( type&MAIL_ATT_ALL ) == 0 ){
		return;
	}

	if( !mail_loadmessage(mail_id, &msg) )
		return;

	if( msg.dest_id != char_id )
		return;

	if( msg.status != MAIL_READ )
		return;

	if( type & MAIL_ATT_ZENY ){
		if( msg.zeny > 0 ){
			if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `zeny` = 0 WHERE `id` = '%d'", schema_config.mail_db, mail_id ) ){
				Sql_ShowDebug(sql_handle);
				return;
			}
		}else{
			type &= ~MAIL_ATT_ZENY;
		}
	}

	if( type & MAIL_ATT_ITEM ){
		int i;

		ARR_FIND(0, MAIL_MAX_ITEM, i, msg.item[i].nameid > 0 && msg.item[i].amount > 0);

		// No item was found
		if( i == MAIL_MAX_ITEM ){
			type &= ~MAIL_ATT_ITEM;
		}else{
			if( !mail_DeleteAttach(mail_id) ){
				return;
			}
		}
	}

	if( type == MAIL_ATT_NONE )
		return; // No Attachment

	WFIFOHEAD(fd, sizeof(struct item)*MAIL_MAX_ITEM + 16);
	WFIFOW(fd,0) = 0x384a;
	WFIFOW(fd,2) = sizeof(struct item)*MAIL_MAX_ITEM + 16;
	WFIFOL(fd,4) = char_id;
	WFIFOL(fd,8) = mail_id;
	if( type & MAIL_ATT_ZENY ){
		WFIFOL(fd,12) = msg.zeny;
	}else{
		WFIFOL(fd, 12) = 0;
	}
	if( type & MAIL_ATT_ITEM ){
		memcpy(WFIFOP(fd, 16), &msg.item, sizeof(struct item)*MAIL_MAX_ITEM);
	}else{
		memset(WFIFOP(fd, 16), 0, sizeof(struct item)*MAIL_MAX_ITEM);
	}
	WFIFOSET(fd,WFIFOW(fd,2));
}
Exemplo n.º 19
0
// Load account_reg from sql (type=2)
int inter_accreg_fromsql(int account_id,int 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'", char_reg_str_db, 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'", acc_reg_str_db, 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 work!\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((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);
	
	switch( type ) {
		case 3: //char reg
			if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `char_id`='%d'", char_reg_num_db, 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'", acc_reg_num_db, 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 work!\n");
			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) = 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((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) = type;
	WFIFOW(fd, 2) = plen;
	WFIFOSET(fd, plen);
	
	SQL->FreeResult(sql_handle);
	return 1;
}
Exemplo n.º 20
0
// パーティ情報要求
void intif_request_partyinfo(int party_id)
{
    WFIFOW(char_fd, 0) = 0x3021;
    WFIFOL(char_fd, 2) = party_id;
    WFIFOSET(char_fd, 6);
}
Exemplo n.º 21
0
/*! 
 *  \brief     Parse from Client
 *  
 *  \author    Fimbulwinter Development Team
 *  \author    GreenBox
 *  \date      08/12/11
 *
 **/
int CharServer::parse_from_client(tcp_connection::pointer cl)
{
	CharSessionData *csd = ((CharSessionData *)cl->get_data());

	if (cl->flags.eof)
	{
		if (csd && csd->auth && auth_conn_ok)
		{
			WFIFOHEAD(auth_conn,6);
			WFIFOW(auth_conn,0) = INTER_CA_SET_ACC_OFF;
			WFIFOL(auth_conn,2) = csd->account_id;
			auth_conn->send_buffer(6);
		}

		set_char_offline(csd->account_id, -1);

		if (csd)
			delete csd;

		ShowInfo("Closed connection from '"CL_WHITE"%s"CL_RESET"'.\n", cl->socket().remote_endpoint().address().to_string().c_str());
		cl->do_close();
		return 0;
	}

	while(RFIFOREST(cl) >= 2)
	{
		unsigned short cmd = RFIFOW(cl, 0);

#define FIFOSD_CHECK(rest) { if(RFIFOREST(cl) < rest) return 0; if (csd==NULL || !csd->auth) { cl->skip(rest); return 0; } }

		switch (cmd)
		{
		case HEADER_CH_SELECT_CHAR:
			FIFOSD_CHECK(3);
			{
				int slot = RFIFOB(cl,2);
				int char_id;
				CharData cd;

				cl->skip(3);

				{
					statement s = (database->prepare << "SELECT `char_id` FROM `char` WHERE `account_id`=:a AND `char_num`=:s",
						use(csd->account_id), use(slot), into(char_id));

					s.execute(true);

					if (s.get_affected_rows() <= 0)
					{
						WFIFOPACKET(cl, spacket, HC_REFUSE_ENTER);
						spacket->error_code = 0;
						cl->send_buffer(sizeof(struct PACKET_HC_REFUSE_ENTER));
					}
				}

				chars->load_char(char_id, cd, true);

				int server = -1;
				if (map_to_zone.count(cd.last_point.map))
					server = map_to_zone[cd.last_point.map];

				if (server < 0)
				{
					// TODO: Find for major city

					WFIFOPACKET(cl, spacket, SC_NOTIFY_BAN);
					spacket->error_code = 1;
					cl->send_buffer(sizeof(struct PACKET_SC_NOTIFY_BAN));
					break;
				}

				auth_nodes[csd->account_id].sex = csd->sex;
				auth_nodes[csd->account_id].char_id = char_id;
				auth_nodes[csd->account_id].gmlevel = csd->gmlevel;
				auth_nodes[csd->account_id].login_id1 = csd->login_id1;
				auth_nodes[csd->account_id].login_id2 = csd->login_id2;
				auth_nodes[csd->account_id].expiration_time = csd->expiration_time;

				WFIFOPACKET(cl, spacket, HC_NOTIFY_ZONESVR);
				spacket->char_id = char_id;
				maps.copy_map_name_ext((char*)spacket->map_name, cd.last_point.map);
				spacket->addr.ip = htonl(servers[server].addr.to_ulong());
				spacket->addr.port = servers[server].port;
				cl->send_buffer(sizeof(struct PACKET_HC_NOTIFY_ZONESVR));
			}
			break;

		case HEADER_CH_REQUEST_DEL_TIMER:
			FIFOSD_CHECK(6);
			delete2_req(cl, csd);
			cl->skip(6);
			break;

		case HEADER_CH_ACCEPT_DEL_REQ:
			FIFOSD_CHECK(12);
			delete2_accept(cl, csd);
			cl->skip(6);
			break;

		case HEADER_CH_CANCEL_DEL_REQ:
			FIFOSD_CHECK(6);
			delete2_cancel(cl, csd);
			cl->skip(6);
			break;

		case HEADER_CH_DELETE_CHAR:
		case HEADER_CH_DELETE_CHAR2:
			if (cmd == HEADER_CH_DELETE_CHAR) FIFOSD_CHECK(sizeof(struct PACKET_CH_DELETE_CHAR));
			if (cmd == HEADER_CH_DELETE_CHAR2) FIFOSD_CHECK(sizeof(struct PACKET_CH_DELETE_CHAR2));
			{
				int cid = RFIFOL(cl,2);
				char email[40];
				memcpy(email, RFIFOP(cl,6), 40);

				cl->skip((cmd == HEADER_CH_DELETE_CHAR) ? sizeof(struct PACKET_CH_DELETE_CHAR) : sizeof(struct PACKET_CH_DELETE_CHAR2));

				if (_strcmpi(email, csd->email) != 0 && (strcmp("*****@*****.**", csd->email) || (strcmp("*****@*****.**", email) && strcmp("", email))))
				{
					WFIFOPACKET(cl, spacket, HC_REFUSE_DELETECHAR); 
					spacket->error_code = 0;
					cl->send_buffer(sizeof(struct PACKET_HC_REFUSE_DELETECHAR));
					break;
				}

				bool found = false;
				int i, ch;
				for (i = 0; i < MAX_CHARS; i++)
				{
					if (csd->found_char[i] == cid)
					{
						found = true;
						break;
					}
				}

				if (!found)
				{
					WFIFOPACKET(cl, spacket, HC_REFUSE_DELETECHAR); 
					spacket->error_code = 0;
					cl->send_buffer(sizeof(struct PACKET_HC_REFUSE_DELETECHAR));
					break;
				}
				else
				{
					for(ch = i; ch < MAX_CHARS - 1; ch++)
						csd->found_char[ch] = csd->found_char[ch+1];

					csd->found_char[MAX_CHARS - 1] = -1;

					if (!chars->delete_char(cid))
					{
						WFIFOPACKET(cl, spacket, HC_REFUSE_DELETECHAR); 
						spacket->error_code = 0;
						cl->send_buffer(sizeof(struct PACKET_HC_REFUSE_DELETECHAR));
						break;
					}

					WFIFOPACKET(cl, spacket, HC_ACCEPT_DELETECHAR);
					cl->send_buffer(sizeof(struct PACKET_HC_ACCEPT_DELETECHAR));
				}
			}
			break;

		case HEADER_CH_MAKE_CHAR:
			FIFOSD_CHECK(sizeof(struct PACKET_CH_MAKE_CHAR));
			{
				TYPECAST_PACKET(RFIFOP(cl,0),rpacket,CH_MAKE_CHAR);

				// TODO: Check create char disabled
				int i = create_char(csd, (char*)rpacket->name,rpacket->str,rpacket->agi,rpacket->vit,rpacket->int_,rpacket->dex,rpacket->luk,rpacket->char_slot,rpacket->head_color,rpacket->head_style);

				//'Charname already exists' (-1), 'Char creation denied' (-2) and 'You are underaged' (-3)
				if (i < 0)
				{
					WFIFOPACKET(cl, spacket, HC_REFUSE_MAKECHAR);

					switch (i) {
					case -1: spacket->error_code = 0x00; break;
					case -2: spacket->error_code = 0xFF; break;
					case -3: spacket->error_code = 0x01; break;
					}

					cl->send_buffer(sizeof(struct PACKET_HC_REFUSE_MAKECHAR));
				}
				else
				{
					// retrieve data
					CharData char_dat;
					memset(&char_dat, 0, sizeof(CharData));
					chars->load_char(i, char_dat, false); //Only the short data is needed.

					// send to player
					WFIFOPACKET(cl, spacket, HC_ACCEPT_MAKECHAR);

					char_to_buf(&spacket->charinfo, &char_dat);

					cl->send_buffer(sizeof(struct PACKET_HC_ACCEPT_MAKECHAR));

					// add new entry to the chars list
					for (int n = 0; n < MAX_CHARS; n++)
					{
						if(csd->found_char[n] == -1)
							csd->found_char[n] = i; // the char_id of the new char
					}
				}
				cl->skip(sizeof(struct PACKET_CH_MAKE_CHAR));
			}
			break;

		case HEADER_CH_ENTER_CHECKBOT:
			FIFOSD_CHECK(sizeof(struct PACKET_CH_ENTER_CHECKBOT));
			{
				WFIFOPACKET(cl, spacket, HC_CHECKBOT_RESULT);
				spacket->packet_len = sizeof(struct PACKET_HC_CHECKBOT_RESULT);
				spacket->result = 1;
				cl->send_buffer(spacket->packet_len);
				cl->skip(TYPECAST_PACKET_ONCE(RFIFOP(cl,0), CH_ENTER_CHECKBOT)->packet_len);
			}
			break;

		case HEADER_CH_CHECKBOT:
			FIFOSD_CHECK(sizeof(struct PACKET_CH_CHECKBOT));
			{
				WFIFOPACKET(cl, spacket, HC_CHECKBOT_RESULT);
				spacket->packet_len = sizeof(struct PACKET_HC_CHECKBOT_RESULT);
				spacket->result = 1;
				cl->send_buffer(spacket->packet_len);
				cl->skip(TYPECAST_PACKET_ONCE(RFIFOP(cl,0), CH_CHECKBOT)->packet_len);
			}
			break;

		case HEADER_CH_ENTER:
			if(RFIFOREST(cl) < sizeof(struct PACKET_CH_ENTER))
				return 0;
			{
				int account_id = RFIFOL(cl,2);
				unsigned int login_id1 = RFIFOL(cl,6);
				unsigned int login_id2 = RFIFOL(cl,10);
				char sex = RFIFOB(cl,16);
				cl->skip(sizeof(struct PACKET_CH_ENTER));

				if (csd)
				{
					break;
				}

				csd = new CharSessionData();
				csd->account_id = account_id;
				csd->login_id1 = login_id1;
				csd->login_id2 = login_id2;
				csd->sex = sex;
				csd->auth = false;
				csd->cl = cl;
				cl->set_data((char*)csd);

				WFIFOHEAD(cl, 4);
				WFIFOL(cl,0) = account_id;
				cl->send_buffer(4);

				if (auth_nodes.count(account_id) && 
					auth_nodes[account_id].login_id1  == login_id1 &&
					auth_nodes[account_id].login_id2  == login_id2)
				{
					auth_nodes.erase(account_id);
					auth_ok(cl, csd);
				}
				else
				{
					if (auth_conn_ok)
					{
						WFIFOHEAD(auth_conn,19);
						WFIFOW(auth_conn,0) = INTER_CA_AUTH;
						WFIFOL(auth_conn,2) = csd->account_id;
						WFIFOL(auth_conn,6) = csd->login_id1;
						WFIFOL(auth_conn,10) = csd->login_id2;
						WFIFOB(auth_conn,14) = csd->sex;
						WFIFOL(auth_conn,15) = cl->tag();
						auth_conn->send_buffer(19);
					}
					else
					{
						WFIFOPACKET(cl, spacket, HC_REFUSE_ENTER);
						spacket->error_code = 0;
						cl->send_buffer(sizeof(struct PACKET_HC_REFUSE_ENTER));
					}
				}
			}
			break;

		case HEADER_PING:
			if (RFIFOREST(cl) < sizeof(PACKET_PING))
				return 0;
			cl->skip(sizeof(PACKET_PING));
			break;

		case INTER_ZC_LOGIN:
			if (RFIFOREST(cl) < 60)
				return 0;
			{
				char *user = (char*)RFIFOP(cl, 2);
				char *pass = (char*)RFIFOP(cl, 26);

				if (strcmp(user, config.inter_login_user.c_str()) || strcmp(pass, config.inter_login_pass.c_str()))
				{
					WFIFOHEAD(cl, 3);
					WFIFOW(cl, 0) = INTER_CZ_LOGIN_REPLY;
					WFIFOB(cl, 2) = 1;
					cl->send_buffer(3);
				}
				else
				{
					int id = cl->tag();
					servers[id].cl = cl;
					servers[id].addr = address_v4(ntohl(RFIFOL(cl, 54)));
					servers[id].port = ntohs(RFIFOW(cl, 58));
					servers[id].users = 0;
					
					cl->set_parser(&CharServer::parse_from_zone);
					cl->flags.server = 1;
					cl->realloc_fifo(FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);

					WFIFOHEAD(cl, 3);
					WFIFOW(cl, 0) = INTER_CZ_LOGIN_REPLY;
					WFIFOB(cl, 2) = 0;
					cl->send_buffer(3);
				}

				cl->skip(60);
			}
			break;

		default:
			ShowWarning("Unknown packet 0x%04x sent from %s, closing connection.\n", cmd, cl->socket().remote_endpoint().address().to_string().c_str());
			cl->set_eof();
			return 0;
		}
	}

	return 0;
}
Exemplo n.º 22
0
/**
 * Player requesting to change map-serv
 * @param fd: wich fd to parse from
 * @return : 0 not enough data received, 1 success
 */
int chmapif_parse_reqchangemapserv(int fd){
	if (RFIFOREST(fd) < 39)
		return 0;
	{
		int map_id, map_fd = -1;
		struct mmo_charstatus* char_data;
		struct mmo_charstatus char_dat;
		DBMap* char_db_ = char_get_chardb();

		map_id = char_search_mapserver(RFIFOW(fd,18), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port.
		if (map_id >= 0)
			map_fd = map_server[map_id].fd;
		//Char should just had been saved before this packet, so this should be safe. [Skotlex]
		char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14));
		if (char_data == NULL) {	//Really shouldn't happen.
			char_mmo_char_fromsql(RFIFOL(fd,14), &char_dat, true);
			char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14));
		}

		if( runflag == CHARSERVER_ST_RUNNING &&
			session_isActive(map_fd) &&
			char_data )
		{	//Send the map server the auth of this player.
			struct online_char_data* data;
			struct auth_node* node;
			DBMap*  auth_db = char_get_authdb();
			DBMap* online_char_db = char_get_onlinedb();

			int aid = RFIFOL(fd,2);

			//Update the "last map" as this is where the player must be spawned on the new map server.
			char_data->last_point.map = RFIFOW(fd,18);
			char_data->last_point.x = RFIFOW(fd,20);
			char_data->last_point.y = RFIFOW(fd,22);
			char_data->sex = RFIFOB(fd,30);

			// create temporary auth entry
			CREATE(node, struct auth_node, 1);
			node->account_id = aid;
			node->char_id = RFIFOL(fd,14);
			node->login_id1 = RFIFOL(fd,6);
			node->login_id2 = RFIFOL(fd,10);
			node->sex = RFIFOB(fd,30);
			node->expiration_time = 0; // FIXME (this thing isn't really supported we could as well purge it instead of fixing)
			node->ip = ntohl(RFIFOL(fd,31));
			node->group_id = RFIFOL(fd,35);
			node->changing_mapservers = 1;
			idb_put(auth_db, aid, node);

			data = idb_ensure(online_char_db, aid, char_create_online_data);
			data->char_id = char_data->char_id;
			data->server = map_id; //Update server where char is.

			//Reply with an ack.
			WFIFOHEAD(fd,30);
			WFIFOW(fd,0) = 0x2b06;
			memcpy(WFIFOP(fd,2), RFIFOP(fd,2), 28);
			WFIFOSET(fd,30);
		} else { //Reply with nak
			WFIFOHEAD(fd,30);
			WFIFOW(fd,0) = 0x2b06;
			memcpy(WFIFOP(fd,2), RFIFOP(fd,2), 28);
			WFIFOL(fd,6) = 0; //Set login1 to 0.
			WFIFOSET(fd,30);
		}
		RFIFOSKIP(fd,39);
	}
Exemplo n.º 23
0
// 倉庫データ要求
void intif_request_storage(int account_id)
{
    WFIFOW(char_fd, 0) = 0x3010;
    WFIFOL(char_fd, 2) = account_id;
    WFIFOSET(char_fd, 6);
}
Exemplo n.º 24
0
void chlogif_send_setallaccoffline(int fd){
	WFIFOHEAD(fd,2);
	WFIFOW(fd,0) = 0x2737;
	WFIFOSET(fd,2);
}
Exemplo n.º 25
0
// pings the charserver
void chrif_keepalive(int fd)
{
	WFIFOHEAD(fd,2);
	WFIFOW(fd,0) = 0x2b23;
	WFIFOSET(fd,2);
}
Exemplo n.º 26
0
int chlogif_parse(int fd) {
	struct char_session_data* sd = NULL;

	// only process data from the login-server
	if( fd != login_fd ) {
		ShowDebug("parse_fromlogin: Disconnecting invalid session #%d (is not the login-server)\n", fd);
		do_close(fd);
		return 0;
	}

	if( session[fd]->flag.eof ) {
		do_close(fd);
		login_fd = -1;
		chlogif_on_disconnect();
		return 0;
	} else if ( session[fd]->flag.ping ) {/* we've reached stall time */
		if( DIFF_TICK(last_tick, session[fd]->rdata_tick) > (stall_time * 2) ) {/* we can't wait any longer */
			set_eof(fd);
			return 0;
		} else if( session[fd]->flag.ping != 2 ) { /* we haven't sent ping out yet */
			WFIFOHEAD(fd,2);// sends a ping packet to login server (will receive pong 0x2718)
			WFIFOW(fd,0) = 0x2719;
			WFIFOSET(fd,2);

			session[fd]->flag.ping = 2;
		}
	}

	sd = (struct char_session_data*)session[fd]->session_data;

	while(RFIFOREST(fd) >= 2) {
		int next=1;
		uint16 command = RFIFOW(fd,0);
		switch( command )
		{
			case 0x2741: next = chlogif_parse_BankingAck(fd); break;
			case 0x2743: next = chlogif_parse_vipack(fd); break;
			// acknowledgement of connect-to-loginserver request
			case 0x2711: next = chlogif_parse_ackconnect(fd,sd); break;
			// acknowledgement of account authentication request
			case 0x2713: next = chlogif_parse_ackaccreq(fd, sd); break;
			// account data
			case 0x2717: next = chlogif_parse_reqaccdata(fd, sd); break;
			// login-server alive packet
			case 0x2718: next = chlogif_parse_keepalive(fd, sd); break;
			// changesex reply
			case 0x2723: next = chlogif_parse_ackchangesex(fd, sd); break;
			// reply to an account_reg2 registry request
			case 0x2729: next = chlogif_parse_ackacc2req(fd, sd); break;
			// State change of account/ban notification (from login-server)
			case 0x2731: next = chlogif_parse_accbannotification(fd, sd); break;
			// Login server request to kick a character out. [Skotlex]
			case 0x2734: next = chlogif_parse_askkick(fd,sd); break;
			// ip address update signal from login server
			case 0x2735: next = chlogif_parse_updip(fd,sd); break;
			// @accinfo result
			case 0x2721: next = chlogif_parse_AccInfoAck(fd); break;
			default:
				ShowError("Unknown packet 0x%04x received from login-server, disconnecting.\n", command);
				set_eof(fd);
				return 0;
		}
		if(next==0) return 0; //do not parse next data
	}

	RFIFOFLUSH(fd);
	return 0;
}
Exemplo n.º 27
0
void pincode_notifyLoginPinError(int account_id) {
	WFIFOHEAD(chr->login_fd,6);
	WFIFOW(chr->login_fd,0) = 0x2739;
	WFIFOL(chr->login_fd,2) = account_id;
	WFIFOSET(chr->login_fd,6);
}
Exemplo n.º 28
0
/**
 * Transmit auth result to client.
 * @param fd: client file desciptor link
 * @param result: result to transmit to client, see below
 *  1 : Server closed
 *  2 : Someone has already logged in with this id
 *  8 : already online
 * <result>.B (SC_NOTIFY_BAN)
 */
static void logclif_sent_auth_result(int fd,char result){
	WFIFOHEAD(fd,3);
	WFIFOW(fd,0) = 0x81;
	WFIFOB(fd,2) = result;
	WFIFOSET(fd,3);
}
Exemplo n.º 29
0
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(<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((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(<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((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);
}
Exemplo n.º 30
0
/**
 * Char-server request to connect to the login-server.
 * This is needed to exchange packets.
 * @param fd: file descriptor to parse from (client)
 * @param sd: client session
 * @param ip: ipv4 address (client)
 * @return 0 packet received too shirt, 1 success
 */
static int logclif_parse_reqcharconnec(int fd, struct login_session_data *sd, char* ip){
	if (RFIFOREST(fd) < 86)
		return 0;
	else {
		int result;
		char server_name[20];
		char message[256];
		uint32 server_ip;
		uint16 server_port;
		uint16 type;
		uint16 new_;

		safestrncpy(sd->userid, RFIFOCP(fd,2), NAME_LENGTH);
		safestrncpy(sd->passwd, RFIFOCP(fd,26), NAME_LENGTH);
		if( login_config.use_md5_passwds )
			MD5_String(sd->passwd, sd->passwd);
		sd->passwdenc = 0;
		server_ip = ntohl(RFIFOL(fd,54));
		server_port = ntohs(RFIFOW(fd,58));
		safestrncpy(server_name, RFIFOCP(fd,60), 20);
		type = RFIFOW(fd,82);
		new_ = RFIFOW(fd,84);
		RFIFOSKIP(fd,86);

		ShowInfo("Connection request of the char-server '%s' @ %u.%u.%u.%u:%u (account: '%s', ip: '%s')\n", server_name, CONVIP(server_ip), server_port, sd->userid, ip);
		sprintf(message, "charserver - %s@%u.%u.%u.%u:%u", server_name, CONVIP(server_ip), server_port);
		login_log(session[fd]->client_addr, sd->userid, 100, message);

		result = login_mmo_auth(sd, true);
		if( runflag == LOGINSERVER_ST_RUNNING &&
			result == -1 &&
			sd->sex == 'S' &&
			sd->account_id < ARRAYLENGTH(ch_server) &&
			!session_isValid(ch_server[sd->account_id].fd) )
		{
			ShowStatus("Connection of the char-server '%s' accepted.\n", server_name);
			safestrncpy(ch_server[sd->account_id].name, server_name, sizeof(ch_server[sd->account_id].name));
			ch_server[sd->account_id].fd = fd;
			ch_server[sd->account_id].ip = server_ip;
			ch_server[sd->account_id].port = server_port;
			ch_server[sd->account_id].users = 0;
			ch_server[sd->account_id].type = type;
			ch_server[sd->account_id].new_ = new_;

			session[fd]->func_parse = logchrif_parse;
			session[fd]->flag.server = 1;
			realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);

			// send connection success
			WFIFOHEAD(fd,3);
			WFIFOW(fd,0) = 0x2711;
			WFIFOB(fd,2) = 0;
			WFIFOSET(fd,3);
		}
		else
		{
			ShowNotice("Connection of the char-server '%s' REFUSED.\n", server_name);
			WFIFOHEAD(fd,3);
			WFIFOW(fd,0) = 0x2711;
			WFIFOB(fd,2) = 3;
			WFIFOSET(fd,3);
		}
	}
	return 1;
}