Permalink
Browse files

Merge pull request #1 from tsibley/search-scope

Search scope bug fixes
  • Loading branch information...
2 parents b080573 + d559ae4 commit 4da84212e1fcae5799dbf201344496acf44a528f @karpet committed Jul 28, 2012
Showing with 78 additions and 8 deletions.
  1. +13 −8 lib/Net/LDAP/Server/Test.pm
  2. +65 −0 t/05-scope.t
@@ -55,6 +55,7 @@ Only one user-level method is implemented: new().
LDAP_OPERATIONS_ERROR
LDAP_UNWILLING_TO_PERFORM
);
+ use Net::LDAP::Util qw(ldap_explode_dn);
use Net::LDAP::Entry;
use Net::LDAP::Filter;
use Net::LDAP::FilterMatch;
@@ -74,6 +75,7 @@ Only one user-level method is implemented: new().
our %Data; # package data lasts as long as $$ does.
our $Cookies = 0;
our %Searches;
+ my @Scopes = qw(base one sub);
# constructor
sub new {
@@ -128,17 +130,16 @@ Only one user-level method is implemented: new().
my @results;
my $base = $reqData->{baseObject};
- my $scope = $reqData->{scope} || 'sub';
+ # $reqData->{scope} is a enum but we want a word
+ my $scope = $Scopes[defined $reqData->{scope} ? $reqData->{scope} : 2];
my @attrs = @{$reqData->{attributes} || []};
my @filters = ();
- if ( $scope ne 'base' ) {
- if ( exists $reqData->{filter} ) {
+ if ( exists $reqData->{filter} ) {
- push( @filters,
- bless( $reqData->{filter}, 'Net::LDAP::Filter' ) );
+ push( @filters,
+ bless( $reqData->{filter}, 'Net::LDAP::Filter' ) );
- }
}
#warn "stored Data: " . Data::Dump::dump \%Data;
@@ -197,7 +198,11 @@ Only one user-level method is implemented: new().
next unless $dn eq $base;
}
elsif ( $scope eq 'one' ) {
- next unless $dn =~ m/^(\w+=\w+,)?$base$/;
+ my $dn_depth = scalar @{ ldap_explode_dn($dn) };
+ my $base_depth = scalar @{ ldap_explode_dn($base) };
+
+ # We're guaranteed to be at or under $base thanks to the m// above
+ next unless $dn_depth == $base_depth + 1;
}
my $entry = $Data{$dn};
@@ -215,7 +220,7 @@ Only one user-level method is implemented: new().
}
#warn "matched $match";
- if ( $match == scalar(@filters) ) { # or $dn eq $base ) {
+ if ( $match == scalar(@filters) ) {
# clone the entry so that client cannot modify %Data
my $result = $entry->clone;
View
@@ -0,0 +1,65 @@
+use strict;
+use warnings;
+
+use Test::More;
+
+use Net::LDAP;
+use Net::LDAP::Server::Test;
+
+my $port = 1024 + int rand(10000) + $$ % 1024;
+
+ok( my $server = Net::LDAP::Server::Test->new( $port, auto_schema => 1 ), "spawn new server" );
+ok( my $ldap = Net::LDAP->new("localhost:$port"), "new LDAP connection" );
+ok( my $rc = $ldap->bind(), "LDAP bind()" );
+
+my @scopes = qw(base one sub);
+
+# Add our nested DNs
+my $dn = my $base = "dc=example,dc=com";
+for my $level (@scopes) {
+ $dn = "cn=$level group,$dn";
+ my $result = $ldap->add(
+ $dn,
+ attr => [
+ cn => "$level group",
+ objectClass => 'Group',
+ ],
+ );
+ ok !$result->code, "added $dn: " . $result->error;
+}
+
+# Do scopes work?
+my %expected = (
+ 'base' => [qw(base)],
+ 'one' => [qw(one)],
+ 'sub' => [qw(base one sub)],
+);
+
+for my $scope (@scopes) {
+ my $cns = $expected{$scope};
+ my $count = scalar @$cns;
+ my $msg = $ldap->search(
+ base => "cn=base group,$base",
+ scope => $scope,
+ filter => '(objectClass=group)',
+ );
+ ok $msg, "searched with scope $scope";
+ is $msg->count, $count, "found $count";
+
+ my %want = map { ("$_ group" => 1) } @$cns;
+ my %found = map { ($_->get_value('cn') => 1) } $msg->entries;
+ is((scalar grep { !$found{$_} } keys %want), 0, "found all expected CNs");
+ is((scalar grep { !$want{$_} } keys %found), 0, "expected all found CNs");
+
+ # test that filters apply correctly on all scopes
+ $msg = $ldap->search(
+ base => "cn=base group,$base",
+ scope => $scope,
+ filter => '(objectClass=404)',
+ );
+ ok $msg, "searched with scope $scope with a non-matching filter";
+ is $msg->count, 0, "found no entries";
+}
+
+ok $ldap->unbind, "unbound";
+done_testing;

0 comments on commit 4da8421

Please sign in to comment.