Hi Rick,

would you be so kind to do the perl-ldap project a favour ?

Here's a patch for Net::LDAP::LDIF that should make it work with
LDIF files that have lines ending in CR+LF.

Would you mind to test it and report any problems with it

Thanks in advance
Peter

On Tuesday, 23. August 2005 18:46, Rick Greene wrote:
> Ok, I found the problem.  Somehow (probably a default action that I
> didn't know about), when taking in the LDIF formatted text from the
> textarea field of the web form, dumping to a local temporary text file,
> and then using Net::LDAP::LDIF's $ldif->read_entry(), ALL the attributes
> were ending up with a CR (ascii 13) character at the end, and the PERL
> chomp function wasn't removing it.  I got more brute-force-ish about it
> and it all works now.
>
> I did two things...after writing the $w->param('ldif') out to a file, I
> then did:
>
> system ("/usr/bin/dos2unix $tmp")
>
> Which probably took care of everything, but I also put in the following
> line in a couple of key places to be sure:
>
> if ( ord(substr($line,-1)) <= 32 ) { chop($line) ; }
>
> Sorry to have taken up everyone's time with this, thanks to Graham for
> the one hint, hopefully this thread will help someone else along the line.
>
> Rick
>
> Rick Greene wrote:
> > Ok, Graham supplied the missing bit, so now I know at least the basics
> > are working.
> >
> > Now the question remains, what is wrong with the original thing I was
> > trying, using the Net::LDAP::LDIF functionality?  Here's the code (part
> > of a script fed from a web form, cut out extraneous details):
> >
> > #Version to do it through LDIF read
> > use Net::LDAP::LDIF ;
> > local $tmp="/tmp/$$.ldif" ;
> > open OUTFILE,"> $tmp"; print OUTFILE $w->param('ldif') ; close OUTFILE ;
> > $ldif = Net::LDAP::LDIF->new($tmp,"r",onerror => 'warn');
> > $entry = $ldif->read_entry();
> > if ($debug) {
> >   print "${redon}ldif loaded with dn=",$entry->dn(),"${redoff}$br";
> >   @attributes=$entry->attributes;
> >   print "${redon}read entry:<BR>"; foreach $key (sort @attributes) {
> > print "$key=" ; print $entry->get_value($key); print "${br}"; } print
> > "${redoff}${br}";
> > }
> > $ldap = Net::LDAP->new($LDAPSERVER);
> > $result=$ldap->bind("$binddn",password=>"$bindpass",version=>"3");
> > $result=$ldap->add($entry);
> > $result->code && die "add error: ", $result->error;
> >
> > And here is the LDIF that is pasted into the form (a textarea field):
> >
> > dn: cn=kingr,o=PennLibraryStaff,dc=library,dc=upenn,dc=edu
> > objectclass: person
> > objectclass: organizationalPerson
> > objectclass: inetOrgPerson
> > objectclass: posixAccount
> > objectclass: upennEduPerson
> > cn: kingr
> > gn: Richard
> > sn: King
> > userid: kingr
> > uidNumber: 3019
> > gidNumber: 100
> > homeDirectory: /home/kingr
> > loginShell: /bin/bash
> > gecos: Richard P. King
> > ou: Reference
> > title: Systems Tech II
> >
> > And here's the results (some debug statements were omitted from the code
> > above, but the output is below):
> > In sub process_ldif
> > creating /tmp/19277.ldif
> > /tmp/19277.ldif contains
> >
> > dn: cn=kingr,o=PennLibraryStaff,dc=library,dc=upenn,dc=edu
> > objectclass: person
> > objectclass: organizationalPerson
> > objectclass: inetOrgPerson
> > objectclass: posixAccount
> > objectclass: upennEduPerson
> > cn: kingr
> > gn: Richard
> > sn: King
> > userid: kingr
> > uidNumber: 3019
> > gidNumber: 100
> > homeDirectory: /home/kingr
> > userPassword: {SHA}6wEWbSyjuY4/gp469HkIAxqj3vs=
> > loginShell: /bin/bash
> > gecos: Richard P. King
> > ou: Reference
> > mail: [EMAIL PROTECTED]
> > telephonenumber: 215-898-5928
> > title: Systems Tech II
> >
> > ldif loaded with
> > dn=cn=kingr,o=PennLibraryStaff,dc=library,dc=upenn,dc=edu read entry:
> > cn=kingr
> > gecos=Richard P. King
> > gidnumber=100
> > gn=Richard
> > homedirectory=/home/kingr
> > loginshell=/bin/bash
> > [EMAIL PROTECTED]
> > objectclass=person organizationalPerson inetOrgPerson posixAccount
> > upennEduPerson
> > ou=Reference
> > sn=King
> > telephonenumber=215-898-5928
> > title=Systems Tech II
> > uidnumber=3019
> > userid=kingr
> > userpassword={SHA}6wEWbSyjuY4/gp469HkIAxqj3vs=
> >
> > add error: objectclass: value #0 invalid per syntax at
> > /var/www/html/bin/ldappasswd.cgi line 117, line 1.
> >
> > So, as far as I can tell the $entry reference has everything in it, and
> > I know the object classes in the LDIF are good, for they are the same as
> > every other entry in this particular LDAP instance.  In fact, if I use
> > this LDIF file from the command line with an ldapadd statement, it works
> > fine.  So again, I am missing something but can't tell what.  It's not
> > the bit I was missing doing it manually that Graham pointed out, for you
> > can see the debug code is correctly outputting $entry->dn() and showing
> > the value is set.
> >
> > Thanks again in advance,
> > Rick
> >
> >
> >
> > ______________________________________________________________________
> > This email has been scanned by the MessageLabs Email Security System.
> > For more information please visit http://www.messagelabs.com/email
> > ______________________________________________________________________
>
> ______________________________________________________________________
> This email has been scanned by the MessageLabs Email Security System.
> For more information please visit http://www.messagelabs.com/email
> ______________________________________________________________________

-- 
Peter Marschall
eMail: [EMAIL PROTECTED]
--- lib/Net/LDAP/LDIF.pm	(revision 455)
+++ lib/Net/LDAP/LDIF.pm	(working copy)
@@ -9,7 +9,7 @@
 require Net::LDAP::Entry;
 use vars qw($VERSION);
 
-$VERSION = "0.16";
+$VERSION = "0.16_01";
 
 my %mode = qw(w > r < a >>);
 
@@ -79,35 +79,49 @@
   
 sub _read_lines {
   my $self = shift;
-  my @ldif;
+  my $fh = $self->{'fh'};
+  my @ldif = ();
+  my $entry = '';
+  my $in_comment = 0;
+  my $entry_completed = 0;
+  my $ln;
 
-  {
-    local $/ = "";
-    my $fh = $self->{'fh'};
-    my $ln;
-    do {	# allow comments separated by blank lines
-      $ln = $self->{_next_lines} || scalar <$fh>;
-      unless ($ln) {
-         $self->{_next_lines} = '';
-         $self->{_current_lines} = '';
-         $self->eof(1);
-         return;
+  return @ldif  if ($self->eof());
+  
+  while (defined($ln = $self->{_buffered_line} || scalar <$fh>)) {
+    delete($self->{_buffered_line});
+    if ($ln =~ /^#/o) {		# ignore 1st line of comments
+      $in_comment = 1;
+    }
+    else {
+      if ($ln =~ /^[ \t]/o) {	# append wrapped line (if not in a comment)
+        $entry .= $ln  if (!$in_comment);
       }
-      $ln =~ s/\n //sg;
-      $ln =~ s/^#.*\n//mg;
-      chomp($ln);
-      $self->{_current_lines} = $ln;
-    } until ($self->{_current_lines} || $self->eof());
-    chomp(@ldif = split(/^/, $ln));
-    do {
-      $ln = scalar <$fh> || '';
-      $self->eof(1) unless $ln;
-      $ln =~ s/\n //sg;
-      $ln =~ s/^#.*\n//mg;
-      chomp($ln);
-      $self->{_next_lines} = $ln;
-    } until ($self->{_next_lines} || $self->eof());
+      else {
+        $in_comment = 0;
+        if ($ln =~ /^\r?\n$/o) {
+          # ignore empty line on start of entry
+          # empty line at non-empty entry indicate entry completion
+          $entry_completed++  if (length($entry));
+	}
+        else {
+	  if ($entry_completed) {
+	    $self->{_buffered_line} = $ln;
+	    last;
+	  }
+	  else {
+            # append non-empty line
+            $entry .= $ln;
+	  }  
+        }	
+      }
+    }
   }
+  $self->eof(1)  if (!defined($ln));
+  $entry =~ s/\r?\n //sgo;	# un-wrap wrapped lines
+  $entry =~ s/\r?\n\t/ /sgo;	# OpenLDAP extension !!!
+  @ldif = split(/^/, $entry);
+  map { s/\r?\n$//; } @ldif;
 
   @ldif;
 }
@@ -177,7 +191,7 @@
 
   my $dn = shift @ldif;
 
-  if (length($1)) {
+  if (length($1)) {	# $1 is the optional colon from above
     eval { require MIME::Base64 };
     if ($@) {
       $self->_error($@, @ldif);

Reply via email to