00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef INSPIRCD_LISTMODE_PROVIDER
00015 #define INSPIRCD_LISTMODE_PROVIDER
00016
00019 inline std::string stringtime()
00020 {
00021 std::ostringstream TIME;
00022 TIME << time(NULL);
00023 return TIME.str();
00024 }
00025
00028 class ListItem : public classbase
00029 {
00030 public:
00031 std::string nick;
00032 std::string mask;
00033 std::string time;
00034 };
00035
00038 class ListLimit : public classbase
00039 {
00040 public:
00041 std::string mask;
00042 unsigned int limit;
00043 };
00044
00047 typedef std::vector<ListItem> modelist;
00050 typedef std::vector<ListLimit> limitlist;
00051
00054 class ListModeRequest : public Request
00055 {
00056 public:
00057 User* user;
00058 Channel* chan;
00059
00067 ListModeRequest(Module* sender, Module* target, User* u, Channel* c) : Request(sender, target, "LM_CHECKLIST"), user(u), chan(c)
00068 {
00069 }
00070
00073 ~ListModeRequest()
00074 {
00075 }
00076 };
00077
00080 class ListModeBase : public ModeHandler
00081 {
00082 protected:
00085 std::string infokey;
00088 unsigned int listnumeric;
00091 unsigned int endoflistnumeric;
00094 std::string endofliststring;
00097 bool tidy;
00100 std::string configtag;
00104 limitlist chanlimits;
00105
00106 public:
00116 ListModeBase(InspIRCd* Instance, char modechar, const std::string &eolstr, unsigned int lnum, unsigned int eolnum, bool autotidy, const std::string &ctag = "banlist")
00117 : ModeHandler(Instance, modechar, 1, 1, true, MODETYPE_CHANNEL, false), listnumeric(lnum), endoflistnumeric(eolnum), endofliststring(eolstr), tidy(autotidy), configtag(ctag)
00118 {
00119 this->DoRehash();
00120 infokey = "listbase_mode_" + std::string(1, mode) + "_list";
00121 }
00122
00125 std::pair<bool,std::string> ModeSet(User*, User*, Channel* channel, const std::string ¶meter)
00126 {
00127 modelist* el;
00128 channel->GetExt(infokey, el);
00129 if (el)
00130 {
00131 for (modelist::iterator it = el->begin(); it != el->end(); it++)
00132 {
00133 if(parameter == it->mask)
00134 {
00135 return std::make_pair(true, parameter);
00136 }
00137 }
00138 }
00139 return std::make_pair(false, parameter);
00140 }
00141
00146 virtual void DisplayList(User* user, Channel* channel)
00147 {
00148 modelist* el;
00149 channel->GetExt(infokey, el);
00150 if (el)
00151 {
00152 for (modelist::reverse_iterator it = el->rbegin(); it != el->rend(); ++it)
00153 {
00154 user->WriteNumeric(listnumeric, "%s %s %s %s %s", user->nick.c_str(), channel->name.c_str(), it->mask.c_str(), it->nick.c_str(), it->time.c_str());
00155 }
00156 }
00157 user->WriteNumeric(endoflistnumeric, "%s %s :%s", user->nick.c_str(), channel->name.c_str(), endofliststring.c_str());
00158 }
00159
00160 virtual void DisplayEmptyList(User* user, Channel* channel)
00161 {
00162 user->WriteNumeric(endoflistnumeric, "%s %s :%s", user->nick.c_str(), channel->name.c_str(), endofliststring.c_str());
00163 }
00164
00169 virtual void RemoveMode(Channel* channel, irc::modestacker* stack)
00170 {
00171 modelist* el;
00172 channel->GetExt(infokey, el);
00173 if (el)
00174 {
00175 irc::modestacker modestack(ServerInstance, false);
00176 std::deque<std::string> stackresult;
00177 std::vector<std::string> mode_junk;
00178 mode_junk.push_back(channel->name);
00179
00180 for (modelist::iterator it = el->begin(); it != el->end(); it++)
00181 {
00182 if (stack)
00183 stack->Push(this->GetModeChar(), it->mask);
00184 else
00185 modestack.Push(this->GetModeChar(), it->mask);
00186 }
00187
00188 if (stack)
00189 return;
00190
00191 while (modestack.GetStackedLine(stackresult))
00192 {
00193 for (size_t j = 0; j < stackresult.size(); j++)
00194 {
00195 mode_junk.push_back(stackresult[j]);
00196 }
00197
00198 ServerInstance->SendMode(mode_junk, ServerInstance->FakeClient);
00199 }
00200 }
00201 }
00202
00205 virtual void RemoveMode(User*, irc::modestacker* stack)
00206 {
00207
00208 }
00209
00212 virtual void DoRehash()
00213 {
00214 ConfigReader Conf(ServerInstance);
00215
00216 chanlimits.clear();
00217
00218 for (int i = 0; i < Conf.Enumerate(configtag); i++)
00219 {
00220
00221 ListLimit limit;
00222 limit.mask = Conf.ReadValue(configtag, "chan", i);
00223 limit.limit = Conf.ReadInteger(configtag, "limit", i, true);
00224
00225 if (limit.mask.size() && limit.limit > 0)
00226 chanlimits.push_back(limit);
00227 }
00228 if (chanlimits.size() == 0)
00229 {
00230 ListLimit limit;
00231 limit.mask = "*";
00232 limit.limit = 64;
00233 chanlimits.push_back(limit);
00234 }
00235 }
00236
00239 virtual void DoImplements(Module* m)
00240 {
00241 Implementation eventlist[] = { I_OnChannelDelete, I_OnSyncChannel, I_OnCleanup, I_OnRehash };
00242 ServerInstance->Modules->Attach(eventlist, m, 4);
00243 }
00244
00248 virtual ModeAction OnModeChange(User* source, User*, Channel* channel, std::string ¶meter, bool adding, bool servermode)
00249 {
00250
00251 modelist* el;
00252 channel->GetExt(infokey, el);
00253
00254 if (adding)
00255 {
00256
00257 if (!el)
00258 {
00259
00260 el = new modelist;
00261 channel->Extend(infokey, el);
00262 }
00263
00264
00265 if (this->tidy)
00266 ModeParser::CleanMask(parameter);
00267
00268
00269 for (modelist::iterator it = el->begin(); it != el->end(); it++)
00270 {
00271 if (parameter == it->mask)
00272 {
00273
00274 TellAlreadyOnList(source, channel, parameter);
00275
00276
00277 return MODEACTION_DENY;
00278 }
00279 }
00280
00281 unsigned int maxsize = 0;
00282
00283 for (limitlist::iterator it = chanlimits.begin(); it != chanlimits.end(); it++)
00284 {
00285 if (InspIRCd::Match(channel->name, it->mask))
00286 {
00287
00288 maxsize = el->size();
00289 if (IS_LOCAL(source) || (maxsize < it->limit))
00290 {
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 if (ValidateParam(source, channel, parameter))
00302 {
00303
00304 ListItem e;
00305 e.mask = parameter;
00306 e.nick = servermode ? ServerInstance->Config->ServerName : source->nick;
00307 e.time = stringtime();
00308
00309 el->push_back(e);
00310 return MODEACTION_ALLOW;
00311 }
00312 else
00313 {
00314
00315 return MODEACTION_DENY;
00316 }
00317 }
00318 }
00319 }
00320
00321
00322 if (!TellListTooLong(source, channel, parameter))
00323 {
00324 source->WriteNumeric(478, "%s %s %s :Channel ban/ignore list is full", source->nick.c_str(), channel->name.c_str(), parameter.c_str());
00325 }
00326
00327 parameter = "";
00328 return MODEACTION_DENY;
00329 }
00330 else
00331 {
00332
00333 if (el)
00334 {
00335 for (modelist::iterator it = el->begin(); it != el->end(); it++)
00336 {
00337 if (parameter == it->mask)
00338 {
00339 el->erase(it);
00340 if (el->size() == 0)
00341 {
00342 channel->Shrink(infokey);
00343 delete el;
00344 }
00345 return MODEACTION_ALLOW;
00346 }
00347 }
00348
00349 TellNotSet(source, channel, parameter);
00350 parameter = "";
00351 return MODEACTION_DENY;
00352 }
00353 else
00354 {
00355
00356 TellNotSet(source, channel, parameter);
00357 parameter = "";
00358 return MODEACTION_DENY;
00359 }
00360 }
00361 return MODEACTION_DENY;
00362 }
00363
00366 virtual std::string& GetInfoKey()
00367 {
00368 return infokey;
00369 }
00370
00375 virtual void DoChannelDelete(Channel* chan)
00376 {
00377 modelist* mlist;
00378 chan->GetExt(infokey, mlist);
00379
00380 if (mlist)
00381 {
00382 chan->Shrink(infokey);
00383 delete mlist;
00384 }
00385 }
00386
00393 virtual void DoSyncChannel(Channel* chan, Module* proto, void* opaque)
00394 {
00395 modelist* mlist;
00396 chan->GetExt(infokey, mlist);
00397 irc::modestacker modestack(ServerInstance, true);
00398 std::deque<std::string> stackresult;
00399 if (mlist)
00400 {
00401 for (modelist::iterator it = mlist->begin(); it != mlist->end(); it++)
00402 {
00403 modestack.Push(std::string(1, mode)[0], it->mask);
00404 }
00405 }
00406 while (modestack.GetStackedLine(stackresult))
00407 {
00408 irc::stringjoiner mode_join(" ", stackresult, 0, stackresult.size() - 1);
00409 std::string line = mode_join.GetJoined();
00410 proto->ProtoSendMode(opaque, TYPE_CHANNEL, chan, line);
00411 }
00412 }
00413
00418 virtual void DoCleanup(int, void*)
00419 {
00420 }
00421
00429 virtual bool ValidateParam(User*, Channel*, std::string&)
00430 {
00431 return true;
00432 }
00433
00441 virtual bool TellListTooLong(User*, Channel*, std::string&)
00442 {
00443 return false;
00444 }
00445
00452 virtual void TellAlreadyOnList(User*, Channel*, std::string&)
00453 {
00454 }
00455
00462 virtual void TellNotSet(User*, Channel*, std::string&)
00463 {
00464 }
00465 };
00466
00467 #endif
00468