first revision
authorHeiko Schlittermann (JUMPER) <hs@schlittermann.de>
Mon, 11 Nov 2013 22:01:35 +0100
changeset 0 3bfbc22cb61c
child 1 9bdcb51cb057
child 3 e26e2d5702bb
first revision
schema2ldif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/schema2ldif	Mon Nov 11 22:01:35 2013 +0100
@@ -0,0 +1,129 @@
+#! /usr/bin/perl
+# according
+# http://www.zytrax.com/books/ldap/ch6/slapd-config.html#use-schemas
+# © 2013 Heiko Schlittermann <hs@schlittermann.de>
+
+use 5.010;
+use strict;
+use warnings;
+use if $ENV{DEBUG} => 'Smart::Comments';
+use English qw(-no_match_vars);
+use File::Temp;
+use File::Spec::Functions;
+use Getopt::Long;
+use Pod::Usage;
+
+our $VERSION = 0.01;
+
+my @opt_schema_dirs = qw(/etc/ldap/schema);
+my @opt_additional_schemas = ();
+
+GetOptions(
+    'schema_dir=s@' => \@opt_schema_dirs,
+    'additional_schema=s@' => \@opt_additional_schemas,
+) and @ARGV == 1 or pod2usage();
+
+# find the additional schema definitions
+my @schemas = do {
+    my @rc = ();
+
+    open(my $f, '<', $ARGV[0]) or die "$PROGRAM_NAME: $ARGV[0]: $!\n";
+    while (<$f>) {
+	if (/^#schema2ldif:include\s+(\S+)/) {
+	    push @opt_additional_schemas, $1;
+	}
+    }
+    close($f);
+    foreach my $file (@opt_additional_schemas) {
+	$file .= '.schema' unless $file =~ /\.schema$/xms;
+	if (-f $file) {
+	    push @rc, catfile('.', $file);
+	    next;
+	}
+	($_) = grep { -f } map { catfile $_, $file } @opt_schema_dirs;
+	if ($_) {
+	    push @rc, $_;
+	    next;
+	}
+	die "$PROGRAM_NAME: $file: $!\n";
+    }
+    @rc;
+};
+
+### @opt_schema_dirs
+### @opt_additional_schemas
+### @schemas
+
+(my $name = $ARGV[0]) =~ s/\.schema$//xms;
+my $cf = File::Temp->new();
+my $cd = File::Temp->newdir();
+
+# create a short temp config
+$cf->print("include $_\n") foreach @schemas, $ARGV[0];
+close $cf or die "Can't close $cf: $!\n";
+# ... convert it
+system slaptest => ( -f => $cf ),
+		   ( -F => $cd );
+die "slaptest failed, exit\n" if $?;
+
+# slurp the generated file
+# FIXME: what, if we had multiple preconditions
+open(my $ldif, '<', $_ = "$cd/cn=config/cn=schema/cn={1}$name.ldif")
+    or die "Can't open $_: $!\n";
+$_ = do { local $RS = undef; <$ldif> };
+close($ldif) or die "Can't close ldif generated ldif file: $!\n";
+
+# some modifications
+s/\n\s+//xgms;
+s/^(?!(?:olc|dn|objectClass|cn)).*?\n//xmsg;
+s/(?<=^dn:\scn=){\d+}(\w+)/$1,cn=schema,cn=config/xms;
+s/(?<=^cn:\s){\d+}//xmsg;
+
+print <<"__", $_;
+# autogenerated by $PROGRAM_NAME
+# do not edit, edit $name.schema instead
+# see https://ssl.schlittermann.de/hg/exim-ldap-schema
+__
+
+__END__
+
+=head1 NAME
+
+ schema2ldif - convert an LDAP schema definition into an LDIF for cn=config
+
+=head1 SYNOPSIS
+
+ schema2ldif [--schema-dir=s]... [--additional-schema=s]... schema
+
+=head1 DESCRIPTION
+
+This B<schema2ldif> converts an LDAP schema definition into an LDIF
+file.
+
+=head2 OPTIONS
+
+=over 4
+
+=item B<--schema-dir> I<dir>
+
+A directory where to search for the additional schema(s). May
+be used multiple times. (default: F</etc/ldap/schemas>
+
+=item B<--additional-schema> I<schema>
+
+Additional schema to be included (preconditions for your self 
+defind schema). The F<.schema> extension may be omitted. First it's
+searched in the local directory, then in the directories given in
+B<--schema-dir> option(s). (default: none)
+
+NOTE: A pseudo comment 
+
+    #include core.schema
+
+may be included in the schema to convert. It works the same way.
+
+=back
+
+=head1 EXAMPLES
+
+ schema2ldif exim.schema | sudo ldapadd -Y external -H ldapi:///