Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "module.h"
00015
00016 class CommandNSSuspend : public Command
00017 {
00018 public:
00019 CommandNSSuspend(Module *creator) : Command(creator, "nickserv/suspend", 2, 3)
00020 {
00021 this->SetDesc(_("Suspend a given nick"));
00022 this->SetSyntax(_("\037nickname\037 [+\037expiry\037] \037reason\037"));
00023 }
00024
00025 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00026 {
00027
00028 const Anope::string &nick = params[0];
00029 Anope::string expiry = params[1];
00030 Anope::string reason = params.size() > 2 ? params[2] : "";
00031 time_t expiry_secs = Config->NSSuspendExpire;
00032
00033 if (Anope::ReadOnly)
00034 {
00035 source.Reply(READ_ONLY_MODE);
00036 return;
00037 }
00038
00039 if (expiry[0] != '+')
00040 {
00041 reason = expiry + " " + reason;
00042 reason.trim();
00043 expiry.clear();
00044 }
00045 else
00046 expiry_secs = Anope::DoTime(expiry);
00047
00048 NickAlias *na = NickAlias::Find(nick);
00049 if (!na)
00050 {
00051 source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
00052 return;
00053 }
00054
00055 if (Config->NSSecureAdmins && na->nc->IsServicesOper())
00056 {
00057 source.Reply(_("You may not suspend other Services Operators' nicknames."));
00058 return;
00059 }
00060
00061 NickCore *nc = na->nc;
00062
00063 nc->ExtendMetadata("SUSPENDED");
00064 nc->ExtendMetadata("SECURE");
00065 nc->Shrink("KILLPROTECT");
00066 nc->Shrink("KILL_QUICK");
00067 nc->Shrink("KILL_IMMED");
00068
00069 nc->ExtendMetadata("suspend:by", source.GetNick());
00070 if (!reason.empty())
00071 nc->ExtendMetadata("suspend:reason", reason);
00072 if (expiry_secs > 0)
00073 nc->ExtendMetadata("suspend:expire", stringify(Anope::CurTime + expiry_secs));
00074
00075
00076 for (unsigned i = 0; i < nc->aliases->size(); ++i)
00077 {
00078 NickAlias *na2 = nc->aliases->at(i);
00079
00080 if (na2 && *na2->nc == *na->nc)
00081 {
00082 na2->last_quit = reason;
00083
00084 User *u2 = User::Find(na2->nick);
00085 if (u2)
00086 {
00087 u2->Logout();
00088 u2->Collide(na2);
00089 }
00090 }
00091 }
00092
00093 Log(LOG_ADMIN, source, this) << "for " << nick << " (" << (!reason.empty() ? reason : "No reason") << "), expires in " << (expiry_secs ? Anope::strftime(Anope::CurTime + expiry_secs) : "never");
00094 source.Reply(_("Nick %s is now suspended."), nick.c_str());
00095
00096 FOREACH_MOD(I_OnNickSuspended, OnNickSuspend(na));
00097
00098 return;
00099 }
00100
00101 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
00102 {
00103 this->SendSyntax(source);
00104 source.Reply(" ");
00105 source.Reply(_("Suspends a registered nickname, which prevents it from being used\n"
00106 "while keeping all the data for that nick. If an expiry is given\n"
00107 "the nick will be unsuspended after that period of time, else the\n"
00108 "default expiry from the configuration is used."));
00109 return true;
00110 }
00111 };
00112
00113 class CommandNSUnSuspend : public Command
00114 {
00115 public:
00116 CommandNSUnSuspend(Module *creator) : Command(creator, "nickserv/unsuspend", 1, 1)
00117 {
00118 this->SetDesc(_("Unsuspend a given nick"));
00119 this->SetSyntax(_("\037nickname\037"));
00120 }
00121
00122 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
00123 {
00124 const Anope::string &nick = params[0];
00125
00126 if (Anope::ReadOnly)
00127 {
00128 source.Reply(READ_ONLY_MODE);
00129 return;
00130 }
00131
00132 NickAlias *na = NickAlias::Find(nick);
00133 if (!na)
00134 {
00135 source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
00136 return;
00137 }
00138
00139 if (!na->nc->HasExt("SUSPENDED"))
00140 {
00141 source.Reply(_("Nick %s is not suspended."), na->nick.c_str());
00142 return;
00143 }
00144
00145 na->nc->Shrink("SUSPENDED");
00146 na->nc->Shrink("suspend:expire");
00147 na->nc->Shrink("suspend:by");
00148 na->nc->Shrink("suspend:reason");
00149
00150 Log(LOG_ADMIN, source, this) << "for " << na->nick;
00151 source.Reply(_("Nick %s is now released."), nick.c_str());
00152
00153 FOREACH_MOD(I_OnNickUnsuspended, OnNickUnsuspended(na));
00154
00155 return;
00156 }
00157
00158 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
00159 {
00160 this->SendSyntax(source);
00161 source.Reply(" ");
00162 source.Reply(_("Unsuspends a nickname which allows it to be used again."));
00163 return true;
00164 }
00165 };
00166
00167 class NSSuspend : public Module
00168 {
00169 CommandNSSuspend commandnssuspend;
00170 CommandNSUnSuspend commandnsunsuspend;
00171
00172 public:
00173 NSSuspend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE),
00174 commandnssuspend(this), commandnsunsuspend(this)
00175 {
00176 this->SetAuthor("Anope");
00177
00178 Implementation i[] = { I_OnPreNickExpire };
00179 ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
00180 }
00181
00182 void OnPreNickExpire(NickAlias *na, bool &expire) anope_override
00183 {
00184 if (!na->nc->HasExt("SUSPENDED"))
00185 return;
00186
00187 expire = false;
00188
00189 Anope::string *str = na->nc->GetExt<ExtensibleItemClass<Anope::string> *>("suspend:expire");
00190 if (str == NULL)
00191 return;
00192
00193 try
00194 {
00195 time_t when = convertTo<time_t>(*str);
00196 if (when < Anope::CurTime)
00197 {
00198 na->last_seen = Anope::CurTime;
00199 na->nc->Shrink("SUSPENDED");
00200 na->nc->Shrink("suspend:expire");
00201 na->nc->Shrink("suspend:by");
00202 na->nc->Shrink("suspend:reason");
00203
00204 Log(LOG_NORMAL, "expire", NickServ) << "Expiring suspend for " << na->nick;
00205 }
00206 }
00207 catch (const ConvertException &) { }
00208 }
00209 };
00210
00211 MODULE_INIT(NSSuspend)