- Moved ignoreAll to state.ignoreAll so it saves some space.

- Cleaned up clif_parse_Wis to prevent crashes from forged packets (using a strlen() on a string where you don't know if it's null-terminated is a NO-NO)
- Cleaned up the implementation of the ignore list so it's more efficient.


git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@9282 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
skotlex 2006-11-21 18:23:08 +00:00
parent 7abcd45cd3
commit 0f433c6c45
4 changed files with 249 additions and 228 deletions

View File

@ -3,6 +3,12 @@ Date Added
AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2006/11/21
* Moved ignoreAll to state.ignoreAll so it saves some space. [Skotlex]
* Cleaned up clif_parse_Wis to prevent crashes from forged packets
[Skotlex]
* Cleaned up the implementation of the ignore list so it's more efficient.
[Skotlex]
2006/11/20
* Implemented NPC_DEFENDER. Reduces ranged Physical+Misc damage by 80%
[Skotlex]

View File

@ -9056,46 +9056,49 @@ void clif_parse_Restart(int fd, struct map_session_data *sd) {
*------------------------------------------
*/
void clif_parse_Wis(int fd, struct map_session_data *sd) { // S 0096 <len>.w <nick>.24B <message>.?B // rewritten by [Yor]
char *gm_command;
char *command, *msg;
struct map_session_data *dstsd;
int i=0;
struct npc_data *npc;
char split_data[10][50];
char target[NAME_LENGTH+1];
char output[256];
unsigned int speclen, scanlen;
unsigned int len;
RFIFOHEAD(fd);
//printf("clif_parse_Wis: message: '%s'.\n", RFIFOP(fd,28));
// Prevent hacked packets like missing null terminator or wrong len specification. [Lance]
speclen = (unsigned int)RFIFOW(fd,2);
scanlen = strlen((const char*)RFIFOP(fd,28)) + 29;
if(scanlen != speclen){
ShowWarning("Hack on Whisper: %s (AID: %d)!\n", sd->status.name, sd->bl.id);
clif_GM_kick(sd,sd,0);
len = RFIFOW(fd,2); //Packet length
if (len < 28)
{ //Invalid packet, specified size is less than minimum! [Skotlex]
ShowWarning("Hack on Whisper: %s (AID/CID: %d:%d)!\n", sd->status.name, sd->status.account_id, sd->status.char_id);
clif_setwaitclose(fd);
return;
}
gm_command = (char*)aMallocA(speclen * sizeof(char)); // 24+3+(RFIFOW(fd,2)-28)+1 or 24+3+(strlen(RFIFOP(fd,28))+1 (size can be wrong with hacker)
sprintf(gm_command, "%s : %s", sd->status.name, RFIFOP(fd,28));
if ((is_charcommand(fd, sd, gm_command) != CharCommand_None) ||
(is_atcommand(fd, sd, gm_command) != AtCommand_None)) {
if(gm_command) aFree(gm_command);
if (len == 28) return; //Not sure if client really lets you send a blank line.
len-=28; //Message length
// 24+3+(RFIFOW(fd,2)-28)+1 <- last 1 is '\0'
command = (char*)aMallocA((NAME_LENGTH+4+len) * sizeof(char));
//No need for out of memory checks, malloc.c aborts the map when that happens.
msg = command;
msg+= sprintf(command, "%s : ", sd->status.name);
memcpy(msg, RFIFOP(fd, 28), len);
msg[len]='\0'; //Force a terminator
if ((is_charcommand(fd, sd, command) != CharCommand_None) ||
(is_atcommand(fd, sd, command) != AtCommand_None)) {
aFree(command);
return;
}
if(gm_command) aFree(gm_command);
if (sd->sc.count &&
(sd->sc.data[SC_BERSERK].timer!=-1 ||
(sd->sc.data[SC_NOCHAT].timer != -1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCHAT)))
(sd->sc.data[SC_NOCHAT].timer != -1 && sd->sc.data[SC_NOCHAT].val1&MANNER_NOCHAT))) {
aFree(command);
return;
}
if (battle_config.min_chat_delay)
{ //[Skotlex]
if (DIFF_TICK(sd->cantalk_tick, gettick()) > 0)
if (DIFF_TICK(sd->cantalk_tick, gettick()) > 0) {
aFree(command);
return;
}
sd->cantalk_tick = gettick() + battle_config.min_chat_delay;
}
@ -9106,21 +9109,17 @@ void clif_parse_Wis(int fd, struct map_session_data *sd) { // S 0096 <len>.w <ni
if(log_config.chat&1 //we log everything then
|| ( log_config.chat&2 //if Whisper bit is on
&& ( !agit_flag || !(log_config.chat&16) ))) //if WOE ONLY flag is off or AGIT is OFF
log_chat("W", 0, sd->status.char_id, sd->status.account_id, (char*)mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, target, (char*)RFIFOP(fd, 28));
log_chat("W", 0, sd->status.char_id, sd->status.account_id, (char*)mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, target, msg);
//-------------------------------------------------------//
// Lordalfa - Paperboy - To whisper NPC commands //
//-------------------------------------------------------//
if (target[0] && (strncasecmp(target,"NPC:",4) == 0) && (strlen(target) >4)) {
char *whisper_tmp = target+4; //Skip the NPC: string part.
if ((npc = npc_name2id(whisper_tmp)))
char *str= target+4; //Skip the NPC: string part.
if ((npc = npc_name2id(str)))
{
char *split, *str;
whisper_tmp=(char *)aMallocA((strlen((char *)(RFIFOP(fd,28)))+1)*sizeof(char));
str=whisper_tmp;
sprintf(whisper_tmp, "%s", (const char*)RFIFOP(fd,28));
char *split;
str = msg;
for( i=0; i < 10; ++i )
{// Splits the message using '#' as separators
split = strchr(str,'#');
@ -9129,7 +9128,7 @@ void clif_parse_Wis(int fd, struct map_session_data *sd) { // S 0096 <len>.w <ni
strncpy(split_data[i], str, sizeof(split_data[0])/sizeof(char));
split_data[i][sizeof(split_data[0])/sizeof(char)-1] = '\0';
for( ++i; i < 10; ++i )
split_data[i][0] = '\0';
split_data[i][0] = '\0';
break;
}
*split = '\0';
@ -9138,90 +9137,98 @@ void clif_parse_Wis(int fd, struct map_session_data *sd) { // S 0096 <len>.w <ni
str = split+1;
}
aFree(whisper_tmp);
whisper_tmp=(char *)aMallocA(15*sizeof(char));
for (i=0;i<10;i++)
{
sprintf(whisper_tmp, "@whispervar%d$", i);
set_var(sd,whisper_tmp,(char *) split_data[i]);
}//You don't need to zero them, just reset them [Kevin]
sprintf(output, "@whispervar%d$", i);
set_var(sd,output,(char *) split_data[i]);
}
aFree(whisper_tmp);
whisper_tmp=(char *)aMallocA((strlen(npc->name)+18)*sizeof(char));
sprintf(whisper_tmp, "%s::OnWhisperGlobal", npc->name);
npc_event(sd,whisper_tmp,0); // Calls the NPC label
sprintf(output, "%s::OnWhisperGlobal", npc->name);
npc_event(sd,output,0); // Calls the NPC label
aFree(whisper_tmp); //I rewrote it a little to use memory allocation, a bit more stable =P [Kevin]
aFree(command);
return;
} //should have just removed the one below that was a my bad =P
}
}
}
// Main chat [LuzZza]
if(strcmpi(target, main_chat_nick) == 0) {
if(!sd->state.mainchat) {
if(!sd->state.mainchat)
clif_displaymessage(fd, msg_txt(388)); // You should enable main chat with "@main on" command.
return;
else {
sprintf(output, msg_txt(386), sd->status.name, msg);
intif_announce(output, strlen(output) + 1, 0xFE000000, 0);
}
sprintf(output, msg_txt(386), sd->status.name, (char *)RFIFOP(fd,28));
intif_announce(output, strlen(output) + 1, 0xFE000000, 0);
aFree(command);
return;
}
// searching destination character
dstsd = map_nick2sd(target);
// player is not on this map-server
if (dstsd == NULL ||
// At this point, don't send wisp/page if it's not exactly the same name, because (example)
// if there are 'Test' player on an other map-server and 'test' player on this map-server,
// and if we ask for 'Test', we must not contact 'test' player
// so, we send information to inter-server, which is the only one which decide (and copy correct name).
strcmp(dstsd->status.name, target) != 0) // not exactly same name
// send message to inter-server
intif_wis_message(sd, target, (char*)RFIFOP(fd,28), RFIFOW(fd,2)-28);
if (dstsd == NULL ||
strcmp(dstsd->status.name, target) != 0)
{ // send message to inter-server
intif_wis_message(sd, target, msg, len);
aFree(command);
return;
}
// player is on this map-server
else {
if (dstsd->fd == fd) {
// if you send to your self, don't send anything to others
if (dstsd->fd == fd) // but, normaly, it's impossible!
clif_wis_message(fd, wisp_server_name, "You can not page yourself. Sorry.", strlen("You can not page yourself. Sorry.") + 1);
// otherwise, send message and answer immediatly
else {
if (dstsd->ignoreAll == 1) {
if (dstsd->sc.option & OPTION_INVISIBLE && pc_isGM(sd) < pc_isGM(dstsd))
clif_wis_end(fd, 1); // 1: target character is not loged in
else
clif_wis_end(fd, 3); // 3: everyone ignored by target
} else {
// if player ignore the source character
for(i = 0; i < MAX_IGNORE_LIST; i++)
if (strcmp(dstsd->ignore[i].name, sd->status.name) == 0) {
clif_wis_end(fd, 2); // 2: ignored by target
break;
}
// if source player not found in ignore list
if (i == MAX_IGNORE_LIST) {
if(strlen(dstsd->away_message) > 0) { // Send away automessage [LuzZza]
//(Automessage has been sent)
sprintf(output, "%s %s", (char*)RFIFOP(fd,28),msg_txt(543));
clif_wis_message(dstsd->fd, sd->status.name, output, strlen(output) + 1);
clif_wis_end(fd, 0); // 0: success to send wisper
if(dstsd->state.autotrade)
//"Away [AT] - \"%s\""
sprintf(output, msg_txt(544), dstsd->away_message);
else
//"Away - \"%s\""
sprintf(output, msg_txt(545), dstsd->away_message);
clif_wis_message(fd, dstsd->status.name, output, strlen(output) + 1);
} else { // Normal message
clif_wis_message(dstsd->fd, sd->status.name, (char*)RFIFOP(fd,28), RFIFOW(fd,2) - 28);
clif_wis_end(fd, 0); // 0: success to send wisper
}
}
}
}
// but, normaly, it's impossible!
clif_wis_message(fd, wisp_server_name,
"You can not page yourself. Sorry.",
strlen("You can not page yourself. Sorry.") + 1);
aFree(command);
return;
}
// otherwise, send message and answer immediatly
if (dstsd->state.ignoreAll) {
if (dstsd->sc.option & OPTION_INVISIBLE && pc_isGM(sd) < pc_isGM(dstsd))
clif_wis_end(fd, 1); // 1: target character is not loged in
else
clif_wis_end(fd, 3); // 3: everyone ignored by target
aFree(command);
return;
}
// if player ignore the source character
for(i = 0; i < MAX_IGNORE_LIST &&
dstsd->ignore[i].name[0] != '\0' &&
strcmp(dstsd->ignore[i].name, sd->status.name) != 0
; i++);
if(i < MAX_IGNORE_LIST && dstsd->ignore[i].name[0] != '\0')
{ //Ignored
clif_wis_end(fd, 2); // 2: ignored by target
aFree(command);
return;
}
// if source player not found in ignore list
if(dstsd->away_message[0] != '\0') { // Send away automessage [LuzZza]
//(Automessage has been sent)
sprintf(output, "%s %s", msg, msg_txt(543));
clif_wis_message(dstsd->fd, sd->status.name, output, strlen(output) + 1);
clif_wis_end(fd, 0); // 0: success to send wisper
if(dstsd->state.autotrade)
//"Away [AT] - \"%s\""
sprintf(output, msg_txt(544), dstsd->away_message);
else
//"Away - \"%s\""
sprintf(output, msg_txt(545), dstsd->away_message);
aFree(command);
clif_wis_message(fd, dstsd->status.name, output, strlen(output) + 1);
return;
}
// Normal message
clif_wis_message(dstsd->fd, sd->status.name, msg, len);
clif_wis_end(fd, 0); // 0: success to send wisper
aFree(command);
return;
}
@ -11028,126 +11035,148 @@ void clif_parse_GMReqNoChatCount(int fd, struct map_session_data *sd)
return;
}
static int pstrcmp(const void *a, const void *b)
{
return strcmp((char *)a, (char *)b);
}
void clif_parse_PMIgnore(int fd, struct map_session_data *sd) { // Rewritten by [Yor]
char output[512];
char *nick; // S 00cf <nick>.24B <type>.B: 00 (/ex nick) deny speech from nick, 01 (/in nick) allow speech from nick
int i, pos;
int i;
RFIFOHEAD(fd);
malloc_tsetdword(output, '\0', sizeof(output));
nick = (char*)RFIFOP(fd,2); // speed up
RFIFOB(fd,NAME_LENGTH+1) = '\0'; // to be sure that the player name have at maximum 23 characters (nick range: [2]->[26])
//printf("Ignore: char '%s' state: %d\n", nick, RFIFOB(fd,26));
WFIFOHEAD(fd,packet_len_table[0xd1]);
WFIFOW(fd,0) = 0x0d1; // R 00d1 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail
WFIFOB(fd,2) = RFIFOB(fd,26);
// do nothing only if nick can not exist
if (strlen(nick) < 4) {
if ((i = strlen(nick)) < 4 || i > NAME_LENGTH) {
WFIFOB(fd,3) = 1; // fail
WFIFOSET(fd, packet_len_table[0x0d1]);
if (RFIFOB(fd,26) == 0) // type
clif_wis_message(fd, wisp_server_name, "It's impossible to block this player.", strlen("It's impossible to block this player.") + 1);
else
clif_wis_message(fd, wisp_server_name, "It's impossible to unblock this player.", strlen("It's impossible to unblock this player.") + 1);
clif_wis_message(fd, wisp_server_name,
"This player name is not valid.",
strlen("This player name is not valid.")+1);
return;
// name can exist
} else {
// deny action (we add nick only if it's not already exist
if (RFIFOB(fd,26) == 0) { // type
pos = -1;
for(i = 0; i < MAX_IGNORE_LIST; i++) {
if (strcmp(sd->ignore[i].name, nick) == 0) {
WFIFOB(fd,3) = 1; // fail
WFIFOSET(fd, packet_len_table[0x0d1]);
clif_wis_message(fd, wisp_server_name, "This player is already blocked.", strlen("This player is already blocked.") + 1);
if (strcmp(wisp_server_name, nick) == 0) { // to found possible bot users who automaticaly ignore people.
sprintf(output, "Character '%s' (account: %d) has tried AGAIN to block wisps from '%s' (wisp name of the server). Bot user?", sd->status.name, sd->status.account_id, wisp_server_name);
intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, output);
}
return;
} else if (pos == -1 && sd->ignore[i].name[0] == '\0')
pos = i;
}
// if a position is found and name not found, we add it in the list
if (pos != -1) {
memcpy(sd->ignore[pos].name, nick, NAME_LENGTH-1);
WFIFOB(fd,3) = 0; // success
WFIFOSET(fd, packet_len_table[0x0d1]);
if (strcmp(wisp_server_name, nick) == 0) { // to found possible bot users who automaticaly ignore people.
sprintf(output, "Character '%s' (account: %d) has tried to block wisps from '%s' (wisp name of the server). Bot user?", sd->status.name, sd->status.account_id, wisp_server_name);
intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, output);
// send something to be inform and force bot to ignore twice... If GM receiving block + block again, it's a bot :)
clif_wis_message(fd, wisp_server_name, "Add me in your ignore list, doesn't block my wisps.", strlen("Add me in your ignore list, doesn't block my wisps.") + 1);
}
} else {
WFIFOB(fd,3) = 1; // fail
WFIFOSET(fd, packet_len_table[0x0d1]);
clif_wis_message(fd, wisp_server_name, "You can not block more people.", strlen("You can not block more people.") + 1);
if (strcmp(wisp_server_name, nick) == 0) { // to found possible bot users who automaticaly ignore people.
sprintf(output, "Character '%s' (account: %d) has tried to block wisps from '%s' (wisp name of the server). Bot user?", sd->status.name, sd->status.account_id, wisp_server_name);
intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, output);
}
}
// allow action (we remove all same nicks if they exist)
} else {
pos = -1;
for(i = 0; i < MAX_IGNORE_LIST; i++)
if (strcmp(sd->ignore[i].name, nick) == 0) {
malloc_tsetdword(sd->ignore[i].name, 0, sizeof(sd->ignore[i].name));
if (pos == -1) {
WFIFOB(fd,3) = 0; // success
WFIFOSET(fd, packet_len_table[0x0d1]);
pos = i; // don't break, to remove ALL same nick
}
}
if (pos == -1) {
WFIFOB(fd,3) = 1; // fail
WFIFOSET(fd, packet_len_table[0x0d1]);
clif_wis_message(fd, wisp_server_name, "This player is not blocked by you.", strlen("This player is not blocked by you.") + 1);
}
}
}
// name can exist
// deny action (we add nick only if it's not already exist
if (RFIFOB(fd,26) == 0) { // Add block
for(i = 0; i < MAX_IGNORE_LIST &&
sd->ignore[i].name[0] != '\0' &&
strcmp(sd->ignore[i].name, nick) != 0
; i++);
// for(i = 0; i < MAX_IGNORE_LIST; i++) // for debug only
// if (sd->ignore[i].name[0] != '\0')
// printf("Ignored player: '%s'\n", sd->ignore[i].name);
if (i == MAX_IGNORE_LIST) { //Full List
WFIFOB(fd,3) = 1; // fail
WFIFOSET(fd, packet_len_table[0x0d1]);
clif_wis_message(fd, wisp_server_name,
"You can not block more people.",
strlen("You can not block more people.") + 1);
if (strcmp(wisp_server_name, nick) == 0)
{ // to found possible bot users who automaticaly ignore people.
sprintf(output, "Character '%s' (account: %d) has tried to block wisps from '%s' (wisp name of the server). Bot user?", sd->status.name, sd->status.account_id, wisp_server_name);
intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, output);
}
return;
}
if(sd->ignore[i].name[0] != '\0')
{ //Name already exists.
WFIFOB(fd,3) = 1; // fail
WFIFOSET(fd, packet_len_table[0x0d1]);
clif_wis_message(fd, wisp_server_name,
"This player is already blocked.",
strlen("This player is already blocked.") + 1);
if (strcmp(wisp_server_name, nick) == 0) { // to found possible bot users who automaticaly ignore people.
sprintf(output, "Character '%s' (account: %d) has tried AGAIN to block wisps from '%s' (wisp name of the server). Bot user?", sd->status.name, sd->status.account_id, wisp_server_name);
intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, output);
}
return;
}
//Insert in position i
memcpy(sd->ignore[i].name, nick, NAME_LENGTH-1);
WFIFOB(fd,3) = 0; // success
WFIFOSET(fd, packet_len_table[0x0d1]);
if (strcmp(wisp_server_name, nick) == 0)
{ // to found possible bot users who automaticaly ignore people.
sprintf(output, "Character '%s' (account: %d) has tried to block wisps from '%s' (wisp name of the server). Bot user?", sd->status.name, sd->status.account_id, wisp_server_name);
intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, output);
// send something to be inform and force bot to ignore twice... If GM receiving block + block again, it's a bot :)
clif_wis_message(fd, wisp_server_name,
"Adding me in your ignore list will not block my wisps.",
strlen("Adding me in your ignore list will not block my wisps.") + 1);
}
//Sort the ignore list.
qsort (sd->ignore[0].name, MAX_IGNORE_LIST, sizeof(sd->ignore[0].name), pstrcmp);
return;
}
//Remove name
for(i = 0; i < MAX_IGNORE_LIST &&
sd->ignore[i].name[0] != '\0' &&
strcmp(sd->ignore[i].name, nick) != 0
; i++);
if (i == MAX_IGNORE_LIST || sd->ignore[i].name[i] == '\0')
{ //Not found
WFIFOB(fd,3) = 1; // fail
WFIFOSET(fd, packet_len_table[0x0d1]);
clif_wis_message(fd, wisp_server_name,
"This player is not blocked by you.",
strlen("This player is not blocked by you.") + 1);
return;
}
//Move everything one place down to overwrite removed entry.
memmove(sd->ignore[i].name, sd->ignore[i+1].name,
(MAX_IGNORE_LIST-i-1)*sizeof(sd->ignore[0].name));
malloc_tsetdword(sd->ignore[MAX_IGNORE_LIST-1].name, 0, sizeof(sd->ignore[0].name));
// success
WFIFOB(fd,3) = 0;
WFIFOSET(fd, packet_len_table[0x0d1]);
// for debug only
// for(i = 0; i < MAX_IGNORE_LIST && sd->ignore[i].name[0] != '\0'; i++) /
// ShowDebug("Ignored player: '%s'\n", sd->ignore[i].name);
return;
}
void clif_parse_PMIgnoreAll(int fd, struct map_session_data *sd) { // Rewritten by [Yor]
//printf("Ignore all: state: %d\n", RFIFOB(fd,2));
RFIFOHEAD(fd);
if (RFIFOB(fd,2) == 0) {// S 00d0 <type>len.B: 00 (/exall) deny all speech, 01 (/inall) allow all speech
WFIFOHEAD(fd,packet_len_table[0xd2]);
WFIFOW(fd,0) = 0x0d2; // R 00d2 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail
WFIFOB(fd,2) = 0;
if (sd->ignoreAll == 0) {
sd->ignoreAll = 1;
WFIFOB(fd,3) = 0; // success
WFIFOSET(fd, packet_len_table[0x0d2]);
} else {
WFIFOHEAD(fd,packet_len_table[0xd2]);
// R 00d2 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail
// S 00d0 <type>len.B: 00 (/exall) deny all speech, 01 (/inall) allow all speech
WFIFOW(fd,0) = 0x0d2;
WFIFOB(fd,2) = RFIFOB(fd,2);
if (RFIFOB(fd,2) == 0) { //Deny all
if (sd->state.ignoreAll) {
WFIFOB(fd,3) = 1; // fail
WFIFOSET(fd, packet_len_table[0x0d2]);
clif_wis_message(fd, wisp_server_name, "You already block everyone.", strlen("You already block everyone.") + 1);
}
} else {
WFIFOHEAD(fd,packet_len_table[0xd2]);
WFIFOW(fd,0) = 0x0d2; // R 00d2 <type>.B <fail>.B: type: 0: deny, 1: allow, fail: 0: success, 1: fail
WFIFOB(fd,2) = 1;
if (sd->ignoreAll == 1) {
sd->ignoreAll = 0;
WFIFOB(fd,3) = 0; // success
WFIFOSET(fd, packet_len_table[0x0d2]);
} else {
WFIFOB(fd,3) = 1; // fail
WFIFOSET(fd, packet_len_table[0x0d2]);
clif_wis_message(fd, wisp_server_name, "You already allow everyone.", strlen("You already allow everyone.") + 1);
clif_wis_message(fd, wisp_server_name,
"You already block everyone.",
strlen("You already block everyone.") + 1);
return;
}
sd->state.ignoreAll = 1;
WFIFOB(fd,3) = 0; // success
WFIFOSET(fd, packet_len_table[0x0d2]);
return ;
}
//Unblock everyone
if (!sd->state.ignoreAll) {
WFIFOB(fd,3) = 1; // fail
WFIFOSET(fd, packet_len_table[0x0d2]);
clif_wis_message(fd, wisp_server_name,
"You already allow everyone.",
strlen("You already allow everyone.") + 1);
return;
}
sd->state.ignoreAll = 0;
WFIFOB(fd,3) = 0; // success
WFIFOSET(fd, packet_len_table[0x0d2]);
return;
}
@ -11155,32 +11184,18 @@ void clif_parse_PMIgnoreAll(int fd, struct map_session_data *sd) { // Rewritten
* WisÛƒŠƒXƒg
*------------------------------------------
*/
int pstrcmp(const void *a, const void *b)
{
return strcmp((char *)a, (char *)b);
}
void clif_parse_PMIgnoreList(int fd,struct map_session_data *sd)
{
int i,j=0,count=0;
int i;
qsort (sd->ignore[0].name, MAX_IGNORE_LIST, sizeof(sd->ignore[0].name), pstrcmp);
for(i = 0; i < MAX_IGNORE_LIST; i++){ //中身があるのを数える
if(sd->ignore[i].name[0] != 0)
count++;
}
WFIFOHEAD(fd, 4 + (NAME_LENGTH * count));
WFIFOHEAD(fd, 4 + (NAME_LENGTH * MAX_IGNORE_LIST));
WFIFOW(fd,0) = 0xd4;
WFIFOW(fd,2) = 4 + (NAME_LENGTH * count);
for(i = 0; i < MAX_IGNORE_LIST; i++){
if(sd->ignore[i].name[0] != 0){
memcpy(WFIFOP(fd, 4 + j * 24),sd->ignore[i].name, NAME_LENGTH);
j++;
}
}
WFIFOSET(fd, WFIFOW(fd,2));
if(count >= MAX_IGNORE_LIST) //満タンなら最後の1個を消す
sd->ignore[MAX_IGNORE_LIST - 1].name[0] = 0;
for(i = 0; i < MAX_IGNORE_LIST && sd->ignore[i].name[0] != '\0'; i++)
memcpy(WFIFOP(fd, 4 + i * NAME_LENGTH),sd->ignore[i].name, NAME_LENGTH);
WFIFOW(fd,2) = 4 + i * NAME_LENGTH;
WFIFOSET(fd, WFIFOW(fd,2));
return;
}

View File

@ -845,33 +845,33 @@ int intif_parse_WisMessage(int fd) { // rewritten by [Yor]
int id, i;
RFIFOHEAD(fd);
id=RFIFOL(fd,4);
i=0; //,j=0;
// if(battle_config.etc_log)
// printf("intif_parse_wismessage: %d %s %s %s\n",id,RFIFOP(fd,6),RFIFOP(fd,30),RFIFOP(fd,54) );
memcpy(name, RFIFOP(fd,32), NAME_LENGTH);
name[NAME_LENGTH-1] = '\0'; //In case name arrived without it's terminator. [Skotlex]
sd=(struct map_session_data *) map_nick2sd(name); // 送信先を探す
if(sd!=NULL && strcmp(sd->status.name, name) == 0){
if(sd->ignoreAll == 1)
intif_wis_replay(RFIFOL(fd,4), 2); // 受信拒否
else {
wisp_source = (char *) RFIFOP(fd,8); // speed up [Yor]
for(i=0;i<MAX_IGNORE_LIST;i++){ //拒否リストに名前があるかどうか判定してあれば拒否
if(strcmp(sd->ignore[i].name, wisp_source)==0){
break;
}
}
if(i==MAX_IGNORE_LIST) // run out of list, so we are not ignored
{
clif_wis_message(sd->fd, wisp_source, (char*)RFIFOP(fd,56),RFIFOW(fd,2)-56);
intif_wis_replay(id,0); // 送信成功
}
else
intif_wis_replay(id, 2); // 受信拒否
}
}else
intif_wis_replay(id,1); // そんな人いません
sd = map_nick2sd(name);
if(sd == NULL || strcmp(sd->status.name, name) != 0)
{ //Not found
intif_wis_replay(id,1);
return 0;
}
if(sd->state.ignoreAll) {
intif_wis_replay(id, 2);
return 0;
}
wisp_source = (char *) RFIFOP(fd,8); // speed up [Yor]
for(i=0; i < MAX_IGNORE_LIST &&
sd->ignore[i].name[0] != '\0' &&
strcmp(sd->ignore[i].name, wisp_source) != 0
; i++);
if (i < MAX_IGNORE_LIST && sd->ignore[i].name[0] != '\0')
{ //Ignored
intif_wis_replay(id, 2);
return 0;
}
//Success to send whisper.
clif_wis_message(sd->fd, wisp_source, (char*)RFIFOP(fd,56),RFIFOW(fd,2)-56);
intif_wis_replay(id,0); // <E28098>M<EFBFBD>¬Œ÷
return 0;
}

View File

@ -596,6 +596,7 @@ struct map_session_data {
unsigned killer : 1;
unsigned killable : 1;
unsigned doridori : 1;
unsigned ignoreAll : 1;
unsigned short autoloot;
struct guild *gmaster_flag;
} state;
@ -638,7 +639,6 @@ struct map_session_data {
struct{
char name[NAME_LENGTH];
} ignore[MAX_IGNORE_LIST];
int ignoreAll;
int followtimer; // [MouseJstr]
int followtarget;