Example #1
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) {
		// -1: Login server is not connected
		//  0: Avoid processing followup packets (prev was probably incomplete) packet
		//  1: Continue parsing
		int next = 1;
		uint16 command = RFIFOW(fd,0);
		switch( command ) {
			case 0x2711: next = chlogif_parse_ackconnect(fd,sd); break;
			case 0x2713: next = chlogif_parse_ackaccreq(fd, sd); break;
			case 0x2717: next = chlogif_parse_reqaccdata(fd, sd); break;
			case 0x2718: next = chlogif_parse_keepalive(fd, sd); break;
			case 0x2721: next = chlogif_parse_AccInfoAck(fd); break;
			case 0x2723: next = chlogif_parse_ackchangesex(fd, sd); break;
			case 0x2726: next = chlogif_parse_ack_global_accreg(fd, sd); break;
			case 0x2731: next = chlogif_parse_accbannotification(fd, sd); break;
			case 0x2734: next = chlogif_parse_askkick(fd,sd); break;
			case 0x2735: next = chlogif_parse_updip(fd,sd); break;
			case 0x2743: next = chlogif_parse_vipack(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;
}
Example #2
0
int recv_to_fifo(int fd)
{
	int len;

	if( !session_isActive(fd) )
		return -1;

	len = sRecv(fd, (char *) session[fd]->rdata + session[fd]->rdata_size, (int)RFIFOSPACE(fd), 0);

	if( len == SOCKET_ERROR )
	{//An exception has occured
		if( sErrno != S_EWOULDBLOCK ) {
			//ShowDebug("recv_to_fifo: code %d, closing connection #%d\n", sErrno, fd);
			set_eof(fd);
		}
		return 0;
	}

	if( len == 0 )
	{//Normal connection end.
		set_eof(fd);
		return 0;
	}

	session[fd]->rdata_size += len;
	session[fd]->rdata_tick = last_tick;
	return 0;
}
Example #3
0
int recv_to_fifo(int fd)
{
	int len;

	if( !session_isActive(fd) )
		return -1;

	len = sRecv(fd, (char *) session[fd]->rdata + session[fd]->rdata_size, (int)RFIFOSPACE(fd), 0);

	if( len == SOCKET_ERROR ) { //An exception has occured
		if( sErrno != S_EWOULDBLOCK ) {
			//ShowDebug("recv_to_fifo: %s, closing connection #%d\n", error_msg(), fd);
			set_eof(fd);
		}
		return 0;
	}

	if( len == 0 ) { //Normal connection end.
		set_eof(fd);
		return 0;
	}

	session[fd]->rdata_size += len;
	session[fd]->rdata_tick = last_tick;
#ifdef SHOW_SERVER_STATS
	socket_data_i += len;
	socket_data_qi += len;
	if (!session[fd]->flag.server) {
		socket_data_ci += len;
	}
#endif
	return 0;
}
void tcp_connection::handle_read(const boost::system::error_code &error, size_t bytes_transferred)
{
	if (!socket_.is_open() && !flags.eof)
	{
		set_eof();
	}

	if (flags.eof)
		return;

	if (error)
	{
		set_eof();
		do_close();
	}
	else if (bytes_transferred == 0)
	{
		set_eof();
		do_close();
	}
	else
	{
		rdata_size += bytes_transferred;

		if (parse_)
			parse_((pointer)this->shared_from_this());

		RFIFOFLUSH(this);

		start_read();
	}
}
Example #5
0
/**
 * Entry point from char-server to log-server.
 * Function that checks incoming command, then splits it to the correct handler.
 * @param fd: file descriptor to parse, (link to char-serv)
 * @return 0=invalid server,marked for disconnection,unknow packet; 1=success
 */
int logchrif_parse(int fd){
	int cid; //char-serv id
	uint32 ipl;
	char ip[16];

	ARR_FIND( 0, ARRAYLENGTH(ch_server), cid, ch_server[cid].fd == fd );
	if( cid == ARRAYLENGTH(ch_server) ){// not a char server
		ShowDebug("logchrif_parse: Disconnecting invalid session #%d (is not a char-server)\n", fd);
		set_eof(fd);
		do_close(fd);
		return 0;
	}

	if( session[fd]->flag.eof ){
		do_close(fd);
		ch_server[cid].fd = -1;
		logchrif_on_disconnect(cid);
		return 0;
	}

	ipl = ch_server[cid].ip;
	ip2str(ipl, ip);

	while( RFIFOREST(fd) >= 2 ){
		int next = 1; // 0: avoid processing followup packets (prev was probably incomplete) packet, 1: Continue parsing
		uint16 command = RFIFOW(fd,0);
		switch( command ){
			case 0x2712: next = logchrif_parse_reqauth(fd, cid, ip); break;
			case 0x2714: next = logchrif_parse_ackusercount(fd, cid); break;
			case 0x2716: next = logchrif_parse_reqaccdata(fd, cid, ip); break;
			case 0x2719: next = logchrif_parse_keepalive(fd); break;
			case 0x2720: next = logchrif_parse_accinfo(fd); break; //@accinfo from inter-server
			case 0x2722: next = logchrif_parse_reqchangemail(fd,cid,ip); break;
			case 0x2724: next = logchrif_parse_requpdaccstate(fd,cid,ip); break;
			case 0x2725: next = logchrif_parse_reqbanacc(fd,cid,ip); break;
			case 0x2727: next = logchrif_parse_reqchgsex(fd,cid,ip); break;
			case 0x2728: next = logchrif_parse_upd_global_accreg(fd,cid,ip); break;
			case 0x272a: next = logchrif_parse_requnbanacc(fd,cid,ip); break;
			case 0x272b: next = logchrif_parse_setacconline(fd,cid); break;
			case 0x272c: next = logchrif_parse_setaccoffline(fd); break;
			case 0x272d: next = logchrif_parse_updonlinedb(fd,cid); break;
			case 0x272e: next = logchrif_parse_req_global_accreg(fd); break;
			case 0x2736: next = logchrif_parse_updcharip(fd,cid); break;
			case 0x2737: next = logchrif_parse_setalloffline(fd,cid); break;
#if PACKETVER_SUPPORTS_PINCODE
			case 0x2738: next = logchrif_parse_updpincode(fd); break;
			case 0x2739: next = logchrif_parse_pincode_authfail(fd); break;
#endif
			case 0x2742: next = logchrif_parse_reqvipdata(fd); break; //Vip sys
			default:
				ShowError("logchrif_parse: Unknown packet 0x%x from a char-server! Disconnecting!\n", command);
				set_eof(fd);
				return 0;
		} // switch
		if (next == 0)
			return 0;
	} // while
	return 1; //or 0
}
Example #6
0
/**
 * Check here hacker for duplicate item in trade
 * normal client refuse to have 2 same types of item (except equipment) in same trade window
 * normal client authorise only no equipped item and only from inventory
 * This function could end player connection if too much hack is detected
 * @param sd : player to check
 * @return -1:zeny hack, 0:all fine, 1:item hack
 */
int impossible_trade_check(struct map_session_data *sd)
{
	struct item inventory[MAX_INVENTORY];
	char message_to_gm[200];
	int i, index;

	nullpo_retr(1, sd);

	if(sd->deal.zeny > sd->status.zeny) {
		pc_setglobalreg(sd,"ZENY_HACKER",1);
		return -1;
	}

	// get inventory of player
	memcpy(&inventory, &sd->status.inventory, sizeof(struct item) * MAX_INVENTORY);

	// remove this part: arrows can be trade and equipped
	// re-added! [celest]
	// remove equipped items (they can not be trade)
	for (i = 0; i < MAX_INVENTORY; i++)
		if (inventory[i].nameid > 0 && inventory[i].equip && !(inventory[i].equip & EQP_AMMO))
			memset(&inventory[i], 0, sizeof(struct item));

	// check items in player inventory
	for(i = 0; i < 10; i++) {
		if (!sd->deal.item[i].amount)
			continue;

		index = sd->deal.item[i].index;

		if (inventory[index].amount < sd->deal.item[i].amount) { // if more than the player have -> hack
			sprintf(message_to_gm, msg_txt(sd,538), sd->status.name, sd->status.account_id); // Hack on trade: character '%s' (account: %d) try to trade more items that he has.
			intif_wis_message_to_gm(wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
			sprintf(message_to_gm, msg_txt(sd,539), inventory[index].amount, inventory[index].nameid, sd->deal.item[i].amount); // This player has %d of a kind of item (id: %d), and try to trade %d of them.
			intif_wis_message_to_gm(wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
			// if we block people
			if (battle_config.ban_hack_trade < 0) {
				chrif_req_login_operation(-1, sd->status.name, CHRIF_OP_LOGIN_BLOCK, 0, 0, 0); // type: 1 - block
				set_eof(sd->fd); // forced to disconnect because of the hack
				// message about the ban
				strcpy(message_to_gm, msg_txt(sd,540)); //  This player has been definitively blocked.
			// if we ban people
			} else if (battle_config.ban_hack_trade > 0) {
				chrif_req_login_operation(-1, sd->status.name, CHRIF_OP_LOGIN_BAN, battle_config.ban_hack_trade*60, 0, 0); // type: 2 - ban (year, month, day, hour, minute, second)
				set_eof(sd->fd); // forced to disconnect because of the hack
				// message about the ban
				sprintf(message_to_gm, msg_txt(sd,507), battle_config.ban_hack_trade); //  This player has been banned for %d minute(s).
			} else
				// message about the ban
				strcpy(message_to_gm, msg_txt(sd,508)); //  This player hasn't been banned (Ban option is disabled).

			intif_wis_message_to_gm(wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
			return 1;
		}

		inventory[index].amount -= sd->deal.item[i].amount; // remove item from inventory
	}
	return 0;
}
Example #7
0
static int recv_to_fifo(int fd)
{
	int len;

	if( (fd<0) || (fd>=FD_SETSIZE) || (NULL==session[fd]) )
		return -1;

	if(session[fd]->eof)
		return -1;

#ifdef __WIN32
	len=recv(fd,(char *)session[fd]->rdata+session[fd]->rdata_size, RFIFOSPACE(fd), 0);
	if (len == SOCKET_ERROR) {
		if (WSAGetLastError() == WSAECONNABORTED) {
			ShowWarning("recv_to_fifo: software de conexao cancelado na sessao #%d\n", fd);
			FD_CLR(fd, &readfds); //Remove the socket so the select() won't hang on it.
//			exit(1);	//Windows can't really recover from this one. [Skotlex]
		}
		if (WSAGetLastError() != WSAEWOULDBLOCK) {
//			ShowDebug("recv_to_fifo: error %d, ending connection #%d\n", WSAGetLastError(), fd);
			set_eof(fd);
		}
		return 0;
	}
#else
	len=read(fd,session[fd]->rdata+session[fd]->rdata_size, RFIFOSPACE(fd));
	if (len == -1)
	{
		if (errno == ECONNABORTED)
		{
			ShowFatalError("recv_to_fifo: Quebra de conexao (software de conexao cancelado na sessao #%d)\n", fd);
//			exit(1); //Temporal debug, maybe this can be fixed.
		}
		if (errno != EAGAIN) {	//Connection error.
//			perror("closing session: recv_to_fifo");
			set_eof(fd);
		}
		return 0;
	}
#endif
	if (len <= 0) {	//Normal connection end.
		set_eof(fd);
		return 0;
	}

	session[fd]->rdata_size+=len;
	session[fd]->rdata_tick = last_tick;
	return 0;
}
Example #8
0
File: dev.c Project: dl5rcw/bareos
/*
 * Called to indicate that we have just read an EOF from the device.
 */
void DEVICE::set_ateof()
{
   set_eof();
   file_addr = 0;
   file_size = 0;
   block_num = 0;
}
Example #9
0
int chlogif_parse_askkick(int fd, struct char_session_data* sd){
	if (RFIFOREST(fd) < 6)
		return 0;
	else {
		DBMap*  online_char_db = char_get_onlinedb();
		DBMap*  auth_db = char_get_authdb();
		int aid = RFIFOL(fd,2);
		struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, aid);
		RFIFOSKIP(fd,6);
		if( character != NULL )
		{// account is already marked as online!
			if( character->server > -1 )
			{	//Kick it from the map server it is on.
				mapif_disconnectplayer(map_server[character->server].fd, character->account_id, character->char_id, 2);
				if (character->waiting_disconnect == INVALID_TIMER)
					character->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, char_chardb_waiting_disconnect, character->account_id, 0);
			}
			else
			{// Manual kick from char server.
				struct char_session_data *tsd;
				int i;
				ARR_FIND( 0, fd_max, i, session[i] && (tsd = (struct char_session_data*)session[i]->session_data) && tsd->account_id == aid );
				if( i < fd_max )
				{
					chclif_send_auth_result(i,2);  //Send "Someone has already logged in with this id"
					set_eof(i);
				}
				else // still moving to the map-server
					char_set_char_offline(-1, aid);
			}
		}
		idb_remove(auth_db, aid);// reject auth attempts from map-server
	}
	return 1;
}
Example #10
0
int send_from_fifo(int fd)
{
	int len;

	if( !session_isValid(fd) )
		return -1;

	if( session[fd]->wdata_size == 0 )
		return 0; // nothing to send

	len = sSend(fd, (const char *) session[fd]->wdata, (int)session[fd]->wdata_size, 0);

	if( len == SOCKET_ERROR )
	{//An exception has occured
		if( sErrno != S_EWOULDBLOCK ) {
			//ShowDebug("send_from_fifo: error %d, ending connection #%d\n", sErrno, fd);
			session[fd]->wdata_size = 0; //Clear the send queue as we can't send anymore. [Skotlex]
			set_eof(fd);
		}
		return 0;
	}

	if( len > 0 )
	{
		// some data could not be transferred?
		// shift unsent data to the beginning of the queue
		if( (size_t)len < session[fd]->wdata_size )
			memmove(session[fd]->wdata, session[fd]->wdata + len, session[fd]->wdata_size - len);

		session[fd]->wdata_size -= len;
	}

	return 0;
}
/*
 * Called to indicate that we have just read an EOF from the device.
 */
void generic_tape_device::set_ateof()
{
   set_eof();
   file++;
   file_addr = 0;
   file_size = 0;
   block_num = 0;
}
Example #12
0
/*
 * Called to indicate that we have just read an
 *  EOF from the device.
 */
void DEVICE::set_ateof()
{
   set_eof();
   if (is_tape()) {
      file++;
   }
   file_addr = 0;
   file_size = 0;
   block_num = 0;
}
Example #13
0
/*==========================================
 * Request char server to change sex of char (modified by Yor)
 *------------------------------------------*/
int chrif_changedsex(int fd) {
	int acc, sex;
	struct map_session_data *sd;

	acc = RFIFOL(fd,2);
	sex = RFIFOL(fd,6);
	
	if ( battle_config.etc_log )
		ShowNotice("chrif_changedsex %d.\n", acc);
	
	sd = map_id2sd(acc);
	if ( sd ) { //Normally there should not be a char logged on right now!
		if ( sd->status.sex == sex ) 
			return 0; //Do nothing? Likely safe.
		sd->status.sex = !sd->status.sex;

		// reset skill of some job
		if ((sd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER) {
			int i, idx = 0;
			// remove specifical skills of Bard classes 
			for(i = 315; i <= 322; i++) {
				idx = skill->get_index(i);
				if (sd->status.skill[idx].id > 0 && sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT) {
					sd->status.skill_point += sd->status.skill[idx].lv;
					sd->status.skill[idx].id = 0;
					sd->status.skill[idx].lv = 0;
				}
			}
			// remove specifical skills of Dancer classes 
			for(i = 323; i <= 330; i++) {
				idx = skill->get_index(i);
				if (sd->status.skill[idx].id > 0 && sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT) {
					sd->status.skill_point += sd->status.skill[idx].lv;
					sd->status.skill[idx].id = 0;
					sd->status.skill[idx].lv = 0;
				}
			}
			clif->updatestatus(sd, SP_SKILLPOINT);
			// change job if necessary
			if (sd->status.sex) //Changed from Dancer
				sd->status.class_ -= 1;
			else	//Changed from Bard
				sd->status.class_ += 1;
			//sd->class_ needs not be updated as both Dancer/Bard are the same.
		}
		// save character
		sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters
							  // do same modify in login-server for the account, but no in char-server (it ask again login_id1 to login, and don't remember it)
		clif->message(sd->fd, msg_txt(409)); //"Your sex has been changed (need disconnection by the server)..."
		set_eof(sd->fd); // forced to disconnect for the change
		map_quit(sd); // Remove leftovers (e.g. autotrading) [Paradox924X]
	}
	return 0;
}
void tcp_connection::handle_write(const boost::system::error_code &error)
{
	if (!error)
	{
		wdata_size = 0;
	}
	else
	{
		set_eof();
		do_close();
	}
}
Example #15
0
/**
 * Load permission for player based on group id
 * @param sd Player
 */
void pc_group_pc_load(struct map_session_data * sd) {
	GroupSettings *group = NULL;
	if ((group = id2group(sd->group_id)) == NULL) {
		ShowWarning("pc_group_pc_load: %s (AID:%d) logged in with unknown group id (%d)! kicking...\n",
					sd->status.name,
					sd->status.account_id,
					sd->group_id);
		set_eof(sd->fd);
		return;
	}
	sd->permissions = group->e_permissions;
	sd->group_pos = group->group_pos;
	sd->group_level = group->level;
}
Example #16
0
File: vbl.c Project: DrItanium/moo
void rewind_recording(
	void)
{
	if(replay.game_is_being_recorded)
	{
		/* This is unnecessary, because it is called from reset_player_queues, */
		/* which is always called from revert_game */
		set_eof(replay.recording_file_refnum, sizeof(struct recording_header));
		set_fpos(replay.recording_file_refnum, sizeof(struct recording_header));

		replay.header.length= sizeof(struct recording_header);
	}
	
	return;
}
Example #17
0
/*==========================================
 * Disconnection of a player (account has been banned of has a status, from login-server) by [Yor]
 *------------------------------------------*/
int chrif_accountban(int fd)
{
	int acc;
	struct map_session_data *sd;

	acc = RFIFOL(fd,2);
	if (battle_config.etc_log)
		ShowNotice("chrif_accountban %d.\n", acc);
	sd = map_id2sd(acc);

	if (acc < 0 || sd == NULL) {
		ShowError("chrif_accountban failed - player not online.\n");
		return 0;
	}

	sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters
	if (RFIFOB(fd,6) == 0) // 0: change of statut, 1: ban
	{ 
		switch (RFIFOL(fd,7)) { // status or final date of a banishment
		case 1: clif_displaymessage(sd->fd, "Your account has 'Unregistered'."); break;
		case 2: clif_displaymessage(sd->fd, "Your account has an 'Incorrect Password'..."); break;
		case 3: clif_displaymessage(sd->fd, "Your account has expired."); break;
		case 4: clif_displaymessage(sd->fd, "Your account has been rejected from server."); break;
		case 5: clif_displaymessage(sd->fd, "Your account has been blocked by the GM Team."); break;
		case 6: clif_displaymessage(sd->fd, "Your Game's EXE file is not the latest version."); break;
		case 7: clif_displaymessage(sd->fd, "Your account has been prohibited to log in."); break;
		case 8: clif_displaymessage(sd->fd, "Server is jammed due to over populated."); break;
		case 9: clif_displaymessage(sd->fd, "Your account has not more authorised."); break;
		case 100: clif_displaymessage(sd->fd, "Your account has been totally erased."); break;
		default:  clif_displaymessage(sd->fd, "Your account has not more authorised."); break;
		}
	}
	else if (RFIFOB(fd,6) == 1) // 0: change of statut, 1: ban
	{ 
		time_t timestamp;
		char tmpstr[2048];
		timestamp = (time_t)RFIFOL(fd,7); // status or final date of a banishment
		strcpy(tmpstr, "Your account has been banished until ");
		strftime(tmpstr + strlen(tmpstr), 24, "%d-%m-%Y %H:%M:%S", localtime(&timestamp));
		clif_displaymessage(sd->fd, tmpstr);
	}

	set_eof(sd->fd); // forced to disconnect for the change
	map_quit(sd); // Remove leftovers (e.g. autotrading) [Paradox924X]
	return 0;
}
Example #18
0
/*==========================================
 * Disconnection of a player (account has been banned of has a status, from login-server) by [Yor]
 *------------------------------------------*/
int chrif_accountban(int fd)
{
	int acc;
	struct map_session_data *sd;

	acc = RFIFOL(fd,2);
	if (battle_config.etc_log)
		ShowNotice("chrif_accountban %d.\n", acc);
	sd = map_id2sd(acc);

	if (acc < 0 || sd == NULL) {
		ShowError("chrif_accountban failed - player not online.\n");
		return 0;
	}

	sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters
	if (RFIFOB(fd,6) == 0) // 0: change of statut, 1: ban
	{ 
		switch (RFIFOL(fd,7)) { // status or final date of a banishment
		case 1: clif_displaymessage(sd->fd, "Your account has 'Unregistered'."); break;
		case 2: clif_displaymessage(sd->fd, "Senha incorreta..."); break;
		case 3: clif_displaymessage(sd->fd, "Sua conta expirou."); break;
		case 4: clif_displaymessage(sd->fd, "Sua conta foi rejeitada pelo map-server."); break;
		case 5: clif_displaymessage(sd->fd, "Sua conta foi bloqueada pela staff do server."); break;
		case 6: clif_displaymessage(sd->fd, "Seu EXE do jogo nуo estс na њltima versуo."); break;
		case 7: clif_displaymessage(sd->fd, "Sua conta foi proibida de fazer login."); break;
		case 8: clif_displaymessage(sd->fd, "Servidor estс lotado."); break;
		case 9: clif_displaymessage(sd->fd, "Your account has not more authorised."); break;
		case 100: clif_displaymessage(sd->fd, "Sua conta foi totalmente apagada."); break;
		default:  clif_displaymessage(sd->fd, "Your account has not more authorised."); break;
		}
	}
	else if (RFIFOB(fd,6) == 1) // 0: change of statut, 1: ban
	{ 
		time_t timestamp;
		char tmpstr[2048];
		timestamp = (time_t)RFIFOL(fd,7); // status or final date of a banishment
		strcpy(tmpstr, "Sua conta foi banida atщ ");
		strftime(tmpstr + strlen(tmpstr), 24, "%d-%m-%Y %H:%M:%S", localtime(&timestamp));
		clif_displaymessage(sd->fd, tmpstr);
	}

	set_eof(sd->fd); // forced to disconnect for the change
	map_quit(sd); // Remove leftovers (e.g. autotrading) [Paradox924X]
	return 0;
}
Example #19
0
/*==========================================
 * Disconnection of a player (account has been banned of has a status, from login-server) by [Yor]
 *------------------------------------------*/
int chrif_accountban(int fd)
{
	int acc;
	struct map_session_data *sd;

	acc = RFIFOL(fd,2);
	if (battle_config.etc_log)
		ShowNotice("chrif_accountban %d.\n", acc);
	sd = map_id2sd(acc);

	if (acc < 0 || sd == NULL) {
		ShowError("chrif_accountban falhou - personagem nao encontrado.\n");
		return 0;
	}

	sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters
	if (RFIFOB(fd,6) == 0) // 0: change of statut, 1: ban
	{ 
		switch (RFIFOL(fd,7)) { // status or final date of a banishment
		case 1: clif_displaymessage(sd->fd, "Sua conta encontra-se 'N�o Registrada'."); break;
		case 2: clif_displaymessage(sd->fd, "Sua conta encontra-se com a 'Senha Incorreta'..."); break;
		case 3: clif_displaymessage(sd->fd, "Sua conta foi expirada."); break;
		case 4: clif_displaymessage(sd->fd, "Sua conta foi rejeitada pelo servidor."); break;
		case 5: clif_displaymessage(sd->fd, "Sua conta foi bloqueada pela Equipe de GMs."); break;
		case 6: clif_displaymessage(sd->fd, "Seu execut�vel do jogo n�o encontra-se na �ltima vers�o."); break;
		case 7: clif_displaymessage(sd->fd, "Sua conta est� proibida de se conectar."); break;
		case 8: clif_displaymessage(sd->fd, "Servidor encontra-se lotado devido ao excesso de usu�rios."); break;
		case 9: clif_displaymessage(sd->fd, "Sua conta n�o est� mais autorizada ao acesso."); break;
		case 100: clif_displaymessage(sd->fd, "Sua conta foi totalmente apagada."); break;
		default:  clif_displaymessage(sd->fd, "Sua conta n�o est� mais autorizada ao acesso."); break;
		}
	}
	else if (RFIFOB(fd,6) == 1) // 0: change of statut, 1: ban
	{ 
		time_t timestamp;
		char tmpstr[2048];
		timestamp = (time_t)RFIFOL(fd,7); // status or final date of a banishment
		strcpy(tmpstr, "Sua conta foi banida at� ");
		strftime(tmpstr + strlen(tmpstr), 24, "%d-%m-%Y %H:%M:%S", localtime(&timestamp));
		clif_displaymessage(sd->fd, tmpstr);
	}

	set_eof(sd->fd); // forced to disconnect for the change
	map_quit(sd); // Remove leftovers (e.g. autotrading) [Paradox924X]
	return 0;
}
Example #20
0
int send_from_fifo(int fd)
{
	ssize_t len;

	if( !sockt->session_isValid(fd) )
		return -1;

	if( session[fd]->wdata_size == 0 )
		return 0; // nothing to send

	len = sSend(fd, (const char *) session[fd]->wdata, (int)session[fd]->wdata_size, MSG_NOSIGNAL);

	if( len == SOCKET_ERROR )
	{//An exception has occured
		if( sErrno != S_EWOULDBLOCK ) {
			//ShowDebug("send_from_fifo: %s, ending connection #%d\n", error_msg(), fd);
#ifdef SHOW_SERVER_STATS
			socket_data_qo -= session[fd]->wdata_size;
#endif
			session[fd]->wdata_size = 0; //Clear the send queue as we can't send anymore. [Skotlex]
			set_eof(fd);
		}
		return 0;
	}

	if( len > 0 )
	{
		// some data could not be transferred?
		// shift unsent data to the beginning of the queue
		if( (size_t)len < session[fd]->wdata_size )
			memmove(session[fd]->wdata, session[fd]->wdata + len, session[fd]->wdata_size - len);

		session[fd]->wdata_size -= len;
#ifdef SHOW_SERVER_STATS
		socket_data_o += len;
		socket_data_qo -= len;
		if (!session[fd]->flag.server)
		{
			socket_data_co += len;
		}
#endif
	}

	return 0;
}
Example #21
0
/**
 * Make a player join a channel
 * - Add player to channel user list
 * - Add channel to user channel list
 * @param channel: Channel data
 * @param sd: Player data
 * @return
 *   0: Success
 *  -1: Invalid channel or player
 *  -2: Player already in channel
 *  -3: Player banned
 *  -4: Reached max limit
 */
int channel_join(struct Channel *channel, struct map_session_data *sd) {
	if(!channel || !sd)
		return -1;
	if(sd->state.autotrade)
		return 0; // fake success
	if(channel_haspc(channel,sd)==1)
		return -2;
	if (!pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) && !channel_pccheckgroup(channel, sd->group_id))
		return -2;

	if(channel_haspcbanned(channel,sd)==1){
		char output[CHAT_SIZE_MAX];
		sprintf(output, msg_txt(sd,1438),channel->name); //You're currently banned from the '%s' channel.
		clif_displaymessage(sd->fd, output);
		return -3;
	}

	if (channel->type == CHAN_TYPE_PRIVATE && db_size(channel->users) >= channel_config.private_channel.max_member) {
		char output[CHAT_SIZE_MAX];
		sprintf(output, msg_txt(sd,760), channel->name, channel_config.private_channel.max_member); // You cannot join channel '%s'. Limit of %d has been met.
		clif_displaymessage(sd->fd, output);
		return -4;
	}

	RECREATE(sd->channels, struct Channel *, ++sd->channel_count);
	sd->channels[ sd->channel_count - 1 ] = channel;
	idb_put(channel->users, sd->status.char_id, sd);
	RECREATE(sd->channel_tick, t_tick, sd->channel_count);
	sd->channel_tick[sd->channel_count-1] = 0;

	if( sd->stealth ) {
		sd->stealth = false;
	} else if( channel->opt & CHAN_OPT_ANNOUNCE_JOIN ) {
		char output[CHAT_SIZE_MAX];
		safesnprintf(output, CHAT_SIZE_MAX, msg_txt(sd,761), channel->alias, sd->status.name); // %s %s has joined.
		clif_channel_msg(channel,output,channel->color);
	}

	/* someone is cheating, we kindly disconnect the bastard */
	if( sd->channel_count > 200 ) {
		set_eof(sd->fd);
	}

	return 0;
}
Example #22
0
/*==========================================
 * Request auth confirmation
 *------------------------------------------*/
void chrif_authreq(struct map_session_data *sd) {
	struct auth_node *node= chrif_search(sd->bl.id);

	if( node != NULL || !chrif_isconnected() ) {
		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);
}
Example #23
0
int cOStream::Read(const char *buf, int len) {
	if (!good()) {
		return -1;
	}

	if (buf==nullptr || len <= 0)
		return 0;
	
	if (len > size()) {
		len = size();
	}
	memcpy(buf, data(), len);
	pos_ = len;
	if (pos() == size()) {
		set_eof(true);
	}
	return len;
}
Example #24
0
int chlogif_parse_ackconnect(int fd, struct char_session_data* sd){
	if (RFIFOREST(fd) < 3)
		return 0;

	if (RFIFOB(fd,2)) {
		//printf("connect login server error : %d\n", RFIFOB(fd,2));
		ShowError("Can not connect to login-server.\n");
		ShowError("The server communication passwords (default s1/p1) are probably invalid.\n");
		ShowError("Also, please make sure your login db has the correct communication username/passwords and the gender of the account is S.\n");
		ShowError("The communication passwords are set in map_athena.conf and char_athena.conf\n");
		set_eof(fd);
		return 0;
	} else {
		ShowStatus("Connected to login-server (connection #%d).\n", fd);
		chlogif_on_ready();
	}
	RFIFOSKIP(fd,3);
	return 1;
}
Example #25
0
/*==========================================
 * Disconnection of a player (account has been deleted in login-server) by [Yor]
 *------------------------------------------*/
int chrif_accountdeletion(int fd)
{
	int acc;
	struct map_session_data *sd;

	acc = RFIFOL(fd,2);
	if (battle_config.etc_log)
		ShowNotice("chrif_accountdeletion %d.\n", acc);
	sd = map_id2sd(acc);
	if (acc > 0) {
		if (sd != NULL) {
			sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters
			clif_displaymessage(sd->fd, "Your account has been deleted (disconnection)...");
			set_eof(sd->fd); // forced to disconnect for the change
		}
	} else {
		if (sd != NULL)
			ShowError("chrif_accountdeletion failed - player not online.\n");
	}

	return 0;
}
Example #26
0
/*==========================================
 * Disconnection of a player (account has been banned of has a status, from login-server) by [Yor]
 *------------------------------------------*/
int chrif_accountban(int fd) {
	int acc;
	struct map_session_data *sd;

	acc = RFIFOL(fd,2);
	
	if ( battle_config.etc_log )
		ShowNotice("chrif_accountban %d.\n", acc);
	
	sd = map_id2sd(acc);

	if ( acc < 0 || sd == NULL ) {
		ShowError("chrif_accountban failed - player not online.\n");
		return 0;
	}

	sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters
	if (RFIFOB(fd,6) == 0) { // 0: change of statut, 1: ban
                int ret_status = RFIFOL(fd,7); // status or final date of a banishment
                if(0<ret_status && ret_status<=9)
                    clif->message(sd->fd, msg_txt(411+ret_status));
                else if(ret_status==100)
                    clif->message(sd->fd, msg_txt(421));
                else    
                    clif->message(sd->fd, msg_txt(420)); //"Your account has not more authorised."
	} else if (RFIFOB(fd,6) == 1) { // 0: change of statut, 1: ban
		time_t timestamp;
		char tmpstr[2048];
		timestamp = (time_t)RFIFOL(fd,7); // status or final date of a banishment
		strcpy(tmpstr, msg_txt(423)); //"Your account has been banished until "
		strftime(tmpstr + strlen(tmpstr), 24, "%d-%m-%Y %H:%M:%S", localtime(&timestamp));
		clif->message(sd->fd, tmpstr);
	}

	set_eof(sd->fd); // forced to disconnect for the change
	map_quit(sd); // Remove leftovers (e.g. autotrading) [Paradox924X]
	return 0;
}
Example #27
0
/*==========================================
 *
 *------------------------------------------*/
int chrif_parse(int fd) {
	int packet_len, cmd;

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

	if ( session[fd]->flag.eof ) {
		do_close(fd);
		char_fd = -1;
		chrif_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 */
			chrif_keepalive(fd);
			session[fd]->flag.ping = 2;
		}
	}

	while ( RFIFOREST(fd) >= 2 ) {
		cmd = RFIFOW(fd,0);
		if (cmd < 0x2af8 || cmd >= 0x2af8 + ARRAYLENGTH(packet_len_table) || packet_len_table[cmd-0x2af8] == 0) {
			int r = intif_parse(fd); // Passed on to the intif

			if (r == 1) continue;	// Treated in intif 
			if (r == 2) return 0;	// Didn't have enough data (len==-1)

			ShowWarning("chrif_parse: session #%d, intif_parse failed (unrecognized command 0x%.4x).\n", fd, cmd);
			set_eof(fd);
			return 0;
		}

		if ( ( packet_len = packet_len_table[cmd-0x2af8] ) == -1) { // dynamic-length packet, second WORD holds the length
			if (RFIFOREST(fd) < 4)
				return 0;
			packet_len = RFIFOW(fd,2);
		}

		if ((int)RFIFOREST(fd) < packet_len)
			return 0;

		//ShowDebug("Received packet 0x%4x (%d bytes) from char-server (connection %d)\n", RFIFOW(fd,0), packet_len, fd);

		switch(cmd) {
			case 0x2af9: chrif_connectack(fd); break;
			case 0x2afb: chrif_sendmapack(fd); break;
			case 0x2afd: chrif_authok(fd); break;
			case 0x2b00: map_setusers(RFIFOL(fd,2)); chrif_keepalive(fd); break;
			case 0x2b03: clif->charselectok(RFIFOL(fd,2), RFIFOB(fd,6)); break;
			case 0x2b04: chrif_recvmap(fd); break;
			case 0x2b06: chrif_changemapserverack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOW(fd,18), RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); break;
			case 0x2b09: map_addnickdb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break;
			case 0x2b0a: socket_datasync(fd, false); break;
			case 0x2b0d: chrif_changedsex(fd); break;
			case 0x2b0f: chrif_char_ask_name_answer(RFIFOL(fd,2), (char*)RFIFOP(fd,6), RFIFOW(fd,30), RFIFOW(fd,32)); break;
			case 0x2b12: chrif_divorceack(RFIFOL(fd,2), RFIFOL(fd,6)); break;
			case 0x2b14: chrif_accountban(fd); break;
			case 0x2b1b: chrif_recvfamelist(fd); break;
			case 0x2b1d: chrif_load_scdata(fd); break;
			case 0x2b1e: chrif_update_ip(fd); break;
			case 0x2b1f: chrif_disconnectplayer(fd); break;
			case 0x2b20: chrif_removemap(fd); break;
			case 0x2b21: chrif_save_ack(fd); break;
			case 0x2b22: chrif_updatefamelist_ack(fd); break;
			case 0x2b24: chrif_keepalive_ack(fd); break;
			case 0x2b25: chrif_deadopt(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break;
			case 0x2b27: chrif_authfail(fd); break;
			default:
				ShowError("chrif_parse : unknown packet (session #%d): 0x%x. Disconnecting.\n", fd, cmd);
				set_eof(fd);
				return 0;
		}
		if ( fd == char_fd ) //There's the slight chance we lost the connection during parse, in which case this would segfault if not checked [Skotlex]
			RFIFOSKIP(fd, packet_len);
	}

	return 0;
}
Example #28
0
static int send_from_fifo(int fd)
{
	int len;
	if( !session_isValid(fd) )
		return -1;

//	if (s->eof) // if we close connection, we can not send last information (you're been disconnected, etc...) [Yor]
//		return -1;
/*
	// clear write buffer if not connected <- I really like more the idea of sending the last information. [Skotlex]
	if( session[fd]->eof )
	{
		session[fd]->wdata_size = 0;
		return -1;
	}
*/

	if (session[fd]->wdata_size == 0)
		return 0;

#ifdef __WIN32
	len=send(fd, (const char *)session[fd]->wdata,session[fd]->wdata_size, 0);
	if (len == SOCKET_ERROR) {
		if (WSAGetLastError() == WSAECONNABORTED) {
			ShowWarning("send_from_fifo: software de conexao cancelado na sessao #%d\n", fd);
			session[fd]->wdata_size = 0; //Clear the send queue as we can't send anymore. [Skotlex]
			set_eof(fd);
			FD_CLR(fd, &readfds); //Remove the socket so the select() won't hang on it.
		}
		if (WSAGetLastError() != WSAEWOULDBLOCK) {
//			ShowDebug("send_from_fifo: error %d, ending connection #%d\n", WSAGetLastError(), fd);
			session[fd]->wdata_size = 0; //Clear the send queue as we can't send anymore. [Skotlex]
			set_eof(fd);
		}
		return 0;
	}
#else
	len=write(fd,session[fd]->wdata,session[fd]->wdata_size);
	if (len == -1)
	{
		if (errno == ECONNABORTED)
		{
			ShowFatalError("send_from_fifo: Quebra de conexao (software de conexao cancelado na sessao #%d)\n", fd);
			session[fd]->wdata_size = 0; //Clear the send queue as we can't send anymore. [Skotlex]
			set_eof(fd);
		}
		if (errno != EAGAIN) {
//			perror("closing session: send_from_fifo");
			session[fd]->wdata_size = 0; //Clear the send queue as we can't send anymore. [Skotlex]
			set_eof(fd);
		}
		return 0;
	}
#endif

	//{ int i; ShowMessage("send %d : ",fd);  for(i=0;i<len;i++){ ShowMessage("%02x ",session[fd]->wdata[i]); } ShowMessage("\n");}
	if(len>0){
		if((unsigned int)len<session[fd]->wdata_size){
			memmove(session[fd]->wdata,session[fd]->wdata+len,session[fd]->wdata_size-len);
			session[fd]->wdata_size-=len;
		} else {
			session[fd]->wdata_size=0;
		}
	}
	return 0;
}
Example #29
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;
}
Example #30
0
/*==========================================
 *
 *------------------------------------------*/
int chrif_parse(int fd)
{
	int packet_len, cmd;

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

	if (session[fd]->flag.eof)
	{
		if (chrif_connected == 1)
			chrif_disconnect(fd);

		do_close(fd);
		return 0;
	}

	while (RFIFOREST(fd) >= 2)
	{
		cmd = RFIFOW(fd,0);
		if (cmd < 0x2af8 || cmd >= 0x2af8 + ARRAYLENGTH(packet_len_table) || packet_len_table[cmd-0x2af8] == 0)
		{
			int r = intif_parse(fd); // intifに渡す

			if (r == 1) continue;	// intifで処理した
			if (r == 2) return 0;	// intifで処理したが、データが足りない

			ShowWarning("chrif_parse: session #%d, intif_parse failed (unrecognized command 0x%.4x).\n", fd, cmd);
			set_eof(fd);
			return 0;
		}

		packet_len = packet_len_table[cmd-0x2af8];
		if (packet_len == -1)
		{ // dynamic-length packet, second WORD holds the length
			if (RFIFOREST(fd) < 4)
				return 0;
			packet_len = RFIFOW(fd,2);
		}

		if ((int)RFIFOREST(fd) < packet_len)
			return 0;

		//ShowDebug("Received packet 0x%4x (%d bytes) from char-server (connection %d)\n", RFIFOW(fd,0), packet_len, fd);

		switch(cmd)
		{
		case 0x2af9: chrif_connectack(fd); break;
		case 0x2afb: chrif_sendmapack(fd); break;
		case 0x2afd: chrif_authok(fd); break;
		case 0x2b00: map_setusers(RFIFOL(fd,2)); chrif_keepalive(fd); break;
		case 0x2b03: clif_charselectok(RFIFOL(fd,2)); break;
		case 0x2b04: chrif_recvmap(fd); break;
		case 0x2b06: chrif_changemapserverack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOW(fd,18), RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); break;
		case 0x2b07: clif_updatemaxid(RFIFOL(fd,2), RFIFOL(fd,6)); break;
		case 0x2b09: map_addnickdb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break;
		case 0x2b0b: chrif_changedgm(fd); break;
		case 0x2b0d: chrif_changedsex(fd); break;
		case 0x2b0f: chrif_char_ask_name_answer(RFIFOL(fd,2), (char*)RFIFOP(fd,6), RFIFOW(fd,30), RFIFOW(fd,32)); break;
		case 0x2b12: chrif_divorce(RFIFOL(fd,2), RFIFOL(fd,6)); break;
		case 0x2b13: chrif_accountdeletion(fd); break;
		case 0x2b14: chrif_accountban(fd); break;
		case 0x2b15: chrif_recvgmaccounts(fd); break;
		case 0x2b1b: chrif_recvfamelist(fd); break;
		case 0x2b1d: chrif_load_scdata(fd); break;
		case 0x2b1e: chrif_update_ip(fd); break;
		case 0x2b1f: chrif_disconnectplayer(fd); break;
		case 0x2b20: chrif_removemap(fd); break;
		case 0x2b21: chrif_save_ack(fd); break;
		case 0x2b22: chrif_updatefamelist_ack(fd); break;
		case 0x2b24: chrif_keepalive_ack(fd); break;
		default:
			ShowError("chrif_parse : unknown packet (session #%d): 0x%x. Disconnecting.\n", fd, cmd);
			set_eof(fd);
			return 0;
		}
		if (fd == char_fd) //There's the slight chance we lost the connection during parse, in which case this would segfault if not checked [Skotlex]
			RFIFOSKIP(fd, packet_len);
	}

	return 0;
}