added code for saxdb_read
[srvx.git] / src / spamserv.c
index 27cabfb9605c32d34144e889f0e4ef2bb9741ee3..9987398772bc4c98737380d9e018fa9b569f37c0 100644 (file)
@@ -152,6 +152,7 @@ static const struct message_entry msgtab[] = {
 #define SSMSG_WARNING_2               "You are violating the network rules"
 #define SSMSG_WARNING_RULES           "%s is against the network rules. Read the network rules at %s"
 #define SSMSG_WARNING_RULES_2         "You are violating the network rules. Read the network rules at %s"
+#define SSMSG_BADWORD_DETECTED           "Your message contained a forbidden word."
 
 static struct
 {
@@ -1877,6 +1878,45 @@ spamserv_punish(struct chanNode *channel, struct userNode *user, time_t expires,
        KickChannelUser(user, channel, spamserv, reason);       
 }
 
+static void
+spamserv_detected_badword(struct userNode *user, struct chanNode *chan, struct badword *badword)
+{
+    char *hostmask;
+    char *reason = SSMSG_BADWORD_DETECTED;
+    char mask[IRC_NTOP_MAX_SIZE+3] = { '*', '@', '\0' };
+    switch(badword->action) {
+        case BADACTION_BAN:
+            hostmask = generate_hostmask(user, GENMASK_STRICT_HOST | GENMASK_ANY_IDENT);
+            sanitize_ircmask(hostmask);
+            if(chan->channel_info) {
+                //registered channel
+                add_channel_ban(chan->channel_info, hostmask, spamserv->nick, now, now, now + spamserv_conf.long_ban_duration, reason);
+            }
+            struct mod_chanmode change;
+            mod_chanmode_init(&change);
+            change.argc = 1;
+            change.args[0].mode = MODE_BAN;
+            change.args[0].u.hostmask = hostmask;
+            mod_chanmode_announce(spamserv, chan, &change);
+            free(hostmask);
+
+        case BADACTION_KICK:
+            if(GetUserMode(chan, user))
+                KickChannelUser(user, chan, spamserv, reason);
+            break;
+        case BADACTION_KILL:
+            DelUser(user, spamserv, 1, reason);
+            break;
+        case BADACTION_GLINE:
+            irc_ntop(mask + 2, sizeof(mask) - 2, &user->ip);
+            gline_add(spamserv->nick, mask, spamserv_conf.gline_duration, reason, now, now, 0, 1);
+            break;
+        default:
+            //error?
+            break;
+        }
+}
+
 void
 spamserv_channel_message(struct chanNode *channel, struct userNode *user, char *text)
 {
@@ -2035,6 +2075,15 @@ spamserv_channel_message(struct chanNode *channel, struct userNode *user, char *
                }
        }
 
+       dict_iterator_t it;
+
+       for (it = dict_first(cInfo->badwords); it; it = iter_next(it)) {
+               struct badword *badword = iter_data(it);
+               if(match_ircglob(text, badword->badword_mask)) {
+                       spamserv_detected_badword(user, channel, badword);
+               }
+       }
+
        if(CHECK_ADV(cInfo) && check_advertising(cInfo, text))
        {
                if(CHECK_ADV_WARNED(uInfo))
@@ -2121,11 +2170,31 @@ spamserv_channel_message(struct chanNode *channel, struct userNode *user, char *
        }
 }
 
+static int
+spamserv_saxdb_read_shitlist(const char *name, void *data, void *extra)
+{
+       struct record_data *rd = data;
+       struct chanInfo *chan = extra;
+       char *badword;
+       char *triggered, *action;
+
+       if (rd->type == RECDB_OBJECT) {
+               dict_t obj = GET_RECORD_OBJECT(rd);
+               /* new style structure */
+               badword = database_get_data(obj, KEY_BADWORD_MASK, RECDB_QSTRING);
+               triggered = database_get_data(obj, KEY_BADWORD_TRIGGERED, RECDB_QSTRING);
+               action = database_get_data(obj, KEY_BADWORD_ACTION, RECDB_QSTRING);
+
+               add_badword(chan, badword, strtoul(triggered, NULL, 0), strtoul(action, NULL, 0), name);
+       }
+       return 0;
+}
+
 static int
 spamserv_saxdb_read(struct dict *database)
 {
        dict_iterator_t it, itbad;
-       struct dict *object;
+       struct dict *object, *badwords;
        struct record_data *hir, hirbad;
        struct chanNode *channel;
        struct chanInfo *cInfo;
@@ -2174,7 +2243,11 @@ spamserv_saxdb_read(struct dict *database)
                                        cInfo->suspend_expiry = expiry;                 
                 cInfo->exceptlevel=exceptlevel;
                 cInfo->badwords = dict_new();
-
+                str = database_get_data(hir->d.object, KEY_LASTBADWORDID, RECDB_QSTRING);
+                badwordid = str ? atoi(str) : 0;
+                cInfo->last_badword_id = badwordid;
+                if ((badwords = database_get_data(hir->d.object, KEY_BADWORDS, RECDB_OBJECT)))
+                       dict_foreach(object, spamserv_saxdb_read_shitlist, cInfo);
                        }
                }
                else
@@ -2207,8 +2280,8 @@ spamserv_saxdb_write(struct saxdb_context *ctx)
                if(cInfo->suspend_expiry)
                        saxdb_write_int(ctx, KEY_EXPIRY, cInfo->suspend_expiry);
 
-               saxdb_start_record(ctx, KEY_BADWORDS, 1);
                saxdb_write_int(ctx, KEY_LASTBADWORDID, cInfo->last_badword_id);
+               saxdb_start_record(ctx, KEY_BADWORDS, 1);
                dict_iterator_t itbad;
                for (itbad = dict_first(cInfo->badwords); itbad; itbad = iter_next(itbad)) {
                        struct badword *badword = iter_data(itbad);