X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fchannels.cpp;h=f067646d3358656ff94647e8846d1bf2ee7058e5;hb=0a58b25ad736e7cec4944eb89e10f617d74225a0;hp=59cfb18bd87c10341d7098e38ccc51692062e470;hpb=fb99e9eaa2627f9276dbfcb1366b218271747f71;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/channels.cpp b/src/channels.cpp index 59cfb18bd..f067646d3 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -2,7 +2,7 @@ * | Inspire Internet Relay Chat Daemon | * +------------------------------------+ * - * Inspire is copyright (C) 2002-2005 ChatSpike-Dev. + * InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev. * E-mail: * * @@ -19,7 +19,6 @@ using namespace std; #include "inspircd_config.h" #include "inspircd.h" #include "inspircd_io.h" -#include "inspircd_util.h" #include #include #include @@ -62,10 +61,6 @@ extern std::vector modules; extern std::vector factory; extern int WHOWAS_STALE; extern int WHOWAS_MAX; -extern time_t startup_time; -extern std::vector module_names; -extern int boundPortCount; -extern std::stringstream config_f; extern time_t TIME; extern chan_hash chanlist; @@ -73,15 +68,12 @@ using namespace std; std::vector custom_mode_params; +chanrec* ForceChan(chanrec* Ptr,ucrec &a,userrec* user, int created); + chanrec::chanrec() { - strcpy(name,""); - strcpy(custom_modes,""); - strcpy(topic,""); - strcpy(setby,""); - strcpy(key,""); - created = topicset = limit = 0; - binarymodes = 0; + *name = *custom_modes = *topic = *setby = *key = 0; + created = topicset = limit = binarymodes = 0; internal_userlist.clear(); } @@ -102,7 +94,7 @@ void chanrec::SetCustomMode(char mode,bool mode_on) std::string a = this->custom_modes; int pos = a.find(mode); a.erase(pos,1); - strncpy(this->custom_modes,a.c_str(),MAXMODES); + strlcpy(this->custom_modes,a.c_str(),MAXMODES); log(DEBUG,"Custom mode %c removed: modelist='%s'",mode,this->custom_modes); this->SetCustomModeParam(mode,"",false); @@ -168,29 +160,96 @@ long chanrec::GetUserCounter() void chanrec::AddUser(char* castuser) { - internal_userlist.push_back(castuser); + internal_userlist[castuser] = castuser; log(DEBUG,"Added casted user to channel's internal list"); } void chanrec::DelUser(char* castuser) { - for (std::vector::iterator a = internal_userlist.begin(); a < internal_userlist.end(); a++) + std::map::iterator a = internal_userlist.find(castuser); + if (a != internal_userlist.end()) { - if (*a == castuser) - { - log(DEBUG,"Removed casted user from channel's internal list"); - internal_userlist.erase(a); - return; - } + log(DEBUG,"Removed casted user from channel's internal list"); + internal_userlist.erase(a); + return; } - log(DEBUG,"BUG BUG BUG! Attempt to remove an uncasted user from the internal list of %s!",name); + /* Tidy up any others */ + DelOppedUser(castuser); + DelHalfoppedUser(castuser); + DelVoicedUser(castuser); +} + +void chanrec::AddOppedUser(char* castuser) +{ + internal_op_userlist[castuser] = castuser; + log(DEBUG,"Added casted user to channel's internal list"); +} + +void chanrec::DelOppedUser(char* castuser) +{ + std::map::iterator a = internal_op_userlist.find(castuser); + if (a != internal_op_userlist.end()) + { + log(DEBUG,"Removed casted user from channel's internal list"); + internal_op_userlist.erase(a); + return; + } +} + +void chanrec::AddHalfoppedUser(char* castuser) +{ + internal_halfop_userlist[castuser] = castuser; + log(DEBUG,"Added casted user to channel's internal list"); +} + +void chanrec::DelHalfoppedUser(char* castuser) +{ + std::map::iterator a = internal_halfop_userlist.find(castuser); + if (a != internal_halfop_userlist.end()) + { + log(DEBUG,"Removed casted user from channel's internal list"); + internal_halfop_userlist.erase(a); + return; + } +} + +void chanrec::AddVoicedUser(char* castuser) +{ + internal_voice_userlist[castuser] = castuser; + log(DEBUG,"Added casted user to channel's internal list"); +} + +void chanrec::DelVoicedUser(char* castuser) +{ + std::map::iterator a = internal_voice_userlist.find(castuser); + if (a != internal_voice_userlist.end()) + { + log(DEBUG,"Removed casted user from channel's internal list"); + internal_voice_userlist.erase(a); + return; + } } -std::vector *chanrec::GetUsers() +std::map *chanrec::GetUsers() { return &internal_userlist; } +std::map *chanrec::GetOppedUsers() +{ + return &internal_op_userlist; +} + +std::map *chanrec::GetHalfoppedUsers() +{ + return &internal_halfop_userlist; +} + +std::map *chanrec::GetVoicedUsers() +{ + return &internal_voice_userlist; +} + /* add a channel to a user, creating the record for it if needed and linking * it to the user record */ @@ -205,7 +264,8 @@ chanrec* add_channel(userrec *user, const char* cn, const char* key, bool overri int created = 0; char cname[MAXBUF]; int MOD_RESULT = 0; - strncpy(cname,cn,CHANMAX); + strlcpy(cname,cn,CHANMAX); + log(DEBUG,"cname='%s' cn='%s'",cname,cn); log(DEBUG,"add_channel: %s %s",user->nick,cname); @@ -216,7 +276,7 @@ chanrec* add_channel(userrec *user, const char* cn, const char* key, bool overri if (user->fd > -1) { MOD_RESULT = 0; - FOREACH_RESULT(OnUserPreJoin(user,NULL,cname)); + FOREACH_RESULT(I_OnUserPreJoin,OnUserPreJoin(user,NULL,cname)); if (MOD_RESULT == 1) return NULL; } @@ -225,8 +285,8 @@ chanrec* add_channel(userrec *user, const char* cn, const char* key, bool overri 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]->topic = 0; + strlcpy(chanlist[cname]->setby, user->nick,NICKMAX); chanlist[cname]->topicset = 0; Ptr = chanlist[cname]; log(DEBUG,"add_channel: created: %s",cname); @@ -246,17 +306,17 @@ chanrec* add_channel(userrec *user, const char* cn, const char* key, bool overri if (user->fd > -1) { MOD_RESULT = 0; - FOREACH_RESULT(OnUserPreJoin(user,Ptr,cname)); + FOREACH_RESULT(I_OnUserPreJoin,OnUserPreJoin(user,Ptr,cname)); if (MOD_RESULT == 1) { return NULL; } - else + else if (MOD_RESULT == 0) { if (*Ptr->key) { MOD_RESULT = 0; - FOREACH_RESULT(OnCheckKey(user, Ptr, key ? key : "")); + FOREACH_RESULT(I_OnCheckKey,OnCheckKey(user, Ptr, key ? key : "")); if (!MOD_RESULT) { if (!key) @@ -278,12 +338,13 @@ chanrec* add_channel(userrec *user, const char* cn, const char* key, bool overri } if (Ptr->binarymodes & CM_INVITEONLY) { - MOD_RESULT = 0; - FOREACH_RESULT(OnCheckInvite(user, Ptr)); + MOD_RESULT = 0; + irc::string xname(Ptr->name); + FOREACH_RESULT(I_OnCheckInvite,OnCheckInvite(user, Ptr)); if (!MOD_RESULT) { log(DEBUG,"add_channel: channel is +i"); - if (user->IsInvited(Ptr->name)) + if (user->IsInvited(xname)) { /* user was invited to channel */ /* there may be an optional channel NOTICE here */ @@ -294,12 +355,12 @@ chanrec* add_channel(userrec *user, const char* cn, const char* key, bool overri return NULL; } } - user->RemoveInvite(Ptr->name); + user->RemoveInvite(xname); } if (Ptr->limit) { MOD_RESULT = 0; - FOREACH_RESULT(OnCheckLimit(user, Ptr)); + FOREACH_RESULT(I_OnCheckLimit,OnCheckLimit(user, Ptr)); if (!MOD_RESULT) { if (usercount(Ptr) >= Ptr->limit) @@ -313,12 +374,12 @@ chanrec* add_channel(userrec *user, const char* cn, const char* key, bool overri { log(DEBUG,"add_channel: about to walk banlist"); MOD_RESULT = 0; - FOREACH_RESULT(OnCheckBan(user, Ptr)); + FOREACH_RESULT(I_OnCheckBan,OnCheckBan(user, Ptr)); if (!MOD_RESULT) { for (BanList::iterator i = Ptr->bans.begin(); i != Ptr->bans.end(); i++) { - if (match(user->GetFullHost(),i->data)) + if ((match(user->GetFullHost(),i->data)) || (match(user->GetFullRealHost(),i->data))) { WriteServ(user->fd,"474 %s %s :Cannot join channel (You're banned)",user->nick, Ptr->name); return NULL; @@ -377,6 +438,7 @@ chanrec* ForceChan(chanrec* Ptr,ucrec &a,userrec* user, int created) { /* first user in is given ops */ a.uc_modes = UCMODE_OP; + Ptr->AddOppedUser((char*)user); } else { @@ -393,7 +455,7 @@ chanrec* ForceChan(chanrec* Ptr,ucrec &a,userrec* user, int created) } userlist(user,Ptr); WriteServ(user->fd,"366 %s %s :End of /NAMES list.", user->nick, Ptr->name); - FOREACH_MOD OnUserJoin(user,Ptr); + FOREACH_MOD(I_OnUserJoin,OnUserJoin(user,Ptr)); return Ptr; } @@ -413,7 +475,6 @@ chanrec* del_channel(userrec *user, const char* cname, const char* reason, bool 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++) @@ -423,10 +484,12 @@ chanrec* del_channel(userrec *user, const char* cname, const char* reason, bool { if (reason) { + FOREACH_MOD(I_OnUserPart,OnUserPart(user,Ptr,reason)); WriteChannel(Ptr,user,"PART %s :%s",Ptr->name, reason); } else { + FOREACH_MOD(I_OnUserPart,OnUserPart(user,Ptr,"")); WriteChannel(Ptr,user,"PART :%s",Ptr->name); } user->chans[i].uc_modes = 0; @@ -449,6 +512,7 @@ chanrec* del_channel(userrec *user, const char* cname, const char* reason, bool if (iter != chanlist.end()) { log(DEBUG,"del_channel: destroyed: %s",Ptr->name); + FOREACH_MOD(I_OnChannelDelete,OnChannelDelete(Ptr)); delete Ptr; chanlist.erase(iter); } @@ -457,59 +521,104 @@ chanrec* del_channel(userrec *user, const char* cname, const char* reason, bool return NULL; } - -void kick_channel(userrec *src,userrec *user, chanrec *Ptr, char* reason) +void server_kick_channel(userrec* user, chanrec* Ptr, char* reason, bool triggerevents) { - if ((!src) || (!user) || (!Ptr) || (!reason)) - { - log(DEFAULT,"*** BUG *** kick_channel was given an invalid parameter"); - return; - } - - if ((!Ptr) || (!user) || (!src)) - { - return; - } + if ((!user) || (!Ptr) || (!reason)) + { + return; + } - log(DEBUG,"kick_channel: removing: %s %s %s",user->nick,Ptr->name,src->nick); + if (IS_LOCAL(user)) + { + if (!has_channel(user,Ptr)) + { + /* Not on channel */ + return; + } + } + + if (triggerevents) + { + FOREACH_MOD(I_OnUserKick,OnUserKick(NULL,user,Ptr,reason)); + } - 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; - } + for (unsigned int i =0; i < user->chans.size(); i++) + { + if (user->chans[i].channel) + if (!strcasecmp(user->chans[i].channel->name,Ptr->name)) + { + WriteChannelWithServ(Config->ServerName,Ptr,"KICK %s %s :%s",Ptr->name, user->nick, reason); + user->chans[i].uc_modes = 0; + user->chans[i].channel = NULL; + break; + } + } - int MOD_RESULT = 0; - FOREACH_RESULT(OnAccessCheck(src,user,Ptr,AC_KICK)); - if ((MOD_RESULT == ACR_DENY) && (!is_uline(src->server))) - return; + Ptr->DelUser((char*)user); - if ((MOD_RESULT == ACR_DEFAULT) || (!is_uline(src->server))) + if (!usercount(Ptr)) { - if ((cstatus(src,Ptr) < STATUS_HOP) || (cstatus(src,Ptr) < cstatus(user,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()) { - 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; + log(DEBUG,"del_channel: destroyed: %s",Ptr->name); + FOREACH_MOD(I_OnChannelDelete,OnChannelDelete(Ptr)); + delete Ptr; + chanlist.erase(iter); } } +} - if (!is_uline(src->server)) +void kick_channel(userrec *src,userrec *user, chanrec *Ptr, char* reason) +{ + if ((!src) || (!user) || (!Ptr) || (!reason)) { - MOD_RESULT = 0; - FOREACH_RESULT(OnUserPreKick(src,user,Ptr,reason)); - if (MOD_RESULT) - return; + log(DEFAULT,"*** BUG *** kick_channel was given an invalid parameter"); + return; } - FOREACH_MOD OnUserKick(src,user,Ptr,reason); + log(DEBUG,"kick_channel: removing: %s %s %s",user->nick,Ptr->name,src->nick); + + if (IS_LOCAL(user)) + { + 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(I_OnAccessCheck,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(I_OnUserPreKick,OnUserPreKick(src,user,Ptr,reason)); + if (MOD_RESULT) + return; + } + } + + FOREACH_MOD(I_OnUserKick,OnUserKick(src,user,Ptr,reason)); for (unsigned int i =0; i < user->chans.size(); i++) { @@ -538,6 +647,7 @@ void kick_channel(userrec *src,userrec *user, chanrec *Ptr, char* reason) if (iter != chanlist.end()) { log(DEBUG,"del_channel: destroyed: %s",Ptr->name); + FOREACH_MOD(I_OnChannelDelete,OnChannelDelete(Ptr)); delete Ptr; chanlist.erase(iter); }