1 ;;; elsp-bsfilter.el --- Bsfilter support for elmo-spam.
3 ;; Copyright (C) 2004 Hiroya Murata <lapis-lazuli@pop06.odn.ne.jp>
4 ;; Copyright (C) 2004 Yuuichi Teranishi <teranisi@gohome.org>
6 ;; Author: Hiroya Murata <lapis-lazuli@pop06.odn.ne.jp>
7 ;; Keywords: mail, net news, spam
9 ;; This file is part of Wanderlust (Yet Another Message Interface on Emacsen).
11 ;; This program is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details.
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
35 (defgroup elmo-spam-bsfilter nil
36 "Spam bsfilter configuration."
39 (defcustom elmo-spam-bsfilter-shell-program "ruby"
42 :group 'elmo-spam-bsfilter)
44 (defcustom elmo-spam-bsfilter-shell-switch nil
47 :group 'elmo-spam-bsfilter)
49 (defcustom elmo-spam-bsfilter-program (exec-installed-p "bsfilter")
50 "*Program name of the Bsfilter."
51 :type '(string :tag "Program name of the bsfilter")
52 :group 'elmo-spam-bsfilter)
54 (defcustom elmo-spam-bsfilter-args nil
55 "*Argument list for bsfilter."
56 :type '(repeat string)
57 :group 'elmo-spam-bsfilter)
59 (defcustom elmo-spam-bsfilter-update-switch "--synchronous-auto-update"
60 "*The switch that Bsfilter uses to update database with classify."
62 :group 'elmo-spam-bsfilter)
64 (defcustom elmo-spam-bsfilter-database-directory nil
65 "*Directory path of the Bsfilter databases."
66 :type '(choice (directory :tag "Location of the Bsfilter database directory")
67 (const :tag "Use the default"))
68 :group 'elmo-spam-bsfilter)
70 (defcustom elmo-spam-bsfilter-max-files-per-process 100
71 "Number of files processed at once."
73 :group 'elmo-spam-bsfilter)
75 (defcustom elmo-spam-bsfilter-max-messages-per-process 30
76 "Number of messages processed at once."
78 :group 'elmo-spam-bsfilter)
80 (defcustom elmo-spam-bsfilter-debug nil
81 "Non-nil to debug elmo bsfilter spam backend."
83 :group 'elmo-spam-bsfilter)
86 (luna-define-class elsp-bsfilter (elsp-generic)))
88 (defsubst elsp-bsfilter-call-bsfilter (&rest args)
89 (apply #'call-process-region
90 (point-min) (point-max)
91 elmo-spam-bsfilter-shell-program
92 nil (if elmo-spam-bsfilter-debug
93 (get-buffer-create "*Debug ELMO Bsfilter*"))
95 (append (if elmo-spam-bsfilter-shell-switch
96 (list elmo-spam-bsfilter-shell-switch))
97 (if elmo-spam-bsfilter-program
98 (list elmo-spam-bsfilter-program))
99 elmo-spam-bsfilter-args
100 (if elmo-spam-bsfilter-database-directory
101 (list "--homedir" elmo-spam-bsfilter-database-directory))
102 (elmo-flatten args))))
104 (luna-define-method elmo-spam-buffer-spam-p ((processor elsp-bsfilter)
105 buffer &optional register)
106 (with-current-buffer buffer
107 (= 0 (elsp-bsfilter-call-bsfilter
108 (if register elmo-spam-bsfilter-update-switch)))))
110 (defun elsp-bsfilter-list-spam-filter (process output)
111 (when (buffer-live-p (process-buffer process))
112 (with-current-buffer (process-buffer process)
114 (goto-char (process-mark process))
116 (set-marker (process-mark process) (point)))
117 (while (re-search-forward "^combined probability.+\r?\n" nil t)
118 (delete-region (match-beginning 0) (match-end 0))
119 (elmo-progress-notify 'elmo-spam-check-spam))
120 (when elmo-spam-bsfilter-debug
121 (with-current-buffer (get-buffer-create "*Debug ELMO Bsfilter*")
122 (goto-char (point-max))
125 (defsubst elsp-bsfilter-start-list-spam (targets)
127 (apply #'start-process
130 elmo-spam-bsfilter-shell-program
131 (append (if elmo-spam-bsfilter-shell-switch
132 (list elmo-spam-bsfilter-shell-switch))
133 (if elmo-spam-bsfilter-program
134 (list elmo-spam-bsfilter-program))
135 elmo-spam-bsfilter-args
137 (if elmo-spam-bsfilter-database-directory
139 elmo-spam-bsfilter-database-directory))
141 (set-process-filter process #'elsp-bsfilter-list-spam-filter)
144 (defsubst elsp-bsfilter-read-list-spam (results hash)
145 (goto-char (point-min))
147 (let* ((filename (buffer-substring (point) (save-excursion
150 (number (elmo-get-hash-val filename hash)))
152 (setq results (cons number results)))
156 (luna-define-method elmo-spam-list-spam-messages :around
157 ((processor elsp-bsfilter) folder &optional numbers)
158 (if (not (elmo-folder-message-file-p folder))
159 (luna-call-next-method)
160 (let* ((nth-of-targets (1- (or elmo-spam-bsfilter-max-files-per-process
162 (numbers (or numbers (elmo-folder-list-messages folder t t)))
163 (hash (elmo-make-hash (length numbers)))
166 (let ((filename (elmo-message-file-name folder number)))
167 (elmo-set-hash-val filename number hash)
173 (let* ((last (nthcdr nth-of-targets targets))
177 (let ((process (elsp-bsfilter-start-list-spam targets)))
178 (while (memq (process-status process) '(open run))
179 (accept-process-output process 1))
180 (setq results (elsp-bsfilter-read-list-spam results hash)))
182 (setq targets next))))
186 (defsubst elsp-bsfilter-register-buffer (buffer spam restore &optional mbox)
187 (with-current-buffer buffer
188 (elsp-bsfilter-call-bsfilter
190 (if restore (if spam "--sub-clean" "--sub-spam"))
191 (if spam "--add-spam" "--add-clean")
192 (if mbox "--mbox"))))
194 (luna-define-method elmo-spam-register-spam-buffer ((processor elsp-bsfilter)
195 buffer &optional restore)
196 (elsp-bsfilter-register-buffer buffer t restore))
198 (luna-define-method elmo-spam-register-good-buffer ((processor elsp-bsfilter)
199 buffer &optional restore)
200 (elsp-bsfilter-register-buffer buffer nil restore))
202 (defsubst elmo-spam-bsfilter-register-messages (folder numbers spam restore)
203 (let ((numbers (or numbers (elmo-folder-list-messages folder t t))))
204 (if (and (> (length numbers) 1)
205 elmo-spam-bsfilter-max-messages-per-process
206 (> elmo-spam-bsfilter-max-messages-per-process 0))
207 (elmo-spam-process-messages-as-mbox
209 elmo-spam-bsfilter-max-messages-per-process
210 (lambda (count spam restore)
211 (elsp-bsfilter-register-buffer (current-buffer) spam restore 'mbox)
212 (elmo-progress-notify 'elmo-spam-register count))
214 (luna-call-next-method))))
216 (luna-define-method elmo-spam-register-spam-messages :around
217 ((processor elsp-bsfilter) folder &optional numbers restore)
218 (elmo-spam-bsfilter-register-messages folder numbers t restore))
220 (luna-define-method elmo-spam-register-good-messages :around
221 ((processor elsp-bsfilter) folder &optional numbers restore)
222 (elmo-spam-bsfilter-register-messages folder numbers nil restore))
225 (product-provide (provide 'elsp-bsfilter) (require 'elmo-version))
227 ;;; elsp-bsfilter.el ends here