Commit a62d3999 a62d399923f765826de158c1030dddffb7817a31 by Sergey Poznyakoff

Rewrite as module. Change

initialization of the syntax tables.
(handle-exception,sieve-verbose-print): New macro
(action-fileinto,action-keep,action-stop,action-discard): Produce
verbose diagnostics if required.
(sieve-run): Take thunk as an argument. Report implicit keep if it
returns #t and the verbose mode is on.
(sieve-main): Take thunk as an argument.
1 parent 59c262ad
...@@ -17,23 +17,66 @@ ...@@ -17,23 +17,66 @@
17 17
18 ;;;; This module provides core functionality for the sieve scripts. 18 ;;;; This module provides core functionality for the sieve scripts.
19 19
20 (set! %load-path (append %load-path (list sieve-libdir))) 20 (define-module (mailutils sieve-core))
21 (use-modules (mailutils)) 21
22 (use-modules (mailutils mailutils))
23
24 ;;; Set to #t when parsing
25 (define-public sieve-parser #f)
26
27 ;;; Name of the input source
28 (define-public sieve-source "UNKNOWN")
22 29
23 ;;; The email address for originator of error messages. Should be <> 30 ;;; The email address for originator of error messages. Should be <>
24 ;;; but current mailutils API is unable to parse and handle it. 31 ;;; but current mailutils API is unable to parse and handle it.
25 ;;; Site administrators are supposed to replace it with the 32 ;;; Site administrators are supposed to replace it with the
26 ;;; actual value. 33 ;;; actual value.
27 (define sieve-daemon-email "MAILER-DAEMON@localhost") 34 (define-public sieve-daemon-email "MAILER-DAEMON@localhost")
28 35
29 ;;; The email address of the user whose mailbox is being processed. 36 ;;; The email address of the user whose mailbox is being processed.
30 ;;; If #f, it will be set by sieve-main 37 ;;; If #f, it will be set by sieve-main
31 (define sieve-my-email #f) 38 (define-public sieve-my-email #f)
32 39
33 (define SIEVE-WARNING "Warning") 40 (define SIEVE-WARNING "Warning")
34 (define SIEVE-ERROR "Error") 41 (define SIEVE-ERROR "Error")
35 (define SIEVE-NOTICE "Notice") 42 (define SIEVE-NOTICE "Notice")
36 43
44 (defmacro handle-exception (. expr)
45 `(catch 'mailutils-error
46 (lambda () ,@expr)
47 (lambda (key . args)
48 (runtime-message SIEVE-ERROR
49 "In function " (car args) ": "
50 (apply format #f
51 (list-ref args 1) (list-ref args 2))
52 (let ((error-code
53 (car (list-ref args (1- (length args))))))
54 (if (= error-code 0)
55 ""
56 (string-append
57 "; Error code: "
58 (number->string error-code)
59 " - "
60 (mu-strerror error-code))))))))
61
62 ;;; Set to #t if verbose action listing is requested
63 (define-public sieve-verbose #f)
64
65 (defmacro sieve-verbose-print (action . rest)
66 `(if sieve-verbose
67 (let ((uid (false-if-exception
68 (mu-message-get-uid sieve-current-message))))
69 (display ,action)
70 (display " on msg uid ")
71 (display uid)
72 (let ((args (list ,@rest)))
73 (cond ((not (null? args))
74 (display ": ")
75 (for-each
76 display
77 args))))
78 (newline))))
79
37 ;;; List of open mailboxes. 80 ;;; List of open mailboxes.
38 ;;; Each entry is: (list MAILBOX-NAME OPEN-FLAGS MBOX) 81 ;;; Each entry is: (list MAILBOX-NAME OPEN-FLAGS MBOX)
39 (define sieve-mailbox-list '()) 82 (define sieve-mailbox-list '())
...@@ -46,7 +89,7 @@ ...@@ -46,7 +89,7 @@
46 (let ((slot (assoc name sieve-mailbox-list))) 89 (let ((slot (assoc name sieve-mailbox-list)))
47 (if slot 90 (if slot
48 (list-ref slot 2) 91 (list-ref slot 2)
49 (let ((mbox (mu-mailbox-open name flags))) 92 (let ((mbox (false-if-exception (mu-mailbox-open name flags))))
50 (if mbox 93 (if mbox
51 (set! sieve-mailbox-list (append 94 (set! sieve-mailbox-list (append
52 sieve-mailbox-list 95 sieve-mailbox-list
...@@ -78,14 +121,14 @@ ...@@ -78,14 +121,14 @@
78 filename))))) 121 filename)))))
79 122
80 ;;; Comparators 123 ;;; Comparators
81 (cond 124 (define-public sieve-standard-comparators
82 (sieve-parser 125 (list (list "i;octet" string=?)
83 (sieve-register-comparator "i;octet" string=?) 126 (list "i;ascii-casemap" string-ci=?)))
84 (sieve-register-comparator "i;ascii-casemap" string-ci=?)))
85 127
86 ;;; Stop statement 128 ;;; Stop statement
87 129
88 (define (sieve-stop) 130 (define-public (sieve-stop)
131 (sieve-verbose-print "STOP")
89 (throw 'sieve-stop)) 132 (throw 'sieve-stop))
90 133
91 ;;; Basic five actions: 134 ;;; Basic five actions:
...@@ -94,14 +137,16 @@ ...@@ -94,14 +137,16 @@
94 137
95 ;;; fileinto 138 ;;; fileinto
96 139
97 (define (action-fileinto filename) 140 (define-public (action-fileinto filename)
98 (let ((name (sieve-expand-filename filename))) 141 (let ((name (sieve-expand-filename filename)))
142 (sieve-verbose-print "FILEINTO" "delivering into " name)
99 (if (string? name) 143 (if (string? name)
100 (let ((outbox (sieve-mailbox-open name "cw"))) 144 (let ((outbox (sieve-mailbox-open name "cw")))
101 (cond 145 (cond
102 (outbox 146 (outbox
147 (handle-exception
103 (mu-mailbox-append-message outbox sieve-current-message) 148 (mu-mailbox-append-message outbox sieve-current-message)
104 (mu-message-delete sieve-current-message)) 149 (mu-message-delete sieve-current-message)))
105 (else 150 (else
106 (runtime-message SIEVE-ERROR 151 (runtime-message SIEVE-ERROR
107 "Could not open mailbox " name)))) 152 "Could not open mailbox " name))))
...@@ -112,20 +157,23 @@ ...@@ -112,20 +157,23 @@
112 157
113 ;;; keep -- does nothing worth mentioning :^) 158 ;;; keep -- does nothing worth mentioning :^)
114 159
115 (define (action-keep) 160 (define-public (action-keep)
116 (mu-message-delete sieve-current-message #f)) 161 (sieve-verbose-print "KEEP")
162 (handle-exception
163 (mu-message-delete sieve-current-message #f)))
117 164
118 ;;; discard 165 ;;; discard
119 166
120 (define (action-discard) 167 (define-public (action-discard)
121 (mu-message-delete sieve-current-message)) 168 (sieve-verbose-print "DISCARD" "marking as deleted")
169 (handle-exception
170 (mu-message-delete sieve-current-message)))
122 171
123 ;;; Register standard actions 172 ;;; Register standard actions
124 (cond 173 (define-public sieve-standard-actions
125 (sieve-parser 174 (list (list "keep" action-keep '() '())
126 (sieve-register-action "keep" action-keep '() '()) 175 (list "discard" action-discard '() '())
127 (sieve-register-action "discard" action-discard '() '()) 176 (list "fileinto" action-fileinto (list 'string) '())))
128 (sieve-register-action "fileinto" action-fileinto (list 'string) '())))
129 177
130 ;;; Some utilities. 178 ;;; Some utilities.
131 179
...@@ -225,7 +273,7 @@ ...@@ -225,7 +273,7 @@
225 273
226 ;;;; Standard tests: 274 ;;;; Standard tests:
227 275
228 (define (test-address header-list key-list . opt-args) 276 (define-public (test-address header-list key-list . opt-args)
229 (let ((comp (find-comp opt-args)) 277 (let ((comp (find-comp opt-args))
230 (match (find-match opt-args)) 278 (match (find-match opt-args))
231 (part (cond 279 (part (cond
...@@ -275,7 +323,7 @@ ...@@ -275,7 +323,7 @@
275 key-list) 323 key-list)
276 #f)))) 324 #f))))
277 325
278 (define (test-size key-size . comp) 326 (define-public (test-size key-size . comp)
279 (let ((size (mu-message-get-size sieve-current-message))) 327 (let ((size (mu-message-get-size sieve-current-message)))
280 (cond 328 (cond
281 ((null? comp) ;; An extension. 329 ((null? comp) ;; An extension.
...@@ -287,7 +335,7 @@ ...@@ -287,7 +335,7 @@
287 (else 335 (else
288 (runtime-message SIEVE-ERROR "test-size: unknown comparator " comp))))) 336 (runtime-message SIEVE-ERROR "test-size: unknown comparator " comp)))))
289 337
290 (define (test-envelope part-list key-list . opt-args) 338 (define-public (test-envelope part-list key-list . opt-args)
291 (let ((comp (find-comp opt-args)) 339 (let ((comp (find-comp opt-args))
292 (match (find-match opt-args))) 340 (match (find-match opt-args)))
293 (call-with-current-continuation 341 (call-with-current-continuation
...@@ -309,7 +357,7 @@ ...@@ -309,7 +357,7 @@
309 part-list) 357 part-list)
310 #f)))) 358 #f))))
311 359
312 (define (test-exists header-list) 360 (define-public (test-exists header-list)
313 (call-with-current-continuation 361 (call-with-current-continuation
314 (lambda (exit) 362 (lambda (exit)
315 (for-each (lambda (hdr) 363 (for-each (lambda (hdr)
...@@ -319,7 +367,7 @@ ...@@ -319,7 +367,7 @@
319 header-list) 367 header-list)
320 #t))) 368 #t)))
321 369
322 (define (test-header header-list key-list . opt-args) 370 (define-public (test-header header-list key-list . opt-args)
323 (let ((comp (find-comp opt-args)) 371 (let ((comp (find-comp opt-args))
324 (match (find-match opt-args))) 372 (match (find-match opt-args)))
325 (call-with-current-continuation 373 (call-with-current-continuation
...@@ -360,45 +408,46 @@ ...@@ -360,45 +408,46 @@
360 (cons "over" #f))) 408 (cons "over" #f)))
361 (define comparator (list (cons "comparator" 'string))) 409 (define comparator (list (cons "comparator" 'string)))
362 410
363 (cond 411 (define-public sieve-standard-tests
364 (sieve-parser 412 (list
365 (sieve-register-test "address" 413 (list "address"
366 test-address 414 test-address
367 (list 'string-list 'string-list) 415 (list 'string-list 'string-list)
368 (append address-part comparator match-type)) 416 (append address-part comparator match-type))
369 (sieve-register-test "size" 417 (list "size"
370 test-size 418 test-size
371 (list 'number) 419 (list 'number)
372 size-comp) 420 size-comp)
373 (sieve-register-test "envelope" 421 (list "envelope"
374 test-envelope 422 test-envelope
375 (list 'string-list 'string-list) 423 (list 'string-list 'string-list)
376 (append comparator address-part match-type)) 424 (append comparator address-part match-type))
377 (sieve-register-test "exists" 425 (list "exists"
378 test-exists 426 test-exists
379 (list 'string-list) 427 (list 'string-list)
380 '()) 428 '())
381 (sieve-register-test "header" 429 (list "header"
382 test-header 430 test-header
383 (list 'string-list 'string-list) 431 (list 'string-list 'string-list)
384 (append comparator match-type)) 432 (append comparator match-type))
385 (sieve-register-test "false" #f '() '()) 433 (list "false" #f '() '())
386 (sieve-register-test "true" #t '() '()))) 434 (list "true" #t '() '())))
387 435
388 ;;; runtime-message 436 ;;; runtime-message
389 437
390 (define (runtime-message level . text) 438 (define-public (runtime-message level . text)
391 (let ((msg (apply string-append 439 (let ((msg (apply string-append
392 (map (lambda (x) 440 (map (lambda (x)
393 (format #f "~A" x)) 441 (format #f "~A" x))
394 (append 442 (append
395 (list "(in " sieve-source ") ") 443 (list "(in " sieve-source ") ")
396 text))))) 444 text)))))
445 (if sieve-current-message
397 (mu-message-set-header sieve-current-message 446 (mu-message-set-header sieve-current-message
398 (string-append "X-Sieve-" level) 447 (string-append "X-Sieve-" level)
399 msg) 448 msg))
400 (if (isatty? (current-output-port)) 449 (if (isatty? (current-error-port))
401 (display (string-append level ": " msg "\n"))))) 450 (display (string-append level ": " msg "\n") (current-error-port)))))
402 451
403 (define (guimb?) 452 (define (guimb?)
404 (catch #t 453 (catch #t
...@@ -411,7 +460,7 @@ ...@@ -411,7 +460,7 @@
411 (define sieve-mailbox #f) 460 (define sieve-mailbox #f)
412 (define sieve-current-message #f) 461 (define sieve-current-message #f)
413 462
414 (define (sieve-run) 463 (define (sieve-run thunk)
415 (if (not sieve-my-email) 464 (if (not sieve-my-email)
416 (set! sieve-my-email (mu-username->email))) 465 (set! sieve-my-email (mu-username->email)))
417 ; (DEBUG 1 "Mailbox: " sieve-mailbox) 466 ; (DEBUG 1 "Mailbox: " sieve-mailbox)
...@@ -421,10 +470,11 @@ ...@@ -421,10 +470,11 @@
421 ((> n count) #f) 470 ((> n count) #f)
422 (set! sieve-current-message 471 (set! sieve-current-message
423 (mu-mailbox-get-message sieve-mailbox n)) 472 (mu-mailbox-get-message sieve-mailbox n))
424 (catch 'sieve-stop 473 (and (catch 'sieve-stop
425 sieve-process-message 474 thunk
426 (lambda args 475 (lambda args
427 #f))) 476 #f))
477 (sieve-verbose-print "IMPLICIT KEEP")))
428 (sieve-close-mailboxes))) 478 (sieve-close-mailboxes)))
429 479
430 (define (sieve-command-line) 480 (define (sieve-command-line)
...@@ -434,7 +484,8 @@ ...@@ -434,7 +484,8 @@
434 (append (list "<temp-file>") args))) 484 (append (list "<temp-file>") args)))
435 (lambda args (command-line)))) 485 (lambda args (command-line))))
436 486
437 (define (sieve-main) 487 (define-public (sieve-main thunk)
488 (handle-exception
438 (cond 489 (cond
439 ((not (guimb?)) 490 ((not (guimb?))
440 (let* ((cl (sieve-command-line)) 491 (let* ((cl (sieve-command-line))
...@@ -443,13 +494,12 @@ ...@@ -443,13 +494,12 @@
443 (cadr cl) 494 (cadr cl)
444 (string-append (mu-mail-directory) "/" 495 (string-append (mu-mail-directory) "/"
445 (passwd:name (mu-getpwuid (getuid))))))) 496 (passwd:name (mu-getpwuid (getuid)))))))
446 ; (DEBUG 2 "mailbox name " name) 497
447 (set! sieve-mailbox (mu-mailbox-open name "rw")) 498 (set! sieve-mailbox (mu-mailbox-open name "rw"))
448 (sieve-run) 499 (sieve-run thunk)
449 (mu-mailbox-expunge sieve-mailbox) 500 (mu-mailbox-expunge sieve-mailbox)
450 (mu-mailbox-close sieve-mailbox))) 501 (mu-mailbox-close sieve-mailbox)))
451 (else 502 (else
452 ; (DEBUG 1 "Using current-mailbox")
453 (set! sieve-mailbox current-mailbox) 503 (set! sieve-mailbox current-mailbox)
454 (sieve-run)))) 504 (sieve-run thunk)))))
455 505
......