Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inclusion from LDAP data sources supports RFC 2696 Paged Results control (#57) #1733

Merged
merged 10 commits into from
Nov 29, 2023
22 changes: 20 additions & 2 deletions src/lib/Sympa/Config/Schema.pm
Original file line number Diff line number Diff line change
Expand Up @@ -3466,7 +3466,16 @@ our %pinfo = (
format_s => '$time_ranges',
occurrence => '0-1',
not_before => '6.2a.16',
}
},
pagesize => {
context => [qw(list)],
order => 12,
gettext_comment =>
'Number of records to fetch per batch (paging), for a LDAP server that supports paging. If not set or set to zero, do not use paging. Typically 1000 for an Active Directory server, to avoid "SizeLimit" errors',
gettext_id => "Page size",
format => '\d*',
length => 6,
},
},
occurrence => '0-n'
},
Expand Down Expand Up @@ -3691,7 +3700,16 @@ our %pinfo = (
format_s => '$time_ranges',
occurrence => '0-1',
not_before => '6.2a.16',
}
},
pagesize => {
context => [qw(list)],
order => 12,
gettext_comment =>
'Number of records to fetch per batch (paging), for a LDAP server that supports paging. If not set or set to zero, do not use paging. Typically 1000 for an Active Directory server, to avoid "SizeLimit" errors',
gettext_id => "Page size",
format => '\d*',
length => 6,
},
},
occurrence => '0-n'
},
Expand Down
43 changes: 39 additions & 4 deletions src/lib/Sympa/DataSource/LDAP.pm
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ package Sympa::DataSource::LDAP;
use strict;
use warnings;

use Net::LDAP::Control::Paged;

use Sympa::Database;
use Sympa::Log;

Expand All @@ -43,6 +45,13 @@ sub _open {
return undef unless $db and $db->connect;
$self->{_db} = $db;

my $pagesize = $options{pagesize} || $self->{pagesize};
if ($pagesize and $db->__dbh->root_dse->supported_control(
Net::LDAP::Constant::LDAP_CONTROL_PAGED()
)) {
$self->{_page} = Net::LDAP::Control::Paged->new( size => $pagesize );
}

my $mesg = $self->_open_operation(%options);
return undef unless $mesg;

Expand All @@ -61,19 +70,29 @@ sub _open_operation {
my $ldap_attrs = $options{attrs} || $self->{attrs};
my $ldap_scope = $options{scope} || $self->{scope};

my $mesg = $self->{_db}->do_operation(
'search',
my @args = (
base => $ldap_suffix,
filter => $ldap_filter,
attrs => [split /\s*,\s*/, $ldap_attrs],
scope => $ldap_scope
scope => $ldap_scope,
control=> $self->{_page} ? [$self->{_page}] : []
);

my $mesg = $self->{_db}->do_operation('search', @args);

unless ($mesg) {
$log->syslog(
'err',
'LDAP search (single level) failed: %s with data source %s',
$self->{_db}->error, $self
);

if ($self->{_page}) {
# We had an abnormal exit, so let the server know we do not want any more
ikedas marked this conversation as resolved.
Show resolved Hide resolved
$self->{_page}->size(0);
$self->{_db}->do_operation('search', @args);
}

return undef;
}

Expand Down Expand Up @@ -108,7 +127,16 @@ sub _load_next {
}

my @retrieved;
my $mesg = $self->__dsh;
my $mesg;
my $cookie = $self->{_page} ? $self->{_page}->cookie : undef;
if (defined($cookie) and length($cookie)) {
# second page, or later one (but not post-last) of a paged search:
# load next page
$mesg = $self->_open_operation(%options);
ikedas marked this conversation as resolved.
Show resolved Hide resolved
}
else {
$mesg = $self->__dsh;
}
while (my $entry = $mesg->shift_entry) {
my $key_values = $entry->get_value($key_attr, asref => 1);
next unless $key_values and @$key_values;
Expand Down Expand Up @@ -151,6 +179,13 @@ sub _load_next {
}
}

if ($self->{_page} and $mesg) {
my $cookie = $mesg->control(
Net::LDAP::Constant::LDAP_CONTROL_PAGED
)->cookie;
$self->{_page}->cookie( $cookie );
}

return [@retrieved];
}

Expand Down
15 changes: 11 additions & 4 deletions src/lib/Sympa/DataSource/LDAP2.pm
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,23 @@ sub _open {
my @values;
while (
my $entry = $self->SUPER::_next(
attrs => $self->{attrs1},
select => $self->{select1},
regex => $self->{regex1},
turn => 'first'
filter => $self->{filter1},
attrs => $self->{attrs1},
select => $self->{select1},
regex => $self->{regex1},
timeout => $self->{timeout1},
suffix => $self->{suffix1},
scope => $self->{scope1},
turn => 'first'
)
) {
push @values, $entry->[0] if defined $entry->[0];
}
$self->{_attr1values} = [@values];

# Don't paginate subsequent children searches, they return only one record
$self->{_page} = undef;

return 1;
}

Expand Down