comparison lisp/vm/vm-mime.el @ 118:7d55a9ba150c r20-1b11

Import from CVS: tag r20-1b11
author cvs
date Mon, 13 Aug 2007 09:24:17 +0200
parents 9f59509498e1
children cca96a509cfe
comparison
equal deleted inserted replaced
117:578fd4947a72 118:7d55a9ba150c
342 1 nil work-buffer) 342 1 nil work-buffer)
343 (forward-char 2)) 343 (forward-char 2))
344 ((looking-at "\n") ; soft line break 344 ((looking-at "\n") ; soft line break
345 (forward-char)) 345 (forward-char))
346 ((looking-at "\r") 346 ((looking-at "\r")
347 ;; assume the user's goatfucking 347 ;; assume the user's goatloving
348 ;; delivery software didn't convert 348 ;; delivery software didn't convert
349 ;; from Internet's CRLF newline 349 ;; from Internet's CRLF newline
350 ;; convention to the local LF 350 ;; convention to the local LF
351 ;; convention. 351 ;; convention.
352 (forward-char)) 352 (forward-char))
524 (if (and vm-display-using-mime 524 (if (and vm-display-using-mime
525 (text-property-any 0 (length string) 'vm-string t string)) 525 (text-property-any 0 (length string) 'vm-string t string))
526 (vm-with-string-as-temp-buffer string 'vm-reencode-mime-encoded-words) 526 (vm-with-string-as-temp-buffer string 'vm-reencode-mime-encoded-words)
527 string )) 527 string ))
528 528
529 (defun vm-mime-parse-content-header (string &optional sepchar keep-quotes) 529 (fset 'vm-mime-parse-content-header 'vm-parse-structured-header)
530 (if (null string)
531 ()
532 (let ((work-buffer nil))
533 (save-excursion
534 (unwind-protect
535 (let ((list nil)
536 (nonspecials "^\"\\( \t\n\r\f")
537 start s char sp+sepchar)
538 (if sepchar
539 (setq nonspecials (concat nonspecials (list sepchar))
540 sp+sepchar (concat "\t\f\n\r " (list sepchar))))
541 (setq work-buffer (generate-new-buffer "*vm-work*"))
542 (buffer-disable-undo work-buffer)
543 (set-buffer work-buffer)
544 (insert string)
545 (goto-char (point-min))
546 (skip-chars-forward "\t\f\n\r ")
547 (setq start (point))
548 (while (not (eobp))
549 (skip-chars-forward nonspecials)
550 (setq char (following-char))
551 (cond ((looking-at "[ \t\n\r\f]")
552 (delete-char 1))
553 ((= char ?\\)
554 (forward-char 1)
555 (if (not (eobp))
556 (forward-char 1)))
557 ((and sepchar (= char sepchar))
558 (setq s (buffer-substring start (point)))
559 (if (or (null (string-match "^[\t\f\n\r ]+$" s))
560 (not (string= s "")))
561 (setq list (cons s list)))
562 (skip-chars-forward sp+sepchar)
563 (setq start (point)))
564 ((looking-at " \t\n\r\f")
565 (skip-chars-forward " \t\n\r\f"))
566 ((= char ?\")
567 (let ((done nil))
568 (if keep-quotes
569 (forward-char 1)
570 (delete-char 1))
571 (while (not done)
572 (if (null (re-search-forward "[\\\"]" nil t))
573 (setq done t)
574 (setq char (char-after (1- (point))))
575 (cond ((char-equal char ?\\)
576 (delete-char -1)
577 (if (eobp)
578 (setq done t)
579 (forward-char 1)))
580 (t (if (not keep-quotes)
581 (delete-char -1))
582 (setq done t)))))))
583 ((= char ?\()
584 (let ((done nil)
585 (pos (point))
586 (parens 1))
587 (forward-char 1)
588 (while (not done)
589 (if (null (re-search-forward "[\\()]" nil t))
590 (setq done t)
591 (setq char (char-after (1- (point))))
592 (cond ((char-equal char ?\\)
593 (if (eobp)
594 (setq done t)
595 (forward-char 1)))
596 ((char-equal char ?\()
597 (setq parens (1+ parens)))
598 (t
599 (setq parens (1- parens)
600 done (zerop parens))))))
601 (delete-region pos (point))))))
602 (setq s (buffer-substring start (point)))
603 (if (and (null (string-match "^[\t\f\n\r ]+$" s))
604 (not (string= s "")))
605 (setq list (cons s list)))
606 (nreverse list))
607 (and work-buffer (kill-buffer work-buffer)))))))
608 530
609 (defun vm-mime-get-header-contents (header-name-regexp) 531 (defun vm-mime-get-header-contents (header-name-regexp)
610 (let ((contents nil) 532 (let ((contents nil)
611 regexp) 533 regexp)
612 (setq regexp (concat "^\\(" header-name-regexp "\\)\\|\\(^$\\)")) 534 (setq regexp (concat "^\\(" header-name-regexp "\\)\\|\\(^$\\)"))
1585 (list this-command) '(vm-mode startup))) 1507 (list this-command) '(vm-mode startup)))
1586 t ) 1508 t )
1587 (fset 'vm-mime-display-button-multipart/digest 1509 (fset 'vm-mime-display-button-multipart/digest
1588 'vm-mime-display-internal-multipart/digest) 1510 'vm-mime-display-internal-multipart/digest)
1589 1511
1512 (defun vm-mime-display-button-message/rfc822 (layout)
1513 (let ((buffer-read-only nil))
1514 (vm-mime-insert-button
1515 (format "%-35.35s [%s to display]"
1516 (vm-mime-layout-description layout)
1517 (if (vm-mouse-support-possible-p)
1518 "Click mouse-2"
1519 "Press RETURN"))
1520 (function
1521 (lambda (layout)
1522 (save-excursion
1523 (vm-mime-display-internal-message/rfc822 layout))))
1524 layout nil)))
1525 (fset 'vm-mime-display-button-message/news
1526 'vm-mime-display-button-message/rfc822)
1527
1590 (defun vm-mime-display-internal-message/rfc822 (layout) 1528 (defun vm-mime-display-internal-message/rfc822 (layout)
1591 (if (vectorp layout) 1529 (if (vectorp layout)
1592 (let ((buffer-read-only nil)) 1530 (vm-mime-display-internal-text/plain layout)
1593 (vm-mime-insert-button
1594 (format "%-35.35s [%s to display]"
1595 (vm-mime-layout-description layout)
1596 (if (vm-mouse-support-possible-p)
1597 "Click mouse-2"
1598 "Press RETURN"))
1599 (function
1600 (lambda (layout)
1601 (save-excursion
1602 (vm-mime-display-internal-message/rfc822 layout))))
1603 layout nil))
1604 (goto-char (vm-extent-start-position layout)) 1531 (goto-char (vm-extent-start-position layout))
1605 (setq layout (vm-extent-property layout 'vm-mime-layout)) 1532 (setq layout (vm-extent-property layout 'vm-mime-layout))
1606 (set-buffer (generate-new-buffer 1533 (set-buffer (generate-new-buffer
1607 (format "message from %s/%s" 1534 (format "message from %s/%s"
1608 (buffer-name vm-mail-buffer) 1535 (buffer-name vm-mail-buffer)
1617 ;; temp buffer, don't offer to save it. 1544 ;; temp buffer, don't offer to save it.
1618 (setq buffer-offer-save nil) 1545 (setq buffer-offer-save nil)
1619 (vm-display (or vm-presentation-buffer (current-buffer)) t 1546 (vm-display (or vm-presentation-buffer (current-buffer)) t
1620 (list this-command) '(vm-mode startup))) 1547 (list this-command) '(vm-mode startup)))
1621 t ) 1548 t )
1622 (fset 'vm-mime-display-button-message/rfc822
1623 'vm-mime-display-internal-message/rfc822)
1624 (fset 'vm-mime-display-internal-message/news 1549 (fset 'vm-mime-display-internal-message/news
1625 'vm-mime-display-internal-message/rfc822) 1550 'vm-mime-display-internal-message/rfc822)
1626 1551
1627 (defun vm-mime-display-internal-message/partial (layout) 1552 (defun vm-mime-display-internal-message/partial (layout)
1628 (if (vectorp layout) 1553 (if (vectorp layout)
1875 ;; for the karking compiler 1800 ;; for the karking compiler
1876 (defvar vm-menu-mime-dispose-menu) 1801 (defvar vm-menu-mime-dispose-menu)
1877 1802
1878 (defun vm-mime-set-extent-glyph-for-layout (e layout) 1803 (defun vm-mime-set-extent-glyph-for-layout (e layout)
1879 (if (and (vm-xemacs-p) (fboundp 'make-glyph) 1804 (if (and (vm-xemacs-p) (fboundp 'make-glyph)
1880 (eq (device-type) 'x) (> (device-bitplanes) 15)) 1805 (eq (device-type) 'x) (> (device-bitplanes) 7))
1881 (let ((type (car (vm-mm-layout-type layout))) 1806 (let ((type (car (vm-mm-layout-type layout)))
1882 (dir vm-image-directory) 1807 (dir vm-image-directory)
1883 glyph) 1808 (colorful (> (device-bitplanes) 15))
1884 (setq glyph 1809 (tuples
1885 (cond ((vm-mime-types-match "text" type) 1810 '(("text" "document-simple.xpm" "document-colorful.xpm")
1886 (make-glyph (vector 1811 ("image" "mona_stamp-simple.xpm" "mona_stamp-colorful.xpm")
1887 'xpm ':file 1812 ("audio" "audio_stamp-simple.xpm" "audio_stamp-colorful.xpm")
1888 (expand-file-name "document.xpm" dir)))) 1813 ("video" "film-simple.xpm" "film-colorful.xpm")
1889 ((vm-mime-types-match "image" type) 1814 ("message" "message-simple.xpm" "message-colorful.xpm")
1890 (make-glyph (vector 1815 ("application" "gear-simple.xpm" "gear-colorful.xpm")
1891 'gif ':file 1816 ("multipart" "stuffed_box-simple.xpm"
1892 (expand-file-name "mona_stamp.gif" dir)))) 1817 "stuffed_box-colorful.xpm")))
1893 ((vm-mime-types-match "audio" type) 1818 glyph file sym p)
1894 (make-glyph (vector 1819 (setq file (catch 'done
1895 'xpm ':file 1820 (while tuples
1896 (expand-file-name "audio_stamp.xpm" dir)))) 1821 (if (vm-mime-types-match (car (car tuples)) type)
1897 ((vm-mime-types-match "video" type) 1822 (throw 'done (car tuples))
1898 (make-glyph (vector 1823 (setq tuples (cdr tuples))))
1899 'xpm ':file 1824 nil)
1900 (expand-file-name "film.xpm" dir)))) 1825 file (and file (if colorful (nth 1 file) (nth 2 file)))
1901 ((vm-mime-types-match "message" type) 1826 sym (and file (intern file vm-image-obarray))
1902 (make-glyph (vector 1827 glyph (and sym (boundp sym) (symbol-value sym))
1903 'xpm ':file 1828 glyph (or glyph (not file)
1904 (expand-file-name "message.xpm" dir)))) 1829 (make-glyph
1905 ((vm-mime-types-match "application" type) 1830 (vector 'autodetect
1906 (make-glyph (vector 1831 ':data (expand-file-name file dir)))))
1907 'xpm ':file 1832 (and sym (not (boundp sym)) (set sym glyph))
1908 (expand-file-name "gear.xpm" dir))))
1909 ((vm-mime-types-match "multipart" type)
1910 (make-glyph (vector
1911 'xpm ':file
1912 (expand-file-name "stuffed_box.xpm" dir))))
1913 (t nil)))
1914 (and glyph (set-extent-begin-glyph e glyph))))) 1833 (and glyph (set-extent-begin-glyph e glyph)))))
1915 1834
1916 (defun vm-mime-insert-button (caption action layout disposable) 1835 (defun vm-mime-insert-button (caption action layout disposable)
1917 (let ((start (point)) e 1836 (let ((start (point)) e
1918 (keymap (make-sparse-keymap)) 1837 (keymap (make-sparse-keymap))
2348 (put-text-property start end 'vm-mime-object object)) 2267 (put-text-property start end 'vm-mime-object object))
2349 ((fboundp 'make-extent) 2268 ((fboundp 'make-extent)
2350 (setq e (make-extent start end)) 2269 (setq e (make-extent start end))
2351 (set-extent-property e 'start-open t) 2270 (set-extent-property e 'start-open t)
2352 (set-extent-property e 'face vm-mime-button-face) 2271 (set-extent-property e 'face vm-mime-button-face)
2353 (vm-set-extent-property e 'duplicable t) 2272 (set-extent-property e 'duplicable t)
2354 (let ((keymap (make-sparse-keymap))) 2273 (let ((keymap (make-sparse-keymap)))
2355 (if vm-popup-menu-on-mouse-3 2274 (if vm-popup-menu-on-mouse-3
2356 (define-key keymap 'button3 2275 (define-key keymap 'button3
2357 'vm-menu-popup-content-disposition-menu)) 2276 'vm-menu-popup-content-disposition-menu))
2358 (vm-set-extent-property e 'keymap keymap) 2277 (set-extent-property e 'keymap keymap)
2359 (set-extent-property e 'balloon-help 'vm-mouse-3-help)) 2278 (set-extent-property e 'balloon-help 'vm-mouse-3-help))
2360 (vm-set-extent-property e 'vm-mime-type type) 2279 (set-extent-property e 'vm-mime-type type)
2361 (vm-set-extent-property e 'vm-mime-object object) 2280 (set-extent-property e 'vm-mime-object object)
2362 (vm-set-extent-property e 'vm-mime-parameters params) 2281 (set-extent-property e 'vm-mime-parameters params)
2363 (vm-set-extent-property e 'vm-mime-description description) 2282 (set-extent-property e 'vm-mime-description description)
2364 (vm-set-extent-property e 'vm-mime-disposition disposition) 2283 (set-extent-property e 'vm-mime-disposition disposition)
2365 (vm-set-extent-property e 'vm-mime-encoded mimed))))) 2284 (set-extent-property e 'vm-mime-encoded mimed)))))
2366 2285
2367 (defun vm-mime-attachment-disposition-at-point () 2286 (defun vm-mime-attachment-disposition-at-point ()
2368 (cond ((vm-fsfemacs-19-p) 2287 (cond ((vm-fsfemacs-19-p)
2369 (let ((disp (get-text-property (point) 'vm-mime-disposition))) 2288 (let ((disp (get-text-property (point) 'vm-mime-disposition)))
2370 (intern (car disp)))) 2289 (intern (car disp))))
2475 (vm-mm-layout-body-start layout) 2394 (vm-mm-layout-body-start layout)
2476 (vm-mm-layout-body-end layout) 2395 (vm-mm-layout-body-end layout)
2477 nil))) 2396 nil)))
2478 2397
2479 (defun vm-mime-encode-composition () 2398 (defun vm-mime-encode-composition ()
2480 "MIME encode the current buffer. 2399 "MIME encode the current mail composition buffer.
2481 Attachment tags added to the buffer with vm-mime-attach-file are expanded 2400 Attachment tags added to the buffer with vm-mime-attach-file are expanded
2482 and the approriate content-type and boundary markup information is added." 2401 and the approriate content-type and boundary markup information is added."
2483 (interactive) 2402 (interactive)
2403 (cond ((vm-xemacs-mule-p)
2404 (vm-mime-xemacs-encode-composition))
2405 ((vm-xemacs-p)
2406 (vm-mime-xemacs-encode-composition))
2407 ((vm-fsfemacs-19-p)
2408 (vm-mime-fsfemacs-encode-composition))
2409 (t
2410 (error "don't know how to MIME encode composition for %s"
2411 (emacs-version)))))
2412
2413 (defun vm-mime-xemacs-encode-composition ()
2484 (save-restriction 2414 (save-restriction
2485 (widen) 2415 (widen)
2486 (if (not (eq major-mode 'mail-mode)) 2416 (if (not (eq major-mode 'mail-mode))
2487 (error "Command must be used in a VM Mail mode buffer.")) 2417 (error "Command must be used in a VM Mail mode buffer."))
2488 (or (null (vm-mail-mode-get-header-contents "MIME-Version:")) 2418 (or (null (vm-mail-mode-get-header-contents "MIME-Version:"))
2492 (boundary-positions nil) 2422 (boundary-positions nil)
2493 already-mimed layout e e-list boundary 2423 already-mimed layout e e-list boundary
2494 type encoding charset params description disposition object 2424 type encoding charset params description disposition object
2495 opoint-min) 2425 opoint-min)
2496 (mail-text) 2426 (mail-text)
2497 (setq e-list (if (fboundp 'extent-list) 2427 (setq e-list (extent-list nil (point) (point-max))
2498 (extent-list nil (point) (point-max))
2499 (vm-mime-fake-attachment-overlays (point) (point-max)))
2500 e-list (vm-delete (function 2428 e-list (vm-delete (function
2501 (lambda (e) 2429 (lambda (e)
2502 (vm-extent-property e 'vm-mime-object))) 2430 (extent-property e 'vm-mime-object)))
2503 e-list t) 2431 e-list t)
2504 e-list (sort e-list (function 2432 e-list (sort e-list (function
2505 (lambda (e1 e2) 2433 (lambda (e1 e2)
2506 (< (vm-extent-end-position e1) 2434 (< (extent-end-position e1)
2507 (vm-extent-end-position e2)))))) 2435 (extent-end-position e2))))))
2508 ;; If there's just one attachment and no other readable 2436 ;; If there's just one attachment and no other readable
2509 ;; text in the buffer then make the message type just be 2437 ;; text in the buffer then make the message type just be
2510 ;; the attachment type rather than sending a multipart 2438 ;; the attachment type rather than sending a multipart
2511 ;; message with one attachment 2439 ;; message with one attachment
2512 (setq just-one (and (= (length e-list) 1) 2440 (setq just-one (and (= (length e-list) 1)
2513 (looking-at "[ \t\n]*") 2441 (looking-at "[ \t\n]*")
2514 (= (match-end 0) 2442 (= (match-end 0)
2515 (vm-extent-start-position (car e-list))) 2443 (extent-start-position (car e-list)))
2516 (save-excursion 2444 (save-excursion
2517 (goto-char (vm-extent-end-position (car e-list))) 2445 (goto-char (extent-end-position (car e-list)))
2518 (looking-at "[ \t\n]*\\'")))) 2446 (looking-at "[ \t\n]*\\'"))))
2519 (if (null e-list) 2447 (if (null e-list)
2520 (progn 2448 (progn
2521 (narrow-to-region (point) (point-max)) 2449 (narrow-to-region (point) (point-max))
2522 (setq charset (vm-determine-proper-charset (point-min) 2450 (setq charset (vm-determine-proper-charset (point-min)
2540 (insert "Content-Type: text/plain; charset=" charset "\n") 2468 (insert "Content-Type: text/plain; charset=" charset "\n")
2541 (insert "Content-Transfer-Encoding: " encoding "\n") 2469 (insert "Content-Transfer-Encoding: " encoding "\n")
2542 (vm-add-mail-mode-header-separator)) 2470 (vm-add-mail-mode-header-separator))
2543 (while e-list 2471 (while e-list
2544 (setq e (car e-list)) 2472 (setq e (car e-list))
2545 (if (or just-one (= (point) (vm-extent-start-position e))) 2473 (if (or just-one (= (point) (extent-start-position e)))
2546 nil 2474 nil
2547 (narrow-to-region (point) (vm-extent-start-position e)) 2475 (narrow-to-region (point) (extent-start-position e))
2548 (setq charset (vm-determine-proper-charset (point-min) 2476 (setq charset (vm-determine-proper-charset (point-min)
2549 (point-max))) 2477 (point-max)))
2550 (setq encoding (vm-determine-proper-content-transfer-encoding 2478 (setq encoding (vm-determine-proper-content-transfer-encoding
2551 (point-min) 2479 (point-min)
2552 (point-max)) 2480 (point-max))
2556 t)) 2484 t))
2557 (setq boundary-positions (cons (point-marker) boundary-positions)) 2485 (setq boundary-positions (cons (point-marker) boundary-positions))
2558 (insert "Content-Type: text/plain; charset=" charset "\n") 2486 (insert "Content-Type: text/plain; charset=" charset "\n")
2559 (insert "Content-Transfer-Encoding: " encoding "\n\n") 2487 (insert "Content-Transfer-Encoding: " encoding "\n\n")
2560 (widen)) 2488 (widen))
2561 (goto-char (vm-extent-start-position e)) 2489 (goto-char (extent-start-position e))
2562 (narrow-to-region (point) (point)) 2490 (narrow-to-region (point) (point))
2563 (setq object (vm-extent-property e 'vm-mime-object)) 2491 (setq object (extent-property e 'vm-mime-object))
2564 ;; insert the object 2492 ;; insert the object
2565 (cond ((bufferp object) 2493 (cond ((bufferp object)
2566 (if (vm-xemacs-p) 2494 (insert-buffer-substring object))
2567 (insert-buffer-substring object)
2568 ;; as of FSF Emacs 19.34, even with the hooks
2569 ;; we've attached to the attachment overlays,
2570 ;; text STILL can be inserted into them when
2571 ;; font-lock is enabled. Explaining why is
2572 ;; beyond the scope of this comment and I
2573 ;; don't know the answer anyway. This works
2574 ;; to prevent it.
2575 (insert-before-markers " ")
2576 (forward-char -1)
2577 (insert-buffer-substring object)
2578 (delete-char 1)))
2579 ((stringp object) 2495 ((stringp object)
2580 (let ((coding-system-for-read 'no-conversion)) 2496 (let ((coding-system-for-read 'no-conversion))
2581 (if (vm-xemacs-p) 2497 (insert-file-contents-literally object))))
2582 (insert-file-contents-literally object)
2583 (insert-before-markers " ")
2584 (forward-char -1)
2585 (insert-file-contents-literally object)
2586 (goto-char (point-max))
2587 (delete-char -1)))))
2588 ;; gather information about the object from the extent. 2498 ;; gather information about the object from the extent.
2589 (if (setq already-mimed (vm-extent-property e 'vm-mime-encoded)) 2499 (if (setq already-mimed (extent-property e 'vm-mime-encoded))
2590 (setq layout (vm-mime-parse-entity 2500 (setq layout (vm-mime-parse-entity
2591 nil (list "text/plain" "charset=us-ascii") 2501 nil (list "text/plain" "charset=us-ascii")
2592 "7bit") 2502 "7bit")
2593 type (or (vm-extent-property e 'vm-mime-type) 2503 type (or (extent-property e 'vm-mime-type)
2594 (car (vm-mm-layout-type layout))) 2504 (car (vm-mm-layout-type layout)))
2595 params (or (vm-extent-property e 'vm-mime-parameters) 2505 params (or (extent-property e 'vm-mime-parameters)
2596 (cdr (vm-mm-layout-qtype layout))) 2506 (cdr (vm-mm-layout-qtype layout)))
2597 description (vm-extent-property e 'vm-mime-description) 2507 description (extent-property e 'vm-mime-description)
2598 disposition 2508 disposition
2599 (if (not 2509 (if (not
2600 (equal 2510 (equal
2601 (car (vm-extent-property e 'vm-mime-disposition)) 2511 (car (extent-property e 'vm-mime-disposition))
2602 "unspecified")) 2512 "unspecified"))
2603 (vm-extent-property e 'vm-mime-disposition) 2513 (extent-property e 'vm-mime-disposition)
2604 (vm-mm-layout-qdisposition layout))) 2514 (vm-mm-layout-qdisposition layout)))
2605 (setq type (vm-extent-property e 'vm-mime-type) 2515 (setq type (extent-property e 'vm-mime-type)
2606 params (vm-extent-property e 'vm-mime-parameters) 2516 params (extent-property e 'vm-mime-parameters)
2607 description (vm-extent-property e 'vm-mime-description) 2517 description (extent-property e 'vm-mime-description)
2608 disposition 2518 disposition
2609 (if (not (equal 2519 (if (not (equal
2610 (car (vm-extent-property e 'vm-mime-disposition)) 2520 (car (extent-property e 'vm-mime-disposition))
2611 "unspecified")) 2521 "unspecified"))
2612 (vm-extent-property e 'vm-mime-disposition) 2522 (extent-property e 'vm-mime-disposition)
2613 nil))) 2523 nil)))
2614 (cond ((vm-mime-types-match "text" type) 2524 (cond ((vm-mime-types-match "text" type)
2615 (setq encoding 2525 (setq encoding
2616 (vm-determine-proper-content-transfer-encoding 2526 (vm-determine-proper-content-transfer-encoding
2617 (if already-mimed 2527 (if already-mimed
2707 (insert "\n"))) 2617 (insert "\n")))
2708 (insert "Content-Transfer-Encoding: " encoding "\n\n")) 2618 (insert "Content-Transfer-Encoding: " encoding "\n\n"))
2709 (goto-char (point-max)) 2619 (goto-char (point-max))
2710 (widen) 2620 (widen)
2711 (save-excursion 2621 (save-excursion
2712 (goto-char (vm-extent-start-position e)) 2622 (goto-char (extent-start-position e))
2713 (vm-assert (looking-at "\\[ATTACHMENT"))) 2623 (vm-assert (looking-at "\\[ATTACHMENT")))
2714 (delete-region (vm-extent-start-position e) 2624 (delete-region (extent-start-position e)
2715 (vm-extent-end-position e)) 2625 (extent-end-position e))
2716 (vm-detach-extent e) 2626 (detach-extent e)
2717 (if (looking-at "\n") 2627 (if (looking-at "\n")
2718 (delete-char 1)) 2628 (delete-char 1))
2719 (setq e-list (cdr e-list))) 2629 (setq e-list (cdr e-list)))
2720 ;; handle the remaining chunk of text after the last 2630 ;; handle the remaining chunk of text after the last
2721 ;; extent, if any. 2631 ;; extent, if any.
2800 (insert "Content-Transfer-Encoding: " encoding "\n") 2710 (insert "Content-Transfer-Encoding: " encoding "\n")
2801 (if 8bit 2711 (if 8bit
2802 (insert "Content-Transfer-Encoding: 8bit\n") 2712 (insert "Content-Transfer-Encoding: 8bit\n")
2803 (insert "Content-Transfer-Encoding: 7bit\n"))))))) 2713 (insert "Content-Transfer-Encoding: 7bit\n")))))))
2804 2714
2715 (defun vm-mime-fsfemacs-encode-composition ()
2716 (save-restriction
2717 (widen)
2718 (if (not (eq major-mode 'mail-mode))
2719 (error "Command must be used in a VM Mail mode buffer."))
2720 (or (null (vm-mail-mode-get-header-contents "MIME-Version:"))
2721 (error "Message is already MIME encoded."))
2722 (let ((8bit nil)
2723 (just-one nil)
2724 (boundary-positions nil)
2725 already-mimed layout o o-list boundary
2726 type encoding charset params description disposition object
2727 opoint-min)
2728 (mail-text)
2729 (setq o-list (vm-mime-fake-attachment-overlays (point) (point-max))
2730 o-list (vm-delete (function
2731 (lambda (o)
2732 (overlay-get o 'vm-mime-object)))
2733 o-list t)
2734 o-list (sort o-list (function
2735 (lambda (e1 e2)
2736 (< (overlay-end e1)
2737 (overlay-end e2))))))
2738 ;; If there's just one attachment and no other readable
2739 ;; text in the buffer then make the message type just be
2740 ;; the attachment type rather than sending a multipart
2741 ;; message with one attachment
2742 (setq just-one (and (= (length o-list) 1)
2743 (looking-at "[ \t\n]*")
2744 (= (match-end 0)
2745 (overlay-start (car o-list)))
2746 (save-excursion
2747 (goto-char (overlay-end (car o-list)))
2748 (looking-at "[ \t\n]*\\'"))))
2749 (if (null o-list)
2750 (progn
2751 (narrow-to-region (point) (point-max))
2752 (setq charset (vm-determine-proper-charset (point-min)
2753 (point-max)))
2754 (if (vm-xemacs-mule-p)
2755 (encode-coding-region (point-min) (point-max)
2756 file-coding-system))
2757 (setq encoding (vm-determine-proper-content-transfer-encoding
2758 (point-min)
2759 (point-max))
2760 encoding (vm-mime-transfer-encode-region encoding
2761 (point-min)
2762 (point-max)
2763 t))
2764 (widen)
2765 (vm-remove-mail-mode-header-separator)
2766 (goto-char (point-min))
2767 (vm-reorder-message-headers
2768 nil nil "\\(Content-Type:\\|Content-Transfer-Encoding\\|MIME-Version:\\)")
2769 (insert "MIME-Version: 1.0\n")
2770 (insert "Content-Type: text/plain; charset=" charset "\n")
2771 (insert "Content-Transfer-Encoding: " encoding "\n")
2772 (vm-add-mail-mode-header-separator))
2773 (while o-list
2774 (setq o (car o-list))
2775 (if (or just-one (= (point) (overlay-start o)))
2776 nil
2777 (narrow-to-region (point) (overlay-start o))
2778 (setq charset (vm-determine-proper-charset (point-min)
2779 (point-max)))
2780 (setq encoding (vm-determine-proper-content-transfer-encoding
2781 (point-min)
2782 (point-max))
2783 encoding (vm-mime-transfer-encode-region encoding
2784 (point-min)
2785 (point-max)
2786 t))
2787 (setq boundary-positions (cons (point-marker) boundary-positions))
2788 (insert "Content-Type: text/plain; charset=" charset "\n")
2789 (insert "Content-Transfer-Encoding: " encoding "\n\n")
2790 (widen))
2791 (goto-char (overlay-start o))
2792 (narrow-to-region (point) (point))
2793 (setq object (overlay-get o 'vm-mime-object))
2794 ;; insert the object
2795 (cond ((bufferp object)
2796 ;; as of FSF Emacs 19.34, even with the hooks
2797 ;; we've attached to the attachment overlays,
2798 ;; text STILL can be inserted into them when
2799 ;; font-lock is enabled. Explaining why is
2800 ;; beyond the scope of this comment and I
2801 ;; don't know the answer anyway. This works
2802 ;; to prevent it.
2803 (insert-before-markers " ")
2804 (forward-char -1)
2805 (insert-buffer-substring object)
2806 (delete-char 1))
2807 ((stringp object)
2808 (insert-before-markers " ")
2809 (forward-char -1)
2810 (insert-file-contents object)
2811 (goto-char (point-max))
2812 (delete-char -1)))
2813 ;; gather information about the object from the extent.
2814 (if (setq already-mimed (overlay-get o 'vm-mime-encoded))
2815 (setq layout (vm-mime-parse-entity
2816 nil (list "text/plain" "charset=us-ascii")
2817 "7bit")
2818 type (or (overlay-get o 'vm-mime-type)
2819 (car (vm-mm-layout-type layout)))
2820 params (or (overlay-get o 'vm-mime-parameters)
2821 (cdr (vm-mm-layout-qtype layout)))
2822 description (overlay-get o 'vm-mime-description)
2823 disposition
2824 (if (not
2825 (equal
2826 (car (overlay-get o 'vm-mime-disposition))
2827 "unspecified"))
2828 (overlay-get o 'vm-mime-disposition)
2829 (vm-mm-layout-qdisposition layout)))
2830 (setq type (overlay-get o 'vm-mime-type)
2831 params (overlay-get o 'vm-mime-parameters)
2832 description (overlay-get o 'vm-mime-description)
2833 disposition
2834 (if (not (equal
2835 (car (overlay-get o 'vm-mime-disposition))
2836 "unspecified"))
2837 (overlay-get o 'vm-mime-disposition)
2838 nil)))
2839 (cond ((vm-mime-types-match "text" type)
2840 (setq encoding
2841 (vm-determine-proper-content-transfer-encoding
2842 (if already-mimed
2843 (vm-mm-layout-body-start layout)
2844 (point-min))
2845 (point-max))
2846 encoding (vm-mime-transfer-encode-region
2847 encoding
2848 (if already-mimed
2849 (vm-mm-layout-body-start layout)
2850 (point-min))
2851 (point-max)
2852 t))
2853 (setq 8bit (or 8bit (equal encoding "8bit"))))
2854 ((or (vm-mime-types-match "message/rfc822" type)
2855 (vm-mime-types-match "message/news" type)
2856 (vm-mime-types-match "multipart" type))
2857 (setq opoint-min (point-min))
2858 (if (not already-mimed)
2859 (setq layout (vm-mime-parse-entity
2860 nil (list "text/plain" "charset=us-ascii")
2861 "7bit")))
2862 ;; MIME messages of type "message" and
2863 ;; "multipart" are required to have a non-opaque
2864 ;; content transfer encoding. This means that
2865 ;; if the user only wants to send out 7bit data,
2866 ;; then any subpart that contains 8bit data must
2867 ;; have an opaque (qp or base64) 8->7bit
2868 ;; conversion performed on it so that the
2869 ;; enclosing entity can use an non-opqaue
2870 ;; encoding.
2871 ;;
2872 ;; message/partial requires a "7bit" encoding so
2873 ;; force 8->7 conversion in that case.
2874 (let ((vm-mime-8bit-text-transfer-encoding
2875 (if (vm-mime-types-match "message/partial" type)
2876 'quoted-printable
2877 vm-mime-8bit-text-transfer-encoding)))
2878 (vm-mime-map-atomic-layouts 'vm-mime-transfer-encode-layout
2879 (vm-mm-layout-parts layout)))
2880 ;; now figure out a proper content trasnfer
2881 ;; encoding value for the enclosing entity.
2882 (re-search-forward "^\n" nil t)
2883 (save-restriction
2884 (narrow-to-region (point) (point-max))
2885 (setq encoding
2886 (vm-determine-proper-content-transfer-encoding
2887 (point-min)
2888 (point-max))))
2889 (setq 8bit (or 8bit (equal encoding "8bit")))
2890 (goto-char (point-max))
2891 (widen)
2892 (narrow-to-region opoint-min (point)))
2893 (t
2894 (vm-mime-base64-encode-region
2895 (if already-mimed
2896 (vm-mm-layout-body-start layout)
2897 (point-min))
2898 (point-max))
2899 (setq encoding "base64")))
2900 (if just-one
2901 nil
2902 (goto-char (point-min))
2903 (setq boundary-positions (cons (point-marker) boundary-positions))
2904 (if (not already-mimed)
2905 nil
2906 ;; trim headers
2907 (vm-reorder-message-headers
2908 nil (nconc (list "Content-Disposition:" "Content-ID:")
2909 (if description
2910 (list "Content-Description:")
2911 nil))
2912 nil)
2913 ;; remove header/text separator
2914 (goto-char (1- (vm-mm-layout-body-start layout)))
2915 (if (looking-at "\n")
2916 (delete-char 1)))
2917 (insert "Content-Type: " type)
2918 (if params
2919 (if vm-mime-avoid-folding-content-type
2920 (insert "; " (mapconcat 'identity params "; ") "\n")
2921 (insert ";\n\t" (mapconcat 'identity params ";\n\t") "\n"))
2922 (insert "\n"))
2923 (and description
2924 (insert "Content-Description: " description "\n"))
2925 (if disposition
2926 (progn
2927 (insert "Content-Disposition: " (car disposition))
2928 (if (cdr disposition)
2929 (insert ";\n\t" (mapconcat 'identity
2930 (cdr disposition)
2931 ";\n\t")))
2932 (insert "\n")))
2933 (insert "Content-Transfer-Encoding: " encoding "\n\n"))
2934 (goto-char (point-max))
2935 (widen)
2936 (save-excursion
2937 (goto-char (overlay-start o))
2938 (vm-assert (looking-at "\\[ATTACHMENT")))
2939 (delete-region (overlay-start o)
2940 (overlay-end o))
2941 (delete-overlay o)
2942 (if (looking-at "\n")
2943 (delete-char 1))
2944 (setq o-list (cdr o-list)))
2945 ;; handle the remaining chunk of text after the last
2946 ;; extent, if any.
2947 (if (or just-one (= (point) (point-max)))
2948 nil
2949 (setq charset (vm-determine-proper-charset (point)
2950 (point-max)))
2951 (if (vm-xemacs-mule-p)
2952 (encode-coding-region (point-min) (point-max)
2953 file-coding-system))
2954 (setq encoding (vm-determine-proper-content-transfer-encoding
2955 (point)
2956 (point-max))
2957 encoding (vm-mime-transfer-encode-region encoding
2958 (point)
2959 (point-max)
2960 t))
2961 (setq 8bit (or 8bit (equal encoding "8bit")))
2962 (setq boundary-positions (cons (point-marker) boundary-positions))
2963 (insert "Content-Type: text/plain; charset=" charset "\n")
2964 (insert "Content-Transfer-Encoding: " encoding "\n\n")
2965 (goto-char (point-max)))
2966 (setq boundary (vm-mime-make-multipart-boundary))
2967 (mail-text)
2968 (while (re-search-forward (concat "^--"
2969 (regexp-quote boundary)
2970 "\\(--\\)?$")
2971 nil t)
2972 (setq boundary (vm-mime-make-multipart-boundary))
2973 (mail-text))
2974 (goto-char (point-max))
2975 (or just-one (insert "\n--" boundary "--\n"))
2976 (while boundary-positions
2977 (goto-char (car boundary-positions))
2978 (insert "\n--" boundary "\n")
2979 (setq boundary-positions (cdr boundary-positions)))
2980 (if (and just-one already-mimed)
2981 (progn
2982 (goto-char (vm-mm-layout-header-start layout))
2983 ;; trim headers
2984 (vm-reorder-message-headers
2985 nil '("Content-Description:" "Content-ID:") nil)
2986 ;; remove header/text separator
2987 (goto-char (1- (vm-mm-layout-body-start layout)))
2988 (if (looking-at "\n")
2989 (delete-char 1))
2990 ;; copy remainder to enclosing entity's header section
2991 (insert-buffer-substring (current-buffer)
2992 (vm-mm-layout-header-start layout)
2993 (vm-mm-layout-body-start layout))
2994 (delete-region (vm-mm-layout-header-start layout)
2995 (vm-mm-layout-body-start layout))))
2996 (goto-char (point-min))
2997 (vm-remove-mail-mode-header-separator)
2998 (vm-reorder-message-headers
2999 nil nil "\\(Content-Type:\\|MIME-Version:\\|Content-Transfer-Encoding\\)")
3000 (vm-add-mail-mode-header-separator)
3001 (insert "MIME-Version: 1.0\n")
3002 (if (not just-one)
3003 (insert (if vm-mime-avoid-folding-content-type
3004 "Content-Type: multipart/mixed; boundary=\""
3005 "Content-Type: multipart/mixed;\n\tboundary=\"")
3006 boundary "\"\n")
3007 (insert "Content-Type: " type)
3008 (if params
3009 (if vm-mime-avoid-folding-content-type
3010 (insert "; " (mapconcat 'identity params "; ") "\n")
3011 (insert ";\n\t" (mapconcat 'identity params ";\n\t"))))
3012 (insert "\n"))
3013 (if just-one
3014 (and description
3015 (insert "Content-Description: " description "\n")))
3016 (if (and just-one disposition)
3017 (progn
3018 (insert "Content-Disposition: " (car disposition))
3019 (if (cdr disposition)
3020 (insert ";\n\t" (mapconcat 'identity
3021 (cdr disposition)
3022 ";\n\t")))
3023 (insert "\n")))
3024 (if just-one
3025 (insert "Content-Transfer-Encoding: " encoding "\n")
3026 (if 8bit
3027 (insert "Content-Transfer-Encoding: 8bit\n")
3028 (insert "Content-Transfer-Encoding: 7bit\n")))))))
3029
2805 (defun vm-mime-fragment-composition (size) 3030 (defun vm-mime-fragment-composition (size)
2806 (save-restriction 3031 (save-restriction
2807 (widen) 3032 (widen)
2808 (message "Fragmenting message...") 3033 (message "Fragmenting message...")
2809 (let ((buffers nil) 3034 (let ((buffers nil)
2814 (vm-remove-mail-mode-header-separator) 3039 (vm-remove-mail-mode-header-separator)
2815 ;; message/partial must have "7bit" content transfer 3040 ;; message/partial must have "7bit" content transfer
2816 ;; encoding, so verify that everything has been encoded for 3041 ;; encoding, so verify that everything has been encoded for
2817 ;; 7bit transmission. 3042 ;; 7bit transmission.
2818 (let ((vm-mime-8bit-text-transfer-encoding 3043 (let ((vm-mime-8bit-text-transfer-encoding
2819 (if (eq vm-mime-8bit-text-transfer-encoding 'send) 3044 (if (eq vm-mime-8bit-text-transfer-encoding '8bit)
2820 'quoted-printable 3045 'quoted-printable
2821 vm-mime-8bit-text-transfer-encoding))) 3046 vm-mime-8bit-text-transfer-encoding)))
2822 (vm-mime-map-atomic-layouts 3047 (vm-mime-map-atomic-layouts
2823 'vm-mime-transfer-encode-layout 3048 'vm-mime-transfer-encode-layout
2824 (list (vm-mime-parse-entity nil (list "text/plain" "charset=us-ascii") 3049 (list (vm-mime-parse-entity nil (list "text/plain" "charset=us-ascii")
2863 (insert mail-header-separator "\n") 3088 (insert mail-header-separator "\n")
2864 (insert-buffer-substring master-buffer start end) 3089 (insert-buffer-substring master-buffer start end)
2865 (vm-increment n) 3090 (vm-increment n)
2866 (set-buffer master-buffer) 3091 (set-buffer master-buffer)
2867 (setq start (point))) 3092 (setq start (point)))
3093 (vm-add-mail-mode-header-separator)
2868 (message "Fragmenting message... done") 3094 (message "Fragmenting message... done")
2869 (nreverse buffers)))) 3095 (nreverse buffers))))
2870 3096
2871 (defun vm-mime-preview-composition () 3097 (defun vm-mime-preview-composition ()
2872 "Show how the current composition buffer might be displayed 3098 "Show how the current composition buffer might be displayed
2885 (setq temp-buffer (generate-new-buffer "composition preview")) 3111 (setq temp-buffer (generate-new-buffer "composition preview"))
2886 (set-buffer temp-buffer) 3112 (set-buffer temp-buffer)
2887 ;; so vm-mime-encode-composition won't complain 3113 ;; so vm-mime-encode-composition won't complain
2888 (setq major-mode 'mail-mode) 3114 (setq major-mode 'mail-mode)
2889 (vm-insert-region-from-buffer mail-buffer) 3115 (vm-insert-region-from-buffer mail-buffer)
3116 (vm-remove-mail-mode-header-separator)
2890 (goto-char (point-min)) 3117 (goto-char (point-min))
2891 (or (vm-mail-mode-get-header-contents "From") 3118 (or (vm-mail-mode-get-header-contents "From")
2892 (insert "From: " (user-login-name) "\n")) 3119 (insert "From: " (user-login-name) "\n"))
2893 (or (vm-mail-mode-get-header-contents "Message-ID") 3120 (or (vm-mail-mode-get-header-contents "Message-ID")
2894 (insert "Message-ID: <fake@fake.fake>\n")) 3121 (insert "Message-ID: <fake@fake.fake>\n"))