|
|
1.1 root 1: ;; Utility functions used both by rmail and rnews
2: ;; Copyright (C) 1985 Free Software Foundation, Inc.
3:
4: ;; This file is part of GNU Emacs.
5:
6: ;; GNU Emacs is distributed in the hope that it will be useful,
7: ;; but WITHOUT ANY WARRANTY. No author or distributor
8: ;; accepts responsibility to anyone for the consequences of using it
9: ;; or for whether it serves any particular purpose or works at all,
10: ;; unless he says so in writing. Refer to the GNU Emacs General Public
11: ;; License for full details.
12:
13: ;; Everyone is granted permission to copy, modify and redistribute
14: ;; GNU Emacs, but only under the conditions described in the
15: ;; GNU Emacs General Public License. A copy of this license is
16: ;; supposed to have been given to you along with GNU Emacs so you
17: ;; can know your rights and responsibilities. It should be in a
18: ;; file named COPYING. Among other things, the copyright notice
19: ;; and this notice must be preserved on all copies.
20:
21:
22: (provide 'mail-utils)
23:
24: ;; should be in loaddefs
25: (defvar mail-use-rfc822 nil
26: "*If non-nil, use a full, hairy RFC822 parser on mail addresses.
27: Otherwise, (the default) use a smaller, somewhat faster and
28: often-correct parser.")
29:
30: (defun mail-string-delete (string start end)
31: "Returns a string containing all of STRING except the part
32: from START (inclusive) to END (exclusive)."
33: (if (null end) (substring string 0 start)
34: (concat (substring string 0 start)
35: (substring string end nil))))
36:
37: (defun mail-strip-quoted-names (address)
38: "Delete comments and quoted strings in an address list ADDRESS.
39: Also delete leading/trailing whitespace and replace FOO <BAR> with just BAR.
40: Return a modified address list."
41: (if mail-use-rfc822
42: (progn (require 'rfc822)
43: (mapconcat 'identity (rfc822-addresses address) ", "))
44: (let (pos)
45: (string-match "\\`[ \t\n]*" address)
46: ;; strip surrounding whitespace
47: (setq address (substring address
48: (match-end 0)
49: (string-match "[ \t\n]*\\'" address
50: (match-end 0))))
51: ;; strip rfc822 comments
52: (while (setq pos (string-match
53: ;; This doesn't hack rfc822 nested comments
54: ;; `(xyzzy (foo) whinge)' properly. Big deal.
55: "[ \t]*(\\([^)\"\\]\\|\\\\.\\|\\\\\n\\)*)"
56: address))
57: (setq address
58: (mail-string-delete address
59: pos (match-end 0))))
60: ;; strip `quoted' names (This is supposed to hack `"Foo Bar" <bar@host>')
61: (setq pos 0)
62: (while (setq pos (string-match
63: "[ \t]*\"\\([^\"\\]\\|\\\\.\\|\\\\\n\\)*\"[ \t\n]*"
64: address pos))
65: ;; If the next thing is "@", we have "foo bar"@host. Leave it.
66: (if (and (> (length address) (match-end 0))
67: (= (aref address (match-end 0)) ?@))
68: (setq pos (match-end 0))
69: (setq address
70: (mail-string-delete address
71: pos (match-end 0)))))
72: ;; Retain only part of address in <> delims, if there is such a thing.
73: (while (setq pos (string-match "\\(,\\|\\`\\)[^,]*<\\([^>,]*>\\)"
74: address))
75: (let ((junk-beg (match-end 1))
76: (junk-end (match-beginning 2))
77: (close (match-end 0)))
78: (setq address (mail-string-delete address (1- close) close))
79: (setq address (mail-string-delete address junk-beg junk-end))))
80: address)))
81:
82: (or (and (boundp 'rmail-default-dont-reply-to-names)
83: (not (null rmail-default-dont-reply-to-names)))
84: (setq rmail-default-dont-reply-to-names "info-"))
85:
86: ; rmail-dont-reply-to-names is defined in loaddefs
87: (defun rmail-dont-reply-to (userids)
88: "Returns string of mail addresses USERIDS sans any recipients
89: that start with matches for rmail-dont-reply-to-names.
90: Usenet paths ending in an element that matches are removed also."
91: (if (null rmail-dont-reply-to-names)
92: (setq rmail-dont-reply-to-names
93: (concat (if rmail-default-dont-reply-to-names
94: (concat rmail-default-dont-reply-to-names "\\|")
95: "")
96: (concat (regexp-quote
97: (or (getenv "USER") (getenv "LOGNAME")
98: (user-login-name)))
99: "\\>"))))
100: (let ((match (concat "\\(^\\|,\\)[ \t\n]*\\([^,\n]*!\\|\\)\\("
101: rmail-dont-reply-to-names
102: "\\)"))
103: (case-fold-search t)
104: pos epos)
105: (while (setq pos (string-match match userids))
106: (if (> pos 0) (setq pos (1+ pos)))
107: (setq epos
108: (if (string-match "[ \t\n,]+" userids (match-end 0))
109: (match-end 0)
110: (length userids)))
111: (setq userids
112: (mail-string-delete
113: userids pos epos)))
114: ;; get rid of any trailing commas
115: (if (setq pos (string-match "[ ,\t\n]*\\'" userids))
116: (setq userids (substring userids 0 pos)))
117: ;; remove leading spaces. they bother me.
118: (if (string-match "\\s *" userids)
119: (substring userids (match-end 0))
120: userids)))
121:
122: (defun mail-fetch-field (field-name &optional last all)
123: "Return the value of the header field FIELD.
124: The buffer is expected to be narrowed to just the headers of the message.
125: If 2nd arg LAST is non-nil, use the last such field if there are several.
126: If 3rd arg ALL is non-nil, concatenate all such fields, with commas between."
127: (save-excursion
128: (goto-char (point-min))
129: (let ((case-fold-search t)
130: (name (concat "^" (regexp-quote field-name) "[ \t]*:[ \t]*")))
131: (goto-char (point-min))
132: (if all
133: (let ((value ""))
134: (while (re-search-forward name nil t)
135: (let ((opoint (point)))
136: (while (progn (forward-line 1)
137: (looking-at "[ \t]")))
138: (setq value (concat value
139: (if (string= value "") "" ", ")
140: (buffer-substring opoint (1- (point)))))))
141: (and (not (string= value "")) value))
142: (if (re-search-forward name nil t)
143: (progn
144: (if last (while (re-search-forward name nil t)))
145: (let ((opoint (point)))
146: (while (progn (forward-line 1)
147: (looking-at "[ \t]")))
148: (buffer-substring opoint (1- (point))))))))))
149:
150: ;; Parse a list of tokens separated by commas.
151: ;; It runs from point to the end of the visible part of the buffer.
152: ;; Whitespace before or after tokens is ignored,
153: ;; but whitespace within tokens is kept.
154: (defun mail-parse-comma-list ()
155: (let (accumulated
156: beg)
157: (skip-chars-forward " ")
158: (while (not (eobp))
159: (setq beg (point))
160: (skip-chars-forward "^,")
161: (skip-chars-backward " ")
162: (setq accumulated
163: (cons (buffer-substring beg (point))
164: accumulated))
165: (skip-chars-forward "^,")
166: (skip-chars-forward ", "))
167: accumulated))
168:
169: (defun mail-comma-list-regexp (labels)
170: (let (pos)
171: (setq pos (or (string-match "[^ \t]" labels) 0))
172: ;; Remove leading and trailing whitespace.
173: (setq labels (substring labels pos (string-match "[ \t]*$" labels pos)))
174: ;; Change each comma to \|, and flush surrounding whitespace.
175: (while (setq pos (string-match "[ \t]*,[ \t]*" labels))
176: (setq labels
177: (concat (substring labels 0 pos)
178: "\\|"
179: (substring labels (match-end 0))))))
180: labels)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.