Mercurial > emacs
annotate lisp/gnus/rfc2047.el @ 37678:ebec0594dece
(compile-files): Redirect output of chmod to
/dev/null.
| author | Gerd Moellmann <gerd@gnu.org> |
|---|---|
| date | Fri, 11 May 2001 10:53:56 +0000 |
| parents | b9c371244b90 |
| children | a26d9b55abb6 |
| rev | line source |
|---|---|
| 31717 | 1 ;;; rfc2047.el --- Functions for encoding and decoding rfc2047 messages |
| 2 ;; Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. | |
| 3 | |
| 4 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org> | |
| 5 ;; MORIOKA Tomohiko <morioka@jaist.ac.jp> | |
| 6 ;; This file is part of GNU Emacs. | |
| 7 | |
| 8 ;; GNU Emacs is free software; you can redistribute it and/or modify | |
| 9 ;; it under the terms of the GNU General Public License as published by | |
| 10 ;; the Free Software Foundation; either version 2, or (at your option) | |
| 11 ;; any later version. | |
| 12 | |
| 13 ;; GNU Emacs is distributed in the hope that it will be useful, | |
| 14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 ;; GNU General Public License for more details. | |
| 17 | |
| 18 ;; You should have received a copy of the GNU General Public License | |
| 19 ;; along with GNU Emacs; see the file COPYING. If not, write to the | |
| 20 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
| 21 ;; Boston, MA 02111-1307, USA. | |
| 22 | |
| 23 ;;; Commentary: | |
| 24 | |
| 34674 | 25 ;; RFC 2047 is "MIME (Multipurpose Internet Mail Extensions) Part |
| 26 ;; Three: Message Header Extensions for Non-ASCII Text". | |
| 27 | |
| 31717 | 28 ;;; Code: |
| 29 | |
| 33304 | 30 (eval-when-compile (require 'cl)) |
| 31717 | 31 |
| 32 (require 'qp) | |
| 33 (require 'mm-util) | |
| 34 (require 'ietf-drums) | |
| 35 (require 'mail-prsvr) | |
| 33304 | 36 (require 'base64) |
| 37 ;; Fixme: Avoid this (for gnus-point-at-...) mm dependence on gnus. | |
| 38 (require 'gnus-util) | |
| 39 (autoload 'mm-body-7-or-8 "mm-bodies") | |
|
33127
eca95f9d7f05
(base64): Require unconditionally.
Dave Love <fx@gnu.org>
parents:
31764
diff
changeset
|
40 |
| 31717 | 41 (defvar rfc2047-header-encoding-alist |
| 42 '(("Newsgroups" . nil) | |
| 43 ("Message-ID" . nil) | |
| 44 (t . mime)) | |
| 45 "*Header/encoding method alist. | |
| 46 The list is traversed sequentially. The keys can either be | |
| 33304 | 47 header regexps or t. |
| 31717 | 48 |
| 49 The values can be: | |
| 50 | |
| 51 1) nil, in which case no encoding is done; | |
| 52 2) `mime', in which case the header will be encoded according to RFC2047; | |
| 53 3) a charset, in which case it will be encoded as that charset; | |
| 54 4) `default', in which case the field will be encoded as the rest | |
| 55 of the article.") | |
| 56 | |
| 57 (defvar rfc2047-charset-encoding-alist | |
| 58 '((us-ascii . nil) | |
| 59 (iso-8859-1 . Q) | |
| 60 (iso-8859-2 . Q) | |
| 61 (iso-8859-3 . Q) | |
| 62 (iso-8859-4 . Q) | |
| 63 (iso-8859-5 . B) | |
| 64 (koi8-r . B) | |
| 65 (iso-8859-7 . Q) | |
| 66 (iso-8859-8 . Q) | |
| 67 (iso-8859-9 . Q) | |
| 33304 | 68 (iso-8859-14 . Q) |
| 69 (iso-8859-15 . Q) | |
| 31717 | 70 (iso-2022-jp . B) |
| 71 (iso-2022-kr . B) | |
| 72 (gb2312 . B) | |
|
35838
53eebdb81828
2001-02-01 ShengHuo ZHU <zsh@cs.rochester.edu>
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
35453
diff
changeset
|
73 (big5 . B) |
|
53eebdb81828
2001-02-01 ShengHuo ZHU <zsh@cs.rochester.edu>
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
35453
diff
changeset
|
74 (cn-big5 . B) |
| 31717 | 75 (cn-gb . B) |
| 76 (cn-gb-2312 . B) | |
| 77 (euc-kr . B) | |
| 78 (iso-2022-jp-2 . B) | |
| 79 (iso-2022-int-1 . B)) | |
| 80 "Alist of MIME charsets to RFC2047 encodings. | |
| 81 Valid encodings are nil, `Q' and `B'.") | |
| 82 | |
| 83 (defvar rfc2047-encoding-function-alist | |
| 84 '((Q . rfc2047-q-encode-region) | |
| 85 (B . rfc2047-b-encode-region) | |
| 86 (nil . ignore)) | |
| 87 "Alist of RFC2047 encodings to encoding functions.") | |
| 88 | |
| 89 (defvar rfc2047-q-encoding-alist | |
| 33304 | 90 '(("\\(From\\|Cc\\|To\\|Bcc\||Reply-To\\):" . "-A-Za-z0-9!*+/") |
| 31764 | 91 ;; = (\075), _ (\137), ? (\077) are used in the encoded word. |
|
35985
b9c371244b90
(rfc2047-fold-region): Don't forward-char at EOB.
Dave Love <fx@gnu.org>
parents:
35838
diff
changeset
|
92 ;; Avoid using 8bit characters. |
| 31764 | 93 ;; Equivalent to "^\000-\007\011\013\015-\037\200-\377=_?" |
| 94 ("." . "\010\012\014\040-\074\076\100-\136\140-\177")) | |
| 31717 | 95 "Alist of header regexps and valid Q characters.") |
| 96 | |
| 97 ;;; | |
| 98 ;;; Functions for encoding RFC2047 messages | |
| 99 ;;; | |
| 100 | |
| 101 (defun rfc2047-narrow-to-field () | |
| 102 "Narrow the buffer to the header on the current line." | |
| 103 (beginning-of-line) | |
| 104 (narrow-to-region | |
| 105 (point) | |
| 106 (progn | |
| 107 (forward-line 1) | |
| 108 (if (re-search-forward "^[^ \n\t]" nil t) | |
| 109 (progn | |
| 110 (beginning-of-line) | |
| 111 (point)) | |
| 112 (point-max)))) | |
| 113 (goto-char (point-min))) | |
| 114 | |
| 115 (defun rfc2047-encode-message-header () | |
| 116 "Encode the message header according to `rfc2047-header-encoding-alist'. | |
| 117 Should be called narrowed to the head of the message." | |
| 118 (interactive "*") | |
| 119 (save-excursion | |
| 120 (goto-char (point-min)) | |
| 121 (let (alist elem method) | |
| 122 (while (not (eobp)) | |
| 123 (save-restriction | |
| 124 (rfc2047-narrow-to-field) | |
| 125 (if (not (rfc2047-encodable-p)) | |
| 126 (if (and (eq (mm-body-7-or-8) '8bit) | |
| 127 (mm-multibyte-p) | |
| 128 (mm-coding-system-p | |
| 129 (car message-posting-charset))) | |
| 130 ;; 8 bit must be decoded. | |
| 131 ;; Is message-posting-charset a coding system? | |
| 33304 | 132 (mm-encode-coding-region |
| 133 (point-min) (point-max) | |
| 31717 | 134 (car message-posting-charset))) |
| 135 ;; We found something that may perhaps be encoded. | |
| 136 (setq method nil | |
| 137 alist rfc2047-header-encoding-alist) | |
| 138 (while (setq elem (pop alist)) | |
| 139 (when (or (and (stringp (car elem)) | |
| 140 (looking-at (car elem))) | |
| 141 (eq (car elem) t)) | |
| 142 (setq alist nil | |
| 143 method (cdr elem)))) | |
| 144 (cond | |
| 145 ((eq method 'mime) | |
| 33304 | 146 (rfc2047-encode-region (point-min) (point-max))) |
| 31717 | 147 ((eq method 'default) |
| 148 (if (and (featurep 'mule) | |
|
33815
61c7f3065929
(rfc2047-encode-message-header): Don't encode if
Dave Love <fx@gnu.org>
parents:
33304
diff
changeset
|
149 (if (boundp 'default-enable-multibyte-characters) |
|
61c7f3065929
(rfc2047-encode-message-header): Don't encode if
Dave Love <fx@gnu.org>
parents:
33304
diff
changeset
|
150 default-enable-multibyte-characters) |
| 31717 | 151 mail-parse-charset) |
| 33304 | 152 (mm-encode-coding-region (point-min) (point-max) |
| 31717 | 153 mail-parse-charset))) |
| 154 ((mm-coding-system-p method) | |
|
33815
61c7f3065929
(rfc2047-encode-message-header): Don't encode if
Dave Love <fx@gnu.org>
parents:
33304
diff
changeset
|
155 (if (and (featurep 'mule) |
|
61c7f3065929
(rfc2047-encode-message-header): Don't encode if
Dave Love <fx@gnu.org>
parents:
33304
diff
changeset
|
156 (if (boundp 'default-enable-multibyte-characters) |
|
61c7f3065929
(rfc2047-encode-message-header): Don't encode if
Dave Love <fx@gnu.org>
parents:
33304
diff
changeset
|
157 default-enable-multibyte-characters)) |
| 31717 | 158 (mm-encode-coding-region (point-min) (point-max) method))) |
| 159 ;; Hm. | |
| 160 (t))) | |
| 161 (goto-char (point-max))))))) | |
| 162 | |
|
35985
b9c371244b90
(rfc2047-fold-region): Don't forward-char at EOB.
Dave Love <fx@gnu.org>
parents:
35838
diff
changeset
|
163 ;; Fixme: This, and the require below may not be the Right Thing, but |
|
b9c371244b90
(rfc2047-fold-region): Don't forward-char at EOB.
Dave Love <fx@gnu.org>
parents:
35838
diff
changeset
|
164 ;; should be safe just before release. -- fx 2001-02-08 |
|
b9c371244b90
(rfc2047-fold-region): Don't forward-char at EOB.
Dave Love <fx@gnu.org>
parents:
35838
diff
changeset
|
165 (eval-when-compile (defvar message-posting-charset)) |
|
b9c371244b90
(rfc2047-fold-region): Don't forward-char at EOB.
Dave Love <fx@gnu.org>
parents:
35838
diff
changeset
|
166 |
| 33304 | 167 (defun rfc2047-encodable-p () |
| 168 "Return non-nil if any characters in current buffer need encoding in headers. | |
| 169 The buffer may be narrowed." | |
|
35985
b9c371244b90
(rfc2047-fold-region): Don't forward-char at EOB.
Dave Love <fx@gnu.org>
parents:
35838
diff
changeset
|
170 (require 'message) ; for message-posting-charset |
| 31717 | 171 (let ((charsets |
| 172 (mapcar | |
| 173 'mm-mime-charset | |
| 174 (mm-find-charset-region (point-min) (point-max)))) | |
| 175 (cs (list 'us-ascii (car message-posting-charset))) | |
| 176 found) | |
| 177 (while charsets | |
| 178 (unless (memq (pop charsets) cs) | |
| 179 (setq found t))) | |
| 180 found)) | |
| 181 | |
| 182 (defun rfc2047-dissect-region (b e) | |
| 183 "Dissect the region between B and E into words." | |
| 33304 | 184 (let ((word-chars "-A-Za-z0-9!*+/") |
| 185 ;; Not using ietf-drums-specials-token makes life simple. | |
| 186 mail-parse-mule-charset | |
| 187 words point current | |
| 188 result word) | |
| 31717 | 189 (save-restriction |
| 190 (narrow-to-region b e) | |
| 191 (goto-char (point-min)) | |
| 33304 | 192 (skip-chars-forward "\000-\177") |
| 31717 | 193 (while (not (eobp)) |
| 33304 | 194 (setq point (point)) |
| 195 (skip-chars-backward word-chars b) | |
| 196 (unless (eq b (point)) | |
| 197 (push (cons (buffer-substring b (point)) nil) words)) | |
| 198 (setq b (point)) | |
| 199 (goto-char point) | |
| 200 (setq current (mm-charset-after)) | |
| 201 (forward-char 1) | |
| 202 (skip-chars-forward word-chars) | |
| 203 (while (and (not (eobp)) | |
| 204 (eq (mm-charset-after) current)) | |
| 205 (forward-char 1) | |
| 206 (skip-chars-forward word-chars)) | |
| 207 (unless (eq b (point)) | |
| 208 (push (cons (buffer-substring b (point)) current) words)) | |
| 209 (setq b (point)) | |
| 210 (skip-chars-forward "\000-\177")) | |
| 211 (unless (eq b (point)) | |
| 212 (push (cons (buffer-substring b (point)) nil) words))) | |
| 213 ;; merge adjacent words | |
| 214 (setq word (pop words)) | |
| 215 (while word | |
| 216 (if (and (cdr word) | |
| 217 (caar words) | |
| 218 (not (cdar words)) | |
| 219 (not (string-match "[^ \t]" (caar words)))) | |
| 220 (if (eq (cdr (nth 1 words)) (cdr word)) | |
| 221 (progn | |
| 222 (setq word (cons (concat | |
| 223 (car (nth 1 words)) (caar words) | |
| 224 (car word)) | |
| 225 (cdr word))) | |
| 226 (pop words) | |
| 227 (pop words)) | |
| 228 (push (cons (concat (caar words) (car word)) (cdr word)) | |
| 229 result) | |
| 230 (pop words) | |
| 231 (setq word (pop words))) | |
| 232 (push word result) | |
| 233 (setq word (pop words)))) | |
| 234 result)) | |
| 31717 | 235 |
| 236 (defun rfc2047-encode-region (b e) | |
|
35985
b9c371244b90
(rfc2047-fold-region): Don't forward-char at EOB.
Dave Love <fx@gnu.org>
parents:
35838
diff
changeset
|
237 "Encode all encodable words in region B to E." |
| 33304 | 238 (let ((words (rfc2047-dissect-region b e)) word) |
| 239 (save-restriction | |
| 240 (narrow-to-region b e) | |
| 241 (delete-region (point-min) (point-max)) | |
| 242 (while (setq word (pop words)) | |
| 243 (if (not (cdr word)) | |
| 244 (insert (car word)) | |
| 245 (rfc2047-fold-region (gnus-point-at-bol) (point)) | |
| 246 (goto-char (point-max)) | |
| 247 (if (> (- (point) (save-restriction | |
| 248 (widen) | |
| 249 (gnus-point-at-bol))) 76) | |
| 250 (insert "\n ")) | |
| 251 ;; Insert blank between encoded words | |
| 252 (if (eq (char-before) ?=) (insert " ")) | |
| 253 (rfc2047-encode (point) | |
| 254 (progn (insert (car word)) (point)) | |
| 255 (cdr word)))) | |
| 256 (rfc2047-fold-region (point-min) (point-max))))) | |
| 31717 | 257 |
| 258 (defun rfc2047-encode-string (string) | |
| 259 "Encode words in STRING." | |
| 260 (with-temp-buffer | |
| 261 (insert string) | |
| 262 (rfc2047-encode-region (point-min) (point-max)) | |
| 263 (buffer-string))) | |
| 264 | |
| 265 (defun rfc2047-encode (b e charset) | |
| 33304 | 266 "Encode the word in the region B to E with CHARSET." |
| 31717 | 267 (let* ((mime-charset (mm-mime-charset charset)) |
|
35838
53eebdb81828
2001-02-01 ShengHuo ZHU <zsh@cs.rochester.edu>
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
35453
diff
changeset
|
268 (cs (mm-charset-to-coding-system mime-charset)) |
| 31717 | 269 (encoding (or (cdr (assq mime-charset |
| 270 rfc2047-charset-encoding-alist)) | |
| 271 'B)) | |
| 272 (start (concat | |
| 273 "=?" (downcase (symbol-name mime-charset)) "?" | |
| 274 (downcase (symbol-name encoding)) "?")) | |
| 275 (first t)) | |
| 276 (save-restriction | |
| 277 (narrow-to-region b e) | |
| 278 (when (eq encoding 'B) | |
| 279 ;; break into lines before encoding | |
| 280 (goto-char (point-min)) | |
| 281 (while (not (eobp)) | |
| 282 (goto-char (min (point-max) (+ 15 (point)))) | |
| 283 (unless (eobp) | |
| 284 (insert "\n")))) | |
| 285 (if (and (mm-multibyte-p) | |
|
35838
53eebdb81828
2001-02-01 ShengHuo ZHU <zsh@cs.rochester.edu>
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
35453
diff
changeset
|
286 (mm-coding-system-p cs)) |
|
53eebdb81828
2001-02-01 ShengHuo ZHU <zsh@cs.rochester.edu>
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
35453
diff
changeset
|
287 (mm-encode-coding-region (point-min) (point-max) cs)) |
| 31717 | 288 (funcall (cdr (assq encoding rfc2047-encoding-function-alist)) |
| 289 (point-min) (point-max)) | |
| 290 (goto-char (point-min)) | |
| 291 (while (not (eobp)) | |
| 292 (unless first | |
| 293 (insert " ")) | |
| 294 (setq first nil) | |
| 295 (insert start) | |
| 296 (end-of-line) | |
| 297 (insert "?=") | |
| 298 (forward-line 1))))) | |
| 299 | |
| 300 (defun rfc2047-fold-region (b e) | |
|
35985
b9c371244b90
(rfc2047-fold-region): Don't forward-char at EOB.
Dave Love <fx@gnu.org>
parents:
35838
diff
changeset
|
301 "Fold long lines in region B to E." |
| 31717 | 302 (save-restriction |
| 303 (narrow-to-region b e) | |
| 304 (goto-char (point-min)) | |
| 33304 | 305 (let ((break nil) |
| 306 (qword-break nil) | |
| 307 (bol (save-restriction | |
| 308 (widen) | |
| 309 (gnus-point-at-bol)))) | |
| 31717 | 310 (while (not (eobp)) |
| 33304 | 311 (when (and (or break qword-break) (> (- (point) bol) 76)) |
| 312 (goto-char (or break qword-break)) | |
| 313 (setq break nil | |
| 314 qword-break nil) | |
|
35453
26726eff41ca
2001-01-21 ShengHuo ZHU <zsh@cs.rochester.edu>
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
34674
diff
changeset
|
315 (if (looking-at " \t") |
|
26726eff41ca
2001-01-21 ShengHuo ZHU <zsh@cs.rochester.edu>
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
34674
diff
changeset
|
316 (insert "\n") |
|
26726eff41ca
2001-01-21 ShengHuo ZHU <zsh@cs.rochester.edu>
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
34674
diff
changeset
|
317 (insert "\n ")) |
| 33304 | 318 (setq bol (1- (point))) |
| 319 ;; Don't break before the first non-LWSP characters. | |
| 320 (skip-chars-forward " \t") | |
|
35985
b9c371244b90
(rfc2047-fold-region): Don't forward-char at EOB.
Dave Love <fx@gnu.org>
parents:
35838
diff
changeset
|
321 (unless (eobp) (forward-char 1))) |
| 31717 | 322 (cond |
| 33304 | 323 ((eq (char-after) ?\n) |
| 324 (forward-char 1) | |
| 325 (setq bol (point) | |
| 326 break nil | |
| 327 qword-break nil) | |
| 328 (skip-chars-forward " \t") | |
| 329 (unless (or (eobp) (eq (char-after) ?\n)) | |
| 330 (forward-char 1))) | |
| 331 ((eq (char-after) ?\r) | |
| 332 (forward-char 1)) | |
| 31717 | 333 ((memq (char-after) '(? ?\t)) |
| 33304 | 334 (skip-chars-forward " \t") |
| 335 (setq break (1- (point)))) | |
| 336 ((not break) | |
| 337 (if (not (looking-at "=\\?[^=]")) | |
| 338 (if (eq (char-after) ?=) | |
| 339 (forward-char 1) | |
| 340 (skip-chars-forward "^ \t\n\r=")) | |
| 341 (setq qword-break (point)) | |
| 342 (skip-chars-forward "^ \t\n\r"))) | |
| 343 (t | |
| 344 (skip-chars-forward "^ \t\n\r")))) | |
| 345 (when (and (or break qword-break) (> (- (point) bol) 76)) | |
| 346 (goto-char (or break qword-break)) | |
| 347 (setq break nil | |
| 348 qword-break nil) | |
|
35453
26726eff41ca
2001-01-21 ShengHuo ZHU <zsh@cs.rochester.edu>
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
34674
diff
changeset
|
349 (if (looking-at " \t") |
|
26726eff41ca
2001-01-21 ShengHuo ZHU <zsh@cs.rochester.edu>
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
34674
diff
changeset
|
350 (insert "\n") |
|
26726eff41ca
2001-01-21 ShengHuo ZHU <zsh@cs.rochester.edu>
ShengHuo ZHU <zsh@cs.rochester.edu>
parents:
34674
diff
changeset
|
351 (insert "\n ")) |
| 33304 | 352 (setq bol (1- (point))) |
| 353 ;; Don't break before the first non-LWSP characters. | |
| 354 (skip-chars-forward " \t") | |
|
35985
b9c371244b90
(rfc2047-fold-region): Don't forward-char at EOB.
Dave Love <fx@gnu.org>
parents:
35838
diff
changeset
|
355 (unless (eobp) (forward-char 1)))))) |
| 33304 | 356 |
| 357 (defun rfc2047-unfold-region (b e) | |
|
35985
b9c371244b90
(rfc2047-fold-region): Don't forward-char at EOB.
Dave Love <fx@gnu.org>
parents:
35838
diff
changeset
|
358 "Unfold lines in region B to E." |
| 33304 | 359 (save-restriction |
| 360 (narrow-to-region b e) | |
| 361 (goto-char (point-min)) | |
| 362 (let ((bol (save-restriction | |
| 363 (widen) | |
| 364 (gnus-point-at-bol))) | |
| 365 (eol (gnus-point-at-eol)) | |
| 366 leading) | |
| 367 (forward-line 1) | |
| 368 (while (not (eobp)) | |
| 369 (looking-at "[ \t]*") | |
| 370 (setq leading (- (match-end 0) (match-beginning 0))) | |
| 371 (if (< (- (gnus-point-at-eol) bol leading) 76) | |
| 372 (progn | |
| 373 (goto-char eol) | |
| 374 (delete-region eol (progn | |
| 375 (skip-chars-forward "[ \t\n\r]+") | |
| 376 (1- (point))))) | |
| 377 (setq bol (gnus-point-at-bol))) | |
| 378 (setq eol (gnus-point-at-eol)) | |
| 379 (forward-line 1))))) | |
| 31717 | 380 |
| 381 (defun rfc2047-b-encode-region (b e) | |
| 33304 | 382 "Base64-encode the header contained in region B to E." |
| 31717 | 383 (save-restriction |
| 384 (narrow-to-region (goto-char b) e) | |
| 385 (while (not (eobp)) | |
| 386 (base64-encode-region (point) (progn (end-of-line) (point)) t) | |
| 387 (if (and (bolp) (eolp)) | |
| 388 (delete-backward-char 1)) | |
| 389 (forward-line)))) | |
| 390 | |
| 391 (defun rfc2047-q-encode-region (b e) | |
| 33304 | 392 "Quoted-printable-encode the header in region B to E." |
| 31717 | 393 (save-excursion |
| 394 (save-restriction | |
| 395 (narrow-to-region (goto-char b) e) | |
| 33304 | 396 (let ((alist rfc2047-q-encoding-alist) |
| 397 (bol (save-restriction | |
| 398 (widen) | |
| 399 (gnus-point-at-bol)))) | |
| 31717 | 400 (while alist |
| 401 (when (looking-at (caar alist)) | |
| 402 (quoted-printable-encode-region b e nil (cdar alist)) | |
| 403 (subst-char-in-region (point-min) (point-max) ? ?_) | |
| 404 (setq alist nil)) | |
| 405 (pop alist)) | |
| 33304 | 406 ;; The size of QP encapsulation is about 20, so set limit to |
| 407 ;; 56=76-20. | |
| 408 (unless (< (- (point-max) (point-min)) 56) | |
| 409 ;; Don't break if it could fit in one line. | |
| 410 ;; Let rfc2047-encode-region break it later. | |
| 411 (goto-char (1+ (point-min))) | |
| 412 (while (and (not (bobp)) (not (eobp))) | |
| 413 (goto-char (min (point-max) (+ 56 bol))) | |
| 414 (search-backward "=" (- (point) 2) t) | |
| 415 (unless (or (bobp) (eobp)) | |
| 416 (insert "\n") | |
| 417 (setq bol (point))))))))) | |
| 31717 | 418 |
| 419 ;;; | |
| 420 ;;; Functions for decoding RFC2047 messages | |
| 421 ;;; | |
| 422 | |
| 423 (defvar rfc2047-encoded-word-regexp | |
| 424 "=\\?\\([^][\000-\040()<>@,\;:\\\"/?.=]+\\)\\?\\(B\\|Q\\)\\?\\([!->@-~ +]+\\)\\?=") | |
| 425 | |
| 426 (defun rfc2047-decode-region (start end) | |
| 427 "Decode MIME-encoded words in region between START and END." | |
| 428 (interactive "r") | |
| 429 (let ((case-fold-search t) | |
| 430 b e) | |
| 431 (save-excursion | |
| 432 (save-restriction | |
| 433 (narrow-to-region start end) | |
| 434 (goto-char (point-min)) | |
| 435 ;; Remove whitespace between encoded words. | |
| 436 (while (re-search-forward | |
| 437 (concat "\\(" rfc2047-encoded-word-regexp "\\)" | |
| 438 "\\(\n?[ \t]\\)+" | |
| 439 "\\(" rfc2047-encoded-word-regexp "\\)") | |
| 440 nil t) | |
| 441 (delete-region (goto-char (match-end 1)) (match-beginning 6))) | |
| 442 ;; Decode the encoded words. | |
| 443 (setq b (goto-char (point-min))) | |
| 444 (while (re-search-forward rfc2047-encoded-word-regexp nil t) | |
| 445 (setq e (match-beginning 0)) | |
| 446 (insert (rfc2047-parse-and-decode | |
| 447 (prog1 | |
| 448 (match-string 0) | |
| 449 (delete-region (match-beginning 0) (match-end 0))))) | |
| 450 (when (and (mm-multibyte-p) | |
| 451 mail-parse-charset | |
| 452 (not (eq mail-parse-charset 'gnus-decoded))) | |
| 453 (mm-decode-coding-region b e mail-parse-charset)) | |
| 454 (setq b (point))) | |
| 455 (when (and (mm-multibyte-p) | |
| 456 mail-parse-charset | |
| 457 (not (eq mail-parse-charset 'us-ascii)) | |
| 458 (not (eq mail-parse-charset 'gnus-decoded))) | |
| 33304 | 459 (mm-decode-coding-region b (point-max) mail-parse-charset)) |
| 460 (rfc2047-unfold-region (point-min) (point-max)))))) | |
| 31717 | 461 |
| 462 (defun rfc2047-decode-string (string) | |
| 463 "Decode the quoted-printable-encoded STRING and return the results." | |
| 464 (let ((m (mm-multibyte-p))) | |
| 465 (with-temp-buffer | |
| 466 (when m | |
| 467 (mm-enable-multibyte)) | |
| 468 (insert string) | |
| 469 (inline | |
| 470 (rfc2047-decode-region (point-min) (point-max))) | |
| 471 (buffer-string)))) | |
| 472 | |
| 473 (defun rfc2047-parse-and-decode (word) | |
| 474 "Decode WORD and return it if it is an encoded word. | |
| 475 Return WORD if not." | |
| 476 (if (not (string-match rfc2047-encoded-word-regexp word)) | |
| 477 word | |
| 478 (or | |
| 479 (condition-case nil | |
| 480 (rfc2047-decode | |
| 481 (match-string 1 word) | |
| 482 (upcase (match-string 2 word)) | |
| 483 (match-string 3 word)) | |
| 484 (error word)) | |
| 485 word))) | |
| 486 | |
| 487 (defun rfc2047-decode (charset encoding string) | |
| 33304 | 488 "Decode STRING from the given MIME CHARSET in the given ENCODING. |
| 31717 | 489 Valid ENCODINGs are \"B\" and \"Q\". |
| 33304 | 490 If your Emacs implementation can't decode CHARSET, return nil." |
| 31717 | 491 (if (stringp charset) |
| 492 (setq charset (intern (downcase charset)))) | |
| 33304 | 493 (if (or (not charset) |
| 31717 | 494 (eq 'gnus-all mail-parse-ignored-charsets) |
| 495 (memq 'gnus-all mail-parse-ignored-charsets) | |
| 496 (memq charset mail-parse-ignored-charsets)) | |
| 497 (setq charset mail-parse-charset)) | |
| 498 (let ((cs (mm-charset-to-coding-system charset))) | |
| 33304 | 499 (if (and (not cs) charset |
| 31717 | 500 (listp mail-parse-ignored-charsets) |
| 501 (memq 'gnus-unknown mail-parse-ignored-charsets)) | |
| 502 (setq cs (mm-charset-to-coding-system mail-parse-charset))) | |
| 503 (when cs | |
| 504 (when (and (eq cs 'ascii) | |
| 505 mail-parse-charset) | |
| 506 (setq cs mail-parse-charset)) | |
| 33304 | 507 ;; Ensure unibyte result in Emacs 20. |
| 508 (let (default-enable-multibyte-characters) | |
| 509 (with-temp-buffer | |
| 510 (mm-decode-coding-string | |
| 511 (cond | |
| 512 ((equal "B" encoding) | |
| 513 (base64-decode-string string)) | |
| 514 ((equal "Q" encoding) | |
| 515 (quoted-printable-decode-string | |
| 516 (mm-replace-chars-in-string string ?_ ? ))) | |
| 517 (t (error "Invalid encoding: %s" encoding))) | |
| 518 cs)))))) | |
| 31717 | 519 |
| 520 (provide 'rfc2047) | |
| 521 | |
| 522 ;;; rfc2047.el ends here |
