#!/usr/bin/perl # # schema2ldif: Tool for converting OpenLDAP-style schemas to the LDIF format # ----------- # # The LDIF-formated LDAP schemas are difficult to edit and maintain. OpenLDAP # defined a similar schema format that is more free-form and easier to edit. # This tool converts the OpenLDAP-formatted schema files to the LDIF. # # Usage # ----- # # schema2ldif < foo.schema > foo.ldif # # OpenLDAP schema format # ---------------------- # # attributetype ( oid-my-attr-1 # NAME 'my-attr-1' # DESC 'description of my-attr-1 attribute' # SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 # ) # # objectclass ( oid-my-person # NAME 'my-person' # DESC 'description of my-person attribute' # SUP 'inetOrgPerson' # MAY ( my-attr-1 ) # ) # # LDIF schema format # ------------------ # # dn: cn=schema # objectClass: top # objectClass: ldapSubentry # objectClass: subschema # cn: schema # attributeTypes: ( oid-my-attr-1 NAME 'my-attr-1' DESC 'description of my-attr-1 attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'user defined' ) # objectClasses: ( oid-my-person NAME 'my-person' DESC 'description of my-person attribute' SUP 'inetOrgPerson' MAY ( my-attr-1 ) X-ORIGIN 'user defined' ) # # schema2ldif, Version 1.1.1, (c) 2005 Radovan Semancik # # Changes: # # v1.0.1: Added X-ORIGIN injection # v1.1: Added support for "modify" LDIF format (changetype: modify operation) # v1.1.1: Fixed "last line" bug # use strict; my $mode = "static"; my $origin = 'user defined'; # Process command-line while ($ARGV[0] =~ /^-/) { my $arg = shift; if ($arg eq "-h") { usage(); exit(); } elsif ($arg eq "-m") { $mode = "modify"; } elsif ($arg eq "-o") { $origin = shift; } else { print STDERR "Unknown option $arg\n"; usage(); exit(-1); } } my %attrNameMap = ( 'attributetype' => 'attributeTypes', 'objectclass' => 'objectClasses', ); my @definitionOrder = qw(attributetype objectclass); my %definitions = (); # Print proper header if ($mode eq "static") { print "dn: cn=schema\n"; print "objectClass: top\n"; print "objectClass: ldapSubentry\n"; print "objectClass: subschema\n"; print "cn: schema\n"; } elsif ($mode eq "modify") { print "dn: cn=schema\n"; print "changetype: modify\n"; } else { die ("Unknown mode $mode\n"); } READLOOP: while (<>) { if (/^\s*#/) { print if ($mode eq "static"); next; } chomp; if ( /^\s*(attributetype)\s*\(/i || /^\s*(objectclass)\s*\(/i ) { my $type = lc($1); my $ldifLine = $attrNameMap{$type}.": ("; $_ = $'; my $level = 1; my $foundOrigin = undef; while ($level) { # raise or lower parenthesis level as necessary while ( /\(/g ) { $level++ } while ( /\)/g ) { $level-- } # find X-ORIGIN clause in the input if (/X\-ORIGIN\s+\'([^\'*])\'/) { $foundOrigin = $1; } # if we are at the end (level 0) and there was no # X-ORIGIN clause, insert the default one # just before the last parenthesis if ($level == 0 && !defined($foundOrigin)) { s/\)\s*$/ X-ORIGIN \'$origin\' \)/; } $ldifLine .= $_; $_ = <>; last unless defined $_; chomp; s/^\s+/ /; s/\s+$//; } if ($mode eq "static") { print $ldifLine . "\n"; } else { if (!$definitions{$type}) { $definitions{$type} = []; } push @{$definitions{$type}},$ldifLine; } last unless defined $_; } } if ($mode eq "modify") { my $first = 1; foreach my $type (@definitionOrder) { next unless ($definitions{$type}); if ($first) { $first = 0; } else { print "-\n"; } print "add: ".$attrNameMap{$type}."\n"; foreach my $line (@{$definitions{$type}}) { print $line."\n"; } } } sub usage { print STDERR "Usage: $0 [-h ] [-m] [-o ] in.schema > out.ldif\n"; print STDERR "\t-h\t\tThis help message.\n"; print STDERR "\t-m\t\tGenerate \"modify\" LDIF instead of \"static\"\n"; print STDERR "\t-o \tSpecify X-ORIGIN to inject (default: user defined)\n"; print STDERR "(c) 2000-2005 Radovan Semancik (http://storm.alert.sk/)\n"; }