00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "inspircd.h"
00015
00016
00017
00018 #define PROTECT_VALUE 40000
00019 #define FOUNDER_VALUE 50000
00020
00023 class FounderProtectBase
00024 {
00025 private:
00026 InspIRCd* MyInstance;
00027 std::string extend;
00028 std::string type;
00029 int list;
00030 int end;
00031 protected:
00032 bool& remove_own_privs;
00033 bool& remove_other_privs;
00034 public:
00035 FounderProtectBase(InspIRCd* Instance, const std::string &ext, const std::string &mtype, int l, int e, bool &remove_own, bool &remove_others) :
00036 MyInstance(Instance), extend(ext), type(mtype), list(l), end(e), remove_own_privs(remove_own), remove_other_privs(remove_others)
00037 {
00038 }
00039
00040 ModePair ModeSet(User* source, User* dest, Channel* channel, const std::string ¶meter)
00041 {
00042 User* x = MyInstance->FindNick(parameter);
00043 if (x)
00044 {
00045 if (!channel->HasUser(x))
00046 {
00047 return std::make_pair(false, parameter);
00048 }
00049 else
00050 {
00051 std::string item = extend+std::string(channel->name);
00052 if (x->GetExt(item))
00053 {
00054 return std::make_pair(true, x->nick);
00055 }
00056 else
00057 {
00058 return std::make_pair(false, parameter);
00059 }
00060 }
00061 }
00062 return std::make_pair(false, parameter);
00063 }
00064
00065 void RemoveMode(Channel* channel, char mc, irc::modestacker* stack)
00066 {
00067 CUList* cl = channel->GetUsers();
00068 std::string item = extend + std::string(channel->name);
00069 std::vector<std::string> mode_junk;
00070 mode_junk.push_back(channel->name);
00071 irc::modestacker modestack(MyInstance, false);
00072 std::deque<std::string> stackresult;
00073
00074 for (CUList::iterator i = cl->begin(); i != cl->end(); i++)
00075 {
00076 if (i->first->GetExt(item))
00077 {
00078 if (stack)
00079 stack->Push(mc, i->first->nick);
00080 else
00081 modestack.Push(mc, i->first->nick);
00082 }
00083 }
00084
00085 if (stack)
00086 return;
00087
00088 while (modestack.GetStackedLine(stackresult))
00089 {
00090 for (size_t j = 0; j < stackresult.size(); j++)
00091 {
00092 mode_junk.push_back(stackresult[j]);
00093 }
00094 MyInstance->SendMode(mode_junk, MyInstance->FakeClient);
00095 }
00096 }
00097
00098 void DisplayList(User* user, Channel* channel)
00099 {
00100 CUList* cl = channel->GetUsers();
00101 std::string item = extend+std::string(channel->name);
00102 for (CUList::reverse_iterator i = cl->rbegin(); i != cl->rend(); ++i)
00103 {
00104 if (i->first->GetExt(item))
00105 {
00106 user->WriteServ("%d %s %s %s", list, user->nick.c_str(), channel->name.c_str(), i->first->nick.c_str());
00107 }
00108 }
00109 user->WriteServ("%d %s %s :End of channel %s list", end, user->nick.c_str(), channel->name.c_str(), type.c_str());
00110 }
00111
00112 User* FindAndVerify(std::string ¶meter, Channel* channel)
00113 {
00114 User* theuser = MyInstance->FindNick(parameter);
00115 if ((!theuser) || (!channel->HasUser(theuser)))
00116 {
00117 parameter.clear();
00118 return NULL;
00119 }
00120 return theuser;
00121 }
00122
00123 bool CanRemoveOthers(User* u1, User* u2, Channel* c)
00124 {
00125 std::string item = extend+std::string(c->name);
00126 return (remove_other_privs && u1->GetExt(item) && u2->GetExt(item));
00127 }
00128
00129 ModeAction HandleChange(User* source, User* theuser, bool adding, Channel* channel, std::string ¶meter)
00130 {
00131 std::string item = extend+std::string(channel->name);
00132
00133 if (adding)
00134 {
00135 if (!theuser->GetExt(item))
00136 {
00137 theuser->Extend(item);
00138 parameter = theuser->nick;
00139 return MODEACTION_ALLOW;
00140 }
00141 }
00142 else
00143 {
00144 if (theuser->GetExt(item))
00145 {
00146 theuser->Shrink(item);
00147 parameter = theuser->nick;
00148 return MODEACTION_ALLOW;
00149 }
00150 }
00151 return MODEACTION_DENY;
00152 }
00153 };
00154
00157 class ChanFounder : public ModeHandler, public FounderProtectBase
00158 {
00159 public:
00160 ChanFounder(InspIRCd* Instance, char my_prefix, bool &depriv_self, bool &depriv_others)
00161 : ModeHandler(Instance, 'q', 1, 1, true, MODETYPE_CHANNEL, false, my_prefix, 0),
00162 FounderProtectBase(Instance, "cm_founder_", "founder", 386, 387, depriv_self, depriv_others) { }
00163
00164 unsigned int GetPrefixRank()
00165 {
00166 return FOUNDER_VALUE;
00167 }
00168
00169 ModePair ModeSet(User* source, User* dest, Channel* channel, const std::string ¶meter)
00170 {
00171 return FounderProtectBase::ModeSet(source, dest, channel, parameter);
00172 }
00173
00174 void RemoveMode(Channel* channel, irc::modestacker* stack)
00175 {
00176 FounderProtectBase::RemoveMode(channel, this->GetModeChar(), stack);
00177 }
00178
00179 void RemoveMode(User* user, irc::modestacker* stack)
00180 {
00181 }
00182
00183 ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding, bool)
00184 {
00185 User* theuser = FounderProtectBase::FindAndVerify(parameter, channel);
00186
00187 if (!theuser)
00188 {
00189 return MODEACTION_DENY;
00190 }
00191
00192 if ((!adding) && FounderProtectBase::CanRemoveOthers(source, theuser, channel))
00193 {
00194 return FounderProtectBase::HandleChange(source, theuser, adding, channel, parameter);
00195 }
00196
00197 if (source == ServerInstance->FakeClient ||
00198 ((source == theuser) && (!adding) && (FounderProtectBase::remove_own_privs)) ||
00199 (ServerInstance->ULine(source->nick.c_str())) ||
00200 (ServerInstance->ULine(source->server)) ||
00201 (!*source->server) ||
00202 (!IS_LOCAL(source)))
00203 {
00204 return FounderProtectBase::HandleChange(source, theuser, adding, channel, parameter);
00205 }
00206 else
00207 {
00208
00209 source->WriteNumeric(468, "%s %s :Only servers may set channel mode +q", source->nick.c_str(), channel->name.c_str());
00210 parameter.clear();
00211 return MODEACTION_DENY;
00212 }
00213 }
00214
00215 void DisplayList(User* user, Channel* channel)
00216 {
00217 FounderProtectBase::DisplayList(user,channel);
00218 }
00219 };
00220
00223 class ChanProtect : public ModeHandler, public FounderProtectBase
00224 {
00225 public:
00226 ChanProtect(InspIRCd* Instance, char my_prefix, bool &depriv_self, bool &depriv_others)
00227 : ModeHandler(Instance, 'a', 1, 1, true, MODETYPE_CHANNEL, false, my_prefix, 0),
00228 FounderProtectBase(Instance,"cm_protect_","protected user", 388, 389, depriv_self, depriv_others) { }
00229
00230 unsigned int GetPrefixRank()
00231 {
00232 return PROTECT_VALUE;
00233 }
00234
00235 ModePair ModeSet(User* source, User* dest, Channel* channel, const std::string ¶meter)
00236 {
00237 return FounderProtectBase::ModeSet(source, dest, channel, parameter);
00238 }
00239
00240 void RemoveMode(Channel* channel, irc::modestacker* stack)
00241 {
00242 FounderProtectBase::RemoveMode(channel, this->GetModeChar(), stack);
00243 }
00244
00245 void RemoveMode(User* user, irc::modestacker* stack)
00246 {
00247 }
00248
00249 ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding, bool)
00250 {
00251 User* theuser = FounderProtectBase::FindAndVerify(parameter, channel);
00252
00253 if (!theuser)
00254 return MODEACTION_DENY;
00255
00256 std::string founder = "cm_founder_"+std::string(channel->name);
00257
00258 if ((!adding) && FounderProtectBase::CanRemoveOthers(source, theuser, channel))
00259 {
00260 return FounderProtectBase::HandleChange(source, theuser, adding, channel, parameter);
00261 }
00262
00263 if (source == ServerInstance->FakeClient ||
00264 ((source == theuser) && (!adding) && (FounderProtectBase::remove_own_privs)) ||
00265 (ServerInstance->ULine(source->nick.c_str())) ||
00266 (ServerInstance->ULine(source->server)) ||
00267 (!*source->server) ||
00268 (source->GetExt(founder)) ||
00269 (!IS_LOCAL(source)))
00270 {
00271 return FounderProtectBase::HandleChange(source, theuser, adding, channel, parameter);
00272 }
00273 else
00274 {
00275
00276 source->WriteNumeric(482, "%s %s :You are not a channel founder", source->nick.c_str(), channel->name.c_str());
00277 return MODEACTION_DENY;
00278 }
00279 }
00280
00281 virtual void DisplayList(User* user, Channel* channel)
00282 {
00283 FounderProtectBase::DisplayList(user, channel);
00284 }
00285
00286 };
00287
00288 class ModuleChanProtect : public Module
00289 {
00290
00291 bool FirstInGetsFounder;
00292 char QPrefix;
00293 char APrefix;
00294 bool DeprivSelf;
00295 bool DeprivOthers;
00296 bool booting;
00297 ChanProtect* cp;
00298 ChanFounder* cf;
00299
00300 public:
00301
00302 ModuleChanProtect(InspIRCd* Me)
00303 : Module(Me), FirstInGetsFounder(false), QPrefix(0), APrefix(0), DeprivSelf(false), DeprivOthers(false), booting(true), cp(NULL), cf(NULL)
00304 {
00305
00306 LoadSettings();
00307 booting = false;
00308
00309
00310
00311 cp = new ChanProtect(ServerInstance, APrefix, DeprivSelf, DeprivOthers);
00312 cf = new ChanFounder(ServerInstance, QPrefix, DeprivSelf, DeprivOthers);
00313
00314 if (!ServerInstance->Modes->AddMode(cp) || !ServerInstance->Modes->AddMode(cf))
00315 {
00316 delete cp;
00317 delete cf;
00318 throw ModuleException("Could not add new modes!");
00319 }
00320
00321 Implementation eventlist[] = { I_OnUserKick, I_OnUserPart, I_OnUserPreJoin, I_OnPostJoin, I_OnAccessCheck };
00322 ServerInstance->Modules->Attach(eventlist, this, 5);
00323 }
00324
00325 virtual void OnUserKick(User* source, User* user, Channel* chan, const std::string &reason, bool &silent)
00326 {
00327
00328 user->Shrink("cm_founder_"+std::string(chan->name));
00329 user->Shrink("cm_protect_"+std::string(chan->name));
00330 }
00331
00332 virtual void OnUserPart(User* user, Channel* channel, std::string &partreason, bool &silent)
00333 {
00334
00335 user->Shrink("cm_founder_"+std::string(channel->name));
00336 user->Shrink("cm_protect_"+std::string(channel->name));
00337 }
00338
00339 void LoadSettings()
00340 {
00341 ConfigReader Conf(ServerInstance);
00342
00343 FirstInGetsFounder = Conf.ReadFlag("chanprotect", "noservices", 0);
00344
00345 std::string qpre = Conf.ReadValue("chanprotect", "qprefix", 0);
00346 QPrefix = qpre.empty() ? 0 : qpre[0];
00347
00348 std::string apre = Conf.ReadValue("chanprotect", "aprefix", 0);
00349 APrefix = apre.empty() ? 0 : apre[0];
00350
00351 if ((APrefix && QPrefix) && APrefix == QPrefix)
00352 throw ModuleException("What the smeg, why are both your +q and +a prefixes the same character?");
00353
00354 if (cp && ServerInstance->Modes->FindPrefix(APrefix) == cp)
00355 throw ModuleException("Looks like the +a prefix you picked for m_chanprotect is already in use. Pick another.");
00356
00357 if (cf && ServerInstance->Modes->FindPrefix(QPrefix) == cf)
00358 throw ModuleException("Looks like the +q prefix you picked for m_chanprotect is already in use. Pick another.");
00359
00360 DeprivSelf = Conf.ReadFlag("chanprotect","deprotectself", "yes", 0);
00361 DeprivOthers = Conf.ReadFlag("chanprotect","deprotectothers", "yes", 0);
00362 }
00363
00364 virtual int OnUserPreJoin(User *user, Channel *chan, const char *cname, std::string &privs, const std::string &keygiven)
00365 {
00366
00367
00368
00369 if (FirstInGetsFounder && !chan)
00370 privs = std::string(1, QPrefix) + "@";
00371
00372 return 0;
00373 }
00374
00375 virtual void OnPostJoin(User *user, Channel *channel)
00376 {
00377
00378
00379
00380
00381
00382
00383
00384
00385 if (FirstInGetsFounder && channel->GetUserCounter() == 1)
00386 user->WriteServ("MODE %s +q %s", channel->name.c_str(), user->nick.c_str());
00387 }
00388
00389 virtual int OnAccessCheck(User* source,User* dest,Channel* channel,int access_type)
00390 {
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 if ((ServerInstance->ULine(source->nick.c_str())) || (ServerInstance->ULine(source->server)) || (!*source->server))
00403 return ACR_ALLOW;
00404
00405 std::string founder("cm_founder_"+channel->name);
00406 std::string protect("cm_protect_"+channel->name);
00407
00408
00409 if (DeprivSelf && source == dest)
00410 return ACR_DEFAULT;
00411
00412 bool candepriv_founder = (DeprivOthers && source->GetExt(founder));
00413 bool candepriv_protected = (source->GetExt(founder) || (DeprivOthers && source->GetExt(protect)));
00414
00415 switch (access_type)
00416 {
00417
00418 case AC_DEOP:
00419 if (dest->GetExt(founder) && !candepriv_founder)
00420 {
00421 source->WriteNumeric(484, source->nick+" "+channel->name+" :Can't deop "+dest->nick+" as they're a channel founder");
00422 return ACR_DENY;
00423 }
00424 if ((dest->GetExt(protect)) && !candepriv_protected)
00425 {
00426 source->WriteNumeric(484, source->nick+" "+channel->name+" :Can't deop "+dest->nick+" as they're protected (+a)");
00427 return ACR_DENY;
00428 }
00429 break;
00430
00431
00432 case AC_KICK:
00433 if (dest->GetExt(founder) && !candepriv_founder)
00434 {
00435 source->WriteNumeric(484, source->nick+" "+channel->name+" :Can't kick "+dest->nick+" as they're a channel founder");
00436 return ACR_DENY;
00437 }
00438 if ((dest->GetExt(protect)) && !candepriv_protected)
00439 {
00440 source->WriteNumeric(484, source->nick+" "+channel->name+" :Can't kick "+dest->nick+" as they're protected (+a)");
00441 return ACR_DENY;
00442 }
00443 break;
00444
00445
00446 case AC_DEHALFOP:
00447 if (dest->GetExt(founder) && !candepriv_founder)
00448 {
00449 source->WriteNumeric(484, source->nick+" "+channel->name+" :Can't de-halfop "+dest->nick+" as they're a channel founder");
00450 return ACR_DENY;
00451 }
00452 if ((dest->GetExt(protect)) && !candepriv_protected)
00453 {
00454 source->WriteNumeric(484, source->nick+" "+channel->name+" :Can't de-halfop "+dest->nick+" as they're protected (+a)");
00455 return ACR_DENY;
00456 }
00457 break;
00458
00459
00460 case AC_DEVOICE:
00461 if (dest->GetExt(founder) && !candepriv_founder)
00462 {
00463 source->WriteNumeric(484, source->nick+" "+channel->name+" :Can't devoice "+dest->nick+" as they're a channel founder");
00464 return ACR_DENY;
00465 }
00466 if ((dest->GetExt(protect)) && !candepriv_protected)
00467 {
00468 source->WriteNumeric(484, source->nick+" "+channel->name+" :Can't devoice "+dest->nick+" as they're protected (+a)");
00469 return ACR_DENY;
00470 }
00471 break;
00472 }
00473
00474
00475 return ACR_DEFAULT;
00476 }
00477
00478 virtual ~ModuleChanProtect()
00479 {
00480 ServerInstance->Modes->DelMode(cp);
00481 ServerInstance->Modes->DelMode(cf);
00482 delete cp;
00483 delete cf;
00484 }
00485
00486 virtual Version GetVersion()
00487 {
00488 return Version("$Id: m_chanprotect.cpp 10752 2008-10-30 20:47:13Z w00t $", VF_COMMON | VF_VENDOR, API_VERSION);
00489 }
00490 };
00491
00492 MODULE_INIT(ModuleChanProtect)