1 ;;; nnfolder.el --- mail folder access for Gnus
2 ;; Copyright (C) 1995 Free Software Foundation, Inc.
4 ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
5 ;; Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
6 ;; Keywords: news, mail
8 ;; This file is part of GNU Emacs.
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)
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
26 ;; For an overview of what the interface functions do, please see the
29 ;; Various enhancements by byer@mv.us.adobe.com (Scott Byer).
37 (defvar nnfolder-directory (expand-file-name "~/Mail/")
38 "The name of the mail box file in the users home directory.")
40 (defvar nnfolder-active-file (concat nnfolder-directory "active")
41 "The name of the active file.")
43 (defvar nnfolder-newsgroups-file (concat nnfolder-directory "newsgroups")
44 "Mail newsgroups description file.")
46 (defvar nnfolder-get-new-mail t
47 "If non-nil, nnml will check the incoming mail file and split the mail.")
51 (defconst nnfolder-version "nnfolder 0.1"
54 (defconst nnfolder-article-marker "X-Gnus-Article-Number: "
55 "String used to demarcate what the article number for a message is.")
57 (defvar nnfolder-current-group nil)
58 (defvar nnfolder-current-buffer nil)
59 (defvar nnfolder-status-string "")
60 (defvar nnfolder-group-alist nil)
61 (defvar nnfolder-buffer-alist nil)
63 (defmacro nnfolder-article-string (article)
64 (` (concat "\n" nnfolder-article-marker (int-to-string (, article)) "")))
66 ;;; Interface functions
68 (defun nnfolder-retrieve-headers (sequence &optional newsgroup server)
70 (set-buffer nntp-server-buffer)
73 (number (length sequence))
74 (delim-string (concat "^" rmail-unix-mail-delimiter))
75 beg article art-string start stop)
76 (nnfolder-possibly-change-group newsgroup)
78 (setq article (car sequence))
79 (setq art-string (nnfolder-article-string article))
80 (set-buffer nnfolder-current-buffer)
81 (if (or (search-forward art-string nil t)
82 ;; Don't search the whole file twice! Also, articles
83 ;; probably have some locality by number, so searching
84 ;; backwards will be faster. Especially if we're at the
85 ;; beginning of the buffer :-). -SLB
86 (search-backward art-string nil t))
88 (setq start (or (re-search-backward delim-string nil t)
90 (search-forward "\n\n" nil t)
91 (setq stop (1- (point)))
92 (set-buffer nntp-server-buffer)
93 (insert (format "221 %d Article retrieved.\n" article))
95 (insert-buffer-substring nnfolder-current-buffer start stop)
96 (goto-char (point-max))
98 (setq sequence (cdr sequence)))
100 ;; Fold continuation lines.
101 (set-buffer nntp-server-buffer)
103 (while (re-search-forward "\\(\r?\n[ \t]+\\)+" nil t)
104 (replace-match " " t t))
107 (defun nnfolder-open-server (host &optional service)
108 (setq nnfolder-status-string "")
109 (setq nnfolder-group-alist nil)
110 (nnheader-init-server-buffer))
112 (defun nnfolder-close-server (&optional server)
115 (defun nnfolder-request-close ()
116 (let ((alist nnfolder-buffer-alist))
118 (nnfolder-close-group (car (car alist)))
119 (setq alist (cdr alist))))
120 (setq nnfolder-buffer-alist nil
121 nnfolder-group-alist nil))
123 (defun nnfolder-server-opened (&optional server)
124 (and nntp-server-buffer
125 (buffer-name nntp-server-buffer)))
127 (defun nnfolder-status-message (&optional server)
128 nnfolder-status-string)
130 (defun nnfolder-request-article (article &optional newsgroup server buffer)
131 (nnfolder-possibly-change-group newsgroup)
132 (if (stringp article)
135 (set-buffer nnfolder-current-buffer)
137 (if (search-forward (nnfolder-article-string article) nil t)
139 (re-search-backward (concat "^" rmail-unix-mail-delimiter) nil t)
142 (or (and (re-search-forward
143 (concat "^" rmail-unix-mail-delimiter) nil t)
145 (goto-char (point-max)))
147 (let ((nntp-server-buffer (or buffer nntp-server-buffer)))
148 (set-buffer nntp-server-buffer)
150 (insert-buffer-substring nnfolder-current-buffer start stop)
151 (goto-char (point-min))
152 (while (looking-at "From ")
154 (insert "X-From-Line: ")
158 (defun nnfolder-request-group (group &optional server dont-check)
160 (nnfolder-possibly-change-group group)
161 (and (assoc group nnfolder-group-alist)
163 (set-buffer nntp-server-buffer)
167 (nnfolder-get-new-mail)
168 (let ((active (assoc group nnfolder-group-alist)))
169 ;; I've been getting stray 211 lines in my nnfolder active
170 ;; file. So, let's make sure that doesn't happen. -SLB
171 (set-buffer nntp-server-buffer)
172 (insert (format "211 %d %d %d %s\n"
173 (1+ (- (cdr (car (cdr active)))
174 (car (car (cdr active)))))
175 (car (car (cdr active)))
176 (cdr (car (cdr active)))
180 (defun nnfolder-close-group (group &optional server)
181 (nnfolder-possibly-change-group group)
183 (set-buffer nnfolder-current-buffer)
184 (or (buffer-modified-p)
185 (kill-buffer (current-buffer))))
186 (setq nnfolder-buffer-alist (delq (assoc group nnfolder-buffer-alist)
187 nnfolder-buffer-alist))
188 (setq nnfolder-current-group nil
189 nnfolder-current-buffer nil)
192 (defun nnfolder-request-list (&optional server)
193 (if server (nnfolder-get-new-mail))
194 (or nnfolder-group-alist
195 (nnmail-find-file nnfolder-active-file)
197 (setq nnfolder-group-alist (nnmail-get-active))
198 (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
199 (nnmail-find-file nnfolder-active-file))))
201 (defun nnfolder-request-newgroups (date &optional server)
202 (nnfolder-request-list server))
204 (defun nnfolder-request-list-newsgroups (&optional server)
205 (nnmail-find-file nnfolder-newsgroups-file))
207 (defun nnfolder-request-post (&optional server)
208 (mail-send-and-exit nil))
210 (fset 'nnfolder-request-post-buffer 'nnmail-request-post-buffer)
212 (defun nnfolder-request-expire-articles (articles newsgroup &optional server force)
213 (nnfolder-possibly-change-group newsgroup)
214 (let* ((days (or (and nnmail-expiry-wait-function
215 (funcall nnmail-expiry-wait-function newsgroup))
219 (set-buffer nnfolder-current-buffer)
222 (if (search-forward (nnfolder-article-string (car articles)) nil t)
224 (> (nnmail-days-between
225 (current-time-string)
227 (point) (progn (end-of-line) (point))))
230 (and gnus-verbose-backends
231 (message "Deleting: %s" (car articles)))
232 (nnfolder-delete-mail))
233 (setq rest (cons (car articles) rest))))
234 (setq articles (cdr articles)))
236 ;; Find the lowest active article in this group.
237 (let ((active (nth 1 (assoc newsgroup nnfolder-group-alist))))
238 (goto-char (point-min))
239 (while (not (search-forward
240 (nnfolder-article-string (car active)) nil t))
241 (setcar active (1+ (car active)))
242 (goto-char (point-min))))
243 (nnmail-save-active nnfolder-group-alist nnfolder-active-file)
246 (defun nnfolder-request-move-article
247 (article group server accept-form &optional last)
248 (nnfolder-possibly-change-group group)
249 (let ((buf (get-buffer-create " *nnfolder move*"))
252 (nnfolder-request-article article group server)
255 (buffer-disable-undo (current-buffer))
257 (insert-buffer-substring nntp-server-buffer)
258 (goto-char (point-min))
259 (while (re-search-forward
261 (save-excursion (search-forward "\n\n" nil t) (point)) t)
262 (delete-region (progn (beginning-of-line) (point))
263 (progn (forward-line 1) (point))))