* Sync up to flim-1_12_5 from flim-1_12_1.
[elisp/flim.git] / ew-dec.el
1 (require 'emu)
2 (require 'ew-var)
3 (require 'ew-unit)
4 (require 'ew-scan-s)
5 (require 'ew-scan-m)
6 (require 'ew-scan-u)
7 (require 'ew-scan-n)
8 (require 'ew-parse)
9 (provide 'ew-dec)
10
11 (defvar ew-decode-field-cache-buf '())
12 (defvar ew-decode-field-cache-num 300)
13
14 (defun ew-decode-field (field-name field-body)
15   "Decode MIME RFC2047 encoded-words in a field.
16 FIELD-NAME is a name of the field such as \"To\", \"Subject\" etc. and
17 used to selecting syntax of body of the field and deciding first
18 column of body of the field.
19 FIELD-BODY is a body of the field.
20
21 If FIELD-BODY has multiple lines, each line is separated by CRLF as
22 pure network representation. Also if the result has multiple lines,
23 each line is separated by CRLF."
24   (let* ((key (ew-cons* field-name field-body
25                         (ew-dynamic-options)))
26          (tmp (assoc key ew-decode-field-cache-buf)))
27     (if tmp
28         (cdr tmp)
29       (let ((decoded (ew-decode-field-no-cache field-name field-body)))
30         (setq tmp (nthcdr ew-decode-field-cache-num
31                           ew-decode-field-cache-buf))
32         (if (cdr tmp)
33             (progn
34               (setcdr (cdr tmp) ew-decode-field-cache-buf)
35               (setq ew-decode-field-cache-buf (cdr tmp))
36               (setcdr tmp nil))
37           (setq ew-decode-field-cache-buf
38                 (cons (cons nil nil)
39                       ew-decode-field-cache-buf)))
40         (setcar (car ew-decode-field-cache-buf) key)
41         (setcdr (car ew-decode-field-cache-buf) decoded)
42         (cdar ew-decode-field-cache-buf)))))
43
44 (defun ew-analyze-field-to-decode (field-name field-body)
45   "Analyze FIELD-BODY to decode."
46   (let ((tmp (assq (intern (downcase field-name)) ew-decode-field-syntax-alist))
47         anchor)
48     (if tmp
49         (setq tmp (cdr tmp))
50       (setq tmp ew-decode-field-default-syntax))
51     (setq anchor (funcall (car tmp) (1+ (length field-name)) field-body))
52     (put anchor 'field-name field-name)
53     (put anchor 'scanner (car tmp))
54     (put anchor 'marker (cdr tmp))
55     anchor))
56
57 (defun ew-decode-analyzed-field (anchor)
58   "Decode analyzed field."
59   (or (get anchor 'decoded)
60       (let (tmp frag1 frag2 decode)
61         (when ew-decode-sticked-encoded-word
62           (ew-separate-eword
63            (get anchor 'next-frag)
64            anchor
65            (if (eq (get anchor 'scanner) 'ew-scan-unibyte-unstructured)
66                '(ew:us-texts)
67              '(ew:cm-texts))))
68         (when (get anchor 'marker)
69           (ew-mark (get anchor 'marker) anchor))
70         (setq frag1 (get anchor 'next-frag))
71         (while (not (eq frag1 anchor))
72           (setq decode (get frag1 'decode))
73           (setq frag2 (get frag1 'next-frag))
74           (while (and (not (eq frag2 anchor))
75                       (eq decode (get frag2 'decode)))
76             (setq frag2 (get frag2 'next-frag)))
77           (funcall decode anchor frag1 frag2)
78           (setq frag1 frag2))
79         (setq frag1 (get anchor 'prev-frag)
80               tmp ())
81         (while (not (eq frag1 anchor))
82           (setq tmp (cons (or (get frag1 'decoded) (symbol-name frag1)) tmp)
83                 frag1 (get frag1 'prev-frag)))
84         (put anchor 'decoded (apply 'concat tmp)))))
85
86 (defun ew-decode-field-no-cache (field-name field-body)
87   "No caching version of ew-decode-field."
88   (ew-decode-analyzed-field
89    (ew-analyze-field-to-decode field-name field-body)))
90
91 (defun ew-mark (tag anchor)
92   (let ((tlist (cons (list (symbol-value tag)) (ew-pair-list anchor))))
93     ;;(insert (format "%s" tlist))
94     (ew-parse
95      (lambda ()
96        (if (null tlist)
97            (cons 0 anchor)
98          (prog1 (car tlist) (setq tlist (cdr tlist)))))
99      (lambda (msg tok)
100        (message "%s%s : %s" msg tok anchor)
101        (when (< 0 ew-parse-error-sit-for-seconds)
102          (sit-for ew-parse-error-sit-for-seconds))))))
103
104 (defsubst ew-decode-us-ascii (str)
105   (decode-mime-charset-string str ew-default-mime-charset 'LF))
106
107 (defun ew-decode-none (anchor frag end)
108   (while (not (eq frag end))
109     (put frag 'decoded (ew-decode-us-ascii (symbol-name frag)))
110     (setq frag (get frag 'next-frag))))
111
112 (defsubst ew-proper-eword-p (frag)
113   (and
114    (or ew-ignore-75bytes-limit
115        (<= (length (symbol-name frag)) 75))
116    (or ew-ignore-76bytes-limit
117        (<= (get frag 'line-length) 76))
118    (cond
119     ((eq (get frag 'type) 'ew:cm-texts)
120      (ew-eword-p (symbol-name frag)))
121     ((eq (get frag 'type) 'ew:qs-texts)
122      (ew-eword-p (symbol-name frag)))
123     ((eq (get frag 'type) 'ew:atom)
124      (and
125       (or ew-permit-sticked-comment
126           (and
127            (not (ew-comment-frag-p (get frag 'prev-frag)))
128            (not (ew-comment-frag-p (get frag 'next-frag)))))
129       (or ew-permit-sticked-special
130           (and
131            (or (ew-comment-frag-p (get frag 'prev-frag))
132                (not (ew-special-frag-p (get frag 'prev-frag))))
133            (or (ew-comment-frag-p (get frag 'next-frag))
134                (not (ew-special-frag-p (get frag 'next-frag))))))
135       (ew-eword-p (symbol-name frag))))
136     ((eq (get frag 'type) 'ew:us-texts)
137      (and
138       (or ew-permit-sticked-special
139           (not (ew-special-frag-p (get frag 'prev-frag))))
140       (ew-eword-p (symbol-name frag))))
141     (t
142      nil))))
143
144 (defun ew-decode-generic (anchor start end
145                           decode-ewords
146                           decode-others
147                           eword gap all)
148   (let ((frag start) (start-others start) type f)
149     (while (not (eq frag end))
150       (setq type (get frag 'type))
151       (cond
152        ((and (memq type eword)
153              (ew-proper-eword-p frag))
154         (when (not (eq start-others frag))
155           (funcall decode-others start-others frag))
156         (let ((first frag) (ewords (list frag)))
157           (while (progn
158                    (setq f (get frag 'next-frag))
159                    (while (and (not (eq f end))
160                                (memq (get f 'type) gap))
161                      (setq f (get f 'next-frag)))
162                    (and (not (eq f end))
163                         (ew-proper-eword-p f)))
164             (setq frag (get frag 'next-frag))
165             (while (not (eq frag f))
166               (put frag 'decoded "")
167               (setq frag (get frag 'next-frag)))
168             (setq ewords (ew-rcons* ewords f)
169                   frag f))
170           (funcall decode-ewords
171                    (nreverse ewords)))
172         (setq start-others (get frag 'next-frag)))
173        ((memq type all)
174         nil)
175        (t
176         (error "unexpected token: %s (%s)" frag type)))
177       (setq frag (get frag 'next-frag)))
178     (when (not (eq start-others end))
179       (funcall decode-others start-others end))))
180
181 (defun ew-decode-generic-others (start end puncts quotes targets)
182   (let ((frag start) (start-nonpunct start) type buff tmp)
183     (while (not (eq frag end))
184       (setq type (get frag 'type))
185       (cond
186        ((memq type puncts)
187         (when buff
188           (setq buff (apply 'concat (nreverse buff))
189                 tmp (ew-decode-us-ascii buff))
190           (if (equal buff tmp)
191               (while (not (eq start-nonpunct frag))
192                 (put start-nonpunct 'decoded (symbol-name start-nonpunct))
193                 (setq start-nonpunct (get start-nonpunct 'next-frag)))
194             (progn
195               (put start-nonpunct 'decoded tmp)
196               (setq start-nonpunct (get start-nonpunct 'next-frag))
197               (while (not (eq start-nonpunct frag))
198                 (put start-nonpunct 'decoded "")
199                 (setq start-nonpunct (get start-nonpunct 'next-frag)))))
200           (setq buff ()))
201         (put frag 'decoded (symbol-name frag))
202         (setq start-nonpunct (get frag 'next-frag)))
203        ((memq type quotes)
204         (setq buff (ew-rcons* buff
205                               (substring (symbol-name frag) 1))))
206        ((memq type targets)
207         (setq buff (ew-rcons* buff
208                               (symbol-name frag))))
209        (t (error "something wrong: unexpected token: %s (%s)" frag type)))
210       (setq frag (get frag 'next-frag)))
211     (when buff
212       (setq buff (apply 'concat (nreverse buff))
213             tmp (ew-decode-us-ascii buff))
214       (if (equal buff tmp)
215           (while (not (eq start-nonpunct frag))
216             (put start-nonpunct 'decoded (symbol-name start-nonpunct))
217             (setq start-nonpunct (get start-nonpunct 'next-frag)))
218         (progn
219           (put start-nonpunct 'decoded tmp)
220           (setq start-nonpunct (get start-nonpunct 'next-frag))
221           (while (not (eq start-nonpunct frag))
222             (put start-nonpunct 'decoded "")
223             (setq start-nonpunct (get start-nonpunct 'next-frag))))))))
224
225 (defun ew-decode-unstructured-ewords (ewords)
226   (while ewords
227     (put (car ewords)
228          'decoded
229          (list (ew-decode-eword (symbol-name (car ewords)))))
230     (setq ewords (cdr ewords))))
231
232 (defun ew-decode-unstructured-others (start end)
233   (let (strs)
234     (while (not (eq start end))
235       (put start 'decoded "")
236       (setq strs (ew-rcons* strs
237                             (symbol-name start))
238             start (get start 'next-frag)))
239     (put (get end 'prev-frag)
240          'decoded
241          (ew-decode-us-ascii
242           (apply 'concat (nreverse strs))))))
243
244 (defun ew-decode-unstructured (anchor start end)
245   (ew-decode-generic
246    anchor start end
247    'ew-decode-unstructured-ewords
248    'ew-decode-unstructured-others
249    '(ew:us-texts)
250    '(ew:us-wsp
251      ew:us-fold)
252    '(ew:us-texts
253      ew:us-wsp
254      ew:us-fold))
255   (let ((frag end) tmp)
256     (while (not (eq frag start))
257       (setq frag (get frag 'prev-frag)
258             tmp (cons (get frag 'decoded) tmp))
259       (put frag 'decoded ""))
260     (put start 'decoded (ew-encode-crlf (apply 'ew-quote-concat tmp)))))
261
262 (defun ew-decode-phrase-ewords (ewords)
263   (let* ((qs (eq (get (car ewords) 'type) 'ew:qs-texts))
264          (regexp (if qs "[\\\\\\\"]" "[][()<>@,;:\\\\\\\".\000-\037]"))
265          has-dangerous-char
266          tmp decoded)
267     (setq tmp ewords)
268     (while tmp
269       (put (car tmp)
270            'decoded
271            (list (setq decoded (ew-decode-eword (symbol-name (car tmp))))))
272       (setq tmp (cdr tmp)
273             has-dangerous-char (or has-dangerous-char
274                                    (string-match regexp decoded))))
275     (when has-dangerous-char
276       (setq tmp ewords)
277       (while tmp
278         (setq decoded (get (car tmp) 'decoded))
279         (setcar decoded (ew-embed-in-quoted-string (car decoded)))
280         (setq tmp (cdr tmp)))
281       (when (not qs)
282         (setq decoded (get (car ewords) 'decoded))
283         (setcar decoded (concat "\"" (car decoded)))
284         (setq decoded (get (car (last ewords)) 'decoded))
285         (setcar decoded (concat (car decoded) "\""))))))
286
287 (defun ew-decode-phrase-others (start end)
288   (ew-decode-generic-others
289    start end
290    '(ew:qs-begin
291      ew:qs-end)
292    '(ew:qs-qfold
293      ew:qs-qpair)
294    '(ew:atom
295      ew:wsp
296      ew:fold
297      ew:qs-texts
298      ew:qs-wsp
299      ew:qs-fold)))
300
301 (defmacro ew-rotate (var val len)
302   (let ((tmp (make-symbol "tmp")))
303     `(let ((,tmp (nthcdr ,(- len 2) ,var)))
304        (if (cdr ,tmp)
305            (progn
306              (setcdr (cdr ,tmp) ,var)
307              (setq ,var (cdr ,tmp))
308              (setcdr ,tmp nil))
309          (setq ,var (cons nil ,var)))
310        (setcar ,var ,val))))
311
312 (defun ew-decode-phrase (anchor start end)
313   (ew-decode-generic
314    anchor start end
315    'ew-decode-phrase-ewords
316    'ew-decode-phrase-others
317    (if ew-decode-quoted-encoded-word
318        '(ew:atom ew:qs-texts)
319      '(ew:atom))
320    '(ew:wsp
321      ew:fold
322      ew:qs-wsp
323      ew:qs-fold)
324    '(ew:atom
325      ew:wsp
326      ew:fold
327      ew:qs-begin
328      ew:qs-end
329      ew:qs-texts
330      ew:qs-wsp
331      ew:qs-fold
332      ew:qs-qfold
333      ew:qs-qpair))
334   (let ((frag start) decoded str len idx char
335         chars frags
336         tmp)
337     (while (not (eq frag end))
338       (setq decoded (get frag 'decoded)
339             str (or (car-safe decoded) decoded)
340             len (length str)
341             idx 0)
342       (while (< idx len)
343         (setq char (sref str idx))
344         (ew-rotate chars char 3)
345         (ew-rotate frags frag 3)
346         (when (and (not (memq char '(?\t ?\ )))
347                    (equal (cdr chars) '(?\n ?\r))
348                    (eq (get (setq tmp (nth 2 frags)) 'type) 'ew:qs-qpair)
349                    (eq (symbol-name tmp) (get tmp 'decoded)))
350           (put tmp 'decoded "\r"))
351         (setq idx (char-next-index char idx)))
352       (setq frag (get frag 'next-frag)))
353     (setq frag end
354           tmp ())
355     (while (not (eq frag start))
356       (setq frag (get frag 'prev-frag)
357             tmp (cons (get frag 'decoded) tmp))
358       (put frag 'decoded ""))
359     (put start 'decoded (ew-encode-crlf (apply 'ew-quote-concat tmp)))))
360
361 (defun ew-decode-comment-ewords (ewords)
362   (let* ((regexp "[()\\\\]")
363          has-dangerous-char
364          tmp decoded)
365     (setq tmp ewords)
366     (while tmp
367       (put (car tmp)
368            'decoded
369            (list (setq decoded (ew-decode-eword (symbol-name (car tmp))))))
370       (setq tmp (cdr tmp)
371             has-dangerous-char (or has-dangerous-char
372                                    (string-match regexp decoded))))
373     (when has-dangerous-char
374       (setq tmp ewords)
375       (while tmp
376         (setq decoded (get (car tmp) 'decoded))
377         (setcar decoded (ew-embed-in-comment (car decoded)))
378         (setq tmp (cdr tmp))))))
379
380 (defun ew-decode-comment-others (start end)
381   (ew-decode-generic-others
382    start end
383    '()
384    '(ew:cm-qfold
385      ew:cm-qpair)
386    '(ew:cm-texts
387      ew:cm-wsp
388      ew:cm-fold)))
389
390 (defun ew-decode-comment (anchor start end)
391   (ew-decode-generic
392    anchor start end
393    'ew-decode-comment-ewords
394    'ew-decode-comment-others
395    '(ew:cm-texts)
396    '(ew:cm-wsp
397      ew:cm-fold)
398    '(ew:cm-texts
399      ew:cm-wsp
400      ew:cm-fold
401      ew:cm-qfold
402      ew:cm-qpair))
403   (let ((frag start) decoded str len idx char
404         chars frags tmp)
405     (while (not (eq frag end))
406       (setq decoded (get frag 'decoded)
407             str (or (car-safe decoded) decoded)
408             len (length str)
409             idx 0)
410       (while (< idx len)
411         (setq char (sref str idx))
412         (ew-rotate chars char 3)
413         (ew-rotate frags frag 3)
414         (when (and (not (memq char '(?\t ?\ )))
415                    (equal (cdr chars) '(?\n ?\r))
416                    (eq (get (setq tmp (nth 2 frags)) 'type) 'ew:cm-qpair)
417                    (eq (symbol-name tmp) (get tmp 'decoded)))
418           (put tmp 'decoded "\r"))
419         (setq idx (char-next-index char idx)))
420       (setq frag (get frag 'next-frag)))
421     (setq frag end
422           tmp ())
423     (while (not (eq frag start))
424       (setq frag (get frag 'prev-frag)
425             tmp (cons (get frag 'decoded) tmp))
426       (put frag 'decoded ""))
427     (put start 'decoded (ew-encode-crlf (apply 'ew-quote-concat tmp)))))
428
429 ;;;
430
431 (defun ew-embed-in-phrase (str)
432   (concat "\"" (ew-embed-in-quoted-string str) "\""))
433
434 (defun ew-embed-in-quoted-string (str)
435   (ew-quote-as-quoted-pair str '(?\\ ?\")))
436
437 (defun ew-embed-in-comment (str)
438   (ew-quote-as-quoted-pair str '(?\\ ?\( ?\))))
439
440 (defun ew-quote-as-quoted-pair (str specials)
441   (let ((i 0) (j 0) (l (length str)) result)
442     (while (< j l)
443       (when (member (aref str j) specials)
444         (setq result (ew-rcons*
445                       result
446                       (substring str i j)
447                       "\\")
448               i j))
449       (setq j (1+ j)))
450     (when (< i l)
451       (setq result (ew-rcons*
452                     result
453                     (substring str i))))
454     (apply 'concat (nreverse result))))
455
456 ;;;
457
458 (defun ew-contain-non-ascii-p (str)
459   (not (eq (charsets-to-mime-charset (find-charset-string str)) 'us-ascii)))
460
461 ;;;
462
463 (defun ew-decode-field-interest-option-order (field-name field-body)
464   (let* ((ew-decode-sticked-encoded-word nil)
465          (ew-decode-quoted-encoded-word nil)
466          (ew-ignore-75bytes-limit nil)
467          (ew-ignore-76bytes-limit nil)
468          (ew-permit-sticked-comment nil)
469          (ew-permit-sticked-special nil)
470          (ew-permit-null-encoded-text nil)
471          (decoded (make-vector (lsh 1 (length ew-option-list)) nil))
472          tmp
473          i j k
474          )
475     (aset decoded 0 (list 0 (ew-decode-field field-name field-body)))
476     (setq i 1)
477     (while (< i (length decoded))
478       (ew-restore-boolean-options i)
479       (setq tmp (ew-decode-field field-name field-body))
480       (setq j 0)
481       (while (<= (lsh 1 j) i)
482         (unless (zerop (logand i (lsh 1 j)))
483           (setq k (logand i (lognot (lsh 1 j))))
484           (when (or (not (aref decoded i))
485                     (< (car (aref decoded i))
486                        (+ (if (equal (cadr (aref decoded k)) tmp) 0 1)
487                           (car (aref decoded k)))))
488             (aset decoded i
489                   (ew-cons*
490                    (+ (if (equal (cadr (aref decoded k)) tmp) 0 1)
491                       (car (aref decoded k)))
492                    tmp
493                    (nth j ew-option-list)
494                    (cddr (aref decoded k))))))
495         (setq j (1+ j)))
496       (setq i (1+ i)))
497     (reverse (cddr (aref decoded (1- (length decoded)))))))
498
499 (defun ew-decode-field-test (field-name field-body)
500   (interactive
501    (list
502     (read-string "field-name:" (or (get-text-property (point) 'original-field-name)
503                                    (save-excursion
504                                      (end-of-line)
505                                      (and
506                                       (re-search-backward "^\\([!-9;-~]+\\):" nil t)
507                                       (match-string 1)))
508                                    ""))
509     (read-string "field-body:" (or (get-text-property (point) 'original-field-body)
510                                    (save-excursion
511                                      (end-of-line)
512                                      (and
513                                       (re-search-backward "^\\([!-9;-~]+\\):" nil t)
514                                       (progn
515                                         (goto-char (match-end 0))
516                                         (looking-at ".*\\(\n[ \t].*\\)*")
517                                         (ew-lf-crlf-to-crlf (match-string 0)))))
518                                    ""))))
519   (with-output-to-temp-buffer "*DOODLE*"
520     (save-excursion
521       (set-buffer standard-output)
522       (let ((ew-decode-sticked-encoded-word nil)
523             (ew-decode-quoted-encoded-word nil)
524             (ew-ignore-75bytes-limit nil)
525             (ew-ignore-76bytes-limit nil)
526             (ew-permit-sticked-comment nil)
527             (ew-permit-sticked-special nil)
528             (ew-permit-null-encoded-text nil)
529             (options
530              '(ew-ignore-76bytes-limit
531                ew-ignore-75bytes-limit
532                ew-permit-sticked-special
533                ew-permit-sticked-comment
534                ew-decode-sticked-encoded-word
535                ew-decode-quoted-encoded-word
536                ew-permit-null-encoded-text
537                ))
538             d1 d2)
539         (when (<= 16 (prefix-numeric-value current-prefix-arg))
540           (setq options (ew-decode-field-interest-option-order field-name field-body)))
541         (setq d1 (ew-decode-field-no-cache field-name field-body))
542         (insert field-name ":" field-body "\n"
543                 (make-string 76 ?-) "\n"
544                 field-name ":" d1 "\n")
545         (while options
546           (set (car options) t)
547           (insert (format "-- %s -> t\n" (car options)))
548           (setq d2 (ew-decode-field-no-cache field-name field-body))
549           (unless (equal d1 d2)
550             (insert field-name ":" d2 "\n")
551             (setq d1 d2))
552           (setq options (cdr options)))
553         (insert (make-string 76 ?-) "\n")
554         (when (<= 4 (prefix-numeric-value current-prefix-arg))
555           (mapcar
556            (lambda (frag)
557              (insert (format "%-15s %S\n"
558                              (substring (symbol-name (get frag 'type)) 3)
559                              (symbol-name frag)))
560              nil)
561            (ew-frag-list (ew-analyze-field-to-decode field-name field-body)))
562           (insert (make-string 76 ?-) "\n"))))))
563
564 ;;;
565
566 '(
567
568 (ew-decode-field "To" " =?US-ASCII?Q?phrase?= <akr@jaist.ac.jp>")
569 (ew-decode-field "To" " =?US-ASCII?Q?phrase?= < =?US-ASCII?Q?akr?= @jaist.ac.jp>")
570 (ew-decode-field "To" " =?US-ASCII?Q?akr?= @jaist.ac.jp")
571 (ew-decode-field "Subject" " =?ISO-2022-JP?B?GyRCJCIbKEI=?=")
572 (ew-decode-field "Content-Type" " text/vnd.latex-z(=?US-ASCII?Q?What=3F?=);charset=ISO-2022-JP")
573
574 (ew-decode-field "To" " =?US-ASCII?Q?A=22B=5CC?= <akr@jaist.ac.jp>")
575 (let ((ew-decode-quoted-encoded-word t))
576   (ew-decode-field "To" " \"=?US-ASCII?Q?A=22B=5CC?=\" <akr@jaist.ac.jp>"))
577
578 (ew-decode-field "To" " akr@jaist.ac.jp (=?US-ASCII?Q?=28A=29B=5C?=)")
579
580 (ew-decode-field "To" "\"A\\BC\e$B\\\"\\\\\e(B\" <foo@bar>")
581 (ew-decode-field "To" "\"A\\BC\" <foo@bar>")
582 (ew-decode-field "To" "\"\e\\$\\B\\$\\\"\e\\(\\B\" <foo@bar>")
583
584 (ew-decode-field-test "Subject" " =?US-ASCII?Q??=?US-ASCII?Q?a?=")
585 (ew-decode-field-test "Subject" " =?xUS-ASCII?Q??=?xUS-ASCII?Q?a?=")
586 (ew-decode-field-test "Subject" " =?+US-ASCII?Q??=?+US-ASCII?Q?a?=")
587
588 (ew-decode-field "From"" ()=?+US-ASCII?Q??=?+US-ASCII?Q?a?= =?US-ASCII?Q??= <akr@foo> (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)")
589
590 (let ((ew-default-mime-charset 'iso-2022-jp-2))
591   (ew-decode-field-no-cache
592      "From" "\"Cl\351ment Brousset\" <cbrousset@staffandline.com>"))
593
594 (ew-decode-field-no-cache "From" " \"Jacek \\\"Jaytee\\\" Szyd\263owski\" <jaytee@friko.onet.pl>")
595
596 )