diff options
-rw-r--r-- | include/channels.h | 4 | ||||
-rw-r--r-- | include/inspircd.h | 6 | ||||
-rw-r--r-- | src/channels.cpp | 355 | ||||
-rw-r--r-- | src/inspircd.cpp | 356 |
4 files changed, 362 insertions, 359 deletions
diff --git a/include/channels.h b/include/channels.h index ed57955a2..7962bc34b 100644 --- a/include/channels.h +++ b/include/channels.h @@ -255,5 +255,9 @@ class ucrec : public classbase virtual ~ucrec() { /* stub */ } }; +chanrec* add_channel(userrec *user, const char* cn, const char* key, bool override); +chanrec* del_channel(userrec *user, const char* cname, const char* reason, bool local); +void kick_channel(userrec *src,userrec *user, chanrec *Ptr, char* reason); + #endif diff --git a/include/inspircd.h b/include/inspircd.h index c0b8810ed..d8f781579 100644 --- a/include/inspircd.h +++ b/include/inspircd.h @@ -94,8 +94,8 @@ typedef void (handlerfunc) (char**, int, userrec*); /* prototypes */ int InspIRCd(char** argv, int argc); -chanrec* add_channel(userrec *user, const char* cn, const char* key, bool override); -chanrec* del_channel(userrec *user, const char* cname, const char* reason, bool local); +/*chanrec* add_channel(userrec *user, const char* cn, const char* key, bool override); +chanrec* del_channel(userrec *user, const char* cname, const char* reason, bool local);*/ void force_nickchange(userrec* user,const char* newnick); void kill_link(userrec *user,const char* r); void kill_link_silent(userrec *user,const char* r); @@ -103,7 +103,7 @@ void call_handler(const char* commandname,char **parameters, int pcnt, userrec * bool is_valid_cmd(const char* commandname, int pcnt, userrec * user); std::string GetRevision(); int loop_call(handlerfunc fn, char **parameters, int pcnt, userrec *u, int start, int end, int joins); -void kick_channel(userrec *src,userrec *user, chanrec *Ptr, char* reason); +/*void kick_channel(userrec *src,userrec *user, chanrec *Ptr, char* reason);*/ void AddWhoWas(userrec* u); void ConnectUser(userrec *user); userrec* ReHashNick(char* Old, char* New); diff --git a/src/channels.cpp b/src/channels.cpp index 573289db9..38e90f286 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -187,3 +187,358 @@ std::vector<char*> *chanrec::GetUsers() { return &internal_userlist; } + +/* add a channel to a user, creating the record for it if needed and linking + * it to the user record */ + +chanrec* add_channel(userrec *user, const char* cn, const char* key, bool override) +{ + if ((!user) || (!cn)) + { + log(DEFAULT,"*** BUG *** add_channel was given an invalid parameter"); + return 0; + } + + int created = 0; + char cname[MAXBUF]; + int MOD_RESULT = 0; + strncpy(cname,cn,CHANMAX); + + log(DEBUG,"add_channel: %s %s",user->nick,cname); + + chanrec* Ptr = FindChan(cname); + + if (!Ptr) + { + if (user->fd > -1) + { + MOD_RESULT = 0; + FOREACH_RESULT(OnUserPreJoin(user,NULL,cname)); + if (MOD_RESULT == 1) + return NULL; + } + /* create a new one */ + chanlist[cname] = new chanrec(); + strlcpy(chanlist[cname]->name, cname,CHANMAX); + chanlist[cname]->binarymodes = CM_TOPICLOCK | CM_NOEXTERNAL; + chanlist[cname]->created = TIME; + strcpy(chanlist[cname]->topic, ""); + strncpy(chanlist[cname]->setby, user->nick,NICKMAX); + chanlist[cname]->topicset = 0; + Ptr = chanlist[cname]; + log(DEBUG,"add_channel: created: %s",cname); + /* set created to 2 to indicate user + * is the first in the channel + * and should be given ops */ + created = 2; + } + else + { + /* Already on the channel */ + if (has_channel(user,Ptr)) + return NULL; + + // remote users are allowed us to bypass channel modes + // and bans (used by servers) + if (user->fd > -1) + { + MOD_RESULT = 0; + FOREACH_RESULT(OnUserPreJoin(user,Ptr,cname)); + if (MOD_RESULT == 1) + { + return NULL; + } + else + { + if (*Ptr->key) + { + MOD_RESULT = 0; + FOREACH_RESULT(OnCheckKey(user, Ptr, key ? key : "")); + if (!MOD_RESULT) + { + if (!key) + { + log(DEBUG,"add_channel: no key given in JOIN"); + WriteServ(user->fd,"475 %s %s :Cannot join channel (Requires key)",user->nick, Ptr->name); + return NULL; + } + else + { + if (strcasecmp(key,Ptr->key)) + { + log(DEBUG,"add_channel: bad key given in JOIN"); + WriteServ(user->fd,"475 %s %s :Cannot join channel (Incorrect key)",user->nick, Ptr->name); + return NULL; + } + } + } + } + if (Ptr->binarymodes & CM_INVITEONLY) + { + MOD_RESULT = 0; + FOREACH_RESULT(OnCheckInvite(user, Ptr)); + if (!MOD_RESULT) + { + log(DEBUG,"add_channel: channel is +i"); + if (user->IsInvited(Ptr->name)) + { + /* user was invited to channel */ + /* there may be an optional channel NOTICE here */ + } + else + { + WriteServ(user->fd,"473 %s %s :Cannot join channel (Invite only)",user->nick, Ptr->name); + return NULL; + } + } + user->RemoveInvite(Ptr->name); + } + if (Ptr->limit) + { + MOD_RESULT = 0; + FOREACH_RESULT(OnCheckLimit(user, Ptr)); + if (!MOD_RESULT) + { + if (usercount(Ptr) >= Ptr->limit) + { + WriteServ(user->fd,"471 %s %s :Cannot join channel (Channel is full)",user->nick, Ptr->name); + return NULL; + } + } + } + if (Ptr->bans.size()) + { + log(DEBUG,"add_channel: about to walk banlist"); + MOD_RESULT = 0; + FOREACH_RESULT(OnCheckBan(user, Ptr)); + if (!MOD_RESULT) + { + for (BanList::iterator i = Ptr->bans.begin(); i != Ptr->bans.end(); i++) + { + if (match(user->GetFullHost(),i->data)) + { + WriteServ(user->fd,"474 %s %s :Cannot join channel (You're banned)",user->nick, Ptr->name); + return NULL; + } + } + } + } + } + } + else + { + log(DEBUG,"Overridden checks"); + } + created = 1; + } + + log(DEBUG,"Passed channel checks"); + + for (unsigned int index =0; index < user->chans.size(); index++) + { + if (user->chans[index].channel == NULL) + { + return ForceChan(Ptr,user->chans[index],user,created); + } + } + /* XXX: If the user is an oper here, we can just extend their user->chans vector by one + * and put the channel in here. Same for remote users which are not bound by + * the channel limits. Otherwise, nope, youre boned. + */ + if (user->fd < 0) + { + ucrec a; + chanrec* c = ForceChan(Ptr,a,user,created); + user->chans.push_back(a); + return c; + } + else if (strchr(user->modes,'o')) + { + /* Oper allows extension up to the OPERMAXCHANS value */ + if (user->chans.size() < OPERMAXCHANS) + { + ucrec a; + chanrec* c = ForceChan(Ptr,a,user,created); + user->chans.push_back(a); + return c; + } + } + log(DEBUG,"add_channel: user channel max exceeded: %s %s",user->nick,cname); + WriteServ(user->fd,"405 %s %s :You are on too many channels",user->nick, cname); + return NULL; +} + +chanrec* ForceChan(chanrec* Ptr,ucrec &a,userrec* user, int created) +{ + if (created == 2) + { + /* first user in is given ops */ + a.uc_modes = UCMODE_OP; + } + else + { + a.uc_modes = 0; + } + a.channel = Ptr; + Ptr->AddUser((char*)user); + WriteChannel(Ptr,user,"JOIN :%s",Ptr->name); + log(DEBUG,"Sent JOIN to client"); + if (Ptr->topicset) + { + WriteServ(user->fd,"332 %s %s :%s", user->nick, Ptr->name, Ptr->topic); + WriteServ(user->fd,"333 %s %s %s %lu", user->nick, Ptr->name, Ptr->setby, (unsigned long)Ptr->topicset); + } + userlist(user,Ptr); + WriteServ(user->fd,"366 %s %s :End of /NAMES list.", user->nick, Ptr->name); + FOREACH_MOD OnUserJoin(user,Ptr); + return Ptr; +} + +/* remove a channel from a users record, and remove the record from memory + * if the channel has become empty */ + +chanrec* del_channel(userrec *user, const char* cname, const char* reason, bool local) +{ + if ((!user) || (!cname)) + { + log(DEFAULT,"*** BUG *** del_channel was given an invalid parameter"); + return NULL; + } + + chanrec* Ptr = FindChan(cname); + + if (!Ptr) + return NULL; + + FOREACH_MOD OnUserPart(user,Ptr); + log(DEBUG,"del_channel: removing: %s %s",user->nick,Ptr->name); + + for (unsigned int i =0; i < user->chans.size(); i++) + { + /* zap it from the channel list of the user */ + if (user->chans[i].channel == Ptr) + { + if (reason) + { + WriteChannel(Ptr,user,"PART %s :%s",Ptr->name, reason); + } + else + { + WriteChannel(Ptr,user,"PART :%s",Ptr->name); + } + user->chans[i].uc_modes = 0; + user->chans[i].channel = NULL; + log(DEBUG,"del_channel: unlinked: %s %s",user->nick,Ptr->name); + break; + } + } + + Ptr->DelUser((char*)user); + + /* if there are no users left on the channel */ + if (!usercount(Ptr)) + { + chan_hash::iterator iter = chanlist.find(Ptr->name); + + log(DEBUG,"del_channel: destroying channel: %s",Ptr->name); + + /* kill the record */ + if (iter != chanlist.end()) + { + log(DEBUG,"del_channel: destroyed: %s",Ptr->name); + delete Ptr; + chanlist.erase(iter); + } + } + + return NULL; +} + + +void kick_channel(userrec *src,userrec *user, chanrec *Ptr, char* reason) +{ + if ((!src) || (!user) || (!Ptr) || (!reason)) + { + log(DEFAULT,"*** BUG *** kick_channel was given an invalid parameter"); + return; + } + + if ((!Ptr) || (!user) || (!src)) + { + return; + } + + log(DEBUG,"kick_channel: removing: %s %s %s",user->nick,Ptr->name,src->nick); + + if (!has_channel(user,Ptr)) + { + WriteServ(src->fd,"441 %s %s %s :They are not on that channel",src->nick, user->nick, Ptr->name); + return; + } + + int MOD_RESULT = 0; + FOREACH_RESULT(OnAccessCheck(src,user,Ptr,AC_KICK)); + if ((MOD_RESULT == ACR_DENY) && (!is_uline(src->server))) + return; + + if ((MOD_RESULT == ACR_DEFAULT) || (!is_uline(src->server))) + { + if ((cstatus(src,Ptr) < STATUS_HOP) || (cstatus(src,Ptr) < cstatus(user,Ptr))) + { + if (cstatus(src,Ptr) == STATUS_HOP) + { + WriteServ(src->fd,"482 %s %s :You must be a channel operator",src->nick, Ptr->name); + } + else + { + WriteServ(src->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",src->nick, Ptr->name); + } + + return; + } + } + + if (!is_uline(src->server)) + { + MOD_RESULT = 0; + FOREACH_RESULT(OnUserPreKick(src,user,Ptr,reason)); + if (MOD_RESULT) + return; + } + + FOREACH_MOD OnUserKick(src,user,Ptr,reason); + + for (unsigned int i =0; i < user->chans.size(); i++) + { + /* zap it from the channel list of the user */ + if (user->chans[i].channel) + if (!strcasecmp(user->chans[i].channel->name,Ptr->name)) + { + WriteChannel(Ptr,src,"KICK %s %s :%s",Ptr->name, user->nick, reason); + user->chans[i].uc_modes = 0; + user->chans[i].channel = NULL; + log(DEBUG,"del_channel: unlinked: %s %s",user->nick,Ptr->name); + break; + } + } + + Ptr->DelUser((char*)user); + + /* if there are no users left on the channel */ + if (!usercount(Ptr)) + { + chan_hash::iterator iter = chanlist.find(Ptr->name); + + log(DEBUG,"del_channel: destroying channel: %s",Ptr->name); + + /* kill the record */ + if (iter != chanlist.end()) + { + log(DEBUG,"del_channel: destroyed: %s",Ptr->name); + delete Ptr; + chanlist.erase(iter); + } + } +} + + diff --git a/src/inspircd.cpp b/src/inspircd.cpp index d3b1e4f09..0da0f580c 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -163,362 +163,6 @@ std::string GetRevision() } -/* add a channel to a user, creating the record for it if needed and linking - * it to the user record */ - -chanrec* add_channel(userrec *user, const char* cn, const char* key, bool override) -{ - if ((!user) || (!cn)) - { - log(DEFAULT,"*** BUG *** add_channel was given an invalid parameter"); - return 0; - } - - int created = 0; - char cname[MAXBUF]; - int MOD_RESULT = 0; - strncpy(cname,cn,CHANMAX); - - log(DEBUG,"add_channel: %s %s",user->nick,cname); - - chanrec* Ptr = FindChan(cname); - - if (!Ptr) - { - if (user->fd > -1) - { - MOD_RESULT = 0; - FOREACH_RESULT(OnUserPreJoin(user,NULL,cname)); - if (MOD_RESULT == 1) - return NULL; - } - /* create a new one */ - chanlist[cname] = new chanrec(); - strlcpy(chanlist[cname]->name, cname,CHANMAX); - chanlist[cname]->binarymodes = CM_TOPICLOCK | CM_NOEXTERNAL; - chanlist[cname]->created = TIME; - strcpy(chanlist[cname]->topic, ""); - strncpy(chanlist[cname]->setby, user->nick,NICKMAX); - chanlist[cname]->topicset = 0; - Ptr = chanlist[cname]; - log(DEBUG,"add_channel: created: %s",cname); - /* set created to 2 to indicate user - * is the first in the channel - * and should be given ops */ - created = 2; - } - else - { - /* Already on the channel */ - if (has_channel(user,Ptr)) - return NULL; - - // remote users are allowed us to bypass channel modes - // and bans (used by servers) - if (user->fd > -1) - { - MOD_RESULT = 0; - FOREACH_RESULT(OnUserPreJoin(user,Ptr,cname)); - if (MOD_RESULT == 1) - { - return NULL; - } - else - { - if (*Ptr->key) - { - MOD_RESULT = 0; - FOREACH_RESULT(OnCheckKey(user, Ptr, key ? key : "")); - if (!MOD_RESULT) - { - if (!key) - { - log(DEBUG,"add_channel: no key given in JOIN"); - WriteServ(user->fd,"475 %s %s :Cannot join channel (Requires key)",user->nick, Ptr->name); - return NULL; - } - else - { - if (strcasecmp(key,Ptr->key)) - { - log(DEBUG,"add_channel: bad key given in JOIN"); - WriteServ(user->fd,"475 %s %s :Cannot join channel (Incorrect key)",user->nick, Ptr->name); - return NULL; - } - } - } - } - if (Ptr->binarymodes & CM_INVITEONLY) - { - MOD_RESULT = 0; - FOREACH_RESULT(OnCheckInvite(user, Ptr)); - if (!MOD_RESULT) - { - log(DEBUG,"add_channel: channel is +i"); - if (user->IsInvited(Ptr->name)) - { - /* user was invited to channel */ - /* there may be an optional channel NOTICE here */ - } - else - { - WriteServ(user->fd,"473 %s %s :Cannot join channel (Invite only)",user->nick, Ptr->name); - return NULL; - } - } - user->RemoveInvite(Ptr->name); - } - if (Ptr->limit) - { - MOD_RESULT = 0; - FOREACH_RESULT(OnCheckLimit(user, Ptr)); - if (!MOD_RESULT) - { - if (usercount(Ptr) >= Ptr->limit) - { - WriteServ(user->fd,"471 %s %s :Cannot join channel (Channel is full)",user->nick, Ptr->name); - return NULL; - } - } - } - if (Ptr->bans.size()) - { - log(DEBUG,"add_channel: about to walk banlist"); - MOD_RESULT = 0; - FOREACH_RESULT(OnCheckBan(user, Ptr)); - if (!MOD_RESULT) - { - for (BanList::iterator i = Ptr->bans.begin(); i != Ptr->bans.end(); i++) - { - if (match(user->GetFullHost(),i->data)) - { - WriteServ(user->fd,"474 %s %s :Cannot join channel (You're banned)",user->nick, Ptr->name); - return NULL; - } - } - } - } - } - } - else - { - log(DEBUG,"Overridden checks"); - } - created = 1; - } - - log(DEBUG,"Passed channel checks"); - - for (unsigned int index =0; index < user->chans.size(); index++) - { - if (user->chans[index].channel == NULL) - { - return ForceChan(Ptr,user->chans[index],user,created); - } - } - /* XXX: If the user is an oper here, we can just extend their user->chans vector by one - * and put the channel in here. Same for remote users which are not bound by - * the channel limits. Otherwise, nope, youre boned. - */ - if (user->fd < 0) - { - ucrec a; - chanrec* c = ForceChan(Ptr,a,user,created); - user->chans.push_back(a); - return c; - } - else if (strchr(user->modes,'o')) - { - /* Oper allows extension up to the OPERMAXCHANS value */ - if (user->chans.size() < OPERMAXCHANS) - { - ucrec a; - chanrec* c = ForceChan(Ptr,a,user,created); - user->chans.push_back(a); - return c; - } - } - log(DEBUG,"add_channel: user channel max exceeded: %s %s",user->nick,cname); - WriteServ(user->fd,"405 %s %s :You are on too many channels",user->nick, cname); - return NULL; -} - -chanrec* ForceChan(chanrec* Ptr,ucrec &a,userrec* user, int created) -{ - if (created == 2) - { - /* first user in is given ops */ - a.uc_modes = UCMODE_OP; - } - else - { - a.uc_modes = 0; - } - a.channel = Ptr; - Ptr->AddUser((char*)user); - WriteChannel(Ptr,user,"JOIN :%s",Ptr->name); - log(DEBUG,"Sent JOIN to client"); - if (Ptr->topicset) - { - WriteServ(user->fd,"332 %s %s :%s", user->nick, Ptr->name, Ptr->topic); - WriteServ(user->fd,"333 %s %s %s %lu", user->nick, Ptr->name, Ptr->setby, (unsigned long)Ptr->topicset); - } - userlist(user,Ptr); - WriteServ(user->fd,"366 %s %s :End of /NAMES list.", user->nick, Ptr->name); - FOREACH_MOD OnUserJoin(user,Ptr); - return Ptr; -} - -/* remove a channel from a users record, and remove the record from memory - * if the channel has become empty */ - -chanrec* del_channel(userrec *user, const char* cname, const char* reason, bool local) -{ - if ((!user) || (!cname)) - { - log(DEFAULT,"*** BUG *** del_channel was given an invalid parameter"); - return NULL; - } - - chanrec* Ptr = FindChan(cname); - - if (!Ptr) - return NULL; - - FOREACH_MOD OnUserPart(user,Ptr); - log(DEBUG,"del_channel: removing: %s %s",user->nick,Ptr->name); - - for (unsigned int i =0; i < user->chans.size(); i++) - { - /* zap it from the channel list of the user */ - if (user->chans[i].channel == Ptr) - { - if (reason) - { - WriteChannel(Ptr,user,"PART %s :%s",Ptr->name, reason); - } - else - { - WriteChannel(Ptr,user,"PART :%s",Ptr->name); - } - user->chans[i].uc_modes = 0; - user->chans[i].channel = NULL; - log(DEBUG,"del_channel: unlinked: %s %s",user->nick,Ptr->name); - break; - } - } - - Ptr->DelUser((char*)user); - - /* if there are no users left on the channel */ - if (!usercount(Ptr)) - { - chan_hash::iterator iter = chanlist.find(Ptr->name); - - log(DEBUG,"del_channel: destroying channel: %s",Ptr->name); - - /* kill the record */ - if (iter != chanlist.end()) - { - log(DEBUG,"del_channel: destroyed: %s",Ptr->name); - delete Ptr; - chanlist.erase(iter); - } - } - - return NULL; -} - - -void kick_channel(userrec *src,userrec *user, chanrec *Ptr, char* reason) -{ - if ((!src) || (!user) || (!Ptr) || (!reason)) - { - log(DEFAULT,"*** BUG *** kick_channel was given an invalid parameter"); - return; - } - - if ((!Ptr) || (!user) || (!src)) - { - return; - } - - log(DEBUG,"kick_channel: removing: %s %s %s",user->nick,Ptr->name,src->nick); - - if (!has_channel(user,Ptr)) - { - WriteServ(src->fd,"441 %s %s %s :They are not on that channel",src->nick, user->nick, Ptr->name); - return; - } - - int MOD_RESULT = 0; - FOREACH_RESULT(OnAccessCheck(src,user,Ptr,AC_KICK)); - if ((MOD_RESULT == ACR_DENY) && (!is_uline(src->server))) - return; - - if ((MOD_RESULT == ACR_DEFAULT) || (!is_uline(src->server))) - { - if ((cstatus(src,Ptr) < STATUS_HOP) || (cstatus(src,Ptr) < cstatus(user,Ptr))) - { - if (cstatus(src,Ptr) == STATUS_HOP) - { - WriteServ(src->fd,"482 %s %s :You must be a channel operator",src->nick, Ptr->name); - } - else - { - WriteServ(src->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",src->nick, Ptr->name); - } - - return; - } - } - - if (!is_uline(src->server)) - { - MOD_RESULT = 0; - FOREACH_RESULT(OnUserPreKick(src,user,Ptr,reason)); - if (MOD_RESULT) - return; - } - - FOREACH_MOD OnUserKick(src,user,Ptr,reason); - - for (unsigned int i =0; i < user->chans.size(); i++) - { - /* zap it from the channel list of the user */ - if (user->chans[i].channel) - if (!strcasecmp(user->chans[i].channel->name,Ptr->name)) - { - WriteChannel(Ptr,src,"KICK %s %s :%s",Ptr->name, user->nick, reason); - user->chans[i].uc_modes = 0; - user->chans[i].channel = NULL; - log(DEBUG,"del_channel: unlinked: %s %s",user->nick,Ptr->name); - break; - } - } - - Ptr->DelUser((char*)user); - - /* if there are no users left on the channel */ - if (!usercount(Ptr)) - { - chan_hash::iterator iter = chanlist.find(Ptr->name); - - log(DEBUG,"del_channel: destroying channel: %s",Ptr->name); - - /* kill the record */ - if (iter != chanlist.end()) - { - log(DEBUG,"del_channel: destroyed: %s",Ptr->name); - delete Ptr; - chanlist.erase(iter); - } - } -} - - - - /* This function pokes and hacks at a parameter list like the following: * * PART #winbot,#darkgalaxy :m00! |