Do not display account notes to non-staff.
[srvx.git] / src / nickserv.c
index 683fd71afe8af4150958fdd8b890fad50a240fc7..f2f42bcffaa677f87942fedcc9f6d4be2c5e8bd3 100644 (file)
@@ -96,7 +96,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"
@@ -219,6 +218,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)." },
@@ -287,14 +289,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" },
@@ -429,7 +429,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;
@@ -1362,20 +1361,22 @@ 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) || IsSupport(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);
+                }
             }
         }
     }
@@ -1528,6 +1529,32 @@ static NICKSERV_FUNC(cmd_nickinfo)
     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;
@@ -2151,7 +2178,7 @@ 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");
@@ -2182,7 +2209,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);
 
@@ -2199,6 +2228,11 @@ static NICKSERV_FUNC(cmd_oset)
         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);
 }
 
@@ -2305,33 +2339,6 @@ static OPTION_FUNC(opt_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) {
@@ -2820,11 +2827,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;
@@ -3066,6 +3068,7 @@ struct nickserv_discrim {
     enum { SUBSET, EXACT, SUPERSET, LASTQUIT } hostmask_type;
     const char *nickmask;
     const char *hostmask;
+    const char *fakehostmask;
     const char *handlemask;
     const char *emailmask;
 };
@@ -3088,11 +3091,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->lastseen = LONG_MAX;
     discrim->min_karma = INT_MIN;
     discrim->max_karma = INT_MAX;
 
@@ -3159,6 +3162,12 @@ nickserv_discrim_create(struct userNode *user, unsigned int argc, char *argv[])
                 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 +3242,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)
@@ -3481,8 +3491,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);
@@ -4032,6 +4040,7 @@ 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);
@@ -4072,10 +4081,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);