;;; nnml.el --- mail spool access for Gnus
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-;; 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+;; 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
;; Authors: Didier Verna <didier@xemacs.org> (adding compaction)
;; Simon Josefsson <simon@josefsson.org> (adding MARKS)
;; This file is part of GNU Emacs.
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
(require 'nnoo)
(eval-when-compile (require 'cl))
-(eval-and-compile
- (autoload 'gnus-article-unpropagatable-p "gnus-sum")
- (autoload 'gnus-backlog-remove-article "gnus-bcklg"))
+;; FIXME first is unused in this file.
+(autoload 'gnus-article-unpropagatable-p "gnus-sum")
+(autoload 'gnus-backlog-remove-article "gnus-bcklg")
(nnoo-declare nnml)
(nnoo-define-basics nnml)
+(eval-when-compile
+ (defsubst nnml-group-name-charset (group server-or-method)
+ (gnus-group-name-charset
+ (if (stringp server-or-method)
+ (gnus-server-to-method
+ (if (string-match "\\+" server-or-method)
+ (concat (substring server-or-method 0 (match-beginning 0))
+ ":" (substring server-or-method (match-end 0)))
+ (concat "nnml:" server-or-method)))
+ (or server-or-method gnus-command-method '(nnml "")))
+ group)))
+
(defun nnml-decoded-group-name (group &optional server-or-method)
"Return a decoded group name of GROUP on SERVER-OR-METHOD."
- (mm-decode-coding-string
+ (if nnmail-group-names-not-encoded-p
+ group
+ (mm-decode-coding-string
+ group
+ (nnml-group-name-charset group server-or-method))))
+
+(defun nnml-encoded-group-name (group &optional server-or-method)
+ "Return an encoded group name of GROUP on SERVER-OR-METHOD."
+ (mm-encode-coding-string
group
- (gnus-group-name-charset
- (if (stringp server-or-method)
- (gnus-server-to-method
- (if (string-match "\\+" server-or-method)
- (concat (substring server-or-method 0 (match-beginning 0))
- ":" (substring server-or-method (match-end 0)))
- (concat "nnml:" server-or-method)))
- (or server-or-method gnus-command-method '(nnml "")))
- group)))
+ (nnml-group-name-charset group server-or-method)))
(defun nnml-group-pathname (group &optional file server)
"Return an absolute file name of FILE for GROUP on SERVER."
- (nnmail-group-pathname (nnml-decoded-group-name group server)
+ (nnmail-group-pathname (inline (nnml-decoded-group-name group server))
nnml-directory file))
(deffoo nnml-retrieve-headers (sequence &optional group server fetch-old)
(string-to-number (file-name-nondirectory path)))))))
(deffoo nnml-request-group (group &optional server dont-check)
- (let ((file-name-coding-system nnmail-pathname-coding-system))
+ (let ((file-name-coding-system nnmail-pathname-coding-system)
+ (decoded (nnml-decoded-group-name group server)))
(cond
((not (nnml-possibly-change-directory group server))
(nnheader-report 'nnml "Invalid group (no such directory)"))
((not (file-directory-p nnml-current-directory))
(nnheader-report 'nnml "%s is not a directory" nnml-current-directory))
(dont-check
- (nnheader-report 'nnml "Group %s selected" group)
+ (nnheader-report 'nnml "Group %s selected" decoded)
t)
(t
(nnheader-re-read-dir nnml-current-directory)
(nnmail-activate 'nnml)
(let ((active (nth 1 (assoc group nnml-group-alist))))
(if (not active)
- (nnheader-report 'nnml "No such group: %s" group)
- (nnheader-report 'nnml "Selected group %s" group)
+ (nnheader-report 'nnml "No such group: %s" decoded)
+ (nnheader-report 'nnml "Selected group %s" decoded)
(nnheader-insert "211 %d %d %d %s\n"
(max (1+ (- (cdr active) (car active))) 0)
(car active) (cdr active) group)))))))
(active-articles
(nnml-directory-articles nnml-current-directory))
(is-old t)
+ (decoded (nnml-decoded-group-name group server))
article rest mod-time number target)
(nnmail-activate 'nnml)
nnml-article-file-alist)
(when (functionp target)
(setq target (funcall target group)))
- (if (and target
- (or (gnus-request-group target)
- (gnus-request-create-group target)))
- (nnmail-expiry-target-group target group)
- (setq target nil))))
+ (when (and target (not (eq target 'delete)))
+ (if (or (gnus-request-group target)
+ (gnus-request-create-group target))
+ (nnmail-expiry-target-group target group)
+ (setq target nil)))))
;; Maybe directory is changed during nnmail-expiry-target-group.
(nnml-possibly-change-directory group server))
(if target
(progn
(nnheader-message 5 "Deleting article %s in %s"
- number group)
+ number decoded)
(condition-case ()
(funcall nnmail-delete-file-function article)
(file-error
(deffoo nnml-request-delete-group (group &optional force server)
(nnml-possibly-change-directory group server)
(let ((file (directory-file-name nnml-current-directory))
- (file-name-directory nnmail-pathname-coding-system))
+ (file-name-coding-system nnmail-pathname-coding-system))
(if (file-exists-p file)
(if (file-directory-p file)
(progn
(concat
nnheader-numerical-short-files
"\\|" (regexp-quote nnml-nov-file-name) "$"
- "\\|" (regexp-quote nnml-marks-file-name) "$"))))
+ "\\|" (regexp-quote nnml-marks-file-name) "$")))
+ (decoded (nnml-decoded-group-name group server)))
(dolist (article articles)
(when (file-writable-p article)
(nnheader-message 5 "Deleting article %s in %s..."
- article group)
+ (file-name-nondirectory article)
+ decoded)
(funcall nnmail-delete-file-function article))))
;; Try to delete the directory itself.
(ignore-errors (delete-directory nnml-current-directory))))
(deffoo nnml-request-rename-group (group new-name &optional server)
(nnml-possibly-change-directory group server)
(let ((new-dir (nnml-group-pathname new-name nil server))
- (old-dir (nnml-group-pathname group nil server)))
+ (old-dir (nnml-group-pathname group nil server))
+ (file-name-coding-system nnmail-pathname-coding-system))
(when (ignore-errors
(make-directory new-dir t)
t)
(nnheader-message 5 "Creating mail directory %s" dir))))
(defun nnml-save-mail (group-art &optional server)
- "Called narrowed to an article."
- (let (chars headers extension)
- (setq chars (nnmail-insert-lines))
- (setq extension
- (and nnml-use-compressed-files
- (> chars nnml-compressed-files-size-threshold)
- (if (stringp nnml-use-compressed-files)
- nnml-use-compressed-files
- ".gz")))
+ "Save a mail into the groups GROUP-ART in the nnml server SERVER.
+GROUP-ART is a list that each element is a cons of a group name and an
+article number. This function is called narrowed to an article."
+ (let* ((chars (nnmail-insert-lines))
+ (extension (and nnml-use-compressed-files
+ (> chars nnml-compressed-files-size-threshold)
+ (if (stringp nnml-use-compressed-files)
+ nnml-use-compressed-files
+ ".gz")))
+ decoded dec file first headers)
+ (when nnmail-group-names-not-encoded-p
+ (dolist (ga (prog1 group-art (setq group-art nil)))
+ (setq group-art (nconc group-art
+ (list (cons (nnml-encoded-group-name (car ga)
+ server)
+ (cdr ga))))
+ decoded (nconc decoded (list (car ga)))))
+ (setq dec decoded))
(nnmail-insert-xref group-art)
(run-hooks 'nnmail-prepare-save-mail-hook)
(run-hooks 'nnml-prepare-save-mail-hook)
(replace-match "X-From-Line: ")
(forward-line 1))
;; We save the article in all the groups it belongs in.
- (let ((ga group-art)
- first)
- (while ga
- (nnml-possibly-create-directory (caar ga) server)
- (let ((file (nnml-group-pathname
- (caar ga) (concat (int-to-string (cdar ga)) extension)
- server)))
- (if first
- ;; It was already saved, so we just make a hard link.
- (funcall nnmail-crosspost-link-function first file t)
- ;; Save the article.
- (nnmail-write-region (point-min) (point-max) file nil
- (if (nnheader-be-verbose 5) nil 'nomesg))
- (setq first file)))
- (setq ga (cdr ga))))
+ (dolist (ga group-art)
+ (if nnmail-group-names-not-encoded-p
+ (progn
+ (nnml-possibly-create-directory (car decoded) server)
+ (setq file (nnmail-group-pathname
+ (pop decoded) nnml-directory
+ (concat (number-to-string (cdr ga)) extension))))
+ (nnml-possibly-create-directory (car ga) server)
+ (setq file (nnml-group-pathname
+ (car ga) (concat (number-to-string (cdr ga)) extension)
+ server)))
+ (if first
+ ;; It was already saved, so we just make a hard link.
+ (let ((file-name-coding-system nnmail-pathname-coding-system))
+ (funcall nnmail-crosspost-link-function first file t))
+ ;; Save the article.
+ (nnmail-write-region (point-min) (point-max) file nil
+ (if (nnheader-be-verbose 5) nil 'nomesg))
+ (setq first file)))
;; Generate a nov line for this article. We generate the nov
;; line after saving, because nov generation destroys the
;; header.
(setq headers (nnml-parse-head chars))
;; Output the nov line to all nov databases that should have it.
- (let ((ga group-art))
- (while ga
- (nnml-add-nov (caar ga) (cdar ga) headers)
- (setq ga (cdr ga))))
- group-art))
+ (if nnmail-group-names-not-encoded-p
+ (dolist (ga group-art)
+ (nnml-add-nov (pop dec) (cdr ga) headers))
+ (dolist (ga group-art)
+ (nnml-add-nov (car ga) (cdr ga) headers))))
+ group-art)
(defun nnml-active-number (group &optional server)
- "Compute the next article number in GROUP."
- (let ((active (cadr (assoc group nnml-group-alist))))
+ "Compute the next article number in GROUP on SERVER."
+ (let ((active (cadr (assoc (if nnmail-group-names-not-encoded-p
+ (nnml-encoded-group-name group server)
+ group)
+ nnml-group-alist))))
;; The group wasn't known to nnml, so we just create an active
;; entry for it.
(unless active
;; Perhaps the active file was corrupt? See whether
;; there are any articles in this group.
(nnml-possibly-create-directory group server)
- (nnml-possibly-change-directory group)
+ (nnml-possibly-change-directory group server)
(unless nnml-article-file-alist
(setq nnml-article-file-alist
(sort
(unless no-active
(nnmail-save-active nnml-group-alist nnml-active-file)))))))
-(eval-when-compile (defvar files))
+(defvar files)
(defun nnml-generate-active-info (dir)
;; Update the active info for this group.
(let ((group (directory-file-name dir))
entry last)
- (setq group (nnheader-file-to-group
- (mm-encode-coding-string
- group
- (gnus-group-name-charset '(nnml "") group))
- nnml-directory)
+ (setq group (nnheader-file-to-group (nnml-encoded-group-name group)
+ nnml-directory)
entry (assoc group nnml-group-alist)
last (or (caadr entry) 0)
nnml-group-alist (delq entry nnml-group-alist))
;; #### already belongs to a range, whereas the corresponding
;; #### article doesn't exist (for example, if you delete an
;; #### article). For that reason, it is important to update
- ;; #### the ranges (meaning remove inexistant articles) before
+ ;; #### the ranges (meaning remove inexistent articles) before
;; #### doing anything on them.
;; 2 a/ read articles:
(let ((read (gnus-info-read info)))
(provide 'nnml)
-;;; arch-tag: 52c97dc3-9735-45de-b439-9e4d23b52004
+;; arch-tag: 52c97dc3-9735-45de-b439-9e4d23b52004
;;; nnml.el ends here