Optionally use the server side pager control for search results.
FossilOrigin-Name: 80a69ef0eaf294692b133e14c1611e6c60373da11c2edeae1d2554dbdb7b1bf3
This commit is contained in:
parent
08ee88750d
commit
2a068606e6
1 changed files with 65 additions and 10 deletions
75
shelldap
75
shelldap
|
|
@ -138,6 +138,19 @@ try and ask the server for a sane default.
|
||||||
|
|
||||||
=over 4
|
=over 4
|
||||||
|
|
||||||
|
=item B<paginate>
|
||||||
|
|
||||||
|
Integer. If enabled, shelldap will attempt to use server side
|
||||||
|
pagination to build listings. Note: if you're using this to avoid
|
||||||
|
sizelimit errors, you'll likely need server configuration to raise the
|
||||||
|
limits for paginated results.
|
||||||
|
|
||||||
|
--paginate 100
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
=item B<promptpass>
|
=item B<promptpass>
|
||||||
|
|
||||||
Force password prompting. Useful to temporarily override cached
|
Force password prompting. Useful to temporarily override cached
|
||||||
|
|
@ -448,15 +461,17 @@ use Net::LDAP qw/
|
||||||
LDAP_OTHER
|
LDAP_OTHER
|
||||||
LDAP_TIMEOUT
|
LDAP_TIMEOUT
|
||||||
LDAP_NO_MEMORY
|
LDAP_NO_MEMORY
|
||||||
LDAP_CONNECT_ERROR /;
|
LDAP_CONNECT_ERROR
|
||||||
|
LDAP_CONTROL_PAGED /;
|
||||||
use Net::LDAP::Util qw/ canonical_dn ldap_explode_dn /;
|
use Net::LDAP::Util qw/ canonical_dn ldap_explode_dn /;
|
||||||
use Net::LDAP::LDIF;
|
use Net::LDAP::LDIF;
|
||||||
|
use Net::LDAP::Extension::SetPassword;
|
||||||
|
use Net::LDAP::Control::Paged;
|
||||||
use Data::Dumper;
|
use Data::Dumper;
|
||||||
use File::Temp;
|
use File::Temp;
|
||||||
use Algorithm::Diff;
|
use Algorithm::Diff;
|
||||||
use Carp 'confess';
|
use Carp 'confess';
|
||||||
use base 'Term::Shell';
|
use base 'Term::Shell';
|
||||||
require Net::LDAP::Extension::SetPassword;
|
|
||||||
|
|
||||||
my $conf = $main::conf;
|
my $conf = $main::conf;
|
||||||
|
|
||||||
|
|
@ -508,6 +523,16 @@ sub init
|
||||||
print "Cipher in use: ", $self->ldap()->cipher(), "\n";
|
print "Cipher in use: ", $self->ldap()->cipher(), "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# check for the pagination extension on the server early, and bail
|
||||||
|
# if necessary.
|
||||||
|
if ( $conf->{'paginate'} && $conf->{'paginate'} =~ /^\d+$/ && $conf->{'paginate'} > 0 ) {
|
||||||
|
my $has_pagination = ( grep $_ eq LDAP_CONTROL_PAGED, $self->{'root_dse'}->get_value('supportedControl') );
|
||||||
|
die "Server pagination is enabled, but the server doesn't seem to support it.\n" unless $has_pagination;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$conf->{'paginate'} = undef;
|
||||||
|
}
|
||||||
|
|
||||||
# try an initial search and bail early if it doesn't work. (bad baseDN?)
|
# try an initial search and bail early if it doesn't work. (bad baseDN?)
|
||||||
my $s = $self->search();
|
my $s = $self->search();
|
||||||
die "LDAP baseDN error: ", $s->{'message'}, "\n" if $s->{'code'};
|
die "LDAP baseDN error: ", $s->{'message'}, "\n" if $s->{'code'};
|
||||||
|
|
@ -873,7 +898,8 @@ sub display
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
### Perform an LDAP search.
|
### Perform an LDAP search, optionally with the server side pager
|
||||||
|
### control.
|
||||||
###
|
###
|
||||||
### Returns a hashref containing the return code and
|
### Returns a hashref containing the return code and
|
||||||
### an arrayref of Net::LDAP::Entry objects.
|
### an arrayref of Net::LDAP::Entry objects.
|
||||||
|
|
@ -882,11 +908,18 @@ sub search
|
||||||
{
|
{
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $opts = shift || {};
|
my $opts = shift || {};
|
||||||
|
my $controls = [];
|
||||||
|
|
||||||
$opts->{'base'} ||= $self->base(),
|
$opts->{'base'} ||= $self->base(),
|
||||||
$opts->{'filter'} ||= '(objectClass=*)';
|
$opts->{'filter'} ||= '(objectClass=*)';
|
||||||
$opts->{'scope'} ||= 'base';
|
$opts->{'scope'} ||= 'base';
|
||||||
|
|
||||||
|
my $pager;
|
||||||
|
if ( $conf->{'paginate'} ) {
|
||||||
|
$pager = Net::LDAP::Control::Paged->new( size => $conf->{'paginate'} );
|
||||||
|
push( @$controls, $pager );
|
||||||
|
}
|
||||||
|
|
||||||
my $search = sub {
|
my $search = sub {
|
||||||
return $self->ldap->search(
|
return $self->ldap->search(
|
||||||
base => $opts->{'base'},
|
base => $opts->{'base'},
|
||||||
|
|
@ -894,19 +927,41 @@ sub search
|
||||||
scope => $opts->{'scope'},
|
scope => $opts->{'scope'},
|
||||||
timelimit => $conf->{'timeout'},
|
timelimit => $conf->{'timeout'},
|
||||||
typesonly => ! $opts->{'vals'},
|
typesonly => ! $opts->{'vals'},
|
||||||
attrs => $opts->{'attrs'} || ['*']
|
attrs => $opts->{'attrs'} || ['*'],
|
||||||
|
control => $controls
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
my $s = $self->with_retry( $search );
|
my $s;
|
||||||
|
my $entries = [];
|
||||||
|
my $token = '-';
|
||||||
|
|
||||||
|
if ( $conf->{'paginate'} ) {
|
||||||
|
while( $token ) {
|
||||||
|
$s = $self->with_retry( $search );
|
||||||
|
push( @$entries, $s->entries() );
|
||||||
|
|
||||||
|
my $page_response = $s->control( LDAP_CONTROL_PAGED ) or last;
|
||||||
|
$token = $page_response->cookie;
|
||||||
|
$pager->cookie( $token );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$s = $self->with_retry( $search );
|
||||||
|
$entries = [ $s->entries() ];
|
||||||
|
}
|
||||||
|
|
||||||
my $rv = {
|
my $rv = {
|
||||||
code => $s->code(),
|
code => $s->code(),
|
||||||
message => $s->error(),
|
message => $s->error()
|
||||||
entries => []
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$rv->{'entries'} =
|
if ( $opts->{'scope'} eq 'base' ) {
|
||||||
$opts->{'scope'} eq 'base' ? [ $s->shift_entry() ] : [ $s->entries() ];
|
$rv->{'entries'} = [ $s->shift_entry() ]
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$rv->{'entries'} = $entries;
|
||||||
|
}
|
||||||
|
|
||||||
return $rv;
|
return $rv;
|
||||||
}
|
}
|
||||||
|
|
@ -2322,6 +2377,7 @@ Getopt::Long::GetOptions(
|
||||||
'binddn|D=s',
|
'binddn|D=s',
|
||||||
'basedn|b=s',
|
'basedn|b=s',
|
||||||
'cacheage=i',
|
'cacheage=i',
|
||||||
|
'paginate=i',
|
||||||
'promptpass|W',
|
'promptpass|W',
|
||||||
'timeout=i',
|
'timeout=i',
|
||||||
'sasl|Y=s',
|
'sasl|Y=s',
|
||||||
|
|
@ -2350,7 +2406,6 @@ if ( $conf->{'configfile'} ) {
|
||||||
while ( my ($k, $v) = each %{$conf} ) { $conf->{ $k } = $v }
|
while ( my ($k, $v) = each %{$conf} ) { $conf->{ $k } = $v }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# defaults
|
# defaults
|
||||||
$conf->{'configfile'} ||= "$ENV{'HOME'}/.shelldap.rc";
|
$conf->{'configfile'} ||= "$ENV{'HOME'}/.shelldap.rc";
|
||||||
$conf->{'cacheage'} ||= 300;
|
$conf->{'cacheage'} ||= 300;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue