| Mozilla-Backup documentation | Contained in the Mozilla-Backup distribution. |
Mozilla::Backup::Plugin::Zip - A zip archive plugin for Mozilla::Backup
use Mozilla::Backup;
my $moz = Mozilla::Backup->new(
plugin => 'Mozilla::Backup::Plugin::Zip'
);
This is a plugin for Mozilla::Backup which allows backups to be saved as zip files.
Methods will return a true value on sucess, or false on failure. (The "false" value is overloaded to return a string value with the error code.)
Methods are outlined below:
$plugin = Mozilla::Backup::Plugin::Zip->new( %options );
The following %options are supported:
The Log::Dispatch objetc used by Mozilla::Backup. This is required.
The debug flag from Mozilla::Backup. This is not used at the moment.
The desired compression level to use when backing up files, between 0
and 9. 0 means to store (not compress) files, 1 is for the
fastest method with the lowest compression, and 9 is for the slowest
method with the fastest compression. (The default is 6.)
See the Archive::Zip documentation for more information on levels.
@options = Mozilla::Backup::Plugin::Zip->allowed_options();
if (Mozilla::Backup::Plugin::Zip->allowed_options('debug')) {
...
}
If no arguments are given, it returns a list of configuration parameters that can be passed to the constructor. If arguments are given, it returns true if all of the arguments are allowable options for the constructor.
$filename = $plugin->munge_location( $filename );
Munges the archive name by adding the "zip" extension to it, if it does not already have it. If called with no arguments, just returns ".zip".
if ($plugin->open_for_backup( $filename, %options )) {
...
}
Creates a new archive for backing the profile. $filename is the
name of the archive file to be used. %options are optional
configuration parameters.
if ($plugin->open_for_restore( $filename, %options )) {
...
}
Opens an existing archive for restoring the profile.
@files = $plugin->get_contents;
Returns a list of files in the archive. Assumes it has been opened for restoring (may or may not work for archives opened for backup; applications are expected to track files backed up separately).
$plugin->backup_file( $local_file, $internal_name );
Backs up the file in the archive, using $internal_name as the
name in the archive. Assumes it has been opened for backup.
$plugin->restore_file( $internal_name, $local_file );
Restores the file from the archive. Assumes it has been opened for restoring.
$plugin->close_backup();
Closes the backup.
$plugin->close_restore();
Closes the restore.
The "MozBackup" utility (http://backup.jasnapaka.com) produces zip archives (with the pcv extension) which should be compatible with this module, although support for handling the indexfiles.txt has not been added (it should probably be exluded in a restore).
Robert Rothenberg <rrwo at cpan.org>
Copyright (c) 2005 Robert Rothenberg. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| Mozilla-Backup documentation | Contained in the Mozilla-Backup distribution. |
package Mozilla::Backup::Plugin::Zip; use strict; use Archive::Zip qw( :ERROR_CODES ); use Carp; use File::Spec; use Log::Dispatch; use Params::Smart 0.04; use Return::Value; # require Mozilla::Backup; # $Revision: 1.27 $ our $VERSION = '0.03';
my @ALLOWED_OPTIONS = ( { name => "log", default => Log::Dispatch->new(), callback => sub { my ($self, $name, $log) = @_; croak "invalid log sink" unless ((ref $log) && $log->isa("Log::Dispatch")); return $log; }, name_only => 1, required => 1, }, { name => "compression", default => 6, name_only => 1, callback => sub { my ($self, $name, $value) = @_; # TODO - check if an integer? croak "expected value between 0 and 9" unless (($value >= 0) && ($value <= 9)); return $value; }, }, { name => "debug", default => 0, name_only => 1, }, ); sub new { my $class = shift || __PACKAGE__; my %args = Params(@ALLOWED_OPTIONS)->args(@_); my $self = { log => $args{log}, debug => $args{debug}, compression => $args{compression}, status => "closed", }; return bless $self, $class; }
sub allowed_options { my $class = shift || __PACKAGE__; my %args = Params(qw( ?*options ))->args(@_); my %allowed = map { $_->{name} => 1, } @ALLOWED_OPTIONS; my @opts = @{$args{options}}, if ($args{options}); if (@opts) { my $allowed = 1; while ($allowed && (my $opt = shift @opts)) { $allowed = $allowed && $allowed{$opt}; } return $allowed; } else { return (keys %allowed); } }
sub munge_location { my $self = shift; my %args = Params(qw( file ))->args(@_); my $file = $args{file} || ""; $file .= ".zip", unless ($file =~ /\.zip$/i); return $file; }
sub open_for_backup { my $self = shift; my %args = Params(qw( path ?*options ))->args(@_); my $path = $args{path}; unless ($self->{status} eq "closed") { return failure $self->_log( "cannot create archive: status is \"$self->{status}\"" ); } $self->{path} = $path; $self->{opts} = $args{options}; $self->_log( level => "debug", message => "creating archive $path\n" ); if ($self->{zip} = Archive::Zip->new()) { $self->{status} = "open for backup"; return success; } else { return failure $self->_log( "unable to create archive" ); } }
sub open_for_restore { my $self = shift; my %args = Params(qw( path ?*options ))->args(@_); my $path = $args{path}; unless ($self->{status} eq "closed") { return failure $self->_log( "cannot open archive: status is \"$self->{status}\"" ); } $self->{path} = $path; $self->{opts} = $args{options}; $self->_log( level => "debug", message => "opening archive $path\n" ); if ($self->{zip} = Archive::Zip->new( $path )) { $self->{status} = "open for restore"; return success; } else { return failure $self->_log( "unable to open archive" ); } }
sub get_contents { my $self = shift; unless ($self->{status} ne "closed") { return failure $self->_log( "cannot get contents: status is \"$self->{status}\"" ); } return $self->{zip}->memberNames(); }
sub backup_file { my $self = shift; my %args = Params(qw( file ?internal ))->args(@_); unless ($self->{status} eq "open for backup") { return failure $self->_log( "cannot backup file: status is \"$self->{status}\"" ); } my $file = $args{file}; # actual file my $name = $args{internal} || $file; # name in archive $self->_log( level => "info", message => "backing up $name\n" ); my $member = $self->{zip}->addFileOrDirectory($file, $name); $member->desiredCompressionLevel( $self->{compression} ); return $member; }
sub restore_file { my $self = shift; my %args = Params(qw( internal file ))->args(@_); unless ($self->{status} eq "open for restore") { return failure $self->_log( "cannot restore file: status is \"$self->{status}\"" ); } my $file = $args{internal}; my $dest = $args{file} || return failure $self->_log( "no destination specified" ); unless (-d $dest) { return failure $self->_log( "destination does not exist" ); } my $path = File::Spec->catfile($dest, $file); if (-e $path) { $self->_log( level => "debug", message => "$path exists\n" ); # TODO: confirmation to overwrite? } $self->_log( level => "info", message => "restoring $file\n" ); $self->{zip}->extractMember($file, $path); unless (-e $path) { return failure $self->_log( "extract failed" ); } return success; }
sub close_backup { my $self = shift; unless ($self->{status} eq "open for backup") { return failure $self->_log( "cannot close archive: status is \"$self->{status}\"" ); } my $path = $self->{path}; $self->_log( level => "debug", message => "saving archive: $path\n" ); if ($self->{zip}->writeToFileNamed( $path ) == AZ_OK) { $self->{status} = "closed"; return success; } else { return failure $self->_log( "writeToFileNamed $path failed" ); } }
sub close_restore { my $self = shift; unless ($self->{status} eq "open for restore") { return failure $self->_log( "cannot close archive: status is \"$self->{status}\"" ); } $self->_log( level => "debug", message => "closing archive\n" ); $self->{status} = "closed"; return success; }
sub _log { my $self = shift; my %args = Params(qw( message ?level="error" ))->args(@_); my $msg = $args{message}; # we want log messages to always have a newline, but not necessarily # the returned value that we pass to carp/croak/return value $args{message} .= "\n" unless ($args{message} =~ /\n$/); $self->{log}->log(%args) if ($self->{log}); return $msg; # when used by carp/croak/return value } 1;