]> jfr.im git - solanum.git/blobdiff - extensions/filter.c
Merge pull request #321 from edk0/hook-priorities
[solanum.git] / extensions / filter.c
index 1cb278294748aabf9399ebacc2940f957cc29e27..07a31e31704db68f97d3ce76b3c50b285a73d767 100644 (file)
@@ -51,6 +51,8 @@
 
 #define FILTER_EXIT_MSG "Connection closed"
 
+static const char filter_desc[] = "Filter messages using a precompiled Hyperscan database";
+
 static void filter_msg_user(void *data);
 static void filter_msg_channel(void *data);
 static void on_client_exit(void *data);
@@ -68,6 +70,7 @@ static int filter_enable = 1;
 static const char *cmdname[MESSAGE_TYPE_COUNT] = {
        [MESSAGE_TYPE_PRIVMSG] = "PRIVMSG",
        [MESSAGE_TYPE_NOTICE] = "NOTICE",
+       [MESSAGE_TYPE_PART] = "PART",
 };
 
 enum filter_state {
@@ -98,12 +101,13 @@ struct Message setfilter_msgtab = {
        {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, {me_setfilter, 2}, {mo_setfilter, 2}}
 };
 
-static void
+static int
 modinit(void)
 {
        filter_umode = user_modes['u'] = find_umode_slot();
        construct_umodebuf();
        filter_chmode = cflag_add('u', chm_simple);
+       return 0;
 }
 
 static void
@@ -126,7 +130,7 @@ moddeinit(void)
 
 mapi_clist_av1 filter_clist[] = { &setfilter_msgtab, NULL };
 
-DECLARE_MODULE_AV1(filter, modinit, moddeinit, filter_clist, NULL, filter_hfnlist, "0.3");
+DECLARE_MODULE_AV2(filter, modinit, moddeinit, filter_clist, NULL, filter_hfnlist, NULL, "0.4", filter_desc);
 
 static int
 setfilter(const char *check, const char *data, const char **error)
@@ -162,6 +166,28 @@ setfilter(const char *check, const char *data, const char **error)
                return 0;
        }
 
+       if (!strcasecmp(data, "drop")) {
+               if (!filter_db) {
+                       if (error) *error = "no database to drop";
+                       return -1;
+               }
+               hs_free_database(filter_db);
+               filter_db = 0;
+               return 0;
+       }
+
+       if (!strcasecmp(data, "abort")) {
+               if (state != FILTER_FILLING) {
+                       if (error) *error = "not filling";
+                       return -1;
+               }
+               state = filter_db ? FILTER_LOADED : FILTER_EMPTY;
+               rb_free(filter_data);
+               filter_data = 0;
+               filter_data_len = 0;
+               return 0;
+       }
+
        if (strcmp(check, check_str) != 0) {
                if (error) *error = "check strings don't match";
                return -1;
@@ -181,6 +207,7 @@ setfilter(const char *check, const char *data, const char **error)
                r = hs_alloc_scratch(db, &filter_scratch);
                if (r != HS_SUCCESS) {
                        if (error) *error = "couldn't allocate scratch";
+                       hs_free_database(db);
                        return -1;
                }
                if (filter_db) {
@@ -196,9 +223,16 @@ setfilter(const char *check, const char *data, const char **error)
                return 0;
        }
 
+       if (*data != '+') {
+               if (error) *error = "unknown command or data doesn't start with +";
+               return -1;
+       }
+
+       data += 1;
+
        if (state == FILTER_FILLING) {
                int dl;
-               unsigned char *d = rb_base64_decode(data, strlen(data), &dl);
+               unsigned char *d = rb_base64_decode((unsigned char *)data, strlen(data), &dl);
                if (!d) {
                        if (error) *error = "invalid data";
                        return -1;
@@ -310,6 +344,8 @@ unsigned match_message(const char *prefix,
                return 0;
        if (!filter_db)
                return 0;
+       if (!command)
+               return 0;
        snprintf(check_buffer, sizeof check_buffer, "%s:%s!%s@%s#%c %s %s :%s",
                 prefix,
 #if FILTER_NICK
@@ -328,8 +364,7 @@ unsigned match_message(const char *prefix,
                 "*",
 #endif
                 source->user && source->user->suser[0] != '\0' ? '1' : '0',
-                command, target,
-                msg);
+                command, target, msg);
        hs_error_t r = hs_scan(filter_db, check_buffer, strlen(check_buffer), 0, filter_scratch, match_callback, &state);
        if (r != HS_SUCCESS && r != HS_SCAN_TERMINATED)
                return 0;
@@ -431,4 +466,3 @@ on_client_exit(void *data_)
                state = filter_db ? FILTER_LOADED : FILTER_EMPTY;
        }
 }
-