X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=lisp%2Fgnus-uu.el;h=676c6f0b95f8e1215f9546484061d6cf187ad44d;hb=3738187cad20787b5b99c4061256e30e19ee721a;hp=776de0a291cec8e7ad306c52368b4ed27af13689;hpb=d9a249ab6f6663e7766b40b54fe8456521c18410;p=elisp%2Fgnus.git- diff --git a/lisp/gnus-uu.el b/lisp/gnus-uu.el index 776de0a..676c6f0 100644 --- a/lisp/gnus-uu.el +++ b/lisp/gnus-uu.el @@ -1,5 +1,6 @@ ;;; gnus-uu.el --- extract (uu)encoded files in Gnus -;; Copyright (C) 1985,86,87,93,94,95,96,97,98 Free Software Foundation, Inc. +;; Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 2000, +;; 2001 Free Software Foundation, Inc. ;; Author: Lars Magne Ingebrigtsen ;; Created: 2 Oct 1993 @@ -58,8 +59,8 @@ '(("\\.te?xt$\\|\\.doc$\\|read.*me\\|\\.c?$\\|\\.h$\\|\\.bat$\\|\\.asm$\\|makefile" "cat %s | sed 's/\r$//'") ("\\.pas$" "cat %s | sed 's/\r$//'") ("\\.[1-9]$" "groff -mandoc -Tascii %s | sed s/\b.//g") - ("\\.\\(jpe?g\\|gif\\|tiff?\\|p[pgb]m\\|xwd\\|xbm\\|pcx\\)$" "xv") - ("\\.tga$" "tgatoppm %s | xv -") + ("\\.\\(jpe?g\\|gif\\|tiff?\\|p[pgb]m\\|xwd\\|xbm\\|pcx\\)$" "display") + ("\\.tga$" "tgatoppm %s | ee -") ("\\.\\(wav\\|aiff\\|hcom\\|u[blw]\\|s[bfw]\\|voc\\|smp\\)$" "sox -v .5 %s -t .au -u - > /dev/audio") ("\\.au$" "cat %s > /dev/audio") @@ -216,7 +217,10 @@ Note that this variable can be used in conjunction with the ;; Various variables users may set -(defcustom gnus-uu-tmp-dir "/tmp/" +(defcustom gnus-uu-tmp-dir + (cond ((fboundp 'temp-directory) (temp-directory)) + ((boundp 'temporary-file-directory) temporary-file-directory) + ("/tmp/")) "*Variable saying where gnus-uu is to do its work. Default is \"/tmp/\"." :group 'gnus-extract @@ -291,7 +295,9 @@ so I simply dropped them." (defcustom gnus-uu-digest-headers '("^Date:" "^From:" "^To:" "^Cc:" "^Subject:" "^Message-ID:" "^Keywords:" - "^Summary:" "^References:" "^Content-Type:" "^Content-Transfer-Encoding:") + "^Summary:" "^References:" "^Content-Type:" "^Content-Transfer-Encoding:" + "^MIME-Version:" "^Content-Disposition:" "^Content-Description:" + "^Content-ID:") "*List of regexps to match headers included in digested messages. The headers will be included in the sequence they are matched." :group 'gnus-extract @@ -329,7 +335,8 @@ didn't work, and overwrite existing files. Otherwise, ask each time." (defvar gnus-uu-shar-begin-string "^#! */bin/sh") (defvar gnus-uu-shar-file-name nil) -(defvar gnus-uu-shar-name-marker "begin [0-7][0-7][0-7][ \t]+\\(\\(\\w\\|\\.\\)*\\b\\)") +(defvar gnus-uu-shar-name-marker + "begin [0-7][0-7][0-7][ \t]+\\(\\(\\w\\|\\.\\)*\\b\\)") (defvar gnus-uu-postscript-begin-string "^%!PS-") (defvar gnus-uu-postscript-end-string "^%%EOF$") @@ -344,6 +351,7 @@ didn't work, and overwrite existing files. Otherwise, ask each time." (defvar gnus-uu-default-dir gnus-article-save-directory) (defvar gnus-uu-digest-from-subject nil) +(defvar gnus-uu-digest-buffer nil) ;; Keymaps @@ -369,7 +377,7 @@ didn't work, and overwrite existing files. Otherwise, ask each time." (gnus-define-keys (gnus-uu-extract-map "X" gnus-summary-mode-map) ;;"x" gnus-uu-extract-any - ;;"m" gnus-uu-extract-mime + "m" gnus-summary-save-parts "u" gnus-uu-decode-uu "U" gnus-uu-decode-uu-and-save "s" gnus-uu-decode-unshar @@ -382,17 +390,17 @@ didn't work, and overwrite existing files. Otherwise, ask each time." "P" gnus-uu-decode-postscript-and-save) (gnus-define-keys - (gnus-uu-extract-view-map "v" gnus-uu-extract-map) - "u" gnus-uu-decode-uu-view - "U" gnus-uu-decode-uu-and-save-view - "s" gnus-uu-decode-unshar-view - "S" gnus-uu-decode-unshar-and-save-view - "o" gnus-uu-decode-save-view - "O" gnus-uu-decode-save-view - "b" gnus-uu-decode-binhex-view - "B" gnus-uu-decode-binhex-view - "p" gnus-uu-decode-postscript-view - "P" gnus-uu-decode-postscript-and-save-view) + (gnus-uu-extract-view-map "v" gnus-uu-extract-map) + "u" gnus-uu-decode-uu-view + "U" gnus-uu-decode-uu-and-save-view + "s" gnus-uu-decode-unshar-view + "S" gnus-uu-decode-unshar-and-save-view + "o" gnus-uu-decode-save-view + "O" gnus-uu-decode-save-view + "b" gnus-uu-decode-binhex-view + "B" gnus-uu-decode-binhex-view + "p" gnus-uu-decode-postscript-view + "P" gnus-uu-decode-postscript-and-save-view) ;; Commands. @@ -514,46 +522,51 @@ didn't work, and overwrite existing files. Otherwise, ask each time." (interactive "P") (let ((gnus-uu-save-in-digest t) (file (make-temp-name (nnheader-concat gnus-uu-tmp-dir "forward"))) - buf subject from) - (gnus-setup-message 'forward - (setq gnus-uu-digest-from-subject nil) - (gnus-uu-decode-save n file) - (setq buf (switch-to-buffer - (gnus-get-buffer-create " *gnus-uu-forward*"))) - (erase-buffer) - (insert-file file) - (let ((fs gnus-uu-digest-from-subject)) - (when fs - (setq from (caar fs) - subject (gnus-simplify-subject-fuzzy (cdar fs)) - fs (cdr fs)) - (while (and fs (or from subject)) - (when from - (unless (string= from (caar fs)) - (setq from nil))) - (when subject - (unless (string= (gnus-simplify-subject-fuzzy (cdar fs)) - subject) - (setq subject nil))) - (setq fs (cdr fs)))) - (unless subject - (setq subject "Digested Articles")) - (unless from - (setq from - (if (gnus-news-group-p gnus-newsgroup-name) - gnus-newsgroup-name - "Various")))) - (goto-char (point-min)) - (when (re-search-forward "^Subject: ") - (delete-region (point) (gnus-point-at-eol)) - (insert subject)) - (goto-char (point-min)) - (when (re-search-forward "^From: ") - (delete-region (point) (gnus-point-at-eol)) - (insert from)) - (message-forward post)) - (delete-file file) - (kill-buffer buf) + (message-forward-as-mime message-forward-as-mime) + (mail-parse-charset gnus-newsgroup-charset) + (mail-parse-ignored-charsets gnus-newsgroup-ignored-charsets) + gnus-uu-digest-buffer subject from) + (if (and n (not (numberp n))) + (setq message-forward-as-mime (not message-forward-as-mime) + n nil)) + (let ((gnus-article-reply (gnus-summary-work-articles n))) + (gnus-setup-message 'forward + (setq gnus-uu-digest-from-subject nil) + (setq gnus-uu-digest-buffer + (gnus-get-buffer-create " *gnus-uu-forward*")) + (gnus-uu-decode-save n file) + (switch-to-buffer gnus-uu-digest-buffer) + (let ((fs gnus-uu-digest-from-subject)) + (when fs + (setq from (caar fs) + subject (gnus-simplify-subject-fuzzy (cdar fs)) + fs (cdr fs)) + (while (and fs (or from subject)) + (when from + (unless (string= from (caar fs)) + (setq from nil))) + (when subject + (unless (string= (gnus-simplify-subject-fuzzy (cdar fs)) + subject) + (setq subject nil))) + (setq fs (cdr fs)))) + (unless subject + (setq subject "Digested Articles")) + (unless from + (setq from + (if (gnus-news-group-p gnus-newsgroup-name) + gnus-newsgroup-name + "Various")))) + (goto-char (point-min)) + (when (re-search-forward "^Subject: ") + (delete-region (point) (gnus-point-at-eol)) + (insert subject)) + (goto-char (point-min)) + (when (re-search-forward "^From:") + (delete-region (point) (gnus-point-at-eol)) + (insert " " from)) + (let ((message-forward-decoded-p t)) + (message-forward post t)))) (setq gnus-uu-digest-from-subject nil))) (defun gnus-uu-digest-post-forward (&optional n) @@ -563,20 +576,46 @@ didn't work, and overwrite existing files. Otherwise, ask each time." ;; Process marking. +(defun gnus-message-process-mark (unmarkp new-marked) + (let ((old (- (length gnus-newsgroup-processable) (length new-marked)))) + (message "%d mark%s %s%s" + (length new-marked) + (if (= (length new-marked) 1) "" "s") + (if unmarkp "removed" "added") + (cond + ((and (zerop old) + (not unmarkp)) + "") + (unmarkp + (format ", %d remain marked" + (length gnus-newsgroup-processable))) + (t + (format ", %d already marked" old)))))) + +(defun gnus-new-processable (unmarkp articles) + (if unmarkp + (gnus-intersection gnus-newsgroup-processable articles) + (gnus-set-difference articles gnus-newsgroup-processable))) + (defun gnus-uu-mark-by-regexp (regexp &optional unmark) - "Ask for a regular expression and set the process mark on all articles that match." - (interactive (list (read-from-minibuffer "Mark (regexp): "))) - (let ((articles (gnus-uu-find-articles-matching regexp))) - (while articles - (if unmark - (gnus-summary-remove-process-mark (pop articles)) - (gnus-summary-set-process-mark (pop articles)))) - (message "")) + "Set the process mark on articles whose subjects match REGEXP. +When called interactively, prompt for REGEXP. +Optional UNMARK non-nil means unmark instead of mark." + (interactive "sMark (regexp): \nP") + (save-excursion + (let* ((articles (gnus-uu-find-articles-matching regexp)) + (new-marked (gnus-new-processable unmark articles))) + (while articles + (if unmark + (gnus-summary-remove-process-mark (pop articles)) + (gnus-summary-set-process-mark (pop articles)))) + (gnus-message-process-mark unmark new-marked))) (gnus-summary-position-point)) -(defun gnus-uu-unmark-by-regexp (regexp &optional unmark) - "Ask for a regular expression and remove the process mark on all articles that match." - (interactive (list (read-from-minibuffer "Mark (regexp): "))) +(defun gnus-uu-unmark-by-regexp (regexp) + "Remove the process mark from articles whose subjects match REGEXP. +When called interactively, prompt for REGEXP." + (interactive "sUnmark (regexp): ") (gnus-uu-mark-by-regexp regexp t)) (defun gnus-uu-mark-series () @@ -619,10 +658,12 @@ didn't work, and overwrite existing files. Otherwise, ask each time." (defun gnus-uu-mark-thread () "Marks all articles downwards in this thread." (interactive) - (let ((level (gnus-summary-thread-level))) - (while (and (gnus-summary-set-process-mark (gnus-summary-article-number)) - (zerop (gnus-summary-next-subject 1)) - (> (gnus-summary-thread-level) level)))) + (gnus-save-hidden-threads + (let ((level (gnus-summary-thread-level))) + (while (and (gnus-summary-set-process-mark + (gnus-summary-article-number)) + (zerop (gnus-summary-next-subject 1 nil t)) + (> (gnus-summary-thread-level) level))))) (gnus-summary-position-point)) (defun gnus-uu-unmark-thread () @@ -651,7 +692,7 @@ didn't work, and overwrite existing files. Otherwise, ask each time." (defun gnus-uu-mark-over (&optional score) "Mark all articles with a score over SCORE (the prefix)." (interactive "P") - (let ((score (gnus-score-default score)) + (let ((score (or score gnus-summary-default-score 0)) (data gnus-newsgroup-data)) (save-excursion (while data @@ -807,8 +848,9 @@ didn't work, and overwrite existing files. Otherwise, ask each time." (gnus-uu-save-separate-articles (save-excursion (set-buffer buffer) - (gnus-write-buffer - (concat gnus-uu-saved-article-name gnus-current-article)) + (let ((coding-system-for-write mm-text-coding-system)) + (gnus-write-buffer + (concat gnus-uu-saved-article-name gnus-current-article))) (cond ((eq in-state 'first) (list gnus-uu-saved-article-name 'begin)) ((eq in-state 'first-and-last) (list gnus-uu-saved-article-name 'begin 'end)) @@ -834,14 +876,18 @@ didn't work, and overwrite existing files. Otherwise, ask each time." (eq in-state 'first-and-last)) (progn (setq state (list 'begin)) - (save-excursion (set-buffer (gnus-get-buffer-create "*gnus-uu-body*")) - (erase-buffer)) + (save-excursion + (set-buffer (gnus-get-buffer-create "*gnus-uu-body*")) + (erase-buffer)) (save-excursion (set-buffer (gnus-get-buffer-create "*gnus-uu-pre*")) (erase-buffer) (insert (format - "Date: %s\nFrom: %s\nSubject: %s Digest\n\nTopics:\n" - (current-time-string) name name)))) + "Date: %s\nFrom: %s\nSubject: %s Digest\n\n" + (current-time-string) name name)) + (when (and message-forward-as-mime gnus-uu-digest-buffer) + (insert "<#part type=message/rfc822>\nSubject: Topics\n\n")) + (insert "Topics:\n"))) (when (not (eq in-state 'end)) (setq state (list 'middle)))) (save-excursion @@ -855,14 +901,20 @@ didn't work, and overwrite existing files. Otherwise, ask each time." ;; These two are necessary for XEmacs 19.12 fascism. (put-text-property (point-min) (point-max) 'invisible nil) (put-text-property (point-min) (point-max) 'intangible nil)) + (when (and message-forward-as-mime + message-forward-show-mml + gnus-uu-digest-buffer) + (mm-enable-multibyte) + (mime-to-mml)) (goto-char (point-min)) (re-search-forward "\n\n") - ;; Quote all 30-dash lines. - (save-excursion - (while (re-search-forward "^-" nil t) - (beginning-of-line) - (delete-char 1) - (insert "- "))) + (unless (and message-forward-as-mime gnus-uu-digest-buffer) + ;; Quote all 30-dash lines. + (save-excursion + (while (re-search-forward "^-" nil t) + (beginning-of-line) + (delete-char 1) + (insert "- ")))) (setq body (buffer-substring (1- (point)) (point-max))) (narrow-to-region (point-min) (point)) (if (not (setq headers gnus-uu-digest-headers)) @@ -880,30 +932,66 @@ didn't work, and overwrite existing files. Otherwise, ask each time." (1- (point))) (progn (forward-line 1) (point))))))))) (widen))) - (insert sorthead) (goto-char (point-max)) - (insert body) (goto-char (point-max)) - (insert (concat "\n" (make-string 30 ?-) "\n\n")) + (if (and message-forward-as-mime gnus-uu-digest-buffer) + (if message-forward-show-mml + (progn + (insert "\n<#mml type=message/rfc822>\n") + (insert sorthead) (goto-char (point-max)) + (insert body) (goto-char (point-max)) + (insert "\n<#/mml>\n")) + (let ((buf (mml-generate-new-buffer " *mml*"))) + (with-current-buffer buf + (insert sorthead) + (goto-char (point-min)) + (when (re-search-forward "^Subject: \\(.*\\)$" nil t) + (setq subj (buffer-substring (match-beginning 1) + (match-end 1)))) + (goto-char (point-max)) + (insert body)) + (insert "\n<#part type=message/rfc822" + " buffer=\"" (buffer-name buf) "\">\n"))) + (insert sorthead) (goto-char (point-max)) + (insert body) (goto-char (point-max)) + (insert (concat "\n" (make-string 30 ?-) "\n\n"))) (goto-char beg) (when (re-search-forward "^Subject: \\(.*\\)$" nil t) - (setq subj (buffer-substring (match-beginning 1) (match-end 1))) + (setq subj (buffer-substring (match-beginning 1) (match-end 1)))) + (when subj (save-excursion (set-buffer "*gnus-uu-pre*") (insert (format " %s\n" subj))))) (when (or (eq in-state 'last) (eq in-state 'first-and-last)) - (save-excursion - (set-buffer "*gnus-uu-pre*") - (insert (format "\n\n%s\n\n" (make-string 70 ?-))) - (gnus-write-buffer gnus-uu-saved-article-name)) - (save-excursion - (set-buffer "*gnus-uu-body*") - (goto-char (point-max)) - (insert - (concat (setq end-string (format "End of %s Digest" name)) - "\n")) - (insert (concat (make-string (length end-string) ?*) "\n")) - (write-region - (point-min) (point-max) gnus-uu-saved-article-name t)) + (if (and message-forward-as-mime gnus-uu-digest-buffer) + (with-current-buffer gnus-uu-digest-buffer + (erase-buffer) + (insert-buffer "*gnus-uu-pre*") + (goto-char (point-max)) + (insert-buffer "*gnus-uu-body*")) + (save-excursion + (set-buffer "*gnus-uu-pre*") + (insert (format "\n\n%s\n\n" (make-string 70 ?-))) + (if gnus-uu-digest-buffer + (with-current-buffer gnus-uu-digest-buffer + (erase-buffer) + (insert-buffer "*gnus-uu-pre*")) + (let ((coding-system-for-write mm-text-coding-system)) + (gnus-write-buffer gnus-uu-saved-article-name)))) + (save-excursion + (set-buffer "*gnus-uu-body*") + (goto-char (point-max)) + (insert + (concat (setq end-string (format "End of %s Digest" name)) + "\n")) + (insert (concat (make-string (length end-string) ?*) "\n")) + (if gnus-uu-digest-buffer + (with-current-buffer gnus-uu-digest-buffer + (goto-char (point-max)) + (insert-buffer "*gnus-uu-body*")) + (let ((coding-system-for-write mm-text-coding-system) + (file-name-coding-system nnmail-pathname-coding-system)) + (write-region + (point-min) (point-max) gnus-uu-saved-article-name t))))) (gnus-kill-buffer "*gnus-uu-pre*") (gnus-kill-buffer "*gnus-uu-body*") (push 'end state)) @@ -950,7 +1038,7 @@ didn't work, and overwrite existing files. Otherwise, ask each time." (beginning-of-line) (forward-line 1) (when (file-exists-p gnus-uu-binhex-article-name) - (append-to-file start-char (point) gnus-uu-binhex-article-name)))) + (mm-append-to-file start-char (point) gnus-uu-binhex-article-name)))) (if (memq 'begin state) (cons gnus-uu-binhex-article-name state) state))) @@ -1025,7 +1113,7 @@ didn't work, and overwrite existing files. Otherwise, ask each time." ;; finally just replaces the next to last number with "[0-9]+". (save-excursion (set-buffer (gnus-get-buffer-create gnus-uu-output-buffer-name)) - (buffer-disable-undo (current-buffer)) + (buffer-disable-undo) (erase-buffer) (insert (regexp-quote string)) @@ -1125,7 +1213,7 @@ didn't work, and overwrite existing files. Otherwise, ask each time." string) (save-excursion (set-buffer (gnus-get-buffer-create gnus-uu-output-buffer-name)) - (buffer-disable-undo (current-buffer)) + (buffer-disable-undo) (while string-list (erase-buffer) (insert (caar string-list)) @@ -1200,9 +1288,10 @@ didn't work, and overwrite existing files. Otherwise, ask each time." &optional sloppy limit no-errors) (let ((state 'first) (gnus-asynchronous nil) + (gnus-inhibit-treatment t) has-been-begin article result-file result-files process-state gnus-summary-display-article-function - gnus-article-display-hook gnus-article-prepare-hook + gnus-article-prepare-hook gnus-display-mime-function article-series files) (while (and articles @@ -1327,6 +1416,9 @@ didn't work, and overwrite existing files. Otherwise, ask each time." (while article-series (gnus-summary-tick-article (pop article-series) t))))) + ;; The original article buffer is hosed, shoot it down. + (gnus-kill-buffer gnus-original-article-buffer) + (setq gnus-current-article nil) result-files)) (defun gnus-uu-grab-view (file) @@ -1393,9 +1485,9 @@ didn't work, and overwrite existing files. Otherwise, ask each time." ;; We replace certain characters that could make things messy. (setq gnus-uu-file-name (let ((nnheader-file-name-translation-alist - '((?/ . ?,) (? . ?_) (?* . ?_) (?$ . ?_)))) + '((?/ . ?,) (? . ?_) (?* . ?_) (?$ . ?_)))) (nnheader-translate-file-chars (match-string 1)))) - (replace-match (concat "begin 644 " gnus-uu-file-name) t t) + (replace-match (concat "begin 644 " gnus-uu-file-name) t t) ;; Remove any non gnus-uu-body-line right after start. (forward-line 1) @@ -1470,6 +1562,21 @@ didn't work, and overwrite existing files. Otherwise, ask each time." (cons (if (= (length files) 1) (car files) files) state) state)))) +(defvar gnus-uu-unshar-warning + "*** WARNING *** + +Shell archives are an archaic method of bundling files for distribution +across computer networks. During the unpacking process, arbitrary commands +are executed on your system, and all kinds of nasty things can happen. +Please examine the archive very carefully before you instruct Emacs to +unpack it. You can browse the archive buffer using \\[scroll-other-window]. + +If you are unsure what to do, please answer \"no\"." + "Text of warning message displayed by `gnus-uu-unshar-article'. +Make sure that this text consists only of few text lines. Otherwise, +Gnus might fail to display all of it.") + + ;; This function is used by `gnus-uu-grab-articles' to treat ;; a shared article. (defun gnus-uu-unshar-article (process-buffer in-state) @@ -1480,14 +1587,31 @@ didn't work, and overwrite existing files. Otherwise, ask each time." (goto-char (point-min)) (if (not (re-search-forward gnus-uu-shar-begin-string nil t)) (setq state (list 'wrong-type)) - (beginning-of-line) - (setq start-char (point)) - (call-process-region - start-char (point-max) shell-file-name nil - (gnus-get-buffer-create gnus-uu-output-buffer-name) nil - shell-command-switch - (concat "cd " gnus-uu-work-dir " " - gnus-shell-command-separator " sh")))) + (save-window-excursion + (save-excursion + (switch-to-buffer (current-buffer)) + (delete-other-windows) + (let ((buffer (get-buffer-create (generate-new-buffer-name + "*Warning*")))) + (unless + (unwind-protect + (with-current-buffer buffer + (insert (substitute-command-keys + gnus-uu-unshar-warning)) + (goto-char (point-min)) + (display-buffer buffer) + (yes-or-no-p "This is a shell archive, unshar it? ")) + (kill-buffer buffer)) + (setq state (list 'error)))))) + (unless (memq 'error state) + (beginning-of-line) + (setq start-char (point)) + (call-process-region + start-char (point-max) shell-file-name nil + (gnus-get-buffer-create gnus-uu-output-buffer-name) nil + shell-command-switch + (concat "cd " gnus-uu-work-dir " " + gnus-shell-command-separator " sh"))))) state)) ;; Returns the name of what the shar file is going to unpack. @@ -1795,8 +1919,10 @@ is t." (gnus-summary-post-news) - (use-local-map (copy-keymap (current-local-map))) - (local-set-key "\C-c\C-c" 'gnus-summary-edit-article-done) + (let ((map (make-sparse-keymap))) + (set-keymap-parent map (current-local-map)) + (use-local-map map)) + ;;(local-set-key "\C-c\C-c" 'gnus-summary-edit-article-done) (local-set-key "\C-c\C-c" 'gnus-uu-post-news-inews) (local-set-key "\C-c\C-s" 'gnus-uu-post-news-inews) (local-set-key "\C-c\C-i" 'gnus-uu-post-insert-binary-in-article) @@ -2030,4 +2156,4 @@ If no file has been included, the user will be asked for a file." (provide 'gnus-uu) -;; gnus-uu.el ends here +;;; gnus-uu.el ends here