summaryrefslogtreecommitdiff
path: root/src/map/clif.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/clif.c')
-rw-r--r--src/map/clif.c845
1 files changed, 427 insertions, 418 deletions
diff --git a/src/map/clif.c b/src/map/clif.c
index 07b0b323b..259bc7253 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -319,17 +319,17 @@ int clif_send_sub(struct block_list *bl, va_list ap) {
return 0;
break;
case AREA_WOC:
- if (sd->chatID || bl == src_bl)
+ if (sd->chat_id != 0 || bl == src_bl)
return 0;
break;
case AREA_WOSC: {
if (src_bl->type == BL_PC) {
const struct map_session_data *ssd = BL_UCCAST(BL_PC, src_bl);
- if (ssd != NULL && sd->chatID != 0 && (sd->chatID == ssd->chatID))
+ if (ssd != NULL && sd->chat_id != 0 && (sd->chat_id == ssd->chat_id))
return 0;
} else if (src_bl->type == BL_NPC) {
const struct npc_data *nd = BL_UCCAST(BL_NPC, src_bl);
- if (nd != NULL && sd->chatID != 0 && (sd->chatID == nd->chat_id))
+ if (nd != NULL && sd->chat_id != 0 && (sd->chat_id == nd->chat_id))
return 0;
}
}
@@ -435,7 +435,7 @@ bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target
{
const struct chat_data *cd = NULL;
if (sd != NULL) {
- cd = map->id2cd(sd->chatID);
+ cd = map->id2cd(sd->chat_id);
} else {
cd = BL_CCAST(BL_CHAT, bl);
}
@@ -1049,6 +1049,7 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu
#endif
#if PACKETVER >= 20150513
p.body = vd->body_style;
+ safestrncpy(p.name, clif->get_bl_name(bl), NAME_LENGTH);
#endif
clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target);
@@ -1189,6 +1190,7 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) {
#endif
#if PACKETVER >= 20150513
p.body = vd->body_style;
+ safestrncpy(p.name, clif->get_bl_name(bl), NAME_LENGTH);
#endif
if( disguised(bl) ) {
nullpo_retv(sd);
@@ -1280,6 +1282,7 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd,
#endif
#if PACKETVER >= 20150513
p.body = vd->body_style;
+ safestrncpy(p.name, clif->get_bl_name(bl), NAME_LENGTH);
#endif
clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target);
@@ -1954,20 +1957,23 @@ void clif_selllist(struct map_session_data *sd)
/// - set npcid of dialog window (0 by default)
/// - if set to clear on next mes, clear contents
/// - append this text
-void clif_scriptmes(struct map_session_data *sd, int npcid, const char *mes) {
- int fd = sd->fd;
- size_t slen;
+void clif_scriptmes(struct map_session_data *sd, int npcid, const char *mes)
+{
+ int fd, slen;
nullpo_retv(sd);
nullpo_retv(mes);
- slen = strlen(mes) + 9;
+
+ fd = sd->fd;
+ slen = (int)strlen(mes) + 9;
+ Assert_retv(slen <= INT16_MAX);
sd->state.dialog = 1;
WFIFOHEAD(fd, slen);
- WFIFOW(fd,0)=0xb4;
- WFIFOW(fd,2)=slen;
- WFIFOL(fd,4)=npcid;
+ WFIFOW(fd,0) = 0xb4;
+ WFIFOW(fd,2) = slen;
+ WFIFOL(fd,4) = npcid;
memcpy(WFIFOP(fd,8), mes, slen-8);
WFIFOSET(fd,WFIFOW(fd,2));
}
@@ -2069,24 +2075,27 @@ void clif_sendfakenpc(struct map_session_data *sd, int npcid) {
/// WARNING: the 'cancel' button closes other windows besides the dialog window and the menu window.
/// Which suggests their have intertwined behavior. (probably the mouse targeting)
/// TODO investigate behavior of other windows [FlavioJS]
-void clif_scriptmenu(struct map_session_data* sd, int npcid, const char* mes) {
- int fd;
- size_t slen;
+void clif_scriptmenu(struct map_session_data *sd, int npcid, const char *mes)
+{
+ int fd, slen;
struct block_list *bl = NULL;
nullpo_retv(sd);
nullpo_retv(mes);
+
fd = sd->fd;
- slen = strlen(mes) + 9;
+ slen = (int)strlen(mes) + 9;
+ Assert_retv(slen <= INT16_MAX);
+
if (!sd->state.using_fake_npc && (npcid == npc->fake_nd->bl.id || ((bl = map->id2bl(npcid)) != NULL && (bl->m!=sd->bl.m ||
bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 ||
bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1))))
clif->sendfakenpc(sd, npcid);
WFIFOHEAD(fd, slen);
- WFIFOW(fd,0)=0xb7;
- WFIFOW(fd,2)=slen;
- WFIFOL(fd,4)=npcid;
+ WFIFOW(fd,0) = 0xb7;
+ WFIFOW(fd,2) = slen;
+ WFIFOL(fd,4) = npcid;
memcpy(WFIFOP(fd,8), mes, slen-8);
WFIFOSET(fd,WFIFOW(fd,2));
}
@@ -3607,26 +3616,29 @@ void clif_createchat(struct map_session_data* sd, int flag)
/// 1 = public
/// 2 = arena (npc waiting room)
/// 3 = PK zone (non-clickable)
-void clif_dispchat(struct chat_data* cd, int fd)
+void clif_dispchat(struct chat_data *cd, int fd)
{
unsigned char buf[128];
uint8 type;
+ int len;
- if( cd == NULL || cd->owner == NULL )
+ if (cd == NULL || cd->owner == NULL)
return;
type = (cd->owner->type == BL_PC ) ? (cd->pub) ? 1 : 0
: (cd->owner->type == BL_NPC) ? (cd->limit) ? 2 : 3
: 1;
+ len = (int)strlen(cd->title);
+ Assert_retv(len <= INT16_MAX - 17);
WBUFW(buf, 0) = 0xd7;
- WBUFW(buf, 2) = 17 + strlen(cd->title);
+ WBUFW(buf, 2) = 17 + len;
WBUFL(buf, 4) = cd->owner->id;
WBUFL(buf, 8) = cd->bl.id;
WBUFW(buf,12) = cd->limit;
WBUFW(buf,14) = (cd->owner->type == BL_NPC) ? cd->users+1 : cd->users;
WBUFB(buf,16) = type;
- memcpy(WBUFP(buf,17), cd->title, strlen(cd->title)); // not zero-terminated
+ memcpy(WBUFP(buf,17), cd->title, len); // not zero-terminated
if( fd ) {
WFIFOHEAD(fd,WBUFW(buf,2));
@@ -3644,10 +3656,11 @@ void clif_dispchat(struct chat_data* cd, int fd)
/// 1 = public
/// 2 = arena (npc waiting room)
/// 3 = PK zone (non-clickable)
-void clif_changechatstatus(struct chat_data* cd)
+void clif_changechatstatus(struct chat_data *cd)
{
unsigned char buf[128];
uint8 type;
+ int len;
if( cd == NULL || cd->usersd[0] == NULL )
return;
@@ -3655,15 +3668,17 @@ void clif_changechatstatus(struct chat_data* cd)
type = (cd->owner->type == BL_PC ) ? (cd->pub) ? 1 : 0
: (cd->owner->type == BL_NPC) ? (cd->limit) ? 2 : 3
: 1;
+ len = (int)strlen(cd->title);
+ Assert_retv(len <= INT16_MAX - 17);
WBUFW(buf, 0) = 0xdf;
- WBUFW(buf, 2) = 17 + strlen(cd->title);
+ WBUFW(buf, 2) = 17 + len;
WBUFL(buf, 4) = cd->owner->id;
WBUFL(buf, 8) = cd->bl.id;
WBUFW(buf,12) = cd->limit;
WBUFW(buf,14) = (cd->owner->type == BL_NPC) ? cd->users+1 : cd->users;
WBUFB(buf,16) = type;
- memcpy(WBUFP(buf,17), cd->title, strlen(cd->title)); // not zero-terminated
+ memcpy(WBUFP(buf,17), cd->title, len); // not zero-terminated
clif->send(buf,WBUFW(buf,2),cd->owner,CHAT);
}
@@ -4112,8 +4127,8 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds
nullpo_retv(sd);
nullpo_retv(dstsd);
- if( dstsd->chatID ) {
- struct chat_data *cd = map->id2cd(dstsd->chatID);
+ if (dstsd->chat_id != 0) {
+ struct chat_data *cd = map->id2cd(dstsd->chat_id);
if (cd != NULL && cd->usersd[0] == dstsd)
clif->dispchat(cd,sd->fd);
} else if( dstsd->state.vending )
@@ -4615,9 +4630,9 @@ int clif_outsight(struct block_list *bl,va_list ap)
case BL_PC:
if (sd->vd.class_ != INVISIBLE_CLASS)
clif->clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd);
- if (sd->chatID) {
- struct chat_data *cd = map->id2cd(sd->chatID);
- if(cd->usersd[0]==sd)
+ if (sd->chat_id != 0) {
+ struct chat_data *cd = map->id2cd(sd->chat_id);
+ if (cd != NULL && cd->usersd[0] == sd)
clif->dispchat(cd,tsd->fd);
}
if( sd->state.vending )
@@ -5475,23 +5490,24 @@ void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val
/// Send message (modified by [Yor]) (ZC_NOTIFY_PLAYERCHAT).
/// 008e <packet len>.W <message>.?B
-void clif_displaymessage(const int fd, const char* mes) {
+void clif_displaymessage(const int fd, const char *mes)
+{
nullpo_retv(mes);
- if( map->cpsd_active && fd == 0 ) {
+ if (map->cpsd_active && fd == 0) {
ShowInfo("HCP: %s\n",mes);
- } else if ( fd > 0 ) {
+ } else if (fd > 0) {
#if PACKETVER == 20141022
/** for some reason game client crashes depending on message pattern (only for this packet) **/
/** so we redirect to ZC_NPC_CHAT **/
clif->messagecolor_self(fd, COLOR_DEFAULT, mes);
#else
- size_t len;
+ int len = (int)strnlen(mes, 255);
- if ( ( len = strnlen(mes, 255) ) > 0 ) { // don't send a void message (it's not displaying on the client chat). @help can send void line.
+ if (len > 0) { // don't send a void message (it's not displaying on the client chat). @help can send void line.
WFIFOHEAD(fd, 5 + len);
WFIFOW(fd,0) = 0x8e;
- WFIFOW(fd,2) = 5 + len; // 4 + len + NULL terminate
+ WFIFOW(fd,2) = 5 + len; // 4 + len + NUL terminate
safestrncpy(WFIFOP(fd,4), mes, len + 1);
WFIFOSET(fd, 5 + len);
}
@@ -5513,7 +5529,7 @@ void clif_displaymessage2(const int fd, const char* mes) {
line = strtok(message, "\n");
while(line != NULL) {
// Limit message to 255+1 characters (otherwise it causes a buffer overflow in the client)
- size_t len = strnlen(line, 255);
+ int len = (int)strnlen(line, 255);
if (len > 0) { // don't send a void message (it's not displaying on the client chat). @help can send void line.
if( map->cpsd_active && fd == 0 ) {
@@ -5567,7 +5583,7 @@ void clif_displaymessage_sprintf(const int fd, const char *mes, ...) {
}
/// Send broadcast message in yellow or blue without font formatting (ZC_BROADCAST).
/// 009a <packet len>.W <message>.?B
-void clif_broadcast(struct block_list *bl, const char *mes, size_t len, int type, enum send_target target)
+void clif_broadcast(struct block_list *bl, const char *mes, int len, int type, enum send_target target)
{
int lp = (type&BC_COLOR_MASK) ? 4 : 0;
unsigned char *buf = NULL;
@@ -5591,38 +5607,38 @@ void clif_broadcast(struct block_list *bl, const char *mes, size_t len, int type
* Displays a message on a 'bl' to all it's nearby clients
* Used by npc_globalmessage
*------------------------------------------*/
-void clif_GlobalMessage(struct block_list* bl, const char* message) {
+void clif_GlobalMessage(struct block_list *bl, const char *message)
+{
char buf[256];
- size_t len;
+ int len;
nullpo_retv(bl);
- if(!message)
+ if (message == NULL)
return;
- len = strlen(message)+1;
+ len = (int)strlen(message)+1;
- if (len > sizeof(buf)-8) {
- ShowWarning("clif_GlobalMessage: Truncating too long message '%s' (len=%"PRIuS").\n", message, len);
- len = sizeof(buf)-8;
+ if (len > (int)sizeof(buf)-8) {
+ ShowWarning("clif_GlobalMessage: Truncating too long message '%s' (len=%d).\n", message, len);
+ len = (int)sizeof(buf)-8;
}
- WBUFW(buf,0)=0x8d;
- WBUFW(buf,2)=len+8;
- WBUFL(buf,4)=bl->id;
+ WBUFW(buf,0) = 0x8d;
+ WBUFW(buf,2) = len+8;
+ WBUFL(buf,4) = bl->id;
safestrncpy(WBUFP(buf,8),message,len);
- clif->send((unsigned char *) buf,WBUFW(buf,2),bl,ALL_CLIENT);
-
+ clif->send(buf,WBUFW(buf,2),bl,ALL_CLIENT);
}
/// Send broadcast message with font formatting (ZC_BROADCAST2).
/// 01c3 <packet len>.W <fontColor>.L <fontType>.W <fontSize>.W <fontAlign>.W <fontY>.W <message>.?B
-void clif_broadcast2(struct block_list* bl, const char* mes, size_t len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target)
+void clif_broadcast2(struct block_list *bl, const char *mes, int len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target)
{
unsigned char *buf;
nullpo_retv(mes);
- buf = (unsigned char*)aMalloc((16 + len)*sizeof(unsigned char));
+ buf = aMalloc((16 + len)*sizeof(unsigned char));
WBUFW(buf,0) = 0x1c3;
WBUFW(buf,2) = len + 16;
WBUFL(buf,4) = fontColor;
@@ -5790,7 +5806,7 @@ void clif_upgrademessage(int fd, int result, int item_id)
/// Whisper is transmitted to the destination player (ZC_WHISPER).
/// 0097 <packet len>.W <nick>.24B <message>.?B
/// 0097 <packet len>.W <nick>.24B <isAdmin>.L <message>.?B (PACKETVER >= 20091104)
-void clif_wis_message(int fd, const char *nick, const char *mes, size_t mes_len)
+void clif_wis_message(int fd, const char *nick, const char *mes, int mes_len)
{
#if PACKETVER >= 20091104
struct map_session_data *ssd = NULL;
@@ -5799,21 +5815,21 @@ void clif_wis_message(int fd, const char *nick, const char *mes, size_t mes_len)
nullpo_retv(mes);
#if PACKETVER < 20091104
- WFIFOHEAD(fd, mes_len + NAME_LENGTH + 4);
+ WFIFOHEAD(fd, mes_len + NAME_LENGTH + 5);
WFIFOW(fd,0) = 0x97;
- WFIFOW(fd,2) = mes_len + NAME_LENGTH + 4;
+ WFIFOW(fd,2) = mes_len + NAME_LENGTH + 5;
safestrncpy(WFIFOP(fd,4), nick, NAME_LENGTH);
- safestrncpy(WFIFOP(fd,28), mes, mes_len);
+ safestrncpy(WFIFOP(fd,28), mes, mes_len + 1);
WFIFOSET(fd,WFIFOW(fd,2));
#else
ssd = map->nick2sd(nick);
- WFIFOHEAD(fd, mes_len + NAME_LENGTH + 8);
+ WFIFOHEAD(fd, mes_len + NAME_LENGTH + 9);
WFIFOW(fd,0) = 0x97;
- WFIFOW(fd,2) = mes_len + NAME_LENGTH + 8;
+ WFIFOW(fd,2) = mes_len + NAME_LENGTH + 9;
safestrncpy(WFIFOP(fd,4), nick, NAME_LENGTH);
WFIFOL(fd,28) = (ssd && pc_get_group_level(ssd) == 99) ? 1 : 0; // isAdmin; if nonzero, also displays text above char
- safestrncpy(WFIFOP(fd,32), mes, mes_len);
+ safestrncpy(WFIFOP(fd,32), mes, mes_len + 1);
WFIFOSET(fd,WFIFOW(fd,2));
#endif
}
@@ -6599,7 +6615,7 @@ void clif_party_withdraw(struct party_data* p, struct map_session_data* sd, int
/// Party chat message (ZC_NOTIFY_CHAT_PARTY).
/// 0109 <packet len>.W <account id>.L <message>.?B
-void clif_party_message(struct party_data* p, int account_id, const char* mes, int len)
+void clif_party_message(struct party_data *p, int account_id, const char *mes, int len)
{
struct map_session_data *sd;
int i;
@@ -6607,22 +6623,24 @@ void clif_party_message(struct party_data* p, int account_id, const char* mes, i
nullpo_retv(p);
nullpo_retv(mes);
- for(i=0; i < MAX_PARTY && !p->data[i].sd;i++);
- if(i < MAX_PARTY){
+ ARR_FIND(0, MAX_PARTY, i, p->data[i].sd != NULL);
+
+ if (i < MAX_PARTY) {
unsigned char buf[1024];
+ int maxlen = (int)sizeof(buf) - 9;
- if (len > sizeof(buf)-8) {
- ShowWarning("clif_party_message: Truncated message '%s' (len=%d, max=%"PRIuS", party_id=%d).\n",
- mes, len, sizeof(buf)-8, p->party.party_id);
- len = sizeof(buf)-8;
+ if (len > maxlen) {
+ ShowWarning("clif_party_message: Truncated message '%s' (len=%d, max=%d, party_id=%d).\n",
+ mes, len, maxlen, p->party.party_id);
+ len = maxlen;
}
sd = p->data[i].sd;
- WBUFW(buf,0)=0x109;
- WBUFW(buf,2)=len+8;
- WBUFL(buf,4)=account_id;
- safestrncpy(WBUFP(buf,8), mes, len);
- clif->send(buf,len+8,&sd->bl,PARTY);
+ WBUFW(buf,0) = 0x109;
+ WBUFW(buf,2) = len+9;
+ WBUFL(buf,4) = account_id;
+ safestrncpy(WBUFP(buf,8), mes, len+1);
+ clif->send(buf, len+9, &sd->bl, PARTY);
}
}
@@ -7934,19 +7952,21 @@ void clif_marriage_proposal(int fd, struct map_session_data *sd, struct map_sess
/*==========================================
* Displays a message using the guild-chat colors to the specified targets. [Skotlex]
*------------------------------------------*/
-void clif_disp_message(struct block_list* src, const char* mes, size_t len, enum send_target target)
+void clif_disp_message(struct block_list *src, const char *mes, enum send_target target)
{
unsigned char buf[256];
+ int len;
+
+ nullpo_retv(mes);
+ nullpo_retv(src);
+ len = (int)strlen(mes);
if (len == 0)
return;
- nullpo_retv(src);
- nullpo_retv(mes);
-
- if (len > sizeof(buf)-5) {
- ShowWarning("clif_disp_message: Truncated message '%s' (len=%"PRIuS", max=%"PRIuS", aid=%d).\n", mes, len, sizeof(buf)-5, src->id);
- len = sizeof(buf)-5;
+ if (len > (int)sizeof(buf)-5) {
+ ShowWarning("clif_disp_message: Truncated message '%s' (len=%d, max=%"PRIuS", aid=%d).\n", mes, len, sizeof(buf)-5, src->id);
+ len = (int)sizeof(buf)-5;
}
WBUFW(buf, 0) = 0x17f;
@@ -8200,10 +8220,11 @@ void clif_specialeffect_value(struct block_list* bl, int effect_id, int num, sen
*/
void clif_messagecolor_self(int fd, uint32 color, const char *msg)
{
- size_t msg_len;
+ int msg_len;
nullpo_retv(msg);
- msg_len = strlen(msg) + 1;
+ msg_len = (int)strlen(msg) + 1;
+ Assert_retv(msg_len <= INT16_MAX - 12);
WFIFOHEAD(fd,msg_len + 12);
WFIFOW(fd,0) = 0x2C1;
@@ -8223,17 +8244,19 @@ void clif_messagecolor_self(int fd, uint32 color, const char *msg)
* @param color Message color (RGB format: 0xRRGGBB)
* @param msg Message text
*/
-void clif_messagecolor(struct block_list* bl, uint32 color, const char *msg)
+void clif_messagecolor(struct block_list *bl, uint32 color, const char *msg)
{
- size_t msg_len = strlen(msg) + 1;
+ int msg_len;
uint8 buf[256];
nullpo_retv(bl);
nullpo_retv(msg);
- if (msg_len > sizeof(buf)-12) {
- ShowWarning("clif_messagecolor: Truncating too long message '%s' (len=%"PRIuS").\n", msg, msg_len);
- msg_len = sizeof(buf)-12;
+ msg_len = (int)strlen(msg) + 1;
+
+ if (msg_len > (int)sizeof(buf)-12) {
+ ShowWarning("clif_messagecolor: Truncating too long message '%s' (len=%d).\n", msg, msg_len);
+ msg_len = (int)sizeof(buf)-12;
}
WBUFW(buf,0) = 0x2C1;
@@ -8313,7 +8336,7 @@ void clif_refresh(struct map_session_data *sd)
clif->elemental_info(sd);
map->foreachinrange(clif->getareachar,&sd->bl,AREA_SIZE,BL_ALL,sd);
clif->weather_check(sd);
- if( sd->chatID )
+ if (sd->chat_id != 0)
chat->leave(sd, false);
if( sd->state.vending )
clif->openvending(sd, sd->bl.id, sd->vending);
@@ -8553,34 +8576,33 @@ void clif_slide(struct block_list *bl, int x, int y)
/// Public chat message (ZC_NOTIFY_CHAT). lordalfa/Skotlex - used by @me as well
/// 008d <packet len>.W <id>.L <message>.?B
-void clif_disp_overhead(struct block_list *bl, const char* mes)
+void clif_disp_overhead(struct block_list *bl, const char *mes)
{
unsigned char buf[256]; //This should be more than sufficient, the theoretical max is CHAT_SIZE + 8 (pads and extra inserted crap)
- size_t len_mes;
+ int mes_len;
nullpo_retv(bl);
nullpo_retv(mes);
- len_mes = strlen(mes)+1; //Account for \0
+ mes_len = (int)strlen(mes)+1; //Account for \0
- if (len_mes > sizeof(buf)-8) {
- ShowError("clif_disp_overhead: Message too long (length %"PRIuS")\n", len_mes);
- len_mes = sizeof(buf)-8; //Trunk it to avoid problems.
+ if (mes_len > (int)sizeof(buf)-8) {
+ ShowError("clif_disp_overhead: Message too long (length %d)\n", mes_len);
+ mes_len = sizeof(buf)-8; //Trunk it to avoid problems.
}
// send message to others
WBUFW(buf,0) = 0x8d;
- WBUFW(buf,2) = len_mes + 8; // len of message + 8 (command+len+id)
+ WBUFW(buf,2) = mes_len + 8; // len of message + 8 (command+len+id)
WBUFL(buf,4) = bl->id;
- safestrncpy(WBUFP(buf,8), mes, len_mes);
+ safestrncpy(WBUFP(buf,8), mes, mes_len);
clif->send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC);
// send back message to the speaker
- if( bl->type == BL_PC ) {
+ if (bl->type == BL_PC) {
WBUFW(buf,0) = 0x8e;
- WBUFW(buf, 2) = len_mes + 4;
- safestrncpy(WBUFP(buf,4), mes, len_mes);
+ WBUFW(buf, 2) = mes_len + 4;
+ safestrncpy(WBUFP(buf,4), mes, mes_len);
clif->send(buf, WBUFW(buf,2), bl, SELF);
}
-
}
/*==========================
@@ -8864,120 +8886,153 @@ void clif_msgtable_skill(struct map_session_data* sd, uint16 skill_id, int msg_i
WFIFOSET(fd, packet_len(0x7e6));
}
-/// Validates one global/guild/party/whisper message packet and tries to recognize its components.
-/// Returns true if the packet was parsed successfully.
-/// Formats: 0 - <packet id>.w <packet len>.w (<name> : <message>).?B 00
-/// 1 - <packet id>.w <packet len>.w <name>.24B <message>.?B 00
-bool clif_process_message(struct map_session_data *sd, int format, const char **name_, size_t *namelen_, const char **message_, size_t *messagelen_)
+/**
+ * Validates and processes a global/guild/party message packet.
+ *
+ * @param[in] sd The source character.
+ * @param[in] packet The packet data.
+ * @param[out] out_buf The output buffer (must be a valid buffer), that will
+ * be filled with "Name : Message".
+ * @param[in] out_buflen The size of out_buf (including the NUL terminator).
+ * @return a pointer to the "Message" part of out_buf.
+ * @retval NULL if the validation failed, the messages was a command or the
+ * character can't send chat messages. out_buf shan't be used.
+ */
+const char *clif_process_chat_message(struct map_session_data *sd, const struct packet_chat_message *packet, char *out_buf, int out_buflen)
{
- const char *text, *name, *message;
- unsigned int packetlen, textlen;
- size_t namelen, messagelen;
- int fd = sd->fd;
+ const char *srcname = NULL, *srcmessage = NULL, *message = NULL;
+ int textlen = 0, namelen = 0, messagelen = 0;
- nullpo_retr(false, sd);
- nullpo_retr(false, name_);
- nullpo_retr(false, namelen_);
- nullpo_retr(false, message_);
- nullpo_retr(false, messagelen_);
-
- *name_ = NULL;
- *namelen_ = 0;
- *message_ = NULL;
- *messagelen_ = 0;
-
- packetlen = RFIFOW(fd,2);
- // basic structure checks
- if (packetlen < 4 + 1) {
+ nullpo_ret(sd);
+ nullpo_ret(packet);
+ nullpo_ret(out_buf);
+
+ if (packet->packet_len < 4 + 1) {
// 4-byte header and at least an empty string is expected
- ShowWarning("clif_process_message: Received malformed packet from player '%s' (no message data)!\n", sd->status.name);
- return false;
+ ShowWarning("clif_process_chat_message: Received malformed packet from player '%s' (no message data)!\n", sd->status.name);
+ return NULL;
}
- text = RFIFOP(fd,4);
- textlen = packetlen - 4;
+#if PACKETVER >= 20151001
+ // Packet doesn't include a NUL terminator
+ textlen = packet->packet_len - 4;
+#else // PACKETVER < 20151001
+ // Packet includes a NUL terminator
+ textlen = packet->packet_len - 4 - 1;
+#endif // PACKETVER > 20151001
- // process <name> part of the packet
- if( format == 0 )
- {// name and message are separated by ' : '
- // validate name
- name = text;
- namelen = strnlen(sd->status.name, NAME_LENGTH-1); // name length (w/o zero byte)
+ // name and message are separated by ' : '
+ srcname = packet->message;
+ namelen = (int)strnlen(sd->status.name, NAME_LENGTH-1); // name length (w/o zero byte)
- if( strncmp(name, sd->status.name, namelen) || // the text must start with the speaker's name
- name[namelen] != ' ' || name[namelen+1] != ':' || name[namelen+2] != ' ' ) // followed by ' : '
- {
- //Hacked message, or infamous "client desynchronize" issue where they pick one char while loading another.
- ShowWarning("clif_process_message: Player '%s' sent a message using an incorrect name! Forcing a relog...\n", sd->status.name);
- sockt->eof(fd); // Just kick them out to correct it.
- return false;
- }
+ if (strncmp(srcname, sd->status.name, namelen) != 0 // the text must start with the speaker's name
+ || srcname[namelen] != ' ' || srcname[namelen+1] != ':' || srcname[namelen+2] != ' ' // followed by ' : '
+ ) {
+ //Hacked message, or infamous "client desynchronize" issue where they pick one char while loading another.
+ ShowWarning("clif_process_chat_message: Player '%s' sent a message using an incorrect name! Forcing a relog...\n", sd->status.name);
+ sockt->eof(sd->fd); // Just kick them out to correct it.
+ return NULL;
+ }
+
+ srcmessage = packet->message + namelen + 3; // <name> " : " <message>
+ messagelen = textlen - namelen - 3;
- message = name + namelen + 3;
- messagelen = textlen - namelen - 3; // this should be the message length (w/ zero byte included)
+ if (messagelen >= CHAT_SIZE_MAX || textlen >= out_buflen) {
+ // messages mustn't be too long
+ // Normally you can only enter CHATBOX_SIZE-1 letters into the chat box, but Frost Joke / Dazzler's text can be longer.
+ // Also, the physical size of strings that use multibyte encoding can go multiple times over the chatbox capacity.
+ // Neither the official client nor server place any restriction on the length of the data in the packet,
+ // but we'll only allow reasonably long strings here. This also makes sure that they fit into the `chatlog` table.
+ ShowWarning("clif_process_chat_message: Player '%s' sent a message too long ('%.*s')!\n", sd->status.name, CHATBOX_SIZE-1, srcmessage);
+ return NULL;
}
- else
- {// name has fixed width
- if( textlen < NAME_LENGTH + 1 )
- {
- ShowWarning("clif_process_message: Received malformed packet from player '%s' (packet length is incorrect)!\n", sd->status.name);
- return false;
- }
- // validate name
- name = text;
- namelen = strnlen(name, NAME_LENGTH-1); // name length (w/o zero byte)
+ safestrncpy(out_buf, packet->message, textlen+1); // [!] packet->message is not necessarily NUL terminated
+ message = out_buf + namelen + 3;
- if (name[namelen] != '\0') {
- // only restriction is that the name must be zero-terminated
- ShowWarning("clif_process_message: Player '%s' sent an unterminated name!\n", sd->status.name);
- return false;
- }
+ if (!pc->process_chat_message(sd, message))
+ return NULL;
+ return message;
+}
- message = name + NAME_LENGTH;
- messagelen = textlen - NAME_LENGTH; // this should be the message length (w/ zero byte included)
- }
+/**
+ * Validates and processes a whisper message packet.
+ *
+ * @param[in] sd The source character.
+ * @param[in] packet The packet data.
+ * @param[out] out_name The parsed target name buffer (must be a valid
+ * buffer of size NAME_LENGTH).
+ * @param[out] out_message The output message buffer (must be a valid buffer).
+ * @param[in] out_messagelen The size of out_message.
+ * @retval true if the validation succeeded and the message is a chat message.
+ * @retval false if the validation failed, the messages was a command or the
+ * character can't send chat messages. out_name and out_message
+ * shan't be used.
+ */
+bool clif_process_whisper_message(struct map_session_data *sd, const struct packet_whisper_message *packet, char *out_name, char *out_message, int out_messagelen)
+{
+ int namelen = 0, messagelen = 0;
+
+ nullpo_retr(false, sd);
+ nullpo_retr(false, packet);
+ nullpo_retr(false, out_name);
+ nullpo_retr(false, out_message);
- if (messagelen != strnlen(message, messagelen)+1) {
- // the declared length must match real length
- ShowWarning("clif_process_message: Received malformed packet from player '%s' (length is incorrect)!\n", sd->status.name);
+ if (packet->packet_len < NAME_LENGTH + 4 + 1) {
+ // 4-byte header and at least an empty string is expected
+ ShowWarning("clif_process_whisper_message: Received malformed packet from player '%s' (packet length is incorrect)!\n", sd->status.name);
return false;
}
- // verify <message> part of the packet
- if (message[messagelen-1] != '\0') {
- // message must be zero-terminated
- ShowWarning("clif_process_message: Player '%s' sent an unterminated message string!\n", sd->status.name);
+
+ // validate name
+ namelen = (int)strnlen(packet->name, NAME_LENGTH-1); // name length (w/o zero byte)
+
+ if (packet->name[namelen] != '\0') {
+ // only restriction is that the name must be zero-terminated
+ ShowWarning("clif_process_whisper_message: Player '%s' sent an unterminated name!\n", sd->status.name);
return false;
}
- if (messagelen > CHAT_SIZE_MAX-1) {
+
+#if PACKETVER >= 20151001
+ // Packet doesn't include a NUL terminator
+ messagelen = packet->packet_len - NAME_LENGTH - 4;
+#else // PACKETVER < 20151001
+ // Packet includes a NUL terminator
+ messagelen = packet->packet_len - NAME_LENGTH - 4 - 1;
+#endif // PACKETVER > 20151001
+
+ if (messagelen >= CHAT_SIZE_MAX || messagelen >= out_messagelen) {
// messages mustn't be too long
// Normally you can only enter CHATBOX_SIZE-1 letters into the chat box, but Frost Joke / Dazzler's text can be longer.
// Also, the physical size of strings that use multibyte encoding can go multiple times over the chatbox capacity.
// Neither the official client nor server place any restriction on the length of the data in the packet,
// but we'll only allow reasonably long strings here. This also makes sure that they fit into the `chatlog` table.
- ShowWarning("clif_process_message: Player '%s' sent a message too long ('%.*s')!\n", sd->status.name, CHAT_SIZE_MAX-1, message);
+ ShowWarning("clif_process_whisper_message: Player '%s' sent a message too long ('%.*s')!\n", sd->status.name, CHAT_SIZE_MAX-1, packet->message);
return false;
}
- *name_ = name;
- *namelen_ = namelen;
- *message_ = message;
- *messagelen_ = messagelen;
+ safestrncpy(out_name, packet->name, namelen+1); // [!] packet->name is not NUL terminated
+ safestrncpy(out_message, packet->message, messagelen+1); // [!] packet->message is not necessarily NUL terminated
+
+ if (!pc->process_chat_message(sd, out_message))
+ return false;
+
return true;
}
void clif_channel_msg(struct channel_data *chan, struct map_session_data *sd, char *msg)
{
- DBIterator *iter;
+ struct DBIterator *iter;
struct map_session_data *user;
- unsigned short msg_len;
+ int msg_len;
uint32 color;
nullpo_retv(chan);
nullpo_retv(sd);
nullpo_retv(msg);
iter = db_iterator(chan->users);
- msg_len = strlen(msg) + 1;
+ msg_len = (int)strlen(msg) + 1;
+ Assert_retv(msg_len <= INT16_MAX - 12);
color = channel->config->colors[chan->color];
WFIFOHEAD(sd->fd,msg_len + 12);
@@ -9002,16 +9057,17 @@ void clif_channel_msg(struct channel_data *chan, struct map_session_data *sd, ch
void clif_channel_msg2(struct channel_data *chan, char *msg)
{
- DBIterator *iter;
+ struct DBIterator *iter;
struct map_session_data *user;
unsigned char buf[210];
- unsigned short msg_len;
+ int msg_len;
uint32 color;
nullpo_retv(chan);
nullpo_retv(msg);
iter = db_iterator(chan->users);
- msg_len = strlen(msg) + 1;
+ msg_len = (int)strlen(msg) + 1;
+ Assert_retv(msg_len <= INT16_MAX - 12);
color = channel->config->colors[chan->color];
WBUFW(buf,0) = 0x2C1;
@@ -9377,7 +9433,7 @@ void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) {
if( map->list[sd->bl.m].flag.allowks && !map_flag_ks(sd->bl.m) ) {
char output[128];
sprintf(output, "[ Kill Steal Protection Disabled. KS is allowed in this map ]");
- clif->broadcast(&sd->bl, output, strlen(output) + 1, BC_BLUE, SELF);
+ clif->broadcast(&sd->bl, output, (int)strlen(output) + 1, BC_BLUE, SELF);
}
map->iwall_get(sd); // Updates Walls Info on this Map to Client
@@ -9709,144 +9765,108 @@ int clif_undisguise_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-/// Validates and processes global messages
-/// 008c <packet len>.W <text>.?B (<name> : <message>) 00 (CZ_REQUEST_CHAT)
-/// There are various variants of this packet.
-void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
+/**
+ * Validates and processed global messages.
+ *
+ * There are various variants of this packet.
+ *
+ * @code
+ * 008c <packet len>.W <text>.?B (<name> : <message>) 00 (CZ_REQUEST_CHAT)
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param sd The related character.
+ */
+void clif_parse_GlobalMessage(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+void clif_parse_GlobalMessage(int fd, struct map_session_data *sd)
{
- const char *text = RFIFOP(fd,4);
- size_t textlen = RFIFOW(fd,2) - 4;
-
- const char *name = NULL, *message = NULL;
- char *fakename = NULL;
- size_t namelen, messagelen;
+ const struct packet_chat_message *packet = NULL;
+ char full_message[CHAT_SIZE_MAX + NAME_LENGTH + 3 + 1];
+ const char *message = NULL;
+ bool is_fakename = false;
+ int outlen = 0;
- bool is_fake;
-
- // validate packet and retrieve name and message
- if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) )
+ packet = RP2PTR(fd);
+ message = clif->process_chat_message(sd, packet, full_message, sizeof full_message);
+ if (message == NULL)
return;
- if( atcommand->exec(fd, sd, message, true) )
- return;
+ pc->check_supernovice_call(sd, message);
- if( !pc->can_talk(sd) )
+ if (sd->gcbind != NULL) {
+ channel->send(sd->gcbind, sd, message);
return;
-
- if( battle_config.min_chat_delay ) { //[Skotlex]
- if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0)
- return;
- sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
}
- if( (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE ) {
- unsigned int next = pc->nextbaseexp(sd);
- if( next == 0 ) next = pc->thisbaseexp(sd);
- if( next ) { // 0%, 10%, 20%, ...
- int percent = (int)( ( (float)sd->status.base_exp/(float)next )*1000. );
- if( (battle_config.snovice_call_type || percent) && ( percent%100 ) == 0 ) {// 10.0%, 20.0%, ..., 90.0%
- switch (sd->state.snovice_call_flag) {
- case 0:
- if( strstr(message, msg_txt(1479)) ) // "Dear angel, can you hear my voice?"
- sd->state.snovice_call_flag = 1;
- break;
- case 1: {
- char buf[256];
- snprintf(buf, 256, msg_txt(1480), sd->status.name);
- if( strstr(message, buf) ) // "I am %s Super Novice~"
- sd->state.snovice_call_flag = 2;
- }
- break;
- case 2:
- if( strstr(message, msg_txt(1481)) ) // "Help me out~ Please~ T_T"
- sd->state.snovice_call_flag = 3;
- break;
- case 3:
- sc_start(NULL,&sd->bl, status->skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill->get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex]
- clif->skill_nodamage(&sd->bl, &sd->bl, MO_EXPLOSIONSPIRITS, 5, 1); // prayer always shows successful Lv5 cast and disregards noskill restrictions
- sd->state.snovice_call_flag = 0;
- break;
- }
- }
- }
+ if (sd->fakename[0] != '\0') {
+ is_fakename = true;
+ outlen = (int)strlen(sd->fakename) + (int)strlen(message) + 3 + 1;
+ } else {
+ outlen = (int)strlen(full_message) + 1;
}
- pc->update_idle_time(sd, BCIDLE_CHAT);
-
- if( sd->gcbind ) {
- channel->send(sd->gcbind,sd,message);
- return;
- } else if ( sd->fontcolor && !sd->chatID ) {
- char mout[200];
- unsigned char mylen = 1;
+ if (sd->fontcolor != 0 && sd->chat_id == 0) {
uint32 color = 0;
- if( sd->disguise == -1 ) {
+ if (sd->disguise == -1) {
sd->fontcolor_tid = timer->add(timer->gettick()+5000, clif->undisguise_timer, sd->bl.id, 0);
pc->disguise(sd,sd->status.class_);
- if( pc_isdead(sd) )
+ if (pc_isdead(sd))
clif->clearunit_single(-sd->bl.id, CLR_DEAD, sd->fd);
- if( unit->is_walking(&sd->bl) )
+ if (unit->is_walking(&sd->bl))
clif->move(&sd->ud);
- } else if ( sd->disguise == sd->status.class_ && sd->fontcolor_tid != INVALID_TIMER ) {
+ } else if (sd->disguise == sd->status.class_ && sd->fontcolor_tid != INVALID_TIMER) {
const struct TimerData *td;
- if( (td = timer->get(sd->fontcolor_tid)) ) {
+ if ((td = timer->get(sd->fontcolor_tid)) != NULL)
timer->settick(sd->fontcolor_tid, td->tick+5000);
- }
}
- mylen += snprintf(mout, 200, "%s : %s",sd->fakename[0]?sd->fakename:sd->status.name,message);
-
color = channel->config->colors[sd->fontcolor - 1];
- WFIFOHEAD(fd,mylen + 12);
+ WFIFOHEAD(fd, outlen + 12);
WFIFOW(fd,0) = 0x2C1;
- WFIFOW(fd,2) = mylen + 12;
+ WFIFOW(fd,2) = outlen + 12;
WFIFOL(fd,4) = sd->bl.id;
WFIFOL(fd,8) = RGB2BGR(color);
- safestrncpy(WFIFOP(fd,12), mout, mylen);
+ if (is_fakename)
+ safesnprintf(WFIFOP(fd, 12), outlen, "%s : %s", sd->fakename, message);
+ else
+ safestrncpy(WFIFOP(fd, 12), full_message, outlen);
clif->send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, AREA_WOS);
WFIFOL(fd,4) = -sd->bl.id;
- WFIFOSET(fd, mylen + 12);
+ WFIFOSET(fd, outlen + 12);
return;
}
- /**
- * Fake Name Design by FatalEror (bug report #9)
- **/
- if( ( is_fake = ( sd->fakename[0] ) ) ) {
- fakename = (char*) aMalloc(strlen(sd->fakename)+messagelen+3);
- strcpy(fakename, sd->fakename);
- strcat(fakename, " : ");
- strcat(fakename, message);
- textlen = strlen(fakename) + 1;
+ {
+ // send message to others
+ void *buf = aMalloc(8 + outlen);
+ WBUFW(buf, 0) = 0x8d;
+ WBUFW(buf, 2) = 8 + outlen;
+ WBUFL(buf, 4) = sd->bl.id;
+ if (is_fakename)
+ safesnprintf(WBUFP(buf, 8), outlen, "%s : %s", sd->fakename, message);
+ else
+ safestrncpy(WBUFP(buf, 8), full_message, outlen);
+ //FIXME: chat has range of 9 only
+ clif->send(buf, WBUFW(buf, 2), &sd->bl, sd->chat_id != 0 ? CHAT_WOS : AREA_CHAT_WOC);
+ aFree(buf);
}
- // send message to others (using the send buffer for temp. storage)
- WFIFOHEAD(fd, 8 + textlen);
- WFIFOW(fd,0) = 0x8d;
- WFIFOW(fd,2) = 8 + textlen;
- WFIFOL(fd,4) = sd->bl.id;
- safestrncpy(WFIFOP(fd,8), is_fake ? fakename : text, textlen);
- //FIXME: chat has range of 9 only
- clif->send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, sd->chatID ? CHAT_WOS : AREA_CHAT_WOC);
// send back message to the speaker
- if( is_fake ) {
- WFIFOW(fd,0) = 0x8e;
- WFIFOW(fd,2) = textlen + 4;
- safestrncpy(WFIFOP(fd,4), fakename, textlen);
- aFree(fakename);
- } else {
- memcpy(WFIFOP(fd,0), RFIFOP(fd,0), RFIFOW(fd,2));
- WFIFOW(fd,0) = 0x8e;
- }
+ WFIFOHEAD(fd, 4 + outlen);
+ WFIFOW(fd, 0) = 0x8e;
+ WFIFOW(fd, 2) = 4 + outlen;
+ if (is_fakename)
+ safesnprintf(WFIFOP(fd, 4), outlen, "%s : %s", sd->fakename, message);
+ else
+ safestrncpy(WFIFOP(fd, 4), full_message, outlen);
WFIFOSET(fd, WFIFOW(fd,2));
// Chat logging type 'O' / Global Chat
logs->chat(LOG_CHAT_GLOBAL, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message);
// trigger listening npcs
- map->foreachinrange(npc_chat->sub, &sd->bl, AREA_SIZE, BL_NPC, text, textlen, &sd->bl);
+ map->foreachinrange(npc_chat->sub, &sd->bl, AREA_SIZE, BL_NPC, full_message, strlen(full_message), &sd->bl);
}
void clif_parse_MapMove(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
@@ -10119,37 +10139,28 @@ void clif_parse_Restart(int fd, struct map_session_data *sd) {
}
}
-void clif_parse_WisMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-/// Validates and processes whispered messages (CZ_WHISPER).
-/// 0096 <packet len>.W <nick>.24B <message>.?B
+/**
+ * Validates and processes whispered messages (CZ_WHISPER).
+ *
+ * @code
+ * 0096 <packet len>.W <nick>.24B <message>.?B
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param sd The related character.
+ */
+void clif_parse_WisMessage(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
void clif_parse_WisMessage(int fd, struct map_session_data* sd)
{
struct map_session_data* dstsd;
int i;
- const char *target, *message;
- size_t namelen, messagelen;
-
- // validate packet and retrieve name and message
- if( !clif->process_message(sd, 1, &target, &namelen, &message, &messagelen) )
- return;
-
- if ( atcommand->exec(fd, sd, message, true) )
- return;
+ char target[NAME_LENGTH], message[CHAT_SIZE_MAX + 1];
+ const struct packet_whisper_message *packet = RP2PTR(fd);
- // Statuses that prevent the player from whispering
- if( !pc->can_talk(sd) )
+ if (!clif->process_whisper_message(sd, packet, target, message, sizeof message))
return;
- if (battle_config.min_chat_delay) { //[Skotlex]
- if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0) {
- return;
- }
- sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
- }
-
- pc->update_idle_time(sd, BCIDLE_CHAT);
-
// Chat logging type 'W' / Whisper
logs->chat(LOG_CHAT_WHISPER, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, target, message);
@@ -10219,7 +10230,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
// 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).
- intif->wis_message(sd, target, message, messagelen);
+ intif->wis_message(sd, target, message, (int)strlen(message));
return;
}
@@ -10233,10 +10244,10 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
}
// if player is autotrading
- if( dstsd->state.autotrade ) {
+ if (dstsd->state.autotrade) {
char output[256];
sprintf(output, "%s is in autotrade mode and cannot receive whispered messages.", dstsd->status.name);
- clif->wis_message(fd, map->wisp_server_name, output, strlen(output) + 1);
+ clif->wis_message(fd, map->wisp_server_name, output, (int)strlen(output));
return;
}
@@ -10253,7 +10264,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
clif->wis_end(fd, 0); // 0: success to send wisper
// Normal message
- clif->wis_message(dstsd->fd, sd->status.name, message, messagelen);
+ clif->wis_message(dstsd->fd, sd->status.name, message, (int)strlen(message));
}
void clif_parse_Broadcast(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
@@ -10370,7 +10381,7 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd)
return;
}
- if ( (!sd->npc_id && pc_istrading(sd)) || sd->chatID )
+ if ((!sd->npc_id && pc_istrading(sd)) || sd->chat_id != 0)
return;
//Whether the item is used or not is irrelevant, the char ain't idle. [Skotlex]
@@ -10730,10 +10741,10 @@ void clif_noask_sub(struct map_session_data *src, struct map_session_data *targe
nullpo_retv(src);
// Your request has been rejected by autoreject option.
msg = msg_sd(src,392);
- clif_disp_onlyself(src, msg, strlen(msg));
+ clif_disp_onlyself(src, msg);
//Notice that a request was rejected.
snprintf(output, 256, msg_sd(target,393+type), src->status.name, 256);
- clif_disp_onlyself(target, output, strlen(output));
+ clif_disp_onlyself(target, output);
}
void clif_parse_TradeRequest(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
@@ -10744,7 +10755,7 @@ void clif_parse_TradeRequest(int fd,struct map_session_data *sd) {
t_sd = map->id2sd(RFIFOL(fd,2));
- if(!sd->chatID && pc_cant_act(sd))
+ if (sd->chat_id == 0 && pc_cant_act(sd))
return; //You can trade while in a chatroom.
// @noask [LuzZza]
@@ -11521,7 +11532,7 @@ void clif_parse_OneClick_ItemIdentify(int fd, struct map_session_data *sd)
return;
if ((n = pc->have_magnifier(sd) ) != INDEX_NOT_FOUND &&
- pc->delitem(sd, n, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER) == 0)
+ pc->delitem(sd, n, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME) == 0)
skill->identify(sd, idx);
}
@@ -11949,36 +11960,26 @@ void clif_parse_PartyChangeOption(int fd, struct map_session_data *sd)
#endif
}
-void clif_parse_PartyMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-/// Validates and processes party messages (CZ_REQUEST_CHAT_PARTY).
-/// 0108 <packet len>.W <text>.?B (<name> : <message>) 00
-void clif_parse_PartyMessage(int fd, struct map_session_data* sd)
+/**
+ * Validates and processes party messages (CZ_REQUEST_CHAT_PARTY).
+ *
+ * @code
+ * 0108 <packet len>.W <text>.?B (<name> : <message>) 00
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param sd The related character.
+ */
+void clif_parse_PartyMessage(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+void clif_parse_PartyMessage(int fd, struct map_session_data *sd)
{
- const char *text = RFIFOP(fd,4);
- int textlen = RFIFOW(fd,2) - 4;
-
- const char *name, *message;
- size_t namelen, messagelen;
+ const struct packet_chat_message *packet = RP2PTR(fd);
+ char message[CHAT_SIZE_MAX + NAME_LENGTH + 3 + 1];
- // validate packet and retrieve name and message
- if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) )
+ if (clif->process_chat_message(sd, packet, message, sizeof message) == NULL)
return;
- if( atcommand->exec(fd, sd, message, true) )
- return;
-
- if( !pc->can_talk(sd) )
- return;
-
- if (battle_config.min_chat_delay) {
- if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0)
- return;
- sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
- }
-
- pc->update_idle_time(sd, BCIDLE_CHAT);
-
- party->send_message(sd, text, textlen);
+ party->send_message(sd, message);
}
void clif_parse_PartyChangeLeader(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
@@ -12820,7 +12821,7 @@ bool clif_validate_emblem(const uint8 *emblem, unsigned long emblem_len) {
//uint8 b;
//uint8 g;
//uint8 r;
- unsigned int rgb:24;
+ uint32 rgb:24;
} __attribute__((packed));
#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
#pragma pack(pop)
@@ -13057,39 +13058,29 @@ void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd) {
guild->expulsion(sd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOP(fd,14));
}
-void clif_parse_GuildMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-/// Validates and processes guild messages (CZ_GUILD_CHAT).
-/// 017e <packet len>.W <text>.?B (<name> : <message>) 00
-void clif_parse_GuildMessage(int fd, struct map_session_data* sd)
+/**
+ * Validates and processes guild messages (CZ_GUILD_CHAT).
+ *
+ * @code
+ * 017e <packet len>.W <text>.?B (<name> : <message>) 00
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param sd The related character.
+ */
+void clif_parse_GuildMessage(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+void clif_parse_GuildMessage(int fd, struct map_session_data *sd)
{
- const char *text = RFIFOP(fd,4);
- int textlen = RFIFOW(fd,2) - 4;
+ const struct packet_chat_message *packet = RP2PTR(fd);
+ char message[CHAT_SIZE_MAX + NAME_LENGTH + 3 + 1];
- const char *name, *message;
- size_t namelen, messagelen;
-
- // validate packet and retrieve name and message
- if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) )
- return;
-
- if( atcommand->exec(fd, sd, message, true) )
+ if (clif->process_chat_message(sd, packet, message, sizeof message) == NULL)
return;
- if( !pc->can_talk(sd) )
- return;
-
- if (battle_config.min_chat_delay) {
- if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0)
- return;
- sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
- }
-
- pc->update_idle_time(sd, BCIDLE_CHAT);
-
- if( sd->bg_id )
- bg->send_message(sd, text, textlen);
+ if (sd->bg_id)
+ bg->send_message(sd, message);
else
- guild->send_message(sd, text, textlen);
+ guild->send_message(sd, message);
}
void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
@@ -13284,7 +13275,7 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd) {
case BL_PC:
{
char command[NAME_LENGTH+6];
- sprintf(command, "%ckick %s", atcommand->at_symbol, status->get_name(target));
+ sprintf(command, "%ckick %s", atcommand->at_symbol, clif->get_bl_name(target));
atcommand->exec(fd, sd, command, true);
}
break;
@@ -13299,7 +13290,7 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd) {
clif->GM_kickack(sd, 0);
return;
}
- sprintf(command, "/kick %s (%d)", status->get_name(target), status->get_class(target));
+ sprintf(command, "/kick %s (%d)", clif->get_bl_name(target), status->get_class(target));
logs->atcommand(sd, command);
status_percent_damage(&sd->bl, target, 100, 0, true); // can invalidate 'target'
}
@@ -14671,7 +14662,7 @@ void clif_Mail_refreshinbox(struct map_session_data *sd)
if( md->full ) {// TODO: is this official?
char output[100];
sprintf(output, "Inbox is full (Max %d). Delete some mails.", MAIL_MAX_INBOX);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
}
}
@@ -14709,11 +14700,16 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id)
struct mail_message *msg = &sd->mail.inbox.msg[i];
struct item *item = &msg->item;
struct item_data *data;
- size_t msg_len = strlen(msg->body), len;
+ int msg_len = (int)strlen(msg->body), len;
- if( msg_len == 0 ) {
+ if (msg_len == 0) {
strcpy(msg->body, "(no message)");
- msg_len = strlen(msg->body);
+ msg_len = (int)strlen(msg->body);
+ }
+
+ if (msg_len > UINT8_MAX) {
+ Assert_report(msg_len > UINT8_MAX);
+ msg_len = UINT8_MAX;
}
len = 101 + msg_len;
@@ -14741,7 +14737,7 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id)
} else // no item, set all to zero
memset(WFIFOP(fd,80), 0x00, 19);
- WFIFOB(fd,99) = (unsigned char)msg_len;
+ WFIFOB(fd,99) = (uint8)msg_len;
safestrncpy(WFIFOP(fd,100), msg->body, msg_len + 1);
WFIFOSET(fd,len);
@@ -14775,7 +14771,6 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd)
{
int mail_id = RFIFOL(fd,2);
int i;
- bool fail = false;
if( !chrif->isconnected() )
return;
@@ -14799,6 +14794,7 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd)
if( sd->mail.inbox.msg[i].item.nameid > 0 ) {
struct item_data *data;
unsigned int weight;
+ bool fail = false;
if ((data = itemdb->exists(sd->mail.inbox.msg[i].item.nameid)) == NULL)
return;
@@ -16148,58 +16144,53 @@ void clif_bg_xy_remove(struct map_session_data *sd)
/// Notifies clients of a battleground message (ZC_BATTLEFIELD_CHAT).
/// 02dc <packet len>.W <account id>.L <name>.24B <message>.?B
-void clif_bg_message(struct battleground_data *bgd, int src_id, const char *name, const char *mes, size_t len)
+void clif_bg_message(struct battleground_data *bgd, int src_id, const char *name, const char *mes)
{
struct map_session_data *sd;
unsigned char *buf;
+ int len;
nullpo_retv(bgd);
nullpo_retv(name);
nullpo_retv(mes);
- if( !bgd->count || (sd = bg->getavailablesd(bgd)) == NULL )
+
+ if (!bgd->count || (sd = bg->getavailablesd(bgd)) == NULL)
return;
+ len = (int)strlen(mes);
+ Assert_retv(len <= INT16_MAX - NAME_LENGTH - 8);
buf = (unsigned char*)aMalloc((len + NAME_LENGTH + 8)*sizeof(unsigned char));
WBUFW(buf,0) = 0x2dc;
WBUFW(buf,2) = len + NAME_LENGTH + 8;
WBUFL(buf,4) = src_id;
memcpy(WBUFP(buf,8), name, NAME_LENGTH);
- memcpy(WBUFP(buf,32), mes, len);
+ memcpy(WBUFP(buf,32), mes, len); // [!] no NUL terminator
clif->send(buf,WBUFW(buf,2), &sd->bl, BG);
aFree(buf);
}
-void clif_parse_BattleChat(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-/// Validates and processes battlechat messages [pakpil] (CZ_BATTLEFIELD_CHAT).
-/// 0x2db <packet len>.W <text>.?B (<name> : <message>) 00
-void clif_parse_BattleChat(int fd, struct map_session_data* sd)
+/**
+ * Validates and processes battlechat messages [pakpil] (CZ_BATTLEFIELD_CHAT).
+ *
+ * @code
+ * 0x2db <packet len>.W <text>.?B (<name> : <message>) 00
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param sd The related character.
+ */
+void clif_parse_BattleChat(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+void clif_parse_BattleChat(int fd, struct map_session_data *sd)
{
- const char *text = RFIFOP(fd,4);
- int textlen = RFIFOW(fd,2) - 4;
-
- const char *name, *message;
- size_t namelen, messagelen;
-
- if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) )
- return;
-
- if( atcommand->exec(fd, sd, message, true) )
- return;
+ const struct packet_chat_message *packet = RP2PTR(fd);
+ char message[CHAT_SIZE_MAX + NAME_LENGTH + 3 + 1];
- if( !pc->can_talk(sd) )
+ if (clif->process_chat_message(sd, packet, message, sizeof message) == NULL)
return;
- if( battle_config.min_chat_delay ) {
- if( DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0 )
- return;
- sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
- }
-
- pc->update_idle_time(sd, BCIDLE_CHAT);
-
- bg->send_message(sd, text, textlen);
+ bg->send_message(sd, message);
}
/// Notifies client of a battleground score change (ZC_BATTLEFIELD_NOTIFY_POINT).
@@ -17694,26 +17685,27 @@ void clif_partytickack(struct map_session_data* sd, bool flag) {
WFIFOSET(sd->fd, packet_len(0x2c9));
}
-void clif_ShowScript(struct block_list* bl, const char* message) {
+void clif_ShowScript(struct block_list *bl, const char *message)
+{
char buf[256];
- size_t len;
+ int len;
nullpo_retv(bl);
- if(!message)
+ if (message == NULL)
return;
- len = strlen(message)+1;
+ len = (int)strlen(message)+1;
- if (len > sizeof(buf)-8) {
- ShowWarning("clif_ShowScript: Truncating too long message '%s' (len=%"PRIuS").\n", message, len);
- len = sizeof(buf)-8;
+ if (len > (int)sizeof(buf)-8) {
+ ShowWarning("clif_ShowScript: Truncating too long message '%s' (len=%d).\n", message, len);
+ len = (int)sizeof(buf)-8;
}
- WBUFW(buf,0)=0x8b3;
- WBUFW(buf,2)=len+8;
- WBUFL(buf,4)=bl->id;
+ WBUFW(buf,0) = 0x8b3;
+ WBUFW(buf,2) = len+8;
+ WBUFL(buf,4) = bl->id;
safestrncpy(WBUFP(buf,8),message,len);
- clif->send((unsigned char *) buf,WBUFW(buf,2),bl,ALL_CLIENT);
+ clif->send(buf,WBUFW(buf,2),bl,ALL_CLIENT);
}
void clif_status_change_end(struct block_list *bl, int tid, enum send_target target, int type) {
@@ -17808,7 +17800,6 @@ void clif_parse_bgqueue_checkstate(int fd, struct map_session_data *sd)
{
const struct packet_bgqueue_checkstate *p = RP2PTR(fd);
- nullpo_retv(sd);
if (sd->bg_queue.arena && sd->bg_queue.type) {
clif->bgqueue_update_info(sd,sd->bg_queue.arena->id,bg->id2pos(sd->bg_queue.arena->queue_id,sd->status.account_id));
} else {
@@ -18059,7 +18050,7 @@ void clif_show_modifiers (struct map_session_data *sd) {
snprintf(output,128,"Base EXP : %d%% | Base Drop: %d%% | Base Death Penalty: %d%%",
sd->status.mod_exp,sd->status.mod_drop,sd->status.mod_death);
- clif->broadcast2(&sd->bl,output, strlen(output) + 1, 0xffbc90, 0x190, 12, 0, 0, SELF);
+ clif->broadcast2(&sd->bl, output, (int)strlen(output) + 1, 0xffbc90, 0x190, 12, 0, 0, SELF);
}
}
@@ -18404,7 +18395,7 @@ void clif_parse_RouletteGenerate(int fd, struct map_session_data* sd) {
it.nameid = clif->rd.nameid[stage][0];
it.identify = 1;
- pc->additem(sd, &it, clif->rd.qty[stage][0], LOG_TYPE_OTHER);/** TODO maybe a new log type for roulette items? **/
+ pc->additem(sd, &it, clif->rd.qty[stage][0], LOG_TYPE_ROULETTE);/** TODO maybe a new log type for roulette items? **/
sd->roulette.stage = 0;
result = GENERATE_ROULETTE_LOSING;
@@ -18439,7 +18430,7 @@ void clif_parse_RouletteRecvItem(int fd, struct map_session_data* sd) {
it.nameid = clif->rd.nameid[sd->roulette.prizeStage][sd->roulette.prizeIdx];
it.identify = 1;
- switch (pc->additem(sd, &it, clif->rd.qty[sd->roulette.prizeStage][sd->roulette.prizeIdx], LOG_TYPE_OTHER)) {
+ switch (pc->additem(sd, &it, clif->rd.qty[sd->roulette.prizeStage][sd->roulette.prizeIdx], LOG_TYPE_ROULETTE)) {
case 0:
p.Result = RECV_ITEM_SUCCESS;
sd->roulette.claimPrize = false;
@@ -18760,6 +18751,22 @@ void clif_selectcart(struct map_session_data *sd)
#endif
}
+/**
+ * Returns the name of the given bl, in a client-friendly format.
+ *
+ * @param bl The requested bl.
+ * @return The bl's name (guaranteed to be non-NULL).
+ */
+const char *clif_get_bl_name(const struct block_list *bl)
+{
+ const char *name = status->get_name(bl);
+
+ if (name == NULL)
+ return "Unknown";
+
+ return name;
+}
+
/* */
unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) {
if( sd ) {
@@ -19346,7 +19353,8 @@ void clif_defaults(void) {
clif->message = clif_displaymessage;
clif->messageln = clif_displaymessage2;
clif->messages = clif_displaymessage_sprintf;
- clif->process_message = clif_process_message;
+ clif->process_chat_message = clif_process_chat_message;
+ clif->process_whisper_message = clif_process_whisper_message;
clif->wisexin = clif_wisexin;
clif->wisall = clif_wisall;
clif->PMIgnoreList = clif_PMIgnoreList;
@@ -19829,4 +19837,5 @@ void clif_defaults(void) {
clif->pHotkeyRowShift = clif_parse_HotkeyRowShift;
clif->dressroom_open = clif_dressroom_open;
clif->pOneClick_ItemIdentify = clif_parse_OneClick_ItemIdentify;
+ clif->get_bl_name = clif_get_bl_name;
}