regchannel.cpp

Go to the documentation of this file.
00001 /* Registered channel functions
00002  *
00003  * (C) 2003-2013 Anope Team
00004  * Contact us at team@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church.
00010  *
00011  */
00012 
00013 #include "services.h"
00014 #include "modules.h"
00015 #include "regchannel.h"
00016 #include "account.h"
00017 #include "access.h"
00018 #include "channels.h"
00019 #include "config.h"
00020 #include "bots.h"
00021 #include "language.h"
00022 #include "servers.h"
00023 
00024 Serialize::Checker<registered_channel_map> RegisteredChannelList("ChannelInfo");
00025 
00026 BadWord::BadWord() : Serializable("BadWord")
00027 {
00028 }
00029 
00030 BadWord::~BadWord()
00031 {
00032         if (this->ci)
00033         {
00034                 std::vector<BadWord *>::iterator it = std::find(this->ci->badwords->begin(), this->ci->badwords->end(), this);
00035                 if (it != this->ci->badwords->end())
00036                         this->ci->badwords->erase(it);
00037         }
00038 }
00039 
00040 void BadWord::Serialize(Serialize::Data &data) const
00041 {
00042         data["ci"] << this->ci->name;
00043         data["word"] << this->word;
00044         data.SetType("type", Serialize::Data::DT_INT); data["type"] << this->type;
00045 }
00046 
00047 Serializable* BadWord::Unserialize(Serializable *obj, Serialize::Data &data)
00048 {
00049         Anope::string sci, sword;
00050 
00051         data["ci"] >> sci;
00052         data["word"] >> sword;
00053 
00054         ChannelInfo *ci = ChannelInfo::Find(sci);
00055         if (!ci)
00056                 return NULL;
00057 
00058         unsigned int n;
00059         data["type"] >> n;
00060         
00061         BadWord *bw;
00062         if (obj)
00063         {
00064                 bw = anope_dynamic_static_cast<BadWord *>(obj);
00065                 data["word"] >> bw->word;
00066                 bw->type = static_cast<BadWordType>(n);
00067         }
00068         else
00069                 bw = ci->AddBadWord(sword, static_cast<BadWordType>(n));
00070         
00071         return bw;
00072 }
00073 
00074 AutoKick::AutoKick() : Serializable("AutoKick")
00075 {
00076 }
00077 
00078 AutoKick::~AutoKick()
00079 {
00080         if (this->ci)
00081         {
00082                 std::vector<AutoKick *>::iterator it = std::find(this->ci->akick->begin(), this->ci->akick->end(), this);
00083                 if (it != this->ci->akick->end())
00084                         this->ci->akick->erase(it);
00085 
00086                 const NickAlias *na = NickAlias::Find(this->mask);
00087                 if (na != NULL)
00088                         na->nc->RemoveChannelReference(this->ci);
00089         }
00090 }
00091 
00092 void AutoKick::Serialize(Serialize::Data &data) const
00093 {
00094         data["ci"] << this->ci->name;
00095         if (this->nc)
00096                 data["nc"] << this->nc->display;
00097         else
00098                 data["mask"] << this->mask;
00099         data["reason"] << this->reason;
00100         data["creator"] << this->creator;
00101         data.SetType("addtime", Serialize::Data::DT_INT); data["addtime"] << this->addtime;
00102         data.SetType("last_used", Serialize::Data::DT_INT); data["last_used"] << this->last_used;
00103 }
00104 
00105 Serializable* AutoKick::Unserialize(Serializable *obj, Serialize::Data &data)
00106 {
00107         Anope::string sci, snc;
00108 
00109         data["ci"] >> sci;
00110         data["nc"] >> snc;
00111 
00112         ChannelInfo *ci = ChannelInfo::Find(sci);
00113         if (!ci)
00114                 return NULL;
00115         
00116         AutoKick *ak;
00117         NickCore *nc = NickCore::Find(snc);
00118         if (obj)
00119         {
00120                 ak = anope_dynamic_static_cast<AutoKick *>(obj);
00121                 data["creator"] >> ak->creator;
00122                 data["reason"] >> ak->reason;
00123                 ak->nc = NickCore::Find(snc);
00124                 data["mask"] >> ak->mask;
00125                 data["addtime"] >> ak->addtime;
00126                 data["last_used"] >> ak->last_used;
00127         }
00128         else
00129         {
00130                 time_t addtime, lastused;
00131                 data["addtime"] >> addtime;
00132                 data["last_used"] >> lastused;
00133 
00134                 Anope::string screator, sreason, smask;
00135 
00136                 data["creator"] >> screator;
00137                 data["reason"] >> sreason;
00138                 data["mask"] >> smask;
00139 
00140                 if (nc) 
00141                         ak = ci->AddAkick(screator, nc, sreason, addtime, lastused);
00142                 else
00143                         ak = ci->AddAkick(screator, smask, sreason, addtime, lastused);
00144         }
00145 
00146         return ak;
00147 }
00148 
00149 ModeLock::ModeLock(ChannelInfo *ch, bool s, const Anope::string &n, const Anope::string &p, const Anope::string &se, time_t c) : Serializable("ModeLock"), ci(ch), set(s), name(n), param(p), setter(se), created(c)
00150 {
00151 }
00152 
00153 ModeLock::~ModeLock()
00154 {
00155         if (this->ci)
00156                 this->ci->RemoveMLock(this);
00157 }
00158 
00159 void ModeLock::Serialize(Serialize::Data &data) const
00160 {
00161         if (!this->ci)
00162                 return;
00163 
00164         data["ci"] << this->ci->name;
00165         data["set"] << this->set;
00166         data["name"] << this->name;
00167         data["param"] << this->param;
00168         data["setter"] << this->setter;
00169         data.SetType("created", Serialize::Data::DT_INT); data["created"] << this->created;
00170 }
00171 
00172 Serializable* ModeLock::Unserialize(Serializable *obj, Serialize::Data &data)
00173 {
00174         Anope::string sci;
00175         
00176         data["ci"] >> sci;
00177 
00178         ChannelInfo *ci = ChannelInfo::Find(sci);
00179         if (!ci)
00180                 return NULL;
00181         
00182         ModeLock *ml;
00183         if (obj)
00184         {
00185                 ml = anope_dynamic_static_cast<ModeLock *>(obj);
00186 
00187                 data["set"] >> ml->set;
00188                 data["name"] >> ml->name;
00189                 data["param"] >> ml->param;
00190                 data["setter"] >> ml->setter;
00191                 data["created"] >> ml->created;
00192                 return ml;
00193         }
00194         else
00195         {
00196                 bool set;
00197                 data["set"] >> set;
00198 
00199                 time_t created;
00200                 data["created"] >> created;
00201 
00202                 Anope::string setter;
00203                 data["setter"] >> setter;
00204 
00205                 Anope::string sname;
00206                 data["name"] >> sname;
00207 
00208                 ml = new ModeLock(ci, set, sname, "", setter, created);
00209                 data["param"] >> ml->param;
00210 
00211                 ci->mode_locks->insert(std::make_pair(ml->name, ml));
00212                 return ml;
00213         }
00214 }
00215 
00216 void LogSetting::Serialize(Serialize::Data &data) const
00217 {
00218         if (!ci)
00219                 return;
00220 
00221         data["ci"] << ci->name;
00222         data["service_name"] << service_name;
00223         data["command_service"] << command_service;
00224         data["command_name"] << command_name;
00225         data["method"] << method;
00226         data["extra"] << extra;
00227         data["creator"] << creator;
00228         data.SetType("created", Serialize::Data::DT_INT); data["created"] << created;
00229 }
00230 
00231 Serializable* LogSetting::Unserialize(Serializable *obj, Serialize::Data &data)
00232 {
00233         Anope::string sci;
00234         
00235         data["ci"] >> sci;
00236 
00237         ChannelInfo *ci = ChannelInfo::Find(sci);
00238         if (ci == NULL)
00239                 return NULL;
00240         
00241         LogSetting *ls;
00242         if (obj)
00243                 ls = anope_dynamic_static_cast<LogSetting *>(obj);
00244         else
00245         {
00246                 ls = new LogSetting();
00247                 ci->log_settings->push_back(ls);
00248         }
00249 
00250         ls->ci = ci;
00251         data["service_name"] >> ls->service_name;
00252         data["command_service"] >> ls->command_service;
00253         data["command_name"] >> ls->command_name;
00254         data["method"] >> ls->method;
00255         data["extra"] >> ls->extra;
00256         data["creator"] >> ls->creator;
00257         data["created"] >> ls->created;
00258 
00259         return ls;
00260 }
00261 
00262 ChannelInfo::ChannelInfo(const Anope::string &chname) : Serializable("ChannelInfo"),
00263         access("ChanAccess"), akick("AutoKick"),
00264         badwords("BadWord"), mode_locks("ModeLock"), log_settings("LogSetting")
00265 {
00266         if (chname.empty())
00267                 throw CoreException("Empty channel passed to ChannelInfo constructor");
00268 
00269         this->founder = NULL;
00270         this->successor = NULL;
00271         this->c = Channel::Find(chname);
00272         if (this->c)
00273                 this->c->ci = this;
00274         this->capsmin = this->capspercent = 0;
00275         this->floodlines = this->floodsecs = 0;
00276         this->repeattimes = 0;
00277         this->bi = NULL;
00278 
00279         this->last_topic_setter = Config->ChanServ;
00280         this->last_topic_time = Anope::CurTime;
00281 
00282         this->name = chname;
00283 
00284         /* Set default channel flags */
00285         for (std::set<Anope::string>::const_iterator it = Config->CSDefFlags.begin(), it_end = Config->CSDefFlags.end(); it != it_end; ++it)
00286                 this->ExtendMetadata(*it);
00287 
00288         /* Set default bot flags */
00289         for (std::set<Anope::string>::const_iterator it = Config->BSDefFlags.begin(), it_end = Config->BSDefFlags.end(); it != it_end; ++it)
00290                 this->ExtendMetadata(*it);
00291 
00292         this->bantype = Config->CSDefBantype;
00293         this->memos.memomax = Config->MSMaxMemos;
00294         this->last_used = this->time_registered = Anope::CurTime;
00295 
00296         for (int i = 0; i < TTB_SIZE; ++i)
00297                 this->ttb[i] = 0;
00298 
00299         size_t old = RegisteredChannelList->size();
00300         (*RegisteredChannelList)[this->name] = this;
00301         if (old == RegisteredChannelList->size())
00302                 Log(LOG_DEBUG) << "Duplicate channel " << this->name << " in registered channel table?";
00303 
00304         FOREACH_MOD(I_OnCreateChan, OnCreateChan(this));
00305 }
00306 
00307 ChannelInfo::ChannelInfo(const ChannelInfo &ci) : Serializable("ChannelInfo"),
00308         access("ChanAccess"), akick("AutoKick"),
00309         badwords("BadWord"), mode_locks("ModeLock"), log_settings("LogSetting")
00310 {
00311         *this = ci;
00312 
00313         if (this->founder)
00314                 --this->founder->channelcount;
00315 
00316         this->access->clear();
00317         this->akick->clear();
00318         this->badwords->clear();
00319 
00320         for (int i = 0; i < TTB_SIZE; ++i)
00321                 this->ttb[i] = ci.ttb[i];
00322 
00323         for (unsigned i = 0; i < ci.GetAccessCount(); ++i)
00324         {
00325                 const ChanAccess *taccess = ci.GetAccess(i);
00326                 AccessProvider *provider = taccess->provider;
00327 
00328                 ChanAccess *newaccess = provider->Create();
00329                 newaccess->ci = this;
00330                 newaccess->mask = taccess->mask;
00331                 newaccess->creator = taccess->creator;
00332                 newaccess->last_seen = taccess->last_seen;
00333                 newaccess->created = taccess->created;
00334                 newaccess->AccessUnserialize(taccess->AccessSerialize());
00335 
00336                 this->AddAccess(newaccess);
00337         }
00338 
00339         for (unsigned i = 0; i < ci.GetAkickCount(); ++i)
00340         {
00341                 const AutoKick *takick = ci.GetAkick(i);
00342                 if (takick->nc)
00343                         this->AddAkick(takick->creator, takick->nc, takick->reason, takick->addtime, takick->last_used);
00344                 else
00345                         this->AddAkick(takick->creator, takick->mask, takick->reason, takick->addtime, takick->last_used);
00346         }
00347         for (unsigned i = 0; i < ci.GetBadWordCount(); ++i)
00348         {
00349                 const BadWord *bw = ci.GetBadWord(i);
00350                 this->AddBadWord(bw->word, bw->type);
00351         }
00352 
00353         for (unsigned i = 0; i < ci.log_settings->size(); ++i)
00354         {
00355                 LogSetting *l = new LogSetting(*ci.log_settings->at(i));
00356                 l->ci = this;
00357                 this->log_settings->push_back(l);
00358         }
00359 }
00360 
00361 ChannelInfo::~ChannelInfo()
00362 {
00363         FOREACH_MOD(I_OnDelChan, OnDelChan(this));
00364 
00365         Log(LOG_DEBUG) << "Deleting channel " << this->name;
00366 
00367         if (this->c)
00368         {
00369                 if (this->bi && this->c->FindUser(this->bi))
00370                         this->bi->Part(this->c);
00371                 this->c->ci = NULL;
00372         }
00373 
00374         RegisteredChannelList->erase(this->name);
00375 
00376         this->SetFounder(NULL);
00377         this->SetSuccessor(NULL);
00378 
00379         this->ClearAccess();
00380         this->ClearAkick();
00381         this->ClearBadWords();
00382 
00383         for (unsigned i = 0; i < this->log_settings->size(); ++i)
00384                 delete this->log_settings->at(i);
00385         this->log_settings->clear();
00386 
00387         while (!this->mode_locks->empty())
00388                 delete this->mode_locks->begin()->second;
00389 
00390         if (!this->memos.memos->empty())
00391         {
00392                 for (unsigned i = 0, end = this->memos.memos->size(); i < end; ++i)
00393                         delete this->memos.GetMemo(i);
00394                 this->memos.memos->clear();
00395         }
00396 
00397         if (this->founder)
00398                 --this->founder->channelcount;
00399 }
00400 
00401 void ChannelInfo::Serialize(Serialize::Data &data) const
00402 {
00403         data["name"] << this->name;
00404         if (this->founder)
00405                 data["founder"] << this->founder->display;
00406         if (this->successor)
00407                 data["successor"] << this->successor->display;
00408         data["description"] << this->desc;
00409         data.SetType("time_registered", Serialize::Data::DT_INT); data["time_registered"] << this->time_registered;
00410         data.SetType("last_used", Serialize::Data::DT_INT); data["last_used"] << this->last_used;
00411         data["last_topic"] << this->last_topic;
00412         data["last_topic_setter"] << this->last_topic_setter;
00413         data.SetType("last_topic_time", Serialize::Data::DT_INT); data["last_topic_time"] << this->last_topic_time;
00414         data.SetType("bantype", Serialize::Data::DT_INT); data["bantype"] << this->bantype;
00415         this->ExtensibleSerialize(data);
00416         {
00417                 Anope::string levels_buffer;
00418                 for (std::map<Anope::string, int16_t>::const_iterator it = this->levels.begin(), it_end = this->levels.end(); it != it_end; ++it)
00419                         levels_buffer += it->first + " " + stringify(it->second) + " ";
00420                 data["levels"] << levels_buffer;
00421         }
00422         if (this->bi)
00423                 data["bi"] << this->bi->nick;
00424         for (int i = 0; i < TTB_SIZE; ++i)
00425                 data["ttb"] << this->ttb[i] << " ";
00426         data.SetType("capsmin", Serialize::Data::DT_INT); data["capsmin"] << this->capsmin;
00427         data.SetType("capspercent", Serialize::Data::DT_INT); data["capspercent"] << this->capspercent;
00428         data.SetType("floodlines", Serialize::Data::DT_INT); data["floodlines"] << this->floodlines;
00429         data.SetType("floodsecs", Serialize::Data::DT_INT); data["floodsecs"] << this->floodsecs;
00430         data.SetType("repeattimes", Serialize::Data::DT_INT); data["repeattimes"] << this->repeattimes;
00431         data["memomax"] << this->memos.memomax;
00432         for (unsigned i = 0; i < this->memos.ignores.size(); ++i)
00433                 data["memoignores"] << this->memos.ignores[i] << " ";
00434 }
00435 
00436 Serializable* ChannelInfo::Unserialize(Serializable *obj, Serialize::Data &data)
00437 {
00438         Anope::string sname, sfounder, ssuccessor, slevels, sbi;
00439 
00440         data["name"] >> sname;
00441         data["founder"] >> sfounder;
00442         data["successor"] >> ssuccessor;
00443         data["levels"] >> slevels;
00444         data["bi"] >> sbi;
00445 
00446         ChannelInfo *ci;
00447         if (obj)
00448                 ci = anope_dynamic_static_cast<ChannelInfo *>(obj);
00449         else
00450                 ci = new ChannelInfo(sname);
00451 
00452         ci->ExtensibleUnserialize(data);
00453 
00454         ci->SetFounder(NickCore::Find(sfounder));
00455         ci->SetSuccessor(NickCore::Find(ssuccessor));
00456 
00457         data["description"] >> ci->desc;
00458         data["time_registered"] >> ci->time_registered;
00459         data["last_used"] >> ci->last_used;
00460         data["last_topic"] >> ci->last_topic;
00461         data["last_topic_setter"] >> ci->last_topic_setter;
00462         data["last_topic_time"] >> ci->last_topic_time;
00463         data["bantype"] >> ci->bantype;
00464         {
00465                 std::vector<Anope::string> v;
00466                 spacesepstream(slevels).GetTokens(v);
00467                 for (unsigned i = 0; i + 1 < v.size(); i += 2)
00468                         ci->levels[v[i]] = convertTo<int16_t>(v[i + 1]);
00469         }
00470         BotInfo *bi = BotInfo::Find(sbi);
00471         if (*ci->bi != bi)
00472         {
00473                 if (ci->bi)
00474                         ci->bi->UnAssign(NULL, ci);
00475                 ci->bi = bi;
00476                 if (ci->bi)
00477                         ci->bi->Assign(NULL, ci);
00478         }
00479         data["capsmin"] >> ci->capsmin;
00480         data["capspercent"] >> ci->capspercent;
00481         data["floodlines"] >> ci->floodlines;
00482         data["floodsecs"] >> ci->floodsecs;
00483         data["repeattimes"] >> ci->repeattimes;
00484         data["memomax"] >> ci->memos.memomax;
00485         {
00486                 Anope::string buf;
00487                 data["memoignores"] >> buf;
00488                 spacesepstream sep(buf);
00489                 ci->memos.ignores.clear();
00490                 while (sep.GetToken(buf))
00491                         ci->memos.ignores.push_back(buf);
00492         }
00493 
00494         /* Compat */
00495         Anope::string sflags, sbotflags;
00496         data["flags"] >> sflags;
00497         data["botflags"] >> sbotflags;
00498         spacesepstream sep(sflags);
00499         Anope::string tok;
00500         while (sep.GetToken(tok))
00501                 ci->ExtendMetadata(tok);
00502         spacesepstream sep2(sbotflags);
00503         while (sep2.GetToken(tok))
00504                 ci->ExtendMetadata("BS_" + tok);
00505         /* End compat */
00506 
00507         return ci;
00508 }
00509 
00510 
00511 void ChannelInfo::SetFounder(NickCore *nc)
00512 {
00513         if (this->founder)
00514         {
00515                 --this->founder->channelcount;
00516                 this->founder->RemoveChannelReference(this);
00517         }
00518 
00519         this->founder = nc;
00520 
00521         if (this->founder)
00522         {
00523                 ++this->founder->channelcount;
00524                 this->founder->AddChannelReference(this);
00525         }
00526 }
00527 
00528 NickCore *ChannelInfo::GetFounder() const
00529 {
00530         return this->founder;
00531 }
00532 
00533 void ChannelInfo::SetSuccessor(NickCore *nc)
00534 {
00535         if (this->successor)
00536                 this->successor->RemoveChannelReference(this);
00537         this->successor = nc;
00538         if (this->successor)
00539                 this->successor->AddChannelReference(this);
00540 }
00541 
00542 NickCore *ChannelInfo::GetSuccessor() const
00543 {
00544         return this->successor;
00545 }
00546 
00547 BotInfo *ChannelInfo::WhoSends() const
00548 {
00549         if (this && this->bi)
00550                 return this->bi;
00551         else if (ChanServ)
00552                 return ChanServ;
00553         else if (!BotListByNick->empty())
00554                 return BotListByNick->begin()->second;
00555         return NULL;
00556 }
00557 
00558 void ChannelInfo::AddAccess(ChanAccess *taccess)
00559 {
00560         this->access->push_back(taccess);
00561 
00562         const NickAlias *na = NickAlias::Find(taccess->mask);
00563         if (na != NULL)
00564                 na->nc->AddChannelReference(this);
00565 }
00566 
00567 ChanAccess *ChannelInfo::GetAccess(unsigned index) const
00568 {
00569         if (this->access->empty() || index >= this->access->size())
00570                 return NULL;
00571 
00572         ChanAccess *acc = (*this->access)[index];
00573         acc->QueueUpdate();
00574         return acc;
00575 }
00576 
00577 AccessGroup ChannelInfo::AccessFor(const User *u)
00578 {
00579         AccessGroup group;
00580 
00581         if (u == NULL)
00582                 return group;
00583 
00584         const NickCore *nc = u->Account();
00585         if (nc == NULL && u->IsRecognized())
00586         {
00587                 const NickAlias *na = NickAlias::Find(u->nick);
00588                 if (na != NULL)
00589                         nc = na->nc;
00590         }
00591 
00592         group.super_admin = u->super_admin;
00593         group.founder = IsFounder(u, this);
00594         group.ci = this;
00595         group.nc = nc;
00596 
00597         for (unsigned i = 0, end = this->GetAccessCount(); i < end; ++i)
00598                 if (this->GetAccess(i)->Matches(u, nc))
00599                         group.push_back(this->GetAccess(i));
00600 
00601         if (group.founder || !group.empty())
00602         {
00603                 this->last_used = Anope::CurTime;
00604 
00605                 for (unsigned i = 0; i < group.size(); ++i)
00606                         group[i]->last_seen = Anope::CurTime;
00607         }
00608 
00609         return group;
00610 }
00611 
00612 AccessGroup ChannelInfo::AccessFor(const NickCore *nc)
00613 {
00614         AccessGroup group;
00615 
00616         group.founder = (this->founder && this->founder == nc);
00617         group.ci = this;
00618         group.nc = nc;
00619 
00620         for (unsigned i = 0, end = this->GetAccessCount(); i < end; ++i)
00621                 if (this->GetAccess(i)->Matches(NULL, nc))
00622                         group.push_back(this->GetAccess(i));
00623         
00624         if (group.founder || !group.empty())
00625         {
00626                 this->last_used = Anope::CurTime;
00627 
00628                 for (unsigned i = 0; i < group.size(); ++i)
00629                         group[i]->last_seen = Anope::CurTime;
00630         }
00631 
00632         return group;
00633 }
00634 
00635 unsigned ChannelInfo::GetAccessCount() const
00636 {
00637         return this->access->size();
00638 }
00639 
00640 void ChannelInfo::EraseAccess(unsigned index)
00641 {
00642         if (this->access->empty() || index >= this->access->size())
00643                 return;
00644 
00645         delete this->access->at(index);
00646 }
00647 
00648 void ChannelInfo::ClearAccess()
00649 {
00650         for (unsigned i = this->access->size(); i > 0; --i)
00651                 delete this->GetAccess(i - 1);
00652 }
00653 
00654 AutoKick *ChannelInfo::AddAkick(const Anope::string &user, NickCore *akicknc, const Anope::string &reason, time_t t, time_t lu)
00655 {
00656         AutoKick *autokick = new AutoKick();
00657         autokick->ci = this;
00658         autokick->nc = akicknc;
00659         autokick->reason = reason;
00660         autokick->creator = user;
00661         autokick->addtime = t;
00662         autokick->last_used = lu;
00663 
00664         this->akick->push_back(autokick);
00665 
00666         akicknc->AddChannelReference(this);
00667 
00668         return autokick;
00669 }
00670 
00671 AutoKick *ChannelInfo::AddAkick(const Anope::string &user, const Anope::string &mask, const Anope::string &reason, time_t t, time_t lu)
00672 {
00673         AutoKick *autokick = new AutoKick();
00674         autokick->ci = this;
00675         autokick->mask = mask;
00676         autokick->nc = NULL;
00677         autokick->reason = reason;
00678         autokick->creator = user;
00679         autokick->addtime = t;
00680         autokick->last_used = lu;
00681 
00682         this->akick->push_back(autokick);
00683 
00684         return autokick;
00685 }
00686 
00687 AutoKick *ChannelInfo::GetAkick(unsigned index) const
00688 {
00689         if (this->akick->empty() || index >= this->akick->size())
00690                 return NULL;
00691 
00692         AutoKick *ak = (*this->akick)[index];
00693         ak->QueueUpdate();
00694         return ak;
00695 }
00696 
00697 unsigned ChannelInfo::GetAkickCount() const
00698 {
00699         return this->akick->size();
00700 }
00701 
00702 void ChannelInfo::EraseAkick(unsigned index)
00703 {
00704         if (this->akick->empty() || index >= this->akick->size())
00705                 return;
00706         
00707         delete this->GetAkick(index);
00708 }
00709 
00710 void ChannelInfo::ClearAkick()
00711 {
00712         while (!this->akick->empty())
00713                 delete this->akick->back();
00714 }
00715 
00716 BadWord* ChannelInfo::AddBadWord(const Anope::string &word, BadWordType type)
00717 {
00718         BadWord *bw = new BadWord();
00719         bw->ci = this;
00720         bw->word = word;
00721         bw->type = type;
00722 
00723         this->badwords->push_back(bw);
00724 
00725         FOREACH_MOD(I_OnBadWordAdd, OnBadWordAdd(this, bw));
00726 
00727         return bw;
00728 }
00729 
00730 BadWord* ChannelInfo::GetBadWord(unsigned index) const
00731 {
00732         if (this->badwords->empty() || index >= this->badwords->size())
00733                 return NULL;
00734 
00735         BadWord *bw = (*this->badwords)[index];
00736         bw->QueueUpdate();
00737         return bw;
00738 }
00739 
00740 unsigned ChannelInfo::GetBadWordCount() const
00741 {
00742         return this->badwords->size();
00743 }
00744 
00745 void ChannelInfo::EraseBadWord(unsigned index)
00746 {
00747         if (this->badwords->empty() || index >= this->badwords->size())
00748                 return;
00749         
00750         FOREACH_MOD(I_OnBadWordDel, OnBadWordDel(this, (*this->badwords)[index]));
00751 
00752         delete this->badwords->at(index);
00753 }
00754 
00755 void ChannelInfo::ClearBadWords()
00756 {
00757         while (!this->badwords->empty())
00758                 delete this->badwords->back();
00759 }
00760 
00761 bool ChannelInfo::HasMLock(ChannelMode *mode, const Anope::string &param, bool status) const
00762 {
00763         std::multimap<Anope::string, ModeLock *>::const_iterator it = this->mode_locks->find(mode->name);
00764 
00765         if (it != this->mode_locks->end())
00766         {
00767                 if (mode->type != MODE_REGULAR)
00768                 {
00769                         std::multimap<Anope::string, ModeLock *>::const_iterator it_end = this->mode_locks->upper_bound(mode->name);
00770 
00771                         for (; it != it_end; ++it)
00772                         {
00773                                 const ModeLock *ml = it->second;
00774                                 if (ml->param == param)
00775                                         return true;
00776                         }
00777                 }
00778                 else
00779                         return it->second->set == status;
00780         }
00781         return false;
00782 }
00783 
00784 bool ChannelInfo::SetMLock(ChannelMode *mode, bool status, const Anope::string &param, Anope::string setter, time_t created)
00785 {
00786         if (setter.empty())
00787                 setter = this->founder ? this->founder->display : "Unknown";
00788         std::pair<Anope::string, ModeLock *> ml = std::make_pair(mode->name, new ModeLock(this, status, mode->name, param, setter, created));
00789 
00790         EventReturn MOD_RESULT;
00791         FOREACH_RESULT(I_OnMLock, OnMLock(this, ml.second));
00792         if (MOD_RESULT == EVENT_STOP)
00793                 return false;
00794 
00795         /* First, remove this */
00796         if (mode->type == MODE_REGULAR || mode->type == MODE_PARAM)
00797         {
00798                 for (ChannelInfo::ModeList::const_iterator it; (it = this->mode_locks->find(mode->name)) != this->mode_locks->end();)
00799                         delete it->second;
00800                 this->mode_locks->erase(mode->name);
00801         }
00802         else
00803         {
00804                 // For list or status modes, we must check the parameter
00805                 ChannelInfo::ModeList::iterator it = this->mode_locks->find(mode->name);
00806                 if (it != this->mode_locks->end())
00807                 {
00808                         ChannelInfo::ModeList::iterator it_end = this->mode_locks->upper_bound(mode->name);
00809                         for (; it != it_end; ++it)
00810                         {
00811                                 const ModeLock *modelock = it->second;
00812                                 if (modelock->param == param)
00813                                 {
00814                                         delete it->second;
00815                                         break;
00816                                 }
00817                         }
00818                 }
00819         }
00820 
00821         this->mode_locks->insert(ml);
00822 
00823         return true;
00824 }
00825 
00826 bool ChannelInfo::RemoveMLock(ChannelMode *mode, bool status, const Anope::string &param)
00827 {
00828         if (mode->type == MODE_REGULAR || mode->type == MODE_PARAM)
00829         {
00830                 ChannelInfo::ModeList::iterator it = this->mode_locks->find(mode->name), it_end = this->mode_locks->upper_bound(mode->name), it_next = it;
00831                 if (it != this->mode_locks->end())
00832                         for (; it != it_end; it = it_next)
00833                         {
00834                                 const ModeLock *ml = it->second;
00835                                 ++it_next;
00836 
00837                                 if (status != ml->set)
00838                                         continue;
00839 
00840                                 EventReturn MOD_RESULT;
00841                                 FOREACH_RESULT(I_OnUnMLock, OnUnMLock(this, it->second));
00842                                 if (MOD_RESULT != EVENT_STOP)
00843                                 {
00844                                         delete it->second;
00845                                         return true;
00846                                 }
00847                         }
00848                 return false;
00849         }
00850         else
00851         {
00852                 // For list or status modes, we must check the parameter
00853                 ChannelInfo::ModeList::iterator it = this->mode_locks->find(mode->name);
00854                 if (it != this->mode_locks->end())
00855                 {
00856                         ChannelInfo::ModeList::iterator it_end = this->mode_locks->upper_bound(mode->name);
00857                         for (; it != it_end; ++it)
00858                         {
00859                                 const ModeLock *ml = it->second;
00860                                 if (ml->set == status && ml->param == param)
00861                                 {
00862                                         EventReturn MOD_RESULT;
00863                                         FOREACH_RESULT(I_OnUnMLock, OnUnMLock(this, it->second));
00864                                         if (MOD_RESULT == EVENT_STOP)
00865                                                 return false;
00866                                         delete it->second;
00867                                         return true;
00868                                 }
00869                         }
00870                 }
00871 
00872                 return false;
00873         }
00874 }
00875 
00876 void ChannelInfo::RemoveMLock(ModeLock *mlock)
00877 {
00878         ChannelInfo::ModeList::iterator it = this->mode_locks->find(mlock->name);
00879         if (it != this->mode_locks->end())
00880                 for (; it != this->mode_locks->upper_bound(mlock->name); ++it)
00881                         if (it->second == mlock)
00882                         {
00883                                 this->mode_locks->erase(it);
00884                                 break;
00885                         }
00886 }
00887 
00888 void ChannelInfo::ClearMLock()
00889 {
00890         while (!this->mode_locks->empty())
00891                 delete this->mode_locks->begin()->second;
00892         this->mode_locks->clear();
00893 }
00894 
00895 const ChannelInfo::ModeList &ChannelInfo::GetMLock() const
00896 {
00897         return this->mode_locks;
00898 }
00899 
00900 std::pair<ChannelInfo::ModeList::iterator, ChannelInfo::ModeList::iterator> ChannelInfo::GetModeList(const Anope::string &mname)
00901 {
00902         ChannelInfo::ModeList::iterator it = this->mode_locks->find(mname), it_end = it;
00903         if (it != this->mode_locks->end())
00904                 it_end = this->mode_locks->upper_bound(mname);
00905         return std::make_pair(it, it_end);
00906 }
00907 
00908 const ModeLock *ChannelInfo::GetMLock(const Anope::string &mname, const Anope::string &param)
00909 {
00910         ChannelInfo::ModeList::iterator it = this->mode_locks->find(mname);
00911         if (it != this->mode_locks->end())
00912         {
00913                 if (param.empty())
00914                         return it->second;
00915                 else
00916                 {
00917                         ChannelInfo::ModeList::iterator it_end = this->mode_locks->upper_bound(mname);
00918                         for (; it != it_end; ++it)
00919                         {
00920                                 if (Anope::Match(param, it->second->param))
00921                                         return it->second;
00922                         }
00923                 }
00924         }
00925 
00926         return NULL;
00927 }
00928 
00929 Anope::string ChannelInfo::GetMLockAsString(bool complete) const
00930 {
00931         Anope::string pos = "+", neg = "-", params;
00932 
00933         for (ChannelInfo::ModeList::const_iterator it = this->GetMLock().begin(), it_end = this->GetMLock().end(); it != it_end; ++it)
00934         {
00935                 const ModeLock *ml = it->second;
00936                 ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name);
00937                 if (!cm || cm->type == MODE_LIST || cm->type == MODE_STATUS)
00938                         continue;
00939 
00940                 if (ml->set)
00941                         pos += cm->mchar;
00942                 else
00943                         neg += cm->mchar;
00944 
00945                 if (complete && !ml->param.empty() && cm->type == MODE_PARAM)
00946                         params += " " + ml->param;
00947         }
00948 
00949         if (pos.length() == 1)
00950                 pos.clear();
00951         if (neg.length() == 1)
00952                 neg.clear();
00953 
00954         return pos + neg + params;
00955 }
00956 
00957 bool ChannelInfo::CheckKick(User *user)
00958 {
00959         if (!user || !this->c)
00960                 return false;
00961 
00962         if (user->super_admin)
00963                 return false;
00964 
00965         /* We don't enforce services restrictions on clients on ulined services
00966          * as this will likely lead to kick/rejoin floods. ~ Viper */
00967         if (user->server->IsULined())
00968                 return false;
00969 
00970         if (user->IsProtected())
00971                 return false;
00972 
00973         Anope::string mask, reason;
00974 
00975         EventReturn MOD_RESULT;
00976         FOREACH_RESULT(I_OnCheckKick, OnCheckKick(user, this, mask, reason));
00977         if (MOD_RESULT != EVENT_STOP)
00978                 return false;
00979         
00980         if (mask.empty())
00981                 mask = this->GetIdealBan(user);
00982         if (reason.empty())
00983                 reason = Language::Translate(user->Account(), CHAN_NOT_ALLOWED_TO_JOIN);
00984 
00985         Log(LOG_DEBUG) << "Autokicking " << user->nick << " (" << mask << ") from " << this->name;
00986 
00987         /* If the channel isn't syncing and doesn't have any users, join ChanServ
00988          * Note that the user AND POSSIBLY the botserv bot exist here
00989          * ChanServ always enforces channels like this to keep people from deleting bots etc
00990          * that are holding channels.
00991          */
00992         if (this->c->users.size() == (this->bi && this->c->FindUser(this->bi) ? 2 : 1) && !this->c->HasExt("INHABIT") && !this->c->HasExt("SYNCING"))
00993         {
00994                 /* Set +ntsi to prevent rejoin */
00995                 c->SetMode(NULL, "NOEXTERNAL");
00996                 c->SetMode(NULL, "TOPIC");
00997                 c->SetMode(NULL, "SECRET");
00998                 c->SetMode(NULL, "INVITE");
00999 
01000                 /* Join ChanServ and set a timer for this channel to part ChanServ later */
01001                 this->c->Hold();
01002         }
01003 
01004         this->c->SetMode(NULL, "BAN", mask);
01005         this->c->Kick(NULL, user, "%s", reason.c_str());
01006 
01007         return true;
01008 }
01009 
01010 void ChannelInfo::CheckTopic()
01011 {
01012         if (!this->c)
01013                 return;
01014 
01015         /* We only compare the topics here, not the time or setter. This is because some (old) IRCds do not
01016          * allow us to set the topic as someone else, meaning we have to bump the TS and change the setter to us.
01017          * This desyncs what is really set with what we have stored, and we end up resetting the topic often when
01018          * it is not required
01019          */
01020         if (this->HasExt("TOPICLOCK") && this->last_topic != this->c->topic)
01021         {
01022                 this->c->ChangeTopic(this->last_topic_setter, this->last_topic, this->last_topic_time);
01023         }
01024         else
01025         {
01026                 this->last_topic = this->c->topic;
01027                 this->last_topic_setter = this->c->topic_setter;
01028                 this->last_topic_time = this->c->topic_ts;
01029         }
01030 }
01031 
01032 void ChannelInfo::RestoreTopic()
01033 {
01034         if (!this->c)
01035                 return;
01036 
01037         if ((this->HasExt("KEEPTOPIC") || this->HasExt("TOPICLOCK")) && this->last_topic != this->c->topic)
01038         {
01039                 this->c->ChangeTopic(!this->last_topic_setter.empty() ? this->last_topic_setter : this->WhoSends()->nick, this->last_topic, this->last_topic_time ? this->last_topic_time : Anope::CurTime);
01040         }
01041 }
01042 
01043 int16_t ChannelInfo::GetLevel(const Anope::string &priv) const
01044 {
01045         if (PrivilegeManager::FindPrivilege(priv) == NULL)
01046         {
01047                 Log(LOG_DEBUG) << "Unknown privilege " + priv;
01048                 return ACCESS_INVALID;
01049         }
01050 
01051         std::map<Anope::string, int16_t>::const_iterator it = this->levels.find(priv);
01052         if (it == this->levels.end())
01053                 return 0;
01054         return it->second;
01055 }
01056 
01057 void ChannelInfo::SetLevel(const Anope::string &priv, int16_t level)
01058 {
01059         this->levels[priv] = level;
01060 }
01061 
01062 void ChannelInfo::RemoveLevel(const Anope::string &priv)
01063 {
01064         this->levels.erase(priv);
01065 }
01066 
01067 void ChannelInfo::ClearLevels()
01068 {
01069         this->levels.clear();
01070 }
01071 
01072 Anope::string ChannelInfo::GetIdealBan(User *u) const
01073 {
01074         switch (this->bantype)
01075         {
01076                 case 0:
01077                         return "*!" + u->GetVIdent() + "@" + u->GetDisplayedHost();
01078                 case 1:
01079                         if (u->GetVIdent()[0] == '~')
01080                                 return "*!*" + u->GetVIdent() + "@" + u->GetDisplayedHost();
01081                         else
01082                                 return "*!" + u->GetVIdent() + "@" + u->GetDisplayedHost();
01083                 case 3:
01084                         return "*!" + u->Mask();
01085                 case 2:
01086                 default:
01087                         return "*!*@" + u->GetDisplayedHost();
01088         }
01089 }
01090 
01091 ChannelInfo* ChannelInfo::Find(const Anope::string &name)
01092 {
01093         registered_channel_map::const_iterator it = RegisteredChannelList->find(name);
01094         if (it != RegisteredChannelList->end())
01095         {
01096                 it->second->QueueUpdate();
01097                 return it->second;
01098         }
01099 
01100         return NULL;
01101 }
01102 
01103 bool IsFounder(const User *user, const ChannelInfo *ci)
01104 {
01105         if (!user || !ci)
01106                 return false;
01107 
01108         if (user->super_admin)
01109                 return true;
01110 
01111         if (user->Account() && user->Account() == ci->GetFounder())
01112                 return true;
01113 
01114         return false;
01115 }
01116