summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2012-10-31 12:37:43 -0400
committerAdam <Adam@anope.org>2012-10-31 12:37:43 -0400
commit3a10fca75f660e90983b3a01d33917c17a0f4fa4 (patch)
tree6b5a41819a3f1602d381d01d70f773bb39cd4ac2
parenta39947cd3c6c76cb708de7d328aabde62e39be0b (diff)
Fix ns_ghost and ns_recover, add nicksev:restoreonghost
-rw-r--r--data/nickserv.example.conf8
-rw-r--r--include/config.h2
-rw-r--r--modules/commands/ns_ghost.cpp65
-rw-r--r--modules/commands/ns_recover.cpp15
-rw-r--r--src/config.cpp1
5 files changed, 65 insertions, 26 deletions
diff --git a/data/nickserv.example.conf b/data/nickserv.example.conf
index 20a9f8163..c6a07354f 100644
--- a/data/nickserv.example.conf
+++ b/data/nickserv.example.conf
@@ -270,6 +270,14 @@ nickserv
* This directive is optional.
*/
#modesonid = "+R"
+
+ /*
+ * If set, Services will svsnick and svsjoin users who use the ghost
+ * command to the nick and channels of the ghosted user.
+ *
+ * This directive is opional.
+ */
+ restoreonghost = yes
}
/*
diff --git a/include/config.h b/include/config.h
index 0f2e127c2..dd00d2666 100644
--- a/include/config.h
+++ b/include/config.h
@@ -570,6 +570,8 @@ class CoreExport ServerConfig
time_t NSKill;
/* Modes set on a user when they identify */
Anope::string NSModesOnID;
+ /* Restore nick/channels on ghost */
+ bool NSRestoreOnGhost;
/* Core ChanServ modules */
Anope::string ChanCoreModules;
diff --git a/modules/commands/ns_ghost.cpp b/modules/commands/ns_ghost.cpp
index 53082e0a4..dfc990cab 100644
--- a/modules/commands/ns_ghost.cpp
+++ b/modules/commands/ns_ghost.cpp
@@ -17,35 +17,64 @@ class NSGhostRequest : public IdentifyRequest
{
CommandSource source;
Command *cmd;
+ dynamic_reference<User> u;
public:
- NSGhostRequest(Module *o, CommandSource &src, Command *c, const Anope::string &user, const Anope::string &pass) : IdentifyRequest(o, user, pass), source(src), cmd(c) { }
+ NSGhostRequest(Module *o, CommandSource &src, Command *c, User *user, const Anope::string &pass) : IdentifyRequest(o, user->nick, pass), source(src), cmd(c), u(user) { }
void OnSuccess() anope_override
{
- if (!source.GetUser() || !source.service)
+ if (!source.GetUser() || !source.service || !u)
return;
- User *user = source.GetUser();
- if (!user->IsIdentified())
- source.Reply(_("You may not ghost an unidentified user, use RECOVER instead."));
- else
+ Anope::string nick = u->nick;
+ NickCore *acc = u->Account();
+ std::vector<std::pair<Anope::string, ChannelStatus> > channels;
+ for (UChannelList::iterator it = u->chans.begin(), it_end = u->chans.end(); it != it_end; ++it)
+ channels.push_back(std::make_pair((*it)->chan->name, *(*it)->Status));
+
+ Log(LOG_COMMAND, source, cmd) << "for " << GetAccount();
+ Anope::string buf = "GHOST command used by " + source.GetNick();
+ u->Kill(source.service->nick, buf);
+ source.Reply(_("Ghost with your nick has been killed."));
+
+ if (Config->NSRestoreOnGhost)
{
- Log(LOG_COMMAND, source, cmd) << "for " << GetAccount();
- Anope::string buf = "GHOST command used by " + source.GetNick();
- user->Kill(source.service->nick, buf);
- source.Reply(_("Ghost with your nick has been killed."));
+ if (acc != NULL)
+ source.GetUser()->Login(acc);
+
+ ircdproto->SendForceNickChange(source.GetUser(), nick, Anope::CurTime);
+
+ for (unsigned i = 0; i < channels.size(); ++i)
+ {
+ ircdproto->SendSVSJoin(source.service, source.GetUser()->GetUID(), channels[i].first, "");
+
+ Channel *c = findchan(channels[i].first);
+ if (c)
+ {
+ for (size_t j = CMODE_BEGIN + 1; j < CMODE_END; ++j)
+ if (channels[i].second.HasFlag(static_cast<ChannelModeName>(j)))
+ c->SetMode(c->ci->WhoSends(), ModeManager::FindChannelModeByName(static_cast<ChannelModeName>(j)), source.GetUser()->GetUID());
+ }
+ }
}
}
void OnFail() anope_override
{
- source.Reply(ACCESS_DENIED);
- if (!GetPassword().empty())
+ if (!u)
+ ;
+ else if (!findnick(GetAccount()))
+ source.Reply(NICK_X_NOT_REGISTERED, GetAccount().c_str());
+ else
{
- Log(LOG_COMMAND, source, cmd) << "with an invalid password for " << GetAccount();
- if (source.GetUser())
- bad_password(source.GetUser());
+ source.Reply(ACCESS_DENIED);
+ if (!GetPassword().empty())
+ {
+ Log(LOG_COMMAND, source, cmd) << "with an invalid password for " << GetAccount();
+ if (source.GetUser())
+ bad_password(source.GetUser());
+ }
}
}
};
@@ -72,6 +101,8 @@ class CommandNSGhost : public Command
source.Reply(NICK_X_NOT_IN_USE, nick.c_str());
else if (user->server == Me)
source.Reply(_("\2%s\2 is a services enforcer."), user->nick.c_str());
+ else if (!user->IsIdentified())
+ source.Reply(_("You may not ghost an unidentified user, use RECOVER instead."));
else if (!na)
source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
else if (na->nc->HasFlag(NI_SUSPENDED))
@@ -90,13 +121,13 @@ class CommandNSGhost : public Command
if (ok == false && !pass.empty())
{
- NSGhostRequest *req = new NSGhostRequest(owner, source, this, na->nc->display, pass);
+ NSGhostRequest *req = new NSGhostRequest(owner, source, this, user, pass);
FOREACH_MOD(I_OnCheckAuthentication, OnCheckAuthentication(source.GetUser(), req));
req->Dispatch();
}
else
{
- NSGhostRequest req(owner, source, this, na->nc->display, pass);
+ NSGhostRequest req(owner, source, this, user, pass);
if (ok)
req.OnSuccess();
diff --git a/modules/commands/ns_recover.cpp b/modules/commands/ns_recover.cpp
index 648bbf032..63d503553 100644
--- a/modules/commands/ns_recover.cpp
+++ b/modules/commands/ns_recover.cpp
@@ -19,17 +19,16 @@ class NSRecoverRequest : public IdentifyRequest
CommandSource source;
Command *cmd;
dynamic_reference<NickAlias> na;
+ dynamic_reference<User> u;
public:
- NSRecoverRequest(Module *m, CommandSource &src, Command *c, NickAlias *n, const Anope::string &pass) : IdentifyRequest(m, n->nc->display, pass), source(src), cmd(c), na(n) { }
+ NSRecoverRequest(Module *m, CommandSource &src, Command *c, User *user, NickAlias *n, const Anope::string &pass) : IdentifyRequest(m, n->nc->display, pass), source(src), cmd(c), na(n), u(user) { }
void OnSuccess() anope_override
{
- if (!source.GetUser() || !na)
+ if (!na || !u)
return;
- User *u = source.GetUser();
-
u->SendMessage(source.service, FORCENICKCHANGE_NOW);
if (u->Account() == na->nc)
@@ -47,11 +46,9 @@ class NSRecoverRequest : public IdentifyRequest
void OnFail() anope_override
{
- if (!source.GetUser())
+ if (!na || !u)
return;
- User *u = source.GetUser();
-
source.Reply(ACCESS_DENIED);
if (!GetPassword().empty())
{
@@ -101,13 +98,13 @@ class CommandNSRecover : public Command
if (ok == false && !pass.empty())
{
- NSRecoverRequest *req = new NSRecoverRequest(owner, source, this, na, pass);
+ NSRecoverRequest *req = new NSRecoverRequest(owner, source, this, u2, na, pass);
FOREACH_MOD(I_OnCheckAuthentication, OnCheckAuthentication(source.GetUser(), req));
req->Dispatch();
}
else
{
- NSRecoverRequest req(owner, source, this, na, pass);
+ NSRecoverRequest req(owner, source, this, u2, na, pass);
if (ok)
req.OnSuccess();
diff --git a/src/config.cpp b/src/config.cpp
index 735b4a4e7..002e2917d 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -1284,6 +1284,7 @@ ConfigItems::ConfigItems(ServerConfig *conf)
{"nickserv", "killquick", "20", new ValueContainerTime(&conf->NSKillQuick), DT_TIME, NoValidation},
{"nickserv", "kill", "60", new ValueContainerTime(&conf->NSKill), DT_TIME, NoValidation},
{"nickserv", "modesonid", "", new ValueContainerString(&conf->NSModesOnID), DT_STRING, NoValidation},
+ {"nickserv", "restoreonghost", "yes", new ValueContainerBool(&conf->NSRestoreOnGhost), DT_BOOLEAN, NoValidation},
{"mail", "usemail", "no", new ValueContainerBool(&conf->UseMail), DT_BOOLEAN, ValidateEmailReg},
{"mail", "sendmailpath", "", new ValueContainerString(&conf->SendMailPath), DT_STRING, ValidateMail},
{"mail", "sendfrom", "", new ValueContainerString(&conf->SendFrom), DT_STRING, ValidateMail},