Mercurial > hg > xemacs-beta
diff lisp/vm/vm-mime.el @ 30:ec9a17fef872 r19-15b98
Import from CVS: tag r19-15b98
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:52:29 +0200 |
parents | 441bb1e64a06 |
children | c53a95d3c46d fe104dbd9147 |
line wrap: on
line diff
--- a/lisp/vm/vm-mime.el Mon Aug 13 08:51:58 2007 +0200 +++ b/lisp/vm/vm-mime.el Mon Aug 13 08:52:29 2007 +0200 @@ -39,6 +39,7 @@ (defun vm-mm-layout-parts (e) (aref e 10)) (defun vm-mm-layout-cache (e) (aref e 11)) +(defun vm-set-mm-layout-type (e type) (aset e 0 type)) (defun vm-set-mm-layout-cache (e c) (aset e 11 c)) (defun vm-mm-layout (m) @@ -362,7 +363,7 @@ (and (> (- end start) 200) (message "Decoding quoted-printable... done"))) -(defun vm-mime-qp-encode-region (start end &optional Q-encoding) +(defun vm-mime-qp-encode-region (start end &optional Q-encoding quote-from) (and (> (- end start) 200) (message "Encoding quoted-printable...")) (let ((work-buffer nil) @@ -386,7 +387,9 @@ ((and (= char 32) (not (= ?\n (char-after (1+ inputpos))))) (vm-insert-char char 1 nil work-buffer) (vm-increment cols)) - ((or (< char 33) (> char 126) (= char 61)) + ((or (< char 33) (> char 126) (= char 61) + (and quote-from (= cols 0) (let ((case-fold-search nil)) + (looking-at "From ")))) (vm-insert-char ?= 1 nil work-buffer) (vm-insert-char (car (rassq (lsh char -4) hex-digit-alist)) 1 nil work-buffer) @@ -415,29 +418,45 @@ (defun vm-decode-mime-message-headers (m) (let ((case-fold-search t) (buffer-read-only nil) + (did-decode nil) charset encoding match-start match-end start end) (save-excursion (goto-char (vm-headers-of m)) (while (re-search-forward vm-mime-encoded-word-regexp (vm-text-of m) t) (setq match-start (match-beginning 0) match-end (match-end 0) - charset (match-string 1) - encoding (match-string 2) + charset (buffer-substring (match-beginning 1) (match-end 1)) + encoding (buffer-substring (match-beginning 2) (match-end 2)) start (match-beginning 3) end (vm-marker (match-end 3))) ;; don't change anything if we can't display the ;; character set properly. (if (not (vm-mime-charset-internally-displayable-p charset)) nil + (setq did-decode t) (delete-region end match-end) - (cond ((string-match "B" encoding) - (vm-mime-B-decode-region start end)) - ((string-match "Q" encoding) - (vm-mime-Q-decode-region start end)) - (t (vm-mime-error "unknown encoded word encoding, %s" - encoding))) + (condition-case data + (cond ((string-match "B" encoding) + (vm-mime-B-decode-region start end)) + ((string-match "Q" encoding) + (vm-mime-Q-decode-region start end)) + (t (vm-mime-error "unknown encoded word encoding, %s" + encoding))) + (vm-mime-error (apply 'message (cdr data)) + (goto-char start) + (insert "**invalid encoded word**") + (delete-region (point) end))) (vm-mime-charset-decode-region charset start end) - (delete-region match-start start)))))) + (delete-region match-start start))) + ;; if we did some decoding, re-electrify the headers since + ;; some of the extents might have been wiped by the + ;; decoding process. + (if did-decode + (save-restriction + (narrow-to-region (vm-headers-of m) (vm-text-of m)) + (vm-energize-urls) + (vm-highlight-headers-maybe) + (vm-energize-headers-and-xfaces)))))) (defun vm-decode-mime-encoded-words () (let ((case-fold-search t) @@ -448,8 +467,8 @@ (while (re-search-forward vm-mime-encoded-word-regexp nil t) (setq match-start (match-beginning 0) match-end (match-end 0) - charset (match-string 1) - encoding (match-string 2) + charset (buffer-substring (match-beginning 1) (match-end 1)) + encoding (buffer-substring (match-beginning 2) (match-end 2)) start (match-beginning 3) end (vm-marker (match-end 3))) ;; don't change anything if we can't display the @@ -457,12 +476,17 @@ (if (not (vm-mime-charset-internally-displayable-p charset)) nil (delete-region end match-end) - (cond ((string-match "B" encoding) - (vm-mime-B-decode-region start end)) - ((string-match "Q" encoding) - (vm-mime-Q-decode-region start end)) - (t (vm-mime-error "unknown encoded word encoding, %s" - encoding))) + (condition-case data + (cond ((string-match "B" encoding) + (vm-mime-B-decode-region start end)) + ((string-match "Q" encoding) + (vm-mime-Q-decode-region start end)) + (t (vm-mime-error "unknown encoded word encoding, %s" + encoding))) + (vm-mime-error (apply 'message (cdr data)) + (goto-char start) + (insert "**invalid encoded word**") + (delete-region (point) end))) (vm-mime-charset-decode-region charset start end) (delete-region match-start start)))))) @@ -715,7 +739,7 @@ ((string-match "^multipart/" (car type)) (setq c-t '("text/plain" "charset=us-ascii") c-t-e "7bit")) ; below - ((string-match "^message/rfc822" (car type)) + ((string-match "^message/\\(rfc822\\|news\\)" (car type)) (setq c-t '("text/plain" "charset=us-ascii") c-t-e "7bit") (goto-char (point-min)) @@ -885,6 +909,10 @@ ;; Tell XEmacs/MULE not to mess with the text on writes. buffer-read-only t mode-line-format vm-mode-line-format) + ;; scroll in place messes with scroll-up and this loses + (defvar scroll-in-place) + (make-local-variable 'scroll-in-place) + (setq scroll-in-place nil) (and (vm-xemacs-mule-p) (set-file-coding-system 'binary t)) (cond ((vm-fsfemacs-19-p) @@ -896,7 +924,7 @@ (copy-sequence standard-display-table))) (standard-display-european t) (setq buffer-display-table standard-display-table)))) - (if vm-frame-per-folder + (if (and vm-frame-per-folder (vm-multiple-frames-possible-p)) (vm-set-hooks-for-frame-deletion)) (use-local-map vm-mode-map) (and (vm-toolbar-support-possible-p) vm-use-toolbar @@ -969,7 +997,7 @@ "iso-2022-jp")) (t (or (car (cdr - (vm-string-assoc + (assoc (car charsets) vm-mime-mule-charset-to-charset-alist))) "unknown")))) @@ -1309,7 +1337,9 @@ ;; display unmatched message and text types as ;; text/plain. (vm-mime-display-internal-text/plain layout))) - (t (vm-mime-display-internal-application/octet-stream + (t (and extent (vm-mime-rewrite-failed-button + extent (vm-mm-layout-cache layout))) + (vm-mime-display-internal-application/octet-stream (or extent layout)))) (and extent (vm-mime-delete-button-maybe extent))) (set-buffer-modified-p modified))) @@ -1348,7 +1378,10 @@ (buffer-read-only nil) (charset (or (vm-mime-get-parameter layout "charset") "us-ascii"))) (if (not (vm-mime-charset-internally-displayable-p charset)) - nil + (progn + (vm-set-mm-layout-cache + layout (concat "Undisplayable charset: " charset)) + nil) (vm-mime-insert-mime-body layout) (setq end (point-marker)) (vm-mime-transfer-decode-region layout start end) @@ -1389,7 +1422,7 @@ (start (point)) end) (if (and (processp process) (eq (process-status process) 'run)) - nil + t (cond ((or (null tempfile) (null (file-exists-p tempfile))) (vm-mime-insert-mime-body layout) (setq end (point-marker)) @@ -1412,9 +1445,7 @@ (setq vm-folder-garbage-alist (cons (cons tempfile 'delete-file) vm-folder-garbage-alist))))) - (message "Launching %s..." (mapconcat 'identity - program-list - " ")) + (message "Launching %s..." (mapconcat 'identity program-list " ")) (setq process (apply 'start-process (format "view %25s" (vm-mime-layout-description layout)) @@ -1601,6 +1632,8 @@ t ) (fset 'vm-mime-display-button-message/rfc822 'vm-mime-display-internal-message/rfc822) +(fset 'vm-mime-display-internal-message/news + 'vm-mime-display-internal-message/rfc822) (defun vm-mime-display-internal-message/partial (layout) (if (vectorp layout) @@ -1829,7 +1862,7 @@ layout disposable) t )) -(defun vm-mime-run-display-function-at-point (&optional function) +(defun vm-mime-run-display-function-at-point (&optional function dispose) (interactive) ;; save excursion to keep point from moving. its motion would ;; drag window point along, to a place arbitrarily far from @@ -1896,7 +1929,8 @@ (keymap (make-sparse-keymap)) (buffer-read-only nil)) (if (fboundp 'set-keymap-parents) - (set-keymap-parents keymap (list (current-local-map))) + (if (current-local-map) + (set-keymap-parents keymap (list (current-local-map)))) (setq keymap (nconc keymap (current-local-map)))) (define-key keymap "\r" 'vm-mime-run-display-function-at-point) (if (and (vm-mouse-xemacs-mouse-p) vm-popup-menu-on-mouse-3) @@ -1927,6 +1961,14 @@ (vm-set-extent-property e 'vm-mime-layout layout) (vm-set-extent-property e 'vm-mime-function action))) +(defun vm-mime-rewrite-failed-button (button error-string) + (let* ((buffer-read-only nil) + (start (point))) + (goto-char (vm-extent-start-position button)) + (insert (format "DISPLAY FAILED -- %s" error-string)) + (vm-set-extent-endpoints button start (vm-extent-end-position button)) + (delete-region (point) (vm-extent-end-position button)))) + (defun vm-mime-send-body-to-file (layout &optional default-filename) (if (not (vectorp layout)) (setq layout (vm-extent-property layout 'vm-mime-layout))) @@ -1982,11 +2024,10 @@ (write-region (point-min) (point-max) file nil nil)) (and work-buffer (kill-buffer work-buffer)))))) -(defun vm-mime-pipe-body-to-command (layout &optional discard-output) +(defun vm-mime-pipe-body-to-command (command layout &optional discard-output) (if (not (vectorp layout)) (setq layout (vm-extent-property layout 'vm-mime-layout))) - (let ((command-line (read-string "Pipe to command: ")) - (output-buffer (if discard-output + (let ((output-buffer (if discard-output 0 (get-buffer-create "*Shell Command Output*"))) (work-buffer nil)) @@ -2009,7 +2050,7 @@ (call-process-region (point-min) (point-max) (or shell-file-name "sh") nil output-buffer nil - shell-command-switch command-line))) + shell-command-switch command))) (and work-buffer (kill-buffer work-buffer))) (if (bufferp output-buffer) (progn @@ -2021,8 +2062,37 @@ '(vm-pipe-message-to-command))))))) t ) -(defun vm-mime-pipe-body-to-command-discard-output (layout) - (vm-mime-pipe-body-to-command layout t)) +(defun vm-mime-pipe-body-to-queried-command (layout &optional discard-output) + (let ((command (read-string "Pipe to command: "))) + (vm-mime-pipe-body-to-command command layout discard-output))) + +(defun vm-mime-pipe-body-to-queried-command-discard-output (layout) + (vm-mime-pipe-body-to-queried-command layout t)) + +(defun vm-mime-send-body-to-printer (layout) + (vm-mime-pipe-body-to-command (mapconcat (function identity) + (nconc (list vm-print-command) + vm-print-command-switches) + " ") + layout)) + +(defun vm-mime-display-body-as-text (button) + (let ((vm-auto-displayed-mime-content-types '("text/plain")) + (layout (copy-sequence (vm-extent-property button 'vm-mime-layout)))) + (vm-set-extent-property button 'vm-mime-disposable t) + (vm-set-extent-property button 'vm-mime-layout layout) + ;; not universally correct, but close enough. + (vm-set-mm-layout-type layout '("text/plain" "charset=us-ascii")) + (goto-char (vm-extent-start-position button)) + (vm-decode-mime-layout button t))) + +(defun vm-mime-display-body-using-external-viewer (button) + (let ((layout (vm-extent-property button 'vm-mime-layout))) + (goto-char (vm-extent-start-position button)) + (if (not (vm-mime-find-external-viewer (car (vm-mm-layout-type layout)))) + (error "No viewer defined for type %s" + (car (vm-mm-layout-type layout))) + (vm-mime-display-external-generic layout)))) (defun vm-mime-scrub-description (string) (let ((work-buffer nil)) @@ -2260,10 +2330,6 @@ (or type "MIME file"))) (insert tag-string "\n") (setq end (1- (point))) - ;; attach default filename for recipient if currently - ;; non-MIME. if already MIME'd don't do this because it - ;; would override any content-disposition header already in - ;; the attachment. (if (and (stringp object) (not mimed)) (progn (if (or (vm-mime-types-match "application" type) @@ -2274,11 +2340,15 @@ (list (concat "filename=\"" (file-name-nondirectory object) - "\"")))))) + "\""))))) + (setq disposition (list "unspecified"))) (cond ((vm-fsfemacs-19-p) (put-text-property start end 'front-sticky nil) (put-text-property start end 'rear-nonsticky t) - (put-text-property start end 'intangible object) +;; can't be intangible because menu clicking at a position needs +;; to set point inside the tag so that a command can access the +;; text properties there. +;; (put-text-property start end 'intangible object) (put-text-property start end 'face vm-mime-button-face) (put-text-property start end 'vm-mime-type type) (put-text-property start end 'vm-mime-object object) @@ -2292,6 +2362,12 @@ (set-extent-property e 'start-open t) (set-extent-property e 'face vm-mime-button-face) (vm-set-extent-property e 'duplicable t) + (let ((keymap (make-sparse-keymap))) + (if vm-popup-menu-on-mouse-3 + (define-key keymap 'button3 + 'vm-menu-popup-content-disposition-menu)) + (vm-set-extent-property e 'keymap keymap) + (set-extent-property e 'balloon-help 'vm-mouse-3-help)) (vm-set-extent-property e 'vm-mime-type type) (vm-set-extent-property e 'vm-mime-object object) (vm-set-extent-property e 'vm-mime-parameters params) @@ -2299,6 +2375,24 @@ (vm-set-extent-property e 'vm-mime-disposition disposition) (vm-set-extent-property e 'vm-mime-encoded mimed))))) +(defun vm-mime-attachment-disposition-at-point () + (cond ((vm-fsfemacs-19-p) + (let ((disp (get-text-property (point) 'vm-mime-disposition))) + (intern (car disp)))) + ((vm-xemacs-p) + (let* ((e (extent-at (point) nil 'vm-mime-disposition)) + (disp (extent-property e 'vm-mime-disposition))) + (intern (car disp)))))) + +(defun vm-mime-set-attachment-disposition-at-point (sym) + (cond ((vm-fsfemacs-19-p) + (let ((disp (get-text-property (point) 'vm-mime-disposition))) + (setcar disp (symbol-name sym)))) + ((vm-xemacs-p) + (let* ((e (extent-at (point) nil 'vm-mime-disposition)) + (disp (extent-property e 'vm-mime-disposition))) + (setcar disp (symbol-name sym)))))) + (defun vm-disallow-overlay-endpoint-insertion (overlay after start end &optional old-size) (cond ((null after) nil) @@ -2360,21 +2454,26 @@ (replace-match mail-header-separator t t)))) (defun vm-mime-transfer-encode-region (encoding beg end crlf) - (let ((case-fold-search t)) + (let ((case-fold-search t) + (armor-from (and vm-mime-composition-armor-from-lines + (let ((case-fold-search nil)) + (save-excursion + (goto-char beg) + (re-search-forward "^From " nil t)))))) (cond ((string-match "^binary$" encoding) (vm-mime-base64-encode-region beg end crlf) (setq encoding "base64")) - ((string-match "^7bit$" encoding) t) + ((and (not armor-from) (string-match "^7bit$" encoding)) t) ((string-match "^base64$" encoding) t) ((string-match "^quoted-printable$" encoding) t) - ;; must be 8bit ((eq vm-mime-8bit-text-transfer-encoding 'quoted-printable) - (vm-mime-qp-encode-region beg end) + (vm-mime-qp-encode-region beg end nil armor-from) (setq encoding "quoted-printable")) ((eq vm-mime-8bit-text-transfer-encoding 'base64) (vm-mime-base64-encode-region beg end crlf) (setq encoding "base64")) - ((eq vm-mime-8bit-text-transfer-encoding 'send) t)) + (armor-from (vm-mime-qp-encode-region beg end nil armor-from)) + ((eq vm-mime-8bit-text-transfer-encoding '8bit) t)) encoding )) (defun vm-mime-transfer-encode-layout (layout) @@ -2475,7 +2574,19 @@ (setq object (vm-extent-property e 'vm-mime-object)) ;; insert the object (cond ((bufferp object) - (insert-buffer-substring object)) + (if (vm-xemacs-p) + (insert-buffer-substring object) + ;; as of FSF Emacs 19.34, even with the hooks + ;; we've attached to the attachment overlays, + ;; text STILL can be inserted into them when + ;; font-lock is enabled. Explaining why is + ;; beyond the scope of this comment and I + ;; don't know the answer anyway. This works + ;; to prevent it. + (insert-before-markers " ") + (forward-char -1) + (insert-buffer-substring object) + (delete-char 1))) ((stringp object) (let ((overridding-file-coding-system 'no-conversion)) (insert-file-contents-literally object)))) @@ -2489,12 +2600,22 @@ params (or (vm-extent-property e 'vm-mime-parameters) (cdr (vm-mm-layout-qtype layout))) description (vm-extent-property e 'vm-mime-description) - disposition (or (vm-extent-property e 'vm-mime-disposition) - (vm-mm-layout-qdisposition layout))) + disposition + (if (not + (equal + (car (vm-extent-property e 'vm-mime-disposition)) + "unspecified")) + (vm-extent-property e 'vm-mime-disposition) + (vm-mm-layout-qdisposition layout))) (setq type (vm-extent-property e 'vm-mime-type) params (vm-extent-property e 'vm-mime-parameters) description (vm-extent-property e 'vm-mime-description) - disposition (vm-extent-property e 'vm-mime-disposition))) + disposition + (if (not (equal + (car (vm-extent-property e 'vm-mime-disposition)) + "unspecified")) + (vm-extent-property e 'vm-mime-disposition) + nil))) (cond ((vm-mime-types-match "text" type) (setq encoding (vm-determine-proper-content-transfer-encoding @@ -2511,6 +2632,7 @@ t)) (setq 8bit (or 8bit (equal encoding "8bit")))) ((or (vm-mime-types-match "message/rfc822" type) + (vm-mime-types-match "message/news" type) (vm-mime-types-match "multipart" type)) (setq opoint-min (point-min)) (if (not already-mimed) @@ -2591,6 +2713,9 @@ (insert "Content-Transfer-Encoding: " encoding "\n\n")) (goto-char (point-max)) (widen) + (save-excursion + (goto-char (vm-extent-start-position e)) + (vm-assert (looking-at "\\[ATTACHMENT"))) (delete-region (vm-extent-start-position e) (vm-extent-end-position e)) (vm-detach-extent e)