Did away with lprintf all together now its called CtdlLogPrintf()
[citadel.git] / citadel / modules / dspam / serv_dspam.c
1 /*
2  * $Id: serv_dspam.c 5876 2007-12-10 23:22:03Z dothebart $
3  *
4  * This module glues libDSpam to the Citadel server in order to implement
5  * DSPAM Spamchecking 
6  *
7  * This code is released under the terms of the GNU General Public License. 
8  */
9
10 #include "sysdep.h"
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <stdio.h>
14 #include <fcntl.h>
15 #include <ctype.h>
16 #include <pwd.h>
17 #include <errno.h>
18 #include <sys/types.h>
19
20 #if TIME_WITH_SYS_TIME
21 # include <sys/time.h>
22 # include <time.h>
23 #else
24 # if HAVE_SYS_TIME_H
25 #  include <sys/time.h>
26 # else
27 #  include <time.h>
28 # endif
29 #endif
30
31 #include <sys/wait.h>
32 #include <string.h>
33 #include <limits.h>
34 #include <libcitadel.h>
35 #include "citadel.h"
36 #include "server.h"
37 #include "citserver.h"
38 #include "support.h"
39 #include "config.h"
40 #include "room_ops.h"
41 #include "policy.h"
42 #include "database.h"
43 #include "msgbase.h"
44 #include "internet_addressing.h"
45
46
47 #include "ctdl_module.h"
48
49
50 #ifdef HAVE_LIBDSPAM
51
52 #undef HAVE_CONFIG_H
53 #include <dspam/libdspam.h>
54 #define HAVE_CONFIG_H
55
56 typedef struct stringlist stringlist;
57
58 struct stringlist {
59         char *Str;
60         long len;
61         stringlist *Next;
62 };
63         
64
65 /*
66  * Citadel protocol to manage sieve scripts.
67  * This is basically a simplified (read: doesn't resemble IMAP) version
68  * of the 'managesieve' protocol.
69  */
70 void cmd_tspam(char *argbuf) {
71         char buf[SIZ];
72         long len;
73         long count;
74         stringlist *Messages; 
75         stringlist *NextMsg; 
76
77         Messages = NULL;
78         NextMsg = NULL;
79         count = 0;
80         if (CtdlAccessCheck(ac_room_aide)) return;
81         if (atoi(argbuf) == 0) {
82                 cprintf("%d Ok.\n", CIT_OK);
83                 return;
84         }
85         cprintf("%d Send info...\n", SEND_LISTING);
86
87         do {
88                 len = client_getln(buf, sizeof buf);
89                 if (strcmp(buf, "000")) {
90                         if (Messages == NULL) {
91                                 Messages = malloc (sizeof (stringlist));
92                                 NextMsg = Messages;
93                         }
94                         else {
95                                 Messages->Next = malloc (sizeof (stringlist));
96                                 NextMsg = NextMsg->Next;
97                         }
98                         NextMsg->Next = NULL;
99                         NextMsg->Str = malloc (len+1);
100                         NextMsg->len = len;
101                         memcpy (NextMsg->Str, buf, len + 1);/// maybe split spam /ham per line?
102                         count++;
103                 }
104         } while (strcmp(buf, "000"));
105 /// is there a way to filter foreachmessage by a list?
106         /* tag mails as spam or Ham */
107         /* probably do: dspam_init(ctdl_dspam_dir); dspam_process dspam_addattribute; dspam_destroy*/
108         // extract DSS_ERROR or DSS_CORPUS from the commandline. error->ham; corpus -> spam?
109         /// todo: send answer listing...
110 }
111
112
113
114 void ctdl_dspam_init(void) {
115
116 ///     libdspam_init("bdb");/* <which database backend do we prefer? */
117
118 }
119
120 void dspam_do_msg(long msgnum, void *userdata) 
121 {
122         char *msgtext;
123         DSPAM_CTX *CTX;                 /* DSPAM Context */
124         struct CtdlMessage *msg;
125         struct _ds_spam_signature SIG;        /* signature */
126
127         CTX = *(DSPAM_CTX**) userdata;
128         msg = CtdlFetchMessage(msgnum, 0);
129         if (msg == NULL) return;
130
131
132         /* Message */
133         CC->redirect_buffer = malloc(SIZ);
134         CC->redirect_len = 0;
135         CC->redirect_alloc = SIZ;
136         CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_ALL, 0, 1);
137         msgtext = CC->redirect_buffer;
138 // don't need?  msglen = CC->redirect_len;
139         CC->redirect_buffer = NULL;
140         CC->redirect_len = 0;
141         CC->redirect_alloc = 0;
142
143         /* Call DSPAM's processor with the message text */
144         if (dspam_process (CTX, msgtext) != 0)
145         {
146                 free(msgtext);
147                 CtdlLogPrintf(CTDL_CRIT, "ERROR: dspam_process failed");
148                 return;
149         }
150         if (CTX->signature == NULL)
151         {
152                 CtdlLogPrintf(CTDL_CRIT,"No signature provided\n");
153         }
154         else
155         {
156 /* Copy to a safe place */
157
158                 SIG.data = malloc (CTX->signature->length);
159                 if (SIG.data != NULL)
160                         memcpy (SIG.data, CTX->signature->data, CTX->signature->length);
161         }
162         free(msgtext);
163
164         SIG.length = CTX->signature->length;
165         /* Print processing results */
166         CtdlLogPrintf (CTDL_DEBUG, "Probability: %2.4f Confidence: %2.4f, Result: %s\n",
167                 CTX->probability,
168                 CTX->confidence,
169                 (CTX->result == DSR_ISSPAM) ? "Spam" : "Innocent");
170
171         //// todo: put signature into the citadel message
172         //// todo: save message; destroy message.
173 }
174
175 int serv_dspam_room(struct ctdlroom *room)
176 {
177         DSPAM_CTX *CTX;                 /* DSPAM Context */
178
179         /* scan for spam; do */
180         /* probably do: dspam_init; dspam_process dspam_addattribute; dspam_destroy*/
181 //DSS_NONE
182 //#define       DSR_ISSPAM              0x01
183 //#define DSR_ISINNOCENT                0x02
184 // dspam_init (cc->username, NULL, ctdl_dspam_home, DSM_PROCESS,
185         //                  DSF_SIGNATURE | DSF_NOISE);
186         /// todo: if roomname = spam / ham -> learn!
187         if (room->QRflags & QR_PRIVATE) /* Are we sending to a private mailbox? */
188         {
189                 char User[64];
190                 // maybe we should better get our realname here?
191                 snprintf(User, 64, "%ld", room->QRroomaide);
192
193                 CTX = dspam_init(User, 
194                                  NULL,
195                                  ctdl_dspam_dir, 
196                                  DSM_PROCESS, 
197                                  DSF_SIGNATURE | DSF_NOISE);
198         }
199         /// else -> todo: global user for public rooms etc.
200         if (CTX == NULL)
201         {
202                 CtdlLogPrintf(CTDL_CRIT, "ERROR: dspam_init failed!\n");
203                 return ERROR + INTERNAL_ERROR;
204         }
205         /* Use graham and robinson algorithms, graham's p-values */
206         CTX->algorithms = DSA_GRAHAM | DSA_BURTON | DSP_GRAHAM;
207
208         /* Use CHAIN tokenizer */
209         CTX->tokenizer = DSZ_CHAIN;
210
211         CtdlForEachMessage(MSGS_GT, 1, NULL, NULL, NULL,
212                            dspam_do_msg,
213                            (void *) &CTX);
214
215         return 0;
216 }
217
218 void serv_dspam_shutdown (void)
219 {
220         libdspam_shutdown ();
221 }
222 #endif  /* HAVE_LIBDSPAM */
223
224 CTDL_MODULE_INIT(dspam)
225 {
226         return "$Id: serv_dspam.c 5876 2007-12-10 23:22:03Z dothebart $" "disabled.";
227         if (!threading)
228         {
229 #ifdef HAVE_LIBDSPAM
230
231                 ctdl_dspam_init();
232                 CtdlRegisterCleanupHook(serv_dspam_shutdown);
233                 CtdlRegisterProtoHook(cmd_tspam, "SPAM", "Tag Message as Spam/Ham to learn DSPAM");
234
235                 CtdlRegisterRoomHook(serv_dspam_room);
236
237                 ///CtdlRegisterSessionHook(perform_dspam_processing, EVT_HOUSE);
238
239 #else   /* HAVE_LIBDSPAM */
240
241                 CtdlLogPrintf(CTDL_INFO, "This server is missing libdspam Spam filtering will be disabled.\n");
242
243 #endif  /* HAVE_LIBDSPAM */
244         }
245         
246         /* return our Subversion id for the Log */
247         return "$Id: serv_dspam.c 5876 2007-12-10 23:22:03Z dothebart $";
248 }
249