فهرست منبع

- 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

skotlex 18 سال پیش
والد
کامیت
0f433c6c45
4فایلهای تغییر یافته به همراه246 افزوده شده و 225 حذف شده
  1. 6 0
      Changelog-Trunk.txt
  2. 215 200
      src/map/clif.c
  3. 24 24
      src/map/intif.c
  4. 1 1
      src/map/map.h

+ 6 - 0
Changelog-Trunk.txt

@@ -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]

+ 215 - 200
src/map/clif.c

@@ -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]
-			
-			aFree(whisper_tmp);
-			whisper_tmp=(char *)aMallocA((strlen(npc->name)+18)*sizeof(char));
+				sprintf(output, "@whispervar%d$", i);
+				set_var(sd,output,(char *) split_data[i]);        
+			}
 			
-			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);
-				}
+	// 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++);
+
+		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);
 			}
-		// 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);
+			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++);
 
-//	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 || 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 {
-			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 {
+	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 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拒否リスト
  *------------------------------------------
  */
- 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;
 }
 

+ 24 - 24
src/map/intif.c

@@ -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);   // 送信成功
 	return 0;
 }
 

+ 1 - 1
src/map/map.h

@@ -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;