00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "inspircd.h"
00015 #include <algorithm>
00016 #include "users.h"
00017 #include "channels.h"
00018 #include "modules.h"
00019 #include "configreader.h"
00020
00021
00022
00025 class SVSHold : public classbase
00026 {
00027 public:
00028 std::string nickname;
00029 std::string set_by;
00030 time_t set_on;
00031 long length;
00032 std::string reason;
00033
00034 SVSHold()
00035 {
00036 }
00037
00038 SVSHold(const std::string &nn, const std::string &sb, const time_t so, const long ln, const std::string &rs) : nickname(nn), set_by(sb), set_on(so), length(ln), reason(rs)
00039 {
00040 }
00041 };
00042
00043
00044 bool SVSHoldComp(const SVSHold* ban1, const SVSHold* ban2);
00045
00046 typedef std::vector<SVSHold*> SVSHoldlist;
00047 typedef std::map<irc::string, SVSHold*> SVSHoldMap;
00048
00049
00050 SVSHoldlist SVSHolds;
00051 SVSHoldMap HoldMap;
00052
00055 class cmd_svshold : public command_t
00056 {
00057 public:
00058 cmd_svshold(InspIRCd* Me) : command_t(Me, "SVSHOLD", 'o', 1)
00059 {
00060 this->source = "m_svshold.so";
00061 this->syntax = "<nickname> [<duration> :<reason>]";
00062 }
00063
00064 CmdResult Handle(const char** parameters, int pcnt, userrec *user)
00065 {
00066
00067
00068
00069 if (!ServerInstance->ULine(user->server))
00070 {
00071
00072 return CMD_FAILURE;
00073 }
00074
00075 if (pcnt == 1)
00076 {
00077 SVSHoldMap::iterator n = HoldMap.find(parameters[0]);
00078 if (n != HoldMap.end())
00079 {
00080
00081 for (SVSHoldlist::iterator iter = SVSHolds.begin(); iter != SVSHolds.end(); iter++)
00082 {
00083 if (parameters[0] == assign((*iter)->nickname))
00084 {
00085 unsigned long remaining = 0;
00086 if ((*iter)->length)
00087 {
00088 remaining = ((*iter)->set_on + (*iter)->length) - ServerInstance->Time();
00089 user->WriteServ( "386 %s %s :Removed SVSHOLD with %lu seconds left before expiry (%s)", user->nick, (*iter)->nickname.c_str(), remaining, (*iter)->reason.c_str());
00090 }
00091 else
00092 {
00093 user->WriteServ( "386 %s %s :Removed permanent SVSHOLD (%s)", user->nick, (*iter)->nickname.c_str(), (*iter)->reason.c_str());
00094 }
00095 SVSHolds.erase(iter);
00096 break;
00097 }
00098 }
00099
00100 HoldMap.erase(n);
00101 delete n->second;
00102 }
00103 }
00104 else if (pcnt >= 2)
00105 {
00106
00107 if (ServerInstance->IsNick(parameters[0]))
00108 {
00109
00110
00111
00112
00113
00114 if (HoldMap.find(parameters[0]) != HoldMap.end())
00115 {
00116 user->WriteServ( "385 %s %s :SVSHOLD already exists", user->nick, parameters[0]);
00117 return CMD_FAILURE;
00118 }
00119
00120 long length = ServerInstance->Duration(parameters[1]);
00121 std::string reason = (pcnt > 2) ? parameters[2] : "No reason supplied";
00122
00123 SVSHold* S = new SVSHold(parameters[0], user->nick, ServerInstance->Time(), length, reason);
00124 SVSHolds.push_back(S);
00125 HoldMap[parameters[0]] = S;
00126
00127 std::sort(SVSHolds.begin(), SVSHolds.end(), SVSHoldComp);
00128
00129 if(length > 0)
00130 {
00131 user->WriteServ( "385 %s %s :Added %lu second SVSHOLD (%s)", user->nick, parameters[0], length, reason.c_str());
00132 }
00133 else
00134 {
00135 user->WriteServ( "385 %s %s :Added permanent SVSHOLD on %s (%s)", user->nick, parameters[0], parameters[0], reason.c_str());
00136 }
00137 }
00138 else
00139 {
00140
00141 return CMD_FAILURE;
00142 }
00143 }
00144
00145 return CMD_SUCCESS;
00146 }
00147 };
00148
00149 bool SVSHoldComp(const SVSHold* ban1, const SVSHold* ban2)
00150 {
00151 return ((ban1->set_on + ban1->length) < (ban2->set_on + ban2->length));
00152 }
00153
00154 class ModuleSVSHold : public Module
00155 {
00156 cmd_svshold *mycommand;
00157
00158
00159 public:
00160 ModuleSVSHold(InspIRCd* Me) : Module(Me)
00161 {
00162 mycommand = new cmd_svshold(Me);
00163 ServerInstance->AddCommand(mycommand);
00164 }
00165
00166 void Implements(char* List)
00167 {
00168 List[I_OnUserPreNick] = List[I_OnSyncOtherMetaData] = List[I_OnDecodeMetaData] = List[I_OnStats] = 1;
00169 }
00170
00171 virtual int OnStats(char symbol, userrec* user, string_list &results)
00172 {
00173 ExpireBans();
00174
00175 if(symbol == 'S')
00176 {
00177 for(SVSHoldlist::iterator iter = SVSHolds.begin(); iter != SVSHolds.end(); iter++)
00178 {
00179 unsigned long remaining = ((*iter)->set_on + (*iter)->length) - ServerInstance->Time();
00180 results.push_back(std::string(ServerInstance->Config->ServerName)+" 210 "+user->nick+" "+(*iter)->nickname.c_str()+" "+(*iter)->set_by+" "+ConvToStr((*iter)->set_on)+" "+ConvToStr((*iter)->length)+" "+ConvToStr(remaining)+" :"+(*iter)->reason);
00181 }
00182 }
00183
00184 return 0;
00185 }
00186
00187 virtual int OnUserPreNick(userrec *user, const std::string &newnick)
00188 {
00189 ExpireBans();
00190
00191
00192 SVSHoldMap::iterator n = HoldMap.find(assign(newnick));
00193 if (n != HoldMap.end())
00194 {
00195 user->WriteServ( "432 %s %s :Reserved nickname: %s", user->nick, newnick.c_str(), n->second->reason.c_str());
00196 return 1;
00197 }
00198 return 0;
00199 }
00200
00201 virtual void OnSyncOtherMetaData(Module* proto, void* opaque, bool displayable)
00202 {
00203 for(SVSHoldMap::iterator iter = HoldMap.begin(); iter != HoldMap.end(); iter++)
00204 {
00205 proto->ProtoSendMetaData(opaque, TYPE_OTHER, NULL, "SVSHold", EncodeSVSHold(iter->second));
00206 }
00207 }
00208
00209 virtual void OnDecodeMetaData(int target_type, void* target, const std::string &extname, const std::string &extdata)
00210 {
00211 if((target_type == TYPE_OTHER) && (extname == "SVSHold"))
00212 {
00213 SVSHold* S = DecodeSVSHold(extdata);
00214 if (HoldMap.find(assign(S->nickname)) == HoldMap.end())
00215 {
00216 SVSHolds.push_back(S);
00217 HoldMap[assign(S->nickname)] = S;
00218 std::sort(SVSHolds.begin(), SVSHolds.end(), SVSHoldComp);
00219 }
00220 else
00221 {
00222 delete S;
00223 }
00224 }
00225 }
00226
00227 virtual ~ModuleSVSHold()
00228 {
00229 }
00230
00231 virtual Version GetVersion()
00232 {
00233 return Version(1, 1, 0, 1, VF_COMMON | VF_VENDOR, API_VERSION);
00234 }
00235
00236 std::string EncodeSVSHold(const SVSHold* ban)
00237 {
00238 std::ostringstream stream;
00239 stream << ban->nickname << " " << ban->set_by << " " << ban->set_on << " " << ban->length << " :" << ban->reason;
00240 return stream.str();
00241 }
00242
00243 SVSHold* DecodeSVSHold(const std::string &data)
00244 {
00245 SVSHold* res = new SVSHold();
00246 int set_on;
00247 irc::tokenstream tokens(data);
00248 tokens.GetToken(res->nickname);
00249 tokens.GetToken(res->set_by);
00250 tokens.GetToken(set_on);
00251 res->set_on = set_on;
00252 tokens.GetToken(res->length);
00253 tokens.GetToken(res->reason);
00254 return res;
00255 }
00256
00257 void ExpireBans()
00258 {
00259 SVSHoldlist::iterator iter,safeiter;
00260 for (iter = SVSHolds.begin(); iter != SVSHolds.end(); iter++)
00261 {
00262
00263 if ((*iter)->length != 0)
00264 {
00265 if ((*iter)->set_on + (*iter)->length <= ServerInstance->Time())
00266 {
00267 ServerInstance->Log(DEBUG, "m_svshold.so: hold on %s expired, removing...", (*iter)->nickname.c_str());
00268 HoldMap.erase(assign((*iter)->nickname));
00269 delete *iter;
00270 safeiter = iter;
00271 --iter;
00272 SVSHolds.erase(safeiter);
00273 }
00274 }
00275 }
00276 }
00277 };
00278
00279 MODULE_INIT(ModuleSVSHold)