@@ -334,8 +334,9 @@ class LdapError < StandardError; end
334
334
68 => "Entry Already Exists"
335
335
}
336
336
337
- module LdapControls
338
- PagedResults = "1.2.840.113556.1.4.319" # Microsoft evil from RFC 2696
337
+ module LDAPControls
338
+ PAGED_RESULTS = "1.2.840.113556.1.4.319" # Microsoft evil from RFC 2696
339
+ DELETE_TREE = "1.2.840.113556.1.4.805"
339
340
end
340
341
341
342
def self . result2string ( code ) #:nodoc:
@@ -552,7 +553,7 @@ def open
552
553
# anything with the bind results. We then pass self to the caller's
553
554
# block, where he will execute his LDAP operations. Of course they will
554
555
# all generate auth failures if the bind was unsuccessful.
555
- raise Net :: LDAP :: LdapError , "Open already in progress" if @open_connection
556
+ raise LdapError , "Open already in progress" if @open_connection
556
557
557
558
begin
558
559
@open_connection = Net ::LDAP ::Connection . new ( :host => @host ,
@@ -1022,6 +1023,19 @@ def delete(args)
1022
1023
@result == 0
1023
1024
end
1024
1025
1026
+ # Delete an entry from the LDAP directory along with all subordinate entries.
1027
+ # the regular delete method will fail to delete an entry if it has subordinate
1028
+ # entries. This method sends an extra control code to tell the LDAP server
1029
+ # to do a tree delete. ('1.2.840.113556.1.4.805')
1030
+ #
1031
+ # Returns True or False to indicate whether the delete succeeded. Extended
1032
+ # status information is available by calling #get_operation_result.
1033
+ #
1034
+ # dn = "[email protected] , ou=people, dc=example, dc=com"
1035
+ # ldap.delete_tree :dn => dn
1036
+ def delete_tree ( args )
1037
+ delete ( args . merge ( :control_codes => [ [ LDAPControls ::DELETE_TREE , true ] ] ) )
1038
+ end
1025
1039
# This method is experimental and subject to change. Return the rootDSE
1026
1040
# record from the LDAP server as a Net::LDAP::Entry, or an empty Entry if
1027
1041
# the server doesn't return the record.
@@ -1092,7 +1106,7 @@ def search_subschema_entry
1092
1106
#++
1093
1107
def paged_searches_supported?
1094
1108
@server_caps ||= search_root_dse
1095
- @server_caps [ :supportedcontrol ] . include? ( Net :: LDAP :: LdapControls :: PagedResults )
1109
+ @server_caps [ :supportedcontrol ] . include? ( LDAPControls :: PAGED_RESULTS )
1096
1110
end
1097
1111
end # class LDAP
1098
1112
@@ -1389,7 +1403,7 @@ def search(args = {})
1389
1403
controls = [ ]
1390
1404
controls <<
1391
1405
[
1392
- Net :: LDAP :: LdapControls :: PagedResults . to_ber ,
1406
+ LDAPControls :: PAGED_RESULTS . to_ber ,
1393
1407
# Criticality MUST be false to interoperate with normal LDAPs.
1394
1408
false . to_ber ,
1395
1409
rfc2696_cookie . map { |v | v . to_ber } . to_ber_sequence . to_s . to_ber
@@ -1437,7 +1451,7 @@ def search(args = {})
1437
1451
more_pages = false
1438
1452
if result_code == 0 and controls
1439
1453
controls . each do |c |
1440
- if c . oid == Net :: LDAP :: LdapControls :: PagedResults
1454
+ if c . oid == LDAPControls :: PAGED_RESULTS
1441
1455
# just in case some bogus server sends us more than 1 of these.
1442
1456
more_pages = false
1443
1457
if c . value and c . value . length > 0
@@ -1545,9 +1559,9 @@ def rename args
1545
1559
#++
1546
1560
def delete ( args )
1547
1561
dn = args [ :dn ] or raise "Unable to delete empty DN"
1548
-
1562
+ controls = args . include? ( :control_codes ) ? args [ :control_codes ] . to_ber_control : nil #use nil so we can compact later
1549
1563
request = dn . to_s . to_ber_application_string ( 10 )
1550
- pkt = [ next_msgid . to_ber , request ] . to_ber_sequence
1564
+ pkt = [ next_msgid . to_ber , request , controls ] . compact . to_ber_sequence
1551
1565
@conn . write pkt
1552
1566
1553
1567
( be = @conn . read_ber ( Net ::LDAP ::AsnSyntax ) ) && ( pdu = Net ::LDAP ::PDU . new ( be ) ) && ( pdu . app_tag == 11 ) or raise Net ::LDAP ::LdapError , "response missing or invalid"
0 commit comments