Add 2012 to FSF copyright years for Emacs files (do not merge to trunk)
[bpt/emacs.git] / lisp / gnus / qp.el
CommitLineData
c113de23 1;;; qp.el --- Quoted-Printable functions
657b2c65 2
9c1cf631 3;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
49f70d46 4;; 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
c113de23
GM
5
6;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
657b2c65
DL
7;; Keywords: mail, extensions
8
c113de23
GM
9;; This file is part of GNU Emacs.
10
5e809f55 11;; GNU Emacs is free software: you can redistribute it and/or modify
c113de23 12;; it under the terms of the GNU General Public License as published by
5e809f55
GM
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
c113de23
GM
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
5e809f55 18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
c113de23
GM
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
5e809f55 22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
c113de23
GM
23
24;;; Commentary:
25
657b2c65
DL
26;; Functions for encoding and decoding quoted-printable text as
27;; defined in RFC 2045.
c113de23 28
657b2c65 29;;; Code:
c113de23 30
b756f5b4 31(require 'mm-util)
9efa445f 32(defvar mm-use-ultra-safe-encoding)
d21a76da 33
23f87bed 34;;;###autoload
d21a76da 35(defun quoted-printable-decode-region (from to &optional coding-system)
657b2c65 36 "Decode quoted-printable in the region between FROM and TO, per RFC 2045.
d21a76da 37If CODING-SYSTEM is non-nil, decode bytes into characters with that
5c543a33
SZ
38coding-system.
39
40Interactively, you can supply the CODING-SYSTEM argument
23f87bed
MB
41with \\[universal-coding-system-argument].
42
43The CODING-SYSTEM argument is a historical hangover and is deprecated.
44QP encodes raw bytes and should be decoded into raw bytes. Decoding
45them into characters should be done separately."
753b4645
EZ
46 (interactive
47 ;; Let the user determine the coding system with "C-x RET c".
48 (list (region-beginning) (region-end) coding-system-for-read))
b5287163
DL
49 (unless (mm-coding-system-p coding-system) ; e.g. `ascii' from Gnus
50 (setq coding-system nil))
c113de23
GM
51 (save-excursion
52 (save-restriction
b5287163
DL
53 ;; RFC 2045: ``An "=" followed by two hexadecimal digits, one
54 ;; or both of which are lowercase letters in "abcdef", is
55 ;; formally illegal. A robust implementation might choose to
56 ;; recognize them as the corresponding uppercase letters.''
d21a76da 57 (let ((case-fold-search t))
c113de23 58 (narrow-to-region from to)
d21a76da
DL
59 ;; Do this in case we're called from Gnus, say, in a buffer
60 ;; which already contains non-ASCII characters which would
61 ;; then get doubly-decoded below.
62 (if coding-system
63 (mm-encode-coding-region (point-min) (point-max) coding-system))
64 (goto-char (point-min))
e4f99da7 65 (while (and (skip-chars-forward "^=")
657b2c65
DL
66 (not (eobp)))
67 (cond ((eq (char-after (1+ (point))) ?\n)
68 (delete-char 2))
69 ((looking-at "=[0-9A-F][0-9A-F]")
e9bd5782 70 (let ((byte (string-to-number (buffer-substring (1+ (point))
01c52d31
MB
71 (+ 3 (point)))
72 16)))
5f8dd322 73 (mm-insert-byte byte 1)
23f87bed 74 (delete-char 3)))
657b2c65 75 (t
23f87bed 76 (message "Malformed quoted-printable text")
d21a76da
DL
77 (forward-char)))))
78 (if coding-system
79 (mm-decode-coding-region (point-min) (point-max) coding-system)))))
c113de23 80
d21a76da 81(defun quoted-printable-decode-string (string &optional coding-system)
657b2c65 82 "Decode the quoted-printable encoded STRING and return the result.
c590ed3a 83If CODING-SYSTEM is non-nil, decode the string with coding-system.
23f87bed
MB
84Use of CODING-SYSTEM is deprecated; this function should deal with
85raw bytes, and coding conversion should be done separately."
86 (mm-with-unibyte-buffer
c113de23 87 (insert string)
d21a76da 88 (quoted-printable-decode-region (point-min) (point-max) coding-system)
c113de23
GM
89 (buffer-string)))
90
91(defun quoted-printable-encode-region (from to &optional fold class)
657b2c65 92 "Quoted-printable encode the region between FROM and TO per RFC 2045.
c113de23 93
657b2c65 94If FOLD, fold long lines at 76 characters (as required by the RFC).
e4f99da7
DL
95If CLASS is non-nil, translate the characters not matched by that
96regexp class, which is in the form expected by `skip-chars-forward'.
97You should probably avoid non-ASCII characters in this arg.
c113de23 98
657b2c65 99If `mm-use-ultra-safe-encoding' is set, fold lines unconditionally and
c113de23
GM
100encode lines starting with \"From\"."
101 (interactive "r")
657b2c65 102 (unless class
158d6e07
SZ
103 ;; Avoid using 8bit characters. = is \075.
104 ;; Equivalent to "^\000-\007\013\015-\037\200-\377="
105 (setq class "\010-\012\014\040-\074\076-\177"))
c113de23 106 (save-excursion
cd01ded9
MB
107 (goto-char from)
108 (if (re-search-forward (mm-string-to-multibyte "[^\x0-\x7f\x80-\xff]")
109 to t)
110 (error "Multibyte character in QP encoding region"))
c113de23
GM
111 (save-restriction
112 (narrow-to-region from to)
e4f99da7
DL
113 ;; Encode all the non-ascii and control characters.
114 (goto-char (point-min))
115 (while (and (skip-chars-forward class)
116 (not (eobp)))
117 (insert
118 (prog1
5f4264e5 119 ;; To unibyte in case of Emacs 23 (unicode) eight-bit.
5f8dd322 120 (format "=%02X" (mm-multibyte-char-to-unibyte (char-after)))
e4f99da7
DL
121 (delete-char 1))))
122 ;; Encode white space at the end of lines.
123 (goto-char (point-min))
124 (while (re-search-forward "[ \t]+$" nil t)
125 (goto-char (match-beginning 0))
126 (while (not (eolp))
c113de23
GM
127 (insert
128 (prog1
158d6e07 129 (format "=%02X" (char-after))
b03b1ad2
DL
130 (delete-char 1)))))
131 (let ((mm-use-ultra-safe-encoding
132 (and (boundp 'mm-use-ultra-safe-encoding)
133 mm-use-ultra-safe-encoding)))
134 (when (or fold mm-use-ultra-safe-encoding)
135 (let ((tab-width 1)) ; HTAB is one character.
136 (goto-char (point-min))
137 (while (not (eobp))
138 ;; In ultra-safe mode, encode "From " at the beginning
139 ;; of a line.
140 (when mm-use-ultra-safe-encoding
141 (if (looking-at "From ")
142 (replace-match "From=20" nil t)
143 (if (looking-at "-")
144 (replace-match "=2D" nil t))))
145 (end-of-line)
146 ;; Fold long lines.
147 (while (> (current-column) 76) ; tab-width must be 1.
148 (beginning-of-line)
149 (forward-char 75) ; 75 chars plus an "="
150 (search-backward "=" (- (point) 2) t)
151 (insert "=\n")
152 (end-of-line))
153 (forward-line))))))))
c113de23
GM
154
155(defun quoted-printable-encode-string (string)
657b2c65 156 "Encode the STRING as quoted-printable and return the result."
9c1cf631
GM
157 (with-temp-buffer
158 (if (mm-multibyte-string-p string)
159 (mm-enable-multibyte)
160 (mm-disable-multibyte))
161 (insert string)
162 (quoted-printable-encode-region (point-min) (point-max))
163 (buffer-string)))
c113de23
GM
164
165(provide 'qp)
166
cbee283d 167;; arch-tag: db89e52a-e4a1-4b69-926f-f434f04216ba
657b2c65 168;;; qp.el ends here