schema2ldif
changeset 12 0c4129f39f2c
parent 11 b1b75460e796
child 13 0be13fe64380
equal deleted inserted replaced
11:b1b75460e796 12:0c4129f39f2c
     1 #! /usr/bin/perl
       
     2 # according
       
     3 # http://www.zytrax.com/books/ldap/ch6/slapd-config.html#use-schemas
       
     4 # © 2013 Heiko Schlittermann <hs@schlittermann.de>
       
     5 
       
     6 use 5.010;
       
     7 use strict;
       
     8 use warnings;
       
     9 use if $ENV{DEBUG} => 'Smart::Comments';
       
    10 use English qw(-no_match_vars);
       
    11 use File::Temp;
       
    12 use File::Spec::Functions;
       
    13 use Getopt::Long;
       
    14 use Pod::Usage;
       
    15 
       
    16 our $VERSION = 0.01;
       
    17 
       
    18 my @opt_schema_dirs = qw(/etc/ldap/schema);
       
    19 my @opt_additional_schemas = ();
       
    20 
       
    21 GetOptions(
       
    22     'schema_dir=s@' => \@opt_schema_dirs,
       
    23     'additional_schema=s@' => \@opt_additional_schemas,
       
    24 ) and @ARGV == 1 or pod2usage();
       
    25 
       
    26 # find the additional schema definitions
       
    27 my @schemas = do {
       
    28     my @rc = ();
       
    29 
       
    30     open(my $f, '<', $ARGV[0]) or die "$PROGRAM_NAME: $ARGV[0]: $!\n";
       
    31     while (<$f>) {
       
    32 	if (/^#schema2ldif:include\s+(\S+)/) {
       
    33 	    push @opt_additional_schemas, $1;
       
    34 	}
       
    35     }
       
    36     close($f);
       
    37     foreach my $file (@opt_additional_schemas) {
       
    38 	$file .= '.schema' unless $file =~ /\.schema$/xms;
       
    39 	if (-f $file) {
       
    40 	    push @rc, catfile('.', $file);
       
    41 	    next;
       
    42 	}
       
    43 	($_) = grep { -f } map { catfile $_, $file } @opt_schema_dirs;
       
    44 	if ($_) {
       
    45 	    push @rc, $_;
       
    46 	    next;
       
    47 	}
       
    48 	die "$PROGRAM_NAME: $file: $!\n";
       
    49     }
       
    50     @rc;
       
    51 };
       
    52 
       
    53 ### @opt_schema_dirs
       
    54 ### @opt_additional_schemas
       
    55 ### @schemas
       
    56 
       
    57 (my $name = $ARGV[0]) =~ s/\.schema$//xms;
       
    58 my $cf = File::Temp->new();
       
    59 my $cd = File::Temp->newdir();
       
    60 
       
    61 # create a short temp config
       
    62 $cf->print("include $_\n") foreach @schemas, $ARGV[0];
       
    63 close $cf or die "Can't close $cf: $!\n";
       
    64 # ... convert it
       
    65 system slaptest => ( -f => $cf ),
       
    66 		   ( -F => $cd );
       
    67 die "slaptest failed, exit\n" if $?;
       
    68 
       
    69 # slurp the generated file
       
    70 # FIXME: what, if we had multiple preconditions
       
    71 open(my $ldif, '<', $_ = "$cd/cn=config/cn=schema/cn={1}$name.ldif")
       
    72     or die "Can't open $_: $!\n";
       
    73 $_ = do { local $RS = undef; <$ldif> };
       
    74 close($ldif) or die "Can't close ldif generated ldif file: $!\n";
       
    75 
       
    76 # some modifications
       
    77 s/\n\s+//xgms;
       
    78 s/^(?!(?:olc|dn|objectClass|cn)).*?\n//xmsg;
       
    79 s/(?<=^dn:\scn=){\d+}(\w+)/$1,cn=schema,cn=config/xms;
       
    80 s/(?<=^cn:\s){\d+}//xmsg;
       
    81 
       
    82 print <<"__", $_;
       
    83 # autogenerated by $PROGRAM_NAME
       
    84 # do not edit, edit $name.schema instead
       
    85 # see https://ssl.schlittermann.de/hg/exim-ldap-schema
       
    86 __
       
    87 
       
    88 __END__
       
    89 
       
    90 =head1 NAME
       
    91 
       
    92  schema2ldif - convert an LDAP schema definition into an LDIF for cn=config
       
    93 
       
    94 =head1 SYNOPSIS
       
    95 
       
    96  schema2ldif [--schema-dir=s]... [--additional-schema=s]... schema
       
    97 
       
    98 =head1 DESCRIPTION
       
    99 
       
   100 This B<schema2ldif> converts an LDAP schema definition into an LDIF
       
   101 file.
       
   102 
       
   103 =head2 OPTIONS
       
   104 
       
   105 =over 4
       
   106 
       
   107 =item B<--schema-dir> I<dir>
       
   108 
       
   109 A directory where to search for the additional schema(s). May
       
   110 be used multiple times. (default: F</etc/ldap/schemas>
       
   111 
       
   112 =item B<--additional-schema> I<schema>
       
   113 
       
   114 Additional schema to be included (preconditions for your self 
       
   115 defind schema). The F<.schema> extension may be omitted. First it's
       
   116 searched in the local directory, then in the directories given in
       
   117 B<--schema-dir> option(s). (default: none)
       
   118 
       
   119 NOTE: A pseudo comment 
       
   120 
       
   121     #include core.schema
       
   122 
       
   123 may be included in the schema to convert. It works the same way.
       
   124 
       
   125 =back
       
   126 
       
   127 =head1 EXAMPLES
       
   128 
       
   129  schema2ldif exim.schema | sudo ldapadd -Y external -H ldapi:///