summaryrefslogtreecommitdiffstats
path: root/ldap/admin/src/scripts/60upgradeschemafiles.pl
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/admin/src/scripts/60upgradeschemafiles.pl')
-rw-r--r--ldap/admin/src/scripts/60upgradeschemafiles.pl137
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;
}