Hi,

On Thursday 03 June 2004 21:29, Brian Reichert wrote:
> I've tried to search the archives on Geocrawler, but they seem to
> be havng issues right now.
>
> Anyway: I see throughout (for example) of Schema.pm version (0.9902)
> tests like this:
>
>   #
>   # If called with an entry, get the OC names and continue
>   #
>   if ( UNIVERSAL::isa( $oc[0], "Net::LDAP::Entry" ) ) {
>     my $entry = $oc[0];
>     @oc = $entry->get_value( "objectclass" )
>       or return;
>   }
>
> This test does not test to see if $oc[0] is of type 'Net::LDAP::Entry'.
>
> In contrast, this test does:
>
>   if ( ref($oc[0]) eq "Net::LDAP::Entry" ) ) {
>
> The differences in these tests bit me during code development.  I
> may have violated some perl coding convention, so this all may not
> be a bug in Schema.pm, but a failure on my part.
>
> I wanted to present a class that would provide a simplified interface
> to the 'qmailUser' object class in the qmail schema for qmail-ldap.
>
> I decided to subclass Net::LDAP::Entry:
>
>   package qmailUser;
>
>   use Net::LDAP::Entry;
>   @ISA = qw(Net::LDAP::Entry);
>
>   sub new {
>     my $entry  = shift;
>     my $class = ref($entry) || $entry;
>     my $self = bless $entry->SUPER::new(), $class;
>     $self;
>   }
>
> Within that package, I wanted to collect a list of MAY attributes:
>
>   sub load_attributes {
>     my $ldap = Net::LDAP->new ( $server ) ||
>       croak "$0: can't connect to LDAP server $server: $!\n";
>
>     my $result = $ldap->bind();
>     $result->code && croak "failed to bind: ".$result->error ;
>     my $schema = $ldap->schema();
>
>     my $oc = 'qmailUser';
>     my @may = $schema->may($oc);
>   }
>
> What happens deep in Schema.pm, at that test, is that my scalar
> value 'qmailUser' is not tested for type; instead UNIVERSAL::isa()
> sees that these is a class 'qmailUser' that is subclassed from
> 'Net::LDAP::Entry'.  And the unwanted behavior begins.
>
> So - have I miscoded here, or have I ticked a bug in Net::LDAP::Schema?
>
> By merely renaming my package to QmailUser, everything works, but
> I don't like the dissociation of my package name from what I intended
> to manipulate...
>
> I'd appreciate any feedback.
>
> Oh: this is for perl 5.005_03, if that's a factor...

I tried to rreproduce the problems on my system (Perl 5.8. BTW) and
I think you have been hit by a bug.
Unfortunately your diagnosis is not correct.
Let me try to give the correct one.
Perl has the ability to treat strings as symbolic refernces. I.e. when Perl 
expects a reference and is not given a real (hard) reference but only
a scalar variable, it interprets the variable as a string naming a reference.

By naming your obhectclass te same as the attribute you tricked
UNIVERSAL::isa(...), which expects a reference as the first argument, into 
believing you gave it a soft reference to your object class instead of the 
name of a variable.

As a workaround you may change the name of your objectclass so that it is 
different from all the variable names you pass to Net::LDAP::Schema->may()

But the correct solution is to change 

  if ( UNIVERSAL::isa( $oc[0], "Net::LDAP::Entry" ) ) {
    my $entry = $oc[0];
    @oc = $entry->get_value( "objectclass" )
      or return;
  }

in Schema.pm to

  if ( ref($oc[0]) && UNIVERSAL::isa( $oc[0], "Net::LDAP::Entry" ) ) {
    my $entry = $oc[0];
    @oc = $entry->get_value( "objectclass" )
      or return;
  }

so that only hard references are checked by UNIVERSAL::isa().

I have updated the perl-ldap SVN accordingly.
Thanks for spotting the bug.

Peter
-- 
Peter Marschall
eMail: [EMAIL PROTECTED]

Reply via email to