1 ;;; eword-decode.el --- RFC 2047 based encoded-word decoder for GNU Emacs
3 ;; Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc.
5 ;; Author: ENAMI Tsugutomo <enami@sys.ptg.sony.co.jp>
6 ;; MORIOKA Tomohiko <morioka@jaist.ac.jp>
7 ;; Maintainer: MORIOKA Tomohiko <morioka@jaist.ac.jp>
9 ;; Original: 1992/07/20 ENAMI Tsugutomo's `mime.el'.
10 ;; Renamed: 1993/06/03 to tiny-mime.el
11 ;; Renamed: 1995/10/03 from tiny-mime.el (split off encoder)
12 ;; Renamed: 1997/02/22 from tm-ew-d.el
13 ;; Keywords: encoded-word, MIME, multilingual, header, mail, news
15 ;; This file is part of SEMI (Spadework for Emacs MIME Interfaces).
17 ;; This program is free software; you can redistribute it and/or
18 ;; modify it under the terms of the GNU General Public License as
19 ;; published by the Free Software Foundation; either version 2, or (at
20 ;; your option) any later version.
22 ;; This program is distributed in the hope that it will be useful, but
23 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
24 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 ;; General Public License for more details.
27 ;; You should have received a copy of the GNU General Public License
28 ;; along with GNU Emacs; see the file COPYING. If not, write to the
29 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
30 ;; Boston, MA 02111-1307, USA.
34 (require 'std11-parse)
38 (defgroup eword-decode nil
39 "Encoded-word decoding"
43 ;;; @ MIME encoded-word definition
46 (defconst eword-encoded-text-regexp "[!->@-~]+")
47 (defconst eword-encoded-word-regexp
48 (concat (regexp-quote "=?")
56 eword-encoded-text-regexp
59 (defconst eword-after-encoded-word-regexp "\\([ \t]\\|$\\)")
61 (defconst eword-encoded-text-in-phrase-regexp "[-A-Za-z0-9!*+/=_]+")
62 (defconst eword-encoded-word-in-phrase-regexp
63 (concat (regexp-quote "=?")
71 eword-encoded-text-in-phrase-regexp
74 (defconst eword-after-encoded-word-in-phrase-regexp "\\([ \t(]\\|$\\)")
76 (defconst eword-encoded-text-in-comment-regexp "[]!-'*->@-[^-~]+")
77 (defconst eword-encoded-word-in-comment-regexp
78 (concat (regexp-quote "=?")
86 eword-encoded-text-in-comment-regexp
89 (defconst eword-after-encoded-word-in-comment-regexp "\\([ \t()\\\\]\\|$\\)")
91 (defconst eword-encoded-text-in-quoted-string-regexp "[]!#->@-[^-~]+")
92 (defconst eword-encoded-word-in-quoted-string-regexp
93 (concat (regexp-quote "=?")
101 eword-encoded-text-in-quoted-string-regexp
103 (regexp-quote "?=")))
104 (defconst eword-after-encoded-word-in-quoted-string-regexp "\\([ \t\"\\\\]\\|$\\)")
110 (defconst base64-token-regexp "[A-Za-z0-9+/]")
111 (defconst base64-token-padding-regexp "[A-Za-z0-9+/=]")
113 (defconst eword-B-encoded-text-regexp
122 base64-token-padding-regexp
123 base64-token-padding-regexp
126 ;; (defconst eword-B-encoding-and-encoded-text-regexp
127 ;; (concat "\\(B\\)\\?" eword-B-encoded-text-regexp))
130 ;;; @@ Quoted-Printable
133 (defconst quoted-printable-hex-chars "0123456789ABCDEF")
134 (defconst quoted-printable-octet-regexp
135 (concat "=[" quoted-printable-hex-chars
136 "][" quoted-printable-hex-chars "]"))
138 (defconst eword-Q-encoded-text-regexp
139 (concat "\\([^=?]\\|" quoted-printable-octet-regexp "\\)+"))
140 ;; (defconst eword-Q-encoding-and-encoded-text-regexp
141 ;; (concat "\\(Q\\)\\?" eword-Q-encoded-text-regexp))
147 (defvar eword-decode-sticked-encoded-word nil
148 "*If non-nil, decode encoded-words sticked on atoms,
149 other encoded-words, etc.
150 however this behaviour violates RFC2047.")
152 (defvar eword-decode-quoted-encoded-word nil
153 "*If non-nil, decode encoded-words in quoted-string
154 however this behaviour violates RFC2047.")
156 (defun eword-decode-first-encoded-words (string
159 &optional must-unfold)
160 "Decode MIME encoded-words in beginning of STRING.
162 EWORD-REGEXP is the regexp that matches a encoded-word.
163 Usual value is eword-encoded-word-regexp,
164 eword-encoded-text-in-phrase-regexp,
165 eword-encoded-word-in-comment-regexp or
166 eword-encoded-word-in-quoted-string-regexp.
168 AFTER-REGEXP is the regexp that matches a after encoded-word.
169 Usual value is eword-after-encoded-word-regexp,
170 eword-after-encoded-text-in-phrase-regexp,
171 eword-after-encoded-word-in-comment-regexp or
172 eword-after-encoded-word-in-quoted-string-regexp.
174 If beginning of STRING matches EWORD-REGEXP and AFTER-REGEXP,
175 returns a cons cell of decoded string(sequence of characters) and
176 the rest(sequence of octets).
178 If beginning of STRING does not matches EWORD-REGEXP and AFTER-REGEXP,
181 If an encoded-word is broken or your emacs implementation can not
182 decode the charset included in it, it is returned in decoded part
183 as encoded-word form.
185 If MUST-UNFOLD is non-nil, it unfolds and eliminates line-breaks even
186 if there are in decoded encoded-words (generated by bad manner MUA
187 such as a version of Net$cape)."
188 (if eword-decode-sticked-encoded-word (setq after-regexp ""))
189 (let ((between-ewords-regexp
190 (if eword-decode-sticked-encoded-word
193 (src string) ; sequence of octets.
194 (dst "")) ; sequence of characters.
196 (concat "\\`\\(" eword-regexp "\\)" after-regexp) src)
199 (ew (substring src 0 q))
200 (dw (eword-decode-encoded-word ew must-unfold)))
201 (setq dst (concat dst dw)
202 src (substring src q))
203 (if (not (string= ew dw))
208 (concat "\\`\\(" between-ewords-regexp "\\)"
209 "\\(" eword-regexp "\\)"
213 (setq p (match-end 1)
215 ew (substring src p q)
216 dw (eword-decode-encoded-word ew must-unfold))
219 (setq dst (concat dst (substring src 0 q))
220 src (substring src q))
223 (setq dst (concat dst dw)
224 src (substring src q)))))
228 (defun eword-decode-comment-string (string &optional must-unfold)
233 (while (< 0 (length src))
234 (let ((ch (aref src 0))
237 (eword-decode-first-encoded-words src
238 eword-encoded-word-in-comment-regexp
239 eword-after-encoded-word-in-comment-regexp
241 (if (and (not (string= buf ""))
242 (or decoded (eq ch ?\() (eq ch ?\))))
243 (setq dst (concat dst
244 (std11-wrap-as-quoted-pairs
245 (decode-mime-charset-string buf
246 default-mime-charset)
251 (setq dst (concat dst
252 (std11-wrap-as-quoted-pairs
256 ((or (eq ch ?\() (eq ch ?\)))
257 (setq dst (concat dst (list ch))
258 src (substring src 1)
261 (setq buf (concat buf (list (aref src 1)))
262 src (substring src 2)
264 ((or (eq ch ?\ ) (eq ch ?\t) (eq ch ?\n))
265 (setq buf (concat buf (list ch))
266 src (substring src 1)
268 ((string-match "\\`=?[^ \t\n()\\\\=]*" src)
269 (setq buf (concat buf (substring src 0 (match-end 0)))
270 src (substring src (match-end 0))
271 flag-ew eword-decode-sticked-encoded-word))
272 (t (error "something wrong")))))
273 (if (not (string= buf ""))
274 (setq dst (concat dst
275 (std11-wrap-as-quoted-pairs
276 (decode-mime-charset-string buf
277 default-mime-charset)
281 (defun eword-decode-quoted-string (string &optional must-unfold)
286 (while (< 0 (length src))
287 (let ((ch (aref src 0))
289 eword-decode-quoted-encoded-word
291 (eword-decode-first-encoded-words src
292 eword-encoded-word-in-quoted-string-regexp
293 eword-after-encoded-word-in-quoted-string-regexp
295 (if (and (not (string= buf ""))
296 (or decoded (eq ch ?\")))
297 (setq dst (concat dst
298 (std11-wrap-as-quoted-pairs
299 (decode-mime-charset-string buf
300 default-mime-charset)
305 (setq dst (concat dst
306 (std11-wrap-as-quoted-pairs
311 (setq dst (concat dst (list ch))
312 src (substring src 1)
315 (setq buf (concat buf (list (aref src 1)))
316 src (substring src 2)
318 ((or (eq ch ?\ ) (eq ch ?\t) (eq ch ?\n))
319 (setq buf (concat buf (list ch))
320 src (substring src 1)
322 ((string-match "\\`=?[^ \t\n\"\\\\=]*" src)
323 (setq buf (concat buf (substring src 0 (match-end 0)))
324 src (substring src (match-end 0))
325 flag-ew eword-decode-sticked-encoded-word))
326 (t (error "something wrong")))))
327 (if (not (string= buf ""))
328 (setq dst (concat dst
329 (std11-wrap-as-quoted-pairs
330 (decode-mime-charset-string buf
331 default-mime-charset)
335 (defun eword-decode-unstructured-string (string &optional must-unfold)
340 (while (< 0 (length src))
341 (let ((ch (aref src 0))
342 (decoded (and flag-ew (eword-decode-first-encoded-words src
343 eword-encoded-word-regexp
344 eword-after-encoded-word-regexp
346 (if (and (not (string= buf ""))
348 (setq dst (concat dst
349 (decode-mime-charset-string buf
350 default-mime-charset))
354 (setq dst (concat dst (car decoded))
356 ((or (eq ch ?\ ) (eq ch ?\t) (eq ch ?\n))
357 (setq buf (concat buf (list ch))
358 src (substring src 1)
360 ((string-match "\\`=?[^ \t\n=]*" src)
361 (setq buf (concat buf (substring src 0 (match-end 0)))
362 src (substring src (match-end 0))
363 flag-ew eword-decode-sticked-encoded-word))
364 (t (error "something wrong")))))
365 (if (not (string= buf ""))
366 (setq dst (concat dst
367 (decode-mime-charset-string buf
368 default-mime-charset))))
371 (defun eword-decode-string (string &optional must-unfold)
372 "Decode MIME encoded-words in STRING.
374 STRING is unfolded before decoding.
376 If an encoded-word is broken or your emacs implementation can not
377 decode the charset included in it, it is not decoded.
379 If MUST-UNFOLD is non-nil, it unfolds and eliminates line-breaks even
380 if there are in decoded encoded-words (generated by bad manner MUA
381 such as a version of Net$cape)."
382 (eword-decode-unstructured-string
383 (std11-unfold-string string)
390 (defun eword-decode-region (start end &optional unfolding must-unfold)
391 "Decode MIME encoded-words in region between START and END.
393 If UNFOLDING is not nil, it unfolds before decoding.
395 If MUST-UNFOLD is non-nil, it unfolds and eliminates line-breaks even
396 if there are in decoded encoded-words (generated by bad manner MUA
397 such as a version of Net$cape)."
401 (narrow-to-region start end)
403 (eword-decode-unfold)
405 (let ((str (eword-decode-unstructured-string
406 (buffer-substring (point-min) (point-max))
408 (delete-region (point-min) (point-max))
412 ;;; @ for message header
415 (defcustom eword-decode-ignored-field-list
416 '(newsgroups path lines nntp-posting-host message-id date)
417 "*List of field-names to be ignored when decoding.
418 Each field name must be symbol."
420 :type '(repeat symbol))
422 (defcustom eword-decode-structured-field-list
423 '(reply-to resent-reply-to from resent-from sender resent-sender
424 to resent-to cc resent-cc bcc resent-bcc dcc
425 mime-version content-type content-transfer-encoding
427 "*List of field-names to decode as structured field.
428 Each field name must be symbol."
430 :type '(repeat symbol))
432 (defun eword-decode-header (&optional code-conversion separator)
433 "Decode MIME encoded-words in header fields.
434 If CODE-CONVERSION is nil, it decodes only encoded-words. If it is
435 mime-charset, it decodes non-ASCII bit patterns as the mime-charset.
436 Otherwise it decodes non-ASCII bit patterns as the
437 default-mime-charset.
438 If SEPARATOR is not nil, it is used as header separator."
442 (std11-narrow-to-header separator)
443 (let ((default-charset
445 (if (mime-charset-to-coding-system code-conversion)
447 default-mime-charset))))
449 (let (beg p end field-name len)
450 (goto-char (point-min))
451 (while (re-search-forward std11-field-head-regexp nil t)
452 (setq beg (match-beginning 0)
454 field-name (buffer-substring beg (1- p))
455 len (string-width field-name)
456 field-name (intern (downcase field-name))
457 end (std11-field-end))
458 (cond ((memq field-name eword-decode-ignored-field-list)
461 ((memq field-name eword-decode-structured-field-list)
462 ;; Decode as structured field
463 (let ((body (buffer-substring p end))
464 (default-mime-charset default-charset))
465 (delete-region p end)
466 (insert (eword-decode-and-fold-structured-field
470 ;; Decode as unstructured field
472 (narrow-to-region beg (1+ end))
474 (let ((default-mime-charset default-charset))
475 (eword-decode-region beg (point-max) 'unfold))
476 (goto-char (point-max))
478 (eword-decode-region (point-min) (point-max) t)
481 (defun eword-decode-unfold ()
482 (goto-char (point-min))
484 (while (re-search-forward std11-field-head-regexp nil t)
485 (setq beg (match-beginning 0)
486 end (std11-field-end))
487 (setq field (buffer-substring beg end))
488 (if (string-match eword-encoded-word-regexp field)
490 (narrow-to-region (goto-char beg) end)
491 (while (re-search-forward "\n\\([ \t]\\)" nil t)
492 (replace-match (match-string 1))
494 (goto-char (point-max))
499 ;;; @ encoded-word decoder
502 (defvar eword-warning-face nil "Face used for invalid encoded-word.")
504 (defun eword-decode-encoded-word (word &optional must-unfold)
505 "Decode WORD if it is an encoded-word.
507 If your emacs implementation can not decode the charset of WORD, it
508 returns WORD. Similarly the encoded-word is broken, it returns WORD.
510 If MUST-UNFOLD is non-nil, it unfolds and eliminates line-breaks even
511 if there are in decoded encoded-word (generated by bad manner MUA such
512 as a version of Net$cape)."
513 (or (if (string-match eword-encoded-word-regexp word)
515 (substring word (match-beginning 1) (match-end 1))
519 (substring word (match-beginning 2) (match-end 2))
522 (substring word (match-beginning 3) (match-end 3))
525 (eword-decode-encoded-text charset encoding text must-unfold)
528 (add-text-properties 0 (length word)
529 (and eword-warning-face
530 (list 'face eword-warning-face))
537 ;;; @ encoded-text decoder
540 (defun eword-decode-encoded-text (charset encoding string
541 &optional must-unfold)
542 "Decode STRING as an encoded-text.
544 If your emacs implementation can not decode CHARSET, it returns nil.
546 If ENCODING is not \"B\" or \"Q\", it occurs error.
547 So you should write error-handling code if you don't want break by errors.
549 If MUST-UNFOLD is non-nil, it unfolds and eliminates line-breaks even
550 if there are in decoded encoded-text (generated by bad manner MUA such
551 as a version of Net$cape)."
552 (let ((cs (mime-charset-to-coding-system charset)))
556 ((string-equal "B" encoding)
557 (if (and (string-match eword-B-encoded-text-regexp string)
558 (string-equal string (match-string 0 string)))
559 (base64-decode-string string)
560 (error "Invalid encoded-text %s" string)))
561 ((string-equal "Q" encoding)
562 (if (and (string-match eword-Q-encoded-text-regexp string)
563 (string-equal string (match-string 0 string)))
564 (q-encoding-decode-string string)
565 (error "Invalid encoded-text %s" string)))
567 (error "Invalid encoding %s" encoding)
572 (setq dest (decode-coding-string dest cs))
579 (t (char-to-string chr)))
581 (std11-unfold-string dest)
587 ;;; @ lexical analyze
590 (defvar eword-lexical-analyze-cache nil)
591 (defvar eword-lexical-analyze-cache-max 299
592 "*Max position of eword-lexical-analyze-cache.
593 It is max size of eword-lexical-analyze-cache - 1.")
595 (defcustom eword-lexical-analyzers
596 '(eword-analyze-quoted-string
597 eword-analyze-domain-literal
598 eword-analyze-comment
600 eword-analyze-special
601 eword-analyze-encoded-word
603 "*List of functions to return result of lexical analyze.
604 Each function must have two arguments: STRING and MUST-UNFOLD.
605 STRING is the target string to be analyzed.
606 If MUST-UNFOLD is not nil, each function must unfold and eliminate
607 bare-CR and bare-LF from the result even if they are included in
608 content of the encoded-word.
609 Each function must return nil if it can not analyze STRING as its
612 Previous function is preferred to next function. If a function
613 returns nil, next function is used. Otherwise the return value will
616 :type '(repeat function))
618 (defun eword-analyze-quoted-string (string &optional must-unfold)
619 (let ((p (std11-check-enclosure string ?\" ?\")))
621 (cons (cons 'quoted-string
622 (eword-decode-quoted-string (substring string 0 p)))
623 (substring string p))
626 (defun eword-analyze-domain-literal (string &optional must-unfold)
627 (std11-analyze-domain-literal string))
629 (defun eword-analyze-comment (string &optional must-unfold)
630 (let ((len (length string)))
631 (if (and (< 0 len) (eq (aref string 0) ?\())
633 (while (and p (< p len) (eq (aref string p) ?\())
634 (setq p (std11-check-enclosure string ?\( ?\) t p)))
637 (eword-decode-comment-string (substring string 0 p)))
638 (substring string p)))
641 (defun eword-analyze-spaces (string &optional must-unfold)
642 (std11-analyze-spaces string))
644 (defun eword-analyze-special (string &optional must-unfold)
645 (std11-analyze-special string))
647 (defun eword-analyze-encoded-word (string &optional must-unfold)
648 (let ((decoded (eword-decode-first-encoded-words
650 eword-encoded-word-in-phrase-regexp
651 eword-after-encoded-word-in-phrase-regexp
654 (cons (cons 'atom (car decoded)) (cdr decoded)))))
656 (defun eword-analyze-atom (string &optional must-unfold)
657 (if (let ((enable-multibyte-characters nil))
658 (string-match std11-atom-regexp string))
659 (let ((end (match-end 0)))
660 (if (and eword-decode-sticked-encoded-word
661 (string-match eword-encoded-word-in-phrase-regexp
662 (substring string 0 end))
663 (< 0 (match-beginning 0)))
664 (setq end (match-beginning 0)))
665 (cons (cons 'atom (decode-mime-charset-string
666 (substring string 0 end)
667 default-mime-charset))
668 (substring string end)
671 (defun eword-lexical-analyze-internal (string must-unfold)
673 (while (not (string-equal string ""))
675 (let ((rest eword-lexical-analyzers)
677 (while (and (setq func (car rest))
678 (null (setq r (funcall func string must-unfold)))
680 (setq rest (cdr rest)))
681 (or r `((error . ,string) . ""))
683 (setq dest (cons (car ret) dest))
684 (setq string (cdr ret))
689 (defun eword-lexical-analyze (string &optional must-unfold)
690 "Return lexical analyzed list corresponding STRING.
691 It is like std11-lexical-analyze, but it decodes non us-ascii
692 characters encoded as encoded-words or invalid \"raw\" format.
693 \"Raw\" non us-ascii characters are regarded as variable
694 `default-mime-charset'."
695 (let* ((str (copy-sequence string))
696 (key (cons str (cons default-mime-charset must-unfold)))
698 (set-text-properties 0 (length str) nil str)
699 (if (setq ret (assoc key eword-lexical-analyze-cache))
701 (setq ret (eword-lexical-analyze-internal str must-unfold))
702 (setq eword-lexical-analyze-cache
704 (last eword-lexical-analyze-cache
705 eword-lexical-analyze-cache-max)))
708 (defun eword-decode-token (token)
711 (defun eword-decode-and-fold-structured-field
712 (string start-column &optional max-column must-unfold)
713 "Decode and fold (fill) STRING as structured field body.
714 It decodes non us-ascii characters in FULL-NAME encoded as
715 encoded-words or invalid \"raw\" string. \"Raw\" non us-ascii
716 characters are regarded as variable `default-mime-charset'.
718 If an encoded-word is broken or your emacs implementation can not
719 decode the charset included in it, it is not decoded.
721 If MAX-COLUMN is omitted, `fill-column' is used.
723 If MUST-UNFOLD is non-nil, it unfolds and eliminates line-breaks even
724 if there are in decoded encoded-words (generated by bad manner MUA
725 such as a version of Net$cape)."
727 (setq max-column fill-column))
728 (let ((c start-column)
729 (tokens (eword-lexical-analyze string must-unfold))
732 (while (and (setq token (car tokens))
733 (setq tokens (cdr tokens)))
734 (let* ((type (car token)))
735 (if (eq type 'spaces)
736 (let* ((next-token (car tokens))
737 (next-str (eword-decode-token next-token))
738 (next-len (string-width next-str))
739 (next-c (+ c next-len 1)))
740 (if (< next-c max-column)
741 (setq result (concat result " " next-str)
743 (setq result (concat result "\n " next-str)
745 (setq tokens (cdr tokens))
747 (let* ((str (eword-decode-token token)))
748 (setq result (concat result str)
749 c (+ c (string-width str)))
752 (concat result (eword-decode-token token))
755 (defun eword-decode-and-unfold-structured-field (string)
756 "Decode and unfold STRING as structured field body.
757 It decodes non us-ascii characters in FULL-NAME encoded as
758 encoded-words or invalid \"raw\" string. \"Raw\" non us-ascii
759 characters are regarded as variable `default-mime-charset'.
761 If an encoded-word is broken or your emacs implementation can not
762 decode the charset included in it, it is not decoded."
763 (let ((tokens (eword-lexical-analyze string 'must-unfold))
766 (let* ((token (car tokens))
768 (setq tokens (cdr tokens))
770 (if (eq type 'spaces)
772 (concat result (eword-decode-token token))
776 (defun eword-decode-structured-field-body (string &optional must-unfold
777 start-column max-column)
778 "Decode non us-ascii characters in STRING as structured field body.
779 STRING is unfolded before decoding.
781 It decodes non us-ascii characters in FULL-NAME encoded as
782 encoded-words or invalid \"raw\" string. \"Raw\" non us-ascii
783 characters are regarded as variable `default-mime-charset'.
785 If an encoded-word is broken or your emacs implementation can not
786 decode the charset included in it, it is not decoded.
788 If MUST-UNFOLD is non-nil, it unfolds and eliminates line-breaks even
789 if there are in decoded encoded-words (generated by bad manner MUA
790 such as a version of Net$cape)."
792 ;; fold with max-column
793 (eword-decode-and-fold-structured-field
794 string start-column max-column must-unfold)
796 (mapconcat (function eword-decode-token)
797 (eword-lexical-analyze string must-unfold)
801 (defun eword-decode-unstructured-field-body (string &optional must-unfold)
802 "Decode non us-ascii characters in STRING as unstructured field body.
803 STRING is unfolded before decoding.
805 It decodes non us-ascii characters in FULL-NAME encoded as
806 encoded-words or invalid \"raw\" string. \"Raw\" non us-ascii
807 characters are regarded as variable `default-mime-charset'.
809 If an encoded-word is broken or your emacs implementation can not
810 decode the charset included in it, it is not decoded.
812 If MUST-UNFOLD is non-nil, it unfolds and eliminates line-breaks even
813 if there are in decoded encoded-words (generated by bad manner MUA
814 such as a version of Net$cape)."
815 (eword-decode-string string must-unfold))
817 (defun eword-extract-address-components (string)
818 "Extract full name and canonical address from STRING.
819 Returns a list of the form (FULL-NAME CANONICAL-ADDRESS).
820 If no name can be extracted, FULL-NAME will be nil.
821 It decodes non us-ascii characters in FULL-NAME encoded as
822 encoded-words or invalid \"raw\" string. \"Raw\" non us-ascii
823 characters are regarded as variable `default-mime-charset'."
824 (let* ((structure (car (std11-parse-address
825 (eword-lexical-analyze
826 (std11-unfold-string string) 'must-unfold))))
827 (phrase (std11-full-name-string structure))
828 (address (std11-address-string structure))
830 (list phrase address)
837 (provide 'eword-decode)
839 ;;; eword-decode.el ends here