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
|
||||
|
||||
=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>
|
||||
|
||||
Force password prompting. Useful to temporarily override cached
|
||||
|
|
@ -448,15 +461,17 @@ use Net::LDAP qw/
|
|||
LDAP_OTHER
|
||||
LDAP_TIMEOUT
|
||||
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::LDIF;
|
||||
use Net::LDAP::Extension::SetPassword;
|
||||
use Net::LDAP::Control::Paged;
|
||||
use Data::Dumper;
|
||||
use File::Temp;
|
||||
use Algorithm::Diff;
|
||||
use Carp 'confess';
|
||||
use base 'Term::Shell';
|
||||
require Net::LDAP::Extension::SetPassword;
|
||||
|
||||
my $conf = $main::conf;
|
||||
|
||||
|
|
@ -508,6 +523,16 @@ sub init
|
|||
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?)
|
||||
my $s = $self->search();
|
||||
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
|
||||
### an arrayref of Net::LDAP::Entry objects.
|
||||
|
|
@ -882,11 +908,18 @@ sub search
|
|||
{
|
||||
my $self = shift;
|
||||
my $opts = shift || {};
|
||||
my $controls = [];
|
||||
|
||||
$opts->{'base'} ||= $self->base(),
|
||||
$opts->{'filter'} ||= '(objectClass=*)';
|
||||
$opts->{'scope'} ||= 'base';
|
||||
|
||||
my $pager;
|
||||
if ( $conf->{'paginate'} ) {
|
||||
$pager = Net::LDAP::Control::Paged->new( size => $conf->{'paginate'} );
|
||||
push( @$controls, $pager );
|
||||
}
|
||||
|
||||
my $search = sub {
|
||||
return $self->ldap->search(
|
||||
base => $opts->{'base'},
|
||||
|
|
@ -894,19 +927,41 @@ sub search
|
|||
scope => $opts->{'scope'},
|
||||
timelimit => $conf->{'timeout'},
|
||||
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 = {
|
||||
code => $s->code(),
|
||||
message => $s->error(),
|
||||
entries => []
|
||||
message => $s->error()
|
||||
};
|
||||
|
||||
$rv->{'entries'} =
|
||||
$opts->{'scope'} eq 'base' ? [ $s->shift_entry() ] : [ $s->entries() ];
|
||||
if ( $opts->{'scope'} eq 'base' ) {
|
||||
$rv->{'entries'} = [ $s->shift_entry() ]
|
||||
}
|
||||
else {
|
||||
$rv->{'entries'} = $entries;
|
||||
}
|
||||
|
||||
return $rv;
|
||||
}
|
||||
|
|
@ -2322,6 +2377,7 @@ Getopt::Long::GetOptions(
|
|||
'binddn|D=s',
|
||||
'basedn|b=s',
|
||||
'cacheage=i',
|
||||
'paginate=i',
|
||||
'promptpass|W',
|
||||
'timeout=i',
|
||||
'sasl|Y=s',
|
||||
|
|
@ -2350,7 +2406,6 @@ if ( $conf->{'configfile'} ) {
|
|||
while ( my ($k, $v) = each %{$conf} ) { $conf->{ $k } = $v }
|
||||
}
|
||||
|
||||
|
||||
# defaults
|
||||
$conf->{'configfile'} ||= "$ENV{'HOME'}/.shelldap.rc";
|
||||
$conf->{'cacheage'} ||= 300;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue