shell bypass 403
package HTML::Template::Pro;
use 5.005;
use strict;
use integer; # no floating point math so far!
use HTML::Template::Pro::WrapAssociate;
use File::Spec; # generate paths that work on all platforms
use Scalar::Util qw(tainted);
use Carp;
require DynaLoader;
require Exporter;
use vars qw($VERSION @ISA @EXPORT_OK %EXPORT_TAGS);
@ISA = qw(DynaLoader Exporter);
$VERSION = '0.9510';
@EXPORT_OK = qw/ASK_NAME_DEFAULT ASK_NAME_AS_IS ASK_NAME_LOWERCASE ASK_NAME_UPPERCASE ASK_NAME_MASK/;
%EXPORT_TAGS = (const => [qw/ASK_NAME_DEFAULT ASK_NAME_AS_IS ASK_NAME_LOWERCASE ASK_NAME_UPPERCASE ASK_NAME_MASK/]);
# constants for tmpl_var_case
use constant {
ASK_NAME_DEFAULT => 0,
ASK_NAME_AS_IS => 1,
ASK_NAME_LOWERCASE => 2,
ASK_NAME_UPPERCASE => 4,
};
use constant ASK_NAME_MASK => ASK_NAME_AS_IS | ASK_NAME_LOWERCASE | ASK_NAME_UPPERCASE;
bootstrap HTML::Template::Pro $VERSION;
## when HTML::Template is not loaded,
## all calls to HTML::Template will be sent to HTML::Template::Pro,
## otherwise native HTML::Template will be used
push @HTML::Template::ISA, qw/HTML::Template::Pro/;
push @HTML::Template::Expr::ISA, qw/HTML::Template::Pro/;
# Preloaded methods go here.
# internal C library init -- required
_init();
# internal C library unload -- it is better to comment it:
# when process terminates, memory is freed anyway
# but END {} can be called between calls (as SpeedyCGI does)
# END {_done()}
# initialize preset function table
use vars qw(%FUNC);
%FUNC =
(
# note that length,defined,sin,cos,log,tan,... are built-in
'sprintf' => sub { sprintf(shift, @_); },
'substr' => sub {
return substr($_[0], $_[1]) if @_ == 2;
return substr($_[0], $_[1], $_[2]);
},
'lc' => sub { lc($_[0]); },
'lcfirst' => sub { lcfirst($_[0]); },
'uc' => sub { uc($_[0]); },
'ucfirst' => sub { ucfirst($_[0]); },
# 'length' => sub { length($_[0]); },
# 'defined' => sub { defined($_[0]); },
# 'abs' => sub { abs($_[0]); },
# 'hex' => sub { hex($_[0]); },
# 'oct' => sub { oct($_[0]); },
'rand' => sub { rand($_[0]); },
'srand' => sub { srand($_[0]); },
);
sub new {
my $class=shift;
my %param;
my $options={param_map=>\%param,
functions => {},
filter => [],
# ---- supported -------
debug => 0,
max_includes => 10,
global_vars => 0,
no_includes => 0,
search_path_on_include => 0,
loop_context_vars => 0,
path => [],
associate => [],
case_sensitive => 0,
__strict_compatibility => 1,
force_untaint => 0,
# ---- unsupported distinct -------
die_on_bad_params => 0,
strict => 0,
# ---- unsupported -------
# vanguard_compatibility_mode => 0,
#=============================================
# The following options are harmless caching-specific.
# They are ignored silently because there is nothing to cache.
#=============================================
# stack_debug => 0,
# timing => 0,
# cache => 0,
# blind_cache => 0,
# file_cache => 0,
# file_cache_dir => '',
# file_cache_dir_mode => 0700,
# cache_debug => 0,
# shared_cache_debug => 0,
# memory_debug => 0,
# shared_cache => 0,
# double_cache => 0,
# double_file_cache => 0,
# ipc_key => 'TMPL',
# ipc_mode => 0666,
# ipc_segment_size => 65536,
# ipc_max_size => 0,
#============================================
@_};
# make sure taint mode is on if force_untaint flag is set
if ($options->{force_untaint} && ! ${^TAINT}) {
croak("HTML::Template->new() : 'force_untaint' option set but perl does not run in taint mode!");
}
# associate should be an array if it's not already
if (ref($options->{associate}) ne 'ARRAY') {
$options->{associate} = [ $options->{associate} ];
}
# path should be an array if it's not already
if (ref($options->{path}) ne 'ARRAY') {
$options->{path} = [ $options->{path} ];
}
# filter should be an array if it's not already
if (ref($options->{filter}) ne 'ARRAY') {
$options->{filter} = [ $options->{filter} ];
}
my $case_sensitive = $options->{case_sensitive};
my $__strict_compatibility = $options->{__strict_compatibility};
# wrap associated objects into tied hash and
# make sure objects in associate are support param()
$options->{associate} = [
map {HTML::Template::Pro::WrapAssociate->_wrap($_, $case_sensitive, $__strict_compatibility)}
@{$options->{associate}}
];
# check for syntax errors:
my $source_count = 0;
exists($options->{filename}) and $source_count++;
exists($options->{filehandle}) and $source_count++;
exists($options->{arrayref}) and $source_count++;
exists($options->{scalarref}) and $source_count++;
if ($source_count != 1) {
croak("HTML::Template->new called with multiple (or no) template sources specified! A valid call to new() has exactly one filename => 'file' OR exactly one scalarref => \\\$scalar OR exactly one arrayref => \\\@array OR exactly one filehandle => \*FH");
}
if ($options->{arrayref}) {
die "bad value of arrayref" unless UNIVERSAL::isa($_[0], 'ARRAY');
my $template=join('',@{$options->{arrayref}});
$options->{scalarref}=\$template;
}
if ($options->{filehandle}) {
local $/; # enable "slurp" mode
local *FH=$options->{filehandle};
my $template=<FH>;
$options->{scalarref}=\$template;
}
# merging built_in funcs with user-defined funcs
$options->{expr_func}={%FUNC, %{$options->{functions}}};
# hack to be fully compatible with HTML::Template;
# caused serious memory leak. it should be done on XS level, if needed.
# &safe_circular_reference($options,'options') ???
#$options->{options}=$options;
bless $options,$class;
$options->_call_filters($options->{scalarref}) if $options->{scalarref} and @{$options->{filter}};
return $options; # == $self
}
# a few shortcuts to new(), of possible use...
sub new_file {
my $pkg = shift; return $pkg->new('filename', @_);
}
sub new_filehandle {
my $pkg = shift; return $pkg->new('filehandle', @_);
}
sub new_array_ref {
my $pkg = shift; return $pkg->new('arrayref', @_);
}
sub new_scalar_ref {
my $pkg = shift; return $pkg->new('scalarref', @_);
}
sub output {
my $self=shift;
my %oparam=(@_);
my $print_to = $oparam{print_to};
if (defined wantarray && ! $print_to) {
return exec_tmpl_string($self);
} else {
exec_tmpl($self,$print_to);
}
}
sub clear_params {
my $self = shift;
%{$self->{param_map}}=();
}
sub param {
my $self = shift;
#my $options = $self->{options};
my $param_map = $self->{param_map};
# compatibility with HTML::Template
# the one-parameter case - could be a parameter value request or a
# hash-ref.
if (scalar @_==0) {
return keys (%$param_map);
} elsif (scalar @_==1) {
if (ref($_[0]) and UNIVERSAL::isa($_[0], 'HASH')) {
# ref to hash of params --- simply dereference it
return $self->param(%{$_[0]});
} else {
my $key=$self->{case_sensitive} ? $_[0] : lc($_[0]);
return $param_map->{$key} || $param_map->{$_[0]};
}
}
# loop below is obvious but wrong for perl
# while (@_) {$param_map->{shift(@_)}=shift(@_);}
if ($self->{case_sensitive}) {
while (@_) {
my $key=shift;
my $val=shift;
$param_map->{$key}=$val;
}
} else {
while (@_) {
my $key=shift;
my $val=shift;
if (ref($val)) {
if (UNIVERSAL::isa($val, 'ARRAY')) {
$param_map->{lc($key)}=[map {_lowercase_keys($_)} @$val];
} else {
$param_map->{lc($key)}=$val;
}
} else {
$param_map->{lc($key)}=$val;
}
}
}
}
sub register_function {
my($self, $name, $sub) = @_;
if ( ref($sub) eq 'CODE' ) {
if (ref $self) {
# per object call
$self->{expr_func}->{$name} = $sub;
$self->{expr_func_user_list}->{$name} = 1;
} else {
# per class call
$FUNC{$name} = $sub;
}
} elsif ( defined $sub ) {
croak("HTML::Template::Pro : last arg of register_function must be subroutine reference\n")
} else {
if (ref $self) {
if ( defined $name ) {
return $self->{expr_func}->{$name};
} else {
return keys %{ $self->{expr_func_user_list} };
}
} else {
return keys %FUNC;
}
}
}
sub _lowercase_keys {
my $orighash=shift;
my $newhash={};
my ($key,$val);
unless (UNIVERSAL::isa($orighash, 'HASH')) {
Carp::carp "HTML::Template::Pro:_lowercase_keys:in param_tree: found strange parameter $orighash while hash was expected";
return;
}
while (($key,$val)=each %$orighash) {
if (ref($val)) {
if (UNIVERSAL::isa($val, 'ARRAY')) {
$newhash->{lc($key)}=[map {_lowercase_keys($_)} @$val];
} else {
$newhash->{lc($key)}=$val;
}
} else {
$newhash->{lc($key)}=$val;
}
}
return $newhash;
}
# sub _load_file {
# my $filepath=shift;
# open my $fh, $filepath or die $!;
# local $/; # enable localized slurp mode
# my $content = <$fh>;
# close $fh;
# return $content;
# }
## HTML::Template based
#### callback function called from C library ##############
# Note that this _get_filepath perl code is deprecated; ##
# by default built-in find_file implementation is used. ##
# use magic option __use_perl_find_file => 1 to re-enable it.
###########################################################
sub _get_filepath {
my ($self, $filename, $last_visited_file) = @_;
# look for the included file...
my $filepath;
if ((not defined $last_visited_file) or $self->{search_path_on_include}) {
$filepath = $self->_find_file($filename);
} else {
$filepath = $self->_find_file($filename,
[File::Spec->splitdir($last_visited_file)]
);
}
carp "HTML::Template::Pro (using callback): template $filename not found!" unless $filepath;
return $filepath;
}
sub _find_file {
my ($options, $filename, $extra_path) = @_;
my $filepath;
# first check for a full path
return File::Spec->canonpath($filename)
if (File::Spec->file_name_is_absolute($filename) and (-e $filename));
# try the extra_path if one was specified
if (defined($extra_path)) {
$extra_path->[$#{$extra_path}] = $filename;
$filepath = File::Spec->canonpath(File::Spec->catfile(@$extra_path));
return File::Spec->canonpath($filepath) if -e $filepath;
}
# try pre-prending HTML_Template_Root
if (defined($ENV{HTML_TEMPLATE_ROOT})) {
$filepath = File::Spec->catfile($ENV{HTML_TEMPLATE_ROOT}, $filename);
return File::Spec->canonpath($filepath) if -e $filepath;
}
# try "path" option list..
foreach my $path (@{$options->{path}}) {
$filepath = File::Spec->catfile($path, $filename);
return File::Spec->canonpath($filepath) if -e $filepath;
}
# try even a relative path from the current directory...
return File::Spec->canonpath($filename) if -e $filename;
# try "path" option list with HTML_TEMPLATE_ROOT prepended...
if (defined($ENV{HTML_TEMPLATE_ROOT})) {
foreach my $path (@{$options->{path}}) {
$filepath = File::Spec->catfile($ENV{HTML_TEMPLATE_ROOT}, $path, $filename);
return File::Spec->canonpath($filepath) if -e $filepath;
}
}
return undef;
}
sub _load_template {
my $self = shift;
my $filepath=shift;
my $template = "";
confess("HTML::Template->new() : Cannot open file $filepath : $!")
unless defined(open(TEMPLATE, $filepath));
# read into scalar
while (read(TEMPLATE, $template, 10240, length($template))) {}
close(TEMPLATE);
$self->_call_filters(\$template) if @{$self->{filter}};
return \$template;
}
# handle calling user defined filters
sub _call_filters {
my $self = shift;
my $template_ref = shift;
my $options = $self;#->{options};
my ($format, $sub);
foreach my $filter (@{$options->{filter}}) {
croak("HTML::Template->new() : bad value set for filter parameter - must be a code ref or a hash ref.")
unless ref $filter;
# translate into CODE->HASH
$filter = { 'format' => 'scalar', 'sub' => $filter }
if (ref $filter eq 'CODE');
if (ref $filter eq 'HASH') {
$format = $filter->{'format'};
$sub = $filter->{'sub'};
# check types and values
croak("HTML::Template->new() : bad value set for filter parameter - hash must contain \"format\" key and \"sub\" key.")
unless defined $format and defined $sub;
croak("HTML::Template->new() : bad value set for filter parameter - \"format\" must be either 'array' or 'scalar'")
unless $format eq 'array' or $format eq 'scalar';
croak("HTML::Template->new() : bad value set for filter parameter - \"sub\" must be a code ref")
unless ref $sub and ref $sub eq 'CODE';
# catch errors
eval {
if ($format eq 'scalar') {
# call
$sub->($template_ref);
} else {
# modulate
my @array = map { $_."\n" } split("\n", $$template_ref);
# call
$sub->(\@array);
# demodulate
$$template_ref = join("", @array);
}
};
croak("HTML::Template->new() : fatal error occured during filter call: $@") if $@;
} else {
croak("HTML::Template->new() : bad value set for filter parameter - must be code ref or hash ref");
}
}
# all done
return $template_ref;
}
1;
__END__
=head1 NAME
HTML::Template::Pro - Perl/XS module to use HTML Templates from CGI scripts
=head1 SYNOPSIS
It is moved out and split.
See L<HTML::Template::SYNTAX/SYNOPSIS> for introduction
to HTML::Template and syntax of template files.
See L<HTML::Template::PerlInterface/SYNOPSIS> for perl interface
of HTML::Template, HTML::Template::Expr and HTML::Template::Pro.
=head1 DESCRIPTION
Original HTML::Template is written by Sam Tregar, sam@tregar.com
with contributions of many people mentioned there.
Their efforts caused HTML::Template to be mature html tempate engine
which separate perl code and html design.
Yet powerful, HTML::Template is slow, especially if mod_perl isn't
available or in case of disk usage and memory limitations.
HTML::Template::Pro is a fast lightweight C/Perl+XS reimplementation
of HTML::Template (as of 2.9) and HTML::Template::Expr (as of 0.0.7).
It is not intended to be a complete replacement,
but to be a fast implementation of HTML::Template if you don't need
querying, the extended facility of HTML::Template.
Designed for heavy upload, resource limitations, abcence of mod_perl.
HTML::Template::Pro has complete support of filters and HTML::Template::Expr's
tag EXPR="<expression>", including user-defined functions and
construction <TMPL_INCLUDE EXPR="...">.
HTML::Template work cycle uses 2 steps. First, it loads and parse template.
Then it accepts param() calls until you call output().
output() is its second phase where it produces a page from the parsed tree
of template, obtained in the 1st step.
HTML::Template::Pro loads, parse and outputs template on fly,
when you call $tmpl->output(), in one pass. The corresponding code is
written in C and glued to Perl using Perl+XS. As a result,
comparing to HTML::Template in ordinary calls, it runs
10-25 times faster. Comparing to HTML::Template with all caching enabled
under mod_perl, it still 1-3 times faster. At that HTML::Template caching
requires considerable amount of memory (per process, shareable, or on disk)
to be permanently filled with parsed trees, whereas HTML::Template::Pro
don't consumes memory for caches and use mmap() for reading templates on disk.
Introduction to HTML::Template and syntax of template files is described
in L<HTML::Template::SYNTAX>.
Perl interface of HTML::Template and HTML::Template::Pro is described
in L<HTML::Template::PerlInterface>.
=head1 SEE ALSO
L<HTML::Template::SYNTAX>, L<HTML::Template::PerlInterface>.
Progect page is http://html-tmpl-pro.sourceforge.net
(and http://sourceforge.net/projects/html-tmpl-pro)
Original modules are L<HTML::Template>, L<HTML::Template::Expr>.
Their progect page is http://html-template.sourceforge.net
=head1 BUGS
See L<HTML::Template::PerlInterface/BUGS>
=head1 AUTHOR
I. Vlasenko, E<lt>viy@altlinux.orgE<gt>
with contributions of
Bruni Emiliano, E<lt>info at ebruni.itE<gt>
Stanislav Yadykin, E<lt>tosick at altlinux.ruE<gt>
Viacheslav Sheveliov E<lt>slavash at aha.ruE<gt>
Shigeki Morimoto E<lt>shigeki.morimoto at mixi.co.jpE<gt>
Kirill Rebenok E<lt>kirill at rebenok.plE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2005-2009 by I. Yu. Vlasenko.
Pieces of code in Pro.pm and documentation of HTML::Template are
copyright (C) 2000-2002 Sam Tregar (sam@tregar.com)
The template syntax, interface conventions and a large piece of documentation
of HTML::Template::Pro are based on CPAN module HTML::Template
by Sam Tregar, sam@tregar.com.
This library is free software; you can redistribute it and/or modify it under
either the LGPL2+ or under the same terms as Perl itself, either Perl version
5.8.4 or, at your option, any later version of Perl 5 you may have available.
=cut