2000-11-14 10:12:05 ShengHuo ZHU <zsh@cs.rochester.edu>
[gnus] / lisp / nnmbox.el
1 ;;; nnmbox.el --- mail mbox access for Gnus
2 ;; Copyright (C) 1995,96,97,98,99 Free Software Foundation, Inc.
3
4 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
5 ;;      Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
6 ;; Keywords: news, mail
7
8 ;; This file is part of GNU Emacs.
9
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14
15 ;; You should have received a copy of the GNU General Public License
16 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
17 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 ;; Boston, MA 02111-1307, USA.
19
20 ;;; Commentary:
21
22 ;; For an overview of what the interface functions do, please see the
23 ;; Gnus sources.
24
25 ;;; Code:
26
27 (require 'nnheader)
28 (require 'message)
29 (require 'nnmail)
30 (require 'nnoo)
31 (eval-when-compile (require 'cl))
32
33 (nnoo-declare nnmbox)
34
35 (defvoo nnmbox-mbox-file (expand-file-name "~/mbox")
36   "The name of the mail box file in the user's home directory.")
37
38 (defvoo nnmbox-active-file (expand-file-name "~/.mbox-active")
39   "The name of the active file for the mail box.")
40
41 (defvoo nnmbox-get-new-mail t
42   "If non-nil, nnmbox will check the incoming mail file and split the mail.")
43
44 (defvoo nnmbox-prepare-save-mail-hook nil
45   "Hook run narrowed to an article before saving.")
46
47 \f
48
49 (defconst nnmbox-version "nnmbox 1.0"
50   "nnmbox version.")
51
52 (defvoo nnmbox-current-group nil
53   "Current nnmbox news group directory.")
54
55 (defconst nnmbox-mbox-buffer nil)
56
57 (defvoo nnmbox-status-string "")
58
59 (defvoo nnmbox-group-alist nil)
60 (defvoo nnmbox-active-timestamp nil)
61
62 (defvoo nnmbox-file-coding-system mm-text-coding-system)
63 (defvoo nnmbox-file-coding-system-for-write nil)
64 (defvoo nnmbox-active-file-coding-system mm-text-coding-system)
65 (defvoo nnmbox-active-file-coding-system-for-write nil)
66
67 \f
68
69 ;;; Interface functions
70
71 (nnoo-define-basics nnmbox)
72
73 (deffoo nnmbox-retrieve-headers (sequence &optional newsgroup server fetch-old)
74   (save-excursion
75     (set-buffer nntp-server-buffer)
76     (erase-buffer)
77     (let ((number (length sequence))
78           (count 0)
79           article art-string start stop)
80       (nnmbox-possibly-change-newsgroup newsgroup server)
81       (while sequence
82         (setq article (car sequence))
83         (setq art-string (nnmbox-article-string article))
84         (set-buffer nnmbox-mbox-buffer)
85         (when (or (search-forward art-string nil t)
86                   (progn (goto-char (point-min))
87                          (search-forward art-string nil t)))
88           (setq start
89                 (save-excursion
90                   (re-search-backward
91                    (concat "^" message-unix-mail-delimiter) nil t)
92                   (point)))
93           (search-forward "\n\n" nil t)
94           (setq stop (1- (point)))
95           (set-buffer nntp-server-buffer)
96           (insert (format "221 %d Article retrieved.\n" article))
97           (insert-buffer-substring nnmbox-mbox-buffer start stop)
98           (goto-char (point-max))
99           (insert ".\n"))
100         (setq sequence (cdr sequence))
101         (setq count (1+ count))
102         (and (numberp nnmail-large-newsgroup)
103              (> number nnmail-large-newsgroup)
104              (zerop (% count 20))
105              (nnheader-message 5 "nnmbox: Receiving headers... %d%%"
106                                (/ (* count 100) number))))
107
108       (and (numberp nnmail-large-newsgroup)
109            (> number nnmail-large-newsgroup)
110            (nnheader-message 5 "nnmbox: Receiving headers...done"))
111
112       (set-buffer nntp-server-buffer)
113       (nnheader-fold-continuation-lines)
114       'headers)))
115
116 (deffoo nnmbox-open-server (server &optional defs)
117   (nnoo-change-server 'nnmbox server defs)
118   (nnmbox-create-mbox)
119   (cond
120    ((not (file-exists-p nnmbox-mbox-file))
121     (nnmbox-close-server)
122     (nnheader-report 'nnmbox "No such file: %s" nnmbox-mbox-file))
123    ((file-directory-p nnmbox-mbox-file)
124     (nnmbox-close-server)
125     (nnheader-report 'nnmbox "Not a regular file: %s" nnmbox-mbox-file))
126    (t
127     (nnheader-report 'nnmbox "Opened server %s using mbox %s" server
128                      nnmbox-mbox-file)
129     t)))
130
131 (deffoo nnmbox-close-server (&optional server)
132   (when (and nnmbox-mbox-buffer
133              (buffer-name nnmbox-mbox-buffer))
134     (kill-buffer nnmbox-mbox-buffer))
135   (nnoo-close-server 'nnmbox server)
136   t)
137
138 (deffoo nnmbox-server-opened (&optional server)
139   (and (nnoo-current-server-p 'nnmbox server)
140        nnmbox-mbox-buffer
141        (buffer-name nnmbox-mbox-buffer)
142        nntp-server-buffer
143        (buffer-name nntp-server-buffer)))
144
145 (deffoo nnmbox-request-article (article &optional newsgroup server buffer)
146   (nnmbox-possibly-change-newsgroup newsgroup server)
147   (save-excursion
148     (set-buffer nnmbox-mbox-buffer)
149     (goto-char (point-min))
150     (when (search-forward (nnmbox-article-string article) nil t)
151       (let (start stop)
152         (re-search-backward (concat "^" message-unix-mail-delimiter) nil t)
153         (setq start (point))
154         (forward-line 1)
155         (or (and (re-search-forward
156                   (concat "^" message-unix-mail-delimiter) nil t)
157                  (forward-line -1))
158             (goto-char (point-max)))
159         (setq stop (point))
160         (let ((nntp-server-buffer (or buffer nntp-server-buffer)))
161           (set-buffer nntp-server-buffer)
162           (erase-buffer)
163           (insert-buffer-substring nnmbox-mbox-buffer start stop)
164           (goto-char (point-min))
165           (while (looking-at "From ")
166             (delete-char 5)
167             (insert "X-From-Line: ")
168             (forward-line 1))
169           (if (numberp article)
170               (cons nnmbox-current-group article)
171             (nnmbox-article-group-number)))))))
172
173 (deffoo nnmbox-request-group (group &optional server dont-check)
174   (nnmbox-possibly-change-newsgroup nil server)
175   (let ((active (cadr (assoc group nnmbox-group-alist))))
176     (cond
177      ((or (null active)
178           (null (nnmbox-possibly-change-newsgroup group server)))
179       (nnheader-report 'nnmbox "No such group: %s" group))
180      (dont-check
181       (nnheader-report 'nnmbox "Selected group %s" group)
182       (nnheader-insert ""))
183      (t
184       (nnheader-report 'nnmbox "Selected group %s" group)
185       (nnheader-insert "211 %d %d %d %s\n"
186                        (1+ (- (cdr active) (car active)))
187                        (car active) (cdr active) group)))))
188
189 (defun nnmbox-save-buffer ()
190   (let ((coding-system-for-write 
191          (or nnmbox-file-coding-system-for-write
192              nnmbox-file-coding-system)))
193     (save-buffer)))
194
195 (defun nnmbox-save-active (group-alist active-file)
196   (let ((nnmail-active-file-coding-system
197          (or nnmbox-active-file-coding-system-for-write
198              nnmbox-active-file-coding-system)))
199     (nnmail-save-active group-alist active-file)))
200
201 (deffoo nnmbox-request-scan (&optional group server)
202   (nnmbox-possibly-change-newsgroup group server)
203   (nnmbox-read-mbox)
204   (nnmail-get-new-mail
205    'nnmbox
206    (lambda ()
207      (save-excursion
208        (set-buffer nnmbox-mbox-buffer)
209        (nnmbox-save-buffer)))
210    (file-name-directory nnmbox-mbox-file)
211    group
212    (lambda ()
213      (save-excursion
214        (let ((in-buf (current-buffer)))