X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/4ad1cf7a5749fe3b9bf3c15e0f8f6dd4832baf9c..9172b03e94b4a23862c5ffeab84d2bcec001cb64:/channel/channel.c diff --git a/channel/channel.c b/channel/channel.c index 3de661b4..b5cd2ad6 100644 --- a/channel/channel.c +++ b/channel/channel.c @@ -8,14 +8,17 @@ #include "../parser/parser.h" #include "../irc/irc.h" #include "../lib/base64.h" +#include "../lib/version.h" +#include "../core/nsmalloc.h" #include #include -#define channelhash(x) (crc32i(x)%CHANNELHASHSIZE) +MODULE_VERSION(""); + +#define channelhash(x) (irc_crc32i(x)%CHANNELHASHSIZE) unsigned long nouser; -chanindex *chantable[CHANNELHASHSIZE]; const flag cmodeflags[] = { { 'n', CHANMODE_NOEXTMSG }, @@ -32,20 +35,24 @@ const flag cmodeflags[] = { { 'D', CHANMODE_DELJOINS }, { 'u', CHANMODE_NOQUITMSG }, { 'N', CHANMODE_NONOTICE }, + { 'M', CHANMODE_MODNOAUTH }, + { 'T', CHANMODE_SINGLETARG }, { '\0', 0 } }; void channelstats(int hooknum, void *arg); void sendchanburst(int hooknum, void *arg); void _init() { - /* Initialise internal structures */ - initchannelalloc(); - initchannelindex(); - memset(chantable,0,sizeof(chantable)); - /* Set up the nouser marker according to our own numeric */ nouser=(mylongnum<<18)|CU_NOUSERMASK; + /* If we're connected to IRC, force a disconnect. This needs to be done + * before we register all our hooks which would otherwise get called + * during the disconnect. */ + if (connected) { + irc_send("%s SQ %s 0 :Resync [adding channel support]",mynumeric->content,myserver->content); irc_disconnected(0); + } + /* Set up our hooks */ registerhook(HOOK_NICK_NEWNICK,&addordelnick); registerhook(HOOK_NICK_LOSTNICK,&addordelnick); @@ -62,15 +69,14 @@ void _init() { registerserverhandler("M",&handlemodemsg,8); registerserverhandler("OM",&handlemodemsg,8); /* Treat OPMODE just like MODE */ registerserverhandler("CM",&handleclearmodemsg,2); - - /* If we're connected to IRC, force a disconnect */ - if (connected) { - irc_send("%s SQ %s 0 :Resync [adding channel support]",mynumeric->content,myserver->content); - irc_disconnected(); - } } void _fini() { + unsigned int i; + struct channel *cp; + struct chanindex *cip, *ncip; + nick *np; + deregisterserverhandler("B",&handleburstmsg); deregisterserverhandler("J",&handlejoinmsg); deregisterserverhandler("C",&handlecreatemsg); @@ -83,7 +89,28 @@ void _fini() { deregisterhook(HOOK_NICK_NEWNICK,&addordelnick); deregisterhook(HOOK_NICK_LOSTNICK,&addordelnick); + deregisterhook(HOOK_CORE_STATSREQUEST,&channelstats); + deregisterhook(HOOK_IRC_SENDBURSTBURSTS,&sendchanburst); deregisterhook(HOOK_NICK_WHOISCHANNELS,&handlewhoischannels); + + /* Free all the channels */ + for(i=0;inext; + if ((cp=cip->channel)) + delchannel(cp); + } + } + + /* We also need to remove the channels array from each user */ + for (i=0;inext) { + array_free(np->channels); + free(np->channels); + } + } + + nsfreeall(POOL_CHANNEL); } int addnicktochannel(channel *cp, long numeric) { @@ -131,7 +158,7 @@ void delnickfromchannel(channel *cp, long numeric, int updateuser) { void *args[2]; if ((np=getnickbynumeric(numeric&CU_NUMERICMASK))==NULL) { - Error("channel",ERR_ERROR,"Trying to remove non-existent nick %d from channel %s",numeric,cp->index->name); + Error("channel",ERR_ERROR,"Trying to remove non-existent nick %lu from channel %s",numeric,cp->index->name->content); return; } @@ -231,7 +258,7 @@ channel *findchannel(char *name) { } void channelstats(int hooknum, void *arg) { - int level=(int)arg; + long level=(long)arg; int i,curchain,maxchain=0,total=0,buckets=0,realchans=0; int users=0,slots=0; chanindex *cip; @@ -388,7 +415,7 @@ unsigned int countuniquehosts(channel *cp) { continue; if ((np=getnickbynumeric(cp->users->content[i]))==NULL) { - Error("channel",ERR_ERROR,"Found unknown numeric %u on channel %s",cp->users->content[i],cp->index->name->content); + Error("channel",ERR_ERROR,"Found unknown numeric %lu on channel %s",cp->users->content[i],cp->index->name->content); continue; } @@ -401,3 +428,19 @@ unsigned int countuniquehosts(channel *cp) { return count; } + +/* + * clean_key: returns a "cleaned" version of the key like ircu does. + * + * Note that s is a signed char, so we are basically allowing everything from 33-127 except : or , + * + * Unlike ircu we don't check against KEYLEN here, this is done elsewhere. + */ +void clean_key(char *key) { + for (;*key;key++) { + if (*key<=32 || *key==':' || *key==',') { + *key=0; + return; + } + } +}