X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=src%2Fnickserv.c;h=63a910e99320a23c72077bcd16e5bb3f589a795d;hb=f435cbfb8f16558ce63be4332be7314c127f1b45;hp=683fd71afe8af4150958fdd8b890fad50a240fc7;hpb=129c7f0f7d18a4a35eaa53a573daa76a0895435f;p=srvx.git diff --git a/src/nickserv.c b/src/nickserv.c index 683fd71..63a910e 100644 --- a/src/nickserv.c +++ b/src/nickserv.c @@ -53,9 +53,9 @@ #define KEY_SET_FAKEHOST_LEVEL "set_fakehost_level" #define KEY_TITLEHOST_SUFFIX "titlehost_suffix" #define KEY_FLAG_LEVELS "flag_levels" -#define KEY_HANDLE_EXPIRE_FREQ "handle_expire_freq" +#define KEY_HANDLE_EXPIRE_FREQ "handle_expire_freq" #define KEY_ACCOUNT_EXPIRE_FREQ "account_expire_freq" -#define KEY_HANDLE_EXPIRE_DELAY "handle_expire_delay" +#define KEY_HANDLE_EXPIRE_DELAY "handle_expire_delay" #define KEY_ACCOUNT_EXPIRE_DELAY "account_expire_delay" #define KEY_NOCHAN_HANDLE_EXPIRE_DELAY "nochan_handle_expire_delay" #define KEY_NOCHAN_ACCOUNT_EXPIRE_DELAY "nochan_account_expire_delay" @@ -71,6 +71,8 @@ #define KEY_COOKIE_TIMEOUT "cookie_timeout" #define KEY_ACCOUNTS_PER_EMAIL "accounts_per_email" #define KEY_EMAIL_SEARCH_LEVEL "email_search_level" +#define KEY_OUNREGISTER_INACTIVE "ounregister_inactive" +#define KEY_OUNREGISTER_FLAGS "ounregister_flags" #define KEY_ID "id" #define KEY_PASSWD "passwd" @@ -96,7 +98,6 @@ #define KEY_ALLOWAUTH "allowauth" #define KEY_EPITHET "epithet" #define KEY_TABLE_WIDTH "table_width" -#define KEY_ANNOUNCEMENTS "announcements" #define KEY_MAXLOGINS "maxlogins" #define KEY_FAKEHOST "fakehost" #define KEY_NOTES "notes" @@ -106,7 +107,7 @@ #define KEY_NOTE_NOTE "note" #define KEY_KARMA "karma" -#define NICKSERV_VALID_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_" +#define NICKSERV_VALID_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_" #define NICKSERV_FUNC(NAME) MODCMD_FUNC(NAME) #define OPTION_FUNC(NAME) int NAME(struct userNode *user, struct handle_info *hi, UNUSED_ARG(unsigned int override), unsigned int argc, char *argv[]) @@ -157,6 +158,7 @@ static const struct message_entry msgtab[] = { { "NSMSG_COOKIE_LIVE", "Account $b%s$b already has a cookie active. Please either finish using that cookie, wait for it to expire, or auth to the account and use the $bdelcookie$b command." }, { "NSMSG_EMAIL_UNACTIVATED", "That email address already has an unused cookie outstanding. Please use the cookie or wait for it to expire." }, { "NSMSG_NO_COOKIE", "Your account does not have any cookie issued right now." }, + { "NSMSG_NO_COOKIE_FOREIGN", "The account $b%s$b does not have any cookie issued right now." }, { "NSMSG_CANNOT_COOKIE", "You cannot use that kind of cookie when you are logged in." }, { "NSMSG_BAD_COOKIE", "That cookie is not the right one. Please make sure you are copying it EXACTLY from the email; it is case-sensitive, so $bABC$b is different from $babc$b." }, { "NSMSG_HANDLE_ACTIVATED", "Your account is now activated (with the password you entered when you registered). You are now authenticated to your account." }, @@ -168,6 +170,7 @@ static const struct message_entry msgtab[] = { { "NSMSG_BAD_COOKIE_TYPE", "Your account had bad cookie type %d; sorry. I am confused. Please report this bug." }, { "NSMSG_MUST_TIME_OUT", "You must wait for cookies of that type to time out." }, { "NSMSG_ATE_COOKIE", "I ate the cookie for your account. You may now have another." }, + { "NSMSG_ATE_COOKIE_FOREIGN", "I ate the cookie for account $b%s$b. It may now have another." }, { "NSMSG_USE_RENAME", "You are already authenticated to account $b%s$b -- contact the support staff to rename your account." }, { "NSMSG_ALREADY_REGISTERING", "You have already used $bREGISTER$b once this session; you may not use it again." }, { "NSMSG_REGISTER_BAD_NICKMASK", "Could not recognize $b%s$b as either a current nick or a hostmask." }, @@ -219,6 +222,9 @@ static const struct message_entry msgtab[] = { { "NSMSG_USERINFO_AUTHED_AS", "$b%s$b is authenticated to account $b%s$b." }, { "NSMSG_USERINFO_NOT_AUTHED", "$b%s$b is not authenticated to any account." }, { "NSMSG_NICKINFO_OWNER", "Nick $b%s$b is owned by account $b%s$b." }, + { "NSMSG_NOTE_EXPIRES", "Note %d (%s ago by %s, expires %s): %s" }, + { "NSMSG_NOTE", "Note %d (%s ago by %s): %s" }, + { "NSMSG_NOTE_COUNT", "%u note(s) for %s." }, { "NSMSG_PASSWORD_INVALID", "Incorrect password; please try again." }, { "NSMSG_PLEASE_SET_EMAIL", "We now require email addresses for users. Please use the $bset email$b command to set your email address!" }, { "NSMSG_WEAK_PASSWORD", "WARNING: You are using a password that is considered weak (easy to guess). It is STRONGLY recommended you change it (now, if not sooner) by typing \"/msg $S@$s PASS oldpass newpass\" (with your current password and a new password)." }, @@ -250,6 +256,9 @@ static const struct message_entry msgtab[] = { { "NSMSG_UNREGNICK_SUCCESS", "Nick $b%s$b has been unregistered." }, { "NSMSG_UNREGISTER_SUCCESS", "Account $b%s$b has been unregistered." }, { "NSMSG_UNREGISTER_NICKS_SUCCESS", "Account $b%s$b and all its nicks have been unregistered." }, + { "NSMSG_UNREGISTER_MUST_FORCE", "Account $b%s$b is not inactive or has special flags set; use FORCE to unregister it." }, + { "NSMSG_UNREGISTER_CANNOT_FORCE", "Account $b%s$b is not inactive or has special flags set; have an IRCOp use FORCE to unregister it." }, + { "NSMSG_UNREGISTER_NODELETE", "Account $b%s$b is protected from unregistration." }, { "NSMSG_HANDLE_STATS", "There are %d nicks registered to your account." }, { "NSMSG_HANDLE_NONE", "You are not authenticated against any account." }, { "NSMSG_GLOBAL_STATS", "There are %d accounts and %d nicks registered globally." }, @@ -267,7 +276,7 @@ static const struct message_entry msgtab[] = { { "NSMSG_SET_FLAG", "Applied flags $b%s$b to %s's $N account." }, { "NSMSG_FLAG_PRIVILEGED", "You have insufficient access to set flag %c." }, { "NSMSG_DB_UNREADABLE", "Unable to read database file %s; check the log for more information." }, - { "NSMSG_DB_MERGED", "$N merged DB from %s (in "FMT_TIME_T".%03lu seconds)." }, + { "NSMSG_DB_MERGED", "$N merged DB from %s (in %lu.%03lu seconds)." }, { "NSMSG_HANDLE_CHANGED", "$b%s$b's account name has been changed to $b%s$b." }, { "NSMSG_BAD_HANDLE", "Account $b%s$b not registered because it is in use by a network service, is too long, or contains invalid characters." }, { "NSMSG_BAD_NICK", "Nickname $b%s$b not registered because it is in use by a network service, is too long, or contains invalid characters." }, @@ -287,14 +296,12 @@ static const struct message_entry msgtab[] = { { "NSMSG_CLONE_AUTH", "Warning: %s (%s@%s) authed to your account." }, { "NSMSG_SETTING_LIST", "$b$N account settings:$b" }, { "NSMSG_INVALID_OPTION", "$b%s$b is an invalid account setting." }, - { "NSMSG_INVALID_ANNOUNCE", "$b%s$b is an invalid announcements value." }, { "NSMSG_SET_INFO", "$bINFO: $b%s" }, { "NSMSG_SET_WIDTH", "$bWIDTH: $b%d" }, { "NSMSG_SET_TABLEWIDTH", "$bTABLEWIDTH: $b%d" }, { "NSMSG_SET_COLOR", "$bCOLOR: $b%s" }, { "NSMSG_SET_PRIVMSG", "$bPRIVMSG: $b%s" }, { "NSMSG_SET_STYLE", "$bSTYLE: $b%s" }, - { "NSMSG_SET_ANNOUNCEMENTS", "$bANNOUNCEMENTS: $b%s" }, { "NSMSG_SET_PASSWORD", "$bPASSWORD: $b%s" }, { "NSMSG_SET_FLAGS", "$bFLAGS: $b%s" }, { "NSMSG_SET_EMAIL", "$bEMAIL: $b%s" }, @@ -319,6 +326,9 @@ static const struct message_entry msgtab[] = { { "NSEMAIL_ALLOWAUTH_BODY", "This email has been sent to let you authenticate (auth) to account %5$s on %1$s. Your cookie is %2$s.\nTo auth to that account, log on to %1$s and type the following command:\n /msg %3$s@%4$s COOKIE %5$s %2$s\nIf you did NOT request this authorization, you do not need to do anything. Please contact the %1$s staff if you have questions." }, { "CHECKPASS_YES", "Yes." }, { "CHECKPASS_NO", "No." }, + { "CHECKEMAIL_NOT_SET", "No email set." }, + { "CHECKEMAIL_YES", "Yes." }, + { "CHECKEMAIL_NO", "No." }, { NULL, NULL } }; @@ -371,6 +381,8 @@ static struct { unsigned long auto_reclaim_delay; unsigned char default_maxlogins; unsigned char hard_maxlogins; + unsigned long ounregister_inactive; + unsigned long ounregister_flags; } nickserv_conf; /* We have 2^32 unique account IDs to use. */ @@ -389,9 +401,9 @@ canonicalize_hostmask(char *mask) { char *out = mask, *temp; if ((temp = strchr(mask, '!'))) { - temp++; - while (*temp) *out++ = *temp++; - *out++ = 0; + temp++; + while (*temp) *out++ = *temp++; + *out++ = 0; } return mask; } @@ -429,7 +441,6 @@ register_handle(const char *handle, const char *passwd, UNUSED_ARG(unsigned long hi = calloc(1, sizeof(*hi)); hi->userlist_style = HI_DEFAULT_STYLE; - hi->announcements = '?'; hi->handle = strdup(handle); safestrncpy(hi->passwd, passwd, sizeof(hi->passwd)); hi->infoline = NULL; @@ -467,15 +478,15 @@ delete_nick(struct nick_info *ni) } /* Remove ni from the nick_info linked list. */ if (ni == ni->owner->nicks) { - ni->owner->nicks = ni->next; + ni->owner->nicks = ni->next; } else { - last = ni->owner->nicks; - next = last->next; - while (next != ni) { - last = next; - next = last->next; - } - last->next = next->next; + last = ni->owner->nicks; + next = last->next; + while (next != ni) { + last = next; + next = last->next; + } + last->next = next->next; } dict_remove(nickserv_nick_dict, ni->nick); } @@ -487,13 +498,13 @@ void reg_unreg_func(unreg_func_t func) { if (unreg_func_used == unreg_func_size) { - if (unreg_func_size) { - unreg_func_size <<= 1; - unreg_func_list = realloc(unreg_func_list, unreg_func_size*sizeof(unreg_func_t)); - } else { - unreg_func_size = 8; - unreg_func_list = malloc(unreg_func_size*sizeof(unreg_func_t)); - } + if (unreg_func_size) { + unreg_func_size <<= 1; + unreg_func_list = realloc(unreg_func_list, unreg_func_size*sizeof(unreg_func_t)); + } else { + unreg_func_size = 8; + unreg_func_list = malloc(unreg_func_size*sizeof(unreg_func_t)); + } } unreg_func_list[unreg_func_used++] = func; } @@ -600,21 +611,21 @@ oper_has_access(struct userNode *user, struct userNode *bot, unsigned int min_le } if (!IsOper(user) && (!IsHelping(user) || min_level)) { - if (!quiet) + if (!quiet) send_message(user, bot, "NSMSG_NO_ACCESS"); - return 0; + return 0; } if (HANDLE_FLAGGED(user->handle_info, OPER_SUSPENDED)) { - if (!quiet) + if (!quiet) send_message(user, bot, "MSG_OPER_SUSPENDED"); - return 0; + return 0; } if (user->handle_info->opserv_level < min_level) { - if (!quiet) + if (!quiet) send_message(user, bot, "NSMSG_NO_ACCESS"); - return 0; + return 0; } return 1; @@ -630,7 +641,7 @@ is_valid_handle(const char *handle) return 0; /* check against maximum length */ if (strlen(handle) > NICKSERV_HANDLE_LEN) - return 0; + return 0; /* for consistency, only allow account names that could be nicks */ if (!is_valid_nick(handle)) return 0; @@ -712,9 +723,9 @@ smart_get_handle_info(struct userNode *service, struct userNode *user, const cha return 0; } if (IsLocal(target)) { - if (IsService(target)) + if (IsService(target)) send_message(user, service, "NSMSG_USER_IS_SERVICE", target->nick); - else + else send_message(user, service, "MSG_USER_AUTHENTICATE", target->nick); return 0; } @@ -750,8 +761,8 @@ get_victim_oper(struct userNode *user, const char *target) if (!(hi = smart_get_handle_info(nickserv, user, target))) return 0; if (HANDLE_FLAGGED(user->handle_info, OPER_SUSPENDED)) { - send_message(user, nickserv, "MSG_OPER_SUSPENDED"); - return 0; + send_message(user, nickserv, "MSG_OPER_SUSPENDED"); + return 0; } return oper_outranks(user, hi) ? hi : NULL; } @@ -770,8 +781,8 @@ valid_user_for(struct userNode *user, struct handle_info *hi) return 1; /* If they are allowauthed to this account, allow it (removing the aa). */ if (dict_find(nickserv_allow_auth_dict, user->nick, NULL) == hi) { - dict_remove(nickserv_allow_auth_dict, user->nick); - return 2; + dict_remove(nickserv_allow_auth_dict, user->nick); + return 2; } /* The user is not allowed to use this account. */ return 0; @@ -802,16 +813,16 @@ is_secure_password(const char *handle, const char *pass, struct userNode *user) return 0; } for (i=0; ihandle_info) { - struct userNode *other; + struct userNode *other; - if (IsHelper(user)) + if (IsHelper(user)) userList_remove(&curr_helpers, user); - /* remove from next_authed linked list */ - if (user->handle_info->users == user) { - user->handle_info->users = user->next_authed; - } else { - for (other = user->handle_info->users; - other->next_authed != user; - other = other->next_authed) ; - other->next_authed = user->next_authed; - } + /* remove from next_authed linked list */ + if (user->handle_info->users == user) { + user->handle_info->users = user->next_authed; + } else { + for (other = user->handle_info->users; + other->next_authed != user; + other = other->next_authed) ; + other->next_authed = user->next_authed; + } /* if nobody left on old handle, and they're not an oper, remove !god */ if (!user->handle_info->users && !user->handle_info->opserv_level) HANDLE_CLEAR_FLAG(user->handle_info, HELPING); /* record them as being last seen at this time */ - user->handle_info->lastseen = now; + user->handle_info->lastseen = now; /* and record their hostmask */ snprintf(user->handle_info->last_quit_host, sizeof(user->handle_info->last_quit_host), "%s@%s", user->ident, user->hostname); } @@ -935,10 +946,10 @@ set_user_handle_info(struct userNode *user, struct handle_info *hi, int stamp) for (other = hi->users; other; other = other->next_authed) send_message(other, nickserv, "NSMSG_CLONE_AUTH", user->nick, user->ident, user->hostname); } - user->next_authed = hi->users; - hi->users = user; - hi->lastseen = now; - if (IsHelper(user)) + user->next_authed = hi->users; + hi->users = user; + hi->lastseen = now; + if (IsHelper(user) && !userList_contains(&curr_helpers, user)) userList_append(&curr_helpers, user); if (hi->fakehost || old_info) @@ -971,7 +982,7 @@ set_user_handle_info(struct userNode *user, struct handle_info *hi, int stamp) timeq_del(0, nickserv_reclaim_p, user, TIMEQ_IGNORE_WHEN); } else { /* We cannot clear the user's account ID, unfortunately. */ - user->next_authed = NULL; + user->next_authed = NULL; } } @@ -983,8 +994,8 @@ nickserv_register(struct userNode *user, struct userNode *settee, const char *ha char crypted[MD5_CRYPT_LENGTH]; if ((hi = dict_find(nickserv_handle_dict, handle, NULL))) { - send_message(user, nickserv, "NSMSG_HANDLE_EXISTS", handle); - return 0; + send_message(user, nickserv, "NSMSG_HANDLE_EXISTS", handle); + return 0; } if (!is_secure_password(handle, passwd, user)) @@ -1149,9 +1160,9 @@ static NICKSERV_FUNC(cmd_register) int no_auth; if (!IsOper(user) && !dict_size(nickserv_handle_dict)) { - /* Require the first handle registered to belong to someone +o. */ - reply("NSMSG_REQUIRE_OPER"); - return 0; + /* Require the first handle registered to belong to someone +o. */ + reply("NSMSG_REQUIRE_OPER"); + return 0; } if (user->handle_info) { @@ -1161,7 +1172,7 @@ static NICKSERV_FUNC(cmd_register) if (IsRegistering(user)) { reply("NSMSG_ALREADY_REGISTERING"); - return 0; + return 0; } if (IsStamped(user)) { @@ -1269,22 +1280,22 @@ static NICKSERV_FUNC(cmd_oregister) mask = NULL; settee = NULL; } else if (strchr(argv[3], '@')) { - mask = canonicalize_hostmask(strdup(argv[3])); - if (argc > 4) { - settee = GetUserH(argv[4]); - if (!settee) { - reply("MSG_NICK_UNKNOWN", argv[4]); + mask = canonicalize_hostmask(strdup(argv[3])); + if (argc > 4) { + settee = GetUserH(argv[4]); + if (!settee) { + reply("MSG_NICK_UNKNOWN", argv[4]); free(mask); - return 0; - } - } else { - settee = NULL; - } + return 0; + } + } else { + settee = NULL; + } } else if ((settee = GetUserH(argv[3]))) { - mask = generate_hostmask(settee, GENMASK_OMITNICK|GENMASK_NO_HIDING|GENMASK_ANY_IDENT); + mask = generate_hostmask(settee, GENMASK_OMITNICK|GENMASK_NO_HIDING|GENMASK_ANY_IDENT); } else { - reply("NSMSG_REGISTER_BAD_NICKMASK", argv[3]); - return 0; + reply("NSMSG_REGISTER_BAD_NICKMASK", argv[3]); + return 0; } if (settee && settee->handle_info) { reply("NSMSG_USER_PREV_AUTH", settee->nick); @@ -1307,6 +1318,7 @@ static NICKSERV_FUNC(cmd_handleinfo) struct userNode *target, *next_un; struct handle_info *hi; const char *nsmsg_none; + time_t feh; if (argc < 2) { if (!(hi = user->handle_info)) { @@ -1322,13 +1334,14 @@ static NICKSERV_FUNC(cmd_handleinfo) #ifdef WITH_PROTOCOL_BAHAMUT reply("NSMSG_HANDLEINFO_ID", hi->id); #endif - reply("NSMSG_HANDLEINFO_REGGED", ctime(&hi->registered)); + feh = hi->registered; + reply("NSMSG_HANDLEINFO_REGGED", ctime(&feh)); if (!hi->users) { - intervalString(buff, now - hi->lastseen, user->handle_info); - reply("NSMSG_HANDLEINFO_LASTSEEN", buff); + intervalString(buff, now - hi->lastseen, user->handle_info); + reply("NSMSG_HANDLEINFO_LASTSEEN", buff); } else { - reply("NSMSG_HANDLEINFO_LASTSEEN_NOW"); + reply("NSMSG_HANDLEINFO_LASTSEEN_NOW"); } reply("NSMSG_HANDLEINFO_INFOLINE", (hi->infoline ? hi->infoline : nsmsg_none)); @@ -1362,35 +1375,37 @@ static NICKSERV_FUNC(cmd_handleinfo) reply(type); } - if (!hi->notes) { - reply("NSMSG_HANDLEINFO_NO_NOTES"); - } else { - struct handle_note *prev, *note; - - WALK_NOTES(hi, prev, note) { - char set_time[INTERVALLEN]; - intervalString(set_time, now - note->set, user->handle_info); - if (note->expires) { - char exp_time[INTERVALLEN]; - intervalString(exp_time, note->expires - now, user->handle_info); - reply("NSMSG_HANDLEINFO_NOTE_EXPIRES", note->id, set_time, note->setter, exp_time, note->note); - } else { - reply("NSMSG_HANDLEINFO_NOTE", note->id, set_time, note->setter, note->note); + if (oper_has_access(user, cmd->parent->bot, 0, 1) || IsStaff(user)) { + if (!hi->notes) { + reply("NSMSG_HANDLEINFO_NO_NOTES"); + } else { + struct handle_note *prev, *note; + + WALK_NOTES(hi, prev, note) { + char set_time[INTERVALLEN]; + intervalString(set_time, now - note->set, user->handle_info); + if (note->expires) { + char exp_time[INTERVALLEN]; + intervalString(exp_time, note->expires - now, user->handle_info); + reply("NSMSG_HANDLEINFO_NOTE_EXPIRES", note->id, set_time, note->setter, exp_time, note->note); + } else { + reply("NSMSG_HANDLEINFO_NOTE", note->id, set_time, note->setter, note->note); + } } } } if (hi->flags) { - unsigned long flen = 1; - char flags[34]; /* 32 bits possible plus '+' and '\0' */ - flags[0] = '+'; - for (i=0, flen=1; handle_flags[i]; i++) - if (hi->flags & 1 << i) + unsigned long flen = 1; + char flags[34]; /* 32 bits possible plus '+' and '\0' */ + flags[0] = '+'; + for (i=0, flen=1; handle_flags[i]; i++) + if (hi->flags & 1 << i) flags[flen++] = handle_flags[i]; - flags[flen] = 0; - reply("NSMSG_HANDLEINFO_FLAGS", flags); + flags[flen] = 0; + reply("NSMSG_HANDLEINFO_FLAGS", flags); } else { - reply("NSMSG_HANDLEINFO_FLAGS", nsmsg_none); + reply("NSMSG_HANDLEINFO_FLAGS", nsmsg_none); } if (HANDLE_FLAGGED(hi, SUPPORT_HELPER) @@ -1408,28 +1423,28 @@ static NICKSERV_FUNC(cmd_handleinfo) reply("NSMSG_HANDLEINFO_LAST_HOST_UNKNOWN"); if (nickserv_conf.disable_nicks) { - /* nicks disabled; don't show anything about registered nicks */ + /* nicks disabled; don't show anything about registered nicks */ } else if (hi->nicks) { - struct nick_info *ni, *next_ni; - for (ni = hi->nicks; ni; ni = next_ni) { - herelen = strlen(ni->nick); - if (pos + herelen + 1 > ArrayLength(buff)) { - next_ni = ni; - goto print_nicks_buff; - } else { - next_ni = ni->next; - } - memcpy(buff+pos, ni->nick, herelen); - pos += herelen; buff[pos++] = ' '; - if (!next_ni) { - print_nicks_buff: - buff[pos-1] = 0; - reply("NSMSG_HANDLEINFO_NICKS", buff); - pos = 0; - } - } + struct nick_info *ni, *next_ni; + for (ni = hi->nicks; ni; ni = next_ni) { + herelen = strlen(ni->nick); + if (pos + herelen + 1 > ArrayLength(buff)) { + next_ni = ni; + goto print_nicks_buff; + } else { + next_ni = ni->next; + } + memcpy(buff+pos, ni->nick, herelen); + pos += herelen; buff[pos++] = ' '; + if (!next_ni) { + print_nicks_buff: + buff[pos-1] = 0; + reply("NSMSG_HANDLEINFO_NICKS", buff); + pos = 0; + } + } } else { - reply("NSMSG_HANDLEINFO_NICKS", nsmsg_none); + reply("NSMSG_HANDLEINFO_NICKS", nsmsg_none); } if (hi->masks->used) { @@ -1453,47 +1468,47 @@ static NICKSERV_FUNC(cmd_handleinfo) } if (hi->channels) { - struct userData *channel, *next; - char *name; + struct userData *channel, *next; + char *name; - for (channel = hi->channels; channel; channel = next) { - next = channel->u_next; + for (channel = hi->channels; channel; channel = next) { + next = channel->u_next; name = channel->channel->channel->name; - herelen = strlen(name); - if (pos + herelen + 7 > ArrayLength(buff)) { - next = channel; + herelen = strlen(name); + if (pos + herelen + 7 > ArrayLength(buff)) { + next = channel; goto print_chans_buff; - } + } if (IsUserSuspended(channel)) buff[pos++] = '-'; pos += sprintf(buff+pos, "%d:%s ", channel->access, name); - if (next == NULL) { - print_chans_buff: - buff[pos-1] = 0; - reply("NSMSG_HANDLEINFO_CHANNELS", buff); - pos = 0; - } - } + if (next == NULL) { + print_chans_buff: + buff[pos-1] = 0; + reply("NSMSG_HANDLEINFO_CHANNELS", buff); + pos = 0; + } + } } else { - reply("NSMSG_HANDLEINFO_CHANNELS", nsmsg_none); + reply("NSMSG_HANDLEINFO_CHANNELS", nsmsg_none); } for (target = hi->users; target; target = next_un) { - herelen = strlen(target->nick); - if (pos + herelen + 1 > ArrayLength(buff)) { - next_un = target; - goto print_cnick_buff; - } else { - next_un = target->next_authed; - } - memcpy(buff+pos, target->nick, herelen); - pos += herelen; buff[pos++] = ' '; - if (!next_un) { - print_cnick_buff: - buff[pos-1] = 0; - reply("NSMSG_HANDLEINFO_CURRENT", buff); - pos = 0; - } + herelen = strlen(target->nick); + if (pos + herelen + 1 > ArrayLength(buff)) { + next_un = target; + goto print_cnick_buff; + } else { + next_un = target->next_authed; + } + memcpy(buff+pos, target->nick, herelen); + pos += herelen; buff[pos++] = ' '; + if (!next_un) { + print_cnick_buff: + buff[pos-1] = 0; + reply("NSMSG_HANDLEINFO_CURRENT", buff); + pos = 0; + } } return 1; @@ -1505,13 +1520,13 @@ static NICKSERV_FUNC(cmd_userinfo) NICKSERV_MIN_PARMS(2); if (!(target = GetUserH(argv[1]))) { - reply("MSG_NICK_UNKNOWN", argv[1]); - return 0; + reply("MSG_NICK_UNKNOWN", argv[1]); + return 0; } if (target->handle_info) - reply("NSMSG_USERINFO_AUTHED_AS", target->nick, target->handle_info->handle); + reply("NSMSG_USERINFO_AUTHED_AS", target->nick, target->handle_info->handle); else - reply("NSMSG_USERINFO_NOT_AUTHED", target->nick); + reply("NSMSG_USERINFO_NOT_AUTHED", target->nick); return 1; } @@ -1521,13 +1536,39 @@ static NICKSERV_FUNC(cmd_nickinfo) NICKSERV_MIN_PARMS(2); if (!(ni = get_nick_info(argv[1]))) { - reply("MSG_NICK_UNKNOWN", argv[1]); - return 0; + reply("MSG_NICK_UNKNOWN", argv[1]); + return 0; } reply("NSMSG_NICKINFO_OWNER", ni->nick, ni->owner->handle); return 1; } +static NICKSERV_FUNC(cmd_notes) +{ + struct handle_info *hi; + struct handle_note *prev, *note; + unsigned int hits; + + NICKSERV_MIN_PARMS(2); + if (!(hi = get_victim_oper(user, argv[1]))) + return 0; + hits = 0; + WALK_NOTES(hi, prev, note) { + char set_time[INTERVALLEN]; + intervalString(set_time, now - note->set, user->handle_info); + if (note->expires) { + char exp_time[INTERVALLEN]; + intervalString(exp_time, note->expires - now, user->handle_info); + reply("NSMSG_NOTE_EXPIRES", note->id, set_time, note->setter, exp_time, note->note); + } else { + reply("NSMSG_NOTE", note->id, set_time, note->setter, note->note); + } + ++hits; + } + reply("NSMSG_NOTE_COUNT", hits, argv[1]); + return 1; +} + static NICKSERV_FUNC(cmd_rename_handle) { struct handle_info *hi; @@ -1817,6 +1858,26 @@ static NICKSERV_FUNC(cmd_delcookie) return 1; } +static NICKSERV_FUNC(cmd_odelcookie) +{ + struct handle_info *hi; + + NICKSERV_MIN_PARMS(2); + + if (!(hi = get_victim_oper(user, argv[1]))) + return 0; + + if (!hi->cookie) { + reply("NSMSG_NO_COOKIE_FOREIGN", hi->handle); + return 0; + } + + nickserv_eat_cookie(hi->cookie); + reply("NSMSG_ATE_COOKIE_FOREIGN", hi->handle); + return 1; +} + + static NICKSERV_FUNC(cmd_resetpass) { struct handle_info *hi; @@ -1937,8 +1998,8 @@ static NICKSERV_FUNC(cmd_oregnick) { } ni = dict_find(nickserv_nick_dict, nick, NULL); if (ni) { - reply("NSMSG_NICK_EXISTS", nick); - return 0; + reply("NSMSG_NICK_EXISTS", nick); + return 0; } register_nick(nick, target); reply("NSMSG_OREGNICK_SUCCESS", nick, target->handle); @@ -1961,8 +2022,8 @@ static NICKSERV_FUNC(cmd_regnick) { } ni = dict_find(nickserv_nick_dict, user->nick, NULL); if (ni) { - reply("NSMSG_NICK_EXISTS", user->nick); - return 0; + reply("NSMSG_NICK_EXISTS", user->nick); + return 0; } register_nick(user->nick, user->handle_info); reply("NSMSG_REGNICK_SUCCESS", user->nick); @@ -1982,8 +2043,8 @@ static NICKSERV_FUNC(cmd_pass) if (!is_secure_password(hi->handle, new_pass, user)) return 0; if (!checkpass(old_pass, hi->passwd)) { argv[1] = "BADPASS"; - reply("NSMSG_PASSWORD_INVALID"); - return 0; + reply("NSMSG_PASSWORD_INVALID"); + return 0; } cryptpass(new_pass, hi->passwd); argv[1] = "****"; @@ -2039,17 +2100,17 @@ nickserv_delmask(struct userNode *user, struct handle_info *hi, const char *del_ { unsigned int i; for (i=0; imasks->used; i++) { - if (!strcmp(del_mask, hi->masks->list[i])) { - char *old_mask = hi->masks->list[i]; - if (hi->masks->used == 1 && !force) { - send_message(user, nickserv, "NSMSG_DELMASK_NOTLAST"); - return 0; - } - hi->masks->list[i] = hi->masks->list[--hi->masks->used]; - send_message(user, nickserv, "NSMSG_DELMASK_SUCCESS", old_mask); - free(old_mask); - return 1; - } + if (!strcmp(del_mask, hi->masks->list[i])) { + char *old_mask = hi->masks->list[i]; + if (hi->masks->used == 1 && !force) { + send_message(user, nickserv, "NSMSG_DELMASK_NOTLAST"); + return 0; + } + hi->masks->list[i] = hi->masks->list[--hi->masks->used]; + send_message(user, nickserv, "NSMSG_DELMASK_SUCCESS", old_mask); + free(old_mask); + return 1; + } } send_message(user, nickserv, "NSMSG_DELMASK_NOT_FOUND"); return 0; @@ -2076,26 +2137,26 @@ nickserv_modify_handle_flags(struct userNode *user, struct userNode *bot, const unsigned long added, removed, flag; for (added=removed=nn=0; str[nn]; nn++) { - switch (str[nn]) { - case '+': add = 1; break; - case '-': add = 0; break; - default: - if (!(pos = handle_inverse_flags[(unsigned char)str[nn]])) { - send_message(user, bot, "NSMSG_INVALID_FLAG", str[nn]); - return 0; - } + switch (str[nn]) { + case '+': add = 1; break; + case '-': add = 0; break; + default: + if (!(pos = handle_inverse_flags[(unsigned char)str[nn]])) { + send_message(user, bot, "NSMSG_INVALID_FLAG", str[nn]); + return 0; + } if (user && (user->handle_info->opserv_level < flag_access_levels[pos-1])) { /* cheesy avoidance of looking up the flag name.. */ send_message(user, bot, "NSMSG_FLAG_PRIVILEGED", str[nn]); return 0; } flag = 1 << (pos - 1); - if (add) + if (add) added |= flag, removed &= ~flag; - else + else removed |= flag, added &= ~flag; - break; - } + break; + } } *padded = added; *premoved = removed; @@ -2151,15 +2212,15 @@ set_list(struct userNode *user, struct handle_info *hi, int override) unsigned int i; char *set_display[] = { "INFO", "WIDTH", "TABLEWIDTH", "COLOR", "PRIVMSG", "STYLE", - "EMAIL", "ANNOUNCEMENTS", "MAXLOGINS", "LANGUAGE" + "EMAIL", "MAXLOGINS", "LANGUAGE" }; send_message(user, nickserv, "NSMSG_SETTING_LIST"); /* Do this so options are presented in a consistent order. */ for (i = 0; i < ArrayLength(set_display); ++i) - if ((opt = dict_find(nickserv_opt_dict, set_display[i], NULL))) - opt(user, hi, override, 0, NULL); + if ((opt = dict_find(nickserv_opt_dict, set_display[i], NULL))) + opt(user, hi, override, 0, NULL); } static NICKSERV_FUNC(cmd_set) @@ -2169,11 +2230,11 @@ static NICKSERV_FUNC(cmd_set) hi = user->handle_info; if (argc < 2) { - set_list(user, hi, 0); - return 1; + set_list(user, hi, 0); + return 1; } if (!(opt = dict_find(nickserv_opt_dict, argv[1], NULL))) { - reply("NSMSG_INVALID_OPTION", argv[1]); + reply("NSMSG_INVALID_OPTION", argv[1]); return 0; } return opt(user, hi, 0, argc-1, argv+1); @@ -2182,7 +2243,9 @@ static NICKSERV_FUNC(cmd_set) static NICKSERV_FUNC(cmd_oset) { struct handle_info *hi; + struct svccmd *subcmd; option_func_t *opt; + char cmdname[MAXLEN]; NICKSERV_MIN_PARMS(2); @@ -2190,15 +2253,20 @@ static NICKSERV_FUNC(cmd_oset) return 0; if (argc < 3) { - set_list(user, hi, 0); - return 1; + set_list(user, hi, 0); + return 1; } if (!(opt = dict_find(nickserv_opt_dict, argv[2], NULL))) { - reply("NSMSG_INVALID_OPTION", argv[2]); + reply("NSMSG_INVALID_OPTION", argv[2]); return 0; } + sprintf(cmdname, "%s %s", cmd->name, argv[2]); + subcmd = dict_find(cmd->parent->commands, cmdname, NULL); + if (subcmd && !svccmd_can_invoke(user, cmd->parent->bot, subcmd, NULL, SVCCMD_NOISY)) + return 0; + return opt(user, hi, 1, argc-2, argv+2); } @@ -2206,12 +2274,12 @@ static OPTION_FUNC(opt_info) { const char *info; if (argc > 1) { - if ((argv[1][0] == '*') && (argv[1][1] == 0)) { + if ((argv[1][0] == '*') && (argv[1][1] == 0)) { free(hi->infoline); hi->infoline = NULL; - } else { - hi->infoline = strdup(unsplit_string(argv+1, argc-1, NULL)); - } + } else { + hi->infoline = strdup(unsplit_string(argv+1, argc-1, NULL)); + } } info = hi->infoline ? hi->infoline : user_find_message(user, "MSG_NONE"); @@ -2222,7 +2290,7 @@ static OPTION_FUNC(opt_info) static OPTION_FUNC(opt_width) { if (argc > 1) - hi->screen_width = strtoul(argv[1], NULL, 0); + hi->screen_width = strtoul(argv[1], NULL, 0); if ((hi->screen_width > 0) && (hi->screen_width < MIN_LINE_SIZE)) hi->screen_width = MIN_LINE_SIZE; @@ -2236,7 +2304,7 @@ static OPTION_FUNC(opt_width) static OPTION_FUNC(opt_tablewidth) { if (argc > 1) - hi->table_width = strtoul(argv[1], NULL, 0); + hi->table_width = strtoul(argv[1], NULL, 0); if ((hi->table_width > 0) && (hi->table_width < MIN_LINE_SIZE)) hi->table_width = MIN_LINE_SIZE; @@ -2250,14 +2318,14 @@ static OPTION_FUNC(opt_tablewidth) static OPTION_FUNC(opt_color) { if (argc > 1) { - if (enabled_string(argv[1])) - HANDLE_SET_FLAG(hi, MIRC_COLOR); + if (enabled_string(argv[1])) + HANDLE_SET_FLAG(hi, MIRC_COLOR); else if (disabled_string(argv[1])) - HANDLE_CLEAR_FLAG(hi, MIRC_COLOR); - else { - send_message(user, nickserv, "MSG_INVALID_BINARY", argv[1]); - return 0; - } + HANDLE_CLEAR_FLAG(hi, MIRC_COLOR); + else { + send_message(user, nickserv, "MSG_INVALID_BINARY", argv[1]); + return 0; + } } send_message(user, nickserv, "NSMSG_SET_COLOR", user_find_message(user, HANDLE_FLAGGED(hi, MIRC_COLOR) ? "MSG_ON" : "MSG_OFF")); @@ -2267,14 +2335,14 @@ static OPTION_FUNC(opt_color) static OPTION_FUNC(opt_privmsg) { if (argc > 1) { - if (enabled_string(argv[1])) - HANDLE_SET_FLAG(hi, USE_PRIVMSG); + if (enabled_string(argv[1])) + HANDLE_SET_FLAG(hi, USE_PRIVMSG); else if (disabled_string(argv[1])) - HANDLE_CLEAR_FLAG(hi, USE_PRIVMSG); - else { - send_message(user, nickserv, "MSG_INVALID_BINARY", argv[1]); - return 0; - } + HANDLE_CLEAR_FLAG(hi, USE_PRIVMSG); + else { + send_message(user, nickserv, "MSG_INVALID_BINARY", argv[1]); + return 0; + } } send_message(user, nickserv, "NSMSG_SET_PRIVMSG", user_find_message(user, HANDLE_FLAGGED(hi, USE_PRIVMSG) ? "MSG_ON" : "MSG_OFF")); @@ -2286,61 +2354,34 @@ static OPTION_FUNC(opt_style) char *style; if (argc > 1) { - if (!irccasecmp(argv[1], "Zoot")) - hi->userlist_style = HI_STYLE_ZOOT; - else if (!irccasecmp(argv[1], "def")) - hi->userlist_style = HI_STYLE_DEF; + if (!irccasecmp(argv[1], "Zoot")) + hi->userlist_style = HI_STYLE_ZOOT; + else if (!irccasecmp(argv[1], "def")) + hi->userlist_style = HI_STYLE_DEF; } switch (hi->userlist_style) { case HI_STYLE_DEF: - style = "def"; - break; + style = "def"; + break; case HI_STYLE_ZOOT: default: - style = "Zoot"; + style = "Zoot"; } send_message(user, nickserv, "NSMSG_SET_STYLE", style); return 1; } -static OPTION_FUNC(opt_announcements) -{ - const char *choice; - - if (argc > 1) { - if (enabled_string(argv[1])) - hi->announcements = 'y'; - else if (disabled_string(argv[1])) - hi->announcements = 'n'; - else if (!strcmp(argv[1], "?") || !irccasecmp(argv[1], "default")) - hi->announcements = '?'; - else { - send_message(user, nickserv, "NSMSG_INVALID_ANNOUNCE", argv[1]); - return 0; - } - } - - switch (hi->announcements) { - case 'y': choice = user_find_message(user, "MSG_ON"); break; - case 'n': choice = user_find_message(user, "MSG_OFF"); break; - case '?': choice = "default"; break; - default: choice = "unknown"; break; - } - send_message(user, nickserv, "NSMSG_SET_ANNOUNCEMENTS", choice); - return 1; -} - static OPTION_FUNC(opt_password) { if (!override) { - send_message(user, nickserv, "NSMSG_USE_CMD_PASS"); - return 0; + send_message(user, nickserv, "NSMSG_USE_CMD_PASS"); + return 0; } if (argc > 1) - cryptpass(argv[1], hi->passwd); + cryptpass(argv[1], hi->passwd); send_message(user, nickserv, "NSMSG_SET_PASSWORD", "***"); return 1; @@ -2352,12 +2393,12 @@ static OPTION_FUNC(opt_flags) unsigned int ii, flen; if (!override) { - send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]); - return 0; + send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]); + return 0; } if (argc > 1) - nickserv_apply_flags(user, hi, argv[1]); + nickserv_apply_flags(user, hi, argv[1]); for (ii = flen = 0; handle_flags[ii]; ii++) if (hi->flags & (1 << ii)) @@ -2480,8 +2521,8 @@ static OPTION_FUNC(opt_level) int res; if (!override) { - send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]); - return 0; + send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]); + return 0; } res = (argc > 1) ? oper_try_set_access(user, nickserv, hi, strtoul(argv[1], NULL, 0)) : 0; @@ -2629,12 +2670,12 @@ static NICKSERV_FUNC(cmd_unregnick) nick = (argc < 2) ? user->nick : (const char*)argv[1]; ni = dict_find(nickserv_nick_dict, nick, NULL); if (!ni) { - reply("NSMSG_UNKNOWN_NICK", nick); - return 0; + reply("NSMSG_UNKNOWN_NICK", nick); + return 0; } if (hi != ni->owner) { - reply("NSMSG_NOT_YOUR_NICK", nick); - return 0; + reply("NSMSG_NOT_YOUR_NICK", nick); + return 0; } reply("NSMSG_UNREGNICK_SUCCESS", ni->nick); delete_nick(ni); @@ -2647,8 +2688,8 @@ static NICKSERV_FUNC(cmd_ounregnick) NICKSERV_MIN_PARMS(2); if (!(ni = get_nick_info(argv[1]))) { - reply("NSMSG_NICK_NOT_REGISTERED", argv[1]); - return 0; + reply("NSMSG_NICK_NOT_REGISTERED", argv[1]); + return 0; } if (!oper_outranks(user, ni->owner)) return 0; @@ -2670,8 +2711,8 @@ static NICKSERV_FUNC(cmd_unregister) nickserv_unregister_handle(hi, user); return 1; } else { - log_module(NS_LOG, LOG_INFO, "Account '%s' tried to unregister with the wrong password.", hi->handle); - reply("NSMSG_PASSWORD_INVALID"); + log_module(NS_LOG, LOG_INFO, "Account '%s' tried to unregister with the wrong password.", hi->handle); + reply("NSMSG_PASSWORD_INVALID"); return 0; } } @@ -2680,10 +2721,26 @@ static NICKSERV_FUNC(cmd_ounregister) { struct handle_info *hi; char reason[MAXLEN]; + int force; NICKSERV_MIN_PARMS(2); if (!(hi = get_victim_oper(user, argv[1]))) return 0; + + if (HANDLE_FLAGGED(hi, NODELETE)) { + reply("NSMSG_UNREGISTER_NODELETE", hi->handle); + return 0; + } + + force = IsOper(user) && (argc > 2) && !irccasecmp(argv[2], "force"); + if (!force && + ((hi->flags & nickserv_conf.ounregister_flags) + || hi->users + || (hi->last_quit_host[0] && ((unsigned)(now - hi->lastseen) < nickserv_conf.ounregister_inactive)))) { + reply((IsOper(user) ? "NSMSG_UNREGISTER_MUST_FORCE" : "NSMSG_UNREGISTER_CANNOT_FORCE"), hi->handle); + return 0; + } + snprintf(reason, sizeof(reason), "%s unregistered account %s.", user->handle_info->handle, hi->handle); global_message(MESSAGE_RECIPIENT_STAFF, reason); nickserv_unregister_handle(hi, user); @@ -2756,7 +2813,13 @@ static NICKSERV_FUNC(cmd_addnote) hi = get_victim_oper(user, argv[1]); if (!hi) return 0; - duration = ParseInterval(argv[2]); + if(!strcmp(argv[2], "0")) + duration = 0; + else if(!(duration = ParseInterval(argv[2]))) + { + reply("MSG_INVALID_DURATION", argv[2]); + return 0; + } if (duration > 2*365*86400) { reply("NSMSG_EXCESSIVE_DURATION", argv[2]); return 0; @@ -2820,11 +2883,6 @@ nickserv_saxdb_write(struct saxdb_context *ctx) { assert(hi->id); #endif saxdb_start_record(ctx, iter_key(it), 0); - if (hi->announcements != '?') { - flags[0] = hi->announcements; - flags[1] = 0; - saxdb_write_string(ctx, KEY_ANNOUNCEMENTS, flags); - } if (hi->cookie) { struct handle_cookie *cookie = hi->cookie; char *type; @@ -3058,14 +3116,15 @@ static NICKSERV_FUNC(cmd_merge) struct nickserv_discrim { unsigned long flags_on, flags_off; - time_t min_registered, max_registered; - time_t lastseen; + unsigned long min_registered, max_registered; + unsigned long lastseen; unsigned int limit; int min_level, max_level; int min_karma, max_karma; enum { SUBSET, EXACT, SUPERSET, LASTQUIT } hostmask_type; const char *nickmask; const char *hostmask; + const char *fakehostmask; const char *handlemask; const char *emailmask; }; @@ -3088,11 +3147,11 @@ nickserv_discrim_create(struct userNode *user, unsigned int argc, char *argv[]) discrim = malloc(sizeof(*discrim)); memset(discrim, 0, sizeof(*discrim)); discrim->min_level = 0; - discrim->max_level = ~0; + discrim->max_level = INT_MAX; discrim->limit = 50; discrim->min_registered = 0; - discrim->max_registered = INT_MAX; - discrim->lastseen = now; + discrim->max_registered = ULONG_MAX; + discrim->lastseen = ULONG_MAX; discrim->min_karma = INT_MIN; discrim->max_karma = INT_MAX; @@ -3148,17 +3207,23 @@ nickserv_discrim_create(struct userNode *user, unsigned int argc, char *argv[]) goto fail; } discrim->hostmask_type = SUPERSET; - } else if (!irccasecmp(argv[i], "lastquit") || !irccasecmp(argv[i], "lastauth")) { - if (i == argc - 1) { - send_message(user, nickserv, "MSG_MISSING_PARAMS", argv[i]); - goto fail; - } - discrim->hostmask_type = LASTQUIT; + } else if (!irccasecmp(argv[i], "lastquit") || !irccasecmp(argv[i], "lastauth")) { + if (i == argc - 1) { + send_message(user, nickserv, "MSG_MISSING_PARAMS", argv[i]); + goto fail; + } + discrim->hostmask_type = LASTQUIT; } else { i--; discrim->hostmask_type = SUPERSET; } discrim->hostmask = argv[++i]; + } else if (!irccasecmp(argv[i], "fakehost")) { + if (!irccasecmp(argv[++i], "*")) { + discrim->fakehostmask = 0; + } else { + discrim->fakehostmask = argv[i]; + } } else if (!irccasecmp(argv[i], "handlemask") || !irccasecmp(argv[i], "accountmask")) { if (!irccasecmp(argv[++i], "*")) { discrim->handlemask = 0; @@ -3233,6 +3298,7 @@ nickserv_discrim_match(struct nickserv_discrim *discrim, struct handle_info *hi) || (discrim->max_registered < hi->registered) || (discrim->lastseen < (hi->users?now:hi->lastseen)) || (discrim->handlemask && !match_ircglob(hi->handle, discrim->handlemask)) + || (discrim->fakehostmask && (!hi->fakehost || !match_ircglob(hi->fakehost, discrim->fakehostmask))) || (discrim->emailmask && (!hi->email_addr || !match_ircglob(hi->email_addr, discrim->emailmask))) || (discrim->min_level > hi->opserv_level) || (discrim->max_level < hi->opserv_level) @@ -3251,8 +3317,8 @@ nickserv_discrim_match(struct nickserv_discrim *discrim, struct handle_info *hi) && !irccasecmp(discrim->hostmask, mask)) break; else if ((discrim->hostmask_type == SUPERSET) && (match_ircglobs(mask, discrim->hostmask))) break; - else if ((discrim->hostmask_type == LASTQUIT) - && (match_ircglobs(discrim->hostmask, hi->last_quit_host))) break; + else if ((discrim->hostmask_type == LASTQUIT) + && (match_ircglobs(discrim->hostmask, hi->last_quit_host))) break; } if (i==hi->masks->used) return 0; } @@ -3412,6 +3478,25 @@ static MODCMD_FUNC(cmd_checkpass) return 1; } +static MODCMD_FUNC(cmd_checkemail) +{ + struct handle_info *hi; + + NICKSERV_MIN_PARMS(3); + if (!(hi = modcmd_get_handle_info(user, argv[1]))) { + reply("MSG_HANDLE_UNKNOWN", argv[1]); + return 0; + } + if (!hi->email_addr) + reply("CHECKEMAIL_NOT_SET"); + else if (!irccasecmp(argv[2], hi->email_addr)) + reply("CHECKEMAIL_YES"); + else + reply("CHECKEMAIL_NO"); + return 1; +} + + static void nickserv_db_read_handle(const char *handle, dict_t obj) { @@ -3462,9 +3547,9 @@ nickserv_db_read_handle(const char *handle, dict_t obj) if (str) hi->infoline = strdup(str); str = database_get_data(obj, KEY_REGISTER_ON, RECDB_QSTRING); - hi->registered = str ? (time_t)strtoul(str, NULL, 0) : now; + hi->registered = str ? strtoul(str, NULL, 0) : now; str = database_get_data(obj, KEY_LAST_SEEN, RECDB_QSTRING); - hi->lastseen = str ? (time_t)strtoul(str, NULL, 0) : hi->registered; + hi->lastseen = str ? strtoul(str, NULL, 0) : hi->registered; str = database_get_data(obj, KEY_KARMA, RECDB_QSTRING); hi->karma = str ? strtoul(str, NULL, 0) : 0; /* We want to read the nicks even if disable_nicks is set. This is so @@ -3481,8 +3566,6 @@ nickserv_db_read_handle(const char *handle, dict_t obj) } str = database_get_data(obj, KEY_USERLIST_STYLE, RECDB_QSTRING); hi->userlist_style = str ? str[0] : HI_STYLE_ZOOT; - str = database_get_data(obj, KEY_ANNOUNCEMENTS, RECDB_QSTRING); - hi->announcements = str ? str[0] : '?'; str = database_get_data(obj, KEY_SCREEN_WIDTH, RECDB_QSTRING); hi->screen_width = str ? strtoul(str, NULL, 0) : 0; str = database_get_data(obj, KEY_TABLE_WIDTH, RECDB_QSTRING); @@ -3616,10 +3699,10 @@ static NICKSERV_FUNC(cmd_mergedb) stop.tv_sec -= start.tv_sec; stop.tv_usec -= start.tv_usec; if (stop.tv_usec < 0) { - stop.tv_sec -= 1; - stop.tv_usec += 1000000; + stop.tv_sec -= 1; + stop.tv_usec += 1000000; } - reply("NSMSG_DB_MERGED", argv[1], stop.tv_sec, stop.tv_usec/1000); + reply("NSMSG_DB_MERGED", argv[1], (unsigned long)stop.tv_sec, (unsigned long)stop.tv_usec/1000); return 1; } @@ -3627,7 +3710,7 @@ static void expire_handles(UNUSED_ARG(void *data)) { dict_iterator_t it, next; - time_t expiry; + unsigned long expiry; struct handle_info *hi; for (it=dict_first(nickserv_handle_dict); it; it=next) { @@ -3693,8 +3776,8 @@ nickserv_conf_read(void) dict_iterator_t it; if (!(conf_node = conf_get_data(NICKSERV_CONF_NAME, RECDB_OBJECT))) { - log_module(NS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", NICKSERV_CONF_NAME); - return; + log_module(NS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", NICKSERV_CONF_NAME); + return; } str = database_get_data(conf_node, KEY_VALID_HANDLE_REGEX, RECDB_QSTRING); if (!str) @@ -3762,6 +3845,18 @@ nickserv_conf_read(void) nickserv_conf.default_maxlogins = str ? strtoul(str, NULL, 0) : 2; str = database_get_data(conf_node, "hard_maxlogins", RECDB_QSTRING); nickserv_conf.hard_maxlogins = str ? strtoul(str, NULL, 0) : 10; + str = database_get_data(conf_node, KEY_OUNREGISTER_INACTIVE, RECDB_QSTRING); + nickserv_conf.ounregister_inactive = str ? ParseInterval(str) : 86400*28; + str = database_get_data(conf_node, KEY_OUNREGISTER_FLAGS, RECDB_QSTRING); + if (!str) + str = "ShgsfnHbu"; + nickserv_conf.ounregister_flags = 0; + while(*str) { + unsigned int pos = handle_inverse_flags[(unsigned char)*str]; + str++; + if(pos) + nickserv_conf.ounregister_flags |= 1 << (pos - 1); + } if (!nickserv_conf.disable_nicks) { str = database_get_data(conf_node, "reclaim_action", RECDB_QSTRING); nickserv_conf.reclaim_action = str ? reclaim_action_from_string(str) : RECLAIM_NONE; @@ -4032,13 +4127,14 @@ init_nickserv(const char *nick) nickserv_define_func("MERGE", cmd_merge, 750, 1, 0); nickserv_define_func("ADDNOTE", cmd_addnote, 0, 1, 0); nickserv_define_func("DELNOTE", cmd_delnote, 0, 1, 0); + nickserv_define_func("NOTES", cmd_notes, 0, 1, 0); if (!nickserv_conf.disable_nicks) { - /* nick management commands */ - nickserv_define_func("REGNICK", cmd_regnick, -1, 1, 0); - nickserv_define_func("OREGNICK", cmd_oregnick, 0, 1, 0); - nickserv_define_func("UNREGNICK", cmd_unregnick, -1, 1, 0); - nickserv_define_func("OUNREGNICK", cmd_ounregnick, 0, 1, 0); - nickserv_define_func("NICKINFO", cmd_nickinfo, -1, 1, 0); + /* nick management commands */ + nickserv_define_func("REGNICK", cmd_regnick, -1, 1, 0); + nickserv_define_func("OREGNICK", cmd_oregnick, 0, 1, 0); + nickserv_define_func("UNREGNICK", cmd_unregnick, -1, 1, 0); + nickserv_define_func("OUNREGNICK", cmd_ounregnick, 0, 1, 0); + nickserv_define_func("NICKINFO", cmd_nickinfo, -1, 1, 0); nickserv_define_func("RECLAIM", cmd_reclaim, -1, 1, 0); } if (nickserv_conf.email_enabled) { @@ -4046,6 +4142,7 @@ init_nickserv(const char *nick) nickserv_define_func("RESETPASS", cmd_resetpass, -1, 0, 1); nickserv_define_func("COOKIE", cmd_cookie, -1, 0, 1); nickserv_define_func("DELCOOKIE", cmd_delcookie, -1, 1, 0); + nickserv_define_func("ODELCOOKIE", cmd_odelcookie, 0, 1, 0); dict_insert(nickserv_opt_dict, "EMAIL", opt_email); } nickserv_define_func("GHOST", cmd_ghost, -1, 1, 0); @@ -4055,6 +4152,7 @@ init_nickserv(const char *nick) nickserv_define_func("SEARCH UNREGISTER", NULL, 800, 1, 0); nickserv_define_func("MERGEDB", cmd_mergedb, 999, 1, 0); nickserv_define_func("CHECKPASS", cmd_checkpass, 601, 1, 0); + nickserv_define_func("CHECKEMAIL", cmd_checkemail, 0, 1, 0); /* other options */ dict_insert(nickserv_opt_dict, "INFO", opt_info); dict_insert(nickserv_opt_dict, "WIDTH", opt_width); @@ -4072,10 +4170,10 @@ init_nickserv(const char *nick) dict_insert(nickserv_opt_dict, "TITLE", opt_title); dict_insert(nickserv_opt_dict, "FAKEHOST", opt_fakehost); } - dict_insert(nickserv_opt_dict, "ANNOUNCEMENTS", opt_announcements); dict_insert(nickserv_opt_dict, "MAXLOGINS", opt_maxlogins); dict_insert(nickserv_opt_dict, "LANGUAGE", opt_language); dict_insert(nickserv_opt_dict, "KARMA", opt_karma); + nickserv_define_func("OSET KARMA", NULL, 0, 1, 0); nickserv_handle_dict = dict_new(); dict_set_free_keys(nickserv_handle_dict, free);