* initial dspam integration module
authorWilfried Göesgens <willi@citadel.org>
Tue, 25 Dec 2007 19:18:30 +0000 (19:18 +0000)
committerWilfried Göesgens <willi@citadel.org>
Tue, 25 Dec 2007 19:18:30 +0000 (19:18 +0000)
citadel/citadel_dirs.c
citadel/citadel_dirs.h
citadel/configure.ac
citadel/modules/dspam/serv_dspam.c [new file with mode: 0644]
citadel/msgbase.c

index 1e35087503134bf8111df3d0c5c244af55cbeffd..54da76ff3425087b9b51f332ae328900fcec3ab5 100644 (file)
@@ -30,6 +30,7 @@ char ctdl_home_directory[PATH_MAX] = "";
 char ctdl_bio_dir[PATH_MAX]="bio";
 char ctdl_bb_dir[PATH_MAX]="bitbucket";
 char ctdl_data_dir[PATH_MAX]="data";
+char ctdl_dspam_dir[PATH_MAX]="dspam";
 char ctdl_file_dir[PATH_MAX]="files";
 char ctdl_hlp_dir[PATH_MAX]="help";
 char ctdl_image_dir[PATH_MAX]="images";
@@ -147,6 +148,7 @@ void calc_dirs_n_files(int relh, int home, const char *relhome, const char  *ctd
        COMPUTE_DIRECTORY(ctdl_bio_dir);
        COMPUTE_DIRECTORY(ctdl_bb_dir);
        COMPUTE_DIRECTORY(ctdl_data_dir);
+       COMPUTE_DIRECTORY(ctdl_dspam_dir);
        COMPUTE_DIRECTORY(ctdl_file_dir);
        COMPUTE_DIRECTORY(ctdl_image_dir);
        COMPUTE_DIRECTORY(ctdl_info_dir);
@@ -247,6 +249,7 @@ void calc_dirs_n_files(int relh, int home, const char *relhome, const char  *ctd
        DBG_PRINT(ctdl_bio_dir);
        DBG_PRINT(ctdl_bb_dir);
        DBG_PRINT(ctdl_data_dir);
+       DBG_PRINT(ctdl_dspam_dir);
        DBG_PRINT(ctdl_file_dir);
        DBG_PRINT(ctdl_hlp_dir);
        DBG_PRINT(ctdl_image_dir);
index f7ba1f3db3b739de4d78534392d7469570e05474..8a9e280f9062cb5eadcb50af29f0dbe4557c8fcb 100644 (file)
@@ -12,6 +12,7 @@ extern int home_specified;
 extern char ctdl_bio_dir[PATH_MAX];
 extern char ctdl_bb_dir[PATH_MAX];
 extern char ctdl_data_dir[PATH_MAX];
+extern char ctdl_dspam_dir[PATH_MAX];
 extern char ctdl_file_dir[PATH_MAX];
 extern char ctdl_hlp_dir[PATH_MAX];
 extern char ctdl_image_dir[PATH_MAX];
index 566eb7df4d706e82f1903c411646815612b46361..cf892f6f0549bc9866db66a4a9e4e8c2b0030938 100644 (file)
@@ -153,6 +153,7 @@ AC_ARG_WITH(with_zlib, [  --with-zlib             use zlib compression if presen
 AC_ARG_WITH(with_ldap, [  --with-ldap             use OpenLDAP client library])
 AC_ARG_WITH(with_libical, [  --with-libical          use libical calendaring library])
 AC_ARG_WITH(with_libsieve, [  --with-libsieve         use libsieve mail sorting library])
+AC_ARG_WITH(with_libdspam, [  --with-libdspam         use libdspam mail spam scanning library])
 AC_ARG_WITH(with_expat, [  --with-expat            use Expat XML parser])
 
 if test "x$with_db" != xno -a "x$with_db" != xyes -a "$with_db"; then
@@ -605,6 +606,20 @@ if test "x$ok_libsieve" = xyes ; then
 fi
 
 
+dnl Checks for the libdspam mail spam scanning library.
+if test "x$with_libdspam" != xno ; then
+       AC_CHECK_HEADERS(dspam/libdspam.h,
+               [AC_CHECK_LIB(dspam, dspam_init,
+                       [ok_libdspam=yes],,
+       )])
+fi
+
+if test "x$ok_libdspam" = xyes ; then
+       SERVER_LIBS="-ldspam $SERVER_LIBS"
+       AC_DEFINE(HAVE_LIBDSPAM, [], [define this if you have the libdspam mail spam scanning library available])
+fi
+
+
 
 
 dnl Checks for the Expat XML parser.
@@ -876,6 +891,7 @@ echo 'zlib compression:                ' $ok_zlib
 echo 'Calendar support:                ' $ok_libical
 echo 'LDAP support:                    ' $ok_ldap
 echo 'Sieve mailbox filtering support: ' $ok_libsieve
+echo 'DSpam Scanning support:          ' $ok_libdspam
 echo 'Expat XML parser present:        ' $ok_expat
 echo 
 echo 'Note: if you are not using Linux, make sure you are using GNU make'
diff --git a/citadel/modules/dspam/serv_dspam.c b/citadel/modules/dspam/serv_dspam.c
new file mode 100644 (file)
index 0000000..90de719
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * $Id: serv_dspam.c 5876 2007-12-10 23:22:03Z dothebart $
+ *
+ * This module glues libDSpam to the Citadel server in order to implement
+ * DSPAM Spamchecking 
+ *
+ * This code is released under the terms of the GNU General Public License. 
+ */
+
+#include "sysdep.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+#include <sys/wait.h>
+#include <string.h>
+#include <limits.h>
+#include <libcitadel.h>
+#include "citadel.h"
+#include "server.h"
+#include "citserver.h"
+#include "support.h"
+#include "config.h"
+#include "room_ops.h"
+#include "policy.h"
+#include "database.h"
+#include "msgbase.h"
+#include "internet_addressing.h"
+
+
+#include "ctdl_module.h"
+
+
+#ifdef HAVE_LIBDSPAM
+
+#undef HAVE_CONFIG_H
+#include <dspam/libdspam.h>
+#define HAVE_CONFIG_H
+/*
+ * Citadel protocol to manage sieve scripts.
+ * This is basically a simplified (read: doesn't resemble IMAP) version
+ * of the 'managesieve' protocol.
+ */
+void cmd_tspam(char *argbuf) {
+       
+
+       /* tag mails as spam or Ham */
+       /* probably do: dspam_init(ctdl_dspam_dir); dspam_process dspam_addattribute; dspam_destroy*/
+       // extract DSS_ERROR or DSS_CORPUS from the commandline. error->ham; corpus -> spam?
+}
+
+
+
+void ctdl_dspam_init(void) {
+
+       libdspam_init("bdb");/* <which database backend do we prefer? */
+
+}
+
+void dspam_do_msg(long msgnum, void *userdata) 
+{
+       DSPAM_CTX *CTX;                 /* DSPAM Context */
+       struct CtdlMessage *msg;
+       struct _ds_spam_signature SIG;        /* signature */
+
+       CTX = *(DSPAM_CTX**) userdata;
+       msg = CtdlFetchMessage(msgnum, 0);
+       if (msg == NULL) return;
+       CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_ALL, 0, 1);
+
+       /* Call DSPAM's processor with the message text */
+       if (dspam_process (CTX, msg->cm_fields['A']) != 0)
+       {
+               lprintf(CTDL_CRIT, "ERROR: dspam_process failed");
+               return;
+       }
+       if (CTX->signature == NULL)
+       {
+               lprintf(CTDL_CRIT,"No signature provided\n");
+       }
+       else
+       {
+/* Copy to a safe place */
+
+               SIG.data = malloc (CTX->signature->length);
+               if (SIG.data != NULL)
+                       memcpy (SIG.data, CTX->signature->data, CTX->signature->length);
+       }
+       SIG.length = CTX->signature->length;
+       /* Print processing results */
+       printf ("Probability: %2.4f Confidence: %2.4f, Result: %s\n",
+               CTX->probability,
+               CTX->confidence,
+               (CTX->result == DSR_ISSPAM) ? "Spam" : "Innocent");
+
+       //// todo: put signature into the citadel message
+       //// todo: save message; destroy message.
+}
+
+int serv_dspam_room(struct ctdlroom *room)
+{
+       DSPAM_CTX *CTX;                 /* DSPAM Context */
+
+       /* scan for spam; do */
+       /* probably do: dspam_init; dspam_process dspam_addattribute; dspam_destroy*/
+//DSS_NONE
+//#define      DSR_ISSPAM              0x01
+//#define DSR_ISINNOCENT               0x02
+// dspam_init (cc->username, NULL, ctdl_dspam_home, DSM_PROCESS,
+       //                  DSF_SIGNATURE | DSF_NOISE);
+       /// todo: if roomname = spam / ham -> learn!
+       if (room->QRflags & QR_PRIVATE) /* Are we sending to a private mailbox? */
+       {
+               char User[64];
+               // maybe we should better get our realname here?
+               snprintf(User, 64, "%ld", room->QRroomaide);
+
+               CTX = dspam_init(User, 
+                                NULL,
+                                ctdl_dspam_dir, 
+                                DSM_PROCESS, 
+                                DSF_SIGNATURE | DSF_NOISE);
+       }
+       /// else -> todo: global user for public rooms etc.
+       if (CTX == NULL)
+       {
+               lprintf(CTDL_CRIT, "ERROR: dspam_init failed!\n");
+               return ERROR + INTERNAL_ERROR;
+       }
+       /* Use graham and robinson algorithms, graham's p-values */
+       CTX->algorithms = DSA_GRAHAM | DSA_BURTON | DSP_GRAHAM;
+
+       /* Use CHAIN tokenizer */
+       CTX->tokenizer = DSZ_CHAIN;
+
+       CtdlForEachMessage(MSGS_GT, NULL, NULL, NULL, NULL,
+                          dspam_do_msg,
+                          (void *) &CTX);
+
+       return 0;
+}
+
+void serv_dspam_shutdown (void)
+{
+       libdspam_shutdown ();
+}
+#endif /* HAVE_LIBDSPAM */
+
+CTDL_MODULE_INIT(dspam)
+{
+       if (!threading)
+       {
+#ifdef HAVE_LIBDSPAM
+
+               ctdl_dspam_init();
+               CtdlRegisterCleanupHook(serv_dspam_shutdown);
+               CtdlRegisterProtoHook(cmd_tspam, "SPAM", "Tag Message as Spam/Ham to learn DSPAM");
+
+               CtdlRegisterRoomHook(serv_dspam_room);
+
+               ///CtdlRegisterSessionHook(perform_dspam_processing, EVT_HOUSE);
+
+#else  /* HAVE_LIBDSPAM */
+
+               lprintf(CTDL_INFO, "This server is missing libdspam Spam filtering will be disabled.\n");
+
+#endif /* HAVE_LIBDSPAM */
+       }
+       
+        /* return our Subversion id for the Log */
+       return "$Id: serv_dspam.c 5876 2007-12-10 23:22:03Z dothebart $";
+}
+
index 6fc437faf5ace9b3ad333b3fc70b73d0b5ef18c6..15fbd3993b02c2f031e069207882d6a096147a6c 100644 (file)
@@ -1708,7 +1708,7 @@ int CtdlOutputPreLoadedMsg(
                }
 
                /* Construct a fun message id */
-               cprintf("Message-ID: <%s", mid);
+               cprintf("Message-ID: <%s", mid);/// todo: this possibly breaks threadding mails.
                if (strchr(mid, '@')==NULL) {
                        cprintf("@%s", snode);
                }