> > Maybe it would be reasonable to add register() functionality to
> > Net::LDAP::Search
> > (like in Net::LDAP::Control), so that one could assign
> > a custom response-message processor (decoder) for a particular
protocolOp
> > for example?
> > (IntermediateResponse with responseName = '1.3.6.1.4.1.4203.1.9.1.4' in
my
> > case)
> >
> > If you wish I can send a quick-and-dirty patch just to illustrate this
> > suggestion.
>
> Please post your patch to the list so that there is something to discuss
> about.

First ASN definition of IntermediateResponse

----------------------------------------------------------------------------
--------------------------------

diff -ru perl-ldap-0.33.orig/lib/Net/LDAP/ASN.pm
perl-ldap-0.33/lib/Net/LDAP/ASN.pm
--- perl-ldap-0.33.orig/lib/Net/LDAP/ASN.pm 2005-04-26 02:54:40.000000000
+0400
+++ perl-ldap-0.33/lib/Net/LDAP/ASN.pm 2005-10-28 14:43:36.000000000 +0400
@@ -57,7 +57,8 @@
      delResponse     DelResponse,
      modDNResponse   ModifyDNResponse,
      compareResponse CompareResponse,
-     extendedResp    ExtendedResponse }
+     extendedResp    ExtendedResponse,
+     intermediateResponse  IntermediateResponse }
   controls       [0] Controls OPTIONAL }

     MessageID ::= INTEGER -- (0 .. maxInt)
@@ -176,6 +177,11 @@
     BindResponse ::= [APPLICATION 1] SEQUENCE {
   COMPONENTS OF LDAPResult,
   serverSaslCreds    [7] OCTET STRING OPTIONAL }
+
+IntermediateResponse ::= [APPLICATION 25] SEQUENCE {
+        responseName     [0] LDAPOID OPTIONAL,
+ responseValue    [1] OCTET STRING OPTIONAL }
+

     UnbindRequest ::= [APPLICATION 2] NULL

----------------------------------------------------------------------------
--------------------------------



Then add functionality to assign the custom decoder for a specific
protocolOp of a response message.

----------------------------------------------------------------------------
--------------------------------

diff -ru perl-ldap-0.33.orig/lib/Net/LDAP/Search.pm
perl-ldap-0.33/lib/Net/LDAP/Search.pm
--- perl-ldap-0.33.orig/lib/Net/LDAP/Search.pm 2005-04-26 02:54:38.000000000
+0400
+++ perl-ldap-0.33/lib/Net/LDAP/Search.pm 2005-11-14 13:54:12.000000000
+0300
@@ -28,17 +28,54 @@
   : 0);
 }

+sub protocolOp_detail {
+  my $self = shift;
+
+  return undef unless exists $self->{_protocolOp_processor};
+
+  my $protocolOp_processor = $self->{_protocolOp_processor};
+
+  my $protocolOp_detail =
$protocolOp_processor->new($self->{_protocolOp_asn});
+  return $protocolOp_detail;
+}
+
+my %Op2Pkg;
+
+sub register {
+  my $protocolOp_pkg = shift;
+  my $protocolOp = shift;
+
+  push @{$Op2Pkg{$protocolOp}}, $protocolOp_pkg;
+}

 sub decode {
   my $self = shift;
   my $result = shift;

+  delete $self->{_protocolOp_asn};
+  delete $self->{_protocolOp_processor};
+
   return $self->SUPER::decode($result)
     if exists $result->{protocolOp}{searchResDone};

   my $data;
   @{$self}{qw(controls ctrl_hash)} = ($result->{controls}, undef);

+  if(exists $Op2Pkg{(keys %{$result->{protocolOp}})[0]}) {
+    my $protocolOp_pkgs = $Op2Pkg{(keys %{$result->{protocolOp}})[0]};
+    foreach my $protocolOp_processor (@$protocolOp_pkgs) {
+
+      if( defined($self->{_protocolOp_asn} = eval
"\$self->${protocolOp_processor}::decode(\$result)")) {
+        $self->{_protocolOp_processor} = $protocolOp_processor;
+
+        $self->{callback}->($self, undef)
+          if (defined $self->{callback});
+
+        return $self;
+      }
+    }
+  }
+
   if ($data = delete $result->{protocolOp}{searchResEntry}) {

     my $entry = Net::LDAP::Entry->new;
----------------------------------------------------------------------------
--------------------------------

Net::LDAP::Search::protocolOp_detail  --  returns a wrapper object for
accessing custom-decoded message attributes.
Net::LDAP::Search::register  -- assigns a package for decoding a response
message with a specific protocolOp value.
Net::LDAP::Search::decode calls assigned custom decoder for a response
message according to protocolOp value


Wrapper object could be used like this
(example for Sync Info IRM):

    my $custom_mesg = $mesg->protocolOp_detail();
    my $sync_info = $custom_mesg if defined $custom_mesg
                                    and $custom_mesg->protocolOp() eq
'IntermediateResponse'
                                    and $custom_mesg->type() eq
LDAP_MESSAGE_IRM_SYNCINFO;

   $sync_info->newcookie() if defined $sync_info;
   $sync_info->syncUUIDs() if defined $sync_info;
   $sync_info->cookie() if defined $sync_info;
   $sync_info->refreshDone() if defined $sync_info;



Decoder (and wrapper) for Sync Info IRM
----------------------------------------------------------------------------
--------------------------------

package Net::LDAP::Message::IRMSyncInfo;

use Net::LDAP::Search;

Net::LDAP::Search::register(__PACKAGE__, 'intermediateResponse');

use strict;
use vars qw(@ISA $VERSION);

use constant LDAP_MESSAGE_IRM_SYNCINFO => '1.3.6.1.4.1.4203.1.9.1.4';

require Exporter;
@ISA = qw(Exporter);

our @EXPORT = qw(LDAP_MESSAGE_IRM_SYNCINFO);

$VERSION = "0.01";

my $SyncInfoValue = new Convert::ASN1;

$SyncInfoValue->prepare(<<SYNC_INFO_VALUE) or die "Can't prepare
SyncInfoValue: " . $SyncInfoValue->error;

syncInfoValue ::= CHOICE {
          newcookie      [0] syncCookie,
          refreshDelete  [1] case1,
          refreshPresent [2] case2,
          syncIdSet      [3] case3
      }

case1 ::=  SEQUENCE {
              cookie         syncCookie OPTIONAL,
              refreshDone    BOOLEAN OPTIONAL
          }

case2 ::=  SEQUENCE {
              cookie         syncCookie OPTIONAL,
              refreshDone    BOOLEAN OPTIONAL
          }

case3 ::=  SEQUENCE {
              cookie         syncCookie OPTIONAL,
              refreshDeletes BOOLEAN OPTIONAL,
              syncUUIDs      SET OF syncUUID
          }
syncUUID ::= OCTET STRING

syncCookie ::= OCTET STRING

SYNC_INFO_VALUE

sub new {
    my $class = shift;
    my $asn = shift;

    $class = ref($class) || $class;

    my $self = {asn => $asn};

    return bless $self, $class;
}

sub decode {
  my $self = shift;
  my $result = shift;

  if(exists $result->{protocolOp}{intermediateResponse}
     and $result->{protocolOp}{intermediateResponse}{responseName} eq
LDAP_MESSAGE_IRM_SYNCINFO) {
 my $buf = $result->{protocolOp}{intermediateResponse}{responseValue};
 return $SyncInfoValue->find('syncInfoValue')->decode($buf);
  }
  return undef;
}

sub protocolOp {'IntermediateResponse'}

sub type {LDAP_MESSAGE_IRM_SYNCINFO}

sub sub_type {
    my $self = shift;

    return (keys %{$self->{asn}})[0];
}

# Make access methods for the message  attributes.
for my $attr (qw(newcookie cookie refreshDone refreshDeletes syncUUIDs)) {
  no strict 'refs';

  *$attr = sub {  my $self = shift;
      return($self->{asn}{newcookie} or '')
             if $attr eq 'newcookie';
      my $attr_val = ${(values %{$self->{asn}})[0]}{$attr};
      return $attr_val if defined $attr_val;
      return ''  if $attr eq 'cookie';
      return undef if $attr eq 'syncUUIDs';
      return $attr eq 'refreshDone' ? 1 : 0;
                };
}

1;
----------------------------------------------------------------------------
--------------------------------


This package implements Sync Info IRM decoder and generates attribute-access
funcions.

All necessary detailed explanations can be sent if needed.


Best regards,
Alexey Kravchuk


Reply via email to