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);