File convert_keyhash.pl of Package pam_mount

#!/usr/bin/perl -w
#
#       convert tool for pam_mount.conf.xml
#
#       Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany.
#       This file is under the same license as pam_mount itself.
#
#       Please submit bugfixes or comments via http://bugs.opensuse.org/
#
use Data::Dumper;
use Getopt::Long;
use IO::File;
use XML::Writer;
use XML::Parser;
use File::Temp qw/ tempfile /;
use File::Copy;
use strict;

my $OLD_CONF = "/etc/security/pam_mount.conf.xml";
my ($TMPFH, $TEMPNAME) = tempfile("pam_mount_conf.XXXXXXXX", DIR => "/tmp/", UNLINK => 1);
my $BAK = "";
my $debug = 0;
my $hasChanges = 0;
my $node = {};
$node->{element} = "";
$node->{attrs}   = {};
$node->{chars}   = "";
$node->{isEmpty} = 1;


Getopt::Long::Configure(qw(bundling));
GetOptions(
        "i=s" => \$OLD_CONF,
        "d"   => \$debug,
);

if( ! -e "$OLD_CONF" )
{
    print STDERR "$OLD_CONF: file not found.\n";
    exit 1;
}

$BAK = "$OLD_CONF";
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$mon  += 1;
$year += 1900;
$BAK .= ".$year-$mon-$mday";


sub handle_decl_tag
{
    my $wrt = shift;
    my( $expat, $version, $encoding, $standalone ) = @_;

    $wrt->xmlDecl($encoding, $standalone);
    $wrt->raw("\n\n");
    print "write xmlDecl with $encoding\n" if($debug);
}

sub handle_start_tag
{
    my $wrt = shift;
    my( $expat, $element, %attrs ) = @_;

    if($node->{element} ne "" && !$node->{drop})
    {
        # subnode write the old one first
        $wrt->startTag($node->{element}, %{$node->{attrs}});
        print "write starttag of $node->{element}\n" if($debug);
        if($node->{chars} ne "")
        {
            $wrt->characters($node->{chars});
            print "write characters\n" if($debug);
        }
        $wrt->raw("\n");
        $node->{element} = "";
        $node->{attrs}   = {};
        $node->{chars}   = "";
        $node->{isEmpty} = 1;
    }

    if(lc($element) eq "volume" && ! exists $attrs{fskeyhash})
    {
        print "!!! set fskeyhash to MD5\n" if($debug);
        $attrs{fskeyhash} = "md5";
        $hasChanges = 1;
    }
    
    if(lc($element) eq "volume" ||
       lc($element) eq "pam_mount" ||
       lc($element) eq "debug" ||
       lc($element) eq "luserconf" ||
       lc($element) eq "mntoptions" ||
       lc($element) eq "path" ||
       lc($element) eq "logout" ||
       lc($element) eq "mkmountpoint"
      )
    {
        $node->{drop} = 0;
    }
    else
    {
        $node->{drop} = 1;
    }
    
    $node->{element} = $element;
    $node->{attrs}   = \%attrs;
    $node->{chars}   = "";
    $node->{isEmpty} = 1;
}

sub handle_char_tag
{
    my $wrt = shift;
    my( $expat, $string ) = @_;
    
    $node->{chars} .= $string;
    $node->{isEmpty} = 0;
}

sub handle_end_tag
{
    my $wrt = shift;
    my( $expat, $element ) = @_;

    if(!$node->{drop} && $element eq $node->{element})
    {
        if($node->{isEmpty})
        {
            $wrt->emptyTag($node->{element}, %{$node->{attrs}});
            $wrt->raw("\n");
            print "write emptytag of $node->{element}\n" if($debug);
        }
        else
        {
            $wrt->startTag($node->{element}, %{$node->{attrs}});
            print "write starttag of $node->{element}\n" if($debug);
            if($node->{chars} ne "")
            {
                $wrt->characters($node->{chars});
                print "write characters\n" if($debug);
            }
            $wrt->endTag($node->{element});
            $wrt->raw("\n");
            print "write endtag of $node->{element}\n" if($debug);
        }
    }
    elsif($element ne $node->{element})
    {
        $wrt->endTag($element);
        print "write endtag of $element\n" if($debug);
    }
    $node->{element} = "";
    $node->{attrs}   = {};
    $node->{chars}   = "";
    $node->{isEmpty} = 1;
}


my $writer = new XML::Writer(OUTPUT => $TMPFH, UNSAFE => 1);
my $parser = XML::Parser->new( Handlers =>
                               { XMLDecl => sub { handle_decl_tag($writer, @_) }, 
                                 Start   => sub { handle_start_tag($writer, @_) },
                                 Char    => sub { handle_char_tag($writer, @_) },
                                 End     => sub { handle_end_tag($writer, @_) },
                               });
$parser->parsefile( $OLD_CONF );

$TMPFH->close();

if($hasChanges)
{
    print "Changes made. $OLD_CONF => $BAK\n" if($debug);
    copy( $OLD_CONF, $BAK );
    print "$TEMPNAME => $OLD_CONF \n" if($debug);
    copy( $TEMPNAME, $OLD_CONF );
}
else
{
    print "No changes made. Keeping $OLD_CONF.\n" if($debug);
}

exit 0;

openSUSE Build Service is sponsored by