Subject: [PATCH] IntermediateMessage and LDAP Content synchronisation fixes: - Fix ASN parsing of syncRequestValue, syncDoneValue and syncInfoValue (attributes with default value are threated as optional values) - Renamed syncInfoValue ASN name to match RFC - Fixed parsing of SyncDone and SyncRequest: avoid emptying the value - Corrected Net::LDAP::Intermediate::SyncInfo parsing - Enable Net::LDAP::Intermediate::SyncInfo - Moved catching of IntermediateMessage from LDAP::Search to LDAP::Message (this is not specific to searches)
--- lib/Net/LDAP/ASN.pm | 16 ++++++++-------- lib/Net/LDAP/Control/SyncDone.pm | 15 ++++++--------- lib/Net/LDAP/Control/SyncRequest.pm | 11 +++-------- lib/Net/LDAP/Control/SyncState.pm | 3 --- lib/Net/LDAP/Intermediate.pm | 2 +- lib/Net/LDAP/Intermediate/SyncInfo.pm | 30 +++++++++++++++--------------- lib/Net/LDAP/Message.pm | 20 ++++++++++++++++---- lib/Net/LDAP/Search.pm | 15 +++------------ 8 files changed, 52 insertions(+), 60 deletions(-) diff --git a/lib/Net/LDAP/ASN.pm b/lib/Net/LDAP/ASN.pm index 82b7c17..9ba0913 100644 --- a/lib/Net/LDAP/ASN.pm +++ b/lib/Net/LDAP/ASN.pm @@ -1,7 +1,7 @@ package Net::LDAP::ASN; -$VERSION = "0.07"; +$VERSION = "0.08"; use Convert::ASN1; @@ -455,7 +455,7 @@ $asn->prepare(<<LDAP_ASN) or die $asn->error; refreshAndPersist (3) } cookie syncCookie OPTIONAL, - reloadHint BOOLEAN -- DEFAULT FALSE + reloadHint BOOLEAN OPTIONAL -- DEFAULT FALSE } syncStateValue ::= SEQUENCE { @@ -471,22 +471,22 @@ $asn->prepare(<<LDAP_ASN) or die $asn->error; syncDoneValue ::= SEQUENCE { cookie syncCookie OPTIONAL, - refreshDeletes BOOLEAN -- DEFAULT FALSE + refreshDeletes BOOLEAN OPTIONAL -- DEFAULT FALSE } syncInfoValue ::= CHOICE { newcookie [0] syncCookie, refreshDelete [1] SEQUENCE { - refreshDeleteCookie syncCookie OPTIONAL, - refreshDeleteDone BOOLEAN -- DEFAULT TRUE + cookie syncCookie OPTIONAL, + refreshDone BOOLEAN OPTIONAL -- DEFAULT TRUE } refreshPresent [2] SEQUENCE { - refreshDeletecookie syncCookie OPTIONAL, - refreshDeleteDone BOOLEAN -- DEFAULT TRUE + cookie syncCookie OPTIONAL, + refreshDone BOOLEAN OPTIONAL -- DEFAULT TRUE } syncIdSet [3] SEQUENCE { cookie syncCookie OPTIONAL, - refreshDeletes BOOLEAN, -- DEFAULT FALSE + refreshDeletes BOOLEAN OPTIONAL, -- DEFAULT FALSE syncUUIDs SET OF syncUUID } } diff --git a/lib/Net/LDAP/Control/SyncDone.pm b/lib/Net/LDAP/Control/SyncDone.pm index 7fcb0d9..e8bc2ae 100644 --- a/lib/Net/LDAP/Control/SyncDone.pm +++ b/lib/Net/LDAP/Control/SyncDone.pm @@ -8,22 +8,19 @@ use vars qw(@ISA $VERSION); use Net::LDAP::Control; @ISA = qw(Net::LDAP::Control); -$VERSION = "0.01"; +$VERSION = "0.02"; use Net::LDAP::ASN qw(syncDoneValue); use strict; -# use some kind of hack here: -# - calling the control without args means: response, -# - giving an argument: means: request sub init { my($self) = @_; - delete $self->{asn}; - - unless (exists $self->{value}) { + if (exists $self->{value}) { + $self->{asn} = $syncDoneValue->decode(delete $self->{value}); + } else { $self->{asn} = { - cookie => $self->{cookie} || '', + cookie => defined($self->{cookie}) ? $self->{cookie} : '', refreshDeletes => $self->{refreshDeletes} || '0', }; } @@ -36,7 +33,7 @@ sub cookie { $self->{asn} ||= $syncDoneValue->decode($self->{value}); if (@_) { delete $self->{value}; - return $self->{asn}{cookie} = shift || 0; + return $self->{asn}{cookie} = defined($_[0]) ? $_[0] : ''; } $self->{asn}{cookie}; } diff --git a/lib/Net/LDAP/Control/SyncRequest.pm b/lib/Net/LDAP/Control/SyncRequest.pm index b33868d..95cd716 100644 --- a/lib/Net/LDAP/Control/SyncRequest.pm +++ b/lib/Net/LDAP/Control/SyncRequest.pm @@ -8,14 +8,11 @@ use vars qw(@ISA $VERSION); use Net::LDAP::Control; @ISA = qw(Net::LDAP::Control); -$VERSION = "0.01"; +$VERSION = "0.02"; use Net::LDAP::ASN qw(syncRequestValue); use strict; -# use some kind of hack here: -# - calling the control without args means: response, -# - giving an argument: means: request sub init { my($self) = @_; @@ -64,10 +61,8 @@ sub reloadHint { sub value { my $self = shift; - - exists $self->{value} - ? $self->{value} - : $self->{value} = $syncRequestValue->encode($self->{asn}); + return $self->{value} if exists $self->{value}; + $self->{value} = $syncRequestValue->encode($self->{asn}); } 1; diff --git a/lib/Net/LDAP/Control/SyncState.pm b/lib/Net/LDAP/Control/SyncState.pm index b069e42..e47c78a 100644 --- a/lib/Net/LDAP/Control/SyncState.pm +++ b/lib/Net/LDAP/Control/SyncState.pm @@ -13,9 +13,6 @@ $VERSION = "0.01"; use Net::LDAP::ASN qw(syncStateValue); use strict; -# use some kind of hack here: -# - calling the control without args means: response, -# - giving an argument: means: request sub init { my($self) = @_; diff --git a/lib/Net/LDAP/Intermediate.pm b/lib/Net/LDAP/Intermediate.pm index b95b849..288d785 100644 --- a/lib/Net/LDAP/Intermediate.pm +++ b/lib/Net/LDAP/Intermediate.pm @@ -15,7 +15,7 @@ $VERSION = "0.01"; my %Class2ResponseName = ( - #'Net::LDAP::Intermediate::SyncInfo' => LDAP_SYNC_INFO, #disabled as decoding doesn't work + 'Net::LDAP::Intermediate::SyncInfo' => LDAP_SYNC_INFO, ); my %ResponseName2Class = reverse %Class2ResponseName; diff --git a/lib/Net/LDAP/Intermediate/SyncInfo.pm b/lib/Net/LDAP/Intermediate/SyncInfo.pm index ed8205a..8d1814c 100644 --- a/lib/Net/LDAP/Intermediate/SyncInfo.pm +++ b/lib/Net/LDAP/Intermediate/SyncInfo.pm @@ -8,23 +8,26 @@ use vars qw(@ISA $VERSION); use Net::LDAP::Intermediate; @ISA = qw(Net::LDAP::Intermediate); -$VERSION = "0.01"; +$VERSION = "0.02"; use Net::LDAP::ASN qw(syncInfoValue); use strict; -# use some kind of hack here: -# - calling the control without args means: response, -# - giving an argument: means: request sub init { my($self) = @_; - delete $self->{asn}; - - unless (exists $self->{responseValue}) { - $self->{asn} = { - newcookie => $self->{newcookie} || '', - }; + if (exists $self->{responseValue}) { + $self->{asn} = $syncInfoValue->decode(delete $self->{responseValue}); + } else { + $self->{asn} = {}; + $self->{asn}{newcookie} = + delete $self->{newcookie} if exists $self->{newcookie}; + $self->{asn}{refreshDelete} = + delete $self->{refreshDelete} if exists $self->{refreshDelete}; + $self->{asn}{refreshPresent} = + delete $self->{refreshPresent} if exists $self->{refreshPresent}; + $self->{asn}{syncIdSet} = + delete $self->{syncIdSet} if exists $self->{syncIdSet}; } $self; @@ -32,11 +35,8 @@ sub init { sub newcookie { my $self = shift; - $self->{asn} ||= $syncInfoValue->decode($self->{responseValue}); - if (@_) { - delete $self->{responseValue}; - return $self->{asn}{newcookie} = shift || 0; - } + @_ ? ($self->{asn}{newcookie}=shift) + : $self->{asn}{newcookie}; $self->{asn}{cookie}; } diff --git a/lib/Net/LDAP/Message.pm b/lib/Net/LDAP/Message.pm index 5007afb..26e5eeb 100644 --- a/lib/Net/LDAP/Message.pm +++ b/lib/Net/LDAP/Message.pm @@ -9,7 +9,7 @@ use Net::LDAP::ASN qw(LDAPRequest); use strict; use vars qw($VERSION); -$VERSION = "1.10"; +$VERSION = "1.11"; my $MsgID = 0; @@ -142,9 +142,21 @@ sub decode { # $self, $pdu, $control # free up memory as we have a result so we will not need to re-send it delete $self->{pdu}; - # tell our LDAP client to forget us as this message has now completed - # all communications with the server - $self->parent->_forgetmesg($self); + if ($data = delete $result->{protocolOp}{intermediateResponse}) { + + my $intermediate = Net::LDAP::Intermediate->from_asn($data); + + push(@{$self->{'intermediate'} ||= []}, $intermediate); + + $self->{callback}->($self, $intermediate) + if (defined $self->{callback}); + + return $self; + } else { + # tell our LDAP client to forget us as this message has now completed + # all communications with the server + $self->parent->_forgetmesg($self); + } $self->{callback}->($self) if (defined $self->{callback}); diff --git a/lib/Net/LDAP/Search.pm b/lib/Net/LDAP/Search.pm index d8c3568..3dd6575 100644 --- a/lib/Net/LDAP/Search.pm +++ b/lib/Net/LDAP/Search.pm @@ -13,7 +13,7 @@ use Net::LDAP::Filter; use Net::LDAP::Constant qw(LDAP_SUCCESS LDAP_DECODING_ERROR); @ISA = qw(Net::LDAP::Message); -$VERSION = "0.12"; +$VERSION = "0.13"; sub first_entry { # compat @@ -36,6 +36,8 @@ sub decode { return $self->SUPER::decode($result) if exists $result->{protocolOp}{searchResDone}; + return $self->SUPER::decode($result) + if exists $result->{protocolOp}{intermediateResponse}; my $data; @{$self}{qw(controls ctrl_hash)} = ($result->{controls}, undef); @@ -64,17 +66,6 @@ sub decode { return $self; } - elsif ($data = delete $result->{protocolOp}{intermediateResponse}) { - - my $intermediate = Net::LDAP::Intermediate->from_asn($data); - - push(@{$self->{'intermediate'} ||= []}, [$intermediate]); - - $self->{callback}->($self, $intermediate) - if (defined $self->{callback}); - - return $self; - } $self->set_error(LDAP_DECODING_ERROR, "LDAP decode error"); return; -- 1.5.6.5