#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2006
    Posts
    9
    Rep Power
    0

    Parsing ldif file


    Hi all,

    I have to parse ldif file in order to perform "full sync" of AD with DB. If you ever did parsing of ldif file in C/C++, I would appreciate any help from you.

    Thank you in advance
  2. #2
  3. Psycho Canadian
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Jan 2001
    Location
    Canada
    Posts
    4,846
    Rep Power
    635
    Instead of answering to both threads (your other thread here I'll answer both here.

    You can do a partial dump of the AD server, when you run ldapsearch (to preform the LDIF dump) you can specifiy which attributes you want dumped, and the other ones are omited. This way you have less data to parse through.

    To parse an LDIF is quite easy, it's just a text file. What part of parsing it do you need help with?

    You say you have to use C/C++ any chance you can use Perl? Perl is great at parsing text so you won't have to create anything new. Perl normally comes with most lunix servers/workstations.
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2006
    Posts
    9
    Rep Power
    0
    thank you for your response,
    the problem is that my ldif file contains a huge number of objects.
    I will be very grateful for any example of parsing ldif file

    thanks in advance
  6. #4
  7. Psycho Canadian
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Jan 2001
    Location
    Canada
    Posts
    4,846
    Rep Power
    635
    Can you give an example (2 or 3 entries) they don't have to have valid data in them, but I need to know what we're working with.
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2006
    Posts
    9
    Rep Power
    0
    # extended LDIF
    #
    # LDAPv3
    # base <OU=xxx,OU=xxx,OU=xxx,DC=xxxx,DC=xx,DC=xx> with scope sub
    # filter: (objectclass=person)
    # requesting: objectguid displayname dn cn objectclass rdn proxyaddresses rfc822mailbox mailnickname loginname displayname memberof email member samaccountname givenName sn mail
    # with pagedResults control: size=100
    #

    # xxxxxxxxxxxxx, xxx, consolidatedmessenger, Hosting, xxxxx
    dn: CN=xxxxx,OU=xxx,OU=consolidatedmessenger,OU=Hosting,DC=xxx,DC=xx,DC=xx
    objectClass: top
    objectClass: person
    objectClass: organizationalPerson
    objectClass: user
    cn: xxxxxxxxx
    sn:: xxxxx
    givenName:: xxxxxx
    displayName:: xxxxxxxx
    proxyAddresses: smtp:xxxxxxx
    proxyAddresses: smtp:xxxxxxxxxxxxxxxxx
    proxyAddresses: SMTP:xxxxxxxxxxxxxxxxx
    mailNickname: xxxxxxxxx
    objectGUID:: xxxxxxxxxxxxxxxxxxxx
    sAMAccountName: xxxxxxxx
    mail: xxxxxxxxxxxx

    # xxxxxxxxxxxx, xxxx, consolidatedmessenger, Hosting, xxxxx
    dn: CN=xxxxx,OU=xxx,OU=consolidatedmessenger,OU=Hosting,DC=xxxx,DC=xx,DC=xx
    objectClass: top
    objectClass: person
    objectClass: organizationalPerson
    objectClass: user
    cn: xxxxxxxxxxxxx
    sn:: xxxxxxxxx
    givenName:: xxxxxxxxxxxxxx
    displayName:: xxxxxxxxxxxxxxx
    proxyAddresses: smtp:xxxxx
    proxyAddresses: smtp:xxxxx
    proxyAddresses: SMTP:xxxxxxxxxxxx
    mailNickname: xxxx
    objectGUID:: xxxxxx
    sAMAccountName: xxxxxx
    mail: xxxxxxxxxxxx

    # search result
    search: 7
    result: 0 Success
    control: 1.2.840.113556.1.4.319 false MIQAAAFhAgEABIQAAAFYAQAAAFgBAAD/////sKoL
    1XsvIlh1xSTRSCtLqw6SpMmhPlROocTYT1fet2cAAAAAAQAAAAAAAAABAwsAJQAAAAUAAAACAAAAA
    AAAAAQAAAAFAAEAGjAAAPQvAACzBQAAAAAAADbnOhYdlxhAuAEwoCfjfywAAAAABAAAAAEAAAAAAA
    AALMFAAAJwy8AAPQvAAAJGjAAAAEDCwAIf4ALAwEAAAAAAAD/////AAAAAAAAAAD/////DwAAACUA
    H8CAAAAsQUAAAmyBQAAswUAAAnDLwAA9C8AAAkaMAAA////////AAA=
    # extended LDIF
    #
    # LDAPv3
    # base <OU=xxxx,OU=consolidatedmessenger,OU=Hosting,DC=xxx,DC=xx,DC=xx> with scope sub
    # filter: (objectclass=person)
    # requesting: objectguid displayname dn cn objectclass rdn proxyaddresses rfc822mailbox mailnickname loginname displayname memberof email member samaccountname givenName sn mail
    # with pagedResults control: size=100
    #

    # xxxxxxxxxxxxx, xxxx, consolidatedmessenger, Hosting, xxxxx
    dn: CN=xxxxx,OU=xxx,OU=consolidatedmessenger,OU=Hosting,DC=xxx,DC=xx,DC=xx
    objectClass: top
    objectClass: person
    objectClass: organizationalPerson
    objectClass: user
    cn: xxxxx
    givenName: xxxxx
    displayName: xxxxx
    proxyAddresses: smtp:xxxxxx
    proxyAddresses: smtp:xxxxxx
    proxyAddresses: SMTP:xxxxxxxxxxxxxxx
    mailNickname: xxxxxxxxx
    objectGUID:: xxxxxxxxx
    sAMAccountName: xxxxxxx
    mail: xxxxxxxx
  10. #6
  11. Psycho Canadian
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Jan 2001
    Location
    Canada
    Posts
    4,846
    Rep Power
    635
    Ok what do you want parsed out of it? I'd personally use regular expressesions and it'd be quite easy, but I think you are looking for something very specific.
  12. #7
  13. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2010
    Posts
    1
    Rep Power
    0

    Perl LDIF parser


    I just finished writing a one-off LDIF parser in Perl. Here is the code in case anyone needs it...

    Code:
    # This routine takes in a path to an LDIF and returns an associative array of associative arrays.
    sub getLDAPEntriesFromLDIF($)
    {
    	# Get the input path.
    	my ($inputLDAPPath) = @_;
    	
    	# Open the input file.
    	open(INPUTFILE, $inputLDAPPath);
    
    	# Get all the lines of the INPUTFILE as an array.
    	my @lines;
    	@lines = <INPUTFILE>;
    	
    	# Create an associative array to hold all the ldap entries.
    	my %ldapEntries;
    	
    	# Create a counter.
    	my $i = 0;
    	
    	# Start a loop that iterates through all the lines of the LDIF.
    	GET_NEXT_ENTRY: for($i; $i < @lines; $i++)
    	{
    		# Create an associative array to hold an individual entry.
    		my %ldapEntry;
    		
    		# Start iterating through the entry.
    		GET_NEXT_LINE: for($i; $i < @lines; $i++)
    		{
    			# If the line is a line continuation, restart the GET_NEXT_LINE loop on the next line.
    			if($lines[$i] =~ /^(\s+\S+)\n$/)
    			{
    				$i++;
    				redo GET_NEXT_LINE;
    			}
    
    			# If the line is empty, it signifies the end of an entry.  In this case, cache the individual entry
    			# to ldapEntries and restart the GET_NEXT_ENTRY loop on the next line.
    			if($lines[$i] =~ /^(\s*)\n$/)
    			{
    				if($ldapEntry{"dn"})
    				{
    					$ldapEntries{$ldapEntry{"dn"}[0]} = [%ldapEntry];
    				}
    				else
    				{
    					print "-------------- ERROR - No \"dn\" for entry at line ".($i+1)." --------------\n";
    				}
    				$i++;
    				redo GET_NEXT_ENTRY;
    			}
    			
    			# Create a temp variable to hold the current line of the ldif
    			my $tempLine = $lines[$i];
    			
    			# Create a variable and populate it with the split line.
    			my @splitLine;
    			if($tempLine =~ /::/)
    			{
    				@splitLine = split(/::/, $tempLine);
    				print "-------------- WARN value for attribute \"".$splitLine[0]."\" at line ".($i+1)." is encrypted --------------\n";
    			}
    			elsif($tempLine =~ /:/)
    			{
    				@splitLine = split(/:/, $tempLine);
    			}
    			
    			# If the next line is a continuation of the current line, go ahead and add its text to the end of the current line.
    			if($lines[$i+1] =~ /^(\s+)/)
    			{
    				if($lines[$i+1] =~ /(\S+)$/)
    				{
    					chomp($splitLine[1]);
    					$splitLine[1] = $splitLine[1].$&;
    				}
    			}
    
    			# Remove the line break from the end of the value portion of the line.
    			chomp($splitLine[1]);
    			
    			# Remove the space from the front of the value portion of the line.
    			$splitLine[1] = substr($splitLine[1], 1);
    			
    			# If everything went okay, go ahead and cache the attribute and value to the ldap entry.
    			if($splitLine[1])
    			{
    				if(!($ldapEntry{$splitLine[0]}))
    				{
    					my @tempArray = ($splitLine[1]);
    					$ldapEntry{$splitLine[0]} = [@tempArray];
    				}
    				else
    				{
    					if($splitLine[1])
    					{
    						push(@{$ldapEntry{$splitLine[0]}}, $splitLine[1])
    					}
    					else
    					{
    						print "ERROR!";
    					}
    				}
    			}
    		}
    	}
    	close(INPUTFILE);
    	return %ldapEntries;
    }
    As you can see, it returns an associative array (keyed on the dn of the entries) of associative arrays (keyed on the attribute names in each entry).

    To access an attribute (and it's values) on an entry use:

    Code:
    my %entry = @{$ldapEntries{$key}}; # Where $key = the entry's 'dn' (e.g. cn=blah,ou=Awesome,dc=code,dc=com).
    my @values = @{$entry{$attr}}; # Where $attr = the attributes name (e.g. "uid").
    I hope this helps someone out.

    Billy

IMN logo majestic logo threadwatch logo seochat tools logo