diff options
Diffstat (limited to 'ldap/admin/src/scripts/60upgradeschemafiles.pl')
-rw-r--r-- | ldap/admin/src/scripts/60upgradeschemafiles.pl | 137 |
1 files changed, 136 insertions, 1 deletions
diff --git a/ldap/admin/src/scripts/60upgradeschemafiles.pl b/ldap/admin/src/scripts/60upgradeschemafiles.pl index c1b1bb7c..ebc71268 100644 --- a/ldap/admin/src/scripts/60upgradeschemafiles.pl +++ b/ldap/admin/src/scripts/60upgradeschemafiles.pl @@ -1,4 +1,5 @@ +use Mozilla::LDAP::LDIF; use DSCreate qw(installSchema); sub runinst { @@ -12,6 +13,14 @@ sub runinst { # them with newer versions my @toremove = qw(00core.ldif 01core389.ldif 01common.ldif 02common.ldif 05rfc2247.ldif 10presence.ldif 28pilot.ldif 30ns-common.ldif 50ns-directory.ldif 60mozilla.ldif); + # these hashes will be used to check for obsolete schema + # in 99user.ldif + my %attrsbyname; + my %attrsbyoid; + my %objclassesbyname; + my %objclassesbyoid; + my $userschemaentry; + # make a backup directory to store the deleted schema, then # don't really delete it, just move it to that directory my $mode = (stat($inf->{slapd}->{schema_dir}))[2]; @@ -36,7 +45,126 @@ sub runinst { } } - if (@errs) { # errors backing up schema + # Remove obsolete schema from 99user.ldif. Compare by name and OID. + if (!open( OLDUSERSCHEMA, $inf->{slapd}->{schema_dir} . "/99user.ldif")) { + push @errs, ["error_reading_schema_file", $inf->{slapd}->{schema_dir} . "/99user.ldif", $!]; + } else { + my $olduserschema = new Mozilla::LDAP::LDIF(*OLDUSERSCHEMA); + + # Find the cn=schema entry. + while ($userschemaentry = readOneEntry $olduserschema) { + my $dn = $userschemaentry->getDN(); + # The only entry should be cn=schema, but best to play it safe. + next if ($dn ne "cn=schema"); + + # create the attributeTypes hashes (name->value, oid->value) + my @attrtypes = $userschemaentry->getValues("attributeTypes"); + foreach my $attrtype (@attrtypes) { + # parse out the attribute name and oid + if ($attrtype =~ /^\(\s*([\d\.]+)\s+NAME\s+'(\w+)'/) { + # normalize the attribute name + $attrsbyname{lc "$2"} = "$attrtype"; + $attrsbyoid{"$1"} = "$attrtype"; + } + } + + # create the objectClasses hashes (name->value, oid->value) + my @objclasses = $userschemaentry->getValues("objectClasses"); + foreach my $objclass (@objclasses) { + # parse out the objectclass name and oid + if ($objclass =~ /^\(\s*([\d\.]+)\s+NAME\s+'(\w+)'/) { + # normalize the objectclass name + $objclassesbyname{lc "$2"} = "$objclass"; + $objclassesbyoid{"$1"} = "$objclass"; + } + } + + # We found the cn=schema entry, so there's no need + # to look for more entries. + last; + } + + close OLDUSERSCHEMA; + } + + for my $file (@toremove) { + my $fullname = "$bakdir/$file"; + + next if (! -f $fullname); # does not exist - skip - already (re)moved + + if (!open( OBSOLETESCHEMA, "$fullname")) { + push @errs, ["error_reading_schema_file", $fullname, $!]; + } else { + my $obsoleteschema = new Mozilla::LDAP::LDIF(*OBSOLETESCHEMA); + + # Find the cn=schema entry. + while (my $entry = readOneEntry $obsoleteschema) { + my $dn = $entry->getDN(); + # The only entry should be cn=schema, but best to play it safe. + next if ($dn ne "cn=schema"); + + # Check if any of the attributeTypes in this file + # are defined in 99user.ldif and remove them if so. + my @attrtypes = $entry->getValues("attributeTypes"); + foreach $attrtype (@attrtypes) { + # parse out the attribute name and oid + if ($attrtype =~ /^\(\s*([\d\.]+)\s+NAME\s+'(\w+)'/) { + # normalize the attribute name + if ($attrsbyname{lc "$2"}) { + $userschemaentry->removeValue("attributeTypes", $attrsbyname{lc "$2"}); + } elsif ($attrsbyoid{"$1"}) { + $userschemaentry->removeValue("attributeTypes", $attrsbyoid{"$1"}); + } + } + } + + # Check if any of the objectClasses in this file + # are defined in 99user.ldif and remove them if so. + my @objclasses = $entry->getValues("objectClasses"); + foreach $objclass (@objclasses) { + # parse out the objectclass name and oid + if ($objclass =~ /^\(\s*([\d\.]+)\s+NAME\s+'(\w+)'/) { + # normalize the objectclass name + if ($objclassesbyname{lc "$2"}) { + $userschemaentry->removeValue("objectClasses", $objclassesbyname{lc "$2"}); + } elsif ($objclassesbyoid{"$1"}) { + $userschemaentry->removeValue("objectClasses", $objclassesbyoid{"$1"}); + } + } + } + } + + close OBSOLETESCHEMA; + } + } + + # Backup the original 99user.ldif + $! = 0; # clear + rename $inf->{slapd}->{schema_dir} . "/99user.ldif", "$bakdir/99user.ldif"; + if ($!) { + push @errs, ["error_renaming_schema", $inf->{slapd}->{schema_dir} . "/99user.ldif", "$bakdir/99user.ldif", $!]; + } + + # Write the new 99user.ldif + if (!open ( NEWUSERSCHEMA, ">" . $inf->{slapd}->{schema_dir} . "/99user.ldif")) { + push @errs, ["error_writing_schema_file", $inf->{slapd}->{schema_dir} . "/99user.ldif", $!]; + } else { + my $newuserschema = new Mozilla::LDAP::LDIF(*NEWUSERSCHEMA); + writeOneEntry $newuserschema $userschemaentry; + close NEWUSERSCHEMA; + + # Set permissions based off of the original 99user.ldif. + my @stat = stat("$bakdir/99user.ldif"); + my $mode = $stat[2]; + my $uid = $stat[4]; + my $gid = $stat[5]; + chmod $mode, $inf->{slapd}->{schema_dir} . "/99user.ldif"; + chown $uid, $gid, $inf->{slapd}->{schema_dir} . "/99user.ldif"; + } + + # If we've encountered any errors up to this point, restore + # the original schema. + if (@errs) { # restore the original schema files for my $file (@toremove) { my $oldname = "$bakdir/$file"; @@ -45,6 +173,13 @@ sub runinst { next if (-f $newname); # not removed rename $oldname, $newname; } + + # Restore 99user.ldif. We overwrite whatever is there since + # it is possible that we have modified it. + if (-f "$bakdir/99user.ldif") { + rename "$bakdir/99user.ldif", $inf->{slapd}->{schema_dir} . "/99user.ldif"; + } + return @errs; } |