summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/example.conf12
-rw-r--r--data/mysql/tables.sql15
-rw-r--r--docs/Changes8
-rw-r--r--docs/Changes.conf11
-rw-r--r--include/account.h23
-rw-r--r--include/anope.h2
-rw-r--r--include/config.h6
-rw-r--r--include/extern.h4
-rw-r--r--include/language.h1
-rw-r--r--include/mail.h1
-rw-r--r--include/modules.h26
-rw-r--r--include/services.h2
-rw-r--r--modules/core/cs_register.cpp8
-rw-r--r--modules/core/db_plain.cpp43
-rw-r--r--modules/core/ns_drop.cpp25
-rw-r--r--modules/core/ns_getpass.cpp11
-rw-r--r--modules/core/ns_group.cpp9
-rw-r--r--modules/core/ns_identify.cpp20
-rw-r--r--modules/core/ns_info.cpp33
-rw-r--r--modules/core/ns_list.cpp92
-rw-r--r--modules/core/ns_register.cpp315
-rw-r--r--modules/core/ns_resetpass.cpp51
-rw-r--r--modules/core/ns_set_email.cpp80
-rw-r--r--modules/extra/db_mysql.cpp31
-rw-r--r--modules/extra/m_ldap.cpp6
-rw-r--r--modules/extra/m_mysql.cpp2
-rw-r--r--modules/extra/ns_identify_ldap.cpp2
-rw-r--r--modules/protocol/bahamut.cpp3
-rw-r--r--modules/protocol/inspircd11.cpp3
-rw-r--r--modules/protocol/inspircd12.cpp2
-rw-r--r--modules/protocol/inspircd20.cpp2
-rw-r--r--modules/protocol/plexus.cpp2
-rw-r--r--modules/protocol/unreal32.cpp6
-rw-r--r--src/commands.cpp2
-rw-r--r--src/config.cpp5
-rw-r--r--src/mail.cpp21
-rw-r--r--src/main.cpp1
-rw-r--r--src/misc.cpp43
-rw-r--r--src/nickalias.cpp19
-rw-r--r--src/nickserv.cpp32
-rw-r--r--src/users.cpp3
41 files changed, 365 insertions, 618 deletions
diff --git a/data/example.conf b/data/example.conf
index 243dcb725..c797a2f84 100644
--- a/data/example.conf
+++ b/data/example.conf
@@ -940,6 +940,12 @@ nickserv
forceemail = yes
/*
+ * Require users who change their email address to confirm they
+ * own it.
+ */
+ confirmemailchanges = no
+
+ /*
* Require an e-mail to be sent to the user before they can register their nick.
*/
#emailregistration = yes
@@ -1018,12 +1024,12 @@ nickserv
#forbidexpire = 90d
/*
- * The length of time a user gets to enter the confirmation code which has been e-mailed
- * to them before the nick will be released for general use again.
+ * The length of time a user using an unconfirmed account has
+ * before the account will be released for general use again.
*
* This directive is only required if the e-mail registration option is enabled.
*/
- #preregexpire = 1d
+ #unconfirmedexpire = 1d
/*
* The maximum number of nicks allowed in a group.
diff --git a/data/mysql/tables.sql b/data/mysql/tables.sql
index 2cda6384e..b3cf06a00 100644
--- a/data/mysql/tables.sql
+++ b/data/mysql/tables.sql
@@ -291,21 +291,6 @@ CREATE TABLE IF NOT EXISTS `anope_ns_core_metadata` (
-- --------------------------------------------------------
--
--- Table structure for table `anope_ns_request`
---
-
-CREATE TABLE IF NOT EXISTS `anope_ns_request` (
- `nick` varchar(255) NOT NULL DEFAULT '',
- `passcode` text NOT NULL,
- `password` text NOT NULL,
- `email` text NOT NULL,
- `requested` int(10) unsigned NOT NULL DEFAULT '0',
- PRIMARY KEY (`nick`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
--- --------------------------------------------------------
-
---
-- Table structure for table `anope_os_akills`
--
diff --git a/docs/Changes b/docs/Changes
index d23343937..9125a6258 100644
--- a/docs/Changes
+++ b/docs/Changes
@@ -2,11 +2,17 @@ Anope Version 1.9.4
--------------------
A Automatically set channel founder to the user with the highest access if there is no successor
A /chanserv clone command to copy settings from one channel to another.
+A /chanserv mode command
A Ability for users to delete their own access in channels
-A Ability for users with registrations pending to drop their registrations with /nickserv drop
A Added support for Plexus 3
A Readded in support for /cs op/deop/etc to op/deop you in all channels
A Added support for ngIRCd
+A Added LDAP support
+A Added live SQL support
+A Added support for learning tracking/storing/locking all modes at runtime
+A Added m_alias
+A Added support for XMLRPC queries
+A Added /botserv set msg
F Changed the GHOST command to not allow ghosting unidentified users if the RECOVER command exists
F Some failed logic in /operserv exception that prevents proper exceptions from being added
F Fixed the anope_os_sxlines MySQL table and code to work after restarting
diff --git a/docs/Changes.conf b/docs/Changes.conf
index c8c9c9719..70e97bb46 100644
--- a/docs/Changes.conf
+++ b/docs/Changes.conf
@@ -1,5 +1,6 @@
Anope Version 1.9.4
-------------------
+** ADDED CONFIGURATION DIRECTIVES **
memoserv:modules added ms_ignore
chanserv:modules added cs_clone and cs_mode
nickserv:suspendexpire and nickserv:forbidexpire added
@@ -7,10 +8,16 @@ chanserv:suspendexpire and chanserv:forbidexpire added
module added cs_entrymsg
nickserv:modules added ns_ajoin
options:nomlock added
+log:target added globops
+nickserv:confirmemailchanges added
+
+** MODIFIED CONFIGURATION DIRECTIVES **
+operserv:notifications removed osglobal, osmode, oskick, osakill, ossnline, ossqline, osszline, osnoop, osjupe, getpass, setpass, forbid, drop
+renamed nickserv:preregexpire to nickserv:unconfirmedexpire
+
+** DELETED CONFIGURATION DIRECTIVES **
opertype:commands removed operserv/umode
operserv:modules removed os_umode
-operserv:notifications removed osglobal, osmode, oskick, osakill, ossnline, ossqline, osszline, osnoop, osjupe, getpass, setpass, forbid, drop
-log:target added globops
Anope Version 1.9.3
------------------
diff --git a/include/account.h b/include/account.h
index b4a792caf..8615083b9 100644
--- a/include/account.h
+++ b/include/account.h
@@ -5,15 +5,12 @@
class NickAlias;
class NickCore;
-class NickRequest;
typedef unordered_map_namespace::unordered_map<Anope::string, NickAlias *, ci::hash, std::equal_to<ci::string> > nickalias_map;
typedef unordered_map_namespace::unordered_map<Anope::string, NickCore *, ci::hash, std::equal_to<ci::string> > nickcore_map;
-typedef unordered_map_namespace::unordered_map<Anope::string, NickRequest *, ci::hash, std::equal_to<ci::string> > nickrequest_map;
extern CoreExport nickalias_map NickAliasList;
extern CoreExport nickcore_map NickCoreList;
-extern CoreExport nickrequest_map NickRequestList;
/* NickServ nickname structures. */
@@ -85,6 +82,9 @@ enum NickCoreFlag
NI_AUTOOP,
/* This nickcore is forbidden, which means the nickalias for it is aswell */
NI_FORBIDDEN,
+ /* If set means the nick core does not have their email addrses confirmed.
+ */
+ NI_UNCONFIRMED,
NI_END
};
@@ -92,22 +92,7 @@ enum NickCoreFlag
const Anope::string NickCoreFlagStrings[] = {
"BEGIN", "KILLPROTECT", "SECURE", "MSG", "MEMO_HARDMAX", "MEMO_SIGNON", "MEMO_RECEIVE",
"PRIVATE", "HIDE_EMAIL", "HIDE_MASK", "HIDE_QUIT", "KILL_QUICK", "KILL_IMMED",
- "MEMO_MAIL", "HIDE_STATUS", "SUSPENDED", "AUTOOP", "FORBIDDEN", ""
-};
-
-class CoreExport NickRequest : public Extensible
-{
- public:
- NickRequest(const Anope::string &nickname);
-
- ~NickRequest();
-
- Anope::string nick;
- Anope::string passcode;
- Anope::string password;
- Anope::string email;
- time_t requested;
- time_t lastmail; /* Unsaved */
+ "MEMO_MAIL", "HIDE_STATUS", "SUSPENDED", "AUTOOP", "FORBIDDEN", "UNCONFIRMED", ""
};
class NickCore;
diff --git a/include/anope.h b/include/anope.h
index ec1d083a5..8153c976f 100644
--- a/include/anope.h
+++ b/include/anope.h
@@ -336,7 +336,7 @@ namespace Anope
* @param ... any number of parameters
* @return a Anope::string
*/
- extern CoreExport string printf(const char *fmt, ...);
+ extern CoreExport string printf(const Anope::string &fmt, ...);
/** Return the last error, uses errno/GetLastError() to determin this
* @return An error message
diff --git a/include/config.h b/include/config.h
index ef71933ec..f4844ded3 100644
--- a/include/config.h
+++ b/include/config.h
@@ -601,10 +601,12 @@ class CoreExport ServerConfig
time_t NSSuspendExpire;
/* How long before forbidden nicks expire */
time_t NSForbidExpire;
- /* Time before NickRequests expire */
- time_t NSRExpire;
+ /* Time before unconfirmed nicks expire */
+ time_t NSUnconfirmedExpire;
/* Force email when registering */
bool NSForceEmail;
+ /* Force users to validate new email addresses */
+ bool NSConfirmEmailChanges;
/* Max number of nicks in a group */
unsigned NSMaxAliases;
/* Max number of allowed strings on the access list */
diff --git a/include/extern.h b/include/extern.h
index 1e88fbbc7..d670ad331 100644
--- a/include/extern.h
+++ b/include/extern.h
@@ -232,8 +232,6 @@ E size_t strlcpy(char *, const char *, size_t);
#ifndef HAVE_STRLCAT
E size_t strlcat(char *, const char *, size_t);
#endif
-E const char *merge_args(int argc, char **argv);
-E const char *merge_args(int argc, const char **argv);
E time_t dotime(const Anope::string &s);
E Anope::string duration(NickCore *nc, time_t seconds);
@@ -277,7 +275,6 @@ E void SetDefaultMLock(ServerConfig *config);
/**** nickserv.c ****/
-E NickRequest *findrequestnick(const Anope::string &nick);
E void get_aliases_stats(long &count, long &mem);
E void get_core_stats(long &count, long &mem);
E void change_core_display(NickCore *nc);
@@ -287,7 +284,6 @@ E int do_setmodes(User *u);
E void ns_init();
E int validate_user(User *u);
E void expire_nicks();
-E void expire_requests();
E NickAlias *findnick(const Anope::string &nick);
E NickCore *findcore(const Anope::string &nick);
E bool is_on_access(const User *u, const NickCore *nc);
diff --git a/include/language.h b/include/language.h
index c27c99087..5e2cdf9e8 100644
--- a/include/language.h
+++ b/include/language.h
@@ -61,7 +61,6 @@
#define NICK_RECOVERED "User claiming your nick has been killed.\n" \
"\002%R%s RELEASE %s\002 to get it back before %s timeout."
#define NICK_REQUESTED "This nick has already been requested, please check your e-mail address for the pass code"
-#define NICK_IS_PREREG "This nick is awaiting an e-mail verification code before completing registration."
#define NICK_CONFIRM_INVALID "Invalid passcode has been entered, please check the e-mail again, and retry"
#define CHAN_NOT_ALLOWED_TO_JOIN "You are not permitted to be on this channel."
#define CHAN_X_INVALID "Channel %s is not a valid channel."
diff --git a/include/mail.h b/include/mail.h
index c62bfb3be..31f35d92d 100644
--- a/include/mail.h
+++ b/include/mail.h
@@ -3,7 +3,6 @@
#include "anope.h"
-extern CoreExport bool Mail(User *u, NickRequest *nr, BotInfo *service, const Anope::string &subject, const Anope::string &message);
extern CoreExport bool Mail(User *u, NickCore *nc, BotInfo *service, const Anope::string &subject, const Anope::string &message);
extern CoreExport bool Mail(NickCore *nc, const Anope::string &subject, const Anope::string &message);
extern CoreExport bool MailValidate(const Anope::string &email);
diff --git a/include/modules.h b/include/modules.h
index 5b78584d1..8367b084f 100644
--- a/include/modules.h
+++ b/include/modules.h
@@ -561,14 +561,6 @@ class CoreExport Module : public Extensible
*/
virtual EventReturn OnDatabaseReadMetadata(NickAlias *na, const Anope::string &key, const std::vector<Anope::string> &params) { return EVENT_CONTINUE; }
- /** Called when nickrequest metadata is read from the database
- * @param nr The nickrequest
- * @parm key The metadata key
- * @param params The params from the database
- * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to stop processing
- */
- virtual EventReturn OnDatabaseReadMetadata(NickRequest *nr, const Anope::string &key, const std::vector<Anope::string> &params) { return EVENT_CONTINUE; }
-
/** Called when botinfo metadata is read from the database
* @param bi The botinfo
* @param key The metadata key
@@ -597,12 +589,6 @@ class CoreExport Module : public Extensible
*/
virtual void OnDatabaseWriteMetadata(void (*WriteMetadata)(const Anope::string &, const Anope::string &), NickAlias *na) { }
- /** Called when we are wrting metadata for a nickrequest
- * @param WriteMetata A callback function used to insert the metadata
- * @param nr The nick request
- */
- virtual void OnDatabaseWriteMetadata(void (*WriteMetadata)(const Anope::string &, const Anope::string &), NickRequest *nr) { }
-
/** Called when we are writing metadata for a botinfo
* @param WriteMetata A callback function used to insert the metadata
* @param bi The botinfo
@@ -884,16 +870,6 @@ class CoreExport Module : public Extensible
*/
virtual void OnChangeCoreDisplay(NickCore *nc, const Anope::string &newdisplay) { }
- /** called from ns_register.c, after the NickRequest have been created
- * @param nr pointer to the NickRequest
- */
- virtual void OnMakeNickRequest(NickRequest *nr) { }
-
- /** called on delnickrequest()
- * @param nr pointer to the NickRequest
- */
- virtual void OnDelNickRequest(NickRequest *nr) { }
-
/** called from NickCore::ClearAccess()
* @param nc pointer to the NickCore
*/
@@ -1082,7 +1058,7 @@ enum Implementation
I_OnPreNickExpire, I_OnNickExpire, I_OnNickForbidden, I_OnNickGroup, I_OnNickLogout, I_OnNickIdentify, I_OnNickDrop,
I_OnNickRegister, I_OnNickSuspended, I_OnNickUnsuspended,
I_OnDelNick, I_OnDelCore, I_OnChangeCoreDisplay,
- I_OnDelNickRequest, I_OnMakeNickRequest, I_OnNickClearAccess, I_OnNickAddAccess, I_OnNickEraseAccess,
+ I_OnNickClearAccess, I_OnNickAddAccess, I_OnNickEraseAccess,
I_OnNickInfo, I_OnFindNick, I_OnFindCore,
/* ChanServ */
diff --git a/include/services.h b/include/services.h
index 58c512d0b..cc2bdf331 100644
--- a/include/services.h
+++ b/include/services.h
@@ -448,7 +448,6 @@ template<typename T> inline T convertTo(const Anope::string &s, bool failIfLefto
class User;
class NickCore;
class NickAlias;
-class NickRequest;
class BotInfo;
class ChannelInfo;
class Channel;
@@ -879,7 +878,6 @@ struct MailInfo
FILE *pipe;
User *sender;
NickCore *recipient;
- NickRequest *recip;
};
/*************************************************************************/
diff --git a/modules/core/cs_register.cpp b/modules/core/cs_register.cpp
index 34cdc50df..1f1c6e9b2 100644
--- a/modules/core/cs_register.cpp
+++ b/modules/core/cs_register.cpp
@@ -32,12 +32,10 @@ class CommandCSRegister : public Command
Channel *c = findchan(chan);
if (readonly)
- {
source.Reply(_("Sorry, channel registration is temporarily disabled."));
- return MOD_CONT;
- }
-
- if (chan[0] == '&')
+ else if (u->Account()->HasFlag(NI_UNCONFIRMED))
+ source.Reply(_("You must confirm your account before you can register a channel."));
+ else if (chan[0] == '&')
source.Reply(_("Local channels cannot be registered."));
else if (chan[0] != '#')
source.Reply(_(CHAN_SYMBOL_REQUIRED));
diff --git a/modules/core/db_plain.cpp b/modules/core/db_plain.cpp
index f47f3156a..4dbf864de 100644
--- a/modules/core/db_plain.cpp
+++ b/modules/core/db_plain.cpp
@@ -22,7 +22,6 @@ enum MDType
MD_NONE,
MD_NC,
MD_NA,
- MD_NR,
MD_BI,
MD_CH
};
@@ -52,7 +51,6 @@ static void ReadDatabase(Module *m = NULL)
NickCore *nc = NULL;
NickAlias *na = NULL;
- NickRequest *nr = NULL;
BotInfo *bi = NULL;
ChannelInfo *ci = NULL;
@@ -100,11 +98,6 @@ static void ReadDatabase(Module *m = NULL)
na = findnick(params[2]);
Type = MD_NA;
}
- else if (params[0].equals_ci("NR"))
- {
- nr = findrequestnick(params[1]);
- Type = MD_NR;
- }
else if (params[0].equals_ci("BI"))
{
bi = findbot(params[1]);
@@ -149,20 +142,6 @@ static void ReadDatabase(Module *m = NULL)
Log() << "[db_plain]: " << ex.GetReason();
}
}
- else if (Type == MD_NR && nr)
- {
- try
- {
- if (m)
- m->OnDatabaseReadMetadata(nr, key, params);
- else
- FOREACH_RESULT(I_OnDatabaseReadMetadata, OnDatabaseReadMetadata(nr, key, params));
- }
- catch (const DatabaseException &ex)
- {
- Log() << "[db_plain]: " << ex.GetReason();
- }
- }
else if (Type == MD_BI && bi)
{
try
@@ -292,17 +271,6 @@ static void LoadNickAlias(const std::vector<Anope::string> &params)
Log(LOG_DEBUG_2) << "[db_plain}: Loaded nickalias for " << na->nick;
}
-static void LoadNickRequest(const std::vector<Anope::string> &params)
-{
- NickRequest *nr = new NickRequest(params[0]);
- nr->passcode = params[1];
- nr->password = params[2];
- nr->email = params[3];
- nr->requested = params[4].is_pos_number_only() ? convertTo<time_t>(params[4]) : 0;
-
- Log(LOG_DEBUG_2) << "[db_plain]: Loaded nickrequest for " << nr->nick;
-}
-
static void LoadBotInfo(const std::vector<Anope::string> &params)
{
BotInfo *bi = findbot(params[0]);
@@ -480,8 +448,6 @@ class DBPlain : public Module
LoadNickCore(otherparams);
else if (key.equals_ci("NA"))
LoadNickAlias(otherparams);
- else if (key.equals_ci("NR"))
- LoadNickRequest(otherparams);
else if (key.equals_ci("BI"))
LoadBotInfo(otherparams);
else if (key.equals_ci("CH"))
@@ -765,15 +731,6 @@ class DBPlain : public Module
db_buffer << "VER 2" << endl;
- for (nickrequest_map::const_iterator it = NickRequestList.begin(), it_end = NickRequestList.end(); it != it_end; ++it)
- {
- NickRequest *nr = it->second;
-
- db_buffer << "NR " << nr->nick << " " << nr->passcode << " " << nr->password << " " << nr->email << " " << nr->requested << endl;
-
- FOREACH_MOD(I_OnDatabaseWriteMetadata, OnDatabaseWriteMetadata(WriteMetadata, nr));
- }
-
for (nickcore_map::const_iterator nit = NickCoreList.begin(), nit_end = NickCoreList.end(); nit != nit_end; ++nit)
{
NickCore *nc = nit->second;
diff --git a/modules/core/ns_drop.cpp b/modules/core/ns_drop.cpp
index e7edcd79a..33a18009d 100644
--- a/modules/core/ns_drop.cpp
+++ b/modules/core/ns_drop.cpp
@@ -36,30 +36,7 @@ class CommandNSDrop : public Command
NickAlias *na = findnick((u->Account() && !nick.empty() ? nick : u->nick));
if (!na)
{
- NickRequest *nr = findrequestnick(u->Account() && !nick.empty() ? nick : u->nick);
- if (nr && u->Account() && u->Account()->IsServicesOper())
- {
- Log(LOG_ADMIN, u, this) << "to drop nickname " << nr->nick << " (email: " << nr->email << ")";
- delete nr;
- source.Reply(_("Nickname \002%s\002 has been dropped."), nick.c_str());
- }
- else if (nr && !nick.empty())
- {
- int res = enc_check_password(nick, nr->password);
- if (res)
- {
- Log(LOG_COMMAND, u, this) << "to drop nick request " << nr->nick;
- source.Reply(_("Nickname \002%s\002 has been dropped."), nr->nick.c_str());
- delete nr;
- }
- else if (bad_password(u))
- return MOD_STOP;
- else
- source.Reply(_(PASSWORD_INCORRECT));
- }
- else
- source.Reply(_(NICK_NOT_REGISTERED));
-
+ source.Reply(_(NICK_NOT_REGISTERED));
return MOD_CONT;
}
diff --git a/modules/core/ns_getpass.cpp b/modules/core/ns_getpass.cpp
index fdd5f2cd0..b034e2ba4 100644
--- a/modules/core/ns_getpass.cpp
+++ b/modules/core/ns_getpass.cpp
@@ -27,18 +27,9 @@ class CommandNSGetPass : public Command
const Anope::string &nick = params[0];
Anope::string tmp_pass;
NickAlias *na;
- NickRequest *nr = NULL;
if (!(na = findnick(nick)))
- {
- if ((nr = findrequestnick(nick)))
- {
- Log(LOG_ADMIN, u, this) << "for " << nr->nick;
- source.Reply(_("Passcode for %s is \002%s\002."), nick.c_str(), nr->passcode.c_str());
- }
- else
- source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str());
- }
+ source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str());
else if (na->HasFlag(NS_FORBIDDEN))
source.Reply(_(NICK_X_FORBIDDEN), na->nick.c_str());
else if (Config->NSSecureAdmins && na->nc->IsServicesOper())
diff --git a/modules/core/ns_group.cpp b/modules/core/ns_group.cpp
index 4ab1d112c..e09a4325a 100644
--- a/modules/core/ns_group.cpp
+++ b/modules/core/ns_group.cpp
@@ -29,12 +29,6 @@ class CommandNSGroup : public Command
const Anope::string &nick = params[0];
Anope::string pass = params[1];
- if (Config->NSEmailReg && findrequestnick(u->nick))
- {
- source.Reply(_(NICK_REQUESTED));
- return MOD_CONT;
- }
-
if (readonly)
{
source.Reply(_("Sorry, nickname grouping is temporarily disabled."));
@@ -121,7 +115,8 @@ class CommandNSGroup : public Command
u->Login(na->nc);
FOREACH_MOD(I_OnNickGroup, OnNickGroup(u, target));
ircdproto->SetAutoIdentificationToken(u);
- u->SetMode(NickServ, UMODE_REGISTERED);
+ if (target->nc->HasFlag(NI_UNCONFIRMED) == false)
+ u->SetMode(NickServ, UMODE_REGISTERED);
Log(LOG_COMMAND, u, this) << "makes " << u->nick << " join group of " << target->nick << " (" << target->nc->display << ") (email: " << (!target->nc->email.empty() ? target->nc->email : "none") << ")";
source.Reply(_("You are now in the group of \002%s\002."), target->nick.c_str());
diff --git a/modules/core/ns_identify.cpp b/modules/core/ns_identify.cpp
index 45b189ca6..074adbb76 100644
--- a/modules/core/ns_identify.cpp
+++ b/modules/core/ns_identify.cpp
@@ -31,13 +31,7 @@ class CommandNSIdentify : public Command
NickAlias *na = findnick(nick), *this_na = findnick(u->nick);
if (!na)
- {
- NickRequest *nr = findrequestnick(nick);
- if (nr)
- source.Reply(_(NICK_IS_PREREG));
- else
- source.Reply(_(NICK_NOT_REGISTERED));
- }
+ source.Reply(_(NICK_NOT_REGISTERED));
else if (na->HasFlag(NS_FORBIDDEN))
source.Reply(_(NICK_X_FORBIDDEN), na->nick.c_str());
else if (na->nc->HasFlag(NI_SUSPENDED))
@@ -72,7 +66,7 @@ class CommandNSIdentify : public Command
ircdproto->SendAccountLogin(u, u->Account());
ircdproto->SetAutoIdentificationToken(u);
- if (this_na && this_na->nc == na->nc)
+ if (this_na && this_na->nc == na->nc && this_na->nc->HasFlag(NI_UNCONFIRMED) == false)
u->SetMode(NickServ, UMODE_REGISTERED);
u->UpdateHost();
@@ -86,7 +80,7 @@ class CommandNSIdentify : public Command
FOREACH_MOD(I_OnNickIdentify, OnNickIdentify(u));
- if (Config->NSForceEmail && u->Account() && u->Account()->email.empty())
+ if (Config->NSForceEmail && u->Account()->email.empty())
{
source.Reply(_("You must now supply an e-mail for your nick.\n"
"This e-mail will allow you to retrieve your password in\n"
@@ -96,6 +90,14 @@ class CommandNSIdentify : public Command
"any third-party person."), NickServ->nick.c_str());
}
+ if (u->Account()->HasFlag(NI_UNCONFIRMED))
+ {
+ source.Reply(_("Your email address is not confirmed. To confirm it, follow the instructions that were emailed to you when you registered."));
+ time_t time_registered = Anope::CurTime - na->time_registered;
+ if (Config->NSUnconfirmedExpire > time_registered)
+ source.Reply(_("Your account will expire, if not confirmed, in %s"), duration(u->Account(), Config->NSUnconfirmedExpire - time_registered).c_str());
+ }
+
check_memos(u);
}
}
diff --git a/modules/core/ns_info.cpp b/modules/core/ns_info.cpp
index 52326ddb6..0ac50d471 100644
--- a/modules/core/ns_info.cpp
+++ b/modules/core/ns_info.cpp
@@ -44,14 +44,7 @@ class CommandNSInfo : public Command
if (!na)
{
- NickRequest *nr = findrequestnick(nick);
- if (nr)
- {
- source.Reply(_(NICK_IS_PREREG));
- if (has_auspex)
- source.Reply(_(" E-mail address: %s"), nr->email.c_str());
- }
- else if (nickIsServices(nick, true))
+ if (nickIsServices(nick, true))
source.Reply(_("Nick \002%s\002 is part of this Network's Services."), nick.c_str());
else
source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str());
@@ -120,11 +113,11 @@ class CommandNSInfo : public Command
Anope::string optbuf;
- CheckOptStr(optbuf, NI_KILLPROTECT, GetString(u->Account(), _("Protection")).c_str(), na->nc);
- CheckOptStr(optbuf, NI_SECURE, GetString(u->Account(), _("Security")).c_str(), na->nc);
- CheckOptStr(optbuf, NI_PRIVATE, GetString(u->Account(), _("Private")).c_str(), na->nc);
- CheckOptStr(optbuf, NI_MSG, GetString(u->Account(), _("Message mode")).c_str(), na->nc);
- CheckOptStr(optbuf, NI_AUTOOP, GetString(u->Account(), _("Auto-op")).c_str(), na->nc);
+ CheckOptStr(optbuf, NI_KILLPROTECT, _("Protection"), na->nc);
+ CheckOptStr(optbuf, NI_SECURE, _("Security"), na->nc);
+ CheckOptStr(optbuf, NI_PRIVATE, _("Private"), na->nc);
+ CheckOptStr(optbuf, NI_MSG, _("Message mode"), na->nc);
+ CheckOptStr(optbuf, NI_AUTOOP, _("Auto-op"), na->nc);
source.Reply(_(NICK_INFO_OPTIONS), optbuf.empty() ? _("None") : optbuf.c_str());
@@ -136,13 +129,21 @@ class CommandNSInfo : public Command
source.Reply(_("This nickname is currently suspended"));
}
- if (na->HasFlag(NS_NO_EXPIRE))
- source.Reply(_("This nickname will not expire."));
+ if (na->nc->HasFlag(NI_UNCONFIRMED) == false)
+ {
+ if (na->HasFlag(NS_NO_EXPIRE))
+ source.Reply(_("This nickname will not expire."));
+ else
+ source.Reply(_("Expires on: %s"), do_strftime(na->last_seen + Config->NSExpire).c_str());
+ }
else
- source.Reply(_("Expires on: %s"), do_strftime(na->last_seen + Config->NSExpire).c_str());
+ source.Reply(_("Expires on: %s"), do_strftime(na->time_registered + Config->NSUnconfirmedExpire).c_str());
}
FOREACH_MOD(I_OnNickInfo, OnNickInfo(source, na, show_hidden));
+
+ if (na->nc->HasFlag(NI_UNCONFIRMED))
+ source.Reply(_("This nickname is unconfirmed."));
}
return MOD_CONT;
}
diff --git a/modules/core/ns_list.cpp b/modules/core/ns_list.cpp
index 1ecbad3d3..fb8673069 100644
--- a/modules/core/ns_list.cpp
+++ b/modules/core/ns_list.cpp
@@ -97,67 +97,53 @@ class CommandNSList : public Command
mync = u->Account();
source.Reply(_(LIST_HEADER), pattern.c_str());
- if (!unconfirmed)
+ for (nickalias_map::const_iterator it = NickAliasList.begin(), it_end = NickAliasList.end(); it != it_end; ++it)
{
- for (nickalias_map::const_iterator it = NickAliasList.begin(), it_end = NickAliasList.end(); it != it_end; ++it)
- {
- NickAlias *na = it->second;
-
- /* Don't show private and forbidden nicks to non-services admins. */
- if (na->HasFlag(NS_FORBIDDEN) && !is_servadmin)
- continue;
- if (na->nc->HasFlag(NI_PRIVATE) && !is_servadmin && na->nc != mync)
- continue;
- if (forbidden && !na->HasFlag(NS_FORBIDDEN))
+ NickAlias *na = it->second;
+
+ /* Don't show private and forbidden nicks to non-services admins. */
+ if (na->HasFlag(NS_FORBIDDEN) && !is_servadmin)
+ continue;
+ else if (na->nc->HasFlag(NI_PRIVATE) && !is_servadmin && na->nc != mync)
+ continue;
+ else if (forbidden && !na->HasFlag(NS_FORBIDDEN))
+ continue;
+ else if (nsnoexpire && !na->HasFlag(NS_NO_EXPIRE))
continue;
- else if (nsnoexpire && !na->HasFlag(NS_NO_EXPIRE))
- continue;
- else if (suspended && !na->nc->HasFlag(NI_SUSPENDED))
- continue;
-
- /* We no longer compare the pattern against the output buffer.
- * Instead we build a nice nick!user@host buffer to compare.
- * The output is then generated separately. -TheShadow */
- snprintf(buf, sizeof(buf), "%s!%s", na->nick.c_str(), !na->last_usermask.empty() && !na->HasFlag(NS_FORBIDDEN) ? na->last_usermask.c_str() : "*@*");
- if (na->nick.equals_ci(pattern) || Anope::Match(buf, pattern))
- {
- if (((count + 1 >= from && count + 1 <= to) || (!from && !to)) && ++nnicks <= Config->NSListMax)
- {
- if (is_servadmin && na->HasFlag(NS_NO_EXPIRE))
- noexpire_char = '!';
- else
- noexpire_char = ' ';
- if (na->nc->HasFlag(NI_HIDE_MASK) && !is_servadmin && na->nc != mync)
- snprintf(buf, sizeof(buf), "%-20s [Hostname Hidden]", na->nick.c_str());
- else if (na->HasFlag(NS_FORBIDDEN))
- snprintf(buf, sizeof(buf), "%-20s [Forbidden]", na->nick.c_str());
- else if (na->nc->HasFlag(NI_SUSPENDED))
- snprintf(buf, sizeof(buf), "%-20s [Suspended]", na->nick.c_str());
- else
- snprintf(buf, sizeof(buf), "%-20s %s", na->nick.c_str(), na->last_usermask.c_str());
- source.Reply(" %c%s", noexpire_char, buf);
- }
- ++count;
- }
- }
- }
-
- if (unconfirmed || is_servadmin)
- {
- noexpire_char = ' ';
-
- for (nickrequest_map::const_iterator it = NickRequestList.begin(), it_end = NickRequestList.end(); it != it_end; ++it)
+ else if (suspended && !na->nc->HasFlag(NI_SUSPENDED))
+ continue;
+ else if (unconfirmed && na->nc->HasFlag(NI_UNCONFIRMED))
+ continue;
+
+ /* We no longer compare the pattern against the output buffer.
+ * Instead we build a nice nick!user@host buffer to compare.
+ * The output is then generated separately. -TheShadow */
+ snprintf(buf, sizeof(buf), "%s!%s", na->nick.c_str(), !na->last_usermask.empty() && !na->HasFlag(NS_FORBIDDEN) ? na->last_usermask.c_str() : "*@*");
+ if (na->nick.equals_ci(pattern) || Anope::Match(buf, pattern))
{
- NickRequest *nr = it->second;
-
- snprintf(buf, sizeof(buf), "%s!*@*", nr->nick.c_str());
- if ((nr->nick.equals_ci(pattern) || Anope::Match(buf, pattern)) && ++nnicks <= Config->NSListMax)
+ if (((count + 1 >= from && count + 1 <= to) || (!from && !to)) && ++nnicks <= Config->NSListMax)
{
- snprintf(buf, sizeof(buf), "%-20s [UNCONFIRMED]", nr->nick.c_str());
+ if (is_servadmin && na->HasFlag(NS_NO_EXPIRE))
+ noexpire_char = '!';
+ else
+ noexpire_char = ' ';
+ if (na->nc->HasFlag(NI_HIDE_MASK) && !is_servadmin && na->nc != mync)
+ snprintf(buf, sizeof(buf), "%-20s [Hostname Hidden]", na->nick.c_str());
+ else if (na->HasFlag(NS_FORBIDDEN))
+ snprintf(buf, sizeof(buf), "%-20s [Forbidden]", na->nick.c_str());
+ else if (na->nc->HasFlag(NI_SUSPENDED))
+ snprintf(buf, sizeof(buf), "%-20s [Suspended]", na->nick.c_str());
+ else if (na->nc->HasFlag(NI_UNCONFIRMED))
+ snprintf(buf, sizeof(buf), "%-20s [Unconfirmed]", na->nick.c_str());
+ else
+ snprintf(buf, sizeof(buf), "%-20s %s", na->nick.c_str(), na->last_usermask.c_str());
source.Reply(" %c%s", noexpire_char, buf);
}
+ ++count;
}
}
+
+
source.Reply(_("End of list - %d/%d matches shown."), nnicks > Config->NSListMax ? Config->NSListMax : nnicks, nnicks);
return MOD_CONT;
}
diff --git a/modules/core/ns_register.cpp b/modules/core/ns_register.cpp
index d7867896c..d336f1f4d 100644
--- a/modules/core/ns_register.cpp
+++ b/modules/core/ns_register.cpp
@@ -13,147 +13,67 @@
#include "module.h"
-static bool SendRegmail(User *u, NickRequest *nr);
+static bool SendRegmail(User *u, NickAlias *na);
class CommandNSConfirm : public Command
{
- protected:
- CommandReturn ActuallyConfirmNick(CommandSource &source, NickRequest *nr, bool force)
+ public:
+ CommandNSConfirm() : Command("CONFIRM", 1, 2)
{
- User *u = source.u;
- NickAlias *na = new NickAlias(nr->nick, new NickCore(nr->nick));
- Anope::string tmp_pass;
-
- na->nc->pass = nr->password;
-
- if (force)
- {
- na->last_usermask = "*@*";
- na->last_realname = "unknown";
- }
- else
- {
- Anope::string last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost();
- na->last_usermask = last_usermask;
- na->last_realname = u->realname;
- if (Config->NSAddAccessOnReg)
- na->nc->AddAccess(create_mask(u));
- }
-
- if (!nr->email.empty())
- na->nc->email = nr->email;
-
- if (!force)
- {
- u->Login(na->nc);
- Log(LOG_COMMAND, u, this) << "to register " << nr->nick << " (email: " << (!nr->email.empty() ? nr->email : "none") << ")";
- if (Config->NSAddAccessOnReg)
- source.Reply(_("Nickname \002%s\002 registered under your account: %s"), u->nick.c_str(), na->nc->GetAccess(0).c_str());
- else
- source.Reply(_("Nickname \002%s\002 registered."), u->nick.c_str());
- delete nr;
-
- ircdproto->SendAccountLogin(u, u->Account());
- ircdproto->SetAutoIdentificationToken(u);
-
- if (enc_decrypt(na->nc->pass, tmp_pass) == 1)
- source.Reply(_("Your password is \002%s\002 - remember this for later use."), tmp_pass.c_str());
-
- u->lastnickreg = Anope::CurTime;
- }
- else
- {
- Log(LOG_COMMAND, u, this) << "to confirm " << nr->nick << " (email: " << (!nr->email.empty() ? nr->email : "none") << ")";
- source.Reply(_("Nickname \002%s\002 confirmed"), nr->nick.c_str());
- User *user = finduser(nr->nick);
- /* Delrequest must be called before validate_user */
- delete nr;
- if (user)
- validate_user(user);
- }
-
- FOREACH_MOD(I_OnNickRegister, OnNickRegister(na));
-
- return MOD_CONT;
+ this->SetFlag(CFLAG_ALLOW_UNREGISTERED);
+ this->SetDesc("Confirm an auth code");
}
- CommandReturn DoConfirm(CommandSource &source, const std::vector<Anope::string> &params)
+ CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> &params)
{
User *u = source.u;
- Anope::string passcode = !params.empty() ? params[0] : "";
+ const Anope::string &passcode = params[0];
- NickRequest *nr = findrequestnick(u->nick);
-
- if (Config->NSEmailReg)
+ if (u->Account() && u->Account()->HasPriv("nickserv/confirm"))
{
- if (passcode.empty())
- {
- this->OnSyntaxError(source, "");
- return MOD_CONT;
- }
-
- if (!nr)
+ NickAlias *na = findnick(passcode);
+ if (na == NULL)
+ source.Reply(_(NICK_X_NOT_REGISTERED), passcode.c_str());
+ else if (na->nc->HasFlag(NI_UNCONFIRMED) == false)
+ source.Reply(_("Nick \002%s\002 is already confirmed."), na->nick.c_str());
{
- if (u->Account() && u->Account()->HasPriv("nickserv/confirm"))
- {
- /* If an admin, their nick is obviously already regged, so look at the passcode to get the nick
- of the user they are trying to validate, and push that user through regardless of passcode */
- nr = findrequestnick(passcode);
- if (nr)
- {
- ActuallyConfirmNick(source, nr, true);
- return MOD_CONT;
- }
- }
- source.Reply(_("Registration step 1 may have expired, please use \"%R%s register <password> <email>\" first."), Config->s_NickServ.c_str());
-
- return MOD_CONT;
- }
-
- if (!nr->passcode.equals_cs(passcode))
- {
- source.Reply(_(NICK_CONFIRM_INVALID));
- return MOD_CONT;
+ na->nc->UnsetFlag(NI_UNCONFIRMED);
+ Log(LOG_ADMIN, u, this) << "to confirm nick " << na->nick << " (" << na->nc->display << ")";
+ source.Reply(_("Nick \002%s\002 has been confirmed."), na->nick.c_str());
}
}
-
- if (!nr)
+ else if (u->Account())
{
- source.Reply(_("Sorry, registration failed."));
- return MOD_CONT;
+ Anope::string code;
+ if (u->Account()->GetExtRegular<Anope::string>("ns_register_passcode", code) && code == passcode)
+ {
+ u->Account()->Shrink("ns_register_passcode");
+ Log(LOG_COMMAND, u, this) << "to confirm their email";
+ source.Reply(_("Your email address of \002%s\002 has been confirmed."), u->Account()->email.c_str());
+ u->Account()->UnsetFlag(NI_UNCONFIRMED);
+ }
+ else
+ source.Reply(_("Invalid passcode."));
}
+ else
+ source.Reply(_("Invalid passcode."));
- ActuallyConfirmNick(source, nr, false);
return MOD_CONT;
}
- public:
- CommandNSConfirm(const Anope::string &cmdn, int min, int max) : Command(cmdn, min, max)
- {
- this->SetFlag(CFLAG_ALLOW_UNREGISTERED);
- this->SetDesc("Confirm a nickserv auth code");
- }
-
- CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> &params)
- {
- return this->DoConfirm(source, params);
- }
-
bool OnHelp(CommandSource &source, const Anope::string &subcommand)
{
User *u = source.u;
source.Reply(_("Syntax: \002CONFIRM \037passcode\037\002\n"
" \n"
- "This is the second step of nickname registration process.\n"
- "You must perform this command in order to get your nickname\n"
- "registered with %s. The passcode (or called auth code also)\n"
- "is sent to your e-mail address in the first step of the\n"
- "registration process. For more information about the first\n"
- "stage of the registration process, type: \002%R%s HELP REGISTER\002\n"
+ "This command is used by several commands as a way to confirm\n"
+ "changes made to your account.\n"
+ " \n"
+ "This is most commonly used to confirm your email address once\n"
+ "you register or change it.\n"
" \n"
"This is also used after the RESETPASS command has been used to\n"
- "force identify you to your nick so you may change your password."),
- NickServ->nick.c_str());
+ "force identify you to your nick so you may change your password."));
if (u->Account() && u->Account()->HasPriv("nickserv/confirm"))
source.Reply(_("Additionally, Services Operators with the \037nickserv/confirm\037 permission can\n"
"replace \037passcode\037 with a users nick to force validate them."));
@@ -166,10 +86,10 @@ class CommandNSConfirm : public Command
}
};
-class CommandNSRegister : public CommandNSConfirm
+class CommandNSRegister : public Command
{
public:
- CommandNSRegister() : CommandNSConfirm("REGISTER", 1, 2)
+ CommandNSRegister() : Command("REGISTER", 1, 2)
{
this->SetFlag(CFLAG_ALLOW_UNREGISTERED);
this->SetDesc("Register a nickname");
@@ -178,22 +98,11 @@ class CommandNSRegister : public CommandNSConfirm
CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> &params)
{
User *u = source.u;
- NickRequest *nr = NULL, *anr = NULL;
NickAlias *na;
size_t prefixlen = Config->NSGuestNickPrefix.length();
size_t nicklen = u->nick.length();
Anope::string pass = params[0];
Anope::string email = params.size() > 1 ? params[1] : "";
- Anope::string passcode;
- int idx, min = 1, max = 62;
- int chars[] = {
- ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
- 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
- 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
- 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
- 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
- };
- std::list<std::pair<Anope::string, Anope::string> >::iterator it, it_end;
if (readonly)
{
@@ -207,12 +116,6 @@ class CommandNSRegister : public CommandNSConfirm
return MOD_CONT;
}
- if ((anr = findrequestnick(u->nick)))
- {
- source.Reply(_(NICK_REQUESTED));
- return MOD_CONT;
- }
-
/* Prevent "Guest" nicks from being registered. -TheShadow */
/* Guest nick can now have a series of between 1 and 7 digits.
@@ -231,7 +134,7 @@ class CommandNSRegister : public CommandNSConfirm
}
if (Config->RestrictOperNicks)
- for (it = Config->Opers.begin(), it_end = Config->Opers.end(); it != it_end; ++it)
+ for (std::list<std::pair<Anope::string, Anope::string> >::iterator it = Config->Opers.begin(), it_end = Config->Opers.end(); it != it_end; ++it)
{
Anope::string nick = it->first;
@@ -265,38 +168,46 @@ class CommandNSRegister : public CommandNSConfirm
source.Reply(_(MAIL_X_INVALID), email.c_str());
else
{
- for (idx = 0; idx < 9; ++idx)
- passcode += chars[1 + static_cast<int>((static_cast<float>(max - min)) * getrandom16() / 65536.0) + min];
- nr = new NickRequest(u->nick);
- nr->passcode = passcode;
- enc_encrypt(pass, nr->password);
+ na = new NickAlias(u->nick, new NickCore(u->nick));
+ enc_encrypt(pass, na->nc->pass);
if (!email.empty())
- nr->email = email;
- nr->requested = Anope::CurTime;
- FOREACH_MOD(I_OnMakeNickRequest, OnMakeNickRequest(nr));
+ na->nc->email = email;
+
+ Anope::string last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost();
+ na->last_usermask = last_usermask;
+ na->last_realname = u->realname;
+ if (Config->NSAddAccessOnReg)
+ na->nc->AddAccess(create_mask(u));
+
+ u->Login(na->nc);
+
+ Log(LOG_COMMAND, u, this) << "to register " << na->nick << " (email: " << (!na->nc->email.empty() ? na->nc->email : "none") << ")";
+
+ FOREACH_MOD(I_OnNickRegister, OnNickRegister(na));
+
+ if (Config->NSAddAccessOnReg)
+ source.Reply(_("Nickname \002%s\002 registered under your account: %s"), u->nick.c_str(), na->nc->GetAccess(0).c_str());
+ else
+ source.Reply(_("Nickname \002%s\002 registered."), u->nick.c_str());
+
+ Anope::string tmp_pass;
+ if (enc_decrypt(na->nc->pass, tmp_pass) == 1)
+ source.Reply(_("Your password is \002%s\002 - remember this for later use."), tmp_pass.c_str());
+
if (Config->NSEmailReg)
{
- if (SendRegmail(u, nr))
+ na->nc->SetFlag(NI_UNCONFIRMED);
+ if (SendRegmail(u, na))
{
- source.Reply(_("A passcode has been sent to %s, please type %R%s confirm <passcode> to complete registration.\n"
- "If you need to cancel your registration, use \"%R%s drop <password>\"."),
- email.c_str(), Config->s_NickServ.c_str(), Config->s_NickServ.c_str());
-
- Log(LOG_COMMAND, u, this) << "send registration verification code to " << nr->email;
- }
- else
- {
- Log(LOG_COMMAND, u, this) << "unable to send registration verification mail";
- source.Reply(_("Nick NOT registered, please try again later."));
- delete nr;
- return MOD_CONT;
+ source.Reply(_("A passcode has been sent to %s, please type %R%s confirm <passcode> to confirm your email address."), email.c_str(), NickServ->nick.c_str());
+ source.Reply(_("If you do not confirm your email address within %s your account will expire."), duration(na->nc, Config->NSUnconfirmedExpire).c_str());
}
}
- else
- {
- std::vector<Anope::string> empty_params;
- return this->DoConfirm(source, empty_params);
- }
+
+ ircdproto->SendAccountLogin(u, u->Account());
+ ircdproto->SetAutoIdentificationToken(u);
+
+ u->lastnickreg = Anope::CurTime;
}
return MOD_CONT;
@@ -353,47 +264,54 @@ class CommandNSResend : public Command
public:
CommandNSResend() : Command("RESEND", 0, 0)
{
- this->SetFlag(CFLAG_ALLOW_UNREGISTERED);
- this->SetDesc("Resend a nickserv auth code");
}
CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> &params)
{
+ if (!Config->NSEmailReg)
+ return MOD_CONT;
+
User *u = source.u;
- NickRequest *nr = NULL;
- if (Config->NSEmailReg)
+ NickAlias *na = findnick(u->nick);
+
+ if (na == NULL)
+ source.Reply(_(NICK_NOT_REGISTERED));
+ else if (na->nc != u->Account() || u->Account()->HasFlag(NI_UNCONFIRMED) == false)
+ source.Reply(_("Your account is already confirmed."));
+ else
{
- if ((nr = findrequestnick(u->nick)))
+ if (Anope::CurTime < u->Account()->lastmail + Config->NSResendDelay)
+ source.Reply(_("Cannot send mail now; please retry a little later."));
+ else if (!SendRegmail(u, na))
{
- if (Anope::CurTime < nr->lastmail + Config->NSResendDelay)
- {
- source.Reply(_("Cannot send mail now; please retry a little later."));
- return MOD_CONT;
- }
- if (!SendRegmail(u, nr))
- {
- nr->lastmail = Anope::CurTime;
- source.Reply(_("Your passcode has been re-sent to %s."), nr->email.c_str());
- Log(LOG_COMMAND, u, this) << "resend registration verification code for " << nr->nick;
- }
- else
- {
- Log(LOG_COMMAND, u, this) << "unable to resend registration verification code for " << nr->nick;
- return MOD_CONT;
- }
+ na->nc->lastmail = Anope::CurTime;
+ source.Reply(_("Your passcode has been re-sent to %s."), na->nc->email.c_str());
+ Log(LOG_COMMAND, u, this) << "to resend registration verification code";
}
+ else
+ Log() << "Unable to resend registration verification code for " << u->nick;
}
+
return MOD_CONT;
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand)
{
+ if (!Config->NSEmailReg)
+ return false;
+
source.Reply(_("Syntax: \002RESEND\002\n"
" \n"
"This command will re-send the auth code (also called passcode)\n"
"to the e-mail address of the user whom is performing it."));
return true;
}
+
+ void OnServHelp(CommandSource &source)
+ {
+ if (Config->NSEmailReg)
+ source.Reply(_("Resend the registration passcode"));
+ }
};
class NSRegister : public Module
@@ -403,7 +321,7 @@ class NSRegister : public Module
CommandNSResend commandnsrsend;
public:
- NSRegister(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), commandnsconfirm("CONFIRM", 1, 1)
+ NSRegister(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator)
{
this->SetAuthor("Anope");
this->SetType(CORE);
@@ -414,21 +332,40 @@ class NSRegister : public Module
}
};
-static bool SendRegmail(User *u, NickRequest *nr)
+static bool SendRegmail(User *u, NickAlias *na)
{
- char subject[BUFSIZE], message[BUFSIZE];
+ Anope::string code;
+ if (na->nc->GetExtRegular<Anope::string>("ns_register_passcode", code) == false)
+ {
+ int chars[] = {
+ ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
+ 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
+ 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
+ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
+ 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
+ };
+ int idx, min = 1, max = 62;
+ for (idx = 0; idx < 9; ++idx)
+ code += chars[1 + static_cast<int>((static_cast<float>(max - min)) * getrandom16() / 65536.0) + min];
+ na->nc->Extend("ns_register_passcode", new ExtensibleItemRegular<Anope::string>(code));
+ }
- snprintf(subject, sizeof(subject), GetString(NULL, "Nickname Registration (%s)").c_str(), nr->nick.c_str());
- snprintf(message, sizeof(message), GetString(NULL, "Hi,\n"
+ Anope::string subject = Anope::printf(_("Nickname Registration (%s)"), na->nick.c_str());
+ Anope::string message = Anope::printf(_("Hi,\n"
" \n"
"You have requested to register the nickname %s on %s.\n"
"Please type \" %R%s confirm %s \" to complete registration.\n"
" \n"
"If you don't know why this mail was sent to you, please ignore it silently.\n"
" \n"
- "%s administrators.").c_str(), nr->nick.c_str(), Config->NetworkName.c_str(), Config->s_NickServ.c_str(), nr->passcode.c_str(), Config->NetworkName.c_str());
+ "%s administrators."), na->nick.c_str(), Config->NetworkName.c_str(), Config->s_NickServ.c_str(), code.c_str(), Config->NetworkName.c_str());
+
+ if (Config->UseStrictPrivMsg)
+ message = message.replace_all_cs("%R", "/");
+ else
+ message = message.replace_all_cs("%R", "/msg ");
- return Mail(u, nr, NickServ, subject, message);
+ return Mail(u, na->nc, NickServ, subject, message);
}
MODULE_INIT(NSRegister)
diff --git a/modules/core/ns_resetpass.cpp b/modules/core/ns_resetpass.cpp
index 068cb2b4f..7f9a3fd11 100644
--- a/modules/core/ns_resetpass.cpp
+++ b/modules/core/ns_resetpass.cpp
@@ -31,7 +31,7 @@ class CommandNSResetPass : public Command
if (Config->RestrictMail && (!u->Account() || !u->Account()->HasCommand("nickserv/resetpass")))
source.Reply(_(ACCESS_DENIED));
- if (!(na = findnick(params[0])))
+ else if (!(na = findnick(params[0])))
source.Reply(_(NICK_X_NOT_REGISTERED), params[0].c_str());
else if (na->HasFlag(NS_FORBIDDEN))
source.Reply(_(NICK_X_FORBIDDEN), na->nick.c_str());
@@ -82,36 +82,40 @@ class NSResetPass : public Module
EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> &params)
{
User *u = source.u;
- BotInfo *service = source.owner;
- if (service == NickServ && command->name.equals_ci("CONFIRM") && !params.empty())
+ if (command->service == NickServ && command->name.equals_ci("CONFIRM") && params.size() > 1)
{
- NickAlias *na = findnick(source.u->nick);
+ NickAlias *na = findnick(params[0]);
time_t t;
Anope::string c;
if (na && na->nc->GetExtRegular("ns_resetpass_code", c) && na->nc->GetExtRegular("ns_resetpass_time", t))
{
+ const Anope::string &passcode = params[1];
if (t < Anope::CurTime - 3600)
{
na->nc->Shrink("ns_resetpass_code");
na->nc->Shrink("ns_resetpass_time");
source.Reply(_("Your password reset request has expired."));
- return EVENT_STOP;
}
-
- Anope::string passcode = params[0];
- if (passcode.equals_cs(c))
+ else if (passcode.equals_cs(c))
{
na->nc->Shrink("ns_resetpass_code");
na->nc->Shrink("ns_resetpass_time");
- u->UpdateHost();
- na->last_realname = u->realname;
- na->last_seen = Anope::CurTime;
+ NickAlias *this_na = findnick(u->nick);
+
+ if (this_na && this_na == na)
+ {
+ u->UpdateHost();
+ na->last_realname = u->realname;
+ na->last_seen = Anope::CurTime;
+ u->SetMode(NickServ, UMODE_REGISTERED);
+ }
+
u->Login(na->nc);
ircdproto->SendAccountLogin(u, u->Account());
ircdproto->SetAutoIdentificationToken(u);
- u->SetMode(NickServ, UMODE_REGISTERED);
+ na->nc->UnsetFlag(NI_UNCONFIRMED);
FOREACH_MOD(I_OnNickIdentify, OnNickIdentify(u));
Log(LOG_COMMAND, u, &commandnsresetpass) << "confirmed RESETPASS to forcefully identify to " << na->nick;
@@ -124,11 +128,7 @@ class NSResetPass : public Module
check_memos(u);
}
else
- {
- Log(LOG_COMMAND, u, &commandnsresetpass) << "invalid confirm passcode for " << na->nick;
- source.Reply(_(NICK_CONFIRM_INVALID));
- bad_password(u);
- }
+ return EVENT_CONTINUE;
return EVENT_STOP;
}
@@ -140,10 +140,6 @@ class NSResetPass : public Module
static bool SendResetEmail(User *u, NickAlias *na)
{
- char subject[BUFSIZE], message[BUFSIZE];
-
- snprintf(subject, sizeof(subject), GetString(na->nc, _("Reset password request for %s")).c_str(), na->nick.c_str());
-
int min = 1, max = 62;
int chars[] = {
' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
@@ -158,18 +154,21 @@ static bool SendResetEmail(User *u, NickAlias *na)
for (idx = 0; idx < 20; ++idx)
passcode += chars[1 + static_cast<int>((static_cast<float>(max - min)) * getrandom16() / 65536.0) + min];
- snprintf(message, sizeof(message), GetString(na->nc,
+ Anope::string subject = Anope::printf(GetString(na->nc, "Reset password request for %s"), na->nick.c_str());
+ Anope::string message = Anope::printf(GetString(na->nc,
"Hi,\n"
" \n"
"You have requested to have the password for %s reset.\n"
- "To reset your password, type \002%R%s CONFIRM %s\002\n"
+ "To reset your password, type %R%s CONFIRM %s %s\n"
" \n"
"If you don't know why this mail was sent to you, please ignore it silently.\n"
" \n"
- "%s administrators.").c_str(), na->nick.c_str(), Config->s_NickServ.c_str(), passcode.c_str(), Config->NetworkName.c_str());
+ "%s administrators."), na->nick.c_str(), Config->s_NickServ.c_str(), na->nick.c_str(), passcode.c_str(), Config->NetworkName.c_str());
- na->nc->Shrink("ns_resetpass_code");
- na->nc->Shrink("ns_resetpass_time");
+ if (Config->UseStrictPrivMsg)
+ message = message.replace_all_cs("%R", "/");
+ else
+ message = message.replace_all_cs("%R", "/msg ");
na->nc->Extend("ns_resetpass_code", new ExtensibleItemRegular<Anope::string>(passcode));
na->nc->Extend("ns_resetpass_time", new ExtensibleItemRegular<time_t>(Anope::CurTime));
diff --git a/modules/core/ns_set_email.cpp b/modules/core/ns_set_email.cpp
index 6d6d97795..f6374f240 100644
--- a/modules/core/ns_set_email.cpp
+++ b/modules/core/ns_set_email.cpp
@@ -13,6 +13,39 @@
#include "module.h"
+static bool SendConfirmMail(User *u)
+{
+ int chars[] = {
+ ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
+ 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
+ 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
+ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
+ 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
+ };
+ int idx, min = 1, max = 62;
+ Anope::string code;
+ for (idx = 0; idx < 9; ++idx)
+ code += chars[1 + static_cast<int>((static_cast<float>(max - min)) * getrandom16() / 65536.0) + min];
+ u->Account()->Extend("ns_set_email_passcode", new ExtensibleItemRegular<Anope::string>(code));
+
+ Anope::string subject = _("Email confirmation");
+ Anope::string message = Anope::printf(_("Hi,\n"
+ " \n"
+ "You have requested to change your email address to %s.\n"
+ "Please type \" %R%s confirm %s \" to confirm this change.\n"
+ " \n"
+ "If you don't know why this mail was sent to you, please ignore it silently.\n"
+ " \n"
+ "%s administrators."), u->Account()->email.c_str(), Config->s_NickServ.c_str(), code.c_str(), Config->NetworkName.c_str());
+
+ if (Config->UseStrictPrivMsg)
+ message = message.replace_all_cs("%R", "/");
+ else
+ message = message.replace_all_cs("%R", "/msg ");
+
+ return Mail(u, u->Account(), NickServ, subject, message);
+}
+
class CommandNSSetEmail : public Command
{
public:
@@ -47,15 +80,27 @@ class CommandNSSetEmail : public Command
return MOD_CONT;
}
- if (!param.empty())
+ if (!param.empty() && Config->NSConfirmEmailChanges && !u->Account()->IsServicesOper())
{
- nc->email = param;
- source.Reply(_("E-mail address for \002%s\002 changed to \002%s\002."), nc->display.c_str(), param.c_str());
+ u->Account()->Extend("ns_set_email", new ExtensibleItemRegular<Anope::string>(param));
+ Anope::string old = u->Account()->email;
+ u->Account()->email = param;
+ if (SendConfirmMail(u))
+ source.Reply(_("A confirmation email has been sent to \002%s\002. Follow the instructions in it to change your email address."), param.c_str());
+ u->Account()->email = old;
}
else
{
- nc->email.clear();
- source.Reply(_("E-mail address for \002%s\002 unset."), nc->display.c_str());
+ if (!param.empty())
+ {
+ nc->email = param;
+ source.Reply(_("E-mail address for \002%s\002 changed to \002%s\002."), nc->display.c_str(), param.c_str());
+ }
+ else
+ {
+ nc->email.clear();
+ source.Reply(_("E-mail address for \002%s\002 unset."), nc->display.c_str());
+ }
}
return MOD_CONT;
@@ -99,6 +144,8 @@ class NSSetEmail : public Module
this->SetAuthor("Anope");
this->SetType(CORE);
+ ModuleManager::Attach(I_OnPreCommand, this);
+
Command *c = FindCommand(NickServ, "SET");
if (c)
c->AddSubcommand(this, &commandnssetemail);
@@ -118,6 +165,29 @@ class NSSetEmail : public Module
if (c)
c->DelSubcommand(&commandnssasetemail);
}
+
+ EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> &params)
+ {
+ User *u = source.u;
+ if (command->service == NickServ && command->name.equals_ci("CONFIRM") && !params.empty() && u->IsIdentified())
+ {
+ Anope::string new_email, passcode;
+ if (u->Account()->GetExtRegular("ns_set_email", new_email) && u->Account()->GetExtRegular("ns_set_email_passcode", passcode))
+ {
+ if (params[0] == passcode)
+ {
+ u->Account()->email = new_email;
+ Log(LOG_COMMAND, u, command) << "to confirm their email address change to " << u->Account()->email;
+ source.Reply(_("Your email address has been changed to \002%s\002."), u->Account()->email.c_str());
+ u->Account()->Shrink("ns_set_email");
+ u->Account()->Shrink("ns_set_email_passcode");
+ return EVENT_STOP;
+ }
+ }
+ }
+
+ return EVENT_CONTINUE;
+ }
};
MODULE_INIT(NSSetEmail)
diff --git a/modules/extra/db_mysql.cpp b/modules/extra/db_mysql.cpp
index 4b06c8ef1..f6dce95d2 100644
--- a/modules/extra/db_mysql.cpp
+++ b/modules/extra/db_mysql.cpp
@@ -217,8 +217,8 @@ class DBMySQL : public Module
I_OnSaveDatabase, I_OnPostCommand,
/* NickServ */
I_OnNickAddAccess, I_OnNickEraseAccess, I_OnNickClearAccess,
- I_OnDelCore, I_OnNickForbidden, I_OnNickGroup, I_OnMakeNickRequest,
- I_OnDelNickRequest, I_OnNickRegister, I_OnChangeCoreDisplay,
+ I_OnDelCore, I_OnNickForbidden, I_OnNickGroup,
+ I_OnNickRegister, I_OnChangeCoreDisplay,
I_OnNickSuspended, I_OnDelNick,
/* ChanServ */
I_OnAccessAdd, I_OnAccessDel, I_OnAccessChange, I_OnAccessClear, I_OnLevelChange,
@@ -236,7 +236,7 @@ class DBMySQL : public Module
/* HostServ */
I_OnSetVhost, I_OnDeleteVhost
};
- ModuleManager::Attach(i, this, 42);
+ ModuleManager::Attach(i, this, 40);
}
EventReturn OnLoadDatabase()
@@ -588,16 +588,6 @@ class DBMySQL : public Module
FOREACH_RESULT(I_OnDatabaseReadMetadata, OnDatabaseReadMetadata(ci, ci->name, Params));
}
- r = SQL->RunQuery("SELECT * FROM `anope_ns_request`");
- for (int i = 0; i < r.Rows(); ++i)
- {
- NickRequest *nr = new NickRequest(r.Get(i, "nick"));
- nr->password = r.Get(i, "passcode");
- nr->password = r.Get(i, "password");
- nr->email = r.Get(i, "email");
- nr->requested = r.Get(i, "requested").is_pos_number_only() ? convertTo<time_t>(r.Get(i, "requested")) : Anope::CurTime;
- }
-
r = SQL->RunQuery("SELECT * FROM `anope_ms_info`");
for (int i = 0; i < r.Rows(); ++i)
{
@@ -947,16 +937,6 @@ class DBMySQL : public Module
OnNickRegister(findnick(u->nick));
}
- void OnMakeNickRequest(NickRequest *nr)
- {
- this->RunQuery("INSERT INTO `anope_ns_request` (nick, passcode, password, email, requested) VALUES('" + this->Escape(nr->nick) + "', '" + this->Escape(nr->passcode) + "', '" + this->Escape(nr->password) + "', '" + this->Escape(nr->email) + "', " + stringify(nr->requested) + ")");
- }
-
- void OnDelNickRequest(NickRequest *nr)
- {
- this->RunQuery("DELETE FROM `anope_ns_request` WHERE `nick` = '" + this->Escape(nr->nick) + "'");
- }
-
void InsertAlias(NickAlias *na)
{
this->RunQuery("INSERT INTO `anope_ns_alias` (nick, last_quit, last_realname, last_usermask, time_registered, last_seen, flags, display) VALUES('" +
@@ -1369,11 +1349,6 @@ static void SaveDatabases()
}
}
- me->RunQuery("TRUNCATE TABLE `anope_ns_request`");
-
- for (nickrequest_map::const_iterator it = NickRequestList.begin(), it_end = NickRequestList.end(); it != it_end; ++it)
- me->OnMakeNickRequest(it->second);
-
if (SGLine)
for (unsigned i = 0, end = SGLine->GetCount(); i < end; ++i)
me->OnAddAkill(NULL, SGLine->GetEntry(i));
diff --git a/modules/extra/m_ldap.cpp b/modules/extra/m_ldap.cpp
index 0d198e27d..1d5aeca09 100644
--- a/modules/extra/m_ldap.cpp
+++ b/modules/extra/m_ldap.cpp
@@ -222,7 +222,10 @@ class ModuleLDAP : public Module, public Pipe
~ModuleLDAP()
{
for (std::map<Anope::string, LDAPService *>::iterator it = this->LDAPServices.begin(); it != this->LDAPServices.end(); ++it)
+ {
it->second->SetExitState();
+ it->second->Wakeup();
+ }
LDAPServices.clear();
}
@@ -239,7 +242,7 @@ class ModuleLDAP : public Module, public Pipe
for (i = 0, num = config.Enumerate("ldap"); i < num; ++i)
{
- if (config.ReadValue("ldap", "name", "", i) == cname)
+ if (config.ReadValue("ldap", "name", "main", i) == cname)
{
break;
}
@@ -250,6 +253,7 @@ class ModuleLDAP : public Module, public Pipe
Log(LOG_NORMAL, "ldap") << "LDAP: Removing server connection " << cname;
s->SetExitState();
+ s->Wakeup();
this->LDAPServices.erase(cname);
}
}
diff --git a/modules/extra/m_mysql.cpp b/modules/extra/m_mysql.cpp
index e26d13b6a..9895d025d 100644
--- a/modules/extra/m_mysql.cpp
+++ b/modules/extra/m_mysql.cpp
@@ -186,7 +186,7 @@ class ModuleSQL : public Module, public Pipe
for (i = 0, num = config.Enumerate("mysql"); i < num; ++i)
{
- if (config.ReadValue("mysql", "name", "", i) == cname)
+ if (config.ReadValue("mysql", "name", "main", i) == cname)
{
break;
}
diff --git a/modules/extra/ns_identify_ldap.cpp b/modules/extra/ns_identify_ldap.cpp
index 7bc237289..6e01e0103 100644
--- a/modules/extra/ns_identify_ldap.cpp
+++ b/modules/extra/ns_identify_ldap.cpp
@@ -68,7 +68,7 @@ class IdentifyInterface : public LDAPInterface, public Command
ircdproto->SendAccountLogin(u, u->Account());
ircdproto->SetAutoIdentificationToken(u);
- if (this_na && this_na->nc == na->nc)
+ if (this_na && this_na->nc == na->nc && this_na->nc->HasFlag(NI_UNCONFIRMED) == false)
u->SetMode(NickServ, UMODE_REGISTERED);
u->UpdateHost();
diff --git a/modules/protocol/bahamut.cpp b/modules/protocol/bahamut.cpp
index be782fe18..285fd316c 100644
--- a/modules/protocol/bahamut.cpp
+++ b/modules/protocol/bahamut.cpp
@@ -296,7 +296,8 @@ class BahamutIRCdMessage : public IRCdMessage
if (user->timestamp == convertTo<time_t>(params[7]) && (na = findnick(user->nick)))
{
user->Login(na->nc);
- user->SetMode(NickServ, UMODE_REGISTERED);
+ if (na->nc->HasFlag(NI_UNCONFIRMED) == false)
+ user->SetMode(NickServ, UMODE_REGISTERED);
}
else
validate_user(user);
diff --git a/modules/protocol/inspircd11.cpp b/modules/protocol/inspircd11.cpp
index 0689b8605..e4ccd90b6 100644
--- a/modules/protocol/inspircd11.cpp
+++ b/modules/protocol/inspircd11.cpp
@@ -296,7 +296,8 @@ class InspircdIRCdMessage : public IRCdMessage
if (na && na->nc->GetExtRegular("authenticationtoken", svidbuf) && svidbuf == params[0])
{
user->Login(na->nc);
- user->SetMode(NickServ, UMODE_REGISTERED);
+ if (na->nc->HasFlag(NI_UNCONFIRMED))
+ user->SetMode(NickServ, UMODE_REGISTERED);
}
else
validate_user(user);
diff --git a/modules/protocol/inspircd12.cpp b/modules/protocol/inspircd12.cpp
index d2ae35c9f..f89ef2dc9 100644
--- a/modules/protocol/inspircd12.cpp
+++ b/modules/protocol/inspircd12.cpp
@@ -264,7 +264,7 @@ bool event_metadata(const Anope::string &source, const std::vector<Anope::string
if (u && nc)
{
u->Login(nc);
- if (user_na && user_na->nc == nc)
+ if (user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false)
u->SetMode(NickServ, UMODE_REGISTERED);
}
}
diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp
index a0fd55481..908868463 100644
--- a/modules/protocol/inspircd20.cpp
+++ b/modules/protocol/inspircd20.cpp
@@ -274,7 +274,7 @@ bool event_metadata(const Anope::string &source, const std::vector<Anope::string
if (u && nc)
{
u->Login(nc);
- if (user_na && user_na->nc == nc)
+ if (user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false)
u->SetMode(NickServ, UMODE_REGISTERED);
}
}
diff --git a/modules/protocol/plexus.cpp b/modules/protocol/plexus.cpp
index 9d360312e..a7ebabd86 100644
--- a/modules/protocol/plexus.cpp
+++ b/modules/protocol/plexus.cpp
@@ -526,7 +526,7 @@ bool event_encap(const Anope::string &source, const std::vector<Anope::string> &
if (u && nc)
{
u->Login(nc);
- if (user_na && user_na->nc == nc)
+ if (user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false)
u->SetMode(NickServ, UMODE_REGISTERED);
}
}
diff --git a/modules/protocol/unreal32.cpp b/modules/protocol/unreal32.cpp
index 89940ab42..c510a4976 100644
--- a/modules/protocol/unreal32.cpp
+++ b/modules/protocol/unreal32.cpp
@@ -427,7 +427,8 @@ class Unreal32IRCdMessage : public IRCdMessage
if (na && user->timestamp == convertTo<time_t>(params[6]))
{
user->Login(na->nc);
- user->SetMode(NickServ, UMODE_REGISTERED);
+ if (na->nc->HasFlag(NI_UNCONFIRMED) == false)
+ user->SetMode(NickServ, UMODE_REGISTERED);
}
else
validate_user(user);
@@ -448,7 +449,8 @@ class Unreal32IRCdMessage : public IRCdMessage
if (na && user->timestamp == convertTo<time_t>(params[6]))
{
user->Login(na->nc);
- user->SetMode(NickServ, UMODE_REGISTERED);
+ if (na->nc->HasFlag(NI_UNCONFIRMED) == false)
+ user->SetMode(NickServ, UMODE_REGISTERED);
}
else
validate_user(user);
diff --git a/src/commands.cpp b/src/commands.cpp
index 425c72671..00fe6574c 100644
--- a/src/commands.cpp
+++ b/src/commands.cpp
@@ -65,7 +65,7 @@ void mod_run_cmd(BotInfo *bi, User *u, ChannelInfo *ci, Command *c, const Anope:
// Command requires registered users only
if (!c->HasFlag(CFLAG_ALLOW_UNREGISTERED) && !u->IsIdentified())
{
- u->SendMessage(bi, _(_(NICK_IDENTIFY_REQUIRED)), Config->s_NickServ.c_str());
+ u->SendMessage(bi, _(NICK_IDENTIFY_REQUIRED), Config->s_NickServ.c_str());
Log(LOG_COMMAND, "denied", bi) << "Access denied for unregistered user " << u->GetMask() << " with command " << command;
PopLanguage();
return;
diff --git a/src/config.cpp b/src/config.cpp
index cc0879936..ae8ccfc8c 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -480,7 +480,7 @@ bool ValidateEmailReg(ServerConfig *config, const Anope::string &tag, const Anop
{
if (config->NSEmailReg)
{
- if (value.equals_ci("preregexpire"))
+ if (value.equals_ci("unconfirmedexpire"))
{
if (!data.GetInteger() && !dotime(data.GetValue()))
throw ConfigException("The value for <" + tag + ":" + value + "> must be non-zero when e-mail registration are enabled!");
@@ -1070,6 +1070,7 @@ void ServerConfig::Read()
{"nickserv", "emailregistration", "no", new ValueContainerBool(&this->NSEmailReg), DT_BOOLEAN, NoValidation},
{"nickserv", "modules", "", new ValueContainerString(&NickCoreModules), DT_STRING, NoValidation},
{"nickserv", "forceemail", "no", new ValueContainerBool(&this->NSForceEmail), DT_BOOLEAN, ValidateEmailReg},
+ {"nickserv", "confirmemailchanges", "no", new ValueContainerBool(&this->NSConfirmEmailChanges), DT_BOOLEAN, NoValidation},
{"nickserv", "defaults", "secure memosignon memoreceive", new ValueContainerString(&NSDefaults), DT_STRING, NoValidation},
{"nickserv", "languages", "", new ValueContainerString(&this->Languages), DT_STRING, NoValidation},
{"nickserv", "defaultlanguage", "0", new ValueContainerString(&this->NSDefLanguage), DT_STRING, NoValidation},
@@ -1078,7 +1079,7 @@ void ServerConfig::Read()
{"nickserv", "expire", "21d", new ValueContainerTime(&this->NSExpire), DT_TIME, NoValidation},
{"nickserv", "suspendexpire", "0", new ValueContainerTime(&this->NSSuspendExpire), DT_TIME, NoValidation},
{"nickserv", "forbidexpire", "0", new ValueContainerTime(&this->NSForbidExpire), DT_TIME, NoValidation},
- {"nickserv", "preregexpire", "0", new ValueContainerTime(&this->NSRExpire), DT_TIME, ValidateEmailReg},
+ {"nickserv", "unconfirmedexpire", "0", new ValueContainerTime(&this->NSUnconfirmedExpire), DT_TIME, ValidateEmailReg},
{"nickserv", "maxaliases", "0", new ValueContainerUInt(&this->NSMaxAliases), DT_UINTEGER, NoValidation},
{"nickserv", "accessmax", "0", new ValueContainerUInt(&this->NSAccessMax), DT_UINTEGER, ValidateNotZero},
{"nickserv", "enforceruser", "", new ValueContainerString(&temp_nsuserhost), DT_STRING, ValidateNotEmpty},
diff --git a/src/mail.cpp b/src/mail.cpp
index 3a07f7e49..58a0ddac8 100644
--- a/src/mail.cpp
+++ b/src/mail.cpp
@@ -37,27 +37,6 @@ void MailThread::Run()
SetExitState();
}
-bool Mail(User *u, NickRequest *nr, BotInfo *service, const Anope::string &subject, const Anope::string &message)
-{
- if (!u || !nr || !service || subject.empty() || message.empty())
- return false;
-
- if (!Config->UseMail)
- u->SendMessage(service, _("Services have been configured to not send mail."));
- else if (Anope::CurTime - u->lastmail < Config->MailDelay)
- u->SendMessage(service, _("Please wait \002%d\002 seconds and retry."), Config->MailDelay - Anope::CurTime - u->lastmail);
- else if (nr->email.empty())
- u->SendMessage(service, _("E-mail for \002%s\002 is invalid."), nr->nick.c_str());
- else
- {
- u->lastmail = nr->lastmail = Anope::CurTime;
- threadEngine.Start(new MailThread(nr->nick, nr->email, subject, message));
- return true;
- }
-
- return false;
-}
-
bool Mail(User *u, NickCore *nc, BotInfo *service, const Anope::string &subject, const Anope::string &message)
{
if (!u || !nc || !service || subject.empty() || message.empty())
diff --git a/src/main.cpp b/src/main.cpp
index c59fe7829..563262195 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -137,7 +137,6 @@ extern void expire_all()
Log(LOG_DEBUG) << "Running expire routines";
expire_nicks();
expire_chans();
- expire_requests();
expire_exceptions();
FOREACH_MOD(I_OnDatabaseExpire, OnDatabaseExpire());
diff --git a/src/misc.cpp b/src/misc.cpp
index 9efacf314..0ad233402 100644
--- a/src/misc.cpp
+++ b/src/misc.cpp
@@ -69,43 +69,6 @@ int tolower(char c)
/*************************************************************************/
-/**
- * merge_args: Take an argument count and argument vector and merge them
- * into a single string in which each argument is separated by
- * a space.
- * @param int Number of Args
- * @param argv Array
- * @return string of the merged array
- */
-const char *merge_args(int argc, const char **argv)
-{
- int i;
- static char s[4096];
- char *t;
-
- t = s;
- for (i = 0; i < argc; ++i)
- t += snprintf(t, sizeof(s) - (t - s), "%s%s", *argv++, i < argc - 1 ? " " : "");
- return s;
-}
-
-/*
- * XXX: temporary "safe" version to avoid casting, it's still ugly.
- */
-const char *merge_args(int argc, char **argv)
-{
- int i;
- static char s[4096];
- char *t;
-
- t = s;
- for (i = 0; i < argc; ++i)
- t += snprintf(t, sizeof(s) - (t - s), "%s%s", *argv++, i < argc - 1 ? " " : "");
- return s;
-}
-
-/*************************************************************************/
-
NumberList::NumberList(const Anope::string &list, bool descending) : is_valid(true), desc(descending)
{
Anope::string error;
@@ -839,12 +802,12 @@ bool Anope::Match(const Anope::string &str, const Anope::string &mask, bool case
* @param ... any number of parameters
* @return a Anope::string
*/
-Anope::string Anope::printf(const char *fmt, ...)
+Anope::string Anope::printf(const Anope::string &fmt, ...)
{
va_list args;
char buf[1024];
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), fmt, args);
+ va_start(args, fmt.c_str());
+ vsnprintf(buf, sizeof(buf), fmt.c_str(), args);
va_end(args);
return buf;
}
diff --git a/src/nickalias.cpp b/src/nickalias.cpp
index 258e46a07..b82e27ce6 100644
--- a/src/nickalias.cpp
+++ b/src/nickalias.cpp
@@ -1,25 +1,6 @@
#include "services.h"
#include "modules.h"
-NickRequest::NickRequest(const Anope::string &nickname)
-{
- if (nickname.empty())
- throw CoreException("Empty nick passed to NickRequest constructor");
-
- this->requested = this->lastmail = 0;
-
- this->nick = nickname;
-
- NickRequestList[this->nick] = this;
-}
-
-NickRequest::~NickRequest()
-{
- FOREACH_MOD(I_OnDelNickRequest, OnDelNickRequest(this));
-
- NickRequestList.erase(this->nick);
-}
-
/** Default constructor
* @param nick The nick
* @param nickcore The nickcofe for this nick
diff --git a/src/nickserv.cpp b/src/nickserv.cpp
index 4a45e6ce2..e12673d08 100644
--- a/src/nickserv.cpp
+++ b/src/nickserv.cpp
@@ -14,7 +14,6 @@
nickalias_map NickAliasList;
nickcore_map NickCoreList;
-nickrequest_map NickRequestList;
typedef std::map<Anope::string, NickServCollide *> nickservcollides_map;
typedef std::map<Anope::string, NickServRelease *> nickservreleases_map;
@@ -169,13 +168,6 @@ void ns_init()
int validate_user(User *u)
{
- NickRequest *nr = findrequestnick(u->nick);
- if (nr)
- {
- u->SendMessage(NickServ, _(NICK_IS_PREREG));
- return 0;
- }
-
NickAlias *na = findnick(u->nick);
if (!na)
return 0;
@@ -291,32 +283,8 @@ void expire_nicks()
}
}
-void expire_requests()
-{
- for (nickrequest_map::const_iterator it = NickRequestList.begin(), it_end = NickRequestList.end(); it != it_end; )
- {
- NickRequest *nr = it->second;
- ++it;
-
- if (Config->NSRExpire && Anope::CurTime - nr->requested >= Config->NSRExpire)
- {
- Log(LOG_NORMAL, "expire") << "Request for nick " << nr->nick << " expiring";
- delete nr;
- }
- }
-}
-
/*************************************************************************/
-NickRequest *findrequestnick(const Anope::string &nick)
-{
- nickrequest_map::const_iterator it = NickRequestList.find(nick);
-
- if (it != NickRequestList.end())
- return it->second;
- return NULL;
-}
-
NickAlias *findnick(const Anope::string &nick)
{
FOREACH_MOD(I_OnFindNick, OnFindNick(nick));
diff --git a/src/users.cpp b/src/users.cpp
index fa486935f..a11e1b5ce 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -806,7 +806,8 @@ User *do_nick(const Anope::string &source, const Anope::string &nick, const Anop
user->UpdateHost();
do_on_id(user);
ircdproto->SetAutoIdentificationToken(user);
- user->SetMode(NickServ, UMODE_REGISTERED);
+ if (na->nc->HasFlag(NI_UNCONFIRMED) == false)
+ user->SetMode(NickServ, UMODE_REGISTERED);
Log(NickServ) << user->GetMask() << " automatically identified for group " << user->Account()->display;
}