[Templates-cvs] cvs commit: TT3/lib/Template Utils.pm
cvs@template-toolkit.org
cvs@template-toolkit.org
Tue, 23 Mar 2004 11:05:31 +0000
cvs 04/03/23 11:05:31
Added: lib/Template Utils.pm
Log:
* Added Template::Utils module
Revision Changes Path
1.1 TT3/lib/Template/Utils.pm
Index: Utils.pm
===================================================================
#============================================================= -*-perl-*-
#
# Template::Utils
#
# DESCRIPTION
# Module implementing various utility functions that we don't want to
# put in the base class object for reasons of security: things like
# loading Perl modules, reading and writing files, etc., shouldn't be
# available to objects exposed in templates.
#
# AUTHOR
# Andy Wardley <abw@wardley.org>
#
# COPYRIGHT
# Copyright (C) 1996-2004 Andy Wardley. All Rights Reserved.
# Copyright (C) 1998-2002 Canon Research Centre Europe Ltd.
# Copyright (C) 2002-2004 Fotango Ltd.
#
# This module is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#
# REVISION
# $Id: Utils.pm,v 1.1 2004/03/23 11:05:30 abw Exp $
#
#========================================================================
package Template::Utils;
use strict;
use warnings;
use File::Path;
use File::Spec;
use File::Temp;
use File::Basename;
use Template::Base;
use vars qw( $VERSION $DEBUG $ERROR );
use base qw( Template::Base );
$VERSION = sprintf("%d.%02d", q$Revision: 1.1 $ =~ /(\d+)\.(\d+)/);
$DEBUG = 0 unless defined $DEBUG;
$ERROR = '';
#------------------------------------------------------------------------
# load_module($name)
#
# Load a Perl module.
#------------------------------------------------------------------------
sub load_module {
my ($self, $module) = @_;
$module =~ s[::][/]g;
$module .= '.pm';
eval { require $module };
return $@ ? $self->error("failed to load $module: $@") : 1;
}
#------------------------------------------------------------------------
# load_file($filename)
#
# Load the contents of a file, returning it as a reference to a scalar.
#------------------------------------------------------------------------
sub load_file {
my ($self, $filename) = @_;
local $/ = undef;
local *FH;
open(FH, "<$filename") || return $self->error("$filename: $!");
my $content = <FH>;
close(FH);
return \$content;
}
#------------------------------------------------------------------------
# save_file($file, $output)
#
# Writes $output to the file denoted by $file using an intermediate
# temporary file which is renamed into place to avoid any race conditions.
#------------------------------------------------------------------------
sub save_file {
my ($self, $file, $output) = @_;
my ($fh, $tmpfile);
# untaint filename
$file =~ /(.*)/;
$file = $1;
# determine base directory
my $dir = File::Basename::dirname($file);
eval {
# make the directory if it doesn't already exist
File::Path::mkpath($dir) unless -d $dir;
# create a temporary file in the same directory
($fh, $tmpfile) = File::Temp::tempfile( DIR => $dir );
print($fh ref($output) ? $$output : $output) || die $!;
close($fh);
};
return $self->error($@) if $@;
rename($tmpfile, $file)
|| return $self->error($!);
return 1;
}
#------------------------------------------------------------------------
# file_path($path1, $path2, $path3, ...)
#
# Wrapper around File::Spec method to concatenate file path components
# and return a canonical representation.
#------------------------------------------------------------------------
sub file_path {
my $self = shift;
File::Spec->canonpath(File::Spec->catfile(@_));
}
#------------------------------------------------------------------------
# path($path1, $path2, $path3, ...)
#
# Similar to file_path() but always uses '/' as a path separator rather
# than any OS specific value.
#------------------------------------------------------------------------
sub path {
# TODO: this should always use '/' for TT paths, regardless of OS
my $self = shift;
File::Spec->catfile(@_);
}
1;
__END__
=head1 NAME
Template::Utils - utility functions for the Template Toolkit
=head1 SYNOPSIS
use Template::Utils
# supports class methods...
# load a Perl module
Template::Utils->load_module('Template::Compiler')
|| die Template::Utils->error();
# load a file
my $text = Template::Utils->load_file('/tmp/foo')
|| die Template::Utils->error();
# save a file
Template::Utils->save_file('/tmp/bar', $text)
|| die Template::Utils->error();
# ...and also object methods
my $utils = Template::Utils->new();
# load a Perl module
$utils->load_module('Template::Compiler')
|| die $utils->error();
# load a file
my $text = $utils->load_file('/tmp/foo')
|| die $utils->error();
# save a file
$utils->save_file('/tmp/bar', $text)
|| die $utils->error();
=head1 DESCRIPTION
This module implements a number of useful utility methods. They can
be called as class methods:
use Template::Utils;
# load a Perl module
Template::Utils->load_module('Template::Compiler')
|| die Template::Utils->error();
Or as object methods:
my $utils = Template::Utils->new();
# load a Perl module
$utils->load_module('Template::Compiler')
|| die $utils->error();
=head1 METHODS
=head2 new()
This constructor method creates a new Template::Utils object.
my $utils = Template::Utils->new();
=head2 load_module($modname)
This method loads the Perl module named by the first argument. Any
occurrences of C<::> in the name will be converted to C</> and C<.pm>
will be appended to it to determine the correct file name.
$utils->load_module('Template::Compiler')
|| die $utils->error();
In the example above, the module loaded (using Perl's C<require>
function) is C<Template/TT3/Compiler.pm>.
=head2 load_file($filename)
This method reads the content of the file named by the first argument
and returns it as a single string.
my $text = $utils->load_file('/tmp/foo')
|| die $utils->error();
=head2 save_file($filename, $text)
This method writes the text passed as the second argument to the
file named by the first. The text can be passed as a scalar value
or as a reference to a scalar value.
# pass text
$utils->save_file('/tmp/bar', $text)
|| die $utils->error();
# pass reference to text
$utils->save_file('/tmp/bar', \$text)
|| die $utils->error();
To avoid any race conditions where two separate processes might
attempt to write the same file at the same time, the method writes
the output to a temporary file and then renames it into place.
=head1 AUTHOR
Andy Wardley E<lt>abw@wardley.orgE<gt>
=head1 VERSION
$Revision: 1.1 $
=head1 COPYRIGHT
Copyright (C) 1996-2003 Andy Wardley. All Rights Reserved.
Copyright (C) 1998-2002 Canon Research Centre Europe Ltd.
This module is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
=cut
# Local Variables:
# mode: perl
# perl-indent-level: 4
# indent-tabs-mode: nil
# End:
#
# vim: expandtab shiftwidth=4: