add id field to cmd_search
[srvx.git] / src / nickserv.c
index 25c2a43cfa9dc427b1adead6d1e66e0e02632d6d..15c5743b663f04fed3bc8bd3562f62ede3765311 100644 (file)
@@ -491,7 +491,7 @@ register_handle(const char *handle, const char *passwd, unsigned long id)
 
     hi->id = id;
     hi->website = NULL;
-    hi->devnull = NULL;
+    hi->devnull_id = 0;
     dict_insert(nickserv_id_dict, strdup(id_base64), hi);
 
     return hi;
@@ -578,7 +578,6 @@ free_handle_info(void *vhi)
     free(hi->infoline);
     free(hi->epithet);
     free(hi->fakehost);
-    free(hi->devnull);
     free(hi->website);
     free(hi->fakeident);
     if (hi->cookie) {
@@ -1510,8 +1509,10 @@ static NICKSERV_FUNC(cmd_handleinfo)
     }
 
     reply("NSMSG_HANDLEINFO_INFOLINE", (hi->infoline ? hi->infoline : nsmsg_none));
-    if ((oper_has_access(user, cmd->parent->bot, 200, 1)) || IsNetworkHelper(user))
-        reply("NSMSG_HANDLEINFO_DEVNULL", (hi->devnull ? hi->devnull : nsmsg_none));
+    if ((oper_has_access(user, cmd->parent->bot, 200, 1)) || IsNetworkHelper(user)) {
+        struct devnull_class *devnull_c = (hi->devnull_id ? devnull_find_id(hi->devnull_id) : NULL);
+        reply("NSMSG_HANDLEINFO_DEVNULL", (devnull_c ? devnull_c->name : nsmsg_none));
+    }
     if (user->handle_info && HANDLE_FLAGGED(user->handle_info, BOT))
         reply("NSMSG_HANDLEINFO_WEBSITE", (hi->website ? hi->website : nsmsg_none));
     if(hi->opserv_level > 0 && user->handle_info && HANDLE_FLAGGED(user->handle_info, BOT))
@@ -2649,52 +2650,46 @@ static OPTION_FUNC(opt_info)
 
 static OPTION_FUNC(opt_devnull)
 {
-    const char *devnull;
-    
+    const char *devnull_name;
+    struct devnull_class *devnull_c;
+
     if (argc > 1) {
         if (!override) {
             send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]);
             return 0;
         }
         if ((argv[1][0] == '*') && (argv[1][1] == 0)) {
-            free(hi->devnull);
-            hi->devnull = NULL;
+            hi->devnull_id = 0;
         } else {
-            devnull = unsplit_string(argv+1, argc-1, NULL);
-            if(devnull_check(devnull) == 1) { 
-                if(hi->devnull)
-                    free(hi->devnull);
-                hi->devnull = strdup(devnull);
-            }
+            devnull_name = unsplit_string(argv+1, argc-1, NULL);
+            devnull_c = devnull_find_name(devnull_name);
+            if(devnull_c)
+                hi->devnull_id = devnull_c->id;
         }
     }
 
-    devnull = hi->devnull ? hi->devnull : user_find_message(user, "MSG_NONE");
-    send_message(user, nickserv, "NSMSG_SET_DEVNULL", devnull);
-    return 1;
-}
-
-void nickserv_devnull_delete(char *name) {
-    dict_iterator_t it;
-    struct handle_info *hi;
-
-    for (it = dict_first(nickserv_handle_dict); it; it = iter_next(it)) {
-        hi = iter_data(it);
-        if (hi->devnull && !irccasecmp(name, hi->devnull)) {
-            free(hi->devnull);
-            hi->devnull = NULL;
+    if(hi->devnull_id) {
+        devnull_c = devnull_find_id(hi->devnull_id);
+        if(devnull_c)
+            devnull_name = devnull_c->name;
+        else {
+            devnull_name = user_find_message(user, "MSG_NONE");
+            hi->devnull_id = 0;
         }
-    }
+    } else
+        devnull_name = user_find_message(user, "MSG_NONE");
+    send_message(user, nickserv, "NSMSG_SET_DEVNULL", devnull_name);
+    return 1;
 }
 
-void nickserv_devnull_rename(char *oldname, char *newname) {
+void nickserv_devnull_delete(unsigned int devnull_id) {
     dict_iterator_t it;
     struct handle_info *hi;
 
     for (it = dict_first(nickserv_handle_dict); it; it = iter_next(it)) {
         hi = iter_data(it);
-        if (hi->devnull && !irccasecmp(oldname, hi->devnull)) {
-            hi->devnull = strdup(newname);
+        if (hi->devnull_id == devnull_id) {
+            hi->devnull_id = 0;
         }
     }
 }
@@ -3500,8 +3495,8 @@ nickserv_saxdb_write(struct saxdb_context *ctx) {
         saxdb_write_int(ctx, KEY_ID, hi->id);
         if (hi->infoline)
             saxdb_write_string(ctx, KEY_INFO, hi->infoline);
-        if (hi->devnull)
-            saxdb_write_string(ctx, KEY_DEVNULL, hi->devnull);
+        if (hi->devnull_id)
+            saxdb_write_int(ctx, KEY_DEVNULL, hi->devnull_id);
         if (hi->website)
             saxdb_write_string(ctx, KEY_WEBSITE, hi->website);
         if (hi->last_quit_host[0])
@@ -3709,8 +3704,9 @@ static NICKSERV_FUNC(cmd_merge)
 #define NICKSERV_DISCRIM_FIELDS_FAKEHOST 0x10
 #define NICKSERV_DISCRIM_FIELDS_WEBSITE  0x20
 #define NICKSERV_DISCRIM_FIELDS_DEVNULL  0x40
+#define NICKSERV_DISCRIM_FIELDS_ID       0x80
 
-#define NICKSERV_DISCRIM_FIELD_COUNT     7
+#define NICKSERV_DISCRIM_FIELD_COUNT     8
 
 struct nickserv_discrim {
     unsigned int show_fields;
@@ -3723,6 +3719,7 @@ struct nickserv_discrim {
     unsigned long lastseen;
     unsigned int limit;
     int min_level, max_level;
+    unsigned int min_id, max_id;
     int min_karma, max_karma;
     enum { SUBSET, EXACT, SUPERSET, LASTQUIT } hostmask_type;
     const char *nickmask;
@@ -3730,9 +3727,10 @@ struct nickserv_discrim {
     const char *fakehostmask;
     const char *fakeidentmask;
     const char *website;
-    const char *devnullclass;
     const char *handlemask;
     const char *emailmask;
+    const char *devnull_name;
+    unsigned int devnull_id;
 };
 
 typedef void (*discrim_search_func)(struct userNode *source, struct handle_info *hi, struct nickserv_discrim *discrim);
@@ -3760,6 +3758,9 @@ nickserv_discrim_create(struct userNode *user, unsigned int argc, char *argv[])
     discrim->lastseen = ULONG_MAX;
     discrim->min_karma = INT_MIN;
     discrim->max_karma = INT_MAX;
+    discrim->min_id = 0;
+    discrim->max_id = INT_MAX;
 
     for (i=0; i<argc; i++) {
         if (i == argc - 1) {
@@ -3784,6 +3785,8 @@ nickserv_discrim_create(struct userNode *user, unsigned int argc, char *argv[])
                     discrim->show_fields |= NICKSERV_DISCRIM_FIELDS_SEEN;
                 else if(!irccasecmp(fields, "access"))
                     discrim->show_fields |= NICKSERV_DISCRIM_FIELDS_ACCESS;
+                else if(!irccasecmp(fields, "id"))
+                     discrim->show_fields |= NICKSERV_DISCRIM_FIELDS_ID;
                 else if(!irccasecmp(fields, "fakehost"))
                     discrim->show_fields |= NICKSERV_DISCRIM_FIELDS_FAKEHOST;
                 else if(!irccasecmp(fields, "website") && IsBot(user))
@@ -3878,9 +3881,16 @@ nickserv_discrim_create(struct userNode *user, unsigned int argc, char *argv[])
             }
         } else if (!irccasecmp(argv[i], "devnull")) {
             if (!irccasecmp(argv[++i], "*")) {
-                discrim->devnullclass = 0;
+                discrim->devnull_id = 0;
+                discrim->devnull_name = 0;
             } else {
-                discrim->devnullclass = argv[i];
+                struct devnull_class *th = devnull_find_name(argv[i]);
+                if(!th) {
+                    send_message(user, nickserv, "OSMSG_DEVNULL_NOTFOUND", argv[i]);
+                    goto fail;
+                }
+                discrim->devnull_name = argv[i];
+                discrim->devnull_id = th->id;
             }
         } else if (!irccasecmp(argv[i], "handlemask") || !irccasecmp(argv[i], "accountmask")) {
             if (!irccasecmp(argv[++i], "*")) {
@@ -3917,6 +3927,26 @@ nickserv_discrim_create(struct userNode *user, unsigned int argc, char *argv[])
             } else {
                 send_message(user, nickserv, "MSG_INVALID_CRITERIA", cmp);
             }
+        } else if (!irccasecmp(argv[i], "id")) {
+            const char *cmp = argv[++i];
+            if (cmp[0] == '<') {
+                if (discrim->min_id == 0) discrim->min_id = 1;
+                if (cmp[1] == '=') {
+                    discrim->max_id = strtoul(cmp+2, NULL, 0);
+                } else {
+                    discrim->max_id = strtoul(cmp+1, NULL, 0) - 1;
+                }
+            } else if (cmp[0] == '=') {
+                discrim->min_id = discrim->max_id = strtoul(cmp+1, NULL, 0);
+            } else if (cmp[0] == '>') {
+                if (cmp[1] == '=') {
+                    discrim->min_id = strtoul(cmp+2, NULL, 0);
+                } else {
+                    discrim->min_id = strtoul(cmp+1, NULL, 0) + 1;
+                }
+            } else {
+                send_message(user, nickserv, "MSG_INVALID_CRITERIA", cmp);
+            }
         } else if (!irccasecmp(argv[i], "karma")) {
             const char *cmp = argv[++i];
             if (cmp[0] == '<') {
@@ -3959,10 +3989,12 @@ nickserv_discrim_match(struct nickserv_discrim *discrim, struct handle_info *hi)
         || (discrim->fakehostmask && (!hi->fakehost || !match_ircglob(hi->fakehost, discrim->fakehostmask)))
         || (discrim->fakeidentmask && (!hi->fakeident || !match_ircglob(hi->fakeident, discrim->fakeidentmask)))
         || (discrim->website && (!hi->website || !match_ircglob(hi->website, discrim->website)))
-        || (discrim->devnullclass && (!hi->devnull || !match_ircglob(hi->devnull, discrim->devnullclass)))
+        || (discrim->devnull_id && discrim->devnull_id != hi->devnull_id)
         || (discrim->emailmask && (!hi->email_addr || !match_ircglob(hi->email_addr, discrim->emailmask)))
         || (discrim->min_level > hi->opserv_level)
         || (discrim->max_level < hi->opserv_level)
+        || (discrim->min_id > hi->id)
+        || (discrim->max_id < hi->id)
         || (discrim->min_karma > hi->karma)
         || (discrim->max_karma < hi->karma)
         ) {
@@ -4039,13 +4071,20 @@ search_print_func(struct userNode *source, struct handle_info *match, struct nic
             }
             if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_ACCESS)
                 discrim->output_table->contents[discrim->output_table_pos][i++] = strtab(match->opserv_level);
+            if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_ID)
+                discrim->output_table->contents[discrim->output_table_pos][i++] = strtab(match->id);
             if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_FAKEHOST)
                 discrim->output_table->contents[discrim->output_table_pos][i++] = (match->fakehost ? match->fakehost : "*");
             if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_WEBSITE)
                 discrim->output_table->contents[discrim->output_table_pos][i++] = (match->website ? match->website : "*");
-            if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_DEVNULL)
-                discrim->output_table->contents[discrim->output_table_pos][i++] = (match->devnull ? match->devnull : "*");
-            
+            if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_DEVNULL) {
+                if(discrim->devnull_name) 
+                    discrim->output_table->contents[discrim->output_table_pos][i++] = discrim->devnull_name;
+                else {
+                    struct devnull_class *devnull = devnull_find_id(match->devnull_id);
+                    discrim->output_table->contents[discrim->output_table_pos][i++] = (devnull ? devnull->name : "*");
+                }
+            }
         }
     } else
         send_message(source, nickserv, "NSMSG_SEARCH_MATCH", match->handle);
@@ -4168,6 +4207,8 @@ static NICKSERV_FUNC(cmd_search)
             discrim->output_table->contents[0][ii++] = "Seen";
         if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_ACCESS)
             discrim->output_table->contents[0][ii++] = "Access";
+        if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_ID)
+            discrim->output_table->contents[0][ii++] = "ID";
         if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_FAKEHOST)
             discrim->output_table->contents[0][ii++] = "Fakehost";
         if(discrim->show_fields & NICKSERV_DISCRIM_FIELDS_WEBSITE)
@@ -4330,8 +4371,7 @@ nickserv_db_read_handle(const char *handle, dict_t obj)
     if (str)
         hi->website = strdup(str);
     str = database_get_data(obj, KEY_DEVNULL, RECDB_QSTRING);
-    if (str)
-        hi->devnull = strdup(str);
+    hi->devnull_id = str ? strtoul(str, NULL, 0) : 0;
     str = database_get_data(obj, KEY_REGISTER_ON, RECDB_QSTRING);
     hi->registered = str ? strtoul(str, NULL, 0) : now;
     str = database_get_data(obj, KEY_LAST_SEEN, RECDB_QSTRING);