00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "inspircd.h"
00015
00016
00017
00018 inline int strtoint(const std::string &str)
00019 {
00020 std::istringstream ss(str);
00021 int result;
00022 ss >> result;
00023 return result;
00024 }
00025
00026 typedef std::map<User*, time_t> delaylist;
00027
00030 class KickRejoin : public ModeHandler
00031 {
00032 public:
00033 KickRejoin(InspIRCd* Instance) : ModeHandler(Instance, 'J', 1, 0, false, MODETYPE_CHANNEL, false) { }
00034
00035 ModePair ModeSet(User* source, User* dest, Channel* channel, const std::string ¶meter)
00036 {
00037 if (channel->IsModeSet('J'))
00038 return std::make_pair(true, channel->GetModeParameter('J'));
00039 else
00040 return std::make_pair(false, parameter);
00041 }
00042
00043 bool CheckTimeStamp(time_t theirs, time_t ours, const std::string &their_param, const std::string &our_param, Channel* channel)
00044 {
00045
00046 return (their_param < our_param);
00047 }
00048
00049 ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding, bool)
00050 {
00051 if (!adding)
00052 {
00053
00054 delaylist* dl;
00055
00056 if (channel->GetExt("norejoinusers", dl))
00057 {
00058 delete dl;
00059 channel->Shrink("norejoinusers");
00060 }
00061
00062 if (!channel->IsModeSet('J'))
00063 {
00064 return MODEACTION_DENY;
00065 }
00066 else
00067 {
00068 channel->SetMode('J', false);
00069 return MODEACTION_ALLOW;
00070 }
00071 }
00072 else if (atoi(parameter.c_str()) > 0)
00073 {
00074 if (!channel->IsModeSet('J'))
00075 {
00076 parameter = ConvToStr(atoi(parameter.c_str()));
00077 channel->SetModeParam('J', parameter.c_str(), adding);
00078 channel->SetMode('J', adding);
00079 return MODEACTION_ALLOW;
00080 }
00081 else
00082 {
00083 std::string cur_param = channel->GetModeParameter('J');
00084 if (cur_param == parameter)
00085 {
00086
00087 return MODEACTION_DENY;
00088 }
00089 else
00090 {
00091
00092 parameter = ConvToStr(atoi(parameter.c_str()));
00093 cur_param = ConvToStr(atoi(cur_param.c_str()));
00094 if (parameter != "0")
00095 {
00096 channel->SetModeParam('J', cur_param.c_str(), false);
00097 channel->SetModeParam('J', parameter.c_str(), adding);
00098 return MODEACTION_ALLOW;
00099 }
00100 else
00101 {
00102
00103 return MODEACTION_DENY;
00104 }
00105 }
00106 }
00107 }
00108 else
00109 {
00110 return MODEACTION_DENY;
00111 }
00112 }
00113 };
00114
00115 class ModuleKickNoRejoin : public Module
00116 {
00117
00118 KickRejoin* kr;
00119
00120 public:
00121
00122 ModuleKickNoRejoin(InspIRCd* Me)
00123 : Module(Me)
00124 {
00125
00126 kr = new KickRejoin(ServerInstance);
00127 if (!ServerInstance->Modes->AddMode(kr))
00128 throw ModuleException("Could not add new modes!");
00129 Implementation eventlist[] = { I_OnCleanup, I_OnChannelDelete, I_OnUserPreJoin, I_OnUserKick };
00130 ServerInstance->Modules->Attach(eventlist, this, 4);
00131 }
00132
00133 virtual int OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven)
00134 {
00135 if (chan)
00136 {
00137 delaylist* dl;
00138 if (chan->GetExt("norejoinusers", dl))
00139 {
00140 std::vector<User*> itemstoremove;
00141
00142 for (delaylist::iterator iter = dl->begin(); iter != dl->end(); iter++)
00143 {
00144 if (iter->second > ServerInstance->Time())
00145 {
00146 if (iter->first == user)
00147 {
00148 user->WriteNumeric(ERR_DELAYREJOIN, "%s %s :You must wait %s seconds after being kicked to rejoin (+J)", user->nick.c_str(), chan->name.c_str(), chan->GetModeParameter('J').c_str());
00149 return 1;
00150 }
00151 }
00152 else
00153 {
00154
00155 itemstoremove.push_back(iter->first);
00156 }
00157 }
00158
00159 for (unsigned int i = 0; i < itemstoremove.size(); i++)
00160 dl->erase(itemstoremove[i]);
00161
00162 if (!dl->size())
00163 {
00164
00165 delete dl;
00166 chan->Shrink("norejoinusers");
00167 }
00168 }
00169 }
00170 return 0;
00171 }
00172
00173 virtual void OnUserKick(User* source, User* user, Channel* chan, const std::string &reason, bool &silent)
00174 {
00175 if (chan->IsModeSet('J') && (source != user))
00176 {
00177 delaylist* dl;
00178 if (!chan->GetExt("norejoinusers", dl))
00179 {
00180 dl = new delaylist;
00181 chan->Extend("norejoinusers", dl);
00182 }
00183 (*dl)[user] = ServerInstance->Time() + strtoint(chan->GetModeParameter('J'));
00184 }
00185 }
00186
00187 virtual void OnChannelDelete(Channel* chan)
00188 {
00189 delaylist* dl;
00190
00191 if (chan->GetExt("norejoinusers", dl))
00192 {
00193 delete dl;
00194 chan->Shrink("norejoinusers");
00195 }
00196 }
00197
00198 virtual void OnCleanup(int target_type, void* item)
00199 {
00200 if(target_type == TYPE_CHANNEL)
00201 OnChannelDelete((Channel*)item);
00202 }
00203
00204
00205 virtual ~ModuleKickNoRejoin()
00206 {
00207 ServerInstance->Modes->DelMode(kr);
00208 delete kr;
00209 }
00210
00211 virtual Version GetVersion()
00212 {
00213 return Version("$Id: m_kicknorejoin.cpp 10783 2008-11-01 23:02:23Z w00t $", VF_COMMON | VF_VENDOR, API_VERSION);
00214 }
00215 };
00216
00217
00218 MODULE_INIT(ModuleKickNoRejoin)