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.
21 (defconst ew-quoting-char ?+)
22 (defconst ew-quoting-chars-regexp
23 (concat (regexp-quote (char-to-string ew-quoting-char)) "*"))
25 (defconst ew-type2-regexp
26 (concat (regexp-quote "=?")
27 "\\(" ew-token-regexp "\\)"
29 "\\(" ew-token-regexp "\\)"
31 "\\(" ew-encoded-text-regexp "\\)"
37 (defun ew-quoting-char-seq (num)
38 (make-string num ew-quoting-char))
41 (ew-quote-concat str))
43 (defun ew-concat (&rest args)
44 (apply 'ew-quote-concat (mapcar 'list args)))
46 (defun ew-quote-concat (&rest args)
47 (let (result raws tmp)
53 (setq raws (cons tmp raws)))
55 ;; quoted encoded word embedding strings
56 (let (str start eword-start charset-start quoting-end eword-end l q r)
60 (while (string-match ew-encoded-word-regexp str start)
61 (setq eword-start (match-beginning 0)
62 charset-start (match-beginning 1)
63 eword-end (match-end 0))
64 (string-match ew-quoting-chars-regexp str charset-start)
65 (setq quoting-end (match-end 0)
66 l (- quoting-end charset-start)
74 (substring str start charset-start)
75 (ew-quoting-char-seq q)
76 (substring str quoting-end eword-end))))
81 (substring str start charset-start)
82 (ew-quoting-char-seq q)
83 (substring str quoting-end (1- eword-end)))))
88 (substring str start eword-start))
92 (ew-quote-sole (apply 'concat (nreverse raws)) t)
93 (substring str eword-start eword-end))
95 (setq start eword-end))
96 (setq raws (ew-rcons* raws (substring str start))
99 (error "ew-quote-concat: %s" tmp)))
100 (setq args (cdr args)))
104 (ew-quote-sole (apply 'concat (nreverse raws)) nil)))
105 (apply 'concat (nreverse result))))
107 (defun ew-quote-sole (str gen-type2)
108 (let (result (start 0) charset-start quoting-end eword-end l)
109 (while (string-match ew-encoded-word-regexp str start)
110 (setq charset-start (match-beginning 1)
111 eword-end (match-end 0))
112 (string-match ew-quoting-chars-regexp str charset-start)
113 (setq quoting-end (match-end 0)
114 l (* (- quoting-end charset-start) 3)
118 (substring str start charset-start)
119 (ew-quoting-char-seq l)
120 (substring str quoting-end eword-end))
123 (string-match ew-type2-regexp str start))
125 (setq charset-start (match-beginning 1)
126 eword-end (match-end 0))
127 (string-match ew-quoting-chars-regexp str charset-start)
128 (setq quoting-end (match-end 0)
129 l (* (- quoting-end charset-start) 3)
133 (substring str start charset-start)
134 (ew-quoting-char-seq (+ l 2))
135 (substring str quoting-end eword-end)
137 (setq result (ew-rcons* result (substring str start))))
138 (apply 'concat (nreverse result))))
140 (defun ew-quote-eword (charset encoding encoded-text)
141 (string-match ew-quoting-chars-regexp charset)
144 (ew-quoting-char-seq (* (- (match-end 0) (match-beginning 0)) 3))
145 (substring charset (match-end 0))
152 (defun ew-encode-crlf (str)
153 (if ew-remove-bare-crlf
154 (ew-crlf-line-convert str nil nil (lambda (nl) ""))
157 (end (length str)) result ms me)
158 (while (string-match "\\(\r\n\\)+" str mstart)
159 (setq ms (match-beginning 0)
162 (when (and (< me end)
163 (member (aref str me) '(?\t ?\ )))
166 (setq result (ew-rcons* result
167 (substring str sstart ms)
171 (setq result (ew-rcons* result "=0D=0A")
173 (setq result (ew-rcons* result "?="))))
175 (setq result (ew-rcons* result
176 (substring str sstart))))
177 (apply 'concat (nreverse result)))))
180 (ew-quote-concat "aaa=?A?B?C?=ccc") ;"aaa=?A?B?C?=ccc"
181 (ew-quote-concat "aaa=?+A?B?C?=ccc") ;"aaa=?+++A?B?C?=ccc"
182 (ew-quote-concat '("aaa=?A?B?C?=ccc")) ;"aaa=?A?B?C?=ccc"
183 (ew-quote-concat '("aaa=?+++A?B?C?=ccc")) ;"aaa=?+++A?B?C?=ccc"
184 (ew-quote-concat "aaa=?+A?B" "?C?=ccc") ;"aaa=?+++A?B?C?=ccc"
185 (ew-quote-concat "a=?+A?B?C?" '("=?+US-ASCII?Q?z?=")) ;"a=?+++++A?B?C?==?+US-ASCII?Q?z?="
186 (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?="
187 (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?="
188 (ew-quote-concat '("a=?++A?B?C?==?+++A?B?C?=c")) ;"a=?A?B?C?=?+A?B?C?=c"