]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
Add user support to sqlite3.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 23 Jul 2015 18:04:02 +0000 (19:04 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 23 Jul 2015 18:04:02 +0000 (19:04 +0100)
src/libstat/backends/sqlite3_backend.c
src/libutil/sqlite_utils.c

index 2d8ae192114a0407ecd97ea2eef2284902fbf640..0852bcf5e0ce4cb20c25a645c48e5a9703540049 100644 (file)
@@ -69,6 +69,7 @@ static const char *create_tables_sql =
                "user INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,"
                "language INTEGER NOT NULL REFERENCES languages(id) ON DELETE CASCADE,"
                "value INTEGER,"
+               "modified INTEGER,"
                "CONSTRAINT tid UNIQUE (token, user, language) ON CONFLICT REPLACE"
                ");"
                "CREATE UNIQUE INDEX IF NOT EXISTS un ON users(name);"
@@ -89,6 +90,10 @@ enum rspamd_stat_sqlite3_stmt_idx {
        RSPAMD_STAT_BACKEND_INC_LEARNS,
        RSPAMD_STAT_BACKEND_DEC_LEARNS,
        RSPAMD_STAT_BACKEND_GET_LEARNS,
+       RSPAMD_STAT_BACKEND_GET_LANGUAGE,
+       RSPAMD_STAT_BACKEND_GET_USER,
+       RSPAMD_STAT_BACKEND_INSERT_LANGUAGE,
+       RSPAMD_STAT_BACKEND_INSERT_USER,
        RSPAMD_STAT_BACKEND_MAX
 };
 
@@ -140,8 +145,8 @@ static struct rspamd_sqlite3_prstmt prepared_stmts[RSPAMD_STAT_BACKEND_MAX] =
        },
        {
                .idx = RSPAMD_STAT_BACKEND_SET_TOKEN,
-               .sql = "INSERT OR REPLACE INTO tokens (token, user, language, value) "
-                               "VALUES (?1, ?2, ?3, ?4);",
+               .sql = "INSERT OR REPLACE INTO tokens (token, user, language, value, modified) "
+                               "VALUES (?1, ?2, ?3, ?4, strftime('%s','now'));",
                .stmt = NULL,
                .args = "IIII",
                .result = SQLITE_DONE,
@@ -172,6 +177,38 @@ static struct rspamd_sqlite3_prstmt prepared_stmts[RSPAMD_STAT_BACKEND_MAX] =
                .args = "",
                .result = SQLITE_ROW,
                .ret = "I"
+       },
+       {
+               .idx = RSPAMD_STAT_BACKEND_GET_LANGUAGE,
+               .sql = "SELECT id FROM languages WHERE name=?1;",
+               .stmt = NULL,
+               .args = "T",
+               .result = SQLITE_ROW,
+               .ret = "I"
+       },
+       {
+               .idx = RSPAMD_STAT_BACKEND_GET_USER,
+               .sql = "SELECT id FROM users WHERE name=?1;",
+               .stmt = NULL,
+               .args = "T",
+               .result = SQLITE_ROW,
+               .ret = "I"
+       },
+       {
+               .idx = RSPAMD_STAT_BACKEND_INSERT_USER,
+               .sql = "INSERT INTO users (name, learns) VALUES (?1, 0);",
+               .stmt = NULL,
+               .args = "T",
+               .result = SQLITE_ROW,
+               .ret = "L"
+       },
+       {
+               .idx = RSPAMD_STAT_BACKEND_INSERT_LANGUAGE,
+               .sql = "INSERT INTO languages (name, learns) VALUES (?1, 0);",
+               .stmt = NULL,
+               .args = "T",
+               .result = SQLITE_ROW,
+               .ret = "L"
        }
 };
 
@@ -181,6 +218,56 @@ rspamd_sqlite3_backend_quark (void)
        return g_quark_from_static_string ("sqlite3-stat-backend");
 }
 
+static gint64
+rspamd_sqlite3_get_user (struct rspamd_stat_sqlite3_db *db,
+               struct rspamd_task *task, gboolean learn)
+{
+       gint64 id = 0; /* Default user is 0 */
+       gint rc;
+       const gchar *user = NULL;
+       const InternetAddress *ia;
+
+       if (task->deliver_to != NULL) {
+               /* Use deliver-to value if presented */
+               user = task->deliver_to;
+       }
+       if (task->user != NULL) {
+               /* Use user value if presented */
+               user = task->user;
+       }
+       else if (task->rcpt_envelope != NULL) {
+               /* Check envelope recipients */
+               if (internet_address_list_length (task->rcpt_envelope) == 1) {
+                       /* XXX: we support now merely single recipient statistics */
+                       ia = internet_address_list_get_address (task->rcpt_envelope, 0);
+
+                       if (ia != NULL) {
+                               user = internet_address_mailbox_get_addr (INTERNET_ADDRESS_MAILBOX (ia));
+                       }
+               }
+       }
+
+       /* XXX: We ignore now mime recipients as they could be easily forged */
+       if (user != NULL) {
+               rc = rspamd_sqlite3_run_prstmt (db->sqlite, db->prstmt,
+                               RSPAMD_STAT_BACKEND_GET_USER, user, &id);
+
+               if (rc != SQLITE_OK && learn) {
+                       /* We need to insert a new user */
+                       if (!db->in_transaction) {
+                               rspamd_sqlite3_run_prstmt (db->sqlite, db->prstmt,
+                                               RSPAMD_STAT_BACKEND_TRANSACTION_START_IM);
+                               db->in_transaction = TRUE;
+                       }
+
+                       rc =  rspamd_sqlite3_run_prstmt (db->sqlite, db->prstmt,
+                                       RSPAMD_STAT_BACKEND_INSERT_USER, user, &id);
+               }
+       }
+
+       return id;
+}
+
 static struct rspamd_stat_sqlite3_db *
 rspamd_sqlite3_opendb (const gchar *path, const ucl_object_t *opts,
                gboolean create, GError **err)
@@ -319,6 +406,7 @@ rspamd_sqlite3_runtime (struct rspamd_task *task,
                rt->ctx = ctx;
                rt->db = bk;
                rt->task = task;
+               rt->user_id = -1;
        }
 
        return rt;
@@ -353,6 +441,10 @@ rspamd_sqlite3_process_token (struct rspamd_task *task, struct token_node_s *tok
                bk->in_transaction = TRUE;
        }
 
+       if (rt->user_id == -1) {
+               rt->user_id = rspamd_sqlite3_get_user (bk, task, FALSE);
+       }
+
        memcpy (&idx, tok->data, sizeof (idx));
 
        /* TODO: language and user support */
@@ -422,6 +514,10 @@ rspamd_sqlite3_learn_token (struct rspamd_task *task, struct token_node_s *tok,
                bk->in_transaction = TRUE;
        }
 
+       if (rt->user_id == -1) {
+               rt->user_id = rspamd_sqlite3_get_user (bk, task, TRUE);
+       }
+
        iv = res->value;
        memcpy (&idx, tok->data, sizeof (idx));
 
index 61ba49cafd1d57921bec6aef5d41f1560902b390..dddb08703bb6d483bf623e6284297ca190f61623 100644 (file)
@@ -153,6 +153,9 @@ rspamd_sqlite3_run_prstmt (sqlite3 *db, GArray *stmts,
                        case 'S':
                                *va_arg (ap, int*) = sqlite3_column_int (stmt, i);
                                break;
+                       case 'L':
+                               *va_arg (ap, gint64*) = sqlite3_last_insert_rowid (db);
+                               break;
                        }
                }