ruby-ldap 0.9.9

Sign up to get free protection for your applications and to get access to all the features.
data/FAQ ADDED
@@ -0,0 +1,62 @@
1
+ $Id: FAQ,v 1.6 2006/04/25 08:43:12 ianmacd Exp $
2
+
3
+
4
+ FAQ
5
+ ---
6
+
7
+ Q. How do I add/modify binary data?
8
+
9
+ A. Create a LDAP::Mod object with the flag LDAP::LDAP_MOD_BVALUES as follows:
10
+
11
+ entry = [
12
+ LDAP::mod(LDAP::LDAP_MOD_ADD|LDAP_MOD_BVALUES, 'jpegPhoto', [jpeg_img]),
13
+ LDAP::mod(LDAP::LDAP_MOD_ADD, 'cn', ['Takaaki Tateishi']),
14
+ ...
15
+ ]
16
+ conn.add("dc=localhost, dc=localdomain", entry)
17
+
18
+
19
+
20
+ Q. Is there shortcut method for adding/modifying entries.
21
+
22
+ A. Yes, there is. You can directly give LDAP::Conn#add/modify hash data as
23
+ follows:
24
+
25
+ entry = {
26
+ 'objectclass' => [ 'top', 'person' ],
27
+ ...
28
+ }
29
+ conn.add( "cn=foobar, dc=localhost, dc=localdomain", entry )
30
+
31
+
32
+
33
+ Q. Can I use SASL authentication?
34
+
35
+ A. Yes, it works for me using Cyrus SASL and Kerberos V via GSSAPI.
36
+ Use LDAP::Conn#sasl_bind. Your mileage may vary.
37
+
38
+
39
+
40
+ Q. Can I put a limit on the number of results returned by the server?
41
+
42
+ A. Yes, as of version 0.9.4, you can. Set the size limit using
43
+ LDAP::Conn#set_option and then check for LDAP::Conn#search or
44
+ LDAP::Conn#search2 having exceeded this limit, by using LDAP::Conn#err:
45
+
46
+ conn = LDAP::Conn.new( 'localhost', 389 )
47
+
48
+ # Limit the results set to a maximum of 10.
49
+ conn.set_option( LDAP::LDAP_OPT_SIZELIMIT, 10 )
50
+
51
+ conn.search2( 'dc=localhost,dc=localdomain',
52
+ LDAP::LDAP_SCOPE_SUBTREE, '(objectClass=*)' )
53
+
54
+ if conn.err == LDAP::LDAP_SIZELIMIT_EXCEEDED
55
+ # Results set was truncated by server.
56
+ end
57
+
58
+ Note that LDAP::LDAP_SIZELIMIT_EXCEEDED may occur even when you have not
59
+ put an explicit limit on the number of results to be returned. The server
60
+ will likely have its own maximum configured, so it can be important to
61
+ check for this condition on all of your calls to LDAP::Conn#search and
62
+ LDAP::Conn#search2.
data/NOTES ADDED
@@ -0,0 +1,77 @@
1
+ $Id: NOTES,v 1.4 2006/08/09 11:22:25 ianmacd Exp $
2
+
3
+ 0.9.9
4
+ -----
5
+
6
+ Supported OpenLDAP 2.4.15 and higher. Thanks to Milos Jakubicek.
7
+ Gem Packaging Support. Thanks to S. Potter [mbbx6spp].
8
+
9
+ 0.9.8
10
+ -----
11
+
12
+ Supported Ruby 1.9.x.
13
+
14
+
15
+ 0.9.7
16
+ -----
17
+
18
+ LDAP_MOD_DELETE and LDAP_MOD_REPLACE were reversed in win/winldap.h, so
19
+ deletion and replacement operations did not work on Win32 systems.
20
+
21
+
22
+ 0.9.6
23
+ -----
24
+
25
+ A segfault on FreeBSD when using AMD64 was fixed for this release.
26
+
27
+ The only other changes are minor clarifications of the documentation.
28
+
29
+
30
+ 0.9.5
31
+ -----
32
+
33
+ The Windows build is now believed to work out of the box. It has been tested
34
+ on Windows XP SP2, using SVC C++ 6.0 to build the software. Thanks to Chris
35
+ Scharf <scharfie@gmail.com> for his work in this area and willingness to work
36
+ with me on fixing the problems.
37
+
38
+
39
+ 0.9.4
40
+ -----
41
+
42
+ LDAP::Conn#search, LDAP::Conn#search2, LDAP::Conn#search_ext and
43
+ LDAP::Conn#search_ext2 have been modified to treat LDAP_SIZELIMIT_EXCEEDED as
44
+ success.
45
+
46
+ After using any of these four methods, the user should use LDAP::Conn#err to
47
+ check whether the error status of the Conn object is
48
+ LDAP::LDAP_SIZELIMIT_EXCEEDED. If true, the results set has been truncated by
49
+ the server.
50
+
51
+ Previously, LDAP_SIZELIMIT_EXCEEDED would raise an exception and no results
52
+ would be returned, which is not the correct behaviour if the user has
53
+ deliberately put a limit on the number of results to be returned, as might be
54
+ done in order to spare the server.
55
+
56
+
57
+ 0.9.3
58
+ -----
59
+
60
+ The usability of the library on Windows platforms is currently a case of 'suck
61
+ it and see'. Some people report the code working, others report immediate
62
+ segfaults; yet others say that it worked after they made some minor
63
+ alterations to the code in order to get it to build.
64
+
65
+ Differences in Windows platform used, chosen compiler and version, plus the
66
+ variety of servers with which the code is used, conspire to result in the
67
+ exact facts of the matter not yet having been ascertained.
68
+
69
+ Most people seemed to experience some difficulty in getting the code to build
70
+ on Windows, so some effort has gone into making this better for the 0.9.3
71
+ release. This work is difficult, since I do not have a Windows build
72
+ environment at my disposal.
73
+
74
+ If you are a Windows user and you found that the code did not work in its
75
+ original form, but you managed to get it to work after some alterations, I
76
+ would be very grateful if you wrote to me to let me know what changes were
77
+ needed. Please include precise details of your build platform.
data/README ADDED
@@ -0,0 +1,266 @@
1
+ Ruby/LDAP -- A Ruby extension library for LDAP
2
+
3
+ $Id: README,v 1.19 2009/03/19 15:25:20 alexey.chebotar Exp $
4
+
5
+ Copyright (C) 2000-2004 Takaaki Tateishi <ttate@users.sourceforge.net>
6
+ Copyright (C) 2005-2006 Ian Macdonald <ian@caliban.org>
7
+ Copyright (C) 2009 Alexey Chebotar <alexey.chebotar@gmail.com>
8
+ -------------------------------------------------------------------------------
9
+
10
+ DESCRIPTION
11
+
12
+ 'Ruby/LDAP' is a Ruby extension library that provides an interface to the LDAP
13
+ API as described in RFC1823.
14
+ -------------------------------------------------------------------------------
15
+
16
+ REQUIREMENT
17
+
18
+ * Ruby 1.8.x / 1.9.x (at least 1.8.2 if you want to use ldap/control)
19
+ * OpenLDAP, Netscape SDK, Windows 2003 or Windows XP
20
+
21
+ -------------------------------------------------------------------------------
22
+
23
+ PORTS
24
+
25
+ * FreeBSD ("Akinori -Aki- MUSHA" <knu@idaemons.org>)
26
+ * Debian (Akira Yamada <akira@ruby-lang.org>)
27
+
28
+ -------------------------------------------------------------------------------
29
+
30
+ BUILDING
31
+
32
+ extconf.rb will try to use the OpenLDAP 2 or Netscape SDK libraries and guess
33
+ paths to some header files and libraries from the position of ldap.h. If you'd
34
+ like to see the available options for extconf.rb, run it with '--help' option.
35
+
36
+ $ ruby extconf.rb [--with-openldap1|--with-openldap2|--with-netscape|--with-wldap32]
37
+ $ make
38
+
39
+ This will create ldap.so, which you can either manually copy into place or
40
+ install with:
41
+
42
+ $ make install
43
+
44
+ If you're building the software on Windows, you may need to use nmake instead
45
+ of make.
46
+
47
+ -------------------------------------------------------------------------------
48
+
49
+ LICENSE
50
+
51
+ See COPYING.
52
+ -------------------------------------------------------------------------------
53
+
54
+ AVAILABLE CLASSES and METHODS
55
+
56
+ LDAP::LDAP_VERSION
57
+ LDAP::LDAP_MAX_VERSION
58
+ LDAP::VERSION
59
+ LDAP::MAJOR_VERSION
60
+ LDAP::MINOR_VERSION
61
+ LDAP::LDAP_PORT
62
+ LDAP::LDAPS_PORT
63
+ LDAP::LDAP_API_INFO_VERSION
64
+ LDAP::LDAP_VENDOR_NAME
65
+ LDAP::LDAP_VENDOR_VERSION
66
+ LDAP::LDAP_API_VERSION
67
+ LDAP.err2string(errcode)
68
+ LDAP.dn2ufn(dn)
69
+ LDAP.mod(mod_op, mod_type, mod_vals) (= LDAP::Mod.new)
70
+ LDAP.hash2mods(mod_op, hash)
71
+ LDAP.entry2hash(entry) (= entry.to_hash)
72
+ LDAP::Conn.new(host = "localhost", port = LDAP::LDAP_PORT)
73
+ : conn (raise LDAP::Error)
74
+ LDAP::Conn.open(host = "localhost", port = LDAP::LDAP_PORT)
75
+ : conn (raise LDAP::Error)
76
+ LDAP::Conn#simple_bind(dn = nil, password = nil) { ... }
77
+ : conn (raise LDAP::ResultError)
78
+ LDAP::Conn#bind(dn = nil, password = nil,
79
+ method = LDAP::LDAP_AUTH_SIMPLE) {|conn| ... }
80
+ (raise LDAP::ResultError)
81
+ LDAP::Conn#bind(dn = nil, password = nil,
82
+ method = LDAP::LDAP_AUTH_SIMPLE) : conn
83
+ (raise LDAP::ResultError)
84
+ LDAP::Conn#sasl_bind(dn = nil, mech = nil, cred = nil,
85
+ sctrls=nil, cctrls=nil) {|conn| ... }
86
+ (raise LDAP::ResultError)
87
+ LDAP::Conn#sasl_bind(dn = nil, mech = nil, cred = nil,
88
+ sctrls=nil, cctrls=nil) : conn
89
+ (raise LDAP::ResultError)
90
+ LDAP::Conn#bound? : true || false
91
+ LDAP::Conn#unbind() (raise LDAP::ResultError)
92
+ LDAP::Conn#start_tls
93
+ LDAP::Conn#perror(str)
94
+ LDAP::Conn#result2error(ldap_msg) : errcode
95
+ LDAP::Conn#err2string(errcode) : errmsg
96
+ LDAP::Conn#get_errno : errcode [if available]
97
+ LDAP::Conn#search(basedn, scope, filter, attrs = nil, attrsonly = false,
98
+ sec = 0, usec = 0,
99
+ s_attr = nil, s_proc = nil) {|entry| ... }
100
+ : conn (raise LDAP::ResultError)
101
+ LDAP::Conn#search2(basedn, scope, filter, attrs = nil, attrsonly = false,
102
+ sec = 0, usec = 0,
103
+ s_attr = nil, s_proc = nil) {|entry_as_hash| ... }
104
+ : conn (if a block is given) /
105
+ Array of Hash (if no block is given)
106
+ (raise LDAP::ResultError)
107
+ LDAP::Conn#search_ext(basedn, scope, filter, attrs = nil,
108
+ attrsonly = false, serverctrls, clientctrls,
109
+ sec = 0, usec = 0,
110
+ s_attr = nil, s_proc = nil) {|entry| ... }
111
+ : conn (raise LDAP::ResultError)
112
+ LDAP::Conn#search_ext2(basedn, scope, filter, attrs = nil,
113
+ attrsonly = false,
114
+ serverctrls, clientctrls, sec = 0, usec = 0,
115
+ s_attr = nil, s_proc = nil) {|entry_as_hash| ... }
116
+ : conn (if a block is given) /
117
+ Array of Hash (if no block is given)
118
+ (raise LDAP::ResultError)
119
+ LDAP::Conn#add(dn, ldap_mods) : self (raise LDAP::ResultError)
120
+ LDAP::Conn#add_ext(dn, ldap_mods, serverctrls, clientctrls)
121
+ : self (raise LDAP::ResultError)
122
+ LDAP::Conn#modify(dn, ldap_mods) : self (raise LDAP::ResultError)
123
+ LDAP::Conn#modify_ext(dn, ldap_mods, serverctrls, clientctrls)
124
+ : self (raise LDAP::ResultError)
125
+ LDAP::Conn#modrdn(olddn, newdn, delete) : self (raise LDAP::ResultError)
126
+ LDAP::Conn#delete(dn) : self (raise LDAP::ResultError)
127
+ LDAP::Conn#delete(dn, serverctrls, clientctrls) : self
128
+ (raise LDAP::ResultError)
129
+ LDAP::Conn#compare(dn, attr, val) : self
130
+ LDAP::Conn#compare_ext(dn, attr, val, serverctrls, clientctrls) : self
131
+ LDAP::Conn#set_option(opt, data) : self (raise LDAP::ResultError)
132
+ LDAP::Conn#get_option(opt) : data (raise LDAP::ResultError)
133
+ LDAP::Conn#schema(base = nil, attrs = nil,
134
+ sec = 0, usec = 0) : LDAP::Schema
135
+ LDAP::Conn#root_dse(attrs = nil, sec = 0, usec = 0) : Array of Hash
136
+ LDAP::SSLConn.new(host = 'localhost', port = LDAP_PORT,
137
+ start_tls = false, sctrls=nil, cctrls=nil)
138
+ : conn (raise LDAP::Error)
139
+ LDAP::Mod.new(mod_op, mod_type, mod_vals) : ldap_mod
140
+ LDAP::Mod#inspect : String
141
+ LDAP::Mod#mod_op : mod_op
142
+ LDAP::Mod#mod_type : mod_type
143
+ LDAP::Mod#mod_vals : mod_vals
144
+ LDAP::Mod#mod_op=(mod_op)
145
+ LDAP::Mod#mod_type=(mod_type)
146
+ LDAP::Mod#mod_vals=(mod_vals)
147
+ LDAP::Entry#get_dn : dn
148
+ LDAP::Entry#get_values : vals
149
+ LDAP::Entry#get_attributes : attrs
150
+ LDAP::Entry#dn (= get_dn)
151
+ LDAP::Entry#vals (= get_values)
152
+ LDAP::Entry#[] (= get_values)
153
+ LDAP::Entry#attrs (= get_attributes)
154
+ LDAP::Entry#to_hash : Hash
155
+ LDAP::Entry#inspect : String
156
+ LDAP::Control.new : LDAP::Control
157
+ LDAP::Control#oid : String
158
+ LDAP::Control#oid=(oid) : oid
159
+ LDAP::Control#critical : true || false
160
+ LDAP::Control#critical? : true || false
161
+ LDAP::Control#critical=(crit) : crit
162
+ LDAP::Control#value : String
163
+ LDAP::Control#value=(val) : val
164
+ LDAP::Control#inspect : String
165
+
166
+ SSLConn is a subclass of Conn, so its objects have access to the same methods
167
+ as Conn objects.
168
+
169
+ In ldap/schema.rb:
170
+
171
+ LDAP::Conn#schema(attrs = nil, sec = 0, usec = 0) : schema
172
+ LDAP::Schema#must(oc) : attributes
173
+ LDAP::Schema#may(oc) : attributes
174
+ LDAP::Schema#names(attr) : names
175
+ LDAP::Schema#sup(oc) : object class
176
+
177
+ In ldap/control.rb:
178
+
179
+ LDAP::Control.encode(array) : String
180
+ LDAP::Control#decode : Array
181
+
182
+ In ldap/ldif.rb:
183
+
184
+ LDAP::Entry#to_ldif : LDAP::LDIF::Entry
185
+ LDAP::Entry#to_s : Alias of LDAP::Entry#to_ldif
186
+ LDAP::Mod#to_ldif(dn) : LDAP::LDIF::Mod
187
+ LDAP::Mod#to_s(dn) : Alias of LDAP::Mod#to_ldif
188
+ LDAP::Record.new(dn, change_type, attrs, mods=nil, ctrls=nil)
189
+ LDAP::Record#send(conn) : self
190
+ LDAP::Record#clean : self
191
+ LDAP::LDIF.mods_to_ldif( dn, *mods )
192
+ LDAP::LDIF.parse_entry(lines) : LDAP::Record (raise LDAP::LDIFError)
193
+ LDAP::LDIF.parse_file(file, sort=false)
194
+ : self (if a block is given) /
195
+ Array (if no block is given)
196
+
197
+ See also test/*.rb for examples.
198
+ -------------------------------------------------------------------------------
199
+
200
+ REFERENCES
201
+
202
+ * T. Howes, M. Smith (University of Michigan): RFC1823, The LDAP Application
203
+ Program Interface, August 1995
204
+ * T. Howes (University of Michigan): RFC1960, A String Representation of LDAP
205
+ Search Filters, June 1996
206
+ * M. Wahl, Critical Angle Inc, T. Hows, Netscape Communications Gorp., S.
207
+ Kille, Isode Limited: Lightweight Directory Access Protocol (v3), December
208
+ 1997
209
+ * M. Wahl, Critical Angle Inc., A. Coulbeck, Isode Inc., T. Howes, Netscape
210
+ Communications Corp., S. Kille, Isode Limited: December 1997
211
+ * M .Wahl, Critical Angle Inc., S. Kille, Isode Ltd., T. Howes, Netscape
212
+ Communications Corp.: Lightweight Directory Access Protocol (v3): UTF-8
213
+ String Representation of Distinguished Names, December 1997
214
+ * T. Howes, Netscape Communications Gorp.: The String Representation of LDAP
215
+ Search Filters, December 1997
216
+ * F. Yergeau (Alis Technologies): RFC2279, UTF-8, a transformation format of
217
+ ISO 10646, October 1998
218
+ * Netscape Communications Corp.: Netscape Directory SDK
219
+ * C. Weider, A. Herron, A. Anantha, T. Howes: RFC2696, LDAP Control
220
+ Extension for Simple Paged Results Manipulation, September 1999
221
+ * Luiz Ernesto Pinheiro Malere: LDAP Linux HOWTO, February 2000
222
+ * G. Good: RFC2849, The LDAP Data Interchange Format (LDIF) - Technical
223
+ Specification, June 2000.
224
+ * Tim Howes, Mark Smith: Understanding and Deploying LDAP Directory Servers
225
+ * The OpenLDAP Project: OpenLDAP 2.2 Administrator's Guide, February 2004
226
+
227
+ Here are some URLs that contain useful information about LDAP:
228
+
229
+ * University of Michigan
230
+ http://www.umich.edu/~dirsvcs/ldap/
231
+ * OpenLDAP Project
232
+ http://www.openldap.org/
233
+ * Netscape Communications
234
+ http://developer.netscape.com/docs/manuals/communicator/ldap45.htm
235
+ * Netscape Directory SDK
236
+ http://www.mozilla.org/directory/
237
+ * Active Directory Service Interfaces Overview
238
+ http://www.microsoft.com/windows2000/techinfo/howitworks/activedirectory/
239
+ adsilinks.asp
240
+ * LDAP schema repository
241
+ http://www.hklc.com/ldapschema/
242
+ http://ldap.hklc.com/
243
+ * Object Identifiers Registry
244
+ http://www.alvestrand.no/harald/objectid/
245
+
246
+ THANKS
247
+
248
+ This list maybe not correct. If you notice mistakes of this list, please point out.
249
+
250
+ * atsu@@metallic.co.jp
251
+ * Akinori MUSHA
252
+ * Akira Yamada
253
+ * Pirmin Kalberer
254
+ * Radek Hnilica
255
+ * Hadmut Danisch
256
+ * Yuuzou Gotou
257
+ * Tilo Sloboda
258
+ * Usa Nakamura
259
+ * Mark Kittisopikul
260
+ * Jan Mikkelsen
261
+ * Adam Doligalski
262
+ * Chris Scharf
263
+ * bidon: Patch.
264
+ * Milos Jakubicek: Patch.
265
+ * S. Potter [mbbx6spp]: Gem Packaging Support
266
+ * Kouhei Sutou
data/TODO ADDED
@@ -0,0 +1,15 @@
1
+ -*- text -*-
2
+
3
+ To-do list
4
+ ----------
5
+
6
+ - Support for more LDAPv3 controls and extensions.
7
+
8
+ - DSML support.
9
+
10
+ - (?) adding ldap_url_search_s(), ldap_url_search_st() and
11
+ ldap_is_ldap_url()
12
+
13
+ - Asynchronous functions.
14
+
15
+ - Correctly implement SASL functions.
data/conn.c ADDED
@@ -0,0 +1,1810 @@
1
+ /*
2
+ * conn.c
3
+ * $Id: conn.c,v 1.51 2006/08/01 00:07:53 ianmacd Exp $
4
+ */
5
+
6
+ #include "ruby.h"
7
+ #include "rbldap.h"
8
+ #if defined(HAVE_SYS_TIME_H)
9
+ # include <sys/time.h>
10
+ #endif
11
+ #if defined(HAVE_UNISTD_H)
12
+ # include <unistd.h>
13
+ #endif
14
+
15
+ /* RDoc needs the following bogus code to find the parent module:
16
+ *
17
+ * rb_mLDAP = rb_define_module ("LDAP");
18
+ */
19
+
20
+ static VALUE rb_ldap_sort_obj = Qnil;
21
+ extern VALUE rb_ldap_control_new2 (LDAPControl * ctl);
22
+ extern VALUE rb_ldap_sslconn_initialize (int argc, VALUE argv[], VALUE self);
23
+ extern VALUE rb_ldap_conn_rebind (VALUE self);
24
+
25
+ VALUE rb_cLDAP_Conn;
26
+
27
+ static void
28
+ rb_ldap_conn_free (RB_LDAP_DATA * ldapdata)
29
+ {
30
+ if (ldapdata->ldap && ldapdata->bind)
31
+ {
32
+ ldap_unbind (ldapdata->ldap);
33
+ };
34
+ };
35
+
36
+ static void
37
+ rb_ldap_conn_mark (RB_LDAP_DATA * ldapdata)
38
+ {
39
+ /* empty */
40
+ };
41
+
42
+ VALUE
43
+ rb_ldap_conn_new (VALUE klass, LDAP * cldap)
44
+ {
45
+ VALUE conn;
46
+ RB_LDAP_DATA *ldapdata;
47
+
48
+ conn = Data_Make_Struct (klass, RB_LDAP_DATA,
49
+ rb_ldap_conn_mark, rb_ldap_conn_free, ldapdata);
50
+ ldapdata->ldap = cldap;
51
+ ldapdata->err = 0;
52
+ ldapdata->bind = 0;
53
+
54
+ return conn;
55
+ };
56
+
57
+ VALUE
58
+ rb_ldap_conn_s_allocate (VALUE klass)
59
+ {
60
+ return rb_ldap_conn_new (klass, (LDAP *) 0);
61
+ }
62
+
63
+ /*
64
+ * call-seq:
65
+ * LDAP::Conn.new(host='localhost', port=LDAP_PORT) => LDAP::Conn
66
+ *
67
+ * Return a new LDAP::Conn connection to the server, +host+, on port +port+.
68
+ */
69
+ VALUE
70
+ rb_ldap_conn_initialize (int argc, VALUE argv[], VALUE self)
71
+ {
72
+ LDAP *cldap;
73
+ char *chost;
74
+ int cport;
75
+ int was_verbose = Qfalse;
76
+ RB_LDAP_DATA *ldapdata;
77
+
78
+ VALUE host, port;
79
+
80
+ Data_Get_Struct (self, RB_LDAP_DATA, ldapdata);
81
+ if (ldapdata->ldap)
82
+ {
83
+ return Qnil;
84
+ }
85
+
86
+ switch (rb_scan_args (argc, argv, "02", &host, &port))
87
+ {
88
+ case 0:
89
+ chost = ALLOCA_N (char, strlen ("localhost") + 1);
90
+ strcpy (chost, "localhost");
91
+ cport = LDAP_PORT;
92
+ break;
93
+ case 1:
94
+ chost = StringValueCStr (host);
95
+ cport = LDAP_PORT;
96
+ break;
97
+ case 2:
98
+ chost = StringValueCStr (host);
99
+ cport = NUM2INT (port);
100
+ break;
101
+ default:
102
+ rb_bug ("rb_ldap_conn_new");
103
+ };
104
+
105
+ cldap = ldap_init (chost, cport);
106
+ if (!cldap)
107
+ rb_raise (rb_eLDAP_ResultError, "can't initialise an LDAP session");
108
+ ldapdata->ldap = cldap;
109
+
110
+ rb_iv_set (self, "@args", rb_ary_new4 (argc, argv));
111
+
112
+ /* Silence warning that next rb_iv_get produces. */
113
+ if (ruby_verbose == Qtrue)
114
+ {
115
+ was_verbose = Qtrue;
116
+ ruby_verbose = Qfalse;
117
+ }
118
+
119
+ if (rb_iv_get (self, "@sasl_quiet") != Qtrue)
120
+ rb_iv_set (self, "@sasl_quiet", Qfalse);
121
+ if (was_verbose == Qtrue)
122
+ ruby_verbose = Qtrue;
123
+
124
+ return Qnil;
125
+ };
126
+
127
+ /*
128
+ * call-seq:
129
+ * LDAP::Conn.open(host='localhost', port=LDAP_PORT) => LDAP::Conn
130
+ *
131
+ * Return a new LDAP::Conn connection to the server, +host+, on port +port+.
132
+ */
133
+ VALUE
134
+ rb_ldap_conn_s_open (int argc, VALUE argv[], VALUE klass)
135
+ {
136
+ LDAP *cldap;
137
+ char *chost;
138
+ int cport;
139
+
140
+ VALUE host, port;
141
+ VALUE conn;
142
+
143
+ switch (rb_scan_args (argc, argv, "02", &host, &port))
144
+ {
145
+ case 0:
146
+ chost = ALLOCA_N (char, strlen ("localhost") + 1);
147
+ strcpy (chost, "localhost");
148
+ cport = LDAP_PORT;
149
+ break;
150
+ case 1:
151
+ chost = StringValueCStr (host);
152
+ cport = LDAP_PORT;
153
+ break;
154
+ case 2:
155
+ chost = StringValueCStr (host);
156
+ cport = NUM2INT (port);
157
+ break;
158
+ default:
159
+ rb_bug ("rb_ldap_conn_new");
160
+ };
161
+
162
+ cldap = ldap_open (chost, cport);
163
+ if (!cldap)
164
+ rb_raise (rb_eLDAP_ResultError, "can't open an LDAP session");
165
+ conn = rb_ldap_conn_new (klass, cldap);
166
+
167
+ return conn;
168
+ };
169
+
170
+ /*
171
+ * call-seq:
172
+ * conn.start_tls => nil
173
+ *
174
+ * Initiate START_TLS for the connection, +conn+.
175
+ */
176
+ VALUE
177
+ rb_ldap_conn_start_tls_s (int argc, VALUE argv[], VALUE self)
178
+ {
179
+ #ifdef HAVE_LDAP_START_TLS_S
180
+ VALUE arg1, arg2;
181
+ RB_LDAP_DATA *ldapdata;
182
+ LDAPControl **serverctrls;
183
+ LDAPControl **clientctrls;
184
+
185
+ switch (rb_scan_args (argc, argv, "02", &arg1, &arg2))
186
+ {
187
+ case 0:
188
+ serverctrls = NULL;
189
+ clientctrls = NULL;
190
+ break;
191
+ case 1:
192
+ case 2:
193
+ rb_notimplement ();
194
+ default:
195
+ rb_bug ("rb_ldap_conn_start_tls_s");
196
+ };
197
+
198
+ GET_LDAP_DATA (self, ldapdata);
199
+ ldapdata->err = ldap_start_tls_s (ldapdata->ldap, serverctrls, clientctrls);
200
+ Check_LDAP_Result (ldapdata->err);
201
+ #else
202
+ rb_notimplement ();
203
+ #endif
204
+ return Qnil;
205
+ };
206
+
207
+ VALUE
208
+ rb_ldap_conn_rebind (VALUE self)
209
+ {
210
+ VALUE ary = rb_iv_get (self, "@args");
211
+
212
+ if (rb_obj_is_kind_of (self, rb_cLDAP_SSLConn) == Qtrue)
213
+ return rb_ldap_sslconn_initialize (RARRAY_LEN (ary), RARRAY_PTR (ary),
214
+ self);
215
+ else
216
+ return rb_ldap_conn_initialize (RARRAY_LEN (ary), RARRAY_PTR (ary),
217
+ self);
218
+ }
219
+
220
+ /*
221
+ * call-seq:
222
+ * conn.simple_bind(dn=nil, password=nil) => self
223
+ * conn.simple_bind(dn=nil, password=nil) { |conn| } => nil
224
+ *
225
+ * Bind an LDAP connection, using the DN, +dn+, and the credential, +password+.
226
+ * If a block is given, +self+ is yielded to the block.
227
+ */
228
+ VALUE
229
+ rb_ldap_conn_simple_bind_s (int argc, VALUE argv[], VALUE self)
230
+ {
231
+ RB_LDAP_DATA *ldapdata;
232
+
233
+ VALUE arg1, arg2;
234
+ char *dn = NULL;
235
+ char *passwd = NULL;
236
+
237
+ Data_Get_Struct (self, RB_LDAP_DATA, ldapdata);
238
+ if (!ldapdata->ldap)
239
+ {
240
+ if (rb_iv_get (self, "@args") != Qnil)
241
+ {
242
+ rb_ldap_conn_rebind (self);
243
+ GET_LDAP_DATA (self, ldapdata);
244
+ }
245
+ else
246
+ {
247
+ rb_raise (rb_eLDAP_InvalidDataError,
248
+ "The LDAP handler has already unbound.");
249
+ }
250
+ }
251
+
252
+ if (ldapdata->bind)
253
+ {
254
+ rb_raise (rb_eLDAP_Error, "already bound.");
255
+ };
256
+ switch (rb_scan_args (argc, argv, "02", &arg1, &arg2))
257
+ {
258
+ case 0:
259
+ break;
260
+ case 1:
261
+ if (arg1 == Qnil)
262
+ {
263
+ dn = NULL;
264
+ }
265
+ else
266
+ {
267
+ dn = StringValueCStr (arg1);
268
+ }
269
+ break;
270
+ case 2:
271
+ if (arg1 == Qnil)
272
+ {
273
+ dn = NULL;
274
+ }
275
+ else
276
+ {
277
+ dn = StringValueCStr (arg1);
278
+ }
279
+ if (arg2 == Qnil)
280
+ {
281
+ passwd = NULL;
282
+ }
283
+ else
284
+ {
285
+ passwd = StringValueCStr (arg2);
286
+ }
287
+ break;
288
+ default:
289
+ rb_bug ("rb_ldap_conn_simple_bind_s");
290
+ }
291
+
292
+ ldapdata->err = ldap_simple_bind_s (ldapdata->ldap, dn, passwd);
293
+ Check_LDAP_Result (ldapdata->err);
294
+ ldapdata->bind = 1;
295
+
296
+ if (rb_block_given_p ())
297
+ {
298
+ rb_ensure (rb_yield, self, rb_ldap_conn_unbind, self);
299
+ return Qnil;
300
+ }
301
+ else
302
+ {
303
+ return self;
304
+ };
305
+ };
306
+
307
+ /*
308
+ * call-seq:
309
+ * conn.bind(dn=nil, password=nil, method=LDAP::LDAP_AUTH_SIMPLE)
310
+ * => self
311
+ * conn.bind(dn=nil, password=nil, method=LDAP::LDAP_AUTH_SIMPLE)
312
+ * { |conn| } => nil
313
+ *
314
+ * Bind an LDAP connection, using the DN, +dn+, the credential, +password+,
315
+ * and the bind method, +method+. If a block is given, +self+ is yielded to
316
+ * the block.
317
+ */
318
+ VALUE
319
+ rb_ldap_conn_bind_s (int argc, VALUE argv[], VALUE self)
320
+ {
321
+ RB_LDAP_DATA *ldapdata;
322
+
323
+ VALUE arg1, arg2, arg3;
324
+ char *dn = NULL;
325
+ char *passwd = NULL;
326
+ int method = LDAP_AUTH_SIMPLE;
327
+
328
+ Data_Get_Struct (self, RB_LDAP_DATA, ldapdata);
329
+ if (!ldapdata->ldap)
330
+ {
331
+ if (rb_iv_get (self, "@args") != Qnil)
332
+ {
333
+ rb_ldap_conn_rebind (self);
334
+ GET_LDAP_DATA (self, ldapdata);
335
+ }
336
+ else
337
+ {
338
+ rb_raise (rb_eLDAP_InvalidDataError,
339
+ "The LDAP handler has already unbound.");
340
+ }
341
+ }
342
+
343
+ if (ldapdata->bind)
344
+ {
345
+ rb_raise (rb_eLDAP_Error, "already bound.");
346
+ };
347
+ switch (rb_scan_args (argc, argv, "03", &arg1, &arg2, &arg3))
348
+ {
349
+ case 0:
350
+ break;
351
+ case 1:
352
+ dn = StringValueCStr (arg1);
353
+ break;
354
+ case 2:
355
+ dn = StringValueCStr (arg1);
356
+ passwd = StringValueCStr (arg2);
357
+ break;
358
+ case 3:
359
+ dn = StringValueCStr (arg1);
360
+ passwd = StringValueCStr (arg2);
361
+ method = NUM2INT (arg3);
362
+ break;
363
+ default:
364
+ rb_bug ("rb_ldap_conn_bind_s");
365
+ }
366
+
367
+ ldapdata->err = ldap_bind_s (ldapdata->ldap, dn, passwd, method);
368
+ Check_LDAP_Result (ldapdata->err);
369
+ ldapdata->bind = 1;
370
+
371
+ if (rb_block_given_p ())
372
+ {
373
+ rb_ensure (rb_yield, self, rb_ldap_conn_unbind, self);
374
+ return Qnil;
375
+ }
376
+ else
377
+ {
378
+ return self;
379
+ };
380
+ };
381
+
382
+ /*
383
+ * call-seq:
384
+ * conn.unbind => nil
385
+ *
386
+ * Unbind the LDAP connection from the server.
387
+ */
388
+ VALUE
389
+ rb_ldap_conn_unbind (VALUE self)
390
+ {
391
+ RB_LDAP_DATA *ldapdata;
392
+
393
+ GET_LDAP_DATA (self, ldapdata);
394
+ ldapdata->err = ldap_unbind (ldapdata->ldap);
395
+ ldapdata->bind = 0;
396
+ ldapdata->ldap = NULL;
397
+ Check_LDAP_Result (ldapdata->err);
398
+
399
+ return Qnil;
400
+ };
401
+
402
+ /*
403
+ * call-seq:
404
+ * conn.bound? => true or false
405
+ *
406
+ * Return *true* if the LDAP connection is still bound.
407
+ */
408
+ VALUE
409
+ rb_ldap_conn_bound (VALUE self)
410
+ {
411
+ RB_LDAP_DATA *ldapdata;
412
+
413
+ Data_Get_Struct (self, RB_LDAP_DATA, ldapdata);
414
+
415
+ return ldapdata->bind == 0 ? Qfalse : Qtrue;
416
+ };
417
+
418
+ /*
419
+ * call-seq:
420
+ * conn.set_option(option, data) => self
421
+ *
422
+ * Set a session-wide option for this LDAP connection.
423
+ *
424
+ * For example:
425
+ *
426
+ * <code>conn.set_option( LDAP::LDAP_OPT_PROTOCOL_VERSION, 3 )</code>
427
+ *
428
+ * would set the protocol of this connection to LDAPv3.
429
+ */
430
+ VALUE
431
+ rb_ldap_conn_set_option (VALUE self, VALUE opt, VALUE data)
432
+ {
433
+ /* ldap_set_option() is defined in IETF draft */
434
+ #ifdef HAVE_LDAP_SET_OPTION
435
+ RB_LDAP_DATA *ldapdata;
436
+ RB_LDAP_DATA dummy;
437
+ int idata;
438
+ void *optdata;
439
+ int copt;
440
+
441
+ if (NIL_P (self))
442
+ {
443
+ dummy.ldap = NULL;
444
+ dummy.err = dummy.bind = 0;
445
+ ldapdata = &dummy;
446
+ }
447
+ else
448
+ GET_LDAP_DATA (self, ldapdata);
449
+ copt = NUM2INT (opt);
450
+
451
+ switch (copt)
452
+ {
453
+ case LDAP_OPT_REFERRALS:
454
+ optdata = (void *) NUM2INT (data);
455
+ break;
456
+ case LDAP_OPT_DEREF:
457
+ case LDAP_OPT_SIZELIMIT:
458
+ case LDAP_OPT_TIMELIMIT:
459
+ case LDAP_OPT_RESTART:
460
+ case LDAP_OPT_PROTOCOL_VERSION:
461
+ if (ldapdata->bind != 0)
462
+ rb_raise (rb_eLDAP_ResultError,
463
+ "can't set LDAP protocol version after bind");
464
+ case LDAP_OPT_ERROR_NUMBER:
465
+ #ifdef LDAP_OPT_SSL
466
+ case LDAP_OPT_SSL:
467
+ #endif
468
+ #ifdef USE_OPENLDAP2
469
+ #ifdef LDAP_OPT_X_TLS
470
+ case LDAP_OPT_X_TLS:
471
+ #endif
472
+ #ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
473
+ case LDAP_OPT_X_TLS_REQUIRE_CERT:
474
+ #endif
475
+ #endif
476
+ idata = NUM2INT (data);
477
+ optdata = &idata;
478
+ break;
479
+ case LDAP_OPT_HOST_NAME:
480
+ case LDAP_OPT_ERROR_STRING:
481
+ #ifdef LDAP_OPT_MATCHED_DN
482
+ case LDAP_OPT_MATCHED_DN:
483
+ #endif
484
+ #ifdef USE_OPENLDAP2
485
+ #ifdef LDAP_OPT_X_TLS_CACERTFILE
486
+ case LDAP_OPT_X_TLS_CACERTFILE:
487
+ #endif
488
+ #ifdef LDAP_OPT_X_TLS_CACERTDIR
489
+ case LDAP_OPT_X_TLS_CACERTDIR:
490
+ #endif
491
+ #ifdef LDAP_OPT_X_TLS_CERT
492
+ case LDAP_OPT_X_TLS_CERT:
493
+ #endif
494
+ #ifdef LDAP_OPT_X_TLS_CERTFILE
495
+ case LDAP_OPT_X_TLS_CERTFILE:
496
+ #endif
497
+ #ifdef LDAP_OPT_X_TLS_KEYFILE
498
+ case LDAP_OPT_X_TLS_KEYFILE:
499
+ #endif
500
+ #ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
501
+ case LDAP_OPT_X_TLS_PROTOCOL_MIN:
502
+ #endif
503
+ #ifdef LDAP_OPT_X_TLS_CIPHER_SUITE
504
+ case LDAP_OPT_X_TLS_CIPHER_SUITE:
505
+ #endif
506
+ #ifdef LDAP_OPT_X_TLS_RANDOM_FILE
507
+ case LDAP_OPT_X_TLS_RANDOM_FILE:
508
+ #endif
509
+ #endif
510
+ optdata = NIL_P (data) ? NULL : StringValueCStr (data);
511
+ break;
512
+ #ifdef LDAP_OPT_API_INFO
513
+ case LDAP_OPT_API_INFO:
514
+ rb_raise (rb_eLDAP_Error, "option is read-only");
515
+ /* optdata = (void*)rb_ldap_get_apiinfo(data); */
516
+ break;
517
+ #endif
518
+ #ifdef LDAP_OPT_SERVER_CONTROLS
519
+ case LDAP_OPT_SERVER_CONTROLS:
520
+ optdata = rb_ldap_get_controls (data);
521
+ break;
522
+ #endif
523
+ default:
524
+ rb_notimplement ();
525
+ }
526
+ ldapdata->err = ldap_set_option (ldapdata->ldap, copt, optdata);
527
+ Check_LDAP_OPT_Result (ldapdata->err);
528
+
529
+ return self;
530
+ #else
531
+ rb_notimplement ();
532
+ #endif
533
+ };
534
+
535
+ static VALUE
536
+ rb_ldap_conn_s_set_option (VALUE klass, VALUE opt, VALUE data)
537
+ {
538
+ return rb_ldap_conn_set_option (Qnil, opt, data);
539
+ }
540
+
541
+ /* call-seq:
542
+ * conn.get_option(opt) => String
543
+ *
544
+ * Return the value associated with the option, +opt+.
545
+ */
546
+ VALUE
547
+ rb_ldap_conn_get_option (VALUE self, VALUE opt)
548
+ {
549
+ #ifdef HAVE_LDAP_GET_OPTION
550
+ RB_LDAP_DATA *ldapdata;
551
+ static RB_LDAP_DATA dummy = { NULL, 0, 0 };
552
+ long *data;
553
+ int copt;
554
+ VALUE val;
555
+
556
+ if (NIL_P (self))
557
+ {
558
+ if (dummy.ldap == NULL)
559
+ dummy.ldap = ldap_init ("", 0);
560
+ ldapdata = &dummy;
561
+ }
562
+ else
563
+ GET_LDAP_DATA (self, ldapdata);
564
+ copt = NUM2INT (opt);
565
+
566
+ #if defined(LDAP_OPT_API_INFO) && defined(LDAP_API_INFO_VERSION)
567
+ if (copt == LDAP_OPT_API_INFO)
568
+ {
569
+ LDAPAPIInfo *info;
570
+
571
+ info = ALLOCA_N (LDAPAPIInfo, 1);
572
+ /* This is from the Netscape SDK docs for 4.1* */
573
+ info->ldapai_info_version = LDAP_API_INFO_VERSION;
574
+ ldapdata->err = ldap_get_option (NULL, copt, (void *) info);
575
+ data = (long *) info;
576
+ }
577
+ else
578
+ {
579
+ data = (void *) ALLOCA_N (char, LDAP_GET_OPT_MAX_BUFFER_SIZE);
580
+ ldapdata->err = ldap_get_option (ldapdata->ldap, copt, (void *) data);
581
+ }
582
+ #else
583
+ data = (void *) ALLOCA_N (char, LDAP_GET_OPT_MAX_BUFFER_SIZE);
584
+ ldapdata->err = ldap_get_option (ldapdata->ldap, copt, (void *) data);
585
+ #endif
586
+
587
+ if (ldapdata->err == LDAP_OPT_SUCCESS)
588
+ {
589
+ switch (copt)
590
+ {
591
+ case LDAP_OPT_DEREF:
592
+ case LDAP_OPT_SIZELIMIT:
593
+ case LDAP_OPT_TIMELIMIT:
594
+ case LDAP_OPT_REFERRALS:
595
+ case LDAP_OPT_RESTART:
596
+ case LDAP_OPT_PROTOCOL_VERSION:
597
+ case LDAP_OPT_ERROR_NUMBER:
598
+ #ifdef USE_OPENLDAP2
599
+ #ifdef LDAP_OPT_X_TLS
600
+ case LDAP_OPT_X_TLS:
601
+ #endif
602
+ #ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
603
+ case LDAP_OPT_X_TLS_REQUIRE_CERT:
604
+ #endif
605
+ #endif
606
+ val = INT2NUM ((int) (*data));
607
+ break;
608
+
609
+ case LDAP_OPT_HOST_NAME:
610
+ case LDAP_OPT_ERROR_STRING:
611
+ #ifdef LDAP_OPT_MATCHED_DN
612
+ case LDAP_OPT_MATCHED_DN:
613
+ #endif
614
+ #ifdef USE_OPENLDAP2
615
+ #ifdef LDAP_OPT_X_TLS_CACERTFILE
616
+ case LDAP_OPT_X_TLS_CACERTFILE:
617
+ #endif
618
+ #ifdef LDAP_OPT_X_TLS_CACERTDIR
619
+ case LDAP_OPT_X_TLS_CACERTDIR:
620
+ #endif
621
+ #ifdef LDAP_OPT_X_TLS_CERT
622
+ case LDAP_OPT_X_TLS_CERT:
623
+ #endif
624
+ #ifdef LDAP_OPT_X_TLS_CERTFILE
625
+ case LDAP_OPT_X_TLS_CERTFILE:
626
+ #endif
627
+ #ifdef LDAP_OPT_X_TLS_KEYFILE
628
+ case LDAP_OPT_X_TLS_KEYFILE:
629
+ #endif
630
+ #ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
631
+ case LDAP_OPT_X_TLS_PROTOCOL_MIN:
632
+ #endif
633
+ #ifdef LDAP_OPT_X_TLS_CIPHER_SUITE
634
+ case LDAP_OPT_X_TLS_CIPHER_SUITE:
635
+ #endif
636
+ #ifdef LDAP_OPT_X_TLS_RANDOM_FILE
637
+ case LDAP_OPT_X_TLS_RANDOM_FILE:
638
+ #endif
639
+ #endif
640
+ val = (data
641
+ && *data) ? rb_tainted_str_new2 ((char *) (*data)) : Qnil;
642
+ break;
643
+ #ifdef LDAP_OPT_API_INFO
644
+ case LDAP_OPT_API_INFO:
645
+ val = rb_ldap_apiinfo_new ((LDAPAPIInfo *) data);
646
+ break;
647
+ #endif
648
+ default:
649
+ rb_notimplement ();
650
+ };
651
+
652
+ return val;
653
+ }
654
+ else
655
+ {
656
+ rb_raise (rb_eLDAP_Error, ldap_err2string (ldapdata->err));
657
+ };
658
+ #else
659
+ rb_notimplement ();
660
+ #endif
661
+ };
662
+
663
+ static VALUE
664
+ rb_ldap_conn_s_get_option (VALUE klass, VALUE opt)
665
+ {
666
+ return rb_ldap_conn_get_option (Qnil, opt);
667
+ }
668
+
669
+ /*
670
+ * call-seq:
671
+ * conn.perror(msg) => nil
672
+ *
673
+ * Print the text string associated with the error code of the last LDAP
674
+ * operation. +msg+ is used to prefix the error.
675
+ */
676
+ VALUE
677
+ rb_ldap_conn_perror (VALUE self, VALUE msg)
678
+ {
679
+ RB_LDAP_DATA *ldapdata;
680
+ char *cmsg;
681
+ #if (! defined(HAVE_LDAP_PERROR)) || defined(USE_NETSCAPE_SDK)
682
+ char *str;
683
+ #endif
684
+
685
+ GET_LDAP_DATA (self, ldapdata);
686
+ cmsg = StringValueCStr (msg);
687
+ #if defined(HAVE_LDAP_PERROR) && (! defined(USE_NETSCAPE_SDK))
688
+ ldap_perror (ldapdata->ldap, cmsg);
689
+ #else
690
+ str = ldap_err2string (ldapdata->err);
691
+ fprintf (stderr, "%s: %s\n", cmsg, str);
692
+ #endif
693
+
694
+ return Qnil;
695
+ };
696
+
697
+ /*
698
+ * call-seq:
699
+ * conn.result2error(msg) => Fixnum
700
+ *
701
+ * Return the error code associated with the LDAP message, +msg+.
702
+ */
703
+ VALUE
704
+ rb_ldap_conn_result2error (VALUE self, VALUE msg)
705
+ {
706
+ RB_LDAP_DATA *ldapdata;
707
+ RB_LDAPENTRY_DATA *edata;
708
+ int cdofree = 0;
709
+
710
+ GET_LDAP_DATA (self, ldapdata);
711
+ Check_Kind (msg, rb_cLDAP_Entry);
712
+ GET_LDAPENTRY_DATA (msg, edata);
713
+
714
+ ldapdata->err = ldap_result2error (ldapdata->ldap, edata->msg, cdofree);
715
+ return INT2NUM (ldapdata->err);
716
+ };
717
+
718
+ /*
719
+ * call-seq:
720
+ * conn.err2string(err) => String
721
+ *
722
+ * Return the text string associated with the LDAP error, +err+.
723
+ */
724
+ VALUE
725
+ rb_ldap_conn_err2string (VALUE self, VALUE err)
726
+ {
727
+ RB_LDAP_DATA *ldapdata;
728
+ int c_err = NUM2INT (err);
729
+ char *str;
730
+
731
+ GET_LDAP_DATA (self, ldapdata);
732
+ str = ldap_err2string (c_err);
733
+ return (str ? rb_tainted_str_new2 (str) : Qnil);
734
+ };
735
+
736
+ VALUE
737
+ rb_ldap_conn_get_errno (VALUE self)
738
+ {
739
+ RB_LDAP_DATA *ldapdata;
740
+ VALUE err;
741
+
742
+ GET_LDAP_DATA (self, ldapdata);
743
+
744
+ #ifdef USE_NETSCAPE_SDK
745
+ cerr = ldap_get_lderrno (ldapdata->ldap, NULL, NULL);
746
+ err = INT2NUM (cerr);
747
+ #else
748
+ # ifdef USE_OPENLDAP1
749
+ cerr = NUM2INT (ldapdata->ldap->ld_errno);
750
+ err = INT2NUM (cerr);
751
+ # else
752
+ rb_notimplement ();
753
+ # endif
754
+ #endif
755
+
756
+ return err;
757
+ };
758
+
759
+ static VALUE
760
+ rb_ldap_conn_invalidate_entry (VALUE msg)
761
+ {
762
+ RB_LDAPENTRY_DATA *edata;
763
+ GET_LDAPENTRY_DATA (msg, edata);
764
+ edata->ldap = NULL;
765
+ edata->msg = NULL;
766
+ return Qnil;
767
+ };
768
+
769
+
770
+ static int
771
+ rb_ldap_internal_strcmp (const char *left, const char *right)
772
+ {
773
+ VALUE res;
774
+
775
+ if (rb_ldap_sort_obj == Qtrue)
776
+ {
777
+ res = rb_funcall (rb_tainted_str_new2 (left), rb_intern ("<=>"), 1,
778
+ rb_tainted_str_new2 (right));
779
+ }
780
+ else if (rb_ldap_sort_obj != Qnil)
781
+ {
782
+ res = rb_funcall (rb_ldap_sort_obj, rb_intern ("call"), 2,
783
+ rb_tainted_str_new2 (left),
784
+ rb_tainted_str_new2 (right));
785
+ }
786
+ else
787
+ {
788
+ res = 0;
789
+ };
790
+
791
+ return INT2NUM (res);
792
+ };
793
+
794
+ static int
795
+ rb_ldap_conn_search_i (int argc, VALUE argv[], VALUE self,
796
+ RB_LDAP_DATA ** ldapdata, LDAPMessage ** cmsg)
797
+ {
798
+ VALUE base, scope, filter, attrs, attrsonly, sec, usec, s_attr, s_proc;
799
+
800
+ LDAP *cldap;
801
+ char *cbase;
802
+ int cscope;
803
+ char *cfilter;
804
+ char **cattrs;
805
+ char *sort_attr;
806
+ int cattrsonly;
807
+ int i;
808
+ struct timeval tv;
809
+
810
+ GET_LDAP_DATA (self, (*ldapdata));
811
+ cldap = (*ldapdata)->ldap;
812
+
813
+ cattrs = NULL;
814
+ cattrsonly = 0;
815
+ tv.tv_sec = 0;
816
+ tv.tv_usec = 0;
817
+ sort_attr = NULL;
818
+ rb_ldap_sort_obj = Qnil;
819
+
820
+ switch (rb_scan_args (argc, argv, "36",
821
+ &base, &scope, &filter, &attrs, &attrsonly, &sec,
822
+ &usec, &s_attr, &s_proc))
823
+ {
824
+ case 9:
825
+ rb_ldap_sort_obj = s_proc; /* Ruby's GC never starts in a C function */
826
+ case 8:
827
+ if (rb_ldap_sort_obj == Qnil)
828
+ {
829
+ rb_ldap_sort_obj = Qtrue;
830
+ }
831
+ sort_attr = StringValueCStr (s_attr);
832
+ case 7:
833
+ tv.tv_usec = NUM2INT (usec);
834
+ case 6:
835
+ tv.tv_sec = NUM2INT (sec);
836
+ case 5:
837
+ cattrsonly = (attrsonly == Qtrue) ? 1 : 0;
838
+ case 4:
839
+ if (TYPE (attrs) == T_NIL)
840
+ {
841
+ cattrs = NULL;
842
+ }
843
+ else
844
+ {
845
+ if (TYPE (attrs) == T_STRING)
846
+ attrs = rb_ary_to_ary (attrs);
847
+ else
848
+ Check_Type (attrs, T_ARRAY);
849
+
850
+ if (RARRAY_LEN (attrs) == 0)
851
+ {
852
+ cattrs = NULL;
853
+ }
854
+ else
855
+ {
856
+ cattrs = ALLOCA_N (char *, (RARRAY_LEN (attrs) + 1));
857
+ for (i = 0; i < RARRAY_LEN (attrs); i++)
858
+ {
859
+ cattrs[i] = StringValueCStr (RARRAY_PTR (attrs)[i]);
860
+ };
861
+ cattrs[RARRAY_LEN (attrs)] = NULL;
862
+ }
863
+ }
864
+ case 3:
865
+ cbase = StringValueCStr (base);
866
+ cscope = NUM2INT (scope);
867
+ cfilter = StringValueCStr (filter);
868
+ break;
869
+ default:
870
+ rb_bug ("rb_ldap_conn_search_s");
871
+ };
872
+
873
+ (*cmsg) = NULL;
874
+ if (tv.tv_sec == 0 && tv.tv_usec == 0)
875
+ {
876
+ (*ldapdata)->err = ldap_search_s (cldap, cbase, cscope, cfilter,
877
+ cattrs, cattrsonly, cmsg);
878
+ }
879
+ else
880
+ {
881
+ (*ldapdata)->err = ldap_search_st (cldap, cbase, cscope, cfilter,
882
+ cattrs, cattrsonly, &tv, cmsg);
883
+ }
884
+ if (!(cmsg && (*cmsg)))
885
+ {
886
+ rb_raise (rb_eRuntimeError, "no result returned by search");
887
+ }
888
+ Check_LDAP_Result ((*ldapdata)->err);
889
+
890
+ #ifdef HAVE_LDAP_SORT_ENTRIES
891
+ if (rb_ldap_sort_obj != Qnil)
892
+ {
893
+ ldap_sort_entries ((*ldapdata)->ldap, cmsg,
894
+ sort_attr, rb_ldap_internal_strcmp);
895
+ };
896
+ #endif
897
+ rb_ldap_sort_obj = Qnil;
898
+
899
+ return (*ldapdata)->err;
900
+ }
901
+
902
+ static VALUE
903
+ rb_ldap_conn_search_b (VALUE rdata)
904
+ {
905
+ void **data = (void **) rdata;
906
+ LDAP *cldap = (LDAP *) data[0];
907
+ LDAPMessage *cmsg = (LDAPMessage *) data[1];
908
+ LDAPMessage *e;
909
+ VALUE m;
910
+
911
+ for (e = ldap_first_entry (cldap, cmsg); e != NULL;
912
+ e = ldap_next_entry (cldap, e))
913
+ {
914
+ m = rb_ldap_entry_new (cldap, e);
915
+ rb_ensure (rb_yield, m, rb_ldap_conn_invalidate_entry, m);
916
+ }
917
+ return Qnil;
918
+ }
919
+
920
+ static VALUE
921
+ rb_ldap_conn_search2_b (VALUE rdata)
922
+ {
923
+ void **data = (void *) rdata;
924
+ LDAP *cldap = (LDAP *) data[0];
925
+ LDAPMessage *cmsg = (LDAPMessage *) data[1];
926
+ VALUE ary = (VALUE) data[2];
927
+ LDAPMessage *e;
928
+ VALUE m;
929
+ VALUE hash;
930
+
931
+ for (e = ldap_first_entry (cldap, cmsg); e != NULL;
932
+ e = ldap_next_entry (cldap, e))
933
+ {
934
+ m = rb_ldap_entry_new (cldap, e);
935
+ hash = rb_ldap_entry_to_hash (m);
936
+ rb_ary_push (ary, hash);
937
+ if (rb_block_given_p ())
938
+ {
939
+ rb_ensure (rb_yield, hash, rb_ldap_conn_invalidate_entry, m);
940
+ }
941
+ }
942
+ return Qnil;
943
+ }
944
+
945
+ static VALUE
946
+ rb_ldap_msgfree (VALUE data)
947
+ {
948
+ LDAPMessage *cmsg = (LDAPMessage *) data;
949
+ ldap_msgfree (cmsg);
950
+ return Qnil;
951
+ }
952
+
953
+ VALUE
954
+ rb_ldap_parse_result (LDAP * cldap, LDAPMessage * cmsg)
955
+ {
956
+ int rc, err, i;
957
+ char **referrals;
958
+ LDAPControl **serverctrls;
959
+ VALUE refs, ctls, ary;
960
+
961
+ refs = rb_ary_new ();
962
+ ctls = rb_ary_new ();
963
+ ary = rb_ary_new ();
964
+
965
+ rc = ldap_parse_result (cldap, cmsg, &err, NULL, NULL,
966
+ &referrals, &serverctrls, 0);
967
+ Check_LDAP_Result (rc);
968
+ Check_LDAP_Result (err);
969
+
970
+ if (referrals)
971
+ {
972
+ for (i = 0; referrals[i]; i++)
973
+ {
974
+ rb_ary_push (refs, rb_str_new2 (referrals[i]));
975
+ }
976
+ }
977
+
978
+ if (serverctrls)
979
+ {
980
+ for (i = 0; serverctrls[i]; i++)
981
+ {
982
+ rb_ary_push (ctls, rb_ldap_control_new2 (serverctrls[i]));
983
+ }
984
+ }
985
+
986
+ rb_ary_push (ary, refs);
987
+ rb_ary_push (ary, ctls);
988
+
989
+ return ary;
990
+ }
991
+
992
+ /*
993
+ * call-seq:
994
+ * conn.search(base_dn, scope, filter, attrs=nil, attrsonly=false,
995
+ * sec=0, usec=0, s_attr=nil, s_proc=nil) { |entry| } => self
996
+ *
997
+ * Perform a search, with the base DN +base_dn+, a scope of +scope+ and a
998
+ * search filter of +filter+.
999
+ *
1000
+ * If +attrs+ is present, it should be an array of the attributes that the
1001
+ * search should return. By default, all attributes are returned, which is the
1002
+ * same as specifying an empty array or *nil*. Alternatively, +attrs+ may be a
1003
+ * single string, in which case it will be treated as a single element array.
1004
+ *
1005
+ * If +attrsonly+ is *true*, attributes will be returned, but not their values.
1006
+ *
1007
+ * If +sec+ and/or +usec+ are given, they define the time-out for the search in
1008
+ * seconds and microseconds, respectively.
1009
+ *
1010
+ * If +s_attr+ is given, it specifies the attribute on which to sort the
1011
+ * entries returned by the server. If +s_proc+ is given, it specifies a Proc
1012
+ * object that will be used to sort the entries returned by the server.
1013
+ *
1014
+ * Note that not all results may be returned by this method. If a
1015
+ * size limit has been set for the number of results to be returned and this
1016
+ * limit is exceeded, the results set will be truncated. You can check for
1017
+ * this by calling LDAP::Conn#err immediately after this method and comparing
1018
+ * the result to LDAP::LDAP_SIZELIMIT_EXCEEDED.
1019
+ */
1020
+ VALUE
1021
+ rb_ldap_conn_search_s (int argc, VALUE argv[], VALUE self)
1022
+ {
1023
+ RB_LDAP_DATA *ldapdata;
1024
+ LDAPMessage *cmsg;
1025
+ LDAP *cldap;
1026
+ VALUE rc_ary = Qnil;
1027
+
1028
+ rb_ldap_conn_search_i (argc, argv, self, &ldapdata, &cmsg);
1029
+ cldap = ldapdata->ldap;
1030
+
1031
+ if (ldapdata->err == LDAP_SUCCESS
1032
+ || ldapdata->err == LDAP_SIZELIMIT_EXCEEDED)
1033
+ {
1034
+ void *pass_data[] = { (void *) cldap, (void *) cmsg };
1035
+
1036
+ rc_ary = rb_ldap_parse_result (cldap, cmsg);
1037
+ rb_iv_set (self, "@referrals", rb_ary_shift (rc_ary));
1038
+ rb_iv_set (self, "@controls", rb_ary_shift (rc_ary));
1039
+
1040
+ rb_ensure (rb_ldap_conn_search_b, (VALUE) pass_data,
1041
+ rb_ldap_msgfree, (VALUE) cmsg);
1042
+ };
1043
+
1044
+ return self;
1045
+ }
1046
+
1047
+ /*
1048
+ * call-seq:
1049
+ * conn.search2(base_dn, scope, filter, attrs=nil, attrsonly=false,
1050
+ * sec=0, usec=0, s_attr=nil, s_proc=nil) => array
1051
+ * conn.search2(base_dn, scope, filter, attrs=nil, attrsonly=false,
1052
+ * sec=0, usec=0, s_attr=nil, s_proc=nil) { |entry_as_hash| } => self
1053
+ *
1054
+ * Perform a search, with the base DN +base_dn+, a scope of +scope+ and a
1055
+ * search filter of +filter+.
1056
+ *
1057
+ * If +attrs+ is present, it should be an array of the attributes that the
1058
+ * search should return. By default, all attributes are returned, which is the
1059
+ * same as specifying an empty array or *nil*. Alternatively, +attrs+ may be a
1060
+ * single string, in which case it will be treated as a single element array.
1061
+ *
1062
+ * If +attrsonly+ is *true*, attributes will be returned, but not their values.
1063
+ *
1064
+ * If +sec+ and/or +usec+ are given, they define the time-out for the search in
1065
+ * seconds and microseconds, respectively.
1066
+ *
1067
+ * If +s_attr+ is given, it specifies the attribute on which to sort the
1068
+ * entries returned by the server. If +s_proc+ is given, it specifies a Proc
1069
+ * object that will be used to sort the entries returned by the server.
1070
+ *
1071
+ * Note that not all results may be returned by this method. If a
1072
+ * size limit has been set for the number of results to be returned and this
1073
+ * limit is exceeded, the results set will be truncated. You can check for
1074
+ * this by calling LDAP::Conn#err immediately after this method and comparing
1075
+ * the result to LDAP::LDAP_SIZELIMIT_EXCEEDED.
1076
+ */
1077
+ VALUE
1078
+ rb_ldap_conn_search2_s (int argc, VALUE argv[], VALUE self)
1079
+ {
1080
+ RB_LDAP_DATA *ldapdata;
1081
+ LDAPMessage *cmsg;
1082
+ LDAP *cldap;
1083
+ VALUE ary = Qnil;
1084
+ VALUE rc_ary = Qnil;
1085
+
1086
+ rb_ldap_conn_search_i (argc, argv, self, &ldapdata, &cmsg);
1087
+ cldap = ldapdata->ldap;
1088
+
1089
+ ary = rb_ary_new ();
1090
+ if (ldapdata->err == LDAP_SUCCESS
1091
+ || ldapdata->err == LDAP_SIZELIMIT_EXCEEDED)
1092
+ {
1093
+ void *pass_data[] = { (void *) cldap, (void *) cmsg, (void *) ary };
1094
+
1095
+ rc_ary = rb_ldap_parse_result (cldap, cmsg);
1096
+ rb_iv_set (self, "@referrals", rb_ary_shift (rc_ary));
1097
+ rb_iv_set (self, "@controls", rb_ary_shift (rc_ary));
1098
+
1099
+ rb_ensure (rb_ldap_conn_search2_b, (VALUE) pass_data,
1100
+ rb_ldap_msgfree, (VALUE) cmsg);
1101
+ }
1102
+
1103
+ if (rb_block_given_p ())
1104
+ {
1105
+ return self;
1106
+ }
1107
+ else
1108
+ {
1109
+ return ary;
1110
+ }
1111
+ }
1112
+
1113
+ #if defined(HAVE_LDAPCONTROL) && defined(HAVE_LDAP_SEARCH_EXT_S)
1114
+ static int
1115
+ rb_ldap_conn_search_ext_i (int argc, VALUE argv[], VALUE self,
1116
+ RB_LDAP_DATA ** ldapdata, LDAPMessage ** cmsg)
1117
+ {
1118
+ VALUE base, scope, filter, attrs, attrsonly;
1119
+ VALUE serverctrls, clientctrls, sec, usec, limit, s_attr, s_proc;
1120
+
1121
+ LDAP *cldap;
1122
+ char *cbase;
1123
+ int cscope;
1124
+ int climit;
1125
+ char *cfilter;
1126
+ char **cattrs;
1127
+ char *sort_attr;
1128
+ int cattrsonly;
1129
+ int i;
1130
+ struct timeval tv;
1131
+ LDAPControl **sctrls, **cctrls;
1132
+
1133
+ GET_LDAP_DATA (self, (*ldapdata));
1134
+ cldap = (*ldapdata)->ldap;
1135
+
1136
+ cattrs = NULL;
1137
+ cattrsonly = 0;
1138
+ cctrls = NULL;
1139
+ sctrls = NULL;
1140
+ tv.tv_sec = 0;
1141
+ tv.tv_usec = 0;
1142
+ sort_attr = NULL;
1143
+ rb_ldap_sort_obj = Qnil;
1144
+ climit = 0;
1145
+
1146
+ switch (rb_scan_args (argc, argv, "39",
1147
+ &base, &scope, &filter, &attrs, &attrsonly,
1148
+ &serverctrls, &clientctrls, &sec, &usec, &limit,
1149
+ &s_attr, &s_proc))
1150
+ {
1151
+ case 12:
1152
+ rb_ldap_sort_obj = s_proc; /* Ruby's GC never start in a C function */
1153
+ case 11:
1154
+ if (rb_ldap_sort_obj == Qnil)
1155
+ {
1156
+ rb_ldap_sort_obj = Qtrue;
1157
+ }
1158
+ sort_attr = StringValueCStr (s_attr);
1159
+ case 10:
1160
+ climit = NUM2INT (limit);
1161
+ case 9:
1162
+ tv.tv_usec = NUM2INT (usec);
1163
+ case 8:
1164
+ tv.tv_sec = NUM2INT (sec);
1165
+ case 7:
1166
+ cctrls = rb_ldap_get_controls (clientctrls);
1167
+ case 6:
1168
+ sctrls = rb_ldap_get_controls (serverctrls);
1169
+ case 5:
1170
+ cattrsonly = (attrsonly == Qtrue) ? 1 : 0;
1171
+ case 4:
1172
+ if (TYPE (attrs) == T_NIL)
1173
+ {
1174
+ cattrs = NULL;
1175
+ }
1176
+ else
1177
+ {
1178
+ if (TYPE (attrs) == T_STRING)
1179
+ attrs = rb_ary_to_ary (attrs);
1180
+ else
1181
+ Check_Type (attrs, T_ARRAY);
1182
+
1183
+ if (RARRAY_LEN (attrs) == 0)
1184
+ {
1185
+ cattrs = NULL;
1186
+ }
1187
+ else
1188
+ {
1189
+ cattrs = ALLOCA_N (char *, (RARRAY_LEN (attrs) + 1));
1190
+ for (i = 0; i < RARRAY_LEN (attrs); i++)
1191
+ {
1192
+ cattrs[i] = StringValueCStr (RARRAY_PTR (attrs)[i]);
1193
+ };
1194
+ cattrs[RARRAY_LEN (attrs)] = NULL;
1195
+ }
1196
+ }
1197
+ case 3:
1198
+ cbase = StringValueCStr (base);
1199
+ cscope = NUM2INT (scope);
1200
+ cfilter = StringValueCStr (filter);
1201
+ break;
1202
+ default:
1203
+ rb_bug ("rb_ldap_conn_search_s");
1204
+ };
1205
+
1206
+ (*cmsg) = NULL;
1207
+ if (tv.tv_sec == 0 && tv.tv_usec == 0)
1208
+ {
1209
+ (*ldapdata)->err = ldap_search_ext_s (cldap, cbase, cscope, cfilter,
1210
+ cattrs, cattrsonly,
1211
+ sctrls, cctrls,
1212
+ NULL, climit, cmsg);
1213
+ }
1214
+ else
1215
+ {
1216
+ (*ldapdata)->err = ldap_search_ext_s (cldap, cbase, cscope, cfilter,
1217
+ cattrs, cattrsonly,
1218
+ sctrls, cctrls,
1219
+ &tv, climit, cmsg);
1220
+ }
1221
+ Check_LDAP_Result ((*ldapdata)->err);
1222
+
1223
+ #ifdef HAVE_LDAP_SORT_ENTRIES
1224
+ if (rb_ldap_sort_obj != Qnil)
1225
+ {
1226
+ ldap_sort_entries ((*ldapdata)->ldap, cmsg,
1227
+ sort_attr, rb_ldap_internal_strcmp);
1228
+ };
1229
+ #endif
1230
+ rb_ldap_sort_obj = Qnil;
1231
+
1232
+ return (*ldapdata)->err;
1233
+ };
1234
+
1235
+ /*
1236
+ * call-seq:
1237
+ * conn.search_ext(base_dn, scope, filter, attrs=nil, attrsonly=false,
1238
+ * sctrls, cctrls, sec=0, usec=0, s_attr=nil, s_proc=nil)
1239
+ * { |entry| } => self
1240
+ *
1241
+ * Perform a search, with the base DN +base_dn+, a scope of +scope+ and a
1242
+ * search filter of +filter+.
1243
+ *
1244
+ * If +attrs+ is present, it should be an array of the attributes that the
1245
+ * search should return. By default, all attributes are returned, which is the
1246
+ * same as specifying an empty array or *nil*. Alternatively, +attrs+ may be a
1247
+ * single string, in which case it will be treated as a single element array.
1248
+ *
1249
+ * If +attrsonly+ is *true*, attributes will be returned, but not their values.
1250
+ *
1251
+ * +sctrls+ is an array of server controls, whilst +cctrls+ is an array of
1252
+ * client controls.
1253
+ *
1254
+ * If +sec+ and/or +usec+ are given, they define the time-out for the search in
1255
+ * seconds and microseconds, respectively.
1256
+ *
1257
+ * If +s_attr+ is given, it specifies the attribute on which to sort the
1258
+ * entries returned by the server. If +s_proc+ is given, it specifies a Proc
1259
+ * object that will be used to sort the entries returned by the server.
1260
+ *
1261
+ * Note that not all results may be returned by this method. If a
1262
+ * size limit has been set for the number of results to be returned and this
1263
+ * limit is exceeded, the results set will be truncated. You can check for
1264
+ * this by calling LDAP::Conn#err immediately after this method and comparing
1265
+ * the result to LDAP::LDAP_SIZELIMIT_EXCEEDED.
1266
+ */
1267
+ VALUE
1268
+ rb_ldap_conn_search_ext_s (int argc, VALUE argv[], VALUE self)
1269
+ {
1270
+ RB_LDAP_DATA *ldapdata;
1271
+ LDAPMessage *cmsg;
1272
+ LDAP *cldap;
1273
+
1274
+ rb_ldap_conn_search_ext_i (argc, argv, self, &ldapdata, &cmsg);
1275
+ cldap = ldapdata->ldap;
1276
+
1277
+ if (ldapdata->err == LDAP_SUCCESS
1278
+ || ldapdata->err == LDAP_SIZELIMIT_EXCEEDED)
1279
+ {
1280
+ void *pass_data[] = { (void *) cldap, (void *) cmsg };
1281
+ rb_ensure (rb_ldap_conn_search_b, (VALUE) pass_data,
1282
+ rb_ldap_msgfree, (VALUE) cmsg);
1283
+ };
1284
+
1285
+ return self;
1286
+ };
1287
+
1288
+ /*
1289
+ * call-seq:
1290
+ * conn.search_ext2(base_dn, scope, filter, attrs=nil,
1291
+ * attrsonly=false, sctrls, cctrls, sec=0, usec=0,
1292
+ * s_attr=nil, s_proc=nil) => array
1293
+ * conn.search_ext2(base_dn, scope, filter, attrs=nil,
1294
+ * attrsonly=false, sctrls, cctrls, sec=0, usec=0,
1295
+ * s_attr=nil, s_proc=nil) { |entry_as_hash| } => self
1296
+ *
1297
+ * Perform a search, with the base DN +base_dn+, a scope of +scope+ and a
1298
+ * search filter of +filter+.
1299
+ *
1300
+ * If +attrs+ is present, it should be an array of the attributes that the
1301
+ * search should return. By default, all attributes are returned, which is the
1302
+ * same as specifying an empty array or *nil*. Alternatively, +attrs+ may be a
1303
+ * single string, in which case it will be treated as a single element array.
1304
+ *
1305
+ * If +attrsonly+ is *true*, attributes will be returned, but not their values.
1306
+ *
1307
+ * +sctrls+ is an array of server controls, whilst +cctrls+ is an array of
1308
+ * client controls.
1309
+ *
1310
+ * If +sec+ and/or +usec+ are given, they define the time-out for the search in
1311
+ * seconds and microseconds, respectively.
1312
+ *
1313
+ * If +s_attr+ is given, it specifies the attribute on which to sort the
1314
+ * entries returned by the server. If +s_proc+ is given, it specifies a Proc
1315
+ * object that will be used to sort the entries returned by the server.
1316
+ *
1317
+ * Note that not all results may be returned by this method. If a
1318
+ * size limit has been set for the number of results to be returned and this
1319
+ * limit is exceeded, the results set will be truncated. You can check for
1320
+ * this by calling LDAP::Conn#err immediately after this method and comparing
1321
+ * the result to LDAP::LDAP_SIZELIMIT_EXCEEDED.
1322
+ */
1323
+ VALUE
1324
+ rb_ldap_conn_search_ext2_s (int argc, VALUE argv[], VALUE self)
1325
+ {
1326
+ RB_LDAP_DATA *ldapdata;
1327
+ LDAPMessage *cmsg;
1328
+ LDAP *cldap;
1329
+ VALUE ary;
1330
+
1331
+ rb_ldap_conn_search_ext_i (argc, argv, self, &ldapdata, &cmsg);
1332
+ cldap = ldapdata->ldap;
1333
+
1334
+ ary = rb_ary_new ();
1335
+ if (ldapdata->err == LDAP_SUCCESS
1336
+ || ldapdata->err == LDAP_SIZELIMIT_EXCEEDED)
1337
+ {
1338
+ void *pass_data[] = { (void *) cldap, (void *) cmsg, (void *) ary };
1339
+ rb_ensure (rb_ldap_conn_search2_b, (VALUE) pass_data,
1340
+ rb_ldap_msgfree, (VALUE) cmsg);
1341
+ }
1342
+
1343
+ if (rb_block_given_p ())
1344
+ {
1345
+ return self;
1346
+ }
1347
+ else
1348
+ {
1349
+ return ary;
1350
+ }
1351
+ }
1352
+ #endif
1353
+
1354
+ /*
1355
+ * call-seq:
1356
+ * conn.add(dn, attrs) => self
1357
+ *
1358
+ * Add an entry with the DN, +dn+, and the attributes, +attrs+. +attrs+
1359
+ * should be either an array of LDAP#Mod objects or a hash of attribute/value
1360
+ * array pairs.
1361
+ */
1362
+ VALUE
1363
+ rb_ldap_conn_add_s (VALUE self, VALUE dn, VALUE attrs)
1364
+ {
1365
+ RB_LDAP_DATA *ldapdata;
1366
+ char *c_dn;
1367
+ LDAPMod **c_attrs;
1368
+ int i;
1369
+
1370
+ switch (TYPE (attrs))
1371
+ {
1372
+ case T_HASH:
1373
+ attrs = rb_ldap_hash2mods (rb_mLDAP,
1374
+ INT2NUM (LDAP_MOD_ADD | LDAP_MOD_BVALUES),
1375
+ attrs);
1376
+ break;
1377
+ case T_ARRAY:
1378
+ break;
1379
+ default:
1380
+ rb_raise (rb_eTypeError, "must be a hash or an array");
1381
+ };
1382
+
1383
+ GET_LDAP_DATA (self, ldapdata);
1384
+ c_dn = StringValueCStr (dn);
1385
+ c_attrs = ALLOCA_N (LDAPMod *, (RARRAY_LEN (attrs) + 1));
1386
+
1387
+ for (i = 0; i < RARRAY_LEN (attrs); i++)
1388
+ {
1389
+ VALUE mod = RARRAY_PTR (attrs)[i];
1390
+ RB_LDAPMOD_DATA *moddata;
1391
+ Check_Kind (mod, rb_cLDAP_Mod);
1392
+ GET_LDAPMOD_DATA (mod, moddata);
1393
+ c_attrs[i] = moddata->mod;
1394
+ };
1395
+ c_attrs[i] = NULL;
1396
+
1397
+ ldapdata->err = ldap_add_s (ldapdata->ldap, c_dn, c_attrs);
1398
+ Check_LDAP_Result (ldapdata->err);
1399
+
1400
+ return self;
1401
+ };
1402
+
1403
+ #if defined(HAVE_LDAPCONTROL) && defined(HAVE_LDAP_ADD_EXT_S)
1404
+ /*
1405
+ * call-seq:
1406
+ * conn.add_ext(dn, attrs, sctrls, cctrls) => self
1407
+ *
1408
+ * Add an entry with the DN, +dn+, and the attributes, +attrs+. +attrs+
1409
+ * should be either an array of LDAP#Mod objects or a hash of attribute/value
1410
+ * array pairs. +sctrls+ is an array of server controls, whilst +cctrls+ is
1411
+ * an array of client controls.
1412
+ */
1413
+ VALUE
1414
+ rb_ldap_conn_add_ext_s (VALUE self, VALUE dn, VALUE attrs,
1415
+ VALUE serverctrls, VALUE clientctrls)
1416
+ {
1417
+ RB_LDAP_DATA *ldapdata;
1418
+ char *c_dn;
1419
+ LDAPMod **c_attrs;
1420
+ int i;
1421
+ LDAPControl **sctrls, **cctrls;
1422
+
1423
+ switch (TYPE (attrs))
1424
+ {
1425
+ case T_HASH:
1426
+ attrs = rb_ldap_hash2mods (rb_mLDAP,
1427
+ INT2NUM (LDAP_MOD_ADD | LDAP_MOD_BVALUES),
1428
+ attrs);
1429
+ break;
1430
+ case T_ARRAY:
1431
+ break;
1432
+ default:
1433
+ rb_raise (rb_eTypeError, "must be a hash or an array");
1434
+ };
1435
+
1436
+ GET_LDAP_DATA (self, ldapdata);
1437
+ c_dn = StringValueCStr (dn);
1438
+ c_attrs = ALLOCA_N (LDAPMod *, (RARRAY_LEN (attrs) + 1));
1439
+ sctrls = rb_ldap_get_controls (serverctrls);
1440
+ cctrls = rb_ldap_get_controls (clientctrls);
1441
+
1442
+ for (i = 0; i < RARRAY_LEN (attrs); i++)
1443
+ {
1444
+ VALUE mod = RARRAY_PTR (attrs)[i];
1445
+ RB_LDAPMOD_DATA *moddata;
1446
+ Check_Kind (mod, rb_cLDAP_Mod);
1447
+ GET_LDAPMOD_DATA (mod, moddata);
1448
+ c_attrs[i] = moddata->mod;
1449
+ };
1450
+ c_attrs[i] = NULL;
1451
+
1452
+ ldapdata->err =
1453
+ ldap_add_ext_s (ldapdata->ldap, c_dn, c_attrs, sctrls, cctrls);
1454
+ Check_LDAP_Result (ldapdata->err);
1455
+
1456
+ return self;
1457
+ }
1458
+ #endif
1459
+
1460
+ /*
1461
+ * call-seq:
1462
+ * conn.modify(dn, mods) => self
1463
+ *
1464
+ * Modify an entry with the DN, +dn+, and the attributes, +mods+. +mods+
1465
+ * should be either an array of LDAP#Mod objects or a hash of attribute/value
1466
+ * array pairs.
1467
+ */
1468
+ VALUE
1469
+ rb_ldap_conn_modify_s (VALUE self, VALUE dn, VALUE attrs)
1470
+ {
1471
+ RB_LDAP_DATA *ldapdata;
1472
+ char *c_dn;
1473
+ LDAPMod **c_attrs;
1474
+ int i;
1475
+
1476
+ switch (TYPE (attrs))
1477
+ {
1478
+ case T_HASH:
1479
+ attrs =
1480
+ rb_ldap_hash2mods (rb_mLDAP,
1481
+ INT2NUM (LDAP_MOD_REPLACE | LDAP_MOD_BVALUES),
1482
+ attrs);
1483
+ break;
1484
+ case T_ARRAY:
1485
+ break;
1486
+ default:
1487
+ rb_raise (rb_eTypeError, "must be a hash or an array");
1488
+ };
1489
+
1490
+ GET_LDAP_DATA (self, ldapdata);
1491
+ c_dn = StringValueCStr (dn);
1492
+ c_attrs = ALLOC_N (LDAPMod *, RARRAY_LEN (attrs) + 1);
1493
+
1494
+ for (i = 0; i < RARRAY_LEN (attrs); i++)
1495
+ {
1496
+ VALUE mod = RARRAY_PTR (attrs)[i];
1497
+ RB_LDAPMOD_DATA *moddata;
1498
+ Check_Kind (mod, rb_cLDAP_Mod);
1499
+ GET_LDAPMOD_DATA (mod, moddata);
1500
+ c_attrs[i] = moddata->mod;
1501
+ };
1502
+ c_attrs[i] = NULL;
1503
+
1504
+ ldapdata->err = ldap_modify_s (ldapdata->ldap, c_dn, c_attrs);
1505
+ Check_LDAP_Result (ldapdata->err);
1506
+
1507
+ return self;
1508
+ };
1509
+
1510
+ #if defined(HAVE_LDAPCONTROL) && defined(HAVE_LDAP_MODIFY_EXT_S)
1511
+ /*
1512
+ * call-seq:
1513
+ * conn.modify_ext(dn, mods, sctrls, cctrls) => self
1514
+ *
1515
+ * Modify an entry with the DN, +dn+, and the attributes, +mods+. +mods+
1516
+ * should be either an array of LDAP#Mod objects or a hash of attribute/value
1517
+ * array pairs. +sctrls+ is an array of server controls, whilst +cctrls+ is
1518
+ * an array of client controls.
1519
+ */
1520
+ VALUE
1521
+ rb_ldap_conn_modify_ext_s (VALUE self, VALUE dn, VALUE attrs,
1522
+ VALUE serverctrls, VALUE clientctrls)
1523
+ {
1524
+ RB_LDAP_DATA *ldapdata;
1525
+ char *c_dn;
1526
+ LDAPMod **c_attrs;
1527
+ int i;
1528
+ LDAPControl **sctrls, **cctrls;
1529
+
1530
+ switch (TYPE (attrs))
1531
+ {
1532
+ case T_HASH:
1533
+ attrs =
1534
+ rb_ldap_hash2mods (rb_mLDAP,
1535
+ INT2NUM (LDAP_MOD_REPLACE | LDAP_MOD_BVALUES),
1536
+ attrs);
1537
+ break;
1538
+ case T_ARRAY:
1539
+ break;
1540
+ default:
1541
+ rb_raise (rb_eTypeError, "must be a hash or an array");
1542
+ };
1543
+
1544
+ GET_LDAP_DATA (self, ldapdata);
1545
+ c_dn = StringValueCStr (dn);
1546
+ c_attrs = ALLOC_N (LDAPMod *, RARRAY_LEN (attrs) + 1);
1547
+ sctrls = rb_ldap_get_controls (serverctrls);
1548
+ cctrls = rb_ldap_get_controls (clientctrls);
1549
+
1550
+ for (i = 0; i < RARRAY_LEN (attrs); i++)
1551
+ {
1552
+ VALUE mod = RARRAY_PTR (attrs)[i];
1553
+ RB_LDAPMOD_DATA *moddata;
1554
+ Check_Kind (mod, rb_cLDAP_Mod);
1555
+ GET_LDAPMOD_DATA (mod, moddata);
1556
+ c_attrs[i] = moddata->mod;
1557
+ };
1558
+ c_attrs[i] = NULL;
1559
+
1560
+ ldapdata->err =
1561
+ ldap_modify_ext_s (ldapdata->ldap, c_dn, c_attrs, sctrls, cctrls);
1562
+ Check_LDAP_Result (ldapdata->err);
1563
+
1564
+ return self;
1565
+ }
1566
+ #endif
1567
+
1568
+ /*
1569
+ * call-seq:
1570
+ * conn.modrdn(dn, new_rdn, delete_old_rdn) => self
1571
+ *
1572
+ * Modify the RDN of the entry with DN, +dn+, giving it the new RDN,
1573
+ * +new_rdn+. If +delete_old_rdn+ is *true*, the old RDN value will be deleted
1574
+ * from the entry.
1575
+ */
1576
+ VALUE
1577
+ rb_ldap_conn_modrdn_s (VALUE self, VALUE dn, VALUE newrdn, VALUE delete_p)
1578
+ {
1579
+ RB_LDAP_DATA *ldapdata;
1580
+ char *c_dn;
1581
+ char *c_newrdn;
1582
+ int c_delete_p;
1583
+
1584
+ GET_LDAP_DATA (self, ldapdata);
1585
+ c_dn = StringValueCStr (dn);
1586
+ c_newrdn = StringValueCStr (newrdn);
1587
+ c_delete_p = (delete_p == Qtrue) ? 1 : 0;
1588
+
1589
+ ldapdata->err = ldap_modrdn2_s (ldapdata->ldap, c_dn, c_newrdn, c_delete_p);
1590
+ Check_LDAP_Result (ldapdata->err);
1591
+
1592
+ return self;
1593
+ };
1594
+
1595
+ /*
1596
+ * call-seq:
1597
+ * conn.delete(dn) => self
1598
+ *
1599
+ * Delete the entry with the DN, +dn+.
1600
+ */
1601
+ VALUE
1602
+ rb_ldap_conn_delete_s (VALUE self, VALUE dn)
1603
+ {
1604
+ RB_LDAP_DATA *ldapdata;
1605
+ char *c_dn;
1606
+
1607
+ GET_LDAP_DATA (self, ldapdata);
1608
+ c_dn = StringValueCStr (dn);
1609
+
1610
+ ldapdata->err = ldap_delete_s (ldapdata->ldap, c_dn);
1611
+ Check_LDAP_Result (ldapdata->err);
1612
+
1613
+ return self;
1614
+ };
1615
+
1616
+ #if defined(HAVE_LDAPCONTROL) && defined(HAVE_LDAP_DELETE_EXT_S)
1617
+ /*
1618
+ * call-seq:
1619
+ * conn.delete_ext(dn, sctrls, cctrls) => self
1620
+ *
1621
+ * Delete the entry with the DN, +dn+. +sctrls+ is an array of server
1622
+ * controls, whilst +cctrls+ is an array of client controls.
1623
+ */
1624
+ VALUE
1625
+ rb_ldap_conn_delete_ext_s (VALUE self, VALUE dn,
1626
+ VALUE serverctrls, VALUE clientctrls)
1627
+ {
1628
+ RB_LDAP_DATA *ldapdata;
1629
+ char *c_dn;
1630
+ LDAPControl **sctrls, **cctrls;
1631
+
1632
+ GET_LDAP_DATA (self, ldapdata);
1633
+ c_dn = StringValueCStr (dn);
1634
+ sctrls = rb_ldap_get_controls (serverctrls);
1635
+ cctrls = rb_ldap_get_controls (clientctrls);
1636
+
1637
+ ldapdata->err = ldap_delete_ext_s (ldapdata->ldap, c_dn, sctrls, cctrls);
1638
+ Check_LDAP_Result (ldapdata->err);
1639
+
1640
+ return self;
1641
+ }
1642
+ #endif
1643
+
1644
+ #if defined(HAVE_LDAP_COMPARE_S)
1645
+ /*
1646
+ * call-seq:
1647
+ * conn.compare(dn, attr, val) => true or false
1648
+ *
1649
+ * Compare the DN given as +dn+ to see whether it has the attribute +attr+
1650
+ * with a value of +val+.
1651
+ */
1652
+ VALUE
1653
+ rb_ldap_conn_compare_s (VALUE self, VALUE dn, VALUE attr, VALUE val)
1654
+ {
1655
+ RB_LDAP_DATA *ldapdata;
1656
+ char *c_dn, *c_attr, *c_val;
1657
+
1658
+ GET_LDAP_DATA (self, ldapdata);
1659
+ c_dn = StringValueCStr (dn);
1660
+ c_attr = StringValueCStr (attr);
1661
+ c_val = StringValueCStr (val);
1662
+
1663
+ ldapdata->err = ldap_compare_s (ldapdata->ldap, c_dn, c_attr, c_val);
1664
+
1665
+ if ((ldapdata->err) == LDAP_COMPARE_TRUE)
1666
+ return Qtrue;
1667
+ else if ((ldapdata->err) == LDAP_COMPARE_FALSE)
1668
+ return Qfalse;
1669
+
1670
+ Check_LDAP_Result (ldapdata->err);
1671
+
1672
+ fprintf (stderr, "rb_ldap_conn_compare_s() unexpectedly set no error.\n");
1673
+
1674
+ return self;
1675
+ }
1676
+ #endif
1677
+
1678
+ #if defined(HAVE_LDAPCONTROL) && defined(HAVE_LDAP_COMPARE_EXT_S)
1679
+ /*
1680
+ * call-seq:
1681
+ * conn.compare_ext(dn, attr, val, sctrls, cctrls) => true or false
1682
+ *
1683
+ * Compare the DN given as +dn+ to see whether it has the attribute +attr+
1684
+ * with a value of +val+. +sctrls+ is an array of server controls, whilst
1685
+ * +cctrls+ is an array of client controls.
1686
+ */
1687
+ VALUE
1688
+ rb_ldap_conn_compare_ext_s (VALUE self, VALUE dn, VALUE attr, VALUE val,
1689
+ VALUE serverctrls, VALUE clientctrls)
1690
+ {
1691
+ RB_LDAP_DATA *ldapdata;
1692
+ char *c_dn, *c_attr;
1693
+ #ifdef USE_WLDAP32
1694
+ char *c_val;
1695
+ #endif
1696
+ struct berval bval;
1697
+ LDAPControl **sctrls, **cctrls;
1698
+
1699
+ GET_LDAP_DATA (self, ldapdata);
1700
+ c_dn = StringValueCStr (dn);
1701
+ c_attr = StringValueCStr (attr);
1702
+ #ifdef USE_WLDAP32
1703
+ c_val = StringValueCStr (val);
1704
+ #endif
1705
+ bval.bv_val = StringValueCStr (val);
1706
+ bval.bv_len = RSTRING_LEN (val);
1707
+ sctrls = rb_ldap_get_controls (serverctrls);
1708
+ cctrls = rb_ldap_get_controls (clientctrls);
1709
+
1710
+ ldapdata->err = ldap_compare_ext_s (ldapdata->ldap, c_dn, c_attr,
1711
+ #ifdef USE_WLDAP32
1712
+ c_val,
1713
+ #endif
1714
+ &bval, sctrls, cctrls);
1715
+
1716
+ if ((ldapdata->err) == LDAP_COMPARE_TRUE)
1717
+ return Qtrue;
1718
+ else if ((ldapdata->err) == LDAP_COMPARE_FALSE)
1719
+ return Qfalse;
1720
+
1721
+ Check_LDAP_Result (ldapdata->err);
1722
+
1723
+ fprintf (stderr,
1724
+ "rb_ldap_conn_compare_ext_s() unexpectedly set no error.\n");
1725
+
1726
+ return self;
1727
+ }
1728
+ #endif
1729
+
1730
+ /*
1731
+ * call-seq:
1732
+ * conn.err => Fixnum
1733
+ *
1734
+ * Return the error associated with the most recent LDAP operation.
1735
+ */
1736
+ VALUE
1737
+ rb_ldap_conn_err (VALUE self)
1738
+ {
1739
+ RB_LDAP_DATA *ldapdata;
1740
+
1741
+ GET_LDAP_DATA (self, ldapdata);
1742
+ return INT2NUM (ldapdata->err);
1743
+ };
1744
+
1745
+ /* Document-class: LDAP::Conn
1746
+ *
1747
+ * Create and manipulate unencrypted LDAP connections.
1748
+ */
1749
+ void
1750
+ Init_ldap_conn ()
1751
+ {
1752
+ rb_ldap_sort_obj = Qnil;
1753
+
1754
+ rb_cLDAP_Conn = rb_define_class_under (rb_mLDAP, "Conn", rb_cData);
1755
+ rb_define_attr (rb_cLDAP_Conn, "referrals", 1, 0);
1756
+ rb_define_attr (rb_cLDAP_Conn, "controls", 1, 0);
1757
+ rb_define_attr (rb_cLDAP_Conn, "sasl_quiet", 1, 1);
1758
+ #if RUBY_VERSION_CODE < 170
1759
+ rb_define_singleton_method (rb_cLDAP_Conn, "new", rb_ldap_class_new, -1);
1760
+ #endif
1761
+ #if RUBY_VERSION_CODE >= 173
1762
+ rb_define_alloc_func (rb_cLDAP_Conn, rb_ldap_conn_s_allocate);
1763
+ #else
1764
+ rb_define_singleton_method (rb_cLDAP_Conn, "allocate",
1765
+ rb_ldap_conn_s_allocate, 0);
1766
+ #endif
1767
+ rb_define_singleton_method (rb_cLDAP_Conn, "open", rb_ldap_conn_s_open, -1);
1768
+ rb_define_singleton_method (rb_cLDAP_Conn, "set_option",
1769
+ rb_ldap_conn_s_set_option, 2);
1770
+ rb_define_singleton_method (rb_cLDAP_Conn, "get_option",
1771
+ rb_ldap_conn_s_get_option, 1);
1772
+ rb_ldap_conn_define_method ("initialize", rb_ldap_conn_initialize, -1);
1773
+ rb_ldap_conn_define_method ("start_tls", rb_ldap_conn_start_tls_s, -1);
1774
+ rb_ldap_conn_define_method ("simple_bind", rb_ldap_conn_simple_bind_s, -1);
1775
+ rb_ldap_conn_define_method ("bind", rb_ldap_conn_bind_s, -1);
1776
+ rb_ldap_conn_define_method ("bound?", rb_ldap_conn_bound, 0);
1777
+ rb_ldap_conn_define_method ("unbind", rb_ldap_conn_unbind, 0);
1778
+ rb_ldap_conn_define_method ("set_option", rb_ldap_conn_set_option, 2);
1779
+ rb_ldap_conn_define_method ("get_option", rb_ldap_conn_get_option, 1);
1780
+ rb_ldap_conn_define_method ("search", rb_ldap_conn_search_s, -1);
1781
+ rb_ldap_conn_define_method ("search2", rb_ldap_conn_search2_s, -1);
1782
+ rb_ldap_conn_define_method ("add", rb_ldap_conn_add_s, 2);
1783
+ rb_ldap_conn_define_method ("modify", rb_ldap_conn_modify_s, 2);
1784
+ rb_ldap_conn_define_method ("modrdn", rb_ldap_conn_modrdn_s, 3);
1785
+ rb_ldap_conn_define_method ("delete", rb_ldap_conn_delete_s, 1);
1786
+ #if defined(HAVE_LDAP_COMPARE_S)
1787
+ rb_ldap_conn_define_method ("compare", rb_ldap_conn_compare_s, 3);
1788
+ #endif
1789
+ rb_ldap_conn_define_method ("perror", rb_ldap_conn_perror, 1);
1790
+ rb_ldap_conn_define_method ("err2string", rb_ldap_conn_err2string, 1);
1791
+ rb_ldap_conn_define_method ("result2error", rb_ldap_conn_result2error, 1);
1792
+ rb_ldap_conn_define_method ("err", rb_ldap_conn_err, 0);
1793
+
1794
+ #if defined(HAVE_LDAP_SEARCH_EXT_S)
1795
+ rb_ldap_conn_define_method ("search_ext", rb_ldap_conn_search_ext_s, -1);
1796
+ rb_ldap_conn_define_method ("search_ext2", rb_ldap_conn_search_ext2_s, -1);
1797
+ #endif
1798
+ #if defined(HAVE_LDAP_ADD_EXT_S)
1799
+ rb_ldap_conn_define_method ("add_ext", rb_ldap_conn_add_ext_s, 4);
1800
+ #endif
1801
+ #if defined(HAVE_LDAP_MODIFY_EXT_S)
1802
+ rb_ldap_conn_define_method ("modify_ext", rb_ldap_conn_modify_ext_s, 4);
1803
+ #endif
1804
+ #if defined(HAVE_LDAP_DELETE_EXT_S)
1805
+ rb_ldap_conn_define_method ("delete_ext", rb_ldap_conn_delete_ext_s, 3);
1806
+ #endif
1807
+ #if defined(HAVE_LDAP_COMPARE_EXT_S)
1808
+ rb_ldap_conn_define_method ("compare_ext", rb_ldap_conn_compare_ext_s, 5);
1809
+ #endif
1810
+ };