ruby-ldap3 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/conn.c ADDED
@@ -0,0 +1,1918 @@
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
+ xfree(ldapdata);
35
+ };
36
+
37
+ static void
38
+ rb_ldap_conn_mark (RB_LDAP_DATA * ldapdata)
39
+ {
40
+ /* empty */
41
+ };
42
+
43
+ VALUE
44
+ rb_ldap_conn_new (VALUE klass, LDAP * cldap)
45
+ {
46
+ VALUE conn;
47
+ RB_LDAP_DATA *ldapdata;
48
+
49
+ conn = Data_Make_Struct (klass, RB_LDAP_DATA,
50
+ rb_ldap_conn_mark, rb_ldap_conn_free, ldapdata);
51
+ ldapdata->ldap = cldap;
52
+ ldapdata->err = 0;
53
+ ldapdata->bind = 0;
54
+
55
+ return conn;
56
+ };
57
+
58
+ VALUE
59
+ rb_ldap_conn_s_allocate (VALUE klass)
60
+ {
61
+ return rb_ldap_conn_new (klass, (LDAP *) 0);
62
+ }
63
+
64
+ /*
65
+ * call-seq:
66
+ * LDAP::Conn.new(host='localhost', port=LDAP_PORT) => LDAP::Conn
67
+ *
68
+ * Return a new LDAP::Conn connection to the server, +host+, on port +port+.
69
+ */
70
+ VALUE
71
+ rb_ldap_conn_initialize (int argc, VALUE argv[], VALUE self)
72
+ {
73
+ LDAP *cldap;
74
+ char *chost;
75
+ int cport;
76
+ int was_verbose = Qfalse;
77
+ RB_LDAP_DATA *ldapdata;
78
+
79
+ VALUE host, port;
80
+
81
+ Data_Get_Struct (self, RB_LDAP_DATA, ldapdata);
82
+ if (ldapdata->ldap)
83
+ {
84
+ return Qnil;
85
+ }
86
+
87
+ switch (rb_scan_args (argc, argv, "02", &host, &port))
88
+ {
89
+ case 0:
90
+ chost = ALLOCA_N (char, strlen ("localhost") + 1);
91
+ strcpy (chost, "localhost");
92
+ cport = LDAP_PORT;
93
+ break;
94
+ case 1:
95
+ chost = StringValueCStr (host);
96
+ cport = LDAP_PORT;
97
+ break;
98
+ case 2:
99
+ chost = StringValueCStr (host);
100
+ cport = NUM2INT (port);
101
+ break;
102
+ default:
103
+ rb_bug ("rb_ldap_conn_new");
104
+ };
105
+
106
+ cldap = ldap_init (chost, cport);
107
+ if (!cldap)
108
+ rb_raise (rb_eLDAP_ResultError, "can't initialise an LDAP session");
109
+ ldapdata->ldap = cldap;
110
+
111
+ rb_iv_set (self, "@args", rb_ary_new4 (argc, argv));
112
+
113
+ /* Silence warning that next rb_iv_get produces. */
114
+ if (ruby_verbose == Qtrue)
115
+ {
116
+ was_verbose = Qtrue;
117
+ ruby_verbose = Qfalse;
118
+ }
119
+
120
+ if (rb_iv_get (self, "@sasl_quiet") != Qtrue)
121
+ rb_iv_set (self, "@sasl_quiet", Qfalse);
122
+ if (was_verbose == Qtrue)
123
+ ruby_verbose = Qtrue;
124
+
125
+ return Qnil;
126
+ };
127
+
128
+ /*
129
+ * call-seq:
130
+ * LDAP::Conn.open(host='localhost', port=LDAP_PORT) => LDAP::Conn
131
+ *
132
+ * Return a new LDAP::Conn connection to the server, +host+, on port +port+.
133
+ */
134
+ VALUE
135
+ rb_ldap_conn_s_open (int argc, VALUE argv[], VALUE klass)
136
+ {
137
+ LDAP *cldap;
138
+ char *chost;
139
+ int cport;
140
+
141
+ VALUE host, port;
142
+ VALUE conn;
143
+
144
+ switch (rb_scan_args (argc, argv, "02", &host, &port))
145
+ {
146
+ case 0:
147
+ chost = ALLOCA_N (char, strlen ("localhost") + 1);
148
+ strcpy (chost, "localhost");
149
+ cport = LDAP_PORT;
150
+ break;
151
+ case 1:
152
+ chost = StringValueCStr (host);
153
+ cport = LDAP_PORT;
154
+ break;
155
+ case 2:
156
+ chost = StringValueCStr (host);
157
+ cport = NUM2INT (port);
158
+ break;
159
+ default:
160
+ rb_bug ("rb_ldap_conn_new");
161
+ };
162
+
163
+ cldap = ldap_open (chost, cport);
164
+ if (!cldap)
165
+ rb_raise (rb_eLDAP_ResultError, "can't open an LDAP session");
166
+ conn = rb_ldap_conn_new (klass, cldap);
167
+
168
+ return conn;
169
+ };
170
+
171
+ /*
172
+ * call-seq:
173
+ * LDAP::Conn.open_uri(uri) => LDAP::Conn
174
+ *
175
+ * Return a new LDAP::Conn connection to the server described with +uri+.
176
+ */
177
+ VALUE
178
+ rb_ldap_conn_s_open_uri (VALUE klass, VALUE uri)
179
+ {
180
+ LDAP *cldap = NULL;
181
+ int rc;
182
+
183
+ rc = ldap_initialize (&cldap, StringValueCStr (uri));
184
+
185
+ if (rc || cldap == NULL)
186
+ rb_raise (rb_eLDAP_ResultError, "can't open an LDAP session");
187
+
188
+ return rb_ldap_conn_new (klass, cldap);
189
+ };
190
+
191
+ /*
192
+ * call-seq:
193
+ * conn.start_tls => nil
194
+ *
195
+ * Initiate START_TLS for the connection, +conn+.
196
+ */
197
+ VALUE
198
+ rb_ldap_conn_start_tls_s (int argc, VALUE argv[], VALUE self)
199
+ {
200
+ #ifdef HAVE_LDAP_START_TLS_S
201
+ VALUE arg1, arg2;
202
+ RB_LDAP_DATA *ldapdata;
203
+ LDAPControl **serverctrls;
204
+ LDAPControl **clientctrls;
205
+
206
+ switch (rb_scan_args (argc, argv, "02", &arg1, &arg2))
207
+ {
208
+ case 0:
209
+ serverctrls = NULL;
210
+ clientctrls = NULL;
211
+ break;
212
+ case 1:
213
+ case 2:
214
+ rb_notimplement ();
215
+ default:
216
+ rb_bug ("rb_ldap_conn_start_tls_s");
217
+ };
218
+
219
+ GET_LDAP_DATA (self, ldapdata);
220
+ ldapdata->err = ldap_start_tls_s (ldapdata->ldap, serverctrls, clientctrls);
221
+ Check_LDAP_Result (ldapdata->err);
222
+ #else
223
+ rb_notimplement ();
224
+ #endif
225
+ return Qnil;
226
+ };
227
+
228
+ VALUE
229
+ rb_ldap_conn_rebind (VALUE self)
230
+ {
231
+ VALUE ary = rb_iv_get (self, "@args");
232
+
233
+ if (rb_obj_is_kind_of (self, rb_cLDAP_SSLConn) == Qtrue)
234
+ return rb_ldap_sslconn_initialize (RARRAY_LEN (ary), RARRAY_PTR (ary),
235
+ self);
236
+ else
237
+ return rb_ldap_conn_initialize (RARRAY_LEN (ary), RARRAY_PTR (ary),
238
+ self);
239
+ }
240
+
241
+ /*
242
+ * call-seq:
243
+ * conn.simple_bind(dn=nil, password=nil) => self
244
+ * conn.simple_bind(dn=nil, password=nil) { |conn| } => nil
245
+ *
246
+ * Bind an LDAP connection, using the DN, +dn+, and the credential, +password+.
247
+ * If a block is given, +self+ is yielded to the block.
248
+ */
249
+ VALUE
250
+ rb_ldap_conn_simple_bind_s (int argc, VALUE argv[], VALUE self)
251
+ {
252
+ RB_LDAP_DATA *ldapdata;
253
+
254
+ VALUE arg1, arg2;
255
+ char *dn = NULL;
256
+ char *passwd = NULL;
257
+
258
+ Data_Get_Struct (self, RB_LDAP_DATA, ldapdata);
259
+ if (!ldapdata->ldap)
260
+ {
261
+ if (rb_iv_get (self, "@args") != Qnil)
262
+ {
263
+ rb_ldap_conn_rebind (self);
264
+ GET_LDAP_DATA (self, ldapdata);
265
+ }
266
+ else
267
+ {
268
+ rb_raise (rb_eLDAP_InvalidDataError,
269
+ "The LDAP handler has already unbound.");
270
+ }
271
+ }
272
+
273
+ if (ldapdata->bind)
274
+ {
275
+ rb_raise (rb_eLDAP_Error, "already bound.");
276
+ };
277
+ switch (rb_scan_args (argc, argv, "02", &arg1, &arg2))
278
+ {
279
+ case 0:
280
+ break;
281
+ case 1:
282
+ if (arg1 == Qnil)
283
+ {
284
+ dn = NULL;
285
+ }
286
+ else
287
+ {
288
+ dn = StringValueCStr (arg1);
289
+ }
290
+ break;
291
+ case 2:
292
+ if (arg1 == Qnil)
293
+ {
294
+ dn = NULL;
295
+ }
296
+ else
297
+ {
298
+ dn = StringValueCStr (arg1);
299
+ }
300
+ if (arg2 == Qnil)
301
+ {
302
+ passwd = NULL;
303
+ }
304
+ else
305
+ {
306
+ passwd = StringValueCStr (arg2);
307
+ }
308
+ break;
309
+ default:
310
+ rb_bug ("rb_ldap_conn_simple_bind_s");
311
+ }
312
+
313
+ ldapdata->err = ldap_simple_bind_s (ldapdata->ldap, dn, passwd);
314
+ Check_LDAP_Result (ldapdata->err);
315
+ ldapdata->bind = 1;
316
+
317
+ if (rb_block_given_p ())
318
+ {
319
+ rb_ensure (rb_yield, self, rb_ldap_conn_unbind, self);
320
+ return Qnil;
321
+ }
322
+ else
323
+ {
324
+ return self;
325
+ };
326
+ };
327
+
328
+ /*
329
+ * call-seq:
330
+ * conn.bind(dn=nil, password=nil, method=LDAP::LDAP_AUTH_SIMPLE)
331
+ * => self
332
+ * conn.bind(dn=nil, password=nil, method=LDAP::LDAP_AUTH_SIMPLE)
333
+ * { |conn| } => nil
334
+ *
335
+ * Bind an LDAP connection, using the DN, +dn+, the credential, +password+,
336
+ * and the bind method, +method+. If a block is given, +self+ is yielded to
337
+ * the block.
338
+ */
339
+ VALUE
340
+ rb_ldap_conn_bind_s (int argc, VALUE argv[], VALUE self)
341
+ {
342
+ RB_LDAP_DATA *ldapdata;
343
+
344
+ VALUE arg1, arg2, arg3;
345
+ char *dn = NULL;
346
+ char *passwd = NULL;
347
+ int method = LDAP_AUTH_SIMPLE;
348
+
349
+ Data_Get_Struct (self, RB_LDAP_DATA, ldapdata);
350
+ if (!ldapdata->ldap)
351
+ {
352
+ if (rb_iv_get (self, "@args") != Qnil)
353
+ {
354
+ rb_ldap_conn_rebind (self);
355
+ GET_LDAP_DATA (self, ldapdata);
356
+ }
357
+ else
358
+ {
359
+ rb_raise (rb_eLDAP_InvalidDataError,
360
+ "The LDAP handler has already unbound.");
361
+ }
362
+ }
363
+
364
+ if (ldapdata->bind)
365
+ {
366
+ rb_raise (rb_eLDAP_Error, "already bound.");
367
+ };
368
+ switch (rb_scan_args (argc, argv, "03", &arg1, &arg2, &arg3))
369
+ {
370
+ case 0:
371
+ break;
372
+ case 1:
373
+ dn = StringValueCStr (arg1);
374
+ break;
375
+ case 2:
376
+ dn = StringValueCStr (arg1);
377
+ passwd = StringValueCStr (arg2);
378
+ break;
379
+ case 3:
380
+ dn = StringValueCStr (arg1);
381
+ passwd = StringValueCStr (arg2);
382
+ method = NUM2INT (arg3);
383
+ break;
384
+ default:
385
+ rb_bug ("rb_ldap_conn_bind_s");
386
+ }
387
+
388
+ ldapdata->err = ldap_bind_s (ldapdata->ldap, dn, passwd, method);
389
+ Check_LDAP_Result (ldapdata->err);
390
+ ldapdata->bind = 1;
391
+
392
+ if (rb_block_given_p ())
393
+ {
394
+ rb_ensure (rb_yield, self, rb_ldap_conn_unbind, self);
395
+ return Qnil;
396
+ }
397
+ else
398
+ {
399
+ return self;
400
+ };
401
+ };
402
+
403
+ /*
404
+ * call-seq:
405
+ * conn.unbind => nil
406
+ *
407
+ * Unbind the LDAP connection from the server.
408
+ */
409
+ VALUE
410
+ rb_ldap_conn_unbind (VALUE self)
411
+ {
412
+ RB_LDAP_DATA *ldapdata;
413
+
414
+ GET_LDAP_DATA (self, ldapdata);
415
+ ldapdata->err = ldap_unbind (ldapdata->ldap);
416
+ ldapdata->bind = 0;
417
+ ldapdata->ldap = NULL;
418
+ Check_LDAP_Result (ldapdata->err);
419
+
420
+ return Qnil;
421
+ };
422
+
423
+ /*
424
+ * call-seq:
425
+ * conn.bound? => true or false
426
+ *
427
+ * Return *true* if the LDAP connection is still bound.
428
+ */
429
+ VALUE
430
+ rb_ldap_conn_bound (VALUE self)
431
+ {
432
+ RB_LDAP_DATA *ldapdata;
433
+
434
+ Data_Get_Struct (self, RB_LDAP_DATA, ldapdata);
435
+
436
+ return ldapdata->bind == 0 ? Qfalse : Qtrue;
437
+ };
438
+
439
+ /*
440
+ * call-seq:
441
+ * conn.set_option(option, data) => self
442
+ *
443
+ * Set a session-wide option for this LDAP connection.
444
+ *
445
+ * For example:
446
+ *
447
+ * <code>conn.set_option( LDAP::LDAP_OPT_PROTOCOL_VERSION, 3 )</code>
448
+ *
449
+ * would set the protocol of this connection to LDAPv3.
450
+ */
451
+ VALUE
452
+ rb_ldap_conn_set_option (VALUE self, VALUE opt, VALUE data)
453
+ {
454
+ /* ldap_set_option() is defined in IETF draft */
455
+ #ifdef HAVE_LDAP_SET_OPTION
456
+ RB_LDAP_DATA *ldapdata;
457
+ RB_LDAP_DATA dummy;
458
+ int idata;
459
+ void *optdata;
460
+ int copt;
461
+
462
+ if (NIL_P (self))
463
+ {
464
+ dummy.ldap = NULL;
465
+ dummy.err = dummy.bind = 0;
466
+ ldapdata = &dummy;
467
+ }
468
+ else
469
+ GET_LDAP_DATA (self, ldapdata);
470
+ copt = NUM2INT (opt);
471
+
472
+ switch (copt)
473
+ {
474
+ #if defined(USE_OPENLDAP1) || defined(USE_OPENLDAP2)
475
+ case LDAP_OPT_NETWORK_TIMEOUT:
476
+ {
477
+ struct timeval tv;
478
+ tv = rb_time_interval(data);
479
+ optdata = &tv;
480
+ }
481
+ break;
482
+ #endif
483
+ case LDAP_OPT_REFERRALS:
484
+ optdata = (void *) NUM2INT (data);
485
+ break;
486
+ case LDAP_OPT_DEREF:
487
+ case LDAP_OPT_SIZELIMIT:
488
+ case LDAP_OPT_TIMELIMIT:
489
+ case LDAP_OPT_RESTART:
490
+ case LDAP_OPT_PROTOCOL_VERSION:
491
+ if (ldapdata->bind != 0)
492
+ rb_raise (rb_eLDAP_ResultError,
493
+ "can't set LDAP protocol version after bind");
494
+ case LDAP_OPT_ERROR_NUMBER:
495
+ #ifdef LDAP_OPT_SSL
496
+ case LDAP_OPT_SSL:
497
+ #endif
498
+ #ifdef USE_OPENLDAP2
499
+ #ifdef LDAP_OPT_X_TLS
500
+ case LDAP_OPT_X_TLS:
501
+ #endif
502
+ #ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
503
+ case LDAP_OPT_X_TLS_REQUIRE_CERT:
504
+ #endif
505
+ #ifdef LDAP_OPT_X_TLS_NEWCTX
506
+ case LDAP_OPT_X_TLS_NEWCTX:
507
+ #endif
508
+ #endif
509
+ idata = NUM2INT (data);
510
+ optdata = &idata;
511
+ break;
512
+ case LDAP_OPT_HOST_NAME:
513
+ case LDAP_OPT_ERROR_STRING:
514
+ #ifdef LDAP_OPT_MATCHED_DN
515
+ case LDAP_OPT_MATCHED_DN:
516
+ #endif
517
+ #ifdef USE_OPENLDAP2
518
+ #ifdef LDAP_OPT_X_TLS_CACERTFILE
519
+ case LDAP_OPT_X_TLS_CACERTFILE:
520
+ #endif
521
+ #ifdef LDAP_OPT_X_TLS_CACERTDIR
522
+ case LDAP_OPT_X_TLS_CACERTDIR:
523
+ #endif
524
+ #ifdef LDAP_OPT_X_TLS_CERT
525
+ case LDAP_OPT_X_TLS_CERT:
526
+ #endif
527
+ #ifdef LDAP_OPT_X_TLS_CERTFILE
528
+ case LDAP_OPT_X_TLS_CERTFILE:
529
+ #endif
530
+ #ifdef LDAP_OPT_X_TLS_KEYFILE
531
+ case LDAP_OPT_X_TLS_KEYFILE:
532
+ #endif
533
+ #ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
534
+ case LDAP_OPT_X_TLS_PROTOCOL_MIN:
535
+ #endif
536
+ #ifdef LDAP_OPT_X_TLS_CIPHER_SUITE
537
+ case LDAP_OPT_X_TLS_CIPHER_SUITE:
538
+ #endif
539
+ #ifdef LDAP_OPT_X_TLS_RANDOM_FILE
540
+ case LDAP_OPT_X_TLS_RANDOM_FILE:
541
+ #endif
542
+ #endif
543
+ optdata = NIL_P (data) ? NULL : StringValueCStr (data);
544
+ break;
545
+ #ifdef LDAP_OPT_API_INFO
546
+ case LDAP_OPT_API_INFO:
547
+ rb_raise (rb_eLDAP_Error, "option is read-only");
548
+ /* optdata = (void*)rb_ldap_get_apiinfo(data); */
549
+ break;
550
+ #endif
551
+ #ifdef LDAP_OPT_SERVER_CONTROLS
552
+ case LDAP_OPT_SERVER_CONTROLS:
553
+ optdata = rb_ldap_get_controls (data);
554
+ break;
555
+ #endif
556
+ default:
557
+ rb_notimplement ();
558
+ }
559
+ ldapdata->err = ldap_set_option (ldapdata->ldap, copt, optdata);
560
+ Check_LDAP_OPT_Result (ldapdata->err);
561
+
562
+ return self;
563
+ #else
564
+ rb_notimplement ();
565
+ #endif
566
+ };
567
+
568
+ static VALUE
569
+ rb_ldap_conn_s_set_option (VALUE klass, VALUE opt, VALUE data)
570
+ {
571
+ return rb_ldap_conn_set_option (Qnil, opt, data);
572
+ }
573
+
574
+ /* call-seq:
575
+ * conn.get_option(opt) => String
576
+ *
577
+ * Return the value associated with the option, +opt+.
578
+ */
579
+ VALUE
580
+ rb_ldap_conn_get_option (VALUE self, VALUE opt)
581
+ {
582
+ #ifdef HAVE_LDAP_GET_OPTION
583
+ RB_LDAP_DATA *ldapdata;
584
+ static RB_LDAP_DATA dummy = { NULL, 0, 0 };
585
+ long *data;
586
+ int copt;
587
+ VALUE val;
588
+
589
+ if (NIL_P (self))
590
+ {
591
+ if (dummy.ldap == NULL)
592
+ dummy.ldap = ldap_init ("", 0);
593
+ ldapdata = &dummy;
594
+ }
595
+ else
596
+ GET_LDAP_DATA (self, ldapdata);
597
+ copt = NUM2INT (opt);
598
+
599
+ #if defined(LDAP_OPT_API_INFO) && defined(LDAP_API_INFO_VERSION)
600
+ if (copt == LDAP_OPT_API_INFO)
601
+ {
602
+ LDAPAPIInfo *info;
603
+
604
+ info = ALLOCA_N (LDAPAPIInfo, 1);
605
+ /* This is from the Netscape SDK docs for 4.1* */
606
+ info->ldapai_info_version = LDAP_API_INFO_VERSION;
607
+ ldapdata->err = ldap_get_option (NULL, copt, (void *) info);
608
+ data = (long *) info;
609
+ }
610
+ #if defined(USE_OPENLDAP1) || defined(USE_OPENLDAP2)
611
+ else if (copt == LDAP_OPT_NETWORK_TIMEOUT)
612
+ {
613
+ struct timeval tv;
614
+ ldapdata->err = ldap_get_option (ldapdata->ldap, copt, &tv);
615
+ if (!tv.tv_sec)
616
+ {
617
+ long x = -1;
618
+ data = &x;
619
+ }
620
+ else
621
+ data = (void *) tv.tv_sec;
622
+ }
623
+ #endif
624
+ else
625
+ {
626
+ data = (void *) ALLOCA_N (char, LDAP_GET_OPT_MAX_BUFFER_SIZE);
627
+ ldapdata->err = ldap_get_option (ldapdata->ldap, copt, (void *) data);
628
+ }
629
+ #else
630
+ data = (void *) ALLOCA_N (char, LDAP_GET_OPT_MAX_BUFFER_SIZE);
631
+ ldapdata->err = ldap_get_option (ldapdata->ldap, copt, (void *) data);
632
+ #endif
633
+
634
+ if (ldapdata->err == LDAP_OPT_SUCCESS)
635
+ {
636
+ switch (copt)
637
+ {
638
+ case LDAP_OPT_DEREF:
639
+ case LDAP_OPT_SIZELIMIT:
640
+ case LDAP_OPT_TIMELIMIT:
641
+ case LDAP_OPT_REFERRALS:
642
+ case LDAP_OPT_RESTART:
643
+ case LDAP_OPT_PROTOCOL_VERSION:
644
+ case LDAP_OPT_ERROR_NUMBER:
645
+ #if defined(USE_OPENLDAP1) || defined(USE_OPENLDAP2)
646
+ case LDAP_OPT_NETWORK_TIMEOUT:
647
+ #endif
648
+ #ifdef USE_OPENLDAP2
649
+ #ifdef LDAP_OPT_X_TLS
650
+ case LDAP_OPT_X_TLS:
651
+ #endif
652
+ #ifdef LDAP_OPT_X_TLS_REQUIRE_CERT
653
+ case LDAP_OPT_X_TLS_REQUIRE_CERT:
654
+ #endif
655
+ #endif
656
+ val = INT2NUM ((int) (*data));
657
+ break;
658
+
659
+ case LDAP_OPT_HOST_NAME:
660
+ case LDAP_OPT_ERROR_STRING:
661
+ #ifdef LDAP_OPT_MATCHED_DN
662
+ case LDAP_OPT_MATCHED_DN:
663
+ #endif
664
+ #ifdef USE_OPENLDAP2
665
+ #ifdef LDAP_OPT_X_TLS_CACERTFILE
666
+ case LDAP_OPT_X_TLS_CACERTFILE:
667
+ #endif
668
+ #ifdef LDAP_OPT_X_TLS_CACERTDIR
669
+ case LDAP_OPT_X_TLS_CACERTDIR:
670
+ #endif
671
+ #ifdef LDAP_OPT_X_TLS_CERT
672
+ case LDAP_OPT_X_TLS_CERT:
673
+ #endif
674
+ #ifdef LDAP_OPT_X_TLS_CERTFILE
675
+ case LDAP_OPT_X_TLS_CERTFILE:
676
+ #endif
677
+ #ifdef LDAP_OPT_X_TLS_KEYFILE
678
+ case LDAP_OPT_X_TLS_KEYFILE:
679
+ #endif
680
+ #ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN
681
+ case LDAP_OPT_X_TLS_PROTOCOL_MIN:
682
+ #endif
683
+ #ifdef LDAP_OPT_X_TLS_CIPHER_SUITE
684
+ case LDAP_OPT_X_TLS_CIPHER_SUITE:
685
+ #endif
686
+ #ifdef LDAP_OPT_X_TLS_RANDOM_FILE
687
+ case LDAP_OPT_X_TLS_RANDOM_FILE:
688
+ #endif
689
+ #endif
690
+ val = (data
691
+ && *data) ? rb_tainted_str_new2 ((char *) (*data)) : Qnil;
692
+ break;
693
+ #ifdef LDAP_OPT_API_INFO
694
+ case LDAP_OPT_API_INFO:
695
+ val = rb_ldap_apiinfo_new ((LDAPAPIInfo *) data);
696
+ break;
697
+ #endif
698
+ default:
699
+ rb_notimplement ();
700
+ };
701
+
702
+ return val;
703
+ }
704
+ else
705
+ {
706
+ rb_raise (rb_eLDAP_Error, "%s", ldap_err2string (ldapdata->err));
707
+ };
708
+ #else
709
+ rb_notimplement ();
710
+ #endif
711
+ };
712
+
713
+ static VALUE
714
+ rb_ldap_conn_s_get_option (VALUE klass, VALUE opt)
715
+ {
716
+ return rb_ldap_conn_get_option (Qnil, opt);
717
+ }
718
+
719
+ /*
720
+ * call-seq:
721
+ * conn.perror(msg) => nil
722
+ *
723
+ * Print the text string associated with the error code of the last LDAP
724
+ * operation. +msg+ is used to prefix the error.
725
+ */
726
+ VALUE
727
+ rb_ldap_conn_perror (VALUE self, VALUE msg)
728
+ {
729
+ RB_LDAP_DATA *ldapdata;
730
+ char *cmsg;
731
+ #if (! defined(HAVE_LDAP_PERROR)) || defined(USE_NETSCAPE_SDK)
732
+ char *str;
733
+ #endif
734
+
735
+ GET_LDAP_DATA (self, ldapdata);
736
+ cmsg = StringValueCStr (msg);
737
+ #if defined(HAVE_LDAP_PERROR) && (! defined(USE_NETSCAPE_SDK))
738
+ ldap_perror (ldapdata->ldap, cmsg);
739
+ #else
740
+ str = ldap_err2string (ldapdata->err);
741
+ fprintf (stderr, "%s: %s\n", cmsg, str);
742
+ #endif
743
+
744
+ return Qnil;
745
+ };
746
+
747
+ /*
748
+ * call-seq:
749
+ * conn.result2error(msg) => Fixnum
750
+ *
751
+ * Return the error code associated with the LDAP message, +msg+.
752
+ */
753
+ VALUE
754
+ rb_ldap_conn_result2error (VALUE self, VALUE msg)
755
+ {
756
+ RB_LDAP_DATA *ldapdata;
757
+ RB_LDAPENTRY_DATA *edata;
758
+ int cdofree = 0;
759
+
760
+ GET_LDAP_DATA (self, ldapdata);
761
+ Check_Kind (msg, rb_cLDAP_Entry);
762
+ Check_LDAPENTRY(msg);
763
+ GET_LDAPENTRY_DATA (msg, edata);
764
+
765
+ ldapdata->err = ldap_result2error (ldapdata->ldap, edata->msg, cdofree);
766
+ return INT2NUM (ldapdata->err);
767
+ };
768
+
769
+ /*
770
+ * call-seq:
771
+ * conn.err2string(err) => String
772
+ *
773
+ * Return the text string associated with the LDAP error, +err+.
774
+ */
775
+ VALUE
776
+ rb_ldap_conn_err2string (VALUE self, VALUE err)
777
+ {
778
+ RB_LDAP_DATA *ldapdata;
779
+ int c_err = NUM2INT (err);
780
+ char *str;
781
+
782
+ GET_LDAP_DATA (self, ldapdata);
783
+ str = ldap_err2string (c_err);
784
+ return (str ? rb_tainted_str_new2 (str) : Qnil);
785
+ };
786
+
787
+ VALUE
788
+ rb_ldap_conn_get_errno (VALUE self)
789
+ {
790
+ RB_LDAP_DATA *ldapdata;
791
+ VALUE err;
792
+
793
+ GET_LDAP_DATA (self, ldapdata);
794
+
795
+ #ifdef USE_NETSCAPE_SDK
796
+ int cerr = ldap_get_lderrno (ldapdata->ldap, NULL, NULL);
797
+ err = INT2NUM (cerr);
798
+ #else
799
+ # ifdef USE_OPENLDAP1
800
+ cerr = NUM2INT (ldapdata->ldap->ld_errno);
801
+ err = INT2NUM (cerr);
802
+ # else
803
+ rb_notimplement ();
804
+ # endif
805
+ #endif
806
+
807
+ return err;
808
+ };
809
+
810
+ static VALUE
811
+ rb_ldap_conn_invalidate_entry (VALUE msg)
812
+ {
813
+ RB_LDAPENTRY_DATA *edata;
814
+ Check_LDAPENTRY(msg);
815
+ GET_LDAPENTRY_DATA (msg, edata);
816
+ edata->ldap = NULL;
817
+ edata->msg = NULL;
818
+ return Qnil;
819
+ };
820
+
821
+
822
+ static int
823
+ rb_ldap_internal_strcmp (const char *left, const char *right)
824
+ {
825
+ VALUE res;
826
+
827
+ if (rb_ldap_sort_obj == Qtrue)
828
+ {
829
+ res = rb_funcall (rb_tainted_str_new2 (left), rb_intern ("<=>"), 1,
830
+ rb_tainted_str_new2 (right));
831
+ }
832
+ else if (rb_ldap_sort_obj != Qnil)
833
+ {
834
+ res = rb_funcall (rb_ldap_sort_obj, rb_intern ("call"), 2,
835
+ rb_tainted_str_new2 (left),
836
+ rb_tainted_str_new2 (right));
837
+ }
838
+ else
839
+ {
840
+ res = 0;
841
+ };
842
+
843
+ return INT2NUM (res);
844
+ };
845
+
846
+ static int
847
+ rb_ldap_conn_search_i (int argc, VALUE argv[], VALUE self,
848
+ RB_LDAP_DATA ** ldapdata, LDAPMessage ** cmsg)
849
+ {
850
+ VALUE base, scope, filter, attrs, attrsonly, sec, usec, s_attr, s_proc;
851
+
852
+ LDAP *cldap;
853
+ char *cbase;
854
+ int cscope;
855
+ char *cfilter;
856
+ char **cattrs;
857
+ char *sort_attr;
858
+ int cattrsonly;
859
+ int i;
860
+ struct timeval tv;
861
+
862
+ GET_LDAP_DATA (self, (*ldapdata));
863
+ cldap = (*ldapdata)->ldap;
864
+
865
+ cattrs = NULL;
866
+ cattrsonly = 0;
867
+ tv.tv_sec = 0;
868
+ tv.tv_usec = 0;
869
+ sort_attr = NULL;
870
+ rb_ldap_sort_obj = Qnil;
871
+
872
+ switch (rb_scan_args (argc, argv, "36",
873
+ &base, &scope, &filter, &attrs, &attrsonly, &sec,
874
+ &usec, &s_attr, &s_proc))
875
+ {
876
+ case 9:
877
+ rb_ldap_sort_obj = s_proc; /* Ruby's GC never starts in a C function */
878
+ case 8:
879
+ if (rb_ldap_sort_obj == Qnil)
880
+ {
881
+ rb_ldap_sort_obj = Qtrue;
882
+ }
883
+ sort_attr = StringValueCStr (s_attr);
884
+ case 7:
885
+ tv.tv_usec = NUM2INT (usec);
886
+ case 6:
887
+ tv.tv_sec = NUM2INT (sec);
888
+ case 5:
889
+ cattrsonly = (attrsonly == Qtrue) ? 1 : 0;
890
+ case 4:
891
+ if (TYPE (attrs) == T_NIL)
892
+ {
893
+ cattrs = NULL;
894
+ }
895
+ else
896
+ {
897
+ if (TYPE (attrs) == T_STRING)
898
+ attrs = rb_ary_to_ary (attrs);
899
+ else
900
+ Check_Type (attrs, T_ARRAY);
901
+
902
+ if (RARRAY_LEN (attrs) == 0)
903
+ {
904
+ cattrs = NULL;
905
+ }
906
+ else
907
+ {
908
+ cattrs = ALLOCA_N (char *, (RARRAY_LEN (attrs) + 1));
909
+ for (i = 0; i < RARRAY_LEN (attrs); i++)
910
+ {
911
+ cattrs[i] = StringValueCStr (RARRAY_PTR (attrs)[i]);
912
+ };
913
+ cattrs[RARRAY_LEN (attrs)] = NULL;
914
+ }
915
+ }
916
+ case 3:
917
+ cbase = StringValueCStr (base);
918
+ cscope = NUM2INT (scope);
919
+ cfilter = StringValueCStr (filter);
920
+ break;
921
+ default:
922
+ rb_bug ("rb_ldap_conn_search_s");
923
+ };
924
+
925
+ (*cmsg) = NULL;
926
+ if (tv.tv_sec == 0 && tv.tv_usec == 0)
927
+ {
928
+ (*ldapdata)->err = ldap_search_s (cldap, cbase, cscope, cfilter,
929
+ cattrs, cattrsonly, cmsg);
930
+ }
931
+ else
932
+ {
933
+ (*ldapdata)->err = ldap_search_st (cldap, cbase, cscope, cfilter,
934
+ cattrs, cattrsonly, &tv, cmsg);
935
+ }
936
+ if (!(cmsg && (*cmsg)))
937
+ {
938
+ rb_raise (rb_eRuntimeError, "no result returned by search");
939
+ }
940
+ Check_LDAP_Result ((*ldapdata)->err);
941
+
942
+ #ifdef HAVE_LDAP_SORT_ENTRIES
943
+ if (rb_ldap_sort_obj != Qnil)
944
+ {
945
+ ldap_sort_entries ((*ldapdata)->ldap, cmsg,
946
+ sort_attr, rb_ldap_internal_strcmp);
947
+ };
948
+ #endif
949
+ rb_ldap_sort_obj = Qnil;
950
+
951
+ return (*ldapdata)->err;
952
+ }
953
+
954
+ static VALUE
955
+ rb_ldap_conn_search_b (VALUE rdata)
956
+ {
957
+ void **data = (void **) rdata;
958
+ LDAP *cldap = (LDAP *) data[0];
959
+ LDAPMessage *cmsg = (LDAPMessage *) data[1];
960
+ LDAPMessage *e;
961
+ VALUE m;
962
+
963
+ for (e = ldap_first_entry (cldap, cmsg); e != NULL;
964
+ e = ldap_next_entry (cldap, e))
965
+ {
966
+ m = rb_ldap_entry_new (cldap, e);
967
+ rb_ensure (rb_yield, m, rb_ldap_conn_invalidate_entry, m);
968
+ }
969
+ return Qnil;
970
+ }
971
+
972
+ static VALUE
973
+ rb_ldap_conn_search2_b (VALUE rdata)
974
+ {
975
+ void **data = (void *) rdata;
976
+ LDAP *cldap = (LDAP *) data[0];
977
+ LDAPMessage *cmsg = (LDAPMessage *) data[1];
978
+ VALUE ary = (VALUE) data[2];
979
+ LDAPMessage *e;
980
+ VALUE m;
981
+ VALUE hash;
982
+
983
+ for (e = ldap_first_entry (cldap, cmsg); e != NULL;
984
+ e = ldap_next_entry (cldap, e))
985
+ {
986
+ m = rb_ldap_entry_new (cldap, e);
987
+ hash = rb_ldap_entry_to_hash (m);
988
+ rb_ary_push (ary, hash);
989
+ if (rb_block_given_p ())
990
+ {
991
+ rb_ensure (rb_yield, hash, rb_ldap_conn_invalidate_entry, m);
992
+ }
993
+ }
994
+ return Qnil;
995
+ }
996
+
997
+ static VALUE
998
+ rb_ldap_msgfree (VALUE data)
999
+ {
1000
+ LDAPMessage *cmsg = (LDAPMessage *) data;
1001
+ ldap_msgfree (cmsg);
1002
+ return Qnil;
1003
+ }
1004
+
1005
+ VALUE
1006
+ rb_ldap_parse_result (LDAP * cldap, LDAPMessage * cmsg)
1007
+ {
1008
+ int rc, err, i;
1009
+ char **referrals;
1010
+ LDAPControl **serverctrls;
1011
+ VALUE refs, ctls, ary;
1012
+
1013
+ refs = rb_ary_new ();
1014
+ ctls = rb_ary_new ();
1015
+ ary = rb_ary_new ();
1016
+
1017
+ rc = ldap_parse_result (cldap, cmsg, &err, NULL, NULL,
1018
+ &referrals, &serverctrls, 0);
1019
+ Check_LDAP_Result (rc);
1020
+ Check_LDAP_Result (err);
1021
+
1022
+ if (referrals)
1023
+ {
1024
+ for (i = 0; referrals[i]; i++)
1025
+ {
1026
+ rb_ary_push (refs, rb_str_new2 (referrals[i]));
1027
+ }
1028
+ }
1029
+
1030
+ if (serverctrls)
1031
+ {
1032
+ for (i = 0; serverctrls[i]; i++)
1033
+ {
1034
+ rb_ary_push (ctls, rb_ldap_control_new2 (serverctrls[i]));
1035
+ }
1036
+ }
1037
+
1038
+ rb_ary_push (ary, refs);
1039
+ rb_ary_push (ary, ctls);
1040
+
1041
+ return ary;
1042
+ }
1043
+
1044
+ /*
1045
+ * call-seq:
1046
+ * conn.search(base_dn, scope, filter, attrs=nil, attrsonly=false,
1047
+ * sec=0, usec=0, s_attr=nil, s_proc=nil) { |entry| } => self
1048
+ *
1049
+ * Perform a search, with the base DN +base_dn+, a scope of +scope+ and a
1050
+ * search filter of +filter+.
1051
+ *
1052
+ * If +attrs+ is present, it should be an array of the attributes that the
1053
+ * search should return. By default, all attributes are returned, which is the
1054
+ * same as specifying an empty array or *nil*. Alternatively, +attrs+ may be a
1055
+ * single string, in which case it will be treated as a single element array.
1056
+ *
1057
+ * If +attrsonly+ is *true*, attributes will be returned, but not their values.
1058
+ *
1059
+ * If +sec+ and/or +usec+ are given, they define the time-out for the search in
1060
+ * seconds and microseconds, respectively.
1061
+ *
1062
+ * If +s_attr+ is given, it specifies the attribute on which to sort the
1063
+ * entries returned by the server. If +s_proc+ is given, it specifies a Proc
1064
+ * object that will be used to sort the entries returned by the server.
1065
+ *
1066
+ * Note that not all results may be returned by this method. If a
1067
+ * size limit has been set for the number of results to be returned and this
1068
+ * limit is exceeded, the results set will be truncated. You can check for
1069
+ * this by calling LDAP::Conn#err immediately after this method and comparing
1070
+ * the result to LDAP::LDAP_SIZELIMIT_EXCEEDED.
1071
+ */
1072
+ VALUE
1073
+ rb_ldap_conn_search_s (int argc, VALUE argv[], VALUE self)
1074
+ {
1075
+ RB_LDAP_DATA *ldapdata;
1076
+ LDAPMessage *cmsg;
1077
+ LDAP *cldap;
1078
+ VALUE rc_ary = Qnil;
1079
+
1080
+ rb_ldap_conn_search_i (argc, argv, self, &ldapdata, &cmsg);
1081
+ cldap = ldapdata->ldap;
1082
+
1083
+ if (ldapdata->err == LDAP_SUCCESS
1084
+ || ldapdata->err == LDAP_SIZELIMIT_EXCEEDED)
1085
+ {
1086
+ void *pass_data[] = { (void *) cldap, (void *) cmsg };
1087
+
1088
+ rc_ary = rb_ldap_parse_result (cldap, cmsg);
1089
+ rb_iv_set (self, "@referrals", rb_ary_shift (rc_ary));
1090
+ rb_iv_set (self, "@controls", rb_ary_shift (rc_ary));
1091
+
1092
+ rb_ensure (rb_ldap_conn_search_b, (VALUE) pass_data,
1093
+ rb_ldap_msgfree, (VALUE) cmsg);
1094
+ };
1095
+
1096
+ return self;
1097
+ }
1098
+
1099
+ /*
1100
+ * call-seq:
1101
+ * conn.search2(base_dn, scope, filter, attrs=nil, attrsonly=false,
1102
+ * sec=0, usec=0, s_attr=nil, s_proc=nil) => array
1103
+ * conn.search2(base_dn, scope, filter, attrs=nil, attrsonly=false,
1104
+ * sec=0, usec=0, s_attr=nil, s_proc=nil) { |entry_as_hash| } => self
1105
+ *
1106
+ * Perform a search, with the base DN +base_dn+, a scope of +scope+ and a
1107
+ * search filter of +filter+.
1108
+ *
1109
+ * If +attrs+ is present, it should be an array of the attributes that the
1110
+ * search should return. By default, all attributes are returned, which is the
1111
+ * same as specifying an empty array or *nil*. Alternatively, +attrs+ may be a
1112
+ * single string, in which case it will be treated as a single element array.
1113
+ *
1114
+ * If +attrsonly+ is *true*, attributes will be returned, but not their values.
1115
+ *
1116
+ * If +sec+ and/or +usec+ are given, they define the time-out for the search in
1117
+ * seconds and microseconds, respectively.
1118
+ *
1119
+ * If +s_attr+ is given, it specifies the attribute on which to sort the
1120
+ * entries returned by the server. If +s_proc+ is given, it specifies a Proc
1121
+ * object that will be used to sort the entries returned by the server.
1122
+ *
1123
+ * Note that not all results may be returned by this method. If a
1124
+ * size limit has been set for the number of results to be returned and this
1125
+ * limit is exceeded, the results set will be truncated. You can check for
1126
+ * this by calling LDAP::Conn#err immediately after this method and comparing
1127
+ * the result to LDAP::LDAP_SIZELIMIT_EXCEEDED.
1128
+ */
1129
+ VALUE
1130
+ rb_ldap_conn_search2_s (int argc, VALUE argv[], VALUE self)
1131
+ {
1132
+ RB_LDAP_DATA *ldapdata;
1133
+ LDAPMessage *cmsg;
1134
+ LDAP *cldap;
1135
+ VALUE ary = Qnil;
1136
+ VALUE rc_ary = Qnil;
1137
+
1138
+ rb_ldap_conn_search_i (argc, argv, self, &ldapdata, &cmsg);
1139
+ cldap = ldapdata->ldap;
1140
+
1141
+ ary = rb_ary_new ();
1142
+ if (ldapdata->err == LDAP_SUCCESS
1143
+ || ldapdata->err == LDAP_SIZELIMIT_EXCEEDED)
1144
+ {
1145
+ void *pass_data[] = { (void *) cldap, (void *) cmsg, (void *) ary };
1146
+
1147
+ rc_ary = rb_ldap_parse_result (cldap, cmsg);
1148
+ rb_iv_set (self, "@referrals", rb_ary_shift (rc_ary));
1149
+ rb_iv_set (self, "@controls", rb_ary_shift (rc_ary));
1150
+
1151
+ rb_ensure (rb_ldap_conn_search2_b, (VALUE) pass_data,
1152
+ rb_ldap_msgfree, (VALUE) cmsg);
1153
+ }
1154
+
1155
+ if (rb_block_given_p ())
1156
+ {
1157
+ return self;
1158
+ }
1159
+ else
1160
+ {
1161
+ return ary;
1162
+ }
1163
+ }
1164
+
1165
+ #if defined(HAVE_LDAPCONTROL) && defined(HAVE_LDAP_SEARCH_EXT_S)
1166
+ static int
1167
+ rb_ldap_conn_search_ext_i (int argc, VALUE argv[], VALUE self,
1168
+ RB_LDAP_DATA ** ldapdata, LDAPMessage ** cmsg)
1169
+ {
1170
+ VALUE base, scope, filter, attrs, attrsonly;
1171
+ VALUE serverctrls, clientctrls, sec, usec, limit, s_attr, s_proc;
1172
+
1173
+ LDAP *cldap;
1174
+ char *cbase;
1175
+ int cscope;
1176
+ int climit;
1177
+ char *cfilter;
1178
+ char **cattrs;
1179
+ char *sort_attr;
1180
+ int cattrsonly;
1181
+ int i;
1182
+ struct timeval tv;
1183
+ LDAPControl **sctrls, **cctrls;
1184
+
1185
+ GET_LDAP_DATA (self, (*ldapdata));
1186
+ cldap = (*ldapdata)->ldap;
1187
+
1188
+ cattrs = NULL;
1189
+ cattrsonly = 0;
1190
+ cctrls = NULL;
1191
+ sctrls = NULL;
1192
+ tv.tv_sec = 0;
1193
+ tv.tv_usec = 0;
1194
+ sort_attr = NULL;
1195
+ rb_ldap_sort_obj = Qnil;
1196
+ climit = 0;
1197
+
1198
+ switch (rb_scan_args (argc, argv, "39",
1199
+ &base, &scope, &filter, &attrs, &attrsonly,
1200
+ &serverctrls, &clientctrls, &sec, &usec, &limit,
1201
+ &s_attr, &s_proc))
1202
+ {
1203
+ case 12:
1204
+ rb_ldap_sort_obj = s_proc; /* Ruby's GC never start in a C function */
1205
+ case 11:
1206
+ if (rb_ldap_sort_obj == Qnil)
1207
+ {
1208
+ rb_ldap_sort_obj = Qtrue;
1209
+ }
1210
+ sort_attr = StringValueCStr (s_attr);
1211
+ case 10:
1212
+ climit = NUM2INT (limit);
1213
+ case 9:
1214
+ tv.tv_usec = NUM2INT (usec);
1215
+ case 8:
1216
+ tv.tv_sec = NUM2INT (sec);
1217
+ case 7:
1218
+ cctrls = rb_ldap_get_controls (clientctrls);
1219
+ case 6:
1220
+ sctrls = rb_ldap_get_controls (serverctrls);
1221
+ case 5:
1222
+ cattrsonly = (attrsonly == Qtrue) ? 1 : 0;
1223
+ case 4:
1224
+ if (TYPE (attrs) == T_NIL)
1225
+ {
1226
+ cattrs = NULL;
1227
+ }
1228
+ else
1229
+ {
1230
+ if (TYPE (attrs) == T_STRING)
1231
+ attrs = rb_ary_to_ary (attrs);
1232
+ else
1233
+ Check_Type (attrs, T_ARRAY);
1234
+
1235
+ if (RARRAY_LEN (attrs) == 0)
1236
+ {
1237
+ cattrs = NULL;
1238
+ }
1239
+ else
1240
+ {
1241
+ cattrs = ALLOCA_N (char *, (RARRAY_LEN (attrs) + 1));
1242
+ for (i = 0; i < RARRAY_LEN (attrs); i++)
1243
+ {
1244
+ cattrs[i] = StringValueCStr (RARRAY_PTR (attrs)[i]);
1245
+ };
1246
+ cattrs[RARRAY_LEN (attrs)] = NULL;
1247
+ }
1248
+ }
1249
+ case 3:
1250
+ cbase = StringValueCStr (base);
1251
+ cscope = NUM2INT (scope);
1252
+ cfilter = StringValueCStr (filter);
1253
+ break;
1254
+ default:
1255
+ rb_bug ("rb_ldap_conn_search_s");
1256
+ };
1257
+
1258
+ (*cmsg) = NULL;
1259
+ if (tv.tv_sec == 0 && tv.tv_usec == 0)
1260
+ {
1261
+ (*ldapdata)->err = ldap_search_ext_s (cldap, cbase, cscope, cfilter,
1262
+ cattrs, cattrsonly,
1263
+ sctrls, cctrls,
1264
+ NULL, climit, cmsg);
1265
+ }
1266
+ else
1267
+ {
1268
+ (*ldapdata)->err = ldap_search_ext_s (cldap, cbase, cscope, cfilter,
1269
+ cattrs, cattrsonly,
1270
+ sctrls, cctrls,
1271
+ &tv, climit, cmsg);
1272
+ }
1273
+ Check_LDAP_Result ((*ldapdata)->err);
1274
+
1275
+ #ifdef HAVE_LDAP_SORT_ENTRIES
1276
+ if (rb_ldap_sort_obj != Qnil)
1277
+ {
1278
+ ldap_sort_entries ((*ldapdata)->ldap, cmsg,
1279
+ sort_attr, rb_ldap_internal_strcmp);
1280
+ };
1281
+ #endif
1282
+ rb_ldap_sort_obj = Qnil;
1283
+
1284
+ return (*ldapdata)->err;
1285
+ };
1286
+
1287
+ /*
1288
+ * call-seq:
1289
+ * conn.search_ext(base_dn, scope, filter, attrs=nil, attrsonly=false,
1290
+ * sctrls, cctrls, sec=0, usec=0, s_attr=nil, s_proc=nil)
1291
+ * { |entry| } => self
1292
+ *
1293
+ * Perform a search, with the base DN +base_dn+, a scope of +scope+ and a
1294
+ * search filter of +filter+.
1295
+ *
1296
+ * If +attrs+ is present, it should be an array of the attributes that the
1297
+ * search should return. By default, all attributes are returned, which is the
1298
+ * same as specifying an empty array or *nil*. Alternatively, +attrs+ may be a
1299
+ * single string, in which case it will be treated as a single element array.
1300
+ *
1301
+ * If +attrsonly+ is *true*, attributes will be returned, but not their values.
1302
+ *
1303
+ * +sctrls+ is an array of server controls, whilst +cctrls+ is an array of
1304
+ * client controls.
1305
+ *
1306
+ * If +sec+ and/or +usec+ are given, they define the time-out for the search in
1307
+ * seconds and microseconds, respectively.
1308
+ *
1309
+ * If +s_attr+ is given, it specifies the attribute on which to sort the
1310
+ * entries returned by the server. If +s_proc+ is given, it specifies a Proc
1311
+ * object that will be used to sort the entries returned by the server.
1312
+ *
1313
+ * Note that not all results may be returned by this method. If a
1314
+ * size limit has been set for the number of results to be returned and this
1315
+ * limit is exceeded, the results set will be truncated. You can check for
1316
+ * this by calling LDAP::Conn#err immediately after this method and comparing
1317
+ * the result to LDAP::LDAP_SIZELIMIT_EXCEEDED.
1318
+ */
1319
+ VALUE
1320
+ rb_ldap_conn_search_ext_s (int argc, VALUE argv[], VALUE self)
1321
+ {
1322
+ RB_LDAP_DATA *ldapdata;
1323
+ LDAPMessage *cmsg;
1324
+ LDAP *cldap;
1325
+ VALUE rc_ary = Qnil;
1326
+
1327
+ rb_ldap_conn_search_ext_i (argc, argv, self, &ldapdata, &cmsg);
1328
+ cldap = ldapdata->ldap;
1329
+
1330
+ if (ldapdata->err == LDAP_SUCCESS
1331
+ || ldapdata->err == LDAP_SIZELIMIT_EXCEEDED)
1332
+ {
1333
+ void *pass_data[] = { (void *) cldap, (void *) cmsg };
1334
+
1335
+ rc_ary = rb_ldap_parse_result (cldap, cmsg);
1336
+ rb_iv_set (self, "@referrals", rb_ary_shift (rc_ary));
1337
+ rb_iv_set (self, "@controls", rb_ary_shift (rc_ary));
1338
+
1339
+ rb_ensure (rb_ldap_conn_search_b, (VALUE) pass_data,
1340
+ rb_ldap_msgfree, (VALUE) cmsg);
1341
+ };
1342
+
1343
+ return self;
1344
+ };
1345
+
1346
+ /*
1347
+ * call-seq:
1348
+ * conn.search_ext2(base_dn, scope, filter, attrs=nil,
1349
+ * attrsonly=false, sctrls, cctrls, sec=0, usec=0,
1350
+ * s_attr=nil, s_proc=nil) => array
1351
+ * conn.search_ext2(base_dn, scope, filter, attrs=nil,
1352
+ * attrsonly=false, sctrls, cctrls, sec=0, usec=0,
1353
+ * s_attr=nil, s_proc=nil) { |entry_as_hash| } => self
1354
+ *
1355
+ * Perform a search, with the base DN +base_dn+, a scope of +scope+ and a
1356
+ * search filter of +filter+.
1357
+ *
1358
+ * If +attrs+ is present, it should be an array of the attributes that the
1359
+ * search should return. By default, all attributes are returned, which is the
1360
+ * same as specifying an empty array or *nil*. Alternatively, +attrs+ may be a
1361
+ * single string, in which case it will be treated as a single element array.
1362
+ *
1363
+ * If +attrsonly+ is *true*, attributes will be returned, but not their values.
1364
+ *
1365
+ * +sctrls+ is an array of server controls, whilst +cctrls+ is an array of
1366
+ * client controls.
1367
+ *
1368
+ * If +sec+ and/or +usec+ are given, they define the time-out for the search in
1369
+ * seconds and microseconds, respectively.
1370
+ *
1371
+ * If +s_attr+ is given, it specifies the attribute on which to sort the
1372
+ * entries returned by the server. If +s_proc+ is given, it specifies a Proc
1373
+ * object that will be used to sort the entries returned by the server.
1374
+ *
1375
+ * Note that not all results may be returned by this method. If a
1376
+ * size limit has been set for the number of results to be returned and this
1377
+ * limit is exceeded, the results set will be truncated. You can check for
1378
+ * this by calling LDAP::Conn#err immediately after this method and comparing
1379
+ * the result to LDAP::LDAP_SIZELIMIT_EXCEEDED.
1380
+ */
1381
+ VALUE
1382
+ rb_ldap_conn_search_ext2_s (int argc, VALUE argv[], VALUE self)
1383
+ {
1384
+ RB_LDAP_DATA *ldapdata;
1385
+ LDAPMessage *cmsg;
1386
+ LDAP *cldap;
1387
+ VALUE ary;
1388
+ VALUE rc_ary = Qnil;
1389
+
1390
+ rb_ldap_conn_search_ext_i (argc, argv, self, &ldapdata, &cmsg);
1391
+ cldap = ldapdata->ldap;
1392
+
1393
+ ary = rb_ary_new ();
1394
+ if (ldapdata->err == LDAP_SUCCESS
1395
+ || ldapdata->err == LDAP_SIZELIMIT_EXCEEDED)
1396
+ {
1397
+ void *pass_data[] = { (void *) cldap, (void *) cmsg, (void *) ary };
1398
+
1399
+ rc_ary = rb_ldap_parse_result (cldap, cmsg);
1400
+ rb_iv_set (self, "@referrals", rb_ary_shift (rc_ary));
1401
+ rb_iv_set (self, "@controls", rb_ary_shift (rc_ary));
1402
+
1403
+ rb_ensure (rb_ldap_conn_search2_b, (VALUE) pass_data,
1404
+ rb_ldap_msgfree, (VALUE) cmsg);
1405
+ }
1406
+
1407
+ if (rb_block_given_p ())
1408
+ {
1409
+ return self;
1410
+ }
1411
+ else
1412
+ {
1413
+ return ary;
1414
+ }
1415
+ }
1416
+ #endif
1417
+
1418
+ /*
1419
+ * call-seq:
1420
+ * conn.add(dn, attrs) => self
1421
+ *
1422
+ * Add an entry with the DN, +dn+, and the attributes, +attrs+. +attrs+
1423
+ * should be either an array of LDAP#Mod objects or a hash of attribute/value
1424
+ * array pairs.
1425
+ */
1426
+ VALUE
1427
+ rb_ldap_conn_add_s (VALUE self, VALUE dn, VALUE attrs)
1428
+ {
1429
+ RB_LDAP_DATA *ldapdata;
1430
+ char *c_dn;
1431
+ LDAPMod **c_attrs;
1432
+ int i;
1433
+
1434
+ switch (TYPE (attrs))
1435
+ {
1436
+ case T_HASH:
1437
+ attrs = rb_ldap_hash2mods (rb_mLDAP,
1438
+ INT2NUM (LDAP_MOD_ADD | LDAP_MOD_BVALUES),
1439
+ attrs);
1440
+ break;
1441
+ case T_ARRAY:
1442
+ break;
1443
+ default:
1444
+ rb_raise (rb_eTypeError, "must be a hash or an array");
1445
+ };
1446
+
1447
+ GET_LDAP_DATA (self, ldapdata);
1448
+ c_dn = StringValueCStr (dn);
1449
+ c_attrs = ALLOCA_N (LDAPMod *, (RARRAY_LEN (attrs) + 1));
1450
+
1451
+ for (i = 0; i < RARRAY_LEN (attrs); i++)
1452
+ {
1453
+ VALUE mod = RARRAY_PTR (attrs)[i];
1454
+ RB_LDAPMOD_DATA *moddata;
1455
+ Check_Kind (mod, rb_cLDAP_Mod);
1456
+ GET_LDAPMOD_DATA (mod, moddata);
1457
+ c_attrs[i] = moddata->mod;
1458
+ };
1459
+ c_attrs[i] = NULL;
1460
+
1461
+ ldapdata->err = ldap_add_s (ldapdata->ldap, c_dn, c_attrs);
1462
+ Check_LDAP_Result (ldapdata->err);
1463
+
1464
+ return self;
1465
+ };
1466
+
1467
+ #if defined(HAVE_LDAPCONTROL) && defined(HAVE_LDAP_ADD_EXT_S)
1468
+ /*
1469
+ * call-seq:
1470
+ * conn.add_ext(dn, attrs, sctrls, cctrls) => self
1471
+ *
1472
+ * Add an entry with the DN, +dn+, and the attributes, +attrs+. +attrs+
1473
+ * should be either an array of LDAP#Mod objects or a hash of attribute/value
1474
+ * array pairs. +sctrls+ is an array of server controls, whilst +cctrls+ is
1475
+ * an array of client controls.
1476
+ */
1477
+ VALUE
1478
+ rb_ldap_conn_add_ext_s (VALUE self, VALUE dn, VALUE attrs,
1479
+ VALUE serverctrls, VALUE clientctrls)
1480
+ {
1481
+ RB_LDAP_DATA *ldapdata;
1482
+ char *c_dn;
1483
+ LDAPMod **c_attrs;
1484
+ int i;
1485
+ LDAPControl **sctrls, **cctrls;
1486
+
1487
+ switch (TYPE (attrs))
1488
+ {
1489
+ case T_HASH:
1490
+ attrs = rb_ldap_hash2mods (rb_mLDAP,
1491
+ INT2NUM (LDAP_MOD_ADD | LDAP_MOD_BVALUES),
1492
+ attrs);
1493
+ break;
1494
+ case T_ARRAY:
1495
+ break;
1496
+ default:
1497
+ rb_raise (rb_eTypeError, "must be a hash or an array");
1498
+ };
1499
+
1500
+ GET_LDAP_DATA (self, ldapdata);
1501
+ c_dn = StringValueCStr (dn);
1502
+ c_attrs = ALLOCA_N (LDAPMod *, (RARRAY_LEN (attrs) + 1));
1503
+ sctrls = rb_ldap_get_controls (serverctrls);
1504
+ cctrls = rb_ldap_get_controls (clientctrls);
1505
+
1506
+ for (i = 0; i < RARRAY_LEN (attrs); i++)
1507
+ {
1508
+ VALUE mod = RARRAY_PTR (attrs)[i];
1509
+ RB_LDAPMOD_DATA *moddata;
1510
+ Check_Kind (mod, rb_cLDAP_Mod);
1511
+ GET_LDAPMOD_DATA (mod, moddata);
1512
+ c_attrs[i] = moddata->mod;
1513
+ };
1514
+ c_attrs[i] = NULL;
1515
+
1516
+ ldapdata->err =
1517
+ ldap_add_ext_s (ldapdata->ldap, c_dn, c_attrs, sctrls, cctrls);
1518
+ Check_LDAP_Result (ldapdata->err);
1519
+
1520
+ return self;
1521
+ }
1522
+ #endif
1523
+
1524
+ /*
1525
+ * call-seq:
1526
+ * conn.modify(dn, mods) => self
1527
+ *
1528
+ * Modify an entry with the DN, +dn+, and the attributes, +mods+. +mods+
1529
+ * should be either an array of LDAP#Mod objects or a hash of attribute/value
1530
+ * array pairs.
1531
+ */
1532
+ VALUE
1533
+ rb_ldap_conn_modify_s (VALUE self, VALUE dn, VALUE attrs)
1534
+ {
1535
+ RB_LDAP_DATA *ldapdata;
1536
+ char *c_dn;
1537
+ LDAPMod **c_attrs;
1538
+ int i;
1539
+
1540
+ switch (TYPE (attrs))
1541
+ {
1542
+ case T_HASH:
1543
+ attrs =
1544
+ rb_ldap_hash2mods (rb_mLDAP,
1545
+ INT2NUM (LDAP_MOD_REPLACE | LDAP_MOD_BVALUES),
1546
+ attrs);
1547
+ break;
1548
+ case T_ARRAY:
1549
+ break;
1550
+ default:
1551
+ rb_raise (rb_eTypeError, "must be a hash or an array");
1552
+ };
1553
+
1554
+ GET_LDAP_DATA (self, ldapdata);
1555
+ c_dn = StringValueCStr (dn);
1556
+ c_attrs = ALLOC_N (LDAPMod *, RARRAY_LEN (attrs) + 1);
1557
+
1558
+ for (i = 0; i < RARRAY_LEN (attrs); i++)
1559
+ {
1560
+ VALUE mod = RARRAY_PTR (attrs)[i];
1561
+ RB_LDAPMOD_DATA *moddata;
1562
+ Check_Kind (mod, rb_cLDAP_Mod);
1563
+ GET_LDAPMOD_DATA (mod, moddata);
1564
+ c_attrs[i] = moddata->mod;
1565
+ };
1566
+ c_attrs[i] = NULL;
1567
+
1568
+ ldapdata->err = ldap_modify_s (ldapdata->ldap, c_dn, c_attrs);
1569
+ Check_LDAP_Result (ldapdata->err);
1570
+ free(c_attrs);
1571
+
1572
+ return self;
1573
+ };
1574
+
1575
+ #if defined(HAVE_LDAPCONTROL) && defined(HAVE_LDAP_MODIFY_EXT_S)
1576
+ /*
1577
+ * call-seq:
1578
+ * conn.modify_ext(dn, mods, sctrls, cctrls) => self
1579
+ *
1580
+ * Modify an entry with the DN, +dn+, and the attributes, +mods+. +mods+
1581
+ * should be either an array of LDAP#Mod objects or a hash of attribute/value
1582
+ * array pairs. +sctrls+ is an array of server controls, whilst +cctrls+ is
1583
+ * an array of client controls.
1584
+ */
1585
+ VALUE
1586
+ rb_ldap_conn_modify_ext_s (VALUE self, VALUE dn, VALUE attrs,
1587
+ VALUE serverctrls, VALUE clientctrls)
1588
+ {
1589
+ RB_LDAP_DATA *ldapdata;
1590
+ char *c_dn;
1591
+ LDAPMod **c_attrs;
1592
+ int i;
1593
+ LDAPControl **sctrls, **cctrls;
1594
+
1595
+ switch (TYPE (attrs))
1596
+ {
1597
+ case T_HASH:
1598
+ attrs =
1599
+ rb_ldap_hash2mods (rb_mLDAP,
1600
+ INT2NUM (LDAP_MOD_REPLACE | LDAP_MOD_BVALUES),
1601
+ attrs);
1602
+ break;
1603
+ case T_ARRAY:
1604
+ break;
1605
+ default:
1606
+ rb_raise (rb_eTypeError, "must be a hash or an array");
1607
+ };
1608
+
1609
+ GET_LDAP_DATA (self, ldapdata);
1610
+ c_dn = StringValueCStr (dn);
1611
+ c_attrs = ALLOC_N (LDAPMod *, RARRAY_LEN (attrs) + 1);
1612
+ sctrls = rb_ldap_get_controls (serverctrls);
1613
+ cctrls = rb_ldap_get_controls (clientctrls);
1614
+
1615
+ for (i = 0; i < RARRAY_LEN (attrs); i++)
1616
+ {
1617
+ VALUE mod = RARRAY_PTR (attrs)[i];
1618
+ RB_LDAPMOD_DATA *moddata;
1619
+ Check_Kind (mod, rb_cLDAP_Mod);
1620
+ GET_LDAPMOD_DATA (mod, moddata);
1621
+ c_attrs[i] = moddata->mod;
1622
+ };
1623
+ c_attrs[i] = NULL;
1624
+
1625
+ ldapdata->err =
1626
+ ldap_modify_ext_s (ldapdata->ldap, c_dn, c_attrs, sctrls, cctrls);
1627
+ Check_LDAP_Result (ldapdata->err);
1628
+
1629
+ return self;
1630
+ }
1631
+ #endif
1632
+
1633
+ /*
1634
+ * call-seq:
1635
+ * conn.modrdn(dn, new_rdn, delete_old_rdn) => self
1636
+ *
1637
+ * Modify the RDN of the entry with DN, +dn+, giving it the new RDN,
1638
+ * +new_rdn+. If +delete_old_rdn+ is *true*, the old RDN value will be deleted
1639
+ * from the entry.
1640
+ */
1641
+ VALUE
1642
+ rb_ldap_conn_modrdn_s (VALUE self, VALUE dn, VALUE newrdn, VALUE delete_p)
1643
+ {
1644
+ RB_LDAP_DATA *ldapdata;
1645
+ char *c_dn;
1646
+ char *c_newrdn;
1647
+ int c_delete_p;
1648
+
1649
+ GET_LDAP_DATA (self, ldapdata);
1650
+ c_dn = StringValueCStr (dn);
1651
+ c_newrdn = StringValueCStr (newrdn);
1652
+ c_delete_p = (delete_p == Qtrue) ? 1 : 0;
1653
+
1654
+ ldapdata->err = ldap_modrdn2_s (ldapdata->ldap, c_dn, c_newrdn, c_delete_p);
1655
+ Check_LDAP_Result (ldapdata->err);
1656
+
1657
+ return self;
1658
+ };
1659
+
1660
+ #if defined(HAVE_LDAPCONTROL) && defined(HAVE_LDAP_RENAME_S)
1661
+ /*
1662
+ * call-seq:
1663
+ * conn.rename(dn, new_rdn, new_parent_dn, delete_old_rdn, sctrls, cctrls) => self
1664
+ *
1665
+ * Modify the RDN of the entry with DN, +dn+, giving it the new RDN in
1666
+ * parent +new_parent_dn+, +new_rdn+. If you don't want to change
1667
+ * parent, specify *nil* to +new_parent_dn+. If +delete_old_rdn+ is
1668
+ * *true*, the old RDN value will be deleted from the entry.
1669
+ */
1670
+ VALUE
1671
+ rb_ldap_conn_rename_s (VALUE self, VALUE dn, VALUE newrdn, VALUE newparentdn, VALUE delete_p,
1672
+ VALUE serverctrls, VALUE clientctrls)
1673
+ {
1674
+ RB_LDAP_DATA *ldapdata;
1675
+ char *c_dn;
1676
+ char *c_newrdn;
1677
+ char *c_newparentdn = NULL;
1678
+ int c_delete_p;
1679
+ LDAPControl **sctrls, **cctrls;
1680
+
1681
+ GET_LDAP_DATA (self, ldapdata);
1682
+ c_dn = StringValueCStr (dn);
1683
+ c_newrdn = StringValueCStr (newrdn);
1684
+ if (!NIL_P(newparentdn)) {
1685
+ c_newparentdn = StringValueCStr (newparentdn);
1686
+ }
1687
+ c_delete_p = (delete_p == Qtrue) ? 1 : 0;
1688
+ sctrls = rb_ldap_get_controls (serverctrls);
1689
+ cctrls = rb_ldap_get_controls (clientctrls);
1690
+
1691
+ ldapdata->err =
1692
+ ldap_rename_s (ldapdata->ldap, c_dn, c_newrdn, c_newparentdn, c_delete_p, sctrls, cctrls);
1693
+ Check_LDAP_Result (ldapdata->err);
1694
+
1695
+ return self;
1696
+ }
1697
+ #endif
1698
+
1699
+ /*
1700
+ * call-seq:
1701
+ * conn.delete(dn) => self
1702
+ *
1703
+ * Delete the entry with the DN, +dn+.
1704
+ */
1705
+ VALUE
1706
+ rb_ldap_conn_delete_s (VALUE self, VALUE dn)
1707
+ {
1708
+ RB_LDAP_DATA *ldapdata;
1709
+ char *c_dn;
1710
+
1711
+ GET_LDAP_DATA (self, ldapdata);
1712
+ c_dn = StringValueCStr (dn);
1713
+
1714
+ ldapdata->err = ldap_delete_s (ldapdata->ldap, c_dn);
1715
+ Check_LDAP_Result (ldapdata->err);
1716
+
1717
+ return self;
1718
+ };
1719
+
1720
+ #if defined(HAVE_LDAPCONTROL) && defined(HAVE_LDAP_DELETE_EXT_S)
1721
+ /*
1722
+ * call-seq:
1723
+ * conn.delete_ext(dn, sctrls, cctrls) => self
1724
+ *
1725
+ * Delete the entry with the DN, +dn+. +sctrls+ is an array of server
1726
+ * controls, whilst +cctrls+ is an array of client controls.
1727
+ */
1728
+ VALUE
1729
+ rb_ldap_conn_delete_ext_s (VALUE self, VALUE dn,
1730
+ VALUE serverctrls, VALUE clientctrls)
1731
+ {
1732
+ RB_LDAP_DATA *ldapdata;
1733
+ char *c_dn;
1734
+ LDAPControl **sctrls, **cctrls;
1735
+
1736
+ GET_LDAP_DATA (self, ldapdata);
1737
+ c_dn = StringValueCStr (dn);
1738
+ sctrls = rb_ldap_get_controls (serverctrls);
1739
+ cctrls = rb_ldap_get_controls (clientctrls);
1740
+
1741
+ ldapdata->err = ldap_delete_ext_s (ldapdata->ldap, c_dn, sctrls, cctrls);
1742
+ Check_LDAP_Result (ldapdata->err);
1743
+
1744
+ return self;
1745
+ }
1746
+ #endif
1747
+
1748
+ #if defined(HAVE_LDAP_COMPARE_S)
1749
+ /*
1750
+ * call-seq:
1751
+ * conn.compare(dn, attr, val) => true or false
1752
+ *
1753
+ * Compare the DN given as +dn+ to see whether it has the attribute +attr+
1754
+ * with a value of +val+.
1755
+ */
1756
+ VALUE
1757
+ rb_ldap_conn_compare_s (VALUE self, VALUE dn, VALUE attr, VALUE val)
1758
+ {
1759
+ RB_LDAP_DATA *ldapdata;
1760
+ char *c_dn, *c_attr, *c_val;
1761
+
1762
+ GET_LDAP_DATA (self, ldapdata);
1763
+ c_dn = StringValueCStr (dn);
1764
+ c_attr = StringValueCStr (attr);
1765
+ c_val = StringValueCStr (val);
1766
+
1767
+ ldapdata->err = ldap_compare_s (ldapdata->ldap, c_dn, c_attr, c_val);
1768
+
1769
+ if ((ldapdata->err) == LDAP_COMPARE_TRUE)
1770
+ return Qtrue;
1771
+ else if ((ldapdata->err) == LDAP_COMPARE_FALSE)
1772
+ return Qfalse;
1773
+
1774
+ Check_LDAP_Result (ldapdata->err);
1775
+
1776
+ fprintf (stderr, "rb_ldap_conn_compare_s() unexpectedly set no error.\n");
1777
+
1778
+ return self;
1779
+ }
1780
+ #endif
1781
+
1782
+ #if defined(HAVE_LDAPCONTROL) && defined(HAVE_LDAP_COMPARE_EXT_S)
1783
+ /*
1784
+ * call-seq:
1785
+ * conn.compare_ext(dn, attr, val, sctrls, cctrls) => true or false
1786
+ *
1787
+ * Compare the DN given as +dn+ to see whether it has the attribute +attr+
1788
+ * with a value of +val+. +sctrls+ is an array of server controls, whilst
1789
+ * +cctrls+ is an array of client controls.
1790
+ */
1791
+ VALUE
1792
+ rb_ldap_conn_compare_ext_s (VALUE self, VALUE dn, VALUE attr, VALUE val,
1793
+ VALUE serverctrls, VALUE clientctrls)
1794
+ {
1795
+ RB_LDAP_DATA *ldapdata;
1796
+ char *c_dn, *c_attr;
1797
+ #ifdef USE_WLDAP32
1798
+ char *c_val;
1799
+ #endif
1800
+ struct berval bval;
1801
+ LDAPControl **sctrls, **cctrls;
1802
+
1803
+ GET_LDAP_DATA (self, ldapdata);
1804
+ c_dn = StringValueCStr (dn);
1805
+ c_attr = StringValueCStr (attr);
1806
+ #ifdef USE_WLDAP32
1807
+ c_val = StringValueCStr (val);
1808
+ #endif
1809
+ bval.bv_val = StringValueCStr (val);
1810
+ bval.bv_len = RSTRING_LEN (val);
1811
+ sctrls = rb_ldap_get_controls (serverctrls);
1812
+ cctrls = rb_ldap_get_controls (clientctrls);
1813
+
1814
+ ldapdata->err = ldap_compare_ext_s (ldapdata->ldap, c_dn, c_attr,
1815
+ #ifdef USE_WLDAP32
1816
+ c_val,
1817
+ #endif
1818
+ &bval, sctrls, cctrls);
1819
+
1820
+ if ((ldapdata->err) == LDAP_COMPARE_TRUE)
1821
+ return Qtrue;
1822
+ else if ((ldapdata->err) == LDAP_COMPARE_FALSE)
1823
+ return Qfalse;
1824
+
1825
+ Check_LDAP_Result (ldapdata->err);
1826
+
1827
+ fprintf (stderr,
1828
+ "rb_ldap_conn_compare_ext_s() unexpectedly set no error.\n");
1829
+
1830
+ return self;
1831
+ }
1832
+ #endif
1833
+
1834
+ /*
1835
+ * call-seq:
1836
+ * conn.err => Fixnum
1837
+ *
1838
+ * Return the error associated with the most recent LDAP operation.
1839
+ */
1840
+ VALUE
1841
+ rb_ldap_conn_err (VALUE self)
1842
+ {
1843
+ RB_LDAP_DATA *ldapdata;
1844
+
1845
+ GET_LDAP_DATA (self, ldapdata);
1846
+ return INT2NUM (ldapdata->err);
1847
+ };
1848
+
1849
+ /* Document-class: LDAP::Conn
1850
+ *
1851
+ * Create and manipulate unencrypted LDAP connections.
1852
+ */
1853
+ void
1854
+ Init_ldap_conn ()
1855
+ {
1856
+ rb_ldap_sort_obj = Qnil;
1857
+
1858
+ rb_cLDAP_Conn = rb_define_class_under (rb_mLDAP, "Conn", rb_cData);
1859
+ rb_define_attr (rb_cLDAP_Conn, "referrals", 1, 0);
1860
+ rb_define_attr (rb_cLDAP_Conn, "controls", 1, 0);
1861
+ rb_define_attr (rb_cLDAP_Conn, "sasl_quiet", 1, 1);
1862
+ #if RUBY_VERSION_CODE < 170
1863
+ rb_define_singleton_method (rb_cLDAP_Conn, "new", rb_ldap_class_new, -1);
1864
+ #endif
1865
+ #if RUBY_VERSION_CODE >= 173
1866
+ rb_define_alloc_func (rb_cLDAP_Conn, rb_ldap_conn_s_allocate);
1867
+ #else
1868
+ rb_define_singleton_method (rb_cLDAP_Conn, "allocate",
1869
+ rb_ldap_conn_s_allocate, 0);
1870
+ #endif
1871
+ rb_define_singleton_method (rb_cLDAP_Conn, "open", rb_ldap_conn_s_open, -1);
1872
+ rb_define_singleton_method (rb_cLDAP_Conn, "open_uri", rb_ldap_conn_s_open_uri, 1);
1873
+ rb_define_singleton_method (rb_cLDAP_Conn, "set_option",
1874
+ rb_ldap_conn_s_set_option, 2);
1875
+ rb_define_singleton_method (rb_cLDAP_Conn, "get_option",
1876
+ rb_ldap_conn_s_get_option, 1);
1877
+ rb_ldap_conn_define_method ("initialize", rb_ldap_conn_initialize, -1);
1878
+ rb_ldap_conn_define_method ("start_tls", rb_ldap_conn_start_tls_s, -1);
1879
+ rb_ldap_conn_define_method ("simple_bind", rb_ldap_conn_simple_bind_s, -1);
1880
+ rb_ldap_conn_define_method ("bind", rb_ldap_conn_bind_s, -1);
1881
+ rb_ldap_conn_define_method ("bound?", rb_ldap_conn_bound, 0);
1882
+ rb_ldap_conn_define_method ("unbind", rb_ldap_conn_unbind, 0);
1883
+ rb_ldap_conn_define_method ("set_option", rb_ldap_conn_set_option, 2);
1884
+ rb_ldap_conn_define_method ("get_option", rb_ldap_conn_get_option, 1);
1885
+ rb_ldap_conn_define_method ("search", rb_ldap_conn_search_s, -1);
1886
+ rb_ldap_conn_define_method ("search2", rb_ldap_conn_search2_s, -1);
1887
+ rb_ldap_conn_define_method ("add", rb_ldap_conn_add_s, 2);
1888
+ rb_ldap_conn_define_method ("modify", rb_ldap_conn_modify_s, 2);
1889
+ rb_ldap_conn_define_method ("modrdn", rb_ldap_conn_modrdn_s, 3);
1890
+ #if defined(HAVE_LDAPCONTROL) && defined(HAVE_LDAP_RENAME_S)
1891
+ rb_ldap_conn_define_method ("rename", rb_ldap_conn_rename_s, 6);
1892
+ #endif
1893
+ rb_ldap_conn_define_method ("delete", rb_ldap_conn_delete_s, 1);
1894
+ #if defined(HAVE_LDAP_COMPARE_S)
1895
+ rb_ldap_conn_define_method ("compare", rb_ldap_conn_compare_s, 3);
1896
+ #endif
1897
+ rb_ldap_conn_define_method ("perror", rb_ldap_conn_perror, 1);
1898
+ rb_ldap_conn_define_method ("err2string", rb_ldap_conn_err2string, 1);
1899
+ rb_ldap_conn_define_method ("result2error", rb_ldap_conn_result2error, 1);
1900
+ rb_ldap_conn_define_method ("err", rb_ldap_conn_err, 0);
1901
+
1902
+ #if defined(HAVE_LDAP_SEARCH_EXT_S)
1903
+ rb_ldap_conn_define_method ("search_ext", rb_ldap_conn_search_ext_s, -1);
1904
+ rb_ldap_conn_define_method ("search_ext2", rb_ldap_conn_search_ext2_s, -1);
1905
+ #endif
1906
+ #if defined(HAVE_LDAP_ADD_EXT_S)
1907
+ rb_ldap_conn_define_method ("add_ext", rb_ldap_conn_add_ext_s, 4);
1908
+ #endif
1909
+ #if defined(HAVE_LDAP_MODIFY_EXT_S)
1910
+ rb_ldap_conn_define_method ("modify_ext", rb_ldap_conn_modify_ext_s, 4);
1911
+ #endif
1912
+ #if defined(HAVE_LDAP_DELETE_EXT_S)
1913
+ rb_ldap_conn_define_method ("delete_ext", rb_ldap_conn_delete_ext_s, 3);
1914
+ #endif
1915
+ #if defined(HAVE_LDAP_COMPARE_EXT_S)
1916
+ rb_ldap_conn_define_method ("compare_ext", rb_ldap_conn_compare_ext_s, 5);
1917
+ #endif
1918
+ };