-;;;
;;; tl-822.el --- RFC 822 parser for GNU Emacs
-;;;
-;;; Copyright (C) 1995 Free Software Foundation, Inc.
-;;; Copyright (C) 1995 MORIOKA Tomohiko
-;;;
-;;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
-;;; Keywords: mail, news, RFC 822
-;;;
-;;; This file is part of tm (Tools for MIME).
-;;;
+
+;; Copyright (C) 1995,1996 Free Software Foundation, Inc.
+
+;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
+;; Keywords: mail, news, RFC 822
+
+;; This file is part of tl (Tiny Library).
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 2, or (at
+;; your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with This program; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Code:
(require 'tl-seq)
(require 'tl-str)
+(require 'std11)
(defconst rfc822/RCS-ID
- "$Id: tl-822.el,v 4.0 1995-10-05 13:22:22 morioka Exp $")
+ "$Id: tl-822.el,v 7.51 1996-08-28 17:25:39 morioka Exp $")
(defconst rfc822/version (get-version-string rfc822/RCS-ID))
-;;; @ field
+;;; @ header
;;;
-(defconst rfc822/field-name-regexp "[!-9;-~]+")
+(defalias 'rfc822/narrow-to-header 'std11-narrow-to-header)
+(defalias 'rfc822/get-header-string 'std11-header-string)
+(defalias 'rfc822/get-header-string-except 'std11-header-string-except)
+(defalias 'rfc822/get-field-names 'std11-collect-field-names)
-(defconst rfc822/field-top-regexp
- (concat "\\(" rfc822/field-name-regexp "\\):"))
-(defconst rfc822::next-field-top-regexp (concat "\n" rfc822/field-top-regexp))
-
-(defun rfc822/field-end ()
- (if (re-search-forward rfc822::next-field-top-regexp nil t)
- (goto-char (match-beginning 0))
- (if (re-search-forward "^$" nil t)
- (goto-char (1- (match-beginning 0)))
- (end-of-line)
- ))
- (point)
- )
+;;; @ field
+;;;
-(defun rfc822/get-field-body (name)
- (let ((case-fold-search t))
- (save-excursion
- (save-restriction
- (narrow-to-region
- (goto-char (point-min))
- (or (and (re-search-forward "^$" nil t) (match-end 0))
- (point-max)
- ))
- (goto-char (point-min))
- (if (re-search-forward (concat "^" name ":[ \t]*") nil t)
- (buffer-substring-no-properties
- (match-end 0)
- (rfc822/field-end)
- ))
- ))))
+(defalias `rfc822/field-end 'std11-field-end)
+(defalias 'rfc822/get-field-body 'std11-find-field-body)
+(defalias 'rfc822/get-field-bodies 'std11-find-field-bodies)
;;; @ quoting
(defconst rfc822/linear-white-space-regexp "\\(\n?[ \t]\\)+")
(defconst rfc822/quoted-pair-regexp "\\\\.")
-(defconst rfc822/qtext-regexp "[^\"\\\n\t \t]")
+(defconst rfc822/non-qtext-char-list '(?\" ?\\ ?\r ?\n))
+(defconst rfc822/qtext-regexp
+ (concat "[^" (char-list-to-string rfc822/non-qtext-char-list) "]"))
(defconst rfc822/quoted-string-regexp
(concat "\""
(regexp-*
- (concat
- "\\(" rfc822/linear-white-space-regexp "?"
- (regexp-or rfc822/qtext-regexp rfc822/quoted-pair-regexp)
- "\\)"))
- rfc822/linear-white-space-regexp "?"
+ (regexp-or rfc822/qtext-regexp rfc822/quoted-pair-regexp)
+ )
+ "\""))
+
+(defun rfc822/wrap-as-quoted-string (str)
+ "Wrap string STR as RFC 822 quoted-string. [tl-822.el]"
+ (concat "\""
+ (mapconcat (function
+ (lambda (chr)
+ (if (memq chr rfc822/non-qtext-char-list)
+ (concat "\\" (char-to-string chr))
+ (char-to-string chr)
+ )
+ )) str "")
"\""))
(defun rfc822/strip-quoted-pair (str)
;;; @ unfolding
;;;
-(defun rfc822/unfolding-string (str)
- (let ((dest ""))
- (while (string-match "\n\\s +" str)
- (setq dest (concat dest (substring str 0 (match-beginning 0)) " "))
- (setq str (substring str (match-end 0)))
- )
- (concat dest str)
- ))
+(defalias 'rfc822/unfolding-string 'std11-unfold-string)
;;; @ lexical analyze
;;;
-(defconst rfc822/special-chars "][()<>@,;:\\<>.\"")
-(defconst rfc822/space-chars " \t\n")
-(defconst rfc822/non-atom-chars
- (concat rfc822/special-chars rfc822/space-chars))
-(defconst rfc822/non-qtext-chars "\"")
-(defconst rfc822/non-dtext-chars "[]")
+(defconst rfc822/non-dtext-chars "][")
(defconst rfc822/non-ctext-chars "()")
-(defun rfc822/analyze-spaces (str)
- (let ((i (position-mismatched
- (function
- (lambda (elt)
- (find elt rfc822/space-chars)
- )) str))
- )
- (if (> i 0)
- (cons (cons 'spaces (substring str 0 i))
- (substring str i)
- ))
- ))
-
-(defun rfc822/analyze-special (str)
- (if (and (> (length str) 0)
- (find (elt str 0) rfc822/special-chars)
- )
- (cons (cons 'specials (substring str 0 1))
- (substring str 1)
- ))
- )
-
-(defun rfc822/analyze-atom (str)
- (let ((i (position-mismatched
- (function
- (lambda (elt)
- (not (find elt rfc822/non-atom-chars))
- )) str))
- )
- (if (> i 0)
- (cons (cons 'atom (substring str 0 i))
- (substring str i)
- ))
- ))
-
-(defun rfc822/analyze-quoted-pair (str)
- (if (and (>= (length str) 2)
- (eq (elt str 0) ?\\)
- )
- (cons (cons 'quoted-pair (substring str 0 2))
- (substring str 2)
- ))
- )
-
-(defun rfc822/analyze-quoted-string (str)
- (if (and (> (length str) 0)
- (eq (elt str 0) ?\")
- )
- (let* ((i (position-mismatched
- (function
- (lambda (elt)
- (not (find elt rfc822/non-qtext-chars))
- ))
- (setq str (substring str 1))
- ))
- (rest (substring str i))
- )
- (if (and (> i 0)
- (> (length rest) 0)
- (eq (elt rest 0) ?\")
- )
- (cons (cons 'quoted-string (substring str 0 i))
- (substring rest 1)
- )
- ))))
+(defalias 'rfc822/analyze-spaces 'std11-analyze-spaces)
+(defalias 'rfc822/analyze-special 'std11-analyze-special)
+(defalias 'rfc822/analyze-atom 'std11-analyze-atom)
+(defalias 'rfc822/analyze-quoted-string 'std11-analyze-quoted-string)
(defun rfc822/analyze-domain-literal (str)
(if (and (> (length str) 0)
- (eq (elt str 0) ?\[)
+ (eq (aref str 0) ?\[)
)
- (let* ((i (position-mismatched
- (function
- (lambda (elt)
- (not (find elt rfc822/non-dtext-chars))
- ))
- (setq str (substring str 1))
- ))
- (rest (substring str i))
+ (let* ((i (string-match (concat "[" rfc822/non-dtext-chars "]") str 1))
+ (rest (and i (substring str i)))
)
- (if (and (> i 0)
+ (if (and i
(> (length rest) 0)
- (eq (elt rest 0) ?\])
+ (eq (aref rest 0) ?\])
)
- (cons (cons 'domain-literal (substring str 0 i))
+ (cons (cons 'domain-literal (substring str 1 i))
(substring rest 1)
)
))))
(eq (elt str 0) ?\()
)
(let ((dest "")
- chr p ret)
+ p ret)
(setq str (substring str 1))
(catch 'tag
(while (not (string-equal str ""))
- (setq p (position-mismatched
- (function
- (lambda (elt)
- (not (find elt rfc822/non-ctext-chars))
- )) str))
+ (setq p (string-match (concat "[" rfc822/non-ctext-chars "]") str))
(cond ((> p 0)
(setq dest (concat dest (substring str 0 p)))
(setq str (substring str p))
))))
(defun rfc822/lexical-analyze (str)
- (let (dest
- (i 0)(len (length str))
- ret)
+ (let (dest ret)
(while (not (string-equal str ""))
(setq ret
(or (rfc822/analyze-quoted-string str)
(setq dest (cons (car ret) dest))
(setq str (cdr ret))
)
- (reverse dest)
+ (nreverse dest)
))
(setq lal (cdr lal))
(setq itl (cons token itl))
)
- (cons (reverse (cons token itl))
+ (cons (nreverse (cons token itl))
(cdr lal))
))
+(defun rfc822/parse-ascii-token (lal)
+ (let (token itl parsed token-value)
+ (while (and lal
+ (setq token (car lal))
+ (if (and (setq token-value (cdr token))
+ (find-charset-string token-value)
+ )
+ (setq token nil)
+ (rfc822/ignored-token-p token)
+ ))
+ (setq lal (cdr lal))
+ (setq itl (cons token itl))
+ )
+ (if (and token
+ (setq parsed (nreverse (cons token itl)))
+ )
+ (cons parsed (cdr lal))
+ )))
+
(defun rfc822/parse-token-or-comment (lal)
(let (token itl)
(while (and lal
(setq lal (cdr lal))
(setq itl (cons token itl))
)
- (cons (reverse (cons token itl))
+ (cons (nreverse (cons token itl))
(cdr lal))
))
(defun rfc822/parse-word (lal)
- (let ((ret (rfc822/parse-token lal)))
+ (let ((ret (rfc822/parse-ascii-token lal)))
(if ret
(let ((elt (car ret))
(rest (cdr ret))
(if ret
(let ((local-part (cdr (car ret))) dot)
(setq lal (cdr ret))
- (while (and (setq ret (rfc822/parse-token lal))
+ (while (and (setq ret (rfc822/parse-ascii-token lal))
(setq dot (car ret))
- (equal (cdr (assq 'specials dot)) ".")
+ (string-equal (cdr (assq 'specials dot)) ".")
(setq ret (rfc822/parse-word (cdr ret)))
(setq local-part
(append local-part dot (cdr (car ret)))
))))
(defun rfc822/parse-sub-domain (lal)
- (let ((ret (rfc822/parse-token lal)))
+ (let ((ret (rfc822/parse-ascii-token lal)))
(if ret
(let ((sub-domain (car ret)))
(if (or (assq 'atom sub-domain)
(if ret
(let ((domain (cdr (car ret))) dot)
(setq lal (cdr ret))
- (while (and (setq ret (rfc822/parse-token lal))
+ (while (and (setq ret (rfc822/parse-ascii-token lal))
(setq dot (car ret))
- (equal (cdr (assq 'specials dot)) ".")
+ (string-equal (cdr (assq 'specials dot)) ".")
(setq ret (rfc822/parse-sub-domain (cdr ret)))
(setq domain
(append domain dot (cdr (car ret)))
))))
(defun rfc822/parse-at-domain (lal)
- (let ((ret (rfc822/parse-token lal)) at-sign)
+ (let ((ret (rfc822/parse-ascii-token lal)) at-sign)
(if (and ret
(setq at-sign (car ret))
- (equal (cdr (assq 'specials at-sign)) "@")
+ (string-equal (cdr (assq 'specials at-sign)) "@")
(setq ret (rfc822/parse-domain (cdr ret)))
)
(cons (cons 'at-domain (append at-sign (cdr (car ret))))
(defun rfc822/parse-addr-spec (lal)
(let ((ret (rfc822/parse-local-part lal))
- addr at-sign)
+ addr)
(if (and ret
(prog1
(setq addr (cdr (car ret)))
(progn
(setq route (cdr (car ret)))
(setq lal (cdr ret))
- (while (and (setq ret (rfc822/parse-token lal))
+ (while (and (setq ret (rfc822/parse-ascii-token lal))
(setq comma (car ret))
- (equal (cdr (assq 'specials comma)) ",")
+ (string-equal (cdr (assq 'specials comma)) ",")
(setq ret (rfc822/parse-at-domain (cdr ret)))
)
(setq route (append route comma (cdr (car ret))))
(setq lal (cdr ret))
)
- (and (setq ret (rfc822/parse-token lal))
+ (and (setq ret (rfc822/parse-ascii-token lal))
(setq colon (car ret))
- (equal (cdr (assq 'specials colon)) ":")
+ (string-equal (cdr (assq 'specials colon)) ":")
(setq route (append route colon))
)
))
)))
(defun rfc822/parse-route-addr (lal)
- (let ((ret (rfc822/parse-token lal))
+ (let ((ret (rfc822/parse-ascii-token lal))
< route addr-spec >)
(if (and ret
(setq < (car ret))
- (equal (cdr (assq 'specials <)) "<")
+ (string-equal (cdr (assq 'specials <)) "<")
(setq lal (cdr ret))
(progn (and (setq ret (rfc822/parse-route lal))
(setq route (cdr (car ret)))
)
(setq addr-spec (cdr (car ret)))
(setq lal (cdr ret))
- (setq ret (rfc822/parse-token lal))
+ (setq ret (rfc822/parse-ascii-token lal))
(setq > (car ret))
- (equal (cdr (assq 'specials >)) ">")
+ (string-equal (cdr (assq 'specials >)) ">")
)
(cons (cons 'route-addr (append route addr-spec))
(cdr ret)
(defun rfc822/parse-group (lal)
(let ((ret (rfc822/parse-phrase lal))
- phrase : comma mbox semicolon)
+ phrase colon comma mbox semicolon)
(if (and ret
(setq phrase (cdr (car ret)))
(setq lal (cdr ret))
- (setq ret (rfc822/parse-token lal))
- (setq : (car ret))
- (equal (cdr (assq 'specials :)) ":")
+ (setq ret (rfc822/parse-ascii-token lal))
+ (setq colon (car ret))
+ (string-equal (cdr (assq 'specials colon)) ":")
(setq lal (cdr ret))
(progn
(and (setq ret (rfc822/parse-mailbox lal))
(setq mbox (list (car ret)))
(setq lal (cdr ret))
(progn
- (while (and (setq ret (rfc822/parse-token lal))
+ (while (and (setq ret (rfc822/parse-ascii-token lal))
(setq comma (car ret))
- (equal (cdr (assq 'specials comma)) ",")
+ (string-equal
+ (cdr (assq 'specials comma)) ",")
(setq lal (cdr ret))
(setq ret (rfc822/parse-mailbox lal))
(setq mbox (cons (car ret) mbox))
(setq lal (cdr ret))
)
)))
- (and (setq ret (rfc822/parse-token lal))
+ (and (setq ret (rfc822/parse-ascii-token lal))
(setq semicolon (car ret))
- (equal (cdr (assq 'specials semicolon)) ";")
+ (string-equal (cdr (assq 'specials semicolon)) ";")
)))
- (cons (list 'group phrase (reverse mbox))
+ (cons (list 'group phrase (nreverse mbox))
(cdr ret)
)
)))
(if ret
(let ((dest (list (car ret))))
(setq lal (cdr ret))
- (while (and (setq ret (rfc822/parse-token lal))
- (equal (cdr (assq 'specials (car ret))) ",")
+ (while (and (setq ret (rfc822/parse-ascii-token lal))
+ (string-equal (cdr (assq 'specials (car ret))) ",")
(setq ret (rfc822/parse-address (cdr ret)))
)
(setq dest (cons (car ret) dest))
(setq lal (cdr ret))
)
- (reverse dest)
+ (nreverse dest)
))))
(defun rfc822/addr-to-string (seq)
)
(defun rfc822/address-string (address)
- (if (eq (car address) 'mailbox)
- (let ((addr (nth 1 address))
- addr-spec)
- (rfc822/addr-to-string
- (if (eq (car addr) 'phrase-route-addr)
- (nth 2 addr)
- (cdr addr)
- )
- ))))
+ (cond ((eq (car address) 'group)
+ (mapconcat (function rfc822/address-string)
+ (nth 2 address)
+ ", ")
+ )
+ ((eq (car address) 'mailbox)
+ (let ((addr (nth 1 address)))
+ (rfc822/addr-to-string
+ (if (eq (car addr) 'phrase-route-addr)
+ (nth 2 addr)
+ (cdr addr)
+ )
+ )))))
(defun rfc822/full-name-string (address)
- (if (eq (car address) 'mailbox)
- (let ((addr (nth 1 address))
- (comment (nth 2 address))
- phrase)
- (if (eq (car addr) 'phrase-route-addr)
- (setq phrase (mapconcat (function
- (lambda (token)
- (cdr token)
- ))
- (nth 1 addr) ""))
- )
- (or phrase comment)
- )))
+ (cond ((eq (car address) 'group)
+ (mapconcat (function
+ (lambda (token)
+ (cdr token)
+ ))
+ (nth 1 address) "")
+ )
+ ((eq (car address) 'mailbox)
+ (let ((addr (nth 1 address))
+ (comment (nth 2 address))
+ phrase)
+ (if (eq (car addr) 'phrase-route-addr)
+ (setq phrase (mapconcat (function
+ (lambda (token)
+ (cdr token)
+ ))
+ (nth 1 addr) ""))
+ )
+ (or phrase comment)
+ ))))
+
+(defun rfc822/extract-address-components (str)
+ "Extract full name and canonical address from STR.
+Returns a list of the form (FULL-NAME CANONICAL-ADDRESS).
+If no name can be extracted, FULL-NAME will be nil. [tl-822.el]"
+ (let* ((structure (car
+ (rfc822/parse-address
+ (rfc822/lexical-analyze str)
+ )))
+ (phrase (rfc822/full-name-string structure))
+ (address (rfc822/address-string structure))
+ )
+ (list phrase address)
+ ))
;;; @ end
;;;
(provide 'tl-822)
+
+;;; tl-822.el ends here