Merge pull request #1 from partnerpedia/add_delete_tree
added the ability to do a delete_tree
This commit is contained in:
commit
528ef30801
6 changed files with 70 additions and 11 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -9,3 +9,4 @@ publish/
|
||||||
coverage/
|
coverage/
|
||||||
coverage.info
|
coverage.info
|
||||||
.rake_tasks~
|
.rake_tasks~
|
||||||
|
Gemfile.lock
|
||||||
|
|
2
Gemfile
Normal file
2
Gemfile
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
source :rubygems
|
||||||
|
gemspec
|
|
@ -79,4 +79,18 @@ module Net::BER::Extensions::Array
|
||||||
oid = ary.pack("w*")
|
oid = ary.pack("w*")
|
||||||
[6, oid.length].pack("CC") + oid
|
[6, oid.length].pack("CC") + oid
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Converts an array into a set of ber control codes
|
||||||
|
# The expected format is [[control_oid, criticality, control_value(optional)]]
|
||||||
|
# [['1.2.840.113556.1.4.805',true]]
|
||||||
|
#
|
||||||
|
def to_ber_control
|
||||||
|
#if our array does not contain at least one array then wrap it in an array before going forward
|
||||||
|
ary = self[0].kind_of?(Array) ? self : [self]
|
||||||
|
ary = ary.collect do |control_sequence|
|
||||||
|
control_sequence.collect{|element| element.to_ber}.to_ber_sequence.reject_empty_ber_arrays
|
||||||
|
end
|
||||||
|
ary.to_ber_sequence.reject_empty_ber_arrays
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -46,15 +46,19 @@ module Net::BER::Extensions::String
|
||||||
def read_ber(syntax = nil)
|
def read_ber(syntax = nil)
|
||||||
StringIO.new(self).read_ber(syntax)
|
StringIO.new(self).read_ber(syntax)
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Destructively reads a BER object from the string.
|
# Destructively reads a BER object from the string.
|
||||||
def read_ber!(syntax = nil)
|
def read_ber!(syntax = nil)
|
||||||
io = StringIO.new(self)
|
io = StringIO.new(self)
|
||||||
|
|
||||||
result = io.read_ber(syntax)
|
result = io.read_ber(syntax)
|
||||||
self.slice!(0...io.pos)
|
self.slice!(0...io.pos)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reject_empty_ber_arrays
|
||||||
|
self.gsub(/0\000/n,'')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -334,8 +334,9 @@ class Net::LDAP
|
||||||
68 => "Entry Already Exists"
|
68 => "Entry Already Exists"
|
||||||
}
|
}
|
||||||
|
|
||||||
module LdapControls
|
module LDAPControls
|
||||||
PagedResults = "1.2.840.113556.1.4.319" # Microsoft evil from RFC 2696
|
PAGED_RESULTS = "1.2.840.113556.1.4.319" # Microsoft evil from RFC 2696
|
||||||
|
DELETE_TREE = "1.2.840.113556.1.4.805"
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.result2string(code) #:nodoc:
|
def self.result2string(code) #:nodoc:
|
||||||
|
@ -552,7 +553,7 @@ class Net::LDAP
|
||||||
# anything with the bind results. We then pass self to the caller's
|
# anything with the bind results. We then pass self to the caller's
|
||||||
# block, where he will execute his LDAP operations. Of course they will
|
# block, where he will execute his LDAP operations. Of course they will
|
||||||
# all generate auth failures if the bind was unsuccessful.
|
# all generate auth failures if the bind was unsuccessful.
|
||||||
raise Net::LDAP::LdapError, "Open already in progress" if @open_connection
|
raise LdapError, "Open already in progress" if @open_connection
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@open_connection = Net::LDAP::Connection.new(:host => @host,
|
@open_connection = Net::LDAP::Connection.new(:host => @host,
|
||||||
|
@ -1022,6 +1023,19 @@ class Net::LDAP
|
||||||
@result == 0
|
@result == 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Delete an entry from the LDAP directory along with all subordinate entries.
|
||||||
|
# the regular delete method will fail to delete an entry if it has subordinate
|
||||||
|
# entries. This method sends an extra control code to tell the LDAP server
|
||||||
|
# to do a tree delete. ('1.2.840.113556.1.4.805')
|
||||||
|
#
|
||||||
|
# Returns True or False to indicate whether the delete succeeded. Extended
|
||||||
|
# status information is available by calling #get_operation_result.
|
||||||
|
#
|
||||||
|
# dn = "mail=deleteme@example.com, ou=people, dc=example, dc=com"
|
||||||
|
# ldap.delete_tree :dn => dn
|
||||||
|
def delete_tree(args)
|
||||||
|
delete(args.merge(:control_codes => [[LDAPControls::DELETE_TREE, true]]))
|
||||||
|
end
|
||||||
# This method is experimental and subject to change. Return the rootDSE
|
# This method is experimental and subject to change. Return the rootDSE
|
||||||
# record from the LDAP server as a Net::LDAP::Entry, or an empty Entry if
|
# record from the LDAP server as a Net::LDAP::Entry, or an empty Entry if
|
||||||
# the server doesn't return the record.
|
# the server doesn't return the record.
|
||||||
|
@ -1092,7 +1106,7 @@ class Net::LDAP
|
||||||
#++
|
#++
|
||||||
def paged_searches_supported?
|
def paged_searches_supported?
|
||||||
@server_caps ||= search_root_dse
|
@server_caps ||= search_root_dse
|
||||||
@server_caps[:supportedcontrol].include?(Net::LDAP::LdapControls::PagedResults)
|
@server_caps[:supportedcontrol].include?(LDAPControls::PAGED_RESULTS)
|
||||||
end
|
end
|
||||||
end # class LDAP
|
end # class LDAP
|
||||||
|
|
||||||
|
@ -1389,7 +1403,7 @@ class Net::LDAP::Connection #:nodoc:
|
||||||
controls = []
|
controls = []
|
||||||
controls <<
|
controls <<
|
||||||
[
|
[
|
||||||
Net::LDAP::LdapControls::PagedResults.to_ber,
|
LDAPControls::PAGED_RESULTS.to_ber,
|
||||||
# Criticality MUST be false to interoperate with normal LDAPs.
|
# Criticality MUST be false to interoperate with normal LDAPs.
|
||||||
false.to_ber,
|
false.to_ber,
|
||||||
rfc2696_cookie.map{ |v| v.to_ber}.to_ber_sequence.to_s.to_ber
|
rfc2696_cookie.map{ |v| v.to_ber}.to_ber_sequence.to_s.to_ber
|
||||||
|
@ -1437,7 +1451,7 @@ class Net::LDAP::Connection #:nodoc:
|
||||||
more_pages = false
|
more_pages = false
|
||||||
if result_code == 0 and controls
|
if result_code == 0 and controls
|
||||||
controls.each do |c|
|
controls.each do |c|
|
||||||
if c.oid == Net::LDAP::LdapControls::PagedResults
|
if c.oid == LDAPControls::PAGED_RESULTS
|
||||||
# just in case some bogus server sends us more than 1 of these.
|
# just in case some bogus server sends us more than 1 of these.
|
||||||
more_pages = false
|
more_pages = false
|
||||||
if c.value and c.value.length > 0
|
if c.value and c.value.length > 0
|
||||||
|
@ -1545,9 +1559,9 @@ class Net::LDAP::Connection #:nodoc:
|
||||||
#++
|
#++
|
||||||
def delete(args)
|
def delete(args)
|
||||||
dn = args[:dn] or raise "Unable to delete empty DN"
|
dn = args[:dn] or raise "Unable to delete empty DN"
|
||||||
|
controls = args.include?(:control_codes) ? args[:control_codes].to_ber_control : nil #use nil so we can compact later
|
||||||
request = dn.to_s.to_ber_application_string(10)
|
request = dn.to_s.to_ber_application_string(10)
|
||||||
pkt = [next_msgid.to_ber, request].to_ber_sequence
|
pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence
|
||||||
@conn.write pkt
|
@conn.write pkt
|
||||||
|
|
||||||
(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"
|
(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"
|
||||||
|
|
24
spec/unit/ber/core_ext/array_spec.rb
Normal file
24
spec/unit/ber/core_ext/array_spec.rb
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
require 'metaid'
|
||||||
|
|
||||||
|
describe Array, "when extended with BER core extensions" do
|
||||||
|
|
||||||
|
it "should correctly convert a control code array" do
|
||||||
|
control_codes = []
|
||||||
|
control_codes << ['1.2.3'.to_ber, true.to_ber].to_ber_sequence
|
||||||
|
control_codes << ['1.7.9'.to_ber, false.to_ber].to_ber_sequence
|
||||||
|
control_codes = control_codes.to_ber_sequence
|
||||||
|
res = [['1.2.3', true],['1.7.9',false]].to_ber_control
|
||||||
|
res.should eq(control_codes)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should wrap the array in another array if a nested array is not passed" do
|
||||||
|
result1 = ['1.2.3', true].to_ber_control
|
||||||
|
result2 = [['1.2.3', true]].to_ber_control
|
||||||
|
result1.should eq(result2)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should return an empty string if an empty array is passed" do
|
||||||
|
[].to_ber_control.should be_empty
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue