1 ;;; quoted encoded word library
8 ;; This library provides functions operating strings embedding
9 ;; unencodable encoded words.
11 ;;;type embedded-pattern denoted-pattern
12 ;; Type-0 =?(QQQ)*A?B?C?= =?(Q)*A?B?C?=
13 ;; Type-1 =?(QQQ)*QA?B?C?= Decode =?(Q)*A?B?C?= as encoded-word
14 ;; Type-2 =?(QQQ)*QQA?B?C?= =?(Q)*A?B?C?
16 ;; Q : quoting character '+'.
17 ;; A : token. But it does not start with quoting character.
22 (defconst ew-quoting-char ?+))
23 (defconst ew-quoting-chars-regexp
25 (concat (regexp-quote (char-to-string ew-quoting-char)) "*")))
27 (defconst ew-type2-regexp
30 (concat (regexp-quote "=?")
31 "\\(" ew-token-regexp "\\)"
33 "\\(" ew-token-regexp "\\)"
35 "\\(" ew-encoded-text-regexp "\\)"
41 (defun ew-quoting-char-seq (num)
42 (make-string num ew-quoting-char))
45 (ew-quote-concat str))
47 (defun ew-concat (&rest args)
48 (apply 'ew-quote-concat (mapcar 'list args)))
50 (defun ew-quote-concat (&rest args)
51 (let (result raws tmp)
57 (setq raws (cons tmp raws)))
59 ;; quoted encoded word embedding strings
60 (let (str start eword-start charset-start quoting-end eword-end l q r)
64 (while (string-match ew-encoded-word-regexp str start)
65 (setq eword-start (match-beginning 0)
66 charset-start (match-beginning 1)
67 eword-end (match-end 0))
68 (string-match ew-quoting-chars-regexp str charset-start)
69 (setq quoting-end (match-end 0)
70 l (- quoting-end charset-start)
78 (substring str start charset-start)
79 (ew-quoting-char-seq q)
80 (substring str quoting-end eword-end))))
85 (substring str start charset-start)
86 (ew-quoting-char-seq q)
87 (substring str quoting-end (1- eword-end)))))
92 (substring str start eword-start))
96 (ew-quote-sole (apply 'concat (nreverse raws)) t)
97 (substring str eword-start eword-end))
99 (setq start eword-end))
100 (setq raws (ew-rcons* raws (substring str start))
103 (error "ew-quote-concat: %s" tmp)))
104 (setq args (cdr args)))
108 (ew-quote-sole (apply 'concat (nreverse raws)) nil)))
109 (apply 'concat (nreverse result))))
111 (defun ew-quote-sole (str gen-type2)
112 (let (result (start 0) charset-start quoting-end eword-end l)
113 (while (string-match ew-encoded-word-regexp str start)
114 (setq charset-start (match-beginning 1)
115 eword-end (match-end 0))
116 (string-match ew-quoting-chars-regexp str charset-start)
117 (setq quoting-end (match-end 0)
118 l (* (- quoting-end charset-start) 3)
122 (substring str start charset-start)
123 (ew-quoting-char-seq l)
124 (substring str quoting-end eword-end))
127 (string-match ew-type2-regexp str start))
129 (setq charset-start (match-beginning 1)
130 eword-end (match-end 0))
131 (string-match ew-quoting-chars-regexp str charset-start)
132 (setq quoting-end (match-end 0)
133 l (* (- quoting-end charset-start) 3)
137 (substring str start charset-start)
138 (ew-quoting-char-seq (+ l 2))
139 (substring str quoting-end eword-end)
141 (setq result (ew-rcons* result (substring str start))))
142 (apply 'concat (nreverse result))))
144 (defun ew-quote-eword (charset encoding encoded-text)
145 (string-match ew-quoting-chars-regexp charset)
148 (ew-quoting-char-seq (* (- (match-end 0) (match-beginning 0)) 3))
149 (substring charset (match-end 0))
156 (defun ew-encode-crlf (str)
157 (if ew-remove-bare-crlf
158 (ew-crlf-line-convert str nil nil (lambda (nl) ""))
161 (end (length str)) result ms me)
162 (while (string-match "\\(\r\n\\)+" str mstart)
163 (setq ms (match-beginning 0)
166 (when (and (< me end)
167 (member (aref str me) '(?\t ?\ )))
170 (setq result (ew-rcons* result
171 (substring str sstart ms)
175 (setq result (ew-rcons* result "=0D=0A")
177 (setq result (ew-rcons* result "?="))))
179 (setq result (ew-rcons* result
180 (substring str sstart))))
181 (apply 'concat (nreverse result)))))
184 (ew-quote-concat "aaa=?A?B?C?=ccc") ;"aaa=?A?B?C?=ccc"
185 (ew-quote-concat "aaa=?+A?B?C?=ccc") ;"aaa=?+++A?B?C?=ccc"
186 (ew-quote-concat '("aaa=?A?B?C?=ccc")) ;"aaa=?A?B?C?=ccc"
187 (ew-quote-concat '("aaa=?+++A?B?C?=ccc")) ;"aaa=?+++A?B?C?=ccc"
188 (ew-quote-concat "aaa=?+A?B" "?C?=ccc") ;"aaa=?+++A?B?C?=ccc"
189 (ew-quote-concat "a=?+A?B?C?" '("=?+US-ASCII?Q?z?=")) ;"a=?+++++A?B?C?==?+US-ASCII?Q?z?="
190 (ew-quote-concat "a=?+A?B?C?=?+D?E?F?" '("=?+US-ASCII?Q?z?=")) ;"a=?+++A?B?C?=?+D?E?F?=?+US-ASCII?Q?z?="
191 (ew-quote-concat "a=?+A?B?C?=?+D?E?F?=?+G?H?I?" '("=?+US-ASCII?Q?z?=")) ;"a=?+++A?B?C?=?+D?E?F?=?+++++G?H?I?==?+US-ASCII?Q?z?="
192 (ew-quote-concat '("a=?++A?B?C?==?+++A?B?C?=c")) ;"a=?A?B?C?=?+A?B?C?=c"