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

Reply via email to