1 /* +------------------------------------+
\r * | Inspire Internet Relay Chat Daemon |
\r * +------------------------------------+
\r *
\r * InspIRCd: (C) 2002-2007 InspIRCd Development Team
\r * See: http://www.inspircd.org/wiki/index.php/Credits
\r *
\r * This program is free but copyrighted software; see
\r * the file COPYING for details.
\r *
\r * ---------------------------------------------------
\r */
\r\r#include "inspircd.h"
\r#include <sstream>
\r#include "users.h"
\r#include "channels.h"
\r#include "modules.h"
\r\r/* $ModDesc: Provides channel mode +J (delay rejoin after kick) */
\r\rinline int strtoint(const std::string &str)
\r{
\r std::istringstream ss(str);
\r int result;
\r ss >> result;
\r return result;
\r}
\r\rtypedef std::map<userrec*, time_t> delaylist;
\r\r/** Handles channel mode +J
\r */
\rclass KickRejoin : public ModeHandler
\r{
\r public:
\r KickRejoin(InspIRCd* Instance) : ModeHandler(Instance, 'J', 1, 0, false, MODETYPE_CHANNEL, false) { }
\r\r ModePair ModeSet(userrec* source, userrec* dest, chanrec* channel, const std::string ¶meter)
\r {
\r if (channel->IsModeSet('J'))
\r return std::make_pair(true, channel->GetModeParameter('J'));
\r else
\r return std::make_pair(false, parameter);
\r }
\r\r bool CheckTimeStamp(time_t theirs, time_t ours, const std::string &their_param, const std::string &our_param, chanrec* channel)
\r {
\r /* When TS is equal, the alphabetically later one wins */
\r return (their_param < our_param);
\r }
\r \r ModeAction OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string ¶meter, bool adding)
\r {
\r if (!adding)
\r {
\r // Taking the mode off, we need to clean up.
\r delaylist* dl;
\r \r if (channel->GetExt("norejoinusers", dl))
\r {
\r DELETE(dl);
\r channel->Shrink("norejoinusers");
\r }
\r \r if (!channel->IsModeSet('J'))
\r {
\r return MODEACTION_DENY;
\r }
\r else
\r {
\r channel->SetMode('J', false);
\r return MODEACTION_ALLOW;
\r }
\r }
\r else if (atoi(parameter.c_str()) > 0)
\r {
\r if (!channel->IsModeSet('J'))
\r {
\r parameter = ConvToStr(atoi(parameter.c_str()));
\r channel->SetModeParam('J', parameter.c_str(), adding);
\r channel->SetMode('J', adding);
\r return MODEACTION_ALLOW;
\r }
\r else
\r {
\r std::string cur_param = channel->GetModeParameter('J');
\r if (cur_param == parameter)
\r {
\r // mode params match, don't change mode
\r return MODEACTION_DENY;
\r }
\r else
\r {
\r // new mode param, replace old with new
\r parameter = ConvToStr(atoi(parameter.c_str()));
\r cur_param = ConvToStr(atoi(cur_param.c_str()));
\r if (parameter != "0")
\r {
\r channel->SetModeParam('J', cur_param.c_str(), false);
\r channel->SetModeParam('J', parameter.c_str(), adding);
\r return MODEACTION_ALLOW;
\r }
\r else
\r {
\r /* Fix to jamie's fix, dont allow +J 0 on the new value! */
\r return MODEACTION_DENY;
\r }
\r }
\r }
\r }
\r else
\r {
\r return MODEACTION_DENY;
\r }
\r }
\r};
\r\rclass ModuleKickNoRejoin : public Module
\r{
\r \r KickRejoin* kr;
\r \rpublic:
\r \r ModuleKickNoRejoin(InspIRCd* Me)
\r : Module(Me)
\r {
\r \r kr = new KickRejoin(ServerInstance);
\r if (!ServerInstance->AddMode(kr, 'J'))
\r throw ModuleException("Could not add new modes!");
\r }
\r\r virtual int OnUserPreJoin(userrec* user, chanrec* chan, const char* cname, std::string &privs)
\r {
\r if (chan)
\r {
\r delaylist* dl;
\r if (chan->GetExt("norejoinusers", dl))
\r {
\r std::vector<userrec*> itemstoremove;
\r \r for (delaylist::iterator iter = dl->begin(); iter != dl->end(); iter++)
\r {
\r if (iter->second > time(NULL))
\r {
\r if (iter->first == user)
\r {
\r user->WriteServ( "495 %s %s :You cannot rejoin this channel yet after being kicked (+J)", user->nick, chan->name);
\r return 1;
\r }
\r }
\r else
\r {
\r // Expired record, remove.
\r itemstoremove.push_back(iter->first);
\r }
\r }
\r \r for (unsigned int i = 0; i < itemstoremove.size(); i++)
\r dl->erase(itemstoremove[i]);
\r \r if (!dl->size())
\r {
\r // Now it's empty..
\r DELETE(dl);
\r chan->Shrink("norejoinusers");
\r }
\r }
\r }
\r return 0;
\r }
\r \r virtual void OnUserKick(userrec* source, userrec* user, chanrec* chan, const std::string &reason, bool &silent)
\r {
\r if (chan->IsModeSet('J') && (source != user))
\r {
\r delaylist* dl;
\r if (!chan->GetExt("norejoinusers", dl))
\r {
\r dl = new delaylist;
\r chan->Extend("norejoinusers", dl);
\r }
\r (*dl)[user] = time(NULL) + strtoint(chan->GetModeParameter('J'));
\r }
\r }
\r \r virtual void OnChannelDelete(chanrec* chan)
\r {
\r delaylist* dl;
\r \r if (chan->GetExt("norejoinusers", dl))
\r {
\r DELETE(dl);
\r chan->Shrink("norejoinusers");
\r }
\r }
\r \r virtual void OnCleanup(int target_type, void* item)
\r {
\r if(target_type == TYPE_CHANNEL)
\r OnChannelDelete((chanrec*)item);
\r }
\r\r virtual void Implements(char* List)
\r {
\r List[I_OnCleanup] = List[I_OnChannelDelete] = List[I_OnUserPreJoin] = List[I_OnUserKick] = 1;
\r }
\r\r virtual ~ModuleKickNoRejoin()
\r {
\r ServerInstance->Modes->DelMode(kr);
\r DELETE(kr);
\r }
\r \r virtual Version GetVersion()
\r {
\r return Version(1, 1, 0, 0, VF_COMMON | VF_VENDOR, API_VERSION);
\r }
\r};
\r\r\rMODULE_INIT(ModuleKickNoRejoin)
\r