diff options
| author | Miles Bader | 2005-03-30 08:14:32 +0000 |
|---|---|---|
| committer | Miles Bader | 2005-03-30 08:14:32 +0000 |
| commit | 10ace8ea53395cc0ca656080cc3e828febc39b34 (patch) | |
| tree | 76c630eeaaeb80f46baa34c8af29ff0b41abfd4b /lisp/gnus | |
| parent | 96a29ab7a8e391db9078d1ffc0c76faffb470a1b (diff) | |
| download | emacs-10ace8ea53395cc0ca656080cc3e828febc39b34.tar.gz emacs-10ace8ea53395cc0ca656080cc3e828febc39b34.zip | |
Revision: miles@gnu.org--gnu-2005/emacs--cvs-trunk--0--patch-220
Merge from gnus--rel--5.10
Patches applied:
* gnus--rel--5.10 (patch 45-52)
- Update from CVS
- Update from CVS: texi Makefile.in CVS keyw cruft
- Update from CVS: ChangeLog tweaks
2005-03-29 Reiner Steib <Reiner.Steib@gmx.de>
* etc/gnus-refcard.tex, etc/gnus-logo.eps: New files.
2005-03-25 Katsumi Yamaoka <yamaoka@jpl.org>
* lisp/gnus/message.el (message-resend): Bind rfc2047-encode-encoded-words.
* lisp/gnus/mm-util.el (mm-replace-in-string): New function.
(mm-xemacs-find-mime-charset-1): Ignore errors while loading
latin-unity, which cannot be used with XEmacs 21.1.
* lisp/gnus/rfc2047.el (rfc2047-encode-function-alist): Rename from
rfc2047-encoding-function-alist in order to avoid conflicting with
the old version.
(rfc2047-encode-message-header): Remove useless goto-char.
(rfc2047-encodable-p): Don't move point.
(rfc2047-syntax-table): Treat `(' and `)' as is.
(rfc2047-encode-region): Concatenate words containing non-ASCII
characters in structured fields; don't encode space-delimited
ASCII words even in unstructured fields; don't break words at
char-category boundaries; encode encoded words in structured
fields; treat text within parentheses as special; show the
original text when error has occurred; move point to the end of
the region after encoding, suggested by IRIE Tetsuya
<irie@t.email.ne.jp>; treat backslash-quoted characters as
non-special; check carefully whether to encode special characters;
fix some kind of misconfigured headers; signal a real error if
debug-on-quit or debug-on-error is non-nil; don't infloop,
suggested by Hiroshi Fujishima <pooh@nature.tsukuba.ac.jp>; assume
the close parenthesis may be included in the encoded word; encode
bogus delimiters.
(rfc2047-encode-string): Use mm-with-multibyte-buffer.
(rfc2047-encode-max-chars): New variable.
(rfc2047-encode-1): New function.
(rfc2047-encode): Use it; encode text so that it occupies the
maximum width within 76-column; work correctly on Q encoding for
iso-2022-* charsets; fold the line before encoding; don't append a
space if the encoded word includes close parenthesis.
(rfc2047-fold-region): Use existing whitespace for LWSP; make it
sure not to break a line just after the header name.
(rfc2047-b-encode-region): Remove.
(rfc2047-b-encode-string): New function.
(rfc2047-q-encode-region): Remove.
(rfc2047-q-encode-string): New function.
(rfc2047-encode-parameter): New function.
(rfc2047-encoded-word-regexp): Don't use shy group.
(rfc2047-decode-region): Follow rfc2047-encoded-word-regexp change.
(rfc2047-parse-and-decode): Ditto.
(rfc2047-decode): Treat the ascii coding-system as raw-text by
default.
2005-03-25 Lars Magne Ingebrigtsen <larsi@gnus.org>
* lisp/gnus/rfc2047.el (rfc2047-encode-encoded-words): New variable.
(rfc2047-field-value): Strip props.
(rfc2047-encode-message-header): Disabled header folding -- not
all headers can be folded, and this should be done by the message
composition mode. Probably. I think.
(rfc2047-encodable-p): Say that =? needs encoding.
(rfc2047-encode-region): Encode =? strings.
2005-03-25 Jesper Harder <harder@ifa.au.dk>
* lisp/gnus/rfc2047.el (rfc2047-encoded-word-regexp): Support RFC 2231
language tags; remove unnecessary '+'. Reported by Stefan Wiens
<s.wi@gmx.net>.
(rfc2047-decode-string): Don't cons a string unnecessarily.
(rfc2047-parse-and-decode, rfc2047-decode): Use a character for
the encoding to avoid consing a string.
(rfc2047-decode): Use mm-subst-char-in-string instead of
mm-replace-chars-in-string.
2005-03-25 TSUCHIYA Masatoshi <tsuchiya@namazu.org>
* lisp/gnus/rfc2047.el (rfc2047-encode): Use uppercase letters to specify
encodings of MIME-encoded words, in order to improve
interoperability with several broken MUAs.
2005-03-21 Reiner Steib <Reiner.Steib@gmx.de>
* lisp/gnus/gnus-srvr.el (gnus-browse-select-group): Add NUMBER argument and
pass it to `gnus-browse-read-group'.
(gnus-browse-read-group): Add NUMBER argument and pass it to
`gnus-group-read-ephemeral-group'.
* lisp/gnus/gnus-group.el (gnus-group-read-ephemeral-group): Add NUMBER
argument and pass it to `gnus-group-read-group'.
2005-03-19 Aidan Kehoe <kehoea@parhasard.net>
* lisp/gnus/mm-util.el (mm-xemacs-find-mime-charset): Only call
mm-xemacs-find-mime-charset-1 if we have the mule feature
available at runtime.
2005-03-25 Katsumi Yamaoka <yamaoka@jpl.org>
* man/emacs-mime.texi (Display Customization): Markup fixes.
(rfc2047): Update.
2005-03-23 Reiner Steib <Reiner.Steib@gmx.de>
* man/gnus-faq.texi: Replaced with auto-generated version.
Diffstat (limited to 'lisp/gnus')
| -rw-r--r-- | lisp/gnus/ChangeLog | 91 | ||||
| -rw-r--r-- | lisp/gnus/gnus-group.el | 6 | ||||
| -rw-r--r-- | lisp/gnus/gnus-srvr.el | 19 | ||||
| -rw-r--r-- | lisp/gnus/message.el | 3 | ||||
| -rw-r--r-- | lisp/gnus/mm-util.el | 30 | ||||
| -rw-r--r-- | lisp/gnus/rfc2047.el | 641 |
6 files changed, 546 insertions, 244 deletions
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog index 3c7c3d3d5c4..fe2fcab6643 100644 --- a/lisp/gnus/ChangeLog +++ b/lisp/gnus/ChangeLog | |||
| @@ -1,3 +1,94 @@ | |||
| 1 | 2005-03-25 Katsumi Yamaoka <yamaoka@jpl.org> | ||
| 2 | |||
| 3 | * message.el (message-resend): Bind rfc2047-encode-encoded-words. | ||
| 4 | |||
| 5 | * mm-util.el (mm-replace-in-string): New function. | ||
| 6 | (mm-xemacs-find-mime-charset-1): Ignore errors while loading | ||
| 7 | latin-unity, which cannot be used with XEmacs 21.1. | ||
| 8 | |||
| 9 | * rfc2047.el (rfc2047-encode-function-alist): Rename from | ||
| 10 | rfc2047-encoding-function-alist in order to avoid conflicting with | ||
| 11 | the old version. | ||
| 12 | (rfc2047-encode-message-header): Remove useless goto-char. | ||
| 13 | (rfc2047-encodable-p): Don't move point. | ||
| 14 | (rfc2047-syntax-table): Treat `(' and `)' as is. | ||
| 15 | (rfc2047-encode-region): Concatenate words containing non-ASCII | ||
| 16 | characters in structured fields; don't encode space-delimited | ||
| 17 | ASCII words even in unstructured fields; don't break words at | ||
| 18 | char-category boundaries; encode encoded words in structured | ||
| 19 | fields; treat text within parentheses as special; show the | ||
| 20 | original text when error has occurred; move point to the end of | ||
| 21 | the region after encoding, suggested by IRIE Tetsuya | ||
| 22 | <irie@t.email.ne.jp>; treat backslash-quoted characters as | ||
| 23 | non-special; check carefully whether to encode special characters; | ||
| 24 | fix some kind of misconfigured headers; signal a real error if | ||
| 25 | debug-on-quit or debug-on-error is non-nil; don't infloop, | ||
| 26 | suggested by Hiroshi Fujishima <pooh@nature.tsukuba.ac.jp>; assume | ||
| 27 | the close parenthesis may be included in the encoded word; encode | ||
| 28 | bogus delimiters. | ||
| 29 | (rfc2047-encode-string): Use mm-with-multibyte-buffer. | ||
| 30 | (rfc2047-encode-max-chars): New variable. | ||
| 31 | (rfc2047-encode-1): New function. | ||
| 32 | (rfc2047-encode): Use it; encode text so that it occupies the | ||
| 33 | maximum width within 76-column; work correctly on Q encoding for | ||
| 34 | iso-2022-* charsets; fold the line before encoding; don't append a | ||
| 35 | space if the encoded word includes close parenthesis. | ||
| 36 | (rfc2047-fold-region): Use existing whitespace for LWSP; make it | ||
| 37 | sure not to break a line just after the header name. | ||
| 38 | (rfc2047-b-encode-region): Remove. | ||
| 39 | (rfc2047-b-encode-string): New function. | ||
| 40 | (rfc2047-q-encode-region): Remove. | ||
| 41 | (rfc2047-q-encode-string): New function. | ||
| 42 | (rfc2047-encode-parameter): New function. | ||
| 43 | (rfc2047-encoded-word-regexp): Don't use shy group. | ||
| 44 | (rfc2047-decode-region): Follow rfc2047-encoded-word-regexp change. | ||
| 45 | (rfc2047-parse-and-decode): Ditto. | ||
| 46 | (rfc2047-decode): Treat the ascii coding-system as raw-text by | ||
| 47 | default. | ||
| 48 | |||
| 49 | 2005-03-25 Lars Magne Ingebrigtsen <larsi@gnus.org> | ||
| 50 | |||
| 51 | * rfc2047.el (rfc2047-encode-encoded-words): New variable. | ||
| 52 | (rfc2047-field-value): Strip props. | ||
| 53 | (rfc2047-encode-message-header): Disabled header folding -- not | ||
| 54 | all headers can be folded, and this should be done by the message | ||
| 55 | composition mode. Probably. I think. | ||
| 56 | (rfc2047-encodable-p): Say that =? needs encoding. | ||
| 57 | (rfc2047-encode-region): Encode =? strings. | ||
| 58 | |||
| 59 | 2005-03-25 Jesper Harder <harder@ifa.au.dk> | ||
| 60 | |||
| 61 | * rfc2047.el (rfc2047-encoded-word-regexp): Support RFC 2231 | ||
| 62 | language tags; remove unnecessary '+'. Reported by Stefan Wiens | ||
| 63 | <s.wi@gmx.net>. | ||
| 64 | (rfc2047-decode-string): Don't cons a string unnecessarily. | ||
| 65 | (rfc2047-parse-and-decode, rfc2047-decode): Use a character for | ||
| 66 | the encoding to avoid consing a string. | ||
| 67 | (rfc2047-decode): Use mm-subst-char-in-string instead of | ||
| 68 | mm-replace-chars-in-string. | ||
| 69 | |||
| 70 | 2005-03-25 TSUCHIYA Masatoshi <tsuchiya@namazu.org> | ||
| 71 | |||
| 72 | * rfc2047.el (rfc2047-encode): Use uppercase letters to specify | ||
| 73 | encodings of MIME-encoded words, in order to improve | ||
| 74 | interoperability with several broken MUAs. | ||
| 75 | |||
| 76 | 2005-03-21 Reiner Steib <Reiner.Steib@gmx.de> | ||
| 77 | |||
| 78 | * gnus-srvr.el (gnus-browse-select-group): Add NUMBER argument and | ||
| 79 | pass it to `gnus-browse-read-group'. | ||
| 80 | (gnus-browse-read-group): Add NUMBER argument and pass it to | ||
| 81 | `gnus-group-read-ephemeral-group'. | ||
| 82 | |||
| 83 | * gnus-group.el (gnus-group-read-ephemeral-group): Add NUMBER | ||
| 84 | argument and pass it to `gnus-group-read-group'. | ||
| 85 | |||
| 86 | 2005-03-19 Aidan Kehoe <kehoea@parhasard.net> | ||
| 87 | |||
| 88 | * mm-util.el (mm-xemacs-find-mime-charset): Only call | ||
| 89 | mm-xemacs-find-mime-charset-1 if we have the mule feature | ||
| 90 | available at runtime. | ||
| 91 | |||
| 1 | 2005-03-25 Werner Lemberg <wl@gnu.org> | 92 | 2005-03-25 Werner Lemberg <wl@gnu.org> |
| 2 | 93 | ||
| 3 | * nnmaildir.el: Replace `illegal' with `invalid'. | 94 | * nnmaildir.el: Replace `illegal' with `invalid'. |
diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el index 767bdacb78e..6d38626998c 100644 --- a/lisp/gnus/gnus-group.el +++ b/lisp/gnus/gnus-group.el | |||
| @@ -1984,7 +1984,8 @@ confirmation is required." | |||
| 1984 | (defun gnus-group-read-ephemeral-group (group method &optional activate | 1984 | (defun gnus-group-read-ephemeral-group (group method &optional activate |
| 1985 | quit-config request-only | 1985 | quit-config request-only |
| 1986 | select-articles | 1986 | select-articles |
| 1987 | parameters) | 1987 | parameters |
| 1988 | number) | ||
| 1988 | "Read GROUP from METHOD as an ephemeral group. | 1989 | "Read GROUP from METHOD as an ephemeral group. |
| 1989 | If ACTIVATE, request the group first. | 1990 | If ACTIVATE, request the group first. |
| 1990 | If QUIT-CONFIG, use that window configuration when exiting from the | 1991 | If QUIT-CONFIG, use that window configuration when exiting from the |
| @@ -1992,6 +1993,7 @@ ephemeral group. | |||
| 1992 | If REQUEST-ONLY, don't actually read the group; just request it. | 1993 | If REQUEST-ONLY, don't actually read the group; just request it. |
| 1993 | If SELECT-ARTICLES, only select those articles. | 1994 | If SELECT-ARTICLES, only select those articles. |
| 1994 | If PARAMETERS, use those as the group parameters. | 1995 | If PARAMETERS, use those as the group parameters. |
| 1996 | If NUMBER, fetch this number of articles. | ||
| 1995 | 1997 | ||
| 1996 | Return the name of the group if selection was successful." | 1998 | Return the name of the group if selection was successful." |
| 1997 | (interactive | 1999 | (interactive |
| @@ -2039,7 +2041,7 @@ Return the name of the group if selection was successful." | |||
| 2039 | (when (let ((gnus-large-newsgroup gnus-large-ephemeral-newsgroup) | 2041 | (when (let ((gnus-large-newsgroup gnus-large-ephemeral-newsgroup) |
| 2040 | (gnus-fetch-old-headers | 2042 | (gnus-fetch-old-headers |
| 2041 | gnus-fetch-old-ephemeral-headers)) | 2043 | gnus-fetch-old-ephemeral-headers)) |
| 2042 | (gnus-group-read-group t t group select-articles)) | 2044 | (gnus-group-read-group (or number t) t group select-articles)) |
| 2043 | group) | 2045 | group) |
| 2044 | ;;(error nil) | 2046 | ;;(error nil) |
| 2045 | (quit | 2047 | (quit |
diff --git a/lisp/gnus/gnus-srvr.el b/lisp/gnus/gnus-srvr.el index e8c7d354145..7b3c033fddb 100644 --- a/lisp/gnus/gnus-srvr.el +++ b/lisp/gnus/gnus-srvr.el | |||
| @@ -851,23 +851,26 @@ buffer. | |||
| 851 | (setq buffer-read-only t) | 851 | (setq buffer-read-only t) |
| 852 | (gnus-run-hooks 'gnus-browse-mode-hook)) | 852 | (gnus-run-hooks 'gnus-browse-mode-hook)) |
| 853 | 853 | ||
| 854 | (defun gnus-browse-read-group (&optional no-article) | 854 | (defun gnus-browse-read-group (&optional no-article number) |
| 855 | "Enter the group at the current line." | 855 | "Enter the group at the current line. |
| 856 | (interactive) | 856 | If NUMBER, fetch this number of articles." |
| 857 | (interactive "P") | ||
| 857 | (let ((group (gnus-browse-group-name))) | 858 | (let ((group (gnus-browse-group-name))) |
| 858 | (if (or (not (gnus-get-info group)) | 859 | (if (or (not (gnus-get-info group)) |
| 859 | (gnus-ephemeral-group-p group)) | 860 | (gnus-ephemeral-group-p group)) |
| 860 | (unless (gnus-group-read-ephemeral-group | 861 | (unless (gnus-group-read-ephemeral-group |
| 861 | group gnus-browse-current-method nil | 862 | group gnus-browse-current-method nil |
| 862 | (cons (current-buffer) 'browse)) | 863 | (cons (current-buffer) 'browse) |
| 864 | nil nil nil number) | ||
| 863 | (error "Couldn't enter %s" group)) | 865 | (error "Couldn't enter %s" group)) |
| 864 | (unless (gnus-group-read-group nil no-article group) | 866 | (unless (gnus-group-read-group nil no-article group) |
| 865 | (error "Couldn't enter %s" group))))) | 867 | (error "Couldn't enter %s" group))))) |
| 866 | 868 | ||
| 867 | (defun gnus-browse-select-group () | 869 | (defun gnus-browse-select-group (&optional number) |
| 868 | "Select the current group." | 870 | "Select the current group. |
| 869 | (interactive) | 871 | If NUMBER, fetch this number of articles." |
| 870 | (gnus-browse-read-group 'no)) | 872 | (interactive "P") |
| 873 | (gnus-browse-read-group 'no number)) | ||
| 871 | 874 | ||
| 872 | (defun gnus-browse-next-group (n) | 875 | (defun gnus-browse-next-group (n) |
| 873 | "Go to the next group." | 876 | "Go to the next group." |
diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index de56fe2be96..9edbce2620e 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el | |||
| @@ -6364,7 +6364,8 @@ Optional DIGEST will use digest to forward." | |||
| 6364 | (replace-match "X-From-Line: ")) | 6364 | (replace-match "X-From-Line: ")) |
| 6365 | ;; Send it. | 6365 | ;; Send it. |
| 6366 | (let ((message-inhibit-body-encoding t) | 6366 | (let ((message-inhibit-body-encoding t) |
| 6367 | message-required-mail-headers) | 6367 | message-required-mail-headers |
| 6368 | rfc2047-encode-encoded-words) | ||
| 6368 | (message-send-mail)) | 6369 | (message-send-mail)) |
| 6369 | (kill-buffer (current-buffer))) | 6370 | (kill-buffer (current-buffer))) |
| 6370 | (message "Resending message to %s...done" address))) | 6371 | (message "Resending message to %s...done" address))) |
diff --git a/lisp/gnus/mm-util.el b/lisp/gnus/mm-util.el index 5b4200d6d52..3be6444f18f 100644 --- a/lisp/gnus/mm-util.el +++ b/lisp/gnus/mm-util.el | |||
| @@ -86,6 +86,32 @@ | |||
| 86 | (multibyte-char-to-unibyte . identity)))) | 86 | (multibyte-char-to-unibyte . identity)))) |
| 87 | 87 | ||
| 88 | (eval-and-compile | 88 | (eval-and-compile |
| 89 | (cond | ||
| 90 | ((fboundp 'replace-in-string) | ||
| 91 | (defalias 'mm-replace-in-string 'replace-in-string)) | ||
| 92 | ((fboundp 'replace-regexp-in-string) | ||
| 93 | (defun mm-replace-in-string (string regexp newtext &optional literal) | ||
| 94 | "Replace all matches for REGEXP with NEWTEXT in STRING. | ||
| 95 | If LITERAL is non-nil, insert NEWTEXT literally. Return a new | ||
| 96 | string containing the replacements. | ||
| 97 | |||
| 98 | This is a compatibility function for different Emacsen." | ||
| 99 | (replace-regexp-in-string regexp newtext string nil literal))) | ||
| 100 | (t | ||
| 101 | (defun mm-replace-in-string (string regexp newtext &optional literal) | ||
| 102 | "Replace all matches for REGEXP with NEWTEXT in STRING. | ||
| 103 | If LITERAL is non-nil, insert NEWTEXT literally. Return a new | ||
| 104 | string containing the replacements. | ||
| 105 | |||
| 106 | This is a compatibility function for different Emacsen." | ||
| 107 | (let ((start 0) tail) | ||
| 108 | (while (string-match regexp string start) | ||
| 109 | (setq tail (- (length string) (match-end 0))) | ||
| 110 | (setq string (replace-match newtext nil literal string)) | ||
| 111 | (setq start (- (length string) tail)))) | ||
| 112 | string)))) | ||
| 113 | |||
| 114 | (eval-and-compile | ||
| 89 | (defalias 'mm-char-or-char-int-p | 115 | (defalias 'mm-char-or-char-int-p |
| 90 | (cond | 116 | (cond |
| 91 | ((fboundp 'char-or-char-int-p) 'char-or-char-int-p) | 117 | ((fboundp 'char-or-char-int-p) 'char-or-char-int-p) |
| @@ -606,7 +632,7 @@ But this is very much a corner case, so don't worry about it." | |||
| 606 | 632 | ||
| 607 | ;; Load the Latin Unity library, if available. | 633 | ;; Load the Latin Unity library, if available. |
| 608 | (when (and (not (featurep 'latin-unity)) (locate-library "latin-unity")) | 634 | (when (and (not (featurep 'latin-unity)) (locate-library "latin-unity")) |
| 609 | (require 'latin-unity)) | 635 | (ignore-errors (require 'latin-unity))) |
| 610 | 636 | ||
| 611 | ;; Now, can we use it? | 637 | ;; Now, can we use it? |
| 612 | (if (featurep 'latin-unity) | 638 | (if (featurep 'latin-unity) |
| @@ -651,7 +677,7 @@ But this is very much a corner case, so don't worry about it." | |||
| 651 | 677 | ||
| 652 | (defmacro mm-xemacs-find-mime-charset (begin end) | 678 | (defmacro mm-xemacs-find-mime-charset (begin end) |
| 653 | (when (featurep 'xemacs) | 679 | (when (featurep 'xemacs) |
| 654 | `(mm-xemacs-find-mime-charset-1 ,begin ,end))) | 680 | `(and (featurep 'mule) (mm-xemacs-find-mime-charset-1 ,begin ,end)))) |
| 655 | 681 | ||
| 656 | (defun mm-find-mime-charset-region (b e &optional hack-charsets) | 682 | (defun mm-find-mime-charset-region (b e &optional hack-charsets) |
| 657 | "Return the MIME charsets needed to encode the region between B and E. | 683 | "Return the MIME charsets needed to encode the region between B and E. |
diff --git a/lisp/gnus/rfc2047.el b/lisp/gnus/rfc2047.el index 6086f422abd..538e22e0f88 100644 --- a/lisp/gnus/rfc2047.el +++ b/lisp/gnus/rfc2047.el | |||
| @@ -119,12 +119,15 @@ The values can be: | |||
| 119 | Valid encodings are nil, `Q' and `B'. These indicate binary (no) encoding, | 119 | Valid encodings are nil, `Q' and `B'. These indicate binary (no) encoding, |
| 120 | quoted-printable and base64 respectively.") | 120 | quoted-printable and base64 respectively.") |
| 121 | 121 | ||
| 122 | (defvar rfc2047-encoding-function-alist | 122 | (defvar rfc2047-encode-function-alist |
| 123 | '((Q . rfc2047-q-encode-region) | 123 | '((Q . rfc2047-q-encode-string) |
| 124 | (B . rfc2047-b-encode-region) | 124 | (B . rfc2047-b-encode-string) |
| 125 | (nil . ignore)) | 125 | (nil . identity)) |
| 126 | "Alist of RFC2047 encodings to encoding functions.") | 126 | "Alist of RFC2047 encodings to encoding functions.") |
| 127 | 127 | ||
| 128 | (defvar rfc2047-encode-encoded-words t | ||
| 129 | "Whether encoded words should be encoded again.") | ||
| 130 | |||
| 128 | ;;; | 131 | ;;; |
| 129 | ;;; Functions for encoding RFC2047 messages | 132 | ;;; Functions for encoding RFC2047 messages |
| 130 | ;;; | 133 | ;;; |
| @@ -166,7 +169,7 @@ This is either `base64' or `quoted-printable'." | |||
| 166 | (save-restriction | 169 | (save-restriction |
| 167 | (rfc2047-narrow-to-field) | 170 | (rfc2047-narrow-to-field) |
| 168 | (re-search-forward ":[ \t\n]*" nil t) | 171 | (re-search-forward ":[ \t\n]*" nil t) |
| 169 | (buffer-substring (point) (point-max))))) | 172 | (buffer-substring-no-properties (point) (point-max))))) |
| 170 | 173 | ||
| 171 | (defvar rfc2047-encoding-type 'address-mime | 174 | (defvar rfc2047-encoding-type 'address-mime |
| 172 | "The type of encoding done by `rfc2047-encode-region'. | 175 | "The type of encoding done by `rfc2047-encode-region'. |
| @@ -186,24 +189,25 @@ Should be called narrowed to the head of the message." | |||
| 186 | (rfc2047-narrow-to-field) | 189 | (rfc2047-narrow-to-field) |
| 187 | (if (not (rfc2047-encodable-p)) | 190 | (if (not (rfc2047-encodable-p)) |
| 188 | (prog1 | 191 | (prog1 |
| 189 | (if (and (eq (mm-body-7-or-8) '8bit) | 192 | (if (and (eq (mm-body-7-or-8) '8bit) |
| 190 | (mm-multibyte-p) | 193 | (mm-multibyte-p) |
| 191 | (mm-coding-system-p | 194 | (mm-coding-system-p |
| 192 | (car message-posting-charset))) | 195 | (car message-posting-charset))) |
| 193 | ;; 8 bit must be decoded. | 196 | ;; 8 bit must be decoded. |
| 194 | (mm-encode-coding-region | 197 | (mm-encode-coding-region |
| 195 | (point-min) (point-max) | 198 | (point-min) (point-max) |
| 196 | (mm-charset-to-coding-system | 199 | (mm-charset-to-coding-system |
| 197 | (car message-posting-charset)))) | 200 | (car message-posting-charset)))) |
| 198 | ;; No encoding necessary, but folding is nice | 201 | ;; No encoding necessary, but folding is nice |
| 199 | (rfc2047-fold-region | 202 | (when nil |
| 200 | (save-excursion | 203 | (rfc2047-fold-region |
| 201 | (goto-char (point-min)) | 204 | (save-excursion |
| 202 | (skip-chars-forward "^:") | 205 | (goto-char (point-min)) |
| 203 | (when (looking-at ": ") | 206 | (skip-chars-forward "^:") |
| 204 | (forward-char 2)) | 207 | (when (looking-at ": ") |
| 205 | (point)) | 208 | (forward-char 2)) |
| 206 | (point-max))) | 209 | (point)) |
| 210 | (point-max)))) | ||
| 207 | ;; We found something that may perhaps be encoded. | 211 | ;; We found something that may perhaps be encoded. |
| 208 | (setq method nil | 212 | (setq method nil |
| 209 | alist rfc2047-header-encoding-alist) | 213 | alist rfc2047-header-encoding-alist) |
| @@ -213,7 +217,6 @@ Should be called narrowed to the head of the message." | |||
| 213 | (eq (car elem) t)) | 217 | (eq (car elem) t)) |
| 214 | (setq alist nil | 218 | (setq alist nil |
| 215 | method (cdr elem)))) | 219 | method (cdr elem)))) |
| 216 | (goto-char (point-min)) | ||
| 217 | (re-search-forward "^[^:]+: *" nil t) | 220 | (re-search-forward "^[^:]+: *" nil t) |
| 218 | (cond | 221 | (cond |
| 219 | ((eq method 'address-mime) | 222 | ((eq method 'address-mime) |
| @@ -267,8 +270,13 @@ The buffer may be narrowed." | |||
| 267 | (require 'message) ; for message-posting-charset | 270 | (require 'message) ; for message-posting-charset |
| 268 | (let ((charsets | 271 | (let ((charsets |
| 269 | (mm-find-mime-charset-region (point-min) (point-max)))) | 272 | (mm-find-mime-charset-region (point-min) (point-max)))) |
| 270 | (and charsets | 273 | (goto-char (point-min)) |
| 271 | (not (equal charsets (list (car message-posting-charset))))))) | 274 | (or (and rfc2047-encode-encoded-words |
| 275 | (prog1 | ||
| 276 | (search-forward "=?" nil t) | ||
| 277 | (goto-char (point-min)))) | ||
| 278 | (and charsets | ||
| 279 | (not (equal charsets (list (car message-posting-charset)))))))) | ||
| 272 | 280 | ||
| 273 | ;; Use this syntax table when parsing into regions that may need | 281 | ;; Use this syntax table when parsing into regions that may need |
| 274 | ;; encoding. Double quotes are string delimiters, backslash is | 282 | ;; encoding. Double quotes are string delimiters, backslash is |
| @@ -292,8 +300,8 @@ The buffer may be narrowed." | |||
| 292 | table)))) | 300 | table)))) |
| 293 | (modify-syntax-entry ?\\ "\\" table) | 301 | (modify-syntax-entry ?\\ "\\" table) |
| 294 | (modify-syntax-entry ?\" "\"" table) | 302 | (modify-syntax-entry ?\" "\"" table) |
| 295 | (modify-syntax-entry ?\( "." table) | 303 | (modify-syntax-entry ?\( "(" table) |
| 296 | (modify-syntax-entry ?\) "." table) | 304 | (modify-syntax-entry ?\) ")" table) |
| 297 | (modify-syntax-entry ?\< "." table) | 305 | (modify-syntax-entry ?\< "." table) |
| 298 | (modify-syntax-entry ?\> "." table) | 306 | (modify-syntax-entry ?\> "." table) |
| 299 | (modify-syntax-entry ?\[ "." table) | 307 | (modify-syntax-entry ?\[ "." table) |
| @@ -310,183 +318,341 @@ By default, the region is treated as containing RFC2822 addresses. | |||
| 310 | Dynamically bind `rfc2047-encoding-type' to change that." | 318 | Dynamically bind `rfc2047-encoding-type' to change that." |
| 311 | (save-restriction | 319 | (save-restriction |
| 312 | (narrow-to-region b e) | 320 | (narrow-to-region b e) |
| 313 | (if (eq 'mime rfc2047-encoding-type) | 321 | (let ((encodable-regexp (if rfc2047-encode-encoded-words |
| 314 | ;; Simple case. Treat as single word after any initial ASCII | 322 | "[^\000-\177]+\\|=\\?" |
| 315 | ;; part and before any tailing ASCII part. The leading ASCII | 323 | "[^\000-\177]+")) |
| 316 | ;; is relevant for instance in Subject headers with `Re:' for | 324 | start ; start of current token |
| 317 | ;; interoperability with non-MIME clients, and we might as | 325 | end begin csyntax |
| 318 | ;; well avoid the tail too. | 326 | ;; Whether there's an encoded word before the current token, |
| 319 | (progn | 327 | ;; either immediately or separated by space. |
| 320 | (goto-char (point-min)) | 328 | last-encoded |
| 321 | ;; Does it need encoding? | 329 | (orig-text (buffer-substring-no-properties b e))) |
| 322 | (skip-chars-forward "\000-\177") | 330 | (if (eq 'mime rfc2047-encoding-type) |
| 323 | (unless (eobp) | 331 | ;; Simple case. Continuous words in which all those contain |
| 324 | (skip-chars-backward "^ \n") ; beginning of space-delimited word | 332 | ;; non-ASCII characters are encoded collectively. Encoding |
| 325 | (rfc2047-encode (point) (progn | 333 | ;; ASCII words, including `Re:' used in Subject headers, is |
| 326 | (goto-char e) | 334 | ;; avoided for interoperability with non-MIME clients and |
| 327 | (skip-chars-backward "\000-\177") | 335 | ;; for making it easy to find keywords. |
| 328 | (skip-chars-forward "^ \n") | 336 | (progn |
| 329 | ;; end of space-delimited word | 337 | (goto-char (point-min)) |
| 330 | (point))))) | 338 | (while (progn (skip-chars-forward " \t\n") |
| 331 | ;; `address-mime' case -- take care of quoted words, comments. | 339 | (not (eobp))) |
| 332 | (with-syntax-table rfc2047-syntax-table | 340 | (setq start (point)) |
| 333 | (let ((start) ; start of current token | 341 | (while (and (looking-at "[ \t\n]*\\([^ \t\n]+\\)") |
| 334 | end ; end of current token | 342 | (progn |
| 335 | ;; Whether there's an encoded word before the current | 343 | (setq end (match-end 0)) |
| 336 | ;; token, either immediately or separated by space. | 344 | (re-search-forward encodable-regexp end t))) |
| 337 | last-encoded) | 345 | (goto-char end)) |
| 346 | (if (> (point) start) | ||
| 347 | (rfc2047-encode start (point)) | ||
| 348 | (goto-char end)))) | ||
| 349 | ;; `address-mime' case -- take care of quoted words, comments. | ||
| 350 | (with-syntax-table rfc2047-syntax-table | ||
| 338 | (goto-char (point-min)) | 351 | (goto-char (point-min)) |
| 339 | (condition-case nil ; in case of unbalanced quotes | 352 | (condition-case err ; in case of unbalanced quotes |
| 340 | ;; Look for rfc2822-style: sequences of atoms, quoted | 353 | ;; Look for rfc2822-style: sequences of atoms, quoted |
| 341 | ;; strings, specials, whitespace. (Specials mustn't be | 354 | ;; strings, specials, whitespace. (Specials mustn't be |
| 342 | ;; encoded.) | 355 | ;; encoded.) |
| 343 | (while (not (eobp)) | 356 | (while (not (eobp)) |
| 344 | (setq start (point)) | ||
| 345 | ;; Skip whitespace. | 357 | ;; Skip whitespace. |
| 346 | (unless (= 0 (skip-chars-forward " \t\n")) | 358 | (skip-chars-forward " \t\n") |
| 347 | (setq start (point))) | 359 | (setq start (point)) |
| 348 | (cond | 360 | (cond |
| 349 | ((not (char-after))) ; eob | 361 | ((not (char-after))) ; eob |
| 350 | ;; else token start | 362 | ;; else token start |
| 351 | ((eq ?\" (char-syntax (char-after))) | 363 | ((eq ?\" (setq csyntax (char-syntax (char-after)))) |
| 352 | ;; Quoted word. | 364 | ;; Quoted word. |
| 353 | (forward-sexp) | 365 | (forward-sexp) |
| 354 | (setq end (point)) | 366 | (setq end (point)) |
| 355 | ;; Does it need encoding? | 367 | ;; Does it need encoding? |
| 356 | (goto-char start) | 368 | (goto-char start) |
| 357 | (skip-chars-forward "\000-\177" end) | 369 | (if (re-search-forward encodable-regexp end 'move) |
| 358 | (if (= end (point)) | 370 | ;; It needs encoding. Strip the quotes first, |
| 359 | (setq last-encoded nil) | 371 | ;; since encoded words can't occur in quotes. |
| 360 | ;; It needs encoding. Strip the quotes first, | 372 | (progn |
| 361 | ;; since encoded words can't occur in quotes. | 373 | (goto-char end) |
| 362 | (goto-char end) | 374 | (delete-backward-char 1) |
| 363 | (delete-backward-char 1) | 375 | (goto-char start) |
| 364 | (goto-char start) | 376 | (delete-char 1) |
| 365 | (delete-char 1) | 377 | (when last-encoded |
| 366 | (when last-encoded | 378 | ;; There was a preceding quoted word. We need |
| 367 | ;; There was a preceding quoted word. We need | 379 | ;; to include any separating whitespace in this |
| 368 | ;; to include any separating whitespace in this | 380 | ;; word to avoid it getting lost. |
| 369 | ;; word to avoid it getting lost. | 381 | (skip-chars-backward " \t") |
| 370 | (skip-chars-backward " \t") | 382 | ;; A space is needed between the encoded words. |
| 371 | ;; A space is needed between the encoded words. | 383 | (insert ? ) |
| 372 | (insert ? ) | 384 | (setq start (point) |
| 373 | (setq start (point) | 385 | end (1+ end))) |
| 374 | end (1+ end))) | 386 | ;; Adjust the end position for the deleted quotes. |
| 375 | ;; Adjust the end position for the deleted quotes. | 387 | (rfc2047-encode start (- end 2)) |
| 376 | (rfc2047-encode start (- end 2)) | 388 | (setq last-encoded t)) ; record that it was encoded |
| 377 | (setq last-encoded t))) ; record that it was encoded | 389 | (setq last-encoded nil))) |
| 378 | ((eq ?. (char-syntax (char-after))) | 390 | ((eq ?. csyntax) |
| 379 | ;; Skip other delimiters, but record that they've | 391 | ;; Skip other delimiters, but record that they've |
| 380 | ;; potentially separated quoted words. | 392 | ;; potentially separated quoted words. |
| 381 | (forward-char) | 393 | (forward-char) |
| 382 | (setq last-encoded nil)) | 394 | (setq last-encoded nil)) |
| 395 | ((eq ?\) csyntax) | ||
| 396 | (error "Unbalanced parentheses")) | ||
| 397 | ((eq ?\( csyntax) | ||
| 398 | ;; Look for the end of parentheses. | ||
| 399 | (forward-list) | ||
| 400 | ;; Encode text as an unstructured field. | ||
| 401 | (let ((rfc2047-encoding-type 'mime)) | ||
| 402 | (rfc2047-encode-region (1+ start) (1- (point)))) | ||
| 403 | (skip-chars-forward ")")) | ||
| 383 | (t ; normal token/whitespace sequence | 404 | (t ; normal token/whitespace sequence |
| 384 | ;; Find the end. | 405 | ;; Find the end. |
| 385 | (forward-word 1) | 406 | ;; Skip one ASCII word, or encode continuous words |
| 386 | (skip-chars-backward " \t") | 407 | ;; in which all those contain non-ASCII characters. |
| 408 | (setq end nil) | ||
| 409 | (while (not (or end (eobp))) | ||
| 410 | (when (looking-at "[\000-\177]+") | ||
| 411 | (setq begin (point) | ||
| 412 | end (match-end 0)) | ||
| 413 | (when (progn | ||
| 414 | (while (and (or (re-search-forward | ||
| 415 | "[ \t\n]\\|\\Sw" end 'move) | ||
| 416 | (setq end nil)) | ||
| 417 | (eq ?\\ (char-syntax (char-before)))) | ||
| 418 | ;; Skip backslash-quoted characters. | ||
| 419 | (forward-char)) | ||
| 420 | end) | ||
| 421 | (setq end (match-beginning 0)) | ||
| 422 | (if rfc2047-encode-encoded-words | ||
| 423 | (progn | ||
| 424 | (goto-char begin) | ||
| 425 | (when (search-forward "=?" end 'move) | ||
| 426 | (goto-char (match-beginning 0)) | ||
| 427 | (setq end nil))) | ||
| 428 | (goto-char end)))) | ||
| 429 | ;; Where the value nil of `end' means there may be | ||
| 430 | ;; text to have to be encoded following the point. | ||
| 431 | ;; Otherwise, the point reached to the end of ASCII | ||
| 432 | ;; words separated by whitespace or a special char. | ||
| 433 | (unless end | ||
| 434 | (when (looking-at encodable-regexp) | ||
| 435 | (goto-char (setq begin (match-end 0))) | ||
| 436 | (while (and (looking-at "[ \t\n]+\\([^ \t\n]+\\)") | ||
| 437 | (setq end (match-end 0)) | ||
| 438 | (progn | ||
| 439 | (while (re-search-forward | ||
| 440 | encodable-regexp end t)) | ||
| 441 | (< begin (point))) | ||
| 442 | (goto-char begin) | ||
| 443 | (or (not (re-search-forward "\\Sw" end t)) | ||
| 444 | (progn | ||
| 445 | (goto-char (match-beginning 0)) | ||
| 446 | nil))) | ||
| 447 | (goto-char end)) | ||
| 448 | (when (looking-at "[^ \t\n]+") | ||
| 449 | (setq end (match-end 0)) | ||
| 450 | (if (re-search-forward "\\Sw+" end t) | ||
| 451 | ;; There are special characters better | ||
| 452 | ;; to be encoded so that MTAs may parse | ||
| 453 | ;; them safely. | ||
| 454 | (cond ((= end (point))) | ||
| 455 | ((looking-at (concat "\\sw*\\(" | ||
| 456 | encodable-regexp | ||
| 457 | "\\)")) | ||
| 458 | (setq end nil)) | ||
| 459 | (t | ||
| 460 | (goto-char (1- (match-end 0))) | ||
| 461 | (unless (= (point) (match-beginning 0)) | ||
| 462 | ;; Separate encodable text and | ||
| 463 | ;; delimiter. | ||
| 464 | (insert " ")))) | ||
| 465 | (goto-char end) | ||
| 466 | (skip-chars-forward " \t\n") | ||
| 467 | (if (and (looking-at "[^ \t\n]+") | ||
| 468 | (string-match encodable-regexp | ||
| 469 | (match-string 0))) | ||
| 470 | (setq end nil) | ||
| 471 | (goto-char end))))))) | ||
| 472 | (skip-chars-backward " \t\n") | ||
| 387 | (setq end (point)) | 473 | (setq end (point)) |
| 388 | ;; Deal with encoding and leading space as for | ||
| 389 | ;; quoted words. | ||
| 390 | (goto-char start) | 474 | (goto-char start) |
| 391 | (skip-chars-forward "\000-\177" end) | 475 | (if (re-search-forward encodable-regexp end 'move) |
| 392 | (if (= end (point)) | 476 | (progn |
| 393 | (setq last-encoded nil) | 477 | (unless (memq (char-before start) '(nil ?\t ? )) |
| 394 | (when last-encoded | 478 | (if (progn |
| 395 | (goto-char start) | 479 | (goto-char start) |
| 396 | (skip-chars-backward " \t") | 480 | (skip-chars-backward "^ \t\n") |
| 397 | (insert ? ) | 481 | (and (looking-at "\\Sw+") |
| 398 | (setq start (point) | 482 | (= (match-end 0) start))) |
| 399 | end (1+ end))) | 483 | ;; Also encode bogus delimiters. |
| 400 | (rfc2047-encode start end) | 484 | (setq start (point)) |
| 401 | (setq last-encoded t))))) | 485 | ;; Separate encodable text and delimiter. |
| 486 | (goto-char start) | ||
| 487 | (insert " ") | ||
| 488 | (setq start (1+ start) | ||
| 489 | end (1+ end)))) | ||
| 490 | (rfc2047-encode start end) | ||
| 491 | (setq last-encoded t)) | ||
| 492 | (setq last-encoded nil))))) | ||
| 402 | (error | 493 | (error |
| 403 | (error "Invalid data for rfc2047 encoding: %s" | 494 | (if (or debug-on-quit debug-on-error) |
| 404 | (buffer-substring b e))))))) | 495 | (signal (car err) (cdr err)) |
| 405 | (rfc2047-fold-region b (point)))) | 496 | (error "Invalid data for rfc2047 encoding: %s" |
| 497 | (mm-replace-in-string orig-text "[ \t\n]+" " ")))))))) | ||
| 498 | (rfc2047-fold-region b (point)) | ||
| 499 | (goto-char (point-max)))) | ||
| 406 | 500 | ||
| 407 | (defun rfc2047-encode-string (string) | 501 | (defun rfc2047-encode-string (string) |
| 408 | "Encode words in STRING. | 502 | "Encode words in STRING. |
| 409 | By default, the string is treated as containing addresses (see | 503 | By default, the string is treated as containing addresses (see |
| 410 | `rfc2047-encoding-type')." | 504 | `rfc2047-encoding-type')." |
| 411 | (with-temp-buffer | 505 | (mm-with-multibyte-buffer |
| 412 | (insert string) | 506 | (insert string) |
| 413 | (rfc2047-encode-region (point-min) (point-max)) | 507 | (rfc2047-encode-region (point-min) (point-max)) |
| 414 | (buffer-string))) | 508 | (buffer-string))) |
| 415 | 509 | ||
| 510 | (defvar rfc2047-encode-max-chars 76 | ||
| 511 | "Maximum characters of each header line that contain encoded-words. | ||
| 512 | If it is nil, encoded-words will not be folded. Too small value may | ||
| 513 | cause an error. Don't change this for no particular reason.") | ||
| 514 | |||
| 515 | (defun rfc2047-encode-1 (column string cs encoder start crest tail | ||
| 516 | &optional eword) | ||
| 517 | "Subroutine used by `rfc2047-encode'." | ||
| 518 | (cond ((string-equal string "") | ||
| 519 | (or eword "")) | ||
| 520 | ((not rfc2047-encode-max-chars) | ||
| 521 | (concat start | ||
| 522 | (funcall encoder (if cs | ||
| 523 | (mm-encode-coding-string string cs) | ||
| 524 | string)) | ||
| 525 | "?=")) | ||
| 526 | ((>= column rfc2047-encode-max-chars) | ||
| 527 | (when eword | ||
| 528 | (cond ((string-match "\n[ \t]+\\'" eword) | ||
| 529 | ;; Reomove a superfluous empty line. | ||
| 530 | (setq eword (substring eword 0 (match-beginning 0)))) | ||
| 531 | ((string-match "(+\\'" eword) | ||
| 532 | ;; Break the line before the open parenthesis. | ||
| 533 | (setq crest (concat crest (match-string 0 eword)) | ||
| 534 | eword (substring eword 0 (match-beginning 0)))))) | ||
| 535 | (rfc2047-encode-1 (length crest) string cs encoder start " " tail | ||
| 536 | (concat eword "\n" crest))) | ||
| 537 | (t | ||
| 538 | (let ((index 0) | ||
| 539 | (limit (1- (length string))) | ||
| 540 | (prev "") | ||
| 541 | next len) | ||
| 542 | (while (and prev | ||
| 543 | (<= index limit)) | ||
| 544 | (setq next (concat start | ||
| 545 | (funcall encoder | ||
| 546 | (if cs | ||
| 547 | (mm-encode-coding-string | ||
| 548 | (substring string 0 (1+ index)) | ||
| 549 | cs) | ||
| 550 | (substring string 0 (1+ index)))) | ||
| 551 | "?=") | ||
| 552 | len (+ column (length next))) | ||
| 553 | (if (> len rfc2047-encode-max-chars) | ||
| 554 | (setq next prev | ||
| 555 | prev nil) | ||
| 556 | (if (or (< index limit) | ||
| 557 | (<= (+ len (or (string-match "\n" tail) | ||
| 558 | (length tail))) | ||
| 559 | rfc2047-encode-max-chars)) | ||
| 560 | (setq prev next | ||
| 561 | index (1+ index)) | ||
| 562 | (if (string-match "\\`)+" tail) | ||
| 563 | ;; Break the line after the close parenthesis. | ||
| 564 | (setq tail (concat (substring tail 0 (match-end 0)) | ||
| 565 | "\n " | ||
| 566 | (substring tail (match-end 0))) | ||
| 567 | prev next | ||
| 568 | index (1+ index)) | ||
| 569 | (setq next prev | ||
| 570 | prev nil))))) | ||
| 571 | (if (> index limit) | ||
| 572 | (concat eword next tail) | ||
| 573 | (if (= 0 index) | ||
| 574 | (if (and eword | ||
| 575 | (string-match "(+\\'" eword)) | ||
| 576 | (setq crest (concat crest (match-string 0 eword)) | ||
| 577 | eword (substring eword 0 (match-beginning 0))) | ||
| 578 | (setq eword (concat eword next))) | ||
| 579 | (setq crest " " | ||
| 580 | eword (concat eword next))) | ||
| 581 | (when (string-match "\n[ \t]+\\'" eword) | ||
| 582 | ;; Reomove a superfluous empty line. | ||
| 583 | (setq eword (substring eword 0 (match-beginning 0)))) | ||
| 584 | (rfc2047-encode-1 (length crest) (substring string index) | ||
| 585 | cs encoder start " " tail | ||
| 586 | (concat eword "\n" crest))))))) | ||
| 587 | |||
| 416 | (defun rfc2047-encode (b e) | 588 | (defun rfc2047-encode (b e) |
| 417 | "Encode the word(s) in the region B to E. | 589 | "Encode the word(s) in the region B to E. |
| 418 | By default, the region is treated as containing addresses (see | 590 | Point moves to the end of the region." |
| 419 | `rfc2047-encoding-type')." | 591 | (let ((mime-charset (or (mm-find-mime-charset-region b e) (list 'us-ascii))) |
| 420 | (let* ((mime-charset (mm-find-mime-charset-region b e)) | 592 | cs encoding tail crest eword) |
| 421 | (cs (if (> (length mime-charset) 1) | 593 | (cond ((> (length mime-charset) 1) |
| 422 | ;; Fixme: Instead of this, try to break region into | 594 | (error "Can't rfc2047-encode `%s'" |
| 423 | ;; parts that can be encoded separately. | 595 | (buffer-substring-no-properties b e))) |
| 424 | (error "Can't rfc2047-encode `%s'" | 596 | ((= (length mime-charset) 1) |
| 425 | (buffer-substring b e)) | 597 | (setq mime-charset (car mime-charset) |
| 426 | (setq mime-charset (car mime-charset)) | 598 | cs (mm-charset-to-coding-system mime-charset)) |
| 427 | (mm-charset-to-coding-system mime-charset))) | 599 | (unless (and (mm-multibyte-p) |
| 428 | ;; Fixme: Better, calculate the number of non-ASCII | 600 | (mm-coding-system-p cs)) |
| 429 | ;; characters, at least for 8-bit charsets. | 601 | (setq cs nil)) |
| 430 | (encoding (or (cdr (assq mime-charset | 602 | (save-restriction |
| 603 | (narrow-to-region b e) | ||
| 604 | (setq encoding | ||
| 605 | (or (cdr (assq mime-charset | ||
| 431 | rfc2047-charset-encoding-alist)) | 606 | rfc2047-charset-encoding-alist)) |
| 432 | ;; For the charsets that don't have a preferred | 607 | ;; For the charsets that don't have a preferred |
| 433 | ;; encoding, choose the one that's shorter. | 608 | ;; encoding, choose the one that's shorter. |
| 434 | (save-restriction | 609 | (if (eq (rfc2047-qp-or-base64) 'base64) |
| 435 | (narrow-to-region b e) | 610 | 'B |
| 436 | (if (eq (rfc2047-qp-or-base64) 'base64) | 611 | 'Q))) |
| 437 | 'B | 612 | (widen) |
| 438 | 'Q)))) | 613 | (goto-char e) |
| 439 | (start (concat | 614 | (skip-chars-forward "^ \t\n") |
| 440 | "=?" (downcase (symbol-name mime-charset)) "?" | 615 | ;; `tail' may contain a close parenthesis. |
| 441 | (downcase (symbol-name encoding)) "?")) | 616 | (setq tail (buffer-substring-no-properties e (point))) |
| 442 | (factor (case mime-charset | 617 | (goto-char b) |
| 443 | ((iso-8859-5 iso-8859-7 iso-8859-8 koi8-r) 1) | 618 | (setq b (point-marker) |
| 444 | ((big5 gb2312 euc-kr) 2) | 619 | e (set-marker (make-marker) e)) |
| 445 | (utf-8 4) | 620 | (rfc2047-fold-region (rfc2047-point-at-bol) b) |
| 446 | (t 8))) | 621 | (goto-char b) |
| 447 | (pre (- b (save-restriction | 622 | (skip-chars-backward "^ \t\n") |
| 448 | (widen) | 623 | (unless (= 0 (skip-chars-backward " \t")) |
| 449 | (rfc2047-point-at-bol)))) | 624 | ;; `crest' may contain whitespace and an open parenthesis. |
| 450 | ;; encoded-words must not be longer than 75 characters, | 625 | (setq crest (buffer-substring-no-properties (point) b))) |
| 451 | ;; including charset, encoding etc. This leaves us with | 626 | (setq eword (rfc2047-encode-1 |
| 452 | ;; 75 - (length start) - 2 - 2 characters. The last 2 is for | 627 | (- b (rfc2047-point-at-bol)) |
| 453 | ;; possible base64 padding. In the worst case (iso-2022-*) | 628 | (mm-replace-in-string |
| 454 | ;; each character expands to 8 bytes which is expanded by a | 629 | (buffer-substring-no-properties b e) |
| 455 | ;; factor of 4/3 by base64 encoding. | 630 | "\n\\([ \t]?\\)" "\\1") |
| 456 | (length (floor (- 75 (length start) 4) (* factor (/ 4.0 3.0)))) | 631 | cs |
| 457 | ;; Limit line length to 76 characters. | 632 | (or (cdr (assq encoding |
| 458 | (length1 (max 1 (floor (- 76 (length start) 4 pre) | 633 | rfc2047-encode-function-alist)) |
| 459 | (* factor (/ 4.0 3.0))))) | 634 | 'identity) |
| 460 | (first t)) | 635 | (concat "=?" (downcase (symbol-name mime-charset)) |
| 461 | (if mime-charset | 636 | "?" (upcase (symbol-name encoding)) "?") |
| 462 | (save-restriction | 637 | (or crest " ") |
| 463 | (narrow-to-region b e) | 638 | tail)) |
| 464 | (when (eq encoding 'B) | 639 | (delete-region (if (eq (aref eword 0) ?\n) |
| 465 | ;; break into lines before encoding | 640 | (if (bolp) |
| 466 | (goto-char (point-min)) | 641 | ;; The line was folded before encoding. |
| 467 | (while (not (eobp)) | 642 | (1- (point)) |
| 468 | (if first | 643 | (point)) |
| 469 | (progn | 644 | (goto-char b)) |
| 470 | (goto-char (min (point-max) (+ length1 (point)))) | 645 | (+ e (length tail))) |
| 471 | (setq first nil)) | 646 | ;; `eword' contains `crest' and `tail'. |
| 472 | (goto-char (min (point-max) (+ length (point))))) | 647 | (insert eword) |
| 473 | (unless (eobp) | 648 | (set-marker b nil) |
| 474 | (insert ?\n))) | 649 | (set-marker e nil) |
| 475 | (setq first t)) | 650 | (unless (or (/= 0 (length tail)) |
| 476 | (if (and (mm-multibyte-p) | 651 | (eobp) |
| 477 | (mm-coding-system-p cs)) | 652 | (looking-at "[ \t\n)]")) |
| 478 | (mm-encode-coding-region (point-min) (point-max) cs)) | 653 | (insert " ")))) |
| 479 | (funcall (cdr (assq encoding rfc2047-encoding-function-alist)) | 654 | (t |
| 480 | (point-min) (point-max)) | 655 | (goto-char e))))) |
| 481 | (goto-char (point-min)) | ||
| 482 | (while (not (eobp)) | ||
| 483 | (unless first | ||
| 484 | (insert ? )) | ||
| 485 | (setq first nil) | ||
| 486 | (insert start) | ||
| 487 | (end-of-line) | ||
| 488 | (insert "?=") | ||
| 489 | (forward-line 1)))))) | ||
| 490 | 656 | ||
| 491 | (defun rfc2047-fold-field () | 657 | (defun rfc2047-fold-field () |
| 492 | "Fold the current header field." | 658 | "Fold the current header field." |
| @@ -512,6 +678,7 @@ By default, the region is treated as containing addresses (see | |||
| 512 | (goto-char (or break qword-break)) | 678 | (goto-char (or break qword-break)) |
| 513 | (setq break nil | 679 | (setq break nil |
| 514 | qword-break nil) | 680 | qword-break nil) |
| 681 | (skip-chars-backward " \t") | ||
| 515 | (if (looking-at "[ \t]") | 682 | (if (looking-at "[ \t]") |
| 516 | (insert ?\n) | 683 | (insert ?\n) |
| 517 | (insert "\n ")) | 684 | (insert "\n ")) |
| @@ -533,10 +700,8 @@ By default, the region is treated as containing addresses (see | |||
| 533 | (forward-char 1)) | 700 | (forward-char 1)) |
| 534 | ((memq (char-after) '(? ?\t)) | 701 | ((memq (char-after) '(? ?\t)) |
| 535 | (skip-chars-forward " \t") | 702 | (skip-chars-forward " \t") |
| 536 | (if first | 703 | (unless first ;; Don't break just after the header name. |
| 537 | ;; Don't break just after the header name. | 704 | (setq break (point)))) |
| 538 | (setq first nil) | ||
| 539 | (setq break (1- (point))))) | ||
| 540 | ((not break) | 705 | ((not break) |
| 541 | (if (not (looking-at "=\\?[^=]")) | 706 | (if (not (looking-at "=\\?[^=]")) |
| 542 | (if (eq (char-after) ?=) | 707 | (if (eq (char-after) ?=) |
| @@ -547,15 +712,17 @@ By default, the region is treated as containing addresses (see | |||
| 547 | (setq qword-break (point))) | 712 | (setq qword-break (point))) |
| 548 | (skip-chars-forward "^ \t\n\r"))) | 713 | (skip-chars-forward "^ \t\n\r"))) |
| 549 | (t | 714 | (t |
| 550 | (skip-chars-forward "^ \t\n\r")))) | 715 | (skip-chars-forward "^ \t\n\r"))) |
| 716 | (setq first nil)) | ||
| 551 | (when (and (or break qword-break) | 717 | (when (and (or break qword-break) |
| 552 | (> (- (point) bol) 76)) | 718 | (> (- (point) bol) 76)) |
| 553 | (goto-char (or break qword-break)) | 719 | (goto-char (or break qword-break)) |
| 554 | (setq break nil | 720 | (setq break nil |
| 555 | qword-break nil) | 721 | qword-break nil) |
| 556 | (if (looking-at "[ \t]") | 722 | (if (or (> 0 (skip-chars-backward " \t")) |
| 557 | (insert ?\n) | 723 | (looking-at "[ \t]")) |
| 558 | (insert "\n ")) | 724 | (insert ?\n) |
| 725 | (insert "\n ")) | ||
| 559 | (setq bol (1- (point))) | 726 | (setq bol (1- (point))) |
| 560 | ;; Don't break before the first non-LWSP characters. | 727 | ;; Don't break before the first non-LWSP characters. |
| 561 | (skip-chars-forward " \t") | 728 | (skip-chars-forward " \t") |
| @@ -590,48 +757,48 @@ By default, the region is treated as containing addresses (see | |||
| 590 | (setq eol (rfc2047-point-at-eol)) | 757 | (setq eol (rfc2047-point-at-eol)) |
| 591 | (forward-line 1))))) | 758 | (forward-line 1))))) |
| 592 | 759 | ||
| 593 | (defun rfc2047-b-encode-region (b e) | 760 | (defun rfc2047-b-encode-string (string) |
| 594 | "Base64-encode the header contained in region B to E." | 761 | "Base64-encode the header contained in STRING." |
| 595 | (save-restriction | 762 | (base64-encode-string string t)) |
| 596 | (narrow-to-region (goto-char b) e) | 763 | |
| 597 | (while (not (eobp)) | 764 | (defun rfc2047-q-encode-string (string) |
| 598 | (base64-encode-region (point) (progn (end-of-line) (point)) t) | 765 | "Quoted-printable-encode the header in STRING." |
| 599 | (if (and (bolp) (eolp)) | 766 | (mm-with-unibyte-buffer |
| 600 | (delete-backward-char 1)) | 767 | (insert string) |
| 601 | (forward-line)))) | 768 | (quoted-printable-encode-region |
| 602 | 769 | (point-min) (point-max) nil | |
| 603 | (defun rfc2047-q-encode-region (b e) | 770 | ;; = (\075), _ (\137), ? (\077) are used in the encoded word. |
| 604 | "Quoted-printable-encode the header in region B to E." | 771 | ;; Avoid using 8bit characters. |
| 605 | (save-excursion | 772 | ;; This list excludes `especials' (see the RFC2047 syntax), |
| 606 | (save-restriction | 773 | ;; meaning that some characters in non-structured fields will |
| 607 | (narrow-to-region (goto-char b) e) | 774 | ;; get encoded when they con't need to be. The following is |
| 608 | (let ((bol (save-restriction | 775 | ;; what it used to be. |
| 609 | (widen) | 776 | ;;; ;; Equivalent to "^\000-\007\011\013\015-\037\200-\377=_?" |
| 610 | (rfc2047-point-at-bol)))) | 777 | ;;; "\010\012\014\040-\074\076\100-\136\140-\177") |
| 611 | (quoted-printable-encode-region | 778 | "-\b\n\f !#-'*+0-9A-Z\\^`-~\d") |
| 612 | b e nil | 779 | (subst-char-in-region (point-min) (point-max) ? ?_) |
| 613 | ;; = (\075), _ (\137), ? (\077) are used in the encoded word. | 780 | (buffer-string))) |
| 614 | ;; Avoid using 8bit characters. | 781 | |
| 615 | ;; This list excludes `especials' (see the RFC2047 syntax), | 782 | (defun rfc2047-encode-parameter (param value) |
| 616 | ;; meaning that some characters in non-structured fields will | 783 | "Return and PARAM=VALUE string encoded in the RFC2047-like style. |
| 617 | ;; get encoded when they con't need to be. The following is | 784 | This is a replacement for the `rfc2231-encode-string' function. |
| 618 | ;; what it used to be. | 785 | |
| 619 | ;;; ;; Equivalent to "^\000-\007\011\013\015-\037\200-\377=_?" | 786 | When attaching files as MIME parts, we should use the RFC2231 encoding |
| 620 | ;;; "\010\012\014\040-\074\076\100-\136\140-\177") | 787 | to specify the file names containing non-ASCII characters. However, |
| 621 | "-\b\n\f !#-'*+0-9A-Z\\^`-~\d") | 788 | many mail softwares don't support it in practice and recipients won't |
| 622 | (subst-char-in-region (point-min) (point-max) ? ?_) | 789 | be able to extract files with correct names. Instead, the RFC2047-like |
| 623 | ;; The size of QP encapsulation is about 20, so set limit to | 790 | encoding is acceptable generally. This function provides the very |
| 624 | ;; 56=76-20. | 791 | RFC2047-like encoding, resigning to such a regrettable trend. To use |
| 625 | (unless (< (- (point-max) (point-min)) 56) | 792 | it, put the following line in your ~/.gnus.el file: |
| 626 | ;; Don't break if it could fit in one line. | 793 | |
| 627 | ;; Let rfc2047-encode-region break it later. | 794 | \(defalias 'mail-header-encode-parameter 'rfc2047-encode-parameter) |
| 628 | (goto-char (1+ (point-min))) | 795 | " |
| 629 | (while (and (not (bobp)) (not (eobp))) | 796 | (let* ((rfc2047-encoding-type 'mime) |
| 630 | (goto-char (min (point-max) (+ 56 bol))) | 797 | (rfc2047-encode-max-chars nil) |
| 631 | (search-backward "=" (- (point) 2) t) | 798 | (string (rfc2047-encode-string value))) |
| 632 | (unless (or (bobp) (eobp)) | 799 | (if (string-match (concat "[" ietf-drums-tspecials "]") string) |
| 633 | (insert ?\n) | 800 | (format "%s=%S" param string) |
| 634 | (setq bol (point))))))))) | 801 | (concat param "=" string)))) |
| 635 | 802 | ||
| 636 | ;;; | 803 | ;;; |
| 637 | ;;; Functions for decoding RFC2047 messages | 804 | ;;; Functions for decoding RFC2047 messages |
| @@ -639,8 +806,8 @@ By default, the region is treated as containing addresses (see | |||
| 639 | 806 | ||
| 640 | (eval-and-compile | 807 | (eval-and-compile |
| 641 | (defconst rfc2047-encoded-word-regexp | 808 | (defconst rfc2047-encoded-word-regexp |
| 642 | "=\\?\\([^][\000-\040()<>@,\;:\\\"/?.=]+\\)\\?\\(B\\|Q\\)\ | 809 | "=\\?\\([^][\000-\040()<>@,\;:*\\\"/?.=]+\\)\\(\\*[^?]+\\)?\ |
| 643 | \\?\\([!->@-~ +]*\\)\\?=")) | 810 | \\?\\(B\\|Q\\)\\?\\([!->@-~ ]*\\)\\?=")) |
| 644 | 811 | ||
| 645 | (defvar rfc2047-quote-decoded-words-containing-tspecials nil | 812 | (defvar rfc2047-quote-decoded-words-containing-tspecials nil |
| 646 | "If non-nil, quote decoded words containing special characters.") | 813 | "If non-nil, quote decoded words containing special characters.") |
| @@ -671,7 +838,7 @@ By default, the region is treated as containing addresses (see | |||
| 671 | "\\(\n?[ \t]\\)+" | 838 | "\\(\n?[ \t]\\)+" |
| 672 | "\\(" rfc2047-encoded-word-regexp "\\)")) | 839 | "\\(" rfc2047-encoded-word-regexp "\\)")) |
| 673 | nil t) | 840 | nil t) |
| 674 | (delete-region (goto-char (match-end 1)) (match-beginning 6))) | 841 | (delete-region (goto-char (match-end 1)) (match-beginning 7))) |
| 675 | ;; Decode the encoded words. | 842 | ;; Decode the encoded words. |
| 676 | (setq b (goto-char (point-min))) | 843 | (setq b (goto-char (point-min))) |
| 677 | (while (re-search-forward rfc2047-encoded-word-regexp nil t) | 844 | (while (re-search-forward rfc2047-encoded-word-regexp nil t) |
| @@ -774,7 +941,20 @@ By default, the region is treated as containing addresses (see | |||
| 774 | mail-parse-charset | 941 | mail-parse-charset |
| 775 | (not (eq mail-parse-charset 'us-ascii)) | 942 | (not (eq mail-parse-charset 'us-ascii)) |
| 776 | (not (eq mail-parse-charset 'gnus-decoded))) | 943 | (not (eq mail-parse-charset 'gnus-decoded))) |
| 777 | (mm-decode-coding-string string mail-parse-charset) | 944 | ;; `decode-coding-string' in Emacs offers a third optional |
| 945 | ;; arg NOCOPY to avoid consing a new string if the decoding | ||
| 946 | ;; is "trivial". Unfortunately it currently doesn't | ||
| 947 | ;; consider anything else than a `nil' coding system | ||
| 948 | ;; trivial. | ||
| 949 | ;; `rfc2047-decode-string' is called multiple times for each | ||
| 950 | ;; article during summary buffer generation, and we really | ||
| 951 | ;; want to avoid unnecessary consing. So we bypass | ||
| 952 | ;; `decode-coding-string' if the string is purely ASCII. | ||
| 953 | (if (and (fboundp 'detect-coding-string) | ||
| 954 | ;; string is purely ASCII | ||
| 955 | (eq (detect-coding-string string t) 'undecided)) | ||
| 956 | string | ||
| 957 | (mm-decode-coding-string string mail-parse-charset)) | ||
| 778 | (mm-string-as-multibyte string))))) | 958 | (mm-string-as-multibyte string))))) |
| 779 | 959 | ||
| 780 | (defun rfc2047-parse-and-decode (word) | 960 | (defun rfc2047-parse-and-decode (word) |
| @@ -787,8 +967,8 @@ decodable." | |||
| 787 | (condition-case nil | 967 | (condition-case nil |
| 788 | (rfc2047-decode | 968 | (rfc2047-decode |
| 789 | (match-string 1 word) | 969 | (match-string 1 word) |
| 790 | (upcase (match-string 2 word)) | 970 | (string-to-char (match-string 3 word)) |
| 791 | (match-string 3 word)) | 971 | (match-string 4 word)) |
| 792 | (error word)) | 972 | (error word)) |
| 793 | word))) ; un-decodable | 973 | word))) ; un-decodable |
| 794 | 974 | ||
| @@ -809,7 +989,7 @@ decodable." | |||
| 809 | 989 | ||
| 810 | (defun rfc2047-decode (charset encoding string) | 990 | (defun rfc2047-decode (charset encoding string) |
| 811 | "Decode STRING from the given MIME CHARSET in the given ENCODING. | 991 | "Decode STRING from the given MIME CHARSET in the given ENCODING. |
| 812 | Valid ENCODINGs are \"B\" and \"Q\". | 992 | Valid ENCODINGs are the characters \"B\" and \"Q\". |
| 813 | If your Emacs implementation can't decode CHARSET, return nil." | 993 | If your Emacs implementation can't decode CHARSET, return nil." |
| 814 | (if (stringp charset) | 994 | (if (stringp charset) |
| 815 | (setq charset (intern (downcase charset)))) | 995 | (setq charset (intern (downcase charset)))) |
| @@ -824,18 +1004,17 @@ If your Emacs implementation can't decode CHARSET, return nil." | |||
| 824 | (memq 'gnus-unknown mail-parse-ignored-charsets)) | 1004 | (memq 'gnus-unknown mail-parse-ignored-charsets)) |
| 825 | (setq cs (mm-charset-to-coding-system mail-parse-charset))) | 1005 | (setq cs (mm-charset-to-coding-system mail-parse-charset))) |
| 826 | (when cs | 1006 | (when cs |
| 827 | (when (and (eq cs 'ascii) | 1007 | (when (eq cs 'ascii) |
| 828 | mail-parse-charset) | 1008 | (setq cs (or mail-parse-charset 'raw-text))) |
| 829 | (setq cs mail-parse-charset)) | ||
| 830 | (mm-decode-coding-string | 1009 | (mm-decode-coding-string |
| 831 | (cond | 1010 | (cond |
| 832 | ((equal "B" encoding) | 1011 | ((char-equal ?B encoding) |
| 833 | (base64-decode-string | 1012 | (base64-decode-string |
| 834 | (rfc2047-pad-base64 string))) | 1013 | (rfc2047-pad-base64 string))) |
| 835 | ((equal "Q" encoding) | 1014 | ((char-equal ?Q encoding) |
| 836 | (quoted-printable-decode-string | 1015 | (quoted-printable-decode-string |
| 837 | (mm-replace-chars-in-string string ?_ ? ))) | 1016 | (mm-subst-char-in-string ?_ ? string t))) |
| 838 | (t (error "Invalid encoding: %s" encoding))) | 1017 | (t (error "Invalid encoding: %c" encoding))) |
| 839 | cs)))) | 1018 | cs)))) |
| 840 | 1019 | ||
| 841 | (provide 'rfc2047) | 1020 | (provide 'rfc2047) |