int isnewchan;
/* (we don't see the first 2 params in cargc) */
- /* AK B #+lod+ 1017561154 +tnk eits ATJWu:o,AiW1a,Ag3lV,AiWnl,AE6oI :%*!@D577A90D.kabel.telenet.be */
+ /* AK B #+lod+ 1017561154 +tnk eits ATJWu:o,AiW1a,Ag3lV,AiWnl,AE6oI :%*!@123.example.net */
if (cargc<2) {
Error("channel",ERR_WARNING,"Burst message with only %d parameters",cargc);
int handlejoinmsg(void *source, int cargc, char **cargv) {
char *pos,*nextchan;
nick *np;
- void *harg[2];
+ void *harg[3];
channel *cp,**ch;
long timestamp=0;
int i;
/* Find out who we are talking about here */
np=getnickbynumericstr(source);
if (np==NULL) {
- Error("channel",ERR_WARNING,"Channel join from non existent user %s",source);
+ Error("channel",ERR_WARNING,"Channel join from non existent user %s",(char *)source);
return CMD_OK;
}
/* Send hook */
harg[0]=ch[i];
harg[1]=np;
+ harg[2]=NULL;
triggerhook(HOOK_CHANNEL_PART,harg);
delnickfromchannel(ch[i],np->numeric,0);
}
if (newchan) {
delchannel(cp);
}
- } else {
+ } else {
+ chanindex *cip=cp->index;
+
/* If we just created a channel, flag it */
if (newchan) {
triggerhook(HOOK_CHANNEL_NEWCHANNEL,cp);
}
-
- /* send hook */
- harg[0]=cp;
- harg[1]=np;
- triggerhook(HOOK_CHANNEL_JOIN,harg);
+
+ /* Don't send HOOK_CHANNEL_JOIN if the channel doesn't exist any
+ * more (can happen if something destroys it in response to
+ * HOOK_CHANNEL_NEWCHANNEL) */
+ if (cp == cip->channel) {
+ /* send hook */
+ harg[0]=cp;
+ harg[1]=np;
+ triggerhook(HOOK_CHANNEL_JOIN,harg);
+ }
}
}
nextchan=pos;
/* Find out who we are talking about here */
np=getnickbynumericstr(source);
if (np==NULL) {
- Error("channel",ERR_WARNING,"Channel create from non existent user %s",source);
+ Error("channel",ERR_WARNING,"Channel create from non existent user %s",(char *)source);
return CMD_OK;
}
if (newchan) {
delchannel(cp);
}
- } else {
+ } else {
+ chanindex *cip = cp->index;
+
/* Flag the channel as new if necessary */
if (newchan) {
triggerhook(HOOK_CHANNEL_NEWCHANNEL,cp);
}
- /* Trigger hook */
- harg[0]=cp;
- harg[1]=np;
- triggerhook(HOOK_CHANNEL_CREATE,harg);
+ /* If HOOK_CHANNEL_NEWCHANNEL has caused the channel to be deleted,
+ * don't trigger the CREATE hook. */
+ if (cip->channel == cp) {
+ /* Trigger hook */
+ harg[0]=cp;
+ harg[1]=np;
+ triggerhook(HOOK_CHANNEL_CREATE,harg);
+ }
}
nextchan=pos;
}
/* Find out who we are talking about here */
np=getnickbynumericstr(source);
if (np==NULL) {
- Error("channel",ERR_WARNING,"PART from non existent numeric %s",source);
+ Error("channel",ERR_WARNING,"PART from non existent numeric %s",(char *)source);
return CMD_OK;
}
/* Erm, parting a channel that's not there?? */
Error("channel",ERR_WARNING,"Nick %s left non-existent channel %s",np->nick,nextchan);
} else {
- /* Trigger hook *FIRST* */
- harg[0]=cp;
- triggerhook(HOOK_CHANNEL_PART,harg);
-
- delnickfromchannel(cp,np->numeric,1);
+ /* Skip ghost parts (confirmation for kick from target server). */
+ if (getnumerichandlefromchanhash(cp->users, np->numeric)) {
+ /* Trigger hook *FIRST* */
+ harg[0]=cp;
+ triggerhook(HOOK_CHANNEL_PART,harg);
+ delnickfromchannel(cp,np->numeric,1);
+ }
}
nextchan=pos;
}
/* Find out who we are talking about here */
if ((np=getnickbynumericstr(cargv[1]))==NULL) {
- Error("channel",ERR_DEBUG,"Non-existant numeric %s kicked from channel %s",source,cargv[0]);
+ Error("channel",ERR_DEBUG,"Non-existant numeric %s kicked from channel %s",(char *)source,cargv[0]);
return CMD_OK;
}
if (cargc>3)
timestamp=strtol(cargv[cargc-3], NULL, 10);
- if ((np=getnickbynumericstr((char *)source))==NULL) {
+ np=getnickbynumericstr((char *)source);
+
+ /* The following check removed because servers can set topics.. */
+#if 0
+ if (np==NULL) {
/* We should check the sender exists, but we still change the topic even if it doesn't */
Error("channel",ERR_WARNING,"Topic change by non-existent user %s",(char *)source);
}
+#endif
/* Grab channel pointer */
if ((cp=findchannel(cargv[0]))==NULL) {
int arg=2;
char *modestr;
unsigned long *lp;
- void *harg[3];
+ void *harg[4];
nick *np, *target;
int hooknum;
int changes=0;
-
+
if (cargc<2) {
return CMD_OK;
}
/* Set up the hook data */
harg[0]=cp;
harg[1]=np;
+ harg[3]=(void *)(long)(cp->flags);
/* Process the mode string one character at a time */
/* Maybe I'll write this more intelligently one day if I can comprehend the ircu code that does this */
changes |= MODECHANGE_MODES;
break;
+ case 'M':
+ if (dir) { SetModNoAuth(cp); } else { ClearModNoAuth(cp); }
+ changes |= MODECHANGE_MODES;
+ break;
+
+ case 'T':
+ if (dir) { SetSingleTarg(cp); } else { ClearSingleTarg(cp); }
+ changes |= MODECHANGE_MODES;
+ break;
+
/* Parameter modes: advance parameter and possibly read it in */
case 'l':
}
}
- harg[2]=(void *)changes;
+ harg[2]=(void *)((long)changes);
triggerhook(HOOK_CHANNEL_MODECHANGE,(void *)harg);
return CMD_OK;
}
int handleclearmodemsg(void *source, int cargc, char **cargv) {
channel *cp;
- void *harg[3];
+ void *harg[4];
nick *np, *target;
char *mcp;
unsigned long usermask=0;
harg[0]=cp;
harg[1]=np;
-
+ harg[3]=(void *)(long)(cp->flags);
+
for (mcp=cargv[1];*mcp;mcp++) {
switch (*mcp) {
case 'o':
ClearNoNotice(cp);
changes |= MODECHANGE_MODES;
break;
+
+ case 'M':
+ ClearModNoAuth(cp);
+ changes |= MODECHANGE_MODES;
+ break;
+
+ case 'T':
+ ClearSingleTarg(cp);
+ changes |= MODECHANGE_MODES;
+ break;
case 'b':
clearallbans(cp);
}
}
- harg[2]=(void *)changes;
+ harg[2]=(void *)((long)changes);
triggerhook(HOOK_CHANNEL_MODECHANGE, harg);
return CMD_OK;
}
void handlewhoischannels(int hooknum, void *arg) {
- channel** chans;
+ channel **chans;
char buffer[1024];
- sstring* name;
- unsigned long* num;
+ unsigned int bufpos;
+ sstring *name;
+ unsigned long *num;
int i;
- void **args = (void **)arg;
- nick *sender = (nick *)args[0], *target = (nick *)args[1];
-
- if(IsService(target) || IsHideChan(target))
+ char **args = (char **)arg;
+ nick *sender = (nick *)args[0]; /* sender nick */
+ nick *target = (nick *)args[1]; /* target nick */
+ char *sourcenum = args[2]; /* source numeric */
+
+ /* do not show channels for +k service clients or IRC Operators
+ * do not show channels for +n users
+ * unless they whois themselves
+ */
+ if ((IsService(target) || IsHideChan(target)) && sender != target)
return;
chans = (channel **)(target->channels->content);
buffer[0] = '\0';
-
+ bufpos=0;
+
/* Not handling delayed joins. */
- for(i=target->channels->cursi-1;i>=0;i++) {
- if(IsSecret(chans[i]) || IsPrivate(chans[i])) { /* check common channels */
- int j;
- channel **senderchans = (channel **)(sender->channels->content);
- for(j=0;j<sender->channels->cursi;j++)
- if(senderchans[j] == chans[i])
- break;
- if(j == sender->channels->cursi)
+ for(i=target->channels->cursi-1;i>=0;i--) {
+ /* Secret / Private channels: only show if the sender is on the channel as well */
+ if(IsSecret(chans[i]) || IsPrivate(chans[i])) {
+ if (!getnumerichandlefromchanhash(chans[i]->users, sender->numeric))
continue;
}
+
name = chans[i]->index->name;
- if (strlen(buffer) + name->length > 508) { /* why 508? */
+ if (bufpos + name->length > 508) { /* why 508? - need room for -@#channame\0 + 1 slack */
irc_send("%s", buffer);
buffer[0] = '\0';
+ bufpos=0;
}
+ /*
+ * 319 RPL_WHOISCHANNELS "source 319 target nick :channels"
+ * "irc.netsplit.net 319 foobar barfoo :@#chan1 +#chan2 #chan3"
+ * "irc.netsplit.net 319 foobar barfoo :-@#chan1 -+#chan2 -#chan3"
+ */
if(buffer[0] == '\0')
- snprintf(buffer, sizeof(buffer), ":%s 319 %s %s :", myserver->content, sender->nick, target->nick);
- else
- strlcat(buffer, " ", sizeof(buffer));
+ bufpos=snprintf(buffer, sizeof(buffer), "%s 319 %s %s :", getmynumeric(), sourcenum, target->nick);
num = getnumerichandlefromchanhash(chans[i]->users, target->numeric);
+
+ /* Adding these flags might make the string "unsafe" (without terminating \0). */
+ /* sprintf'ing the channel name afterwards is guaranteed to fix it though */
+ if (IsDeaf(target))
+ buffer[bufpos++]='-';
if (*num & CUMODE_OP)
- strlcat(buffer, "@", sizeof(buffer));
+ buffer[bufpos++]='@';
else if (*num & CUMODE_VOICE)
- strlcat(buffer, "+", sizeof(buffer));
+ buffer[bufpos++]='+';
- strlcat(buffer, name->content, sizeof(buffer));
+ bufpos += sprintf(buffer+bufpos, "%s ",name->content);
}
if (buffer[0] != '\0')