Exemplo n.º 1
0
// Wisp/Page reception
static
int intif_parse_WisMessage (int fd)
{                               // rewritten by [Yor]
    struct map_session_data *sd;
    int  i;

    if (battle_config.etc_log)
        printf
            ("intif_parse_wismessage: id: %d, from: %s, to: %s, message: '%s'\n",
             RFIFOL (fd, 4), RFIFOP (fd, 8), RFIFOP (fd, 32), RFIFOP (fd,
                                                                      56));
    sd = map_nick2sd ((const char *)RFIFOP (fd, 32)); // Searching destination player
    if (sd != NULL && strcmp (sd->status.name, (const char *)RFIFOP (fd, 32)) == 0)
    {                           // exactly same name (inter-server have checked the name before)
        // if player ignore all
        if (sd->ignoreAll == 1)
            intif_wis_replay (RFIFOL (fd, 4), 2);   // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
        else
        {
            const char *wisp_source = (const char *)RFIFOP (fd, 8);   // speed up
            // if player ignore the source character
            for (i = 0; i < (sizeof (sd->ignore) / sizeof (sd->ignore[0]));
                 i++)
                if (strcmp (sd->ignore[i].name, wisp_source) == 0)
                {
                    intif_wis_replay (RFIFOL (fd, 4), 2);   // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
                    break;
                }
            // if source player not found in ignore list
            if (i == (sizeof (sd->ignore) / sizeof (sd->ignore[0])))
            {
                clif_wis_message (sd->fd, (const char *)RFIFOP (fd, 8), (const char *)RFIFOP (fd, 56),
                                  RFIFOW (fd, 2) - 56);
                intif_wis_replay (RFIFOL (fd, 4), 0);   // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
            }
        }
    }
    else
        intif_wis_replay (RFIFOL (fd, 4), 1);   // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
    return 0;
}
Exemplo n.º 2
0
// map server からの通信
// ・1パケットのみ解析すること
// ・パケット長データはinter.cにセットしておくこと
// ・パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない
// ・エラーなら0(false)、そうでないなら1(true)をかえさなければならない
int inter_party_parse_frommap(int fd)
{
	switch(RFIFOW(fd,0)){
	case 0x3020: mapif_parse_CreateParty(fd,RFIFOL(fd,2),(char*)RFIFOP(fd,6),(char*)RFIFOP(fd,30),(char*)RFIFOP(fd,54),RFIFOW(fd,70), RFIFOB(fd,72), RFIFOB(fd,73)); break;
	case 0x3021: mapif_parse_PartyInfo(fd,RFIFOL(fd,2)); break;
	case 0x3022: mapif_parse_PartyAddMember(fd,RFIFOL(fd,2),RFIFOL(fd,6),(char*)RFIFOP(fd,10),(char*)RFIFOP(fd,34),RFIFOW(fd,50)); break;
	case 0x3023: mapif_parse_PartyChangeOption(fd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOW(fd,10),RFIFOW(fd,12)); break;
	case 0x3024: mapif_parse_PartyLeave(fd,RFIFOL(fd,2),RFIFOL(fd,6)); break;
	case 0x3025: mapif_parse_PartyChangeMap(fd,RFIFOL(fd,2),RFIFOL(fd,6),(char*)RFIFOP(fd,10),RFIFOB(fd,26),RFIFOW(fd,27)); break;
	case 0x3026: mapif_parse_BreakParty(fd,RFIFOL(fd,2)); break;
	case 0x3027: mapif_parse_PartyMessage(fd,RFIFOL(fd,4),RFIFOL(fd,8),(char*)RFIFOP(fd,12),RFIFOW(fd,2)-12); break;
	case 0x3028: mapif_parse_PartyCheck(fd,RFIFOL(fd,2),RFIFOL(fd,6),(char*)RFIFOP(fd,10)); break;
	default:
		return 0;
	}
	return 1;
}
Exemplo n.º 3
0
int mapif_parse_SaveGuildStorage(int fd)
{
    int guild_exist=1;
    int guild_id;
    int len;
    RFIFOHEAD(fd);
    guild_id=RFIFOL(fd,8);
    len=RFIFOW(fd,2);
    if(sizeof(struct guild_storage)!=len-12) {
        ShowError("inter storage: data size error %d %d\n",sizeof(struct guild_storage),len-12);
    }
    else {
#if 0	// Again, innodb key checks make the check pointless
        // Check if guild exists, I may write a function for this later, coz I use it several times.
        //printf("- Check if guild %d exists\n",g->guild_id);
        sprintf(tmp_sql, "SELECT count(*) FROM `%s` WHERE `guild_id`='%d'",guild_db, guild_id);
        if(mysql_query(&mysql_handle, tmp_sql) ) {
            ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
            ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
        }
        sql_res = mysql_store_result(&mysql_handle) ;
        if (sql_res!=NULL && mysql_num_rows(sql_res)>0) {
            sql_row = mysql_fetch_row(sql_res);
            guild_exist =  atoi (sql_row[0]);
            //printf("- Check if guild %d exists : %s\n",g->guild_id,((guild_exist==0)?"No":"Yes"));
        }
        mysql_free_result(sql_res) ; //resource free
#endif
        if(guild_exist==1) {
            memcpy(guild_storage_pt,RFIFOP(fd,12),sizeof(struct guild_storage));
            guild_storage_tosql(guild_id,guild_storage_pt);
            mapif_save_guild_storage_ack(fd,RFIFOL(fd,4),guild_id,0);
        }
        else
            mapif_save_guild_storage_ack(fd,RFIFOL(fd,4),guild_id,1);
    }
    return 0;
}
Exemplo n.º 4
0
// ギルドメンバ情報変更通知
static
int intif_parse_GuildMemberInfoChanged (int fd)
{
    int  type = RFIFOW (fd, 16), guild_id = RFIFOL (fd, 4);
    int  account_id = RFIFOL (fd, 8), char_id = RFIFOL (fd, 12);
    void *data = RFIFOP (fd, 18);
    struct guild *g = guild_search (guild_id);
    int  idx, dd = *((int *) data);
    if (g == NULL)
        return 0;
    idx = guild_getindex (g, account_id, char_id);
    switch (type)
    {
        case GMI_POSITION:
            g->member[idx].position = dd;
            guild_memberposition_changed (g, idx, dd);
            break;
        case GMI_EXP:
            g->member[idx].exp = dd;
            break;
    }
    return 0;
}
Exemplo n.º 5
0
static void mapif_parse_Mail_receiver_check(int fd) {
	char name[NAME_LENGTH], esc_name[NAME_LENGTH * 2 + 1];
	uint32 char_id = 0;
	uint16 class_ = 0, base_level = 0;

	safestrncpy(name, (char *)RFIFOP(fd,6), NAME_LENGTH);

	// Try to find the Dest Char by Name
	Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));

	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`class`,`base_level` FROM `%s` WHERE `name` = '%s'", char_db, esc_name) )
		Sql_ShowDebug(sql_handle);
	else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) {
		char *data;

		Sql_GetData(sql_handle, 0, &data, NULL); char_id = atoi(data);
		Sql_GetData(sql_handle, 1, &data, NULL); class_ = atoi(data);
		Sql_GetData(sql_handle, 2, &data, NULL); base_level = atoi(data);
	}

	Sql_FreeResult(sql_handle);
	mapif_Mail_receiver_send(fd, RFIFOL(fd,2), char_id, class_, base_level, name);
}
Exemplo n.º 6
0
// ギルド情報
static
int intif_parse_GuildInfo (int fd)
{
    if (RFIFOW (fd, 2) == 8)
    {
        if (battle_config.error_log)
            printf ("intif: guild noinfo %d\n", RFIFOL (fd, 4));
        guild_recv_noinfo (RFIFOL (fd, 4));
        return 0;
    }

//  if(battle_config.etc_log)
//      printf("intif: guild info %d\n",RFIFOL(fd,4));
    if (RFIFOW (fd, 2) != sizeof (struct guild) + 4)
    {
        if (battle_config.error_log)
            printf ("intif: guild info : data size error\n %d %d %d",
                    RFIFOL (fd, 4), RFIFOW (fd, 2),
                    sizeof (struct guild) + 4);
    }
    guild_recv_info ((struct guild *) RFIFOP (fd, 4));
    return 0;
}
Exemplo n.º 7
0
static void mapif_parse_Mail_send(int fd)
{
	struct mail_message msg;
	char esc_name[NAME_LENGTH*2+1];
	int account_id = 0;

	if(RFIFOW(fd,2) != 8 + sizeof(struct mail_message))
		return;

	account_id = RFIFOL(fd,4);
	memcpy(&msg, RFIFOP(fd,8), sizeof(struct mail_message));

	// Try to find the Dest Char by Name
	SQL->EscapeStringLen(sql_handle, esc_name, msg.dest_name, strnlen(msg.dest_name, NAME_LENGTH));
	if ( SQL_ERROR == SQL->Query(sql_handle, "SELECT `account_id`, `char_id` FROM `%s` WHERE `name` = '%s'", char_db, esc_name) )
		Sql_ShowDebug(sql_handle);
	else
	if ( SQL_SUCCESS == SQL->NextRow(sql_handle) )
	{
		char *data;
		SQL->GetData(sql_handle, 0, &data, NULL);
		if (atoi(data) != account_id)
		{ // Cannot send mail to char in the same account
			SQL->GetData(sql_handle, 1, &data, NULL);
			msg.dest_id = atoi(data);
		}
	}
	SQL->FreeResult(sql_handle);
	msg.status = MAIL_NEW;

	if( msg.dest_id > 0 )
		msg.id = mail_savemessage(&msg);

	mapif_Mail_send(fd, &msg); // notify sender
	mapif_Mail_new(&msg); // notify recipient
}
Exemplo n.º 8
0
// ギルド基本情報変更通知
static
int intif_parse_GuildBasicInfoChanged (int fd)
{
    int  type = RFIFOW (fd, 8), guild_id = RFIFOL (fd, 4);
    void *data = RFIFOP (fd, 10);
    struct guild *g = guild_search (guild_id);
    short dw = *((short *) data);
    int  dd = *((int *) data);
    if (g == NULL)
        return 0;
    switch (type)
    {
        case GBI_EXP:
            g->exp = dd;
            break;
        case GBI_GUILDLV:
            g->guild_lv = dw;
            break;
        case GBI_SKILLPOINT:
            g->skill_point = dd;
            break;
    }
    return 0;
}
Exemplo n.º 9
0
// ギルド城データ一括受信(初期化時)
static
int intif_parse_GuildCastleAllDataLoad (int fd)
{
    return guild_castlealldataload (RFIFOW (fd, 2),
                                    (struct guild_castle *) RFIFOP (fd, 4));
}
Exemplo n.º 10
0
// ギルド告知変更通知
static
int intif_parse_GuildNotice (int fd)
{
    guild_notice_changed (RFIFOL (fd, 2), (const char *)RFIFOP (fd, 6), (const char *)RFIFOP (fd, 66));
    return 0;
}
Exemplo n.º 11
0
/*==========================================
 * Inter Packets
 *------------------------------------------*/
int inter_homunculus_parse_frommap(int fd)
{
	unsigned short cmd = RFIFOW(fd,0);

	switch( cmd )
	{
		case 0x3090: mapif_parse_homunculus_create(fd, (int)RFIFOW(fd,2), (int)RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,8)); break;
		case 0x3091: mapif_parse_homunculus_load  (fd, (int)RFIFOL(fd,2), (int)RFIFOL(fd,6)); break;
		case 0x3092: mapif_parse_homunculus_save  (fd, (int)RFIFOW(fd,2), (int)RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,8)); break;
		case 0x3093: mapif_parse_homunculus_delete(fd, (int)RFIFOL(fd,2)); break;
		case 0x3094: mapif_parse_homunculus_rename(fd, (int)RFIFOL(fd,2), (int)RFIFOL(fd,6), (char*)RFIFOP(fd,10)); break;
		default:
			return 0;
	}
	return 1;
}
Exemplo n.º 12
0
/* [Dekamaster/Nightroad] */
void mapif_parse_accinfo(int fd) {
	int u_fd = RFIFOL(fd,2), aid = RFIFOL(fd,6), castergroup = RFIFOL(fd,10);
	char query[NAME_LENGTH], query_esq[NAME_LENGTH*2+1];
	int account_id;
	char *data;

	safestrncpy(query, (char*) RFIFOP(fd,14), NAME_LENGTH);

	SQL->EscapeString(sql_handle, query_esq, query);

	account_id = atoi(query);

	if (account_id < START_ACCOUNT_NUM) {	// is string
		if ( SQL_ERROR == SQL->Query(sql_handle, "SELECT `account_id`,`name`,`class`,`base_level`,`job_level`,`online` FROM `%s` WHERE `name` LIKE '%s' LIMIT 10", char_db, query_esq)
				|| SQL->NumRows(sql_handle) == 0 ) {
			if( SQL->NumRows(sql_handle) == 0 ) {
				inter_msg_to_fd(fd, u_fd, aid, "No matches were found for your criteria, '%s'",query);
			} else {
				Sql_ShowDebug(sql_handle);
				inter_msg_to_fd(fd, u_fd, aid, "An error occured, bother your admin about it.");
			}
			SQL->FreeResult(sql_handle);
			return;
		} else {
			if( SQL->NumRows(sql_handle) == 1 ) {//we found a perfect match
				SQL->NextRow(sql_handle);
				SQL->GetData(sql_handle, 0, &data, NULL); account_id = atoi(data);
				SQL->FreeResult(sql_handle);
			} else {// more than one, listing... [Dekamaster/Nightroad]
				inter_msg_to_fd(fd, u_fd, aid, "Your query returned the following %d results, please be more specific...",(int)SQL->NumRows(sql_handle));
				while ( SQL_SUCCESS == SQL->NextRow(sql_handle) ) {
					int class_;
					short base_level, job_level, online;
					char name[NAME_LENGTH];

					SQL->GetData(sql_handle, 0, &data, NULL); account_id = atoi(data);
					SQL->GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name));
					SQL->GetData(sql_handle, 2, &data, NULL); class_ = atoi(data);
					SQL->GetData(sql_handle, 3, &data, NULL); base_level = atoi(data);
					SQL->GetData(sql_handle, 4, &data, NULL); job_level = atoi(data);
					SQL->GetData(sql_handle, 5, &data, NULL); online = atoi(data);

					inter_msg_to_fd(fd, u_fd, aid, "[AID: %d] %s | %s | Level: %d/%d | %s", account_id, name, job_name(class_), base_level, job_level, online?"Online":"Offline");
				}
				SQL->FreeResult(sql_handle);
				return;
			}
		}
	}

	/* it will only get here if we have a single match */
	if( account_id ) {
		char userid[NAME_LENGTH], user_pass[NAME_LENGTH], email[40], last_ip[20], lastlogin[30], pin_code[5], birthdate[11];
		short level = -1;
		int logincount = 0,state = 0;
		// FIXME: No, this doesn't really look right.  We can't, and shouldn't, access the login table from the char server.
		if ( SQL_ERROR == SQL->Query(sql_handle, "SELECT `userid`, `user_pass`, `email`, `last_ip`, `group_id`, `lastlogin`, `logincount`, `state`,`pincode`,`birthdate` FROM `login` WHERE `account_id` = '%d' LIMIT 1", account_id)
			|| SQL->NumRows(sql_handle) == 0 ) {
			if( SQL->NumRows(sql_handle) == 0 ) {
				inter_msg_to_fd(fd, u_fd, aid,  "No account with ID '%d' was found.", account_id );
			} else {
				inter_msg_to_fd(fd, u_fd, aid, "An error occured, bother your admin about it.");
				Sql_ShowDebug(sql_handle);
			}
		} else {
			SQL->NextRow(sql_handle);
			SQL->GetData(sql_handle, 0, &data, NULL); safestrncpy(userid, data, sizeof(userid));
			SQL->GetData(sql_handle, 1, &data, NULL); safestrncpy(user_pass, data, sizeof(user_pass));
			SQL->GetData(sql_handle, 2, &data, NULL); safestrncpy(email, data, sizeof(email));
			SQL->GetData(sql_handle, 3, &data, NULL); safestrncpy(last_ip, data, sizeof(last_ip));
			SQL->GetData(sql_handle, 4, &data, NULL); level = atoi(data);
			SQL->GetData(sql_handle, 5, &data, NULL); safestrncpy(lastlogin, data, sizeof(lastlogin));
			SQL->GetData(sql_handle, 6, &data, NULL); logincount = atoi(data);
			SQL->GetData(sql_handle, 7, &data, NULL); state = atoi(data);
			SQL->GetData(sql_handle, 8, &data, NULL); safestrncpy(pin_code, data, sizeof(pin_code));
			SQL->GetData(sql_handle, 9, &data, NULL); safestrncpy(birthdate, data, sizeof(birthdate));
		}

		SQL->FreeResult(sql_handle);

		if (level == -1)
			return;

		inter_msg_to_fd(fd, u_fd, aid, "-- Account %d --", account_id );
		inter_msg_to_fd(fd, u_fd, aid, "User: %s | GM Group: %d | State: %d", userid, level, state );

		if (level < castergroup) { /* only show pass if your gm level is greater than the one you're searching for */
			if( strlen(pin_code) )
				inter_msg_to_fd(fd, u_fd, aid, "Password: %s (PIN:%s)", user_pass, pin_code );
			else
				inter_msg_to_fd(fd, u_fd, aid, "Password: %s", user_pass );
		}

		inter_msg_to_fd(fd, u_fd, aid, "Account e-mail: %s | Birthdate: %s", email, birthdate);
		inter_msg_to_fd(fd, u_fd, aid, "Last IP: %s (%s)", last_ip, geoip_getcountry(str2ip(last_ip)) );
		inter_msg_to_fd(fd, u_fd, aid, "This user has logged %d times, the last time were at %s", logincount, lastlogin );
		inter_msg_to_fd(fd, u_fd, aid, "-- Character Details --" );


		if ( SQL_ERROR == SQL->Query(sql_handle, "SELECT `char_id`, `name`, `char_num`, `class`, `base_level`, `job_level`, `online` FROM `%s` WHERE `account_id` = '%d' ORDER BY `char_num` LIMIT %d", char_db, account_id, MAX_CHARS)
				|| SQL->NumRows(sql_handle) == 0 ) {

				if( SQL->NumRows(sql_handle) == 0 )
					inter_msg_to_fd(fd, u_fd, aid,"This account doesn't have characters.");
				else {
					inter_msg_to_fd(fd, u_fd, aid,"An error occured, bother your admin about it.");
					Sql_ShowDebug(sql_handle);
				}

		} else {
			while ( SQL_SUCCESS == SQL->NextRow(sql_handle) ) {
				int char_id, class_;
				short char_num, base_level, job_level, online;
				char name[NAME_LENGTH];

				SQL->GetData(sql_handle, 0, &data, NULL); char_id = atoi(data);
				SQL->GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name));
				SQL->GetData(sql_handle, 2, &data, NULL); char_num = atoi(data);
				SQL->GetData(sql_handle, 3, &data, NULL); class_ = atoi(data);
				SQL->GetData(sql_handle, 4, &data, NULL); base_level = atoi(data);
				SQL->GetData(sql_handle, 5, &data, NULL); job_level = atoi(data);
				SQL->GetData(sql_handle, 6, &data, NULL); online = atoi(data);

				inter_msg_to_fd(fd, u_fd, aid, "[Slot/CID: %d/%d] %s | %s | Level: %d/%d | %s", char_num, char_id, name, job_name(class_), base_level, job_level, online?"On":"Off");
			}
		}
		SQL->FreeResult(sql_handle);
	}

	return;
}
Exemplo n.º 13
0
// Wisp/page request to send
int mapif_parse_WisRequest(int fd)
{
	struct WisData* wd;
	static int wisid = 0;
	char name[NAME_LENGTH];
	char esc_name[NAME_LENGTH*2+1];// escaped name
	char* data;
	size_t len;


	if ( fd <= 0 ) {return 0;} // check if we have a valid fd

	if (RFIFOW(fd,2)-52 >= sizeof(wd->msg)) {
		ShowWarning("inter: Wis message size too long.\n");
		return 0;
	} else if (RFIFOW(fd,2)-52 <= 0) { // normaly, impossible, but who knows...
		ShowError("inter: Wis message doesn't exist.\n");
		return 0;
	}

	safestrncpy(name, (char*)RFIFOP(fd,28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex]

	SQL->EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
	if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `name` FROM `%s` WHERE `name`='%s'", char_db, esc_name) )
		Sql_ShowDebug(sql_handle);

	// search if character exists before to ask all map-servers
	if( SQL_SUCCESS != SQL->NextRow(sql_handle) )
	{
		unsigned char buf[27];
		WBUFW(buf, 0) = 0x3802;
		memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH);
		WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
		mapif_send(fd, buf, 27);
	}
	else
	{// Character exists. So, ask all map-servers
		// to be sure of the correct name, rewrite it
		SQL->GetData(sql_handle, 0, &data, &len);
		memset(name, 0, NAME_LENGTH);
		memcpy(name, data, min(len, NAME_LENGTH));
		// if source is destination, don't ask other servers.
		if( strncmp((const char*)RFIFOP(fd,4), name, NAME_LENGTH) == 0 )
		{
			uint8 buf[27];
			WBUFW(buf, 0) = 0x3802;
			memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH);
			WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
			mapif_send(fd, buf, 27);
		}
		else
		{

			CREATE(wd, struct WisData, 1);

			// Whether the failure of previous wisp/page transmission (timeout)
			check_ttl_wisdata();

			wd->id = ++wisid;
			wd->fd = fd;
			wd->len= RFIFOW(fd,2)-52;
			memcpy(wd->src, RFIFOP(fd, 4), NAME_LENGTH);
			memcpy(wd->dst, RFIFOP(fd,28), NAME_LENGTH);
			memcpy(wd->msg, RFIFOP(fd,52), wd->len);
			wd->tick = timer->gettick();
			idb_put(wis_db, wd->id, wd);
			mapif_wis_message(wd);
		}
	}

	SQL->FreeResult(sql_handle);
	return 0;
}
Exemplo n.º 14
0
int mapif_parse_SavePet(int fd)
{
	RFIFOHEAD(fd);
	mapif->save_pet(fd, RFIFOL(fd, 4), RFIFOP(fd, 8));
	return 0;
}
Exemplo n.º 15
0
static
int intif_parse_LoadGuildStorage (int fd)
{
    struct guild_storage *gstor;
    struct map_session_data *sd;
    int  guild_id;

    guild_id = RFIFOL (fd, 8);
    if (guild_id > 0)
    {
        gstor = guild2storage (guild_id);
        if (!gstor)
        {
            if (battle_config.error_log)
                printf
                    ("intif_parse_LoadGuildStorage: error guild_id %d not exist\n",
                     guild_id);
            return 1;
        }
        if (RFIFOW (fd, 2) - 12 != sizeof (struct guild_storage))
        {
            gstor->storage_status = 0;
            if (battle_config.error_log)
                printf
                    ("intif_parse_LoadGuildStorage: data size error %d %d\n",
                     RFIFOW (fd, 2) - 12, sizeof (struct guild_storage));
            return 1;
        }
        sd = map_id2sd (RFIFOL (fd, 4));
        if (sd == NULL)
        {
            if (battle_config.error_log)
                printf ("intif_parse_LoadGuildStorage: user not found %d\n",
                        RFIFOL (fd, 4));
            return 1;
        }
        if (gstor->storage_status == 1)
        {                       // Already open.. lets ignore this update
            if (battle_config.error_log)
                printf
                    ("intif_parse_LoadGuildStorage: storage received for a client already open (User %d:%d)\n",
                     sd->status.account_id, sd->status.char_id);
            return 1;
        }
        if (gstor->dirty)
        {                       // Already have storage, and it has been modified and not saved yet! Exploit! [Skotlex]
            if (battle_config.error_log)
                printf
                    ("intif_parse_LoadGuildStorage: received storage for an already modified non-saved storage! (User %d:%d)\n",
                     sd->status.account_id, sd->status.char_id);
            return 1;
        }
        if (battle_config.save_log)
            printf ("intif_open_guild_storage: %d\n", RFIFOL (fd, 4));
        memcpy (gstor, RFIFOP (fd, 12), sizeof (struct guild_storage));
        gstor->storage_status = 1;
        sd->state.storage_flag = 2;
        clif_guildstorageitemlist (sd, gstor);
        clif_guildstorageequiplist (sd, gstor);
        clif_updateguildstorageamount (sd, gstor);
    }
    return 0;
}
Exemplo n.º 16
0
// Wisp/page request to send
int mapif_parse_WisRequest(int fd) {
	struct WisData* wd;
	static int wisid = 0;
	char name[NAME_LENGTH], t_name[NAME_LENGTH*2]; //Needs space to allocate names with escaped chars [Skotlex]

	if ( fd <= 0 ) {return 0;} // check if we have a valid fd

	if (RFIFOW(fd,2)-52 >= sizeof(wd->msg)) {
		ShowWarning("inter: Wis message size too long.\n");
		return 0;
	} else if (RFIFOW(fd,2)-52 <= 0) { // normaly, impossible, but who knows...
		ShowError("inter: Wis message doesn't exist.\n");
		return 0;
	}
	memcpy(name, RFIFOP(fd,28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex]
	name[NAME_LENGTH-1]= '\0';
	
	sprintf (tmp_sql, "SELECT `name` FROM `%s` WHERE `name`='%s'",
		char_db, jstrescapecpy(t_name, name));
	if(mysql_query(&mysql_handle, tmp_sql) ) {
		ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
		ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
	}
	sql_res = mysql_store_result(&mysql_handle);

	// search if character exists before to ask all map-servers
	if (!(sql_row = mysql_fetch_row(sql_res))) {
		unsigned char buf[27];
		WBUFW(buf, 0) = 0x3802;
		memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH);
		WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
		mapif_send(fd, buf, 27);
	// Character exists. So, ask all map-servers
	} else {
		// to be sure of the correct name, rewrite it
		memset(name, 0, NAME_LENGTH);
		strncpy(name, sql_row[0], NAME_LENGTH);
		// if source is destination, don't ask other servers.
		if (strcmp((char*)RFIFOP(fd,4),name) == 0) {
			unsigned char buf[27];
			WBUFW(buf, 0) = 0x3802;
			memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH);
			WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
			mapif_send(fd, buf, 27);
		} else {

	CREATE(wd, struct WisData, 1);

			// Whether the failure of previous wisp/page transmission (timeout)
			check_ttl_wisdata();

			wd->id = ++wisid;
			wd->fd = fd;
			wd->len= RFIFOW(fd,2)-52;
			memcpy(wd->src, RFIFOP(fd, 4), NAME_LENGTH);
			memcpy(wd->dst, RFIFOP(fd,28), NAME_LENGTH);
			memcpy(wd->msg, RFIFOP(fd,52), wd->len);
			wd->tick = gettick();
			numdb_insert(wis_db, wd->id, wd);
			mapif_wis_message(wd);
		}
	}
	
	//Freeing ... O.o 
	if(sql_res){
		mysql_free_result(sql_res);
	}
	
	return 0;
}
Exemplo n.º 17
0
//-----------------------------------------------------------------
// inter serverからの通信
// エラーがあれば0(false)を返すこと
// パケットが処理できれば1,パケット長が足りなければ2を返すこと
int intif_parse (int fd)
{
    int  packet_len;
    int  cmd = RFIFOW (fd, 0);
    // パケットのID確認
    if (cmd < 0x3800
        || cmd >=
        0x3800 + (sizeof (packet_len_table) / sizeof (packet_len_table[0]))
        || packet_len_table[cmd - 0x3800] == 0)
    {
        return 0;
    }
    // パケットの長さ確認
    packet_len = packet_len_table[cmd - 0x3800];
    if (packet_len == -1)
    {
        if (RFIFOREST (fd) < 4)
            return 2;
        packet_len = RFIFOW (fd, 2);
    }
//  if(battle_config.etc_log)
//      printf("intif_parse %d %x %d %d\n",fd,cmd,packet_len,RFIFOREST(fd));
    if (RFIFOREST (fd) < packet_len)
    {
        return 2;
    }
    // 処理分岐
    switch (cmd)
    {
        case 0x3800:
            clif_GMmessage (NULL, (const char *)RFIFOP (fd, 4), packet_len - 4, 0);
            break;
        case 0x3801:
            intif_parse_WisMessage (fd);
            break;
        case 0x3802:
            intif_parse_WisEnd (fd);
            break;
        case 0x3803:
            mapif_parse_WisToGM (fd);
            break;
        case 0x3804:
            intif_parse_AccountReg (fd);
            break;
        case 0x3810:
            intif_parse_LoadStorage (fd);
            break;
        case 0x3811:
            intif_parse_SaveStorage (fd);
            break;
        case 0x3818:
            intif_parse_LoadGuildStorage (fd);
            break;
        case 0x3819:
            intif_parse_SaveGuildStorage (fd);
            break;
        case 0x3820:
            intif_parse_PartyCreated (fd);
            break;
        case 0x3821:
            intif_parse_PartyInfo (fd);
            break;
        case 0x3822:
            intif_parse_PartyMemberAdded (fd);
            break;
        case 0x3823:
            intif_parse_PartyOptionChanged (fd);
            break;
        case 0x3824:
            intif_parse_PartyMemberLeaved (fd);
            break;
        case 0x3825:
            intif_parse_PartyMove (fd);
            break;
        case 0x3826:
            intif_parse_PartyBroken (fd);
            break;
        case 0x3827:
            intif_parse_PartyMessage (fd);
            break;
        case 0x3830:
            intif_parse_GuildCreated (fd);
            break;
        case 0x3831:
            intif_parse_GuildInfo (fd);
            break;
        case 0x3832:
            intif_parse_GuildMemberAdded (fd);
            break;
        case 0x3834:
            intif_parse_GuildMemberLeaved (fd);
            break;
        case 0x3835:
            intif_parse_GuildMemberInfoShort (fd);
            break;
        case 0x3836:
            intif_parse_GuildBroken (fd);
            break;
        case 0x3837:
            intif_parse_GuildMessage (fd);
            break;
        case 0x3839:
            intif_parse_GuildBasicInfoChanged (fd);
            break;
        case 0x383a:
            intif_parse_GuildMemberInfoChanged (fd);
            break;
        case 0x383b:
            intif_parse_GuildPosition (fd);
            break;
        case 0x383c:
            intif_parse_GuildSkillUp (fd);
            break;
        case 0x383d:
            intif_parse_GuildAlliance (fd);
            break;
        case 0x383e:
            intif_parse_GuildNotice (fd);
            break;
        case 0x383f:
            intif_parse_GuildEmblem (fd);
            break;
        case 0x3840:
            intif_parse_GuildCastleDataLoad (fd);
            break;
        case 0x3841:
            intif_parse_GuildCastleDataSave (fd);
            break;
        case 0x3842:
            intif_parse_GuildCastleAllDataLoad (fd);
            break;
            //case 0x3880:  intif_parse_CreateP.et(fd); break;
            //case 0x3881:  intif_parse_RecvP.etData(fd); break;
            //case 0x3882:  intif_parse_SaveP.etOk(fd); break;
            //case 0x3883:  intif_parse_DeleteP.etOk(fd); break;
        default:
            if (battle_config.error_log)
                printf ("intif_parse : unknown packet %d %x\n", fd,
                        RFIFOW (fd, 0));
            return 0;
    }
    // パケット読み飛ばし
    RFIFOSKIP (fd, packet_len);
    return 1;
}
Exemplo n.º 18
0
// GM message sending
int mapif_parse_GMmessage(int fd)
{
	mapif_GMmessage(RFIFOP(fd, 8), RFIFOW(fd, 2), RFIFOL(fd, 4), fd);
	return 0;
}
Exemplo n.º 19
0
/*==========================================
 * Auth confirmation ack
 *------------------------------------------*/
void chrif_authok(int fd) {
	int account_id, group_id, char_id;
	uint32 login_id1,login_id2;
	time_t expiration_time;
	struct mmo_charstatus* status;
	struct auth_node *node;
	bool changing_mapservers;
	TBL_PC* sd;

	//Check if both servers agree on the struct's size
	if( RFIFOW(fd,2) - 25 != sizeof(struct mmo_charstatus) ) {
		ShowError("chrif_authok: Data size mismatch! %d != %d\n", RFIFOW(fd,2) - 25, sizeof(struct mmo_charstatus));
		return;
	}

	account_id = RFIFOL(fd,4);
	login_id1 = RFIFOL(fd,8);
	login_id2 = RFIFOL(fd,12);
	expiration_time = (time_t)(int32)RFIFOL(fd,16);
	group_id = RFIFOL(fd,20);
	changing_mapservers = (RFIFOB(fd,24));
	status = (struct mmo_charstatus*)RFIFOP(fd,25);
	char_id = status->char_id;

	//Check if we don't already have player data in our server
	//Causes problems if the currently connected player tries to quit or this data belongs to an already connected player which is trying to re-auth.
	if ( ( sd = map_id2sd(account_id) ) != NULL )
		return;
	
	if ( ( node = chrif_search(account_id) ) == NULL )
		return; // should not happen

	if ( node->state != ST_LOGIN )
		return; //character in logout phase, do not touch that data.

	if ( node->sd == NULL ) {
		/*
		//When we receive double login info and the client has not connected yet,
		//discard the older one and keep the new one.
		chrif_auth_delete(node->account_id, node->char_id, ST_LOGIN);
		*/
		return; // should not happen
	}

	sd = node->sd;

	if( runflag == MAPSERVER_ST_RUNNING &&
		node->char_dat == NULL &&
		node->account_id == account_id &&
		node->char_id == char_id &&
		node->login_id1 == login_id1 )
	{ //Auth Ok
		if (pc_authok(sd, login_id2, expiration_time, group_id, status, changing_mapservers))
			return;
	} else { //Auth Failed
		pc_authfail(sd);
	}
	
	chrif_char_offline(sd); //Set him offline, the char server likely has it set as online already.
	chrif_auth_delete(account_id, char_id, ST_LOGIN);
}
Exemplo n.º 20
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;
}
Exemplo n.º 21
0
// 傭兵のデータ受信&保存
int mapif_parse_SaveMerc(int fd)
{
	mapif_save_merc(fd,RFIFOL(fd,4),(struct mmo_mercstatus *)RFIFOP(fd,8));
	return 0;
}
Exemplo n.º 22
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.º 23
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.º 24
0
int mapif_parse_CreatePet(int fd){
	RFIFOHEAD(fd);
	mapif_create_pet(fd, RFIFOL(fd, 2), RFIFOL(fd, 6), RFIFOW(fd, 10), RFIFOW(fd, 12), RFIFOW(fd, 14), RFIFOW(fd, 16), RFIFOW(fd, 18),
		RFIFOW(fd, 20), RFIFOB(fd, 22), RFIFOB(fd, 23), (char*)RFIFOP(fd, 24));
	return 0;
}
Exemplo n.º 25
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.º 26
0
// broadcast sending
int mapif_parse_broadcast(int fd)
{
	mapif_broadcast(RFIFOP(fd,16), RFIFOW(fd,2), RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), fd);
	return 0;
}
Exemplo n.º 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)
	{
		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;
}
Exemplo n.º 28
0
/**
 * Received a connection request.
 * @param fd: file descriptor to parse from (client)
 * @param sd: client session
 * @param command: packet type sent
 * @param ip: ipv4 address (client)
 *  S 0064 <version>.L <username>.24B <password>.24B <clienttype>.B
 *  S 0277 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B
 *  S 02b0 <version>.L <username>.24B <password>.24B <clienttype>.B <ip address>.16B <adapter address>.13B <g_isGravityID>.B
 *  S 01dd <version>.L <username>.24B <password hash>.16B <clienttype>.B
 *  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"))
 *  S 027c <version>.L <username>.24B <password hash>.16B <clienttype>.B <?>.13B(junk)
 *  S 0825 <packetsize>.W <version>.L <clienttype>.B <userid>.24B <password>.27B <mac>.17B <ip>.15B <token>.(packetsize - 0x5C)B
 * @param fd: fd to parse from (client fd)
 * @return 0 failure, 1 success
 */
static int logclif_parse_reqauth(int fd, struct login_session_data *sd, int command, char* ip){
	size_t packet_len = RFIFOREST(fd);

	if( (command == 0x0064 && packet_len < 55)
	||  (command == 0x0277 && packet_len < 84)
	||  (command == 0x02b0 && packet_len < 85)
	||  (command == 0x01dd && packet_len < 47)
	||  (command == 0x01fa && packet_len < 48)
	||  (command == 0x027c && packet_len < 60)
	||  (command == 0x0825 && (packet_len < 4 || packet_len < RFIFOW(fd, 2))) )
		return 0;
	else {
		int result;
		char username[NAME_LENGTH];
		char password[PASSWD_LENGTH];
		unsigned char passhash[16];
		uint8 clienttype;
		bool israwpass = (command==0x0064 || command==0x0277 || command==0x02b0 || command == 0x0825);

		// Shinryo: For the time being, just use token as password.
		if(command == 0x0825) {
			char *accname = RFIFOCP(fd, 9);
			char *token = RFIFOCP(fd, 0x5C);
			size_t uAccLen = strlen(accname);
			size_t uTokenLen = RFIFOREST(fd) - 0x5C;

			if(uAccLen > NAME_LENGTH - 1 || uAccLen == 0 || uTokenLen > NAME_LENGTH - 1  || uTokenLen == 0)
			{
				logclif_auth_failed(sd, 3);
				return 0;
			}

			safestrncpy(username, accname, uAccLen + 1);
			safestrncpy(password, token, uTokenLen + 1);
			clienttype = RFIFOB(fd, 8);
		}
		else
		{
			safestrncpy(username, RFIFOCP(fd,6), NAME_LENGTH);
			if( israwpass )
			{
				safestrncpy(password, RFIFOCP(fd,30), PASSWD_LENGTH);
				clienttype = RFIFOB(fd,54);
			}
			else
			{
				memcpy(passhash, RFIFOP(fd,30), 16);
				clienttype = RFIFOB(fd,46);
			}
		}
		RFIFOSKIP(fd,RFIFOREST(fd)); // assume no other packet was sent

		sd->clienttype = clienttype;
		safestrncpy(sd->userid, username, NAME_LENGTH);
		if( israwpass )
		{
			ShowStatus("Request for connection of %s (ip: %s)\n", sd->userid, ip);
			safestrncpy(sd->passwd, password, NAME_LENGTH);
			if( login_config.use_md5_passwds )
				MD5_String(sd->passwd, sd->passwd);
			sd->passwdenc = 0;
		}
		else
		{
			ShowStatus("Request for connection (passwdenc mode) of %s (ip: %s)\n", sd->userid, ip);
			bin2hex(sd->passwd, passhash, 16); // raw binary data here!
			sd->passwdenc = PASSWORDENC;
		}

		if( sd->passwdenc != 0 && login_config.use_md5_passwds )
		{
			logclif_auth_failed(sd, 3); // send "rejected from server"
			return 0;
		}

		result = login_mmo_auth(sd, false);

		if( result == -1 )
			logclif_auth_ok(sd);
		else
			logclif_auth_failed(sd, result);
	}
	return 1;
}
Exemplo n.º 29
0
int mapif_parse_SavePet(int fd){
	RFIFOHEAD(fd);
	mapif_save_pet(fd, RFIFOL(fd, 4), (struct s_pet *) RFIFOP(fd, 8));
	return 0;
}
Exemplo n.º 30
0
//character selected, insert into auth db
void chrif_authok(int fd)
{
	struct auth_node *node;
	int account_id = RFIFOL(fd, 4);
	struct mmo_charstatus *status = (struct mmo_charstatus *)RFIFOP(fd, 20);
	int char_id = status->char_id;
	TBL_PC* sd;

	//Check if both servers agree on the struct's size
	if( RFIFOW(fd,2) - 20 != sizeof(struct mmo_charstatus) )
	{
		ShowError("chrif_authok: Data size mismatch! %d != %d\n", RFIFOW(fd,2) - 20, sizeof(struct mmo_charstatus));
		return;
	}

	//Check if we don't already have player data in our server
	//Causes problems if the currently connected player tries to quit or this data belongs to an already connected player which is trying to re-auth.
	if ((sd = map_id2sd(account_id)) != NULL)
		return;
	
	if ((node = chrif_search(account_id)))
	{	//Is the character already awaiting authorization?
		if (node->state != ST_LOGIN)
			return; //character in logout phase, do not touch that data.
		if (node->sd)
		{
			sd = node->sd;
			if(node->char_dat == NULL &&
				node->account_id == account_id &&
				node->char_id == char_id &&
				node->login_id1 == RFIFOL(fd, 8))
			{ //Auth Ok
				if (pc_authok(sd, RFIFOL(fd, 16), RFIFOL(fd, 12), status))
				{
					chrif_char_online(sd);
					return;
				}
			} else { //Auth Failed
				pc_authfail(sd);				
			}
			chrif_char_offline(sd); //Set client offline
			chrif_auth_delete(account_id, char_id, ST_LOGIN);
			return;
		}
		//When we receive double login info and the client has not connected yet,
		//discard the older one and keep the new one.
		chrif_auth_delete(node->account_id, node->char_id, ST_LOGIN);
	}

	// Awaiting for client to connect.
	node = ers_alloc(auth_db_ers, struct auth_node);
	memset(node, 0, sizeof(struct auth_node));
	node->char_dat = (struct mmo_charstatus *) aMalloc(sizeof(struct mmo_charstatus));

	node->account_id=account_id;
	node->char_id=char_id;
	node->login_id1=RFIFOL(fd, 8);
	node->connect_until_time=RFIFOL(fd, 12);
	node->login_id2=RFIFOL(fd, 16);
	memcpy(node->char_dat,status,sizeof(struct mmo_charstatus));
	node->node_created=gettick();
	idb_put(auth_db, account_id, node);
}