* gnus-start.el (gnus-convert-old-newsrc): Fixed numeric
[gnus] / lisp / smime-ldap.el
1 ;;; smime-ldap.el --- client interface to LDAP for Emacs
2
3 ;; Copyright (C) 1998, 1999, 2000, 2005 Free Software Foundation, Inc.
4
5 ;; Author: Oscar Figueiredo <Oscar.Figueiredo@di.epfl.ch>
6 ;; Maintainer: Arne J\e,Ax\e(Brgensen <arne@arnested.dk>
7 ;; Created: February 2005
8 ;; Keywords: comm
9
10 ;; This file is part of GNU Emacs.
11
12 ;; GNU Emacs is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; any later version.
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
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 ;; GNU General Public License for more details.
21
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
24 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 ;; Boston, MA 02111-1307, USA.
26
27 ;;; Commentary:
28
29 ;; This file has a slightly changed implementation of Emacs 21.3's
30 ;; ldap-search and ldap-search-internal from ldap.el. The changes are
31 ;; made to achieve compatibility with OpenLDAP v2 and to make it
32 ;; possible to retrieve LDAP attributes that are tagged ie ";binary".
33
34 ;; When Gnus drops support for Emacs 21.x this file can be removed and
35 ;; smime.el changed to
36
37 ;;   - (require 'smime-ldap)   =>   (require 'ldap)
38 ;;   - (smime-ldap-search ...) =>   (ldap-search ...)
39
40 ;; If we are running in Emacs 22 or newer it just uses the build-in
41 ;; version of ldap-search.
42
43 ;;; Code:
44
45 (require 'ldap)
46
47 (defun smime-ldap-search (filter &optional host attributes attrsonly withdn)
48   "Perform an LDAP search.
49 FILTER is the search filter in RFC1558 syntax.
50 HOST is the LDAP host on which to perform the search.
51 ATTRIBUTES are the specific attributes to retrieve, nil means
52 retrieve all.
53 ATTRSONLY, if non-nil, retrieves the attributes only, without
54 the associated values.
55 If WITHDN is non-nil, each entry in the result will be prepended with
56 its distinguished name WITHDN.
57 Additional search parameters can be specified through
58 `ldap-host-parameters-alist', which see."
59   (interactive "sFilter:")
60   (if (>= emacs-major-version 22)
61       (ldap-search filter host attributes attrsonly)
62     (or host
63         (setq host ldap-default-host)
64         (error "No LDAP host specified"))
65     (let ((host-plist (cdr (assoc host ldap-host-parameters-alist)))
66           result)
67       (setq result (smime-ldap-search-internal
68                     (append host-plist
69                             (list 'host host
70                                   'filter filter
71                                   'attributes attributes
72                                   'attrsonly attrsonly
73                                   'withdn withdn))))
74       (if ldap-ignore-attribute-codings
75           result
76         (mapcar (function
77                  (lambda (record)
78                    (mapcar 'ldap-decode-attribute record)))
79                 result)))))
80
81 (defun smime-ldap-search-internal (search-plist)
82   "Perform a search on a LDAP server.
83 SEARCH-PLIST is a property list describing the search request.
84 Valid keys in that list are:
85 `host' is a string naming one or more (blank-separated) LDAP servers to
86 to try to connect to.  Each host name may optionally be of the form HOST:PORT.
87 `filter' is a filter string for the search as described in RFC 1558.
88 `attributes' is a list of strings indicating which attributes to retrieve
89 for each matching entry. If nil, return all available attributes.
90 `attrsonly', if non-nil, indicates that only attributes are retrieved,
91 not their associated values.
92 `base' is the base for the search as described in RFC 1779.
93 `scope' is one of the three symbols `sub', `base' or `one'.
94 `binddn' is the distinguished name of the user to bind as (in RFC 1779 syntax).
95 `passwd' is the password to use for simple authentication.
96 `deref' is one of the symbols `never', `always', `search' or `find'.
97 `timelimit' is the timeout limit for the connection in seconds.
98 `sizelimit' is the maximum number of matches to return.
99 `withdn' if non-nil each entry in the result will be prepended with
100 its distinguished name DN.
101 The function returns a list of matching entries.  Each entry is itself
102 an alist of attribute/value pairs."
103   (let ((buf (get-buffer-create " *ldap-search*"))
104         (bufval (get-buffer-create " *ldap-value*"))
105         (host (or (plist-get search-plist 'host)
106                   ldap-default-host))
107         (filter (plist-get search-plist 'filter))
108         (attributes (plist-get search-plist 'attributes))
109         (attrsonly (plist-get search-plist 'attrsonly))
110         (base (or (plist-get search-plist 'base)
111                   ldap-default-base))
112         (scope (plist-get search-plist 'scope))
113         (binddn (plist-get search-plist 'binddn))
114         (passwd (plist-get search-plist 'passwd))
115         (deref (plist-get search-plist 'deref))
116         (timelimit (plist-get search-plist 'timelimit))
117         (sizelimit (plist-get search-plist 'sizelimit))
118         (withdn (plist-get search-plist 'withdn))
119         (numres 0)
120         arglist dn name value record result)
121     (if (or (null filter)
122             (equal "" filter))
123         (error "No search filter"))
124     (setq filter (cons filter attributes))
125     (save-excursion
126       (set-buffer buf)
127       (erase-buffer)
128       (if (and host
129                (not (equal "" host)))
130           (setq arglist (nconc arglist (list (format "-h%s" host)))))
131       (if (and attrsonly
132                (not (equal "" attrsonly)))
133           (setq arglist (nconc arglist (list "-A"))))
134       (if (and base
135                (not (equal "" base)))
136           (setq arglist (nconc arglist (list (format "-b%s" base)))))
137       (if (and scope
138                (not (equal "" scope)))
139           (setq arglist (nconc arglist (list (format "-s%s" scope)))))
140       (if (and binddn
141                (not (equal "" binddn)))
142           (setq arglist (nconc arglist (list (format "-D%s" binddn)))))
143       (if (and passwd
144                (not (equal "" passwd)))
145           (setq arglist (nconc arglist (list (format "-w%s" passwd)))))
146       (if (and deref
147                (not (equal "" deref)))
148           (setq arglist (nconc arglist (list (format "-a%s" deref)))))
149       (if (and timelimit
150                (not (equal "" timelimit)))
151           (setq arglist (nconc arglist (list (format "-l%s" timelimit)))))
152       (if (and sizelimit
153                (not (equal "" sizelimit)))
154           (setq arglist (nconc arglist (list (format "-z%s" sizelimit)))))
155       (eval `(call-process ldap-ldapsearch-prog
156                            nil
157                            buf
158                            nil
159                            ,@arglist
160                            "-tt"                ; Write values to temp files
161                            "-x"
162                            "-LL"
163                            ;                       ,@ldap-ldapsearch-args
164                            ,@filter))
165       (insert "\n")
166       (goto-char (point-min))
167
168       (while (re-search-forward "[\t\n\f]+ " nil t)
169         (replace-match "" nil nil))
170       (goto-char (point-min))
171
172       (if (looking-at "usage")
173           (error "Incorrect ldapsearch invocation")
174         (message "Parsing results... ")
175         (while (progn
176                  (skip-chars-forward " \t\n")
177                  (not (eobp)))
178           (setq dn (buffer-substring (point) (save-excursion
179                                                (end-of-line)
180                                                (point))))
181           (forward-line 1)
182           (while (looking-at (concat "^\\(\\w*\\)\\(;\\w*\\)?[=:\t ]+"
183                                      "\\(<[\t ]*file://\\)?\\(.*\\)$"))
184             (setq name (match-string 1)
185                   value (match-string 4))
186             (save-excursion
187               (set-buffer bufval)
188               (erase-buffer)
189               (insert-file-contents-literally value)
190               (delete-file value)
191               (setq value (buffer-substring (point-min) (point-max))))
192             (setq record (cons (list name value)
193                                record))
194             (forward-line 1))
195           (setq result (cons (if withdn
196                                  (cons dn (nreverse record))
197                                (nreverse record)) result))
198           (setq record nil)
199           (skip-chars-forward " \t\n")
200           (message "Parsing results... %d" numres)
201           (1+ numres))
202         (message "Parsing results... done")
203         (nreverse result)))))
204
205 (provide 'smime-ldap)
206
207 ;; arch-tag: 87e6bc44-21fc-4e9b-a89b-f55f031f78f8
208 ;;; smime-ldap.el ends here