Kod: Kodu kopyalamak için üzerine çift tıklayın!
/* Main NickServ module.
*
* IRC Services is copyright (c) 1996-2005 Andrew Church.
* E-mail: <
Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.
>
* Parts written by Andrew Kempe and others.
* This program is free but copyrighted software; see the file COPYING for
* details.
*/
#include "services.h"
#include "modules.h"
#include "conffile.h"
#include "language.h"
#include "commands.h"
#include "encrypt.h"
#include "modules/operserv/operserv.h"
#include "nickserv.h"
#include "ns-local.h"
/*************************************************************************/
static Module *module;
static int cb_command = -1;
static int cb_help = -1;
static int cb_help_cmds = -1;
int cb_reglink_check = -1; /* called from util.c */
static int cb_registered = -1;
static int cb_id_check = -1;
static int cb_identified = -1;
static int db_opened = 0;
char *s_NickServ;
static char *desc_NickServ;
static char *NickDBName;
EXPORT_VAR(char *,s_NickServ)
int32 NSRegEmailMax;
int NSRequireEmail;
time_t NSRegDelay;
time_t NSInitialRegDelay;
int32 NSDefFlags;
time_t N***pire;
time_t N***pireWarning;
int NSShowPassword;
char * NSEnforcerUser;
char * NSEnforcerHost;
int NSForceNickChange;
time_t NSReleaseTimeout;
int NSAllowKillImmed;
int NSListOpersOnly;
int32 NSListMax;
int NSSecureAdmins;
time_t NSSuspendExpire;
time_t NSSuspendGrace;
static int NSHelpWarning;
static int NSEnableDropEmail;
static time_t NSDropEmailExpire;
/*************************************************************************/
static void do_help(User *u);
static void do_register(User *u);
static void do_identify(User *u);
static void do_drop(User *u);
static void do_dropnick(User *u);
static void do_dropemail(User *u);
static void do_dropemail_confirm(User *u);
static void do_info(User *u);
static void do_listchans(User *u);
static void do_list(User *u);
static void do_listemail(User *u);
static void do_recover(User *u);
static void do_release(User *u);
static void do_ghost(User *u);
static void do_status(User *u);
static void do_getpass(User *u);
static void do_forbid(User *u);
static void do_suspend(User *u);
static void do_unsuspend(User *u);
#ifdef DEBUG_COMMANDS
static void do_listnick(User *u);
#endif
/*************************************************************************/
static Command cmds[] = {
{ "HELP", do_help, NULL, -1, -1,-1 },
{ "REGISTER", do_register, NULL, NICK_HELP_REGISTER, -1,-1 },
{ "IDENTIFY", do_identify, NULL, NICK_HELP_IDENTIFY, -1,-1 },
{ "SIDENTIFY",do_identify, NULL, -1, -1,-1 },
{ "DROP", do_drop, NULL, NICK_HELP_DROP, -1,-1 },
{ "SET", do_set, NULL, NICK_HELP_SET,
-1, NICK_OPER_HELP_SET },
{ "SET PASSWORD", NULL, NULL, NICK_HELP_SET_PASSWORD, -1,-1 },
{ "SET URL", NULL, NULL, NICK_HELP_SET_URL, -1,-1 },
{ "SET EMAIL", NULL, NULL, NICK_HELP_SET_EMAIL, -1,-1 },
{ "SET INFO", NULL, NULL, NICK_HELP_SET_INFO, -1,-1 },
{ "SET MSN", NULL, NULL, NICK_HELP_SET_MSN, -1,-1 },
{ "SET ICQ", NULL, NULL, NICK_HELP_SET_ICQ, -1,-1 },
{ "SET SEHIR", NULL, NULL, NICK_HELP_SET_LOCATION, -1,-1 },
{ "SET ISIM", NULL, NULL, NICK_HELP_SET_ISIM, -1,-1 },
{ "SET YAS", NULL, NULL, NICK_HELP_SET_YAS, -1,-1 },
{ "SET KILL", NULL, NULL, NICK_HELP_SET_KILL, -1,-1 },
{ "SET SECURE", NULL, NULL, NICK_HELP_SET_SECURE, -1,-1 },
{ "SET PRIVATE", NULL, NULL, NICK_HELP_SET_PRIVATE, -1,-1 },
{ "SET HIDE", NULL, NULL, NICK_HELP_SET_HIDE, -1,-1 },
{ "SET TIMEZONE", NULL, NULL, NICK_HELP_SET_TIMEZONE, -1,-1 },
{ "SET NOEXPIRE", NULL, NULL, -1, -1,
NICK_OPER_HELP_SET_NOEXPIRE },
{ "UNSET", do_unset, NULL, NICK_HELP_UNSET,
-1, NICK_OPER_HELP_UNSET },
{ "RECOVER", do_recover, NULL, NICK_HELP_RECOVER, -1,-1 },
{ "RELEASE", do_release, NULL, NICK_HELP_RELEASE, -1,-1 },
{ "GHOST", do_ghost, NULL, NICK_HELP_GHOST, -1,-1 },
{ "INFO", do_info, NULL, NICK_HELP_INFO,
-1, NICK_OPER_HELP_INFO },
{ "LIST", do_list, NULL, -1,
NICK_HELP_LIST, NICK_OPER_HELP_LIST },
{ "LISTEMAIL",do_listemail,NULL, -1,
NICK_HELP_LISTEMAIL, NICK_OPER_HELP_LISTEMAIL },
{ "STATUS", do_status, NULL, NICK_HELP_STATUS, -1,-1 },
{ "LISTCHANS",do_listchans,NULL, NICK_HELP_LISTCHANS,
-1, NICK_OPER_HELP_LISTCHANS },
{ "DROPNICK", do_dropnick, is_services_oper, -1,
-1, NICK_OPER_HELP_DROPNICK },
{ "DROPEMAIL",do_dropemail,is_services_oper, -1,
-1, NICK_OPER_HELP_DROPEMAIL },
{ "DROPEMAIL-CONFIRM", do_dropemail_confirm, is_services_oper, -1,
-1, NICK_OPER_HELP_DROPEMAIL },
{ "GETPASS", do_getpass, is_services_admin, -1,
-1, NICK_OPER_HELP_GETPASS },
{ "FORBID", do_forbid, is_services_oper, -1,
-1, NICK_OPER_HELP_FORBID },
{ "SUSPEND", do_suspend, is_services_oper, -1,
-1, NICK_OPER_HELP_SUSPEND },
{ "UNSUSPEND",do_unsuspend,is_services_oper, -1,
-1, NICK_OPER_HELP_UNSUSPEND },
#ifdef DEBUG_COMMANDS
{ "LISTNICK", do_listnick, is_services_admin, -1, -1, -1 },
#endif
{ NULL }
};
/*************************************************************************/
/************************ Main NickServ routines *************************/
/*************************************************************************/
/* Introduce the NickServ pseudoclient. */
static int introduce_nickserv(const char *nick)
{
if (!nick || irc_stricmp(nick, s_NickServ) == 0) {
char modebuf[BUFSIZE];
snprintf(modebuf, sizeof(modebuf), "o%s", pseudoclient_modes);
send_nick(s_NickServ, ServiceUser, ServiceHost, ServerName,
desc_NickServ, modebuf);
return nick ? 1 : 0;
}
return 0;
}
/*************************************************************************/
/* Main NickServ routine. */
static int nickserv(const char *source, const char *target, char *buf)
{
char *cmd;
User *u = get_user(source);
if (irc_stricmp(target, s_NickServ) != 0)
return 0;
if (!u) {
module_log("user record for %s not found", source);
notice(s_NickServ, source,
getstring(NULL, INTERNAL_ERROR));
return 1;
}
cmd = strtok(buf, " ");
if (!cmd) {
return 1;
} else if (stricmp(cmd, "\1PING") == 0) {
const char *s;
if (!(s = strtok(NULL, "")))
s = "\1";
notice(s_NickServ, source, "\1PING %s", s);
} else {
if (call_callback_2(module, cb_command, u, cmd) <= 0)
run_cmd(s_NickServ, u, module, cmd);
}
return 1;
}
/*************************************************************************/
/* Return a /WHOIS response for NickServ. */
static int nickserv_whois(const char *source, char *who, char *extra)
{
if (irc_stricmp(who, s_NickServ) != 0)
return 0;
send_cmd(ServerName, "311 %s %s %s %s * :%s", source, who,
ServiceUser, ServiceHost, desc_NickServ);
send_cmd(ServerName, "312 %s %s %s :%s", source, who,
ServerName, ServerDesc);
send_cmd(ServerName, "313 %s %s :is a network service", source, who);
send_cmd(ServerName, "318 %s %s End of /WHOIS response.", source, who);
return 1;
}
/*************************************************************************/
/* Save nickname database. */
static int do_save_data()
{
sync_nick_db(NickDBName);
return 0;
}
/*************************************************************************/
/*************************************************************************/
/* Callback for users connecting to the network. */
static int do_user_create(User *user, int ac, char **av)
{
validate_user(user);
return 0;
}
/*************************************************************************/
/* Callbacks for users changing nicknames (before and after). */
static int do_user_nickchange_before(User *user, const char *newnick)
{
/* Changing nickname case isn't a real change; pop out immediately
* in that case. */
if (irc_stricmp(newnick, user->nick) == 0)
return 0;
cancel_user(user);
return 0;
}
static int do_user_nickchange_after(User *user, const char *oldnick)
{
/* Changing nickname case isn't a real change; pop out immediately
* in that case. */
if (irc_stricmp(oldnick, user->nick) == 0)
return 0;
user->my_signon = time(NULL);
validate_user(user);
if (usermode_reg) {
if (user_identified(user)) {
send_cmd(s_NickServ, "SVSMODE %s :+%s", user->nick,
mode_flags_to_string(usermode_reg, MODE_USER));
user->mode |= usermode_reg;
} else {
send_cmd(s_NickServ, "SVSMODE %s :-%s", user->nick,
mode_flags_to_string(usermode_reg, MODE_USER));
user->mode &= ~usermode_reg;
}
}
return 0;
}
/*************************************************************************/
/* Callback for users disconnecting from the network. */
static int do_user_delete(User *user, const char *reason)
{
NickInfo *ni = user->ni;
int i, j;
if (user_recognized(user)) {
free(ni->last_quit);
ni->last_quit = *reason ? sstrdup(reason) : NULL;
put_nickinfo(ni);
}
ARRAY_FOREACH (i, user->id_nicks) {
NickGroupInfo *ngi = get_ngi_id(user->id_nicks[i]);
if (!ngi)
continue;
ARRAY_SEARCH_PLAIN_SCALAR(ngi->id_users, user, j);
if (j < ngi->id_users_count) {
ARRAY_REMOVE(ngi->id_users, j);
} else {
module_log("BUG: do_user_delete(): nickgroup %u listed in"
" id_nicks for user %p (%s), but user not in"
" id_users!", ngi->id, user, user->nick);
}
}
cancel_user(user);
return 0;
}
/*************************************************************************/
/* Callback for REGISTER/LINK check; we disallow registration/linking of
* the NickServ pseudoclient nickname or guest nicks. This is done here
* instead of in the routines themselves to avoid duplication of code at an
* insignificant performance cost.
*/
static int do_reglink_check(const User *u, const char *nick,
const char *pass, const char *email)
{
if ((protocol_features & PF_CHANGENICK) && is_guest_nick(u->nick)) {
/* Don't allow guest nicks to be registered or linked. This check
* has to be done regardless of the state of NSForceNickChange
* because other modules might take advantage of forced nick
* changing. */
return 1;
}
return irc_stricmp(nick, s_NickServ) == 0;
}
/*************************************************************************/
/*********************** NickServ command routines ***********************/
/*************************************************************************/
/* Return a help message. */
static void do_help(User *u)
{
char *cmd = strtok_remaining();
if (!cmd) {
notice_help(s_NickServ, u, NICK_HELP);
if (N***pire)
notice_help(s_NickServ, u, NICK_HELP_EXPIRES,
maketime(u->ngi,N***pire,0));
if (NSHelpWarning)
notice_help(s_NickServ, u, NICK_HELP_WARNING);
} else if (call_callback_2(module, cb_help, u, cmd) > 0) {
return;
} else if (stricmp(cmd, "COMMANDS") == 0) {
notice_help(s_NickServ, u, NICK_HELP_COMMANDS);
if (find_module("nickserv/mail-auth"))
notice_help(s_NickServ, u, NICK_HELP_COMMANDS_AUTH);
notice_help(s_NickServ, u, NICK_HELP_COMMANDS_IDENTIFY);
if (find_module("nickserv/sendpass"))
notice_help(s_NickServ, u, NICK_HELP_COMMANDS_SENDPASS);
notice_help(s_NickServ, u, NICK_HELP_COMMANDS_DROP);
if (find_module("nickserv/link"))
notice_help(s_NickServ, u, NICK_HELP_COMMANDS_LINK);
if (find_module("nickserv/oldlink"))
notice_help(s_NickServ, u, NICK_HELP_COMMANDS_OLDLINK);
if (find_module("nickserv/access"))
notice_help(s_NickServ, u, NICK_HELP_COMMANDS_ACCESS);
if (find_module("nickserv/autojoin"))
notice_help(s_NickServ, u, NICK_HELP_COMMANDS_AJOIN);
notice_help(s_NickServ, u, NICK_HELP_COMMANDS_SET);
if (!NSListOpersOnly)
notice_help(s_NickServ, u, NICK_HELP_COMMANDS_LIST);
notice_help(s_NickServ, u, NICK_HELP_COMMANDS_LISTCHANS);
call_callback_2(module, cb_help_cmds, u, 0);
if (is_oper(u)) {
notice_help(s_NickServ, u, NICK_OPER_HELP_COMMANDS);
if (NSEnableDropEmail)
notice_help(s_NickServ, u, NICK_OPER_HELP_COMMANDS_DROPEMAIL);
if (EnableGetpass)
notice_help(s_NickServ, u, NICK_OPER_HELP_COMMANDS_GETPASS);
notice_help(s_NickServ, u, NICK_OPER_HELP_COMMANDS_FORBID);
if (find_module("nickserv/oldlink"))
notice_help(s_NickServ, u, NICK_OPER_HELP_COMMANDS_LISTLINKS);
if (NSListOpersOnly)
notice_help(s_NickServ, u, NICK_HELP_COMMANDS_LIST);
if (find_module("nickserv/mail-auth"))
notice_help(s_NickServ, u, NICK_OPER_HELP_COMMANDS_SETAUTH);
call_callback_2(module, cb_help_cmds, u, 1);
notice_help(s_NickServ, u, NICK_OPER_HELP_COMMANDS_END);
}
} else if (stricmp(cmd, "REGISTER") == 0) {
notice_help(s_NickServ, u, NICK_HELP_REGISTER,
getstring(u->ngi,NICK_REGISTER_SYNTAX));
notice_help(s_NickServ, u, NICK_HELP_REGISTER_EMAIL);
notice_help(s_NickServ, u, NICK_HELP_REGISTER_END);
} else if (stricmp(cmd, "DROP") == 0) {
notice_help(s_NickServ, u, NICK_HELP_DROP);
if (find_module("nickserv/link") || find_module("nickserv/oldlink"))
notice_help(s_NickServ, u, NICK_HELP_DROP_LINK);
notice_help(s_NickServ, u, NICK_HELP_DROP_END);
} else if ((stricmp(cmd, "DROPEMAIL") == 0
|| stricmp(cmd, "DROPEMAIL-CONFIRM") == 0)
&& NSEnableDropEmail
&& is_oper(u)
) {
notice_help(s_NickServ, u, NICK_OPER_HELP_DROPEMAIL,
maketime(u->ngi,NSDropEmailExpire,0));
} else if (stricmp(cmd, "SET") == 0) {
notice_help(s_NickServ, u, NICK_HELP_SET);
if (find_module("nickserv/link"))
notice_help(s_NickServ, u, NICK_HELP_SET_OPTION_MAINNICK);
notice_help(s_NickServ, u, NICK_HELP_SET_END);
if (is_oper(u))
notice_help(s_NickServ, u, NICK_OPER_HELP_SET);
} else if (strnicmp(cmd, "SET", 3) == 0
&& isspace(cmd[3])
&& stricmp(cmd+4+strspn(cmd+4," \t"), "LANGUAGE") == 0) {
int i;
notice_help(s_NickServ, u, NICK_HELP_SET_LANGUAGE);
for (i = 0; i < NUM_LANGS && langlist[i] >= 0; i++) {
notice(s_NickServ, u->nick, " %2d) %s",
i+1, getstring_lang(langlist[i],LANG_NAME));
}
} else if (stricmp(cmd, "INFO") == 0) {
notice_help(s_NickServ, u, NICK_HELP_INFO);
if (find_module("nickserv/mail-auth"))
notice_help(s_NickServ, u, NICK_HELP_INFO_AUTH);
if (is_oper(u))
notice_help(s_NickServ, u, NICK_OPER_HELP_INFO);
} else if (stricmp(cmd, "LIST") == 0) {
if (is_oper(u))
notice_help(s_NickServ, u, NICK_OPER_HELP_LIST);
else
notice_help(s_NickServ, u, NICK_HELP_LIST);
if (NSListOpersOnly)
notice_help(s_NickServ, u, NICK_HELP_LIST_OPERSONLY);
} else if (stricmp(cmd, "RECOVER") == 0) {
notice_help(s_NickServ, u, NICK_HELP_RECOVER,
maketime(u->ngi,NSReleaseTimeout,MT_SECONDS));
} else if (stricmp(cmd, "RELEASE") == 0) {
notice_help(s_NickServ, u, NICK_HELP_RELEASE,
maketime(u->ngi,NSReleaseTimeout,MT_SECONDS));
} else if (stricmp(cmd, "SUSPEND") == 0 && is_oper(u)) {
notice_help(s_NickServ, u, NICK_OPER_HELP_SUSPEND, s_OperServ);
} else {
help_cmd(s_NickServ, u, module, cmd);
}
}
/*************************************************************************/
/* Register a nick. */
static void do_register(User *u)
{
NickInfo *ni;
NickGroupInfo *ngi;
char *pass = strtok(NULL, " ");
char *email = strtok(NULL, " ");
int n;
time_t now = time(NULL);
if (readonly) {
notice_lang(s_NickServ, u, NICK_REGISTRATION_DISABLED);
return;
}
if (now < u->lastnickreg + NSRegDelay) {
time_t left = (u->lastnickreg + NSRegDelay) - now;
notice_lang(s_NickServ, u, NICK_REG_PLEASE_WAIT,
maketime(u->ngi, left, MT_SECONDS));
} else if (time(NULL) < u->my_signon + NSInitialRegDelay) {
time_t left = (u->my_signon + NSInitialRegDelay) - now;
notice_lang(s_NickServ, u, NICK_REG_PLEASE_WAIT_FIRST,
maketime(u->ngi, left, MT_SECONDS));
} else if (!pass || (NSRequireEmail && !email)
|| (stricmp(pass, u->nick) == 0
&& (strtok(NULL, "")
|| (email && (!strchr(email,'@')
|| !strchr(email,'.')))))
) {
/* No password/email, or they (apparently) tried to include the nick
* in the command. */
syntax_error(s_NickServ, u, "REGISTER", NICK_REGISTER_SYNTAX);
} else if (!reglink_check(u, u->nick, pass, email)) {
/* Denied by the callback. */
notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED, u->nick);
return;
} else if (u->ni) { /* i.e. there's already such a nick regged */
if (u->ni->status & NS_VERBOTEN) {
module_log("%s@%s tried to register forbidden nick %s",
u->username, u->host, u->nick);
notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED, u->nick);
} else {
if (u->ngi->suspendinfo)
module_log("%s@%s tried to register suspended nick %s",
u->username, u->host, u->nick);
notice_lang(s_NickServ, u, NICK_X_ALREADY_REGISTERED, u->nick);
}
} else if (u->ngi == NICKGROUPINFO_INVALID) {
module_log("%s@%s tried to register nick %s with missing nick group",
u->username, u->host, u->nick);
notice_lang(s_NickServ, u, NICK_REGISTRATION_FAILED);
} else if (stricmp(pass, u->nick) == 0
|| (StrictPasswords && strlen(pass) < 5)
) {
notice_lang(s_NickServ, u, MORE_OBSCURE_PASSWORD);
} else if (email && !valid_email(email)) {
/* Display the syntax as well in case the user just got E-mail and
* password backwards. Don't use syntax_error(), because that also
* prints a "for more help" message which might just confuse the
* user more. */
char buf[BUFSIZE];
snprintf(buf, sizeof(buf), getstring(u->ngi,NICK_REGISTER_SYNTAX),
"REGISTER");
notice_lang(s_NickServ, u, SYNTAX_ERROR, buf);
notice_lang(s_NickServ, u, BAD_EMAIL);
} else if (NSRegEmailMax && email && !is_services_admin(u)
&& ((n = count_nicks_with_email(email)) < 0
|| n >= NSRegEmailMax)) {
if (n < 0) {
notice_lang(s_NickServ, u, NICK_REGISTER_EMAIL_UNAUTHED);
} else {
notice_lang(s_NickServ, u, NICK_REGISTER_TOO_MANY_NICKS, n,
NSRegEmailMax);
}
} else {
int replied = 0;
int len = strlen(pass), max;
char passbuf[PASSMAX];
/* Make sure the password will fit in a PASSMAX-size buffer */
max = encrypt_check_len(len, PASSMAX);
/* Require the original password (including trailing NULL) to fit
* in a PASSMAX-size buffer as well */
if ((max == 0 && len > PASSMAX-1) || max > PASSMAX-1)
max = PASSMAX-1;
/* Truncate password if too long */
if (max > 0) {
memset(pass+max, 0, len-max);
len = max;
notice_lang(s_NickServ, u, PASSWORD_TRUNCATED, max);
}
/* Encrypt password */
if (encrypt(pass, len, passbuf, PASSMAX) < 0) {
memset(pass, 0, len);
module_log("Failed to encrypt password for %s (register)",
u->nick);
notice_lang(s_NickServ, u, NICK_REGISTRATION_FAILED);
return;
}
/* Do nick setup stuff */
ni = makenick(u->nick, &ngi);
if (!ni) {
module_log("makenick(%s) failed", u->nick);
notice_lang(s_NickServ, u, NICK_REGISTRATION_FAILED);
return;
}
memcpy(ngi->pass, passbuf, PASSMAX);
memset(passbuf, 0, PASSMAX);
ni->time_registered = ni->last_seen = time(NULL);
ni->authstat = NA_IDENTIFIED | NA_RECOGNIZED;
if (email)
ngi->email = sstrdup(email);
ngi->flags = NSDefFlags;
ngi->memos.memomax = MEMOMAX_DEFAULT;
ngi->channelmax = CHANMAX_DEFAULT;
ngi->language = LANG_DEFAULT;
ngi->timezone = TIMEZONE_DEFAULT;
call_callback_4(module, cb_registered, u, ni, ngi, &replied);
/* If the IDENTIFIED flag is still set (a module might have
* cleared it, e.g. mail-auth), record the ID stamp */
if (nick_identified(ni))
ni->id_stamp = u->servicestamp;
/* Link back and forth to user record and store modified data */
u->ni = ni;
u->ngi = ngi;
ni->user = u;
update_userinfo(u);
put_nickinfo(ni);
put_nickgroupinfo(ngi);
/* Tell people about it */
if (email) {
module_log("%s registered by %s@%s (%s)",
u->nick, u->username, u->host, email);
} else {
module_log("%s registered by %s@%s",
u->nick, u->username, u->host);
}
if (!replied)
notice_lang(s_NickServ, u, NICK_REGISTERED, u->nick);
if (NSShowPassword)
notice_lang(s_NickServ, u, NICK_PASSWORD_IS, pass);
/* Clear password from memory and other last-minute things */
memset(pass, 0, len);
/* Note time REGISTER command was used */
u->lastnickreg = time(NULL);
/* Set +r (or other registered-nick mode) if IDENTIFIED is still
* set. */
if (nick_identified(ni) && usermode_reg) {
send_cmd(s_NickServ, "SVSMODE %s :+%s", u->nick,
mode_flags_to_string(usermode_reg, MODE_USER));
}
}
}
/*************************************************************************/
static void do_identify(User *u)
{
char *pass = strtok_remaining();
NickInfo *ni = NULL;
NickGroupInfo *ngi = NULL;
if (!pass) {
syntax_error(s_NickServ, u, "IDENTIFY", NICK_IDENTIFY_SYNTAX);
} else if (!(ni = u->ni)) {
notice_lang(s_NickServ, u, NICK_NOT_REGISTERED);
} else if (ni->status & NS_VERBOTEN) {
notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, u->nick);
} else if (!(ngi = u->ngi) || ngi == NICKGROUPINFO_INVALID) {
module_log("IDENTIFY: missing NickGroupInfo for %s", u->nick);
notice_lang(s_NickServ, u, NICK_NOT_REGISTERED);
} else if (ngi->suspendinfo) {
notice_lang(s_NickServ, u, NICK_X_SUSPENDED, u->nick);
} else if (!nick_check_password(u, u->ni, pass, "IDENTIFY",
NICK_IDENTIFY_FAILED)) {
/* nothing */
} else if (NSRequireEmail && !ngi->email) {
ni->authstat |= NA_IDENT_NOMAIL;
notice_lang(s_NickServ, u, NICK_IDENTIFY_EMAIL_MISSING, s_NickServ);
} else if (call_callback_2(module, cb_id_check, u, pass) <= 0) {
int old_authstat = ni->authstat;
set_identified(u, ni, ngi);
module_log("%s!%s@%s identified for nick %s",
u->nick, u->username, u->host, u->nick);
notice_lang(s_NickServ, u, NICK_IDENTIFY_SUCCEEDED);
send_cmd(s_NickServ, "CHGHOST %s %s.Yuzukchat.Net", u->nick, u->nick);
send_cmd(s_NickServ, "CHGHOST RainmaN Yuzukchat.Net", u->nick, u->nick);
send_cmd(s_NickServ, "NOTICE %s :[VHost] %s.Yuzukchat.Net adresine sahipsiniz.", u->nick, u->nick);
call_callback_2(module, cb_identified, u, old_authstat);
}
}
/*************************************************************************/
static void do_drop(User *u)
{
char *pass = strtok(NULL, " ");
NickInfo *ni = u->ni;
NickGroupInfo *ngi = (u->ngi==NICKGROUPINFO_INVALID ? NULL : u->ngi);
if (readonly && !is_services_admin(u)) {
notice_lang(s_NickServ, u, NICK_DROP_DISABLED);
return;
}
if (!pass || strtok_remaining()) {
syntax_error(s_NickServ, u, "DROP", NICK_DROP_SYNTAX);
if (find_module("nickserv/link") || find_module("nickserv/oldlink"))
notice_lang(s_NickServ, u, NICK_DROP_WARNING);
} else if (!ni || !ngi) {
notice_lang(s_NickServ, u, NICK_NOT_REGISTERED);
} else if (ngi->suspendinfo) {
notice_lang(s_NickServ, u, NICK_X_SUSPENDED, u->nick);
} else if (!nick_check_password(u, u->ni, pass, "DROP",
NICK_DROP_FAILED)) {
/* nothing */
} else {
if (readonly) /* they must be a servadmin in this case */
notice_lang(s_NickServ, u, READ_ONLY_MODE);
drop_nickgroup(ngi, u, NULL);
notice_lang(s_NickServ, u, NICK_DROPPED);
}
}
/*************************************************************************/
/* Services admin function to drop another user's nickname. Privileges
* assumed to be pre-checked.
*/
static void do_dropnick(User *u)
{
char *nick = strtok(NULL, " ");
NickInfo *ni;
NickGroupInfo *ngi;
#ifdef CLEAN_COMPILE
ngi = NULL;
#endif
if (!nick) {
syntax_error(s_NickServ, u, "DROPNICK", NICK_DROPNICK_SYNTAX);
} else if (!(ni = get_nickinfo(nick))) {
notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick);
} else if (ni->nickgroup && !(ngi = get_ngi(ni))) {
notice_lang(s_NickServ, u, INTERNAL_ERROR);
} else if (NSSecureAdmins && nick_is_services_admin(ni) &&
!is_services_root(u)) {
notice_lang(s_NickServ, u, PERMISSION_DENIED);
} else {
if (readonly)
notice_lang(s_NickServ, u, READ_ONLY_MODE);
if (ni->nickgroup) {
drop_nickgroup(ngi, u, PTR_INVALID);
} else {
module_log("%s!%s@%s dropped forbidden nick %s",
u->nick, u->username, u->host, ni->nick);
delnick(ni);
}
notice_lang(s_NickServ, u, NICK_X_DROPPED, nick);
}
}
/*************************************************************************/
/* Services admin function to drop all nicknames whose E-mail address
* matches the given mask. Privileges assumed to be pre-checked.
*/
/* List of recent DROPEMAILs for CONFIRM */
static struct {
char sender[NICKMAX]; /* Who sent the command (empty = no entry) */
char mask[BUFSIZE]; /* What mask was used */
int count;
time_t sent; /* When the command was sent */
} dropemail_buffer[DROPEMAIL_BUFSIZE];
static void do_dropemail(User *u)
{
char *mask = strtok(NULL, " ");
NickGroupInfo *ngi;
int count, i, found;
/* Parameter check */
if (!mask || strtok_remaining()) {
syntax_error(s_NickServ, u, "DROPEMAIL", NICK_DROPEMAIL_SYNTAX);
return;
}
if (strlen(mask) > sizeof(dropemail_buffer[0].mask)-1) {
notice_lang(s_NickServ, u, NICK_DROPEMAIL_PATTERN_TOO_LONG,
sizeof(dropemail_buffer[0].mask)-1);
return;
}
/* Count nicks matching this mask; exit if none found */
if (strcmp(mask,"-") == 0)
mask = NULL;
count = 0;
for (ngi = first_nickgroupinfo(); ngi; ngi = next_nickgroupinfo()) {
if ((mask && ngi->email && match_wild_nocase(mask,ngi->email))
|| (!mask && !ngi->email)
) {
count += ngi->nicks_count;
}
}
if (!count) {
notice_lang(s_NickServ, u, NICK_DROPEMAIL_NONE);
return;
}
if (mask == NULL)
mask = "-";
/* Clear out any previous entries for this sender/mask */
for (i = 0; i < DROPEMAIL_BUFSIZE; i++) {
if (irc_stricmp(u->nick, dropemail_buffer[i].sender) == 0
&& stricmp(mask, dropemail_buffer[i].mask) == 0
) {
memset(&dropemail_buffer[i], 0, sizeof(dropemail_buffer[i]));
}
}
/* Register command in buffer */
found = -1;
for (i = 0; i < DROPEMAIL_BUFSIZE; i++) {
if (!*dropemail_buffer[i].sender) {
found = i;
break;
}
}
if (found < 0) {
found = 0;
for (i = 1; i < DROPEMAIL_BUFSIZE; i++) {
if (dropemail_buffer[i].sent < dropemail_buffer[found].sent)
found = i;
}
}
memset(&dropemail_buffer[found], 0, sizeof(dropemail_buffer[found]));
strscpy(dropemail_buffer[found].sender, u->nick,
sizeof(dropemail_buffer[found].sender));
strscpy(dropemail_buffer[found].mask, mask,
sizeof(dropemail_buffer[found].mask));
dropemail_buffer[found].sent = time(NULL);
dropemail_buffer[found].count = count;
/* Send count and prompt for confirmation */
notice_lang(s_NickServ, u, NICK_DROPEMAIL_COUNT, count, s_NickServ, mask);
}
static void do_dropemail_confirm(User *u)
{
char *mask = strtok(NULL, " ");
NickGroupInfo *ngi;
int i;
/* Parameter check */
if (!mask || strtok_remaining()) {
syntax_error(s_NickServ, u, "DROPEMAIL-CONFIRM",
NICK_DROPEMAIL_CONFIRM_SYNTAX);
return;
}
/* Make sure this is a DROPEMAIL that (1) we've seen and (2) hasn't
* expired */
for (i = 0; i < DROPEMAIL_BUFSIZE; i++) {
if (irc_stricmp(u->nick, dropemail_buffer[i].sender) == 0
&& stricmp(mask, dropemail_buffer[i].mask) == 0
&& time(NULL) - dropemail_buffer[i].sent < NSDropEmailExpire
) {
break;
}
}
if (i >= DROPEMAIL_BUFSIZE) {
notice_lang(s_NickServ, u, NICK_DROPEMAIL_CONFIRM_UNKNOWN);
return;
}
/* Okay, go ahead and delete */
notice_lang(s_NickServ, u, NICK_DROPEMAIL_CONFIRM_DROPPING,
dropemail_buffer[i].count);
if (readonly)
notice_lang(s_NickServ, u, READ_ONLY_MODE);
if (strcmp(mask,"-") == 0)
mask = NULL;
for (ngi = first_nickgroupinfo(); ngi; ngi = next_nickgroupinfo()) {
if ((mask && ngi->email && match_wild_nocase(mask,ngi->email))
|| (!mask && !ngi->email)
) {
drop_nickgroup(ngi, u, mask ? mask : "-");
}
}
notice_lang(s_NickServ, u, NICK_DROPEMAIL_CONFIRM_DROPPED);
}
/*************************************************************************/
/* Show hidden info to nick owners and sadmins when the "ALL" parameter is
* supplied. If a nick is online, the "Last seen address" changes to "Is
* online from".
* Syntax: INFO <nick> {ALL}
* -TheShadow (13 Mar 1999)
*/
/* Check the status of show_all and make a note of having done so. This is
* used at the end, to see whether we should print a "use ALL for more info"
* message. Note that this should be the last test in a boolean expression,
* to ensure that used_all isn't set inappropriately. */
#define CHECK_SHOW_ALL (used_all++, show_all)
static void do_info(User *u)
{
char *nick = strtok(NULL, " ");
char *param = strtok(NULL, " ");
NickInfo *ni;
NickGroupInfo *ngi;
time_t simdi = time(NULL);
time_t zaman, zaman2;
if (!nick) {
syntax_error(s_NickServ, u, "INFO", NICK_INFO_SYNTAX);
} else if (!(ni = get_nickinfo(nick))) {
notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick);
} else if (ni->status & NS_VERBOTEN) {
notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, nick);
} else {
char buf[BUFSIZE], *end;
char *buf2[BUFSIZE];
const char *commastr = getstring(u->ngi, COMMA_SPACE);
int need_comma = 0;
int nick_online = 0;
int can_show_all = 0, show_all = 0, used_all = 0;
ngi = get_ngi(ni);
if (!ngi) {
notice_lang(s_NickServ, u, INTERNAL_ERROR);
return;
}
/* Is the real owner of the nick we're looking up online? -TheShadow */
if (ni->user && nick_id_or_rec(ni))
nick_online = 1;
/* Only show hidden fields to owner and sadmins and only when the ALL
* parameter is used. -TheShadow */
can_show_all = ((u==ni->user && nick_online) || is_services_admin(u));
if (can_show_all && (param && stricmp(param, "ALL") == 0))
show_all = 1;
notice_lang(s_NickServ, u, NICK_INFO_REALNAME,
nick, ni->last_realname);
/* Ignore HIDE and show the real hostmask to anyone who can use
* INFO ALL. */
if (nick_online) {
if (!(ngi->flags & NF_HIDE_MASK) || can_show_all)
notice_lang(s_NickServ, u, NICK_INFO_ADDRESS_ONLINE,
can_show_all ? ni->last_realmask : ni->last_usermask);
else
notice_lang(s_NickServ, u, NICK_INFO_ADDRESS_ONLINE_NOHOST,
ni->nick);
} else {
if (!(ngi->flags & NF_HIDE_MASK) || can_show_all)
notice_lang(s_NickServ, u, NICK_INFO_ADDRESS,
can_show_all ? ni->last_realmask : ni->last_usermask);
zaman = simdi - ni->last_seen;
strftime_lang(buf, sizeof(buf), u->ngi,
STRFTIME_DATE_TIME_FORMAT, ni->last_seen);
notice_lang(s_NickServ, u, NICK_INFO_LAST_SEEN, buf, maketime2(u->ngi, zaman));
}
zaman2 = simdi - ni->time_registered;
strftime_lang(buf, sizeof(buf), u->ngi, STRFTIME_DATE_TIME_FORMAT,
ni->time_registered);
notice_lang(s_NickServ, u, NICK_INFO_TIME_REGGED, buf, maketime2(u->ngi, zaman2));
if (ni->last_quit && (!(ngi->flags & NF_HIDE_QUIT) || CHECK_SHOW_ALL))
notice_lang(s_NickServ, u, NICK_INFO_LAST_QUIT, ni->last_quit);
if (ngi->isim)
notice_lang(s_NickServ, u, NICK_INFO_ISIM, ngi->isim);
if (ngi->yas)
notice_lang(s_NickServ, u, NICK_INFO_YAS, ngi->Yas);
if (ngi->sehir)
notice_lang(s_NickServ, u, NICK_INFO_LOCATION, ngi->Sehir);
if (ngi->msn)
notice_lang(s_NickServ, u, NICK_INFO_MSN, ngi->MSN);
if (ngi->icq)
notice_lang(s_NickServ, u, NICK_INFO_ICQ, ngi->ICQ);
if (ngi->info)
notice_lang(s_NickServ, u, NICK_INFO_INFO, ngi->Info);
if (ngi->url)
notice_lang(s_NickServ, u, NICK_INFO_URL, ngi->Url);
if (ngi->email && (!(ngi->flags & NF_HIDE_EMAIL) || CHECK_SHOW_ALL)) {
if (ngi->authcode) {
if (can_show_all) {
notice_lang(s_NickServ, u, NICK_INFO_EMAIL_UNAUTHED,
ngi->email);
}
} else {
notice_lang(s_NickServ, u, NICK_INFO_EMAIL, ngi->email);
}
}
*buf = 0;
end = buf;
if (ngi->flags & NF_KILLPROTECT) {
end += snprintf(end, sizeof(buf)-(end-buf), "%s",
getstring(u->ngi, NICK_INFO_OPT_KILL));
need_comma = 1;
}
if (ngi->flags & NF_SECURE) {
end += snprintf(end, sizeof(buf)-(end-buf), "%s%s",
need_comma ? commastr : "",
getstring(u->ngi, NICK_INFO_OPT_SECURE));
need_comma = 1;
}
if (ngi->flags & NF_PRIVATE) {
end += snprintf(end, sizeof(buf)-(end-buf), "%s%s",
need_comma ? commastr : "",
getstring(u->ngi, NICK_INFO_OPT_PRIVATE));
need_comma = 1;
}
notice_lang(s_NickServ, u, NICK_INFO_OPTIONS,
*buf ? buf : getstring(u->ngi, NICK_INFO_OPT_NONE));
if ((ni->status & NS_NOEXPIRE) && CHECK_SHOW_ALL)
notice_lang(s_NickServ, u, NICK_INFO_NO_EXPIRE);
if (ngi->suspendinfo) {
notice_lang(s_NickServ, u, NICK_X_SUSPENDED, nick);
if (CHECK_SHOW_ALL) {
SuspendInfo *si = ngi->suspendinfo;
char timebuf[BUFSIZE], expirebuf[BUFSIZE];
strftime_lang(timebuf, sizeof(timebuf), u->ngi,
STRFTIME_DATE_TIME_FORMAT, si->suspended);
expires_in_lang(expirebuf, sizeof(expirebuf), u->ngi,
si->expires);
notice_lang(s_NickServ, u, NICK_INFO_SUSPEND_DETAILS,
si->who, timebuf, expirebuf);
notice_lang(s_NickServ, u, NICK_INFO_SUSPEND_REASON,
si->reason);
}
}
if (can_show_all && !show_all && used_all)
notice_lang(s_NickServ, u, NICK_INFO_SHOW_ALL, s_NickServ,
ni->nick);
}
}
/*************************************************************************/
static void do_listchans(User *u)
{
NickInfo *ni = u->ni;
NickGroupInfo *ngi;
if (is_oper(u)) {
char *nick = strtok(NULL, " ");
if (nick) {
NickInfo *ni2 = get_nickinfo(nick);
if (!ni2) {
notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick);
return;
} else if (ni2 == ni) {
/* Let the command through even for non-servadmins if they
* gave their own nick; it's less confusing than a
* "Permission denied" error */
} else if (!is_services_admin(u)) {
notice_lang(s_NickServ, u, PERMISSION_DENIED);
return;
} else {
ni = ni2;
}
}
} else if (strtok_remaining()) {
syntax_error(s_NickServ, u, "LISTCHANS", NICK_LISTCHANS_SYNTAX);
return;
}
if (!ni) {
notice_lang(s_NickServ, u, NICK_NOT_REGISTERED);
return;
}
if (ni->status & NS_VERBOTEN) {
notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, ni->nick);
} else if (!user_identified(u)) {
notice_lang(s_NickServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ);
} else if (!(ngi = get_ngi(ni))) {
notice_lang(s_NickServ, u, INTERNAL_ERROR);
} else if (!ngi->channels_count) {
notice_lang(s_NickServ, u, NICK_LISTCHANS_NONE, ni->nick);
} else {
int i;
notice_lang(s_NickServ, u, NICK_LISTCHANS_HEADER, ni->nick);
ARRAY_FOREACH (i, ngi->channels)
notice(s_NickServ, u->nick, " %s", ngi->channels[i]);
notice_lang(s_NickServ, u, NICK_LISTCHANS_END, ngi->channels_count);
}
}
/*************************************************************************/
static void do_list(User *u)
{
char *pattern = strtok(NULL, " ");
char *keyword;
NickInfo *ni;
NickGroupInfo *ngi;
int nnicks;
char buf[BUFSIZE];
int is_servadmin = is_services_admin(u);
int16 match_NS = 0; /* NS_ flags a nick must match one of to qualify */
int32 match_NF = 0; /* NF_ flags a nick must match one of to qualify */
int match_susp = 0; /* 1 if we match on suspended nicks */
int match_auth = 0; /* 1 if we match on nicks with auth codes */
int have_auth_module = 0; /* so we don't show no-auth char if no module */
if (NSListOpersOnly && !is_oper(u)) {
notice_lang(s_NickServ, u, PERMISSION_DENIED);
return;
}
have_auth_module = (find_module("nickserv/mail-auth") != NULL);
if (!pattern) {
syntax_error(s_NickServ, u, "LIST",
is_oper(u) ? NICK_LIST_OPER_SYNTAX : NICK_LIST_SYNTAX);
} else {
int mask_has_at = (strchr(pattern,'@') != 0);
nnicks = 0;
while (is_servadmin && (keyword = strtok(NULL, " "))) {
if (stricmp(keyword, "FORBIDDEN") == 0) {
match_NS |= NS_VERBOTEN;
} else if (stricmp(keyword, "NOEXPIRE") == 0) {
match_NS |= NS_NOEXPIRE;
} else if (stricmp(keyword, "SUSPENDED") == 0) {
match_susp = 1;
} else if (stricmp(keyword, "NOAUTH") == 0 && have_auth_module) {
match_auth = 1;
} else {
syntax_error(s_NickServ, u, "LIST",
is_oper(u) ? NICK_LIST_OPER_SYNTAX : NICK_LIST_SYNTAX);
}
}
notice_lang(s_NickServ, u, NICK_LIST_HEADER, pattern);
for (ni = first_nickinfo(); ni; ni = next_nickinfo()) {
int usermask_seen = 0; /* does user get to see the usermask? */
const char *mask; /* which mask to show? (fake vs. real) */
if (u == ni->user || is_services_admin(u))
mask = ni->last_realmask;
else
mask = ni->last_usermask;
ngi = get_nickgroupinfo(ni->nickgroup);
if (!is_servadmin && ((ngi && (ngi->flags & NF_PRIVATE))
|| (ni->status & NS_VERBOTEN)))
continue;
if (match_NS || match_NF || match_susp || match_auth)
/* ok, we have flags, now see if they match */
if (!((ni->status & match_NS)
|| (ngi && (ngi->flags & match_NF))
|| (ngi && ngi->suspendinfo && match_susp)
|| (ngi && ngi->authcode && match_auth)
)) {
continue;
}
if (!is_servadmin && (ngi->flags & NF_HIDE_MASK)) {
snprintf(buf, sizeof(buf), "%-20s [Hidden]", ni->nick);
} else if (ni->status & NS_VERBOTEN) {
snprintf(buf, sizeof(buf), "%-20s [Forbidden]", ni->nick);
} else {
usermask_seen = 1;
snprintf(buf, sizeof(buf), "%-20s %s", ni->nick, mask);
}
if ((!mask_has_at && match_wild_nocase(pattern, ni->nick))
|| (mask_has_at && usermask_seen
&& match_wild_nocase(pattern, mask))
) {
if (++nnicks <= NSListMax) {
char suspended_char = ' ';
char noexpire_char = ' ';
const char *auth_char = have_auth_module ? " " : "";
if (is_servadmin) {
if (ngi && ngi->suspendinfo)
suspended_char = '*';
if (ni->status & NS_NOEXPIRE)
noexpire_char = '!';
if (have_auth_module && ngi && ngi->authcode)
auth_char = "?";
}
notice(s_NickServ, u->nick, " %c%c%s %s",
suspended_char, noexpire_char, auth_char, buf);
}
}
}
notice_lang(s_NickServ, u, NICK_LIST_RESULTS,
nnicks>NSListMax ? NSListMax : nnicks, nnicks);
}
}
/*************************************************************************/
static void do_listemail(User *u)
{
char *pattern = strtok(NULL, " ");
char *keyword;
NickInfo *ni;
NickGroupInfo *ngi;
int nnicks;
char buf[BUFSIZE];
int is_servadmin = is_services_admin(u);
int16 match_NS = 0; /* NS_ flags a nick must match one of to qualify */
int32 match_NF = 0; /* NF_ flags a nick must match one of to qualify */
int match_susp = 0; /* 1 if we match on suspended nicks */
int match_auth = 0; /* 1 if we match on nicks with auth codes */
int have_auth_module = 0; /* so we don't show no-auth char if no module */
if (NSListOpersOnly && !is_oper(u)) {
notice_lang(s_NickServ, u, PERMISSION_DENIED);
return;
}
have_auth_module = (find_module("nickserv/mail-auth") != NULL);
if (!pattern) {
syntax_error(s_NickServ, u, "LISTEMAIL",
is_oper(u) ? NICK_LIST_OPER_SYNTAX : NICK_LIST_SYNTAX);
} else {
const char *nonestr = getstring(u->ngi, NICK_LISTEMAIL_NONE);
int mask_has_at = (strchr(pattern,'@') != 0);
nnicks = 0;
while (is_servadmin && (keyword = strtok(NULL, " "))) {
if (stricmp(keyword, "FORBIDDEN") == 0) {
match_NS |= NS_VERBOTEN;
} else if (stricmp(keyword, "NOEXPIRE") == 0) {
match_NS |= NS_NOEXPIRE;
} else if (stricmp(keyword, "SUSPENDED") == 0) {
match_susp = 1;
} else if (stricmp(keyword, "NOAUTH") == 0 && have_auth_module) {
match_auth = 1;
} else {
syntax_error(s_NickServ, u, "LISTEMAIL",
is_oper(u) ? NICK_LIST_OPER_SYNTAX : NICK_LIST_SYNTAX);
}
}
notice_lang(s_NickServ, u, NICK_LIST_HEADER, pattern);
for (ni = first_nickinfo(); ni; ni = next_nickinfo()) {
int email_seen = 0; /* does user get to see the address? */
ngi = get_nickgroupinfo(ni->nickgroup);
if (!is_servadmin && ((ngi && (ngi->flags & NF_PRIVATE))
|| (ni->status & NS_VERBOTEN)))
continue;
if (match_NS || match_NF || match_susp || match_auth)
/* ok, we have flags, now see if they match */
if (!((ni->status & match_NS)
|| (ngi && (ngi->flags & match_NF))
|| (ngi && ngi->suspendinfo && match_susp)
|| (ngi && ngi->authcode && match_auth)
)) {
continue;
}
if (!is_servadmin && (ngi->flags & NF_HIDE_EMAIL)
&& (!valid_ngi(u) || ngi->id!=u->ngi->id || !user_identified(u))){
snprintf(buf, sizeof(buf), "%-20s [Hidden]", ni->nick);
} else if (ni->status & NS_VERBOTEN) {
snprintf(buf, sizeof(buf), "%-20s [Forbidden]", ni->nick);
} else {
email_seen = 1;
snprintf(buf, sizeof(buf), "%-20s %s", ni->nick,
ngi->email ? ngi->email : nonestr);
}
if ((!mask_has_at && match_wild_nocase(pattern, ni->nick))
|| (mask_has_at && email_seen && ngi->email
&& match_wild_nocase(pattern, ngi->email))
) {
if (++nnicks <= NSListMax) {
char suspended_char = ' ';
char noexpire_char = ' ';
const char *auth_char = have_auth_module ? " " : "";
if (is_servadmin) {
if (ngi && ngi->suspendinfo)
suspended_char = '*';
if (ni->status & NS_NOEXPIRE)
noexpire_char = '!';
if (have_auth_module && ngi && ngi->authcode)
auth_char = "?";
}
notice(s_NickServ, u->nick, " %c%c%s %s",
suspended_char, noexpire_char, auth_char, buf);
}
}
}
notice_lang(s_NickServ, u, NICK_LIST_RESULTS,
nnicks>NSListMax ? NSListMax : nnicks, nnicks);
}
}
/*************************************************************************/
static void do_recover(User *u)
{
char *nick = strtok(NULL, " ");
char *pass = strtok(NULL, " ");
NickInfo *ni;
User *u2;
if (!nick || strtok_remaining()) {
syntax_error(s_NickServ, u, "RECOVER", NICK_RECOVER_SYNTAX);
} else if (!(u2 = get_user(nick))) {
notice_lang(s_NickServ, u, NICK_X_NOT_IN_USE, nick);
} else if (!(ni = u2->ni)) {
notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick);
} else if (ni->status & NS_GUESTED) {
notice_lang(s_NickServ, u, NICK_X_NOT_IN_USE, nick);
} else if (ni->status & NS_VERBOTEN) {
notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, nick);
} else if (irc_stricmp(nick, u->nick) == 0) {
notice_lang(s_NickServ, u, NICK_NO_RECOVER_SELF);
} else {
if (pass) {
if (!nick_check_password(u, ni, pass, "RECOVER", ACCESS_DENIED))
return;
} else if (!has_identified_nick(u, ni->nickgroup)) {
notice_lang(s_NickServ, u, ACCESS_DENIED);
return;
}
collide(ni, 0);
notice_lang(s_NickServ, u, NICK_RECOVERED, s_NickServ, nick);
}
}
/*************************************************************************/
static void do_release(User *u)
{
char *nick = strtok(NULL, " ");
char *pass = strtok(NULL, " ");
NickInfo *ni;
if (!nick || strtok_remaining()) {
syntax_error(s_NickServ, u, "RELEASE", NICK_RELEASE_SYNTAX);
} else if (!(ni = get_nickinfo(nick))) {
notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick);
} else if (ni->status & NS_VERBOTEN) {
notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, nick);
} else if (!(ni->status & NS_KILL_HELD)) {
notice_lang(s_NickServ, u, NICK_RELEASE_NOT_HELD, nick);
} else {
if (pass) {
if (!nick_check_password(u, ni, pass, "RELEASE", ACCESS_DENIED))
return;
} else if (!has_identified_nick(u, ni->nickgroup)) {
notice_lang(s_NickServ, u, ACCESS_DENIED);
return;
}
release(ni, 0);
notice_lang(s_NickServ, u, NICK_RELEASED, ni->nick);
}
}
/*************************************************************************/
static void do_ghost(User *u)
{
char *nick = strtok(NULL, " ");
char *pass = strtok(NULL, " ");
NickInfo *ni;
User *u2;
if (!nick || strtok_remaining()) {
syntax_error(s_NickServ, u, "GHOST", NICK_GHOST_SYNTAX);
} else if (!(u2 = get_user(nick))) {
notice_lang(s_NickServ, u, NICK_X_NOT_IN_USE, nick);
} else if (!(ni = u2->ni)) {
notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick);
} else if (ni->status & NS_GUESTED) {
notice_lang(s_NickServ, u, NICK_X_NOT_IN_USE, nick);
} else if (ni->status & NS_VERBOTEN) {
notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, nick);
} else if (irc_stricmp(nick, u->nick) == 0) {
notice_lang(s_NickServ, u, NICK_NO_GHOST_SELF);
} else {
char buf[NICKMAX+32];
if (pass) {
if (!nick_check_password(u, ni, pass, "GHOST", ACCESS_DENIED))
return;
} else if (!has_identified_nick(u, ni->nickgroup)) {
notice_lang(s_NickServ, u, ACCESS_DENIED);
return;
}
snprintf(buf, sizeof(buf), "GHOST command used by %s", u->nick);
kill_user(s_NickServ, nick, buf);
notice_lang(s_NickServ, u, NICK_GHOST_KILLED, nick);
}
}
/*************************************************************************/
static void do_status(User *u)
{
char *nick;
User *u2;
int i = 0;
while ((nick = strtok(NULL, " ")) && (i++ < 16)) {
if (!(u2 = get_user(nick)) || !u2->ni)
notice(s_NickServ, u->nick, "STATUS %s 0", nick);
else if (user_identified(u2))
notice(s_NickServ, u->nick, "STATUS %s 3", nick);
else if (user_recognized(u2))
notice(s_NickServ, u->nick, "STATUS %s 2", nick);
else
notice(s_NickServ, u->nick, "STATUS %s 1", nick);
}
}
/*************************************************************************/
static void do_getpass(User *u)
{
char *nick = strtok(NULL, " ");
char pass[PASSMAX];
NickInfo *ni;
NickGroupInfo *ngi;
int i;
/* Assumes that permission checking has already been done. */
if (!nick) {
syntax_error(s_NickServ, u, "GETPASS", NICK_GETPASS_SYNTAX);
} else if (!(ni = get_nickinfo(nick))) {
notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick);
} else if (ni->status & NS_VERBOTEN) {
notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, nick);
} else if (!(ngi = get_ngi(ni))) {
notice_lang(s_NickServ, u, INTERNAL_ERROR);
} else if (NSSecureAdmins && nick_is_services_admin(ni) &&
!is_services_root(u)) {
notice_lang(s_NickServ, u, PERMISSION_DENIED);
} else if ((i = decrypt(ngi->pass, pass, PASSMAX)) < 0) {
module_log("decrypt() failed for GETPASS on %s", nick);
notice_lang(s_NickServ, u, INTERNAL_ERROR);
} else if (i == 0) {
notice_lang(s_NickServ, u, NICK_GETPASS_UNAVAILABLE);
} else {
module_log("%s!%s@%s used GETPASS on %s",
u->nick, u->username, u->host, nick);
if (WallGetpass)
wallops(s_NickServ, "\2%s\2 used GETPASS on \2%s\2", u->nick,nick);
notice_lang(s_NickServ, u, NICK_GETPASS_PASSWORD_IS, nick, pass);
}
}
/*************************************************************************/
static void do_forbid(User *u)
{
NickInfo *ni;
char *nick = strtok(NULL, " ");
User *u2;
/* Assumes that permission checking has already been done. */
if (!nick) {
syntax_error(s_NickServ, u, "FORBID", NICK_FORBID_SYNTAX);
return;
}
u2 = get_user(nick);
if ((ni = get_nickinfo(nick)) != NULL) {
if (NSSecureAdmins && nick_is_services_admin(ni) &&
!is_services_root(u)) {
notice_lang(s_NickServ, u, PERMISSION_DENIED);
return;
}
delnick(ni);
if (u2) {
u2->ni = NULL;
u2->ngi = NULL;
}
}
if (readonly)
notice_lang(s_NickServ, u, READ_ONLY_MODE);
ni = makenick(nick, NULL);
if (ni) {
ni->status |= NS_VERBOTEN;
ni->time_registered = time(NULL);
module_log("%s!%s@%s set FORBID for nick %s",
u->nick, u->username, u->host, nick);
notice_lang(s_NickServ, u, NICK_FORBID_SUCCEEDED, nick);
/* If someone is using the nick, make them stop */
if (u2)
validate_user(u2);
} else {
module_log("Valid FORBID for %s by %s!%s@%s failed",
nick, u->nick, u->username, u->host);
notice_lang(s_NickServ, u, NICK_FORBID_FAILED, nick);
}
}
/*************************************************************************/
static void do_suspend(User *u)
{
NickInfo *ni;
NickGroupInfo *ngi;
char *expiry, *nick, *reason;
time_t expires;
nick = strtok(NULL, " ");
if (nick && *nick == '+') {
expiry = nick+1;
nick = strtok(NULL, " ");
} else {
expiry = NULL;
}
reason = strtok_remaining();
if (!reason) {
syntax_error(s_NickServ, u, "SUSPEND", NICK_SUSPEND_SYNTAX);
} else if (!(ni = get_nickinfo(nick))) {
notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick);
} else if (ni->status & NS_VERBOTEN) {
notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, nick);
} else if (!(ngi = get_ngi(ni))) {
notice_lang(s_NickServ, u, INTERNAL_ERROR);
} else if (ngi->suspendinfo) {
notice_lang(s_NickServ, u, NICK_SUSPEND_ALREADY_SUSPENDED, nick);
} else {
if (expiry)
expires = dotime(expiry);
else
expires = NSSuspendExpire;
if (expires < 0) {
notice_lang(s_NickServ, u, BAD_EXPIRY_TIME);
return;
} else if (expires > 0) {
expires += time(NULL); /* Set an absolute time */
}
module_log("%s!%s@%s suspended %s",
u->nick, u->username, u->host, ni->nick);
suspend_nick(ngi, reason, u->nick, expires);
notice_lang(s_NickServ, u, NICK_SUSPEND_SUCCEEDED, nick);
if (readonly)
notice_lang(s_NickServ, u, READ_ONLY_MODE);
/* If someone is using the nick, make them stop */
if (ni->user)
validate_user(ni->user);
}
}
/*************************************************************************/
static void do_unsuspend(User *u)
{
NickInfo *ni;
NickGroupInfo *ngi;
char *nick = strtok(NULL, " ");
if (!nick) {
syntax_error(s_NickServ, u, "UNSUSPEND", NICK_UNSUSPEND_SYNTAX);
} else if (!(ni = get_nickinfo(nick))) {
notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick);
} else if (ni->status & NS_VERBOTEN) {
notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, nick);
} else if (!(ngi = get_ngi(ni))) {
notice_lang(s_NickServ, u, INTERNAL_ERROR);
} else if (!ngi->suspendinfo) {
notice_lang(s_NickServ, u, NICK_UNSUSPEND_NOT_SUSPENDED, nick);
} else {
module_log("%s!%s@%s unsuspended %s",
u->nick, u->username, u->host, ni->nick);
unsuspend_nick(ngi, 1);
notice_lang(s_NickServ, u, NICK_UNSUSPEND_SUCCEEDED, nick);
if (readonly)
notice_lang(s_NickServ, u, READ_ONLY_MODE);
}
}
/*************************************************************************/
#ifdef DEBUG_COMMANDS
/* Return all the fields in the NickInfo structure. */
static void do_listnick(User *u)
{
NickInfo *ni;
NickGroupInfo *ngi;
char *nick = strtok(NULL, " ");
char buf1[BUFSIZE], buf2[BUFSIZE];
char *s;
int i;
if (!nick)
return;
ni = get_nickinfo(nick);
if (!ni) {
notice(s_NickServ, u->nick, "%s", nick);
notice(s_NickServ, u->nick, ":");
return;
}
ngi = get_nickgroupinfo(ni->nickgroup);
notice(s_NickServ, u->nick, "%s group:%u usermask:%s realmask:%s"
" reg:%d seen:%d stat:%04X auth:%04X idstamp:%d badpass:%d :%s;%s",
ni->nick, (int)ni->nickgroup, ni->last_usermask, ni->last_realmask,
(int)ni->time_registered, (int)ni->last_seen, ni->status & 0xFFFF,
ni->authstat & 0xFFFF, ni->id_stamp, ni->bad_passwords,
ni->last_realname, (ni->last_quit ? ni->last_quit : "-"));
if (ngi) {
if (ngi->authcode) {
snprintf(buf1, sizeof(buf1), "%d.%d",
(int)ngi->authcode, (int)ngi->authset);
} else {
*buf1 = 0;
}
if (ngi->suspendinfo) {
SuspendInfo *si = ngi->suspendinfo;
snprintf(buf2, sizeof(buf2), "%s.%d.%d.%s",
si->who, (int)si->suspended, (int)si->expires,
si->reason ? si->reason : "-");
strnrepl(buf2, sizeof(buf2), " ", "_");
} else {
*buf2 = 0;
}
notice(s_NickServ, u->nick, "+ flags:%08X ospriv:%04X authcode:%s"
" susp:%s chancnt:%d chanmax:%d lang:%d tz:%d acccnt:%d"
" ajoincnt:%d memocnt:%d memomax:%d igncnt:%d",
ngi->flags, ngi->os_priv, buf1, buf2, ngi->channels_count,
ngi->channelmax, ngi->language, ngi->timezone,
ngi->access_count, ngi->ajoin_count, ngi->memos.memos_count,
ngi->memos.memomax, ngi->ignore_count);
notice(s_NickServ, u->nick, "+ url:%s", ngi->url ? ngi->url : "");
notice(s_NickServ, u->nick, "+ email:%s", ngi->email?ngi->email:"");
notice(s_NickServ, u->nick, "+ info:%s", ngi->info ? ngi->info : "");
s = buf1;
*buf1 = 0;
ARRAY_FOREACH (i, ngi->access)
s += snprintf(s, sizeof(buf1)-(s-buf1), "%s%s",
*buf1 ? "," : "", ngi->access[i]);
strnrepl(buf1, sizeof(buf1), " ", "_");
notice(s_NickServ, u->nick, "+ acc:%s", buf1);
s = buf1;
*buf1 = 0;
ARRAY_FOREACH (i, ngi->ajoin)
s += snprintf(s, sizeof(buf1)-(s-buf1), "%s%s",
*buf1 ? "," : "", ngi->ajoin[i]);
strnrepl(buf1, sizeof(buf1), " ", "_");
notice(s_NickServ, u->nick, "+ ajoin:%s", buf1);
s = buf1;
*buf1 = 0;
ARRAY_FOREACH (i, ngi->ignore)
s += snprintf(s, sizeof(buf1)-(s-buf1), "%s%s",
*buf1 ? "," : "", ngi->ignore[i]);
strnrepl(buf1, sizeof(buf1), " ", "_");
notice(s_NickServ, u->nick, "+ ign:%s", buf1);
} else {
notice(s_NickServ, u->nick, ":");
}
}
#endif /* DEBUG_COMMANDS */
/*************************************************************************/
/***************************** Module stuff ******************************/
/*************************************************************************/
const int32 module_version = MODULE_VERSION_CODE;
static int NSDefKill;
static int NSDefKillQuick;
static int NSDefSecure;
static int NSDefPrivate;
static int NSDefHideEmail;
static int NSDefHideUsermask;
static int NSDefHideQuit;
static int NSDefMemoSignon;
static int NSDefMemoReceive;
static int NSEnableRegister;
static char *temp_nsuserhost;
ConfigDirective module_config[] = {
{ "NickservDB", { { CD_STRING, CF_DIRREQ, &NickDBName } } },
{ "NickServName", { { CD_STRING, CF_DIRREQ, &s_NickServ },
{ CD_STRING, 0, &desc_NickServ } } },
{ "NSAllowKillImmed", { { CD_SET, 0, &NSAllowKillImmed } } },
{ "NSDefHideEmail", { { CD_SET, 0, &NSDefHideEmail } } },
{ "NSDefHideQuit", { { CD_SET, 0, &NSDefHideQuit } } },
{ "NSDefHideUsermask",{ { CD_SET, 0, &NSDefHideUsermask } } },
{ "NSDefKill", { { CD_SET, 0, &NSDefKill } } },
{ "NSDefKillQuick", { { CD_SET, 0, &NSDefKillQuick } } },
{ "NSDefMemoReceive", { { CD_SET, 0, &NSDefMemoReceive } } },
{ "NSDefMemoSignon", { { CD_SET, 0, &NSDefMemoSignon } } },
{ "NSDefPrivate", { { CD_SET, 0, &NSDefPrivate } } },
{ "NSDefSecure", { { CD_SET, 0, &NSDefSecure } } },
{ "NSDropEmailExpire",{ { CD_TIME, CF_DIRREQ, &NSDropEmailExpire } } },
{ "NSEnableDropEmail",{ { CD_SET, 0, &NSEnableDropEmail } } },
{ "NSEnableRegister", { { CD_SET, 0, &NSEnableRegister } } },
{ "NSEnforcerUser", { { CD_STRING, CF_DIRREQ, &temp_nsuserhost } } },
{ "N***pire", { { CD_TIME, 0, &N***pire } } },
{ "N***pireWarning", { { CD_TIME, 0, &N***pireWarning } } },
{ "NSForceNickChange",{ { CD_SET, 0, &NSForceNickChange } } },
{ "NSHelpWarning", { { CD_SET, 0, &NSHelpWarning } } },
{ "NSInitialRegDelay",{ { CD_TIME, 0, &NSInitialRegDelay } } },
{ "NSListMax", { { CD_POSINT, CF_DIRREQ, &NSListMax } } },
{ "NSListOpersOnly", { { CD_SET, 0, &NSListOpersOnly } } },
{ "NSRegDelay", { { CD_TIME, 0, &NSRegDelay } } },
{ "NSRegEmailMax", { { CD_POSINT, 0, &NSRegEmailMax } } },
{ "NSRequireEmail", { { CD_SET, 0, &NSRequireEmail } } },
{ "NSReleaseTimeout", { { CD_TIME, CF_DIRREQ, &NSReleaseTimeout } } },
{ "NSSecureAdmins", { { CD_SET, 0, &NSSecureAdmins } } },
{ "NSShowPassword", { { CD_SET, 0, &NSShowPassword } } },
{ "NSSuspendExpire", { { CD_TIME, 0 , &NSSuspendExpire },
{ CD_TIME, 0 , &NSSuspendGrace } } },
{ NULL }
};
/* Pointer to command records (for EnableCommand) */
static Command *cmd_REGISTER;
static Command *cmd_DROPEMAIL;
static Command *cmd_DROPEMAIL_CONFIRM;
static Command *cmd_GETPASS;
/* Old message numbers */
static int old_REGISTER_SYNTAX = -1;
static int old_HELP_REGISTER_EMAIL = -1;
static int old_HELP_UNSET = -1;
static int old_DISCONNECT_IN_1_MINUTE = -1;
static int old_DISCONNECT_IN_20_SECONDS = -1;
/*************************************************************************/
static void handle_config(void)
{
char *s;
if (temp_nsuserhost) {
NSEnforcerUser = temp_nsuserhost;
if (!(s = strchr(temp_nsuserhost, '@'))) {
NSEnforcerHost = ServiceHost;
} else {
*s++ = 0;
NSEnforcerHost = s;
}
}
NSDefFlags = 0;
if (NSDefKill)
NSDefFlags |= NF_KILLPROTECT;
if (NSDefKillQuick)
NSDefFlags |= NF_KILL_QUICK;
if (NSDefSecure)
NSDefFlags |= NF_SECURE;
if (NSDefPrivate)
NSDefFlags |= NF_PRIVATE;
if (NSDefHideEmail)
NSDefFlags |= NF_HIDE_EMAIL;
if (NSDefHideUsermask)
NSDefFlags |= NF_HIDE_MASK;
if (NSDefHideQuit)
NSDefFlags |= NF_HIDE_QUIT;
if (NSDefMemoSignon)
NSDefFlags |= NF_MEMO_SIGNON;
if (NSDefMemoReceive)
NSDefFlags |= NF_MEMO_RECEIVE;
if (NSForceNickChange && !(protocol_features & PF_CHANGENICK)) {
module_log("warning: forced nick changing not supported by IRC"
" server, disabling NSForceNickChange");
NSForceNickChange = 0;
}
}
/*************************************************************************/
static int do_command_line(const char *option, const char *value)
{
NickGroupInfo *ngi;
if (!option || strcmp(option, "clear-nick-email") != 0)
return 0;
if (value) {
fprintf(stderr, "-clear-nick-email takes no options\n");
return 2;
}
module_log("Clearing all E-mail addresses (-clear-nick-email specified"
" on command line)");
for (ngi = first_nickgroupinfo(); ngi; ngi = next_nickgroupinfo()) {
free(ngi->email);
ngi->email = NULL;
}
return 1;
}
/*************************************************************************/
static int do_reconfigure(int after_configure)
{
static char old_s_NickServ[NICKMAX];
static char *old_desc_NickServ = NULL;
static char *old_NickDBName = NULL;
if (!after_configure) {
/* Before reconfiguration: save old values. */
strscpy(old_s_NickServ, s_NickServ, NICKMAX);
old_desc_NickServ = strdup(desc_NickServ);
old_NickDBName = strdup(NickDBName);
} else {
/* After reconfiguration: handle value changes. */
handle_config();
if (strcmp(old_s_NickServ,s_NickServ) != 0)
send_nickchange(old_s_NickServ, s_NickServ);
if (!old_desc_NickServ || strcmp(old_desc_NickServ,desc_NickServ) != 0)
send_namechange(s_NickServ, desc_NickServ);
if (!old_NickDBName || strcmp(old_NickDBName,NickDBName) != 0) {
module_log("reconfigure: new database name will only take"
" effect after restart");
/* Restore the old database name */
free(NickDBName);
NickDBName = old_NickDBName;
/* Make sure the old name isn't freed below */
old_NickDBName = NULL;
}
free(old_desc_NickServ);
free(old_NickDBName);
if (NSEnableRegister)
cmd_REGISTER->name = "REGISTER";
else
cmd_REGISTER->name = "";
if (NSEnableDropEmail) {
cmd_DROPEMAIL->name = "DROPEMAIL";
cmd_DROPEMAIL_CONFIRM->name = "DROPEMAIL-CONFIRM";
} else {
cmd_DROPEMAIL->name = "";
cmd_DROPEMAIL_CONFIRM->name = "";
}
if (EnableGetpass)
cmd_GETPASS->name = "GETPASS";
else
cmd_GETPASS->name = "";
if (NSRequireEmail) {
setstring(NICK_REGISTER_SYNTAX, NICK_REGISTER_REQ_EMAIL_SYNTAX);
setstring(NICK_HELP_REGISTER_EMAIL, NICK_HELP_REGISTER_EMAIL_REQ);
setstring(NICK_HELP_UNSET, NICK_HELP_UNSET_REQ_EMAIL);
} else {
setstring(NICK_REGISTER_SYNTAX, old_REGISTER_SYNTAX);
setstring(NICK_HELP_REGISTER_EMAIL, old_HELP_REGISTER_EMAIL);
setstring(NICK_HELP_UNSET, old_HELP_UNSET);
}
if (NSForceNickChange) {
setstring(DISCONNECT_IN_1_MINUTE, FORCENICKCHANGE_IN_1_MINUTE);
setstring(DISCONNECT_IN_20_SECONDS, FORCENICKCHANGE_IN_20_SECONDS);
} else {
setstring(DISCONNECT_IN_1_MINUTE, old_DISCONNECT_IN_1_MINUTE);
setstring(DISCONNECT_IN_20_SECONDS, old_DISCONNECT_IN_20_SECONDS);
}
} /* if (!after_configure) */
return 0;
}
/*************************************************************************/
int init_module(Module *module_)
{
module = module_;
handle_config();
if (!new_commandlist(module) || !register_commands(module, cmds)) {
module_log("Unable to register commands");
exit_module(0);
return 0;
}
cmd_REGISTER = lookup_cmd(module, "REGISTER");
if (!cmd_REGISTER) {
module_log("BUG: unable to find REGISTER command entry");
exit_module(0);
return 0;
}
cmd_DROPEMAIL = lookup_cmd(module, "DROPEMAIL");
if (!cmd_DROPEMAIL) {
module_log("BUG: unable to find DROPEMAIL command entry");
exit_module(0);
return 0;
}
cmd_DROPEMAIL_CONFIRM = lookup_cmd(module, "DROPEMAIL-CONFIRM");
if (!cmd_DROPEMAIL_CONFIRM) {
module_log("BUG: unable to find DROPEMAIL-CONFIRM command entry");
exit_module(0);
return 0;
}
cmd_GETPASS = lookup_cmd(module, "GETPASS");
if (!cmd_GETPASS) {
module_log("BUG: unable to find GETPASS command entry");
exit_module(0);
return 0;
}
if (!NSEnableRegister)
cmd_REGISTER->name = "";
if (!NSEnableDropEmail) {
cmd_DROPEMAIL->name = "";
cmd_DROPEMAIL_CONFIRM->name = "";
}
if (!EnableGetpass)
cmd_GETPASS->name = "";
cb_command = register_callback(module, "command");
cb_help = register_callback(module, "HELP");
cb_help_cmds = register_callback(module, "HELP COMMANDS");
cb_reglink_check = register_callback(module, "REGISTER/LINK check");
cb_registered = register_callback(module, "registered");
cb_id_check = register_callback(module, "IDENTIFY check");
cb_identified = register_callback(module, "identified");
if (cb_command < 0 || cb_help < 0 || cb_help_cmds < 0
|| cb_reglink_check < 0 || cb_registered < 0 || cb_id_check < 0
|| cb_identified < 0
) {
module_log("Unable to register callbacks");
exit_module(0);
return 0;
}
if (!add_callback(NULL, "command line", do_command_line)
|| !add_callback(NULL, "reconfigure", do_reconfigure)
|| !add_callback(NULL, "introduce_user", introduce_nickserv)
|| !add_callback(NULL, "m_privmsg", nickserv)
|| !add_callback(NULL, "m_whois", nickserv_whois)
|| !add_callback(NULL, "save data", do_save_data)
|| !add_callback(NULL, "user create", do_user_create)
|| !add_callback(NULL, "user nickchange (before)",
do_user_nickchange_before)
|| !add_callback(NULL, "user nickchange (after)",
do_user_nickchange_after)
|| !add_callback(NULL, "user delete", do_user_delete)
|| !add_callback(module, "REGISTER/LINK check", do_reglink_check)
) {
module_log("Unable to add callbacks");
exit_module(0);
return 0;
}
if (!init_collide(module) || !init_set(module) || !init_util(module)) {
exit_module(0);
return 0;
}
open_nick_db(NickDBName);
db_opened = 1;
old_REGISTER_SYNTAX =
setstring(NICK_REGISTER_SYNTAX, NICK_REGISTER_SYNTAX);
old_HELP_REGISTER_EMAIL =
setstring(NICK_HELP_REGISTER_EMAIL, NICK_HELP_REGISTER_EMAIL);
old_HELP_UNSET =
setstring(NICK_HELP_UNSET, NICK_HELP_UNSET);
old_DISCONNECT_IN_1_MINUTE =
setstring(DISCONNECT_IN_1_MINUTE, DISCONNECT_IN_1_MINUTE);
old_DISCONNECT_IN_20_SECONDS =
setstring(DISCONNECT_IN_20_SECONDS, DISCONNECT_IN_20_SECONDS);
if (NSRequireEmail) {
setstring(NICK_REGISTER_SYNTAX, NICK_REGISTER_REQ_EMAIL_SYNTAX);
setstring(NICK_HELP_REGISTER_EMAIL, NICK_HELP_REGISTER_EMAIL_REQ);
setstring(NICK_HELP_UNSET, NICK_HELP_UNSET_REQ_EMAIL);
}
if (NSForceNickChange) {
setstring(DISCONNECT_IN_1_MINUTE, FORCENICKCHANGE_IN_1_MINUTE);
setstring(DISCONNECT_IN_20_SECONDS, FORCENICKCHANGE_IN_20_SECONDS);
}
if (linked)
introduce_nickserv(NULL);
return 1;
}
/*************************************************************************/
int exit_module(int shutdown_unused)
{
#ifdef CLEAN_COMPILE
shutdown_unused = shutdown_unused;
#endif
if (linked)
send_cmd(s_NickServ, "QUIT :");
if (old_REGISTER_SYNTAX >= 0) {
setstring(NICK_REGISTER_SYNTAX, old_REGISTER_SYNTAX);
old_REGISTER_SYNTAX = -1;
}
if (old_HELP_REGISTER_EMAIL >= 0) {
setstring(NICK_HELP_REGISTER_EMAIL, old_HELP_REGISTER_EMAIL);
old_HELP_REGISTER_EMAIL = -1;
}
if (old_HELP_UNSET >= 0) {
setstring(NICK_HELP_UNSET, old_HELP_UNSET);
old_HELP_UNSET = -1;
}
if (old_DISCONNECT_IN_1_MINUTE >= 0) {
setstring(DISCONNECT_IN_1_MINUTE, old_DISCONNECT_IN_1_MINUTE);
old_DISCONNECT_IN_1_MINUTE = -1;
}
if (old_DISCONNECT_IN_20_SECONDS >= 0) {
setstring(DISCONNECT_IN_20_SECONDS, old_DISCONNECT_IN_20_SECONDS);
old_DISCONNECT_IN_20_SECONDS = -1;
}
if (db_opened)
close_nick_db(NickDBName);
exit_util();
exit_set();
exit_collide();
remove_callback(module, "REGISTER/LINK check", do_reglink_check);
remove_callback(NULL, "user delete", do_user_delete);
remove_callback(NULL, "user nickchange (after)",
do_user_nickchange_after);
remove_callback(NULL, "user nickchange (before)",
do_user_nickchange_before);
remove_callback(NULL, "user create", do_user_create);
remove_callback(NULL, "save data", do_save_data);
remove_callback(NULL, "m_whois", nickserv_whois);
remove_callback(NULL, "m_privmsg", nickserv);
remove_callback(NULL, "introduce_user", introduce_nickserv);
remove_callback(NULL, "reconfigure", do_reconfigure);
remove_callback(NULL, "command line", do_command_line);
unregister_callback(module, cb_identified);
unregister_callback(module, cb_id_check);
unregister_callback(module, cb_registered);
unregister_callback(module, cb_reglink_check);
unregister_callback(module, cb_help_cmds);
unregister_callback(module, cb_help);
unregister_callback(module, cb_command);
/* These are static, so the pointers don't need to be cleared */
if (cmd_GETPASS)
cmd_GETPASS->name = "GETPASS";
if (cmd_DROPEMAIL_CONFIRM)
cmd_DROPEMAIL_CONFIRM->name = "DROPEMAIL-CONFIRM";
if (cmd_DROPEMAIL)
cmd_DROPEMAIL->name = "DROPEMAIL";
if (cmd_REGISTER)
cmd_REGISTER->name = "REGISTER";
unregister_commands(module, cmds);
del_commandlist(module);
return 1;
}
/*************************************************************************/