Convert consecutive FSF copyright years to ranges.
[bpt/emacs.git] / lisp / net / netrc.el
CommitLineData
97b913ad 1;;; netrc.el --- .netrc parsing functionality
73b0cd50 2;; Copyright (C) 1996-2011 Free Software Foundation, Inc.
97b913ad
RS
3
4;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
5;; Keywords: news
88f4758e 6;;
97b913ad
RS
7;; Modularized by Ted Zlatanov <tzz@lifelogs.com>
8;; when it was part of Gnus.
9
10;; This file is part of GNU Emacs.
11
874a927a 12;; GNU Emacs is free software: you can redistribute it and/or modify
97b913ad 13;; it under the terms of the GNU General Public License as published by
874a927a
GM
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
97b913ad
RS
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
874a927a 19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
97b913ad
RS
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
874a927a 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
97b913ad
RS
24
25;;; Commentary:
26
27;; Just the .netrc parsing functionality, abstracted so other packages
28;; besides Gnus can use it.
29
30;;; Code:
31
32;;;
01c52d31 33;;; .netrc and .authinfo rc parsing
97b913ad
RS
34;;;
35
01c52d31
MB
36(defgroup netrc nil
37 "Netrc configuration."
38 :group 'comm)
39
a9ec34f4
LMI
40(defcustom netrc-file "~/.authinfo"
41 "File where user credentials are stored."
42 :type 'file
43 :group 'netrc)
44
01c52d31
MB
45(defvar netrc-services-file "/etc/services"
46 "The name of the services file.")
97b913ad 47
7410c270
G
48(defvar netrc-cache nil)
49
a9ec34f4 50(defun netrc-parse (&optional file)
01c52d31 51 (interactive "fFile to Parse: ")
8f7abae3 52 "Parse FILE and return a list of all entries in the file."
a9ec34f4
LMI
53 (unless file
54 (setq file netrc-file))
5b51650c 55 (if (listp file)
7410c270 56 ;; We got already parsed contents; just return it.
5b51650c
MB
57 file
58 (when (file-exists-p file)
59 (with-temp-buffer
60 (let ((tokens '("machine" "default" "login"
61 "password" "account" "macdef" "force"
62 "port"))
5b51650c 63 alist elem result pair)
7410c270
G
64 (if (and netrc-cache
65 (equal (car netrc-cache) (nth 5 (file-attributes file))))
66 ;; Store the contents of the file heavily encrypted in memory.
67 (insert (base64-decode-string (rot13-string (cdr netrc-cache))))
68 (insert-file-contents file)
69 (when (string-match "\\.gpg\\'" file)
70 (setq netrc-cache (cons (nth 5 (file-attributes file))
71 (rot13-string
72 (base64-encode-string
73 (buffer-string)))))))
5b51650c
MB
74 (goto-char (point-min))
75 ;; Go through the file, line by line.
97b913ad 76 (while (not (eobp))
5b51650c
MB
77 (narrow-to-region (point) (point-at-eol))
78 ;; For each line, get the tokens and values.
79 (while (not (eobp))
80 (skip-chars-forward "\t ")
81 ;; Skip lines that begin with a "#".
82 (if (eq (char-after) ?#)
83 (goto-char (point-max))
84 (unless (eobp)
85 (setq elem
86 (if (= (following-char) ?\")
87 (read (current-buffer))
88 (buffer-substring
89 (point) (progn (skip-chars-forward "^\t ")
90 (point)))))
91 (cond
92 ((equal elem "macdef")
93 ;; We skip past the macro definition.
94 (widen)
95 (while (and (zerop (forward-line 1))
96 (looking-at "$")))
97 (narrow-to-region (point) (point)))
98 ((member elem tokens)
99 ;; Tokens that don't have a following value are ignored,
100 ;; except "default".
101 (when (and pair (or (cdr pair)
102 (equal (car pair) "default")))
103 (push pair alist))
104 (setq pair (list elem)))
105 (t
106 ;; Values that haven't got a preceding token are ignored.
107 (when pair
108 (setcdr pair elem)
109 (push pair alist)
110 (setq pair nil)))))))
111 (when alist
112 (push (nreverse alist) result))
113 (setq alist nil
114 pair nil)
115 (widen)
116 (forward-line 1))
117 (nreverse result))))))
97b913ad
RS
118
119(defun netrc-machine (list machine &optional port defaultport)
120 "Return the netrc values from LIST for MACHINE or for the default entry.
121If PORT specified, only return entries with matching port tokens.
122Entries without port tokens default to DEFAULTPORT."
123 (let ((rest list)
124 result)
125 (while list
126 (when (equal (cdr (assoc "machine" (car list))) machine)
127 (push (car list) result))
128 (pop list))
129 (unless result
130 ;; No machine name matches, so we look for default entries.
131 (while rest
132 (when (assoc "default" (car rest))
6b958814
G
133 (let ((elem (car rest)))
134 (setq elem (delete (assoc "default" elem) elem))
135 (push elem result)))
97b913ad
RS
136 (pop rest)))
137 (when result
138 (setq result (nreverse result))
6b958814
G
139 (if (not port)
140 (car result)
141 (while (and result
142 (not (netrc-port-equal
143 (or port defaultport "nntp")
144 ;; when port is not given in the netrc file,
145 ;; it should mean "any port"
146 (or (netrc-get (car result) "port")
147 defaultport port))))
148 (pop result))
149 (car result)))))
97b913ad 150
01c52d31
MB
151(defun netrc-machine-user-or-password (mode authinfo-file-or-list machines ports defaults)
152 "Get the user name or password according to MODE from AUTHINFO-FILE-OR-LIST.
153Matches a machine from MACHINES and a port from PORTS, giving
154default ports DEFAULTS to `netrc-machine'.
155
156MODE can be \"login\" or \"password\", suitable for passing to
157`netrc-get'."
158 (let ((authinfo-list (if (stringp authinfo-file-or-list)
159 (netrc-parse authinfo-file-or-list)
160 authinfo-file-or-list))
161 (ports (or ports '(nil)))
162 (defaults (or defaults '(nil)))
163 info)
3b36c17e 164 (if (listp mode)
c9fc72fa
LMI
165 (setq info
166 (mapcar
167 (lambda (mode-element)
3b36c17e
MB
168 (netrc-machine-user-or-password
169 mode-element
170 authinfo-list
171 machines
172 ports
173 defaults))
174 mode))
175 (dolist (machine machines)
176 (dolist (default defaults)
177 (dolist (port ports)
178 (let ((alist (netrc-machine authinfo-list machine port default)))
179 (setq info (or (netrc-get alist mode) info)))))))
01c52d31
MB
180 info))
181
97b913ad
RS
182(defun netrc-get (alist type)
183 "Return the value of token TYPE from ALIST."
184 (cdr (assoc type alist)))
185
01c52d31
MB
186(defun netrc-port-equal (port1 port2)
187 (when (numberp port1)
188 (setq port1 (or (netrc-find-service-name port1) port1)))
189 (when (numberp port2)
190 (setq port2 (or (netrc-find-service-name port2) port2)))
191 (equal port1 port2))
192
193(defun netrc-parse-services ()
194 (when (file-exists-p netrc-services-file)
195 (let ((services nil))
196 (with-temp-buffer
197 (insert-file-contents netrc-services-file)
198 (while (search-forward "#" nil t)
199 (delete-region (1- (point)) (point-at-eol)))
200 (goto-char (point-min))
201 (while (re-search-forward
202 "^ *\\([^ \n\t]+\\)[ \t]+\\([0-9]+\\)/\\([^ \t\n]+\\)" nil t)
203 (push (list (match-string 1) (string-to-number (match-string 2))
204 (intern (downcase (match-string 3))))
205 services))
206 (nreverse services)))))
207
208(defun netrc-find-service-name (number &optional type)
209 (let ((services (netrc-parse-services))
210 service)
211 (setq type (or type 'tcp))
212 (while (and (setq service (pop services))
213 (not (and (= number (cadr service))
cb11d614 214 (eq type (car (cddr service)))))))
01c52d31
MB
215 (car service)))
216
217(defun netrc-find-service-number (name &optional type)
218 (let ((services (netrc-parse-services))
219 service)
220 (setq type (or type 'tcp))
221 (while (and (setq service (pop services))
222 (not (and (string= name (car service))
cb11d614 223 (eq type (car (cddr service)))))))
01c52d31
MB
224 (cadr service)))
225
1821a7b4
LMI
226(defun netrc-store-data (file host port user password)
227 (with-temp-buffer
228 (when (file-exists-p file)
229 (insert-file-contents file))
230 (goto-char (point-max))
231 (unless (bolp)
232 (insert "\n"))
233 (insert (format "machine %s login %s password %s port %s\n"
234 host user password port))
235 (write-region (point-min) (point-max) file nil 'silent)))
236
20a673b2 237;;;###autoload
a9ec34f4
LMI
238(defun netrc-credentials (machine &rest ports)
239 "Return a user name/password pair.
240Port specifications will be prioritised in the order they are
241listed in the PORTS list."
242 (let ((list (netrc-parse))
243 found)
6b958814
G
244 (if (not ports)
245 (setq found (netrc-machine list machine))
246 (while (and ports
247 (not found))
248 (setq found (netrc-machine list machine (pop ports)))))
a9ec34f4
LMI
249 (when found
250 (list (cdr (assoc "login" found))
251 (cdr (assoc "password" found))))))
252
97b913ad
RS
253(provide 'netrc)
254
255;;; netrc.el ends here