summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Bundle/Xxv.pm77
-rw-r--r--lib/CGI.pm7318
-rw-r--r--lib/CGI/Apache.pm26
-rw-r--r--lib/CGI/Carp.pm524
-rw-r--r--lib/CGI/Cookie.pm478
-rw-r--r--lib/CGI/Fast.pm230
-rw-r--r--lib/CGI/Pretty.pm275
-rw-r--r--lib/CGI/Push.pm328
-rw-r--r--lib/CGI/Switch.pm27
-rw-r--r--lib/CGI/Util.pm317
-rw-r--r--lib/Config/Tiny.pm248
-rw-r--r--lib/Date/Manip.pm7362
-rw-r--r--lib/Digest/HMAC.pm111
-rw-r--r--lib/Digest/HMAC_MD5.pm71
-rw-r--r--lib/Digest/HMAC_SHA1.pm71
-rw-r--r--lib/GD/Graph/Data.pm725
-rw-r--r--lib/GD/Graph/Error.pm346
-rw-r--r--lib/GD/Graph/FAQ.pod130
-rw-r--r--lib/GD/Graph/area.pm112
-rw-r--r--lib/GD/Graph/axestype3d.pm787
-rw-r--r--lib/GD/Graph/bars.pm372
-rw-r--r--lib/GD/Graph/bars3d.pm349
-rw-r--r--lib/GD/Graph/colour.pm371
-rw-r--r--lib/GD/Graph/cylinder.pm126
-rw-r--r--lib/GD/Graph/cylinder3d.pm30
-rw-r--r--lib/GD/Graph/hbars.pm71
-rw-r--r--lib/GD/Graph/lines.pm182
-rw-r--r--lib/GD/Graph/lines3d.pm522
-rw-r--r--lib/GD/Graph/linespoints.pm46
-rw-r--r--lib/GD/Graph/mixed.pm99
-rw-r--r--lib/GD/Graph/pie.pm446
-rw-r--r--lib/GD/Graph/pie3d.pm331
-rw-r--r--lib/GD/Graph/points.pm183
-rw-r--r--lib/GD/Graph/utils.pm49
-rw-r--r--lib/GD/Graph3d.pm157
-rw-r--r--lib/HTML/TextToHTML.pm5266
-rw-r--r--lib/MP3/Info.pm1563
-rw-r--r--lib/Mail/SendEasy.pm6
-rw-r--r--lib/Net/Amazon.pm1255
-rw-r--r--lib/Net/Amazon/Attribute/Review.pm104
-rw-r--r--lib/Net/Amazon/Attribute/ReviewSet.pm137
-rw-r--r--lib/Net/Amazon/Property.pm320
-rw-r--r--lib/Net/Amazon/Property/Book.pm152
-rw-r--r--lib/Net/Amazon/Property/DVD.pm156
-rw-r--r--lib/Net/Amazon/Property/Music.pm161
-rw-r--r--lib/Net/Amazon/Request.pm221
-rw-r--r--lib/Net/Amazon/Request/ASIN.pm139
-rw-r--r--lib/Net/Amazon/Request/Artist.pm86
-rw-r--r--lib/Net/Amazon/Request/Blended.pm80
-rw-r--r--lib/Net/Amazon/Request/BrowseNode.pm137
-rw-r--r--lib/Net/Amazon/Request/Exchange.pm91
-rw-r--r--lib/Net/Amazon/Request/Keyword.pm90
-rw-r--r--lib/Net/Amazon/Request/Manufacturer.pm78
-rw-r--r--lib/Net/Amazon/Request/Power.pm95
-rw-r--r--lib/Net/Amazon/Request/Seller.pm84
-rw-r--r--lib/Net/Amazon/Request/Similar.pm95
-rw-r--r--lib/Net/Amazon/Request/Sort.pm246
-rw-r--r--lib/Net/Amazon/Request/TextStream.pm76
-rw-r--r--lib/Net/Amazon/Request/UPC.pm94
-rw-r--r--lib/Net/Amazon/Request/Wishlist.pm89
-rw-r--r--lib/Net/Amazon/Response.pm214
-rw-r--r--lib/Net/Amazon/Response/ASIN.pm28
-rw-r--r--lib/Net/Amazon/Response/Artist.pm29
-rw-r--r--lib/Net/Amazon/Response/Blended.pm73
-rw-r--r--lib/Net/Amazon/Response/BrowseNode.pm29
-rw-r--r--lib/Net/Amazon/Response/Exchange.pm81
-rw-r--r--lib/Net/Amazon/Response/Keyword.pm29
-rw-r--r--lib/Net/Amazon/Response/Manufacturer.pm29
-rw-r--r--lib/Net/Amazon/Response/Power.pm28
-rw-r--r--lib/Net/Amazon/Response/Seller.pm78
-rw-r--r--lib/Net/Amazon/Response/Similar.pm28
-rw-r--r--lib/Net/Amazon/Response/TextStream.pm28
-rw-r--r--lib/Net/Amazon/Response/UPC.pm40
-rw-r--r--lib/Net/Amazon/Response/Wishlist.pm29
-rw-r--r--lib/Net/Amazon/Result/Seller.pm130
-rw-r--r--lib/Net/Amazon/Result/Seller/Listing.pm146
-rw-r--r--lib/Template.pm961
-rw-r--r--lib/Template/Base.pm314
-rw-r--r--lib/Template/Config.pm467
-rw-r--r--lib/Template/Constants.pm287
-rw-r--r--lib/Template/Context.pm1570
-rw-r--r--lib/Template/Directive.pm1004
-rw-r--r--lib/Template/Document.pm492
-rw-r--r--lib/Template/Exception.pm254
-rw-r--r--lib/Template/FAQ.pod329
-rw-r--r--lib/Template/Filters.pm1448
-rw-r--r--lib/Template/Grammar.pm6179
-rw-r--r--lib/Template/Iterator.pm456
-rw-r--r--lib/Template/Library/HTML.pod316
-rw-r--r--lib/Template/Library/PostScript.pod78
-rw-r--r--lib/Template/Library/Splash.pod1030
-rw-r--r--lib/Template/Manual.pod180
-rw-r--r--lib/Template/Manual/Config.pod2122
-rw-r--r--lib/Template/Manual/Credits.pod188
-rw-r--r--lib/Template/Manual/Directives.pod2179
-rw-r--r--lib/Template/Manual/Filters.pod529
-rw-r--r--lib/Template/Manual/Internals.pod556
-rw-r--r--lib/Template/Manual/Intro.pod295
-rw-r--r--lib/Template/Manual/Plugins.pod552
-rw-r--r--lib/Template/Manual/Refs.pod171
-rw-r--r--lib/Template/Manual/Syntax.pod306
-rw-r--r--lib/Template/Manual/VMethods.pod529
-rw-r--r--lib/Template/Manual/Variables.pod868
-rw-r--r--lib/Template/Manual/Views.pod642
-rw-r--r--lib/Template/Modules.pod448
-rw-r--r--lib/Template/Namespace/Constants.pm205
-rw-r--r--lib/Template/Parser.pm1446
-rw-r--r--lib/Template/Plugin.pm409
-rw-r--r--lib/Template/Plugin/Autoformat.pm242
-rw-r--r--lib/Template/Plugin/CGI.pm168
-rw-r--r--lib/Template/Plugin/DBI.pm947
-rw-r--r--lib/Template/Plugin/Datafile.pm198
-rw-r--r--lib/Template/Plugin/Date.pm361
-rw-r--r--lib/Template/Plugin/Directory.pm410
-rw-r--r--lib/Template/Plugin/Dumper.pm179
-rw-r--r--lib/Template/Plugin/File.pm416
-rw-r--r--lib/Template/Plugin/Filter.pm436
-rw-r--r--lib/Template/Plugin/Format.pm124
-rw-r--r--lib/Template/Plugin/GD/Constants.pm138
-rw-r--r--lib/Template/Plugin/GD/Graph/area.pm148
-rw-r--r--lib/Template/Plugin/GD/Graph/bars.pm191
-rw-r--r--lib/Template/Plugin/GD/Graph/bars3d.pm166
-rw-r--r--lib/Template/Plugin/GD/Graph/lines.pm178
-rw-r--r--lib/Template/Plugin/GD/Graph/lines3d.pm166
-rw-r--r--lib/Template/Plugin/GD/Graph/linespoints.pm158
-rw-r--r--lib/Template/Plugin/GD/Graph/mixed.pm176
-rw-r--r--lib/Template/Plugin/GD/Graph/pie.pm141
-rw-r--r--lib/Template/Plugin/GD/Graph/pie3d.pm145
-rw-r--r--lib/Template/Plugin/GD/Graph/points.pm155
-rw-r--r--lib/Template/Plugin/GD/Image.pm184
-rw-r--r--lib/Template/Plugin/GD/Polygon.pm155
-rw-r--r--lib/Template/Plugin/GD/Text.pm140
-rw-r--r--lib/Template/Plugin/GD/Text/Align.pm147
-rw-r--r--lib/Template/Plugin/GD/Text/Wrap.pm183
-rw-r--r--lib/Template/Plugin/HTML.pm197
-rw-r--r--lib/Template/Plugin/Image.pm425
-rw-r--r--lib/Template/Plugin/Iterator.pm118
-rw-r--r--lib/Template/Plugin/Pod.pm116
-rw-r--r--lib/Template/Plugin/Procedural.pm170
-rw-r--r--lib/Template/Plugin/String.pm796
-rw-r--r--lib/Template/Plugin/Table.pm464
-rw-r--r--lib/Template/Plugin/URL.pm236
-rw-r--r--lib/Template/Plugin/View.pm127
-rw-r--r--lib/Template/Plugin/Wrap.pm162
-rw-r--r--lib/Template/Plugin/XML/DOM.pm841
-rw-r--r--lib/Template/Plugin/XML/RSS.pm194
-rw-r--r--lib/Template/Plugin/XML/Simple.pm124
-rw-r--r--lib/Template/Plugin/XML/Style.pm357
-rw-r--r--lib/Template/Plugin/XML/XPath.pm284
-rw-r--r--lib/Template/Plugins.pm1041
-rw-r--r--lib/Template/Provider.pm1449
-rw-r--r--lib/Template/Service.pm775
-rw-r--r--lib/Template/Stash.pm1040
-rw-r--r--lib/Template/Stash/Context.pm791
-rw-r--r--lib/Template/Stash/XS.pm176
-rw-r--r--lib/Template/Test.pm711
-rw-r--r--lib/Template/Tools/tpage.pod76
-rw-r--r--lib/Template/Tools/ttree.pod332
-rw-r--r--lib/Template/Tutorial.pod109
-rw-r--r--lib/Template/Tutorial/Datafile.pod461
-rw-r--r--lib/Template/Tutorial/Web.pod801
-rw-r--r--lib/Template/View.pm752
-rw-r--r--lib/Text/Wrap.pm106
-rw-r--r--lib/URI.pm1019
-rw-r--r--lib/URI/Escape.pm218
-rw-r--r--lib/URI/Heuristic.pm224
-rw-r--r--lib/URI/QueryParam.pm200
-rw-r--r--lib/URI/Split.pm96
-rw-r--r--lib/URI/URL.pm305
-rw-r--r--lib/URI/WithBase.pm171
-rw-r--r--lib/URI/_foreign.pm6
-rw-r--r--lib/URI/_generic.pm249
-rw-r--r--lib/URI/_ldap.pm140
-rw-r--r--lib/URI/_login.pm10
-rw-r--r--lib/URI/_query.pm81
-rw-r--r--lib/URI/_segment.pm20
-rw-r--r--lib/URI/_server.pm106
-rw-r--r--lib/URI/_userpass.pm51
-rw-r--r--lib/URI/data.pm139
-rw-r--r--lib/URI/file.pm329
-rw-r--r--lib/URI/file/Base.pm80
-rw-r--r--lib/URI/file/FAT.pm23
-rw-r--r--lib/URI/file/Mac.pm120
-rw-r--r--lib/URI/file/OS2.pm28
-rw-r--r--lib/URI/file/QNX.pm18
-rw-r--r--lib/URI/file/Unix.pm55
-rw-r--r--lib/URI/file/Win32.pm84
-rw-r--r--lib/URI/ftp.pm45
-rw-r--r--lib/URI/gopher.pm94
-rw-r--r--lib/URI/http.pm25
-rw-r--r--lib/URI/https.pm7
-rw-r--r--lib/URI/ldap.pm122
-rw-r--r--lib/URI/ldapi.pm30
-rw-r--r--lib/URI/ldaps.pm7
-rw-r--r--lib/URI/mailto.pm72
-rw-r--r--lib/URI/mms.pm8
-rw-r--r--lib/URI/news.pm68
-rw-r--r--lib/URI/nntp.pm6
-rw-r--r--lib/URI/pop.pm68
-rw-r--r--lib/URI/rlogin.pm7
-rw-r--r--lib/URI/rsync.pm12
-rw-r--r--lib/URI/rtsp.pm8
-rw-r--r--lib/URI/rtspu.pm8
-rw-r--r--lib/URI/sip.pm86
-rw-r--r--lib/URI/sips.pm7
-rw-r--r--lib/URI/snews.pm8
-rw-r--r--lib/URI/ssh.pm9
-rw-r--r--lib/URI/telnet.pm7
-rw-r--r--lib/URI/tn3270.pm7
-rw-r--r--lib/URI/urn.pm97
-rw-r--r--lib/URI/urn/isbn.pm58
-rw-r--r--lib/URI/urn/oid.pm18
-rw-r--r--lib/XML/Dumper.pm897
-rw-r--r--lib/XML/Simple.pm3041
-rw-r--r--lib/XML/Stream.pm3268
-rw-r--r--lib/XML/Stream/Namespace.pm190
-rw-r--r--lib/XML/Stream/Node.pm944
-rw-r--r--lib/XML/Stream/Parser.pm567
-rw-r--r--lib/XML/Stream/Parser/DTD.pm769
-rw-r--r--lib/XML/Stream/Tree.pm682
-rw-r--r--lib/XML/Stream/XPath.pm50
-rw-r--r--lib/XML/Stream/XPath/Op.pm919
-rw-r--r--lib/XML/Stream/XPath/Query.pm374
-rw-r--r--lib/XML/Stream/XPath/Value.pm153
-rw-r--r--lib/XXV/MODULES/CONFIG.pm2
-rw-r--r--lib/XXV/MODULES/TELNET.pm3
-rw-r--r--lib/XXV/OUTPUT/Console.pm9
-rw-r--r--lib/XXV/OUTPUT/Html.pm6
-rw-r--r--lib/XXV/OUTPUT/Wml.pm2
229 files changed, 43 insertions, 97319 deletions
diff --git a/lib/Bundle/Xxv.pm b/lib/Bundle/Xxv.pm
index 411e679..a881441 100644
--- a/lib/Bundle/Xxv.pm
+++ b/lib/Bundle/Xxv.pm
@@ -2,7 +2,7 @@ package Bundle::Xxv;
use strict;
use warnings;
-$VERSION = '0.04';
+$VERSION = '1.0';
1;
@@ -20,55 +20,38 @@ Bundle::Xxv - A bundle to install various xxv related modules
=head1 CONTENTS
-Test::Simple - Test package to test varios funktion
-DBI - Database package for perl
-DBD::mysql - Database driver to connect over DBI
+CGI
+Compress::Zlib
Config::Tiny
-Event - the great famos Event libary
-MIME::Base64 - Code library to encrypt and decrypt Strings
-Time::HiRes - High Resolutin timer
-Locale::gettext - Localization in perl
-Net::Telnet
-URI
-URI::file
-URI::URL
-Compress::Zlib - for compressed output
-HTML::Tagset
-HTML::Parser
-HTML::Form
-HTTP::Status
-HTTP::Daemon
-HTTP::Request
-LWP::UserAgent
-LWP
-WWW::Mechanize - for Robot Module
-Data::Random
-WWW::Mechanize::FormFiller
-GD - GD Image library
-Digest::SHA1
-Digest::HMAC_MD5
+Data::Dumper
+Date::Manip
+DBD::mysql
+DBI
Digest::MD5
-Net::IP
-Net::DNS
-XML::Parser
-XML::RSS - create an rss feed
-Math::BigInt::FastCalc
-Authen::SASL
-XML::Stream
-Net::XMPP - create an Jabber message
-Proc::Killfam - killall for Perl
-Proc::ProcessTable
-Term::ReadLine::Gnu - Better Support for telnet interface
-Template
-SOAP::Lite
-MP3::Icecast
-MP3::Info
-CGI
-LWP::Simple
-Net::Amazon
+Digest::HMAC_MD5
+Event
+GD
+Getopt::Long
+HTML::TextToHTML
+HTML::TreeBuilder
+JSON
+LWP::Simple
+LWP::UserAgent
+Locale::gettext
+MIME::Base64
+MP3::Info
+Net::Amazon
Net::Amazon::Request::Artist
-JSON - Parse and convert to JSON (JavaScript Object Notation)
-
+Net::Telnet
+Net::XMPP
+SOAP::Lite
+SOAP::Transport::HTTP
+Template
+Time::Local
+Time::HiRes
+URI::Escape
+XML::RSS
+XML::Simple
=head1 DESCRIPTION
diff --git a/lib/CGI.pm b/lib/CGI.pm
deleted file mode 100644
index 148b861..0000000
--- a/lib/CGI.pm
+++ /dev/null
@@ -1,7318 +0,0 @@
-package CGI;
-require 5.004;
-use Carp 'croak';
-
-# See the bottom of this file for the POD documentation. Search for the
-# string '=head'.
-
-# You can run this file through either pod2man or pod2html to produce pretty
-# documentation in manual or html file format (these utilities are part of the
-# Perl 5 distribution).
-
-# Copyright 1995-1998 Lincoln D. Stein. All rights reserved.
-# It may be used and modified freely, but I do request that this copyright
-# notice remain attached to the file. You may modify this module as you
-# wish, but if you redistribute a modified version, please attach a note
-# listing the modifications you have made.
-
-# The most recent version and complete docs are available at:
-# http://stein.cshl.org/WWW/software/CGI/
-
-$CGI::revision = '$Id: CGI.pm,v 1.165 2004/04/12 20:37:26 lstein Exp $';
-$CGI::VERSION=3.05;
-
-# HARD-CODED LOCATION FOR FILE UPLOAD TEMPORARY FILES.
-# UNCOMMENT THIS ONLY IF YOU KNOW WHAT YOU'RE DOING.
-# $CGITempFile::TMPDIRECTORY = '/usr/tmp';
-use CGI::Util qw(rearrange make_attributes unescape escape expires ebcdic2ascii ascii2ebcdic);
-
-#use constant XHTML_DTD => ['-//W3C//DTD XHTML Basic 1.0//EN',
-# 'http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd'];
-
-use constant XHTML_DTD => ['-//W3C//DTD XHTML 1.0 Transitional//EN',
- 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'];
-
-{
- local $^W = 0;
- $TAINTED = substr("$0$^X",0,0);
-}
-
-$MOD_PERL = 0; # no mod_perl by default
-@SAVED_SYMBOLS = ();
-
-# >>>>> Here are some globals that you might want to adjust <<<<<<
-sub initialize_globals {
- # Set this to 1 to enable copious autoloader debugging messages
- $AUTOLOAD_DEBUG = 0;
-
- # Set this to 1 to generate XTML-compatible output
- $XHTML = 1;
-
- # Change this to the preferred DTD to print in start_html()
- # or use default_dtd('text of DTD to use');
- $DEFAULT_DTD = [ '-//W3C//DTD HTML 4.01 Transitional//EN',
- 'http://www.w3.org/TR/html4/loose.dtd' ] ;
-
- # Set this to 1 to enable NOSTICKY scripts
- # or:
- # 1) use CGI qw(-nosticky)
- # 2) $CGI::nosticky(1)
- $NOSTICKY = 0;
-
- # Set this to 1 to enable NPH scripts
- # or:
- # 1) use CGI qw(-nph)
- # 2) CGI::nph(1)
- # 3) print header(-nph=>1)
- $NPH = 0;
-
- # Set this to 1 to enable debugging from @ARGV
- # Set to 2 to enable debugging from STDIN
- $DEBUG = 1;
-
- # Set this to 1 to make the temporary files created
- # during file uploads safe from prying eyes
- # or do...
- # 1) use CGI qw(:private_tempfiles)
- # 2) CGI::private_tempfiles(1);
- $PRIVATE_TEMPFILES = 0;
-
- # Set this to 1 to cause files uploaded in multipart documents
- # to be closed, instead of caching the file handle
- # or:
- # 1) use CGI qw(:close_upload_files)
- # 2) $CGI::close_upload_files(1);
- # Uploads with many files run out of file handles.
- # Also, for performance, since the file is already on disk,
- # it can just be renamed, instead of read and written.
- $CLOSE_UPLOAD_FILES = 0;
-
- # Set this to a positive value to limit the size of a POSTing
- # to a certain number of bytes:
- $POST_MAX = -1;
-
- # Change this to 1 to disable uploads entirely:
- $DISABLE_UPLOADS = 0;
-
- # Automatically determined -- don't change
- $EBCDIC = 0;
-
- # Change this to 1 to suppress redundant HTTP headers
- $HEADERS_ONCE = 0;
-
- # separate the name=value pairs by semicolons rather than ampersands
- $USE_PARAM_SEMICOLONS = 1;
-
- # Do not include undefined params parsed from query string
- # use CGI qw(-no_undef_params);
- $NO_UNDEF_PARAMS = 0;
-
- # Other globals that you shouldn't worry about.
- undef $Q;
- $BEEN_THERE = 0;
- $DTD_PUBLIC_IDENTIFIER = "";
- undef @QUERY_PARAM;
- undef %EXPORT;
- undef $QUERY_CHARSET;
- undef %QUERY_FIELDNAMES;
-
- # prevent complaints by mod_perl
- 1;
-}
-
-# ------------------ START OF THE LIBRARY ------------
-
-*end_form = \&endform;
-
-# make mod_perlhappy
-initialize_globals();
-
-# FIGURE OUT THE OS WE'RE RUNNING UNDER
-# Some systems support the $^O variable. If not
-# available then require() the Config library
-unless ($OS) {
- unless ($OS = $^O) {
- require Config;
- $OS = $Config::Config{'osname'};
- }
-}
-if ($OS =~ /^MSWin/i) {
- $OS = 'WINDOWS';
-} elsif ($OS =~ /^VMS/i) {
- $OS = 'VMS';
-} elsif ($OS =~ /^dos/i) {
- $OS = 'DOS';
-} elsif ($OS =~ /^MacOS/i) {
- $OS = 'MACINTOSH';
-} elsif ($OS =~ /^os2/i) {
- $OS = 'OS2';
-} elsif ($OS =~ /^epoc/i) {
- $OS = 'EPOC';
-} elsif ($OS =~ /^cygwin/i) {
- $OS = 'CYGWIN';
-} else {
- $OS = 'UNIX';
-}
-
-# Some OS logic. Binary mode enabled on DOS, NT and VMS
-$needs_binmode = $OS=~/^(WINDOWS|DOS|OS2|MSWin|CYGWIN)/;
-
-# This is the default class for the CGI object to use when all else fails.
-$DefaultClass = 'CGI' unless defined $CGI::DefaultClass;
-
-# This is where to look for autoloaded routines.
-$AutoloadClass = $DefaultClass unless defined $CGI::AutoloadClass;
-
-# The path separator is a slash, backslash or semicolon, depending
-# on the paltform.
-$SL = {
- UNIX => '/', OS2 => '\\', EPOC => '/', CYGWIN => '/',
- WINDOWS => '\\', DOS => '\\', MACINTOSH => ':', VMS => '/'
- }->{$OS};
-
-# This no longer seems to be necessary
-# Turn on NPH scripts by default when running under IIS server!
-# $NPH++ if defined($ENV{'SERVER_SOFTWARE'}) && $ENV{'SERVER_SOFTWARE'}=~/IIS/;
-$IIS++ if defined($ENV{'SERVER_SOFTWARE'}) && $ENV{'SERVER_SOFTWARE'}=~/IIS/;
-
-# Turn on special checking for Doug MacEachern's modperl
-if (exists $ENV{MOD_PERL}) {
- eval "require mod_perl";
- # mod_perl handlers may run system() on scripts using CGI.pm;
- # Make sure so we don't get fooled by inherited $ENV{MOD_PERL}
- if (defined $mod_perl::VERSION) {
- if ($mod_perl::VERSION >= 1.99) {
- $MOD_PERL = 2;
- require Apache::Response;
- require Apache::RequestRec;
- require Apache::RequestUtil;
- require APR::Pool;
- } else {
- $MOD_PERL = 1;
- require Apache;
- }
- }
-}
-
-# Turn on special checking for ActiveState's PerlEx
-$PERLEX++ if defined($ENV{'GATEWAY_INTERFACE'}) && $ENV{'GATEWAY_INTERFACE'} =~ /^CGI-PerlEx/;
-
-# Define the CRLF sequence. I can't use a simple "\r\n" because the meaning
-# of "\n" is different on different OS's (sometimes it generates CRLF, sometimes LF
-# and sometimes CR). The most popular VMS web server
-# doesn't accept CRLF -- instead it wants a LR. EBCDIC machines don't
-# use ASCII, so \015\012 means something different. I find this all
-# really annoying.
-$EBCDIC = "\t" ne "\011";
-if ($OS eq 'VMS') {
- $CRLF = "\n";
-} elsif ($EBCDIC) {
- $CRLF= "\r\n";
-} else {
- $CRLF = "\015\012";
-}
-
-if ($needs_binmode) {
- $CGI::DefaultClass->binmode(\*main::STDOUT);
- $CGI::DefaultClass->binmode(\*main::STDIN);
- $CGI::DefaultClass->binmode(\*main::STDERR);
-}
-
-%EXPORT_TAGS = (
- ':html2'=>['h1'..'h6',qw/p br hr ol ul li dl dt dd menu code var strong em
- tt u i b blockquote pre img a address cite samp dfn html head
- base body Link nextid title meta kbd start_html end_html
- input Select option comment charset escapeHTML/],
- ':html3'=>[qw/div table caption th td TR Tr sup Sub strike applet Param
- embed basefont style span layer ilayer font frameset frame script small big Area Map/],
- ':html4'=>[qw/abbr acronym bdo col colgroup del fieldset iframe
- ins label legend noframes noscript object optgroup Q
- thead tbody tfoot/],
- ':netscape'=>[qw/blink fontsize center/],
- ':form'=>[qw/textfield textarea filefield password_field hidden checkbox checkbox_group
- submit reset defaults radio_group popup_menu button autoEscape
- scrolling_list image_button start_form end_form startform endform
- start_multipart_form end_multipart_form isindex tmpFileName uploadInfo URL_ENCODED MULTIPART/],
- ':cgi'=>[qw/param upload path_info path_translated url self_url script_name cookie Dump
- raw_cookie request_method query_string Accept user_agent remote_host content_type
- remote_addr referer server_name server_software server_port server_protocol virtual_port
- virtual_host remote_ident auth_type http append
- save_parameters restore_parameters param_fetch
- remote_user user_name header redirect import_names put
- Delete Delete_all url_param cgi_error/],
- ':ssl' => [qw/https/],
- ':cgi-lib' => [qw/ReadParse PrintHeader HtmlTop HtmlBot SplitParam Vars/],
- ':html' => [qw/:html2 :html3 :html4 :netscape/],
- ':standard' => [qw/:html2 :html3 :html4 :form :cgi/],
- ':push' => [qw/multipart_init multipart_start multipart_end multipart_final/],
- ':all' => [qw/:html2 :html3 :netscape :form :cgi :internal :html4/]
- );
-
-# to import symbols into caller
-sub import {
- my $self = shift;
-
- # This causes modules to clash.
- undef %EXPORT_OK;
- undef %EXPORT;
-
- $self->_setup_symbols(@_);
- my ($callpack, $callfile, $callline) = caller;
-
- # To allow overriding, search through the packages
- # Till we find one in which the correct subroutine is defined.
- my @packages = ($self,@{"$self\:\:ISA"});
- foreach $sym (keys %EXPORT) {
- my $pck;
- my $def = ${"$self\:\:AutoloadClass"} || $DefaultClass;
- foreach $pck (@packages) {
- if (defined(&{"$pck\:\:$sym"})) {
- $def = $pck;
- last;
- }
- }
- *{"${callpack}::$sym"} = \&{"$def\:\:$sym"};
- }
-}
-
-sub compile {
- my $pack = shift;
- $pack->_setup_symbols('-compile',@_);
-}
-
-sub expand_tags {
- my($tag) = @_;
- return ("start_$1","end_$1") if $tag=~/^(?:\*|start_|end_)(.+)/;
- my(@r);
- return ($tag) unless $EXPORT_TAGS{$tag};
- foreach (@{$EXPORT_TAGS{$tag}}) {
- push(@r,&expand_tags($_));
- }
- return @r;
-}
-
-#### Method: new
-# The new routine. This will check the current environment
-# for an existing query string, and initialize itself, if so.
-####
-sub new {
- my($class,@initializer) = @_;
- my $self = {};
-
- bless $self,ref $class || $class || $DefaultClass;
- if (ref($initializer[0])
- && (UNIVERSAL::isa($initializer[0],'Apache')
- ||
- UNIVERSAL::isa($initializer[0],'Apache::RequestRec')
- )) {
- $self->r(shift @initializer);
- }
- if (ref($initializer[0])
- && (UNIVERSAL::isa($initializer[0],'CODE'))) {
- $self->upload_hook(shift @initializer, shift @initializer);
- }
- if ($MOD_PERL) {
- $self->r(Apache->request) unless $self->r;
- my $r = $self->r;
- if ($MOD_PERL == 1) {
- $r->register_cleanup(\&CGI::_reset_globals);
- }
- else {
- # XXX: once we have the new API
- # will do a real PerlOptions -SetupEnv check
- $r->subprocess_env unless exists $ENV{REQUEST_METHOD};
- $r->pool->cleanup_register(\&CGI::_reset_globals);
- }
- undef $NPH;
- }
- $self->_reset_globals if $PERLEX;
- $self->init(@initializer);
- return $self;
-}
-
-# We provide a DESTROY method so that we can ensure that
-# temporary files are closed (via Fh->DESTROY) before they
-# are unlinked (via CGITempFile->DESTROY) because it is not
-# possible to unlink an open file on Win32. We explicitly
-# call DESTROY on each, rather than just undefing them and
-# letting Perl DESTROY them by garbage collection, in case the
-# user is still holding any reference to them as well.
-sub DESTROY {
- my $self = shift;
- foreach my $href (values %{$self->{'.tmpfiles'}}) {
- $href->{hndl}->DESTROY if defined $href->{hndl};
- $href->{name}->DESTROY if defined $href->{name};
- }
-}
-
-sub r {
- my $self = shift;
- my $r = $self->{'.r'};
- $self->{'.r'} = shift if @_;
- $r;
-}
-
-sub upload_hook {
- my ($self,$hook,$data) = self_or_default(@_);
- $self->{'.upload_hook'} = $hook;
- $self->{'.upload_data'} = $data;
-}
-
-#### Method: param
-# Returns the value(s)of a named parameter.
-# If invoked in a list context, returns the
-# entire list. Otherwise returns the first
-# member of the list.
-# If name is not provided, return a list of all
-# the known parameters names available.
-# If more than one argument is provided, the
-# second and subsequent arguments are used to
-# set the value of the parameter.
-####
-sub param {
- my($self,@p) = self_or_default(@_);
- return $self->all_parameters unless @p;
- my($name,$value,@other);
-
- # For compatibility between old calling style and use_named_parameters() style,
- # we have to special case for a single parameter present.
- if (@p > 1) {
- ($name,$value,@other) = rearrange([NAME,[DEFAULT,VALUE,VALUES]],@p);
- my(@values);
-
- if (substr($p[0],0,1) eq '-') {
- @values = defined($value) ? (ref($value) && ref($value) eq 'ARRAY' ? @{$value} : $value) : ();
- } else {
- foreach ($value,@other) {
- push(@values,$_) if defined($_);
- }
- }
- # If values is provided, then we set it.
- if (@values) {
- $self->add_parameter($name);
- $self->{$name}=[@values];
- }
- } else {
- $name = $p[0];
- }
-
- return unless defined($name) && $self->{$name};
- return wantarray ? @{$self->{$name}} : $self->{$name}->[0];
-}
-
-sub self_or_default {
- return @_ if defined($_[0]) && (!ref($_[0])) &&($_[0] eq 'CGI');
- unless (defined($_[0]) &&
- (ref($_[0]) eq 'CGI' || UNIVERSAL::isa($_[0],'CGI')) # slightly optimized for common case
- ) {
- $Q = $CGI::DefaultClass->new unless defined($Q);
- unshift(@_,$Q);
- }
- return wantarray ? @_ : $Q;
-}
-
-sub self_or_CGI {
- local $^W=0; # prevent a warning
- if (defined($_[0]) &&
- (substr(ref($_[0]),0,3) eq 'CGI'
- || UNIVERSAL::isa($_[0],'CGI'))) {
- return @_;
- } else {
- return ($DefaultClass,@_);
- }
-}
-
-########################################
-# THESE METHODS ARE MORE OR LESS PRIVATE
-# GO TO THE __DATA__ SECTION TO SEE MORE
-# PUBLIC METHODS
-########################################
-
-# Initialize the query object from the environment.
-# If a parameter list is found, this object will be set
-# to an associative array in which parameter names are keys
-# and the values are stored as lists
-# If a keyword list is found, this method creates a bogus
-# parameter list with the single parameter 'keywords'.
-
-sub init {
- my $self = shift;
- my($query_string,$meth,$content_length,$fh,@lines) = ('','','','');
-
- my $initializer = shift; # for backward compatibility
- local($/) = "\n";
-
- # set autoescaping on by default
- $self->{'escape'} = 1;
-
- # if we get called more than once, we want to initialize
- # ourselves from the original query (which may be gone
- # if it was read from STDIN originally.)
- if (defined(@QUERY_PARAM) && !defined($initializer)) {
- foreach (@QUERY_PARAM) {
- $self->param('-name'=>$_,'-value'=>$QUERY_PARAM{$_});
- }
- $self->charset($QUERY_CHARSET);
- $self->{'.fieldnames'} = {%QUERY_FIELDNAMES};
- return;
- }
-
- $meth=$ENV{'REQUEST_METHOD'} if defined($ENV{'REQUEST_METHOD'});
- $content_length = defined($ENV{'CONTENT_LENGTH'}) ? $ENV{'CONTENT_LENGTH'} : 0;
-
- $fh = to_filehandle($initializer) if $initializer;
-
- # set charset to the safe ISO-8859-1
- $self->charset('ISO-8859-1');
-
- METHOD: {
-
- # avoid unreasonably large postings
- if (($POST_MAX > 0) && ($content_length > $POST_MAX)) {
- # quietly read and discard the post
- my $buffer;
- my $max = $content_length;
- while ($max > 0 &&
- (my $bytes = $MOD_PERL
- ? $self->r->read($buffer,$max < 10000 ? $max : 10000)
- : read(STDIN,$buffer,$max < 10000 ? $max : 10000)
- )) {
- $self->cgi_error("413 Request entity too large");
- last METHOD;
- }
- }
-
- # Process multipart postings, but only if the initializer is
- # not defined.
- if ($meth eq 'POST'
- && defined($ENV{'CONTENT_TYPE'})
- && $ENV{'CONTENT_TYPE'}=~m|^multipart/form-data|
- && !defined($initializer)
- ) {
- my($boundary) = $ENV{'CONTENT_TYPE'} =~ /boundary=\"?([^\";,]+)\"?/;
- $self->read_multipart($boundary,$content_length);
- last METHOD;
- }
-
- # If initializer is defined, then read parameters
- # from it.
- if (defined($initializer)) {
- if (UNIVERSAL::isa($initializer,'CGI')) {
- $query_string = $initializer->query_string;
- last METHOD;
- }
- if (ref($initializer) && ref($initializer) eq 'HASH') {
- foreach (keys %$initializer) {
- $self->param('-name'=>$_,'-value'=>$initializer->{$_});
- }
- last METHOD;
- }
-
- if (defined($fh) && ($fh ne '')) {
- while (<$fh>) {
- chomp;
- last if /^=/;
- push(@lines,$_);
- }
- # massage back into standard format
- if ("@lines" =~ /=/) {
- $query_string=join("&",@lines);
- } else {
- $query_string=join("+",@lines);
- }
- last METHOD;
- }
-
- if (defined($fh) && ($fh ne '')) {
- while (<$fh>) {
- chomp;
- last if /^=/;
- push(@lines,$_);
- }
- # massage back into standard format
- if ("@lines" =~ /=/) {
- $query_string=join("&",@lines);
- } else {
- $query_string=join("+",@lines);
- }
- last METHOD;
- }
-
- # last chance -- treat it as a string
- $initializer = $$initializer if ref($initializer) eq 'SCALAR';
- $query_string = $initializer;
-
- last METHOD;
- }
-
- # If method is GET or HEAD, fetch the query from
- # the environment.
- if ($meth=~/^(GET|HEAD)$/) {
- if ($MOD_PERL) {
- $query_string = $self->r->args;
- } else {
- $query_string = $ENV{'QUERY_STRING'} if defined $ENV{'QUERY_STRING'};
- $query_string ||= $ENV{'REDIRECT_QUERY_STRING'} if defined $ENV{'REDIRECT_QUERY_STRING'};
- }
- last METHOD;
- }
-
- if ($meth eq 'POST') {
- $self->read_from_client(\$query_string,$content_length,0)
- if $content_length > 0;
- # Some people want to have their cake and eat it too!
- # Uncomment this line to have the contents of the query string
- # APPENDED to the POST data.
- # $query_string .= (length($query_string) ? '&' : '') . $ENV{'QUERY_STRING'} if defined $ENV{'QUERY_STRING'};
- last METHOD;
- }
-
- # If $meth is not of GET, POST or HEAD, assume we're being debugged offline.
- # Check the command line and then the standard input for data.
- # We use the shellwords package in order to behave the way that
- # UN*X programmers expect.
- if ($DEBUG)
- {
- my $cmdline_ret = read_from_cmdline();
- $query_string = $cmdline_ret->{'query_string'};
- if (defined($cmdline_ret->{'subpath'}))
- {
- $self->path_info($cmdline_ret->{'subpath'});
- }
- }
- }
-
-# YL: Begin Change for XML handler 10/19/2001
- if ($meth eq 'POST'
- && defined($ENV{'CONTENT_TYPE'})
- && $ENV{'CONTENT_TYPE'} !~ m|^application/x-www-form-urlencoded|
- && $ENV{'CONTENT_TYPE'} !~ m|^multipart/form-data| ) {
- my($param) = 'POSTDATA' ;
- $self->add_parameter($param) ;
- push (@{$self->{$param}},$query_string);
- undef $query_string ;
- }
-# YL: End Change for XML handler 10/19/2001
-
- # We now have the query string in hand. We do slightly
- # different things for keyword lists and parameter lists.
- if (defined $query_string && length $query_string) {
- if ($query_string =~ /[&=;]/) {
- $self->parse_params($query_string);
- } else {
- $self->add_parameter('keywords');
- $self->{'keywords'} = [$self->parse_keywordlist($query_string)];
- }
- }
-
- # Special case. Erase everything if there is a field named
- # .defaults.
- if ($self->param('.defaults')) {
- $self->delete_all();
- }
-
- # Associative array containing our defined fieldnames
- $self->{'.fieldnames'} = {};
- foreach ($self->param('.cgifields')) {
- $self->{'.fieldnames'}->{$_}++;
- }
-
- # Clear out our default submission button flag if present
- $self->delete('.submit');
- $self->delete('.cgifields');
-
- $self->save_request unless defined $initializer;
-}
-
-# FUNCTIONS TO OVERRIDE:
-# Turn a string into a filehandle
-sub to_filehandle {
- my $thingy = shift;
- return undef unless $thingy;
- return $thingy if UNIVERSAL::isa($thingy,'GLOB');
- return $thingy if UNIVERSAL::isa($thingy,'FileHandle');
- if (!ref($thingy)) {
- my $caller = 1;
- while (my $package = caller($caller++)) {
- my($tmp) = $thingy=~/[\':]/ ? $thingy : "$package\:\:$thingy";
- return $tmp if defined(fileno($tmp));
- }
- }
- return undef;
-}
-
-# send output to the browser
-sub put {
- my($self,@p) = self_or_default(@_);
- $self->print(@p);
-}
-
-# print to standard output (for overriding in mod_perl)
-sub print {
- shift;
- CORE::print(@_);
-}
-
-# get/set last cgi_error
-sub cgi_error {
- my ($self,$err) = self_or_default(@_);
- $self->{'.cgi_error'} = $err if defined $err;
- return $self->{'.cgi_error'};
-}
-
-sub save_request {
- my($self) = @_;
- # We're going to play with the package globals now so that if we get called
- # again, we initialize ourselves in exactly the same way. This allows
- # us to have several of these objects.
- @QUERY_PARAM = $self->param; # save list of parameters
- foreach (@QUERY_PARAM) {
- next unless defined $_;
- $QUERY_PARAM{$_}=$self->{$_};
- }
- $QUERY_CHARSET = $self->charset;
- %QUERY_FIELDNAMES = %{$self->{'.fieldnames'}};
-}
-
-sub parse_params {
- my($self,$tosplit) = @_;
- my(@pairs) = split(/[&;]/,$tosplit);
- my($param,$value);
- foreach (@pairs) {
- ($param,$value) = split('=',$_,2);
- next unless defined $param;
- next if $NO_UNDEF_PARAMS and not defined $value;
- $value = '' unless defined $value;
- $param = unescape($param);
- $value = unescape($value);
- $self->add_parameter($param);
- push (@{$self->{$param}},$value);
- }
-}
-
-sub add_parameter {
- my($self,$param)=@_;
- return unless defined $param;
- push (@{$self->{'.parameters'}},$param)
- unless defined($self->{$param});
-}
-
-sub all_parameters {
- my $self = shift;
- return () unless defined($self) && $self->{'.parameters'};
- return () unless @{$self->{'.parameters'}};
- return @{$self->{'.parameters'}};
-}
-
-# put a filehandle into binary mode (DOS)
-sub binmode {
- return unless defined($_[1]) && defined fileno($_[1]);
- CORE::binmode($_[1]);
-}
-
-sub _make_tag_func {
- my ($self,$tagname) = @_;
- my $func = qq(
- sub $tagname {
- my (\$q,\$a,\@rest) = self_or_default(\@_);
- my(\$attr) = '';
- if (ref(\$a) && ref(\$a) eq 'HASH') {
- my(\@attr) = make_attributes(\$a,\$q->{'escape'});
- \$attr = " \@attr" if \@attr;
- } else {
- unshift \@rest,\$a if defined \$a;
- }
- );
- if ($tagname=~/start_(\w+)/i) {
- $func .= qq! return "<\L$1\E\$attr>";} !;
- } elsif ($tagname=~/end_(\w+)/i) {
- $func .= qq! return "<\L/$1\E>"; } !;
- } else {
- $func .= qq#
- return \$XHTML ? "\L<$tagname\E\$attr />" : "\L<$tagname\E\$attr>" unless \@rest;
- my(\$tag,\$untag) = ("\L<$tagname\E\$attr>","\L</$tagname>\E");
- my \@result = map { "\$tag\$_\$untag" }
- (ref(\$rest[0]) eq 'ARRAY') ? \@{\$rest[0]} : "\@rest";
- return "\@result";
- }#;
- }
-return $func;
-}
-
-sub AUTOLOAD {
- print STDERR "CGI::AUTOLOAD for $AUTOLOAD\n" if $CGI::AUTOLOAD_DEBUG;
- my $func = &_compile;
- goto &$func;
-}
-
-sub _compile {
- my($func) = $AUTOLOAD;
- my($pack,$func_name);
- {
- local($1,$2); # this fixes an obscure variable suicide problem.
- $func=~/(.+)::([^:]+)$/;
- ($pack,$func_name) = ($1,$2);
- $pack=~s/::SUPER$//; # fix another obscure problem
- $pack = ${"$pack\:\:AutoloadClass"} || $CGI::DefaultClass
- unless defined(${"$pack\:\:AUTOLOADED_ROUTINES"});
-
- my($sub) = \%{"$pack\:\:SUBS"};
- unless (%$sub) {
- my($auto) = \${"$pack\:\:AUTOLOADED_ROUTINES"};
- eval "package $pack; $$auto";
- croak("$AUTOLOAD: $@") if $@;
- $$auto = ''; # Free the unneeded storage (but don't undef it!!!)
- }
- my($code) = $sub->{$func_name};
-
- $code = "sub $AUTOLOAD { }" if (!$code and $func_name eq 'DESTROY');
- if (!$code) {
- (my $base = $func_name) =~ s/^(start_|end_)//i;
- if ($EXPORT{':any'} ||
- $EXPORT{'-any'} ||
- $EXPORT{$base} ||
- (%EXPORT_OK || grep(++$EXPORT_OK{$_},&expand_tags(':html')))
- && $EXPORT_OK{$base}) {
- $code = $CGI::DefaultClass->_make_tag_func($func_name);
- }
- }
- croak("Undefined subroutine $AUTOLOAD\n") unless $code;
- eval "package $pack; $code";
- if ($@) {
- $@ =~ s/ at .*\n//;
- croak("$AUTOLOAD: $@");
- }
- }
- CORE::delete($sub->{$func_name}); #free storage
- return "$pack\:\:$func_name";
-}
-
-sub _selected {
- my $self = shift;
- my $value = shift;
- return '' unless $value;
- return $XHTML ? qq( selected="selected") : qq( selected);
-}
-
-sub _checked {
- my $self = shift;
- my $value = shift;
- return '' unless $value;
- return $XHTML ? qq( checked="checked") : qq( checked);
-}
-
-sub _reset_globals { initialize_globals(); }
-
-sub _setup_symbols {
- my $self = shift;
- my $compile = 0;
-
- # to avoid reexporting unwanted variables
- undef %EXPORT;
-
- foreach (@_) {
- $HEADERS_ONCE++, next if /^[:-]unique_headers$/;
- $NPH++, next if /^[:-]nph$/;
- $NOSTICKY++, next if /^[:-]nosticky$/;
- $DEBUG=0, next if /^[:-]no_?[Dd]ebug$/;
- $DEBUG=2, next if /^[:-][Dd]ebug$/;
- $USE_PARAM_SEMICOLONS++, next if /^[:-]newstyle_urls$/;
- $XHTML++, next if /^[:-]xhtml$/;
- $XHTML=0, next if /^[:-]no_?xhtml$/;
- $USE_PARAM_SEMICOLONS=0, next if /^[:-]oldstyle_urls$/;
- $PRIVATE_TEMPFILES++, next if /^[:-]private_tempfiles$/;
- $CLOSE_UPLOAD_FILES++, next if /^[:-]close_upload_files$/;
- $EXPORT{$_}++, next if /^[:-]any$/;
- $compile++, next if /^[:-]compile$/;
- $NO_UNDEF_PARAMS++, next if /^[:-]no_undef_params$/;
-
- # This is probably extremely evil code -- to be deleted some day.
- if (/^[-]autoload$/) {
- my($pkg) = caller(1);
- *{"${pkg}::AUTOLOAD"} = sub {
- my($routine) = $AUTOLOAD;
- $routine =~ s/^.*::/CGI::/;
- &$routine;
- };
- next;
- }
-
- foreach (&expand_tags($_)) {
- tr/a-zA-Z0-9_//cd; # don't allow weird function names
- $EXPORT{$_}++;
- }
- }
- _compile_all(keys %EXPORT) if $compile;
- @SAVED_SYMBOLS = @_;
-}
-
-sub charset {
- my ($self,$charset) = self_or_default(@_);
- $self->{'.charset'} = $charset if defined $charset;
- $self->{'.charset'};
-}
-
-###############################################################################
-################# THESE FUNCTIONS ARE AUTOLOADED ON DEMAND ####################
-###############################################################################
-$AUTOLOADED_ROUTINES = ''; # get rid of -w warning
-$AUTOLOADED_ROUTINES=<<'END_OF_AUTOLOAD';
-
-%SUBS = (
-
-'URL_ENCODED'=> <<'END_OF_FUNC',
-sub URL_ENCODED { 'application/x-www-form-urlencoded'; }
-END_OF_FUNC
-
-'MULTIPART' => <<'END_OF_FUNC',
-sub MULTIPART { 'multipart/form-data'; }
-END_OF_FUNC
-
-'SERVER_PUSH' => <<'END_OF_FUNC',
-sub SERVER_PUSH { 'multipart/x-mixed-replace;boundary="' . shift() . '"'; }
-END_OF_FUNC
-
-'new_MultipartBuffer' => <<'END_OF_FUNC',
-# Create a new multipart buffer
-sub new_MultipartBuffer {
- my($self,$boundary,$length) = @_;
- return MultipartBuffer->new($self,$boundary,$length);
-}
-END_OF_FUNC
-
-'read_from_client' => <<'END_OF_FUNC',
-# Read data from a file handle
-sub read_from_client {
- my($self, $buff, $len, $offset) = @_;
- local $^W=0; # prevent a warning
- return $MOD_PERL
- ? $self->r->read($$buff, $len, $offset)
- : read(\*STDIN, $$buff, $len, $offset);
-}
-END_OF_FUNC
-
-'delete' => <<'END_OF_FUNC',
-#### Method: delete
-# Deletes the named parameter entirely.
-####
-sub delete {
- my($self,@p) = self_or_default(@_);
- my(@names) = rearrange([NAME],@p);
- my @to_delete = ref($names[0]) eq 'ARRAY' ? @$names[0] : @names;
- my %to_delete;
- foreach my $name (@to_delete)
- {
- CORE::delete $self->{$name};
- CORE::delete $self->{'.fieldnames'}->{$name};
- $to_delete{$name}++;
- }
- @{$self->{'.parameters'}}=grep { !exists($to_delete{$_}) } $self->param();
- return;
-}
-END_OF_FUNC
-
-#### Method: import_names
-# Import all parameters into the given namespace.
-# Assumes namespace 'Q' if not specified
-####
-'import_names' => <<'END_OF_FUNC',
-sub import_names {
- my($self,$namespace,$delete) = self_or_default(@_);
- $namespace = 'Q' unless defined($namespace);
- die "Can't import names into \"main\"\n" if \%{"${namespace}::"} == \%::;
- if ($delete || $MOD_PERL || exists $ENV{'FCGI_ROLE'}) {
- # can anyone find an easier way to do this?
- foreach (keys %{"${namespace}::"}) {
- local *symbol = "${namespace}::${_}";
- undef $symbol;
- undef @symbol;
- undef %symbol;
- }
- }
- my($param,@value,$var);
- foreach $param ($self->param) {
- # protect against silly names
- ($var = $param)=~tr/a-zA-Z0-9_/_/c;
- $var =~ s/^(?=\d)/_/;
- local *symbol = "${namespace}::$var";
- @value = $self->param($param);
- @symbol = @value;
- $symbol = $value[0];
- }
-}
-END_OF_FUNC
-
-#### Method: keywords
-# Keywords acts a bit differently. Calling it in a list context
-# returns the list of keywords.
-# Calling it in a scalar context gives you the size of the list.
-####
-'keywords' => <<'END_OF_FUNC',
-sub keywords {
- my($self,@values) = self_or_default(@_);
- # If values is provided, then we set it.
- $self->{'keywords'}=[@values] if @values;
- my(@result) = defined($self->{'keywords'}) ? @{$self->{'keywords'}} : ();
- @result;
-}
-END_OF_FUNC
-
-# These are some tie() interfaces for compatibility
-# with Steve Brenner's cgi-lib.pl routines
-'Vars' => <<'END_OF_FUNC',
-sub Vars {
- my $q = shift;
- my %in;
- tie(%in,CGI,$q);
- return %in if wantarray;
- return \%in;
-}
-END_OF_FUNC
-
-# These are some tie() interfaces for compatibility
-# with Steve Brenner's cgi-lib.pl routines
-'ReadParse' => <<'END_OF_FUNC',
-sub ReadParse {
- local(*in);
- if (@_) {
- *in = $_[0];
- } else {
- my $pkg = caller();
- *in=*{"${pkg}::in"};
- }
- tie(%in,CGI);
- return scalar(keys %in);
-}
-END_OF_FUNC
-
-'PrintHeader' => <<'END_OF_FUNC',
-sub PrintHeader {
- my($self) = self_or_default(@_);
- return $self->header();
-}
-END_OF_FUNC
-
-'HtmlTop' => <<'END_OF_FUNC',
-sub HtmlTop {
- my($self,@p) = self_or_default(@_);
- return $self->start_html(@p);
-}
-END_OF_FUNC
-
-'HtmlBot' => <<'END_OF_FUNC',
-sub HtmlBot {
- my($self,@p) = self_or_default(@_);
- return $self->end_html(@p);
-}
-END_OF_FUNC
-
-'SplitParam' => <<'END_OF_FUNC',
-sub SplitParam {
- my ($param) = @_;
- my (@params) = split ("\0", $param);
- return (wantarray ? @params : $params[0]);
-}
-END_OF_FUNC
-
-'MethGet' => <<'END_OF_FUNC',
-sub MethGet {
- return request_method() eq 'GET';
-}
-END_OF_FUNC
-
-'MethPost' => <<'END_OF_FUNC',
-sub MethPost {
- return request_method() eq 'POST';
-}
-END_OF_FUNC
-
-'TIEHASH' => <<'END_OF_FUNC',
-sub TIEHASH {
- my $class = shift;
- my $arg = $_[0];
- if (ref($arg) && UNIVERSAL::isa($arg,'CGI')) {
- return $arg;
- }
- return $Q ||= $class->new(@_);
-}
-END_OF_FUNC
-
-'STORE' => <<'END_OF_FUNC',
-sub STORE {
- my $self = shift;
- my $tag = shift;
- my $vals = shift;
- my @vals = index($vals,"\0")!=-1 ? split("\0",$vals) : $vals;
- $self->param(-name=>$tag,-value=>\@vals);
-}
-END_OF_FUNC
-
-'FETCH' => <<'END_OF_FUNC',
-sub FETCH {
- return $_[0] if $_[1] eq 'CGI';
- return undef unless defined $_[0]->param($_[1]);
- return join("\0",$_[0]->param($_[1]));
-}
-END_OF_FUNC
-
-'FIRSTKEY' => <<'END_OF_FUNC',
-sub FIRSTKEY {
- $_[0]->{'.iterator'}=0;
- $_[0]->{'.parameters'}->[$_[0]->{'.iterator'}++];
-}
-END_OF_FUNC
-
-'NEXTKEY' => <<'END_OF_FUNC',
-sub NEXTKEY {
- $_[0]->{'.parameters'}->[$_[0]->{'.iterator'}++];
-}
-END_OF_FUNC
-
-'EXISTS' => <<'END_OF_FUNC',
-sub EXISTS {
- exists $_[0]->{$_[1]};
-}
-END_OF_FUNC
-
-'DELETE' => <<'END_OF_FUNC',
-sub DELETE {
- $_[0]->delete($_[1]);
-}
-END_OF_FUNC
-
-'CLEAR' => <<'END_OF_FUNC',
-sub CLEAR {
- %{$_[0]}=();
-}
-####
-END_OF_FUNC
-
-####
-# Append a new value to an existing query
-####
-'append' => <<'EOF',
-sub append {
- my($self,@p) = @_;
- my($name,$value) = rearrange([NAME,[VALUE,VALUES]],@p);
- my(@values) = defined($value) ? (ref($value) ? @{$value} : $value) : ();
- if (@values) {
- $self->add_parameter($name);
- push(@{$self->{$name}},@values);
- }
- return $self->param($name);
-}
-EOF
-
-#### Method: delete_all
-# Delete all parameters
-####
-'delete_all' => <<'EOF',
-sub delete_all {
- my($self) = self_or_default(@_);
- my @param = $self->param();
- $self->delete(@param);
-}
-EOF
-
-'Delete' => <<'EOF',
-sub Delete {
- my($self,@p) = self_or_default(@_);
- $self->delete(@p);
-}
-EOF
-
-'Delete_all' => <<'EOF',
-sub Delete_all {
- my($self,@p) = self_or_default(@_);
- $self->delete_all(@p);
-}
-EOF
-
-#### Method: autoescape
-# If you want to turn off the autoescaping features,
-# call this method with undef as the argument
-'autoEscape' => <<'END_OF_FUNC',
-sub autoEscape {
- my($self,$escape) = self_or_default(@_);
- my $d = $self->{'escape'};
- $self->{'escape'} = $escape;
- $d;
-}
-END_OF_FUNC
-
-
-#### Method: version
-# Return the current version
-####
-'version' => <<'END_OF_FUNC',
-sub version {
- return $VERSION;
-}
-END_OF_FUNC
-
-#### Method: url_param
-# Return a parameter in the QUERY_STRING, regardless of
-# whether this was a POST or a GET
-####
-'url_param' => <<'END_OF_FUNC',
-sub url_param {
- my ($self,@p) = self_or_default(@_);
- my $name = shift(@p);
- return undef unless exists($ENV{QUERY_STRING});
- unless (exists($self->{'.url_param'})) {
- $self->{'.url_param'}={}; # empty hash
- if ($ENV{QUERY_STRING} =~ /=/) {
- my(@pairs) = split(/[&;]/,$ENV{QUERY_STRING});
- my($param,$value);
- foreach (@pairs) {
- ($param,$value) = split('=',$_,2);
- $param = unescape($param);
- $value = unescape($value);
- push(@{$self->{'.url_param'}->{$param}},$value);
- }
- } else {
- $self->{'.url_param'}->{'keywords'} = [$self->parse_keywordlist($ENV{QUERY_STRING})];
- }
- }
- return keys %{$self->{'.url_param'}} unless defined($name);
- return () unless $self->{'.url_param'}->{$name};
- return wantarray ? @{$self->{'.url_param'}->{$name}}
- : $self->{'.url_param'}->{$name}->[0];
-}
-END_OF_FUNC
-
-#### Method: Dump
-# Returns a string in which all the known parameter/value
-# pairs are represented as nested lists, mainly for the purposes
-# of debugging.
-####
-'Dump' => <<'END_OF_FUNC',
-sub Dump {
- my($self) = self_or_default(@_);
- my($param,$value,@result);
- return '<ul></ul>' unless $self->param;
- push(@result,"<ul>");
- foreach $param ($self->param) {
- my($name)=$self->escapeHTML($param);
- push(@result,"<li><strong>$param</strong></li>");
- push(@result,"<ul>");
- foreach $value ($self->param($param)) {
- $value = $self->escapeHTML($value);
- $value =~ s/\n/<br \/>\n/g;
- push(@result,"<li>$value</li>");
- }
- push(@result,"</ul>");
- }
- push(@result,"</ul>");
- return join("\n",@result);
-}
-END_OF_FUNC
-
-#### Method as_string
-#
-# synonym for "dump"
-####
-'as_string' => <<'END_OF_FUNC',
-sub as_string {
- &Dump(@_);
-}
-END_OF_FUNC
-
-#### Method: save
-# Write values out to a filehandle in such a way that they can
-# be reinitialized by the filehandle form of the new() method
-####
-'save' => <<'END_OF_FUNC',
-sub save {
- my($self,$filehandle) = self_or_default(@_);
- $filehandle = to_filehandle($filehandle);
- my($param);
- local($,) = ''; # set print field separator back to a sane value
- local($\) = ''; # set output line separator to a sane value
- foreach $param ($self->param) {
- my($escaped_param) = escape($param);
- my($value);
- foreach $value ($self->param($param)) {
- print $filehandle "$escaped_param=",escape("$value"),"\n";
- }
- }
- foreach (keys %{$self->{'.fieldnames'}}) {
- print $filehandle ".cgifields=",escape("$_"),"\n";
- }
- print $filehandle "=\n"; # end of record
-}
-END_OF_FUNC
-
-
-#### Method: save_parameters
-# An alias for save() that is a better name for exportation.
-# Only intended to be used with the function (non-OO) interface.
-####
-'save_parameters' => <<'END_OF_FUNC',
-sub save_parameters {
- my $fh = shift;
- return save(to_filehandle($fh));
-}
-END_OF_FUNC
-
-#### Method: restore_parameters
-# A way to restore CGI parameters from an initializer.
-# Only intended to be used with the function (non-OO) interface.
-####
-'restore_parameters' => <<'END_OF_FUNC',
-sub restore_parameters {
- $Q = $CGI::DefaultClass->new(@_);
-}
-END_OF_FUNC
-
-#### Method: multipart_init
-# Return a Content-Type: style header for server-push
-# This has to be NPH on most web servers, and it is advisable to set $| = 1
-#
-# Many thanks to Ed Jordan <ed@fidalgo.net> for this
-# contribution, updated by Andrew Benham (adsb@bigfoot.com)
-####
-'multipart_init' => <<'END_OF_FUNC',
-sub multipart_init {
- my($self,@p) = self_or_default(@_);
- my($boundary,@other) = rearrange([BOUNDARY],@p);
- $boundary = $boundary || '------- =_aaaaaaaaaa0';
- $self->{'separator'} = "$CRLF--$boundary$CRLF";
- $self->{'final_separator'} = "$CRLF--$boundary--$CRLF";
- $type = SERVER_PUSH($boundary);
- return $self->header(
- -nph => 0,
- -type => $type,
- (map { split "=", $_, 2 } @other),
- ) . "WARNING: YOUR BROWSER DOESN'T SUPPORT THIS SERVER-PUSH TECHNOLOGY." . $self->multipart_end;
-}
-END_OF_FUNC
-
-
-#### Method: multipart_start
-# Return a Content-Type: style header for server-push, start of section
-#
-# Many thanks to Ed Jordan <ed@fidalgo.net> for this
-# contribution, updated by Andrew Benham (adsb@bigfoot.com)
-####
-'multipart_start' => <<'END_OF_FUNC',
-sub multipart_start {
- my(@header);
- my($self,@p) = self_or_default(@_);
- my($type,@other) = rearrange([TYPE],@p);
- $type = $type || 'text/html';
- push(@header,"Content-Type: $type");
-
- # rearrange() was designed for the HTML portion, so we
- # need to fix it up a little.
- foreach (@other) {
- # Don't use \s because of perl bug 21951
- next unless my($header,$value) = /([^ \r\n\t=]+)=\"?(.+?)\"?$/;
- ($_ = $header) =~ s/^(\w)(.*)/$1 . lc ($2) . ': '.$self->unescapeHTML($value)/e;
- }
- push(@header,@other);
- my $header = join($CRLF,@header)."${CRLF}${CRLF}";
- return $header;
-}
-END_OF_FUNC
-
-
-#### Method: multipart_end
-# Return a MIME boundary separator for server-push, end of section
-#
-# Many thanks to Ed Jordan <ed@fidalgo.net> for this
-# contribution
-####
-'multipart_end' => <<'END_OF_FUNC',
-sub multipart_end {
- my($self,@p) = self_or_default(@_);
- return $self->{'separator'};
-}
-END_OF_FUNC
-
-
-#### Method: multipart_final
-# Return a MIME boundary separator for server-push, end of all sections
-#
-# Contributed by Andrew Benham (adsb@bigfoot.com)
-####
-'multipart_final' => <<'END_OF_FUNC',
-sub multipart_final {
- my($self,@p) = self_or_default(@_);
- return $self->{'final_separator'} . "WARNING: YOUR BROWSER DOESN'T SUPPORT THIS SERVER-PUSH TECHNOLOGY." . $CRLF;
-}
-END_OF_FUNC
-
-
-#### Method: header
-# Return a Content-Type: style header
-#
-####
-'header' => <<'END_OF_FUNC',
-sub header {
- my($self,@p) = self_or_default(@_);
- my(@header);
-
- return "" if $self->{'.header_printed'}++ and $HEADERS_ONCE;
-
- my($type,$status,$cookie,$target,$expires,$nph,$charset,$attachment,$p3p,@other) =
- rearrange([['TYPE','CONTENT_TYPE','CONTENT-TYPE'],
- 'STATUS',['COOKIE','COOKIES'],'TARGET',
- 'EXPIRES','NPH','CHARSET',
- 'ATTACHMENT','P3P'],@p);
-
- $nph ||= $NPH;
- if (defined $charset) {
- $self->charset($charset);
- } else {
- $charset = $self->charset;
- }
-
- # rearrange() was designed for the HTML portion, so we
- # need to fix it up a little.
- foreach (@other) {
- # Don't use \s because of perl bug 21951
- next unless my($header,$value) = /([^ \r\n\t=]+)=\"?(.+?)\"?$/;
- ($_ = $header) =~ s/^(\w)(.*)/"\u$1\L$2" . ': '.$self->unescapeHTML($value)/e;
- }
-
- $type ||= 'text/html' unless defined($type);
- $type .= "; charset=$charset" if $type ne '' and $type =~ m!^text/! and $type !~ /\bcharset\b/ and $charset ne '';
-
- # Maybe future compatibility. Maybe not.
- my $protocol = $ENV{SERVER_PROTOCOL} || 'HTTP/1.0';
- push(@header,$protocol . ' ' . ($status || '200 OK')) if $nph;
- push(@header,"Server: " . &server_software()) if $nph;
-
- push(@header,"Status: $status") if $status;
- push(@header,"Window-Target: $target") if $target;
- if ($p3p) {
- $p3p = join ' ',@$p3p if ref($p3p) eq 'ARRAY';
- push(@header,qq(P3P: policyref="/w3c/p3p.xml", CP="$p3p"));
- }
- # push all the cookies -- there may be several
- if ($cookie) {
- my(@cookie) = ref($cookie) && ref($cookie) eq 'ARRAY' ? @{$cookie} : $cookie;
- foreach (@cookie) {
- my $cs = UNIVERSAL::isa($_,'CGI::Cookie') ? $_->as_string : $_;
- push(@header,"Set-Cookie: $cs") if $cs ne '';
- }
- }
- # if the user indicates an expiration time, then we need
- # both an Expires and a Date header (so that the browser is
- # uses OUR clock)
- push(@header,"Expires: " . expires($expires,'http'))
- if $expires;
- push(@header,"Date: " . expires(0,'http')) if $expires || $cookie || $nph;
- push(@header,"Pragma: no-cache") if $self->cache();
- push(@header,"Content-Disposition: attachment; filename=\"$attachment\"") if $attachment;
- push(@header,map {ucfirst $_} @other);
- push(@header,"Content-Type: $type") if $type ne '';
- my $header = join($CRLF,@header)."${CRLF}${CRLF}";
- if ($MOD_PERL and not $nph) {
- $self->r->send_cgi_header($header);
- return '';
- }
- return $header;
-}
-END_OF_FUNC
-
-
-#### Method: cache
-# Control whether header() will produce the no-cache
-# Pragma directive.
-####
-'cache' => <<'END_OF_FUNC',
-sub cache {
- my($self,$new_value) = self_or_default(@_);
- $new_value = '' unless $new_value;
- if ($new_value ne '') {
- $self->{'cache'} = $new_value;
- }
- return $self->{'cache'};
-}
-END_OF_FUNC
-
-
-#### Method: redirect
-# Return a Location: style header
-#
-####
-'redirect' => <<'END_OF_FUNC',
-sub redirect {
- my($self,@p) = self_or_default(@_);
- my($url,$target,$status,$cookie,$nph,@other) =
- rearrange([[LOCATION,URI,URL],TARGET,STATUS,['COOKIE','COOKIES'],NPH],@p);
- $status = '302 Moved' unless defined $status;
- $url ||= $self->self_url;
- my(@o);
- foreach (@other) { tr/\"//d; push(@o,split("=",$_,2)); }
- unshift(@o,
- '-Status' => $status,
- '-Location'=> $url,
- '-nph' => $nph);
- unshift(@o,'-Target'=>$target) if $target;
- unshift(@o,'-Type'=>'');
- my @unescaped;
- unshift(@unescaped,'-Cookie'=>$cookie) if $cookie;
- return $self->header((map {$self->unescapeHTML($_)} @o),@unescaped);
-}
-END_OF_FUNC
-
-
-#### Method: start_html
-# Canned HTML header
-#
-# Parameters:
-# $title -> (optional) The title for this HTML document (-title)
-# $author -> (optional) e-mail address of the author (-author)
-# $base -> (optional) if set to true, will enter the BASE address of this document
-# for resolving relative references (-base)
-# $xbase -> (optional) alternative base at some remote location (-xbase)
-# $target -> (optional) target window to load all links into (-target)
-# $script -> (option) Javascript code (-script)
-# $no_script -> (option) Javascript <noscript> tag (-noscript)
-# $meta -> (optional) Meta information tags
-# $head -> (optional) any other elements you'd like to incorporate into the <head> tag
-# (a scalar or array ref)
-# $style -> (optional) reference to an external style sheet
-# @other -> (optional) any other named parameters you'd like to incorporate into
-# the <body> tag.
-####
-'start_html' => <<'END_OF_FUNC',
-sub start_html {
- my($self,@p) = &self_or_default(@_);
- my($title,$author,$base,$xbase,$script,$noscript,
- $target,$meta,$head,$style,$dtd,$lang,$encoding,@other) =
- rearrange([TITLE,AUTHOR,BASE,XBASE,SCRIPT,NOSCRIPT,TARGET,META,HEAD,STYLE,DTD,LANG,ENCODING],@p);
-
- $encoding = 'iso-8859-1' unless defined $encoding;
-
- # Need to sort out the DTD before it's okay to call escapeHTML().
- my(@result,$xml_dtd);
- if ($dtd) {
- if (defined(ref($dtd)) and (ref($dtd) eq 'ARRAY')) {
- $dtd = $DEFAULT_DTD unless $dtd->[0] =~ m|^-//|;
- } else {
- $dtd = $DEFAULT_DTD unless $dtd =~ m|^-//|;
- }
- } else {
- $dtd = $XHTML ? XHTML_DTD : $DEFAULT_DTD;
- }
-
- $xml_dtd++ if ref($dtd) eq 'ARRAY' && $dtd->[0] =~ /\bXHTML\b/i;
- $xml_dtd++ if ref($dtd) eq '' && $dtd =~ /\bXHTML\b/i;
- push @result,qq(<?xml version="1.0" encoding="$encoding"?>) if $xml_dtd;
-
- if (ref($dtd) && ref($dtd) eq 'ARRAY') {
- push(@result,qq(<!DOCTYPE html\n\tPUBLIC "$dtd->[0]"\n\t "$dtd->[1]">));
- $DTD_PUBLIC_IDENTIFIER = $dtd->[0];
- } else {
- push(@result,qq(<!DOCTYPE html\n\tPUBLIC "$dtd">));
- $DTD_PUBLIC_IDENTIFIER = $dtd;
- }
-
- # Now that we know whether we're using the HTML 3.2 DTD or not, it's okay to
- # call escapeHTML(). Strangely enough, the title needs to be escaped as
- # HTML while the author needs to be escaped as a URL.
- $title = $self->escapeHTML($title || 'Untitled Document');
- $author = $self->escape($author);
-
- if ($DTD_PUBLIC_IDENTIFIER =~ /[^X]HTML (2\.0|3\.2)/i) {
- $lang = "" unless defined $lang;
- $XHTML = 0;
- }
- else {
- $lang = 'en-US' unless defined $lang;
- }
-
- push(@result,$XHTML ? qq(<html xmlns="http://www.w3.org/1999/xhtml" lang="$lang" xml:lang="$lang"><head><title>$title</title>)
- : ($lang ? qq(<html lang="$lang">) : "<html>")
- . "<head><title>$title</title>");
- if (defined $author) {
- push(@result,$XHTML ? "<link rev=\"made\" href=\"mailto:$author\" />"
- : "<link rev=\"made\" href=\"mailto:$author\">");
- }
-
- if ($base || $xbase || $target) {
- my $href = $xbase || $self->url('-path'=>1);
- my $t = $target ? qq/ target="$target"/ : '';
- push(@result,$XHTML ? qq(<base href="$href"$t />) : qq(<base href="$href"$t>));
- }
-
- if ($meta && ref($meta) && (ref($meta) eq 'HASH')) {
- foreach (keys %$meta) { push(@result,$XHTML ? qq(<meta name="$_" content="$meta->{$_}" />)
- : qq(<meta name="$_" content="$meta->{$_}">)); }
- }
-
- push(@result,ref($head) ? @$head : $head) if $head;
-
- # handle the infrequently-used -style and -script parameters
- push(@result,$self->_style($style)) if defined $style;
- push(@result,$self->_script($script)) if defined $script;
-
- # handle -noscript parameter
- push(@result,<<END) if $noscript;
-<noscript>
-$noscript
-</noscript>
-END
- ;
- my($other) = @other ? " @other" : '';
- push(@result,"</head><body$other>");
- return join("\n",@result);
-}
-END_OF_FUNC
-
-### Method: _style
-# internal method for generating a CSS style section
-####
-'_style' => <<'END_OF_FUNC',
-sub _style {
- my ($self,$style) = @_;
- my (@result);
- my $type = 'text/css';
-
- my $cdata_start = $XHTML ? "\n<!--/* <![CDATA[ */" : "\n<!-- ";
- my $cdata_end = $XHTML ? "\n/* ]]> */-->\n" : " -->\n";
-
- my @s = ref($style) eq 'ARRAY' ? @$style : $style;
-
- for my $s (@s) {
- if (ref($s)) {
- my($src,$code,$verbatim,$stype,$foo,@other) =
- rearrange([qw(SRC CODE VERBATIM TYPE FOO)],
- ('-foo'=>'bar',
- ref($s) eq 'ARRAY' ? @$s : %$s));
- $type = $stype if $stype;
- my $other = @other ? join ' ',@other : '';
-
- if (ref($src) eq "ARRAY") # Check to see if the $src variable is an array reference
- { # If it is, push a LINK tag for each one
- foreach $src (@$src)
- {
- push(@result,$XHTML ? qq(<link rel="stylesheet" type="$type" href="$src" $other/>)
- : qq(<link rel="stylesheet" type="$type" href="$src"$other>)) if $src;
- }
- }
- else
- { # Otherwise, push the single -src, if it exists.
- push(@result,$XHTML ? qq(<link rel="stylesheet" type="$type" href="$src" $other/>)
- : qq(<link rel="stylesheet" type="$type" href="$src"$other>)
- ) if $src;
- }
- if ($verbatim) {
- my @v = ref($verbatim) eq 'ARRAY' ? @$verbatim : $verbatim;
- push(@result, "<style type=\"text/css\">\n$_\n</style>") foreach @v;
- }
- my @c = ref($code) eq 'ARRAY' ? @$code : $code if $code;
- push(@result,style({'type'=>$type},"$cdata_start\n$_\n$cdata_end")) foreach @c;
-
- } else {
- my $src = $s;
- push(@result,$XHTML ? qq(<link rel="stylesheet" type="$type" href="$src" $other/>)
- : qq(<link rel="stylesheet" type="$type" href="$src"$other>));
- }
- }
- @result;
-}
-END_OF_FUNC
-
-'_script' => <<'END_OF_FUNC',
-sub _script {
- my ($self,$script) = @_;
- my (@result);
-
- my (@scripts) = ref($script) eq 'ARRAY' ? @$script : ($script);
- foreach $script (@scripts) {
- my($src,$code,$language);
- if (ref($script)) { # script is a hash
- ($src,$code,$language, $type) =
- rearrange([SRC,CODE,LANGUAGE,TYPE],
- '-foo'=>'bar', # a trick to allow the '-' to be omitted
- ref($script) eq 'ARRAY' ? @$script : %$script);
- # User may not have specified language
- $language ||= 'JavaScript';
- unless (defined $type) {
- $type = lc $language;
- # strip '1.2' from 'javascript1.2'
- $type =~ s/^(\D+).*$/text\/$1/;
- }
- } else {
- ($src,$code,$language, $type) = ('',$script,'JavaScript', 'text/javascript');
- }
-
- my $comment = '//'; # javascript by default
- $comment = '#' if $type=~/perl|tcl/i;
- $comment = "'" if $type=~/vbscript/i;
-
- my ($cdata_start,$cdata_end);
- if ($XHTML) {
- $cdata_start = "$comment<![CDATA[\n";
- $cdata_end .= "\n$comment]]>";
- } else {
- $cdata_start = "\n<!-- Hide script\n";
- $cdata_end = $comment;
- $cdata_end .= " End script hiding -->\n";
- }
- my(@satts);
- push(@satts,'src'=>$src) if $src;
- push(@satts,'language'=>$language) unless defined $type;
- push(@satts,'type'=>$type);
- $code = "$cdata_start$code$cdata_end" if defined $code;
- push(@result,script({@satts},$code || ''));
- }
- @result;
-}
-END_OF_FUNC
-
-#### Method: end_html
-# End an HTML document.
-# Trivial method for completeness. Just returns "</body>"
-####
-'end_html' => <<'END_OF_FUNC',
-sub end_html {
- return "</body></html>";
-}
-END_OF_FUNC
-
-
-################################
-# METHODS USED IN BUILDING FORMS
-################################
-
-#### Method: isindex
-# Just prints out the isindex tag.
-# Parameters:
-# $action -> optional URL of script to run
-# Returns:
-# A string containing a <isindex> tag
-'isindex' => <<'END_OF_FUNC',
-sub isindex {
- my($self,@p) = self_or_default(@_);
- my($action,@other) = rearrange([ACTION],@p);
- $action = qq/ action="$action"/ if $action;
- my($other) = @other ? " @other" : '';
- return $XHTML ? "<isindex$action$other />" : "<isindex$action$other>";
-}
-END_OF_FUNC
-
-
-#### Method: startform
-# Start a form
-# Parameters:
-# $method -> optional submission method to use (GET or POST)
-# $action -> optional URL of script to run
-# $enctype ->encoding to use (URL_ENCODED or MULTIPART)
-'startform' => <<'END_OF_FUNC',
-sub startform {
- my($self,@p) = self_or_default(@_);
-
- my($method,$action,$enctype,@other) =
- rearrange([METHOD,ACTION,ENCTYPE],@p);
-
- $method = $self->escapeHTML(lc($method) || 'post');
- $enctype = $self->escapeHTML($enctype || &URL_ENCODED);
- if (defined $action) {
- $action = $self->escapeHTML($action);
- }
- else {
- $action = $self->escapeHTML($self->url(-absolute=>1,-path=>1));
- if (exists $ENV{QUERY_STRING} && length($ENV{QUERY_STRING})>0) {
- $action .= "?".$self->escapeHTML($ENV{QUERY_STRING},1);
- }
- }
- $action = qq(action="$action");
- my($other) = @other ? " @other" : '';
- $self->{'.parametersToAdd'}={};
- return qq/<form method="$method" $action enctype="$enctype"$other>\n/;
-}
-END_OF_FUNC
-
-
-#### Method: start_form
-# synonym for startform
-'start_form' => <<'END_OF_FUNC',
-sub start_form {
- &startform;
-}
-END_OF_FUNC
-
-'end_multipart_form' => <<'END_OF_FUNC',
-sub end_multipart_form {
- &endform;
-}
-END_OF_FUNC
-
-#### Method: start_multipart_form
-# synonym for startform
-'start_multipart_form' => <<'END_OF_FUNC',
-sub start_multipart_form {
- my($self,@p) = self_or_default(@_);
- if (defined($param[0]) && substr($param[0],0,1) eq '-') {
- my(%p) = @p;
- $p{'-enctype'}=&MULTIPART;
- return $self->startform(%p);
- } else {
- my($method,$action,@other) =
- rearrange([METHOD,ACTION],@p);
- return $self->startform($method,$action,&MULTIPART,@other);
- }
-}
-END_OF_FUNC
-
-
-#### Method: endform
-# End a form
-'endform' => <<'END_OF_FUNC',
-sub endform {
- my($self,@p) = self_or_default(@_);
- if ( $NOSTICKY ) {
- return wantarray ? ("</form>") : "\n</form>";
- } else {
- return wantarray ? ("<div>",$self->get_fields,"</div>","</form>") :
- "<div>".$self->get_fields ."</div>\n</form>";
- }
-}
-END_OF_FUNC
-
-
-'_textfield' => <<'END_OF_FUNC',
-sub _textfield {
- my($self,$tag,@p) = self_or_default(@_);
- my($name,$default,$size,$maxlength,$override,@other) =
- rearrange([NAME,[DEFAULT,VALUE,VALUES],SIZE,MAXLENGTH,[OVERRIDE,FORCE]],@p);
-
- my $current = $override ? $default :
- (defined($self->param($name)) ? $self->param($name) : $default);
-
- $current = defined($current) ? $self->escapeHTML($current,1) : '';
- $name = defined($name) ? $self->escapeHTML($name) : '';
- my($s) = defined($size) ? qq/ size="$size"/ : '';
- my($m) = defined($maxlength) ? qq/ maxlength="$maxlength"/ : '';
- my($other) = @other ? " @other" : '';
- # this entered at cristy's request to fix problems with file upload fields
- # and WebTV -- not sure it won't break stuff
- my($value) = $current ne '' ? qq(value="$current") : '';
- return $XHTML ? qq(<input type="$tag" name="$name" $value$s$m$other />)
- : qq(<input type="$tag" name="$name" $value$s$m$other>);
-}
-END_OF_FUNC
-
-#### Method: textfield
-# Parameters:
-# $name -> Name of the text field
-# $default -> Optional default value of the field if not
-# already defined.
-# $size -> Optional width of field in characaters.
-# $maxlength -> Optional maximum number of characters.
-# Returns:
-# A string containing a <input type="text"> field
-#
-'textfield' => <<'END_OF_FUNC',
-sub textfield {
- my($self,@p) = self_or_default(@_);
- $self->_textfield('text',@p);
-}
-END_OF_FUNC
-
-
-#### Method: filefield
-# Parameters:
-# $name -> Name of the file upload field
-# $size -> Optional width of field in characaters.
-# $maxlength -> Optional maximum number of characters.
-# Returns:
-# A string containing a <input type="file"> field
-#
-'filefield' => <<'END_OF_FUNC',
-sub filefield {
- my($self,@p) = self_or_default(@_);
- $self->_textfield('file',@p);
-}
-END_OF_FUNC
-
-
-#### Method: password
-# Create a "secret password" entry field
-# Parameters:
-# $name -> Name of the field
-# $default -> Optional default value of the field if not
-# already defined.
-# $size -> Optional width of field in characters.
-# $maxlength -> Optional maximum characters that can be entered.
-# Returns:
-# A string containing a <input type="password"> field
-#
-'password_field' => <<'END_OF_FUNC',
-sub password_field {
- my ($self,@p) = self_or_default(@_);
- $self->_textfield('password',@p);
-}
-END_OF_FUNC
-
-#### Method: textarea
-# Parameters:
-# $name -> Name of the text field
-# $default -> Optional default value of the field if not
-# already defined.
-# $rows -> Optional number of rows in text area
-# $columns -> Optional number of columns in text area
-# Returns:
-# A string containing a <textarea></textarea> tag
-#
-'textarea' => <<'END_OF_FUNC',
-sub textarea {
- my($self,@p) = self_or_default(@_);
-
- my($name,$default,$rows,$cols,$override,@other) =
- rearrange([NAME,[DEFAULT,VALUE],ROWS,[COLS,COLUMNS],[OVERRIDE,FORCE]],@p);
-
- my($current)= $override ? $default :
- (defined($self->param($name)) ? $self->param($name) : $default);
-
- $name = defined($name) ? $self->escapeHTML($name) : '';
- $current = defined($current) ? $self->escapeHTML($current) : '';
- my($r) = $rows ? qq/ rows="$rows"/ : '';
- my($c) = $cols ? qq/ cols="$cols"/ : '';
- my($other) = @other ? " @other" : '';
- return qq{<textarea name="$name"$r$c$other>$current</textarea>};
-}
-END_OF_FUNC
-
-
-#### Method: button
-# Create a javascript button.
-# Parameters:
-# $name -> (optional) Name for the button. (-name)
-# $value -> (optional) Value of the button when selected (and visible name) (-value)
-# $onclick -> (optional) Text of the JavaScript to run when the button is
-# clicked.
-# Returns:
-# A string containing a <input type="button"> tag
-####
-'button' => <<'END_OF_FUNC',
-sub button {
- my($self,@p) = self_or_default(@_);
-
- my($label,$value,$script,@other) = rearrange([NAME,[VALUE,LABEL],
- [ONCLICK,SCRIPT]],@p);
-
- $label=$self->escapeHTML($label);
- $value=$self->escapeHTML($value,1);
- $script=$self->escapeHTML($script);
-
- my($name) = '';
- $name = qq/ name="$label"/ if $label;
- $value = $value || $label;
- my($val) = '';
- $val = qq/ value="$value"/ if $value;
- $script = qq/ onclick="$script"/ if $script;
- my($other) = @other ? " @other" : '';
- return $XHTML ? qq(<input type="button"$name$val$script$other />)
- : qq(<input type="button"$name$val$script$other>);
-}
-END_OF_FUNC
-
-
-#### Method: submit
-# Create a "submit query" button.
-# Parameters:
-# $name -> (optional) Name for the button.
-# $value -> (optional) Value of the button when selected (also doubles as label).
-# $label -> (optional) Label printed on the button(also doubles as the value).
-# Returns:
-# A string containing a <input type="submit"> tag
-####
-'submit' => <<'END_OF_FUNC',
-sub submit {
- my($self,@p) = self_or_default(@_);
-
- my($label,$value,@other) = rearrange([NAME,[VALUE,LABEL]],@p);
-
- $label=$self->escapeHTML($label);
- $value=$self->escapeHTML($value,1);
-
- my $name = $NOSTICKY ? '' : ' name=".submit"';
- $name = qq/ name="$label"/ if defined($label);
- $value = defined($value) ? $value : $label;
- my $val = '';
- $val = qq/ value="$value"/ if defined($value);
- my($other) = @other ? " @other" : '';
- return $XHTML ? qq(<input type="submit"$name$val$other />)
- : qq(<input type="submit"$name$val$other>);
-}
-END_OF_FUNC
-
-
-#### Method: reset
-# Create a "reset" button.
-# Parameters:
-# $name -> (optional) Name for the button.
-# Returns:
-# A string containing a <input type="reset"> tag
-####
-'reset' => <<'END_OF_FUNC',
-sub reset {
- my($self,@p) = self_or_default(@_);
- my($label,$value,@other) = rearrange(['NAME',['VALUE','LABEL']],@p);
- $label=$self->escapeHTML($label);
- $value=$self->escapeHTML($value,1);
- my ($name) = ' name=".reset"';
- $name = qq/ name="$label"/ if defined($label);
- $value = defined($value) ? $value : $label;
- my($val) = '';
- $val = qq/ value="$value"/ if defined($value);
- my($other) = @other ? " @other" : '';
- return $XHTML ? qq(<input type="reset"$name$val$other />)
- : qq(<input type="reset"$name$val$other>);
-}
-END_OF_FUNC
-
-
-#### Method: defaults
-# Create a "defaults" button.
-# Parameters:
-# $name -> (optional) Name for the button.
-# Returns:
-# A string containing a <input type="submit" name=".defaults"> tag
-#
-# Note: this button has a special meaning to the initialization script,
-# and tells it to ERASE the current query string so that your defaults
-# are used again!
-####
-'defaults' => <<'END_OF_FUNC',
-sub defaults {
- my($self,@p) = self_or_default(@_);
-
- my($label,@other) = rearrange([[NAME,VALUE]],@p);
-
- $label=$self->escapeHTML($label,1);
- $label = $label || "Defaults";
- my($value) = qq/ value="$label"/;
- my($other) = @other ? " @other" : '';
- return $XHTML ? qq(<input type="submit" name=".defaults"$value$other />)
- : qq/<input type="submit" NAME=".defaults"$value$other>/;
-}
-END_OF_FUNC
-
-
-#### Method: comment
-# Create an HTML <!-- comment -->
-# Parameters: a string
-'comment' => <<'END_OF_FUNC',
-sub comment {
- my($self,@p) = self_or_CGI(@_);
- return "<!-- @p -->";
-}
-END_OF_FUNC
-
-#### Method: checkbox
-# Create a checkbox that is not logically linked to any others.
-# The field value is "on" when the button is checked.
-# Parameters:
-# $name -> Name of the checkbox
-# $checked -> (optional) turned on by default if true
-# $value -> (optional) value of the checkbox, 'on' by default
-# $label -> (optional) a user-readable label printed next to the box.
-# Otherwise the checkbox name is used.
-# Returns:
-# A string containing a <input type="checkbox"> field
-####
-'checkbox' => <<'END_OF_FUNC',
-sub checkbox {
- my($self,@p) = self_or_default(@_);
-
- my($name,$checked,$value,$label,$override,@other) =
- rearrange([NAME,[CHECKED,SELECTED,ON],VALUE,LABEL,[OVERRIDE,FORCE]],@p);
-
- $value = defined $value ? $value : 'on';
-
- if (!$override && ($self->{'.fieldnames'}->{$name} ||
- defined $self->param($name))) {
- $checked = grep($_ eq $value,$self->param($name)) ? $self->_checked(1) : '';
- } else {
- $checked = $self->_checked($checked);
- }
- my($the_label) = defined $label ? $label : $name;
- $name = $self->escapeHTML($name);
- $value = $self->escapeHTML($value,1);
- $the_label = $self->escapeHTML($the_label);
- my($other) = @other ? " @other" : '';
- $self->register_parameter($name);
- return $XHTML ? qq{<input type="checkbox" name="$name" value="$value"$checked$other />$the_label}
- : qq{<input type="checkbox" name="$name" value="$value"$checked$other>$the_label};
-}
-END_OF_FUNC
-
-
-#### Method: checkbox_group
-# Create a list of logically-linked checkboxes.
-# Parameters:
-# $name -> Common name for all the check boxes
-# $values -> A pointer to a regular array containing the
-# values for each checkbox in the group.
-# $defaults -> (optional)
-# 1. If a pointer to a regular array of checkbox values,
-# then this will be used to decide which
-# checkboxes to turn on by default.
-# 2. If a scalar, will be assumed to hold the
-# value of a single checkbox in the group to turn on.
-# $linebreak -> (optional) Set to true to place linebreaks
-# between the buttons.
-# $labels -> (optional)
-# A pointer to an associative array of labels to print next to each checkbox
-# in the form $label{'value'}="Long explanatory label".
-# Otherwise the provided values are used as the labels.
-# Returns:
-# An ARRAY containing a series of <input type="checkbox"> fields
-####
-'checkbox_group' => <<'END_OF_FUNC',
-sub checkbox_group {
- my($self,@p) = self_or_default(@_);
-
- my($name,$values,$defaults,$linebreak,$labels,$attributes,$rows,$columns,
- $rowheaders,$colheaders,$override,$nolabels,@other) =
- rearrange([NAME,[VALUES,VALUE],[DEFAULTS,DEFAULT],
- LINEBREAK,LABELS,ATTRIBUTES,ROWS,[COLUMNS,COLS],
- ROWHEADERS,COLHEADERS,
- [OVERRIDE,FORCE],NOLABELS],@p);
-
- my($checked,$break,$result,$label);
-
- my(%checked) = $self->previous_or_default($name,$defaults,$override);
-
- if ($linebreak) {
- $break = $XHTML ? "<br />" : "<br>";
- }
- else {
- $break = '';
- }
- $name=$self->escapeHTML($name);
-
- # Create the elements
- my(@elements,@values);
-
- @values = $self->_set_values_and_labels($values,\$labels,$name);
-
- my($other) = @other ? " @other" : '';
- foreach (@values) {
- $checked = $self->_checked($checked{$_});
- $label = '';
- unless (defined($nolabels) && $nolabels) {
- $label = $_;
- $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
- $label = $self->escapeHTML($label);
- }
- my $attribs = $self->_set_attributes($_, $attributes);
- $_ = $self->escapeHTML($_,1);
- push(@elements,$XHTML ? qq(<input type="checkbox" name="$name" value="$_"$checked$other$attribs />${label}${break})
- : qq/<input type="checkbox" name="$name" value="$_"$checked$other$attribs>${label}${break}/);
- }
- $self->register_parameter($name);
- return wantarray ? @elements : join(' ',@elements)
- unless defined($columns) || defined($rows);
- $rows = 1 if $rows && $rows < 1;
- $cols = 1 if $cols && $cols < 1;
- return _tableize($rows,$columns,$rowheaders,$colheaders,@elements);
-}
-END_OF_FUNC
-
-# Escape HTML -- used internally
-'escapeHTML' => <<'END_OF_FUNC',
-sub escapeHTML {
- # hack to work around earlier hacks
- push @_,$_[0] if @_==1 && $_[0] eq 'CGI';
- my ($self,$toencode,$newlinestoo) = CGI::self_or_default(@_);
- return undef unless defined($toencode);
- return $toencode if ref($self) && !$self->{'escape'};
- $toencode =~ s{&}{&amp;}gso;
- $toencode =~ s{<}{&lt;}gso;
- $toencode =~ s{>}{&gt;}gso;
- if ($DTD_PUBLIC_IDENTIFIER =~ /[^X]HTML 3\.2/i) {
- # $quot; was accidentally omitted from the HTML 3.2 DTD -- see
- # <http://validator.w3.org/docs/errors.html#bad-entity> /
- # <http://lists.w3.org/Archives/Public/www-html/1997Mar/0003.html>.
- $toencode =~ s{"}{&#34;}gso;
- }
- else {
- $toencode =~ s{"}{&quot;}gso;
- }
- my $latin = uc $self->{'.charset'} eq 'ISO-8859-1' ||
- uc $self->{'.charset'} eq 'WINDOWS-1252';
- if ($latin) { # bug in some browsers
- $toencode =~ s{'}{&#39;}gso;
- $toencode =~ s{\x8b}{&#8249;}gso;
- $toencode =~ s{\x9b}{&#8250;}gso;
- if (defined $newlinestoo && $newlinestoo) {
- $toencode =~ s{\012}{&#10;}gso;
- $toencode =~ s{\015}{&#13;}gso;
- }
- }
- return $toencode;
-}
-END_OF_FUNC
-
-# unescape HTML -- used internally
-'unescapeHTML' => <<'END_OF_FUNC',
-sub unescapeHTML {
- # hack to work around earlier hacks
- push @_,$_[0] if @_==1 && $_[0] eq 'CGI';
- my ($self,$string) = CGI::self_or_default(@_);
- return undef unless defined($string);
- my $latin = defined $self->{'.charset'} ? $self->{'.charset'} =~ /^(ISO-8859-1|WINDOWS-1252)$/i
- : 1;
- # thanks to Randal Schwartz for the correct solution to this one
- $string=~ s[&(.*?);]{
- local $_ = $1;
- /^amp$/i ? "&" :
- /^quot$/i ? '"' :
- /^gt$/i ? ">" :
- /^lt$/i ? "<" :
- /^#(\d+)$/ && $latin ? chr($1) :
- /^#x([0-9a-f]+)$/i && $latin ? chr(hex($1)) :
- $_
- }gex;
- return $string;
-}
-END_OF_FUNC
-
-# Internal procedure - don't use
-'_tableize' => <<'END_OF_FUNC',
-sub _tableize {
- my($rows,$columns,$rowheaders,$colheaders,@elements) = @_;
- $rowheaders = [] unless defined $rowheaders;
- $colheaders = [] unless defined $colheaders;
- my($result);
-
- if (defined($columns)) {
- $rows = int(0.99 + @elements/$columns) unless defined($rows);
- }
- if (defined($rows)) {
- $columns = int(0.99 + @elements/$rows) unless defined($columns);
- }
-
- # rearrange into a pretty table
- $result = "<table>";
- my($row,$column);
- unshift(@$colheaders,'') if @$colheaders && @$rowheaders;
- $result .= "<tr>" if @{$colheaders};
- foreach (@{$colheaders}) {
- $result .= "<th>$_</th>";
- }
- for ($row=0;$row<$rows;$row++) {
- $result .= "<tr>";
- $result .= "<th>$rowheaders->[$row]</th>" if @$rowheaders;
- for ($column=0;$column<$columns;$column++) {
- $result .= "<td>" . $elements[$column*$rows + $row] . "</td>"
- if defined($elements[$column*$rows + $row]);
- }
- $result .= "</tr>";
- }
- $result .= "</table>";
- return $result;
-}
-END_OF_FUNC
-
-
-#### Method: radio_group
-# Create a list of logically-linked radio buttons.
-# Parameters:
-# $name -> Common name for all the buttons.
-# $values -> A pointer to a regular array containing the
-# values for each button in the group.
-# $default -> (optional) Value of the button to turn on by default. Pass '-'
-# to turn _nothing_ on.
-# $linebreak -> (optional) Set to true to place linebreaks
-# between the buttons.
-# $labels -> (optional)
-# A pointer to an associative array of labels to print next to each checkbox
-# in the form $label{'value'}="Long explanatory label".
-# Otherwise the provided values are used as the labels.
-# Returns:
-# An ARRAY containing a series of <input type="radio"> fields
-####
-'radio_group' => <<'END_OF_FUNC',
-sub radio_group {
- my($self,@p) = self_or_default(@_);
-
- my($name,$values,$default,$linebreak,$labels,$attributes,
- $rows,$columns,$rowheaders,$colheaders,$override,$nolabels,@other) =
- rearrange([NAME,[VALUES,VALUE],DEFAULT,LINEBREAK,LABELS,ATTRIBUTES,
- ROWS,[COLUMNS,COLS],
- ROWHEADERS,COLHEADERS,
- [OVERRIDE,FORCE],NOLABELS],@p);
- my($result,$checked);
-
- if (!$override && defined($self->param($name))) {
- $checked = $self->param($name);
- } else {
- $checked = $default;
- }
- my(@elements,@values);
- @values = $self->_set_values_and_labels($values,\$labels,$name);
-
- # If no check array is specified, check the first by default
- $checked = $values[0] unless defined($checked) && $checked ne '';
- $name=$self->escapeHTML($name);
-
- my($other) = @other ? " @other" : '';
- foreach (@values) {
- my($checkit) = $checked eq $_ ? qq/ checked="checked"/ : '';
- my($break);
- if ($linebreak) {
- $break = $XHTML ? "<br />" : "<br>";
- }
- else {
- $break = '';
- }
- my($label)='';
- unless (defined($nolabels) && $nolabels) {
- $label = $_;
- $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
- $label = $self->escapeHTML($label,1);
- }
- my $attribs = $self->_set_attributes($_, $attributes);
- $_=$self->escapeHTML($_);
- push(@elements,$XHTML ? qq(<input type="radio" name="$name" value="$_"$checkit$other$attribs />${label}${break})
- : qq/<input type="radio" name="$name" value="$_"$checkit$other$attribs>${label}${break}/);
- }
- $self->register_parameter($name);
- return wantarray ? @elements : join(' ',@elements)
- unless defined($columns) || defined($rows);
- return _tableize($rows,$columns,$rowheaders,$colheaders,@elements);
-}
-END_OF_FUNC
-
-
-#### Method: popup_menu
-# Create a popup menu.
-# Parameters:
-# $name -> Name for all the menu
-# $values -> A pointer to a regular array containing the
-# text of each menu item.
-# $default -> (optional) Default item to display
-# $labels -> (optional)
-# A pointer to an associative array of labels to print next to each checkbox
-# in the form $label{'value'}="Long explanatory label".
-# Otherwise the provided values are used as the labels.
-# Returns:
-# A string containing the definition of a popup menu.
-####
-'popup_menu' => <<'END_OF_FUNC',
-sub popup_menu {
- my($self,@p) = self_or_default(@_);
-
- my($name,$values,$default,$labels,$attributes,$override,@other) =
- rearrange([NAME,[VALUES,VALUE],[DEFAULT,DEFAULTS],LABELS,
- ATTRIBUTES,[OVERRIDE,FORCE]],@p);
- my($result,$selected);
-
- if (!$override && defined($self->param($name))) {
- $selected = $self->param($name);
- } else {
- $selected = $default;
- }
- $name=$self->escapeHTML($name);
- my($other) = @other ? " @other" : '';
-
- my(@values);
- @values = $self->_set_values_and_labels($values,\$labels,$name);
-
- $result = qq/<select name="$name"$other>\n/;
- foreach (@values) {
- if (/<optgroup/) {
- foreach (split(/\n/)) {
- my $selectit = $XHTML ? 'selected="selected"' : 'selected';
- s/(value="$selected")/$selectit $1/ if defined $selected;
- $result .= "$_\n";
- }
- }
- else {
- my $attribs = $self->_set_attributes($_, $attributes);
- my($selectit) = defined($selected) ? $self->_selected($selected eq $_) : '';
- my($label) = $_;
- $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
- my($value) = $self->escapeHTML($_);
- $label=$self->escapeHTML($label,1);
- $result .= "<option$selectit$attribs value=\"$value\">$label</option>\n";
- }
- }
-
- $result .= "</select>";
- return $result;
-}
-END_OF_FUNC
-
-
-#### Method: optgroup
-# Create a optgroup.
-# Parameters:
-# $name -> Label for the group
-# $values -> A pointer to a regular array containing the
-# values for each option line in the group.
-# $labels -> (optional)
-# A pointer to an associative array of labels to print next to each item
-# in the form $label{'value'}="Long explanatory label".
-# Otherwise the provided values are used as the labels.
-# $labeled -> (optional)
-# A true value indicates the value should be used as the label attribute
-# in the option elements.
-# The label attribute specifies the option label presented to the user.
-# This defaults to the content of the <option> element, but the label
-# attribute allows authors to more easily use optgroup without sacrificing
-# compatibility with browsers that do not support option groups.
-# $novals -> (optional)
-# A true value indicates to suppress the val attribute in the option elements
-# Returns:
-# A string containing the definition of an option group.
-####
-'optgroup' => <<'END_OF_FUNC',
-sub optgroup {
- my($self,@p) = self_or_default(@_);
- my($name,$values,$attributes,$labeled,$noval,$labels,@other)
- = rearrange([NAME,[VALUES,VALUE],ATTRIBUTES,LABELED,NOVALS,LABELS],@p);
-
- my($result,@values);
- @values = $self->_set_values_and_labels($values,\$labels,$name,$labeled,$novals);
- my($other) = @other ? " @other" : '';
-
- $name=$self->escapeHTML($name);
- $result = qq/<optgroup label="$name"$other>\n/;
- foreach (@values) {
- if (/<optgroup/) {
- foreach (split(/\n/)) {
- my $selectit = $XHTML ? 'selected="selected"' : 'selected';
- s/(value="$selected")/$selectit $1/ if defined $selected;
- $result .= "$_\n";
- }
- }
- else {
- my $attribs = $self->_set_attributes($_, $attributes);
- my($label) = $_;
- $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
- $label=$self->escapeHTML($label);
- my($value)=$self->escapeHTML($_,1);
- $result .= $labeled ? $novals ? "<option$attribs label=\"$value\">$label</option>\n"
- : "<option$attribs label=\"$value\" value=\"$value\">$label</option>\n"
- : $novals ? "<option$attribs>$label</option>\n"
- : "<option$attribs value=\"$value\">$label</option>\n";
- }
- }
- $result .= "</optgroup>";
- return $result;
-}
-END_OF_FUNC
-
-
-#### Method: scrolling_list
-# Create a scrolling list.
-# Parameters:
-# $name -> name for the list
-# $values -> A pointer to a regular array containing the
-# values for each option line in the list.
-# $defaults -> (optional)
-# 1. If a pointer to a regular array of options,
-# then this will be used to decide which
-# lines to turn on by default.
-# 2. Otherwise holds the value of the single line to turn on.
-# $size -> (optional) Size of the list.
-# $multiple -> (optional) If set, allow multiple selections.
-# $labels -> (optional)
-# A pointer to an associative array of labels to print next to each checkbox
-# in the form $label{'value'}="Long explanatory label".
-# Otherwise the provided values are used as the labels.
-# Returns:
-# A string containing the definition of a scrolling list.
-####
-'scrolling_list' => <<'END_OF_FUNC',
-sub scrolling_list {
- my($self,@p) = self_or_default(@_);
- my($name,$values,$defaults,$size,$multiple,$labels,$attributes,$override,@other)
- = rearrange([NAME,[VALUES,VALUE],[DEFAULTS,DEFAULT],
- SIZE,MULTIPLE,LABELS,ATTRIBUTES,[OVERRIDE,FORCE]],@p);
-
- my($result,@values);
- @values = $self->_set_values_and_labels($values,\$labels,$name);
-
- $size = $size || scalar(@values);
-
- my(%selected) = $self->previous_or_default($name,$defaults,$override);
- my($is_multiple) = $multiple ? qq/ multiple="multiple"/ : '';
- my($has_size) = $size ? qq/ size="$size"/: '';
- my($other) = @other ? " @other" : '';
-
- $name=$self->escapeHTML($name);
- $result = qq/<select name="$name"$has_size$is_multiple$other>\n/;
- foreach (@values) {
- my($selectit) = $self->_selected($selected{$_});
- my($label) = $_;
- $label = $labels->{$_} if defined($labels) && defined($labels->{$_});
- $label=$self->escapeHTML($label);
- my($value)=$self->escapeHTML($_,1);
- my $attribs = $self->_set_attributes($_, $attributes);
- $result .= "<option$selectit$attribs value=\"$value\">$label</option>\n";
- }
- $result .= "</select>";
- $self->register_parameter($name);
- return $result;
-}
-END_OF_FUNC
-
-
-#### Method: hidden
-# Parameters:
-# $name -> Name of the hidden field
-# @default -> (optional) Initial values of field (may be an array)
-# or
-# $default->[initial values of field]
-# Returns:
-# A string containing a <input type="hidden" name="name" value="value">
-####
-'hidden' => <<'END_OF_FUNC',
-sub hidden {
- my($self,@p) = self_or_default(@_);
-
- # this is the one place where we departed from our standard
- # calling scheme, so we have to special-case (darn)
- my(@result,@value);
- my($name,$default,$override,@other) =
- rearrange([NAME,[DEFAULT,VALUE,VALUES],[OVERRIDE,FORCE]],@p);
-
- my $do_override = 0;
- if ( ref($p[0]) || substr($p[0],0,1) eq '-') {
- @value = ref($default) ? @{$default} : $default;
- $do_override = $override;
- } else {
- foreach ($default,$override,@other) {
- push(@value,$_) if defined($_);
- }
- }
-
- # use previous values if override is not set
- my @prev = $self->param($name);
- @value = @prev if !$do_override && @prev;
-
- $name=$self->escapeHTML($name);
- foreach (@value) {
- $_ = defined($_) ? $self->escapeHTML($_,1) : '';
- push @result,$XHTML ? qq(<input type="hidden" name="$name" value="$_" @other />)
- : qq(<input type="hidden" name="$name" value="$_" @other>);
- }
- return wantarray ? @result : join('',@result);
-}
-END_OF_FUNC
-
-
-#### Method: image_button
-# Parameters:
-# $name -> Name of the button
-# $src -> URL of the image source
-# $align -> Alignment style (TOP, BOTTOM or MIDDLE)
-# Returns:
-# A string containing a <input type="image" name="name" src="url" align="alignment">
-####
-'image_button' => <<'END_OF_FUNC',
-sub image_button {
- my($self,@p) = self_or_default(@_);
-
- my($name,$src,$alignment,@other) =
- rearrange([NAME,SRC,ALIGN],@p);
-
- my($align) = $alignment ? " align=\U\"$alignment\"" : '';
- my($other) = @other ? " @other" : '';
- $name=$self->escapeHTML($name);
- return $XHTML ? qq(<input type="image" name="$name" src="$src"$align$other />)
- : qq/<input type="image" name="$name" src="$src"$align$other>/;
-}
-END_OF_FUNC
-
-
-#### Method: self_url
-# Returns a URL containing the current script and all its
-# param/value pairs arranged as a query. You can use this
-# to create a link that, when selected, will reinvoke the
-# script with all its state information preserved.
-####
-'self_url' => <<'END_OF_FUNC',
-sub self_url {
- my($self,@p) = self_or_default(@_);
- return $self->url('-path_info'=>1,'-query'=>1,'-full'=>1,@p);
-}
-END_OF_FUNC
-
-
-# This is provided as a synonym to self_url() for people unfortunate
-# enough to have incorporated it into their programs already!
-'state' => <<'END_OF_FUNC',
-sub state {
- &self_url;
-}
-END_OF_FUNC
-
-
-#### Method: url
-# Like self_url, but doesn't return the query string part of
-# the URL.
-####
-'url' => <<'END_OF_FUNC',
-sub url {
- my($self,@p) = self_or_default(@_);
- my ($relative,$absolute,$full,$path_info,$query,$base) =
- rearrange(['RELATIVE','ABSOLUTE','FULL',['PATH','PATH_INFO'],['QUERY','QUERY_STRING'],'BASE'],@p);
- my $url;
- $full++ if $base || !($relative || $absolute);
-
- my $path = $self->path_info;
- my $script_name = $self->script_name;
-
- # for compatibility with Apache's MultiViews
- if (exists($ENV{REQUEST_URI})) {
- my $index;
- $script_name = unescape($ENV{REQUEST_URI});
- $script_name =~ s/\?.+$//s; # strip query string
- # and path
- if (exists($ENV{PATH_INFO})) {
- my $encoded_path = unescape($ENV{PATH_INFO});
- $script_name =~ s/\Q$encoded_path\E$//i;
- }
- }
-
- if ($full) {
- my $protocol = $self->protocol();
- $url = "$protocol://";
- my $vh = http('x_forwarded_host') || http('host');
- if ($vh) {
- $url .= $vh;
- } else {
- $url .= server_name();
- my $port = $self->server_port;
- $url .= ":" . $port
- unless (lc($protocol) eq 'http' && $port == 80)
- || (lc($protocol) eq 'https' && $port == 443);
- }
- return $url if $base;
- $url .= $script_name;
- } elsif ($relative) {
- ($url) = $script_name =~ m!([^/]+)$!;
- } elsif ($absolute) {
- $url = $script_name;
- }
-
- $url .= $path if $path_info and defined $path;
- $url .= "?" . $self->query_string if $query and $self->query_string;
- $url = '' unless defined $url;
- $url =~ s/([^a-zA-Z0-9_.%;&?\/\\:+=~-])/sprintf("%%%02X",ord($1))/eg;
- return $url;
-}
-
-END_OF_FUNC
-
-#### Method: cookie
-# Set or read a cookie from the specified name.
-# Cookie can then be passed to header().
-# Usual rules apply to the stickiness of -value.
-# Parameters:
-# -name -> name for this cookie (optional)
-# -value -> value of this cookie (scalar, array or hash)
-# -path -> paths for which this cookie is valid (optional)
-# -domain -> internet domain in which this cookie is valid (optional)
-# -secure -> if true, cookie only passed through secure channel (optional)
-# -expires -> expiry date in format Wdy, DD-Mon-YYYY HH:MM:SS GMT (optional)
-####
-'cookie' => <<'END_OF_FUNC',
-sub cookie {
- my($self,@p) = self_or_default(@_);
- my($name,$value,$path,$domain,$secure,$expires) =
- rearrange([NAME,[VALUE,VALUES],PATH,DOMAIN,SECURE,EXPIRES],@p);
-
- require CGI::Cookie;
-
- # if no value is supplied, then we retrieve the
- # value of the cookie, if any. For efficiency, we cache the parsed
- # cookies in our state variables.
- unless ( defined($value) ) {
- $self->{'.cookies'} = CGI::Cookie->fetch
- unless $self->{'.cookies'};
-
- # If no name is supplied, then retrieve the names of all our cookies.
- return () unless $self->{'.cookies'};
- return keys %{$self->{'.cookies'}} unless $name;
- return () unless $self->{'.cookies'}->{$name};
- return $self->{'.cookies'}->{$name}->value if defined($name) && $name ne '';
- }
-
- # If we get here, we're creating a new cookie
- return undef unless defined($name) && $name ne ''; # this is an error
-
- my @param;
- push(@param,'-name'=>$name);
- push(@param,'-value'=>$value);
- push(@param,'-domain'=>$domain) if $domain;
- push(@param,'-path'=>$path) if $path;
- push(@param,'-expires'=>$expires) if $expires;
- push(@param,'-secure'=>$secure) if $secure;
-
- return new CGI::Cookie(@param);
-}
-END_OF_FUNC
-
-'parse_keywordlist' => <<'END_OF_FUNC',
-sub parse_keywordlist {
- my($self,$tosplit) = @_;
- $tosplit = unescape($tosplit); # unescape the keywords
- $tosplit=~tr/+/ /; # pluses to spaces
- my(@keywords) = split(/\s+/,$tosplit);
- return @keywords;
-}
-END_OF_FUNC
-
-'param_fetch' => <<'END_OF_FUNC',
-sub param_fetch {
- my($self,@p) = self_or_default(@_);
- my($name) = rearrange([NAME],@p);
- unless (exists($self->{$name})) {
- $self->add_parameter($name);
- $self->{$name} = [];
- }
-
- return $self->{$name};
-}
-END_OF_FUNC
-
-###############################################
-# OTHER INFORMATION PROVIDED BY THE ENVIRONMENT
-###############################################
-
-#### Method: path_info
-# Return the extra virtual path information provided
-# after the URL (if any)
-####
-'path_info' => <<'END_OF_FUNC',
-sub path_info {
- my ($self,$info) = self_or_default(@_);
- if (defined($info)) {
- $info = "/$info" if $info ne '' && substr($info,0,1) ne '/';
- $self->{'.path_info'} = $info;
- } elsif (! defined($self->{'.path_info'}) ) {
- $self->{'.path_info'} = defined($ENV{'PATH_INFO'}) ?
- $ENV{'PATH_INFO'} : '';
-
- # hack to fix broken path info in IIS
- $self->{'.path_info'} =~ s/^\Q$ENV{'SCRIPT_NAME'}\E// if $IIS;
-
- }
- return $self->{'.path_info'};
-}
-END_OF_FUNC
-
-
-#### Method: request_method
-# Returns 'POST', 'GET', 'PUT' or 'HEAD'
-####
-'request_method' => <<'END_OF_FUNC',
-sub request_method {
- return $ENV{'REQUEST_METHOD'};
-}
-END_OF_FUNC
-
-#### Method: content_type
-# Returns the content_type string
-####
-'content_type' => <<'END_OF_FUNC',
-sub content_type {
- return $ENV{'CONTENT_TYPE'};
-}
-END_OF_FUNC
-
-#### Method: path_translated
-# Return the physical path information provided
-# by the URL (if any)
-####
-'path_translated' => <<'END_OF_FUNC',
-sub path_translated {
- return $ENV{'PATH_TRANSLATED'};
-}
-END_OF_FUNC
-
-
-#### Method: query_string
-# Synthesize a query string from our current
-# parameters
-####
-'query_string' => <<'END_OF_FUNC',
-sub query_string {
- my($self) = self_or_default(@_);
- my($param,$value,@pairs);
- foreach $param ($self->param) {
- my($eparam) = escape($param);
- foreach $value ($self->param($param)) {
- $value = escape($value);
- next unless defined $value;
- push(@pairs,"$eparam=$value");
- }
- }
- foreach (keys %{$self->{'.fieldnames'}}) {
- push(@pairs,".cgifields=".escape("$_"));
- }
- return join($USE_PARAM_SEMICOLONS ? ';' : '&',@pairs);
-}
-END_OF_FUNC
-
-
-#### Method: accept
-# Without parameters, returns an array of the
-# MIME types the browser accepts.
-# With a single parameter equal to a MIME
-# type, will return undef if the browser won't
-# accept it, 1 if the browser accepts it but
-# doesn't give a preference, or a floating point
-# value between 0.0 and 1.0 if the browser
-# declares a quantitative score for it.
-# This handles MIME type globs correctly.
-####
-'Accept' => <<'END_OF_FUNC',
-sub Accept {
- my($self,$search) = self_or_CGI(@_);
- my(%prefs,$type,$pref,$pat);
-
- my(@accept) = split(',',$self->http('accept'));
-
- foreach (@accept) {
- ($pref) = /q=(\d\.\d+|\d+)/;
- ($type) = m#(\S+/[^;]+)#;
- next unless $type;
- $prefs{$type}=$pref || 1;
- }
-
- return keys %prefs unless $search;
-
- # if a search type is provided, we may need to
- # perform a pattern matching operation.
- # The MIME types use a glob mechanism, which
- # is easily translated into a perl pattern match
-
- # First return the preference for directly supported
- # types:
- return $prefs{$search} if $prefs{$search};
-
- # Didn't get it, so try pattern matching.
- foreach (keys %prefs) {
- next unless /\*/; # not a pattern match
- ($pat = $_) =~ s/([^\w*])/\\$1/g; # escape meta characters
- $pat =~ s/\*/.*/g; # turn it into a pattern
- return $prefs{$_} if $search=~/$pat/;
- }
-}
-END_OF_FUNC
-
-
-#### Method: user_agent
-# If called with no parameters, returns the user agent.
-# If called with one parameter, does a pattern match (case
-# insensitive) on the user agent.
-####
-'user_agent' => <<'END_OF_FUNC',
-sub user_agent {
- my($self,$match)=self_or_CGI(@_);
- return $self->http('user_agent') unless $match;
- return $self->http('user_agent') =~ /$match/i;
-}
-END_OF_FUNC
-
-
-#### Method: raw_cookie
-# Returns the magic cookies for the session.
-# The cookies are not parsed or altered in any way, i.e.
-# cookies are returned exactly as given in the HTTP
-# headers. If a cookie name is given, only that cookie's
-# value is returned, otherwise the entire raw cookie
-# is returned.
-####
-'raw_cookie' => <<'END_OF_FUNC',
-sub raw_cookie {
- my($self,$key) = self_or_CGI(@_);
-
- require CGI::Cookie;
-
- if (defined($key)) {
- $self->{'.raw_cookies'} = CGI::Cookie->raw_fetch
- unless $self->{'.raw_cookies'};
-
- return () unless $self->{'.raw_cookies'};
- return () unless $self->{'.raw_cookies'}->{$key};
- return $self->{'.raw_cookies'}->{$key};
- }
- return $self->http('cookie') || $ENV{'COOKIE'} || '';
-}
-END_OF_FUNC
-
-#### Method: virtual_host
-# Return the name of the virtual_host, which
-# is not always the same as the server
-######
-'virtual_host' => <<'END_OF_FUNC',
-sub virtual_host {
- my $vh = http('x_forwarded_host') || http('host') || server_name();
- $vh =~ s/:\d+$//; # get rid of port number
- return $vh;
-}
-END_OF_FUNC
-
-#### Method: remote_host
-# Return the name of the remote host, or its IP
-# address if unavailable. If this variable isn't
-# defined, it returns "localhost" for debugging
-# purposes.
-####
-'remote_host' => <<'END_OF_FUNC',
-sub remote_host {
- return $ENV{'REMOTE_HOST'} || $ENV{'REMOTE_ADDR'}
- || 'localhost';
-}
-END_OF_FUNC
-
-
-#### Method: remote_addr
-# Return the IP addr of the remote host.
-####
-'remote_addr' => <<'END_OF_FUNC',
-sub remote_addr {
- return $ENV{'REMOTE_ADDR'} || '127.0.0.1';
-}
-END_OF_FUNC
-
-
-#### Method: script_name
-# Return the partial URL to this script for
-# self-referencing scripts. Also see
-# self_url(), which returns a URL with all state information
-# preserved.
-####
-'script_name' => <<'END_OF_FUNC',
-sub script_name {
- return $ENV{'SCRIPT_NAME'} if defined($ENV{'SCRIPT_NAME'});
- # These are for debugging
- return "/$0" unless $0=~/^\//;
- return $0;
-}
-END_OF_FUNC
-
-
-#### Method: referer
-# Return the HTTP_REFERER: useful for generating
-# a GO BACK button.
-####
-'referer' => <<'END_OF_FUNC',
-sub referer {
- my($self) = self_or_CGI(@_);
- return $self->http('referer');
-}
-END_OF_FUNC
-
-
-#### Method: server_name
-# Return the name of the server
-####
-'server_name' => <<'END_OF_FUNC',
-sub server_name {
- return $ENV{'SERVER_NAME'} || 'localhost';
-}
-END_OF_FUNC
-
-#### Method: server_software
-# Return the name of the server software
-####
-'server_software' => <<'END_OF_FUNC',
-sub server_software {
- return $ENV{'SERVER_SOFTWARE'} || 'cmdline';
-}
-END_OF_FUNC
-
-#### Method: virtual_port
-# Return the server port, taking virtual hosts into account
-####
-'virtual_port' => <<'END_OF_FUNC',
-sub virtual_port {
- my($self) = self_or_default(@_);
- my $vh = $self->http('x_forwarded_host') || $self->http('host');
- if ($vh) {
- return ($vh =~ /:(\d+)$/)[0] || '80';
- } else {
- return $self->server_port();
- }
-}
-END_OF_FUNC
-
-#### Method: server_port
-# Return the tcp/ip port the server is running on
-####
-'server_port' => <<'END_OF_FUNC',
-sub server_port {
- return $ENV{'SERVER_PORT'} || 80; # for debugging
-}
-END_OF_FUNC
-
-#### Method: server_protocol
-# Return the protocol (usually HTTP/1.0)
-####
-'server_protocol' => <<'END_OF_FUNC',
-sub server_protocol {
- return $ENV{'SERVER_PROTOCOL'} || 'HTTP/1.0'; # for debugging
-}
-END_OF_FUNC
-
-#### Method: http
-# Return the value of an HTTP variable, or
-# the list of variables if none provided
-####
-'http' => <<'END_OF_FUNC',
-sub http {
- my ($self,$parameter) = self_or_CGI(@_);
- return $ENV{$parameter} if $parameter=~/^HTTP/;
- $parameter =~ tr/-/_/;
- return $ENV{"HTTP_\U$parameter\E"} if $parameter;
- my(@p);
- foreach (keys %ENV) {
- push(@p,$_) if /^HTTP/;
- }
- return @p;
-}
-END_OF_FUNC
-
-#### Method: https
-# Return the value of HTTPS
-####
-'https' => <<'END_OF_FUNC',
-sub https {
- local($^W)=0;
- my ($self,$parameter) = self_or_CGI(@_);
- return $ENV{HTTPS} unless $parameter;
- return $ENV{$parameter} if $parameter=~/^HTTPS/;
- $parameter =~ tr/-/_/;
- return $ENV{"HTTPS_\U$parameter\E"} if $parameter;
- my(@p);
- foreach (keys %ENV) {
- push(@p,$_) if /^HTTPS/;
- }
- return @p;
-}
-END_OF_FUNC
-
-#### Method: protocol
-# Return the protocol (http or https currently)
-####
-'protocol' => <<'END_OF_FUNC',
-sub protocol {
- local($^W)=0;
- my $self = shift;
- return 'https' if uc($self->https()) eq 'ON';
- return 'https' if $self->server_port == 443;
- my $prot = $self->server_protocol;
- my($protocol,$version) = split('/',$prot);
- return "\L$protocol\E";
-}
-END_OF_FUNC
-
-#### Method: remote_ident
-# Return the identity of the remote user
-# (but only if his host is running identd)
-####
-'remote_ident' => <<'END_OF_FUNC',
-sub remote_ident {
- return $ENV{'REMOTE_IDENT'};
-}
-END_OF_FUNC
-
-
-#### Method: auth_type
-# Return the type of use verification/authorization in use, if any.
-####
-'auth_type' => <<'END_OF_FUNC',
-sub auth_type {
- return $ENV{'AUTH_TYPE'};
-}
-END_OF_FUNC
-
-
-#### Method: remote_user
-# Return the authorization name used for user
-# verification.
-####
-'remote_user' => <<'END_OF_FUNC',
-sub remote_user {
- return $ENV{'REMOTE_USER'};
-}
-END_OF_FUNC
-
-
-#### Method: user_name
-# Try to return the remote user's name by hook or by
-# crook
-####
-'user_name' => <<'END_OF_FUNC',
-sub user_name {
- my ($self) = self_or_CGI(@_);
- return $self->http('from') || $ENV{'REMOTE_IDENT'} || $ENV{'REMOTE_USER'};
-}
-END_OF_FUNC
-
-#### Method: nosticky
-# Set or return the NOSTICKY global flag
-####
-'nosticky' => <<'END_OF_FUNC',
-sub nosticky {
- my ($self,$param) = self_or_CGI(@_);
- $CGI::NOSTICKY = $param if defined($param);
- return $CGI::NOSTICKY;
-}
-END_OF_FUNC
-
-#### Method: nph
-# Set or return the NPH global flag
-####
-'nph' => <<'END_OF_FUNC',
-sub nph {
- my ($self,$param) = self_or_CGI(@_);
- $CGI::NPH = $param if defined($param);
- return $CGI::NPH;
-}
-END_OF_FUNC
-
-#### Method: private_tempfiles
-# Set or return the private_tempfiles global flag
-####
-'private_tempfiles' => <<'END_OF_FUNC',
-sub private_tempfiles {
- my ($self,$param) = self_or_CGI(@_);
- $CGI::PRIVATE_TEMPFILES = $param if defined($param);
- return $CGI::PRIVATE_TEMPFILES;
-}
-END_OF_FUNC
-#### Method: close_upload_files
-# Set or return the close_upload_files global flag
-####
-'close_upload_files' => <<'END_OF_FUNC',
-sub close_upload_files {
- my ($self,$param) = self_or_CGI(@_);
- $CGI::CLOSE_UPLOAD_FILES = $param if defined($param);
- return $CGI::CLOSE_UPLOAD_FILES;
-}
-END_OF_FUNC
-
-
-#### Method: default_dtd
-# Set or return the default_dtd global
-####
-'default_dtd' => <<'END_OF_FUNC',
-sub default_dtd {
- my ($self,$param,$param2) = self_or_CGI(@_);
- if (defined $param2 && defined $param) {
- $CGI::DEFAULT_DTD = [ $param, $param2 ];
- } elsif (defined $param) {
- $CGI::DEFAULT_DTD = $param;
- }
- return $CGI::DEFAULT_DTD;
-}
-END_OF_FUNC
-
-# -------------- really private subroutines -----------------
-'previous_or_default' => <<'END_OF_FUNC',
-sub previous_or_default {
- my($self,$name,$defaults,$override) = @_;
- my(%selected);
-
- if (!$override && ($self->{'.fieldnames'}->{$name} ||
- defined($self->param($name)) ) ) {
- grep($selected{$_}++,$self->param($name));
- } elsif (defined($defaults) && ref($defaults) &&
- (ref($defaults) eq 'ARRAY')) {
- grep($selected{$_}++,@{$defaults});
- } else {
- $selected{$defaults}++ if defined($defaults);
- }
-
- return %selected;
-}
-END_OF_FUNC
-
-'register_parameter' => <<'END_OF_FUNC',
-sub register_parameter {
- my($self,$param) = @_;
- $self->{'.parametersToAdd'}->{$param}++;
-}
-END_OF_FUNC
-
-'get_fields' => <<'END_OF_FUNC',
-sub get_fields {
- my($self) = @_;
- return $self->CGI::hidden('-name'=>'.cgifields',
- '-values'=>[keys %{$self->{'.parametersToAdd'}}],
- '-override'=>1);
-}
-END_OF_FUNC
-
-'read_from_cmdline' => <<'END_OF_FUNC',
-sub read_from_cmdline {
- my($input,@words);
- my($query_string);
- my($subpath);
- if ($DEBUG && @ARGV) {
- @words = @ARGV;
- } elsif ($DEBUG > 1) {
- require "shellwords.pl";
- print STDERR "(offline mode: enter name=value pairs on standard input; press ^D or ^Z when done)\n";
- chomp(@lines = <STDIN>); # remove newlines
- $input = join(" ",@lines);
- @words = &shellwords($input);
- }
- foreach (@words) {
- s/\\=/%3D/g;
- s/\\&/%26/g;
- }
-
- if ("@words"=~/=/) {
- $query_string = join('&',@words);
- } else {
- $query_string = join('+',@words);
- }
- if ($query_string =~ /^(.*?)\?(.*)$/)
- {
- $query_string = $2;
- $subpath = $1;
- }
- return { 'query_string' => $query_string, 'subpath' => $subpath };
-}
-END_OF_FUNC
-
-#####
-# subroutine: read_multipart
-#
-# Read multipart data and store it into our parameters.
-# An interesting feature is that if any of the parts is a file, we
-# create a temporary file and open up a filehandle on it so that the
-# caller can read from it if necessary.
-#####
-'read_multipart' => <<'END_OF_FUNC',
-sub read_multipart {
- my($self,$boundary,$length) = @_;
- my($buffer) = $self->new_MultipartBuffer($boundary,$length);
- return unless $buffer;
- my(%header,$body);
- my $filenumber = 0;
- while (!$buffer->eof) {
- %header = $buffer->readHeader;
-
- unless (%header) {
- $self->cgi_error("400 Bad request (malformed multipart POST)");
- return;
- }
-
- my($param)= $header{'Content-Disposition'}=~/ name="([^;]*)"/;
- $param .= $TAINTED;
-
- # Bug: Netscape doesn't escape quotation marks in file names!!!
- my($filename) = $header{'Content-Disposition'}=~/ filename="([^;]*)"/;
- # Test for Opera's multiple upload feature
- my($multipart) = ( defined( $header{'Content-Type'} ) &&
- $header{'Content-Type'} =~ /multipart\/mixed/ ) ?
- 1 : 0;
-
- # add this parameter to our list
- $self->add_parameter($param);
-
- # If no filename specified, then just read the data and assign it
- # to our parameter list.
- if ( ( !defined($filename) || $filename eq '' ) && !$multipart ) {
- my($value) = $buffer->readBody;
- $value .= $TAINTED;
- push(@{$self->{$param}},$value);
- next;
- }
-
- my ($tmpfile,$tmp,$filehandle);
- UPLOADS: {
- # If we get here, then we are dealing with a potentially large
- # uploaded form. Save the data to a temporary file, then open
- # the file for reading.
-
- # skip the file if uploads disabled
- if ($DISABLE_UPLOADS) {
- while (defined($data = $buffer->read)) { }
- last UPLOADS;
- }
-
- # set the filename to some recognizable value
- if ( ( !defined($filename) || $filename eq '' ) && $multipart ) {
- $filename = "multipart/mixed";
- }
-
- # choose a relatively unpredictable tmpfile sequence number
- my $seqno = unpack("%16C*",join('',localtime,values %ENV));
- for (my $cnt=10;$cnt>0;$cnt--) {
- next unless $tmpfile = new CGITempFile($seqno);
- $tmp = $tmpfile->as_string;
- last if defined($filehandle = Fh->new($filename,$tmp,$PRIVATE_TEMPFILES));
- $seqno += int rand(100);
- }
- die "CGI open of tmpfile: $!\n" unless defined $filehandle;
- $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode
- && defined fileno($filehandle);
-
- # if this is an multipart/mixed attachment, save the header
- # together with the body for later parsing with an external
- # MIME parser module
- if ( $multipart ) {
- foreach ( keys %header ) {
- print $filehandle "$_: $header{$_}${CRLF}";
- }
- print $filehandle "${CRLF}";
- }
-
- my ($data);
- local($\) = '';
- my $totalbytes;
- while (defined($data = $buffer->read)) {
- if (defined $self->{'.upload_hook'})
- {
- $totalbytes += length($data);
- &{$self->{'.upload_hook'}}($filename ,$data, $totalbytes, $self->{'.upload_data'});
- }
- print $filehandle $data;
- }
-
- # back up to beginning of file
- seek($filehandle,0,0);
-
- ## Close the filehandle if requested this allows a multipart MIME
- ## upload to contain many files, and we won't die due to too many
- ## open file handles. The user can access the files using the hash
- ## below.
- close $filehandle if $CLOSE_UPLOAD_FILES;
- $CGI::DefaultClass->binmode($filehandle) if $CGI::needs_binmode;
-
- # Save some information about the uploaded file where we can get
- # at it later.
- $self->{'.tmpfiles'}->{fileno($filehandle)}= {
- hndl => $filehandle,
- name => $tmpfile,
- info => {%header},
- };
- push(@{$self->{$param}},$filehandle);
- }
- }
-}
-END_OF_FUNC
-
-'upload' =><<'END_OF_FUNC',
-sub upload {
- my($self,$param_name) = self_or_default(@_);
- my @param = grep(ref && fileno($_), $self->param($param_name));
- return unless @param;
- return wantarray ? @param : $param[0];
-}
-END_OF_FUNC
-
-'tmpFileName' => <<'END_OF_FUNC',
-sub tmpFileName {
- my($self,$filename) = self_or_default(@_);
- return $self->{'.tmpfiles'}->{fileno($filename)}->{name} ?
- $self->{'.tmpfiles'}->{fileno($filename)}->{name}->as_string
- : '';
-}
-END_OF_FUNC
-
-'uploadInfo' => <<'END_OF_FUNC',
-sub uploadInfo {
- my($self,$filename) = self_or_default(@_);
- return $self->{'.tmpfiles'}->{fileno($filename)}->{info};
-}
-END_OF_FUNC
-
-# internal routine, don't use
-'_set_values_and_labels' => <<'END_OF_FUNC',
-sub _set_values_and_labels {
- my $self = shift;
- my ($v,$l,$n) = @_;
- $$l = $v if ref($v) eq 'HASH' && !ref($$l);
- return $self->param($n) if !defined($v);
- return $v if !ref($v);
- return ref($v) eq 'HASH' ? keys %$v : @$v;
-}
-END_OF_FUNC
-
-# internal routine, don't use
-'_set_attributes' => <<'END_OF_FUNC',
-sub _set_attributes {
- my $self = shift;
- my($element, $attributes) = @_;
- return '' unless defined($attributes->{$element});
- $attribs = ' ';
- foreach my $attrib (keys %{$attributes->{$element}}) {
- (my $clean_attrib = $attrib) =~ s/^-//;
- $attribs .= "@{[lc($clean_attrib)]}=\"$attributes->{$element}{$attrib}\" ";
- }
- $attribs =~ s/ $//;
- return $attribs;
-}
-END_OF_FUNC
-
-'_compile_all' => <<'END_OF_FUNC',
-sub _compile_all {
- foreach (@_) {
- next if defined(&$_);
- $AUTOLOAD = "CGI::$_";
- _compile();
- }
-}
-END_OF_FUNC
-
-);
-END_OF_AUTOLOAD
-;
-
-#########################################################
-# Globals and stubs for other packages that we use.
-#########################################################
-
-################### Fh -- lightweight filehandle ###############
-package Fh;
-use overload
- '""' => \&asString,
- 'cmp' => \&compare,
- 'fallback'=>1;
-
-$FH='fh00000';
-
-*Fh::AUTOLOAD = \&CGI::AUTOLOAD;
-
-$AUTOLOADED_ROUTINES = ''; # prevent -w error
-$AUTOLOADED_ROUTINES=<<'END_OF_AUTOLOAD';
-%SUBS = (
-'asString' => <<'END_OF_FUNC',
-sub asString {
- my $self = shift;
- # get rid of package name
- (my $i = $$self) =~ s/^\*(\w+::fh\d{5})+//;
- $i =~ s/%(..)/ chr(hex($1)) /eg;
- return $i.$CGI::TAINTED;
-# BEGIN DEAD CODE
-# This was an extremely clever patch that allowed "use strict refs".
-# Unfortunately it relied on another bug that caused leaky file descriptors.
-# The underlying bug has been fixed, so this no longer works. However
-# "strict refs" still works for some reason.
-# my $self = shift;
-# return ${*{$self}{SCALAR}};
-# END DEAD CODE
-}
-END_OF_FUNC
-
-'compare' => <<'END_OF_FUNC',
-sub compare {
- my $self = shift;
- my $value = shift;
- return "$self" cmp $value;
-}
-END_OF_FUNC
-
-'new' => <<'END_OF_FUNC',
-sub new {
- my($pack,$name,$file,$delete) = @_;
- _setup_symbols(@SAVED_SYMBOLS) if @SAVED_SYMBOLS;
- require Fcntl unless defined &Fcntl::O_RDWR;
- (my $safename = $name) =~ s/([':%])/ sprintf '%%%02X', ord $1 /eg;
- my $fv = ++$FH . $safename;
- my $ref = \*{"Fh::$fv"};
- $file =~ m!^([a-zA-Z0-9_ \'\":/.\$\\-]+)$! || return;
- my $safe = $1;
- sysopen($ref,$safe,Fcntl::O_RDWR()|Fcntl::O_CREAT()|Fcntl::O_EXCL(),0600) || return;
- unlink($safe) if $delete;
- CORE::delete $Fh::{$fv};
- return bless $ref,$pack;
-}
-END_OF_FUNC
-
-'DESTROY' => <<'END_OF_FUNC',
-sub DESTROY {
- my $self = shift;
- close $self;
-}
-END_OF_FUNC
-
-);
-END_OF_AUTOLOAD
-
-######################## MultipartBuffer ####################
-package MultipartBuffer;
-
-use constant DEBUG => 0;
-
-# how many bytes to read at a time. We use
-# a 4K buffer by default.
-$INITIAL_FILLUNIT = 1024 * 4;
-$TIMEOUT = 240*60; # 4 hour timeout for big files
-$SPIN_LOOP_MAX = 2000; # bug fix for some Netscape servers
-$CRLF=$CGI::CRLF;
-
-#reuse the autoload function
-*MultipartBuffer::AUTOLOAD = \&CGI::AUTOLOAD;
-
-# avoid autoloader warnings
-sub DESTROY {}
-
-###############################################################################
-################# THESE FUNCTIONS ARE AUTOLOADED ON DEMAND ####################
-###############################################################################
-$AUTOLOADED_ROUTINES = ''; # prevent -w error
-$AUTOLOADED_ROUTINES=<<'END_OF_AUTOLOAD';
-%SUBS = (
-
-'new' => <<'END_OF_FUNC',
-sub new {
- my($package,$interface,$boundary,$length) = @_;
- $FILLUNIT = $INITIAL_FILLUNIT;
- $CGI::DefaultClass->binmode($IN); # if $CGI::needs_binmode; # just do it always
-
- # If the user types garbage into the file upload field,
- # then Netscape passes NOTHING to the server (not good).
- # We may hang on this read in that case. So we implement
- # a read timeout. If nothing is ready to read
- # by then, we return.
-
- # Netscape seems to be a little bit unreliable
- # about providing boundary strings.
- my $boundary_read = 0;
- if ($boundary) {
-
- # Under the MIME spec, the boundary consists of the
- # characters "--" PLUS the Boundary string
-
- # BUG: IE 3.01 on the Macintosh uses just the boundary -- not
- # the two extra hyphens. We do a special case here on the user-agent!!!!
- $boundary = "--$boundary" unless CGI::user_agent('MSIE\s+3\.0[12];\s*Mac|DreamPassport');
-
- } else { # otherwise we find it ourselves
- my($old);
- ($old,$/) = ($/,$CRLF); # read a CRLF-delimited line
- $boundary = <STDIN>; # BUG: This won't work correctly under mod_perl
- $length -= length($boundary);
- chomp($boundary); # remove the CRLF
- $/ = $old; # restore old line separator
- $boundary_read++;
- }
-
- my $self = {LENGTH=>$length,
- BOUNDARY=>$boundary,
- INTERFACE=>$interface,
- BUFFER=>'',
- };
-
- $FILLUNIT = length($boundary)
- if length($boundary) > $FILLUNIT;
-
- my $retval = bless $self,ref $package || $package;
-
- # Read the preamble and the topmost (boundary) line plus the CRLF.
- unless ($boundary_read) {
- while ($self->read(0)) { }
- }
- die "Malformed multipart POST: data truncated\n" if $self->eof;
-
- return $retval;
-}
-END_OF_FUNC
-
-'readHeader' => <<'END_OF_FUNC',
-sub readHeader {
- my($self) = @_;
- my($end);
- my($ok) = 0;
- my($bad) = 0;
-
- local($CRLF) = "\015\012" if $CGI::OS eq 'VMS' || $CGI::EBCDIC;
-
- do {
- $self->fillBuffer($FILLUNIT);
- $ok++ if ($end = index($self->{BUFFER},"${CRLF}${CRLF}")) >= 0;
- $ok++ if $self->{BUFFER} eq '';
- $bad++ if !$ok && $self->{LENGTH} <= 0;
- # this was a bad idea
- # $FILLUNIT *= 2 if length($self->{BUFFER}) >= $FILLUNIT;
- } until $ok || $bad;
- return () if $bad;
-
- #EBCDIC NOTE: translate header into EBCDIC, but watch out for continuation lines!
-
- my($header) = substr($self->{BUFFER},0,$end+2);
- substr($self->{BUFFER},0,$end+4) = '';
- my %return;
-
- if ($CGI::EBCDIC) {
- warn "untranslated header=$header\n" if DEBUG;
- $header = CGI::Util::ascii2ebcdic($header);
- warn "translated header=$header\n" if DEBUG;
- }
-
- # See RFC 2045 Appendix A and RFC 822 sections 3.4.8
- # (Folding Long Header Fields), 3.4.3 (Comments)
- # and 3.4.5 (Quoted-Strings).
-
- my $token = '[-\w!\#$%&\'*+.^_\`|{}~]';
- $header=~s/$CRLF\s+/ /og; # merge continuation lines
-
- while ($header=~/($token+):\s+([^$CRLF]*)/mgox) {
- my ($field_name,$field_value) = ($1,$2);
- $field_name =~ s/\b(\w)/uc($1)/eg; #canonicalize
- $return{$field_name}=$field_value;
- }
- return %return;
-}
-END_OF_FUNC
-
-# This reads and returns the body as a single scalar value.
-'readBody' => <<'END_OF_FUNC',
-sub readBody {
- my($self) = @_;
- my($data);
- my($returnval)='';
-
- #EBCDIC NOTE: want to translate returnval into EBCDIC HERE
-
- while (defined($data = $self->read)) {
- $returnval .= $data;
- }
-
- if ($CGI::EBCDIC) {
- warn "untranslated body=$returnval\n" if DEBUG;
- $returnval = CGI::Util::ascii2ebcdic($returnval);
- warn "translated body=$returnval\n" if DEBUG;
- }
- return $returnval;
-}
-END_OF_FUNC
-
-# This will read $bytes or until the boundary is hit, whichever happens
-# first. After the boundary is hit, we return undef. The next read will
-# skip over the boundary and begin reading again;
-'read' => <<'END_OF_FUNC',
-sub read {
- my($self,$bytes) = @_;
-
- # default number of bytes to read
- $bytes = $bytes || $FILLUNIT;
-
- # Fill up our internal buffer in such a way that the boundary
- # is never split between reads.
- $self->fillBuffer($bytes);
-
- my $boundary_start = $CGI::EBCDIC ? CGI::Util::ebcdic2ascii($self->{BOUNDARY}) : $self->{BOUNDARY};
- my $boundary_end = $CGI::EBCDIC ? CGI::Util::ebcdic2ascii($self->{BOUNDARY}.'--') : $self->{BOUNDARY}.'--';
-
- # Find the boundary in the buffer (it may not be there).
- my $start = index($self->{BUFFER},$boundary_start);
-
- warn "boundary=$self->{BOUNDARY} length=$self->{LENGTH} start=$start\n" if DEBUG;
- # protect against malformed multipart POST operations
- die "Malformed multipart POST\n" unless ($start >= 0) || ($self->{LENGTH} > 0);
-
-
- #EBCDIC NOTE: want to translate boundary search into ASCII here.
-
- # If the boundary begins the data, then skip past it
- # and return undef.
- if ($start == 0) {
-
- # clear us out completely if we've hit the last boundary.
- if (index($self->{BUFFER},$boundary_end)==0) {
- $self->{BUFFER}='';
- $self->{LENGTH}=0;
- return undef;
- }
-
- # just remove the boundary.
- substr($self->{BUFFER},0,length($boundary_start))='';
- $self->{BUFFER} =~ s/^\012\015?//;
- return undef;
- }
-
- my $bytesToReturn;
- if ($start > 0) { # read up to the boundary
- $bytesToReturn = $start-2 > $bytes ? $bytes : $start;
- } else { # read the requested number of bytes
- # leave enough bytes in the buffer to allow us to read
- # the boundary. Thanks to Kevin Hendrick for finding
- # this one.
- $bytesToReturn = $bytes - (length($boundary_start)+1);
- }
-
- my $returnval=substr($self->{BUFFER},0,$bytesToReturn);
- substr($self->{BUFFER},0,$bytesToReturn)='';
-
- # If we hit the boundary, remove the CRLF from the end.
- return ($bytesToReturn==$start)
- ? substr($returnval,0,-2) : $returnval;
-}
-END_OF_FUNC
-
-
-# This fills up our internal buffer in such a way that the
-# boundary is never split between reads
-'fillBuffer' => <<'END_OF_FUNC',
-sub fillBuffer {
- my($self,$bytes) = @_;
- return unless $self->{LENGTH};
-
- my($boundaryLength) = length($self->{BOUNDARY});
- my($bufferLength) = length($self->{BUFFER});
- my($bytesToRead) = $bytes - $bufferLength + $boundaryLength + 2;
- $bytesToRead = $self->{LENGTH} if $self->{LENGTH} < $bytesToRead;
-
- # Try to read some data. We may hang here if the browser is screwed up.
- my $bytesRead = $self->{INTERFACE}->read_from_client(\$self->{BUFFER},
- $bytesToRead,
- $bufferLength);
- warn "bytesToRead=$bytesToRead, bufferLength=$bufferLength, buffer=$self->{BUFFER}\n" if DEBUG;
- $self->{BUFFER} = '' unless defined $self->{BUFFER};
-
- # An apparent bug in the Apache server causes the read()
- # to return zero bytes repeatedly without blocking if the
- # remote user aborts during a file transfer. I don't know how
- # they manage this, but the workaround is to abort if we get
- # more than SPIN_LOOP_MAX consecutive zero reads.
- if ($bytesRead == 0) {
- die "CGI.pm: Server closed socket during multipart read (client aborted?).\n"
- if ($self->{ZERO_LOOP_COUNTER}++ >= $SPIN_LOOP_MAX);
- } else {
- $self->{ZERO_LOOP_COUNTER}=0;
- }
-
- $self->{LENGTH} -= $bytesRead;
-}
-END_OF_FUNC
-
-
-# Return true when we've finished reading
-'eof' => <<'END_OF_FUNC'
-sub eof {
- my($self) = @_;
- return 1 if (length($self->{BUFFER}) == 0)
- && ($self->{LENGTH} <= 0);
- undef;
-}
-END_OF_FUNC
-
-);
-END_OF_AUTOLOAD
-
-####################################################################################
-################################## TEMPORARY FILES #################################
-####################################################################################
-package CGITempFile;
-
-sub find_tempdir {
- undef $TMPDIRECTORY;
- $SL = $CGI::SL;
- $MAC = $CGI::OS eq 'MACINTOSH';
- my ($vol) = $MAC ? MacPerl::Volumes() =~ /:(.*)/ : "";
- unless ($TMPDIRECTORY) {
- @TEMP=("${SL}usr${SL}tmp","${SL}var${SL}tmp",
- "C:${SL}temp","${SL}tmp","${SL}temp",
- "${vol}${SL}Temporary Items",
- "${SL}WWW_ROOT", "${SL}SYS\$SCRATCH",
- "C:${SL}system${SL}temp");
- unshift(@TEMP,$ENV{'TMPDIR'}) if defined $ENV{'TMPDIR'};
-
- # this feature was supposed to provide per-user tmpfiles, but
- # it is problematic.
- # unshift(@TEMP,(getpwuid($<))[7].'/tmp') if $CGI::OS eq 'UNIX';
- # Rob: getpwuid() is unfortunately UNIX specific. On brain dead OS'es this
- # : can generate a 'getpwuid() not implemented' exception, even though
- # : it's never called. Found under DOS/Win with the DJGPP perl port.
- # : Refer to getpwuid() only at run-time if we're fortunate and have UNIX.
- # unshift(@TEMP,(eval {(getpwuid($>))[7]}).'/tmp') if $CGI::OS eq 'UNIX' and $> != 0;
-
- foreach (@TEMP) {
- do {$TMPDIRECTORY = $_; last} if -d $_ && -w _;
- }
- }
- $TMPDIRECTORY = $MAC ? "" : "." unless $TMPDIRECTORY;
-}
-
-find_tempdir();
-
-$MAXTRIES = 5000;
-
-# cute feature, but overload implementation broke it
-# %OVERLOAD = ('""'=>'as_string');
-*CGITempFile::AUTOLOAD = \&CGI::AUTOLOAD;
-
-sub DESTROY {
- my($self) = @_;
- $$self =~ m!^([a-zA-Z0-9_ \'\":/.\$\\-]+)$! || return;
- my $safe = $1; # untaint operation
- unlink $safe; # get rid of the file
-}
-
-###############################################################################
-################# THESE FUNCTIONS ARE AUTOLOADED ON DEMAND ####################
-###############################################################################
-$AUTOLOADED_ROUTINES = ''; # prevent -w error
-$AUTOLOADED_ROUTINES=<<'END_OF_AUTOLOAD';
-%SUBS = (
-
-'new' => <<'END_OF_FUNC',
-sub new {
- my($package,$sequence) = @_;
- my $filename;
- find_tempdir() unless -w $TMPDIRECTORY;
- for (my $i = 0; $i < $MAXTRIES; $i++) {
- last if ! -f ($filename = sprintf("${TMPDIRECTORY}${SL}CGItemp%d",$sequence++));
- }
- # check that it is a more-or-less valid filename
- return unless $filename =~ m!^([a-zA-Z0-9_ \'\":/.\$\\-]+)$!;
- # this used to untaint, now it doesn't
- # $filename = $1;
- return bless \$filename;
-}
-END_OF_FUNC
-
-'as_string' => <<'END_OF_FUNC'
-sub as_string {
- my($self) = @_;
- return $$self;
-}
-END_OF_FUNC
-
-);
-END_OF_AUTOLOAD
-
-package CGI;
-
-# We get a whole bunch of warnings about "possibly uninitialized variables"
-# when running with the -w switch. Touch them all once to get rid of the
-# warnings. This is ugly and I hate it.
-if ($^W) {
- $CGI::CGI = '';
- $CGI::CGI=<<EOF;
- $CGI::VERSION;
- $MultipartBuffer::SPIN_LOOP_MAX;
- $MultipartBuffer::CRLF;
- $MultipartBuffer::TIMEOUT;
- $MultipartBuffer::INITIAL_FILLUNIT;
-EOF
- ;
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-CGI - Simple Common Gateway Interface Class
-
-=head1 SYNOPSIS
-
- # CGI script that creates a fill-out form
- # and echoes back its values.
-
- use CGI qw/:standard/;
- print header,
- start_html('A Simple Example'),
- h1('A Simple Example'),
- start_form,
- "What's your name? ",textfield('name'),p,
- "What's the combination?", p,
- checkbox_group(-name=>'words',
- -values=>['eenie','meenie','minie','moe'],
- -defaults=>['eenie','minie']), p,
- "What's your favorite color? ",
- popup_menu(-name=>'color',
- -values=>['red','green','blue','chartreuse']),p,
- submit,
- end_form,
- hr;
-
- if (param()) {
- print "Your name is",em(param('name')),p,
- "The keywords are: ",em(join(", ",param('words'))),p,
- "Your favorite color is ",em(param('color')),
- hr;
- }
-
-=head1 ABSTRACT
-
-This perl library uses perl5 objects to make it easy to create Web
-fill-out forms and parse their contents. This package defines CGI
-objects, entities that contain the values of the current query string
-and other state variables. Using a CGI object's methods, you can
-examine keywords and parameters passed to your script, and create
-forms whose initial values are taken from the current query (thereby
-preserving state information). The module provides shortcut functions
-that produce boilerplate HTML, reducing typing and coding errors. It
-also provides functionality for some of the more advanced features of
-CGI scripting, including support for file uploads, cookies, cascading
-style sheets, server push, and frames.
-
-CGI.pm also provides a simple function-oriented programming style for
-those who don't need its object-oriented features.
-
-The current version of CGI.pm is available at
-
- http://www.genome.wi.mit.edu/ftp/pub/software/WWW/cgi_docs.html
- ftp://ftp-genome.wi.mit.edu/pub/software/WWW/
-
-=head1 DESCRIPTION
-
-=head2 PROGRAMMING STYLE
-
-There are two styles of programming with CGI.pm, an object-oriented
-style and a function-oriented style. In the object-oriented style you
-create one or more CGI objects and then use object methods to create
-the various elements of the page. Each CGI object starts out with the
-list of named parameters that were passed to your CGI script by the
-server. You can modify the objects, save them to a file or database
-and recreate them. Because each object corresponds to the "state" of
-the CGI script, and because each object's parameter list is
-independent of the others, this allows you to save the state of the
-script and restore it later.
-
-For example, using the object oriented style, here is how you create
-a simple "Hello World" HTML page:
-
- #!/usr/local/bin/perl -w
- use CGI; # load CGI routines
- $q = new CGI; # create new CGI object
- print $q->header, # create the HTTP header
- $q->start_html('hello world'), # start the HTML
- $q->h1('hello world'), # level 1 header
- $q->end_html; # end the HTML
-
-In the function-oriented style, there is one default CGI object that
-you rarely deal with directly. Instead you just call functions to
-retrieve CGI parameters, create HTML tags, manage cookies, and so
-on. This provides you with a cleaner programming interface, but
-limits you to using one CGI object at a time. The following example
-prints the same page, but uses the function-oriented interface.
-The main differences are that we now need to import a set of functions
-into our name space (usually the "standard" functions), and we don't
-need to create the CGI object.
-
- #!/usr/local/bin/perl
- use CGI qw/:standard/; # load standard CGI routines
- print header, # create the HTTP header
- start_html('hello world'), # start the HTML
- h1('hello world'), # level 1 header
- end_html; # end the HTML
-
-The examples in this document mainly use the object-oriented style.
-See HOW TO IMPORT FUNCTIONS for important information on
-function-oriented programming in CGI.pm
-
-=head2 CALLING CGI.PM ROUTINES
-
-Most CGI.pm routines accept several arguments, sometimes as many as 20
-optional ones! To simplify this interface, all routines use a named
-argument calling style that looks like this:
-
- print $q->header(-type=>'image/gif',-expires=>'+3d');
-
-Each argument name is preceded by a dash. Neither case nor order
-matters in the argument list. -type, -Type, and -TYPE are all
-acceptable. In fact, only the first argument needs to begin with a
-dash. If a dash is present in the first argument, CGI.pm assumes
-dashes for the subsequent ones.
-
-Several routines are commonly called with just one argument. In the
-case of these routines you can provide the single argument without an
-argument name. header() happens to be one of these routines. In this
-case, the single argument is the document type.
-
- print $q->header('text/html');
-
-Other such routines are documented below.
-
-Sometimes named arguments expect a scalar, sometimes a reference to an
-array, and sometimes a reference to a hash. Often, you can pass any
-type of argument and the routine will do whatever is most appropriate.
-For example, the param() routine is used to set a CGI parameter to a
-single or a multi-valued value. The two cases are shown below:
-
- $q->param(-name=>'veggie',-value=>'tomato');
- $q->param(-name=>'veggie',-value=>['tomato','tomahto','potato','potahto']);
-
-A large number of routines in CGI.pm actually aren't specifically
-defined in the module, but are generated automatically as needed.
-These are the "HTML shortcuts," routines that generate HTML tags for
-use in dynamically-generated pages. HTML tags have both attributes
-(the attribute="value" pairs within the tag itself) and contents (the
-part between the opening and closing pairs.) To distinguish between
-attributes and contents, CGI.pm uses the convention of passing HTML
-attributes as a hash reference as the first argument, and the
-contents, if any, as any subsequent arguments. It works out like
-this:
-
- Code Generated HTML
- ---- --------------
- h1() <h1>
- h1('some','contents'); <h1>some contents</h1>
- h1({-align=>left}); <h1 align="LEFT">
- h1({-align=>left},'contents'); <h1 align="LEFT">contents</h1>
-
-HTML tags are described in more detail later.
-
-Many newcomers to CGI.pm are puzzled by the difference between the
-calling conventions for the HTML shortcuts, which require curly braces
-around the HTML tag attributes, and the calling conventions for other
-routines, which manage to generate attributes without the curly
-brackets. Don't be confused. As a convenience the curly braces are
-optional in all but the HTML shortcuts. If you like, you can use
-curly braces when calling any routine that takes named arguments. For
-example:
-
- print $q->header( {-type=>'image/gif',-expires=>'+3d'} );
-
-If you use the B<-w> switch, you will be warned that some CGI.pm argument
-names conflict with built-in Perl functions. The most frequent of
-these is the -values argument, used to create multi-valued menus,
-radio button clusters and the like. To get around this warning, you
-have several choices:
-
-=over 4
-
-=item 1.
-
-Use another name for the argument, if one is available.
-For example, -value is an alias for -values.
-
-=item 2.
-
-Change the capitalization, e.g. -Values
-
-=item 3.
-
-Put quotes around the argument name, e.g. '-values'
-
-=back
-
-Many routines will do something useful with a named argument that it
-doesn't recognize. For example, you can produce non-standard HTTP
-header fields by providing them as named arguments:
-
- print $q->header(-type => 'text/html',
- -cost => 'Three smackers',
- -annoyance_level => 'high',
- -complaints_to => 'bit bucket');
-
-This will produce the following nonstandard HTTP header:
-
- HTTP/1.0 200 OK
- Cost: Three smackers
- Annoyance-level: high
- Complaints-to: bit bucket
- Content-type: text/html
-
-Notice the way that underscores are translated automatically into
-hyphens. HTML-generating routines perform a different type of
-translation.
-
-This feature allows you to keep up with the rapidly changing HTTP and
-HTML "standards".
-
-=head2 CREATING A NEW QUERY OBJECT (OBJECT-ORIENTED STYLE):
-
- $query = new CGI;
-
-This will parse the input (from both POST and GET methods) and store
-it into a perl5 object called $query.
-
-=head2 CREATING A NEW QUERY OBJECT FROM AN INPUT FILE
-
- $query = new CGI(INPUTFILE);
-
-If you provide a file handle to the new() method, it will read
-parameters from the file (or STDIN, or whatever). The file can be in
-any of the forms describing below under debugging (i.e. a series of
-newline delimited TAG=VALUE pairs will work). Conveniently, this type
-of file is created by the save() method (see below). Multiple records
-can be saved and restored.
-
-Perl purists will be pleased to know that this syntax accepts
-references to file handles, or even references to filehandle globs,
-which is the "official" way to pass a filehandle:
-
- $query = new CGI(\*STDIN);
-
-You can also initialize the CGI object with a FileHandle or IO::File
-object.
-
-If you are using the function-oriented interface and want to
-initialize CGI state from a file handle, the way to do this is with
-B<restore_parameters()>. This will (re)initialize the
-default CGI object from the indicated file handle.
-
- open (IN,"test.in") || die;
- restore_parameters(IN);
- close IN;
-
-You can also initialize the query object from an associative array
-reference:
-
- $query = new CGI( {'dinosaur'=>'barney',
- 'song'=>'I love you',
- 'friends'=>[qw/Jessica George Nancy/]}
- );
-
-or from a properly formatted, URL-escaped query string:
-
- $query = new CGI('dinosaur=barney&color=purple');
-
-or from a previously existing CGI object (currently this clones the
-parameter list, but none of the other object-specific fields, such as
-autoescaping):
-
- $old_query = new CGI;
- $new_query = new CGI($old_query);
-
-To create an empty query, initialize it from an empty string or hash:
-
- $empty_query = new CGI("");
-
- -or-
-
- $empty_query = new CGI({});
-
-=head2 FETCHING A LIST OF KEYWORDS FROM THE QUERY:
-
- @keywords = $query->keywords
-
-If the script was invoked as the result of an <ISINDEX> search, the
-parsed keywords can be obtained as an array using the keywords() method.
-
-=head2 FETCHING THE NAMES OF ALL THE PARAMETERS PASSED TO YOUR SCRIPT:
-
- @names = $query->param
-
-If the script was invoked with a parameter list
-(e.g. "name1=value1&name2=value2&name3=value3"), the param() method
-will return the parameter names as a list. If the script was invoked
-as an <ISINDEX> script and contains a string without ampersands
-(e.g. "value1+value2+value3") , there will be a single parameter named
-"keywords" containing the "+"-delimited keywords.
-
-NOTE: As of version 1.5, the array of parameter names returned will
-be in the same order as they were submitted by the browser.
-Usually this order is the same as the order in which the
-parameters are defined in the form (however, this isn't part
-of the spec, and so isn't guaranteed).
-
-=head2 FETCHING THE VALUE OR VALUES OF A SINGLE NAMED PARAMETER:
-
- @values = $query->param('foo');
-
- -or-
-
- $value = $query->param('foo');
-
-Pass the param() method a single argument to fetch the value of the
-named parameter. If the parameter is multivalued (e.g. from multiple
-selections in a scrolling list), you can ask to receive an array. Otherwise
-the method will return a single value.
-
-If a value is not given in the query string, as in the queries
-"name1=&name2=" or "name1&name2", it will be returned as an empty
-string. This feature is new in 2.63.
-
-
-If the parameter does not exist at all, then param() will return undef
-in a scalar context, and the empty list in a list context.
-
-
-=head2 SETTING THE VALUE(S) OF A NAMED PARAMETER:
-
- $query->param('foo','an','array','of','values');
-
-This sets the value for the named parameter 'foo' to an array of
-values. This is one way to change the value of a field AFTER
-the script has been invoked once before. (Another way is with
-the -override parameter accepted by all methods that generate
-form elements.)
-
-param() also recognizes a named parameter style of calling described
-in more detail later:
-
- $query->param(-name=>'foo',-values=>['an','array','of','values']);
-
- -or-
-
- $query->param(-name=>'foo',-value=>'the value');
-
-=head2 APPENDING ADDITIONAL VALUES TO A NAMED PARAMETER:
-
- $query->append(-name=>'foo',-values=>['yet','more','values']);
-
-This adds a value or list of values to the named parameter. The
-values are appended to the end of the parameter if it already exists.
-Otherwise the parameter is created. Note that this method only
-recognizes the named argument calling syntax.
-
-=head2 IMPORTING ALL PARAMETERS INTO A NAMESPACE:
-
- $query->import_names('R');
-
-This creates a series of variables in the 'R' namespace. For example,
-$R::foo, @R:foo. For keyword lists, a variable @R::keywords will appear.
-If no namespace is given, this method will assume 'Q'.
-WARNING: don't import anything into 'main'; this is a major security
-risk!!!!
-
-NOTE 1: Variable names are transformed as necessary into legal Perl
-variable names. All non-legal characters are transformed into
-underscores. If you need to keep the original names, you should use
-the param() method instead to access CGI variables by name.
-
-NOTE 2: In older versions, this method was called B<import()>. As of version 2.20,
-this name has been removed completely to avoid conflict with the built-in
-Perl module B<import> operator.
-
-=head2 DELETING A PARAMETER COMPLETELY:
-
- $query->delete('foo','bar','baz');
-
-This completely clears a list of parameters. It sometimes useful for
-resetting parameters that you don't want passed down between script
-invocations.
-
-If you are using the function call interface, use "Delete()" instead
-to avoid conflicts with Perl's built-in delete operator.
-
-=head2 DELETING ALL PARAMETERS:
-
- $query->delete_all();
-
-This clears the CGI object completely. It might be useful to ensure
-that all the defaults are taken when you create a fill-out form.
-
-Use Delete_all() instead if you are using the function call interface.
-
-=head2 DIRECT ACCESS TO THE PARAMETER LIST:
-
- $q->param_fetch('address')->[1] = '1313 Mockingbird Lane';
- unshift @{$q->param_fetch(-name=>'address')},'George Munster';
-
-If you need access to the parameter list in a way that isn't covered
-by the methods above, you can obtain a direct reference to it by
-calling the B<param_fetch()> method with the name of the . This
-will return an array reference to the named parameters, which you then
-can manipulate in any way you like.
-
-You can also use a named argument style using the B<-name> argument.
-
-=head2 FETCHING THE PARAMETER LIST AS A HASH:
-
- $params = $q->Vars;
- print $params->{'address'};
- @foo = split("\0",$params->{'foo'});
- %params = $q->Vars;
-
- use CGI ':cgi-lib';
- $params = Vars;
-
-Many people want to fetch the entire parameter list as a hash in which
-the keys are the names of the CGI parameters, and the values are the
-parameters' values. The Vars() method does this. Called in a scalar
-context, it returns the parameter list as a tied hash reference.
-Changing a key changes the value of the parameter in the underlying
-CGI parameter list. Called in a list context, it returns the
-parameter list as an ordinary hash. This allows you to read the
-contents of the parameter list, but not to change it.
-
-When using this, the thing you must watch out for are multivalued CGI
-parameters. Because a hash cannot distinguish between scalar and
-list context, multivalued parameters will be returned as a packed
-string, separated by the "\0" (null) character. You must split this
-packed string in order to get at the individual values. This is the
-convention introduced long ago by Steve Brenner in his cgi-lib.pl
-module for Perl version 4.
-
-If you wish to use Vars() as a function, import the I<:cgi-lib> set of
-function calls (also see the section on CGI-LIB compatibility).
-
-=head2 SAVING THE STATE OF THE SCRIPT TO A FILE:
-
- $query->save(FILEHANDLE)
-
-This will write the current state of the form to the provided
-filehandle. You can read it back in by providing a filehandle
-to the new() method. Note that the filehandle can be a file, a pipe,
-or whatever!
-
-The format of the saved file is:
-
- NAME1=VALUE1
- NAME1=VALUE1'
- NAME2=VALUE2
- NAME3=VALUE3
- =
-
-Both name and value are URL escaped. Multi-valued CGI parameters are
-represented as repeated names. A session record is delimited by a
-single = symbol. You can write out multiple records and read them
-back in with several calls to B<new>. You can do this across several
-sessions by opening the file in append mode, allowing you to create
-primitive guest books, or to keep a history of users' queries. Here's
-a short example of creating multiple session records:
-
- use CGI;
-
- open (OUT,">>test.out") || die;
- $records = 5;
- foreach (0..$records) {
- my $q = new CGI;
- $q->param(-name=>'counter',-value=>$_);
- $q->save(OUT);
- }
- close OUT;
-
- # reopen for reading
- open (IN,"test.out") || die;
- while (!eof(IN)) {
- my $q = new CGI(IN);
- print $q->param('counter'),"\n";
- }
-
-The file format used for save/restore is identical to that used by the
-Whitehead Genome Center's data exchange format "Boulderio", and can be
-manipulated and even databased using Boulderio utilities. See
-
- http://stein.cshl.org/boulder/
-
-for further details.
-
-If you wish to use this method from the function-oriented (non-OO)
-interface, the exported name for this method is B<save_parameters()>.
-
-=head2 RETRIEVING CGI ERRORS
-
-Errors can occur while processing user input, particularly when
-processing uploaded files. When these errors occur, CGI will stop
-processing and return an empty parameter list. You can test for
-the existence and nature of errors using the I<cgi_error()> function.
-The error messages are formatted as HTTP status codes. You can either
-incorporate the error text into an HTML page, or use it as the value
-of the HTTP status:
-
- my $error = $q->cgi_error;
- if ($error) {
- print $q->header(-status=>$error),
- $q->start_html('Problems'),
- $q->h2('Request not processed'),
- $q->strong($error);
- exit 0;
- }
-
-When using the function-oriented interface (see the next section),
-errors may only occur the first time you call I<param()>. Be ready
-for this!
-
-=head2 USING THE FUNCTION-ORIENTED INTERFACE
-
-To use the function-oriented interface, you must specify which CGI.pm
-routines or sets of routines to import into your script's namespace.
-There is a small overhead associated with this importation, but it
-isn't much.
-
- use CGI <list of methods>;
-
-The listed methods will be imported into the current package; you can
-call them directly without creating a CGI object first. This example
-shows how to import the B<param()> and B<header()>
-methods, and then use them directly:
-
- use CGI 'param','header';
- print header('text/plain');
- $zipcode = param('zipcode');
-
-More frequently, you'll import common sets of functions by referring
-to the groups by name. All function sets are preceded with a ":"
-character as in ":html3" (for tags defined in the HTML 3 standard).
-
-Here is a list of the function sets you can import:
-
-=over 4
-
-=item B<:cgi>
-
-Import all CGI-handling methods, such as B<param()>, B<path_info()>
-and the like.
-
-=item B<:form>
-
-Import all fill-out form generating methods, such as B<textfield()>.
-
-=item B<:html2>
-
-Import all methods that generate HTML 2.0 standard elements.
-
-=item B<:html3>
-
-Import all methods that generate HTML 3.0 elements (such as
-<table>, <super> and <sub>).
-
-=item B<:html4>
-
-Import all methods that generate HTML 4 elements (such as
-<abbrev>, <acronym> and <thead>).
-
-=item B<:netscape>
-
-Import all methods that generate Netscape-specific HTML extensions.
-
-=item B<:html>
-
-Import all HTML-generating shortcuts (i.e. 'html2' + 'html3' +
-'netscape')...
-
-=item B<:standard>
-
-Import "standard" features, 'html2', 'html3', 'html4', 'form' and 'cgi'.
-
-=item B<:all>
-
-Import all the available methods. For the full list, see the CGI.pm
-code, where the variable %EXPORT_TAGS is defined.
-
-=back
-
-If you import a function name that is not part of CGI.pm, the module
-will treat it as a new HTML tag and generate the appropriate
-subroutine. You can then use it like any other HTML tag. This is to
-provide for the rapidly-evolving HTML "standard." For example, say
-Microsoft comes out with a new tag called <gradient> (which causes the
-user's desktop to be flooded with a rotating gradient fill until his
-machine reboots). You don't need to wait for a new version of CGI.pm
-to start using it immediately:
-
- use CGI qw/:standard :html3 gradient/;
- print gradient({-start=>'red',-end=>'blue'});
-
-Note that in the interests of execution speed CGI.pm does B<not> use
-the standard L<Exporter> syntax for specifying load symbols. This may
-change in the future.
-
-If you import any of the state-maintaining CGI or form-generating
-methods, a default CGI object will be created and initialized
-automatically the first time you use any of the methods that require
-one to be present. This includes B<param()>, B<textfield()>,
-B<submit()> and the like. (If you need direct access to the CGI
-object, you can find it in the global variable B<$CGI::Q>). By
-importing CGI.pm methods, you can create visually elegant scripts:
-
- use CGI qw/:standard/;
- print
- header,
- start_html('Simple Script'),
- h1('Simple Script'),
- start_form,
- "What's your name? ",textfield('name'),p,
- "What's the combination?",
- checkbox_group(-name=>'words',
- -values=>['eenie','meenie','minie','moe'],
- -defaults=>['eenie','moe']),p,
- "What's your favorite color?",
- popup_menu(-name=>'color',
- -values=>['red','green','blue','chartreuse']),p,
- submit,
- end_form,
- hr,"\n";
-
- if (param) {
- print
- "Your name is ",em(param('name')),p,
- "The keywords are: ",em(join(", ",param('words'))),p,
- "Your favorite color is ",em(param('color')),".\n";
- }
- print end_html;
-
-=head2 PRAGMAS
-
-In addition to the function sets, there are a number of pragmas that
-you can import. Pragmas, which are always preceded by a hyphen,
-change the way that CGI.pm functions in various ways. Pragmas,
-function sets, and individual functions can all be imported in the
-same use() line. For example, the following use statement imports the
-standard set of functions and enables debugging mode (pragma
--debug):
-
- use CGI qw/:standard -debug/;
-
-The current list of pragmas is as follows:
-
-=over 4
-
-=item -any
-
-When you I<use CGI -any>, then any method that the query object
-doesn't recognize will be interpreted as a new HTML tag. This allows
-you to support the next I<ad hoc> Netscape or Microsoft HTML
-extension. This lets you go wild with new and unsupported tags:
-
- use CGI qw(-any);
- $q=new CGI;
- print $q->gradient({speed=>'fast',start=>'red',end=>'blue'});
-
-Since using <cite>any</cite> causes any mistyped method name
-to be interpreted as an HTML tag, use it with care or not at
-all.
-
-=item -compile
-
-This causes the indicated autoloaded methods to be compiled up front,
-rather than deferred to later. This is useful for scripts that run
-for an extended period of time under FastCGI or mod_perl, and for
-those destined to be crunched by Malcom Beattie's Perl compiler. Use
-it in conjunction with the methods or method families you plan to use.
-
- use CGI qw(-compile :standard :html3);
-
-or even
-
- use CGI qw(-compile :all);
-
-Note that using the -compile pragma in this way will always have
-the effect of importing the compiled functions into the current
-namespace. If you want to compile without importing use the
-compile() method instead:
-
- use CGI();
- CGI->compile();
-
-This is particularly useful in a mod_perl environment, in which you
-might want to precompile all CGI routines in a startup script, and
-then import the functions individually in each mod_perl script.
-
-=item -nosticky
-
-This makes CGI.pm not generating the hidden fields .submit
-and .cgifields. It is very useful if you don't want to
-have the hidden fields appear in the querystring in a GET method.
-For example, a search script generated this way will have
-a very nice url with search parameters for bookmarking.
-
-=item -no_undef_params
-
-This keeps CGI.pm from including undef params in the parameter list.
-
-=item -no_xhtml
-
-By default, CGI.pm versions 2.69 and higher emit XHTML
-(http://www.w3.org/TR/xhtml1/). The -no_xhtml pragma disables this
-feature. Thanks to Michalis Kabrianis <kabrianis@hellug.gr> for this
-feature.
-
-If start_html()'s -dtd parameter specifies an HTML 2.0 or 3.2 DTD,
-XHTML will automatically be disabled without needing to use this
-pragma.
-
-=item -nph
-
-This makes CGI.pm produce a header appropriate for an NPH (no
-parsed header) script. You may need to do other things as well
-to tell the server that the script is NPH. See the discussion
-of NPH scripts below.
-
-=item -newstyle_urls
-
-Separate the name=value pairs in CGI parameter query strings with
-semicolons rather than ampersands. For example:
-
- ?name=fred;age=24;favorite_color=3
-
-Semicolon-delimited query strings are always accepted, but will not be
-emitted by self_url() and query_string() unless the -newstyle_urls
-pragma is specified.
-
-This became the default in version 2.64.
-
-=item -oldstyle_urls
-
-Separate the name=value pairs in CGI parameter query strings with
-ampersands rather than semicolons. This is no longer the default.
-
-=item -autoload
-
-This overrides the autoloader so that any function in your program
-that is not recognized is referred to CGI.pm for possible evaluation.
-This allows you to use all the CGI.pm functions without adding them to
-your symbol table, which is of concern for mod_perl users who are
-worried about memory consumption. I<Warning:> when
-I<-autoload> is in effect, you cannot use "poetry mode"
-(functions without the parenthesis). Use I<hr()> rather
-than I<hr>, or add something like I<use subs qw/hr p header/>
-to the top of your script.
-
-=item -no_debug
-
-This turns off the command-line processing features. If you want to
-run a CGI.pm script from the command line to produce HTML, and you
-don't want it to read CGI parameters from the command line or STDIN,
-then use this pragma:
-
- use CGI qw(-no_debug :standard);
-
-=item -debug
-
-This turns on full debugging. In addition to reading CGI arguments
-from the command-line processing, CGI.pm will pause and try to read
-arguments from STDIN, producing the message "(offline mode: enter
-name=value pairs on standard input)" features.
-
-See the section on debugging for more details.
-
-=item -private_tempfiles
-
-CGI.pm can process uploaded file. Ordinarily it spools the uploaded
-file to a temporary directory, then deletes the file when done.
-However, this opens the risk of eavesdropping as described in the file
-upload section. Another CGI script author could peek at this data
-during the upload, even if it is confidential information. On Unix
-systems, the -private_tempfiles pragma will cause the temporary file
-to be unlinked as soon as it is opened and before any data is written
-into it, reducing, but not eliminating the risk of eavesdropping
-(there is still a potential race condition). To make life harder for
-the attacker, the program chooses tempfile names by calculating a 32
-bit checksum of the incoming HTTP headers.
-
-To ensure that the temporary file cannot be read by other CGI scripts,
-use suEXEC or a CGI wrapper program to run your script. The temporary
-file is created with mode 0600 (neither world nor group readable).
-
-The temporary directory is selected using the following algorithm:
-
- 1. if the current user (e.g. "nobody") has a directory named
- "tmp" in its home directory, use that (Unix systems only).
-
- 2. if the environment variable TMPDIR exists, use the location
- indicated.
-
- 3. Otherwise try the locations /usr/tmp, /var/tmp, C:\temp,
- /tmp, /temp, ::Temporary Items, and \WWW_ROOT.
-
-Each of these locations is checked that it is a directory and is
-writable. If not, the algorithm tries the next choice.
-
-=back
-
-=head2 SPECIAL FORMS FOR IMPORTING HTML-TAG FUNCTIONS
-
-Many of the methods generate HTML tags. As described below, tag
-functions automatically generate both the opening and closing tags.
-For example:
-
- print h1('Level 1 Header');
-
-produces
-
- <h1>Level 1 Header</h1>
-
-There will be some times when you want to produce the start and end
-tags yourself. In this case, you can use the form start_I<tag_name>
-and end_I<tag_name>, as in:
-
- print start_h1,'Level 1 Header',end_h1;
-
-With a few exceptions (described below), start_I<tag_name> and
-end_I<tag_name> functions are not generated automatically when you
-I<use CGI>. However, you can specify the tags you want to generate
-I<start/end> functions for by putting an asterisk in front of their
-name, or, alternatively, requesting either "start_I<tag_name>" or
-"end_I<tag_name>" in the import list.
-
-Example:
-
- use CGI qw/:standard *table start_ul/;
-
-In this example, the following functions are generated in addition to
-the standard ones:
-
-=over 4
-
-=item 1. start_table() (generates a <table> tag)
-
-=item 2. end_table() (generates a </table> tag)
-
-=item 3. start_ul() (generates a <ul> tag)
-
-=item 4. end_ul() (generates a </ul> tag)
-
-=back
-
-=head1 GENERATING DYNAMIC DOCUMENTS
-
-Most of CGI.pm's functions deal with creating documents on the fly.
-Generally you will produce the HTTP header first, followed by the
-document itself. CGI.pm provides functions for generating HTTP
-headers of various types as well as for generating HTML. For creating
-GIF images, see the GD.pm module.
-
-Each of these functions produces a fragment of HTML or HTTP which you
-can print out directly so that it displays in the browser window,
-append to a string, or save to a file for later use.
-
-=head2 CREATING A STANDARD HTTP HEADER:
-
-Normally the first thing you will do in any CGI script is print out an
-HTTP header. This tells the browser what type of document to expect,
-and gives other optional information, such as the language, expiration
-date, and whether to cache the document. The header can also be
-manipulated for special purposes, such as server push and pay per view
-pages.
-
- print $query->header;
-
- -or-
-
- print $query->header('image/gif');
-
- -or-
-
- print $query->header('text/html','204 No response');
-
- -or-
-
- print $query->header(-type=>'image/gif',
- -nph=>1,
- -status=>'402 Payment required',
- -expires=>'+3d',
- -cookie=>$cookie,
- -charset=>'utf-7',
- -attachment=>'foo.gif',
- -Cost=>'$2.00');
-
-header() returns the Content-type: header. You can provide your own
-MIME type if you choose, otherwise it defaults to text/html. An
-optional second parameter specifies the status code and a human-readable
-message. For example, you can specify 204, "No response" to create a
-script that tells the browser to do nothing at all.
-
-The last example shows the named argument style for passing arguments
-to the CGI methods using named parameters. Recognized parameters are
-B<-type>, B<-status>, B<-expires>, and B<-cookie>. Any other named
-parameters will be stripped of their initial hyphens and turned into
-header fields, allowing you to specify any HTTP header you desire.
-Internal underscores will be turned into hyphens:
-
- print $query->header(-Content_length=>3002);
-
-Most browsers will not cache the output from CGI scripts. Every time
-the browser reloads the page, the script is invoked anew. You can
-change this behavior with the B<-expires> parameter. When you specify
-an absolute or relative expiration interval with this parameter, some
-browsers and proxy servers will cache the script's output until the
-indicated expiration date. The following forms are all valid for the
--expires field:
-
- +30s 30 seconds from now
- +10m ten minutes from now
- +1h one hour from now
- -1d yesterday (i.e. "ASAP!")
- now immediately
- +3M in three months
- +10y in ten years time
- Thursday, 25-Apr-1999 00:40:33 GMT at the indicated time & date
-
-The B<-cookie> parameter generates a header that tells the browser to provide
-a "magic cookie" during all subsequent transactions with your script.
-Netscape cookies have a special format that includes interesting attributes
-such as expiration time. Use the cookie() method to create and retrieve
-session cookies.
-
-The B<-nph> parameter, if set to a true value, will issue the correct
-headers to work with a NPH (no-parse-header) script. This is important
-to use with certain servers that expect all their scripts to be NPH.
-
-The B<-charset> parameter can be used to control the character set
-sent to the browser. If not provided, defaults to ISO-8859-1. As a
-side effect, this sets the charset() method as well.
-
-The B<-attachment> parameter can be used to turn the page into an
-attachment. Instead of displaying the page, some browsers will prompt
-the user to save it to disk. The value of the argument is the
-suggested name for the saved file. In order for this to work, you may
-have to set the B<-type> to "application/octet-stream".
-
-The B<-p3p> parameter will add a P3P tag to the outgoing header. The
-parameter can be an arrayref or a space-delimited string of P3P tags.
-For example:
-
- print header(-p3p=>[qw(CAO DSP LAW CURa)]);
- print header(-p3p=>'CAO DSP LAW CURa');
-
-In either case, the outgoing header will be formatted as:
-
- P3P: policyref="/w3c/p3p.xml" cp="CAO DSP LAW CURa"
-
-=head2 GENERATING A REDIRECTION HEADER
-
- print $query->redirect('http://somewhere.else/in/movie/land');
-
-Sometimes you don't want to produce a document yourself, but simply
-redirect the browser elsewhere, perhaps choosing a URL based on the
-time of day or the identity of the user.
-
-The redirect() function redirects the browser to a different URL. If
-you use redirection like this, you should B<not> print out a header as
-well.
-
-You should always use full URLs (including the http: or ftp: part) in
-redirection requests. Relative URLs will not work correctly.
-
-You can also use named arguments:
-
- print $query->redirect(-uri=>'http://somewhere.else/in/movie/land',
- -nph=>1,
- -status=>301);
-
-The B<-nph> parameter, if set to a true value, will issue the correct
-headers to work with a NPH (no-parse-header) script. This is important
-to use with certain servers, such as Microsoft IIS, which
-expect all their scripts to be NPH.
-
-The B<-status> parameter will set the status of the redirect. HTTP
-defines three different possible redirection status codes:
-
- 301 Moved Permanently
- 302 Found
- 303 See Other
-
-The default if not specified is 302, which means "moved temporarily."
-You may change the status to another status code if you wish. Be
-advised that changing the status to anything other than 301, 302 or
-303 will probably break redirection.
-
-=head2 CREATING THE HTML DOCUMENT HEADER
-
- print $query->start_html(-title=>'Secrets of the Pyramids',
- -author=>'fred@capricorn.org',
- -base=>'true',
- -target=>'_blank',
- -meta=>{'keywords'=>'pharaoh secret mummy',
- 'copyright'=>'copyright 1996 King Tut'},
- -style=>{'src'=>'/styles/style1.css'},
- -BGCOLOR=>'blue');
-
-After creating the HTTP header, most CGI scripts will start writing
-out an HTML document. The start_html() routine creates the top of the
-page, along with a lot of optional information that controls the
-page's appearance and behavior.
-
-This method returns a canned HTML header and the opening <body> tag.
-All parameters are optional. In the named parameter form, recognized
-parameters are -title, -author, -base, -xbase, -dtd, -lang and -target
-(see below for the explanation). Any additional parameters you
-provide, such as the Netscape unofficial BGCOLOR attribute, are added
-to the <body> tag. Additional parameters must be proceeded by a
-hyphen.
-
-The argument B<-xbase> allows you to provide an HREF for the <base> tag
-different from the current location, as in
-
- -xbase=>"http://home.mcom.com/"
-
-All relative links will be interpreted relative to this tag.
-
-The argument B<-target> allows you to provide a default target frame
-for all the links and fill-out forms on the page. B<This is a
-non-standard HTTP feature which only works with Netscape browsers!>
-See the Netscape documentation on frames for details of how to
-manipulate this.
-
- -target=>"answer_window"
-
-All relative links will be interpreted relative to this tag.
-You add arbitrary meta information to the header with the B<-meta>
-argument. This argument expects a reference to an associative array
-containing name/value pairs of meta information. These will be turned
-into a series of header <meta> tags that look something like this:
-
- <meta name="keywords" content="pharaoh secret mummy">
- <meta name="description" content="copyright 1996 King Tut">
-
-To create an HTTP-EQUIV type of <meta> tag, use B<-head>, described
-below.
-
-The B<-style> argument is used to incorporate cascading stylesheets
-into your code. See the section on CASCADING STYLESHEETS for more
-information.
-
-The B<-lang> argument is used to incorporate a language attribute into
-the <html> tag. For example:
-
- print $q->start_html(-lang=>'fr-CA');
-
-The default if not specified is "en-US" for US English, unless the
--dtd parameter specifies an HTML 2.0 or 3.2 DTD, in which case the
-lang attribute is left off. You can force the lang attribute to left
-off in other cases by passing an empty string (-lang=>'').
-
-The B<-encoding> argument can be used to specify the character set for
-XHTML. It defaults to iso-8859-1 if not specified.
-
-You can place other arbitrary HTML elements to the <head> section with the
-B<-head> tag. For example, to place the rarely-used <link> element in the
-head section, use this:
-
- print start_html(-head=>Link({-rel=>'next',
- -href=>'http://www.capricorn.com/s2.html'}));
-
-To incorporate multiple HTML elements into the <head> section, just pass an
-array reference:
-
- print start_html(-head=>[
- Link({-rel=>'next',
- -href=>'http://www.capricorn.com/s2.html'}),
- Link({-rel=>'previous',
- -href=>'http://www.capricorn.com/s1.html'})
- ]
- );
-
-And here's how to create an HTTP-EQUIV <meta> tag:
-
- print start_html(-head=>meta({-http_equiv => 'Content-Type',
- -content => 'text/html'}))
-
-
-JAVASCRIPTING: The B<-script>, B<-noScript>, B<-onLoad>,
-B<-onMouseOver>, B<-onMouseOut> and B<-onUnload> parameters are used
-to add Netscape JavaScript calls to your pages. B<-script> should
-point to a block of text containing JavaScript function definitions.
-This block will be placed within a <script> block inside the HTML (not
-HTTP) header. The block is placed in the header in order to give your
-page a fighting chance of having all its JavaScript functions in place
-even if the user presses the stop button before the page has loaded
-completely. CGI.pm attempts to format the script in such a way that
-JavaScript-naive browsers will not choke on the code: unfortunately
-there are some browsers, such as Chimera for Unix, that get confused
-by it nevertheless.
-
-The B<-onLoad> and B<-onUnload> parameters point to fragments of JavaScript
-code to execute when the page is respectively opened and closed by the
-browser. Usually these parameters are calls to functions defined in the
-B<-script> field:
-
- $query = new CGI;
- print $query->header;
- $JSCRIPT=<<END;
- // Ask a silly question
- function riddle_me_this() {
- var r = prompt("What walks on four legs in the morning, " +
- "two legs in the afternoon, " +
- "and three legs in the evening?");
- response(r);
- }
- // Get a silly answer
- function response(answer) {
- if (answer == "man")
- alert("Right you are!");
- else
- alert("Wrong! Guess again.");
- }
- END
- print $query->start_html(-title=>'The Riddle of the Sphinx',
- -script=>$JSCRIPT);
-
-Use the B<-noScript> parameter to pass some HTML text that will be displayed on
-browsers that do not have JavaScript (or browsers where JavaScript is turned
-off).
-
-Netscape 3.0 recognizes several attributes of the <script> tag,
-including LANGUAGE and SRC. The latter is particularly interesting,
-as it allows you to keep the JavaScript code in a file or CGI script
-rather than cluttering up each page with the source. To use these
-attributes pass a HASH reference in the B<-script> parameter containing
-one or more of -language, -src, or -code:
-
- print $q->start_html(-title=>'The Riddle of the Sphinx',
- -script=>{-language=>'JAVASCRIPT',
- -src=>'/javascript/sphinx.js'}
- );
-
- print $q->(-title=>'The Riddle of the Sphinx',
- -script=>{-language=>'PERLSCRIPT',
- -code=>'print "hello world!\n;"'}
- );
-
-
-A final feature allows you to incorporate multiple <script> sections into the
-header. Just pass the list of script sections as an array reference.
-this allows you to specify different source files for different dialects
-of JavaScript. Example:
-
- print $q->start_html(-title=>'The Riddle of the Sphinx',
- -script=>[
- { -language => 'JavaScript1.0',
- -src => '/javascript/utilities10.js'
- },
- { -language => 'JavaScript1.1',
- -src => '/javascript/utilities11.js'
- },
- { -language => 'JavaScript1.2',
- -src => '/javascript/utilities12.js'
- },
- { -language => 'JavaScript28.2',
- -src => '/javascript/utilities219.js'
- }
- ]
- );
-
-If this looks a bit extreme, take my advice and stick with straight CGI scripting.
-
-See
-
- http://home.netscape.com/eng/mozilla/2.0/handbook/javascript/
-
-for more information about JavaScript.
-
-The old-style positional parameters are as follows:
-
-=over 4
-
-=item B<Parameters:>
-
-=item 1.
-
-The title
-
-=item 2.
-
-The author's e-mail address (will create a <link rev="MADE"> tag if present
-
-=item 3.
-
-A 'true' flag if you want to include a <base> tag in the header. This
-helps resolve relative addresses to absolute ones when the document is moved,
-but makes the document hierarchy non-portable. Use with care!
-
-=item 4, 5, 6...
-
-Any other parameters you want to include in the <body> tag. This is a good
-place to put Netscape extensions, such as colors and wallpaper patterns.
-
-=back
-
-=head2 ENDING THE HTML DOCUMENT:
-
- print $query->end_html
-
-This ends an HTML document by printing the </body></html> tags.
-
-=head2 CREATING A SELF-REFERENCING URL THAT PRESERVES STATE INFORMATION:
-
- $myself = $query->self_url;
- print q(<a href="$myself">I'm talking to myself.</a>);
-
-self_url() will return a URL, that, when selected, will reinvoke
-this script with all its state information intact. This is most
-useful when you want to jump around within the document using
-internal anchors but you don't want to disrupt the current contents
-of the form(s). Something like this will do the trick.
-
- $myself = $query->self_url;
- print "<a href=\"$myself#table1\">See table 1</a>";
- print "<a href=\"$myself#table2\">See table 2</a>";
- print "<a href=\"$myself#yourself\">See for yourself</a>";
-
-If you want more control over what's returned, using the B<url()>
-method instead.
-
-You can also retrieve the unprocessed query string with query_string():
-
- $the_string = $query->query_string;
-
-=head2 OBTAINING THE SCRIPT'S URL
-
- $full_url = $query->url();
- $full_url = $query->url(-full=>1); #alternative syntax
- $relative_url = $query->url(-relative=>1);
- $absolute_url = $query->url(-absolute=>1);
- $url_with_path = $query->url(-path_info=>1);
- $url_with_path_and_query = $query->url(-path_info=>1,-query=>1);
- $netloc = $query->url(-base => 1);
-
-B<url()> returns the script's URL in a variety of formats. Called
-without any arguments, it returns the full form of the URL, including
-host name and port number
-
- http://your.host.com/path/to/script.cgi
-
-You can modify this format with the following named arguments:
-
-=over 4
-
-=item B<-absolute>
-
-If true, produce an absolute URL, e.g.
-
- /path/to/script.cgi
-
-=item B<-relative>
-
-Produce a relative URL. This is useful if you want to reinvoke your
-script with different parameters. For example:
-
- script.cgi
-
-=item B<-full>
-
-Produce the full URL, exactly as if called without any arguments.
-This overrides the -relative and -absolute arguments.
-
-=item B<-path> (B<-path_info>)
-
-Append the additional path information to the URL. This can be
-combined with B<-full>, B<-absolute> or B<-relative>. B<-path_info>
-is provided as a synonym.
-
-=item B<-query> (B<-query_string>)
-
-Append the query string to the URL. This can be combined with
-B<-full>, B<-absolute> or B<-relative>. B<-query_string> is provided
-as a synonym.
-
-=item B<-base>
-
-Generate just the protocol and net location, as in http://www.foo.com:8000
-
-=back
-
-=head2 MIXING POST AND URL PARAMETERS
-
- $color = $query->url_param('color');
-
-It is possible for a script to receive CGI parameters in the URL as
-well as in the fill-out form by creating a form that POSTs to a URL
-containing a query string (a "?" mark followed by arguments). The
-B<param()> method will always return the contents of the POSTed
-fill-out form, ignoring the URL's query string. To retrieve URL
-parameters, call the B<url_param()> method. Use it in the same way as
-B<param()>. The main difference is that it allows you to read the
-parameters, but not set them.
-
-
-Under no circumstances will the contents of the URL query string
-interfere with similarly-named CGI parameters in POSTed forms. If you
-try to mix a URL query string with a form submitted with the GET
-method, the results will not be what you expect.
-
-=head1 CREATING STANDARD HTML ELEMENTS:
-
-CGI.pm defines general HTML shortcut methods for most, if not all of
-the HTML 3 and HTML 4 tags. HTML shortcuts are named after a single
-HTML element and return a fragment of HTML text that you can then
-print or manipulate as you like. Each shortcut returns a fragment of
-HTML code that you can append to a string, save to a file, or, most
-commonly, print out so that it displays in the browser window.
-
-This example shows how to use the HTML methods:
-
- $q = new CGI;
- print $q->blockquote(
- "Many years ago on the island of",
- $q->a({href=>"http://crete.org/"},"Crete"),
- "there lived a Minotaur named",
- $q->strong("Fred."),
- ),
- $q->hr;
-
-This results in the following HTML code (extra newlines have been
-added for readability):
-
- <blockquote>
- Many years ago on the island of
- <a href="http://crete.org/">Crete</a> there lived
- a minotaur named <strong>Fred.</strong>
- </blockquote>
- <hr>
-
-If you find the syntax for calling the HTML shortcuts awkward, you can
-import them into your namespace and dispense with the object syntax
-completely (see the next section for more details):
-
- use CGI ':standard';
- print blockquote(
- "Many years ago on the island of",
- a({href=>"http://crete.org/"},"Crete"),
- "there lived a minotaur named",
- strong("Fred."),
- ),
- hr;
-
-=head2 PROVIDING ARGUMENTS TO HTML SHORTCUTS
-
-The HTML methods will accept zero, one or multiple arguments. If you
-provide no arguments, you get a single tag:
-
- print hr; # <hr>
-
-If you provide one or more string arguments, they are concatenated
-together with spaces and placed between opening and closing tags:
-
- print h1("Chapter","1"); # <h1>Chapter 1</h1>"
-
-If the first argument is an associative array reference, then the keys
-and values of the associative array become the HTML tag's attributes:
-
- print a({-href=>'fred.html',-target=>'_new'},
- "Open a new frame");
-
- <a href="fred.html",target="_new">Open a new frame</a>
-
-You may dispense with the dashes in front of the attribute names if
-you prefer:
-
- print img {src=>'fred.gif',align=>'LEFT'};
-
- <img align="LEFT" src="fred.gif">
-
-Sometimes an HTML tag attribute has no argument. For example, ordered
-lists can be marked as COMPACT. The syntax for this is an argument that
-that points to an undef string:
-
- print ol({compact=>undef},li('one'),li('two'),li('three'));
-
-Prior to CGI.pm version 2.41, providing an empty ('') string as an
-attribute argument was the same as providing undef. However, this has
-changed in order to accommodate those who want to create tags of the form
-<img alt="">. The difference is shown in these two pieces of code:
-
- CODE RESULT
- img({alt=>undef}) <img alt>
- img({alt=>''}) <img alt="">
-
-=head2 THE DISTRIBUTIVE PROPERTY OF HTML SHORTCUTS
-
-One of the cool features of the HTML shortcuts is that they are
-distributive. If you give them an argument consisting of a
-B<reference> to a list, the tag will be distributed across each
-element of the list. For example, here's one way to make an ordered
-list:
-
- print ul(
- li({-type=>'disc'},['Sneezy','Doc','Sleepy','Happy'])
- );
-
-This example will result in HTML output that looks like this:
-
- <ul>
- <li type="disc">Sneezy</li>
- <li type="disc">Doc</li>
- <li type="disc">Sleepy</li>
- <li type="disc">Happy</li>
- </ul>
-
-This is extremely useful for creating tables. For example:
-
- print table({-border=>undef},
- caption('When Should You Eat Your Vegetables?'),
- Tr({-align=>CENTER,-valign=>TOP},
- [
- th(['Vegetable', 'Breakfast','Lunch','Dinner']),
- td(['Tomatoes' , 'no', 'yes', 'yes']),
- td(['Broccoli' , 'no', 'no', 'yes']),
- td(['Onions' , 'yes','yes', 'yes'])
- ]
- )
- );
-
-=head2 HTML SHORTCUTS AND LIST INTERPOLATION
-
-Consider this bit of code:
-
- print blockquote(em('Hi'),'mom!'));
-
-It will ordinarily return the string that you probably expect, namely:
-
- <blockquote><em>Hi</em> mom!</blockquote>
-
-Note the space between the element "Hi" and the element "mom!".
-CGI.pm puts the extra space there using array interpolation, which is
-controlled by the magic $" variable. Sometimes this extra space is
-not what you want, for example, when you are trying to align a series
-of images. In this case, you can simply change the value of $" to an
-empty string.
-
- {
- local($") = '';
- print blockquote(em('Hi'),'mom!'));
- }
-
-I suggest you put the code in a block as shown here. Otherwise the
-change to $" will affect all subsequent code until you explicitly
-reset it.
-
-=head2 NON-STANDARD HTML SHORTCUTS
-
-A few HTML tags don't follow the standard pattern for various
-reasons.
-
-B<comment()> generates an HTML comment (<!-- comment -->). Call it
-like
-
- print comment('here is my comment');
-
-Because of conflicts with built-in Perl functions, the following functions
-begin with initial caps:
-
- Select
- Tr
- Link
- Delete
- Accept
- Sub
-
-In addition, start_html(), end_html(), start_form(), end_form(),
-start_multipart_form() and all the fill-out form tags are special.
-See their respective sections.
-
-=head2 AUTOESCAPING HTML
-
-By default, all HTML that is emitted by the form-generating functions
-is passed through a function called escapeHTML():
-
-=over 4
-
-=item $escaped_string = escapeHTML("unescaped string");
-
-Escape HTML formatting characters in a string.
-
-=back
-
-Provided that you have specified a character set of ISO-8859-1 (the
-default), the standard HTML escaping rules will be used. The "<"
-character becomes "&lt;", ">" becomes "&gt;", "&" becomes "&amp;", and
-the quote character becomes "&quot;". In addition, the hexadecimal
-0x8b and 0x9b characters, which some browsers incorrectly interpret
-as the left and right angle-bracket characters, are replaced by their
-numeric character entities ("&#8249" and "&#8250;"). If you manually change
-the charset, either by calling the charset() method explicitly or by
-passing a -charset argument to header(), then B<all> characters will
-be replaced by their numeric entities, since CGI.pm has no lookup
-table for all the possible encodings.
-
-The automatic escaping does not apply to other shortcuts, such as
-h1(). You should call escapeHTML() yourself on untrusted data in
-order to protect your pages against nasty tricks that people may enter
-into guestbooks, etc.. To change the character set, use charset().
-To turn autoescaping off completely, use autoEscape(0):
-
-=over 4
-
-=item $charset = charset([$charset]);
-
-Get or set the current character set.
-
-=item $flag = autoEscape([$flag]);
-
-Get or set the value of the autoescape flag.
-
-=back
-
-=head2 PRETTY-PRINTING HTML
-
-By default, all the HTML produced by these functions comes out as one
-long line without carriage returns or indentation. This is yuck, but
-it does reduce the size of the documents by 10-20%. To get
-pretty-printed output, please use L<CGI::Pretty>, a subclass
-contributed by Brian Paulsen.
-
-=head1 CREATING FILL-OUT FORMS:
-
-I<General note> The various form-creating methods all return strings
-to the caller, containing the tag or tags that will create the requested
-form element. You are responsible for actually printing out these strings.
-It's set up this way so that you can place formatting tags
-around the form elements.
-
-I<Another note> The default values that you specify for the forms are only
-used the B<first> time the script is invoked (when there is no query
-string). On subsequent invocations of the script (when there is a query
-string), the former values are used even if they are blank.
-
-If you want to change the value of a field from its previous value, you have two
-choices:
-
-(1) call the param() method to set it.
-
-(2) use the -override (alias -force) parameter (a new feature in version 2.15).
-This forces the default value to be used, regardless of the previous value:
-
- print $query->textfield(-name=>'field_name',
- -default=>'starting value',
- -override=>1,
- -size=>50,
- -maxlength=>80);
-
-I<Yet another note> By default, the text and labels of form elements are
-escaped according to HTML rules. This means that you can safely use
-"<CLICK ME>" as the label for a button. However, it also interferes with
-your ability to incorporate special HTML character sequences, such as &Aacute;,
-into your fields. If you wish to turn off automatic escaping, call the
-autoEscape() method with a false value immediately after creating the CGI object:
-
- $query = new CGI;
- $query->autoEscape(undef);
-
-I<A Lurking Trap!> Some of the form-element generating methods return
-multiple tags. In a scalar context, the tags will be concatenated
-together with spaces, or whatever is the current value of the $"
-global. In a list context, the methods will return a list of
-elements, allowing you to modify them if you wish. Usually you will
-not notice this behavior, but beware of this:
-
- printf("%s\n",$query->end_form())
-
-end_form() produces several tags, and only the first of them will be
-printed because the format only expects one value.
-
-<p>
-
-
-=head2 CREATING AN ISINDEX TAG
-
- print $query->isindex(-action=>$action);
-
- -or-
-
- print $query->isindex($action);
-
-Prints out an <isindex> tag. Not very exciting. The parameter
--action specifies the URL of the script to process the query. The
-default is to process the query with the current script.
-
-=head2 STARTING AND ENDING A FORM
-
- print $query->start_form(-method=>$method,
- -action=>$action,
- -enctype=>$encoding);
- <... various form stuff ...>
- print $query->endform;
-
- -or-
-
- print $query->start_form($method,$action,$encoding);
- <... various form stuff ...>
- print $query->endform;
-
-start_form() will return a <form> tag with the optional method,
-action and form encoding that you specify. The defaults are:
-
- method: POST
- action: this script
- enctype: application/x-www-form-urlencoded
-
-endform() returns the closing </form> tag.
-
-Start_form()'s enctype argument tells the browser how to package the various
-fields of the form before sending the form to the server. Two
-values are possible:
-
-B<Note:> This method was previously named startform(), and startform()
-is still recognized as an alias.
-
-=over 4
-
-=item B<application/x-www-form-urlencoded>
-
-This is the older type of encoding used by all browsers prior to
-Netscape 2.0. It is compatible with many CGI scripts and is
-suitable for short fields containing text data. For your
-convenience, CGI.pm stores the name of this encoding
-type in B<&CGI::URL_ENCODED>.
-
-=item B<multipart/form-data>
-
-This is the newer type of encoding introduced by Netscape 2.0.
-It is suitable for forms that contain very large fields or that
-are intended for transferring binary data. Most importantly,
-it enables the "file upload" feature of Netscape 2.0 forms. For
-your convenience, CGI.pm stores the name of this encoding type
-in B<&CGI::MULTIPART>
-
-Forms that use this type of encoding are not easily interpreted
-by CGI scripts unless they use CGI.pm or another library designed
-to handle them.
-
-=back
-
-For compatibility, the start_form() method uses the older form of
-encoding by default. If you want to use the newer form of encoding
-by default, you can call B<start_multipart_form()> instead of
-B<start_form()>.
-
-JAVASCRIPTING: The B<-name> and B<-onSubmit> parameters are provided
-for use with JavaScript. The -name parameter gives the
-form a name so that it can be identified and manipulated by
-JavaScript functions. -onSubmit should point to a JavaScript
-function that will be executed just before the form is submitted to your
-server. You can use this opportunity to check the contents of the form
-for consistency and completeness. If you find something wrong, you
-can put up an alert box or maybe fix things up yourself. You can
-abort the submission by returning false from this function.
-
-Usually the bulk of JavaScript functions are defined in a <script>
-block in the HTML header and -onSubmit points to one of these function
-call. See start_html() for details.
-
-=head2 CREATING A TEXT FIELD
-
- print $query->textfield(-name=>'field_name',
- -default=>'starting value',
- -size=>50,
- -maxlength=>80);
- -or-
-
- print $query->textfield('field_name','starting value',50,80);
-
-textfield() will return a text input field.
-
-=over 4
-
-=item B<Parameters>
-
-=item 1.
-
-The first parameter is the required name for the field (-name).
-
-=item 2.
-
-The optional second parameter is the default starting value for the field
-contents (-default).
-
-=item 3.
-
-The optional third parameter is the size of the field in
- characters (-size).
-
-=item 4.
-
-The optional fourth parameter is the maximum number of characters the
- field will accept (-maxlength).
-
-=back
-
-As with all these methods, the field will be initialized with its
-previous contents from earlier invocations of the script.
-When the form is processed, the value of the text field can be
-retrieved with:
-
- $value = $query->param('foo');
-
-If you want to reset it from its initial value after the script has been
-called once, you can do so like this:
-
- $query->param('foo',"I'm taking over this value!");
-
-NEW AS OF VERSION 2.15: If you don't want the field to take on its previous
-value, you can force its current value by using the -override (alias -force)
-parameter:
-
- print $query->textfield(-name=>'field_name',
- -default=>'starting value',
- -override=>1,
- -size=>50,
- -maxlength=>80);
-
-JAVASCRIPTING: You can also provide B<-onChange>, B<-onFocus>,
-B<-onBlur>, B<-onMouseOver>, B<-onMouseOut> and B<-onSelect>
-parameters to register JavaScript event handlers. The onChange
-handler will be called whenever the user changes the contents of the
-text field. You can do text validation if you like. onFocus and
-onBlur are called respectively when the insertion point moves into and
-out of the text field. onSelect is called when the user changes the
-portion of the text that is selected.
-
-=head2 CREATING A BIG TEXT FIELD
-
- print $query->textarea(-name=>'foo',
- -default=>'starting value',
- -rows=>10,
- -columns=>50);
-
- -or
-
- print $query->textarea('foo','starting value',10,50);
-
-textarea() is just like textfield, but it allows you to specify
-rows and columns for a multiline text entry box. You can provide
-a starting value for the field, which can be long and contain
-multiple lines.
-
-JAVASCRIPTING: The B<-onChange>, B<-onFocus>, B<-onBlur> ,
-B<-onMouseOver>, B<-onMouseOut>, and B<-onSelect> parameters are
-recognized. See textfield().
-
-=head2 CREATING A PASSWORD FIELD
-
- print $query->password_field(-name=>'secret',
- -value=>'starting value',
- -size=>50,
- -maxlength=>80);
- -or-
-
- print $query->password_field('secret','starting value',50,80);
-
-password_field() is identical to textfield(), except that its contents
-will be starred out on the web page.
-
-JAVASCRIPTING: The B<-onChange>, B<-onFocus>, B<-onBlur>,
-B<-onMouseOver>, B<-onMouseOut> and B<-onSelect> parameters are
-recognized. See textfield().
-
-=head2 CREATING A FILE UPLOAD FIELD
-
- print $query->filefield(-name=>'uploaded_file',
- -default=>'starting value',
- -size=>50,
- -maxlength=>80);
- -or-
-
- print $query->filefield('uploaded_file','starting value',50,80);
-
-filefield() will return a file upload field for Netscape 2.0 browsers.
-In order to take full advantage of this I<you must use the new
-multipart encoding scheme> for the form. You can do this either
-by calling B<start_form()> with an encoding type of B<&CGI::MULTIPART>,
-or by calling the new method B<start_multipart_form()> instead of
-vanilla B<start_form()>.
-
-=over 4
-
-=item B<Parameters>
-
-=item 1.
-
-The first parameter is the required name for the field (-name).
-
-=item 2.
-
-The optional second parameter is the starting value for the field contents
-to be used as the default file name (-default).
-
-For security reasons, browsers don't pay any attention to this field,
-and so the starting value will always be blank. Worse, the field
-loses its "sticky" behavior and forgets its previous contents. The
-starting value field is called for in the HTML specification, however,
-and possibly some browser will eventually provide support for it.
-
-=item 3.
-
-The optional third parameter is the size of the field in
-characters (-size).
-
-=item 4.
-
-The optional fourth parameter is the maximum number of characters the
-field will accept (-maxlength).
-
-=back
-
-When the form is processed, you can retrieve the entered filename
-by calling param():
-
- $filename = $query->param('uploaded_file');
-
-Different browsers will return slightly different things for the
-name. Some browsers return the filename only. Others return the full
-path to the file, using the path conventions of the user's machine.
-Regardless, the name returned is always the name of the file on the
-I<user's> machine, and is unrelated to the name of the temporary file
-that CGI.pm creates during upload spooling (see below).
-
-The filename returned is also a file handle. You can read the contents
-of the file using standard Perl file reading calls:
-
- # Read a text file and print it out
- while (<$filename>) {
- print;
- }
-
- # Copy a binary file to somewhere safe
- open (OUTFILE,">>/usr/local/web/users/feedback");
- while ($bytesread=read($filename,$buffer,1024)) {
- print OUTFILE $buffer;
- }
-
-However, there are problems with the dual nature of the upload fields.
-If you C<use strict>, then Perl will complain when you try to use a
-string as a filehandle. You can get around this by placing the file
-reading code in a block containing the C<no strict> pragma. More
-seriously, it is possible for the remote user to type garbage into the
-upload field, in which case what you get from param() is not a
-filehandle at all, but a string.
-
-To be safe, use the I<upload()> function (new in version 2.47). When
-called with the name of an upload field, I<upload()> returns a
-filehandle, or undef if the parameter is not a valid filehandle.
-
- $fh = $query->upload('uploaded_file');
- while (<$fh>) {
- print;
- }
-
-In an list context, upload() will return an array of filehandles.
-This makes it possible to create forms that use the same name for
-multiple upload fields.
-
-This is the recommended idiom.
-
-When a file is uploaded the browser usually sends along some
-information along with it in the format of headers. The information
-usually includes the MIME content type. Future browsers may send
-other information as well (such as modification date and size). To
-retrieve this information, call uploadInfo(). It returns a reference to
-an associative array containing all the document headers.
-
- $filename = $query->param('uploaded_file');
- $type = $query->uploadInfo($filename)->{'Content-Type'};
- unless ($type eq 'text/html') {
- die "HTML FILES ONLY!";
- }
-
-If you are using a machine that recognizes "text" and "binary" data
-modes, be sure to understand when and how to use them (see the Camel book).
-Otherwise you may find that binary files are corrupted during file
-uploads.
-
-There are occasionally problems involving parsing the uploaded file.
-This usually happens when the user presses "Stop" before the upload is
-finished. In this case, CGI.pm will return undef for the name of the
-uploaded file and set I<cgi_error()> to the string "400 Bad request
-(malformed multipart POST)". This error message is designed so that
-you can incorporate it into a status code to be sent to the browser.
-Example:
-
- $file = $query->upload('uploaded_file');
- if (!$file && $query->cgi_error) {
- print $query->header(-status=>$query->cgi_error);
- exit 0;
- }
-
-You are free to create a custom HTML page to complain about the error,
-if you wish.
-
-You can set up a callback that will be called whenever a file upload
-is being read during the form processing. This is much like the
-UPLOAD_HOOK facility available in Apache::Request, with the exception
-that the first argument to the callback is an Apache::Upload object,
-here it's the remote filename.
-
- $q = CGI->new();
- $q->upload_hook(\&hook,$data);
-
- sub hook
- {
- my ($filename, $buffer, $bytes_read, $data) = @_;
- print "Read $bytes_read bytes of $filename\n";
- }
-
-If using the function-oriented interface, call the CGI::upload_hook()
-method before calling param() or any other CGI functions:
-
- CGI::upload_hook(\&hook,$data);
-
-This method is not exported by default. You will have to import it
-explicitly if you wish to use it without the CGI:: prefix.
-
-If you are using CGI.pm on a Windows platform and find that binary
-files get slightly larger when uploaded but that text files remain the
-same, then you have forgotten to activate binary mode on the output
-filehandle. Be sure to call binmode() on any handle that you create
-to write the uploaded file to disk.
-
-JAVASCRIPTING: The B<-onChange>, B<-onFocus>, B<-onBlur>,
-B<-onMouseOver>, B<-onMouseOut> and B<-onSelect> parameters are
-recognized. See textfield() for details.
-
-=head2 CREATING A POPUP MENU
-
- print $query->popup_menu('menu_name',
- ['eenie','meenie','minie'],
- 'meenie');
-
- -or-
-
- %labels = ('eenie'=>'your first choice',
- 'meenie'=>'your second choice',
- 'minie'=>'your third choice');
- %attributes = ('eenie'=>{'class'=>'class of first choice'});
- print $query->popup_menu('menu_name',
- ['eenie','meenie','minie'],
- 'meenie',\%labels,\%attributes);
-
- -or (named parameter style)-
-
- print $query->popup_menu(-name=>'menu_name',
- -values=>['eenie','meenie','minie'],
- -default=>'meenie',
- -labels=>\%labels,
- -attributes=>\%attributes);
-
-popup_menu() creates a menu.
-
-=over 4
-
-=item 1.
-
-The required first argument is the menu's name (-name).
-
-=item 2.
-
-The required second argument (-values) is an array B<reference>
-containing the list of menu items in the menu. You can pass the
-method an anonymous array, as shown in the example, or a reference to
-a named array, such as "\@foo".
-
-=item 3.
-
-The optional third parameter (-default) is the name of the default
-menu choice. If not specified, the first item will be the default.
-The values of the previous choice will be maintained across queries.
-
-=item 4.
-
-The optional fourth parameter (-labels) is provided for people who
-want to use different values for the user-visible label inside the
-popup menu and the value returned to your script. It's a pointer to an
-associative array relating menu values to user-visible labels. If you
-leave this parameter blank, the menu values will be displayed by
-default. (You can also leave a label undefined if you want to).
-
-=item 5.
-
-The optional fifth parameter (-attributes) is provided to assign
-any of the common HTML attributes to an individual menu item. It's
-a pointer to an associative array relating menu values to another
-associative array with the attribute's name as the key and the
-attribute's value as the value.
-
-=back
-
-When the form is processed, the selected value of the popup menu can
-be retrieved using:
-
- $popup_menu_value = $query->param('menu_name');
-
-JAVASCRIPTING: popup_menu() recognizes the following event handlers:
-B<-onChange>, B<-onFocus>, B<-onMouseOver>, B<-onMouseOut>, and
-B<-onBlur>. See the textfield() section for details on when these
-handlers are called.
-
-=head2 CREATING AN OPTION GROUP
-
-Named parameter style
-
- print $query->popup_menu(-name=>'menu_name',
- -values=>[qw/eenie meenie minie/,
- $q->optgroup(-name=>'optgroup_name',
- -values ['moe','catch'],
- -attributes=>{'catch'=>{'class'=>'red'}}),
- -labels=>{'eenie'=>'one',
- 'meenie'=>'two',
- 'minie'=>'three'},
- -default=>'meenie');
-
- Old style
- print $query->popup_menu('menu_name',
- ['eenie','meenie','minie',
- $q->optgroup('optgroup_name', ['moe', 'catch'],
- {'catch'=>{'class'=>'red'}})],'meenie',
- {'eenie'=>'one','meenie'=>'two','minie'=>'three'});
-
-optgroup creates an option group within a popup menu.
-
-=over 4
-
-=item 1.
-
-The required first argument (B<-name>) is the label attribute of the
-optgroup and is B<not> inserted in the parameter list of the query.
-
-=item 2.
-
-The required second argument (B<-values>) is an array reference
-containing the list of menu items in the menu. You can pass the
-method an anonymous array, as shown in the example, or a reference
-to a named array, such as \@foo. If you pass a HASH reference,
-the keys will be used for the menu values, and the values will be
-used for the menu labels (see -labels below).
-
-=item 3.
-
-The optional third parameter (B<-labels>) allows you to pass a reference
-to an associative array containing user-visible labels for one or more
-of the menu items. You can use this when you want the user to see one
-menu string, but have the browser return your program a different one.
-If you don't specify this, the value string will be used instead
-("eenie", "meenie" and "minie" in this example). This is equivalent
-to using a hash reference for the -values parameter.
-
-=item 4.
-
-An optional fourth parameter (B<-labeled>) can be set to a true value
-and indicates that the values should be used as the label attribute
-for each option element within the optgroup.
-
-=item 5.
-
-An optional fifth parameter (-novals) can be set to a true value and
-indicates to suppress the val attribut in each option element within
-the optgroup.
-
-See the discussion on optgroup at W3C
-(http://www.w3.org/TR/REC-html40/interact/forms.html#edef-OPTGROUP)
-for details.
-
-=item 6.
-
-An optional sixth parameter (-attributes) is provided to assign
-any of the common HTML attributes to an individual menu item. It's
-a pointer to an associative array relating menu values to another
-associative array with the attribute's name as the key and the
-attribute's value as the value.
-
-=back
-
-=head2 CREATING A SCROLLING LIST
-
- print $query->scrolling_list('list_name',
- ['eenie','meenie','minie','moe'],
- ['eenie','moe'],5,'true',{'moe'=>{'class'=>'red'}});
- -or-
-
- print $query->scrolling_list('list_name',
- ['eenie','meenie','minie','moe'],
- ['eenie','moe'],5,'true',
- \%labels,%attributes);
-
- -or-
-
- print $query->scrolling_list(-name=>'list_name',
- -values=>['eenie','meenie','minie','moe'],
- -default=>['eenie','moe'],
- -size=>5,
- -multiple=>'true',
- -labels=>\%labels,
- -attributes=>\%attributes);
-
-scrolling_list() creates a scrolling list.
-
-=over 4
-
-=item B<Parameters:>
-
-=item 1.
-
-The first and second arguments are the list name (-name) and values
-(-values). As in the popup menu, the second argument should be an
-array reference.
-
-=item 2.
-
-The optional third argument (-default) can be either a reference to a
-list containing the values to be selected by default, or can be a
-single value to select. If this argument is missing or undefined,
-then nothing is selected when the list first appears. In the named
-parameter version, you can use the synonym "-defaults" for this
-parameter.
-
-=item 3.
-
-The optional fourth argument is the size of the list (-size).
-
-=item 4.
-
-The optional fifth argument can be set to true to allow multiple
-simultaneous selections (-multiple). Otherwise only one selection
-will be allowed at a time.
-
-=item 5.
-
-The optional sixth argument is a pointer to an associative array
-containing long user-visible labels for the list items (-labels).
-If not provided, the values will be displayed.
-
-=item 6.
-
-The optional sixth parameter (-attributes) is provided to assign
-any of the common HTML attributes to an individual menu item. It's
-a pointer to an associative array relating menu values to another
-associative array with the attribute's name as the key and the
-attribute's value as the value.
-
-When this form is processed, all selected list items will be returned as
-a list under the parameter name 'list_name'. The values of the
-selected items can be retrieved with:
-
- @selected = $query->param('list_name');
-
-=back
-
-JAVASCRIPTING: scrolling_list() recognizes the following event
-handlers: B<-onChange>, B<-onFocus>, B<-onMouseOver>, B<-onMouseOut>
-and B<-onBlur>. See textfield() for the description of when these
-handlers are called.
-
-=head2 CREATING A GROUP OF RELATED CHECKBOXES
-
- print $query->checkbox_group(-name=>'group_name',
- -values=>['eenie','meenie','minie','moe'],
- -default=>['eenie','moe'],
- -linebreak=>'true',
- -labels=>\%labels,
- -attributes=>\%attributes);
-
- print $query->checkbox_group('group_name',
- ['eenie','meenie','minie','moe'],
- ['eenie','moe'],'true',\%labels,
- {'moe'=>{'class'=>'red'}});
-
- HTML3-COMPATIBLE BROWSERS ONLY:
-
- print $query->checkbox_group(-name=>'group_name',
- -values=>['eenie','meenie','minie','moe'],
- -rows=2,-columns=>2);
-
-
-checkbox_group() creates a list of checkboxes that are related
-by the same name.
-
-=over 4
-
-=item B<Parameters:>
-
-=item 1.
-
-The first and second arguments are the checkbox name and values,
-respectively (-name and -values). As in the popup menu, the second
-argument should be an array reference. These values are used for the
-user-readable labels printed next to the checkboxes as well as for the
-values passed to your script in the query string.
-
-=item 2.
-
-The optional third argument (-default) can be either a reference to a
-list containing the values to be checked by default, or can be a
-single value to checked. If this argument is missing or undefined,
-then nothing is selected when the list first appears.
-
-=item 3.
-
-The optional fourth argument (-linebreak) can be set to true to place
-line breaks between the checkboxes so that they appear as a vertical
-list. Otherwise, they will be strung together on a horizontal line.
-
-=item 4.
-
-The optional fifth argument is a pointer to an associative array
-relating the checkbox values to the user-visible labels that will
-be printed next to them (-labels). If not provided, the values will
-be used as the default.
-
-=item 5.
-
-B<HTML3-compatible browsers> (such as Netscape) can take advantage of
-the optional parameters B<-rows>, and B<-columns>. These parameters
-cause checkbox_group() to return an HTML3 compatible table containing
-the checkbox group formatted with the specified number of rows and
-columns. You can provide just the -columns parameter if you wish;
-checkbox_group will calculate the correct number of rows for you.
-
-=item 6.
-
-The optional sixth parameter (-attributes) is provided to assign
-any of the common HTML attributes to an individual menu item. It's
-a pointer to an associative array relating menu values to another
-associative array with the attribute's name as the key and the
-attribute's value as the value.
-
-To include row and column headings in the returned table, you
-can use the B<-rowheaders> and B<-colheaders> parameters. Both
-of these accept a pointer to an array of headings to use.
-The headings are just decorative. They don't reorganize the
-interpretation of the checkboxes -- they're still a single named
-unit.
-
-=back
-
-When the form is processed, all checked boxes will be returned as
-a list under the parameter name 'group_name'. The values of the
-"on" checkboxes can be retrieved with:
-
- @turned_on = $query->param('group_name');
-
-The value returned by checkbox_group() is actually an array of button
-elements. You can capture them and use them within tables, lists,
-or in other creative ways:
-
- @h = $query->checkbox_group(-name=>'group_name',-values=>\@values);
- &use_in_creative_way(@h);
-
-JAVASCRIPTING: checkbox_group() recognizes the B<-onClick>
-parameter. This specifies a JavaScript code fragment or
-function call to be executed every time the user clicks on
-any of the buttons in the group. You can retrieve the identity
-of the particular button clicked on using the "this" variable.
-
-=head2 CREATING A STANDALONE CHECKBOX
-
- print $query->checkbox(-name=>'checkbox_name',
- -checked=>1,
- -value=>'ON',
- -label=>'CLICK ME');
-
- -or-
-
- print $query->checkbox('checkbox_name','checked','ON','CLICK ME');
-
-checkbox() is used to create an isolated checkbox that isn't logically
-related to any others.
-
-=over 4
-
-=item B<Parameters:>
-
-=item 1.
-
-The first parameter is the required name for the checkbox (-name). It
-will also be used for the user-readable label printed next to the
-checkbox.
-
-=item 2.
-
-The optional second parameter (-checked) specifies that the checkbox
-is turned on by default. Synonyms are -selected and -on.
-
-=item 3.
-
-The optional third parameter (-value) specifies the value of the
-checkbox when it is checked. If not provided, the word "on" is
-assumed.
-
-=item 4.
-
-The optional fourth parameter (-label) is the user-readable label to
-be attached to the checkbox. If not provided, the checkbox name is
-used.
-
-=back
-
-The value of the checkbox can be retrieved using:
-
- $turned_on = $query->param('checkbox_name');
-
-JAVASCRIPTING: checkbox() recognizes the B<-onClick>
-parameter. See checkbox_group() for further details.
-
-=head2 CREATING A RADIO BUTTON GROUP
-
- print $query->radio_group(-name=>'group_name',
- -values=>['eenie','meenie','minie'],
- -default=>'meenie',
- -linebreak=>'true',
- -labels=>\%labels,
- -attributes=>\%attributes);
-
- -or-
-
- print $query->radio_group('group_name',['eenie','meenie','minie'],
- 'meenie','true',\%labels,\%attributes);
-
-
- HTML3-COMPATIBLE BROWSERS ONLY:
-
- print $query->radio_group(-name=>'group_name',
- -values=>['eenie','meenie','minie','moe'],
- -rows=2,-columns=>2);
-
-radio_group() creates a set of logically-related radio buttons
-(turning one member of the group on turns the others off)
-
-=over 4
-
-=item B<Parameters:>
-
-=item 1.
-
-The first argument is the name of the group and is required (-name).
-
-=item 2.
-
-The second argument (-values) is the list of values for the radio
-buttons. The values and the labels that appear on the page are
-identical. Pass an array I<reference> in the second argument, either
-using an anonymous array, as shown, or by referencing a named array as
-in "\@foo".
-
-=item 3.
-
-The optional third parameter (-default) is the name of the default
-button to turn on. If not specified, the first item will be the
-default. You can provide a nonexistent button name, such as "-" to
-start up with no buttons selected.
-
-=item 4.
-
-The optional fourth parameter (-linebreak) can be set to 'true' to put
-line breaks between the buttons, creating a vertical list.
-
-=item 5.
-
-The optional fifth parameter (-labels) is a pointer to an associative
-array relating the radio button values to user-visible labels to be
-used in the display. If not provided, the values themselves are
-displayed.
-
-=item 6.
-
-B<HTML3-compatible browsers> (such as Netscape) can take advantage
-of the optional
-parameters B<-rows>, and B<-columns>. These parameters cause
-radio_group() to return an HTML3 compatible table containing
-the radio group formatted with the specified number of rows
-and columns. You can provide just the -columns parameter if you
-wish; radio_group will calculate the correct number of rows
-for you.
-
-=item 6.
-
-The optional sixth parameter (-attributes) is provided to assign
-any of the common HTML attributes to an individual menu item. It's
-a pointer to an associative array relating menu values to another
-associative array with the attribute's name as the key and the
-attribute's value as the value.
-
-To include row and column headings in the returned table, you
-can use the B<-rowheader> and B<-colheader> parameters. Both
-of these accept a pointer to an array of headings to use.
-The headings are just decorative. They don't reorganize the
-interpretation of the radio buttons -- they're still a single named
-unit.
-
-=back
-
-When the form is processed, the selected radio button can
-be retrieved using:
-
- $which_radio_button = $query->param('group_name');
-
-The value returned by radio_group() is actually an array of button
-elements. You can capture them and use them within tables, lists,
-or in other creative ways:
-
- @h = $query->radio_group(-name=>'group_name',-values=>\@values);
- &use_in_creative_way(@h);
-
-=head2 CREATING A SUBMIT BUTTON
-
- print $query->submit(-name=>'button_name',
- -value=>'value');
-
- -or-
-
- print $query->submit('button_name','value');
-
-submit() will create the query submission button. Every form
-should have one of these.
-
-=over 4
-
-=item B<Parameters:>
-
-=item 1.
-
-The first argument (-name) is optional. You can give the button a
-name if you have several submission buttons in your form and you want
-to distinguish between them.
-
-=item 2.
-
-The second argument (-value) is also optional. This gives the button
-a value that will be passed to your script in the query string. The
-name will also be used as the user-visible label.
-
-=item 3.
-
-You can use -label as an alias for -value. I always get confused
-about which of -name and -value changes the user-visible label on the
-button.
-
-=back
-
-You can figure out which button was pressed by using different
-values for each one:
-
- $which_one = $query->param('button_name');
-
-JAVASCRIPTING: radio_group() recognizes the B<-onClick>
-parameter. See checkbox_group() for further details.
-
-=head2 CREATING A RESET BUTTON
-
- print $query->reset
-
-reset() creates the "reset" button. Note that it restores the
-form to its value from the last time the script was called,
-NOT necessarily to the defaults.
-
-Note that this conflicts with the Perl reset() built-in. Use
-CORE::reset() to get the original reset function.
-
-=head2 CREATING A DEFAULT BUTTON
-
- print $query->defaults('button_label')
-
-defaults() creates a button that, when invoked, will cause the
-form to be completely reset to its defaults, wiping out all the
-changes the user ever made.
-
-=head2 CREATING A HIDDEN FIELD
-
- print $query->hidden(-name=>'hidden_name',
- -default=>['value1','value2'...]);
-
- -or-
-
- print $query->hidden('hidden_name','value1','value2'...);
-
-hidden() produces a text field that can't be seen by the user. It
-is useful for passing state variable information from one invocation
-of the script to the next.
-
-=over 4
-
-=item B<Parameters:>
-
-=item 1.
-
-The first argument is required and specifies the name of this
-field (-name).
-
-=item 2.
-
-The second argument is also required and specifies its value
-(-default). In the named parameter style of calling, you can provide
-a single value here or a reference to a whole list
-
-=back
-
-Fetch the value of a hidden field this way:
-
- $hidden_value = $query->param('hidden_name');
-
-Note, that just like all the other form elements, the value of a
-hidden field is "sticky". If you want to replace a hidden field with
-some other values after the script has been called once you'll have to
-do it manually:
-
- $query->param('hidden_name','new','values','here');
-
-=head2 CREATING A CLICKABLE IMAGE BUTTON
-
- print $query->image_button(-name=>'button_name',
- -src=>'/source/URL',
- -align=>'MIDDLE');
-
- -or-
-
- print $query->image_button('button_name','/source/URL','MIDDLE');
-
-image_button() produces a clickable image. When it's clicked on the
-position of the click is returned to your script as "button_name.x"
-and "button_name.y", where "button_name" is the name you've assigned
-to it.
-
-JAVASCRIPTING: image_button() recognizes the B<-onClick>
-parameter. See checkbox_group() for further details.
-
-=over 4
-
-=item B<Parameters:>
-
-=item 1.
-
-The first argument (-name) is required and specifies the name of this
-field.
-
-=item 2.
-
-The second argument (-src) is also required and specifies the URL
-
-=item 3.
-The third option (-align, optional) is an alignment type, and may be
-TOP, BOTTOM or MIDDLE
-
-=back
-
-Fetch the value of the button this way:
- $x = $query->param('button_name.x');
- $y = $query->param('button_name.y');
-
-=head2 CREATING A JAVASCRIPT ACTION BUTTON
-
- print $query->button(-name=>'button_name',
- -value=>'user visible label',
- -onClick=>"do_something()");
-
- -or-
-
- print $query->button('button_name',"do_something()");
-
-button() produces a button that is compatible with Netscape 2.0's
-JavaScript. When it's pressed the fragment of JavaScript code
-pointed to by the B<-onClick> parameter will be executed. On
-non-Netscape browsers this form element will probably not even
-display.
-
-=head1 HTTP COOKIES
-
-Netscape browsers versions 1.1 and higher, and all versions of
-Internet Explorer, support a so-called "cookie" designed to help
-maintain state within a browser session. CGI.pm has several methods
-that support cookies.
-
-A cookie is a name=value pair much like the named parameters in a CGI
-query string. CGI scripts create one or more cookies and send
-them to the browser in the HTTP header. The browser maintains a list
-of cookies that belong to a particular Web server, and returns them
-to the CGI script during subsequent interactions.
-
-In addition to the required name=value pair, each cookie has several
-optional attributes:
-
-=over 4
-
-=item 1. an expiration time
-
-This is a time/date string (in a special GMT format) that indicates
-when a cookie expires. The cookie will be saved and returned to your
-script until this expiration date is reached if the user exits
-the browser and restarts it. If an expiration date isn't specified, the cookie
-will remain active until the user quits the browser.
-
-=item 2. a domain
-
-This is a partial or complete domain name for which the cookie is
-valid. The browser will return the cookie to any host that matches
-the partial domain name. For example, if you specify a domain name
-of ".capricorn.com", then the browser will return the cookie to
-Web servers running on any of the machines "www.capricorn.com",
-"www2.capricorn.com", "feckless.capricorn.com", etc. Domain names
-must contain at least two periods to prevent attempts to match
-on top level domains like ".edu". If no domain is specified, then
-the browser will only return the cookie to servers on the host the
-cookie originated from.
-
-=item 3. a path
-
-If you provide a cookie path attribute, the browser will check it
-against your script's URL before returning the cookie. For example,
-if you specify the path "/cgi-bin", then the cookie will be returned
-to each of the scripts "/cgi-bin/tally.pl", "/cgi-bin/order.pl",
-and "/cgi-bin/customer_service/complain.pl", but not to the script
-"/cgi-private/site_admin.pl". By default, path is set to "/", which
-causes the cookie to be sent to any CGI script on your site.
-
-=item 4. a "secure" flag
-
-If the "secure" attribute is set, the cookie will only be sent to your
-script if the CGI request is occurring on a secure channel, such as SSL.
-
-=back
-
-The interface to HTTP cookies is the B<cookie()> method:
-
- $cookie = $query->cookie(-name=>'sessionID',
- -value=>'xyzzy',
- -expires=>'+1h',
- -path=>'/cgi-bin/database',
- -domain=>'.capricorn.org',
- -secure=>1);
- print $query->header(-cookie=>$cookie);
-
-B<cookie()> creates a new cookie. Its parameters include:
-
-=over 4
-
-=item B<-name>
-
-The name of the cookie (required). This can be any string at all.
-Although browsers limit their cookie names to non-whitespace
-alphanumeric characters, CGI.pm removes this restriction by escaping
-and unescaping cookies behind the scenes.
-
-=item B<-value>
-
-The value of the cookie. This can be any scalar value,
-array reference, or even associative array reference. For example,
-you can store an entire associative array into a cookie this way:
-
- $cookie=$query->cookie(-name=>'family information',
- -value=>\%childrens_ages);
-
-=item B<-path>
-
-The optional partial path for which this cookie will be valid, as described
-above.
-
-=item B<-domain>
-
-The optional partial domain for which this cookie will be valid, as described
-above.
-
-=item B<-expires>
-
-The optional expiration date for this cookie. The format is as described
-in the section on the B<header()> method:
-
- "+1h" one hour from now
-
-=item B<-secure>
-
-If set to true, this cookie will only be used within a secure
-SSL session.
-
-=back
-
-The cookie created by cookie() must be incorporated into the HTTP
-header within the string returned by the header() method:
-
- print $query->header(-cookie=>$my_cookie);
-
-To create multiple cookies, give header() an array reference:
-
- $cookie1 = $query->cookie(-name=>'riddle_name',
- -value=>"The Sphynx's Question");
- $cookie2 = $query->cookie(-name=>'answers',
- -value=>\%answers);
- print $query->header(-cookie=>[$cookie1,$cookie2]);
-
-To retrieve a cookie, request it by name by calling cookie() method
-without the B<-value> parameter:
-
- use CGI;
- $query = new CGI;
- $riddle = $query->cookie('riddle_name');
- %answers = $query->cookie('answers');
-
-Cookies created with a single scalar value, such as the "riddle_name"
-cookie, will be returned in that form. Cookies with array and hash
-values can also be retrieved.
-
-The cookie and CGI namespaces are separate. If you have a parameter
-named 'answers' and a cookie named 'answers', the values retrieved by
-param() and cookie() are independent of each other. However, it's
-simple to turn a CGI parameter into a cookie, and vice-versa:
-
- # turn a CGI parameter into a cookie
- $c=$q->cookie(-name=>'answers',-value=>[$q->param('answers')]);
- # vice-versa
- $q->param(-name=>'answers',-value=>[$q->cookie('answers')]);
-
-See the B<cookie.cgi> example script for some ideas on how to use
-cookies effectively.
-
-=head1 WORKING WITH FRAMES
-
-It's possible for CGI.pm scripts to write into several browser panels
-and windows using the HTML 4 frame mechanism. There are three
-techniques for defining new frames programmatically:
-
-=over 4
-
-=item 1. Create a <Frameset> document
-
-After writing out the HTTP header, instead of creating a standard
-HTML document using the start_html() call, create a <frameset>
-document that defines the frames on the page. Specify your script(s)
-(with appropriate parameters) as the SRC for each of the frames.
-
-There is no specific support for creating <frameset> sections
-in CGI.pm, but the HTML is very simple to write. See the frame
-documentation in Netscape's home pages for details
-
- http://home.netscape.com/assist/net_sites/frames.html
-
-=item 2. Specify the destination for the document in the HTTP header
-
-You may provide a B<-target> parameter to the header() method:
-
- print $q->header(-target=>'ResultsWindow');
-
-This will tell the browser to load the output of your script into the
-frame named "ResultsWindow". If a frame of that name doesn't already
-exist, the browser will pop up a new window and load your script's
-document into that. There are a number of magic names that you can
-use for targets. See the frame documents on Netscape's home pages for
-details.
-
-=item 3. Specify the destination for the document in the <form> tag
-
-You can specify the frame to load in the FORM tag itself. With
-CGI.pm it looks like this:
-
- print $q->start_form(-target=>'ResultsWindow');
-
-When your script is reinvoked by the form, its output will be loaded
-into the frame named "ResultsWindow". If one doesn't already exist
-a new window will be created.
-
-=back
-
-The script "frameset.cgi" in the examples directory shows one way to
-create pages in which the fill-out form and the response live in
-side-by-side frames.
-
-=head1 LIMITED SUPPORT FOR CASCADING STYLE SHEETS
-
-CGI.pm has limited support for HTML3's cascading style sheets (css).
-To incorporate a stylesheet into your document, pass the
-start_html() method a B<-style> parameter. The value of this
-parameter may be a scalar, in which case it is treated as the source
-URL for the stylesheet, or it may be a hash reference. In the latter
-case you should provide the hash with one or more of B<-src> or
-B<-code>. B<-src> points to a URL where an externally-defined
-stylesheet can be found. B<-code> points to a scalar value to be
-incorporated into a <style> section. Style definitions in B<-code>
-override similarly-named ones in B<-src>, hence the name "cascading."
-
-You may also specify the type of the stylesheet by adding the optional
-B<-type> parameter to the hash pointed to by B<-style>. If not
-specified, the style defaults to 'text/css'.
-
-To refer to a style within the body of your document, add the
-B<-class> parameter to any HTML element:
-
- print h1({-class=>'Fancy'},'Welcome to the Party');
-
-Or define styles on the fly with the B<-style> parameter:
-
- print h1({-style=>'Color: red;'},'Welcome to Hell');
-
-You may also use the new B<span()> element to apply a style to a
-section of text:
-
- print span({-style=>'Color: red;'},
- h1('Welcome to Hell'),
- "Where did that handbasket get to?"
- );
-
-Note that you must import the ":html3" definitions to have the
-B<span()> method available. Here's a quick and dirty example of using
-CSS's. See the CSS specification at
-http://www.w3.org/pub/WWW/TR/Wd-css-1.html for more information.
-
- use CGI qw/:standard :html3/;
-
- #here's a stylesheet incorporated directly into the page
- $newStyle=<<END;
- <!--
- P.Tip {
- margin-right: 50pt;
- margin-left: 50pt;
- color: red;
- }
- P.Alert {
- font-size: 30pt;
- font-family: sans-serif;
- color: red;
- }
- -->
- END
- print header();
- print start_html( -title=>'CGI with Style',
- -style=>{-src=>'http://www.capricorn.com/style/st1.css',
- -code=>$newStyle}
- );
- print h1('CGI with Style'),
- p({-class=>'Tip'},
- "Better read the cascading style sheet spec before playing with this!"),
- span({-style=>'color: magenta'},
- "Look Mom, no hands!",
- p(),
- "Whooo wee!"
- );
- print end_html;
-
-Pass an array reference to B<-code> or B<-src> in order to incorporate
-multiple stylesheets into your document.
-
-Should you wish to incorporate a verbatim stylesheet that includes
-arbitrary formatting in the header, you may pass a -verbatim tag to
-the -style hash, as follows:
-
-print $q->start_html (-STYLE => {-verbatim => '@import
-url("/server-common/css/'.$cssFile.'");',
- -src => '/server-common/css/core.css'});
-</blockquote></pre>
-
-
-This will generate an HTML header that contains this:
-
- <link rel="stylesheet" type="text/css" href="/server-common/css/core.css">
- <style type="text/css">
- @import url("/server-common/css/main.css");
- </style>
-
-Any additional arguments passed in the -style value will be
-incorporated into the <link> tag. For example:
-
- start_html(-style=>{-src=>['/styles/print.css','/styles/layout.css'],
- -media => 'all'});
-
-This will give:
-
- <link rel="stylesheet" type="text/css" href="/styles/print.css" media="all"/>
- <link rel="stylesheet" type="text/css" href="/styles/layout.css" media="all"/>
-
-<p>
-
-To make more complicated <link> tags, use the Link() function
-and pass it to start_html() in the -head argument, as in:
-
- @h = (Link({-rel=>'stylesheet',-type=>'text/css',-src=>'/ss/ss.css',-media=>'all'}),
- Link({-rel=>'stylesheet',-type=>'text/css',-src=>'/ss/fred.css',-media=>'paper'}));
- print start_html({-head=>\@h})
-
-=head1 DEBUGGING
-
-If you are running the script from the command line or in the perl
-debugger, you can pass the script a list of keywords or
-parameter=value pairs on the command line or from standard input (you
-don't have to worry about tricking your script into reading from
-environment variables). You can pass keywords like this:
-
- your_script.pl keyword1 keyword2 keyword3
-
-or this:
-
- your_script.pl keyword1+keyword2+keyword3
-
-or this:
-
- your_script.pl name1=value1 name2=value2
-
-or this:
-
- your_script.pl name1=value1&name2=value2
-
-To turn off this feature, use the -no_debug pragma.
-
-To test the POST method, you may enable full debugging with the -debug
-pragma. This will allow you to feed newline-delimited name=value
-pairs to the script on standard input.
-
-When debugging, you can use quotes and backslashes to escape
-characters in the familiar shell manner, letting you place
-spaces and other funny characters in your parameter=value
-pairs:
-
- your_script.pl "name1='I am a long value'" "name2=two\ words"
-
-Finally, you can set the path info for the script by prefixing the first
-name/value parameter with the path followed by a question mark (?):
-
- your_script.pl /your/path/here?name1=value1&name2=value2
-
-=head2 DUMPING OUT ALL THE NAME/VALUE PAIRS
-
-The Dump() method produces a string consisting of all the query's
-name/value pairs formatted nicely as a nested list. This is useful
-for debugging purposes:
-
- print $query->Dump
-
-
-Produces something that looks like:
-
- <ul>
- <li>name1
- <ul>
- <li>value1
- <li>value2
- </ul>
- <li>name2
- <ul>
- <li>value1
- </ul>
- </ul>
-
-As a shortcut, you can interpolate the entire CGI object into a string
-and it will be replaced with the a nice HTML dump shown above:
-
- $query=new CGI;
- print "<h2>Current Values</h2> $query\n";
-
-=head1 FETCHING ENVIRONMENT VARIABLES
-
-Some of the more useful environment variables can be fetched
-through this interface. The methods are as follows:
-
-=over 4
-
-=item B<Accept()>
-
-Return a list of MIME types that the remote browser accepts. If you
-give this method a single argument corresponding to a MIME type, as in
-$query->Accept('text/html'), it will return a floating point value
-corresponding to the browser's preference for this type from 0.0
-(don't want) to 1.0. Glob types (e.g. text/*) in the browser's accept
-list are handled correctly.
-
-Note that the capitalization changed between version 2.43 and 2.44 in
-order to avoid conflict with Perl's accept() function.
-
-=item B<raw_cookie()>
-
-Returns the HTTP_COOKIE variable, an HTTP extension implemented by
-Netscape browsers version 1.1 and higher, and all versions of Internet
-Explorer. Cookies have a special format, and this method call just
-returns the raw form (?cookie dough). See cookie() for ways of
-setting and retrieving cooked cookies.
-
-Called with no parameters, raw_cookie() returns the packed cookie
-structure. You can separate it into individual cookies by splitting
-on the character sequence "; ". Called with the name of a cookie,
-retrieves the B<unescaped> form of the cookie. You can use the
-regular cookie() method to get the names, or use the raw_fetch()
-method from the CGI::Cookie module.
-
-=item B<user_agent()>
-
-Returns the HTTP_USER_AGENT variable. If you give
-this method a single argument, it will attempt to
-pattern match on it, allowing you to do something
-like $query->user_agent(netscape);
-
-=item B<path_info()>
-
-Returns additional path information from the script URL.
-E.G. fetching /cgi-bin/your_script/additional/stuff will result in
-$query->path_info() returning "/additional/stuff".
-
-NOTE: The Microsoft Internet Information Server
-is broken with respect to additional path information. If
-you use the Perl DLL library, the IIS server will attempt to
-execute the additional path information as a Perl script.
-If you use the ordinary file associations mapping, the
-path information will be present in the environment,
-but incorrect. The best thing to do is to avoid using additional
-path information in CGI scripts destined for use with IIS.
-
-=item B<path_translated()>
-
-As per path_info() but returns the additional
-path information translated into a physical path, e.g.
-"/usr/local/etc/httpd/htdocs/additional/stuff".
-
-The Microsoft IIS is broken with respect to the translated
-path as well.
-
-=item B<remote_host()>
-
-Returns either the remote host name or IP address.
-if the former is unavailable.
-
-=item B<script_name()>
-Return the script name as a partial URL, for self-refering
-scripts.
-
-=item B<referer()>
-
-Return the URL of the page the browser was viewing
-prior to fetching your script. Not available for all
-browsers.
-
-=item B<auth_type ()>
-
-Return the authorization/verification method in use for this
-script, if any.
-
-=item B<server_name ()>
-
-Returns the name of the server, usually the machine's host
-name.
-
-=item B<virtual_host ()>
-
-When using virtual hosts, returns the name of the host that
-the browser attempted to contact
-
-=item B<server_port ()>
-
-Return the port that the server is listening on.
-
-=item B<virtual_port ()>
-
-Like server_port() except that it takes virtual hosts into account.
-Use this when running with virtual hosts.
-
-=item B<server_software ()>
-
-Returns the server software and version number.
-
-=item B<remote_user ()>
-
-Return the authorization/verification name used for user
-verification, if this script is protected.
-
-=item B<user_name ()>
-
-Attempt to obtain the remote user's name, using a variety of different
-techniques. This only works with older browsers such as Mosaic.
-Newer browsers do not report the user name for privacy reasons!
-
-=item B<request_method()>
-
-Returns the method used to access your script, usually
-one of 'POST', 'GET' or 'HEAD'.
-
-=item B<content_type()>
-
-Returns the content_type of data submitted in a POST, generally
-multipart/form-data or application/x-www-form-urlencoded
-
-=item B<http()>
-
-Called with no arguments returns the list of HTTP environment
-variables, including such things as HTTP_USER_AGENT,
-HTTP_ACCEPT_LANGUAGE, and HTTP_ACCEPT_CHARSET, corresponding to the
-like-named HTTP header fields in the request. Called with the name of
-an HTTP header field, returns its value. Capitalization and the use
-of hyphens versus underscores are not significant.
-
-For example, all three of these examples are equivalent:
-
- $requested_language = $q->http('Accept-language');
- $requested_language = $q->http('Accept_language');
- $requested_language = $q->http('HTTP_ACCEPT_LANGUAGE');
-
-=item B<https()>
-
-The same as I<http()>, but operates on the HTTPS environment variables
-present when the SSL protocol is in effect. Can be used to determine
-whether SSL is turned on.
-
-=back
-
-=head1 USING NPH SCRIPTS
-
-NPH, or "no-parsed-header", scripts bypass the server completely by
-sending the complete HTTP header directly to the browser. This has
-slight performance benefits, but is of most use for taking advantage
-of HTTP extensions that are not directly supported by your server,
-such as server push and PICS headers.
-
-Servers use a variety of conventions for designating CGI scripts as
-NPH. Many Unix servers look at the beginning of the script's name for
-the prefix "nph-". The Macintosh WebSTAR server and Microsoft's
-Internet Information Server, in contrast, try to decide whether a
-program is an NPH script by examining the first line of script output.
-
-
-CGI.pm supports NPH scripts with a special NPH mode. When in this
-mode, CGI.pm will output the necessary extra header information when
-the header() and redirect() methods are
-called.
-
-The Microsoft Internet Information Server requires NPH mode. As of
-version 2.30, CGI.pm will automatically detect when the script is
-running under IIS and put itself into this mode. You do not need to
-do this manually, although it won't hurt anything if you do. However,
-note that if you have applied Service Pack 6, much of the
-functionality of NPH scripts, including the ability to redirect while
-setting a cookie, b<do not work at all> on IIS without a special patch
-from Microsoft. See
-http://support.microsoft.com/support/kb/articles/Q280/3/41.ASP:
-Non-Parsed Headers Stripped From CGI Applications That Have nph-
-Prefix in Name.
-
-=over 4
-
-=item In the B<use> statement
-
-Simply add the "-nph" pragmato the list of symbols to be imported into
-your script:
-
- use CGI qw(:standard -nph)
-
-=item By calling the B<nph()> method:
-
-Call B<nph()> with a non-zero parameter at any point after using CGI.pm in your program.
-
- CGI->nph(1)
-
-=item By using B<-nph> parameters
-
-in the B<header()> and B<redirect()> statements:
-
- print $q->header(-nph=>1);
-
-=back
-
-=head1 Server Push
-
-CGI.pm provides four simple functions for producing multipart
-documents of the type needed to implement server push. These
-functions were graciously provided by Ed Jordan <ed@fidalgo.net>. To
-import these into your namespace, you must import the ":push" set.
-You are also advised to put the script into NPH mode and to set $| to
-1 to avoid buffering problems.
-
-Here is a simple script that demonstrates server push:
-
- #!/usr/local/bin/perl
- use CGI qw/:push -nph/;
- $| = 1;
- print multipart_init(-boundary=>'----here we go!');
- foreach (0 .. 4) {
- print multipart_start(-type=>'text/plain'),
- "The current time is ",scalar(localtime),"\n";
- if ($_ < 4) {
- print multipart_end;
- } else {
- print multipart_final;
- }
- sleep 1;
- }
-
-This script initializes server push by calling B<multipart_init()>.
-It then enters a loop in which it begins a new multipart section by
-calling B<multipart_start()>, prints the current local time,
-and ends a multipart section with B<multipart_end()>. It then sleeps
-a second, and begins again. On the final iteration, it ends the
-multipart section with B<multipart_final()> rather than with
-B<multipart_end()>.
-
-=over 4
-
-=item multipart_init()
-
- multipart_init(-boundary=>$boundary);
-
-Initialize the multipart system. The -boundary argument specifies
-what MIME boundary string to use to separate parts of the document.
-If not provided, CGI.pm chooses a reasonable boundary for you.
-
-=item multipart_start()
-
- multipart_start(-type=>$type)
-
-Start a new part of the multipart document using the specified MIME
-type. If not specified, text/html is assumed.
-
-=item multipart_end()
-
- multipart_end()
-
-End a part. You must remember to call multipart_end() once for each
-multipart_start(), except at the end of the last part of the multipart
-document when multipart_final() should be called instead of multipart_end().
-
-=item multipart_final()
-
- multipart_final()
-
-End all parts. You should call multipart_final() rather than
-multipart_end() at the end of the last part of the multipart document.
-
-=back
-
-Users interested in server push applications should also have a look
-at the CGI::Push module.
-
-Only Netscape Navigator supports server push. Internet Explorer
-browsers do not.
-
-=head1 Avoiding Denial of Service Attacks
-
-A potential problem with CGI.pm is that, by default, it attempts to
-process form POSTings no matter how large they are. A wily hacker
-could attack your site by sending a CGI script a huge POST of many
-megabytes. CGI.pm will attempt to read the entire POST into a
-variable, growing hugely in size until it runs out of memory. While
-the script attempts to allocate the memory the system may slow down
-dramatically. This is a form of denial of service attack.
-
-Another possible attack is for the remote user to force CGI.pm to
-accept a huge file upload. CGI.pm will accept the upload and store it
-in a temporary directory even if your script doesn't expect to receive
-an uploaded file. CGI.pm will delete the file automatically when it
-terminates, but in the meantime the remote user may have filled up the
-server's disk space, causing problems for other programs.
-
-The best way to avoid denial of service attacks is to limit the amount
-of memory, CPU time and disk space that CGI scripts can use. Some Web
-servers come with built-in facilities to accomplish this. In other
-cases, you can use the shell I<limit> or I<ulimit>
-commands to put ceilings on CGI resource usage.
-
-
-CGI.pm also has some simple built-in protections against denial of
-service attacks, but you must activate them before you can use them.
-These take the form of two global variables in the CGI name space:
-
-=over 4
-
-=item B<$CGI::POST_MAX>
-
-If set to a non-negative integer, this variable puts a ceiling
-on the size of POSTings, in bytes. If CGI.pm detects a POST
-that is greater than the ceiling, it will immediately exit with an error
-message. This value will affect both ordinary POSTs and
-multipart POSTs, meaning that it limits the maximum size of file
-uploads as well. You should set this to a reasonably high
-value, such as 1 megabyte.
-
-=item B<$CGI::DISABLE_UPLOADS>
-
-If set to a non-zero value, this will disable file uploads
-completely. Other fill-out form values will work as usual.
-
-=back
-
-You can use these variables in either of two ways.
-
-=over 4
-
-=item B<1. On a script-by-script basis>
-
-Set the variable at the top of the script, right after the "use" statement:
-
- use CGI qw/:standard/;
- use CGI::Carp 'fatalsToBrowser';
- $CGI::POST_MAX=1024 * 100; # max 100K posts
- $CGI::DISABLE_UPLOADS = 1; # no uploads
-
-=item B<2. Globally for all scripts>
-
-Open up CGI.pm, find the definitions for $POST_MAX and
-$DISABLE_UPLOADS, and set them to the desired values. You'll
-find them towards the top of the file in a subroutine named
-initialize_globals().
-
-=back
-
-An attempt to send a POST larger than $POST_MAX bytes will cause
-I<param()> to return an empty CGI parameter list. You can test for
-this event by checking I<cgi_error()>, either after you create the CGI
-object or, if you are using the function-oriented interface, call
-<param()> for the first time. If the POST was intercepted, then
-cgi_error() will return the message "413 POST too large".
-
-This error message is actually defined by the HTTP protocol, and is
-designed to be returned to the browser as the CGI script's status
- code. For example:
-
- $uploaded_file = param('upload');
- if (!$uploaded_file && cgi_error()) {
- print header(-status=>cgi_error());
- exit 0;
- }
-
-However it isn't clear that any browser currently knows what to do
-with this status code. It might be better just to create an
-HTML page that warns the user of the problem.
-
-=head1 COMPATIBILITY WITH CGI-LIB.PL
-
-To make it easier to port existing programs that use cgi-lib.pl the
-compatibility routine "ReadParse" is provided. Porting is simple:
-
-OLD VERSION
- require "cgi-lib.pl";
- &ReadParse;
- print "The value of the antique is $in{antique}.\n";
-
-NEW VERSION
- use CGI;
- CGI::ReadParse;
- print "The value of the antique is $in{antique}.\n";
-
-CGI.pm's ReadParse() routine creates a tied variable named %in,
-which can be accessed to obtain the query variables. Like
-ReadParse, you can also provide your own variable. Infrequently
-used features of ReadParse, such as the creation of @in and $in
-variables, are not supported.
-
-Once you use ReadParse, you can retrieve the query object itself
-this way:
-
- $q = $in{CGI};
- print $q->textfield(-name=>'wow',
- -value=>'does this really work?');
-
-This allows you to start using the more interesting features
-of CGI.pm without rewriting your old scripts from scratch.
-
-=head1 AUTHOR INFORMATION
-
-Copyright 1995-1998, Lincoln D. Stein. All rights reserved.
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-Address bug reports and comments to: lstein@cshl.org. When sending
-bug reports, please provide the version of CGI.pm, the version of
-Perl, the name and version of your Web server, and the name and
-version of the operating system you are using. If the problem is even
-remotely browser dependent, please provide information about the
-affected browers as well.
-
-=head1 CREDITS
-
-Thanks very much to:
-
-=over 4
-
-=item Matt Heffron (heffron@falstaff.css.beckman.com)
-
-=item James Taylor (james.taylor@srs.gov)
-
-=item Scott Anguish <sanguish@digifix.com>
-
-=item Mike Jewell (mlj3u@virginia.edu)
-
-=item Timothy Shimmin (tes@kbs.citri.edu.au)
-
-=item Joergen Haegg (jh@axis.se)
-
-=item Laurent Delfosse (delfosse@delfosse.com)
-
-=item Richard Resnick (applepi1@aol.com)
-
-=item Craig Bishop (csb@barwonwater.vic.gov.au)
-
-=item Tony Curtis (tc@vcpc.univie.ac.at)
-
-=item Tim Bunce (Tim.Bunce@ig.co.uk)
-
-=item Tom Christiansen (tchrist@convex.com)
-
-=item Andreas Koenig (k@franz.ww.TU-Berlin.DE)
-
-=item Tim MacKenzie (Tim.MacKenzie@fulcrum.com.au)
-
-=item Kevin B. Hendricks (kbhend@dogwood.tyler.wm.edu)
-
-=item Stephen Dahmen (joyfire@inxpress.net)
-
-=item Ed Jordan (ed@fidalgo.net)
-
-=item David Alan Pisoni (david@cnation.com)
-
-=item Doug MacEachern (dougm@opengroup.org)
-
-=item Robin Houston (robin@oneworld.org)
-
-=item ...and many many more...
-
-for suggestions and bug fixes.
-
-=back
-
-=head1 A COMPLETE EXAMPLE OF A SIMPLE FORM-BASED SCRIPT
-
-
- #!/usr/local/bin/perl
-
- use CGI;
-
- $query = new CGI;
-
- print $query->header;
- print $query->start_html("Example CGI.pm Form");
- print "<h1> Example CGI.pm Form</h1>\n";
- &print_prompt($query);
- &do_work($query);
- &print_tail;
- print $query->end_html;
-
- sub print_prompt {
- my($query) = @_;
-
- print $query->start_form;
- print "<em>What's your name?</em><br>";
- print $query->textfield('name');
- print $query->checkbox('Not my real name');
-
- print "<p><em>Where can you find English Sparrows?</em><br>";
- print $query->checkbox_group(
- -name=>'Sparrow locations',
- -values=>[England,France,Spain,Asia,Hoboken],
- -linebreak=>'yes',
- -defaults=>[England,Asia]);
-
- print "<p><em>How far can they fly?</em><br>",
- $query->radio_group(
- -name=>'how far',
- -values=>['10 ft','1 mile','10 miles','real far'],
- -default=>'1 mile');
-
- print "<p><em>What's your favorite color?</em> ";
- print $query->popup_menu(-name=>'Color',
- -values=>['black','brown','red','yellow'],
- -default=>'red');
-
- print $query->hidden('Reference','Monty Python and the Holy Grail');
-
- print "<p><em>What have you got there?</em><br>";
- print $query->scrolling_list(
- -name=>'possessions',
- -values=>['A Coconut','A Grail','An Icon',
- 'A Sword','A Ticket'],
- -size=>5,
- -multiple=>'true');
-
- print "<p><em>Any parting comments?</em><br>";
- print $query->textarea(-name=>'Comments',
- -rows=>10,
- -columns=>50);
-
- print "<p>",$query->reset;
- print $query->submit('Action','Shout');
- print $query->submit('Action','Scream');
- print $query->endform;
- print "<hr>\n";
- }
-
- sub do_work {
- my($query) = @_;
- my(@values,$key);
-
- print "<h2>Here are the current settings in this form</h2>";
-
- foreach $key ($query->param) {
- print "<strong>$key</strong> -> ";
- @values = $query->param($key);
- print join(", ",@values),"<br>\n";
- }
- }
-
- sub print_tail {
- print <<END;
- <hr>
- <address>Lincoln D. Stein</address><br>
- <a href="/">Home Page</a>
- END
- }
-
-=head1 BUGS
-
-Please report them.
-
-=head1 SEE ALSO
-
-L<CGI::Carp>, L<CGI::Fast>, L<CGI::Pretty>
-
-=cut
-
diff --git a/lib/CGI/Apache.pm b/lib/CGI/Apache.pm
deleted file mode 100644
index c711a48..0000000
--- a/lib/CGI/Apache.pm
+++ /dev/null
@@ -1,26 +0,0 @@
-use CGI;
-
-$VERSION = '1.00';
-
-1;
-__END__
-
-=head1 NAME
-
-CGI::Apache - Backward compatibility module for CGI.pm
-
-=head1 SYNOPSIS
-
-Do not use this module. It is deprecated.
-
-=head1 ABSTRACT
-
-=head1 DESCRIPTION
-
-=head1 AUTHOR INFORMATION
-
-=head1 BUGS
-
-=head1 SEE ALSO
-
-=cut
diff --git a/lib/CGI/Carp.pm b/lib/CGI/Carp.pm
deleted file mode 100644
index e25cd7f..0000000
--- a/lib/CGI/Carp.pm
+++ /dev/null
@@ -1,524 +0,0 @@
-package CGI::Carp;
-
-=head1 NAME
-
-B<CGI::Carp> - CGI routines for writing to the HTTPD (or other) error log
-
-=head1 SYNOPSIS
-
- use CGI::Carp;
-
- croak "We're outta here!";
- confess "It was my fault: $!";
- carp "It was your fault!";
- warn "I'm confused";
- die "I'm dying.\n";
-
- use CGI::Carp qw(cluck);
- cluck "I wouldn't do that if I were you";
-
- use CGI::Carp qw(fatalsToBrowser);
- die "Fatal error messages are now sent to browser";
-
-=head1 DESCRIPTION
-
-CGI scripts have a nasty habit of leaving warning messages in the error
-logs that are neither time stamped nor fully identified. Tracking down
-the script that caused the error is a pain. This fixes that. Replace
-the usual
-
- use Carp;
-
-with
-
- use CGI::Carp
-
-And the standard warn(), die (), croak(), confess() and carp() calls
-will automagically be replaced with functions that write out nicely
-time-stamped messages to the HTTP server error log.
-
-For example:
-
- [Fri Nov 17 21:40:43 1995] test.pl: I'm confused at test.pl line 3.
- [Fri Nov 17 21:40:43 1995] test.pl: Got an error message: Permission denied.
- [Fri Nov 17 21:40:43 1995] test.pl: I'm dying.
-
-=head1 REDIRECTING ERROR MESSAGES
-
-By default, error messages are sent to STDERR. Most HTTPD servers
-direct STDERR to the server's error log. Some applications may wish
-to keep private error logs, distinct from the server's error log, or
-they may wish to direct error messages to STDOUT so that the browser
-will receive them.
-
-The C<carpout()> function is provided for this purpose. Since
-carpout() is not exported by default, you must import it explicitly by
-saying
-
- use CGI::Carp qw(carpout);
-
-The carpout() function requires one argument, which should be a
-reference to an open filehandle for writing errors. It should be
-called in a C<BEGIN> block at the top of the CGI application so that
-compiler errors will be caught. Example:
-
- BEGIN {
- use CGI::Carp qw(carpout);
- open(LOG, ">>/usr/local/cgi-logs/mycgi-log") or
- die("Unable to open mycgi-log: $!\n");
- carpout(LOG);
- }
-
-carpout() does not handle file locking on the log for you at this point.
-
-The real STDERR is not closed -- it is moved to CGI::Carp::SAVEERR. Some
-servers, when dealing with CGI scripts, close their connection to the
-browser when the script closes STDOUT and STDERR. CGI::Carp::SAVEERR is there to
-prevent this from happening prematurely.
-
-You can pass filehandles to carpout() in a variety of ways. The "correct"
-way according to Tom Christiansen is to pass a reference to a filehandle
-GLOB:
-
- carpout(\*LOG);
-
-This looks weird to mere mortals however, so the following syntaxes are
-accepted as well:
-
- carpout(LOG);
- carpout(main::LOG);
- carpout(main'LOG);
- carpout(\LOG);
- carpout(\'main::LOG');
-
- ... and so on
-
-FileHandle and other objects work as well.
-
-Use of carpout() is not great for performance, so it is recommended
-for debugging purposes or for moderate-use applications. A future
-version of this module may delay redirecting STDERR until one of the
-CGI::Carp methods is called to prevent the performance hit.
-
-=head1 MAKING PERL ERRORS APPEAR IN THE BROWSER WINDOW
-
-If you want to send fatal (die, confess) errors to the browser, ask to
-import the special "fatalsToBrowser" subroutine:
-
- use CGI::Carp qw(fatalsToBrowser);
- die "Bad error here";
-
-Fatal errors will now be echoed to the browser as well as to the log. CGI::Carp
-arranges to send a minimal HTTP header to the browser so that even errors that
-occur in the early compile phase will be seen.
-Nonfatal errors will still be directed to the log file only (unless redirected
-with carpout).
-
-=head2 Changing the default message
-
-By default, the software error message is followed by a note to
-contact the Webmaster by e-mail with the time and date of the error.
-If this message is not to your liking, you can change it using the
-set_message() routine. This is not imported by default; you should
-import it on the use() line:
-
- use CGI::Carp qw(fatalsToBrowser set_message);
- set_message("It's not a bug, it's a feature!");
-
-You may also pass in a code reference in order to create a custom
-error message. At run time, your code will be called with the text
-of the error message that caused the script to die. Example:
-
- use CGI::Carp qw(fatalsToBrowser set_message);
- BEGIN {
- sub handle_errors {
- my $msg = shift;
- print "<h1>Oh gosh</h1>";
- print "<p>Got an error: $msg</p>";
- }
- set_message(\&handle_errors);
- }
-
-In order to correctly intercept compile-time errors, you should call
-set_message() from within a BEGIN{} block.
-
-=head1 MAKING WARNINGS APPEAR AS HTML COMMENTS
-
-It is now also possible to make non-fatal errors appear as HTML
-comments embedded in the output of your program. To enable this
-feature, export the new "warningsToBrowser" subroutine. Since sending
-warnings to the browser before the HTTP headers have been sent would
-cause an error, any warnings are stored in an internal buffer until
-you call the warningsToBrowser() subroutine with a true argument:
-
- use CGI::Carp qw(fatalsToBrowser warningsToBrowser);
- use CGI qw(:standard);
- print header();
- warningsToBrowser(1);
-
-You may also give a false argument to warningsToBrowser() to prevent
-warnings from being sent to the browser while you are printing some
-content where HTML comments are not allowed:
-
- warningsToBrowser(0); # disable warnings
- print "<script type=\"text/javascript\"><!--\n";
- print_some_javascript_code();
- print "//--></script>\n";
- warningsToBrowser(1); # re-enable warnings
-
-Note: In this respect warningsToBrowser() differs fundamentally from
-fatalsToBrowser(), which you should never call yourself!
-
-=head1 OVERRIDING THE NAME OF THE PROGRAM
-
-CGI::Carp includes the name of the program that generated the error or
-warning in the messages written to the log and the browser window.
-Sometimes, Perl can get confused about what the actual name of the
-executed program was. In these cases, you can override the program
-name that CGI::Carp will use for all messages.
-
-The quick way to do that is to tell CGI::Carp the name of the program
-in its use statement. You can do that by adding
-"name=cgi_carp_log_name" to your "use" statement. For example:
-
- use CGI::Carp qw(name=cgi_carp_log_name);
-
-. If you want to change the program name partway through the program,
-you can use the C<set_progname()> function instead. It is not
-exported by default, you must import it explicitly by saying
-
- use CGI::Carp qw(set_progname);
-
-Once you've done that, you can change the logged name of the program
-at any time by calling
-
- set_progname(new_program_name);
-
-You can set the program back to the default by calling
-
- set_progname(undef);
-
-Note that this override doesn't happen until after the program has
-compiled, so any compile-time errors will still show up with the
-non-overridden program name
-
-=head1 CHANGE LOG
-
-1.05 carpout() added and minor corrections by Marc Hedlund
- <hedlund@best.com> on 11/26/95.
-
-1.06 fatalsToBrowser() no longer aborts for fatal errors within
- eval() statements.
-
-1.08 set_message() added and carpout() expanded to allow for FileHandle
- objects.
-
-1.09 set_message() now allows users to pass a code REFERENCE for
- really custom error messages. croak and carp are now
- exported by default. Thanks to Gunther Birznieks for the
- patches.
-
-1.10 Patch from Chris Dean (ctdean@cogit.com) to allow
- module to run correctly under mod_perl.
-
-1.11 Changed order of &gt; and &lt; escapes.
-
-1.12 Changed die() on line 217 to CORE::die to avoid B<-w> warning.
-
-1.13 Added cluck() to make the module orthogonal with Carp.
- More mod_perl related fixes.
-
-1.20 Patch from Ilmari Karonen (perl@itz.pp.sci.fi): Added
- warningsToBrowser(). Replaced <CODE> tags with <PRE> in
- fatalsToBrowser() output.
-
-1.23 ineval() now checks both $^S and inspects the message for the "eval" pattern
- (hack alert!) in order to accomodate various combinations of Perl and
- mod_perl.
-
-1.24 Patch from Scott Gifford (sgifford@suspectclass.com): Add support
- for overriding program name.
-
-1.26 Replaced CORE::GLOBAL::die with the evil $SIG{__DIE__} because the
- former isn't working in some people's hands. There is no such thing
- as reliable exception handling in Perl.
-
-1.27 Replaced tell STDOUT with bytes=tell STDOUT.
-
-=head1 AUTHORS
-
-Copyright 1995-2002, Lincoln D. Stein. All rights reserved.
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-Address bug reports and comments to: lstein@cshl.org
-
-=head1 SEE ALSO
-
-Carp, CGI::Base, CGI::BasePlus, CGI::Request, CGI::MiniSvr, CGI::Form,
-CGI::Response
- if (defined($CGI::Carp::PROGNAME))
- {
- $file = $CGI::Carp::PROGNAME;
- }
-
-=cut
-
-require 5.000;
-use Exporter;
-#use Carp;
-BEGIN {
- require Carp;
- *CORE::GLOBAL::die = \&CGI::Carp::die;
-}
-
-use File::Spec;
-
-@ISA = qw(Exporter);
-@EXPORT = qw(confess croak carp);
-@EXPORT_OK = qw(carpout fatalsToBrowser warningsToBrowser wrap set_message set_progname cluck ^name= die);
-
-$main::SIG{__WARN__}=\&CGI::Carp::warn;
-
-$CGI::Carp::VERSION = '1.28';
-$CGI::Carp::CUSTOM_MSG = undef;
-
-
-# fancy import routine detects and handles 'errorWrap' specially.
-sub import {
- my $pkg = shift;
- my(%routines);
- my(@name);
-
- if (@name=grep(/^name=/,@_))
- {
- my($n) = (split(/=/,$name[0]))[1];
- set_progname($n);
- @_=grep(!/^name=/,@_);
- }
-
- grep($routines{$_}++,@_,@EXPORT);
- $WRAP++ if $routines{'fatalsToBrowser'} || $routines{'wrap'};
- $WARN++ if $routines{'warningsToBrowser'};
- my($oldlevel) = $Exporter::ExportLevel;
- $Exporter::ExportLevel = 1;
- Exporter::import($pkg,keys %routines);
- $Exporter::ExportLevel = $oldlevel;
- $main::SIG{__DIE__} =\&CGI::Carp::die if $routines{'fatalsToBrowser'};
-# $pkg->export('CORE::GLOBAL','die');
-}
-
-# These are the originals
-sub realwarn { CORE::warn(@_); }
-sub realdie { CORE::die(@_); }
-
-sub id {
- my $level = shift;
- my($pack,$file,$line,$sub) = caller($level);
- my($dev,$dirs,$id) = File::Spec->splitpath($file);
- return ($file,$line,$id);
-}
-
-sub stamp {
- my $time = scalar(localtime);
- my $frame = 0;
- my ($id,$pack,$file,$dev,$dirs);
- if (defined($CGI::Carp::PROGNAME)) {
- $id = $CGI::Carp::PROGNAME;
- } else {
- do {
- $id = $file;
- ($pack,$file) = caller($frame++);
- } until !$file;
- }
- ($dev,$dirs,$id) = File::Spec->splitpath($id);
- return "[$time] $id: ";
-}
-
-sub set_progname {
- $CGI::Carp::PROGNAME = shift;
- return $CGI::Carp::PROGNAME;
-}
-
-
-sub warn {
- my $message = shift;
- my($file,$line,$id) = id(1);
- $message .= " at $file line $line.\n" unless $message=~/\n$/;
- _warn($message) if $WARN;
- my $stamp = stamp;
- $message=~s/^/$stamp/gm;
- realwarn $message;
-}
-
-sub _warn {
- my $msg = shift;
- if ($EMIT_WARNINGS) {
- # We need to mangle the message a bit to make it a valid HTML
- # comment. This is done by substituting similar-looking ISO
- # 8859-1 characters for <, > and -. This is a hack.
- $msg =~ tr/<>-/\253\273\255/;
- chomp $msg;
- print STDOUT "<!-- warning: $msg -->\n";
- } else {
- push @WARNINGS, $msg;
- }
-}
-
-
-# The mod_perl package Apache::Registry loads CGI programs by calling
-# eval. These evals don't count when looking at the stack backtrace.
-sub _longmess {
- my $message = Carp::longmess();
- $message =~ s,eval[^\n]+(ModPerl|Apache)/Registry\w*\.pm.*,,s
- if exists $ENV{MOD_PERL};
- return $message;
-}
-
-sub ineval {
- (exists $ENV{MOD_PERL} ? 0 : $^S) || _longmess() =~ /eval [\{\']/m
-}
-
-sub die {
- my ($arg,@rest) = @_;
- realdie ($arg,@rest) if ineval();
-
- if (!ref($arg)) {
- $arg = join("", ($arg,@rest));
- my($file,$line,$id) = id(1);
- $arg .= " at $file line $line." unless $arg=~/\n$/;
- &fatalsToBrowser($arg) if $WRAP;
- if (($arg =~ /\n$/) || !exists($ENV{MOD_PERL})) {
- my $stamp = stamp;
- $arg=~s/^/$stamp/gm;
- }
- if ($arg !~ /\n$/) {
- $arg .= "\n";
- }
- }
- realdie $arg;
-}
-
-sub set_message {
- $CGI::Carp::CUSTOM_MSG = shift;
- return $CGI::Carp::CUSTOM_MSG;
-}
-
-sub confess { CGI::Carp::die Carp::longmess @_; }
-sub croak { CGI::Carp::die Carp::shortmess @_; }
-sub carp { CGI::Carp::warn Carp::shortmess @_; }
-sub cluck { CGI::Carp::warn Carp::longmess @_; }
-
-# We have to be ready to accept a filehandle as a reference
-# or a string.
-sub carpout {
- my($in) = @_;
- my($no) = fileno(to_filehandle($in));
- realdie("Invalid filehandle $in\n") unless defined $no;
-
- open(SAVEERR, ">&STDERR");
- open(STDERR, ">&$no") or
- ( print SAVEERR "Unable to redirect STDERR: $!\n" and exit(1) );
-}
-
-sub warningsToBrowser {
- $EMIT_WARNINGS = @_ ? shift : 1;
- _warn(shift @WARNINGS) while $EMIT_WARNINGS and @WARNINGS;
-}
-
-# headers
-sub fatalsToBrowser {
- my($msg) = @_;
- $msg=~s/&/&amp;/g;
- $msg=~s/>/&gt;/g;
- $msg=~s/</&lt;/g;
- $msg=~s/\"/&quot;/g;
- my($wm) = $ENV{SERVER_ADMIN} ?
- qq[the webmaster (<a href="mailto:$ENV{SERVER_ADMIN}">$ENV{SERVER_ADMIN}</a>)] :
- "this site's webmaster";
- my ($outer_message) = <<END;
-For help, please send mail to $wm, giving this error message
-and the time and date of the error.
-END
- ;
- my $mod_perl = exists $ENV{MOD_PERL};
-
- if ($CUSTOM_MSG) {
- if (ref($CUSTOM_MSG) eq 'CODE') {
- print STDOUT "Content-type: text/html\n\n"
- unless $mod_perl;
- &$CUSTOM_MSG($msg); # nicer to perl 5.003 users
- return;
- } else {
- $outer_message = $CUSTOM_MSG;
- }
- }
-
- my $mess = <<END;
-<h1>Software error:</h1>
-<pre>$msg</pre>
-<p>
-$outer_message
-</p>
-END
- ;
-
- if ($mod_perl) {
- require mod_perl;
- if ($mod_perl::VERSION >= 1.99) {
- $mod_perl = 2;
- require Apache::RequestRec;
- require Apache::RequestIO;
- require Apache::RequestUtil;
- require APR::Pool;
- require ModPerl::Util;
- require Apache::Response;
- }
- my $r = Apache->request;
- # If bytes have already been sent, then
- # we print the message out directly.
- # Otherwise we make a custom error
- # handler to produce the doc for us.
- if ($r->bytes_sent) {
- $r->print($mess);
- $mod_perl == 2 ? ModPerl::Util::exit(0) : $r->exit;
- } else {
- # MSIE won't display a custom 500 response unless it is >512 bytes!
- if ($ENV{HTTP_USER_AGENT} =~ /MSIE/) {
- $mess = "<!-- " . (' ' x 513) . " -->\n$mess";
- }
- $r->custom_response(500,$mess);
- }
- } else {
- my $bytes_written = eval{tell STDOUT};
- if (defined $bytes_written && $bytes_written > 0) {
- print STDOUT $mess;
- }
- else {
- print STDOUT "Content-type: text/html\n\n";
- print STDOUT $mess;
- }
- }
-
- warningsToBrowser(1); # emit warnings before dying
-}
-
-# Cut and paste from CGI.pm so that we don't have the overhead of
-# always loading the entire CGI module.
-sub to_filehandle {
- my $thingy = shift;
- return undef unless $thingy;
- return $thingy if UNIVERSAL::isa($thingy,'GLOB');
- return $thingy if UNIVERSAL::isa($thingy,'FileHandle');
- if (!ref($thingy)) {
- my $caller = 1;
- while (my $package = caller($caller++)) {
- my($tmp) = $thingy=~/[\':]/ ? $thingy : "$package\:\:$thingy";
- return $tmp if defined(fileno($tmp));
- }
- }
- return undef;
-}
-
-1;
diff --git a/lib/CGI/Cookie.pm b/lib/CGI/Cookie.pm
deleted file mode 100644
index 27a93c5..0000000
--- a/lib/CGI/Cookie.pm
+++ /dev/null
@@ -1,478 +0,0 @@
-package CGI::Cookie;
-
-# See the bottom of this file for the POD documentation. Search for the
-# string '=head'.
-
-# You can run this file through either pod2man or pod2html to produce pretty
-# documentation in manual or html file format (these utilities are part of the
-# Perl 5 distribution).
-
-# Copyright 1995-1999, Lincoln D. Stein. All rights reserved.
-# It may be used and modified freely, but I do request that this copyright
-# notice remain attached to the file. You may modify this module as you
-# wish, but if you redistribute a modified version, please attach a note
-# listing the modifications you have made.
-
-$CGI::Cookie::VERSION='1.24';
-
-use CGI::Util qw(rearrange unescape escape);
-use overload '""' => \&as_string,
- 'cmp' => \&compare,
- 'fallback'=>1;
-
-# Turn on special checking for Doug MacEachern's modperl
-my $MOD_PERL = 0;
-if (exists $ENV{MOD_PERL}) {
- eval "require mod_perl";
- if (defined $mod_perl::VERSION) {
- if ($mod_perl::VERSION >= 1.99) {
- $MOD_PERL = 2;
- require Apache::RequestUtil;
- } else {
- $MOD_PERL = 1;
- require Apache;
- }
- }
-}
-
-# fetch a list of cookies from the environment and
-# return as a hash. the cookies are parsed as normal
-# escaped URL data.
-sub fetch {
- my $class = shift;
- my $raw_cookie = get_raw_cookie(@_) or return;
- return $class->parse($raw_cookie);
-}
-
-# Fetch a list of cookies from the environment or the incoming headers and
-# return as a hash. The cookie values are not unescaped or altered in any way.
- sub raw_fetch {
- my $class = shift;
- my $raw_cookie = get_raw_cookie(@_) or return;
- my %results;
- my($key,$value);
-
- my(@pairs) = split("; ?",$raw_cookie);
- foreach (@pairs) {
- s/\s*(.*?)\s*/$1/;
- if (/^([^=]+)=(.*)/) {
- $key = $1;
- $value = $2;
- }
- else {
- $key = $_;
- $value = '';
- }
- $results{$key} = $value;
- }
- return \%results unless wantarray;
- return %results;
-}
-
-sub get_raw_cookie {
- my $r = shift;
- $r ||= eval { Apache->request() } if $MOD_PERL;
- if ($r) {
- $raw_cookie = $r->headers_in->{'Cookie'};
- } else {
- if ($MOD_PERL && !exists $ENV{REQUEST_METHOD}) {
- die "Run $r->subprocess_env; before calling fetch()";
- }
- $raw_cookie = $ENV{HTTP_COOKIE} || $ENV{COOKIE};
- }
-}
-
-
-sub parse {
- my ($self,$raw_cookie) = @_;
- my %results;
-
- my(@pairs) = split("; ?",$raw_cookie);
- foreach (@pairs) {
- s/\s*(.*?)\s*/$1/;
- my($key,$value) = split("=",$_,2);
-
- # Some foreign cookies are not in name=value format, so ignore
- # them.
- next if !defined($value);
- my @values = ();
- if ($value ne '') {
- @values = map unescape($_),split(/[&;]/,$value.'&dmy');
- pop @values;
- }
- $key = unescape($key);
- # A bug in Netscape can cause several cookies with same name to
- # appear. The FIRST one in HTTP_COOKIE is the most recent version.
- $results{$key} ||= $self->new(-name=>$key,-value=>\@values);
- }
- return \%results unless wantarray;
- return %results;
-}
-
-sub new {
- my $class = shift;
- $class = ref($class) if ref($class);
- my($name,$value,$path,$domain,$secure,$expires) =
- rearrange([NAME,[VALUE,VALUES],PATH,DOMAIN,SECURE,EXPIRES],@_);
-
- # Pull out our parameters.
- my @values;
- if (ref($value)) {
- if (ref($value) eq 'ARRAY') {
- @values = @$value;
- } elsif (ref($value) eq 'HASH') {
- @values = %$value;
- }
- } else {
- @values = ($value);
- }
-
- bless my $self = {
- 'name'=>$name,
- 'value'=>[@values],
- },$class;
-
- # IE requires the path and domain to be present for some reason.
- $path ||= "/";
- # however, this breaks networks which use host tables without fully qualified
- # names, so we comment it out.
- # $domain = CGI::virtual_host() unless defined $domain;
-
- $self->path($path) if defined $path;
- $self->domain($domain) if defined $domain;
- $self->secure($secure) if defined $secure;
- $self->expires($expires) if defined $expires;
-# $self->max_age($expires) if defined $expires;
- return $self;
-}
-
-sub as_string {
- my $self = shift;
- return "" unless $self->name;
-
- my(@constant_values,$domain,$path,$expires,$max_age,$secure);
-
- push(@constant_values,"domain=$domain") if $domain = $self->domain;
- push(@constant_values,"path=$path") if $path = $self->path;
- push(@constant_values,"expires=$expires") if $expires = $self->expires;
- push(@constant_values,"max-age=$max_age") if $max_age = $self->max_age;
- push(@constant_values,"secure") if $secure = $self->secure;
-
- my($key) = escape($self->name);
- my($cookie) = join("=",$key,join("&",map escape($_),$self->value));
- return join("; ",$cookie,@constant_values);
-}
-
-sub compare {
- my $self = shift;
- my $value = shift;
- return "$self" cmp $value;
-}
-
-# accessors
-sub name {
- my $self = shift;
- my $name = shift;
- $self->{'name'} = $name if defined $name;
- return $self->{'name'};
-}
-
-sub value {
- my $self = shift;
- my $value = shift;
- if (defined $value) {
- my @values;
- if (ref($value)) {
- if (ref($value) eq 'ARRAY') {
- @values = @$value;
- } elsif (ref($value) eq 'HASH') {
- @values = %$value;
- }
- } else {
- @values = ($value);
- }
- $self->{'value'} = [@values];
- }
- return wantarray ? @{$self->{'value'}} : $self->{'value'}->[0]
-}
-
-sub domain {
- my $self = shift;
- my $domain = shift;
- $self->{'domain'} = $domain if defined $domain;
- return $self->{'domain'};
-}
-
-sub secure {
- my $self = shift;
- my $secure = shift;
- $self->{'secure'} = $secure if defined $secure;
- return $self->{'secure'};
-}
-
-sub expires {
- my $self = shift;
- my $expires = shift;
- $self->{'expires'} = CGI::Util::expires($expires,'cookie') if defined $expires;
- return $self->{'expires'};
-}
-
-sub max_age {
- my $self = shift;
- my $expires = shift;
- $self->{'max-age'} = CGI::Util::expire_calc($expires)-time() if defined $expires;
- return $self->{'max-age'};
-}
-
-sub path {
- my $self = shift;
- my $path = shift;
- $self->{'path'} = $path if defined $path;
- return $self->{'path'};
-}
-
-1;
-
-=head1 NAME
-
-CGI::Cookie - Interface to Netscape Cookies
-
-=head1 SYNOPSIS
-
- use CGI qw/:standard/;
- use CGI::Cookie;
-
- # Create new cookies and send them
- $cookie1 = new CGI::Cookie(-name=>'ID',-value=>123456);
- $cookie2 = new CGI::Cookie(-name=>'preferences',
- -value=>{ font => Helvetica,
- size => 12 }
- );
- print header(-cookie=>[$cookie1,$cookie2]);
-
- # fetch existing cookies
- %cookies = fetch CGI::Cookie;
- $id = $cookies{'ID'}->value;
-
- # create cookies returned from an external source
- %cookies = parse CGI::Cookie($ENV{COOKIE});
-
-=head1 DESCRIPTION
-
-CGI::Cookie is an interface to Netscape (HTTP/1.1) cookies, an
-innovation that allows Web servers to store persistent information on
-the browser's side of the connection. Although CGI::Cookie is
-intended to be used in conjunction with CGI.pm (and is in fact used by
-it internally), you can use this module independently.
-
-For full information on cookies see
-
- http://www.ics.uci.edu/pub/ietf/http/rfc2109.txt
-
-=head1 USING CGI::Cookie
-
-CGI::Cookie is object oriented. Each cookie object has a name and a
-value. The name is any scalar value. The value is any scalar or
-array value (associative arrays are also allowed). Cookies also have
-several optional attributes, including:
-
-=over 4
-
-=item B<1. expiration date>
-
-The expiration date tells the browser how long to hang on to the
-cookie. If the cookie specifies an expiration date in the future, the
-browser will store the cookie information in a disk file and return it
-to the server every time the user reconnects (until the expiration
-date is reached). If the cookie species an expiration date in the
-past, the browser will remove the cookie from the disk file. If the
-expiration date is not specified, the cookie will persist only until
-the user quits the browser.
-
-=item B<2. domain>
-
-This is a partial or complete domain name for which the cookie is
-valid. The browser will return the cookie to any host that matches
-the partial domain name. For example, if you specify a domain name
-of ".capricorn.com", then Netscape will return the cookie to
-Web servers running on any of the machines "www.capricorn.com",
-"ftp.capricorn.com", "feckless.capricorn.com", etc. Domain names
-must contain at least two periods to prevent attempts to match
-on top level domains like ".edu". If no domain is specified, then
-the browser will only return the cookie to servers on the host the
-cookie originated from.
-
-=item B<3. path>
-
-If you provide a cookie path attribute, the browser will check it
-against your script's URL before returning the cookie. For example,
-if you specify the path "/cgi-bin", then the cookie will be returned
-to each of the scripts "/cgi-bin/tally.pl", "/cgi-bin/order.pl", and
-"/cgi-bin/customer_service/complain.pl", but not to the script
-"/cgi-private/site_admin.pl". By default, the path is set to "/", so
-that all scripts at your site will receive the cookie.
-
-=item B<4. secure flag>
-
-If the "secure" attribute is set, the cookie will only be sent to your
-script if the CGI request is occurring on a secure channel, such as SSL.
-
-=back
-
-=head2 Creating New Cookies
-
- $c = new CGI::Cookie(-name => 'foo',
- -value => 'bar',
- -expires => '+3M',
- -domain => '.capricorn.com',
- -path => '/cgi-bin/database',
- -secure => 1
- );
-
-Create cookies from scratch with the B<new> method. The B<-name> and
-B<-value> parameters are required. The name must be a scalar value.
-The value can be a scalar, an array reference, or a hash reference.
-(At some point in the future cookies will support one of the Perl
-object serialization protocols for full generality).
-
-B<-expires> accepts any of the relative or absolute date formats
-recognized by CGI.pm, for example "+3M" for three months in the
-future. See CGI.pm's documentation for details.
-
-B<-domain> points to a domain name or to a fully qualified host name.
-If not specified, the cookie will be returned only to the Web server
-that created it.
-
-B<-path> points to a partial URL on the current server. The cookie
-will be returned to all URLs beginning with the specified path. If
-not specified, it defaults to '/', which returns the cookie to all
-pages at your site.
-
-B<-secure> if set to a true value instructs the browser to return the
-cookie only when a cryptographic protocol is in use.
-
-=head2 Sending the Cookie to the Browser
-
-Within a CGI script you can send a cookie to the browser by creating
-one or more Set-Cookie: fields in the HTTP header. Here is a typical
-sequence:
-
- my $c = new CGI::Cookie(-name => 'foo',
- -value => ['bar','baz'],
- -expires => '+3M');
-
- print "Set-Cookie: $c\n";
- print "Content-Type: text/html\n\n";
-
-To send more than one cookie, create several Set-Cookie: fields.
-
-If you are using CGI.pm, you send cookies by providing a -cookie
-argument to the header() method:
-
- print header(-cookie=>$c);
-
-Mod_perl users can set cookies using the request object's header_out()
-method:
-
- $r->headers_out->set('Set-Cookie' => $c);
-
-Internally, Cookie overloads the "" operator to call its as_string()
-method when incorporated into the HTTP header. as_string() turns the
-Cookie's internal representation into an RFC-compliant text
-representation. You may call as_string() yourself if you prefer:
-
- print "Set-Cookie: ",$c->as_string,"\n";
-
-=head2 Recovering Previous Cookies
-
- %cookies = fetch CGI::Cookie;
-
-B<fetch> returns an associative array consisting of all cookies
-returned by the browser. The keys of the array are the cookie names. You
-can iterate through the cookies this way:
-
- %cookies = fetch CGI::Cookie;
- foreach (keys %cookies) {
- do_something($cookies{$_});
- }
-
-In a scalar context, fetch() returns a hash reference, which may be more
-efficient if you are manipulating multiple cookies.
-
-CGI.pm uses the URL escaping methods to save and restore reserved characters
-in its cookies. If you are trying to retrieve a cookie set by a foreign server,
-this escaping method may trip you up. Use raw_fetch() instead, which has the
-same semantics as fetch(), but performs no unescaping.
-
-You may also retrieve cookies that were stored in some external
-form using the parse() class method:
-
- $COOKIES = `cat /usr/tmp/Cookie_stash`;
- %cookies = parse CGI::Cookie($COOKIES);
-
-If you are in a mod_perl environment, you can save some overhead by
-passing the request object to fetch() like this:
-
- CGI::Cookie->fetch($r);
-
-=head2 Manipulating Cookies
-
-Cookie objects have a series of accessor methods to get and set cookie
-attributes. Each accessor has a similar syntax. Called without
-arguments, the accessor returns the current value of the attribute.
-Called with an argument, the accessor changes the attribute and
-returns its new value.
-
-=over 4
-
-=item B<name()>
-
-Get or set the cookie's name. Example:
-
- $name = $c->name;
- $new_name = $c->name('fred');
-
-=item B<value()>
-
-Get or set the cookie's value. Example:
-
- $value = $c->value;
- @new_value = $c->value(['a','b','c','d']);
-
-B<value()> is context sensitive. In a list context it will return
-the current value of the cookie as an array. In a scalar context it
-will return the B<first> value of a multivalued cookie.
-
-=item B<domain()>
-
-Get or set the cookie's domain.
-
-=item B<path()>
-
-Get or set the cookie's path.
-
-=item B<expires()>
-
-Get or set the cookie's expiration time.
-
-=back
-
-
-=head1 AUTHOR INFORMATION
-
-Copyright 1997-1998, Lincoln D. Stein. All rights reserved.
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-Address bug reports and comments to: lstein@cshl.org
-
-=head1 BUGS
-
-This section intentionally left blank.
-
-=head1 SEE ALSO
-
-L<CGI::Carp>, L<CGI>
-
-=cut
diff --git a/lib/CGI/Fast.pm b/lib/CGI/Fast.pm
deleted file mode 100644
index 43b8709..0000000
--- a/lib/CGI/Fast.pm
+++ /dev/null
@@ -1,230 +0,0 @@
-package CGI::Fast;
-
-# See the bottom of this file for the POD documentation. Search for the
-# string '=head'.
-
-# You can run this file through either pod2man or pod2html to produce pretty
-# documentation in manual or html file format (these utilities are part of the
-# Perl 5 distribution).
-
-# Copyright 1995,1996, Lincoln D. Stein. All rights reserved.
-# It may be used and modified freely, but I do request that this copyright
-# notice remain attached to the file. You may modify this module as you
-# wish, but if you redistribute a modified version, please attach a note
-# listing the modifications you have made.
-
-# The most recent version and complete docs are available at:
-# http://www.genome.wi.mit.edu/ftp/pub/software/WWW/cgi_docs.html
-# ftp://ftp-genome.wi.mit.edu/pub/software/WWW/
-$CGI::Fast::VERSION='1.05';
-
-use CGI;
-use FCGI;
-@ISA = ('CGI');
-
-# workaround for known bug in libfcgi
-while (($ignore) = each %ENV) { }
-
-# override the initialization behavior so that
-# state is NOT maintained between invocations
-sub save_request {
- # no-op
-}
-
-# If ENV{FCGI_SOCKET_PATH} is specified, we maintain a FCGI Request handle
-# in this package variable.
-use vars qw($Ext_Request);
-BEGIN {
- # If ENV{FCGI_SOCKET_PATH} is given, explicitly open the socket,
- # and keep the request handle around from which to call Accept().
- if ($ENV{FCGI_SOCKET_PATH}) {
- my $path = $ENV{FCGI_SOCKET_PATH};
- my $backlog = $ENV{FCGI_LISTEN_QUEUE} || 100;
- my $socket = FCGI::OpenSocket( $path, $backlog );
- $Ext_Request = FCGI::Request( \*STDIN, \*STDOUT, \*STDERR,
- \%ENV, $socket, 1 );
- }
-}
-
-# New is slightly different in that it calls FCGI's
-# accept() method.
-sub new {
- my ($self, $initializer, @param) = @_;
- unless (defined $initializer) {
- if ($Ext_Request) {
- return undef unless $Ext_Request->Accept() >= 0;
- } else {
- return undef unless FCGI::accept() >= 0;
- }
- }
- return $CGI::Q = $self->SUPER::new($initializer, @param);
-}
-
-1;
-
-=head1 NAME
-
-CGI::Fast - CGI Interface for Fast CGI
-
-=head1 SYNOPSIS
-
- use CGI::Fast qw(:standard);
- $COUNTER = 0;
- while (new CGI::Fast) {
- print header;
- print start_html("Fast CGI Rocks");
- print
- h1("Fast CGI Rocks"),
- "Invocation number ",b($COUNTER++),
- " PID ",b($$),".",
- hr;
- print end_html;
- }
-
-=head1 DESCRIPTION
-
-CGI::Fast is a subclass of the CGI object created by
-CGI.pm. It is specialized to work well with the Open Market
-FastCGI standard, which greatly speeds up CGI scripts by
-turning them into persistently running server processes. Scripts
-that perform time-consuming initialization processes, such as
-loading large modules or opening persistent database connections,
-will see large performance improvements.
-
-=head1 OTHER PIECES OF THE PUZZLE
-
-In order to use CGI::Fast you'll need a FastCGI-enabled Web
-server. Open Market's server is FastCGI-savvy. There are also
-freely redistributable FastCGI modules for NCSA httpd 1.5 and Apache.
-FastCGI-enabling modules for Microsoft Internet Information Server and
-Netscape Communications Server have been announced.
-
-In addition, you'll need a version of the Perl interpreter that has
-been linked with the FastCGI I/O library. Precompiled binaries are
-available for several platforms, including DEC Alpha, HP-UX and
-SPARC/Solaris, or you can rebuild Perl from source with patches
-provided in the FastCGI developer's kit. The FastCGI Perl interpreter
-can be used in place of your normal Perl without ill consequences.
-
-You can find FastCGI modules for Apache and NCSA httpd, precompiled
-Perl interpreters, and the FastCGI developer's kit all at URL:
-
- http://www.fastcgi.com/
-
-=head1 WRITING FASTCGI PERL SCRIPTS
-
-FastCGI scripts are persistent: one or more copies of the script
-are started up when the server initializes, and stay around until
-the server exits or they die a natural death. After performing
-whatever one-time initialization it needs, the script enters a
-loop waiting for incoming connections, processing the request, and
-waiting some more.
-
-A typical FastCGI script will look like this:
-
- #!/usr/local/bin/perl # must be a FastCGI version of perl!
- use CGI::Fast;
- &do_some_initialization();
- while ($q = new CGI::Fast) {
- &process_request($q);
- }
-
-Each time there's a new request, CGI::Fast returns a
-CGI object to your loop. The rest of the time your script
-waits in the call to new(). When the server requests that
-your script be terminated, new() will return undef. You can
-of course exit earlier if you choose. A new version of the
-script will be respawned to take its place (this may be
-necessary in order to avoid Perl memory leaks in long-running
-scripts).
-
-CGI.pm's default CGI object mode also works. Just modify the loop
-this way:
-
- while (new CGI::Fast) {
- &process_request;
- }
-
-Calls to header(), start_form(), etc. will all operate on the
-current request.
-
-=head1 INSTALLING FASTCGI SCRIPTS
-
-See the FastCGI developer's kit documentation for full details. On
-the Apache server, the following line must be added to srm.conf:
-
- AddType application/x-httpd-fcgi .fcgi
-
-FastCGI scripts must end in the extension .fcgi. For each script you
-install, you must add something like the following to srm.conf:
-
- FastCgiServer /usr/etc/httpd/fcgi-bin/file_upload.fcgi -processes 2
-
-This instructs Apache to launch two copies of file_upload.fcgi at
-startup time.
-
-=head1 USING FASTCGI SCRIPTS AS CGI SCRIPTS
-
-Any script that works correctly as a FastCGI script will also work
-correctly when installed as a vanilla CGI script. However it will
-not see any performance benefit.
-
-=head1 EXTERNAL FASTCGI SERVER INVOCATION
-
-FastCGI supports a TCP/IP transport mechanism which allows FastCGI scripts to run
-external to the webserver, perhaps on a remote machine. To configure the
-webserver to connect to an external FastCGI server, you would add the following
-to your srm.conf:
-
- FastCgiExternalServer /usr/etc/httpd/fcgi-bin/file_upload.fcgi -host sputnik:8888
-
-Two environment variables affect how the C<CGI::Fast> object is created,
-allowing C<CGI::Fast> to be used as an external FastCGI server. (See C<FCGI>
-documentation for C<FCGI::OpenSocket> for more information.)
-
-=over
-
-=item FCGI_SOCKET_PATH
-
-The address (TCP/IP) or path (UNIX Domain) of the socket the external FastCGI
-script to which bind an listen for incoming connections from the web server.
-
-=item FCGI_LISTEN_QUEUE
-
-Maximum length of the queue of pending connections.
-
-=back
-
-For example:
-
- #!/usr/local/bin/perl # must be a FastCGI version of perl!
- use CGI::Fast;
- &do_some_initialization();
- $ENV{FCGI_SOCKET_PATH} = "sputnik:8888";
- $ENV{FCGI_LISTEN_QUEUE} = 100;
- while ($q = new CGI::Fast) {
- &process_request($q);
- }
-
-=head1 CAVEATS
-
-I haven't tested this very much.
-
-=head1 AUTHOR INFORMATION
-
-Copyright 1996-1998, Lincoln D. Stein. All rights reserved.
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-Address bug reports and comments to: lstein@cshl.org
-
-=head1 BUGS
-
-This section intentionally left blank.
-
-=head1 SEE ALSO
-
-L<CGI::Carp>, L<CGI>
-
-=cut
diff --git a/lib/CGI/Pretty.pm b/lib/CGI/Pretty.pm
deleted file mode 100644
index d824a02..0000000
--- a/lib/CGI/Pretty.pm
+++ /dev/null
@@ -1,275 +0,0 @@
-package CGI::Pretty;
-
-# See the bottom of this file for the POD documentation. Search for the
-# string '=head'.
-
-# You can run this file through either pod2man or pod2html to produce pretty
-# documentation in manual or html file format (these utilities are part of the
-# Perl 5 distribution).
-
-use strict;
-use CGI ();
-
-$CGI::Pretty::VERSION = '1.08';
-$CGI::DefaultClass = __PACKAGE__;
-$CGI::Pretty::AutoloadClass = 'CGI';
-@CGI::Pretty::ISA = qw( CGI );
-
-initialize_globals();
-
-sub _prettyPrint {
- my $input = shift;
- return if !$$input;
- return if !$CGI::Pretty::LINEBREAK || !$CGI::Pretty::INDENT;
-
-# print STDERR "'", $$input, "'\n";
-
- foreach my $i ( @CGI::Pretty::AS_IS ) {
- if ( $$input =~ m{</$i>}si ) {
- my ( $a, $b, $c ) = $$input =~ m{(.*)(<$i[\s/>].*?</$i>)(.*)}si;
- next if !$b;
- $a ||= "";
- $c ||= "";
-
- _prettyPrint( \$a ) if $a;
- _prettyPrint( \$c ) if $c;
-
- $b ||= "";
- $$input = "$a$b$c";
- return;
- }
- }
- $$input =~ s/$CGI::Pretty::LINEBREAK/$CGI::Pretty::LINEBREAK$CGI::Pretty::INDENT/g;
-}
-
-sub comment {
- my($self,@p) = CGI::self_or_CGI(@_);
-
- my $s = "@p";
- $s =~ s/$CGI::Pretty::LINEBREAK/$CGI::Pretty::LINEBREAK$CGI::Pretty::INDENT/g if $CGI::Pretty::LINEBREAK;
-
- return $self->SUPER::comment( "$CGI::Pretty::LINEBREAK$CGI::Pretty::INDENT$s$CGI::Pretty::LINEBREAK" ) . $CGI::Pretty::LINEBREAK;
-}
-
-sub _make_tag_func {
- my ($self,$tagname) = @_;
-
- # As Lincoln as noted, the last else clause is VERY hairy, and it
- # took me a while to figure out what I was trying to do.
- # What it does is look for tags that shouldn't be indented (e.g. PRE)
- # and makes sure that when we nest tags, those tags don't get
- # indented.
- # For an example, try print td( pre( "hello\nworld" ) );
- # If we didn't care about stuff like that, the code would be
- # MUCH simpler. BTW: I won't claim to be a regular expression
- # guru, so if anybody wants to contribute something that would
- # be quicker, easier to read, etc, I would be more than
- # willing to put it in - Brian
-
- my $func = qq"
- sub $tagname {";
-
- $func .= q'
- shift if $_[0] &&
- (ref($_[0]) &&
- (substr(ref($_[0]),0,3) eq "CGI" ||
- UNIVERSAL::isa($_[0],"CGI")));
- my($attr) = "";
- if (ref($_[0]) && ref($_[0]) eq "HASH") {
- my(@attr) = make_attributes(shift()||undef,1);
- $attr = " @attr" if @attr;
- }';
-
- if ($tagname=~/start_(\w+)/i) {
- $func .= qq!
- return "<\L$1\E\$attr>\$CGI::Pretty::LINEBREAK";} !;
- } elsif ($tagname=~/end_(\w+)/i) {
- $func .= qq!
- return "<\L/$1\E>\$CGI::Pretty::LINEBREAK"; } !;
- } else {
- $func .= qq#
- return ( \$CGI::XHTML ? "<\L$tagname\E\$attr />" : "<\L$tagname\E\$attr>" ) .
- \$CGI::Pretty::LINEBREAK unless \@_;
- my(\$tag,\$untag) = ("<\L$tagname\E\$attr>","</\L$tagname>\E");
-
- my \%ASIS = map { lc("\$_") => 1 } \@CGI::Pretty::AS_IS;
- my \@args;
- if ( \$CGI::Pretty::LINEBREAK || \$CGI::Pretty::INDENT ) {
- if(ref(\$_[0]) eq 'ARRAY') {
- \@args = \@{\$_[0]}
- } else {
- foreach (\@_) {
- \$args[0] .= \$_;
- \$args[0] .= \$CGI::Pretty::LINEBREAK if \$args[0] !~ /\$CGI::Pretty::LINEBREAK\$/ && 0;
- chomp \$args[0] if exists \$ASIS{ "\L$tagname\E" };
-
- \$args[0] .= \$" if \$args[0] !~ /\$CGI::Pretty::LINEBREAK\$/ && 1;
- }
- chop \$args[0];
- }
- }
- else {
- \@args = ref(\$_[0]) eq 'ARRAY' ? \@{\$_[0]} : "\@_";
- }
-
- my \@result;
- if ( exists \$ASIS{ "\L$tagname\E" } ) {
- \@result = map { "\$tag\$_\$untag\$CGI::Pretty::LINEBREAK" }
- \@args;
- }
- else {
- \@result = map {
- chomp;
- my \$tmp = \$_;
- CGI::Pretty::_prettyPrint( \\\$tmp );
- \$tag . \$CGI::Pretty::LINEBREAK .
- \$CGI::Pretty::INDENT . \$tmp . \$CGI::Pretty::LINEBREAK .
- \$untag . \$CGI::Pretty::LINEBREAK
- } \@args;
- }
- local \$" = "" if \$CGI::Pretty::LINEBREAK || \$CGI::Pretty::INDENT;
- return "\@result";
- }#;
- }
-
- return $func;
-}
-
-sub start_html {
- return CGI::start_html( @_ ) . $CGI::Pretty::LINEBREAK;
-}
-
-sub end_html {
- return CGI::end_html( @_ ) . $CGI::Pretty::LINEBREAK;
-}
-
-sub new {
- my $class = shift;
- my $this = $class->SUPER::new( @_ );
-
- if ($CGI::MOD_PERL) {
- my $r = Apache->request;
- if ($CGI::MOD_PERL == 1) {
- $r->register_cleanup(\&CGI::Pretty::_reset_globals);
- }
- else {
- $r->pool->cleanup_register(\&CGI::Pretty::_reset_globals);
- }
- }
- $class->_reset_globals if $CGI::PERLEX;
-
- return bless $this, $class;
-}
-
-sub initialize_globals {
- # This is the string used for indentation of tags
- $CGI::Pretty::INDENT = "\t";
-
- # This is the string used for seperation between tags
- $CGI::Pretty::LINEBREAK = $/;
-
- # These tags are not prettify'd.
- @CGI::Pretty::AS_IS = qw( a pre code script textarea td );
-
- 1;
-}
-sub _reset_globals { initialize_globals(); }
-
-1;
-
-=head1 NAME
-
-CGI::Pretty - module to produce nicely formatted HTML code
-
-=head1 SYNOPSIS
-
- use CGI::Pretty qw( :html3 );
-
- # Print a table with a single data element
- print table( TR( td( "foo" ) ) );
-
-=head1 DESCRIPTION
-
-CGI::Pretty is a module that derives from CGI. It's sole function is to
-allow users of CGI to output nicely formatted HTML code.
-
-When using the CGI module, the following code:
- print table( TR( td( "foo" ) ) );
-
-produces the following output:
- <TABLE><TR><TD>foo</TD></TR></TABLE>
-
-If a user were to create a table consisting of many rows and many columns,
-the resultant HTML code would be quite difficult to read since it has no
-carriage returns or indentation.
-
-CGI::Pretty fixes this problem. What it does is add a carriage
-return and indentation to the HTML code so that one can easily read
-it.
-
- print table( TR( td( "foo" ) ) );
-
-now produces the following output:
- <TABLE>
- <TR>
- <TD>
- foo
- </TD>
- </TR>
- </TABLE>
-
-
-=head2 Tags that won't be formatted
-
-The <A> and <PRE> tags are not formatted. If these tags were formatted, the
-user would see the extra indentation on the web browser causing the page to
-look different than what would be expected. If you wish to add more tags to
-the list of tags that are not to be touched, push them onto the C<@AS_IS> array:
-
- push @CGI::Pretty::AS_IS,qw(CODE XMP);
-
-=head2 Customizing the Indenting
-
-If you wish to have your own personal style of indenting, you can change the
-C<$INDENT> variable:
-
- $CGI::Pretty::INDENT = "\t\t";
-
-would cause the indents to be two tabs.
-
-Similarly, if you wish to have more space between lines, you may change the
-C<$LINEBREAK> variable:
-
- $CGI::Pretty::LINEBREAK = "\n\n";
-
-would create two carriage returns between lines.
-
-If you decide you want to use the regular CGI indenting, you can easily do
-the following:
-
- $CGI::Pretty::INDENT = $CGI::Pretty::LINEBREAK = "";
-
-=head1 BUGS
-
-This section intentionally left blank.
-
-=head1 AUTHOR
-
-Brian Paulsen <Brian@ThePaulsens.com>, with minor modifications by
-Lincoln Stein <lstein@cshl.org> for incorporation into the CGI.pm
-distribution.
-
-Copyright 1999, Brian Paulsen. All rights reserved.
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-Bug reports and comments to Brian@ThePaulsens.com. You can also write
-to lstein@cshl.org, but this code looks pretty hairy to me and I'm not
-sure I understand it!
-
-=head1 SEE ALSO
-
-L<CGI>
-
-=cut
diff --git a/lib/CGI/Push.pm b/lib/CGI/Push.pm
deleted file mode 100644
index 8356c60..0000000
--- a/lib/CGI/Push.pm
+++ /dev/null
@@ -1,328 +0,0 @@
-package CGI::Push;
-
-# See the bottom of this file for the POD documentation. Search for the
-# string '=head'.
-
-# You can run this file through either pod2man or pod2html to produce pretty
-# documentation in manual or html file format (these utilities are part of the
-# Perl 5 distribution).
-
-# Copyright 1995-2000, Lincoln D. Stein. All rights reserved.
-# It may be used and modified freely, but I do request that this copyright
-# notice remain attached to the file. You may modify this module as you
-# wish, but if you redistribute a modified version, please attach a note
-# listing the modifications you have made.
-
-# The most recent version and complete docs are available at:
-# http://stein.cshl.org/WWW/software/CGI/
-
-$CGI::Push::VERSION='1.04';
-use CGI;
-use CGI::Util 'rearrange';
-@ISA = ('CGI');
-
-$CGI::DefaultClass = 'CGI::Push';
-$CGI::Push::AutoloadClass = 'CGI';
-
-# add do_push() and push_delay() to exported tags
-push(@{$CGI::EXPORT_TAGS{':standard'}},'do_push','push_delay');
-
-sub do_push {
- my ($self,@p) = CGI::self_or_default(@_);
-
- # unbuffer output
- $| = 1;
- srand;
- my ($random) = sprintf("%08.0f",rand()*1E8);
- my ($boundary) = "----=_NeXtPaRt$random";
-
- my (@header);
- my ($type,$callback,$delay,$last_page,$cookie,$target,$expires,$nph,$handle,@other) = rearrange([TYPE,NEXT_PAGE,DELAY,LAST_PAGE,[COOKIE,COOKIES],TARGET,EXPIRES,NPH,HANDLE],@p);
- $type = 'text/html' unless $type;
- $callback = \&simple_counter unless $callback && ref($callback) eq 'CODE';
- $delay = 1 unless defined($delay);
- $self->push_delay($delay);
- $nph = 1 unless defined($nph);
- $handle = \*STDOUT unless defined($handle);
-
-sdf;kjsdlfsdfkl
-
- my(@o);
- foreach (@other) { push(@o,split("=")); }
- push(@o,'-Target'=>$target) if defined($target);
- push(@o,'-Cookie'=>$cookie) if defined($cookie);
- push(@o,'-Type'=>"multipart/x-mixed-replace;boundary=\"$boundary\"");
- push(@o,'-Server'=>"CGI.pm Push Module") if $nph;
- push(@o,'-Status'=>'200 OK');
- push(@o,'-nph'=>1) if $nph;
- $handle->print($self->header(@o));
-
- $boundary = "$CGI::CRLF--$boundary";
-
- $handle->print("WARNING: YOUR BROWSER DOESN'T SUPPORT THIS SERVER-PUSH TECHNOLOGY.${boundary}$CGI::CRLF");
-
- my (@contents) = &$callback($self,++$COUNTER);
-
- # now we enter a little loop
- while (1) {
- $handle->print("Content-type: ${type}$CGI::CRLF$CGI::CRLF") unless $type =~ /^dynamic|heterogeneous$/i;
- $handle->print(@contents);
- @contents = &$callback($self,++$COUNTER);
- if ((@contents) && defined($contents[0])) {
- $handle->print("${boundary}$CGI::CRLF");
- do_sleep($self->push_delay()) if $self->push_delay();
- } else {
- if ($last_page && ref($last_page) eq 'CODE') {
- $handle->print("${boundary}$CGI::CRLF");
- do_sleep($self->push_delay()) if $self->push_delay();
- $handle->print("Content-type: ${type}$CGI::CRLF$CGI::CRLF") unless $type =~ /^dynamic|heterogeneous$/i;
- $handle->print(&$last_page($self,$COUNTER));
- }
- $handle->print("${boundary}--$CGI::CRLF");
- last;
- }
- }
- $handle->print("WARNING: YOUR BROWSER DOESN'T SUPPORT THIS SERVER-PUSH TECHNOLOGY.${boundary}$CGI::CRLF");
-}
-
-sub simple_counter {
- my ($self,$count) = @_;
- return $self->start_html("CGI::Push Default Counter"),
- $self->h1("CGI::Push Default Counter"),
- "This page has been updated ",$self->strong($count)," times.",
- $self->hr(),
- $self->a({'-href'=>'http://www.genome.wi.mit.edu/ftp/pub/software/WWW/cgi_docs.html'},'CGI.pm home page'),
- $self->end_html;
-}
-
-sub do_sleep {
- my $delay = shift;
- if ( ($delay >= 1) && ($delay!~/\./) ){
- sleep($delay);
- } else {
- select(undef,undef,undef,$delay);
- }
-}
-
-sub push_delay {
- my ($self,$delay) = CGI::self_or_default(@_);
- return defined($delay) ? $self->{'.delay'} =
- $delay : $self->{'.delay'};
-}
-
-1;
-
-=head1 NAME
-
-CGI::Push - Simple Interface to Server Push
-
-=head1 SYNOPSIS
-
- use CGI::Push qw(:standard);
-
- do_push(-next_page=>\&next_page,
- -last_page=>\&last_page,
- -delay=>0.5);
-
- sub next_page {
- my($q,$counter) = @_;
- return undef if $counter >= 10;
- return start_html('Test'),
- h1('Visible'),"\n",
- "This page has been called ", strong($counter)," times",
- end_html();
- }
-
- sub last_page {
- my($q,$counter) = @_;
- return start_html('Done'),
- h1('Finished'),
- strong($counter - 1),' iterations.',
- end_html;
- }
-
-=head1 DESCRIPTION
-
-CGI::Push is a subclass of the CGI object created by CGI.pm. It is
-specialized for server push operations, which allow you to create
-animated pages whose content changes at regular intervals.
-
-You provide CGI::Push with a pointer to a subroutine that will draw
-one page. Every time your subroutine is called, it generates a new
-page. The contents of the page will be transmitted to the browser
-in such a way that it will replace what was there beforehand. The
-technique will work with HTML pages as well as with graphics files,
-allowing you to create animated GIFs.
-
-Only Netscape Navigator supports server push. Internet Explorer
-browsers do not.
-
-=head1 USING CGI::Push
-
-CGI::Push adds one new method to the standard CGI suite, do_push().
-When you call this method, you pass it a reference to a subroutine
-that is responsible for drawing each new page, an interval delay, and
-an optional subroutine for drawing the last page. Other optional
-parameters include most of those recognized by the CGI header()
-method.
-
-You may call do_push() in the object oriented manner or not, as you
-prefer:
-
- use CGI::Push;
- $q = new CGI::Push;
- $q->do_push(-next_page=>\&draw_a_page);
-
- -or-
-
- use CGI::Push qw(:standard);
- do_push(-next_page=>\&draw_a_page);
-
-Parameters are as follows:
-
-=over 4
-
-=item -next_page
-
- do_push(-next_page=>\&my_draw_routine);
-
-This required parameter points to a reference to a subroutine responsible for
-drawing each new page. The subroutine should expect two parameters
-consisting of the CGI object and a counter indicating the number
-of times the subroutine has been called. It should return the
-contents of the page as an B<array> of one or more items to print.
-It can return a false value (or an empty array) in order to abort the
-redrawing loop and print out the final page (if any)
-
- sub my_draw_routine {
- my($q,$counter) = @_;
- return undef if $counter > 100;
- return start_html('testing'),
- h1('testing'),
- "This page called $counter times";
- }
-
-You are of course free to refer to create and use global variables
-within your draw routine in order to achieve special effects.
-
-=item -last_page
-
-This optional parameter points to a reference to the subroutine
-responsible for drawing the last page of the series. It is called
-after the -next_page routine returns a false value. The subroutine
-itself should have exactly the same calling conventions as the
--next_page routine.
-
-=item -type
-
-This optional parameter indicates the content type of each page. It
-defaults to "text/html". Normally the module assumes that each page
-is of a homogenous MIME type. However if you provide either of the
-magic values "heterogeneous" or "dynamic" (the latter provided for the
-convenience of those who hate long parameter names), you can specify
-the MIME type -- and other header fields -- on a per-page basis. See
-"heterogeneous pages" for more details.
-
-=item -delay
-
-This indicates the delay, in seconds, between frames. Smaller delays
-refresh the page faster. Fractional values are allowed.
-
-B<If not specified, -delay will default to 1 second>
-
-=item -cookie, -target, -expires, -nph
-
-These have the same meaning as the like-named parameters in
-CGI::header().
-
-If not specified, -nph will default to 1 (as needed for many servers, see below).
-
-=back
-
-=head2 Heterogeneous Pages
-
-Ordinarily all pages displayed by CGI::Push share a common MIME type.
-However by providing a value of "heterogeneous" or "dynamic" in the
-do_push() -type parameter, you can specify the MIME type of each page
-on a case-by-case basis.
-
-If you use this option, you will be responsible for producing the
-HTTP header for each page. Simply modify your draw routine to
-look like this:
-
- sub my_draw_routine {
- my($q,$counter) = @_;
- return header('text/html'), # note we're producing the header here
- start_html('testing'),
- h1('testing'),
- "This page called $counter times";
- }
-
-You can add any header fields that you like, but some (cookies and
-status fields included) may not be interpreted by the browser. One
-interesting effect is to display a series of pages, then, after the
-last page, to redirect the browser to a new URL. Because redirect()
-does b<not> work, the easiest way is with a -refresh header field,
-as shown below:
-
- sub my_draw_routine {
- my($q,$counter) = @_;
- return undef if $counter > 10;
- return header('text/html'), # note we're producing the header here
- start_html('testing'),
- h1('testing'),
- "This page called $counter times";
- }
-
- sub my_last_page {
- return header(-refresh=>'5; URL=http://somewhere.else/finished.html',
- -type=>'text/html'),
- start_html('Moved'),
- h1('This is the last page'),
- 'Goodbye!'
- hr,
- end_html;
- }
-
-=head2 Changing the Page Delay on the Fly
-
-If you would like to control the delay between pages on a page-by-page
-basis, call push_delay() from within your draw routine. push_delay()
-takes a single numeric argument representing the number of seconds you
-wish to delay after the current page is displayed and before
-displaying the next one. The delay may be fractional. Without
-parameters, push_delay() just returns the current delay.
-
-=head1 INSTALLING CGI::Push SCRIPTS
-
-Server push scripts must be installed as no-parsed-header (NPH)
-scripts in order to work correctly on many servers. On Unix systems,
-this is most often accomplished by prefixing the script's name with "nph-".
-Recognition of NPH scripts happens automatically with WebSTAR and
-Microsoft IIS. Users of other servers should see their documentation
-for help.
-
-Apache web server from version 1.3b2 on does not need server
-push scripts installed as NPH scripts: the -nph parameter to do_push()
-may be set to a false value to disable the extra headers needed by an
-NPH script.
-
-=head1 AUTHOR INFORMATION
-
-Copyright 1995-1998, Lincoln D. Stein. All rights reserved.
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-Address bug reports and comments to: lstein@cshl.org
-
-=head1 BUGS
-
-This section intentionally left blank.
-
-=head1 SEE ALSO
-
-L<CGI::Carp>, L<CGI>
-
-=cut
-
diff --git a/lib/CGI/Switch.pm b/lib/CGI/Switch.pm
deleted file mode 100644
index b8cc9ef..0000000
--- a/lib/CGI/Switch.pm
+++ /dev/null
@@ -1,27 +0,0 @@
-use CGI;
-
-$VERSION = '1.00';
-
-1;
-
-__END__
-
-=head1 NAME
-
-CGI::Switch - Backward compatibility module for defunct CGI::Switch
-
-=head1 SYNOPSIS
-
-Do not use this module. It is deprecated.
-
-=head1 ABSTRACT
-
-=head1 DESCRIPTION
-
-=head1 AUTHOR INFORMATION
-
-=head1 BUGS
-
-=head1 SEE ALSO
-
-=cut
diff --git a/lib/CGI/Util.pm b/lib/CGI/Util.pm
deleted file mode 100644
index 6af42de..0000000
--- a/lib/CGI/Util.pm
+++ /dev/null
@@ -1,317 +0,0 @@
-package CGI::Util;
-
-use strict;
-use vars qw($VERSION @EXPORT_OK @ISA $EBCDIC @A2E @E2A);
-require Exporter;
-@ISA = qw(Exporter);
-@EXPORT_OK = qw(rearrange make_attributes unescape escape
- expires ebcdic2ascii ascii2ebcdic);
-
-$VERSION = '1.5';
-
-$EBCDIC = "\t" ne "\011";
-# (ord('^') == 95) for codepage 1047 as on os390, vmesa
-@A2E = (
- 0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 21, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31,
- 64, 90,127,123, 91,108, 80,125, 77, 93, 92, 78,107, 96, 75, 97,
- 240,241,242,243,244,245,246,247,248,249,122, 94, 76,126,110,111,
- 124,193,194,195,196,197,198,199,200,201,209,210,211,212,213,214,
- 215,216,217,226,227,228,229,230,231,232,233,173,224,189, 95,109,
- 121,129,130,131,132,133,134,135,136,137,145,146,147,148,149,150,
- 151,152,153,162,163,164,165,166,167,168,169,192, 79,208,161, 7,
- 32, 33, 34, 35, 36, 37, 6, 23, 40, 41, 42, 43, 44, 9, 10, 27,
- 48, 49, 26, 51, 52, 53, 54, 8, 56, 57, 58, 59, 4, 20, 62,255,
- 65,170, 74,177,159,178,106,181,187,180,154,138,176,202,175,188,
- 144,143,234,250,190,160,182,179,157,218,155,139,183,184,185,171,
- 100,101, 98,102, 99,103,158,104,116,113,114,115,120,117,118,119,
- 172,105,237,238,235,239,236,191,128,253,254,251,252,186,174, 89,
- 68, 69, 66, 70, 67, 71,156, 72, 84, 81, 82, 83, 88, 85, 86, 87,
- 140, 73,205,206,203,207,204,225,112,221,222,219,220,141,142,223
- );
-@E2A = (
- 0, 1, 2, 3,156, 9,134,127,151,141,142, 11, 12, 13, 14, 15,
- 16, 17, 18, 19,157, 10, 8,135, 24, 25,146,143, 28, 29, 30, 31,
- 128,129,130,131,132,133, 23, 27,136,137,138,139,140, 5, 6, 7,
- 144,145, 22,147,148,149,150, 4,152,153,154,155, 20, 21,158, 26,
- 32,160,226,228,224,225,227,229,231,241,162, 46, 60, 40, 43,124,
- 38,233,234,235,232,237,238,239,236,223, 33, 36, 42, 41, 59, 94,
- 45, 47,194,196,192,193,195,197,199,209,166, 44, 37, 95, 62, 63,
- 248,201,202,203,200,205,206,207,204, 96, 58, 35, 64, 39, 61, 34,
- 216, 97, 98, 99,100,101,102,103,104,105,171,187,240,253,254,177,
- 176,106,107,108,109,110,111,112,113,114,170,186,230,184,198,164,
- 181,126,115,116,117,118,119,120,121,122,161,191,208, 91,222,174,
- 172,163,165,183,169,167,182,188,189,190,221,168,175, 93,180,215,
- 123, 65, 66, 67, 68, 69, 70, 71, 72, 73,173,244,246,242,243,245,
- 125, 74, 75, 76, 77, 78, 79, 80, 81, 82,185,251,252,249,250,255,
- 92,247, 83, 84, 85, 86, 87, 88, 89, 90,178,212,214,210,211,213,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,179,219,220,217,218,159
- );
-
-if ($EBCDIC && ord('^') == 106) { # as in the BS2000 posix-bc coded character set
- $A2E[91] = 187; $A2E[92] = 188; $A2E[94] = 106; $A2E[96] = 74;
- $A2E[123] = 251; $A2E[125] = 253; $A2E[126] = 255; $A2E[159] = 95;
- $A2E[162] = 176; $A2E[166] = 208; $A2E[168] = 121; $A2E[172] = 186;
- $A2E[175] = 161; $A2E[217] = 224; $A2E[219] = 221; $A2E[221] = 173;
- $A2E[249] = 192;
-
- $E2A[74] = 96; $E2A[95] = 159; $E2A[106] = 94; $E2A[121] = 168;
- $E2A[161] = 175; $E2A[173] = 221; $E2A[176] = 162; $E2A[186] = 172;
- $E2A[187] = 91; $E2A[188] = 92; $E2A[192] = 249; $E2A[208] = 166;
- $E2A[221] = 219; $E2A[224] = 217; $E2A[251] = 123; $E2A[253] = 125;
- $E2A[255] = 126;
- }
-elsif ($EBCDIC && ord('^') == 176) { # as in codepage 037 on os400
- $A2E[10] = 37; $A2E[91] = 186; $A2E[93] = 187; $A2E[94] = 176;
- $A2E[133] = 21; $A2E[168] = 189; $A2E[172] = 95; $A2E[221] = 173;
-
- $E2A[21] = 133; $E2A[37] = 10; $E2A[95] = 172; $E2A[173] = 221;
- $E2A[176] = 94; $E2A[186] = 91; $E2A[187] = 93; $E2A[189] = 168;
-}
-
-# Smart rearrangement of parameters to allow named parameter
-# calling. We do the rearangement if:
-# the first parameter begins with a -
-sub rearrange {
- my($order,@param) = @_;
- return () unless @param;
-
- if (ref($param[0]) eq 'HASH') {
- @param = %{$param[0]};
- } else {
- return @param
- unless (defined($param[0]) && substr($param[0],0,1) eq '-');
- }
-
- # map parameters into positional indices
- my ($i,%pos);
- $i = 0;
- foreach (@$order) {
- foreach (ref($_) eq 'ARRAY' ? @$_ : $_) { $pos{lc($_)} = $i; }
- $i++;
- }
-
- my (@result,%leftover);
- $#result = $#$order; # preextend
- while (@param) {
- my $key = lc(shift(@param));
- $key =~ s/^\-//;
- if (exists $pos{$key}) {
- $result[$pos{$key}] = shift(@param);
- } else {
- $leftover{$key} = shift(@param);
- }
- }
-
- push (@result,make_attributes(\%leftover,1)) if %leftover;
- @result;
-}
-
-sub make_attributes {
- my $attr = shift;
- return () unless $attr && ref($attr) && ref($attr) eq 'HASH';
- my $escape = shift || 0;
- my(@att);
- foreach (keys %{$attr}) {
- my($key) = $_;
- $key=~s/^\-//; # get rid of initial - if present
-
- # old way: breaks EBCDIC!
- # $key=~tr/A-Z_/a-z-/; # parameters are lower case, use dashes
-
- ($key="\L$key") =~ tr/_/-/; # parameters are lower case, use dashes
-
- my $value = $escape ? simple_escape($attr->{$_}) : $attr->{$_};
- push(@att,defined($attr->{$_}) ? qq/$key="$value"/ : qq/$key/);
- }
- return @att;
-}
-
-sub simple_escape {
- return unless defined(my $toencode = shift);
- $toencode =~ s{&}{&amp;}gso;
- $toencode =~ s{<}{&lt;}gso;
- $toencode =~ s{>}{&gt;}gso;
- $toencode =~ s{\"}{&quot;}gso;
-# Doesn't work. Can't work. forget it.
-# $toencode =~ s{\x8b}{&#139;}gso;
-# $toencode =~ s{\x9b}{&#155;}gso;
- $toencode;
-}
-
-sub utf8_chr {
- my $c = shift(@_);
-
- if ($c < 0x80) {
- return sprintf("%c", $c);
- } elsif ($c < 0x800) {
- return sprintf("%c%c", 0xc0 | ($c >> 6), 0x80 | ($c & 0x3f));
- } elsif ($c < 0x10000) {
- return sprintf("%c%c%c",
- 0xe0 | ($c >> 12),
- 0x80 | (($c >> 6) & 0x3f),
- 0x80 | ( $c & 0x3f));
- } elsif ($c < 0x200000) {
- return sprintf("%c%c%c%c",
- 0xf0 | ($c >> 18),
- 0x80 | (($c >> 12) & 0x3f),
- 0x80 | (($c >> 6) & 0x3f),
- 0x80 | ( $c & 0x3f));
- } elsif ($c < 0x4000000) {
- return sprintf("%c%c%c%c%c",
- 0xf8 | ($c >> 24),
- 0x80 | (($c >> 18) & 0x3f),
- 0x80 | (($c >> 12) & 0x3f),
- 0x80 | (($c >> 6) & 0x3f),
- 0x80 | ( $c & 0x3f));
-
- } elsif ($c < 0x80000000) {
- return sprintf("%c%c%c%c%c%c",
- 0xfc | ($c >> 30),
- 0x80 | (($c >> 24) & 0x3f),
- 0x80 | (($c >> 18) & 0x3f),
- 0x80 | (($c >> 12) & 0x3f),
- 0x80 | (($c >> 6) & 0x3f),
- 0x80 | ( $c & 0x3f));
- } else {
- return utf8_chr(0xfffd);
- }
-}
-
-# unescape URL-encoded data
-sub unescape {
- shift() if @_ > 1 and (ref($_[0]) || (defined $_[1] && $_[0] eq $CGI::DefaultClass));
- my $todecode = shift;
- return undef unless defined($todecode);
- $todecode =~ tr/+/ /; # pluses become spaces
- $EBCDIC = "\t" ne "\011";
- if ($EBCDIC) {
- $todecode =~ s/%([0-9a-fA-F]{2})/chr $A2E[hex($1)]/ge;
- } else {
- $todecode =~ s/%(?:([0-9a-fA-F]{2})|u([0-9a-fA-F]{4}))/
- defined($1)? chr hex($1) : utf8_chr(hex($2))/ge;
- }
- return $todecode;
-}
-
-# URL-encode data
-sub escape {
- shift() if @_ > 1 and ( ref($_[0]) || (defined $_[1] && $_[0] eq $CGI::DefaultClass));
- my $toencode = shift;
- return undef unless defined($toencode);
- # force bytes while preserving backward compatibility -- dankogai
- $toencode = pack("C*", unpack("C*", $toencode));
- if ($EBCDIC) {
- $toencode=~s/([^a-zA-Z0-9_.-])/uc sprintf("%%%02x",$E2A[ord($1)])/eg;
- } else {
- $toencode=~s/([^a-zA-Z0-9_.-])/uc sprintf("%%%02x",ord($1))/eg;
- }
- return $toencode;
-}
-
-# This internal routine creates date strings suitable for use in
-# cookies and HTTP headers. (They differ, unfortunately.)
-# Thanks to Mark Fisher for this.
-sub expires {
- my($time,$format) = @_;
- $format ||= 'http';
-
- my(@MON)=qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/;
- my(@WDAY) = qw/Sun Mon Tue Wed Thu Fri Sat/;
-
- # pass through preformatted dates for the sake of expire_calc()
- $time = expire_calc($time);
- return $time unless $time =~ /^\d+$/;
-
- # make HTTP/cookie date string from GMT'ed time
- # (cookies use '-' as date separator, HTTP uses ' ')
- my($sc) = ' ';
- $sc = '-' if $format eq "cookie";
- my($sec,$min,$hour,$mday,$mon,$year,$wday) = gmtime($time);
- $year += 1900;
- return sprintf("%s, %02d$sc%s$sc%04d %02d:%02d:%02d GMT",
- $WDAY[$wday],$mday,$MON[$mon],$year,$hour,$min,$sec);
-}
-
-# This internal routine creates an expires time exactly some number of
-# hours from the current time. It incorporates modifications from
-# Mark Fisher.
-sub expire_calc {
- my($time) = @_;
- my(%mult) = ('s'=>1,
- 'm'=>60,
- 'h'=>60*60,
- 'd'=>60*60*24,
- 'M'=>60*60*24*30,
- 'y'=>60*60*24*365);
- # format for time can be in any of the forms...
- # "now" -- expire immediately
- # "+180s" -- in 180 seconds
- # "+2m" -- in 2 minutes
- # "+12h" -- in 12 hours
- # "+1d" -- in 1 day
- # "+3M" -- in 3 months
- # "+2y" -- in 2 years
- # "-3m" -- 3 minutes ago(!)
- # If you don't supply one of these forms, we assume you are
- # specifying the date yourself
- my($offset);
- if (!$time || (lc($time) eq 'now')) {
- $offset = 0;
- } elsif ($time=~/^\d+/) {
- return $time;
- } elsif ($time=~/^([+-]?(?:\d+|\d*\.\d*))([mhdMy]?)/) {
- $offset = ($mult{$2} || 1)*$1;
- } else {
- return $time;
- }
- return (time+$offset);
-}
-
-sub ebcdic2ascii {
- my $data = shift;
- $data =~ s/(.)/chr $E2A[ord($1)]/ge;
- $data;
-}
-
-sub ascii2ebcdic {
- my $data = shift;
- $data =~ s/(.)/chr $A2E[ord($1)]/ge;
- $data;
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-CGI::Util - Internal utilities used by CGI module
-
-=head1 SYNOPSIS
-
-none
-
-=head1 DESCRIPTION
-
-no public subroutines
-
-=head1 AUTHOR INFORMATION
-
-Copyright 1995-1998, Lincoln D. Stein. All rights reserved.
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-Address bug reports and comments to: lstein@cshl.org. When sending
-bug reports, please provide the version of CGI.pm, the version of
-Perl, the name and version of your Web server, and the name and
-version of the operating system you are using. If the problem is even
-remotely browser dependent, please provide information about the
-affected browers as well.
-
-=head1 SEE ALSO
-
-L<CGI>
-
-=cut
diff --git a/lib/Config/Tiny.pm b/lib/Config/Tiny.pm
deleted file mode 100644
index c543756..0000000
--- a/lib/Config/Tiny.pm
+++ /dev/null
@@ -1,248 +0,0 @@
-package Config::Tiny;
-
-# If you thought Config::Simple was small...
-
-use 5.004;
-use strict;
-
-use vars qw{$VERSION $errstr};
-BEGIN {
- $VERSION = '2.00';
- $errstr = '';
-}
-
-# Create an empty object
-sub new { bless {}, shift }
-
-# Create an object from a file
-sub read {
- my $class = ref $_[0] ? ref shift : shift;
-
- # Check the file
- my $file = shift or return $class->_error( 'You did not specify a file name' );
- return $class->_error( "File '$file' does not exist" ) unless -e $file;
- return $class->_error( "'$file' is a directory, not a file" ) unless -f _;
- return $class->_error( "Insufficient permissions to read '$file'" ) unless -r _;
-
- # Slurp in the file
- local $/ = undef;
- open CFG, $file or return $class->_error( "Failed to open file '$file': $!" );
- my $contents = <CFG>;
- close CFG;
-
- $class->read_string( $contents );
-}
-
-# Create an object from a string
-sub read_string {
- my $class = ref $_[0] ? ref shift : shift;
- my $self = bless {}, $class;
- return undef unless defined $_[0];
-
- # Parse the file
- my $ns = '_';
- my $counter = 0;
- foreach ( split /(?:\015{1,2}\012|\015|\012)/, shift ) {
- $counter++;
-
- # Skip comments and empty lines
- next if /^\s*(?:\#|\;|$)/;
-
- # Handle section headers
- if ( /^\s*\[(.+?)\]\s*$/ ) {
- # Create the sub-hash if it doesn't exist.
- # Without this sections without keys will not
- # appear at all in the completed struct.
- $ns = $1;
- $self->{$ns} = {};
- next;
- }
-
- # Handle properties
- if ( /^\s*([^=]+?)\s*=\s*(.*?)\s*$/ ) {
- $self->{$ns}->{$1} = $2;
- next;
- }
-
- return $self->_error( "Syntax error at line $counter: '$_'" );
- }
-
- $self;
-}
-
-# Save an object to a file
-sub write {
- my $self = shift;
- my $file = shift or return $self->_error( 'No file name provided' );
-
- # Write it to the file
- open( CFG, '>', $file )
- or return $self->_error( "Failed to open file '$file' for writing: $!" );
- print CFG $self->write_string;
- close CFG;
-}
-
-# Save an object to a string
-sub write_string {
- my $self = shift;
-
- my $contents = '';
- foreach my $section ( sort { (($b eq '_') <=> ($a eq '_')) || ($a cmp $b) } keys %$self ) {
- my $block = $self->{$section};
- $contents .= "\n" if length $contents;
- $contents .= "[$section]\n" unless $section eq '_';
- foreach my $property ( sort keys %$block ) {
- $contents .= "$property=$block->{$property}\n";
- }
- }
-
- $contents;
-}
-
-# Error handling
-sub errstr { $errstr }
-sub _error { $errstr = $_[1]; undef }
-
-1;
-
-__END__
-
-=pod
-
-=head1 NAME
-
-Config::Tiny - Read/Write .ini style files with as little code as possible
-
-=head1 SYNOPSIS
-
- # In your configuration file
- rootproperty=blah
-
- [section]
- one=twp
- three= four
- Foo =Bar
- empty=
-
- # In your program
- use Config::Tiny;
-
- # Create a config
- my $Config = Config::Tiny->new();
-
- # Open the config
- $Config = Config::Tiny->read( 'file.conf' );
-
- # Reading properties
- my $rootproperty = $Config->{_}->{rootproperty};
- my $one = $Config->{section}->{one};
- my $Foo = $Config->{section}->{Foo};
-
- # Changing data
- $Config->{newsection} = { this => 'that' }; # Add a section
- $Config->{section}->{Foo} = 'Not Bar!'; # Change a value
- delete $Config->{_}; # Delete a value or section
-
- # Save a config
- $Config->write( 'file.conf' );
-
-=head1 DESCRIPTION
-
-Config::Tiny is a perl class to read and write .ini style configuration files
-with as little code as possible, reducing load time and memory overhead.
-Memory usage is normally scoffed at in Perl, but in my opinion should be
-at least kept in mind.
-
-This module is primarily for reading human written files, and anything we
-write shouldn't need to have documentation/comments. If you need something
-with more power, move up to Config::Simple, Config::General or one of the
-many other Config:: modules. To rephrase, Config::Tiny does not preserve
-your comments, whitespace, or the order of your config file.
-
-=head1 CONFIGURATION FILE SYNTAX
-
-Files are the same as windows .ini files, for example.
-
- [section]
- var1=value1
- var2=value2
-
-If a property is outside of a section, it will be assigned to the root
-section, available at C<$Config-E<gt>{_}>.
-
-Lines starting with '#' or ';' are comments, and blank lines are ignored.
-
-When writing back to the config file, any comments are discarded.
-
-=head1 METHODS
-
-=head2 new
-
-The constructor C<new> creates and returns an empty Config::Tiny object.
-
-=head2 read $filename
-
-The C<read> constructor reads a config file, and returns a new Config::Tiny
-object containing the properties in the file.
-
-Returns the object on success, or C<undef> on error.
-
-=head2 read_string $string;
-
-The C<read_string> method takes as argument the contents of a config file as a string
-and returns the Config::Tiny object for it.
-
-=head2 write
-
-The C<write $filename> generates the file for the properties, and writes it
-to disk.
-
-Returns true on success or C<undef> on error.
-
-=head2 write_string
-
-Generates the file for the object and returns it as a string.
-
-=head2 errstr
-
-When an error occurs, you can retrieve the error message either from the
-C<$Config::Tiny::errstr> variable, or using the C<errstr()> method.
-
-=head1 SUPPORT
-
-Bugs should be reported via the CPAN bug tracker at
-
- http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Config%3A%3ATiny
-
-For other issues, contact the author
-
-=head1 TO DO
-
-I'm debating adding a get and set method to get or set a section.key based
-value...
-
-Implementation is left as an exercise for the reader.
-
-=head1 AUTHOR
-
- Adam Kennedy ( maintainer )
- cpan@ali.as
- http://ali.as/
-
-Thanks to Sherzod Ruzmetov <sherzodr@cpan.org> for Config::Simple,
-which inspired this module by being not quite "simple" enough for me :)
-
-=head1 SEE ALSO
-
-L<Config::Simple>, L<Config::General>
-
-=head1 COPYRIGHT
-
-Copyright 2002-2004 Adam Kennedy. All rights reserved.
-This program is free software; you can redistribute
-it and/or modify it under the same terms as Perl itself.
-
-The full text of the license can be found in the
-LICENSE file included with this module.
-
-=cut
diff --git a/lib/Date/Manip.pm b/lib/Date/Manip.pm
deleted file mode 100644
index 7a3f810..0000000
--- a/lib/Date/Manip.pm
+++ /dev/null
@@ -1,7362 +0,0 @@
-package Date::Manip;
-# Copyright (c) 1995-2003 Sullivan Beck. All rights reserved.
-# This program is free software; you can redistribute it and/or modify it
-# under the same terms as Perl itself.
-
-###########################################################################
-###########################################################################
-
-use vars qw($OS %Lang %Holiday %Events %Curr %Cnf %Zone $VERSION @ISA @EXPORT);
-
-# Determine the type of OS...
-$OS="Unix";
-$OS="Windows" if ((defined $^O and
- $^O =~ /MSWin32/i ||
- $^O =~ /Windows_95/i ||
- $^O =~ /Windows_NT/i) ||
- (defined $ENV{OS} and
- $ENV{OS} =~ /MSWin32/i ||
- $ENV{OS} =~ /Windows_95/i ||
- $ENV{OS} =~ /Windows_NT/i));
-$OS="Netware" if (defined $^O and
- $^O =~ /NetWare/i);
-$OS="Mac" if ((defined $^O and
- $^O =~ /MacOS/i) ||
- (defined $ENV{OS} and
- $ENV{OS} =~ /MacOS/i));
-$OS="MPE" if (defined $^O and
- $^O =~ /MPE/i);
-$OS="OS2" if (defined $^O and
- $^O =~ /os2/i);
-$OS="VMS" if (defined $^O and
- $^O =~ /VMS/i);
-
-# Determine if we're doing taint checking
-$Date::Manip::NoTaint = eval { local $^W; unlink "$^X$^T"; 1 };
-
-###########################################################################
-# CUSTOMIZATION
-###########################################################################
-#
-# See the section of the POD documentation section CUSTOMIZING DATE::MANIP
-# below for a complete description of each of these variables.
-
-
-# Location of a the global config file. Tilde (~) expansions are allowed.
-# This should be set in Date_Init arguments.
-$Cnf{"GlobalCnf"}="";
-$Cnf{"IgnoreGlobalCnf"}="";
-
-# Name of a personal config file and the path to search for it. Tilde (~)
-# expansions are allowed. This should be set in Date_Init arguments or in
-# the global config file.
-
-@Date::Manip::DatePath=();
-if ($OS eq "Windows") {
- $Cnf{"PathSep"} = ";";
- $Cnf{"PersonalCnf"} = "Manip.cnf";
- $Cnf{"PersonalCnfPath"} = ".";
-
-} elsif ($OS eq "Netware") {
- $Cnf{"PathSep"} = ";";
- $Cnf{"PersonalCnf"} = "Manip.cnf";
- $Cnf{"PersonalCnfPath"} = ".";
-
-} elsif ($OS eq "MPE") {
- $Cnf{"PathSep"} = ":";
- $Cnf{"PersonalCnf"} = "Manip.cnf";
- $Cnf{"PersonalCnfPath"} = ".";
-
-} elsif ($OS eq "OS2") {
- $Cnf{"PathSep"} = ":";
- $Cnf{"PersonalCnf"} = "Manip.cnf";
- $Cnf{"PersonalCnfPath"} = ".";
-
-} elsif ($OS eq "Mac") {
- $Cnf{"PathSep"} = ":";
- $Cnf{"PersonalCnf"} = "Manip.cnf";
- $Cnf{"PersonalCnfPath"} = ".";
-
-} elsif ($OS eq "VMS") {
- # VMS doesn't like files starting with "."
- $Cnf{"PathSep"} = "\n";
- $Cnf{"PersonalCnf"} = "Manip.cnf";
- $Cnf{"PersonalCnfPath"} = ".\n~";
-
-} else {
- # Unix
- $Cnf{"PathSep"} = ":";
- $Cnf{"PersonalCnf"} = ".DateManip.cnf";
- $Cnf{"PersonalCnfPath"} = ".:~";
- @Date::Manip::DatePath=qw(/bin /usr/bin /usr/local/bin);
-}
-
-### Date::Manip variables set in the global or personal config file
-
-# Which language to use when parsing dates.
-$Cnf{"Language"}="English";
-
-# 12/10 = Dec 10 (US) or Oct 12 (anything else)
-$Cnf{"DateFormat"}="US";
-
-# Local timezone
-$Cnf{"TZ"}="";
-
-# Timezone to work in (""=local, "IGNORE", or a timezone)
-$Cnf{"ConvTZ"}="";
-
-# Date::Manip internal format (0=YYYYMMDDHH:MN:SS, 1=YYYYHHMMDDHHMNSS)
-$Cnf{"Internal"}=0;
-
-# First day of the week (1=monday, 7=sunday). ISO 8601 says monday.
-$Cnf{"FirstDay"}=1;
-
-# First and last day of the work week (1=monday, 7=sunday)
-$Cnf{"WorkWeekBeg"}=1;
-$Cnf{"WorkWeekEnd"}=5;
-
-# If non-nil, a work day is treated as 24 hours long (WorkDayBeg/WorkDayEnd
-# ignored)
-$Cnf{"WorkDay24Hr"}=0;
-
-# Start and end time of the work day (any time format allowed, seconds
-# ignored)
-$Cnf{"WorkDayBeg"}="08:00";
-$Cnf{"WorkDayEnd"}="17:00";
-
-# If "today" is a holiday, we look either to "tomorrow" or "yesterday" for
-# the nearest business day. By default, we'll always look "tomorrow"
-# first.
-$Cnf{"TomorrowFirst"}=1;
-
-# Erase the old holidays
-$Cnf{"EraseHolidays"}="";
-
-# Set this to non-zero to be produce completely backwards compatible deltas
-$Cnf{"DeltaSigns"}=0;
-
-# If this is 0, use the ISO 8601 standard that Jan 4 is in week 1. If 1,
-# make week 1 contain Jan 1.
-$Cnf{"Jan1Week1"}=0;
-
-# 2 digit years fall into the 100 year period given by [ CURR-N,
-# CURR+(99-N) ] where N is 0-99. Default behavior is 89, but other useful
-# numbers might be 0 (forced to be this year or later) and 99 (forced to be
-# this year or earlier). It can also be set to "c" (current century) or
-# "cNN" (i.e. c18 forces the year to bet 1800-1899). Also accepts the
-# form cNNNN to give the 100 year period NNNN to NNNN+99.
-$Cnf{"YYtoYYYY"}=89;
-
-# Set this to 1 if you want a long-running script to always update the
-# timezone. This will slow Date::Manip down. Read the POD documentation.
-$Cnf{"UpdateCurrTZ"}=0;
-
-# Use an international character set.
-$Cnf{"IntCharSet"}=0;
-
-# Use this to force the current date to be set to this:
-$Cnf{"ForceDate"}="";
-
-###########################################################################
-
-require 5.000;
-require Exporter;
-@ISA = qw(Exporter);
-@EXPORT = qw(
- DateManipVersion
- Date_Init
- ParseDateString
- ParseDate
- ParseRecur
- Date_Cmp
- DateCalc
- ParseDateDelta
- UnixDate
- Delta_Format
- Date_GetPrev
- Date_GetNext
- Date_SetTime
- Date_SetDateField
- Date_IsHoliday
- Events_List
-
- Date_DaysInMonth
- Date_DayOfWeek
- Date_SecsSince1970
- Date_SecsSince1970GMT
- Date_DaysSince1BC
- Date_DayOfYear
- Date_DaysInYear
- Date_WeekOfYear
- Date_LeapYear
- Date_DaySuffix
- Date_ConvTZ
- Date_TimeZone
- Date_IsWorkDay
- Date_NextWorkDay
- Date_PrevWorkDay
- Date_NearestWorkDay
- Date_NthDayOfYear
-);
-use strict;
-use integer;
-use Carp;
-
-use IO::File;
-
-$VERSION="5.42";
-
-########################################################################
-########################################################################
-
-$Curr{"InitLang"} = 1; # Whether a language is being init'ed
-$Curr{"InitDone"} = 0; # Whether Init_Date has been called
-$Curr{"InitFilesRead"} = 0;
-$Curr{"ResetWorkDay"} = 1;
-$Curr{"Debug"} = "";
-$Curr{"DebugVal"} = "";
-
-$Holiday{"year"} = 0;
-$Holiday{"dates"} = {};
-$Holiday{"desc"} = {};
-
-$Events{"raw"} = [];
-$Events{"parsed"} = 0;
-$Events{"dates"} = [];
-$Events{"recur"} = [];
-
-########################################################################
-########################################################################
-# THESE ARE THE MAIN ROUTINES
-########################################################################
-########################################################################
-
-# Get rid of a problem with old versions of perl
-no strict "vars";
-# This sorts from longest to shortest element
-sub sortByLength {
- return (length $b <=> length $a);
-}
-use strict "vars";
-
-sub DateManipVersion {
- print "DEBUG: DateManipVersion\n" if ($Curr{"Debug"} =~ /trace/);
- return $VERSION;
-}
-
-sub Date_Init {
- print "DEBUG: Date_Init\n" if ($Curr{"Debug"} =~ /trace/);
- $Curr{"Debug"}="";
-
- my(@args)=@_;
- $Curr{"InitDone"}=1;
- local($_)=();
- my($internal,$firstday)=();
- my($var,$val,$file,@tmp)=();
-
- # InitFilesRead = 0 : no conf files read yet
- # 1 : global read, no personal read
- # 2 : personal read
-
- $Cnf{"EraseHolidays"}=0;
- foreach (@args) {
- s/\s*$//;
- s/^\s*//;
- /^(\S+) \s* = \s* (.+)$/x;
- ($var,$val)=($1,$2);
- if ($var =~ /^GlobalCnf$/i) {
- $Cnf{"GlobalCnf"}=$val;
- if ($val) {
- $Curr{"InitFilesRead"}=0;
- &EraseHolidays();
- }
- } elsif ($var =~ /^PathSep$/i) {
- $Cnf{"PathSep"}=$val;
- } elsif ($var =~ /^PersonalCnf$/i) {
- $Cnf{"PersonalCnf"}=$val;
- $Curr{"InitFilesRead"}=1 if ($Curr{"InitFilesRead"}==2);
- } elsif ($var =~ /^PersonalCnfPath$/i) {
- $Cnf{"PersonalCnfPath"}=$val;
- $Curr{"InitFilesRead"}=1 if ($Curr{"InitFilesRead"}==2);
- } elsif ($var =~ /^IgnoreGlobalCnf$/i) {
- $Curr{"InitFilesRead"}=1 if ($Curr{"InitFilesRead"}==0);
- $Cnf{"IgnoreGlobalCnf"}=1;
- } elsif ($var =~ /^EraseHolidays$/i) {
- &EraseHolidays();
- } else {
- push(@tmp,$_);
- }
- }
- @args=@tmp;
-
- # Read global config file
- if ($Curr{"InitFilesRead"}<1 && ! $Cnf{"IgnoreGlobalCnf"}) {
- $Curr{"InitFilesRead"}=1;
-
- if ($Cnf{"GlobalCnf"}) {
- $file=&ExpandTilde($Cnf{"GlobalCnf"});
- &Date_InitFile($file) if ($file);
- }
- }
-
- # Read personal config file
- if ($Curr{"InitFilesRead"}<2) {
- $Curr{"InitFilesRead"}=2;
-
- if ($Cnf{"PersonalCnf"} and $Cnf{"PersonalCnfPath"}) {
- $file=&SearchPath($Cnf{"PersonalCnf"},$Cnf{"PersonalCnfPath"},"r");
- &Date_InitFile($file) if ($file);
- }
- }
-
- foreach (@args) {
- s/\s*$//;
- s/^\s*//;
- /^(\S+) \s* = \s* (.*)$/x;
- ($var,$val)=($1,$2);
- $val="" if (! defined $val);
- &Date_SetConfigVariable($var,$val);
- }
-
- confess "ERROR: Unknown FirstDay in Date::Manip.\n"
- if (! &IsInt($Cnf{"FirstDay"},1,7));
- confess "ERROR: Unknown WorkWeekBeg in Date::Manip.\n"
- if (! &IsInt($Cnf{"WorkWeekBeg"},1,7));
- confess "ERROR: Unknown WorkWeekEnd in Date::Manip.\n"
- if (! &IsInt($Cnf{"WorkWeekEnd"},1,7));
- confess "ERROR: Invalid WorkWeek in Date::Manip.\n"
- if ($Cnf{"WorkWeekEnd"} <= $Cnf{"WorkWeekBeg"});
-
- my(%lang,
- $tmp,%tmp,$tmp2,@tmp2,
- $i,$j,@tmp3,
- $zonesrfc,@zones)=();
-
- my($L)=$Cnf{"Language"};
-
- if ($Curr{"InitLang"}) {
- $Curr{"InitLang"}=0;
-
- if ($L eq "English") {
- &Date_Init_English(\%lang);
-
- } elsif ($L eq "French") {
- &Date_Init_French(\%lang);
-
- } elsif ($L eq "Swedish") {
- &Date_Init_Swedish(\%lang);
-
- } elsif ($L eq "German") {
- &Date_Init_German(\%lang);
-
- } elsif ($L eq "Polish") {
- &Date_Init_Polish(\%lang);
-
- } elsif ($L eq "Dutch" ||
- $L eq "Nederlands") {
- &Date_Init_Dutch(\%lang);
-
- } elsif ($L eq "Spanish") {
- &Date_Init_Spanish(\%lang);
-
- } elsif ($L eq "Portuguese") {
- &Date_Init_Portuguese(\%lang);
-
- } elsif ($L eq "Romanian") {
- &Date_Init_Romanian(\%lang);
-
- } elsif ($L eq "Italian") {
- &Date_Init_Italian(\%lang);
-
- } elsif ($L eq "Russian") {
- &Date_Init_Russian(\%lang);
-
- } elsif ($L eq "Turkish") {
- &Date_Init_Turkish(\%lang);
-
- } elsif ($L eq "Danish") {
- &Date_Init_Danish(\%lang);
-
- } else {
- confess "ERROR: Unknown language in Date::Manip.\n";
- }
-
- # variables for months
- # Month = "(jan|january|feb|february ... )"
- # MonL = [ "Jan","Feb",... ]
- # MonthL = [ "January","February", ... ]
- # MonthH = { "january"=>1, "jan"=>1, ... }
-
- $Lang{$L}{"MonthH"}={};
- $Lang{$L}{"MonthL"}=[];
- $Lang{$L}{"MonL"}=[];
- &Date_InitLists([$lang{"month_name"},
- $lang{"month_abb"}],
- \$Lang{$L}{"Month"},"lc,sort,back",
- [$Lang{$L}{"MonthL"},
- $Lang{$L}{"MonL"}],
- [$Lang{$L}{"MonthH"},1]);
-
- # variables for day of week
- # Week = "(mon|monday|tue|tuesday ... )"
- # WL = [ "M","T",... ]
- # WkL = [ "Mon","Tue",... ]
- # WeekL = [ "Monday","Tudesday",... ]
- # WeekH = { "monday"=>1,"mon"=>1,"m"=>1,... }
-
- $Lang{$L}{"WeekH"}={};
- $Lang{$L}{"WeekL"}=[];
- $Lang{$L}{"WkL"}=[];
- $Lang{$L}{"WL"}=[];
- &Date_InitLists([$lang{"day_name"},
- $lang{"day_abb"}],
- \$Lang{$L}{"Week"},"lc,sort,back",
- [$Lang{$L}{"WeekL"},
- $Lang{$L}{"WkL"}],
- [$Lang{$L}{"WeekH"},1]);
- &Date_InitLists([$lang{"day_char"}],
- "","lc",
- [$Lang{$L}{"WL"}],
- [\%tmp,1]);
- %{ $Lang{$L}{"WeekH"} } =
- (%{ $Lang{$L}{"WeekH"} },%tmp);
-
- # variables for last
- # Last = "(last)"
- # LastL = [ "last" ]
- # Each = "(each)"
- # EachL = [ "each" ]
- # variables for day of month
- # DoM = "(1st|first ... 31st)"
- # DoML = [ "1st","2nd",... "31st" ]
- # DoMH = { "1st"=>1,"first"=>1, ... "31st"=>31 }
- # variables for week of month
- # WoM = "(1st|first| ... 5th|last)"
- # WoMH = { "1st"=>1, ... "5th"=>5,"last"=>-1 }
-
- $Lang{$L}{"LastL"}=$lang{"last"};
- &Date_InitStrings($lang{"last"},
- \$Lang{$L}{"Last"},"lc,sort");
-
- $Lang{$L}{"EachL"}=$lang{"each"};
- &Date_InitStrings($lang{"each"},
- \$Lang{$L}{"Each"},"lc,sort");
-
- $Lang{$L}{"DoMH"}={};
- $Lang{$L}{"DoML"}=[];
- &Date_InitLists([$lang{"num_suff"},
- $lang{"num_word"}],
- \$Lang{$L}{"DoM"},"lc,sort,back,escape",
- [$Lang{$L}{"DoML"},
- \@tmp],
- [$Lang{$L}{"DoMH"},1]);
-
- @tmp=();
- foreach $tmp (keys %{ $Lang{$L}{"DoMH"} }) {
- $tmp2=$Lang{$L}{"DoMH"}{$tmp};
- if ($tmp2<6) {
- $Lang{$L}{"WoMH"}{$tmp} = $tmp2;
- push(@tmp,$tmp);
- }
- }
- foreach $tmp (@{ $Lang{$L}{"LastL"} }) {
- $Lang{$L}{"WoMH"}{$tmp} = -1;
- push(@tmp,$tmp);
- }
- &Date_InitStrings(\@tmp,\$Lang{$L}{"WoM"},
- "lc,sort,back,escape");
-
- # variables for AM or PM
- # AM = "(am)"
- # PM = "(pm)"
- # AmPm = "(am|pm)"
- # AMstr = "AM"
- # PMstr = "PM"
-
- &Date_InitStrings($lang{"am"},\$Lang{$L}{"AM"},"lc,sort,escape");
- &Date_InitStrings($lang{"pm"},\$Lang{$L}{"PM"},"lc,sort,escape");
- &Date_InitStrings([ @{$lang{"am"}},@{$lang{"pm"}} ],\$Lang{$L}{"AmPm"},
- "lc,back,sort,escape");
- $Lang{$L}{"AMstr"}=$lang{"am"}[0];
- $Lang{$L}{"PMstr"}=$lang{"pm"}[0];
-
- # variables for expressions used in parsing deltas
- # Yabb = "(?:y|yr|year|years)"
- # Mabb = similar for months
- # Wabb = similar for weeks
- # Dabb = similar for days
- # Habb = similar for hours
- # MNabb = similar for minutes
- # Sabb = similar for seconds
- # Repl = { "abb"=>"replacement" }
- # Whenever an abbreviation could potentially refer to two different
- # strings (M standing for Minutes or Months), the abbreviation must
- # be listed in Repl instead of in the appropriate Xabb values. This
- # only applies to abbreviations which are substrings of other values
- # (so there is no confusion between Mn and Month).
-
- &Date_InitStrings($lang{"years"} ,\$Lang{$L}{"Yabb"}, "lc,sort");
- &Date_InitStrings($lang{"months"} ,\$Lang{$L}{"Mabb"}, "lc,sort");
- &Date_InitStrings($lang{"weeks"} ,\$Lang{$L}{"Wabb"}, "lc,sort");
- &Date_InitStrings($lang{"days"} ,\$Lang{$L}{"Dabb"}, "lc,sort");
- &Date_InitStrings($lang{"hours"} ,\$Lang{$L}{"Habb"}, "lc,sort");
- &Date_InitStrings($lang{"minutes"},\$Lang{$L}{"MNabb"},"lc,sort");
- &Date_InitStrings($lang{"seconds"},\$Lang{$L}{"Sabb"}, "lc,sort");
- $Lang{$L}{"Repl"}={};
- &Date_InitHash($lang{"replace"},undef,"lc",$Lang{$L}{"Repl"});
-
- # variables for special dates that are offsets from now
- # Now = "(now|today)"
- # Offset = "(yesterday|tomorrow)"
- # OffsetH = { "yesterday"=>"-0:0:0:1:0:0:0",... ]
- # Times = "(noon|midnight)"
- # TimesH = { "noon"=>"12:00:00","midnight"=>"00:00:00" }
- # SepHM = hour/minute separator
- # SepMS = minute/second separator
- # SepSS = second/fraction separator
-
- $Lang{$L}{"TimesH"}={};
- &Date_InitHash($lang{"times"},
- \$Lang{$L}{"Times"},"lc,sort,back",
- $Lang{$L}{"TimesH"});
- &Date_InitStrings($lang{"now"},\$Lang{$L}{"Now"},"lc,sort");
- $Lang{$L}{"OffsetH"}={};
- &Date_InitHash($lang{"offset"},
- \$Lang{$L}{"Offset"},"lc,sort,back",
- $Lang{$L}{"OffsetH"});
- $Lang{$L}{"SepHM"}=$lang{"sephm"};
- $Lang{$L}{"SepMS"}=$lang{"sepms"};
- $Lang{$L}{"SepSS"}=$lang{"sepss"};
-
- # variables for time zones
- # zones = regular expression with all zone names (EST)
- # n2o = a hash of all parsable zone names with their offsets
- # tzones = reguar expression with all tzdata timezones (US/Eastern)
- # tz2z = hash of all tzdata timezones to full timezone (EST#EDT)
-
- $zonesrfc=
- "idlw -1200 ". # International Date Line West
- "nt -1100 ". # Nome
- "hst -1000 ". # Hawaii Standard
- "cat -1000 ". # Central Alaska
- "ahst -1000 ". # Alaska-Hawaii Standard
- "akst -0900 ". # Alaska Standard
- "yst -0900 ". # Yukon Standard
- "hdt -0900 ". # Hawaii Daylight
- "akdt -0800 ". # Alaska Daylight
- "ydt -0800 ". # Yukon Daylight
- "pst -0800 ". # Pacific Standard
- "pdt -0700 ". # Pacific Daylight
- "mst -0700 ". # Mountain Standard
- "mdt -0600 ". # Mountain Daylight
- "cst -0600 ". # Central Standard
- "cdt -0500 ". # Central Daylight
- "est -0500 ". # Eastern Standard
- "act -0500 ". # Brazil, Acre
- "sat -0400 ". # Chile
- "bot -0400 ". # Bolivia
- "amt -0400 ". # Brazil, Amazon
- "acst -0400 ". # Brazil, Acre Daylight
- "edt -0400 ". # Eastern Daylight
- "ast -0400 ". # Atlantic Standard
- #"nst -0330 ". # Newfoundland Standard nst=North Sumatra +0630
- "nft -0330 ". # Newfoundland
- #"gst -0300 ". # Greenland Standard gst=Guam Standard +1000
- #"bst -0300 ". # Brazil Standard bst=British Summer +0100
- "brt -0300 ". # Brazil Standard (official time)
- "brst -0300 ". # Brazil Standard
- "adt -0300 ". # Atlantic Daylight
- "art -0300 ". # Argentina
- "amst -0300 ". # Brazil, Amazon Daylight
- "ndt -0230 ". # Newfoundland Daylight
- "brst -0200 ". # Brazil Daylight (official time)
- "fnt -0200 ". # Brazil, Fernando de Noronha
- "at -0200 ". # Azores
- "wat -0100 ". # West Africa
- "fnst -0100 ". # Brazil, Fernando de Noronha Daylight
- "gmt +0000 ". # Greenwich Mean
- "ut +0000 ". # Universal
- "utc +0000 ". # Universal (Coordinated)
- "wet +0000 ". # Western European
- "cet +0100 ". # Central European
- "fwt +0100 ". # French Winter
- "met +0100 ". # Middle European
- "mez +0100 ". # Middle European
- "mewt +0100 ". # Middle European Winter
- "swt +0100 ". # Swedish Winter
- "bst +0100 ". # British Summer bst=Brazil standard -0300
- "gb +0100 ". # GMT with daylight savings
- "west +0000 ". # Western European Daylight
- "eet +0200 ". # Eastern Europe, USSR Zone 1
- "cest +0200 ". # Central European Summer
- "fst +0200 ". # French Summer
- "ist +0200 ". # Israel standard
- "mest +0200 ". # Middle European Summer
- "mesz +0200 ". # Middle European Summer
- "metdst +0200 ". # An alias for mest used by HP-UX
- "sast +0200 ". # South African Standard
- "sst +0200 ". # Swedish Summer sst=South Sumatra +0700
- "bt +0300 ". # Baghdad, USSR Zone 2
- "eest +0300 ". # Eastern Europe Summer
- "eetedt +0300 ". # Eastern Europe, USSR Zone 1
- "idt +0300 ". # Israel Daylight
- "msk +0300 ". # Moscow
- "eat +0300 ". # East Africa
- "it +0330 ". # Iran
- "zp4 +0400 ". # USSR Zone 3
- "msd +0400 ". # Moscow Daylight
- "zp5 +0500 ". # USSR Zone 4
- "ist +0530 ". # Indian Standard
- "zp6 +0600 ". # USSR Zone 5
- "novst +0600 ". # Novosibirsk time zone, Russia
- "nst +0630 ". # North Sumatra nst=Newfoundland Std -0330
- #"sst +0700 ". # South Sumatra, USSR Zone 6 sst=Swedish Summer +0200
- "javt +0700 ". # Java
- "hkt +0800 ". # Hong Kong
- "sgt +0800 ". # Singapore
- "cct +0800 ". # China Coast, USSR Zone 7
- "awst +0800 ". # Australian Western Standard
- "wst +0800 ". # West Australian Standard
- "pht +0800 ". # Asia Manila
- "kst +0900 ". # Republic of Korea
- "jst +0900 ". # Japan Standard, USSR Zone 8
- "rok +0900 ". # Republic of Korea
- "acst +0930 ". # Australian Central Standard
- "cast +0930 ". # Central Australian Standard
- "aest +1000 ". # Australian Eastern Standard
- "east +1000 ". # Eastern Australian Standard
- "gst +1000 ". # Guam Standard, USSR Zone 9 gst=Greenland Std -0300
- "acdt +1030 ". # Australian Central Daylight
- "cadt +1030 ". # Central Australian Daylight
- "aedt +1100 ". # Australian Eastern Daylight
- "eadt +1100 ". # Eastern Australian Daylight
- "idle +1200 ". # International Date Line East
- "nzst +1200 ". # New Zealand Standard
- "nzt +1200 ". # New Zealand
- "nzdt +1300 ". # New Zealand Daylight
- "z +0000 ".
- "a +0100 b +0200 c +0300 d +0400 e +0500 f +0600 g +0700 h +0800 ".
- "i +0900 k +1000 l +1100 m +1200 ".
- "n -0100 o -0200 p -0300 q -0400 r -0500 s -0600 t -0700 u -0800 ".
- "v -0900 w -1000 x -1100 y -1200";
-
- $Zone{"n2o"} = {};
- ($Zone{"zones"},%{ $Zone{"n2o"} })=
- &Date_Regexp($zonesrfc,"sort,lc,under,back",
- "keys");
-
- $tmp=
- "US/Pacific PST8PDT ".
- "US/Mountain MST7MDT ".
- "US/Central CST6CDT ".
- "US/Eastern EST5EDT ".
- "Canada/Pacific PST8PDT ".
- "Canada/Mountain MST7MDT ".
- "Canada/Central CST6CDT ".
- "Canada/Eastern EST5EDT";
-
- $Zone{"tz2z"} = {};
- ($Zone{"tzones"},%{ $Zone{"tz2z"} })=
- &Date_Regexp($tmp,"lc,under,back","keys");
- $Cnf{"TZ"}=&Date_TimeZone;
-
- # misc. variables
- # At = "(?:at)"
- # Of = "(?:in|of)"
- # On = "(?:on)"
- # Future = "(?:in)"
- # Later = "(?:later)"
- # Past = "(?:ago)"
- # Next = "(?:next)"
- # Prev = "(?:last|previous)"
-
- &Date_InitStrings($lang{"at"}, \$Lang{$L}{"At"}, "lc,sort");
- &Date_InitStrings($lang{"on"}, \$Lang{$L}{"On"}, "lc,sort");
- &Date_InitStrings($lang{"future"},\$Lang{$L}{"Future"}, "lc,sort");
- &Date_InitStrings($lang{"later"}, \$Lang{$L}{"Later"}, "lc,sort");
- &Date_InitStrings($lang{"past"}, \$Lang{$L}{"Past"}, "lc,sort");
- &Date_InitStrings($lang{"next"}, \$Lang{$L}{"Next"}, "lc,sort");
- &Date_InitStrings($lang{"prev"}, \$Lang{$L}{"Prev"}, "lc,sort");
- &Date_InitStrings($lang{"of"}, \$Lang{$L}{"Of"}, "lc,sort");
-
- # calc mode variables
- # Approx = "(?:approximately)"
- # Exact = "(?:exactly)"
- # Business = "(?:business)"
-
- &Date_InitStrings($lang{"exact"}, \$Lang{$L}{"Exact"}, "lc,sort");
- &Date_InitStrings($lang{"approx"}, \$Lang{$L}{"Approx"}, "lc,sort");
- &Date_InitStrings($lang{"business"},\$Lang{$L}{"Business"},"lc,sort");
-
- ############### END OF LANGUAGE INITIALIZATION
- }
-
- if ($Curr{"ResetWorkDay"}) {
- my($h1,$m1,$h2,$m2)=();
- if ($Cnf{"WorkDay24Hr"}) {
- ($Curr{"WDBh"},$Curr{"WDBm"})=(0,0);
- ($Curr{"WDEh"},$Curr{"WDEm"})=(24,0);
- $Curr{"WDlen"}=24*60;
- $Cnf{"WorkDayBeg"}="00:00";
- $Cnf{"WorkDayEnd"}="23:59";
-
- } else {
- confess "ERROR: Invalid WorkDayBeg in Date::Manip.\n"
- if (! (($h1,$m1)=&CheckTime($Cnf{"WorkDayBeg"})));
- $Cnf{"WorkDayBeg"}="$h1:$m1";
- confess "ERROR: Invalid WorkDayEnd in Date::Manip.\n"
- if (! (($h2,$m2)=&CheckTime($Cnf{"WorkDayEnd"})));
- $Cnf{"WorkDayEnd"}="$h2:$m2";
-
- ($Curr{"WDBh"},$Curr{"WDBm"})=($h1,$m1);
- ($Curr{"WDEh"},$Curr{"WDEm"})=($h2,$m2);
-
- # Work day length = h1:m1 or 0:len (len minutes)
- $h1=$h2-$h1;
- $m1=$m2-$m1;
- if ($m1<0) {
- $h1--;
- $m1+=60;
- }
- $Curr{"WDlen"}=$h1*60+$m1;
- }
- $Curr{"ResetWorkDay"}=0;
- }
-
- # current time
- my($s,$mn,$h,$d,$m,$y,$wday,$yday,$isdst,$ampm,$wk)=();
- if ($Cnf{"ForceDate"}=~
- /^(\d{4})-(\d{2})-(\d{2})-(\d{2}):(\d{2}):(\d{2})$/) {
- ($y,$m,$d,$h,$mn,$s)=($1,$2,$3,$4,$5,$6);
- } else {
- ($s,$mn,$h,$d,$m,$y,$wday,$yday,$isdst)=localtime(time);
- $y+=1900;
- $m++;
- }
- &Date_DateCheck(\$y,\$m,\$d,\$h,\$mn,\$s,\$ampm,\$wk);
- $Curr{"Y"}=$y;
- $Curr{"M"}=$m;
- $Curr{"D"}=$d;
- $Curr{"H"}=$h;
- $Curr{"Mn"}=$mn;
- $Curr{"S"}=$s;
- $Curr{"AmPm"}=$ampm;
- $Curr{"Now"}=&Date_Join($y,$m,$d,$h,$mn,$s);
-
- $Curr{"Debug"}=$Curr{"DebugVal"};
-
- # If we're in array context, let's return a list of config variables
- # that could be passed to Date_Init to get the same state as we're
- # currently in.
- if (wantarray) {
- # Some special variables that have to be in a specific order
- my(@special)=qw(IgnoreGlobalCnf GlobalCnf PersonalCnf PersonalCnfPath);
- my(%tmp)=map { $_,1 } @special;
- my(@tmp,$key,$val);
- foreach $key (@special) {
- $val=$Cnf{$key};
- push(@tmp,"$key=$val");
- }
- foreach $key (keys %Cnf) {
- next if (exists $tmp{$key});
- $val=$Cnf{$key};
- push(@tmp,"$key=$val");
- }
- return @tmp;
- }
- return ();
-}
-
-sub ParseDateString {
- print "DEBUG: ParseDateString\n" if ($Curr{"Debug"} =~ /trace/);
- local($_)=@_;
- return "" if (! $_);
-
- my($y,$m,$d,$h,$mn,$s,$i,$wofm,$dofw,$wk,$tmp,$z,$num,$err,$iso,$ampm)=();
- my($date,$z2,$delta,$from,$falsefrom,$to,$which,$midnight)=();
-
- # We only need to reinitialize if we have to determine what NOW is.
- &Date_Init() if (! $Curr{"InitDone"} or $Cnf{"UpdateCurrTZ"});
-
- my($L)=$Cnf{"Language"};
- my($type)=$Cnf{"DateFormat"};
-
- # Mode is set in DateCalc. ParseDate only overrides it if the string
- # contains a mode.
- if ($Lang{$L}{"Exact"} &&
- s/$Lang{$L}{"Exact"}//) {
- $Curr{"Mode"}=0;
- } elsif ($Lang{$L}{"Approx"} &&
- s/$Lang{$L}{"Approx"}//) {
- $Curr{"Mode"}=1;
- } elsif ($Lang{$L}{"Business"} &&
- s/$Lang{$L}{"Business"}//) {
- $Curr{"Mode"}=2;
- } elsif (! exists $Curr{"Mode"}) {
- $Curr{"Mode"}=0;
- }
-
- # Unfortunately, some deltas can be parsed as dates. An example is
- # 1 second == 1 2nd == 1 2
- # But, some dates can be parsed as deltas. The most important being:
- # 1998010101:00:00
- # We'll check to see if a "date" can be parsed as a delta. If so, we'll
- # assume that it is a delta (since they are much simpler, it is much
- # less likely that we'll mistake a delta for a date than vice versa)
- # unless it is an ISO-8601 date.
- #
- # This is important because we are using DateCalc to test whether a
- # string is a date or a delta. Dates are tested first, so we need to
- # be able to pass a delta into this routine and have it correctly NOT
- # interpreted as a date.
- #
- # We will insist that the string contain something other than digits and
- # colons so that the following will get correctly interpreted as a date
- # rather than a delta:
- # 12:30
- # 19980101
-
- $delta="";
- $delta=&ParseDateDelta($_) if (/[^:0-9]/);
-
- # Put parse in a simple loop for an easy exit.
- PARSE: {
- my(@tmp)=&Date_Split($_);
- if (@tmp) {
- ($y,$m,$d,$h,$mn,$s)=@tmp;
- last PARSE;
- }
-
- # Fundamental regular expressions
-
- my($month)=$Lang{$L}{"Month"}; # (jan|january|...)
- my(%month)=%{ $Lang{$L}{"MonthH"} }; # { jan=>1, ... }
- my($week)=$Lang{$L}{"Week"}; # (mon|monday|...)
- my(%week)=%{ $Lang{$L}{"WeekH"} }; # { mon=>1, monday=>1, ... }
- my($wom)=$Lang{$L}{"WoM"}; # (1st|...|fifth|last)
- my(%wom)=%{ $Lang{$L}{"WoMH"} }; # { 1st=>1,... fifth=>5,last=>-1 }
- my($dom)=$Lang{$L}{"DoM"}; # (1st|first|...31st)
- my(%dom)=%{ $Lang{$L}{"DoMH"} }; # { 1st=>1, first=>1, ... }
- my($ampmexp)=$Lang{$L}{"AmPm"}; # (am|pm)
- my($timeexp)=$Lang{$L}{"Times"}; # (noon|midnight)
- my($now)=$Lang{$L}{"Now"}; # (now|today)
- my($offset)=$Lang{$L}{"Offset"}; # (yesterday|tomorrow)
- my($zone)=$Zone{"zones"} . '(?:\s+|$)'; # (edt|est|...)\s+
- my($day)='\s*'.$Lang{$L}{"Dabb"}; # \s*(?:d|day|days)
- my($mabb)='\s*'.$Lang{$L}{"Mabb"}; # \s*(?:mon|month|months)
- my($wkabb)='\s*'.$Lang{$L}{"Wabb"}; # \s*(?:w|wk|week|weeks)
- my($next)='\s*'.$Lang{$L}{"Next"}; # \s*(?:next)
- my($prev)='\s*'.$Lang{$L}{"Prev"}; # \s*(?:last|previous)
- my($past)='\s*'.$Lang{$L}{"Past"}; # \s*(?:ago)
- my($future)='\s*'.$Lang{$L}{"Future"}; # \s*(?:in)
- my($later)='\s*'.$Lang{$L}{"Later"}; # \s*(?:later)
- my($at)=$Lang{$L}{"At"}; # (?:at)
- my($of)='\s*'.$Lang{$L}{"Of"}; # \s*(?:in|of)
- my($on)='(?:\s*'.$Lang{$L}{"On"}.'\s*|\s+)';
- # \s*(?:on)\s* or \s+
- my($last)='\s*'.$Lang{$L}{"Last"}; # \s*(?:last)
- my($hm)=$Lang{$L}{"SepHM"}; # :
- my($ms)=$Lang{$L}{"SepMS"}; # :
- my($ss)=$Lang{$L}{"SepSS"}; # .
-
- # Other regular expressions
-
- my($D4)='(\d{4})'; # 4 digits (yr)
- my($YY)='(\d{4}|\d{2})'; # 2 or 4 digits (yr)
- my($DD)='(\d{2})'; # 2 digits (mon/day/hr/min/sec)
- my($D) ='(\d{1,2})'; # 1 or 2 digit (mon/day/hr)
- my($FS)="(?:$ss\\d+)?"; # fractional secs
- my($sep)='[\/.-]'; # non-ISO8601 m/d/yy separators
- # absolute time zone +0700 (GMT)
- my($hzone)='(?:[0-1][0-9]|2[0-3])'; # 00 - 23
- my($mzone)='(?:[0-5][0-9])'; # 00 - 59
- my($zone2)='(?:\s*([+-](?:'."$hzone$mzone|$hzone:$mzone|$hzone))".
- # +0700 +07:00 -07
- '(?:\s*\([^)]+\))?)'; # (GMT)
-
- # A regular expression for the time EXCEPT for the hour part
- my($mnsec)="$hm$DD(?:$ms$DD$FS)?(?:\\s*$ampmexp)?";
-
- # A special regular expression for /YYYY:HH:MN:SS used by Apache
- my($apachetime)='(/\d{4}):' . "$DD$hm$DD$ms$DD";
-
- my($time)="";
- $ampm="";
- $date="";
-
- # Substitute all special time expressions.
- if (/(^|[^a-z])$timeexp($|[^a-z])/i) {
- $tmp=$2;
- $tmp=$Lang{$L}{"TimesH"}{lc($tmp)};
- s/(^|[^a-z])$timeexp($|[^a-z])/$1 $tmp $3/i;
- }
-
- # Remove some punctuation
- s/[,]/ /g;
-
- # Make sure that ...7EST works (i.e. a timezone immediately following
- # a digit.
- s/(\d)$zone(\s+|$|[0-9])/$1 $2$3/i;
- $zone = '\s+'.$zone;
-
- # Remove the time
- $iso=1;
- $midnight=0;
- $from="24${hm}00(?:${ms}00)?";
- $falsefrom="${hm}24${ms}00"; # Don't trap XX:24:00
- $to="00${hm}00${ms}00";
- $midnight=1 if (!/$falsefrom/ && s/$from/$to/);
-
- $h=$mn=$s=0;
- if (/$D$mnsec/i || /$ampmexp/i) {
- $iso=0;
- $tmp=0;
- $tmp=1 if (/$mnsec$zone2?\s*$/i); # or /$mnsec$zone/ ??
- $tmp=0 if (/$ampmexp/i);
- if (s/$apachetime$zone()/$1 /i ||
- s/$apachetime$zone2?/$1 /i ||
- s/(^|[^a-z])$at\s*$D$mnsec$zone()/$1 /i ||
- s/(^|[^a-z])$at\s*$D$mnsec$zone2?/$1 /i ||
- s/(^|[^0-9])(\d)$mnsec$zone()/$1 /i ||
- s/(^|[^0-9])(\d)$mnsec$zone2?/$1 /i ||
- (s/(t)$D$mnsec$zone()/$1 /i and (($iso=-$tmp) || 1)) ||
- (s/(t)$D$mnsec$zone2?/$1 /i and (($iso=-$tmp) || 1)) ||
- (s/()$DD$mnsec$zone()/ /i and (($iso=$tmp) || 1)) ||
- (s/()$DD$mnsec$zone2?/ /i and (($iso=$tmp) || 1)) ||
- s/(^|$at\s*|\s+)$D()()\s*$ampmexp$zone()/ /i ||
- s/(^|$at\s*|\s+)$D()()\s*$ampmexp$zone2?/ /i ||
- 0
- ) {
- ($h,$mn,$s,$ampm,$z,$z2)=($2,$3,$4,$5,$6,$7);
- if (defined ($z)) {
- if ($z =~ /^[+-]\d{2}:\d{2}$/) {
- $z=~ s/://;
- } elsif ($z =~ /^[+-]\d{2}$/) {
- $z .= "00";
- }
- }
- $time=1;
- &Date_TimeCheck(\$h,\$mn,\$s,\$ampm);
- $y=$m=$d="";
- # We're going to be calling TimeCheck again below (when we check the
- # final date), so get rid of $ampm so that we don't have an error
- # due to "15:30:00 PM". It'll get reset below.
- $ampm="";
- if (/^\s*$/) {
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- last PARSE;
- }
- }
- }
- $time=0 if ($time ne "1");
- s/\s+$//;
- s/^\s+//;
-
- # dateTtime ISO 8601 formats
- my($orig)=$_;
- s/t$//i if ($iso<0);
-
- # Parse ISO 8601 dates now (which may still have a zone stuck to it).
- if ( ($iso && /^([0-9-]+(?:W[0-9-]+)?)$zone?$/i) ||
- ($iso && /^([0-9-]+(?:W[0-9-]+)?)$zone2?$/i) ||
- ($iso && /^([0-9-]+(?:T[0-9-]+)?)$zone?$/i) ||
- ($iso && /^([0-9-]+(?:T[0-9-]+)?)$zone2?$/i) ||
- 0) {
-
- # ISO 8601 dates
- ($_,$z,$z2) = ($1,$2);
- s,-, ,g; # Change all ISO8601 seps to spaces
- s/^\s+//;
- s/\s+$//;
-
- if (/^$D4\s*$DD\s*$DD\s*t?$DD(?:$DD(?:$DD(\d*))?)?$/i ||
- /^$DD\s+$DD\s*$DD\s*t?$DD(?:$DD(?:$DD(\d*))?)?$/i ||
- 0
- ) {
- # ISO 8601 Dates with times
- # YYYYMMDDHHMNSSFFFF...
- # YYYYMMDDHHMNSS
- # YYYYMMDDHHMN
- # YYYYMMDDHH
- # YY MMDDHHMNSSFFFF...
- # YY MMDDHHMNSS
- # YY MMDDHHMN
- # YY MMDDHH
- ($y,$m,$d,$h,$mn,$s,$tmp)=($1,$2,$3,$4,$5,$6,$7);
- if ($h==24 && (! defined $mn || $mn==0) && (! defined $s || $s==0)) {
- $h=0;
- $midnight=1;
- }
- $z = "" if (! defined $h);
- return "" if ($time && defined $h);
- last PARSE;
-
- } elsif (/^$D4(?:\s*$DD(?:\s*$DD)?)?$/ ||
- /^$DD(?:\s+$DD(?:\s*$DD)?)?$/) {
- # ISO 8601 Dates
- # YYYYMMDD
- # YYYYMM
- # YYYY
- # YY MMDD
- # YY MM
- # YY
- ($y,$m,$d)=($1,$2,$3);
- last PARSE;
-
- } elsif (/^$YY\s+$D\s+$D/) {
- # YY-M-D
- ($y,$m,$d)=($1,$2,$3);
- last PARSE;
-
- } elsif (/^$YY\s*W$DD\s*(\d)?$/i) {
- # YY-W##-D
- ($y,$wofm,$dofw)=($1,$2,$3);
- ($y,$m,$d)=&Date_NthWeekOfYear($y,$wofm,$dofw);
- last PARSE;
-
- } elsif (/^$D4\s*(\d{3})$/ ||
- /^$DD\s*(\d{3})$/) {
- # YYDOY
- ($y,$which)=($1,$2);
- ($y,$m,$d)=&Date_NthDayOfYear($y,$which);
- last PARSE;
-
- } elsif ($iso<0) {
- # We confused something like 1999/August12:00:00
- # with a dateTtime format
- $_=$orig;
-
- } else {
- return "";
- }
- }
-
- # All deltas that are not ISO-8601 dates are NOT dates.
- return "" if ($Curr{"InCalc"} && $delta);
- if ($delta) {
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- return &DateCalc_DateDelta($Curr{"Now"},$delta);
- }
-
- # Check for some special types of dates (next, prev)
- foreach $from (keys %{ $Lang{$L}{"Repl"} }) {
- $to=$Lang{$L}{"Repl"}{$from};
- s/(^|[^a-z])$from($|[^a-z])/$1$to$2/i;
- }
- if (/$wom/i || /$future/i || /$later/i || /$past/i ||
- /$next/i || /$prev/i || /^$week$/i || /$wkabb/i) {
- $tmp=0;
-
- if (/^$wom\s*$week$of\s*$month\s*$YY?$/i) {
- # last friday in October 95
- ($wofm,$dofw,$m,$y)=($1,$2,$3,$4);
- # fix $m, $y
- return "" if (&Date_DateCheck(\$y,\$m,\$d,\$h,\$mn,\$s,\$ampm,\$wk));
- $dofw=$week{lc($dofw)};
- $wofm=$wom{lc($wofm)};
- # Get the first day of the month
- $date=&Date_Join($y,$m,1,$h,$mn,$s);
- if ($wofm==-1) {
- $date=&DateCalc_DateDelta($date,"+0:1:0:0:0:0:0",\$err,0);
- $date=&Date_GetPrev($date,$dofw,0);
- } else {
- for ($i=0; $i<$wofm; $i++) {
- if ($i==0) {
- $date=&Date_GetNext($date,$dofw,1);
- } else {
- $date=&Date_GetNext($date,$dofw,0);
- }
- }
- }
- last PARSE;
-
- } elsif (/^$last$day$of\s*$month(?:$of?\s*$YY)?/i) {
- # last day in month
- ($m,$y)=($1,$2);
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- $y=&Date_FixYear($y) if (! defined $y or length($y)<4);
- $m=$month{lc($m)};
- $d=&Date_DaysInMonth($m,$y);
- last PARSE;
-
- } elsif (/^$week$/i) {
- # friday
- ($dofw)=($1);
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- $date=&Date_GetPrev($Curr{"Now"},$Cnf{"FirstDay"},1);
- $date=&Date_GetNext($date,$dofw,1,$h,$mn,$s);
- last PARSE;
-
- } elsif (/^$next\s*$week$/i) {
- # next friday
- ($dofw)=($1);
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- $date=&Date_GetNext($Curr{"Now"},$dofw,0,$h,$mn,$s);
- last PARSE;
-
- } elsif (/^$prev\s*$week$/i) {
- # last friday
- ($dofw)=($1);
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- $date=&Date_GetPrev($Curr{"Now"},$dofw,0,$h,$mn,$s);
- last PARSE;
-
- } elsif (/^$next$wkabb$/i) {
- # next week
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- $date=&DateCalc_DateDelta($Curr{"Now"},"+0:0:1:0:0:0:0",\$err,0);
- $date=&Date_SetTime($date,$h,$mn,$s) if (defined $h);
- last PARSE;
- } elsif (/^$prev$wkabb$/i) {
- # last week
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- $date=&DateCalc_DateDelta($Curr{"Now"},"-0:0:1:0:0:0:0",\$err,0);
- $date=&Date_SetTime($date,$h,$mn,$s) if (defined $h);
- last PARSE;
-
- } elsif (/^$next$mabb$/i) {
- # next month
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- $date=&DateCalc_DateDelta($Curr{"Now"},"+0:1:0:0:0:0:0",\$err,0);
- $date=&Date_SetTime($date,$h,$mn,$s) if (defined $h);
- last PARSE;
- } elsif (/^$prev$mabb$/i) {
- # last month
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- $date=&DateCalc_DateDelta($Curr{"Now"},"-0:1:0:0:0:0:0",\$err,0);
- $date=&Date_SetTime($date,$h,$mn,$s) if (defined $h);
- last PARSE;
-
- } elsif (/^$future\s*(\d+)$day$/i ||
- /^(\d+)$day$later$/i) {
- # in 2 days
- # 2 days later
- ($num)=($1);
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- $date=&DateCalc_DateDelta($Curr{"Now"},"+0:0:0:$num:0:0:0",
- \$err,0);
- $date=&Date_SetTime($date,$h,$mn,$s) if (defined $h);
- last PARSE;
- } elsif (/^(\d+)$day$past$/i) {
- # 2 days ago
- ($num)=($1);
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- $date=&DateCalc_DateDelta($Curr{"Now"},"-0:0:0:$num:0:0:0",
- \$err,0);
- $date=&Date_SetTime($date,$h,$mn,$s) if (defined $h);
- last PARSE;
-
- } elsif (/^$future\s*(\d+)$wkabb$/i ||
- /^(\d+)$wkabb$later$/i) {
- # in 2 weeks
- # 2 weeks later
- ($num)=($1);
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- $date=&DateCalc_DateDelta($Curr{"Now"},"+0:0:$num:0:0:0:0",
- \$err,0);
- $date=&Date_SetTime($date,$h,$mn,$s) if (defined $h);
- last PARSE;
- } elsif (/^(\d+)$wkabb$past$/i) {
- # 2 weeks ago
- ($num)=($1);
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- $date=&DateCalc_DateDelta($Curr{"Now"},"-0:0:$num:0:0:0:0",
- \$err,0);
- $date=&Date_SetTime($date,$h,$mn,$s) if (defined $h);
- last PARSE;
-
- } elsif (/^$future\s*(\d+)$mabb$/i ||
- /^(\d+)$mabb$later$/i) {
- # in 2 months
- # 2 months later
- ($num)=($1);
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- $date=&DateCalc_DateDelta($Curr{"Now"},"+0:$num:0:0:0:0:0",
- \$err,0);
- $date=&Date_SetTime($date,$h,$mn,$s) if (defined $h);
- last PARSE;
- } elsif (/^(\d+)$mabb$past$/i) {
- # 2 months ago
- ($num)=($1);
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- $date=&DateCalc_DateDelta($Curr{"Now"},"-0:$num:0:0:0:0:0",
- \$err,0);
- $date=&Date_SetTime($date,$h,$mn,$s) if (defined $h);
- last PARSE;
-
- } elsif (/^$week$future\s*(\d+)$wkabb$/i ||
- /^$week\s*(\d+)$wkabb$later$/i) {
- # friday in 2 weeks
- # friday 2 weeks later
- ($dofw,$num)=($1,$2);
- $tmp="+";
- } elsif (/^$week\s*(\d+)$wkabb$past$/i) {
- # friday 2 weeks ago
- ($dofw,$num)=($1,$2);
- $tmp="-";
- } elsif (/^$future\s*(\d+)$wkabb$on$week$/i ||
- /^(\d+)$wkabb$later$on$week$/i) {
- # in 2 weeks on friday
- # 2 weeks later on friday
- ($num,$dofw)=($1,$2);
- $tmp="+"
- } elsif (/^(\d+)$wkabb$past$on$week$/i) {
- # 2 weeks ago on friday
- ($num,$dofw)=($1,$2);
- $tmp="-";
- } elsif (/^$week\s*$wkabb$/i) {
- # monday week (British date: in 1 week on monday)
- $dofw=$1;
- $num=1;
- $tmp="+";
- } elsif (/^$now\s*$wkabb$/i) {
- # today week (British date: 1 week from today)
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- $date=&DateCalc_DateDelta($Curr{"Now"},"+0:0:1:0:0:0:0",\$err,0);
- $date=&Date_SetTime($date,$h,$mn,$s) if (defined $h);
- last PARSE;
- } elsif (/^$offset\s*$wkabb$/i) {
- # tomorrow week (British date: 1 week from tomorrow)
- ($offset)=($1);
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- $offset=$Lang{$L}{"OffsetH"}{lc($offset)};
- $date=&DateCalc_DateDelta($Curr{"Now"},$offset,\$err,0);
- $date=&DateCalc_DateDelta($date,"+0:0:1:0:0:0:0",\$err,0);
- if ($time) {
- return ""
- if (&Date_DateCheck(\$y,\$m,\$d,\$h,\$mn,\$s,\$ampm,\$wk));
- $date=&Date_SetTime($date,$h,$mn,$s);
- }
- last PARSE;
- }
-
- if ($tmp) {
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- $date=&DateCalc_DateDelta($Curr{"Now"},
- $tmp . "0:0:$num:0:0:0:0",\$err,0);
- $date=&Date_GetPrev($date,$Cnf{"FirstDay"},1);
- $date=&Date_GetNext($date,$dofw,1,$h,$mn,$s);
- last PARSE;
- }
- }
-
- # Change (2nd, second) to 2
- $tmp=0;
- if (/(^|[^a-z0-9])$dom($|[^a-z0-9])/i) {
- if (/^\s*$dom\s*$/) {
- ($d)=($1);
- $d=$dom{lc($d)};
- $m=$Curr{"M"};
- last PARSE;
- }
- my $from = $2;
- my $to = $dom{ lc($from) };
- s/(^|[^a-z])$from($|[^a-z])/$1 $to $2/i;
- s/^\s+//;
- s/\s+$//;
- }
-
- # Another set of special dates (Nth week)
- if (/^$D\s*$week(?:$of?\s*$YY)?$/i) {
- # 22nd sunday in 1996
- ($which,$dofw,$y)=($1,$2,$3);
- $y=$Curr{"Y"} if (! $y);
- $y--; # previous year
- $tmp=&Date_GetNext("$y-12-31",$dofw,0);
- if ($which>1) {
- $tmp=&DateCalc_DateDelta($tmp,"+0:0:".($which-1).":0:0:0:0",\$err,0);
- }
- ($y,$m,$d)=(&Date_Split($tmp, 1))[0..2];
- last PARSE;
- } elsif (/^$week$wkabb\s*$D(?:$of?\s*$YY)?$/i ||
- /^$week\s*$D$wkabb(?:$of?\s*$YY)?$/i) {
- # sunday week 22 in 1996
- # sunday 22nd week in 1996
- ($dofw,$which,$y)=($1,$2,$3);
- ($y,$m,$d)=&Date_NthWeekOfYear($y,$which,$dofw);
- last PARSE;
- }
-
- # Get rid of day of week
- if (/(^|[^a-z])$week($|[^a-z])/i) {
- $wk=$2;
- (s/(^|[^a-z])$week,/$1 /i) ||
- s/(^|[^a-z])$week($|[^a-z])/$1 $3/i;
- s/^\s+//;
- s/\s+$//;
- }
-
- {
- # So that we can handle negative epoch times, let's convert
- # things like "epoch -" to "epochNEGATIVE " before we strip out
- # the $sep chars, which include '-'.
- s,epoch\s*-,epochNEGATIVE ,g;
-
- # Non-ISO8601 dates
- s,\s*$sep\s*, ,g; # change all non-ISO8601 seps to spaces
- s,^\s*,,; # remove leading/trailing space
- s,\s*$,,;
-
- if (/^$D\s+$D(?:\s+$YY)?$/) {
- # MM DD YY (DD MM YY non-US)
- ($m,$d,$y)=($1,$2,$3);
- ($m,$d)=($d,$m) if ($type ne "US");
- last PARSE;
-
- } elsif (/^$D4\s*$D\s*$D$/) {
- # YYYY MM DD
- ($y,$m,$d)=($1,$2,$3);
- last PARSE;
-
- } elsif (s/(^|[^a-z])$month($|[^a-z])/$1 $3/i) {
- ($m)=($2);
-
- if (/^\s*$D(?:\s+$YY)?\s*$/) {
- # mmm DD YY
- # DD mmm YY
- # DD YY mmm
- ($d,$y)=($1,$2);
- last PARSE;
-
- } elsif (/^\s*$D$D4\s*$/) {
- # mmm DD YYYY
- # DD mmm YYYY
- # DD YYYY mmm
- ($d,$y)=($1,$2);
- last PARSE;
-
- } elsif (/^\s*$D4\s*$D\s*$/) {
- # mmm YYYY DD
- # YYYY mmm DD
- # YYYY DD mmm
- ($y,$d)=($1,$2);
- last PARSE;
-
- } elsif (/^\s*$D4\s*$/) {
- # mmm YYYY
- # YYYY mmm
- ($y,$d)=($1,1);
- last PARSE;
-
- } else {
- return "";
- }
-
- } elsif (/^epochNEGATIVE (\d+)$/) {
- $s=$1;
- $date=&DateCalc("1970-01-01 00:00 GMT","-0:0:$s");
- } elsif (/^epoch\s*(\d+)$/i) {
- $s=$1;
- $date=&DateCalc("1970-01-01 00:00 GMT","+0:0:$s");
-
- } elsif (/^$now$/i) {
- # now, today
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- $date=$Curr{"Now"};
- if ($time) {
- return ""
- if (&Date_DateCheck(\$y,\$m,\$d,\$h,\$mn,\$s,\$ampm,\$wk));
- $date=&Date_SetTime($date,$h,$mn,$s);
- }
- last PARSE;
-
- } elsif (/^$offset$/i) {
- # yesterday, tomorrow
- ($offset)=($1);
- &Date_Init() if (! $Cnf{"UpdateCurrTZ"});
- $offset=$Lang{$L}{"OffsetH"}{lc($offset)};
- $date=&DateCalc_DateDelta($Curr{"Now"},$offset,\$err,0);
- if ($time) {
- return ""
- if (&Date_DateCheck(\$y,\$m,\$d,\$h,\$mn,\$s,\$ampm,\$wk));
- $date=&Date_SetTime($date,$h,$mn,$s);
- }
- last PARSE;
-
- } else {
- return "";
- }
- }
- }
-
- if (! $date) {
- return "" if (&Date_DateCheck(\$y,\$m,\$d,\$h,\$mn,\$s,\$ampm,\$wk));
- $date=&Date_Join($y,$m,$d,$h,$mn,$s);
- }
- $date=&Date_ConvTZ($date,$z);
- if ($midnight) {
- $date=&DateCalc_DateDelta($date,"+0:0:0:1:0:0:0");
- }
- return $date;
-}
-
-sub ParseDate {
- print "DEBUG: ParseDate\n" if ($Curr{"Debug"} =~ /trace/);
- &Date_Init() if (! $Curr{"InitDone"});
- my($args,@args,@a,$ref,$date)=();
- @a=@_;
-
- # @a : is the list of args to ParseDate. Currently, only one argument
- # is allowed and it must be a scalar (or a reference to a scalar)
- # or a reference to an array.
-
- if ($#a!=0) {
- print "ERROR: Invalid number of arguments to ParseDate.\n";
- return "";
- }
- $args=$a[0];
- $ref=ref $args;
- if (! $ref) {
- return $args if (&Date_Split($args));
- @args=($args);
- } elsif ($ref eq "ARRAY") {
- @args=@$args;
- } elsif ($ref eq "SCALAR") {
- return $$args if (&Date_Split($$args));
- @args=($$args);
- } else {
- print "ERROR: Invalid arguments to ParseDate.\n";
- return "";
- }
- @a=@args;
-
- # @args : a list containing all the arguments (dereferenced if appropriate)
- # @a : a list containing all the arguments currently being examined
- # $ref : nil, "SCALAR", or "ARRAY" depending on whether a scalar, a
- # reference to a scalar, or a reference to an array was passed in
- # $args : the scalar or refererence passed in
-
- PARSE: while($#a>=0) {
- $date=join(" ",@a);
- $date=&ParseDateString($date);
- last if ($date);
- pop(@a);
- } # PARSE
-
- splice(@args,0,$#a + 1);
- @$args= @args if (defined $ref and $ref eq "ARRAY");
- $date;
-}
-
-sub Date_Cmp {
- my($D1,$D2)=@_;
- my($date1)=&ParseDateString($D1);
- my($date2)=&ParseDateString($D2);
- return $date1 cmp $date2;
-}
-
-# **NOTE**
-# The calc routines all call parse routines, so it is never necessary to
-# call Date_Init in the calc routines.
-sub DateCalc {
- print "DEBUG: DateCalc\n" if ($Curr{"Debug"} =~ /trace/);
- my($D1,$D2,@arg)=@_;
- my($ref,$err,$errref,$mode)=();
-
- $errref=shift(@arg);
- $ref=0;
- if (defined $errref) {
- if (ref $errref) {
- $mode=shift(@arg);
- $ref=1;
- } else {
- $mode=$errref;
- $errref="";
- }
- }
-
- my(@date,@delta,$ret,$tmp,$old)=();
-
- if (defined $mode and $mode>=0 and $mode<=3) {
- $Curr{"Mode"}=$mode;
- } else {
- $Curr{"Mode"}=0;
- }
-
- $old=$Curr{"InCalc"};
- $Curr{"InCalc"}=1;
-
- if ($tmp=&ParseDateString($D1)) {
- # If we've already parsed the date, we don't want to do it a second
- # time (so we don't convert timezones twice).
- if (&Date_Split($D1)) {
- push(@date,$D1);
- } else {
- push(@date,$tmp);
- }
- } elsif ($tmp=&ParseDateDelta($D1)) {
- push(@delta,$tmp);
- } else {
- $$errref=1 if ($ref);
- return;
- }
-
- if ($tmp=&ParseDateString($D2)) {
- if (&Date_Split($D2)) {
- push(@date,$D2);
- } else {
- push(@date,$tmp);
- }
- } elsif ($tmp=&ParseDateDelta($D2)) {
- push(@delta,$tmp);
- } else {
- $$errref=2 if ($ref);
- return;
- }
- $mode=$Curr{"Mode"};
- $Curr{"InCalc"}=$old;
-
- if ($#date==1) {
- $ret=&DateCalc_DateDate(@date,$mode);
- } elsif ($#date==0) {
- $ret=&DateCalc_DateDelta(@date,@delta,\$err,$mode);
- $$errref=$err if ($ref);
- } else {
- $ret=&DateCalc_DeltaDelta(@delta,$mode);
- }
- $ret;
-}
-
-sub ParseDateDelta {
- print "DEBUG: ParseDateDelta\n" if ($Curr{"Debug"} =~ /trace/);
- my($args,@args,@a,$ref)=();
- local($_)=();
- @a=@_;
-
- # @a : is the list of args to ParseDateDelta. Currently, only one argument
- # is allowed and it must be a scalar (or a reference to a scalar)
- # or a reference to an array.
-
- if ($#a!=0) {
- print "ERROR: Invalid number of arguments to ParseDateDelta.\n";
- return "";
- }
- $args=$a[0];
- $ref=ref $args;
- if (! $ref) {
- @args=($args);
- } elsif ($ref eq "ARRAY") {
- @args=@$args;
- } elsif ($ref eq "SCALAR") {
- @args=($$args);
- } else {
- print "ERROR: Invalid arguments to ParseDateDelta.\n";
- return "";
- }
- @a=@args;
-
- # @args : a list containing all the arguments (dereferenced if appropriate)
- # @a : a list containing all the arguments currently being examined
- # $ref : nil, "SCALAR", or "ARRAY" depending on whether a scalar, a
- # reference to a scalar, or a reference to an array was passed in
- # $args : the scalar or refererence passed in
-
- my(@colon,@delta,$delta,$dir,$colon,$sign,$val)=();
- my($len,$tmp,$tmp2,$tmpl)=();
- my($from,$to)=();
- my($workweek)=$Cnf{"WorkWeekEnd"}-$Cnf{"WorkWeekBeg"}+1;
-
- &Date_Init() if (! $Curr{"InitDone"});
- # A sign can be a sequence of zero or more + and - signs, this
- # allows for deltas like '+ -2 days'.
- my($signexp)='((?:[+-]\s*)*)';
- my($numexp)='(\d+)';
- my($exp1)="(?: \\s* $signexp \\s* $numexp \\s*)";
- my($yexp,$mexp,$wexp,$dexp,$hexp,$mnexp,$sexp,$i)=();
- $yexp=$mexp=$wexp=$dexp=$hexp=$mnexp=$sexp="()()";
- $yexp ="(?: $exp1 ". $Lang{$Cnf{"Language"}}{"Yabb"} .")?";
- $mexp ="(?: $exp1 ". $Lang{$Cnf{"Language"}}{"Mabb"} .")?";
- $wexp ="(?: $exp1 ". $Lang{$Cnf{"Language"}}{"Wabb"} .")?";
- $dexp ="(?: $exp1 ". $Lang{$Cnf{"Language"}}{"Dabb"} .")?";
- $hexp ="(?: $exp1 ". $Lang{$Cnf{"Language"}}{"Habb"} .")?";
- $mnexp="(?: $exp1 ". $Lang{$Cnf{"Language"}}{"MNabb"}.")?";
- $sexp ="(?: $exp1 ". $Lang{$Cnf{"Language"}}{"Sabb"} ."?)?";
- my($future)=$Lang{$Cnf{"Language"}}{"Future"};
- my($later)=$Lang{$Cnf{"Language"}}{"Later"};
- my($past)=$Lang{$Cnf{"Language"}}{"Past"};
-
- $delta="";
- PARSE: while (@a) {
- $_ = join(" ", grep {defined;} @a);
- s/\s+$//;
- last if ($_ eq "");
-
- # Mode is set in DateCalc. ParseDateDelta only overrides it if the
- # string contains a mode.
- if ($Lang{$Cnf{"Language"}}{"Exact"} &&
- s/$Lang{$Cnf{"Language"}}{"Exact"}//) {
- $Curr{"Mode"}=0;
- } elsif ($Lang{$Cnf{"Language"}}{"Approx"} &&
- s/$Lang{$Cnf{"Language"}}{"Approx"}//) {
- $Curr{"Mode"}=1;
- } elsif ($Lang{$Cnf{"Language"}}{"Business"} &&
- s/$Lang{$Cnf{"Language"}}{"Business"}//) {
- $Curr{"Mode"}=2;
- } elsif (! exists $Curr{"Mode"}) {
- $Curr{"Mode"}=0;
- }
- $workweek=7 if ($Curr{"Mode"} != 2);
-
- foreach $from (keys %{ $Lang{$Cnf{"Language"}}{"Repl"} }) {
- $to=$Lang{$Cnf{"Language"}}{"Repl"}{$from};
- s/(^|[^a-z])$from($|[^a-z])/$1$to$2/i;
- }
-
- # in or ago
- #
- # We need to make sure that $later, $future, and $past don't contain each
- # other... Romanian pointed this out where $past is "in urma" and $future
- # is "in". When they do, we have to take this into account.
- # $len length of best match (greatest wins)
- # $tmp string after best match
- # $dir direction (prior, after) of best match
- #
- # $tmp2 string before/after current match
- # $tmpl length of current match
-
- $len=0;
- $tmp=$_;
- $dir=1;
-
- $tmp2=$_;
- if ($tmp2 =~ s/(^|[^a-z])($future)($|[^a-z])/$1 $3/i) {
- $tmpl=length($2);
- if ($tmpl>$len) {
- $tmp=$tmp2;
- $dir=1;
- $len=$tmpl;
- }
- }
-
- $tmp2=$_;
- if ($tmp2 =~ s/(^|[^a-z])($later)($|[^a-z])/$1 $3/i) {
- $tmpl=length($2);
- if ($tmpl>$len) {
- $tmp=$tmp2;
- $dir=1;
- $len=$tmpl;
- }
- }
-
- $tmp2=$_;
- if ($tmp2 =~ s/(^|[^a-z])($past)($|[^a-z])/$1 $3/i) {
- $tmpl=length($2);
- if ($tmpl>$len) {
- $tmp=$tmp2;
- $dir=-1;
- $len=$tmpl;
- }
- }
-
- $_ = $tmp;
- s/\s*$//;
-
- # the colon part of the delta
- $colon="";
- if (s/($signexp?$numexp?(:($signexp?$numexp)?){1,6})$//) {
- $colon=$1;
- s/\s+$//;
- }
- @colon=split(/:/,$colon);
-
- # the non-colon part of the delta
- $sign="+";
- @delta=();
- $i=6;
- foreach $exp1 ($yexp,$mexp,$wexp,$dexp,$hexp,$mnexp,$sexp) {
- last if ($#colon>=$i--);
- $val=0;
- if (s/^$exp1//ix) {
- $val=$2 if ($2);
- $sign=$1 if ($1);
- }
-
- # Collapse a sign like '+ -' into a single character like '-',
- # by counting the occurrences of '-'.
- #
- $sign =~ s/\s+//g;
- $sign =~ tr/+//d;
- my $count = ($sign =~ tr/-//d);
- die "bad characters in sign: $sign" if length $sign;
- $sign = $count % 2 ? '-' : '+';
-
- push(@delta,"$sign$val");
- }
- if (! /^\s*$/) {
- pop(@a);
- next PARSE;
- }
-
- # make sure that the colon part has a sign
- for ($i=0; $i<=$#colon; $i++) {
- $val=0;
- if ($colon[$i] =~ /^$signexp$numexp?/) {
- $val=$2 if ($2);
- $sign=$1 if ($1);
- }
- $colon[$i] = "$sign$val";
- }
-
- # combine the two
- push(@delta,@colon);
- if ($dir<0) {
- for ($i=0; $i<=$#delta; $i++) {
- $delta[$i] =~ tr/-+/+-/;
- }
- }
-
- # form the delta and shift off the valid part
- $delta=join(":",@delta);
- splice(@args,0,$#a+1);
- @$args=@args if (defined $ref and $ref eq "ARRAY");
- last PARSE;
- }
-
- $delta=&Delta_Normalize($delta,$Curr{"Mode"});
- return $delta;
-}
-
-sub UnixDate {
- print "DEBUG: UnixDate\n" if ($Curr{"Debug"} =~ /trace/);
- my($date,@format)=@_;
- local($_)=();
- my($format,%f,$out,@out,$c,$date1,$date2,$tmp)=();
- my($scalar)=();
- $date=&ParseDateString($date);
- return if (! $date);
-
- my($y,$m,$d,$h,$mn,$s)=($f{"Y"},$f{"m"},$f{"d"},$f{"H"},$f{"M"},$f{"S"})=
- &Date_Split($date, 1);
- $f{"y"}=substr $f{"Y"},2;
- &Date_Init() if (! $Curr{"InitDone"});
-
- if (! wantarray) {
- $format=join(" ",@format);
- @format=($format);
- $scalar=1;
- }
-
- # month, week
- $_=$m;
- s/^0//;
- $f{"b"}=$f{"h"}=$Lang{$Cnf{"Language"}}{"MonL"}[$_-1];
- $f{"B"}=$Lang{$Cnf{"Language"}}{"MonthL"}[$_-1];
- $_=$m;
- s/^0/ /;
- $f{"f"}=$_;
- $f{"U"}=&Date_WeekOfYear($m,$d,$y,7);
- $f{"W"}=&Date_WeekOfYear($m,$d,$y,1);
-
- # check week 52,53 and 0
- $f{"G"}=$f{"L"}=$y;
- if ($f{"W"}>=52 || $f{"U"}>=52) {
- my($dd,$mm,$yy)=($d,$m,$y);
- $dd+=7;
- if ($dd>31) {
- $dd-=31;
- $mm=1;
- $yy++;
- if (&Date_WeekOfYear($mm,$dd,$yy,1)==2) {
- $f{"G"}=$yy;
- $f{"W"}=1;
- }
- if (&Date_WeekOfYear($mm,$dd,$yy,7)==2) {
- $f{"L"}=$yy;
- $f{"U"}=1;
- }
- }
- }
- if ($f{"W"}==0) {
- my($dd,$mm,$yy)=($d,$m,$y);
- $dd-=7;
- $dd+=31 if ($dd<1);
- $yy--;
- $mm=12;
- $f{"G"}=$yy;
- $f{"W"}=&Date_WeekOfYear($mm,$dd,$yy,1)+1;
- }
- if ($f{"U"}==0) {
- my($dd,$mm,$yy)=($d,$m,$y);
- $dd-=7;
- $dd+=31 if ($dd<1);
- $yy--;
- $mm=12;
- $f{"L"}=$yy;
- $f{"U"}=&Date_WeekOfYear($mm,$dd,$yy,7)+1;
- }
-
- $f{"U"}="0".$f{"U"} if (length $f{"U"} < 2);
- $f{"W"}="0".$f{"W"} if (length $f{"W"} < 2);
-
- # day
- $f{"j"}=&Date_DayOfYear($m,$d,$y);
- $f{"j"} = "0" . $f{"j"} while (length($f{"j"})<3);
- $_=$d;
- s/^0/ /;
- $f{"e"}=$_;
- $f{"w"}=&Date_DayOfWeek($m,$d,$y);
- $f{"v"}=$Lang{$Cnf{"Language"}}{"WL"}[$f{"w"}-1];
- $f{"v"}=" ".$f{"v"} if (length $f{"v"} < 2);
- $f{"a"}=$Lang{$Cnf{"Language"}}{"WkL"}[$f{"w"}-1];
- $f{"A"}=$Lang{$Cnf{"Language"}}{"WeekL"}[$f{"w"}-1];
- $f{"E"}=&Date_DaySuffix($f{"e"});
-
- # hour
- $_=$h;
- s/^0/ /;
- $f{"k"}=$_;
- $f{"i"}=$f{"k"}+1;
- $f{"i"}=$f{"k"};
- $f{"i"}=12 if ($f{"k"}==0);
- $f{"i"}=$f{"k"}-12 if ($f{"k"}>12);
- $f{"i"}=$f{"i"}-12 if ($f{"i"}>12);
- $f{"i"}=" ".$f{"i"} if (length($f{"i"})<2);
- $f{"I"}=$f{"i"};
- $f{"I"}=~ s/^ /0/;
- $f{"p"}=$Lang{$Cnf{"Language"}}{"AMstr"};
- $f{"p"}=$Lang{$Cnf{"Language"}}{"PMstr"} if ($f{"k"}>11);
-
- # minute, second, timezone
- $f{"o"}=&Date_SecsSince1970($m,$d,$y,$h,$mn,$s);
- $f{"s"}=&Date_SecsSince1970GMT($m,$d,$y,$h,$mn,$s);
- $f{"Z"}=($Cnf{"ConvTZ"} eq "IGNORE" or $Cnf{"ConvTZ"} eq "") ?
- $Cnf{"TZ"} : $Cnf{"ConvTZ"};
- $f{"z"}=($f{"Z"}=~/^[+-]\d{4}/) ? $f{"Z"} : ($Zone{"n2o"}{lc $f{"Z"}} || "");
-
- # date, time
- $f{"c"}=qq|$f{"a"} $f{"b"} $f{"e"} $h:$mn:$s $y|;
- $f{"C"}=$f{"u"}=
- qq|$f{"a"} $f{"b"} $f{"e"} $h:$mn:$s $f{"z"} $y|;
- $f{"g"}=qq|$f{"a"}, $d $f{"b"} $y $h:$mn:$s $f{"z"}|;
- $f{"D"}=$f{"x"}=qq|$m/$d/$f{"y"}|;
- $f{"r"}=qq|$f{"I"}:$mn:$s $f{"p"}|;
- $f{"R"}=qq|$h:$mn|;
- $f{"T"}=$f{"X"}=qq|$h:$mn:$s|;
- $f{"V"}=qq|$m$d$h$mn$f{"y"}|;
- $f{"Q"}="$y$m$d";
- $f{"q"}=qq|$y$m$d$h$mn$s|;
- $f{"P"}=qq|$y$m$d$h:$mn:$s|;
- $f{"F"}=qq|$f{"A"}, $f{"B"} $f{"e"}, $f{"Y"}|;
- if ($f{"W"}==0) {
- $y--;
- $tmp=&Date_WeekOfYear(12,31,$y,1);
- $tmp="0$tmp" if (length($tmp) < 2);
- $f{"J"}=qq|$y-W$tmp-$f{"w"}|;
- } else {
- $f{"J"}=qq|$f{"G"}-W$f{"W"}-$f{"w"}|;
- }
- $f{"K"}=qq|$y-$f{"j"}|;
- # %l is a special case. Since it requires the use of the calculator
- # which requires this routine, an infinite recursion results. To get
- # around this, %l is NOT determined every time this is called so the
- # recursion breaks.
-
- # other formats
- $f{"n"}="\n";
- $f{"t"}="\t";
- $f{"%"}="%";
- $f{"+"}="+";
-
- foreach $format (@format) {
- $format=reverse($format);
- $out="";
- while ($format ne "") {
- $c=chop($format);
- if ($c eq "%") {
- $c=chop($format);
- if ($c eq "l") {
- &Date_Init();
- $date1=&DateCalc_DateDelta($Curr{"Now"},"-0:6:0:0:0:0:0");
- $date2=&DateCalc_DateDelta($Curr{"Now"},"+0:6:0:0:0:0:0");
- if (&Date_Cmp($date,$date1)>=0 && &Date_Cmp($date,$date2)<=0) {
- $f{"l"}=qq|$f{"b"} $f{"e"} $h:$mn|;
- } else {
- $f{"l"}=qq|$f{"b"} $f{"e"} $f{"Y"}|;
- }
- $out .= $f{"$c"};
- } elsif (exists $f{"$c"}) {
- $out .= $f{"$c"};
- } else {
- $out .= $c;
- }
- } else {
- $out .= $c;
- }
- }
- push(@out,$out);
- }
- if ($scalar) {
- return $out[0];
- } else {
- return (@out);
- }
-}
-
-# Can't be in "use integer" because we're doing decimal arithmatic
-no integer;
-sub Delta_Format {
- print "DEBUG: Delta_Format\n" if ($Curr{"Debug"} =~ /trace/);
- my($delta,$dec,@format)=@_;
- $delta=&ParseDateDelta($delta);
- return "" if (! $delta);
- my(@out,%f,$out,$c1,$c2,$scalar,$format)=();
- local($_)=$delta;
- my($y,$M,$w,$d,$h,$m,$s)=&Delta_Split($delta);
- # Get rid of positive signs.
- ($y,$M,$w,$d,$h,$m,$s)=map { 1*$_; }($y,$M,$w,$d,$h,$m,$s);
-
- if (defined $dec && $dec>0) {
- $dec="%." . ($dec*1) . "f";
- } else {
- $dec="%f";
- }
-
- if (! wantarray) {
- $format=join(" ",@format);
- @format=($format);
- $scalar=1;
- }
-
- # Length of each unit in seconds
- my($sl,$ml,$hl,$dl,$wl,$yl)=();
- $sl = 1;
- $ml = $sl*60;
- $hl = $ml*60;
- $dl = $hl*24;
- $wl = $dl*7;
- $yl = $dl*365.25;
-
- # The decimal amount of each unit contained in all smaller units
- my($yd,$Md,$sd,$md,$hd,$dd,$wd)=();
- if ($M) {
- $yd = $M/12;
- $Md = 0;
- } else {
- $yd = ($w*$wl + $d*$dl + $h*$hl + $m*$ml + $s*$sl)/$yl;
- $Md = 0;
- }
-
- $wd = ($d*$dl + $h*$hl + $m*$ml + $s*$sl)/$wl;
- $dd = ($h*$hl + $m*$ml + $s*$sl)/$dl;
- $hd = ($m*$ml + $s*$sl)/$hl;
- $md = ($s*$sl)/$ml;
- $sd = 0;
-
- # The amount of each unit contained in higher units.
- my($yh,$Mh,$sh,$mh,$hh,$dh,$wh)=();
- $yh = 0;
-
- if ($M) {
- $Mh = ($yh+$y)*12;
- $wh = 0;
- $dh = ($wh+$w)*7;
- } else {
- $Mh = 0;
- $wh = ($yh+$y)*365.25/7;
- $dh = ($yh+$y)*365.25 + $w*7;
- }
-
- $hh = ($dh+$d)*24;
- $mh = ($hh+$h)*60;
- $sh = ($mh+$m)*60;
-
- # Set up the formats
-
- $f{"yv"} = $y;
- $f{"Mv"} = $M;
- $f{"wv"} = $w;
- $f{"dv"} = $d;
- $f{"hv"} = $h;
- $f{"mv"} = $m;
- $f{"sv"} = $s;
-
- $f{"yh"} = $y+$yh;
- $f{"Mh"} = $M+$Mh;
- $f{"wh"} = $w+$wh;
- $f{"dh"} = $d+$dh;
- $f{"hh"} = $h+$hh;
- $f{"mh"} = $m+$mh;
- $f{"sh"} = $s+$sh;
-
- $f{"yd"} = sprintf($dec,$y+$yd);
- $f{"Md"} = sprintf($dec,$M+$Md);
- $f{"wd"} = sprintf($dec,$w+$wd);
- $f{"dd"} = sprintf($dec,$d+$dd);
- $f{"hd"} = sprintf($dec,$h+$hd);
- $f{"md"} = sprintf($dec,$m+$md);
- $f{"sd"} = sprintf($dec,$s+$sd);
-
- $f{"yt"} = sprintf($dec,$yh+$y+$yd);
- $f{"Mt"} = sprintf($dec,$Mh+$M+$Md);
- $f{"wt"} = sprintf($dec,$wh+$w+$wd);
- $f{"dt"} = sprintf($dec,$dh+$d+$dd);
- $f{"ht"} = sprintf($dec,$hh+$h+$hd);
- $f{"mt"} = sprintf($dec,$mh+$m+$md);
- $f{"st"} = sprintf($dec,$sh+$s+$sd);
-
- $f{"%"} = "%";
-
- foreach $format (@format) {
- $format=reverse($format);
- $out="";
- PARSE: while ($format) {
- $c1=chop($format);
- if ($c1 eq "%") {
- $c1=chop($format);
- if (exists($f{$c1})) {
- $out .= $f{$c1};
- next PARSE;
- }
- $c2=chop($format);
- if (exists($f{"$c1$c2"})) {
- $out .= $f{"$c1$c2"};
- next PARSE;
- }
- $out .= $c1;
- $format .= $c2;
- } else {
- $out .= $c1;
- }
- }
- push(@out,$out);
- }
- if ($scalar) {
- return $out[0];
- } else {
- return (@out);
- }
-}
-use integer;
-
-sub ParseRecur {
- print "DEBUG: ParseRecur\n" if ($Curr{"Debug"} =~ /trace/);
- &Date_Init() if (! $Curr{"InitDone"});
-
- my($recur,$dateb,$date0,$date1,$flag)=@_;
- local($_)=$recur;
-
- my($recur_0,$recur_1,@recur0,@recur1)=();
- my(@tmp,$tmp,$each,$num,$y,$m,$d,$w,$h,$mn,$s,$delta,$y0,$y1,$yb)=();
- my($yy,$n,$dd,@d,@tmp2,$date,@date,@w,@tmp3,@m,@y,$tmp2,$d2,@flags)=();
-
- # $date0, $date1, $dateb, $flag : passed in (these are always the final say
- # in determining whether a date matches a
- # recurrence IF they are present.
- # $date_b, $date_0, $date_1 : if a value can be determined from the
- # $flag_t recurrence, they are stored here.
- #
- # If values can be determined from the recurrence AND are passed in, the
- # following are used:
- # max($date0,$date_0) i.e. the later of the two dates
- # min($date1,$date_1) i.e. the earlier of the two dates
- #
- # The base date that is used is the first one defined from
- # $dateb $date_b
- # The base date is only used if necessary (as determined by the recur).
- # For example, "every other friday" requires a base date, but "2nd
- # friday of every month" doesn't.
-
- my($date_b,$date_0,$date_1,$flag_t);
-
- #
- # Check the arguments passed in.
- #
-
- $date0="" if (! defined $date0);
- $date1="" if (! defined $date1);
- $dateb="" if (! defined $dateb);
- $flag ="" if (! defined $flag);
-
- if ($dateb) {
- $dateb=&ParseDateString($dateb);
- return "" if (! $dateb);
- }
- if ($date0) {
- $date0=&ParseDateString($date0);
- return "" if (! $date0);
- }
- if ($date1) {
- $date1=&ParseDateString($date1);
- return "" if (! $date1);
- }
-
- #
- # Parse the recur. $date_b, $date_0, and $date_e are values obtained
- # from the recur.
- #
-
- @tmp=&Recur_Split($_);
-
- if (@tmp) {
- ($recur_0,$recur_1,$flag_t,$date_b,$date_0,$date_1)=@tmp;
- $recur_0 = "" if (! defined $recur_0);
- $recur_1 = "" if (! defined $recur_1);
- $flag_t = "" if (! defined $flag_t);
- $date_b = "" if (! defined $date_b);
- $date_0 = "" if (! defined $date_0);
- $date_1 = "" if (! defined $date_1);
-
- @recur0 = split(/:/,$recur_0);
- @recur1 = split(/:/,$recur_1);
- return "" if ($#recur0 + $#recur1 + 2 != 7);
-
- if ($date_b) {
- $date_b=&ParseDateString($date_b);
- return "" if (! $date_b);
- }
- if ($date_0) {
- $date_0=&ParseDateString($date_0);
- return "" if (! $date_0);
- }
- if ($date_1) {
- $date_1=&ParseDateString($date_1);
- return "" if (! $date_1);
- }
-
- } else {
-
- my($mmm)='\s*'.$Lang{$Cnf{"Language"}}{"Month"}; # \s*(jan|january|...)
- my(%mmm)=%{ $Lang{$Cnf{"Language"}}{"MonthH"} }; # { jan=>1, ... }
- my($wkexp)='\s*'.$Lang{$Cnf{"Language"}}{"Week"}; # \s*(mon|monday|...)
- my(%week)=%{ $Lang{$Cnf{"Language"}}{"WeekH"} }; # { monday=>1, ... }
- my($day)='\s*'.$Lang{$Cnf{"Language"}}{"Dabb"}; # \s*(?:d|day|days)
- my($month)='\s*'.$Lang{$Cnf{"Language"}}{"Mabb"}; # \s*(?:mon|month|months)
- my($week)='\s*'.$Lang{$Cnf{"Language"}}{"Wabb"}; # \s*(?:w|wk|week|weeks)
- my($daysexp)=$Lang{$Cnf{"Language"}}{"DoM"}; # (1st|first|...31st)
- my(%dayshash)=%{ $Lang{$Cnf{"Language"}}{"DoMH"} };
- # { 1st=>1,first=>1,...}
- my($of)='\s*'.$Lang{$Cnf{"Language"}}{"Of"}; # \s*(?:in|of)
- my($lastexp)=$Lang{$Cnf{"Language"}}{"Last"}; # (?:last)
- my($each)=$Lang{$Cnf{"Language"}}{"Each"}; # (?:each|every)
-
- my($D)='\s*(\d+)';
- my($Y)='\s*(\d{4}|\d{2})';
-
- # Change 1st to 1
- if (/(^|[^a-z])$daysexp($|[^a-z])/i) {
- $tmp=lc($2);
- $tmp=$dayshash{"$tmp"};
- s/(^|[^a-z])$daysexp($|[^a-z])/$1 $tmp $3/i;
- }
- s/\s*$//;
-
- # Get rid of "each"
- if (/(^|[^a-z])$each($|[^a-z])/i) {
- s/(^|[^a-z])$each($|[^a-z])/$1 $2/i;
- $each=1;
- } else {
- $each=0;
- }
-
- if ($each) {
-
- if (/^$D?$day(?:$of$mmm?$Y)?$/i ||
- /^$D?$day(?:$of$mmm())?$/i) {
- # every [2nd] day in [june] 1997
- # every [2nd] day [in june]
- ($num,$m,$y)=($1,$2,$3);
- $num=1 if (! defined $num);
- $m="" if (! defined $m);
- $y="" if (! defined $y);
-
- $y=$Curr{"Y"} if (! $y);
- if ($m) {
- $m=$mmm{lc($m)};
- $date_0=&Date_Join($y,$m,1,0,0,0);
- $date_1=&DateCalc_DateDelta($date_0,"+0:1:0:0:0:0:0",0);
- } else {
- $date_0=&Date_Join($y, 1,1,0,0,0);
- $date_1=&Date_Join($y+1,1,1,0,0,0);
- }
- $date_b=&DateCalc($date_0,"-0:0:0:1:0:0:0",0);
- @recur0=(0,0,0,$num,0,0,0);
- @recur1=();
-
- } elsif (/^$D$day?$of$month(?:$of?$Y)?$/) {
- # 2nd [day] of every month [in 1997]
- ($num,$y)=($1,$2);
- $y=$Curr{"Y"} if (! $y);
-
- $date_0=&Date_Join($y, 1,1,0,0,0);
- $date_1=&Date_Join($y+1,1,1,0,0,0);
- $date_b=$date_0;
-
- @recur0=(0,1,0);
- @recur1=($num,0,0,0);
-
- } elsif (/^$D$wkexp$of$month(?:$of?$Y)?$/ ||
- /^($lastexp)$wkexp$of$month(?:$of?$Y)?$/) {
- # 2nd tuesday of every month [in 1997]
- # last tuesday of every month [in 1997]
- ($num,$d,$y)=($1,$2,$3);
- $y=$Curr{"Y"} if (! $y);
- $d=$week{lc($d)};
- $num=-1 if ($num !~ /^$D$/);
-
- $date_0=&Date_Join($y,1,1,0,0,0);
- $date_1=&Date_Join($y+1,1,1,0,0,0);
- $date_b=$date_0;
-
- @recur0=(0,1);
- @recur1=($num,$d,0,0,0);
-
- } elsif (/^$D?$wkexp(?:$of$mmm?$Y)?$/i ||
- /^$D?$wkexp(?:$of$mmm())?$/i) {
- # every tuesday in june 1997
- # every 2nd tuesday in june 1997
- ($num,$d,$m,$y)=($1,$2,$3,$4);
- $y=$Curr{"Y"} if (! $y);
- $num=1 if (! defined $num);
- $m="" if (! defined $m);
- $d=$week{lc($d)};
-
- if ($m) {
- $m=$mmm{lc($m)};
- $date_0=&Date_Join($y,$m,1,0,0,0);
- $date_1=&DateCalc_DateDelta($date_0,"+0:1:0:0:0:0:0",0);
- } else {
- $date_0=&Date_Join($y,1,1,0,0,0);
- $date_1=&Date_Join($y+1,1,1,0,0,0);
- }
- $date_b=&DateCalc($date_0,"-0:0:0:1:0:0:0",0);
-
- @recur0=(0,0,$num);
- @recur1=($d,0,0,0);
-
- } else {
- return "";
- }
-
- $date_0="" if ($date0);
- $date_1="" if ($date1);
- } else {
- return "";
- }
- }
-
- #
- # Override with any values passed in
- #
-
- if ($date0 && $date_0) {
- $date0=( &Date_Cmp($date0,$date_0) > 1 ? $date0 : $date_0);
- } elsif ($date_0) {
- $date0 = $date_0;
- }
-
- if ($date1 && $date_1) {
- $date1=( &Date_Cmp($date1,$date_1) > 1 ? $date_1 : $date1);
- } elsif ($date_1) {
- $date1 = $date_1;
- }
-
- $dateb=$date_b if (! $dateb);
-
- if ($flag =~ s/^\+//) {
- if ($flag_t) {
- $flag="$flag_t,$flag";
- }
- }
- $flag =$flag_t if (! $flag && $flag_t);
-
- if (! wantarray) {
- $tmp = join(":",@recur0);
- $tmp .= "*" . join(":",@recur1) if (@recur1);
- $tmp .= "*$flag*$dateb*$date0*$date1";
- return $tmp;
- }
- if (@recur0) {
- return () if (! $date0 || ! $date1); # dateb is NOT required in all case
- }
-
- #
- # Some flags affect parsing.
- #
-
- @flags = split(/,/,$flag);
- my($MDn) = 0;
- my($MWn) = 7;
- my($f);
- foreach $f (@flags) {
- if ($f =~ /^MW([1-7])$/i) {
- $MWn=$1;
- $MDn=0;
-
- } elsif ($f =~ /^MD([1-7])$/i) {
- $MDn=$1;
- $MWn=0;
-
- } elsif ($f =~ /^EASTER$/i) {
- ($y,$m,$w,$d,$h,$mn,$s)=(@recur0,@recur1);
- # We want something that will return Jan 1 for the given years.
- if ($#recur0==-1) {
- @recur1=($y,1,0,1,$h,$mn,$s);
- } elsif ($#recur0<=3) {
- @recur0=($y,0,0,0);
- @recur1=($h,$mn,$s);
- } elsif ($#recur0==4) {
- @recur0=($y,0,0,0,0);
- @recur1=($mn,$s);
- } elsif ($#recur0==5) {
- @recur0=($y,0,0,0,0,0);
- @recur1=($s);
- } else {
- @recur0=($y,0,0,0,0,0,0);
- }
- }
- }
-
- #
- # Determine the dates referenced by the recur. Also, fix the base date
- # as necessary for the recurrences which require it.
- #
-
- ($y,$m,$w,$d,$h,$mn,$s)=(@recur0,@recur1);
- @y=@m=@w=@d=();
- my(@time)=($h,$mn,$s);
-
- RECUR: while (1) {
-
- if ($#recur0==-1) {
- # * Y-M-W-D-H-MN-S
- if ($y eq "0") {
- push(@recur0,0);
- shift(@recur1);
-
- } else {
- @y=&ReturnList($y);
- foreach $y (@y) {
- $y=&Date_FixYear($y) if (length($y)==2);
- return () if (length($y)!=4 || ! &IsInt($y));
- }
- @y=sort { $a<=>$b } @y;
-
- $date0=&ParseDate("0000-01-01") if (! $date0);
- $date1=&ParseDate("9999-12-31 23:59:59") if (! $date1);
-
- if ($m eq "0" and $w eq "0") {
- # * Y-0-0-0-H-MN-S
- # * Y-0-0-DOY-H-MN-S
- if ($d eq "0") {
- @d=(1);
- } else {
- @d=&ReturnList($d);
- return () if (! @d);
- foreach $d (@d) {
- return () if (! &IsInt($d,1,366));
- }
- @d=sort { $a<=>$b } (@d);
- }
-
- @date=();
- foreach $yy (@y) {
- foreach $d (@d) {
- ($y,$m,$dd)=&Date_NthDayOfYear($yy,$d);
- push(@date, &Date_Join($y,$m,$dd,0,0,0));
- }
- }
- last RECUR;
-
- } elsif ($w eq "0") {
- # * Y-M-0-0-H-MN-S
- # * Y-M-0-DOM-H-MN-S
-
- @m=&ReturnList($m);
- return () if (! @m);
- foreach $m (@m) {
- return () if (! &IsInt($m,1,12));
- }
- @m=sort { $a<=>$b } (@m);
-
- if ($d eq "0") {
- @d=(1);
- } else {
- @d=&ReturnList($d);
- return () if (! @d);
- foreach $d (@d) {
- return () if (! &IsInt($d,1,31));
- }
- @d=sort { $a<=>$b } (@d);
- }
-
- @date=();
- foreach $y (@y) {
- foreach $m (@m) {
- foreach $d (@d) {
- $date=&Date_Join($y,$m,$d,0,0,0);
- push(@date,$date) if ($d<29 || &Date_Split($date));
- }
- }
- }
- last RECUR;
-
- } elsif ($m eq "0") {
- # * Y-0-WOY-DOW-H-MN-S
- # * Y-0-WOY-0-H-MN-S
- @w=&ReturnList($w);
- return () if (! @w);
- foreach $w (@w) {
- return () if (! &IsInt($w,1,53));
- }
-
- if ($d eq "0") {
- @d=($Cnf{"FirstDay"});
- } else {
- @d=&ReturnList($d);
- return () if (! @d);
- foreach $d (@d) {
- return () if (! &IsInt($d,1,7));
- }
- @d=sort { $a<=>$b } (@d);
- }
-
- @date=();
- foreach $y (@y) {
- foreach $w (@w) {
- $w="0$w" if (length($w)==1);
- foreach $d (@d) {
- $date=&ParseDateString("$y-W$w-$d");
- push(@date,$date);
- }
- }
- }
- last RECUR;
-
- } else {
- # * Y-M-WOM-DOW-H-MN-S
- # * Y-M-WOM-0-H-MN-S
-
- @m=&ReturnList($m);
- return () if (! @m);
- foreach $m (@m) {
- return () if (! &IsInt($m,1,12));
- }
- @m=sort { $a<=>$b } (@m);
-
- @w=&ReturnList($w);
-
- if ($d eq "0") {
- @d=();
- } else {
- @d=&ReturnList($d);
- }
-
- @date=&Date_Recur_WoM(\@y,\@m,\@w,\@d,$MWn,$MDn);
- last RECUR;
- }
- }
- }
-
- if ($#recur0==0) {
- # Y * M-W-D-H-MN-S
- $n=$y;
- $n=1 if ($n==0);
-
- @m=&ReturnList($m);
- return () if (! @m);
- foreach $m (@m) {
- return () if (! &IsInt($m,1,12));
- }
- @m=sort { $a<=>$b } (@m);
-
- if ($m eq "0") {
- # Y * 0-W-D-H-MN-S (equiv to Y-0 * W-D-H-MN-S)
- push(@recur0,0);
- shift(@recur1);
-
- } elsif ($w eq "0") {
- # Y * M-0-DOM-H-MN-S
- return () if (! $dateb);
- $d=1 if ($d eq "0");
-
- @d=&ReturnList($d);
- return () if (! @d);
- foreach $d (@d) {
- return () if (! &IsInt($d,1,31));
- }
- @d=sort { $a<=>$b } (@d);
-
- # We need to find years that are a multiple of $n from $y(base)
- ($y0)=( &Date_Split($date0, 1) )[0];
- ($y1)=( &Date_Split($date1, 1) )[0];
- ($yb)=( &Date_Split($dateb, 1) )[0];
- @date=();
- for ($yy=$y0; $yy<=$y1; $yy++) {
- if (($yy-$yb)%$n == 0) {
- foreach $m (@m) {
- foreach $d (@d) {
- $date=&Date_Join($yy,$m,$d,0,0,0);
- push(@date,$date) if ($d<29 || &Date_Split($date));
- }
- }
- }
- }
- last RECUR;
-
- } else {
- # Y * M-WOM-DOW-H-MN-S
- # Y * M-WOM-0-H-MN-S
- return () if (! $dateb);
- @m=&ReturnList($m);
- @w=&ReturnList($w);
- if ($d eq "0") {
- @d=();
- } else {
- @d=&ReturnList($d);
- }
-
- ($y0)=( &Date_Split($date0, 1) )[0];
- ($y1)=( &Date_Split($date1, 1) )[0];
- ($yb)=( &Date_Split($dateb, 1) )[0];
- @y=();
- for ($yy=$y0; $yy<=$y1; $yy++) {
- if (($yy-$yb)%$n == 0) {
- push(@y,$yy);
- }
- }
-
- @date=&Date_Recur_WoM(\@y,\@m,\@w,\@d,$MWn,$MDn);
- last RECUR;
- }
- }
-
- if ($#recur0==1) {
- # Y-M * W-D-H-MN-S
-
- if ($w eq "0") {
- # Y-M * 0-D-H-MN-S (equiv to Y-M-0 * D-H-MN-S)
- push(@recur0,0);
- shift(@recur1);
-
- } elsif ($m==0) {
- # Y-0 * WOY-0-H-MN-S
- # Y-0 * WOY-DOW-H-MN-S
- return () if (! $dateb);
- $n=$y;
- $n=1 if ($n==0);
-
- @w=&ReturnList($w);
- return () if (! @w);
- foreach $w (@w) {
- return () if (! &IsInt($w,1,53));
- }
-
- if ($d eq "0") {
- @d=($Cnf{"FirstDay"});
- } else {
- @d=&ReturnList($d);
- return () if (! @d);
- foreach $d (@d) {
- return () if (! &IsInt($d,1,7));
- }
- @d=sort { $a<=>$b } (@d);
- }
-
- # We need to find years that are a multiple of $n from $y(base)
- ($y0)=( &Date_Split($date0, 1) )[0];
- ($y1)=( &Date_Split($date1, 1) )[0];
- ($yb)=( &Date_Split($dateb, 1) )[0];
- @date=();
- for ($yy=$y0; $yy<=$y1; $yy++) {
- if (($yy-$yb)%$n == 0) {
- foreach $w (@w) {
- $w="0$w" if (length($w)==1);
- foreach $tmp (@d) {
- $date=&ParseDateString("$yy-W$w-$tmp");
- push(@date,$date);
- }
- }
- }
- }
- last RECUR;
-
- } else {
- # Y-M * WOM-0-H-MN-S
- # Y-M * WOM-DOW-H-MN-S
- return () if (! $dateb);
- @tmp=(@recur0);
- push(@tmp,0) while ($#tmp<6);
- $delta=join(":",@tmp);
- @tmp=&Date_Recur($date0,$date1,$dateb,$delta);
-
- @w=&ReturnList($w);
- @m=();
- if ($d eq "0") {
- @d=();
- } else {
- @d=&ReturnList($d);
- }
-
- @date=&Date_Recur_WoM(\@tmp,\@m,\@w,\@d,$MWn,$MDn);
- last RECUR;
- }
- }
-
- if ($#recur0==2) {
- # Y-M-W * D-H-MN-S
-
- if ($d eq "0") {
- # Y-M-W * 0-H-MN-S
- return () if (! $dateb);
- $y=1 if ($y==0 && $m==0 && $w==0);
- $delta="$y:$m:$w:0:0:0:0";
- @date=&Date_Recur($date0,$date1,$dateb,$delta);
- last RECUR;
-
- } elsif ($m==0 && $w==0) {
- # Y-0-0 * DOY-H-MN-S
- $y=1 if ($y==0);
- $n=$y;
- return () if (! $dateb && $y!=1);
-
- @d=&ReturnList($d);
- return () if (! @d);
- foreach $d (@d) {
- return () if (! &IsInt($d,1,366));
- }
- @d=sort { $a<=>$b } (@d);
-
- # We need to find years that are a multiple of $n from $y(base)
- ($y0)=( &Date_Split($date0, 1) )[0];
- ($y1)=( &Date_Split($date1, 1) )[0];
- ($yb)=( &Date_Split($dateb, 1) )[0];
- @date=();
- for ($yy=$y0; $yy<=$y1; $yy++) {
- if (($yy-$yb)%$n == 0) {
- foreach $d (@d) {
- ($y,$m,$dd)=&Date_NthDayOfYear($yy,$d);
- push(@date, &Date_Join($y,$m,$dd,0,0,0));
- }
- }
- }
- last RECUR;
-
- } elsif ($w>0) {
- # Y-M-W * DOW-H-MN-S
- return () if (! $dateb);
- @tmp=(@recur0);
- push(@tmp,0) while ($#tmp<6);
- $delta=join(":",@tmp);
-
- @d=&ReturnList($d);
- return () if (! @d);
- foreach $d (@d) {
- return () if (! &IsInt($d,1,7));
- }
-
- # Find out what DofW the basedate is.
- @tmp2=&Date_Split($dateb, 1);
- $tmp=&Date_DayOfWeek($tmp2[1],$tmp2[2],$tmp2[0]);
-
- @date=();
- foreach $d (@d) {
- $date_b=$dateb;
- # Move basedate to DOW
- if ($d != $tmp) {
- if (($tmp>=$Cnf{"FirstDay"} && $d<$Cnf{"FirstDay"}) ||
- ($tmp>=$Cnf{"FirstDay"} && $d>$tmp) ||
- ($tmp<$d && $d<$Cnf{"FirstDay"})) {
- $date_b=&Date_GetNext($date_b,$d);
- } else {
- $date_b=&Date_GetPrev($date_b,$d);
- }
- }
- push(@date,&Date_Recur($date0,$date1,$date_b,$delta));
- }
- @date=sort(@date);
- last RECUR;
-
- } elsif ($m>0) {
- # Y-M-0 * DOM-H-MN-S
- return () if (! $dateb);
- @tmp=(@recur0);
- push(@tmp,0) while ($#tmp<6);
- $delta=join(":",@tmp);
-
- @d=&ReturnList($d);
- return () if (! @d);
- foreach $d (@d) {
- return () if (! &IsInt($d,-31,31) || $d==0);
- }
- @d=sort { $a<=>$b } (@d);
-
- @tmp2=&Date_Recur($date0,$date1,$dateb,$delta);
- @date=();
- foreach $date (@tmp2) {
- ($y,$m)=( &Date_Split($date, 1) )[0..1];
- $tmp2=&Date_DaysInMonth($m,$y);
- foreach $d (@d) {
- $d2=$d;
- $d2=$tmp2+1+$d if ($d<0);
- push(@date,&Date_Join($y,$m,$d2,0,0,0)) if ($d2<=$tmp2);
- }
- }
- @date=sort (@date);
- last RECUR;
-
- } else {
- return ();
- }
- }
-
- if ($#recur0>2) {
- # Y-M-W-D * H-MN-S
- # Y-M-W-D-H * MN-S
- # Y-M-W-D-H-MN * S
- # Y-M-W-D-H-S
- return () if (! $dateb);
- @tmp=(@recur0);
- push(@tmp,0) while ($#tmp<6);
- $delta=join(":",@tmp);
- return () if ($delta !~ /[1-9]/); # return if "0:0:0:0:0:0:0"
- @date=&Date_Recur($date0,$date1,$dateb,$delta);
- if (@recur1) {
- unshift(@recur1,-1) while ($#recur1<2);
- @time=@recur1;
- } else {
- shift(@date);
- pop(@date);
- @time=();
- }
- }
-
- last RECUR;
- }
- @date=&Date_RecurSetTime($date0,$date1,\@date,@time) if (@time);
-
- #
- # We've got a list of dates. Operate on them with the flags.
- #
-
- my($sign,$forw,$today,$df,$db,$work,$i);
- if (@flags) {
- FLAG: foreach $f (@flags) {
- $f = uc($f);
-
- if ($f =~ /^(P|N)(D|T)([1-7])$/) {
- @tmp=($1,$2,$3);
- $forw =($tmp[0] eq "P" ? 0 : 1);
- $today=($tmp[1] eq "D" ? 0 : 1);
- $d=$tmp[2];
- @tmp=();
- foreach $date (@date) {
- if ($forw) {
- push(@tmp, &Date_GetNext($date,$d,$today));
- } else {
- push(@tmp, &Date_GetPrev($date,$d,$today));
- }
- }
- @date=@tmp;
- next FLAG;
- }
-
- # We want to go forward exact amounts of time instead of
- # business mode calculations so that we don't change the time
- # (which may have been set in the recur).
- if ($f =~ /^(F|B)(D|W)(\d+)$/) {
- @tmp=($1,$2,$3);
- $sign="+";
- $sign="-" if ($tmp[0] eq "B");
- $work=0;
- $work=1 if ($tmp[1] eq "W");
- $n=$tmp[2];
- @tmp=();
- foreach $date (@date) {
- for ($i=1; $i<=$n; $i++) {
- while (1) {
- $date=&DateCalc($date,"${sign}0:0:0:1:0:0:0");
- last if (! $work || &Date_IsWorkDay($date,0));
- }
- }
- push(@tmp,$date);
- }
- @date=@tmp;
- next FLAG;
- }
-
- if ($f =~ /^CW(N|P|D)$/ || $f =~ /^(N|P|D)W(D)$/) {
- $tmp=$1;
- my $noalt = $2 ? 1 : 0;
- if ($tmp eq "N" || ($tmp eq "D" && $Cnf{"TomorrowFirst"})) {
- $forw=1;
- } else {
- $forw=0;
- }
-
- @tmp=();
- DATE: foreach $date (@date) {
- $df=$db=$date;
- if (&Date_IsWorkDay($date)) {
- push(@tmp,$date);
- next DATE;
- }
- while (1) {
- if ($forw) {
- $d=$df=&DateCalc($df,"+0:0:0:1:0:0:0");
- } else {
- $d=$db=&DateCalc($db,"-0:0:0:1:0:0:0");
- }
- if (&Date_IsWorkDay($d)) {
- push(@tmp,$d);
- next DATE;
- }
- $forw=1-$forw if (! $noalt);
- }
- }
- @date=@tmp;
- next FLAG;
- }
-
- if ($f eq "EASTER") {
- @tmp=();
- foreach $date (@date) {
- ($y,$m,$d,$h,$mn,$s)=&Date_Split($date, 1);
- ($m,$d)=&Date_Easter($y);
- $date=&Date_Join($y,$m,$d,$h,$mn,$s);
- next if (&Date_Cmp($date,$date0)<0 ||
- &Date_Cmp($date,$date1)>0);
- push(@tmp,$date);
- }
- @date=@tmp;
- }
- }
- @date = sort(@date);
- }
- @date;
-}
-
-sub Date_GetPrev {
- print "DEBUG: Date_GetPrev\n" if ($Curr{"Debug"} =~ /trace/);
- my($date,$dow,$today,$hr,$min,$sec)=@_;
- &Date_Init() if (! $Curr{"InitDone"});
- my($y,$m,$d,$h,$mn,$s,$err,$curr_dow,%dow,$num,$delta,$th,$tm,$ts,
- $adjust,$curr)=();
- $hr="00" if (defined $hr && $hr eq "0");
- $min="00" if (defined $min && $min eq "0");
- $sec="00" if (defined $sec && $sec eq "0");
-
- if (! &Date_Split($date)) {
- $date=&ParseDateString($date);
- return "" if (! $date);
- }
- $curr=$date;
- ($y,$m,$d)=( &Date_Split($date, 1) )[0..2];
-
- if ($dow) {
- $curr_dow=&Date_DayOfWeek($m,$d,$y);
- %dow=%{ $Lang{$Cnf{"Language"}}{"WeekH"} };
- if (&IsInt($dow)) {
- return "" if ($dow<1 || $dow>7);
- } else {
- return "" if (! exists $dow{lc($dow)});
- $dow=$dow{lc($dow)};
- }
- if ($dow == $curr_dow) {
- $date=&DateCalc_DateDelta($date,"-0:0:1:0:0:0:0",\$err,0) if (! $today);
- $adjust=1 if ($today==2);
- } else {
- $dow -= 7 if ($dow>$curr_dow); # make sure previous day is less
- $num = $curr_dow - $dow;
- $date=&DateCalc_DateDelta($date,"-0:0:0:$num:0:0:0",\$err,0);
- }
- $date=&Date_SetTime($date,$hr,$min,$sec) if (defined $hr);
- $date=&DateCalc_DateDelta($date,"-0:0:1:0:0:0:0",\$err,0)
- if ($adjust && &Date_Cmp($date,$curr)>0);
-
- } else {
- ($h,$mn,$s)=( &Date_Split($date, 1) )[3..5];
- ($th,$tm,$ts)=&Date_ParseTime($hr,$min,$sec);
- if ($hr) {
- ($hr,$min,$sec)=($th,$tm,$ts);
- $delta="-0:0:0:1:0:0:0";
- } elsif ($min) {
- ($hr,$min,$sec)=($h,$tm,$ts);
- $delta="-0:0:0:0:1:0:0";
- } elsif ($sec) {
- ($hr,$min,$sec)=($h,$mn,$ts);
- $delta="-0:0:0:0:0:1:0";
- } else {
- confess "ERROR: invalid arguments in Date_GetPrev.\n";
- }
-
- $d=&Date_SetTime($date,$hr,$min,$sec);
- if ($today) {
- $d=&DateCalc_DateDelta($d,$delta,\$err,0) if (&Date_Cmp($d,$date)>0);
- } else {
- $d=&DateCalc_DateDelta($d,$delta,\$err,0) if (&Date_Cmp($d,$date)>=0);
- }
- $date=$d;
- }
- return $date;
-}
-
-sub Date_GetNext {
- print "DEBUG: Date_GetNext\n" if ($Curr{"Debug"} =~ /trace/);
- my($date,$dow,$today,$hr,$min,$sec)=@_;
- &Date_Init() if (! $Curr{"InitDone"});
- my($y,$m,$d,$h,$mn,$s,$err,$curr_dow,%dow,$num,$delta,$th,$tm,$ts,
- $adjust,$curr)=();
- $hr="00" if (defined $hr && $hr eq "0");
- $min="00" if (defined $min && $min eq "0");
- $sec="00" if (defined $sec && $sec eq "0");
-
- if (! &Date_Split($date)) {
- $date=&ParseDateString($date);
- return "" if (! $date);
- }
- $curr=$date;
- ($y,$m,$d)=( &Date_Split($date, 1) )[0..2];
-
- if ($dow) {
- $curr_dow=&Date_DayOfWeek($m,$d,$y);
- %dow=%{ $Lang{$Cnf{"Language"}}{"WeekH"} };
- if (&IsInt($dow)) {
- return "" if ($dow<1 || $dow>7);
- } else {
- return "" if (! exists $dow{lc($dow)});
- $dow=$dow{lc($dow)};
- }
- if ($dow == $curr_dow) {
- $date=&DateCalc_DateDelta($date,"+0:0:1:0:0:0:0",\$err,0) if (! $today);
- $adjust=1 if ($today==2);
- } else {
- $curr_dow -= 7 if ($curr_dow>$dow); # make sure next date is greater
- $num = $dow - $curr_dow;
- $date=&DateCalc_DateDelta($date,"+0:0:0:$num:0:0:0",\$err,0);
- }
- $date=&Date_SetTime($date,$hr,$min,$sec) if (defined $hr);
- $date=&DateCalc_DateDelta($date,"+0:0:1:0:0:0:0",\$err,0)
- if ($adjust && &Date_Cmp($date,$curr)<0);
-
- } else {
- ($h,$mn,$s)=( &Date_Split($date, 1) )[3..5];
- ($th,$tm,$ts)=&Date_ParseTime($hr,$min,$sec);
- if ($hr) {
- ($hr,$min,$sec)=($th,$tm,$ts);
- $delta="+0:0:0:1:0:0:0";
- } elsif ($min) {
- ($hr,$min,$sec)=($h,$tm,$ts);
- $delta="+0:0:0:0:1:0:0";
- } elsif ($sec) {
- ($hr,$min,$sec)=($h,$mn,$ts);
- $delta="+0:0:0:0:0:1:0";
- } else {
- confess "ERROR: invalid arguments in Date_GetNext.\n";
- }
-
- $d=&Date_SetTime($date,$hr,$min,$sec);
- if ($today) {
- $d=&DateCalc_DateDelta($d,$delta,\$err,0) if (&Date_Cmp($d,$date)<0);
- } else {
- $d=&DateCalc_DateDelta($d,$delta,\$err,0) if (&Date_Cmp($d,$date)<1);
- }
- $date=$d;
- }
-
- return $date;
-}
-
-sub Date_IsHoliday {
- print "DEBUG: Date_IsHoliday\n" if ($Curr{"Debug"} =~ /trace/);
- my($date)=@_;
- &Date_Init() if (! $Curr{"InitDone"});
- $date=&ParseDateString($date);
- return undef if (! $date);
- $date=&Date_SetTime($date,0,0,0);
- my($y)=(&Date_Split($date, 1))[0];
- &Date_UpdateHolidays($y) if (! exists $Holiday{"dates"}{$y});
- return undef if (! exists $Holiday{"dates"}{$y}{$date});
- my($name)=$Holiday{"dates"}{$y}{$date};
- return "" if (! $name);
- $name;
-}
-
-sub Events_List {
- print "DEBUG: Events_List\n" if ($Curr{"Debug"} =~ /trace/);
- my(@args)=@_;
- &Date_Init() if (! $Curr{"InitDone"});
- &Events_ParseRaw();
-
- my($tmp,$date0,$date1,$flag);
- $date0=&ParseDateString($args[0]);
- warn "Invalid date $args[0]", return undef if (! $date0);
-
- if ($#args == 0) {
- return &Events_Calc($date0);
- }
-
- if ($args[1]) {
- $date1=&ParseDateString($args[1]);
- warn "Invalid date $args[1]\n", return undef if (! $date1);
- if (&Date_Cmp($date0,$date1)>0) {
- $tmp=$date1;
- $date1=$date0;
- $date0=$tmp;
- }
- } else {
- $date0=&Date_SetTime($date0,"00:00:00");
- $date1=&DateCalc_DateDelta($date0,"+0:0:0:1:0:0:0");
- }
-
- $tmp=&Events_Calc($date0,$date1);
-
- $flag=$args[2];
- return $tmp if (! $flag);
-
- my(@tmp,%ret,$delta)=();
- @tmp=@$tmp;
- push(@tmp,$date1);
-
- if ($flag==1) {
- while ($#tmp>0) {
- ($date0,$tmp)=splice(@tmp,0,2);
- $date1=$tmp[0];
- $delta=&DateCalc_DateDate($date0,$date1);
- foreach $flag (@$tmp) {
- if (exists $ret{$flag}) {
- $ret{$flag}=&DateCalc_DeltaDelta($ret{$flag},$delta);
- } else {
- $ret{$flag}=$delta;
- }
- }
- }
- return \%ret;
-
- } elsif ($flag==2) {
- while ($#tmp>0) {
- ($date0,$tmp)=splice(@tmp,0,2);
- $date1=$tmp[0];
- $delta=&DateCalc_DateDate($date0,$date1);
- $flag=join("+",sort @$tmp);
- next if (! $flag);
- if (exists $ret{$flag}) {
- $ret{$flag}=&DateCalc_DeltaDelta($ret{$flag},$delta);
- } else {
- $ret{$flag}=$delta;
- }
- }
- return \%ret;
- }
-
- warn "Invalid flag $flag\n";
- return undef;
-}
-
-###
-# NOTE: The following routines may be called in the routines below with very
-# little time penalty.
-###
-sub Date_SetTime {
- print "DEBUG: Date_SetTime\n" if ($Curr{"Debug"} =~ /trace/);
- my($date,$h,$mn,$s)=@_;
- &Date_Init() if (! $Curr{"InitDone"});
- my($y,$m,$d)=();
-
- if (! &Date_Split($date)) {
- $date=&ParseDateString($date);
- return "" if (! $date);
- }
-
- ($y,$m,$d)=( &Date_Split($date, 1) )[0..2];
- ($h,$mn,$s)=&Date_ParseTime($h,$mn,$s);
-
- my($ampm,$wk);
- return "" if (&Date_DateCheck(\$y,\$m,\$d,\$h,\$mn,\$s,\$ampm,\$wk));
- &Date_Join($y,$m,$d,$h,$mn,$s);
-}
-
-sub Date_SetDateField {
- print "DEBUG: Date_SetDateField\n" if ($Curr{"Debug"} =~ /trace/);
- my($date,$field,$val,$nocheck)=@_;
- my($y,$m,$d,$h,$mn,$s)=();
- $nocheck=0 if (! defined $nocheck);
-
- ($y,$m,$d,$h,$mn,$s)=&Date_Split($date);
-
- if (! $y) {
- $date=&ParseDateString($date);
- return "" if (! $date);
- ($y,$m,$d,$h,$mn,$s)=&Date_Split($date, 1);
- }
-
- if (lc($field) eq "y") {
- $y=$val;
- } elsif (lc($field) eq "m") {
- $m=$val;
- } elsif (lc($field) eq "d") {
- $d=$val;
- } elsif (lc($field) eq "h") {
- $h=$val;
- } elsif (lc($field) eq "mn") {
- $mn=$val;
- } elsif (lc($field) eq "s") {
- $s=$val;
- } else {
- confess "ERROR: Date_SetDateField: invalid field: $field\n";
- }
-
- $date=&Date_Join($y,$m,$d,$h,$mn,$s);
- return $date if ($nocheck || &Date_Split($date));
- return "";
-}
-
-########################################################################
-# OTHER SUBROUTINES
-########################################################################
-# NOTE: These routines should not call any of the routines above as
-# there will be a severe time penalty (and the possibility of
-# infinite recursion). The last couple routines above are
-# exceptions.
-# NOTE: Date_Init is a special case. It should be called (conditionally)
-# in every routine that uses any variable from the Date::Manip
-# namespace.
-########################################################################
-
-sub Date_DaysInMonth {
- print "DEBUG: Date_DaysInMonth\n" if ($Curr{"Debug"} =~ /trace/);
- my($m,$y)=@_;
- $y=&Date_FixYear($y) if (length($y)!=4);
- my(@d_in_m)=(0,31,28,31,30,31,30,31,31,30,31,30,31);
- $d_in_m[2]=29 if (&Date_LeapYear($y));
- return $d_in_m[$m];
-}
-
-sub Date_DayOfWeek {
- print "DEBUG: Date_DayOfWeek\n" if ($Curr{"Debug"} =~ /trace/);
- my($m,$d,$y)=@_;
- $y=&Date_FixYear($y) if (length($y)!=4);
- my($dayofweek,$dec31)=();
-
- $dec31=5; # Dec 31, 1BC was Friday
- $dayofweek=(&Date_DaysSince1BC($m,$d,$y)+$dec31) % 7;
- $dayofweek=7 if ($dayofweek==0);
- return $dayofweek;
-}
-
-# Can't be in "use integer" because the numbers are too big.
-no integer;
-sub Date_SecsSince1970 {
- print "DEBUG: Date_SecsSince1970\n" if ($Curr{"Debug"} =~ /trace/);
- my($m,$d,$y,$h,$mn,$s)=@_;
- $y=&Date_FixYear($y) if (length($y)!=4);
- my($sec_now,$sec_70)=();
- $sec_now=(&Date_DaysSince1BC($m,$d,$y)-1)*24*3600 + $h*3600 + $mn*60 + $s;
-# $sec_70 =(&Date_DaysSince1BC(1,1,1970)-1)*24*3600;
- $sec_70 =62167219200;
- return ($sec_now-$sec_70);
-}
-
-sub Date_SecsSince1970GMT {
- print "DEBUG: Date_SecsSince1970GMT\n" if ($Curr{"Debug"} =~ /trace/);
- my($m,$d,$y,$h,$mn,$s)=@_;
- &Date_Init() if (! $Curr{"InitDone"});
- $y=&Date_FixYear($y) if (length($y)!=4);
-
- my($sec)=&Date_SecsSince1970($m,$d,$y,$h,$mn,$s);
- return $sec if ($Cnf{"ConvTZ"} eq "IGNORE");
-
- my($tz)=$Cnf{"ConvTZ"};
- $tz=$Cnf{"TZ"} if (! $tz);
- $tz=$Zone{"n2o"}{lc($tz)} if ($tz !~ /^[+-]\d{4}$/);
-
- my($tzs)=1;
- $tzs=-1 if ($tz<0);
- $tz=~/.(..)(..)/;
- my($tzh,$tzm)=($1,$2);
- $sec - $tzs*($tzh*3600+$tzm*60);
-}
-use integer;
-
-sub Date_DaysSince1BC {
- print "DEBUG: Date_DaysSince1BC\n" if ($Curr{"Debug"} =~ /trace/);
- my($m,$d,$y)=@_;
- $y=&Date_FixYear($y) if (length($y)!=4);
- my($Ny,$N4,$N100,$N400,$dayofyear,$days)=();
- my($cc,$yy)=();
-
- $y=~ /(\d{2})(\d{2})/;
- ($cc,$yy)=($1,$2);
-
- # Number of full years since Dec 31, 1BC (counting the year 0000).
- $Ny=$y;
-
- # Number of full 4th years (incl. 0000) since Dec 31, 1BC
- $N4=($Ny-1)/4 + 1;
- $N4=0 if ($y==0);
-
- # Number of full 100th years (incl. 0000)
- $N100=$cc + 1;
- $N100-- if ($yy==0);
- $N100=0 if ($y==0);
-
- # Number of full 400th years (incl. 0000)
- $N400=($N100-1)/4 + 1;
- $N400=0 if ($y==0);
-
- $dayofyear=&Date_DayOfYear($m,$d,$y);
- $days= $Ny*365 + $N4 - $N100 + $N400 + $dayofyear;
-
- return $days;
-}
-
-sub Date_DayOfYear {
- print "DEBUG: Date_DayOfYear\n" if ($Curr{"Debug"} =~ /trace/);
- my($m,$d,$y)=@_;
- $y=&Date_FixYear($y) if (length($y)!=4);
- # DinM = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
- my(@days) = ( 0, 31, 59, 90,120,151,181,212,243,273,304,334,365);
- my($ly)=0;
- $ly=1 if ($m>2 && &Date_LeapYear($y));
- return ($days[$m-1]+$d+$ly);
-}
-
-sub Date_DaysInYear {
- print "DEBUG: Date_DaysInYear\n" if ($Curr{"Debug"} =~ /trace/);
- my($y)=@_;
- $y=&Date_FixYear($y) if (length($y)!=4);
- return 366 if (&Date_LeapYear($y));
- return 365;
-}
-
-sub Date_WeekOfYear {
- print "DEBUG: Date_WeekOfYear\n" if ($Curr{"Debug"} =~ /trace/);
- my($m,$d,$y,$f)=@_;
- &Date_Init() if (! $Curr{"InitDone"});
- $y=&Date_FixYear($y) if (length($y)!=4);
-
- my($day,$dow,$doy)=();
- $doy=&Date_DayOfYear($m,$d,$y);
-
- # The current DayOfYear and DayOfWeek
- if ($Cnf{"Jan1Week1"}) {
- $day=1;
- } else {
- $day=4;
- }
- $dow=&Date_DayOfWeek(1,$day,$y);
-
- # Move back to the first day of week 1.
- $f-=7 if ($f>$dow);
- $day-= ($dow-$f);
-
- return 0 if ($day>$doy); # Day is in last week of previous year
- return (($doy-$day)/7 + 1);
-}
-
-sub Date_LeapYear {
- print "DEBUG: Date_LeapYear\n" if ($Curr{"Debug"} =~ /trace/);
- my($y)=@_;
- $y=&Date_FixYear($y) if (length($y)!=4);
- return 0 unless $y % 4 == 0;
- return 1 unless $y % 100 == 0;
- return 0 unless $y % 400 == 0;
- return 1;
-}
-
-sub Date_DaySuffix {
- print "DEBUG: Date_DaySuffix\n" if ($Curr{"Debug"} =~ /trace/);
- my($d)=@_;
- &Date_Init() if (! $Curr{"InitDone"});
- return $Lang{$Cnf{"Language"}}{"DoML"}[$d-1];
-}
-
-sub Date_ConvTZ {
- print "DEBUG: Date_ConvTZ\n" if ($Curr{"Debug"} =~ /trace/);
- my($date,$from,$to)=@_;
- if (not Date_Split($date)) {
- croak "date passed in ('$date') is not a Date::Manip object";
- }
-
- &Date_Init() if (! $Curr{"InitDone"});
- my($gmt)=();
-
- if (! $from) {
-
- if (! $to) {
- # TZ -> ConvTZ
- return $date if ($Cnf{"ConvTZ"} eq "IGNORE" or ! $Cnf{"ConvTZ"});
- $from=$Cnf{"TZ"};
- $to=$Cnf{"ConvTZ"};
-
- } else {
- # ConvTZ,TZ -> $to
- $from=$Cnf{"ConvTZ"};
- $from=$Cnf{"TZ"} if (! $from);
- }
-
- } else {
-
- if (! $to) {
- # $from -> ConvTZ,TZ
- return $date if ($Cnf{"ConvTZ"} eq "IGNORE");
- $to=$Cnf{"ConvTZ"};
- $to=$Cnf{"TZ"} if (! $to);
-
- } else {
- # $from -> $to
- }
- }
-
- $to=$Zone{"n2o"}{lc($to)}
- if (exists $Zone{"n2o"}{lc($to)});
- $from=$Zone{"n2o"}{lc($from)}
- if (exists $Zone{"n2o"}{lc($from)});
- $gmt=$Zone{"n2o"}{"gmt"};
-
- return $date if ($from !~ /^[+-]\d{4}$/ or $to !~ /^[+-]\d{4}$/);
- return $date if ($from eq $to);
-
- my($s1,$h1,$m1,$s2,$h2,$m2,$d,$h,$m,$sign,$delta,$err,$yr,$mon,$sec)=();
- # We're going to try to do the calculation without calling DateCalc.
- ($yr,$mon,$d,$h,$m,$sec)=&Date_Split($date, 1);
-
- # Convert $date from $from to GMT
- $from=~/([+-])(\d{2})(\d{2})/;
- ($s1,$h1,$m1)=($1,$2,$3);
- $s1= ($s1 eq "-" ? "+" : "-"); # switch sign
- $sign=$s1 . "1"; # + or - 1
-
- # and from GMT to $to
- $to=~/([+-])(\d{2})(\d{2})/;
- ($s2,$h2,$m2)=($1,$2,$3);
-
- if ($s1 eq $s2) {
- # Both the same sign
- $m+= $sign*($m1+$m2);
- $h+= $sign*($h1+$h2);
- } else {
- $sign=($s2 eq "-" ? +1 : -1) if ($h1<$h2 || ($h1==$h2 && $m1<$m2));
- $m+= $sign*($m1-$m2);
- $h+= $sign*($h1-$h2);
- }
-
- if ($m>59) {
- $h+= $m/60;
- $m-= ($m/60)*60;
- } elsif ($m<0) {
- $h+= ($m/60 - 1);
- $m-= ($m/60 - 1)*60;
- }
-
- if ($h>23) {
- $delta=$h/24;
- $h -= $delta*24;
- if (($d + $delta) > 28) {
- $date=&Date_Join($yr,$mon,$d,$h,$m,$sec);
- return &DateCalc_DateDelta($date,"+0:0:0:$delta:0:0:0",\$err,0);
- }
- $d+= $delta;
- } elsif ($h<0) {
- $delta=-$h/24 + 1;
- $h += $delta*24;
- if (($d - $delta) < 1) {
- $date=&Date_Join($yr,$mon,$d,$h,$m,$sec);
- return &DateCalc_DateDelta($date,"-0:0:0:$delta:0:0:0",\$err,0);
- }
- $d-= $delta;
- }
- return &Date_Join($yr,$mon,$d,$h,$m,$sec);
-}
-
-sub Date_TimeZone {
- print "DEBUG: Date_TimeZone\n" if ($Curr{"Debug"} =~ /trace/);
- my($null,$tz,@tz,$std,$dst,$time,$isdst,$tmp,$in)=();
- &Date_Init() if (! $Curr{"InitDone"});
-
- # Get timezones from all of the relevant places
-
- push(@tz,$Cnf{"TZ"}) if (defined $Cnf{"TZ"}); # TZ config var
- push(@tz,$ENV{"TZ"}) if (defined $ENV{"TZ"}); # TZ environ var
- push(@tz,$ENV{'SYS$TIMEZONE_RULE'})
- if defined $ENV{'SYS$TIMEZONE_RULE'}; # VMS TZ environ var
- push(@tz,$ENV{'SYS$TIMEZONE_NAME'})
- if defined $ENV{'SYS$TIMEZONE_NAME'}; # VMS TZ name environ var
- push(@tz,$ENV{'UCX$TZ'})
- if defined $ENV{'UCX$TZ'}; # VMS TZ environ var
- push(@tz,$ENV{'TCPIP$TZ'})
- if defined $ENV{'TCPIP$TZ'}; # VMS TZ environ var
-
- # The `date` command... if we're doing taint checking, we need to
- # always call it with a full path... otherwise, use the user's path.
- #
- # Microsoft operating systems don't have a date command built in. Try
- # to trap all the various ways of knowing we are on one of these systems.
- #
- # We'll try `date +%Z` first, and if that fails, we'll take just the
- # `date` program and assume the output is of the format:
- # Thu Aug 31 14:57:46 EDT 2000
-
- unless (($^X =~ /perl\.exe$/i) or
- ($OS eq "Windows") or
- ($OS eq "Netware") or
- ($OS eq "VMS")) {
- if ($Date::Manip::NoTaint) {
- if ($OS eq "VMS") {
- $tz=$ENV{'SYS$TIMEZONE_NAME'};
- if (! $tz) {
- $tz=$ENV{'MULTINET_TIMEZONE'};
- if (! $tz) {
- $tz=$ENV{'SYS$TIMEZONE_DIFFERENTIAL'}/3600.; # e.g. '-4' for EDT
- }
- }
- } else {
- $tz=`date +%Z 2> /dev/null`;
- chomp($tz);
- if (! $tz) {
- $tz=`date 2> /dev/null`;
- chomp($tz);
- $tz=(split(/\s+/,$tz))[4];
- }
- }
- push(@tz,$tz);
- } else {
- # We need to satisfy taint checking, but also look in all the
- # directories in @DatePath.
- #
- local $ENV{PATH} = join(':', @Date::Manip::DatePath);
- local $ENV{BASH_ENV} = '';
- $tz=`date +%Z 2> /dev/null`;
- chomp($tz);
- if (! $tz) {
- $tz=`date 2> /dev/null`;
- chomp($tz);
- $tz=(split(/\s+/,$tz))[4];
- }
- push(@tz,$tz);
- }
- }
-
- push(@tz,$main::TZ) if (defined $main::TZ); # $main::TZ
-
- if (-s "/etc/TIMEZONE") { # /etc/TIMEZONE
- $in=new IO::File;
- $in->open("/etc/TIMEZONE","r");
- while (! eof($in)) {
- $tmp=<$in>;
- if ($tmp =~ /^TZ\s*=\s*(.*?)\s*$/) {
- push(@tz,$1);
- last;
- }
- }
- $in->close;
- }
-
- if (-s "/etc/timezone") { # /etc/timezone
- $in=new IO::File;
- $in->open("/etc/timezone","r");
- while (! eof($in)) {
- $tmp=<$in>;
- next if ($tmp =~ /^\s*\043/);
- chomp($tmp);
- if ($tmp =~ /^\s*(.*?)\s*$/) {
- push(@tz,$1);
- last;
- }
- }
- $in->close;
- }
-
- # Now parse each one to find the first valid one.
- foreach $tz (@tz) {
- $tz =~ s/\s*$//;
- $tz =~ s/^\s*//;
- next if (! $tz);
-
- return uc($tz)
- if (defined $Zone{"n2o"}{lc($tz)});
-
- if ($tz =~ /^[+-]\d{4}$/) {
- return $tz;
- } elsif ($tz =~ /^([+-]\d{2})(?::(\d{2}))?$/) {
- my($h,$m)=($1,$2);
- $m="00" if (! $m);
- return "$h$m";
- }
-
- # Handle US/Eastern format
- if ($tz =~ /^$Zone{"tzones"}$/i) {
- $tmp=lc $1;
- $tz=$Zone{"tz2z"}{$tmp};
- }
-
- # Handle STD#DST# format (and STD-#DST-# formats)
- if ($tz =~ /^([a-z]+)-?\d([a-z]+)-?\d?$/i) {
- ($std,$dst)=($1,$2);
- next if (! defined $Zone{"n2o"}{lc($std)} or
- ! defined $Zone{"n2o"}{lc($dst)});
- $time = time();
- ($null,$null,$null,$null,$null,$null,$null,$null,$isdst) =
- localtime($time);
- return uc($dst) if ($isdst);
- return uc($std);
- }
- }
-
- confess "ERROR: Date::Manip unable to determine TimeZone.\n";
-}
-
-# Returns 1 if $date is a work day. If $time is non-zero, the time is
-# also checked to see if it falls within work hours. Returns "" if
-# an invalid date is passed in.
-sub Date_IsWorkDay {
- print "DEBUG: Date_IsWorkDay\n" if ($Curr{"Debug"} =~ /trace/);
- my($date,$time)=@_;
- &Date_Init() if (! $Curr{"InitDone"});
- $date=&ParseDateString($date);
- return "" if (! $date);
- my($d)=$date;
- $d=&Date_SetTime($date,$Cnf{"WorkDayBeg"}) if (! $time);
-
- my($y,$mon,$day,$tmp,$h,$m,$dow)=();
- ($y,$mon,$day,$h,$m,$tmp)=&Date_Split($d, 1);
- $dow=&Date_DayOfWeek($mon,$day,$y);
-
- return 0 if ($dow<$Cnf{"WorkWeekBeg"} or
- $dow>$Cnf{"WorkWeekEnd"} or
- "$h:$m" lt $Cnf{"WorkDayBeg"} or
- "$h:$m" gt $Cnf{"WorkDayEnd"});
-
- if (! exists $Holiday{"dates"}{$y}) {
- # There will be recursion problems if we ever end up here twice.
- $Holiday{"dates"}{$y}={};
- &Date_UpdateHolidays($y)
- }
- $d=&Date_SetTime($date,"00:00:00");
- return 0 if (exists $Holiday{"dates"}{$y}{$d});
- 1;
-}
-
-# Finds the day $off work days from now. If $time is passed in, we must
-# also take into account the time of day.
-#
-# If $time is not passed in, day 0 is today (if today is a workday) or the
-# next work day if it isn't. In any case, the time of day is unaffected.
-#
-# If $time is passed in, day 0 is now (if now is part of a workday) or the
-# start of the very next work day.
-sub Date_NextWorkDay {
- print "DEBUG: Date_NextWorkDay\n" if ($Curr{"Debug"} =~ /trace/);
- my($date,$off,$time)=@_;
- &Date_Init() if (! $Curr{"InitDone"});
- $date=&ParseDateString($date);
- my($err)=();
-
- if (! &Date_IsWorkDay($date,$time)) {
- if ($time) {
- while (1) {
- $date=&Date_GetNext($date,undef,0,$Cnf{"WorkDayBeg"});
- last if (&Date_IsWorkDay($date,$time));
- }
- } else {
- while (1) {
- $date=&DateCalc_DateDelta($date,"+0:0:0:1:0:0:0",\$err,0);
- last if (&Date_IsWorkDay($date,$time));
- }
- }
- }
-
- while ($off>0) {
- while (1) {
- $date=&DateCalc_DateDelta($date,"+0:0:0:1:0:0:0",\$err,0);
- last if (&Date_IsWorkDay($date,$time));
- }
- $off--;
- }
-
- return $date;
-}
-
-# Finds the day $off work days before now. If $time is passed in, we must
-# also take into account the time of day.
-#
-# If $time is not passed in, day 0 is today (if today is a workday) or the
-# previous work day if it isn't. In any case, the time of day is unaffected.
-#
-# If $time is passed in, day 0 is now (if now is part of a workday) or the
-# end of the previous work period. Note that since the end of a work day
-# will automatically be turned into the start of the next one, this time
-# may actually be treated as AFTER the current time.
-sub Date_PrevWorkDay {
- print "DEBUG: Date_PrevWorkDay\n" if ($Curr{"Debug"} =~ /trace/);
- my($date,$off,$time)=@_;
- &Date_Init() if (! $Curr{"InitDone"});
- $date=&ParseDateString($date);
- my($err)=();
-
- if (! &Date_IsWorkDay($date,$time)) {
- if ($time) {
- while (1) {
- $date=&Date_GetPrev($date,undef,0,$Cnf{"WorkDayEnd"});
- last if (&Date_IsWorkDay($date,$time));
- }
- while (1) {
- $date=&Date_GetNext($date,undef,0,$Cnf{"WorkDayBeg"});
- last if (&Date_IsWorkDay($date,$time));
- }
- } else {
- while (1) {
- $date=&DateCalc_DateDelta($date,"-0:0:0:1:0:0:0",\$err,0);
- last if (&Date_IsWorkDay($date,$time));
- }
- }
- }
-
- while ($off>0) {
- while (1) {
- $date=&DateCalc_DateDelta($date,"-0:0:0:1:0:0:0",\$err,0);
- last if (&Date_IsWorkDay($date,$time));
- }
- $off--;
- }
-
- return $date;
-}
-
-# This finds the nearest workday to $date. If $date is a workday, it
-# is returned.
-sub Date_NearestWorkDay {
- print "DEBUG: Date_NearestWorkDay\n" if ($Curr{"Debug"} =~ /trace/);
- my($date,$tomorrow)=@_;
- &Date_Init() if (! $Curr{"InitDone"});
- $date=&ParseDateString($date);
- my($a,$b,$dela,$delb,$err)=();
- $tomorrow=$Cnf{"TomorrowFirst"} if (! defined $tomorrow);
-
- return $date if (&Date_IsWorkDay($date));
-
- # Find the nearest one.
- if ($tomorrow) {
- $dela="+0:0:0:1:0:0:0";
- $delb="-0:0:0:1:0:0:0";
- } else {
- $dela="-0:0:0:1:0:0:0";
- $delb="+0:0:0:1:0:0:0";
- }
- $a=$b=$date;
-
- while (1) {
- $a=&DateCalc_DateDelta($a,$dela,\$err);
- return $a if (&Date_IsWorkDay($a));
- $b=&DateCalc_DateDelta($b,$delb,\$err);
- return $b if (&Date_IsWorkDay($b));
- }
-}
-
-# &Date_NthDayOfYear($y,$n);
-# Returns a list of (YYYY,MM,DD,HH,MM,SS) for the Nth day of the year.
-sub Date_NthDayOfYear {
- no integer;
- print "DEBUG: Date_NthDayOfYear\n" if ($Curr{"Debug"} =~ /trace/);
- my($y,$n)=@_;
- $y=$Curr{"Y"} if (! $y);
- $n=1 if (! defined $n or $n eq "");
- $n+=0; # to turn 023 into 23
- $y=&Date_FixYear($y) if (length($y)<4);
- my $leap=&Date_LeapYear($y);
- return () if ($n<1);
- return () if ($n >= ($leap ? 367 : 366));
-
- my(@d_in_m)=(31,28,31,30,31,30,31,31,30,31,30,31);
- $d_in_m[1]=29 if ($leap);
-
- # Calculate the hours, minutes, and seconds into the day.
- my $remain=($n - int($n))*24;
- my $h=int($remain);
- $remain=($remain - $h)*60;
- my $mn=int($remain);
- $remain=($remain - $mn)*60;
- my $s=$remain;
-
- # Calculate the month and the day.
- my($m,$d)=(0,0);
- $n=int($n);
- while ($n>0) {
- $m++;
- if ($n<=$d_in_m[0]) {
- $d=int($n);
- $n=0;
- } else {
- $n-= $d_in_m[0];
- shift(@d_in_m);
- }
- }
-
- ($y,$m,$d,$h,$mn,$s);
-}
-
-########################################################################
-# NOT FOR EXPORT
-########################################################################
-
-# This is used in Date_Init to fill in a hash based on international
-# data. It takes a list of keys and values and returns both a hash
-# with these values and a regular expression of keys.
-#
-# IN:
-# $data = [ key1 val1 key2 val2 ... ]
-# $opts = lc : lowercase the keys in the regexp
-# sort : sort (by length) the keys in the regexp
-# back : create a regexp with a back reference
-# escape : escape all strings in the regexp
-#
-# OUT:
-# $regexp = '(?:key1|key2|...)'
-# $hash = { key1=>val1 key2=>val2 ... }
-
-sub Date_InitHash {
- print "DEBUG: Date_InitHash\n" if ($Curr{"Debug"} =~ /trace/);
- my($data,$regexp,$opts,$hash)=@_;
- my(@data)=@$data;
- my($key,$val,@list)=();
-
- # Parse the options
- my($lc,$sort,$back,$escape)=(0,0,0,0);
- $lc=1 if ($opts =~ /lc/i);
- $sort=1 if ($opts =~ /sort/i);
- $back=1 if ($opts =~ /back/i);
- $escape=1 if ($opts =~ /escape/i);
-
- # Create the hash
- while (@data) {
- ($key,$val,@data)=@data;
- $key=lc($key) if ($lc);
- $$hash{$key}=$val;
- }
-
- # Create the regular expression
- if ($regexp) {
- @list=keys(%$hash);
- @list=sort sortByLength(@list) if ($sort);
- if ($escape) {
- foreach $val (@list) {
- $val="\Q$val\E";
- }
- }
- if ($back) {
- $$regexp="(" . join("|",@list) . ")";
- } else {
- $$regexp="(?:" . join("|",@list) . ")";
- }
- }
-}
-
-# This is used in Date_Init to fill in regular expressions, lists, and
-# hashes based on international data. It takes a list of lists which have
-# to be stored as regular expressions (to find any element in the list),
-# lists, and hashes (indicating the location in the lists).
-#
-# IN:
-# $data = [ [ [ valA1 valA2 ... ][ valA1' valA2' ... ] ... ]
-# [ [ valB1 valB2 ... ][ valB1' valB2' ... ] ... ]
-# ...
-# [ [ valZ1 valZ2 ... ] [valZ1' valZ1' ... ] ... ] ]
-# $lists = [ \@listA \@listB ... \@listZ ]
-# $opts = lc : lowercase the values in the regexp
-# sort : sort (by length) the values in the regexp
-# back : create a regexp with a back reference
-# escape : escape all strings in the regexp
-# $hash = [ \%hash, TYPE ]
-# TYPE 0 : $hash{ valBn=>n-1 }
-# TYPE 1 : $hash{ valBn=>n }
-#
-# OUT:
-# $regexp = '(?:valA1|valA2|...|valB1|...)'
-# $lists = [ [ valA1 valA2 ... ] # only the 1st list (or
-# [ valB1 valB2 ... ] ... ] # 2nd for int. characters)
-# $hash
-
-sub Date_InitLists {
- print "DEBUG: Date_InitLists\n" if ($Curr{"Debug"} =~ /trace/);
- my($data,$regexp,$opts,$lists,$hash)=@_;
- my(@data)=@$data;
- my(@lists)=@$lists;
- my($i,@ele,$ele,@list,$j,$tmp)=();
-
- # Parse the options
- my($lc,$sort,$back,$escape)=(0,0,0,0);
- $lc=1 if ($opts =~ /lc/i);
- $sort=1 if ($opts =~ /sort/i);
- $back=1 if ($opts =~ /back/i);
- $escape=1 if ($opts =~ /escape/i);
-
- # Set each of the lists
- if (@lists) {
- confess "ERROR: Date_InitLists: lists must be 1 per data\n"
- if ($#lists != $#data);
- for ($i=0; $i<=$#data; $i++) {
- @ele=@{ $data[$i] };
- if ($Cnf{"IntCharSet"} && $#ele>0) {
- @{ $lists[$i] } = @{ $ele[1] };
- } else {
- @{ $lists[$i] } = @{ $ele[0] };
- }
- }
- }
-
- # Create the hash
- my($hashtype,$hashsave,%hash)=();
- if (@$hash) {
- ($hash,$hashtype)=@$hash;
- $hashsave=1;
- } else {
- $hashtype=0;
- $hashsave=0;
- }
- for ($i=0; $i<=$#data; $i++) {
- @ele=@{ $data[$i] };
- foreach $ele (@ele) {
- @list = @{ $ele };
- for ($j=0; $j<=$#list; $j++) {
- $tmp=$list[$j];
- next if (! $tmp);
- $tmp=lc($tmp) if ($lc);
- $hash{$tmp}= $j+$hashtype;
- }
- }
- }
- %$hash = %hash if ($hashsave);
-
- # Create the regular expression
- if ($regexp) {
- @list=keys(%hash);
- @list=sort sortByLength(@list) if ($sort);
- if ($escape) {
- foreach $ele (@list) {
- $ele="\Q$ele\E";
- }
- }
- if ($back) {
- $$regexp="(" . join("|",@list) . ")";
- } else {
- $$regexp="(?:" . join("|",@list) . ")";
- }
- }
-}
-
-# This is used in Date_Init to fill in regular expressions and lists based
-# on international data. This takes a list of strings and returns a regular
-# expression (to find any one of them).
-#
-# IN:
-# $data = [ string1 string2 ... ]
-# $opts = lc : lowercase the values in the regexp
-# sort : sort (by length) the values in the regexp
-# back : create a regexp with a back reference
-# escape : escape all strings in the regexp
-#
-# OUT:
-# $regexp = '(string1|string2|...)'
-
-sub Date_InitStrings {
- print "DEBUG: Date_InitStrings\n" if ($Curr{"Debug"} =~ /trace/);
- my($data,$regexp,$opts)=@_;
- my(@list)=@{ $data };
-
- # Parse the options
- my($lc,$sort,$back,$escape)=(0,0,0,0);
- $lc=1 if ($opts =~ /lc/i);
- $sort=1 if ($opts =~ /sort/i);
- $back=1 if ($opts =~ /back/i);
- $escape=1 if ($opts =~ /escape/i);
-
- # Create the regular expression
- my($ele)=();
- @list=sort sortByLength(@list) if ($sort);
- if ($escape) {
- foreach $ele (@list) {
- $ele="\Q$ele\E";
- }
- }
- if ($back) {
- $$regexp="(" . join("|",@list) . ")";
- } else {
- $$regexp="(?:" . join("|",@list) . ")";
- }
- $$regexp=lc($$regexp) if ($lc);
-}
-
-# items is passed in (either as a space separated string, or a reference to
-# a list) and a regular expression which matches any one of the items is
-# prepared. The regular expression will be of one of the forms:
-# "(a|b)" @list not empty, back option included
-# "(?:a|b)" @list not empty
-# "()" @list empty, back option included
-# "" @list empty
-# $options is a string which contains any of the following strings:
-# back : the regular expression has a backreference
-# opt : the regular expression is optional and a "?" is appended in
-# the first two forms
-# optws : the regular expression is optional and may be replaced by
-# whitespace
-# optWs : the regular expression is optional, but if not present, must
-# be replaced by whitespace
-# sort : the items in the list are sorted by length (longest first)
-# lc : the string is lowercased
-# under : any underscores are converted to spaces
-# pre : it may be preceded by whitespace
-# Pre : it must be preceded by whitespace
-# PRE : it must be preceded by whitespace or the start
-# post : it may be followed by whitespace
-# Post : it must be followed by whitespace
-# POST : it must be followed by whitespace or the end
-# Spaces due to pre/post options will not be included in the back reference.
-#
-# If $array is included, then the elements will also be returned as a list.
-# $array is a string which may contain any of the following:
-# keys : treat the list as a hash and only the keys go into the regexp
-# key0 : treat the list as the values of a hash with keys 0 .. N-1
-# key1 : treat the list as the values of a hash with keys 1 .. N
-# val0 : treat the list as the keys of a hash with values 0 .. N-1
-# val1 : treat the list as the keys of a hash with values 1 .. N
-
-# &Date_InitLists([$lang{"month_name"},$lang{"month_abb"}],
-# [\$Month,"lc,sort,back"],
-# [\@Month,\@Mon],
-# [\%Month,1]);
-
-# This is used in Date_Init to prepare regular expressions. A list of
-# items is passed in (either as a space separated string, or a reference to
-# a list) and a regular expression which matches any one of the items is
-# prepared. The regular expression will be of one of the forms:
-# "(a|b)" @list not empty, back option included
-# "(?:a|b)" @list not empty
-# "()" @list empty, back option included
-# "" @list empty
-# $options is a string which contains any of the following strings:
-# back : the regular expression has a backreference
-# opt : the regular expression is optional and a "?" is appended in
-# the first two forms
-# optws : the regular expression is optional and may be replaced by
-# whitespace
-# optWs : the regular expression is optional, but if not present, must
-# be replaced by whitespace
-# sort : the items in the list are sorted by length (longest first)
-# lc : the string is lowercased
-# under : any underscores are converted to spaces
-# pre : it may be preceded by whitespace
-# Pre : it must be preceded by whitespace
-# PRE : it must be preceded by whitespace or the start
-# post : it may be followed by whitespace
-# Post : it must be followed by whitespace
-# POST : it must be followed by whitespace or the end
-# Spaces due to pre/post options will not be included in the back reference.
-#
-# If $array is included, then the elements will also be returned as a list.
-# $array is a string which may contain any of the following:
-# keys : treat the list as a hash and only the keys go into the regexp
-# key0 : treat the list as the values of a hash with keys 0 .. N-1
-# key1 : treat the list as the values of a hash with keys 1 .. N
-# val0 : treat the list as the keys of a hash with values 0 .. N-1
-# val1 : treat the list as the keys of a hash with values 1 .. N
-sub Date_Regexp {
- print "DEBUG: Date_Regexp\n" if ($Curr{"Debug"} =~ /trace/);
- my($list,$options,$array)=@_;
- my(@list,$ret,%hash,$i)=();
- local($_)=();
- $options="" if (! defined $options);
- $array="" if (! defined $array);
-
- my($sort,$lc,$under)=(0,0,0);
- $sort =1 if ($options =~ /sort/i);
- $lc =1 if ($options =~ /lc/i);
- $under=1 if ($options =~ /under/i);
- my($back,$opt,$pre,$post,$ws)=("?:","","","","");
- $back ="" if ($options =~ /back/i);
- $opt ="?" if ($options =~ /opt/i);
- $pre ='\s*' if ($options =~ /pre/);
- $pre ='\s+' if ($options =~ /Pre/);
- $pre ='(?:\s+|^)' if ($options =~ /PRE/);
- $post ='\s*' if ($options =~ /post/);
- $post ='\s+' if ($options =~ /Post/);
- $post ='(?:$|\s+)' if ($options =~ /POST/);
- $ws ='\s*' if ($options =~ /optws/);
- $ws ='\s+' if ($options =~ /optws/);
-
- my($hash,$keys,$key0,$key1,$val0,$val1)=(0,0,0,0,0,0);
- $keys =1 if ($array =~ /keys/i);
- $key0 =1 if ($array =~ /key0/i);
- $key1 =1 if ($array =~ /key1/i);
- $val0 =1 if ($array =~ /val0/i);
- $val1 =1 if ($array =~ /val1/i);
- $hash =1 if ($keys or $key0 or $key1 or $val0 or $val1);
-
- my($ref)=ref $list;
- if (! $ref) {
- $list =~ s/\s*$//;
- $list =~ s/^\s*//;
- $list =~ s/\s+/&&&/g;
- } elsif ($ref eq "ARRAY") {
- $list = join("&&&",@$list);
- } else {
- confess "ERROR: Date_Regexp.\n";
- }
-
- if (! $list) {
- if ($back eq "") {
- return "()";
- } else {
- return "";
- }
- }
-
- $list=lc($list) if ($lc);
- $list=~ s/_/ /g if ($under);
- @list=split(/&&&/,$list);
- if ($keys) {
- %hash=@list;
- @list=keys %hash;
- } elsif ($key0 or $key1 or $val0 or $val1) {
- $i=0;
- $i=1 if ($key1 or $val1);
- if ($key0 or $key1) {
- %hash= map { $_,$i++ } @list;
- } else {
- %hash= map { $i++,$_ } @list;
- }
- }
- @list=sort sortByLength(@list) if ($sort);
-
- $ret="($back" . join("|",@list) . ")";
- $ret="(?:$pre$ret$post)" if ($pre or $post);
- $ret.=$opt;
- $ret="(?:$ret|$ws)" if ($ws);
-
- if ($array and $hash) {
- return ($ret,%hash);
- } elsif ($array) {
- return ($ret,@list);
- } else {
- return $ret;
- }
-}
-
-# This will produce a delta with the correct number of signs. At most two
-# signs will be in it normally (one before the year, and one in front of
-# the day), but if appropriate, signs will be in front of all elements.
-# Also, as many of the signs will be equivalent as possible.
-sub Delta_Normalize {
- print "DEBUG: Delta_Normalize\n" if ($Curr{"Debug"} =~ /trace/);
- my($delta,$mode)=@_;
- return "" if (! $delta);
- return "+0:+0:+0:+0:+0:+0:+0"
- if ($delta =~ /^([+-]?0+:){6}[+-]?0+$/ and $Cnf{"DeltaSigns"});
- return "+0:0:0:0:0:0:0" if ($delta =~ /^([+-]?0+:){6}[+-]?0+$/);
-
- my($tmp,$sign1,$sign2,$len)=();
-
- # Calculate the length of the day in minutes
- $len=24*60;
- $len=$Curr{"WDlen"} if ($mode==2 || $mode==3);
-
- # We have to get the sign of every component explicitely so that a "-0"
- # or "+0" doesn't get lost by treating it numerically (i.e. "-0:0:2" must
- # be a negative delta).
-
- my($y,$mon,$w,$d,$h,$m,$s)=&Delta_Split($delta);
-
- # We need to make sure that the signs of all parts of a delta are the
- # same. The easiest way to do this is to convert all of the large
- # components to the smallest ones, then convert the smaller components
- # back to the larger ones.
-
- # Do the year/month part
-
- $mon += $y*12; # convert y to m
- $sign1="+";
- if ($mon<0) {
- $mon *= -1;
- $sign1="-";
- }
-
- $y = $mon/12; # convert m to y
- $mon -= $y*12;
-
- $y=0 if ($y eq "-0"); # get around silly -0 problem
- $mon=0 if ($mon eq "-0");
-
- # Do the wk/day/hour/min/sec part
-
- {
- # Unfortunately, $s is overflowing for dates more than ~70 years
- # apart.
- no integer;
-
- if ($mode==3 || $mode==2) {
- $s += $d*$len*60 + $h*3600 + $m*60; # convert d/h/m to s
- } else {
- $s += ($d+7*$w)*$len*60 + $h*3600 + $m*60; # convert w/d/h/m to s
- }
- $sign2="+";
- if ($s<0) {
- $s*=-1;
- $sign2="-";
- }
-
- $m = int($s/60); # convert s to m
- $s -= $m*60;
- $d = int($m/$len); # convert m to d
- $m -= $d*$len;
-
- # The rest should be fine.
- }
- $h = $m/60; # convert m to h
- $m -= $h*60;
- if ($mode == 3 || $mode == 2) {
- $w = $w*1; # get around +0 problem
- } else {
- $w = $d/7; # convert d to w
- $d -= $w*7;
- }
-
- $w=0 if ($w eq "-0"); # get around silly -0 problem
- $d=0 if ($d eq "-0");
- $h=0 if ($h eq "-0");
- $m=0 if ($m eq "-0");
- $s=0 if ($s eq "-0");
-
- # Only include two signs if necessary
- $sign1=$sign2 if ($y==0 and $mon==0);
- $sign2=$sign1 if ($w==0 and $d==0 and $h==0 and $m==0 and $s==0);
- $sign2="" if ($sign1 eq $sign2 and ! $Cnf{"DeltaSigns"});
-
- if ($Cnf{"DeltaSigns"}) {
- return "$sign1$y:$sign1$mon:$sign2$w:$sign2$d:$sign2$h:$sign2$m:$sign2$s";
- } else {
- return "$sign1$y:$mon:$sign2$w:$d:$h:$m:$s";
- }
-}
-
-# This checks a delta to make sure it is valid. If it is, it splits
-# it and returns the elements with a sign on each. The 2nd argument
-# specifies the default sign. Blank elements are set to 0. If the
-# third element is non-nil, exactly 7 elements must be included.
-sub Delta_Split {
- print "DEBUG: Delta_Split\n" if ($Curr{"Debug"} =~ /trace/);
- my($delta,$sign,$exact)=@_;
- my(@delta)=split(/:/,$delta);
- return () if ($exact and $#delta != 6);
- my($i)=();
- $sign="+" if (! defined $sign);
- for ($i=0; $i<=$#delta; $i++) {
- $delta[$i]="0" if (! $delta[$i]);
- return () if ($delta[$i] !~ /^[+-]?\d+$/);
- $sign = ($delta[$i] =~ s/^([+-])// ? $1 : $sign);
- $delta[$i] = $sign.$delta[$i];
- }
- @delta;
-}
-
-# Reads up to 3 arguments. $h may contain the time in any international
-# format. Any empty elements are set to 0.
-sub Date_ParseTime {
- print "DEBUG: Date_ParseTime\n" if ($Curr{"Debug"} =~ /trace/);
- my($h,$m,$s)=@_;
- my($t)=&CheckTime("one");
-
- if (defined $h and $h =~ /$t/) {
- $h=$1;
- $m=$2;
- $s=$3 if (defined $3);
- }
- $h="00" if (! defined $h);
- $m="00" if (! defined $m);
- $s="00" if (! defined $s);
-
- ($h,$m,$s);
-}
-
-# Forms a date with the 6 elements passed in (all of which must be defined).
-# No check as to validity is made.
-sub Date_Join {
- print "DEBUG: Date_Join\n" if ($Curr{"Debug"} =~ /trace/);
- foreach (0 .. $#_) {
- croak "undefined arg $_ to Date_Join()" if not defined $_[$_];
- }
- my($y,$m,$d,$h,$mn,$s)=@_;
- my($ym,$md,$dh,$hmn,$mns)=();
-
- if ($Cnf{"Internal"} == 0) {
- $ym=$md=$dh="";
- $hmn=$mns=":";
-
- } elsif ($Cnf{"Internal"} == 1) {
- $ym=$md=$dh=$hmn=$mns="";
-
- } elsif ($Cnf{"Internal"} == 2) {
- $ym=$md="-";
- $dh=" ";
- $hmn=$mns=":";
-
- } else {
- confess "ERROR: Invalid internal format in Date_Join.\n";
- }
- $m="0$m" if (length($m)==1);
- $d="0$d" if (length($d)==1);
- $h="0$h" if (length($h)==1);
- $mn="0$mn" if (length($mn)==1);
- $s="0$s" if (length($s)==1);
- "$y$ym$m$md$d$dh$h$hmn$mn$mns$s";
-}
-
-# This checks a time. If it is valid, it splits it and returns 3 elements.
-# If "one" or "two" is passed in, a regexp with 1/2 or 2 digit hours is
-# returned.
-sub CheckTime {
- print "DEBUG: CheckTime\n" if ($Curr{"Debug"} =~ /trace/);
- my($time)=@_;
- my($h)='(?:0?[0-9]|1[0-9]|2[0-3])';
- my($h2)='(?:0[0-9]|1[0-9]|2[0-3])';
- my($m)='[0-5][0-9]';
- my($s)=$m;
- my($hm)="(?:". $Lang{$Cnf{"Language"}}{"SepHM"} ."|:)";
- my($ms)="(?:". $Lang{$Cnf{"Language"}}{"SepMS"} ."|:)";
- my($ss)=$Lang{$Cnf{"Language"}}{"SepSS"};
- my($t)="^($h)$hm($m)(?:$ms($s)(?:$ss\\d+)?)?\$";
- if ($time eq "one") {
- return $t;
- } elsif ($time eq "two") {
- $t="^($h2)$hm($m)(?:$ms($s)(?:$ss\\d+)?)?\$";
- return $t;
- }
-
- if ($time =~ /$t/i) {
- ($h,$m,$s)=($1,$2,$3);
- $h="0$h" if (length($h)<2);
- $m="0$m" if (length($m)<2);
- $s="00" if (! defined $s);
- return ($h,$m,$s);
- } else {
- return ();
- }
-}
-
-# This checks a recurrence. If it is valid, it splits it and returns the
-# elements. Otherwise, it returns an empty list.
-# ($recur0,$recur1,$flags,$dateb,$date0,$date1)=&Recur_Split($recur);
-sub Recur_Split {
- print "DEBUG: Recur_Split\n" if ($Curr{"Debug"} =~ /trace/);
- my($recur)=@_;
- my(@ret,@tmp);
-
- my($R) = '(\*?(?:[-,0-9]+[:\*]){6}[-,0-9]+)';
- my($F) = '(?:\*([^*]*))';
- my($DB,$D0,$D1);
- $DB=$D0=$D1=$F;
-
- if ($recur =~ /^$R$F?$DB?$D0?$D1?$/) {
- @ret=($1,$2,$3,$4,$5);
- @tmp=split(/\*/,shift(@ret));
- return () if ($#tmp>1);
- return (@tmp,"",@ret) if ($#tmp==0);
- return (@tmp,@ret);
- }
- return ();
-}
-
-# This checks a date. If it is valid, it splits it and returns the elements.
-# If no date is passed in, it returns a regular expression for the date.
-#
-# The optional second argument says 'I really expect this to be a
-# valid Date::Manip object, please throw an exception if it is
-# not'. Otherwise, errors are signalled by returning ().
-#
-sub Date_Split {
- print "DEBUG: Date_Split\n" if ($Curr{"Debug"} =~ /trace/);
- my($date, $definitely_valid)=@_;
- $definitely_valid = 0 if not defined $definitely_valid;
- my($ym,$md,$dh,$hmn,$mns)=();
- my($y)='(\d{4})';
- my($m)='(0[1-9]|1[0-2])';
- my($d)='(0[1-9]|[1-2][0-9]|3[0-1])';
- my($h)='([0-1][0-9]|2[0-3])';
- my($mn)='([0-5][0-9])';
- my($s)=$mn;
-
- if ($Cnf{"Internal"} == 0) {
- $ym=$md=$dh="";
- $hmn=$mns=":";
-
- } elsif ($Cnf{"Internal"} == 1) {
- $ym=$md=$dh=$hmn=$mns="";
-
- } elsif ($Cnf{"Internal"} == 2) {
- $ym=$md="-";
- $dh=" ";
- $hmn=$mns=":";
-
- } else {
- confess "ERROR: Invalid internal format in Date_Split.\n";
- }
-
- my($t)="^$y$ym$m$md$d$dh$h$hmn$mn$mns$s\$";
-
- if (not defined $date or $date eq '') {
- if ($definitely_valid) {
- die "bad date '$date'";
- } else {
- return $t;
- }
- }
-
- if ($date =~ /$t/) {
- ($y,$m,$d,$h,$mn,$s)=($1,$2,$3,$4,$5,$6);
- my(@d_in_m)=(0,31,28,31,30,31,30,31,31,30,31,30,31);
- $d_in_m[2]=29 if (&Date_LeapYear($y));
- if ($d>$d_in_m[$m]) {
- my $msg = "invalid date $date: day $d of month $m, but only $d_in_m[$m] days in that month";
- if ($definitely_valid) {
- die $msg;
- }
- else {
- warn $msg;
- return ();
- }
- }
- return ($y,$m,$d,$h,$mn,$s);
- }
-
- if ($definitely_valid) {
- die "invalid date $date: doesn't match regexp $t";
- }
- return ();
-}
-
-# This returns the date easter occurs on for a given year as ($month,$day).
-# This is from the Calendar FAQ.
-sub Date_Easter {
- my($y)=@_;
- $y=&Date_FixYear($y) if (length($y)==2);
-
- my($c) = $y/100;
- my($g) = $y % 19;
- my($k) = ($c-17)/25;
- my($i) = ($c - $c/4 - ($c-$k)/3 + 19*$g + 15) % 30;
- $i = $i - ($i/28)*(1 - ($i/28)*(29/($i+1))*((21-$g)/11));
- my($j) = ($y + $y/4 + $i + 2 - $c + $c/4) % 7;
- my($l) = $i-$j;
- my($m) = 3 + ($l+40)/44;
- my($d) = $l + 28 - 31*($m/4);
- return ($m,$d);
-}
-
-# This takes a list of years, months, WeekOfMonth's, and optionally
-# DayOfWeek's, and returns a list of dates. Optionally, a list of dates
-# can be passed in as the 1st argument (with the 2nd argument the null list)
-# and the year/month of these will be used.
-#
-# If $FDn is non-zero, the first week of the month contains the first
-# occurence of this day (1=Monday). If $FIn is non-zero, the first week of
-# the month contains the date (i.e. $FIn'th day of the month).
-sub Date_Recur_WoM {
- my($y,$m,$w,$d,$FDn,$FIn)=@_;
- my(@y)=@$y;
- my(@m)=@$m;
- my(@w)=@$w;
- my(@d)=@$d;
- my($date0,$date1,@tmp,@date,$d0,$d1,@tmp2)=();
-
- if (@m) {
- @tmp=();
- foreach $y (@y) {
- return () if (length($y)==1 || length($y)==3 || ! &IsInt($y,0,9999));
- $y=&Date_FixYear($y) if (length($y)==2);
- push(@tmp,$y);
- }
- @y=sort { $a<=>$b } (@tmp);
-
- return () if (! @m);
- foreach $m (@m) {
- return () if (! &IsInt($m,1,12));
- }
- @m=sort { $a<=>$b } (@m);
-
- @tmp=@tmp2=();
- foreach $y (@y) {
- foreach $m (@m) {
- push(@tmp,$y);
- push(@tmp2,$m);
- }
- }
-
- @y=@tmp;
- @m=@tmp2;
-
- } else {
- foreach $d0 (@y) {
- @tmp=&Date_Split($d0);
- return () if (! @tmp);
- push(@tmp2,$tmp[0]);
- push(@m,$tmp[1]);
- }
- @y=@tmp2;
- }
-
- return () if (! @w);
- foreach $w (@w) {
- return () if ($w==0 || ! &IsInt($w,-5,5));
- }
-
- if (@d) {
- foreach $d (@d) {
- return () if (! &IsInt($d,1,7));
- }
- @d=sort { $a<=>$b } (@d);
- }
-
- @date=();
- foreach $y (@y) {
- $m=shift(@m);
-
- # Find 1st day of this month and next month
- $date0=&Date_Join($y,$m,1,0,0,0);
- $date1=&DateCalc($date0,"+0:1:0:0:0:0:0");
-
- if (@d) {
- foreach $d (@d) {
- # Find 1st occurence of DOW (in both months)
- $d0=&Date_GetNext($date0,$d,1);
- $d1=&Date_GetNext($date1,$d,1);
-
- @tmp=();
- while (&Date_Cmp($d0,$d1)<0) {
- push(@tmp,$d0);
- $d0=&DateCalc($d0,"+0:0:1:0:0:0:0");
- }
-
- @tmp2=();
- foreach $w (@w) {
- if ($w>0) {
- push(@tmp2,$tmp[$w-1]);
- } else {
- push(@tmp2,$tmp[$#tmp+1+$w]);
- }
- }
- @tmp2=sort(@tmp2);
- push(@date,@tmp2);
- }
-
- } else {
- # Find 1st day of 1st week
- if ($FDn != 0) {
- $date0=&Date_GetNext($date0,$FDn,1);
- } else {
- $date0=&Date_Join($y,$m,$FIn,0,0,0);
- }
- $date0=&Date_GetPrev($date0,$Cnf{"FirstDay"},1);
-
- # Find 1st day of 1st week of next month
- if ($FDn != 0) {
- $date1=&Date_GetNext($date1,$FDn,1);
- } else {
- $date1=&DateCalc($date1,"+0:0:0:".($FIn-1).":0:0:0") if ($FIn>1);
- }
- $date1=&Date_GetPrev($date1,$Cnf{"FirstDay"},1);
-
- @tmp=();
- while (&Date_Cmp($date0,$date1)<0) {
- push(@tmp,$date0);
- $date0=&DateCalc($date0,"+0:0:1:0:0:0:0");
- }
-
- @tmp2=();
- foreach $w (@w) {
- if ($w>0) {
- push(@tmp2,$tmp[$w-1]);
- } else {
- push(@tmp2,$tmp[$#tmp+1+$w]);
- }
- }
- @tmp2=sort(@tmp2);
- push(@date,@tmp2);
- }
- }
-
- @date;
-}
-
-# This returns a sorted list of dates formed by adding/subtracting
-# $delta to $dateb in the range $date0<=$d<$dateb. The first date int
-# the list is actually the first date<$date0 and the last date in the
-# list is the first date>=$date1 (because sometimes the set part will
-# move the date back into the range).
-sub Date_Recur {
- my($date0,$date1,$dateb,$delta)=@_;
- my(@ret,$d)=();
-
- while (&Date_Cmp($dateb,$date0)<0) {
- $dateb=&DateCalc_DateDelta($dateb,$delta);
- }
- while (&Date_Cmp($dateb,$date1)>=0) {
- $dateb=&DateCalc_DateDelta($dateb,"-$delta");
- }
-
- # Add the dates $date0..$dateb
- $d=$dateb;
- while (&Date_Cmp($d,$date0)>=0) {
- unshift(@ret,$d);
- $d=&DateCalc_DateDelta($d,"-$delta");
- }
- # Add the first date earler than the range
- unshift(@ret,$d);
-
- # Add the dates $dateb..$date1
- $d=&DateCalc_DateDelta($dateb,$delta);
- while (&Date_Cmp($d,$date1)<0) {
- push(@ret,$d);
- $d=&DateCalc_DateDelta($d,$delta);
- }
- # Add the first date later than the range
- push(@ret,$d);
-
- @ret;
-}
-
-# This sets the values in each date of a recurrence.
-#
-# $h,$m,$s can each be values or lists "1-2,4". If any are equal to "-1",
-# they are not set (and none of the larger elements are set).
-sub Date_RecurSetTime {
- my($date0,$date1,$dates,$h,$m,$s)=@_;
- my(@dates)=@$dates;
- my(@h,@m,@s,$date,@tmp)=();
-
- $m="-1" if ($s eq "-1");
- $h="-1" if ($m eq "-1");
-
- if ($h ne "-1") {
- @h=&ReturnList($h);
- return () if ! (@h);
- @h=sort { $a<=>$b } (@h);
-
- @tmp=();
- foreach $date (@dates) {
- foreach $h (@h) {
- push(@tmp,&Date_SetDateField($date,"h",$h,1));
- }
- }
- @dates=@tmp;
- }
-
- if ($m ne "-1") {
- @m=&ReturnList($m);
- return () if ! (@m);
- @m=sort { $a<=>$b } (@m);
-
- @tmp=();
- foreach $date (@dates) {
- foreach $m (@m) {
- push(@tmp,&Date_SetDateField($date,"mn",$m,1));
- }
- }
- @dates=@tmp;
- }
-
- if ($s ne "-1") {
- @s=&ReturnList($s);
- return () if ! (@s);
- @s=sort { $a<=>$b } (@s);
-
- @tmp=();
- foreach $date (@dates) {
- foreach $s (@s) {
- push(@tmp,&Date_SetDateField($date,"s",$s,1));
- }
- }
- @dates=@tmp;
- }
-
- @tmp=();
- foreach $date (@dates) {
- push(@tmp,$date) if (&Date_Cmp($date,$date0)>=0 &&
- &Date_Cmp($date,$date1)<0 &&
- &Date_Split($date));
- }
-
- @tmp;
-}
-
-sub DateCalc_DateDate {
- print "DEBUG: DateCalc_DateDate\n" if ($Curr{"Debug"} =~ /trace/);
- my($D1,$D2,$mode)=@_;
- my(@d_in_m)=(0,31,28,31,30,31,30,31,31,30,31,30,31);
- $mode=0 if (! defined $mode);
-
- # Exact mode
- if ($mode==0) {
- my($y1,$m1,$d1,$h1,$mn1,$s1)=&Date_Split($D1, 1);
- my($y2,$m2,$d2,$h2,$mn2,$s2)=&Date_Split($D2, 1);
- my($i,@delta,$d,$delta,$y)=();
-
- # form the delta for hour/min/sec
- $delta[4]=$h2-$h1;
- $delta[5]=$mn2-$mn1;
- $delta[6]=$s2-$s1;
-
- # form the delta for yr/mon/day
- $delta[0]=$delta[1]=0;
- $d=0;
- if ($y2>$y1) {
- $d=&Date_DaysInYear($y1) - &Date_DayOfYear($m1,$d1,$y1);
- $d+=&Date_DayOfYear($m2,$d2,$y2);
- for ($y=$y1+1; $y<$y2; $y++) {
- $d+= &Date_DaysInYear($y);
- }
- } elsif ($y2<$y1) {
- $d=&Date_DaysInYear($y2) - &Date_DayOfYear($m2,$d2,$y2);
- $d+=&Date_DayOfYear($m1,$d1,$y1);
- for ($y=$y2+1; $y<$y1; $y++) {
- $d+= &Date_DaysInYear($y);
- }
- $d *= -1;
- } else {
- $d=&Date_DayOfYear($m2,$d2,$y2) - &Date_DayOfYear($m1,$d1,$y1);
- }
- $delta[2]=0;
- $delta[3]=$d;
-
- for ($i=0; $i<7; $i++) {
- $delta[$i]="+".$delta[$i] if ($delta[$i]>=0);
- }
-
- $delta=join(":",@delta);
- $delta=&Delta_Normalize($delta,0);
- return $delta;
- }
-
- my($date1,$date2)=($D1,$D2);
- my($tmp,$sign,$err,@tmp)=();
-
- # make sure both are work days
- if ($mode==2 || $mode==3) {
- $date1=&Date_NextWorkDay($date1,0,1);
- $date2=&Date_NextWorkDay($date2,0,1);
- }
-
- # make sure date1 comes before date2
- if (&Date_Cmp($date1,$date2)>0) {
- $sign="-";
- $tmp=$date1;
- $date1=$date2;
- $date2=$tmp;
- } else {
- $sign="+";
- }
- if (&Date_Cmp($date1,$date2)==0) {
- return "+0:+0:+0:+0:+0:+0:+0" if ($Cnf{"DeltaSigns"});
- return "+0:0:0:0:0:0:0";
- }
-
- my($y1,$m1,$d1,$h1,$mn1,$s1)=&Date_Split($date1, 1);
- my($y2,$m2,$d2,$h2,$mn2,$s2)=&Date_Split($date2, 1);
- my($dy,$dm,$dw,$dd,$dh,$dmn,$ds,$ddd)=(0,0,0,0,0,0,0,0);
-
- if ($mode != 3) {
-
- # Do years
- $dy=$y2-$y1;
- $dm=0;
- if ($dy>0) {
- $tmp=&DateCalc_DateDelta($date1,"+$dy:0:0:0:0:0:0",\$err,0);
- if (&Date_Cmp($tmp,$date2)>0) {
- $dy--;
- $tmp=$date1;
- $tmp=&DateCalc_DateDelta($date1,"+$dy:0:0:0:0:0:0",\$err,0)
- if ($dy>0);
- $dm=12;
- }
- $date1=$tmp;
- }
-
- # Do months
- $dm+=$m2-$m1;
- if ($dm>0) {
- $tmp=&DateCalc_DateDelta($date1,"+0:$dm:0:0:0:0:0",\$err,0);
- if (&Date_Cmp($tmp,$date2)>0) {
- $dm--;
- $tmp=$date1;
- $tmp=&DateCalc_DateDelta($date1,"+0:$dm:0:0:0:0:0",\$err,0)
- if ($dm>0);
- }
- $date1=$tmp;
- }
-
- # At this point, check to see that we're on a business day again so that
- # Aug 3 (Monday) -> Sep 3 (Sunday) -> Sep 4 (Monday) = 1 month
- if ($mode==2) {
- if (! &Date_IsWorkDay($date1,0)) {
- $date1=&Date_NextWorkDay($date1,0,1);
- }
- }
- }
-
- # Do days
- if ($mode==2 || $mode==3) {
- $dd=0;
- while (1) {
- $tmp=&Date_NextWorkDay($date1,1,1);
- if (&Date_Cmp($tmp,$date2)<=0) {
- $dd++;
- $date1=$tmp;
- } else {
- last;
- }
- }
-
- } else {
- ($y1,$m1,$d1)=( &Date_Split($date1, 1) )[0..2];
- $dd=0;
- # If we're jumping across months, set $d1 to the first of the next month
- # (or possibly the 0th of next month which is equivalent to the last day
- # of this month)
- if ($m1!=$m2) {
- $d_in_m[2]=29 if (&Date_LeapYear($y1));
- $dd=$d_in_m[$m1]-$d1+1;
- $d1=1;
- $tmp=&DateCalc_DateDelta($date1,"+0:0:0:$dd:0:0:0",\$err,0);
- if (&Date_Cmp($tmp,$date2)>0) {
- $dd--;
- $d1--;
- $tmp=&DateCalc_DateDelta($date1,"+0:0:0:$dd:0:0:0",\$err,0);
- }
- $date1=$tmp;
- }
-
- $ddd=0;
- if ($d1<$d2) {
- $ddd=$d2-$d1;
- $tmp=&DateCalc_DateDelta($date1,"+0:0:0:$ddd:0:0:0",\$err,0);
- if (&Date_Cmp($tmp,$date2)>0) {
- $ddd--;
- $tmp=&DateCalc_DateDelta($date1,"+0:0:0:$ddd:0:0:0",\$err,0);
- }
- $date1=$tmp;
- }
- $dd+=$ddd;
- }
-
- # in business mode, make sure h1 comes before h2 (if not find delta between
- # now and end of day and move to start of next business day)
- $d1=( &Date_Split($date1, 1) )[2];
- $dh=$dmn=$ds=0;
- if ($mode==2 || $mode==3 and $d1 != $d2) {
- $tmp=&Date_SetTime($date1,$Cnf{"WorkDayEnd"});
- $tmp=&DateCalc_DateDelta($tmp,"+0:0:0:0:0:1:0")
- if ($Cnf{"WorkDay24Hr"});
- $tmp=&DateCalc_DateDate($date1,$tmp,0);
- ($tmp,$tmp,$tmp,$tmp,$dh,$dmn,$ds)=&Delta_Split($tmp);
- $date1=&Date_NextWorkDay($date1,1,0);
- $date1=&Date_SetTime($date1,$Cnf{"WorkDayBeg"});
- $d1=( &Date_Split($date1, 1) )[2];
- confess "ERROR: DateCalc DateDate Business.\n" if ($d1 != $d2);
- }
-
- # Hours, minutes, seconds
- $tmp=&DateCalc_DateDate($date1,$date2,0);
- @tmp=&Delta_Split($tmp);
- $dh += $tmp[4];
- $dmn += $tmp[5];
- $ds += $tmp[6];
-
- $tmp="$sign$dy:$dm:0:$dd:$dh:$dmn:$ds";
- &Delta_Normalize($tmp,$mode);
-}
-
-sub DateCalc_DeltaDelta {
- print "DEBUG: DateCalc_DeltaDelta\n" if ($Curr{"Debug"} =~ /trace/);
- my($D1,$D2,$mode)=@_;
- my(@delta1,@delta2,$i,$delta,@delta)=();
- $mode=0 if (! defined $mode);
-
- @delta1=&Delta_Split($D1);
- @delta2=&Delta_Split($D2);
- for ($i=0; $i<7; $i++) {
- $delta[$i]=$delta1[$i]+$delta2[$i];
- $delta[$i]="+".$delta[$i] if ($delta[$i]>=0);
- }
-
- $delta=join(":",@delta);
- $delta=&Delta_Normalize($delta,$mode);
- return $delta;
-}
-
-sub DateCalc_DateDelta {
- print "DEBUG: DateCalc_DateDelta\n" if ($Curr{"Debug"} =~ /trace/);
- my($D1,$D2,$errref,$mode)=@_;
- my($date)=();
- my(@d_in_m)=(0,31,28,31,30,31,30,31,31,30,31,30,31);
- my($h1,$m1,$h2,$m2,$len,$hh,$mm)=();
- $mode=0 if (! defined $mode);
-
- if ($mode==2 || $mode==3) {
- $h1=$Curr{"WDBh"};
- $m1=$Curr{"WDBm"};
- $h2=$Curr{"WDEh"};
- $m2=$Curr{"WDEm"};
- $hh=$h2-$h1;
- $mm=$m2-$m1;
- if ($mm<0) {
- $hh--;
- $mm+=60;
- }
- }
-
- # Date, delta
- my($y,$m,$d,$h,$mn,$s)=&Date_Split($D1, 1);
- my($dy,$dm,$dw,$dd,$dh,$dmn,$ds)=&Delta_Split($D2);
-
- # do the month/year part
- $y+=$dy;
- while (length($y)<4) {
- $y = "0$y";
- }
- &ModuloAddition(-12,$dm,\$m,\$y); # -12 means 1-12 instead of 0-11
- $d_in_m[2]=29 if (&Date_LeapYear($y));
-
- # if we have gone past the last day of a month, move the date back to
- # the last day of the month
- if ($d>$d_in_m[$m]) {
- $d=$d_in_m[$m];
- }
-
- # do the week part
- if ($mode==0 || $mode==1) {
- $dd += $dw*7;
- } else {
- $date=&DateCalc_DateDelta(&Date_Join($y,$m,$d,$h,$mn,$s),
- "+0:0:$dw:0:0:0:0",0);
- ($y,$m,$d,$h,$mn,$s)=&Date_Split($date, 1);
- }
-
- # in business mode, set the day to a work day at this point so the h/mn/s
- # stuff will work out
- if ($mode==2 || $mode==3) {
- $d=$d_in_m[$m] if ($d>$d_in_m[$m]);
- $date=&Date_NextWorkDay(&Date_Join($y,$m,$d,$h,$mn,$s),0,1);
- ($y,$m,$d,$h,$mn,$s)=&Date_Split($date, 1);
- }
-
- # seconds, minutes, hours
- &ModuloAddition(60,$ds,\$s,\$mn);
- if ($mode==2 || $mode==3) {
- while (1) {
- &ModuloAddition(60,$dmn,\$mn,\$h);
- $h+= $dh;
-
- if ($h>$h2 or $h==$h2 && $mn>$m2) {
- $dh=$h-$h2;
- $dmn=$mn-$m2;
- $h=$h1;
- $mn=$m1;
- $dd++;
-
- } elsif ($h<$h1 or $h==$h1 && $mn<$m1) {
- $dh=$h-$h1;
- $dmn=$m1-$mn;
- $h=$h2;
- $mn=$m2;
- $dd--;
-
- } elsif ($h==$h2 && $mn==$m2) {
- $dd++;
- $dh=-$hh;
- $dmn=-$mm;
-
- } else {
- last;
- }
- }
-
- } else {
- &ModuloAddition(60,$dmn,\$mn,\$h);
- &ModuloAddition(24,$dh,\$h,\$d);
- }
-
- # If we have just gone past the last day of the month, we need to make
- # up for this:
- if ($d>$d_in_m[$m]) {
- $dd+= $d-$d_in_m[$m];
- $d=$d_in_m[$m];
- }
-
- # days
- if ($mode==2 || $mode==3) {
- if ($dd>=0) {
- $date=&Date_NextWorkDay(&Date_Join($y,$m,$d,$h,$mn,$s),$dd,1);
- } else {
- $date=&Date_PrevWorkDay(&Date_Join($y,$m,$d,$h,$mn,$s),-$dd,1);
- }
- ($y,$m,$d,$h,$mn,$s)=&Date_Split($date, 1);
-
- } else {
- $d_in_m[2]=29 if (&Date_LeapYear($y));
- $d=$d_in_m[$m] if ($d>$d_in_m[$m]);
- $d += $dd;
- while ($d<1) {
- $m--;
- if ($m==0) {
- $m=12;
- $y--;
- if (&Date_LeapYear($y)) {
- $d_in_m[2]=29;
- } else {
- $d_in_m[2]=28;
- }
- }
- $d += $d_in_m[$m];
- }
- while ($d>$d_in_m[$m]) {
- $d -= $d_in_m[$m];
- $m++;
- if ($m==13) {
- $m=1;
- $y++;
- if (&Date_LeapYear($y)) {
- $d_in_m[2]=29;
- } else {
- $d_in_m[2]=28;
- }
- }
- }
- }
-
- if ($y<0 or $y>9999) {
- $$errref=3;
- return;
- }
- &Date_Join($y,$m,$d,$h,$mn,$s);
-}
-
-sub Date_UpdateHolidays {
- print "DEBUG: Date_UpdateHolidays\n" if ($Curr{"Debug"} =~ /trace/);
- my($year)=@_;
- $Holiday{"year"}=$year;
- $Holiday{"dates"}{$year}={};
-
- my($date,$delta,$err)=();
- my($key,@tmp,$tmp);
-
- foreach $key (keys %{ $Holiday{"desc"} }) {
- @tmp=&Recur_Split($key);
- if (@tmp) {
- $tmp=&ParseDateString("${year}010100:00:00");
- ($date)=&ParseRecur($key,$tmp,$tmp,($year+1)."-01-01");
- next if (! $date);
-
- } elsif ($key =~ /^(.*)([+-].*)$/) {
- # Date +/- Delta
- ($date,$delta)=($1,$2);
- $tmp=&ParseDateString("$date $year");
- if ($tmp) {
- $date=$tmp;
- } else {
- $date=&ParseDateString($date);
- next if ($date !~ /^$year/);
- }
- $date=&DateCalc($date,$delta,\$err,0);
-
- } else {
- # Date
- $date=$key;
- $tmp=&ParseDateString("$date $year");
- if ($tmp) {
- $date=$tmp;
- } else {
- $date=&ParseDateString($date);
- next if ($date !~ /^$year/);
- }
- }
- $Holiday{"dates"}{$year}{$date}=$Holiday{"desc"}{$key};
- }
-}
-
-# This sets a Date::Manip config variable.
-sub Date_SetConfigVariable {
- print "DEBUG: Date_SetConfigVariable\n" if ($Curr{"Debug"} =~ /trace/);
- my($var,$val)=@_;
-
- # These are most appropriate for command line options instead of in files.
- $Cnf{"PathSep"}=$val, return if ($var =~ /^PathSep$/i);
- $Cnf{"PersonalCnf"}=$val, return if ($var =~ /^PersonalCnf$/i);
- $Cnf{"PersonalCnfPath"}=$val, return if ($var =~ /^PersonalCnfPath$/i);
- &EraseHolidays(), return if ($var =~ /^EraseHolidays$/i);
- $Cnf{"IgnoreGlobalCnf"}=1, return if ($var =~ /^IgnoreGlobalCnf$/i);
- $Cnf{"GlobalCnf"}=$val, return if ($var =~ /^GlobalCnf$/i);
-
- $Curr{"InitLang"}=1,
- $Cnf{"Language"}=$val, return if ($var =~ /^Language$/i);
- $Cnf{"DateFormat"}=$val, return if ($var =~ /^DateFormat$/i);
- $Cnf{"TZ"}=$val, return if ($var =~ /^TZ$/i);
- $Cnf{"ConvTZ"}=$val, return if ($var =~ /^ConvTZ$/i);
- $Cnf{"Internal"}=$val, return if ($var =~ /^Internal$/i);
- $Cnf{"FirstDay"}=$val, return if ($var =~ /^FirstDay$/i);
- $Cnf{"WorkWeekBeg"}=$val, return if ($var =~ /^WorkWeekBeg$/i);
- $Cnf{"WorkWeekEnd"}=$val, return if ($var =~ /^WorkWeekEnd$/i);
- $Cnf{"WorkDayBeg"}=$val,
- $Curr{"ResetWorkDay"}=1, return if ($var =~ /^WorkDayBeg$/i);
- $Cnf{"WorkDayEnd"}=$val,
- $Curr{"ResetWorkDay"}=1, return if ($var =~ /^WorkDayEnd$/i);
- $Cnf{"WorkDay24Hr"}=$val,
- $Curr{"ResetWorkDay"}=1, return if ($var =~ /^WorkDay24Hr$/i);
- $Cnf{"DeltaSigns"}=$val, return if ($var =~ /^DeltaSigns$/i);
- $Cnf{"Jan1Week1"}=$val, return if ($var =~ /^Jan1Week1$/i);
- $Cnf{"YYtoYYYY"}=$val, return if ($var =~ /^YYtoYYYY$/i);
- $Cnf{"UpdateCurrTZ"}=$val, return if ($var =~ /^UpdateCurrTZ$/i);
- $Cnf{"IntCharSet"}=$val, return if ($var =~ /^IntCharSet$/i);
- $Curr{"DebugVal"}=$val, return if ($var =~ /^Debug$/i);
- $Cnf{"TomorrowFirst"}=$val, return if ($var =~ /^TomorrowFirst$/i);
- $Cnf{"ForceDate"}=$val, return if ($var =~ /^ForceDate$/i);
-
- confess "ERROR: Unknown configuration variable $var in Date::Manip.\n";
-}
-
-sub EraseHolidays {
- print "DEBUG: EraseHolidays\n" if ($Curr{"Debug"} =~ /trace/);
-
- $Cnf{"EraseHolidays"}=0;
- delete $Holiday{"list"};
- $Holiday{"list"}={};
- delete $Holiday{"desc"};
- $Holiday{"desc"}={};
- $Holiday{"dates"}={};
-}
-
-# This returns a pointer to a list of times and events in the format
-# [ date, [ events ], date, [ events ], ... ]
-# where each list of events are events that are in effect at the date
-# immediately preceding the list.
-#
-# This takes either one date or two dates as arguments.
-sub Events_Calc {
- print "DEBUG: Events_Calc\n" if ($Curr{"Debug"} =~ /trace/);
-
- my($date0,$date1)=@_;
-
- my($tmp);
- $date0=&ParseDateString($date0);
- return undef if (! $date0);
- if ($date1) {
- $date1=&ParseDateString($date1);
- if (&Date_Cmp($date0,$date1)>0) {
- $tmp=$date1;
- $date1=$date0;
- $date0=$tmp;
- }
- } else {
- $date1=&DateCalc_DateDelta($date0,"+0:0:0:0:0:0:1");
- }
-
- #
- # [ d0,d1,del,name ] => [ d0, d1+del )
- # [ d0,0,del,name ] => [ d0, d0+del )
- #
- my(%ret,$d0,$d1,$del,$name,$c0,$c1);
- my(@tmp)=@{ $Events{"dates"} };
- DATE: while (@tmp) {
- ($d0,$d1,$del,$name)=splice(@tmp,0,4);
- $d0=&ParseDateString($d0);
- $d1=&ParseDateString($d1) if ($d1);
- $del=&ParseDateDelta($del) if ($del);
- if ($d1) {
- if ($del) {
- $d1=&DateCalc_DateDelta($d1,$del);
- }
- } else {
- $d1=&DateCalc_DateDelta($d0,$del);
- }
- if (&Date_Cmp($d0,$d1)>0) {
- $tmp=$d1;
- $d1=$d0;
- $d0=$tmp;
- }
- # [ date0,date1 )
- # [ d0,d1 ) OR [ d0,d1 )
- next DATE if (&Date_Cmp($d1,$date0)<=0 ||
- &Date_Cmp($d0,$date1)>=0);
- # [ date0,date1 )
- # [ d0,d1 )
- # [ d0, d1 )
- if (&Date_Cmp($d0,$date0)<=0) {
- push @{ $ret{$date0} },$name;
- push @{ $ret{$d1} },"!$name" if (&Date_Cmp($d1,$date1)<0);
- next DATE;
- }
- # [ date0,date1 )
- # [ d0,d1 )
- if (&Date_Cmp($d1,$date1)>=0) {
- push @{ $ret{$d0} },$name;
- next DATE;
- }
- # [ date0,date1 )
- # [ d0,d1 )
- push @{ $ret{$d0} },$name;
- push @{ $ret{$d1} },"!$name";
- }
-
- #
- # [ recur,delta0,delta1,name ] => [ {date-delta0},{date+delta1} )
- #
- my($rec,$del0,$del1,@d);
- @tmp=@{ $Events{"recur"} };
- RECUR: while (@tmp) {
- ($rec,$del0,$del1,$name)=splice(@tmp,0,4);
- @d=();
-
- }
-
- # Sort them AND take into account the "!$name" entries.
- my(%tmp,$date,@tmp2,@ret);
- @d=sort { &Date_Cmp($a,$b) } keys %ret;
- foreach $date (@d) {
- @tmp=@{ $ret{$date} };
- @tmp2=();
- foreach $tmp (@tmp) {
- push(@tmp2,$tmp), next if ($tmp =~ /^!/);
- $tmp{$tmp}=1;
- }
- foreach $tmp (@tmp2) {
- $tmp =~ s/^!//;
- delete $tmp{$tmp};
- }
- push(@ret,$date,[ keys %tmp ]);
- }
-
- return \@ret;
-}
-
-# This parses the raw events list
-sub Events_ParseRaw {
- print "DEBUG: Events_ParseRaw\n" if ($Curr{"Debug"} =~ /trace/);
-
- # Only need to be parsed once
- my($force)=@_;
- $Events{"parsed"}=0 if ($force);
- return if ($Events{"parsed"});
- $Events{"parsed"}=1;
-
- my(@events)=@{ $Events{"raw"} };
- my($event,$name,@event,$date0,$date1,$tmp,$delta,$recur0,$recur1,@recur,$r,
- $recur);
- EVENT: while (@events) {
- ($event,$name)=splice(@events,0,2);
- @event=split(/\s*;\s*/,$event);
-
- if ($#event == 0) {
-
- if ($date0=&ParseDateString($event[0])) {
- #
- # date = event
- #
- $tmp=&ParseDateString("$event[0] 00:00:00");
- if ($tmp && $tmp eq $date0) {
- $delta="+0:0:0:1:0:0:0";
- } else {
- $delta="+0:0:0:0:1:0:0";
- }
- push @{ $Events{"dates"} },($date0,0,$delta,$name);
-
- } elsif ($recur=&ParseRecur($event[0])) {
- #
- # recur = event
- #
- ($recur0,$recur1)=&Recur_Split($recur);
- if ($recur0) {
- if ($recur1) {
- $r="$recur0:$recur1";
- } else {
- $r=$recur0;
- }
- } else {
- $r=$recur1;
- }
- (@recur)=split(/:/,$r);
- if (pop(@recur)==0 && pop(@recur)==0 && pop(@recur)==0) {
- $delta="+0:0:0:1:0:0:0";
- } else {
- $delta="+0:0:0:0:1:0:0";
- }
- push @{ $Events{"recur"} },($recur,0,$delta,$name);
-
- } else {
- # ??? = event
- warn "WARNING: illegal event ignored [ @event ]\n";
- next EVENT;
- }
-
- } elsif ($#event == 1) {
-
- if ($date0=&ParseDateString($event[0])) {
-
- if ($date1=&ParseDateString($event[1])) {
- #
- # date ; date = event
- #
- $tmp=&ParseDateString("$event[1] 00:00:00");
- if ($tmp && $tmp eq $date1) {
- $date1=&DateCalc_DateDelta($date1,"+0:0:0:1:0:0:0");
- }
- push @{ $Events{"dates"} },($date0,$date1,0,$name);
-
- } elsif ($delta=&ParseDateDelta($event[1])) {
- #
- # date ; delta = event
- #
- push @{ $Events{"dates"} },($date0,0,$delta,$name);
-
- } else {
- # date ; ??? = event
- warn "WARNING: illegal event ignored [ @event ]\n";
- next EVENT;
- }
-
- } elsif ($recur=&ParseRecur($event[0])) {
-
- if ($delta=&ParseDateDelta($event[1])) {
- #
- # recur ; delta = event
- #
- push @{ $Events{"recur"} },($recur,0,$delta,$name);
-
- } else {
- # recur ; ??? = event
- warn "WARNING: illegal event ignored [ @event ]\n";
- next EVENT;
- }
-
- } else {
- # ??? ; ??? = event
- warn "WARNING: illegal event ignored [ @event ]\n";
- next EVENT;
- }
-
- } else {
- # date ; delta0 ; delta1 = event
- # recur ; delta0 ; delta1 = event
- # ??? ; ??? ; ??? ... = event
- warn "WARNING: illegal event ignored [ @event ]\n";
- next EVENT;
- }
- }
-}
-
-# This reads an init file.
-sub Date_InitFile {
- print "DEBUG: Date_InitFile\n" if ($Curr{"Debug"} =~ /trace/);
- my($file)=@_;
- my($in)=new IO::File;
- local($_)=();
- my($section)="vars";
- my($var,$val,$recur,$name)=();
-
- $in->open($file) || return;
- while(defined ($_=<$in>)) {
- chomp;
- s/^\s+//;
- s/\s+$//;
- next if (! $_ or /^\#/);
-
- if (/^\*holiday/i) {
- $section="holiday";
- &EraseHolidays() if ($section =~ /holiday/i && $Cnf{"EraseHolidays"});
- next;
- } elsif (/^\*events/i) {
- $section="events";
- next;
- }
-
- if ($section =~ /var/i) {
- confess "ERROR: invalid Date::Manip config file line.\n $_\n"
- if (! /(.*\S)\s*=\s*(.*)$/);
- ($var,$val)=($1,$2);
- &Date_SetConfigVariable($var,$val);
-
- } elsif ($section =~ /holiday/i) {
- confess "ERROR: invalid Date::Manip config file line.\n $_\n"
- if (! /(.*\S)\s*=\s*(.*)$/);
- ($recur,$name)=($1,$2);
- $name="" if (! defined $name);
- $Holiday{"desc"}{$recur}=$name;
-
- } elsif ($section =~ /events/i) {
- confess "ERROR: invalid Date::Manip config file line.\n $_\n"
- if (! /(.*\S)\s*=\s*(.*)$/);
- ($val,$var)=($1,$2);
- push @{ $Events{"raw"} },($val,$var);
-
- } else {
- # A section not currently used by Date::Manip (but may be
- # used by some extension to it).
- next;
- }
- }
- close($in);
-}
-
-# $flag=&Date_TimeCheck(\$h,\$mn,\$s,\$ampm);
-# Returns 1 if any of the fields are bad. All fields are optional, and
-# all possible checks are done on the data. If a field is not passed in,
-# it is set to default values. If data is missing, appropriate defaults
-# are supplied.
-sub Date_TimeCheck {
- print "DEBUG: Date_TimeCheck\n" if ($Curr{"Debug"} =~ /trace/);
- my($h,$mn,$s,$ampm)=@_;
- my($tmp1,$tmp2,$tmp3)=();
-
- $$h="" if (! defined $$h);
- $$mn="" if (! defined $$mn);
- $$s="" if (! defined $$s);
- $$ampm="" if (! defined $$ampm);
- $$ampm=uc($$ampm) if ($$ampm);
-
- # Check hour
- $tmp1=$Lang{$Cnf{"Language"}}{"AmPm"};
- $tmp2="";
- if ($$ampm =~ /^$tmp1$/i) {
- $tmp3=$Lang{$Cnf{"Language"}}{"AM"};
- $tmp2="AM" if ($$ampm =~ /^$tmp3$/i);
- $tmp3=$Lang{$Cnf{"Language"}}{"PM"};
- $tmp2="PM" if ($$ampm =~ /^$tmp3$/i);
- } elsif ($$ampm) {
- return 1;
- }
- if ($tmp2 eq "AM" || $tmp2 eq "PM") {
- $$h="0$$h" if (length($$h)==1);
- return 1 if ($$h<1 || $$h>12);
- $$h="00" if ($tmp2 eq "AM" and $$h==12);
- $$h += 12 if ($tmp2 eq "PM" and $$h!=12);
- } else {
- $$h="00" if ($$h eq "");
- $$h="0$$h" if (length($$h)==1);
- return 1 if (! &IsInt($$h,0,23));
- $tmp2="AM" if ($$h<12);
- $tmp2="PM" if ($$h>=12);
- }
- $$ampm=$Lang{$Cnf{"Language"}}{"AMstr"};
- $$ampm=$Lang{$Cnf{"Language"}}{"PMstr"} if ($tmp2 eq "PM");
-
- # Check minutes
- $$mn="00" if ($$mn eq "");
- $$mn="0$$mn" if (length($$mn)==1);
- return 1 if (! &IsInt($$mn,0,59));
-
- # Check seconds
- $$s="00" if ($$s eq "");
- $$s="0$$s" if (length($$s)==1);
- return 1 if (! &IsInt($$s,0,59));
-
- return 0;
-}
-
-# $flag=&Date_DateCheck(\$y,\$m,\$d,\$h,\$mn,\$s,\$ampm,\$wk);
-# Returns 1 if any of the fields are bad. All fields are optional, and
-# all possible checks are done on the data. If a field is not passed in,
-# it is set to default values. If data is missing, appropriate defaults
-# are supplied.
-#
-# If the flag UpdateHolidays is set, the year is set to
-# CurrHolidayYear.
-sub Date_DateCheck {
- print "DEBUG: Date_DateCheck\n" if ($Curr{"Debug"} =~ /trace/);
- my($y,$m,$d,$h,$mn,$s,$ampm,$wk)=@_;
- my($tmp1,$tmp2,$tmp3)=();
-
- my(@d_in_m)=(0,31,28,31,30,31,30,31,31,30,31,30,31);
- my($curr_y)=$Curr{"Y"};
- my($curr_m)=$Curr{"M"};
- my($curr_d)=$Curr{"D"};
- $$m=1, $$d=1 if (defined $$y and ! defined $$m and ! defined $$d);
- $$y="" if (! defined $$y);
- $$m="" if (! defined $$m);
- $$d="" if (! defined $$d);
- $$wk="" if (! defined $$wk);
- $$d=$curr_d if ($$y eq "" and $$m eq "" and $$d eq "");
-
- # Check year.
- $$y=$curr_y if ($$y eq "");
- $$y=&Date_FixYear($$y) if (length($$y)<4);
- return 1 if (! &IsInt($$y,0,9999));
- $d_in_m[2]=29 if (&Date_LeapYear($$y));
-
- # Check month
- $$m=$curr_m if ($$m eq "");
- $$m=$Lang{$Cnf{"Language"}}{"MonthH"}{lc($$m)}
- if (exists $Lang{$Cnf{"Language"}}{"MonthH"}{lc($$m)});
- $$m="0$$m" if (length($$m)==1);
- return 1 if (! &IsInt($$m,1,12));
-
- # Check day
- $$d="01" if ($$d eq "");
- $$d="0$$d" if (length($$d)==1);
- return 1 if (! &IsInt($$d,1,$d_in_m[$$m]));
- if ($$wk) {
- $tmp1=&Date_DayOfWeek($$m,$$d,$$y);
- $tmp2=$Lang{$Cnf{"Language"}}{"WeekH"}{lc($$wk)}
- if (exists $Lang{$Cnf{"Language"}}{"WeekH"}{lc($$wk)});
- return 1 if ($tmp1 != $tmp2);
- }
-
- return &Date_TimeCheck($h,$mn,$s,$ampm);
-}
-
-# Takes a year in 2 digit form and returns it in 4 digit form
-sub Date_FixYear {
- print "DEBUG: Date_FixYear\n" if ($Curr{"Debug"} =~ /trace/);
- my($y)=@_;
- my($curr_y)=$Curr{"Y"};
- $y=$curr_y if (! defined $y or ! $y);
- return $y if (length($y)==4);
- confess "ERROR: Invalid year ($y)\n" if (length($y)!=2);
- my($y1,$y2)=();
-
- if (lc($Cnf{"YYtoYYYY"}) eq "c") {
- $y1=substring($y,0,2);
- $y="$y1$y";
-
- } elsif ($Cnf{"YYtoYYYY"} =~ /^c(\d{2})$/i) {
- $y1=$1;
- $y="$y1$y";
-
- } elsif ($Cnf{"YYtoYYYY"} =~ /^c(\d{2})(\d{2})$/i) {
- $y1="$1$2";
- $y ="$1$y";
- $y += 100 if ($y<$y1);
-
- } else {
- $y1=$curr_y-$Cnf{"YYtoYYYY"};
- $y2=$y1+99;
- $y="19$y";
- while ($y<$y1) {
- $y+=100;
- }
- while ($y>$y2) {
- $y-=100;
- }
- }
- $y;
-}
-
-# &Date_NthWeekOfYear($y,$n);
-# Returns a list of (YYYY,MM,DD) for the 1st day of the Nth week of the
-# year.
-# &Date_NthWeekOfYear($y,$n,$dow,$flag);
-# Returns a list of (YYYY,MM,DD) for the Nth DoW of the year. If flag
-# is nil, the first DoW of the year may actually be in the previous
-# year (since the 1st week may include days from the previous year).
-# If flag is non-nil, the 1st DoW of the year refers to the 1st one
-# actually in the year
-sub Date_NthWeekOfYear {
- print "DEBUG: Date_NthWeekOfYear\n" if ($Curr{"Debug"} =~ /trace/);
- my($y,$n,$dow,$flag)=@_;
- my($m,$d,$err,$tmp,$date,%dow)=();
- $y=$Curr{"Y"} if (! defined $y or ! $y);
- $n=1 if (! defined $n or $n eq "");
- return () if ($n<0 || $n>53);
- if (defined $dow) {
- $dow=lc($dow);
- %dow=%{ $Lang{$Cnf{"Language"}}{"WeekH"} };
- $dow=$dow{$dow} if (exists $dow{$dow});
- return () if ($dow<1 || $dow>7);
- $flag="" if (! defined $flag);
- } else {
- $dow="";
- $flag="";
- }
-
- $y=&Date_FixYear($y) if (length($y)<4);
- if ($Cnf{"Jan1Week1"}) {
- $date=&Date_Join($y,1,1,0,0,0);
- } else {
- $date=&Date_Join($y,1,4,0,0,0);
- }
- $date=&Date_GetPrev($date,$Cnf{"FirstDay"},1);
- $date=&Date_GetNext($date,$dow,1) if ($dow ne "");
-
- if ($flag) {
- ($tmp)=&Date_Split($date, 1);
- $n++ if ($tmp != $y);
- }
-
- if ($n>1) {
- $date=&DateCalc_DateDelta($date,"+0:0:". ($n-1) . ":0:0:0:0",\$err,0);
- } elsif ($n==0) {
- $date=&DateCalc_DateDelta($date,"-0:0:1:0:0:0:0",\$err,0);
- }
- ($y,$m,$d)=&Date_Split($date, 1);
- ($y,$m,$d);
-}
-
-########################################################################
-# LANGUAGE INITIALIZATION
-########################################################################
-
-# 8-bit international characters can be gotten by "\xXX". I don't know
-# how to get 16-bit characters. I've got to read up on perllocale.
-sub Char_8Bit {
- my($hash)=@_;
-
- # grave `
- # A` 00c0 a` 00e0
- # E` 00c8 e` 00e8
- # I` 00cc i` 00ec
- # O` 00d2 o` 00f2
- # U` 00d9 u` 00f9
- # W` 1e80 w` 1e81
- # Y` 1ef2 y` 1ef3
-
- $$hash{"A`"} = "\xc0"; # LATIN CAPITAL LETTER A WITH GRAVE
- $$hash{"E`"} = "\xc8"; # LATIN CAPITAL LETTER E WITH GRAVE
- $$hash{"I`"} = "\xcc"; # LATIN CAPITAL LETTER I WITH GRAVE
- $$hash{"O`"} = "\xd2"; # LATIN CAPITAL LETTER O WITH GRAVE
- $$hash{"U`"} = "\xd9"; # LATIN CAPITAL LETTER U WITH GRAVE
- $$hash{"a`"} = "\xe0"; # LATIN SMALL LETTER A WITH GRAVE
- $$hash{"e`"} = "\xe8"; # LATIN SMALL LETTER E WITH GRAVE
- $$hash{"i`"} = "\xec"; # LATIN SMALL LETTER I WITH GRAVE
- $$hash{"o`"} = "\xf2"; # LATIN SMALL LETTER O WITH GRAVE
- $$hash{"u`"} = "\xf9"; # LATIN SMALL LETTER U WITH GRAVE
-
- # acute '
- # A' 00c1 a' 00e1
- # C' 0106 c' 0107
- # E' 00c9 e' 00e9
- # I' 00cd i' 00ed
- # L' 0139 l' 013a
- # N' 0143 n' 0144
- # O' 00d3 o' 00f3
- # R' 0154 r' 0155
- # S' 015a s' 015b
- # U' 00da u' 00fa
- # W' 1e82 w' 1e83
- # Y' 00dd y' 00fd
- # Z' 0179 z' 017a
-
- $$hash{"A'"} = "\xc1"; # LATIN CAPITAL LETTER A WITH ACUTE
- $$hash{"E'"} = "\xc9"; # LATIN CAPITAL LETTER E WITH ACUTE
- $$hash{"I'"} = "\xcd"; # LATIN CAPITAL LETTER I WITH ACUTE
- $$hash{"O'"} = "\xd3"; # LATIN CAPITAL LETTER O WITH ACUTE
- $$hash{"U'"} = "\xda"; # LATIN CAPITAL LETTER U WITH ACUTE
- $$hash{"Y'"} = "\xdd"; # LATIN CAPITAL LETTER Y WITH ACUTE
- $$hash{"a'"} = "\xe1"; # LATIN SMALL LETTER A WITH ACUTE
- $$hash{"e'"} = "\xe9"; # LATIN SMALL LETTER E WITH ACUTE
- $$hash{"i'"} = "\xed"; # LATIN SMALL LETTER I WITH ACUTE
- $$hash{"o'"} = "\xf3"; # LATIN SMALL LETTER O WITH ACUTE
- $$hash{"u'"} = "\xfa"; # LATIN SMALL LETTER U WITH ACUTE
- $$hash{"y'"} = "\xfd"; # LATIN SMALL LETTER Y WITH ACUTE
-
- # double acute " "
- # O" 0150 o" 0151
- # U" 0170 u" 0171
-
- # circumflex ^
- # A^ 00c2 a^ 00e2
- # C^ 0108 c^ 0109
- # E^ 00ca e^ 00ea
- # G^ 011c g^ 011d
- # H^ 0124 h^ 0125
- # I^ 00ce i^ 00ee
- # J^ 0134 j^ 0135
- # O^ 00d4 o^ 00f4
- # S^ 015c s^ 015d
- # U^ 00db u^ 00fb
- # W^ 0174 w^ 0175
- # Y^ 0176 y^ 0177
-
- $$hash{"A^"} = "\xc2"; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
- $$hash{"E^"} = "\xca"; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX
- $$hash{"I^"} = "\xce"; # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
- $$hash{"O^"} = "\xd4"; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
- $$hash{"U^"} = "\xdb"; # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
- $$hash{"a^"} = "\xe2"; # LATIN SMALL LETTER A WITH CIRCUMFLEX
- $$hash{"e^"} = "\xea"; # LATIN SMALL LETTER E WITH CIRCUMFLEX
- $$hash{"i^"} = "\xee"; # LATIN SMALL LETTER I WITH CIRCUMFLEX
- $$hash{"o^"} = "\xf4"; # LATIN SMALL LETTER O WITH CIRCUMFLEX
- $$hash{"u^"} = "\xfb"; # LATIN SMALL LETTER U WITH CIRCUMFLEX
-
- # tilde ~
- # A~ 00c3 a~ 00e3
- # I~ 0128 i~ 0129
- # N~ 00d1 n~ 00f1
- # O~ 00d5 o~ 00f5
- # U~ 0168 u~ 0169
-
- $$hash{"A~"} = "\xc3"; # LATIN CAPITAL LETTER A WITH TILDE
- $$hash{"N~"} = "\xd1"; # LATIN CAPITAL LETTER N WITH TILDE
- $$hash{"O~"} = "\xd5"; # LATIN CAPITAL LETTER O WITH TILDE
- $$hash{"a~"} = "\xe3"; # LATIN SMALL LETTER A WITH TILDE
- $$hash{"n~"} = "\xf1"; # LATIN SMALL LETTER N WITH TILDE
- $$hash{"o~"} = "\xf5"; # LATIN SMALL LETTER O WITH TILDE
-
- # macron -
- # A- 0100 a- 0101
- # E- 0112 e- 0113
- # I- 012a i- 012b
- # O- 014c o- 014d
- # U- 016a u- 016b
-
- # breve ( [half circle up]
- # A( 0102 a( 0103
- # G( 011e g( 011f
- # U( 016c u( 016d
-
- # dot .
- # C. 010a c. 010b
- # E. 0116 e. 0117
- # G. 0120 g. 0121
- # I. 0130
- # Z. 017b z. 017c
-
- # diaeresis : [side by side dots]
- # A: 00c4 a: 00e4
- # E: 00cb e: 00eb
- # I: 00cf i: 00ef
- # O: 00d6 o: 00f6
- # U: 00dc u: 00fc
- # W: 1e84 w: 1e85
- # Y: 0178 y: 00ff
-
- $$hash{"A:"} = "\xc4"; # LATIN CAPITAL LETTER A WITH DIAERESIS
- $$hash{"E:"} = "\xcb"; # LATIN CAPITAL LETTER E WITH DIAERESIS
- $$hash{"I:"} = "\xcf"; # LATIN CAPITAL LETTER I WITH DIAERESIS
- $$hash{"O:"} = "\xd6"; # LATIN CAPITAL LETTER O WITH DIAERESIS
- $$hash{"U:"} = "\xdc"; # LATIN CAPITAL LETTER U WITH DIAERESIS
- $$hash{"a:"} = "\xe4"; # LATIN SMALL LETTER A WITH DIAERESIS
- $$hash{"e:"} = "\xeb"; # LATIN SMALL LETTER E WITH DIAERESIS
- $$hash{"i:"} = "\xef"; # LATIN SMALL LETTER I WITH DIAERESIS
- $$hash{"o:"} = "\xf6"; # LATIN SMALL LETTER O WITH DIAERESIS
- $$hash{"u:"} = "\xfc"; # LATIN SMALL LETTER U WITH DIAERESIS
- $$hash{"y:"} = "\xff"; # LATIN SMALL LETTER Y WITH DIAERESIS
-
- # ring o
- # U0 016e u0 016f
-
- # cedilla , [squiggle down and left below the letter]
- # ,C 00c7 ,c 00e7
- # ,G 0122 ,g 0123
- # ,K 0136 ,k 0137
- # ,L 013b ,l 013c
- # ,N 0145 ,n 0146
- # ,R 0156 ,r 0157
- # ,S 015e ,s 015f
- # ,T 0162 ,t 0163
-
- $$hash{",C"} = "\xc7"; # LATIN CAPITAL LETTER C WITH CEDILLA
- $$hash{",c"} = "\xe7"; # LATIN SMALL LETTER C WITH CEDILLA
-
- # ogonek ; [squiggle down and right below the letter]
- # A; 0104 a; 0105
- # E; 0118 e; 0119
- # I; 012e i; 012f
- # U; 0172 u; 0173
-
- # caron < [little v on top]
- # A< 01cd a< 01ce
- # C< 010c c< 010d
- # D< 010e d< 010f
- # E< 011a e< 011b
- # L< 013d l< 013e
- # N< 0147 n< 0148
- # R< 0158 r< 0159
- # S< 0160 s< 0161
- # T< 0164 t< 0165
- # Z< 017d z< 017e
-
-
- # Other characters
-
- # First character is below, 2nd character is above
- $$hash{"||"} = "\xa6"; # BROKEN BAR
- $$hash{" :"} = "\xa8"; # DIAERESIS
- $$hash{"-a"} = "\xaa"; # FEMININE ORDINAL INDICATOR
- #$$hash{" -"}= "\xaf"; # MACRON (narrow bar)
- $$hash{" -"} = "\xad"; # HYPHEN (wide bar)
- $$hash{" o"} = "\xb0"; # DEGREE SIGN
- $$hash{"-+"} = "\xb1"; # PLUS\342\200\220MINUS SIGN
- $$hash{" 1"} = "\xb9"; # SUPERSCRIPT ONE
- $$hash{" 2"} = "\xb2"; # SUPERSCRIPT TWO
- $$hash{" 3"} = "\xb3"; # SUPERSCRIPT THREE
- $$hash{" '"} = "\xb4"; # ACUTE ACCENT
- $$hash{"-o"} = "\xba"; # MASCULINE ORDINAL INDICATOR
- $$hash{" ."} = "\xb7"; # MIDDLE DOT
- $$hash{", "} = "\xb8"; # CEDILLA
- $$hash{"Ao"} = "\xc5"; # LATIN CAPITAL LETTER A WITH RING ABOVE
- $$hash{"ao"} = "\xe5"; # LATIN SMALL LETTER A WITH RING ABOVE
- $$hash{"ox"} = "\xf0"; # LATIN SMALL LETTER ETH
-
- # upside down characters
-
- $$hash{"ud!"} = "\xa1"; # INVERTED EXCLAMATION MARK
- $$hash{"ud?"} = "\xbf"; # INVERTED QUESTION MARK
-
- # overlay characters
-
- $$hash{"X o"} = "\xa4"; # CURRENCY SIGN
- $$hash{"Y ="} = "\xa5"; # YEN SIGN
- $$hash{"S o"} = "\xa7"; # SECTION SIGN
- $$hash{"O c"} = "\xa9"; # COPYRIGHT SIGN Copyright
- $$hash{"O R"} = "\xae"; # REGISTERED SIGN
- $$hash{"D -"} = "\xd0"; # LATIN CAPITAL LETTER ETH
- $$hash{"O /"} = "\xd8"; # LATIN CAPITAL LETTER O WITH STROKE
- $$hash{"o /"} = "\xf8"; # LATIN SMALL LETTER O WITH STROKE
-
- # special names
-
- $$hash{"1/4"} = "\xbc"; # VULGAR FRACTION ONE QUARTER
- $$hash{"1/2"} = "\xbd"; # VULGAR FRACTION ONE HALF
- $$hash{"3/4"} = "\xbe"; # VULGAR FRACTION THREE QUARTERS
- $$hash{"<<"} = "\xab"; # LEFT POINTING DOUBLE ANGLE QUOTATION MARK
- $$hash{">>"} = "\xbb"; # RIGHT POINTING DOUBLE ANGLE QUOTATION MARK
- $$hash{"cent"}= "\xa2"; # CENT SIGN
- $$hash{"lb"} = "\xa3"; # POUND SIGN
- $$hash{"mu"} = "\xb5"; # MICRO SIGN
- $$hash{"beta"}= "\xdf"; # LATIN SMALL LETTER SHARP S
- $$hash{"para"}= "\xb6"; # PILCROW SIGN
- $$hash{"-|"} = "\xac"; # NOT SIGN
- $$hash{"AE"} = "\xc6"; # LATIN CAPITAL LETTER AE
- $$hash{"ae"} = "\xe6"; # LATIN SMALL LETTER AE
- $$hash{"x"} = "\xd7"; # MULTIPLICATION SIGN
- $$hash{"P"} = "\xde"; # LATIN CAPITAL LETTER THORN
- $$hash{"/"} = "\xf7"; # DIVISION SIGN
- $$hash{"p"} = "\xfe"; # LATIN SMALL LETTER THORN
-}
-
-# $hashref = &Date_Init_LANGUAGE;
-# This returns a hash containing all of the initialization for a
-# specific language. The hash elements are:
-#
-# @ month_name full month names January February ...
-# @ month_abb month abbreviations Jan Feb ...
-# @ day_name day names Monday Tuesday ...
-# @ day_abb day abbreviations Mon Tue ...
-# @ day_char day character abbrevs M T ...
-# @ am AM notations
-# @ pm PM notations
-#
-# @ num_suff number with suffix 1st 2nd ...
-# @ num_word numbers spelled out first second ...
-#
-# $ now words which mean now now today ...
-# $ last words which mean last last final ...
-# $ each words which mean each each every ...
-# $ of of (as in a member of) in of ...
-# ex. 4th day OF June
-# $ at at 4:00 at
-# $ on on Sunday on
-# $ future in the future in
-# $ past in the past ago
-# $ next next item next
-# $ prev previous item last previous
-# $ later 2 hours later
-#
-# % offset a hash of special dates { tomorrow->0:0:0:1:0:0:0 }
-# % times a hash of times { noon->12:00:00 ... }
-#
-# $ years words for year y yr year ...
-# $ months words for month
-# $ weeks words for week
-# $ days words for day
-# $ hours words for hour
-# $ minutes words for minute
-# $ seconds words for second
-# % replace
-# The replace element is quite important, but a bit tricky. In
-# English (and probably other languages), one of the abbreviations
-# for the word month that would be nice is "m". The problem is that
-# "m" matches the "m" in "minute" which causes the string to be
-# improperly matched in some cases. Hence, the list of abbreviations
-# for month is given as:
-# "mon month months"
-# In order to allow you to enter "m", replacements can be done.
-# $replace is a list of pairs of words which are matched and replaced
-# AS ENTIRE WORDS. Having $replace equal to "m"->"month" means that
-# the entire word "m" will be replaced with "month". This allows the
-# desired abbreviation to be used. Make sure that replace contains
-# an even number of words (i.e. all must be pairs). Any time a
-# desired abbreviation matches the start of any other, it has to go
-# here.
-#
-# $ exact exact mode exactly
-# $ approx approximate mode approximately
-# $ business business mode business
-#
-# r sephm hour/minute separator (?::)
-# r sepms minute/second separator (?::)
-# r sepss second/fraction separator (?:[.:])
-#
-# Elements marked with an asterix (@) are returned as a set of lists.
-# Each list contains the strings for each element. The first set is used
-# when the 7-bit ASCII (US) character set is wanted. The 2nd set is used
-# when an international character set is available. Both of the 1st two
-# sets should be complete (but the 2nd list can be left empty to force the
-# first set to be used always). The 3rd set and later can be partial sets
-# if desired.
-#
-# Elements marked with a dollar ($) are returned as a simple list of words.
-#
-# Elements marked with a percent (%) are returned as a hash list.
-#
-# Elements marked with (r) are regular expression elements which must not
-# create a back reference.
-#
-# ***NOTE*** Every hash element (unless otherwise noted) MUST be defined in
-# every language.
-
-sub Date_Init_English {
- print "DEBUG: Date_Init_English\n" if ($Curr{"Debug"} =~ /trace/);
- my($d)=@_;
-
- $$d{"month_name"}=
- [["January","February","March","April","May","June",
- "July","August","September","October","November","December"]];
-
- $$d{"month_abb"}=
- [["Jan","Feb","Mar","Apr","May","Jun",
- "Jul","Aug","Sep","Oct","Nov","Dec"],
- [],
- ["","","","","","","","","Sept"]];
-
- $$d{"day_name"}=
- [["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]];
- $$d{"day_abb"}=
- [["Mon","Tue","Wed","Thu","Fri","Sat","Sun"],
- ["", "Tues","", "Thur","", "", ""]];
- $$d{"day_char"}=
- [["M","T","W","Th","F","Sa","S"]];
-
- $$d{"num_suff"}=
- [["1st","2nd","3rd","4th","5th","6th","7th","8th","9th","10th",
- "11th","12th","13th","14th","15th","16th","17th","18th","19th","20th",
- "21st","22nd","23rd","24th","25th","26th","27th","28th","29th","30th",
- "31st"]];
- $$d{"num_word"}=
- [["first","second","third","fourth","fifth","sixth","seventh","eighth",
- "ninth","tenth","eleventh","twelfth","thirteenth","fourteenth",
- "fifteenth","sixteenth","seventeenth","eighteenth","nineteenth",
- "twentieth","twenty-first","twenty-second","twenty-third",
- "twenty-fourth","twenty-fifth","twenty-sixth","twenty-seventh",
- "twenty-eighth","twenty-ninth","thirtieth","thirty-first"]];
-
- $$d{"now"} =["today","now"];
- $$d{"last"} =["last","final"];
- $$d{"each"} =["each","every"];
- $$d{"of"} =["in","of"];
- $$d{"at"} =["at"];
- $$d{"on"} =["on"];
- $$d{"future"} =["in"];
- $$d{"past"} =["ago"];
- $$d{"next"} =["next"];
- $$d{"prev"} =["previous","last"];
- $$d{"later"} =["later"];
-
- $$d{"exact"} =["exactly"];
- $$d{"approx"} =["approximately"];
- $$d{"business"}=["business"];
-
- $$d{"offset"} =["yesterday","-0:0:0:1:0:0:0","tomorrow","+0:0:0:1:0:0:0"];
- $$d{"times"} =["noon","12:00:00","midnight","00:00:00"];
-
- $$d{"years"} =["y","yr","year","yrs","years"];
- $$d{"months"} =["mon","month","months"];
- $$d{"weeks"} =["w","wk","wks","week","weeks"];
- $$d{"days"} =["d","day","days"];
- $$d{"hours"} =["h","hr","hrs","hour","hours"];
- $$d{"minutes"} =["mn","min","minute","minutes"];
- $$d{"seconds"} =["s","sec","second","seconds"];
- $$d{"replace"} =["m","month"];
-
- $$d{"sephm"} =':';
- $$d{"sepms"} =':';
- $$d{"sepss"} ='[.:]';
-
- $$d{"am"} = ["AM","A.M."];
- $$d{"pm"} = ["PM","P.M."];
-}
-
-sub Date_Init_Italian {
- print "DEBUG: Date_Init_Italian\n" if ($Curr{"Debug"} =~ /trace/);
- my($d)=@_;
- my(%h)=();
- &Char_8Bit(\%h);
- my($i)=$h{"i'"};
-
- $$d{"month_name"}=
- [[qw(Gennaio Febbraio Marzo Aprile Maggio Giugno
- Luglio Agosto Settembre Ottobre Novembre Dicembre)]];
-
- $$d{"month_abb"}=
- [[qw(Gen Feb Mar Apr Mag Giu Lug Ago Set Ott Nov Dic)]];
-
- $$d{"day_name"}=
- [[qw(Lunedi Martedi Mercoledi Giovedi Venerdi Sabato Domenica)],
- [qw(Luned${i} Marted${i} Mercoled${i} Gioved${i} Venerd${i})]];
- $$d{"day_abb"}=
- [[qw(Lun Mar Mer Gio Ven Sab Dom)]];
- $$d{"day_char"}=
- [[qw(L Ma Me G V S D)]];
-
- $$d{"num_suff"}=
- [[qw(1mo 2do 3zo 4to 5to 6to 7mo 8vo 9no 10mo 11mo 12mo 13mo 14mo 15mo
- 16mo 17mo 18mo 19mo 20mo 21mo 22mo 23mo 24mo 25mo 26mo 27mo 28mo
- 29mo 3mo 31mo)]];
- $$d{"num_word"}=
- [[qw(primo secondo terzo quarto quinto sesto settimo ottavo nono decimo
- undicesimo dodicesimo tredicesimo quattordicesimo quindicesimo
- sedicesimo diciassettesimo diciottesimo diciannovesimo ventesimo
- ventunesimo ventiduesimo ventitreesimo ventiquattresimo
- venticinquesimo ventiseiesimo ventisettesimo ventottesimo
- ventinovesimo trentesimo trentunesimo)]];
-
- $$d{"now"} =[qw(adesso oggi)];
- $$d{"last"} =[qw(ultimo)];
- $$d{"each"} =[qw(ogni)];
- $$d{"of"} =[qw(della del)];
- $$d{"at"} =[qw(alle)];
- $$d{"on"} =[qw(di)];
- $$d{"future"} =[qw(fra)];
- $$d{"past"} =[qw(fa)];
- $$d{"next"} =[qw(prossimo)];
- $$d{"prev"} =[qw(ultimo)];
- $$d{"later"} =[qw(dopo)];
-
- $$d{"exact"} =[qw(esattamente)];
- $$d{"approx"} =[qw(circa)];
- $$d{"business"}=[qw(lavorativi lavorativo)];
-
- $$d{"offset"} =[qw(ieri -0:0:0:1:0:0:0 domani +0:0:0:1:0:0:0)];
- $$d{"times"} =[qw(mezzogiorno 12:00:00 mezzanotte 00:00:00)];
-
- $$d{"years"} =[qw(anni anno a)];
- $$d{"months"} =[qw(mesi mese mes)];
- $$d{"weeks"} =[qw(settimane settimana sett)];
- $$d{"days"} =[qw(giorni giorno g)];
- $$d{"hours"} =[qw(ore ora h)];
- $$d{"minutes"} =[qw(minuti minuto min)];
- $$d{"seconds"} =[qw(secondi secondo sec)];
- $$d{"replace"} =[qw(s sec m mes)];
-
- $$d{"sephm"} =':';
- $$d{"sepms"} =':';
- $$d{"sepss"} ='[.:]';
-
- $$d{"am"} = [qw(AM)];
- $$d{"pm"} = [qw(PM)];
-}
-
-sub Date_Init_French {
- print "DEBUG: Date_Init_French\n" if ($Curr{"Debug"} =~ /trace/);
- my($d)=@_;
- my(%h)=();
- &Char_8Bit(\%h);
- my($e)=$h{"e'"};
- my($u)=$h{"u^"};
- my($a)=$h{"a'"};
-
- $$d{"month_name"}=
- [["janvier","fevrier","mars","avril","mai","juin",
- "juillet","aout","septembre","octobre","novembre","decembre"],
- ["janvier","f${e}vrier","mars","avril","mai","juin",
- "juillet","ao${u}t","septembre","octobre","novembre","d${e}cembre"]];
- $$d{"month_abb"}=
- [["jan","fev","mar","avr","mai","juin",
- "juil","aout","sept","oct","nov","dec"],
- ["jan","f${e}v","mar","avr","mai","juin",
- "juil","ao${u}t","sept","oct","nov","d${e}c"]];
-
- $$d{"day_name"}=
- [["lundi","mardi","mercredi","jeudi","vendredi","samedi","dimanche"]];
- $$d{"day_abb"}=
- [["lun","mar","mer","jeu","ven","sam","dim"]];
- $$d{"day_char"}=
- [["l","ma","me","j","v","s","d"]];
-
- $$d{"num_suff"}=
- [["1er","2e","3e","4e","5e","6e","7e","8e","9e","10e",
- "11e","12e","13e","14e","15e","16e","17e","18e","19e","20e",
- "21e","22e","23e","24e","25e","26e","27e","28e","29e","30e",
- "31e"]];
- $$d{"num_word"}=
- [["premier","deux","trois","quatre","cinq","six","sept","huit","neuf",
- "dix","onze","douze","treize","quatorze","quinze","seize","dix-sept",
- "dix-huit","dix-neuf","vingt","vingt et un","vingt-deux","vingt-trois",
- "vingt-quatre","vingt-cinq","vingt-six","vingt-sept","vingt-huit",
- "vingt-neuf","trente","trente et un"],
- ["1re"]];
-
- $$d{"now"} =["aujourd'hui","maintenant"];
- $$d{"last"} =["dernier"];
- $$d{"each"} =["chaque","tous les","toutes les"];
- $$d{"of"} =["en","de"];
- $$d{"at"} =["a","${a}0"];
- $$d{"on"} =["sur"];
- $$d{"future"} =["en"];
- $$d{"past"} =["il y a"];
- $$d{"next"} =["suivant"];
- $$d{"prev"} =["precedent","pr${e}c${e}dent"];
- $$d{"later"} =["plus tard"];
-
- $$d{"exact"} =["exactement"];
- $$d{"approx"} =["approximativement"];
- $$d{"business"}=["professionel"];
-
- $$d{"offset"} =["hier","-0:0:0:1:0:0:0","demain","+0:0:0:1:0:0:0"];
- $$d{"times"} =["midi","12:00:00","minuit","00:00:00"];
-
- $$d{"years"} =["an","annee","ans","annees","ann${e}e","ann${e}es"];
- $$d{"months"} =["mois"];
- $$d{"weeks"} =["sem","semaine"];
- $$d{"days"} =["j","jour","jours"];
- $$d{"hours"} =["h","heure","heures"];
- $$d{"minutes"} =["mn","min","minute","minutes"];
- $$d{"seconds"} =["s","sec","seconde","secondes"];
- $$d{"replace"} =["m","mois"];
-
- $$d{"sephm"} ='[h:]';
- $$d{"sepms"} =':';
- $$d{"sepss"} ='[.:,]';
-
- $$d{"am"} = ["du matin"];
- $$d{"pm"} = ["du soir"];
-}
-
-sub Date_Init_Romanian {
- print "DEBUG: Date_Init_Romanian\n" if ($Curr{"Debug"} =~ /trace/);
- my($d)=@_;
- my(%h)=();
- &Char_8Bit(\%h);
- my($p)=$h{"p"};
- my($i)=$h{"i^"};
- my($a)=$h{"a~"};
- my($o)=$h{"-o"};
-
- $$d{"month_name"}=
- [["ianuarie","februarie","martie","aprilie","mai","iunie",
- "iulie","august","septembrie","octombrie","noiembrie","decembrie"]];
- $$d{"month_abb"}=
- [["ian","febr","mart","apr","mai","iun",
- "iul","aug","sept","oct","nov","dec"],
- ["","feb"]];
-
- $$d{"day_name"}=
- [["luni","marti","miercuri","joi","vineri","simbata","duminica"],
- ["luni","mar${p}i","miercuri","joi","vineri","s${i}mb${a}t${a}",
- "duminic${a}"]];
- $$d{"day_abb"}=
- [["lun","mar","mie","joi","vin","sim","dum"],
- ["lun","mar","mie","joi","vin","s${i}m","dum"]];
- $$d{"day_char"}=
- [["L","Ma","Mi","J","V","S","D"]];
-
- $$d{"num_suff"}=
- [["prima","a doua","a 3-a","a 4-a","a 5-a","a 6-a","a 7-a","a 8-a",
- "a 9-a","a 10-a","a 11-a","a 12-a","a 13-a","a 14-a","a 15-a",
- "a 16-a","a 17-a","a 18-a","a 19-a","a 20-a","a 21-a","a 22-a",
- "a 23-a","a 24-a","a 25-a","a 26-a","a 27-a","a 28-a","a 29-a",
- "a 30-a","a 31-a"]];
-
- $$d{"num_word"}=
- [["prima","a doua","a treia","a patra","a cincea","a sasea","a saptea",
- "a opta","a noua","a zecea","a unsprezecea","a doisprezecea",
- "a treisprezecea","a patrusprezecea","a cincisprezecea","a saiprezecea",
- "a saptesprezecea","a optsprezecea","a nouasprezecea","a douazecea",
- "a douazecisiuna","a douazecisidoua","a douazecisitreia",
- "a douazecisipatra","a douazecisicincea","a douazecisisasea",
- "a douazecisisaptea","a douazecisiopta","a douazecisinoua","a treizecea",
- "a treizecisiuna"],
- ["prima","a doua","a treia","a patra","a cincea","a ${o}asea",
- "a ${o}aptea","a opta","a noua","a zecea","a unsprezecea",
- "a doisprezecea","a treisprezecea","a patrusprezecea","a cincisprezecea",
- "a ${o}aiprezecea","a ${o}aptesprezecea","a optsprezecea",
- "a nou${a}sprezecea","a dou${a}zecea","a dou${a}zeci${o}iuna",
- "a dou${a}zeci${o}idoua","a dou${a}zeci${o}itreia",
- "a dou${a}zeci${o}ipatra","a dou${a}zeci${o}icincea",
- "a dou${a}zeci${o}i${o}asea","a dou${a}zeci${o}i${o}aptea",
- "a dou${a}zeci${o}iopta","a dou${a}zeci${o}inoua","a treizecea",
- "a treizeci${o}iuna"],
- ["intii", "doi", "trei", "patru", "cinci", "sase", "sapte",
- "opt","noua","zece","unsprezece","doisprezece",
- "treisprezece","patrusprezece","cincisprezece","saiprezece",
- "saptesprezece","optsprezece","nouasprezece","douazeci",
- "douazecisiunu","douazecisidoi","douazecisitrei",
- "douazecisipatru","douazecisicinci","douazecisisase","douazecisisapte",
- "douazecisiopt","douazecisinoua","treizeci","treizecisiunu"],
- ["${i}nt${i}i", "doi", "trei", "patru", "cinci", "${o}ase", "${o}apte",
- "opt","nou${a}","zece","unsprezece","doisprezece",
- "treisprezece","patrusprezece","cincisprezece","${o}aiprezece",
- "${o}aptesprezece","optsprezece","nou${a}sprezece","dou${a}zeci",
- "dou${a}zeci${o}iunu","dou${a}zeci${o}idoi","dou${a}zeci${o}itrei",
- "dou${a}zecisipatru","dou${a}zeci${o}icinci","dou${a}zeci${o}i${o}ase",
- "dou${a}zeci${o}i${o}apte","dou${a}zeci${o}iopt",
- "dou${a}zeci${o}inou${a}","treizeci","treizeci${o}iunu"]];
-
- $$d{"now"} =["acum","azi","astazi","ast${a}zi"];
- $$d{"last"} =["ultima"];
- $$d{"each"} =["fiecare"];
- $$d{"of"} =["din","in","n"];
- $$d{"at"} =["la"];
- $$d{"on"} =["on"];
- $$d{"future"} =["in","${i}n"];
- $$d{"past"} =["in urma", "${i}n urm${a}"];
- $$d{"next"} =["urmatoarea","urm${a}toarea"];
- $$d{"prev"} =["precedenta","ultima"];
- $$d{"later"} =["mai tirziu", "mai t${i}rziu"];
-
- $$d{"exact"} =["exact"];
- $$d{"approx"} =["aproximativ"];
- $$d{"business"}=["de lucru","lucratoare","lucr${a}toare"];
-
- $$d{"offset"} =["ieri","-0:0:0:1:0:0:0",
- "alaltaieri", "-0:0:0:2:0:0:0",
- "alalt${a}ieri","-0:0:0:2:0:0:0",
- "miine","+0:0:0:1:0:0:0",
- "m${i}ine","+0:0:0:1:0:0:0",
- "poimiine","+0:0:0:2:0:0:0",
- "poim${i}ine","+0:0:0:2:0:0:0"];
- $$d{"times"} =["amiaza","12:00:00",
- "amiaz${a}","12:00:00",
- "miezul noptii","00:00:00",
- "miezul nop${p}ii","00:00:00"];
-
- $$d{"years"} =["ani","an","a"];
- $$d{"months"} =["luni","luna","lun${a}","l"];
- $$d{"weeks"} =["saptamini","s${a}pt${a}m${i}ni","saptamina",
- "s${a}pt${a}m${i}na","sapt","s${a}pt"];
- $$d{"days"} =["zile","zi","z"];
- $$d{"hours"} =["ore", "ora", "or${a}", "h"];
- $$d{"minutes"} =["minute","min","m"];
- $$d{"seconds"} =["secunde","sec",];
- $$d{"replace"} =["s","secunde"];
-
- $$d{"sephm"} =':';
- $$d{"sepms"} =':';
- $$d{"sepss"} ='[.:,]';
-
- $$d{"am"} = ["AM","A.M."];
- $$d{"pm"} = ["PM","P.M."];
-}
-
-sub Date_Init_Swedish {
- print "DEBUG: Date_Init_Swedish\n" if ($Curr{"Debug"} =~ /trace/);
- my($d)=@_;
- my(%h)=();
- &Char_8Bit(\%h);
- my($ao)=$h{"ao"};
- my($o) =$h{"o:"};
- my($a) =$h{"a:"};
-
- $$d{"month_name"}=
- [["Januari","Februari","Mars","April","Maj","Juni",
- "Juli","Augusti","September","Oktober","November","December"]];
- $$d{"month_abb"}=
- [["Jan","Feb","Mar","Apr","Maj","Jun",
- "Jul","Aug","Sep","Okt","Nov","Dec"]];
-
- $$d{"day_name"}=
- [["Mandag","Tisdag","Onsdag","Torsdag","Fredag","Lordag","Sondag"],
- ["M${ao}ndag","Tisdag","Onsdag","Torsdag","Fredag","L${o}rdag",
- "S${o}ndag"]];
- $$d{"day_abb"}=
- [["Man","Tis","Ons","Tor","Fre","Lor","Son"],
- ["M${ao}n","Tis","Ons","Tor","Fre","L${o}r","S${o}n"]];
- $$d{"day_char"}=
- [["M","Ti","O","To","F","L","S"]];
-
- $$d{"num_suff"}=
- [["1:a","2:a","3:e","4:e","5:e","6:e","7:e","8:e","9:e","10:e",
- "11:e","12:e","13:e","14:e","15:e","16:e","17:e","18:e","19:e","20:e",
- "21:a","22:a","23:e","24:e","25:e","26:e","27:e","28:e","29:e","30:e",
- "31:a"]];
- $$d{"num_word"}=
- [["forsta","andra","tredje","fjarde","femte","sjatte","sjunde",
- "attonde","nionde","tionde","elfte","tolfte","trettonde","fjortonde",
- "femtonde","sextonde","sjuttonde","artonde","nittonde","tjugonde",
- "tjugoforsta","tjugoandra","tjugotredje","tjugofjarde","tjugofemte",
- "tjugosjatte","tjugosjunde","tjugoattonde","tjugonionde",
- "trettionde","trettioforsta"],
- ["f${o}rsta","andra","tredje","fj${a}rde","femte","sj${a}tte","sjunde",
- "${ao}ttonde","nionde","tionde","elfte","tolfte","trettonde","fjortonde",
- "femtonde","sextonde","sjuttonde","artonde","nittonde","tjugonde",
- "tjugof${o}rsta","tjugoandra","tjugotredje","tjugofj${a}rde","tjugofemte",
- "tjugosj${a}tte","tjugosjunde","tjugo${ao}ttonde","tjugonionde",
- "trettionde","trettiof${o}rsta"]];
-
- $$d{"now"} =["idag","nu"];
- $$d{"last"} =["forra","f${o}rra","senaste"];
- $$d{"each"} =["varje"];
- $$d{"of"} =["om"];
- $$d{"at"} =["kl","kl.","klockan"];
- $$d{"on"} =["pa","p${ao}"];
- $$d{"future"} =["om"];
- $$d{"past"} =["sedan"];
- $$d{"next"} =["nasta","n${a}sta"];
- $$d{"prev"} =["forra","f${o}rra"];
- $$d{"later"} =["senare"];
-
- $$d{"exact"} =["exakt"];
- $$d{"approx"} =["ungefar","ungef${a}r"];
- $$d{"business"}=["arbetsdag","arbetsdagar"];
-
- $$d{"offset"} =["ig${ao}r","-0:0:0:1:0:0:0","igar","-0:0:0:1:0:0:0",
- "imorgon","+0:0:0:1:0:0:0"];
- $$d{"times"} =["mitt pa dagen","12:00:00","mitt p${ao} dagen","12:00:00",
- "midnatt","00:00:00"];
-
- $$d{"years"} =["ar","${ao}r"];
- $$d{"months"} =["man","manad","manader","m${ao}n","m${ao}nad","m${ao}nader"];
- $$d{"weeks"} =["v","vecka","veckor"];
- $$d{"days"} =["d","dag","dagar"];
- $$d{"hours"} =["t","tim","timme","timmar"];
- $$d{"minutes"} =["min","minut","minuter"];
- $$d{"seconds"} =["s","sek","sekund","sekunder"];
- $$d{"replace"} =["m","minut"];
-
- $$d{"sephm"} ='[.:]';
- $$d{"sepms"} =':';
- $$d{"sepss"} ='[.:]';
-
- $$d{"am"} = ["FM"];
- $$d{"pm"} = ["EM"];
-}
-
-sub Date_Init_German {
- print "DEBUG: Date_Init_German\n" if ($Curr{"Debug"} =~ /trace/);
- my($d)=@_;
- my(%h)=();
- &Char_8Bit(\%h);
- my($a)=$h{"a:"};
- my($u)=$h{"u:"};
- my($o)=$h{"o:"};
- my($b)=$h{"beta"};
-
- $$d{"month_name"}=
- [["Januar","Februar","Maerz","April","Mai","Juni",
- "Juli","August","September","Oktober","November","Dezember"],
- ["J${a}nner","Februar","M${a}rz","April","Mai","Juni",
- "Juli","August","September","Oktober","November","Dezember"]];
- $$d{"month_abb"}=
- [["Jan","Feb","Mar","Apr","Mai","Jun",
- "Jul","Aug","Sep","Okt","Nov","Dez"],
- ["J${a}n","Feb","M${a}r","Apr","Mai","Jun",
- "Jul","Aug","Sep","Okt","Nov","Dez"]];
-
- $$d{"day_name"}=
- [["Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag",
- "Sonntag"]];
- $$d{"day_abb"}=
- [["Mon","Die","Mit","Don","Fre","Sam","Son"]];
- $$d{"day_char"}=
- [["M","Di","Mi","Do","F","Sa","So"]];
-
- $$d{"num_suff"}=
- [["1.","2.","3.","4.","5.","6.","7.","8.","9.","10.",
- "11.","12.","13.","14.","15.","16.","17.","18.","19.","20.",
- "21.","22.","23.","24.","25.","26.","27.","28.","29.","30.",
- "31."]];
- $$d{"num_word"}=
- [
- ["erste","zweite","dritte","vierte","funfte","sechste","siebente",
- "achte","neunte","zehnte","elfte","zwolfte","dreizehnte","vierzehnte",
- "funfzehnte","sechzehnte","siebzehnte","achtzehnte","neunzehnte",
- "zwanzigste","einundzwanzigste","zweiundzwanzigste","dreiundzwanzigste",
- "vierundzwanzigste","funfundzwanzigste","sechundzwanzigste",
- "siebundzwanzigste","achtundzwanzigste","neunundzwanzigste",
- "dreibigste","einunddreibigste"],
- ["erste","zweite","dritte","vierte","f${u}nfte","sechste","siebente",
- "achte","neunte","zehnte","elfte","zw${o}lfte","dreizehnte",
- "vierzehnte","f${u}nfzehnte","sechzehnte","siebzehnte","achtzehnte",
- "neunzehnte","zwanzigste","einundzwanzigste","zweiundzwanzigste",
- "dreiundzwanzigste","vierundzwanzigste","f${u}nfundzwanzigste",
- "sechundzwanzigste","siebundzwanzigste","achtundzwanzigste",
- "neunundzwanzigste","drei${b}igste","einunddrei${b}igste"],
- ["erster"]];
-
- $$d{"now"} =["heute","jetzt"];
- $$d{"last"} =["letzte","letzten"];
- $$d{"each"} =["jeden"];
- $$d{"of"} =["der","im","des"];
- $$d{"at"} =["um"];
- $$d{"on"} =["am"];
- $$d{"future"} =["in"];
- $$d{"past"} =["vor"];
- $$d{"next"} =["nachste","n${a}chste","nachsten","n${a}chsten"];
- $$d{"prev"} =["vorherigen","vorherige","letzte","letzten"];
- $$d{"later"} =["spater","sp${a}ter"];
-
- $$d{"exact"} =["genau"];
- $$d{"approx"} =["ungefahr","ungef${a}hr"];
- $$d{"business"}=["Arbeitstag"];
-
- $$d{"offset"} =["gestern","-0:0:0:1:0:0:0","morgen","+0:0:0:1:0:0:0"];
- $$d{"times"} =["mittag","12:00:00","mitternacht","00:00:00"];
-
- $$d{"years"} =["j","Jahr","Jahre"];
- $$d{"months"} =["Monat","Monate"];
- $$d{"weeks"} =["w","Woche","Wochen"];
- $$d{"days"} =["t","Tag","Tage"];
- $$d{"hours"} =["h","std","Stunde","Stunden"];
- $$d{"minutes"} =["min","Minute","Minuten"];
- $$d{"seconds"} =["s","sek","Sekunde","Sekunden"];
- $$d{"replace"} =["m","Monat"];
-
- $$d{"sephm"} =':';
- $$d{"sepms"} ='[: ]';
- $$d{"sepss"} ='[.:]';
-
- $$d{"am"} = ["FM"];
- $$d{"pm"} = ["EM"];
-}
-
-sub Date_Init_Dutch {
- print "DEBUG: Date_Init_Dutch\n" if ($Curr{"Debug"} =~ /trace/);
- my($d)=@_;
- my(%h)=();
- &Char_8Bit(\%h);
-
- $$d{"month_name"}=
- [["januari","februari","maart","april","mei","juni","juli","augustus",
- "september","october","november","december"],
- ["","","","","","","","","","oktober"]];
-
- $$d{"month_abb"}=
- [["jan","feb","maa","apr","mei","jun","jul",
- "aug","sep","oct","nov","dec"],
- ["","","mrt","","","","","","","okt"]];
- $$d{"day_name"}=
- [["maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag",
- "zondag"]];
- $$d{"day_abb"}=
- [["ma","di","wo","do","vr","zat","zon"],
- ["","","","","","za","zo"]];
- $$d{"day_char"}=
- [["M","D","W","D","V","Za","Zo"]];
-
- $$d{"num_suff"}=
- [["1ste","2de","3de","4de","5de","6de","7de","8ste","9de","10de",
- "11de","12de","13de","14de","15de","16de","17de","18de","19de","20ste",
- "21ste","22ste","23ste","24ste","25ste","26ste","27ste","28ste","29ste",
- "30ste","31ste"]];
- $$d{"num_word"}=
- [["eerste","tweede","derde","vierde","vijfde","zesde","zevende","achtste",
- "negende","tiende","elfde","twaalfde",
- map {"${_}tiende";} qw (der veer vijf zes zeven acht negen),
- "twintigste",
- map {"${_}entwintigste";} qw (een twee drie vier vijf zes zeven acht
- negen),
- "dertigste","eenendertigste"],
- ["","","","","","","","","","","","","","","","","","","","",
- map {"${_}-en-twintigste";} qw (een twee drie vier vijf zes zeven acht
- negen),
- "dertigste","een-en-dertigste"],
- ["een","twee","drie","vier","vijf","zes","zeven","acht","negen","tien",
- "elf","twaalf",
- map {"${_}tien"} qw (der veer vijf zes zeven acht negen),
- "twintig",
- map {"${_}entwintig"} qw (een twee drie vier vijf zes zeven acht negen),
- "dertig","eenendertig"],
- ["","","","","","","","","","","","","","","","","","","","",
- map {"${_}-en-twintig"} qw (een twee drie vier vijf zes zeven acht
- negen),
- "dertig","een-en-dertig"]];
-
- $$d{"now"} =["nu","nou","vandaag"];
- $$d{"last"} =["laatste"];
- $$d{"each"} =["elke","elk"];
- $$d{"of"} =["in","van"];
- $$d{"at"} =["om"];
- $$d{"on"} =["op"];
- $$d{"future"} =["over"];
- $$d{"past"} =["geleden","vroeger","eerder"];
- $$d{"next"} =["volgende","volgend"];
- $$d{"prev"} =["voorgaande","voorgaand"];
- $$d{"later"} =["later"];
-
- $$d{"exact"} =["exact","precies","nauwkeurig"];
- $$d{"approx"} =["ongeveer","ong",'ong\.',"circa","ca",'ca\.'];
- $$d{"business"}=["werk","zakelijke","zakelijk"];
-
- $$d{"offset"} =["morgen","+0:0:0:1:0:0:0","overmorgen","+0:0:0:2:0:0:0",
- "gisteren","-0:0:0:1:0:0:0","eergisteren","-0::00:2:0:0:0"];
- $$d{"times"} =["noen","12:00:00","middernacht","00:00:00"];
-
- $$d{"years"} =["jaar","jaren","ja","j"];
- $$d{"months"} =["maand","maanden","mnd"];
- $$d{"weeks"} =["week","weken","w"];
- $$d{"days"} =["dag","dagen","d"];
- $$d{"hours"} =["uur","uren","u","h"];
- $$d{"minutes"} =["minuut","minuten","min"];
- $$d{"seconds"} =["seconde","seconden","sec","s"];
- $$d{"replace"} =["m","minuten"];
-
- $$d{"sephm"} ='[:.uh]';
- $$d{"sepms"} ='[:.m]';
- $$d{"sepss"} ='[.:]';
-
- $$d{"am"} = ["am","a.m.","vm","v.m.","voormiddag","'s_ochtends",
- "ochtend","'s_nachts","nacht"];
- $$d{"pm"} = ["pm","p.m.","nm","n.m.","namiddag","'s_middags","middag",
- "'s_avonds","avond"];
-}
-
-sub Date_Init_Polish {
- print "DEBUG: Date_Init_Polish\n" if ($Curr{"Debug"} =~ /trace/);
- my($d)=@_;
-
- $$d{"month_name"}=
- [["stycznia","luty","marca","kwietnia","maja","czerwca",
- "lipca","sierpnia","wrzesnia","pazdziernika","listopada","grudnia"],
- ["stycznia","luty","marca","kwietnia","maja","czerwca","lipca",
- "sierpnia","wrze\x9cnia","pa\x9fdziernika","listopada","grudnia"]];
- $$d{"month_abb"}=
- [["sty.","lut.","mar.","kwi.","maj","cze.",
- "lip.","sie.","wrz.","paz.","lis.","gru."],
- ["sty.","lut.","mar.","kwi.","maj","cze.",
- "lip.","sie.","wrz.","pa\x9f.","lis.","gru."]];
-
- $$d{"day_name"}=
- [["poniedzialek","wtorek","sroda","czwartek","piatek","sobota",
- "niedziela"],
- ["poniedzia\x81\xb3ek","wtorek","\x9croda","czwartek","pi\x81\xb9tek",
- "sobota","niedziela"]];
- $$d{"day_abb"}=
- [["po.","wt.","sr.","cz.","pi.","so.","ni."],
- ["po.","wt.","\x9cr.","cz.","pi.","so.","ni."]];
- $$d{"day_char"}=
- [["p","w","e","c","p","s","n"],
- ["p","w","\x9c.","c","p","s","n"]];
-
- $$d{"num_suff"}=
- [["1.","2.","3.","4.","5.","6.","7.","8.","9.","10.",
- "11.","12.","13.","14.","15.","16.","17.","18.","19.","20.",
- "21.","22.","23.","24.","25.","26.","27.","28.","29.","30.",
- "31."]];
- $$d{"num_word"}=
- [["pierwszego","drugiego","trzeczego","czwartego","piatego","szostego",
- "siodmego","osmego","dziewiatego","dziesiatego",
- "jedenastego","dwunastego","trzynastego","czternastego","pietnastego",
- "szestnastego","siedemnastego","osiemnastego","dziewietnastego",
- "dwudziestego",
- "dwudziestego pierwszego","dwudziestego drugiego",
- "dwudziestego trzeczego","dwudziestego czwartego",
- "dwudziestego piatego","dwudziestego szostego",
- "dwudziestego siodmego","dwudziestego osmego",
- "dwudziestego dziewiatego","trzydziestego","trzydziestego pierwszego"],
- ["pierwszego","drugiego","trzeczego","czwartego","pi\x81\xb9tego",
- "sz\x81\xf3stego","si\x81\xf3dmego","\x81\xf3smego","dziewi\x81\xb9tego",
- "dziesi\x81\xb9tego","jedenastego","dwunastego","trzynastego",
- "czternastego","pi\x81\xeatnastego","szestnastego","siedemnastego",
- "osiemnastego","dziewietnastego","dwudziestego",
- "dwudziestego pierwszego","dwudziestego drugiego",
- "dwudziestego trzeczego","dwudziestego czwartego",
- "dwudziestego pi\x81\xb9tego","dwudziestego sz\x81\xf3stego",
- "dwudziestego si\x81\xf3dmego","dwudziestego \x81\xf3smego",
- "dwudziestego dziewi\x81\xb9tego","trzydziestego",
- "trzydziestego pierwszego"]];
-
- $$d{"now"} =["dzisaj","teraz"];
- $$d{"last"} =["ostatni","ostatna"];
- $$d{"each"} =["kazdy","ka\x81\xbfdy", "kazdym","ka\x81\xbfdym"];
- $$d{"of"} =["w","z"];
- $$d{"at"} =["o","u"];
- $$d{"on"} =["na"];
- $$d{"future"} =["za"];
- $$d{"past"} =["temu"];
- $$d{"next"} =["nastepny","nast\x81\xeapny","nastepnym","nast\x81\xeapnym",
- "przyszly","przysz\x81\xb3y","przyszlym",
- "przysz\x81\xb3ym"];
- $$d{"prev"} =["zeszly","zesz\x81\xb3y","zeszlym","zesz\x81\xb3ym"];
- $$d{"later"} =["later"];
-
- $$d{"exact"} =["doklandnie","dok\x81\xb3andnie"];
- $$d{"approx"} =["w przyblizeniu","w przybli\x81\xbfeniu","mniej wiecej",
- "mniej wi\x81\xeacej","okolo","oko\x81\xb3o"];
- $$d{"business"}=["sluzbowy","s\x81\xb3u\x81\xbfbowy","sluzbowym",
- "s\x81\xb3u\x81\xbfbowym"];
-
- $$d{"times"} =["po\x81\xb3udnie","12:00:00",
- "p\x81\xf3\x81\xb3noc","00:00:00",
- "poludnie","12:00:00","polnoc","00:00:00"];
- $$d{"offset"} =["wczoraj","-0:0:1:0:0:0","jutro","+0:0:1:0:0:0"];
-
- $$d{"years"} =["rok","lat","lata","latach"];
- $$d{"months"} =["m.","miesiac","miesi\x81\xb9c","miesiecy",
- "miesi\x81\xeacy","miesiacu","miesi\x81\xb9cu"];
- $$d{"weeks"} =["ty.","tydzien","tydzie\x81\xf1","tygodniu"];
- $$d{"days"} =["d.","dzien","dzie\x81\xf1","dni"];
- $$d{"hours"} =["g.","godzina","godziny","godzinie"];
- $$d{"minutes"} =["mn.","min.","minut","minuty"];
- $$d{"seconds"} =["s.","sekund","sekundy"];
- $$d{"replace"} =["m.","miesiac"];
-
- $$d{"sephm"} =':';
- $$d{"sepms"} =':';
- $$d{"sepss"} ='[.:]';
-
- $$d{"am"} = ["AM","A.M."];
- $$d{"pm"} = ["PM","P.M."];
-}
-
-sub Date_Init_Spanish {
- print "DEBUG: Date_Init_Spanish\n" if ($Curr{"Debug"} =~ /trace/);
- my($d)=@_;
- my(%h)=();
- &Char_8Bit(\%h);
-
- $$d{"month_name"}=
- [["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto",
- "Septiembre","Octubre","Noviembre","Diciembre"]];
-
- $$d{"month_abb"}=
- [["Ene","Feb","Mar","Abr","May","Jun","Jul","Ago","Sep","Oct",
- "Nov","Dic"]];
-
- $$d{"day_name"}=
- [["Lunes","Martes","Miercoles","Jueves","Viernes","Sabado","Domingo"]];
- $$d{"day_abb"}=
- [["Lun","Mar","Mie","Jue","Vie","Sab","Dom"]];
- $$d{"day_char"}=
- [["L","Ma","Mi","J","V","S","D"]];
-
- $$d{"num_suff"}=
- [["1o","2o","3o","4o","5o","6o","7o","8o","9o","10o",
- "11o","12o","13o","14o","15o","16o","17o","18o","19o","20o",
- "21o","22o","23o","24o","25o","26o","27o","28o","29o","30o","31o"],
- ["1a","2a","3a","4a","5a","6a","7a","8a","9a","10a",
- "11a","12a","13a","14a","15a","16a","17a","18a","19a","20a",
- "21a","22a","23a","24a","25a","26a","27a","28a","29a","30a","31a"]];
- $$d{"num_word"}=
- [["Primero","Segundo","Tercero","Cuarto","Quinto","Sexto","Septimo",
- "Octavo","Noveno","Decimo","Decimo Primero","Decimo Segundo",
- "Decimo Tercero","Decimo Cuarto","Decimo Quinto","Decimo Sexto",
- "Decimo Septimo","Decimo Octavo","Decimo Noveno","Vigesimo",
- "Vigesimo Primero","Vigesimo Segundo","Vigesimo Tercero",
- "Vigesimo Cuarto","Vigesimo Quinto","Vigesimo Sexto",
- "Vigesimo Septimo","Vigesimo Octavo","Vigesimo Noveno","Trigesimo",
- "Trigesimo Primero"],
- ["Primera","Segunda","Tercera","Cuarta","Quinta","Sexta","Septima",
- "Octava","Novena","Decima","Decimo Primera","Decimo Segunda",
- "Decimo Tercera","Decimo Cuarta","Decimo Quinta","Decimo Sexta",
- "Decimo Septima","Decimo Octava","Decimo Novena","Vigesima",
- "Vigesimo Primera","Vigesimo Segunda","Vigesimo Tercera",
- "Vigesimo Cuarta","Vigesimo Quinta","Vigesimo Sexta",
- "Vigesimo Septima","Vigesimo Octava","Vigesimo Novena","Trigesima",
- "Trigesimo Primera"]];
-
- $$d{"now"} =["Hoy","Ahora"];
- $$d{"last"} =["ultimo"];
- $$d{"each"} =["cada"];
- $$d{"of"} =["en","de"];
- $$d{"at"} =["a"];
- $$d{"on"} =["el"];
- $$d{"future"} =["en"];
- $$d{"past"} =["hace"];
- $$d{"next"} =["siguiente"];
- $$d{"prev"} =["anterior"];
- $$d{"later"} =["later"];
-
- $$d{"exact"} =["exactamente"];
- $$d{"approx"} =["aproximadamente"];
- $$d{"business"}=["laborales"];
-
- $$d{"offset"} =["ayer","-0:0:0:1:0:0:0","manana","+0:0:0:1:0:0:0"];
- $$d{"times"} =["mediodia","12:00:00","medianoche","00:00:00"];
-
- $$d{"years"} =["a","ano","ano","anos","anos"];
- $$d{"months"} =["m","mes","mes","meses"];
- $$d{"weeks"} =["sem","semana","semana","semanas"];
- $$d{"days"} =["d","dia","dias"];
- $$d{"hours"} =["hr","hrs","hora","horas"];
- $$d{"minutes"} =["min","min","minuto","minutos"];
- $$d{"seconds"} =["s","seg","segundo","segundos"];
- $$d{"replace"} =["m","mes"];
-
- $$d{"sephm"} =':';
- $$d{"sepms"} =':';
- $$d{"sepss"} ='[.:]';
-
- $$d{"am"} = ["AM","A.M."];
- $$d{"pm"} = ["PM","P.M."];
-}
-
-sub Date_Init_Portuguese {
- print "DEBUG: Date_Init_Portuguese\n" if ($Curr{"Debug"} =~ /trace/);
- my($d)=@_;
- my(%h)=();
- &Char_8Bit(\%h);
- my($o) = $h{"-o"};
- my($c) = $h{",c"};
- my($a) = $h{"a'"};
- my($e) = $h{"e'"};
- my($u) = $h{"u'"};
- my($o2)= $h{"o'"};
- my($a2)= $h{"a`"};
- my($a3)= $h{"a~"};
- my($e2)= $h{"e^"};
-
- $$d{"month_name"}=
- [["Janeiro","Fevereiro","Marco","Abril","Maio","Junho",
- "Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],
- ["Janeiro","Fevereiro","Mar${c}o","Abril","Maio","Junho",
- "Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"]];
-
- $$d{"month_abb"}=
- [["Jan","Fev","Mar","Abr","Mai","Jun",
- "Jul","Ago","Set","Out","Nov","Dez"]];
-
- $$d{"day_name"}=
- [["Segunda","Terca","Quarta","Quinta","Sexta","Sabado","Domingo"],
- ["Segunda","Ter${c}a","Quarta","Quinta","Sexta","S${a}bado","Domingo"]];
- $$d{"day_abb"}=
- [["Seg","Ter","Qua","Qui","Sex","Sab","Dom"],
- ["Seg","Ter","Qua","Qui","Sex","S${a}b","Dom"]];
- $$d{"day_char"}=
- [["Sg","T","Qa","Qi","Sx","Sb","D"]];
-
- $$d{"num_suff"}=
- [["1${o}","2${o}","3${o}","4${o}","5${o}","6${o}","7${o}","8${o}",
- "9${o}","10${o}","11${o}","12${o}","13${o}","14${o}","15${o}",
- "16${o}","17${o}","18${o}","19${o}","20${o}","21${o}","22${o}",
- "23${o}","24${o}","25${o}","26${o}","27${o}","28${o}","29${o}",
- "30${o}","31${o}"]];
- $$d{"num_word"}=
- [["primeiro","segundo","terceiro","quarto","quinto","sexto","setimo",
- "oitavo","nono","decimo","decimo primeiro","decimo segundo",
- "decimo terceiro","decimo quarto","decimo quinto","decimo sexto",
- "decimo setimo","decimo oitavo","decimo nono","vigesimo",
- "vigesimo primeiro","vigesimo segundo","vigesimo terceiro",
- "vigesimo quarto","vigesimo quinto","vigesimo sexto","vigesimo setimo",
- "vigesimo oitavo","vigesimo nono","trigesimo","trigesimo primeiro"],
- ["primeiro","segundo","terceiro","quarto","quinto","sexto","s${e}timo",
- "oitavo","nono","d${e}cimo","d${e}cimo primeiro","d${e}cimo segundo",
- "d${e}cimo terceiro","d${e}cimo quarto","d${e}cimo quinto",
- "d${e}cimo sexto","d${e}cimo s${e}timo","d${e}cimo oitavo",
- "d${e}cimo nono","vig${e}simo","vig${e}simo primeiro",
- "vig${e}simo segundo","vig${e}simo terceiro","vig${e}simo quarto",
- "vig${e}simo quinto","vig${e}simo sexto","vig${e}simo s${e}timo",
- "vig${e}simo oitavo","vig${e}simo nono","trig${e}simo",
- "trig${e}simo primeiro"]];
-
- $$d{"now"} =["agora","hoje"];
- $$d{"last"} =["${u}ltimo","ultimo"];
- $$d{"each"} =["cada"];
- $$d{"of"} =["da","do"];
- $$d{"at"} =["as","${a2}s"];
- $$d{"on"} =["na","no"];
- $$d{"future"} =["em"];
- $$d{"past"} =["a","${a2}"];
- $$d{"next"} =["proxima","proximo","pr${o2}xima","pr${o2}ximo"];
- $$d{"prev"} =["ultima","ultimo","${u}ltima","${u}ltimo"];
- $$d{"later"} =["passadas","passados"];
-
- $$d{"exact"} =["exactamente"];
- $$d{"approx"} =["aproximadamente"];
- $$d{"business"}=["util","uteis"];
-
- $$d{"offset"} =["ontem","-0:0:0:1:0:0:0",
- "amanha","+0:0:0:1:0:0:0","amanh${a3}","+0:0:0:1:0:0:0"];
- $$d{"times"} =["meio-dia","12:00:00","meia-noite","00:00:00"];
-
- $$d{"years"} =["anos","ano","ans","an","a"];
- $$d{"months"} =["meses","m${e2}s","mes","m"];
- $$d{"weeks"} =["semanas","semana","sem","sems","s"];
- $$d{"days"} =["dias","dia","d"];
- $$d{"hours"} =["horas","hora","hr","hrs"];
- $$d{"minutes"} =["minutos","minuto","min","mn"];
- $$d{"seconds"} =["segundos","segundo","seg","sg"];
- $$d{"replace"} =["m","mes","s","sems"];
-
- $$d{"sephm"} =':';
- $$d{"sepms"} =':';
- $$d{"sepss"} ='[,]';
-
- $$d{"am"} = ["AM","A.M."];
- $$d{"pm"} = ["PM","P.M."];
-}
-
-sub Date_Init_Russian {
- print "DEBUG: Date_Init_Russian\n" if ($Curr{"Debug"} =~ /trace/);
- my($d)=@_;
- my(%h)=();
- &Char_8Bit(\%h);
- my($a) =$h{"a:"};
-
- $$d{"month_name"}=
- [
- ["\xd1\xce\xd7\xc1\xd2\xd1","\xc6\xc5\xd7\xd2\xc1\xcc\xd1",
- "\xcd\xc1\xd2\xd4\xc1","\xc1\xd0\xd2\xc5\xcc\xd1","\xcd\xc1\xd1",
- "\xc9\xc0\xce\xd1",
- "\xc9\xc0\xcc\xd1","\xc1\xd7\xc7\xd5\xd3\xd4\xc1",
- "\xd3\xc5\xce\xd4\xd1\xc2\xd2\xd1","\xcf\xcb\xd4\xd1\xc2\xd2\xd1",
- "\xce\xcf\xd1\xc2\xd2\xd1","\xc4\xc5\xcb\xc1\xc2\xd2\xd1"],
- ["\xd1\xce\xd7\xc1\xd2\xd8","\xc6\xc5\xd7\xd2\xc1\xcc\xd8",
- "\xcd\xc1\xd2\xd4","\xc1\xd0\xd2\xc5\xcc\xd8","\xcd\xc1\xca",
- "\xc9\xc0\xce\xd8",
- "\xc9\xc0\xcc\xd8","\xc1\xd7\xc7\xd5\xd3\xd4",
- "\xd3\xc5\xce\xd4\xd1\xc2\xd2\xd8","\xcf\xcb\xd4\xd1\xc2\xd2\xd8",
- "\xce\xcf\xd1\xc2\xd2\xd8","\xc4\xc5\xcb\xc1\xc2\xd2\xd8"]
- ];
-
- $$d{"month_abb"}=
- [["\xd1\xce\xd7","\xc6\xc5\xd7","\xcd\xd2\xd4","\xc1\xd0\xd2",
- "\xcd\xc1\xca","\xc9\xc0\xce",
- "\xc9\xc0\xcc","\xc1\xd7\xc7","\xd3\xce\xd4","\xcf\xcb\xd4",
- "\xce\xcf\xd1\xc2","\xc4\xc5\xcb"],
- ["","\xc6\xd7\xd2","","","\xcd\xc1\xd1","",
- "","","\xd3\xc5\xce","\xcf\xcb\xd4","\xce\xcf\xd1",""]];
-
- $$d{"day_name"}=
- [["\xd0\xcf\xce\xc5\xc4\xc5\xcc\xd8\xce\xc9\xcb",
- "\xd7\xd4\xcf\xd2\xce\xc9\xcb","\xd3\xd2\xc5\xc4\xc1",
- "\xde\xc5\xd4\xd7\xc5\xd2\xc7","\xd0\xd1\xd4\xce\xc9\xc3\xc1",
- "\xd3\xd5\xc2\xc2\xcf\xd4\xc1",
- "\xd7\xcf\xd3\xcb\xd2\xc5\xd3\xc5\xce\xd8\xc5"]];
- $$d{"day_abb"}=
- [["\xd0\xce\xc4","\xd7\xd4\xd2","\xd3\xd2\xc4","\xde\xd4\xd7",
- "\xd0\xd4\xce","\xd3\xd5\xc2","\xd7\xd3\xcb"],
- ["\xd0\xcf\xce","\xd7\xd4\xcf","\xd3\xd2e","\xde\xc5\xd4",
- "\xd0\xd1\xd4","\xd3\xd5\xc2","\xd7\xcf\xd3\xcb"]];
- $$d{"day_char"}=
- [["\xd0\xce","\xd7\xd4","\xd3\xd2","\xde\xd4","\xd0\xd4","\xd3\xc2",
- "\xd7\xd3"]];
-
- $$d{"num_suff"}=
- [["1 ","2 ","3 ","4 ","5 ","6 ","7 ","8 ","9 ","10 ",
- "11 ","12 ","13 ","14 ","15 ","16 ","17 ","18 ","19 ","20 ",
- "21 ","22 ","23 ","24 ","25 ","26 ","27 ","28 ","29 ","30 ",
- "31 "]];
- $$d{"num_word"}=
- [["\xd0\xc5\xd2\xd7\xd9\xca","\xd7\xd4\xcf\xd2\xcf\xca",
- "\xd4\xd2\xc5\xd4\xc9\xca","\xde\xc5\xd4\xd7\xc5\xd2\xd4\xd9\xca",
- "\xd0\xd1\xd4\xd9\xca","\xdb\xc5\xd3\xd4\xcf\xca",
- "\xd3\xc5\xc4\xd8\xcd\xcf\xca","\xd7\xcf\xd3\xd8\xcd\xcf\xca",
- "\xc4\xc5\xd7\xd1\xd4\xd9\xca","\xc4\xc5\xd3\xd1\xd4\xd9\xca",
- "\xcf\xc4\xc9\xce\xce\xc1\xc4\xc3\xc1\xd4\xd9\xca",
- "\xc4\xd7\xc5\xce\xc1\xc4\xde\xc1\xd4\xd9\xca",
- "\xd4\xd2\xc5\xce\xc1\xc4\xc3\xc1\xd4\xd9\xca",
- "\xde\xc5\xd4\xd9\xd2\xce\xc1\xc4\xc3\xc1\xd4\xd9\xca",
- "\xd0\xd1\xd4\xce\xc1\xc4\xc3\xc1\xd4\xd9\xca",
- "\xdb\xc5\xd3\xd4\xce\xc1\xc4\xc3\xc1\xd4\xd9\xca",
- "\xd3\xc5\xcd\xd8\xce\xc1\xc4\xc3\xc1\xd4\xd9\xca",
- "\xd7\xcf\xd3\xc5\xcd\xd8\xce\xc1\xc4\xc3\xc1\xd4\xd9\xca",
- "\xc4\xc5\xd7\xd1\xd4\xce\xc1\xc4\xc3\xc1\xd4\xd9\xca",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd9\xca",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd0\xc5\xd2\xd7\xd9\xca",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd7\xd4\xcf\xd2\xcf\xca",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd4\xd2\xc5\xd4\xc9\xca",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xde\xc5\xd4\xd7\xc5\xd2\xd4\xd9\xca",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd0\xd1\xd4\xd9\xca",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xdb\xc5\xd3\xd4\xcf\xca",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd3\xc5\xc4\xd8\xcd\xcf\xca",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd7\xcf\xd3\xd8\xcd\xcf\xca",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xc4\xc5\xd7\xd1\xd4\xd9\xca",
- "\xd4\xd2\xc9\xc4\xc3\xc1\xd4\xd9\xca",
- "\xd4\xd2\xc9\xc4\xc3\xc1\xd4\xd8 \xd0\xc5\xd2\xd7\xd9\xca"],
-
- ["\xd0\xc5\xd2\xd7\xcf\xc5","\xd7\xd4\xcf\xd2\xcf\xc5",
- "\xd4\xd2\xc5\xd4\xd8\xc5","\xde\xc5\xd4\xd7\xc5\xd2\xd4\xcf\xc5",
- "\xd0\xd1\xd4\xcf\xc5","\xdb\xc5\xd3\xd4\xcf\xc5",
- "\xd3\xc5\xc4\xd8\xcd\xcf\xc5","\xd7\xcf\xd3\xd8\xcd\xcf\xc5",
- "\xc4\xc5\xd7\xd1\xd4\xcf\xc5","\xc4\xc5\xd3\xd1\xd4\xcf\xc5",
- "\xcf\xc4\xc9\xce\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc5",
- "\xc4\xd7\xc5\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc5",
- "\xd4\xd2\xc5\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc5",
- "\xde\xc5\xd4\xd9\xd2\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc5",
- "\xd0\xd1\xd4\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc5",
- "\xdb\xc5\xd3\xd4\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc5",
- "\xd3\xc5\xcd\xd8\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc5",
- "\xd7\xcf\xd3\xc5\xcd\xd8\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc5",
- "\xc4\xc5\xd7\xd1\xd4\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc5",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xcf\xc5",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd0\xc5\xd2\xd7\xcf\xc5",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd7\xd4\xcf\xd2\xcf\xc5",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd4\xd2\xc5\xd4\xd8\xc5",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xde\xc5\xd4\xd7\xc5\xd2\xd4\xcf\xc5",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd0\xd1\xd4\xcf\xc5",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xdb\xc5\xd3\xd4\xcf\xc5",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd3\xc5\xc4\xd8\xcd\xcf\xc5",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd7\xcf\xd3\xd8\xcd\xcf\xc5",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xc4\xc5\xd7\xd1\xd4\xcf\xc5",
- "\xd4\xd2\xc9\xc4\xc3\xc1\xd4\xcf\xc5",
- "\xd4\xd2\xc9\xc4\xc3\xc1\xd4\xd8 \xd0\xc5\xd2\xd7\xcf\xc5"],
-
- ["\xd0\xc5\xd2\xd7\xcf\xc7\xcf","\xd7\xd4\xcf\xd2\xcf\xc7\xcf",
- "\xd4\xd2\xc5\xd4\xd8\xc5\xc7\xcf",
- "\xde\xc5\xd4\xd7\xc5\xd2\xd4\xcf\xc7\xcf","\xd0\xd1\xd4\xcf\xc7\xcf",
- "\xdb\xc5\xd3\xd4\xcf\xc7\xcf","\xd3\xc5\xc4\xd8\xcd\xcf\xc7\xcf",
- "\xd7\xcf\xd3\xd8\xcd\xcf\xc7\xcf",
- "\xc4\xc5\xd7\xd1\xd4\xcf\xc7\xcf","\xc4\xc5\xd3\xd1\xd4\xcf\xc7\xcf",
- "\xcf\xc4\xc9\xce\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf",
- "\xc4\xd7\xc5\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf",
- "\xd4\xd2\xc5\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf",
- "\xde\xc5\xd4\xd9\xd2\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf",
- "\xd0\xd1\xd4\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf",
- "\xdb\xc5\xd3\xd4\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf",
- "\xd3\xc5\xcd\xd8\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf",
- "\xd7\xcf\xd3\xc5\xcd\xd8\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf",
- "\xc4\xc5\xd7\xd1\xd4\xce\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xcf\xc7\xcf",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd0\xc5\xd2\xd7\xcf\xc7\xcf",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd7\xd4\xcf\xd2\xcf\xc5",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd4\xd2\xc5\xd4\xd8\xc5\xc7\xcf",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xde\xc5\xd4\xd7\xc5\xd2\xd4\xcf\xc7\xcf",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd0\xd1\xd4\xcf\xc7\xcf",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xdb\xc5\xd3\xd4\xcf\xc7\xcf",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd3\xc5\xc4\xd8\xcd\xcf\xc7\xcf",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xd7\xcf\xd3\xd8\xcd\xcf\xc7\xcf",
- "\xc4\xd7\xc1\xc4\xc3\xc1\xd4\xd8 \xc4\xc5\xd7\xd1\xd4\xcf\xc7\xcf",
- "\xd4\xd2\xc9\xc4\xc3\xc1\xd4\xcf\xc7\xcf",
- "\xd4\xd2\xc9\xc4\xc3\xc1\xd4\xd8 \xd0\xc5\xd2\xd7\xcf\xc7\xcf"]];
-
- $$d{"now"} =["\xd3\xc5\xc7\xcf\xc4\xce\xd1","\xd3\xc5\xca\xde\xc1\xd3"];
- $$d{"last"} =["\xd0\xcf\xd3\xcc\xc5\xc4\xce\xc9\xca"];
- $$d{"each"} =["\xcb\xc1\xd6\xc4\xd9\xca"];
- $$d{"of"} =[" "];
- $$d{"at"} =["\xd7"];
- $$d{"on"} =["\xd7"];
- $$d{"future"} =["\xd7\xd0\xc5\xd2\xc5\xc4 \xce\xc1"];
- $$d{"past"} =["\xce\xc1\xda\xc1\xc4 \xce\xc1 "];
- $$d{"next"} =["\xd3\xcc\xc5\xc4\xd5\xc0\xdd\xc9\xca"];
- $$d{"prev"} =["\xd0\xd2\xc5\xc4\xd9\xc4\xd5\xdd\xc9\xca"];
- $$d{"later"} =["\xd0\xcf\xda\xd6\xc5"];
-
- $$d{"exact"} =["\xd4\xcf\xde\xce\xcf"];
- $$d{"approx"} =["\xd0\xd2\xc9\xcd\xc5\xd2\xce\xcf"];
- $$d{"business"}=["\xd2\xc1\xc2\xcf\xde\xc9\xc8"];
-
- $$d{"offset"} =["\xd0\xcf\xda\xc1\xd7\xde\xc5\xd2\xc1","-0:0:0:2:0:0:0",
- "\xd7\xde\xc5\xd2\xc1","-0:0:0:1:0:0:0",
- "\xda\xc1\xd7\xd4\xd2\xc1","+0:0:0:1:0:0:0",
- "\xd0\xcf\xd3\xcc\xc5\xda\xc1\xd7\xd4\xd2\xc1",
- "+0:0:0:2:0:0:0"];
- $$d{"times"} =["\xd0\xcf\xcc\xc4\xc5\xce\xd8","12:00:00",
- "\xd0\xcf\xcc\xce\xcf\xde\xd8","00:00:00"];
-
- $$d{"years"} =["\xc7","\xc7\xc4","\xc7\xcf\xc4","\xcc\xc5\xd4",
- "\xcc\xc5\xd4","\xc7\xcf\xc4\xc1"];
- $$d{"months"} =["\xcd\xc5\xd3","\xcd\xc5\xd3\xd1\xc3",
- "\xcd\xc5\xd3\xd1\xc3\xc5\xd7"];
- $$d{"weeks"} =["\xce\xc5\xc4\xc5\xcc\xd1","\xce\xc5\xc4\xc5\xcc\xd8",
- "\xce\xc5\xc4\xc5\xcc\xc9","\xce\xc5\xc4\xc5\xcc\xc0"];
- $$d{"days"} =["\xc4","\xc4\xc5\xce\xd8","\xc4\xce\xc5\xca",
- "\xc4\xce\xd1"];
- $$d{"hours"} =["\xde","\xde.","\xde\xd3","\xde\xd3\xd7","\xde\xc1\xd3",
- "\xde\xc1\xd3\xcf\xd7","\xde\xc1\xd3\xc1"];
- $$d{"minutes"} =["\xcd\xce","\xcd\xc9\xce","\xcd\xc9\xce\xd5\xd4\xc1",
- "\xcd\xc9\xce\xd5\xd4"];
- $$d{"seconds"} =["\xd3","\xd3\xc5\xcb","\xd3\xc5\xcb\xd5\xce\xc4\xc1",
- "\xd3\xc5\xcb\xd5\xce\xc4"];
- $$d{"replace"} =[];
-
- $$d{"sephm"} ="[:\xde]";
- $$d{"sepms"} ="[:\xcd]";
- $$d{"sepss"} ="[:.\xd3]";
-
- $$d{"am"} = ["\xc4\xd0","${a}\xf0","${a}.\xf0.","\xce\xcf\xde\xc9",
- "\xd5\xd4\xd2\xc1",
- "\xc4\xcf \xd0\xcf\xcc\xd5\xc4\xce\xd1"];
- $$d{"pm"} = ["\xd0\xd0","\xf0\xf0","\xf0.\xf0.","\xc4\xce\xd1",
- "\xd7\xc5\xde\xc5\xd2\xc1",
- "\xd0\xcf\xd3\xcc\xc5 \xd0\xcf\xcc\xd5\xc4\xce\xd1",
- "\xd0\xcf \xd0\xcf\xcc\xd5\xc4\xce\xc0"];
-}
-
-sub Date_Init_Turkish {
- print "DEBUG: Date_Init_Turkish\n" if ($Curr{"Debug"} =~ /trace/);
- my($d)=@_;
-
- $$d{"month_name"}=
- [
- ["ocak","subat","mart","nisan","mayis","haziran",
- "temmuz","agustos","eylul","ekim","kasim","aralik"],
- ["ocak","\xfeubat","mart","nisan","may\xfds","haziran",
- "temmuz","a\xf0ustos","eyl\xfcl","ekim","kas\xfdm","aral\xfdk"]
- ];
-
- $$d{"month_abb"}=
- [
- ["oca","sub","mar","nis","may","haz",
- "tem","agu","eyl","eki","kas","ara"],
- ["oca","\xfeub","mar","nis","may","haz",
- "tem","a\xf0u","eyl","eki","kas","ara"]
- ];
-
- $$d{"day_name"}=
- [
- ["pazartesi","sali","carsamba","persembe","cuma","cumartesi","pazar"],
- ["pazartesi","sal\xfd","\xe7ar\xfeamba","per\xfeembe","cuma",
- "cumartesi","pazar"],
- ];
-
- $$d{"day_abb"}=
- [
- ["pzt","sal","car","per","cum","cts","paz"],
- ["pzt","sal","\xe7ar","per","cum","cts","paz"],
- ];
-
- $$d{"day_char"}=
- [["Pt","S","Cr","Pr","C","Ct","P"],
- ["Pt","S","\xc7","Pr","C","Ct","P"]];
-
- $$d{"num_suff"}=
- [[ "1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.", "9.", "10.",
- "11.", "12.", "13.", "14.", "15.", "16.", "17.", "18.", "19.", "20.",
- "21.", "22.", "23.", "24.", "25.", "26.", "27.", "28.", "29.", "30.",
- "31."]];
-
- $$d{"num_word"}=
- [
- ["birinci","ikinci","ucuncu","dorduncu",
- "besinci","altinci","yedinci","sekizinci",
- "dokuzuncu","onuncu","onbirinci","onikinci",
- "onucuncu","ondordoncu",
- "onbesinci","onaltinci","onyedinci","onsekizinci",
- "ondokuzuncu","yirminci","yirmibirinci","yirmikinci",
- "yirmiucuncu","yirmidorduncu",
- "yirmibesinci","yirmialtinci","yirmiyedinci","yirmisekizinci",
- "yirmidokuzuncu","otuzuncu","otuzbirinci"],
- ["birinci","ikinci","\xfc\xe7\xfcnc\xfc","d\xf6rd\xfcnc\xfc",
- "be\xfeinci","alt\xfdnc\xfd","yedinci","sekizinci",
- "dokuzuncu","onuncu","onbirinci","onikinci",
- "on\xfc\xe7\xfcnc\xfc","ond\xf6rd\xfcnc\xfc",
- "onbe\xfeinci","onalt\xfdnc\xfd","onyedinci","onsekizinci",
- "ondokuzuncu","yirminci","yirmibirinci","yirmikinci",
- "yirmi\xfc\xe7\xfcnc\xfc","yirmid\xf6rd\xfcnc\xfc",
- "yirmibe\xfeinci","yirmialt\xfdnc\xfd","yirmiyedinci","yirmisekizinci",
- "yirmidokuzuncu","otuzuncu","otuzbirinci"]
- ];
-
- $$d{"now"} =["\xfeimdi", "simdi", "bugun","bug\xfcn"];
- $$d{"last"} =["son", "sonuncu"];
- $$d{"each"} =["her"];
- $$d{"of"} =["of"];
- $$d{"at"} =["saat"];
- $$d{"on"} =["on"];
- $$d{"future"} =["gelecek"];
- $$d{"past"} =["ge\xe7mi\xfe", "gecmis","gecen", "ge\xe7en"];
- $$d{"next"} =["gelecek","sonraki"];
- $$d{"prev"} =["onceki","\xf6nceki"];
- $$d{"later"} =["sonra"];
-
- $$d{"exact"} =["tam"];
- $$d{"approx"} =["yakla\xfe\xfdk", "yaklasik"];
- $$d{"business"}=["i\xfe","\xe7al\xfd\xfema","is", "calisma"];
-
- $$d{"offset"} =["d\xfcn","-0:0:0:1:0:0:0",
- "dun", "-0:0:0:1:0:0:0",
- "yar\xfdn","+0:0:0:1:0:0:0",
- "yarin","+0:0:0:1:0:0:0"];
-
- $$d{"times"} =["\xf6\xf0len","12:00:00",
- "oglen","12:00:00",
- "yarim","12:300:00",
- "yar\xfdm","12:30:00",
- "gece yar\xfds\xfd","00:00:00",
- "gece yarisi","00:00:00"];
-
- $$d{"years"} =["yil","y"];
- $$d{"months"} =["ay","a"];
- $$d{"weeks"} =["hafta", "h"];
- $$d{"days"} =["gun","g"];
- $$d{"hours"} =["saat"];
- $$d{"minutes"} =["dakika","dak","d"];
- $$d{"seconds"} =["saniye","sn",];
- $$d{"replace"} =["s","saat"];
-
- $$d{"sephm"} =':';
- $$d{"sepms"} =':';
- $$d{"sepss"} ='[.:,]';
-
- $$d{"am"} = ["\xf6gleden \xf6nce","ogleden once"];
- $$d{"pm"} = ["\xf6\xf0leden sonra","ogleden sonra"];
-}
-
-sub Date_Init_Danish {
- print "DEBUG: Date_Init_Danish\n" if ($Curr{"Debug"} =~ /trace/);
- my($d)=@_;
-
- $$d{"month_name"}=
- [["Januar","Februar","Marts","April","Maj","Juni",
- "Juli","August","September","Oktober","November","December"]];
- $$d{"month_abb"}=
- [["Jan","Feb","Mar","Apr","Maj","Jun",
- "Jul","Aug","Sep","Okt","Nov","Dec"]];
-
- $$d{"day_name"}=
- [["Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lordag","Sondag"],
- ["Mandag","Tirsdag","Onsdag","Torsdag","Fredag","L\xf8rdag","S\xf8ndag"]];
-
- $$d{"day_abb"}=
- [["Man","Tis","Ons","Tor","Fre","Lor","Son"],
- ["Man","Tis","Ons","Tor","Fre","L\xf8r","S\xf8n"]];
- $$d{"day_char"}=
- [["M","Ti","O","To","F","L","S"]];
-
- $$d{"num_suff"}=
- [["1:e","2:e","3:e","4:e","5:e","6:e","7:e","8:e","9:e","10:e",
- "11:e","12:e","13:e","14:e","15:e","16:e","17:e","18:e","19:e","20:e",
- "21:e","22:e","23:e","24:e","25:e","26:e","27:e","28:e","29:e","30:e",
- "31:e"]];
- $$d{"num_word"}=
- [["forste","anden","tredie","fjerde","femte","sjette","syvende",
- "ottende","niende","tiende","elfte","tolvte","trettende","fjortende",
- "femtende","sekstende","syttende","attende","nittende","tyvende",
- "enogtyvende","toogtyvende","treogtyvende","fireogtyvende","femogtyvende",
- "seksogtyvende","syvogtyvende","otteogtyvende","niogtyvende",
- "tredivte","enogtredivte"],
- ["f\xf8rste","anden","tredie","fjerde","femte","sjette","syvende",
- "ottende","niende","tiende","elfte","tolvte","trettende","fjortende",
- "femtende","sekstende","syttende","attende","nittende","tyvende",
- "enogtyvende","toogtyvende","treogtyvende","fireogtyvende","femogtyvende",
- "seksogtyvende","syvogtyvende","otteogtyvende","niogtyvende",
- "tredivte","enogtredivte"]];
-
- $$d{"now"} =["idag","nu"];
- $$d{"last"} =["forrige","sidste","nyeste"];
- $$d{"each"} =["hver"];
- $$d{"of"} =["om"];
- $$d{"at"} =["kl","kl.","klokken"];
- $$d{"on"} =["pa","p\xe5"];
- $$d{"future"} =["om"];
- $$d{"past"} =["siden"];
- $$d{"next"} =["nasta","n\xe6ste"];
- $$d{"prev"} =["forrige"];
- $$d{"later"} =["senere"];
-
- $$d{"exact"} =["pracist","pr\xe6cist"];
- $$d{"approx"} =["circa"];
- $$d{"business"}=["arbejdsdag","arbejdsdage"];
-
- $$d{"offset"} =["ig\xe5r","-0:0:0:1:0:0:0","igar","-0:0:0:1:0:0:0",
- "imorgen","+0:0:0:1:0:0:0"];
- $$d{"times"} =["midt pa dagen","12:00:00","midt p\xe5 dagen","12:00:00",
- "midnat","00:00:00"];
-
- $$d{"years"} =["ar","\xe5r"];
- $$d{"months"} =["man","maned","maneder","m\xe5n","m\xe5ned","m\xe5neder"];
- $$d{"weeks"} =["u","uge","uger"];
- $$d{"days"} =["d","dag","dage"];
- $$d{"hours"} =["t","tim","time","timer"];
- $$d{"minutes"} =["min","minut","minutter"];
- $$d{"seconds"} =["s","sek","sekund","sekunder"];
- $$d{"replace"} =["m","minut"];
-
- $$d{"sephm"} ='[.:]';
- $$d{"sepms"} =':';
- $$d{"sepss"} ='[.:]';
-
- $$d{"am"} = ["FM"];
- $$d{"pm"} = ["EM"];
-}
-
-########################################################################
-# FROM MY PERSONAL LIBRARIES
-########################################################################
-
-no integer;
-
-# &ModuloAddition($N,$add,\$val,\$rem);
-# This calculates $val=$val+$add and forces $val to be in a certain range.
-# This is useful for adding numbers for which only a certain range is
-# allowed (for example, minutes can be between 0 and 59 or months can be
-# between 1 and 12). The absolute value of $N determines the range and
-# the sign of $N determines whether the range is 0 to N-1 (if N>0) or
-# 1 to N (N<0). The remainder (as modulo N) is added to $rem.
-# Example:
-# To add 2 hours together (with the excess returned in days) use:
-# &ModuloAddition(60,$s1,\$s,\$day);
-sub ModuloAddition {
- my($N,$add,$val,$rem)=@_;
- return if ($N==0);
- $$val+=$add;
- if ($N<0) {
- # 1 to N
- $N = -$N;
- if ($$val>$N) {
- $$rem+= int(($$val-1)/$N);
- $$val = ($$val-1)%$N +1;
- } elsif ($$val<1) {
- $$rem-= int(-$$val/$N)+1;
- $$val = $N-(-$$val % $N);
- }
-
- } else {
- # 0 to N-1
- if ($$val>($N-1)) {
- $$rem+= int($$val/$N);
- $$val = $$val%$N;
- } elsif ($$val<0) {
- $$rem-= int(-($$val+1)/$N)+1;
- $$val = ($N-1)-(-($$val+1)%$N);
- }
- }
-}
-
-# $Flag=&IsInt($String [,$low, $high]);
-# Returns 1 if $String is a valid integer, 0 otherwise. If $low is
-# entered, $String must be >= $low. If $high is entered, $String must
-# be <= $high. It is valid to check only one of the bounds.
-sub IsInt {
- my($N,$low,$high)=@_;
- return 0 if (! defined $N or
- $N !~ /^\s*[-+]?\d+\s*$/ or
- defined $low && $N<$low or
- defined $high && $N>$high);
- return 1;
-}
-
-# $Pos=&SinLindex(\@List,$Str [,$offset [,$CaseInsensitive]]);
-# Searches for an exact string in a list.
-#
-# This is similar to RinLindex except that it searches for elements
-# which are exactly equal to $Str (possibly case insensitive).
-sub SinLindex {
- my($listref,$Str,$offset,$Insensitive)=@_;
- my($i,$len,$tmp)=();
- $len=$#$listref;
- return -2 if ($len<0 or ! $Str);
- return -1 if (&Index_First(\$offset,$len));
- $Str=uc($Str) if ($Insensitive);
- for ($i=$offset; $i<=$len; $i++) {
- $tmp=$$listref[$i];
- $tmp=uc($tmp) if ($Insensitive);
- return $i if ($tmp eq $Str);
- }
- return -1;
-}
-
-sub Index_First {
- my($offsetref,$max)=@_;
- $$offsetref=0 if (! $$offsetref);
- if ($$offsetref < 0) {
- $$offsetref += $max + 1;
- $$offsetref=0 if ($$offsetref < 0);
- }
- return -1 if ($$offsetref > $max);
- return 0;
-}
-
-# $File=&CleanFile($file);
-# This cleans up a path to remove the following things:
-# double slash /a//b -> /a/b
-# trailing dot /a/. -> /a
-# leading dot ./a -> a
-# trailing slash a/ -> a
-sub CleanFile {
- my($file)=@_;
- $file =~ s/\s*$//;
- $file =~ s/^\s*//;
- $file =~ s|//+|/|g; # multiple slash
- $file =~ s|/\.$|/|; # trailing /. (leaves trailing slash)
- $file =~ s|^\./|| # leading ./
- if ($file ne "./");
- $file =~ s|/$|| # trailing slash
- if ($file ne "/");
- return $file;
-}
-
-# $File=&ExpandTilde($file);
-# This checks to see if a "~" appears as the first character in a path.
-# If it does, the "~" expansion is interpreted (if possible) and the full
-# path is returned. If a "~" expansion is used but cannot be
-# interpreted, an empty string is returned.
-#
-# This is Windows/Mac friendly.
-# This is efficient.
-sub ExpandTilde {
- my($file)=shift;
- my($user,$home)=();
- # ~aaa/bbb= ~ aaa /bbb
- if ($file =~ s|^~([^/]*)||) {
- $user=$1;
- # Single user operating systems (Mac, MSWindows) don't have the getpwnam
- # and getpwuid routines defined. Try to catch various different ways
- # of knowing we are on one of these systems:
- return "" if ($OS eq "Windows" or
- $OS eq "Mac" or
- $OS eq "Netware" or
- $OS eq "MPE");
- $user="" if (! defined $user);
-
- if ($user) {
- $home= (getpwnam($user))[7];
- } else {
- $home= (getpwuid($<))[7];
- }
- $home = VMS::Filespec::unixpath($home) if ($OS eq "VMS");
- return "" if (! $home);
- $file="$home/$file";
- }
- $file;
-}
-
-# $File=&FullFilePath($file);
-# Returns the full or relative path to $file (expanding "~" if necessary).
-# Returns an empty string if a "~" expansion cannot be interpreted. The
-# path does not need to exist. CleanFile is called.
-sub FullFilePath {
- my($file)=shift;
- my($rootpat) = '^/'; #default pattern to match absolute path
- $rootpat = '^(\\|/|([A-Za-z]:[\\/]))' if ($OS eq 'Windows');
- $file=&ExpandTilde($file);
- return "" if (! $file);
- return &CleanFile($file);
-}
-
-# $Flag=&CheckFilePath($file [,$mode]);
-# Checks to see if $file exists, to see what type it is, and whether
-# the script can access it. If it exists and has the correct mode, 1
-# is returned.
-#
-# $mode is a string which may contain any of the valid file test operator
-# characters except t, M, A, C. The appropriate test is run for each
-# character. For example, if $mode is "re" the -r and -e tests are both
-# run.
-#
-# An empty string is returned if the file doesn't exist. A 0 is returned
-# if the file exists but any test fails.
-#
-# All characters in $mode which do not correspond to valid tests are
-# ignored.
-sub CheckFilePath {
- my($file,$mode)=@_;
- my($test)=();
- $file=&FullFilePath($file);
- $mode = "" if (! defined $mode);
-
- # Run tests
- return 0 if (! defined $file or ! $file);
- return 0 if (( ! -e $file) or
- ($mode =~ /r/ && ! -r $file) or
- ($mode =~ /w/ && ! -w $file) or
- ($mode =~ /x/ && ! -x $file) or
- ($mode =~ /R/ && ! -R $file) or
- ($mode =~ /W/ && ! -W $file) or
- ($mode =~ /X/ && ! -X $file) or
- ($mode =~ /o/ && ! -o $file) or
- ($mode =~ /O/ && ! -O $file) or
- ($mode =~ /z/ && ! -z $file) or
- ($mode =~ /s/ && ! -s $file) or
- ($mode =~ /f/ && ! -f $file) or
- ($mode =~ /d/ && ! -d $file) or
- ($mode =~ /l/ && ! -l $file) or
- ($mode =~ /s/ && ! -s $file) or
- ($mode =~ /p/ && ! -p $file) or
- ($mode =~ /b/ && ! -b $file) or
- ($mode =~ /c/ && ! -c $file) or
- ($mode =~ /u/ && ! -u $file) or
- ($mode =~ /g/ && ! -g $file) or
- ($mode =~ /k/ && ! -k $file) or
- ($mode =~ /T/ && ! -T $file) or
- ($mode =~ /B/ && ! -B $file));
- return 1;
-}
-#&&
-
-# $Path=&FixPath($path [,$full] [,$mode] [,$error]);
-# Makes sure that every directory in $path (a colon separated list of
-# directories) appears as a full path or relative path. All "~"
-# expansions are removed. All trailing slashes are removed also. If
-# $full is non-nil, relative paths are expanded to full paths as well.
-#
-# If $mode is given, it may be either "e", "r", or "w". In this case,
-# additional checking is done to each directory. If $mode is "e", it
-# need ony exist to pass the check. If $mode is "r", it must have have
-# read and execute permission. If $mode is "w", it must have read,
-# write, and execute permission.
-#
-# The value of $error determines what happens if the directory does not
-# pass the test. If it is non-nil, if any directory does not pass the
-# test, the subroutine returns the empty string. Otherwise, it is simply
-# removed from $path.
-#
-# The corrected path is returned.
-sub FixPath {
- my($path,$full,$mode,$err)=@_;
- local($_)="";
- my(@dir)=split(/$Cnf{"PathSep"}/,$path);
- $full=0 if (! defined $full);
- $mode="" if (! defined $mode);
- $err=0 if (! defined $err);
- $path="";
- if ($mode eq "e") {
- $mode="de";
- } elsif ($mode eq "r") {
- $mode="derx";
- } elsif ($mode eq "w") {
- $mode="derwx";
- }
-
- foreach (@dir) {
-
- # Expand path
- if ($full) {
- $_=&FullFilePath($_);
- } else {
- $_=&ExpandTilde($_);
- }
- if (! $_) {
- return "" if ($err);
- next;
- }
-
- # Check mode
- if (! $mode or &CheckFilePath($_,$mode)) {
- $path .= $Cnf{"PathSep"} . $_;
- } else {
- return "" if ($err);
- }
- }
- $path =~ s/^$Cnf{"PathSep"}//;
- return $path;
-}
-#&&
-
-# $File=&SearchPath($file,$path [,$mode] [,@suffixes]);
-# Searches through directories in $path for a file named $file. The
-# full path is returned if one is found, or an empty string otherwise.
-# The file may exist with one of the @suffixes. The mode is checked
-# similar to &CheckFilePath.
-#
-# The first full path that matches the name and mode is returned. If none
-# is found, an empty string is returned.
-sub SearchPath {
- my($file,$path,$mode,@suff)=@_;
- my($f,$s,$d,@dir,$fs)=();
- $path=&FixPath($path,1,"r");
- @dir=split(/$Cnf{"PathSep"}/,$path);
- foreach $d (@dir) {
- $f="$d/$file";
- $f=~ s|//|/|g;
- return $f if (&CheckFilePath($f,$mode));
- foreach $s (@suff) {
- $fs="$f.$s";
- return $fs if (&CheckFilePath($fs,$mode));
- }
- }
- return "";
-}
-
-# @list=&ReturnList($str);
-# This takes a string which should be a comma separated list of integers
-# or ranges (5-7). It returns a sorted list of all integers referred to
-# by the string, or () if there is an invalid element.
-#
-# Negative integers are also handled. "-2--1" is equivalent to "-2,-1".
-sub ReturnList {
- my($str)=@_;
- my(@ret,@str,$from,$to,$tmp)=();
- @str=split(/,/,$str);
- foreach $str (@str) {
- if ($str =~ /^[-+]?\d+$/) {
- push(@ret,$str);
- } elsif ($str =~ /^([-+]?\d+)-([-+]?\d+)$/) {
- ($from,$to)=($1,$2);
- if ($from>$to) {
- $tmp=$from;
- $from=$to;
- $to=$tmp;
- }
- push(@ret,$from..$to);
- } else {
- return ();
- }
- }
- @ret;
-}
-
-1;
diff --git a/lib/Digest/HMAC.pm b/lib/Digest/HMAC.pm
deleted file mode 100644
index e2e6b60..0000000
--- a/lib/Digest/HMAC.pm
+++ /dev/null
@@ -1,111 +0,0 @@
-package Digest::HMAC;
-$VERSION = "1.01";
-
-use strict;
-
-# OO interface
-
-sub new
-{
- my($class, $key, $hasher, $block_size) = @_;
- $block_size ||= 64;
- $key = $hasher->new->add($key)->digest if length($key) > $block_size;
-
- my $self = bless {}, $class;
- $self->{k_ipad} = $key ^ (chr(0x36) x $block_size);
- $self->{k_opad} = $key ^ (chr(0x5c) x $block_size);
- $self->{hasher} = $hasher->new->add($self->{k_ipad});
- $self;
-}
-
-sub reset
-{
- my $self = shift;
- $self->{hasher}->reset->add($self->{k_ipad});
- $self;
-}
-
-sub add { my $self = shift; $self->{hasher}->add(@_); $self; }
-sub addfile { my $self = shift; $self->{hasher}->addfile(@_); $self; }
-
-sub _digest
-{
- my $self = shift;
- my $inner_digest = $self->{hasher}->digest;
- $self->{hasher}->reset->add($self->{k_opad}, $inner_digest);
-}
-
-sub digest { shift->_digest->digest; }
-sub hexdigest { shift->_digest->hexdigest; }
-sub b64digest { shift->_digest->b64digest; }
-
-
-# Functional interface
-
-require Exporter;
-*import = \&Exporter::import;
-use vars qw(@EXPORT_OK);
-@EXPORT_OK = qw(hmac hmac_hex);
-
-sub hmac
-{
- my($data, $key, $hash_func, $block_size) = @_;
- $block_size ||= 64;
- $key = &$hash_func($key) if length($key) > $block_size;
-
- my $k_ipad = $key ^ (chr(0x36) x $block_size);
- my $k_opad = $key ^ (chr(0x5c) x $block_size);
-
- &$hash_func($k_opad, &$hash_func($k_ipad, $data));
-}
-
-sub hmac_hex { unpack("H*", &hmac); }
-
-1;
-
-__END__
-
-=head1 NAME
-
-Digest::HMAC - Keyed-Hashing for Message Authentication
-
-=head1 SYNOPSIS
-
- # Functional style
- use Digest::HMAC qw(hmac hmac_hex);
- $digest = hmac($data, $key, \&myhash);
- print hmac_hex($data, $key, \&myhash);
-
- # OO style
- use Digest::HMAC;
- $hmac = Digest::HMAC->new($key, "Digest::MyHash");
-
- $hmac->add($data);
- $hmac->addfile(*FILE);
-
- $digest = $hmac->digest;
- $digest = $hmac->hexdigest;
- $digest = $hmac->b64digest;
-
-=head1 DESCRIPTION
-
-HMAC is used for message integrity checks between two parties that
-share a secret key, and works in combination with some other Digest
-algorithm, usually MD5 or SHA-1. The HMAC mechanism is described in
-RFC 2104.
-
-HMAC follow the common C<Digest::> interface, but the constructor
-takes the secret key and the name of some other simple C<Digest::>
-as argument.
-
-=head1 SEE ALSO
-
-L<Digest::HMAC_MD5>, L<Digest::HMAC_SHA1>
-
-RFC 2104
-
-=head1 AUTHORS
-
-Graham Barr <gbarr@ti.com>, Gisle Aas <gisle@aas.no>
-
-=cut
diff --git a/lib/Digest/HMAC_MD5.pm b/lib/Digest/HMAC_MD5.pm
deleted file mode 100644
index 6efa0a1..0000000
--- a/lib/Digest/HMAC_MD5.pm
+++ /dev/null
@@ -1,71 +0,0 @@
-package Digest::HMAC_MD5;
-$VERSION="1.01";
-
-use strict;
-use Digest::MD5 qw(md5);
-use Digest::HMAC qw(hmac);
-
-# OO interface
-use vars qw(@ISA);
-@ISA=qw(Digest::HMAC);
-sub new
-{
- my $class = shift;
- $class->SUPER::new($_[0], "Digest::MD5", 64);
-}
-
-# Functional interface
-require Exporter;
-*import = \&Exporter::import;
-use vars qw(@EXPORT_OK);
-@EXPORT_OK=qw(hmac_md5 hmac_md5_hex);
-
-sub hmac_md5
-{
- hmac($_[0], $_[1], \&md5, 64);
-}
-
-sub hmac_md5_hex
-{
- unpack("H*", &hmac_md5)
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Digest::HMAC_MD5 - Keyed-Hashing for Message Authentication
-
-=head1 SYNOPSIS
-
- # Functional style
- use Digest::HMAC_MD5 qw(hmac_md5 hmac_md5_hex);
- $digest = hmac_md5($data, $key);
- print hmac_md5_hex($data, $key);
-
- # OO style
- use Digest::HMAC_MD5;
- $hmac = Digest::HMAC_MD5->new($key);
-
- $hmac->add($data);
- $hmac->addfile(*FILE);
-
- $digest = $hmac->digest;
- $digest = $hmac->hexdigest;
- $digest = $hmac->b64digest;
-
-=head1 DESCRIPTION
-
-This module provide HMAC-MD5 hashing.
-
-=head1 SEE ALSO
-
-L<Digest::HMAC>, L<Digest::MD5>, L<Digest::HMAC_SHA1>
-
-=head1 AUTHOR
-
-Gisle Aas <gisle@aas.no>
-
-=cut
diff --git a/lib/Digest/HMAC_SHA1.pm b/lib/Digest/HMAC_SHA1.pm
deleted file mode 100644
index fadfb40..0000000
--- a/lib/Digest/HMAC_SHA1.pm
+++ /dev/null
@@ -1,71 +0,0 @@
-package Digest::HMAC_SHA1;
-$VERSION="1.01";
-
-use strict;
-use Digest::SHA1 qw(sha1);
-use Digest::HMAC qw(hmac);
-
-# OO interface
-use vars qw(@ISA);
-@ISA=qw(Digest::HMAC);
-sub new
-{
- my $class = shift;
- $class->SUPER::new($_[0], "Digest::SHA1", 64);
-}
-
-# Functional interface
-require Exporter;
-*import = \&Exporter::import;
-use vars qw(@EXPORT_OK);
-@EXPORT_OK=qw(hmac_sha1 hmac_sha1_hex);
-
-sub hmac_sha1
-{
- hmac($_[0], $_[1], \&sha1, 64);
-}
-
-sub hmac_sha1_hex
-{
- unpack("H*", &hmac_sha1)
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Digest::HMAC_SHA1 - Keyed-Hashing for Message Authentication
-
-=head1 SYNOPSIS
-
- # Functional style
- use Digest::HMAC_SHA1 qw(hmac_sha1 hmac_sha1_hex);
- $digest = hmac_sha1($data, $key);
- print hmac_sha1_hex($data, $key);
-
- # OO style
- use Digest::HMAC_SHA1;
- $hmac = Digest::HMAC_SHA1->new($key);
-
- $hmac->add($data);
- $hmac->addfile(*FILE);
-
- $digest = $hmac->digest;
- $digest = $hmac->hexdigest;
- $digest = $hmac->b64digest;
-
-=head1 DESCRIPTION
-
-This module provide HMAC-SHA-1 hashing.
-
-=head1 SEE ALSO
-
-L<Digest::HMAC>, L<Digest::SHA1>, L<Digest::HMAC_MD5>
-
-=head1 AUTHOR
-
-Gisle Aas <gisle@aas.no>
-
-=cut
diff --git a/lib/GD/Graph/Data.pm b/lib/GD/Graph/Data.pm
deleted file mode 100644
index 23f4624..0000000
--- a/lib/GD/Graph/Data.pm
+++ /dev/null
@@ -1,725 +0,0 @@
-#==========================================================================
-# Copyright (c) 1995-2000 Martien Verbruggen
-#--------------------------------------------------------------------------
-#
-# Name:
-# GD::Graph::Data.pm
-#
-# $Id: Data.pm,v 1.21 2003/06/17 03:28:11 mgjv Exp $
-#
-#==========================================================================
-
-package GD::Graph::Data;
-
-($GD::Graph::Data::VERSION) = '$Revision: 1.21 $' =~ /\s([\d.]+)/;
-
-use strict;
-use GD::Graph::Error;
-
-@GD::Graph::Data::ISA = qw( GD::Graph::Error );
-
-=head1 NAME
-
-GD::Graph::Data - Data set encapsulation for GD::Graph
-
-=head1 SYNOPSIS
-
-use GD::Graph::Data;
-
-=head1 DESCRIPTION
-
-This module encapsulates the data structure that is needed for GD::Graph
-and friends. An object of this class contains a list of X values, and a
-number of lists of corresponding Y values. This only really makes sense
-if the Y values are numerical, but you can basically store anything.
-Undefined values have a special meaning to GD::Graph, so they are
-treated with care when stored.
-
-Many of the methods of this module are intended for internal use by
-GD::Graph and the module itself, and will most likely not be useful to
-you. Many won't even I<seem> useful to you...
-
-=head1 EXAMPLES
-
- use GD::Graph::Data;
- use GD::Graph::bars;
-
- my $data = GD::Graph::Data->new();
-
- $data->read(file => '/data/sales.dat', delimiter => ',');
- $data = $data->copy(wanted => [2, 4, 5]);
-
- # Add the newer figures from the database
- use DBI;
- # do DBI things, like connecting to the database, statement
- # preparation and execution
-
- while (@row = $sth->fetchrow_array)
- {
- $data->add_point(@row);
- }
-
- my $chart = GD::Graph::bars->new();
- my $gd = $chart->plot($data);
-
-or for quick changes to legacy code
-
- # Legacy code builds array like this
- @data = ( [qw(Jan Feb Mar)], [1, 2, 3], [5, 4, 3], [6, 3, 7] );
-
- # And we quickly need to do some manipulations on that
- my $data = GD::Graph::Data->new();
- $data->copy_from(\@data);
-
- # And now do all the new stuff that's wanted.
- while (@foo = bar_baz())
- {
- $data->add_point(@foo);
- }
-
-=head1 METHODS
-
-=head2 $data = GD::Graph::Data->new()
-
-Create a new GD::Graph::Data object.
-
-=cut
-
-# Error constants
-use constant ERR_ILL_DATASET => 'Illegal dataset number';
-use constant ERR_ILL_POINT => 'Illegal point number';
-use constant ERR_NO_DATASET => 'No data sets set';
-use constant ERR_ARGS_NO_HASH => 'Arguments must be given as a hash list';
-
-sub new
-{
- my $proto = shift;
- my $class = ref($proto) || $proto;
- my $self = [];
- bless $self => $class;
- $self->copy_from(@_) or return $self->_move_errors if (@_);
- return $self;
-}
-
-sub DESTROY
-{
- my $self = shift;
- $self->clear_errors();
-}
-
-sub _set_value
-{
- my $self = shift;
- my ($nd, $np, $val) = @_;
-
- # Make sure we have empty arrays in between
- if ($nd > $self->num_sets)
- {
- # XXX maybe do this with splice
- for ($self->num_sets .. $nd - 1)
- {
- push @{$self}, [];
- }
- }
- $self->[$nd][$np] = $val;
-
- return $self;
-}
-
-=head2 $data->set_x($np, $value);
-
-Set the X value of point I<$np> to I<$value>. Points are numbered
-starting with 0. You probably will never need this. Returns undef on
-failure.
-
-=cut
-
-sub set_x
-{
- my $self = shift;
- $self->_set_value(0, @_);
-}
-
-=head2 $data->get_x($np)
-
-Get the X value of point I<$np>. See L<"set_x">.
-
-=cut
-
-sub get_x
-{
- my $self = shift;
- my $np = shift;
- return $self->_set_error(ERR_ILL_POINT)
- unless defined $np && $np >= 0;
-
- $self->[0][$np];
-}
-
-=head2 $data->set_y($nd, $np, $value);
-
-Set the Y value of point I<$np> in data set I<$nd> to I<$value>. Points
-are numbered starting with 0, data sets are numbered starting with 1.
-You probably will never need this. Returns undef on failure.
-
-=cut
-
-sub set_y
-{
- my $self = shift;
- return $self->_set_error(ERR_ILL_DATASET)
- unless defined $_[0] && $_[0] >= 1;
- $self->_set_value(@_);
-}
-
-=head2 $data->get_y($nd, $np)
-
-Get the Y value of point I<$np> in data set I<$nd>. See L<"set_y">. This
-will return undef on an error, but the fact that it returns undef does
-not mean there was an error (since undefined values can be stored, and
-therefore returned).
-
-=cut
-
-sub get_y
-{
- my $self = shift;
- my ($nd, $np) = @_;
- return $self->_set_error(ERR_ILL_DATASET)
- unless defined $nd && $nd >= 1 && $nd <= $self->num_sets;
- return $self->_set_error(ERR_ILL_POINT)
- unless defined $np && $np >= 0;
-
- $self->[$nd][$np];
-}
-
-=head2 $data->get_y_cumulative($nd, $np)
-
-Get the cumulative value of point I<$np> in data set<$nd>. The
-cumulative value is obtained by adding all the values of the points
-I<$np> in the data sets 1 to I<$nd>.
-
-=cut
-
-sub get_y_cumulative
-{
- my $self = shift;
- my ($nd, $np) = @_;
- return $self->_set_error(ERR_ILL_DATASET)
- unless defined $nd && $nd >= 1 && $nd <= $self->num_sets;
- return $self->_set_error(ERR_ILL_POINT)
- unless defined $np && $np >= 0;
-
- my $value;
- for (my $i = 1; $i <= $nd; $i++)
- {
- $value += $self->[$i][$np] || 0;
- }
-
- return $value;
-}
-
-sub _get_min_max
-{
- my $self = shift;
- my $nd = shift;
- my ($min, $max);
-
- for my $val (@{$self->[$nd]})
- {
- next unless defined $val;
- $min = $val if !defined $min || $val < $min;
- $max = $val if !defined $max || $val > $max;
- }
-
- return $self->_set_error("No (defined) values in " .
- ($nd == 0 ? "X list" : "dataset $nd"))
- unless defined $min && defined $max;
-
- return ($min, $max);
-}
-
-=head2 $data->get_min_max_x
-
-Returns a list of the minimum and maximum x value or the
-empty list on failure.
-
-=cut
-
-sub get_min_max_x
-{
- my $self = shift;
- $self->_get_min_max(0);
-}
-
-=head2 $data->get_min_max_y($nd)
-
-Returns a list of the minimum and maximum y value in data set $nd or the
-empty list on failure.
-
-=cut
-
-sub get_min_max_y
-{
- my $self = shift;
- my $nd = shift;
-
- return $self->_set_error(ERR_ILL_DATASET)
- unless defined $nd && $nd >= 1 && $nd <= $self->num_sets;
-
- $self->_get_min_max($nd);
-}
-
-=head2 $data->get_min_max_y_all()
-
-Returns a list of the minimum and maximum y value in all data sets or the
-empty list on failure.
-
-=cut
-
-sub get_min_max_y_all
-{
- my $self = shift;
- my ($min, $max);
-
- for (my $ds = 1; $ds <= $self->num_sets; $ds++)
- {
- my ($ds_min, $ds_max) = $self->get_min_max_y($ds);
- next unless defined $ds_min;
- $min = $ds_min if !defined $min || $ds_min < $min;
- $max = $ds_max if !defined $max || $ds_max > $max;
- }
-
- return $self->_set_error('No (defined) values in any data set')
- unless defined $min && defined $max;
-
- return ($min, $max);
-}
-
-# Undocumented, not part of interface right now. Might expose at later
-# point in time.
-
-sub set_point
-{
- my $self = shift;
- my $np = shift;
- return $self->_set_error(ERR_ILL_POINT)
- unless defined $np && $np >= 0;
-
- for (my $ds = 0; $ds < @_; $ds++)
- {
- $self->_set_value($ds, $np, $_[$ds]);
- }
- return $self;
-}
-
-=head2 $data->add_point($X, $Y1, $Y2 ...)
-
-Adds a point to the data set. The base for the addition is the current
-number of X values. This means that if you have a data set with the
-contents
-
- (X1, X2)
- (Y11, Y12)
- (Y21)
- (Y31, Y32, Y33, Y34)
-
-a $data->add_point(Xx, Y1x, Y2x, Y3x, Y4x) will result in
-
- (X1, X2, Xx )
- (Y11, Y12, Y1x)
- (Y21, undef, Y2x)
- (Y31, Y32, Y3x, Y34)
- (undef, undef, Y4x)
-
-In other words: beware how you use this. As long as you make sure that
-all data sets are of equal length, this method is safe to use.
-
-=cut
-
-sub add_point
-{
- my $self = shift;
- $self->set_point(scalar $self->num_points, @_);
-}
-
-=head2 $data->num_sets()
-
-Returns the number of data sets.
-
-=cut
-
-sub num_sets
-{
- my $self = shift;
- @{$self} - 1;
-}
-
-=head2 $data->num_points()
-
-In list context, returns a list with its first element the number of X
-values, and the subsequent elements the number of respective Y values
-for each data set. In scalar context returns the number of points
-that have an X value set, i.e. the number of data sets that would result
-from a call to C<make_strict>.
-
-=cut
-
-sub num_points
-{
- my $self = shift;
- return (0) unless @{$self};
-
- wantarray ?
- map { scalar @{$_} } @{$self} :
- scalar @{$self->[0]}
-}
-
-=head2 $data->x_values()
-
-Return a list of all the X values.
-
-=cut
-
-sub x_values
-{
- my $self = shift;
- return $self->_set_error(ERR_NO_DATASET)
- unless @{$self};
- @{$self->[0]};
-}
-
-=head2 $data->y_values($nd)
-
-Return a list of the Y values for data set I<$nd>. Data sets are
-numbered from 1. Returns the empty list if $nd is out of range, or if
-the data set at $nd is empty.
-
-=cut
-
-sub y_values
-{
- my $self = shift;
- my $nd = shift;
- return $self->_set_error(ERR_ILL_DATASET)
- unless defined $nd && $nd >= 1 && $nd <= $self->num_sets;
- return $self->_set_error(ERR_NO_DATASET)
- unless @{$self};
-
- @{$self->[$nd]};
-}
-
-=head2 $data->reset() OR GD::Graph::Data->reset()
-
-As an object method: Reset the data container, get rid of all data and
-error messages. As a class method: get rid of accumulated error messages
-and possible other crud.
-
-=cut
-
-sub reset
-{
- my $self = shift;
- @{$self} = () if ref($self);
- $self->clear_errors();
- return $self;
-}
-
-=head2 $data->make_strict()
-
-Make all data set lists the same length as the X list by truncating data
-sets that are too long, and filling data sets that are too short with
-undef values. always returns a true value.
-
-=cut
-
-sub make_strict
-{
- my $self = shift;
-
- for my $ds (1 .. $self->num_sets)
- {
- my $data_set = $self->[$ds];
-
- my $short = $self->num_points - @{$data_set};
- next if $short == 0;
-
- if ($short > 0)
- {
- my @fill = (undef) x $short;
- push @{$data_set}, @fill;
- }
- else
- {
- splice @{$data_set}, $short;
- }
- }
- return $self;
-}
-
-=head2 $data->cumulate(preserve_undef => boolean)
-
-The B<cumulate> parameter will summarise the Y value sets as follows:
-the first Y value list will be unchanged, the second will contain a
-sum of the first and second, the third will contain the sum of first,
-second and third, and so on. Returns undef on failure.
-
-if the argument I<preserve_undef> is set to a true value, then the sum
-of exclusively undefined values will be preserved as an undefined value.
-If it is not present or a false value, undef will be treated as zero.
-Note that this still will leave undefined values in the first data set
-alone.
-
-Note: Any non-numerical defined Y values will be treated as 0, but you
-really shouldn't be using this to store that sort of Y data.
-
-=cut
-
-sub cumulate
-{
- my $self = shift;
-
- return $self->_set_error(ERR_ARGS_NO_HASH) if (@_ && @_ % 2);
- my %args = @_;
-
- # For all the sets, starting at the last one, ending just
- # before the first
- for (my $ds = $self->num_sets; $ds > 1; $ds--)
- {
- # For each point in the set
- for my $point (0 .. $#{$self->[$ds]})
- {
- # Add the value for each point in lower sets to this one
- for my $i (1 .. $ds - 1)
- {
- # If neither are defined, we want to preserve the
- # undefinedness of this point. If we don't do this, then
- # the mathematical operation will force undef to be a 0.
- next if
- $args{preserve_undef} &&
- ! defined $self->[$ds][$point] &&
- ! defined $self->[$i][$point];
-
- $self->[$ds][$point] += $self->[$i][$point] || 0;
- }
- }
- }
- return $self;
-}
-
-=head2 $data->wanted(indexes)
-
-Removes all data sets except the ones in the argument list. It will also
-reorder the data sets in the order given. Returns undef on failure.
-
-To remove all data sets except the first, sixth and second, in that
-order:
-
- $data->wanted(1, 6, 2) or die $data->error;
-
-=cut
-
-sub wanted
-{
- my $self = shift;
-
- for my $wanted (@_)
- {
- return $self->_set_error("Wanted index $wanted out of range 1-"
- . $self->num_sets)
- if $wanted < 1 || $wanted > $self->num_sets;
- }
- @{$self} = @{$self}[0, @_];
- return $self;
-}
-
-=head2 $data->reverse
-
-Reverse the order of the data sets.
-
-=cut
-
-sub reverse
-{
- my $self = shift;
- @{$self} = ($self->[0], reverse @{$self}[1..$#{$self}]);
- return $self;
-}
-
-=head2 $data->copy_from($data_ref)
-
-Copy an 'old' style GD::Graph data structure or another GD::Graph::Data
-object into this object. This will remove the current data. Returns undef
-on failure.
-
-=cut
-
-sub copy_from
-{
- my $self = shift;
- my $data = shift;
- return $self->_set_error('Not a valid source data structure')
- unless defined $data && (
- ref($data) eq 'ARRAY' || ref($data) eq __PACKAGE__);
-
- $self->reset;
-
- my $i = 0;
- for my $data_set (@{$data})
- {
- return $self->_set_error("Invalid data set: $i")
- unless ref($data_set) eq 'ARRAY';
-
- push @{$self}, [@{$data_set}];
- $i++;
- }
-
- return $self;
-}
-
-=head2 $data->copy()
-
-Returns a copy of the object, or undef on failure.
-
-=cut
-
-sub copy
-{
- my $self = shift;
-
- my $new = $self->new();
- $new->copy_from($self);
- return $new;
-}
-
-=head2 $data->read(I<arguments>)
-
-Read a data set from a file. This will remove the current data. returns
-undef on failure. This method uses the standard module
-Text::ParseWords to parse lines. If you don't have this for some odd
-reason, don't use this method, or your program will die.
-
-B<Data file format>: The default data file format is tab separated data
-(which can be changed with the delimiter argument). Comment lines are
-any lines that start with a #. In the following example I have replaced
-literal tabs with <tab> for clarity
-
- # This is a comment, and will be ignored
- Jan<tab>12<tab>24
- Feb<tab>13<tab>37
- # March is missing
- Mar<tab><tab>
- Apr<tab>9<tab>18
-
-Valid arguments are:
-
-I<file>, mandatory. The file name of the file to read from, or a
-reference to a file handle or glob.
-
- $data->read(file => '/data/foo.dat') or die $data->error;
- $data->read(file => \*DATA) or die $data->error;
- $data->read(file => $file_handle) or die $data->error;
-
-I<no_comment>, optional. Give this a true value if you don't want lines
-with an initial # to be skipped.
-
- $data->read(file => '/data/foo.dat', no_comment => 1);
-
-I<delimiter>, optional. A regular expression that will become the
-delimiter instead of a single tab.
-
- $data->read(file => '/data/foo.dat', delimiter => '\s+');
- $data->read(file => '/data/foo.dat', delimiter => qr/\s+/);
-
-=cut
-
-sub read
-{
- my $self = shift;
-
- return $self->_set_error(ERR_ARGS_NO_HASH) if (@_ && @_ % 2);
- my %args = @_;
-
- return $self->_set_error('Missing required argument: file')
- unless $args{file};
-
- my $delim = $args{delimiter} || "\t";
-
- $self->reset();
-
- # The following will die if these modules are not present, as
- # documented.
- require Text::ParseWords;
-
- my $fh;
- local *FH;
-
- if (UNIVERSAL::isa($args{file}, "GLOB"))
- {
- $fh = $args{file};
- }
- else
- {
- # $fh = \do{ local *FH }; # Odd... This dumps core, sometimes in 5.005
- $fh = \*FH; # XXX Need this for perl 5.005
- open($fh, $args{file}) or
- return $self->_set_error("open ($args{file}): $!");
- }
-
- while (my $line = <$fh>)
- {
- chomp $line;
- next if $line =~ /^#/ && !$args{no_comment};
- my @fields = Text::ParseWords::parse_line($delim, 1, $line);
- next unless @fields;
- $self->add_point(@fields);
- }
- return $self;
-}
-
-=head2 $data->error() OR GD::Graph::Data->error()
-
-Returns a list of all the errors that the current object has
-accumulated. In scalar context, returns the last error. If called as a
-class method it works at a class level.
-
-This method is inherited, see L<GD::Graph::Error> for more information.
-
-=cut
-
-=head2 $data->has_error() OR GD::Graph::Data->has_error()
-
-Returns true if the object (or class) has errors pending, false if not.
-In some cases (see L<"copy">) this is the best way to check for errors.
-
-This method is inherited, see L<GD::Graph::Error> for more information.
-
-=cut
-
-=head1 NOTES
-
-As with all Modules for Perl: Please stick to using the interface. If
-you try to fiddle too much with knowledge of the internals of this
-module, you could get burned. I may change them at any time.
-Specifically, I probably won't always keep this implemented as an array
-reference.
-
-=head1 AUTHOR
-
-Martien Verbruggen E<lt>mgjv@tradingpost.com.auE<gt>
-
-=head2 Copyright
-
-(c) Martien Verbruggen.
-
-All rights reserved. This package is free software; you can redistribute
-it and/or modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<GD::Graph>, L<GD::Graph::Error>
-
-=cut
-
-"Just another true value";
-
diff --git a/lib/GD/Graph/Error.pm b/lib/GD/Graph/Error.pm
deleted file mode 100644
index 0d8e50c..0000000
--- a/lib/GD/Graph/Error.pm
+++ /dev/null
@@ -1,346 +0,0 @@
-#==========================================================================
-# Copyright (c) 1995-2000 Martien Verbruggen
-#--------------------------------------------------------------------------
-#
-# Name:
-# GD::Graph::Error.pm
-#
-# $Id: Error.pm,v 1.8 2003/02/10 22:12:41 mgjv Exp $
-#
-#==========================================================================
-
-package GD::Graph::Error;
-
-($GD::Graph::Error::VERSION) = '$Revision: 1.8 $' =~ /\s([\d.]+)/;
-
-use strict;
-use Carp;
-
-my %Errors;
-use vars qw( $Debug $ErrorLevel $CriticalLevel );
-
-$Debug = 0;
-
-# Warnings from 0 to 4, Errors from 5 to 9, and Critical 10 and above.
-$ErrorLevel = 5;
-$CriticalLevel = 10;
-
-=head1 NAME
-
-GD::Graph::Error - Error handling for GD::Graph classes
-
-=head1 SYNOPSIS
-
-use GD::Graph::Error_subclass;
-
-=head1 DESCRIPTION
-
-This class is a parent for all GD::Graph classes, including
-GD::Graph::Data, and offers error and warning handling and some
-debugging control.
-
-Errors are stored in a lexical hash in this package, so the
-implementation of the subclass should be irrelevant.
-
-=head1 PUBLIC METHODS
-
-These methods can be used by users of any of the subclasses of
-GD::Graph::Error to get at the errors of objects or classes.
-
-=head2 $object->error() OR Class->error()
-
-Returns a list of all the errors that the current object has
-accumulated. In scalar context, returns the last error. If called as a
-class method it works at a class level. This is handy when a constructor
-fails, for example:
-
- my $data = GD::Graph::Data->new()
- or die GD::Graph::Data->error;
- $data->read(file => '/foo/bar.data')
- or die $data->error;
-
-or if you really are only interested in the last error:
-
- $data->read(file => '/foo/bar.data')
- or die scalar $data->error;
-
-This implementation does not clear the error list, so if you don't die
-on errors, you will need to make sure to never ask for anything but the
-last error (put this in scalar context) or to call C<clear_error()> now
-and again.
-
-Errors are more verbose about where the errors originated if the
-$GD::Graph::Error::Debug variable is set to a true value, and even more
-verbose if this value is larger than 5.
-
-If $Debug is larger than 3, both of these will always return the
-full list of errors and warnings (although the meaning of C<has_warning>
-and C<has_error> does not change).
-
-=cut
-
-sub _error
-{
- my $self = shift;
- my $min_level = shift || 0;
- my $max_level = shift || 1 << 31;
- return unless exists $Errors{$self};
- my $error = $Errors{$self};
-
- my @return;
-
- @return =
- map {
- ($Debug > 3 ? "[$_->{level}] " : '') .
- "$_->{msg}" .
- ($Debug ? " at $_->{whence}[1] line $_->{whence}[2]" : '') .
- ($Debug > 5 ? " => $_->{caller}[0]($_->{caller}[2])" : '') .
- "\n"
- }
- grep { $_->{level} >= $min_level && $_->{level} <= $max_level }
- @$error;
-
- wantarray && @return > 1 and
- $return[-1] =~ s/\n/\n\t/ or
- $return[-1] =~ s/\n//;
-
- return wantarray ? @return : $return[-1];
-}
-
-sub error
-{
- my $self = shift;
- $Debug > 3 and return $self->_error();
- $self->_error($ErrorLevel);
-}
-
-sub warning
-{
- my $self = shift;
- $Debug > 3 and return $self->_error();
- $self->_error(0, $ErrorLevel - 1);
-}
-
-=head2 $object->has_error() OR Class->has_error()
-
-=head2 $object->has_warning() OR Class->has_warning()
-
-Returns true if there are pending errors (warnings) for the object
-(or class). To be more precise, it returns a list of errors in list
-context, and the number of errors in scalar context.
-
-This allows you to check for errors and warnings after a large number of
-operations which each might fail:
-
- $data->read(file => '/foo/bar.data') or die $data->error;
- while (my @foo = $sth->fetchrow_array)
- {
- $data->add_point(@foo);
- }
- $data->set_x(12, 'Foo');
- $data->has_warning and warn $data->warning;
- $data->has_error and die $data->error;
-
-The reason to call this, instead of just calling C<error()> or
-C<warning()> and looking at its return value, is that this method is
-much more efficient and fast.
-
-If you want to count anything as bad, just set $ErrorLevel to 0, after
-which you only need to call C<has_error>.
-
-=cut
-
-sub has_error
-{
- my $self = shift;
- return unless exists $Errors{$self};
- grep { $_->{level} >= $ErrorLevel } @{$Errors{$self}};
-}
-
-sub has_warning
-{
- my $self = shift;
- return unless exists $Errors{$self};
- grep { $_->{level} < $ErrorLevel } @{$Errors{$self}};
-}
-
-=head2 $object->clear_errors() or Class->clear_errors()
-
-Clears all outstanding errors.
-
-=cut
-
-sub clear_errors
-{
- my $self = shift;
- delete $Errors{$self};
-}
-
-=head1 PROTECTED METHODS
-
-These methods are only to be called from within this class and its
-Subclasses.
-
-=head2 $object->_set_error(I<arg>) or Class->_set_error(I<arg>)
-
-=head2 $object->_set_warning(I<arg>) or Class->_set_warning(I<arg>)
-
-Subclasses call this to set an error. The argument can be a reference
-to an array, of which the first element should be the error level, and
-the second element the error message. Alternatively, it can just be the
-message, in which case the error level will be assumed to be
-$ErrorLevel.
-
-If the error level is >= $CriticalLevel the program will die, using
-Carp::croak to display the current message, as well as all the other
-error messages pending.
-
-In the current implementation these are almost identical when called
-with a scalar argument, except that the default ewrror level is
-different. When called with an array reference, they are identical in
-function. This may change in the future. They're mainly here for code
-clarity.
-
-=cut
-
-# Private, for construction of error hash. This should probably be an
-# object, but that's too much work right now.
-sub __error_hash
-{
- my $caller = shift;
- my $default = shift;
- my $msg = shift;
-
- my %error = (caller => $caller);
-
- if (ref($msg) && ref($msg) eq 'ARRAY' && @{$msg} >= 2)
- {
- # Array reference
- $error{level} = $msg->[0];
- $error{msg} = $msg->[1];
- }
- elsif (ref($_[0]) eq '')
- {
- # simple scalar
- $error{level} = $default;
- $error{msg} = $msg;
- }
- else
- {
- # someting else, which I can't deal with
- warn "Did you read the documentation for GD::Graph::Error?";
- return;
- }
-
- my $lvl = 1;
- while (my @c = caller($lvl))
- {
- $error{whence} = [@c[0..2]];
- $lvl++;
- }
-
- return \%error;
-}
-
-sub _set_error
-{
- my $self = shift;
- return unless @_;
-
- while (@_)
- {
- my $e_h = __error_hash([caller], $ErrorLevel, shift) or return;
- push @{$Errors{$self}}, $e_h;
- croak $self->error if $e_h->{level} >= $CriticalLevel;
- }
- return;
-}
-
-sub _set_warning
-{
- my $self = shift;
- return unless @_;
-
- while (@_)
- {
- my $e_h = __error_hash([caller], $ErrorLevel, shift) or return;
- push @{$Errors{$self}}, $e_h;
- croak $self->error if $e_h->{level} >= $CriticalLevel;
- }
- return;
-}
-
-=head2 $object->_move_errors
-
-Move errors from an object into the class it belongs to. This can be
-useful if something nasty happens in the constructor, while
-instantiating one of these objects, and you need to move these errors
-into the class space before returning. (see GD::Graph::Data::new for an
-example)
-
-=cut
-
-sub _move_errors
-{
- my $self = shift;
- my $class = ref($self);
- push @{$Errors{$class}}, @{$Errors{$self}};
- return;
-}
-
-sub _dump
-{
- my $self = shift;
- require Data::Dumper;
- my $dd = Data::Dumper->new([$self], ['me']);
- $dd->Dumpxs;
-}
-
-=head1 VARIABLES
-
-=head2 $GD::Graph::Error::Debug
-
-The higher this value, the more verbose error messages will be. At the
-moment, any true value will cause the line number and source file of the
-caller at the top of the stack to be included, a value of more than 2
-will include the error severity, and a value of more than 5 will also
-include the direct caller's (i.e. the spot where the error message was
-generated) line number and package. Default: 0.
-
-=head2 $GD::Graph::Error::ErrorLevel
-
-Errors levels below this value will be counted as warnings, and error
-levels above (and inclusive) up to $CriticalLevel will be counted as
-errors. This is also the default error level for the C<_set_error()>
-method. This value should be 0 or larger, and smaller than
-$CriticalLevel. Default: 5.
-
-=head2 $GD::Graph::Error::CriticalLevel
-
-Any errorlevel of or above this level will immediately cause the program
-to die with the specified message, using Carp::croak. Default: 10.
-
-=head1 NOTES
-
-As with all Modules for Perl: Please stick to using the interface. If
-you try to fiddle too much with knowledge of the internals of this
-module, you could get burned. I may change them at any time.
-
-=head1 AUTHOR
-
-Martien Verbruggen E<lt>mgjv@tradingpost.com.auE<gt>
-
-=head2 Copyright
-
-(c) Martien Verbruggen.
-
-All rights reserved. This package is free software; you can redistribute
-it and/or modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<GD::Graph>, L<GD::Graph::Data>
-
-=cut
-
-"Just another true value";
diff --git a/lib/GD/Graph/FAQ.pod b/lib/GD/Graph/FAQ.pod
deleted file mode 100644
index f6ed237..0000000
--- a/lib/GD/Graph/FAQ.pod
+++ /dev/null
@@ -1,130 +0,0 @@
-=head1 NAME
-
-GD::Graph::FAQ - Frequently asked questions
-
-=head1 DESCRIPTION
-
-=head2 I get errors like "Can't call method METHOD on an undefined value". What gives?
-
-You probably had an error somewhere, most likely in the plot() method,
-and you didn't check for it. See the section on Error Handling in the
-documentation for L<GD::Graph> to find out how to deal with this sort
-of thing, and how to get more information about what the error was.
-
-=head2 I am drawing a bar chart, and the chart area is a lot smaller than the image. What is going on?
-
-As of version 1.30, GD::Graph automatically corrects the width of the
-plotting area of a chart if it needs to draw bars (i.e. for bars and
-some mixed charts). This is necessary, because rounding errors cause
-irregular gaps between or overlaps of bars if the bar is not an exact
-integer number of pixels wide.
-
-If you want the old behaviour back, set the correct_with attribute to a
-false value.
-
-
-=head2 I have my data in some format that doesn't look at all like the array that I am supposed to give to GD::Graph's plot method. Do I really need to mess around with array references?
-
-Not necessarily. Check out the GD::Graph::Data class.
-
-
-=head2 How do I stop those pesky accents appearing around bars or inside area charts?
-
-You can set the C<accent_treshold> option to a large enough value
-(larger than your chart). Alternatively, you may like it better to set
-the C<borderclrs> attribute to be the same as the dclrs one.
-
-I'll probably include an option in a future version that gives better
-control over this.
-
-
-=head2 Where is the ActiveState ppm of GD::Graph?
-
-Ask them. I have asked them, but didn't get an answer. I don't know what
-to do to get it included in their set of ppms, and I really do not have
-the time to keep asking them.
-
-I believe that GD::graph has finally made it into ActiveState's ppm
-archive. However, I am going to leave this question here in case they
-get behind again.
-
-
-=head2 Do you have some example code for me?
-
-The distribution has a large set of examples in it. If you don't have
-the original distribution, please get it from CPAN (http://www.cpan.org/
-or some local mirror).
-
-
-=head2 Will you support X or Y?
-
-If you send me a patch that (in a decent manner) adds the functionality
-to the latest version, I may very well add it for the next release. If
-you don't send me a patch, but just a question, you will have to be
-patient.
-
-=head2 Why does export_format give me a weird string, instead of just 'png' or 'gif'?
-
-As of version 1.31, export_format in a list context returns all formats
-that GD can export. If you are only interested in the answer 'gif' or
-'png', make sure that you call it in a scalar context.
-
- $export_format = GD::Graph->export_format;
- $export_format = $graph->export_format;
- print "Export format is ", scalar $graph->export_format, "\n";
- print "Export format is " . $graph->export_format . "\n";
- @export_formats = $graph->export_format;
-
-
-=head2 TrueType fonts don't work when I use GD::Graph from a CGI program.
-
-When your programs run as CGI, they typically do not have the same
-environment as when you use them from the command line. The Perl FAQ,
-section 9, has some information on this. It is also not guaranteed that
-your script runs from the directory that it is in. It is probably better
-to include something like:
-
- use GD::Text;
- GD::Text->font_path("/path/to/my/font_dir");
-
-See the GD::Text documentation for more information about font paths.
-
-=head2 I'm trying to use GD's builtin fonts, but it's not working.
-
-Most likely, you are using the font short name, like gdGiantFont or
-gdMediumBoldFont, and you have not put a C<use GD> in your program.
-This is needed, because these short names need to be exported into
-your name space by the GD library:
-
- use GD;
- # ...
- $graph->set_x_axis_font(gdMediumBoldFont);
-
-If you don't want to include the GD library, you can use the
-longer alternative names (which is what I'd recommend anyway):
-
- $graph1->set_x_axis_font(GD::Font->MediumBold);
-
-If you C<use strict> then you will actually get an error message if
-you try to use the short names without including the GD module.
-
-Also see the L<GD::Text> documentation for this information.
-
-=head2 When I have many data sets, some end up having the same colour.
-
-The default number of colours for data sets is seven, so if you use
-more than seven data sets, those colours will be re-used for the
-higher data sets.
-
-This is described in the entry for the C<dclrs> attribute in the
-L<GD::Graph> documentation.
-
-=head1 AUTHOR
-
-Martien Verbruggen E<lt>mgjv@tradingpost.com.auE<gt>
-
-(c) Martien Verbruggen.
-
-All rights reserved. This package is free software; you can redistribute
-it and/or modify it under the same terms as Perl itself.
-
diff --git a/lib/GD/Graph/area.pm b/lib/GD/Graph/area.pm
deleted file mode 100644
index a06f114..0000000
--- a/lib/GD/Graph/area.pm
+++ /dev/null
@@ -1,112 +0,0 @@
-#==========================================================================
-# Copyright (c) 1995-2000 Martien Verbruggen
-#--------------------------------------------------------------------------
-#
-# Name:
-# GD::Graph::area.pm
-#
-# $Id: area.pm,v 1.16 2003/02/10 23:33:40 mgjv Exp $
-#
-#==========================================================================
-
-package GD::Graph::area;
-
-($GD::Graph::area::VERSION) = '$Revision: 1.16 $' =~ /\s([\d.]+)/;
-
-use strict;
-
-use GD::Graph::axestype;
-
-@GD::Graph::area::ISA = qw( GD::Graph::axestype );
-
-# PRIVATE
-sub draw_data_set
-{
- my $self = shift; # object reference
- my $ds = shift; # number of the data set
-
- my @values = $self->{_data}->y_values($ds) or
- return $self->_set_error("Impossible illegal data set: $ds",
- $self->{_data}->error);
-
- # Select a data colour
- my $dsci = $self->set_clr($self->pick_data_clr($ds));
- my $brci = $self->set_clr($self->pick_border_clr($ds));
-
- # Create a new polygon
- my $poly = GD::Polygon->new();
-
- my @bottom;
-
- # Add the data points
- for (my $i = 0; $i < @values; $i++)
- {
- my $value = $values[$i];
- next unless defined $value;
-
- my $bottom = $self->_get_bottom($ds, $i);
- $value = $self->{_data}->get_y_cumulative($ds, $i)
- if ($self->{overwrite} == 2);
-
- my ($x, $y) = $self->val_to_pixel($i + 1, $value, $ds);
- $poly->addPt($x, $y);
- # Need to keep track of this stuff for hotspots, and because
- # it's the only reliable way of closing the polygon, without
- # making odd assumptions.
- push @bottom, [$x, $bottom];
-
- # Hotspot stuff
- # XXX needs fixing. Not used at the moment.
- next unless defined $self->{_hotspots}->[$ds]->[$i];
- if ($i == 0)
- {
- $self->{_hotspots}->[$ds]->[$i] = ["poly",
- $x, $y,
- $x , $bottom,
- $x - 1, $bottom,
- $x - 1, $y,
- $x, $y];
- }
- else
- {
- $self->{_hotspots}->[$ds]->[$i] = ["poly",
- $poly->getPt($i),
- @{$bottom[$i]},
- @{$bottom[$i-1]},
- $poly->getPt($i-1),
- $poly->getPt($i)];
- }
- }
-
- foreach my $bottom (reverse @bottom)
- {
- $poly->addPt($bottom->[0], $bottom->[1]);
- }
-
- # Draw a filled and a line polygon
- $self->{graph}->filledPolygon($poly, $dsci)
- if defined $dsci;
- $self->{graph}->polygon($poly, $brci)
- if defined $brci;
-
- # Draw the accent lines
- if (defined $brci &&
- ($self->{right} - $self->{left})/@values > $self->{accent_treshold})
- {
- for (my $i = 1; $i < @values - 1; $i++)
- {
- my $value = $values[$i];
- ## XXX Why don't I need this line?
- ##next unless defined $value;
-
- my ($x, $y) = $poly->getPt($i);
- my $bottom = $bottom[$i]->[1];
-
- $self->{graph}->dashedLine($x, $y, $x, $bottom, $brci);
- }
- }
-
- return $ds
-}
-
-"Just another true value";
diff --git a/lib/GD/Graph/axestype3d.pm b/lib/GD/Graph/axestype3d.pm
deleted file mode 100644
index 7acb7f3..0000000
--- a/lib/GD/Graph/axestype3d.pm
+++ /dev/null
@@ -1,787 +0,0 @@
-#==========================================================================
-# Module: GD::Graph::axestype3d
-#
-# Copyright (C) 1999,2001 Wadsack-Allen. All Rights Reserved.
-#
-# Based on axestype.pm,v 1.21 2000/04/15 08:59:36 mgjv
-# Copyright (c) 1995-1998 Martien Verbruggen
-#
-#--------------------------------------------------------------------------
-# Date Modification Author
-# -------------------------------------------------------------------------
-# 1999SEP18 Created 3D axestype base class (this JW
-# module) changes noted in comments.
-# 1999OCT15 Fixed to include all GIFgraph functions JW
-# necessary for PNG support.
-# 2000JAN19 Converted to GD::Graph sublcass JW
-# 2000FEB21 Fixed bug in y-labels' height JW
-# 2000APR18 Updated for compatibility with GD::Graph 1.30 JW
-# 2000AUG21 Added 3d shading JW
-# 2000SEP04 Allowed box_clr without box axis JW
-# 06Dec2001 Fixed bug in rendering of x tick when x_tick_number is set JW
-#==========================================================================
-# TODO
-# * Modify to use true 3-d extrusions at any theta and phi
-#==========================================================================
-package GD::Graph::axestype3d;
-
-use strict;
-
-use GD::Graph;
-use GD::Graph::axestype;
-use GD::Graph::utils qw(:all);
-use GD::Graph::colour qw(:colours);
-use Carp;
-
-@GD::Graph::axestype3d::ISA = qw(GD::Graph::axestype);
-$GD::Graph::axestype3d::VERSION = '0.63';
-
-# Commented inheritance from GD::Graph::axestype unless otherwise noted.
-
-use constant PI => 4 * atan2(1,1);
-
-my %Defaults = (
- depth_3d => 20,
- '3d_shading' => 1,
-
- # the rest are inherited
-);
-
-# Inherit _has_default
-
-
-# Can't inherit initialise, because %Defaults is referenced file-
-# specific, not class specific.
-sub initialise
-{
- my $self = shift;
-
- my $rc = $self->SUPER::initialise();
-
- while( my($key, $val) = each %Defaults ) {
- $self->{$key} = $val
- } # end while
-
- return $rc;
-} # end initialise
-
-# PUBLIC
-# Inherit plot
-# Inherit set
-# Inherit setup_text
-# Inherit set_x_label_font
-# Inherit set_y_label_font
-# Inherit set_x_axis_font
-# Inherit set_y_axis_font
-# Inherit set_legend
-# Inherit set_legend_font
-
-
-
-# ----------------------------------------------------------
-# Sub: init_graph
-#
-# Args: (None)
-#
-# Description:
-# Override GD::Graph::init_graph to add 3d shading colors,
-# if requested
-#
-# [From GD::Graph]
-# Initialise the graph output canvas, setting colours (and
-# getting back index numbers for them) setting the graph to
-# transparent, and interlaced, putting a logo (if defined)
-# on there.
-# ----------------------------------------------------------
-# Date Modification Author
-# ----------------------------------------------------------
-# 20Aug2000 Added to support 3d graph extensions JW
-# ----------------------------------------------------------
-sub init_graph {
- my $self = shift;
-
- # Sets up the canvas and color palette
- $self->SUPER::init_graph( @_ );
-
- # Now create highlights and showdows for each color
- # in the palette
- if( $self->{'3d_shading'} ) {
- $self->{'3d_highlights'} = [];
- $self->{'3d_shadows'} = [];
- $self->{'3d_highlights'}[$self->{bgci}] = $self->set_clr( $self->_brighten( _rgb($self->{bgclr}) ) );
- $self->{'3d_shadows'}[$self->{bgci}] = $self->set_clr( $self->_darken( _rgb($self->{bgclr}) ) );
-
- $self->{'3d_highlights'}[$self->{fgci}] = $self->set_clr( $self->_brighten( _rgb($self->{fgclr}) ) );
- $self->{'3d_shadows'}[$self->{fgci}] = $self->set_clr( $self->_darken( _rgb($self->{fgclr}) ) );
-
- $self->{'3d_highlights'}[$self->{tci}] = $self->set_clr( $self->_brighten( _rgb($self->{textclr}) ) );
- $self->{'3d_shadows'}[$self->{tci}] = $self->set_clr( $self->_darken( _rgb($self->{textclr}) ) );
-
- $self->{'3d_highlights'}[$self->{lci}] = $self->set_clr( $self->_brighten( _rgb($self->{labelclr}) ) );
- $self->{'3d_shadows'}[$self->{lci}] = $self->set_clr( $self->_darken( _rgb($self->{labelclr}) ) );
-
- $self->{'3d_highlights'}[$self->{alci}] = $self->set_clr( $self->_brighten( _rgb($self->{axislabelclr}) ) );
- $self->{'3d_shadows'}[$self->{alci}] = $self->set_clr( $self->_darken( _rgb($self->{axislabelclr}) ) );
-
- $self->{'3d_highlights'}[$self->{acci}] = $self->set_clr( $self->_brighten( _rgb($self->{accentclr}) ) );
- $self->{'3d_shadows'}[$self->{acci}] = $self->set_clr( $self->_darken( _rgb($self->{accentclr}) ) );
-
- $self->{'3d_highlights'}[$self->{valuesci}] = $self->set_clr( $self->_brighten( _rgb($self->{valuesclr}) ) );
- $self->{'3d_shadows'}[$self->{valuesci}] = $self->set_clr( $self->_darken( _rgb($self->{valuesclr}) ) );
-
- $self->{'3d_highlights'}[$self->{legendci}] = $self->set_clr( $self->_brighten( _rgb($self->{legendclr}) ) );
- $self->{'3d_shadows'}[$self->{legendci}] = $self->set_clr( $self->_darken( _rgb($self->{legendclr}) ) );
-
- if( $self->{boxclr} ) {
- $self->{'3d_highlights'}[$self->{boxci}] = $self->set_clr( $self->_brighten( _rgb($self->{boxclr}) ) );
- $self->{'3d_shadows'}[$self->{boxci}] = $self->set_clr( $self->_darken( _rgb($self->{boxclr}) ) );
- } # end if
- } # end if
-
- return $self;
-} # end init_graph
-
-
-# PRIVATE
-
-# ----------------------------------------------------------
-# Sub: _brighten
-#
-# Args: $r, $g, $b
-# $r, $g, $b The Red, Green, and Blue components of a color
-#
-# Description: Brightens the color by adding white
-# ----------------------------------------------------------
-# Date Modification Author
-# ----------------------------------------------------------
-# 21AUG2000 Created to build 3d highlights table JW
-# ----------------------------------------------------------
-sub _brighten {
- my $self = shift;
- my( $r, $g, $b ) = @_;
- my $p = ($r + $g + $b) / 70;
- $p = 3 if $p < 3;
- my $f = _max( $r / $p, _max( $g / $p, $b / $p ) );
- $r = _min( 255, int( $r + $f ) );
- $g = _min( 255, int( $g + $f ) );
- $b = _min( 255, int( $b + $f ) );
- return( $r, $g, $b );
-} # end _brighten
-
-# ----------------------------------------------------------
-# Sub: _darken
-#
-# Args: $r, $g, $b
-# $r, $g, $b The Red, Green, and Blue components of a color
-#
-# Description: Darkens the color by adding black
-# ----------------------------------------------------------
-# Date Modification Author
-# ----------------------------------------------------------
-# 21AUG2000 Created to build 3d shadows table JW
-# ----------------------------------------------------------
-sub _darken {
- my $self = shift;
- my( $r, $g, $b ) = @_;
- my $p = ($r + $g + $b) / 70;
- $p = 3 if $p < 3;
- my $f = _max( $r / $p, _max( $g / $p, $b / $p) );
- $r = _max( 0, int( $r - $f ) );
- $g = _max( 0, int( $g - $f ) );
- $b = _max( 0, int( $b - $f ) );
- return( $r, $g, $b );
-} # end _darken
-
-
-# inherit check_data from GD::Graph
-
-# [JAW] Setup boundaries as parent, the adjust for 3d extrusion
-sub _setup_boundaries
-{
- my $self = shift;
-
- $self->SUPER::_setup_boundaries();
-
- # adjust for top of 3-d extrusion
- $self->{top} += $self->{depth_3d};
-
- return $self->_set_error('Vertical size too small')
- if $self->{bottom} <= $self->{top};
-
- # adjust for right of 3-d extrusion
- $self->{right} -= $self->{depth_3d};
-
- return $self->_set_error('Horizontal size too small')
- if $self->{right} <= $self->{left};
-
- return $self;
-} # end _setup_boundaries
-
-# [JAW] Determine 3d-extrusion depth, then call parent
-sub setup_coords
-{
- my $self = shift;
-
- # Calculate the 3d-depth of the graph
- # Note this sets a minimum depth of ~20 pixels
-# if (!defined $self->{x_tick_number}) {
- my $depth = _max( $self->{bar_depth}, $self->{line_depth} );
- if( $self->{overwrite} == 1 ) {
- $depth *= $self->{_data}->num_sets();
- } # end if
- $self->{depth_3d} = _max( $depth, $self->{depth_3d} );
-# } # end if
-
- $self->SUPER::setup_coords();
-
- return $self;
-} # end setup_coords
-
-# Inherit create_y_labels
-# Inherit get_x_axis_label_height
-# Inherit create_x_labels
-# inherit open_graph from GD::Graph
-# Inherit draw_text
-
-# [JAW] Draws entire bounding cube for 3-d extrusion
-sub draw_axes
-{
- my $s = shift;
- my $g = $s->{graph};
-
- my ($l, $r, $b, $t) =
- ( $s->{left}, $s->{right}, $s->{bottom}, $s->{top} );
- my $depth = $s->{depth_3d};
-
- if ( $s->{box_axis} ) {
- # -- Draw a bounding box
- if( $s->{boxci} ) {
- # -- Fill the box with color
- # Back box
- $g->filledRectangle($l+$depth+1, $t-$depth+1, $r+$depth-1, $b-$depth-1, $s->{boxci});
-
- # Left side
- my $poly = new GD::Polygon;
- $poly->addPt( $l, $t );
- $poly->addPt( $l + $depth, $t - $depth );
- $poly->addPt( $l + $depth, $b - $depth );
- $poly->addPt( $l, $b );
- if( $s->{'3d_shading'} ) {
- $g->filledPolygon( $poly, $s->{'3d_shadows'}[$s->{boxci}] );
- } else {
- $g->filledPolygon( $poly, $s->{boxci} );
- } # end if
-
- # Bottom
- $poly = new GD::Polygon;
- $poly->addPt( $l, $b );
- $poly->addPt( $l + $depth, $b - $depth );
- $poly->addPt( $r + $depth, $b - $depth );
- $poly->addPt( $r, $b );
- if( $s->{'3d_shading'} ) {
- $g->filledPolygon( $poly, $s->{'3d_highlights'}[$s->{boxci}] );
- } else {
- $g->filledPolygon( $poly, $s->{boxci} );
- } # end if
- } # end if
-
- # -- Draw the box frame
-
- # Back box
- $g->rectangle($l+$depth, $t-$depth, $r+$depth, $b-$depth, $s->{fgci});
-
- # Connecting frame
- $g->line($l, $t, $l + $depth, $t - $depth, $s->{fgci});
- $g->line($r, $t, $r + $depth, $t - $depth, $s->{fgci});
- $g->line($l, $b, $l + $depth, $b - $depth, $s->{fgci});
- $g->line($r, $b, $r + $depth, $b - $depth, $s->{fgci});
-
- # Front box
- $g->rectangle($l, $t, $r, $b, $s->{fgci});
-
- } else {
- if( $s->{boxci} ) {
- # -- Fill the background box with color
- # Back box
- $g->filledRectangle($l+$depth+1, $t-$depth+1, $r+$depth-1, $b-$depth-1, $s->{boxci});
-
- # Left side
- my $poly = new GD::Polygon;
- $poly->addPt( $l, $t );
- $poly->addPt( $l + $depth, $t - $depth );
- $poly->addPt( $l + $depth, $b - $depth );
- $poly->addPt( $l, $b );
- if( $s->{'3d_shading'} ) {
- $g->filledPolygon( $poly, $s->{'3d_shadows'}[$s->{boxci}] );
- } else {
- $g->filledPolygon( $poly, $s->{boxci} );
- } # end if
-
- # Bottom
- $poly = new GD::Polygon;
- $poly->addPt( $l, $b );
- $poly->addPt( $l + $depth, $b - $depth );
- $poly->addPt( $r + $depth, $b - $depth );
- $poly->addPt( $r, $b );
- if( $s->{'3d_shading'} ) {
- $g->filledPolygon( $poly, $s->{'3d_highlights'}[$s->{boxci}] );
- } else {
- $g->filledPolygon( $poly, $s->{boxci} );
- } # end if
- } # end if
- # -- Draw the frame only for back & sides
-
- # Back box
- $g->rectangle($l + $depth, $t - $depth, $r + $depth, $b - $depth, $s->{fgci});
-
- # Y axis
- my $poly = new GD::Polygon;
- $poly->addPt( $l, $t );
- $poly->addPt( $l, $b );
- $poly->addPt( $l + $depth, $b - $depth );
- $poly->addPt( $l + $depth, $t - $depth );
- $g->polygon( $poly, $s->{fgci} );
-
- # X axis
- if( !$s->{zero_axis_only} ) {
- $poly = new GD::Polygon;
- $poly->addPt( $l, $b );
- $poly->addPt( $r, $b );
- $poly->addPt( $r + $depth, $b - $depth );
- $poly->addPt( $l + $depth, $b - $depth );
- $g->polygon( $poly, $s->{fgci} );
- } # end if
-
- # Second Y axis
- if( $s->{two_axes} ){
- $poly = new GD::Polygon;
- $poly->addPt( $r, $b );
- $poly->addPt( $r, $t );
- $poly->addPt( $r + $depth, $t - $depth );
- $poly->addPt( $r + $depth, $b - $depth );
- $g->polygon( $poly, $s->{fgci} );
- } # end if
- } # end if
-
- # Zero axis
- if ($s->{zero_axis} or $s->{zero_axis_only}) {
- my ($x, $y) = $s->val_to_pixel(0, 0, 1);
- my $poly = new GD::Polygon;
- $poly->addPt( $l, $y );
- $poly->addPt( $r, $y );
- $poly->addPt( $r + $depth, $y - $depth );
- $poly->addPt( $l + $depth, $y - $depth);
- $g->polygon( $poly, $s->{fgci} );
- } # end if
-
-} # end draw_axes
-
-# [JAW] Draws ticks and values for y axes in 3d extrusion
-# Modified from MVERB source
-sub draw_y_ticks
-{
- my $self = shift;
-
- for my $t (0 .. $self->{y_tick_number})
- {
- for my $a (1 .. ($self->{two_axes} + 1))
- {
- my $value = $self->{y_values}[$a][$t];
- my $label = $self->{y_labels}[$a][$t];
-
- my ($x, $y) = $self->val_to_pixel(0, $value, $a);
- $x = ($a == 1) ? $self->{left} : $self->{right};
-
- # CONTRIB Jeremy Wadsack
- # Draw on the back of the extrusion
- $x += $self->{depth_3d};
- $y -= $self->{depth_3d};
-
- if ($self->{y_long_ticks})
- {
- $self->{graph}->line(
- $x, $y,
- $x + $self->{right} - $self->{left}, $y,
- $self->{fgci}
- ) unless ($a-1);
- # CONTRIB Jeremy Wadsack
- # Draw conector ticks
- $self->{graph}->line( $x - $self->{depth_3d},
- $y + $self->{depth_3d},
- $x,
- $y,
- $self->{fgci}
- ) unless ($a-1);
- }
- else
- {
- $self->{graph}->line(
- $x, $y,
- $x + (3 - 2 * $a) * $self->{y_tick_length}, $y,
- $self->{fgci}
- );
- # CONTRIB Jeremy Wadsack
- # Draw conector ticks
- $self->{graph}->line( $x - $self->{depth_3d},
- $y + $self->{depth_3d},
- $x - $self->{depth_3d} + (3 - 2 * $a) * $self->{y_tick_length},
- $y + $self->{depth_3d} - (3 - 2 * $a) * $self->{y_tick_length},
- $self->{fgci}
- );
- }
-
- next
- if $t % ($self->{y_label_skip}) || ! $self->{y_plot_values};
-
- $self->{gdta_y_axis}->set_text($label);
- $self->{gdta_y_axis}->set_align('center',
- $a == 1 ? 'right' : 'left');
- $x -= (3 - 2 * $a) * $self->{axis_space};
-
- # CONTRIB Jeremy Wadsack
- # Subtract 3-d extrusion width from left axis label
- # (it was added for ticks)
- $x -= (2 - $a) * $self->{depth_3d};
-
- # CONTRIB Jeremy Wadsack
- # Add 3-d extrusion height to label
- # (it was subtracted for ticks)
- $y += $self->{depth_3d};
-
- $self->{gdta_y_axis}->draw($x, $y);
-
- } # end foreach
- } # end foreach
-
- return $self;
-
-} # end draw_y_ticks
-
-# [JAW] Darws ticks and values for x axes wih 3d extrusion
-# Modified from MVERB source
-sub draw_x_ticks
-{
- my $self = shift;
-
- for (my $i = 0; $i < $self->{_data}->num_points; $i++)
- {
- my ($x, $y) = $self->val_to_pixel($i + 1, 0, 1);
-
- $y = $self->{bottom} unless $self->{zero_axis_only};
-
- # CONTRIB Damon Brodie for x_tick_offset
- next if (!$self->{x_all_ticks} and
- ($i - $self->{x_tick_offset}) % $self->{x_label_skip} and
- $i != $self->{_data}->num_points - 1
- );
-
- # CONTRIB Jeremy Wadsack
- # Draw on the back of the extrusion
- $x += $self->{depth_3d};
- $y -= $self->{depth_3d};
-
- if ($self->{x_ticks})
- {
- if ($self->{x_long_ticks})
- {
- # CONTRIB Jeremy Wadsack
- # Move up by 3d depth
- $self->{graph}->line( $x,
- $self->{bottom} - $self->{depth_3d},
- $x,
- $self->{top} - $self->{depth_3d},
- $self->{fgci});
- # CONTRIB Jeremy Wadsack
- # Draw conector ticks
- $self->{graph}->line( $x - $self->{depth_3d},
- $y + $self->{depth_3d},
- $x,
- $y,
- $self->{fgci}
- );
- }
- else
- {
- $self->{graph}->line( $x, $y, $x, $y - $self->{x_tick_length}, $self->{fgci} );
- # CONTRIB Jeremy Wadsack
- # Draw conector ticks
- $self->{graph}->line( $x - $self->{depth_3d},
- $y + $self->{depth_3d},
- $x - $self->{depth_3d} + $self->{x_tick_length},
- $y + $self->{depth_3d} - $self->{x_tick_length},
- $self->{fgci}
- );
- }
- }
-
- # CONTRIB Damon Brodie for x_tick_offset
- next if
- ($i - $self->{x_tick_offset}) % ($self->{x_label_skip}) and
- $i != $self->{_data}->num_points - 1;
-
- $self->{gdta_x_axis}->set_text($self->{_data}->get_x($i));
-
- # CONTRIB Jeremy Wadsack
- # Subtract 3-d extrusion width from left label
- # Add 3-d extrusion height to left label
- # (they were changed for ticks)
- $x -= $self->{depth_3d};
- $y += $self->{depth_3d};
-
- my $yt = $y + $self->{axis_space};
-
- if ($self->{x_labels_vertical})
- {
- $self->{gdta_x_axis}->set_align('center', 'right');
- $self->{gdta_x_axis}->draw($x, $yt, PI/2);
- }
- else
- {
- $self->{gdta_x_axis}->set_align('top', 'center');
- $self->{gdta_x_axis}->draw($x, $yt);
- }
-
- } # end for
-
- return $self;
-
-} # end draw_x_ticks
-
-
-# CONTRIB Scott Prahl
-# Assume x array contains equally spaced x-values
-# and generate an appropriate axis
-#
-####
-# 'True' numerical X axis addition
-# From: Gary Deschaines
-#
-# These modification to draw_x_ticks_number pass x-tick values to the
-# val_to_pixel subroutine instead of x-tick indices when ture[sic] numerical
-# x-axis mode is detected. Also, x_tick_offset and x_label_skip are
-# processed differently when true numerical x-axis mode is detected to
-# allow labeled major x-tick marks and un-labeled minor x-tick marks.
-#
-# For example:
-#
-# x_tick_number => 14,
-# x_ticks => 1,
-# x_long_ticks => 1,
-# x_tick_length => -4,
-# x_min_value => 100,
-# x_max_value => 800,
-# x_tick_offset => 2,
-# x_label_skip => 2,
-#
-#
-# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-# | | | | | | | | | | | | |
-# 1 -| | | | | | | | | | | | |
-# | | | | | | | | | | | | |
-# 0 _|_________|____|____|____|____|____|____|____|____|____|____|_________|
-# | | | | | | | | | | |
-# 200 300 400 500 600 700
-####
-# [JAW] Added commented items for 3d rendering
-# Based on MVERB source
-sub draw_x_ticks_number
-{
- my $self = shift;
-
- for my $i (0 .. $self->{x_tick_number})
- {
- my ($value, $x, $y);
-
- if (defined($self->{x_min_value}) && defined($self->{x_max_value}))
- {
- next if ($i - $self->{x_tick_offset}) < 0;
- next if ($i + $self->{x_tick_offset}) > $self->{x_tick_number};
- $value = $self->{x_values}[$i];
- ($x, $y) = $self->val_to_pixel($value, 0, 1);
- }
- else
- {
- $value = ($self->{_data}->num_points - 1)
- * ($self->{x_values}[$i] - $self->{true_x_min})
- / ($self->{true_x_max} - $self->{true_x_min});
- ($x, $y) = $self->val_to_pixel($value + 1, 0, 1);
- }
-
- $y = $self->{bottom} unless $self->{zero_axis_only};
-
- # Draw on the back of the extrusion
- $x += $self->{depth_3d};
- $y -= $self->{depth_3d};
-
- if ($self->{x_ticks})
- {
- if ($self->{x_long_ticks})
- {
- # XXX This mod needs to be done everywhere ticks are
- # drawn
- if ( $self->{x_tick_length} >= 0 )
- {
- # Move up by 3d depth
- $self->{graph}->line( $x,
- $self->{bottom} - $self->{depth_3d},
- $x,
- $self->{top} - $self->{depth_3d},
- $self->{fgci});
- }
- else
- {
- $self->{graph}->line(
- $x, $self->{bottom} - $self->{x_tick_length},
- $x, $self->{top}, $self->{fgci});
- }
- # CONTRIB Jeremy Wadsack
- # Draw conector ticks
- $self->{graph}->line( $x - $self->{depth_3d},
- $y + $self->{depth_3d},
- $x,
- $y,
- $self->{fgci}
- );
- }
- else
- {
- $self->{graph}->line($x, $y,
- $x, $y - $self->{x_tick_length}, $self->{fgci} );
- # CONTRIB Jeremy Wadsack
- # Draw conector ticks
- $self->{graph}->line( $x - $self->{depth_3d},
- $y + $self->{depth_3d},
- $x, - $self->{depth_3d} + $self->{tick_length},
- $y, + $self->{depth_3d} - $self->{tick_length},
- $self->{fgci}
- );
- } # end if -- x_long_ticks
- } # end if -- x_ticks
-
- # If we have to skip labels, we'll do it here.
- # Make sure to always draw the last one.
- next if $i % $self->{x_label_skip} && $i != $self->{x_tick_number};
-
- $self->{gdta_x_axis}->set_text($self->{x_labels}[$i]);
-
- # CONTRIB Jeremy Wadsack
- # Subtract 3-d extrusion width from left label
- # Add 3-d extrusion height to left label
- # (they were changed for ticks)
- $x -= $self->{depth_3d};
- $y += $self->{depth_3d};
-
- if ($self->{x_labels_vertical})
- {
- $self->{gdta_x_axis}->set_align('center', 'right');
- my $yt = $y + $self->{text_space}/2;
- $self->{gdta_x_axis}->draw($x, $yt, PI/2);
- }
- else
- {
- $self->{gdta_x_axis}->set_align('top', 'center');
- my $yt = $y + $self->{text_space}/2;
- $self->{gdta_x_axis}->draw($x, $yt);
- } # end if
- } # end for
-
- return $self;
-
-} # end draw_x_tick_number
-
-# Inherit draw_ticks
-# Inherit draw_data
-# Inherit draw_data_set
-# Inherit set_max_min
-# Inherit get_max_y
-# Inherit get_min_y
-# Inherit get_max_min_y_all
-# Inherit _get_bottom
-# Inherit val_to_pixel
-# Inherit setup_legend
-
-
-# [JW] Override draw_legend and reverse the drawing order
-# if cumulate is enabled so legend matches data on chart
-sub draw_legend
-{
- my $self = shift;
-
- return unless defined $self->{legend};
-
- my $xl = $self->{lg_xs} + $self->{legend_spacing};
- my $y = $self->{lg_ys} + $self->{legend_spacing} - 1;
-
- # If there's a frame, offset by the size and margin
- $xl += $self->{legend_frame_margin} + $self->{legend_frame_size} if $self->{legend_frame_size};
- $y += $self->{legend_frame_margin} + $self->{legend_frame_size} if $self->{legend_frame_size};
-
- my $i = 0;
- my $row = 1;
- my $x = $xl; # start position of current element
- my @legends = @{$self->{legend}};
- my $i_step = 1;
-
- # If we are working in cumulate mode, then reverse the drawing order
- if( $self->{cumulate} ) {
- @legends = reverse @legends;
- $i = scalar(@legends);
- $i = $self->{_data}->num_sets if $self->{_data}->num_sets < $i;
- $i++;
- $i_step = -1;
- } # end if
-
- foreach my $legend (@legends)
- {
- $i += $i_step;
-
- # Legend for Pie goes over first set, and all points
- # Works in either direction
- last if $i > $self->{_data}->num_sets;
- last if $i < 1;
-
- my $xe = $x; # position within an element
-
- next unless defined($legend) && $legend ne "";
-
- $self->draw_legend_marker($i, $xe, $y);
-
- $xe += $self->{legend_marker_width} + $self->{legend_spacing};
- my $ys = int($y + $self->{lg_el_height}/2 - $self->{lgfh}/2);
-
- $self->{gdta_legend}->set_text($legend);
- $self->{gdta_legend}->draw($xe, $ys);
-
- $x += $self->{lg_el_width};
-
- if (++$row > $self->{lg_cols})
- {
- $row = 1;
- $y += $self->{lg_el_height};
- $x = $xl;
- }
- }
-
- # If there's a frame, draw it now
- if( $self->{legend_frame_size} ) {
- $x = $self->{lg_xs} + $self->{legend_spacing};
- $y = $self->{lg_ys} + $self->{legend_spacing} - 1;
-
- for $i ( 0 .. $self->{legend_frame_size} - 1 ) {
- $self->{graph}->rectangle(
- $x + $i,
- $y + $i,
- $x + $self->{lg_x_size} + 2 * $self->{legend_frame_margin} - $i - 1,
- $y + $self->{lg_y_size} + 2 * $self->{legend_frame_margin} - $i - 1,
- $self->{acci},
- );
- } # end for
- } # end if
-
-}
-
-
-
-# Inherit draw_legend_marker
-
-1;
diff --git a/lib/GD/Graph/bars.pm b/lib/GD/Graph/bars.pm
deleted file mode 100644
index 2650351..0000000
--- a/lib/GD/Graph/bars.pm
+++ /dev/null
@@ -1,372 +0,0 @@
-#==========================================================================
-# Copyright (c) 1995-1998 Martien Verbruggen
-#--------------------------------------------------------------------------
-#
-# Name:
-# GD::Graph::bars.pm
-#
-# $Id: bars.pm,v 1.25 2003/06/11 00:43:49 mgjv Exp $
-#
-#==========================================================================
-
-package GD::Graph::bars;
-
-($GD::Graph::bars::VERSION) = '$Revision: 1.25 $' =~ /\s([\d.]+)/;
-
-use strict;
-
-use GD::Graph::axestype;
-use GD::Graph::utils qw(:all);
-use GD::Graph::colour qw(:colours);
-
-@GD::Graph::bars::ISA = qw(GD::Graph::axestype);
-
-use constant PI => 4 * atan2(1,1);
-
-sub initialise
-{
- my $self = shift;
- $self->SUPER::initialise();
- $self->set(correct_width => 1);
-}
-
-sub draw_data
-{
- my $self = shift;
-
- $self->SUPER::draw_data() or return;
-
- unless ($self->{no_axes})
- {
- # redraw the 'zero' axis
- if ($self->{rotate_chart})
- {
- $self->{graph}->line(
- $self->{zeropoint}, $self->{top},
- $self->{zeropoint}, $self->{bottom},
- $self->{fgci} );
- }
- else
- {
- $self->{graph}->line(
- $self->{left}, $self->{zeropoint},
- $self->{right}, $self->{zeropoint},
- $self->{fgci} );
- }
- }
-
- return $self;
-}
-
-sub _top_values
-{
- my $self = shift;
- my @topvalues;
-
- if ($self->{cumulate})
- {
- my $data = $self->{_data};
- for my $i (0 .. $data->num_points - 1)
- {
- push @topvalues, $data->get_y_cumulative($data->num_sets, $i);
- }
- }
-
- return \@topvalues;
-}
-
-#
-# Draw the shadow
-#
-sub _draw_shadow
-{
- my $self = shift;
- my ($ds, $i, $value, $topvalues, $l, $t, $r, $b) = @_;
- my $bsd = $self->{shadow_depth} or return;
- my $bsci = $self->set_clr(_rgb($self->{shadowclr}));
-
- if ($self->{cumulate})
- {
- return if $ds > 1;
- $value = $topvalues->[$i];
- if ($self->{rotate_chart})
- {
- $r = ($self->val_to_pixel($i + 1, $value, $ds))[0];
- }
- else
- {
- $t = ($self->val_to_pixel($i + 1, $value, $ds))[1];
- }
- }
-
- # XXX Clean this up
- if ($value >= 0)
- {
- if ($self->{rotate_chart})
- {
- $self->{graph}->filledRectangle(
- $l, $t + $bsd, $r - $bsd, $b + $bsd, $bsci);
- }
- else
- {
- $self->{graph}->filledRectangle(
- $l + $bsd, $t + $bsd, $r + $bsd, $b, $bsci);
- }
- }
- else
- {
- if ($self->{rotate_chart})
- {
- $self->{graph}->filledRectangle(
- $l + $bsd, $t, $r + $bsd, $b, $bsci);
- }
- else
- {
- $self->{graph}->filledRectangle(
- $l + $bsd, $b, $r + $bsd, $t + $bsd, $bsci);
- }
- }
-}
-
-sub draw_data_set_h
-{
- my $self = shift;
- my $ds = shift;
-
- my $bar_s = $self->{bar_spacing}/2;
-
- # Pick a data colour
- my $dsci = $self->set_clr($self->pick_data_clr($ds));
- # contrib "Bremford, Mike" <mike.bremford@gs.com>
- my $brci = $self->set_clr($self->pick_border_clr($ds));
-
- my @values = $self->{_data}->y_values($ds) or
- return $self->_set_error("Impossible illegal data set: $ds",
- $self->{_data}->error);
-
- my $topvalues = $self->_top_values;
-
- for my $i (0 .. $#values)
- {
- my $value = $values[$i];
- next unless defined $value;
-
- my $l = $self->_get_bottom($ds, $i);
- $value = $self->{_data}->get_y_cumulative($ds, $i)
- if ($self->{cumulate});
-
- # CONTRIB Jeremy Wadsack
- #
- # cycle_clrs option sets the color based on the point,
- # not the dataset.
- $dsci = $self->set_clr($self->pick_data_clr($i + 1))
- if $self->{cycle_clrs};
- $brci = $self->set_clr($self->pick_data_clr($i + 1))
- if $self->{cycle_clrs} > 1;
-
- # get coordinates of right and center of bar
- my ($r, $xp) = $self->val_to_pixel($i + 1, $value, $ds);
-
- # calculate top and bottom of bar
- my ($t, $b);
-
- if (ref $self eq 'GD::Graph::mixed' || $self->{overwrite})
- {
- $t = $xp - $self->{x_step}/2 + $bar_s + 1;
- $b = $xp + $self->{x_step}/2 - $bar_s;
- }
- else
- {
- $t = $xp
- - $self->{x_step}/2
- + ($ds - 1) * $self->{x_step}/$self->{_data}->num_sets
- + $bar_s + 1;
- $b = $xp
- - $self->{x_step}/2
- + $ds * $self->{x_step}/$self->{_data}->num_sets
- - $bar_s;
- }
-
- # draw the bar
- $self->_draw_shadow($ds, $i, $value, $topvalues, $l, $t, $r, $b);
- if ($value >= 0)
- {
- # positive value
- $self->{graph}->filledRectangle($l, $t, $r, $b, $dsci)
- if defined $dsci;
- $self->{graph}->rectangle($l, $t, $r, $b, $brci)
- if defined $brci && $b - $t > $self->{accent_treshold};
-
- $self->{_hotspots}->[$ds]->[$i] = ['rect', $t, $l, $r, $b]
- }
- else
- {
- # negative value
- $self->{graph}->filledRectangle($r, $t, $l, $b, $dsci)
- if defined $dsci;
- $self->{graph}->rectangle($l, $t, $r, $b, $brci)
- if defined $brci && $b - $t > $self->{accent_treshold};
-
- $self->{_hotspots}->[$ds]->[$i] = ['rect', $t, $l, $b, $r]
- }
- }
-
- return $ds;
-}
-
-sub draw_data_set_v
-{
- my $self = shift;
- my $ds = shift;
-
- my $bar_s = $self->{bar_spacing}/2;
-
- # Pick a data colour
- my $dsci = $self->set_clr($self->pick_data_clr($ds));
- # contrib "Bremford, Mike" <mike.bremford@gs.com>
- my $brci = $self->set_clr($self->pick_border_clr($ds));
-
- my @values = $self->{_data}->y_values($ds) or
- return $self->_set_error("Impossible illegal data set: $ds",
- $self->{_data}->error);
-
- my $topvalues = $self->_top_values;
-
- for (my $i = 0; $i < @values; $i++)
- {
- my $value = $values[$i];
- next unless defined $value;
-
- my $bottom = $self->_get_bottom($ds, $i);
- $value = $self->{_data}->get_y_cumulative($ds, $i)
- if ($self->{cumulate});
-
- # CONTRIB Jeremy Wadsack
- #
- # cycle_clrs option sets the color based on the point,
- # not the dataset.
- $dsci = $self->set_clr($self->pick_data_clr($i + 1))
- if $self->{cycle_clrs};
- $brci = $self->set_clr($self->pick_data_clr($i + 1))
- if $self->{cycle_clrs} > 1;
-
- # get coordinates of top and center of bar
- my ($xp, $t) = $self->val_to_pixel($i + 1, $value, $ds);
-
- # calculate left and right of bar
- my ($l, $r);
-
- if (ref $self eq 'GD::Graph::mixed' || $self->{overwrite})
- {
- $l = $xp - $self->{x_step}/2 + $bar_s + 1;
- $r = $xp + $self->{x_step}/2 - $bar_s;
- }
- else
- {
- $l = $xp
- - $self->{x_step}/2
- + ($ds - 1) * $self->{x_step}/$self->{_data}->num_sets
- + $bar_s + 1;
- $r = $xp
- - $self->{x_step}/2
- + $ds * $self->{x_step}/$self->{_data}->num_sets
- - $bar_s;
- }
-
- # draw the bar
- $self->_draw_shadow($ds, $i, $value, $topvalues, $l, $t, $r, $bottom);
- if ($value >= 0)
- {
- # positive value
- $self->{graph}->filledRectangle($l, $t, $r, $bottom, $dsci)
- if defined $dsci;
- $self->{graph}->rectangle($l, $t, $r, $bottom, $brci)
- if defined $brci && $r - $l > $self->{accent_treshold};
-
- $self->{_hotspots}->[$ds]->[$i] = ['rect', $l, $t, $r, $bottom]
- }
- else
- {
- # negative value
- $self->{graph}->filledRectangle($l, $bottom, $r, $t, $dsci)
- if defined $dsci;
- $self->{graph}->rectangle($l, $bottom, $r, $t, $brci)
- if defined $brci && $r - $l > $self->{accent_treshold};
-
- $self->{_hotspots}->[$ds]->[$i] = ['rect', $l, $bottom, $r, $t]
- }
- }
-
- return $ds;
-}
-
-sub draw_data_set
-{
- $_[0]->{rotate_chart} ? goto &draw_data_set_h : goto &draw_data_set_v;
-}
-
-sub draw_values
-{
- my $self = shift;
-
- return $self unless $self->{show_values};
-
- my $text_angle = $self->{values_vertical} ? PI/2 : 0;
-
- for (my $dsn = 1; $dsn <= $self->{_data}->num_sets; $dsn++)
- {
- my @values = $self->{_data}->y_values($dsn) or
- return $self->_set_error("Impossible illegal data set: $dsn",
- $self->{_data}->error);
- my @display = $self->{show_values}->y_values($dsn) or next;
-
- for (my $i = 0; $i < @values; $i++)
- {
- next unless defined $display[$i];
-
- my $value = $display[$i];
- if (defined $self->{values_format})
- {
- $value = ref $self->{values_format} eq 'CODE' ?
- &{$self->{values_format}}($value) :
- sprintf($self->{values_format}, $value);
- }
-
- my ($xp, $yp);
- if (defined($self->{x_min_value}) && defined($self->{x_max_value}))
- {
- ($xp, $yp) = $self->val_to_pixel(
- $self->{_data}->get_x($i), $values[$i], $dsn);
- }
- else
- {
- ($xp, $yp) = $self->val_to_pixel($i+1, $values[$i], $dsn);
- }
- if ($self->{rotate_chart})
- {
- $xp += $self->{values_space};
- unless ($self->{overwrite})
- {
- $yp -= $self->{x_step}/2 - ($dsn - 0.5)
- * $self->{x_step}/$self->{_data}->num_sets;
- }
- }
- else
- {
- $yp -= $self->{values_space};
- unless ($self->{overwrite})
- {
- $xp -= $self->{x_step}/2 - ($dsn - 0.5)
- * $self->{x_step}/$self->{_data}->num_sets;
- }
- }
-
- $self->{gdta_values}->set_text($value);
- $self->{gdta_values}->draw($xp, $yp, $text_angle);
- }
- }
-
- return $self
-}
-
-"Just another true value";
diff --git a/lib/GD/Graph/bars3d.pm b/lib/GD/Graph/bars3d.pm
deleted file mode 100644
index 5344976..0000000
--- a/lib/GD/Graph/bars3d.pm
+++ /dev/null
@@ -1,349 +0,0 @@
-#==========================================================================
-# Module: GD::Graph::bars3d
-#
-# Copyright (C) 1999,2001 Wadsack-Allen. All Rights Reserved.
-#
-# Based on GD::Graph::bars.pm,v 1.16 2000/03/18 10:58:39 mgjv
-# Copyright (c) 1995-1998 Martien Verbruggen
-#
-#--------------------------------------------------------------------------
-# Date Modification Author
-# -------------------------------------------------------------------------
-# 1999SEP18 Created 3D bar chart class (this module) JAW
-# 1999SEP19 Rewrote to include a single bar-drawing JAW
-# function and process all bars in series
-# 1999SEP19 Implemented support for overwrite 2 style JAW
-# 1999SEP19 Fixed a bug in color cycler (colors were off by 1) JAW
-# 2000JAN19 Converted to GD::Graph class JAW
-# 2000MAR10 Fixed bug where bars ran off bottom of chart JAW
-# 2000APR18 Modified to be compatible with GD::Graph 1.30 JAW
-# 2000APR24 Fixed a lot of rendering bugs and added shading JAW
-# 2000AUG21 Added 3d shading JAW
-# 2000AUG24 Fixed shading on cycle_clrs option JAW
-# 06Dec2002 Fixed on-bar rendering with bars.pm draw_values JW
-#==========================================================================
-package GD::Graph::bars3d;
-
-use strict;
-
-use GD::Graph::axestype3d;
-use GD::Graph::bars;
-use GD::Graph::utils qw(:all);
-use GD::Graph::colour qw(:colours);
-
-@GD::Graph::bars3d::ISA = qw(GD::Graph::axestype3d);
-$GD::Graph::bars3d::VERSION = '0.63';
-
-use constant PI => 4 * atan2(1,1);
-
-
-my %Defaults = (
- # Spacing between the bars
- bar_spacing => 0,
-
- # The 3-d extrusion depth of the bars
- bar_depth => 10,
-);
-
-sub initialise
-{
- my $self = shift;
-
- my $rc = $self->SUPER::initialise();
- $self->set(correct_width => 1);
-
- while( my($key, $val) = each %Defaults ) {
- $self->{$key} = $val
- } # end while
-
- return $rc;
-} # end initialise
-
-sub set
-{
- my $s = shift;
- my %args = @_;
-
- $s->{_set_error} = 0;
-
- for (keys %args)
- {
- /^bar_depth$/ and do
- {
- $s->{bar_depth} = $args{$_};
- delete $args{$_};
- next;
- };
- }
-
- return $s->SUPER::set(%args);
-}
-
-
-# CONTRIB Jeremy Wadsack
-# This is a complete overhaul of the original GD::Graph::bars
-# design, because all versions (overwrite = 0, 1, 2)
-# require that the bars be drawn in a loop of point over sets
-sub draw_data
-{
- my $self = shift;
- my $g = $self->{graph};
-
- my $bar_s = _round($self->{bar_spacing}/2);
-
- my $zero = $self->{zeropoint};
-
- my $i;
- my @iterate = (0 .. $self->{_data}->num_points());
- for $i ($self->{rotate_chart} ? reverse(@iterate) : @iterate) {
- my ($xp, $t);
- my $overwrite = 0;
- $overwrite = $self->{overwrite} if defined $self->{overwrite};
-
- my $j;
- my @iterate = (1 .. $self->{_data}->num_sets());
- for $j (($self->{rotate_chart} && $self->{cumulate} == 0) ? reverse(@iterate) : @iterate) {
- my $value = $self->{_data}->get_y( $j, $i );
- next unless defined $value;
-
- my $bottom = $self->_get_bottom($j, $i);
- $value = $self->{_data}->get_y_cumulative($j, $i)
- if ($self->{cumulate});
-
- # Pick a data colour, calc shading colors too, if requested
- # cycle_clrs option sets the color based on the point, not the dataset.
- my @rgb;
- if( $self->{cycle_clrs} ) {
- @rgb = $self->pick_data_clr( $i + 1 );
- } else {
- @rgb = $self->pick_data_clr( $j );
- } # end if
- my $dsci = $self->set_clr( @rgb );
- if( $self->{'3d_shading'} ) {
- $self->{'3d_highlights'}[$dsci] = $self->set_clr( $self->_brighten( @rgb ) );
- $self->{'3d_shadows'}[$dsci] = $self->set_clr( $self->_darken( @rgb ) );
- } # end if
-
- # contrib "Bremford, Mike" <mike.bremford@gs.com>
- my $brci;
- if( $self->{cycle_clrs} > 1 ) {
- $brci = $self->set_clr($self->pick_data_clr($i + 1));
- } else {
- $brci = $self->set_clr($self->pick_border_clr($j));
- } # end if
-
-
- # get coordinates of top and center of bar
- ($xp, $t) = $self->val_to_pixel($i + 1, $value, $j);
-
- # calculate offsets of this bar
- my $x_offset = 0;
- my $y_offset = 0;
- if( $overwrite == 1 ) {
- $x_offset = $self->{bar_depth} * ($self->{_data}->num_sets() - $j);
- $y_offset = $self->{bar_depth} * ($self->{_data}->num_sets() - $j);
- }
- $t -= $y_offset;
-
-
- # calculate left and right of bar
- my ($l, $r);
- if ($self->{rotate_chart}) {
- $l = $bottom;
- ($r) = $self->val_to_pixel($i + 1, $value, $j);
- }
-
- if( (ref $self eq 'GD::Graph::mixed') || ($overwrite >= 1) )
- {
- if ($self->{rotate_chart}) {
- $bottom = $t + $self->{x_step}/2 - $bar_s + $x_offset;
- $t = $t - $self->{x_step}/2 + $bar_s + $x_offset;
- }
- else
- {
- $l = $xp - $self->{x_step}/2 + $bar_s + $x_offset;
- $r = $xp + $self->{x_step}/2 - $bar_s + $x_offset;
- }
- }
- else
- {
- if ($self->{rotate_chart}) {
- warn "base is $t";
- $bottom = $t - $self->{x_step}/2
- + ($j) * $self->{x_step}/$self->{_data}->num_sets()
- + $bar_s + $x_offset;
- $t = $t - $self->{x_step}/2
- + ($j-1) * $self->{x_step}/$self->{_data}->num_sets()
- - $bar_s + $x_offset;
- warn "top bottom is ($t, $bottom)";
- }
- else
- {
- $l = $xp
- - $self->{x_step}/2
- + ($j - 1) * $self->{x_step}/$self->{_data}->num_sets()
- + $bar_s + $x_offset;
- $r = $xp
- - $self->{x_step}/2
- + $j * $self->{x_step}/$self->{_data}->num_sets()
- - $bar_s + $x_offset;
- }
- }
-
- if ($value >= 0) {
- # draw the positive bar
- $self->draw_bar( $g, $l, $t, $r, $bottom-$y_offset, $dsci, $brci, 0 )
- } else {
- # draw the negative bar
- $self->draw_bar( $g, $l, $bottom-$y_offset, $r, $t, $dsci, $brci, -1 )
- } # end if
-
- } # end for
- } # end for
-
-
- # redraw the 'zero' axis, front and right
- if( $self->{zero_axis} ) {
- $g->line(
- $self->{left}, $self->{zeropoint},
- $self->{right}, $self->{zeropoint},
- $self->{fgci} );
- $g->line(
- $self->{right}, $self->{zeropoint},
- $self->{right}+$self->{depth_3d}, $self->{zeropoint}-$self->{depth_3d},
- $self->{fgci} );
- } # end if
-
- # redraw the box face
- if ( $self->{box_axis} ) {
- # Axes box
- $g->rectangle($self->{left}, $self->{top}, $self->{right}, $self->{bottom}, $self->{fgci});
- $g->line($self->{right}, $self->{top}, $self->{right} + $self->{depth_3d}, $self->{top} - $self->{depth_3d}, $self->{fgci});
- $g->line($self->{right}, $self->{bottom}, $self->{right} + $self->{depth_3d}, $self->{bottom} - $self->{depth_3d}, $self->{fgci});
- } # end if
-
- return $self;
-
-} # end draw_data
-
-# CONTRIB Jeremy Wadsack
-# This function draws a bar at the given
-# coordinates. This is called in all three
-# overwrite modes.
-sub draw_bar {
- my $self = shift;
- my $g = shift;
- my( $l, $t, $r, $b, $dsci, $brci, $neg ) = @_;
-
- # get depth of the bar
- my $depth = $self->{bar_depth};
-
- # get the bar shadow depth and color
- my $bsd = $self->{shadow_depth};
- my $bsci = $self->set_clr(_rgb($self->{shadowclr}));
-
- my( $xi );
-
- # shadow
- if( $bsd > 0 ) {
- my $sb = $b - $depth;
- my $st = $t - $depth + $bsd;
-
- if( $neg != 0 ) {
- $st -= $bsd;
- if( $self->{zero_axis_only} ) {
- $sb += $bsd;
- } else {
- $sb = _min($b-$depth+$bsd, $self->{bottom}-$depth);
- } # end if
- } # end if
-
- # ** If this isn't the back bar, then no side shadow should be
- # drawn or else the top should be lowered by
- # ($bsd * dataset_num), it should be drawn on the back surface,
- # and a shadow should be drawn behind the front bar if the
- # bar is positive and the back is negative.
-
- $g->filledRectangle($l+$depth+$bsd,
- $st,
- $r+$depth+$bsd,
- $sb,
- $bsci);
-
- # Only draw bottom shadow if at the bottom and has bottom
- # axis. Always draw top shadow
- if( ($neg == 0) || ($sb >= $self->{bottom}-$depth) ) {
- my $poly = new GD::Polygon;
- $poly->addPt( $r, $b );
- $poly->addPt( $r+$bsd, $b );
- $poly->addPt( $r+$depth+$bsd, $b-$depth );
- $poly->addPt( $r+$depth, $b-$depth );
- $g->filledPolygon( $poly, $bsci );
- } # end if
-
- } # end if
-
- # side
- my $poly = new GD::Polygon;
- $poly->addPt( $r, $t );
- $poly->addPt( $r+$depth, $t-$depth );
- $poly->addPt( $r+$depth, $b-$depth );
- $poly->addPt( $r, $b );
- if( $self->{'3d_shading'} ) {
- $g->filledPolygon( $poly, $self->{'3d_shadows'}[$dsci] );
- } else {
- $g->filledPolygon( $poly, $dsci );
- } # end if
- $g->polygon( $poly, $brci );
-
- # top
- # -- only draw negative tops if the bar starts at zero
- if( ($neg == 0) || ($t <= $self->{zeropoint}) ) {
- $poly = new GD::Polygon;
- $poly->addPt( $l, $t );
- $poly->addPt( $l+$depth, $t-$depth );
- $poly->addPt( $r+$depth, $t-$depth );
- $poly->addPt( $r, $t );
- if( $self->{'3d_shading'} ) {
- $g->filledPolygon( $poly, $self->{'3d_highlights'}[$dsci] );
- } else {
- $g->filledPolygon( $poly, $dsci );
- } # end if
- $g->polygon( $poly, $brci );
- } # end if
-
- # face
- $g->filledRectangle( $l, $t, $r, $b, $dsci );
- $g->rectangle( $l, $t, $r, $b, $brci );
-
-} # end draw_bar
-
-# [JAW] Overrides axestype's set_max_min.
-# Go through the parent's process then adjust the baseline to 0 for bar graphs.
-sub set_max_min {
- my $self = shift;
-
- $self->SUPER::set_max_min( @_ );
-
- # This code is taken from Martien's axestype.pm
- for my $i (1..($self->{two_axes} ? 2 : 1)) {
- # If at the same side of the zero axis
- if( $self->{y_max}[$i] && $self->{y_min}[$i]/$self->{y_max}[$i] > 0 ) {
- $self->{y_min}[$i] > 0 ?
- $self->{y_min}[$i] = 0 :
- $self->{y_max}[$i] = 0 ;
- } # end if
- } # end for
-
- return $self;
-} # end set_max_min
-
-
-# [JW] Just use the one in GD::Graph::bars
-sub draw_values
-{
- return &GD::Graph::bars::draw_values( @_ );
-}
-
-
-1;
diff --git a/lib/GD/Graph/colour.pm b/lib/GD/Graph/colour.pm
deleted file mode 100644
index 8b25059..0000000
--- a/lib/GD/Graph/colour.pm
+++ /dev/null
@@ -1,371 +0,0 @@
-#==========================================================================
-# Copyright (c) 1995-1998 Martien Verbruggen
-#--------------------------------------------------------------------------
-#
-# Name:
-# GD::Graph::colour.pm
-#
-# Description:
-# Package of colour manipulation routines, to be used
-# with GD::Graph.
-#
-# $Id: colour.pm,v 1.10 2003/02/11 05:38:46 mgjv Exp $
-#
-#==========================================================================
-
-
-package GD::Graph::colour;
-
-($GD::Graph::colour::VERSION) = '$Revision: 1.10 $' =~ /\s([\d.]+)/;
-
-=head1 NAME
-
-GD::Graph::colour - Colour manipulation routines for use with GD::Graph
-
-=head1 SYNOPSIS
-
-use GD::Graph::colour qw(:colours :lists :files :convert);
-
-=head1 DESCRIPTION
-
-The B<GD::Graph::colour> package provides a few routines to work with
-colours. The functionality of this package is mainly defined by what is
-needed, now and historically, by the GD::Graph modules.
-
-=cut
-
-use vars qw( @EXPORT_OK %EXPORT_TAGS );
-use strict;
-require Exporter;
-use Carp;
-
-@GD::Graph::colour::ISA = qw( Exporter );
-
-@EXPORT_OK = qw(
- _rgb _luminance _hue add_colour
- colour_list sorted_colour_list
- read_rgb
- hex2rgb rgb2hex
-);
-%EXPORT_TAGS = (
- colours => [qw( add_colour _rgb _luminance _hue )],
- lists => [qw( colour_list sorted_colour_list )],
- files => [qw( read_rgb )],
- convert => [qw( hex2rgb rgb2hex )],
-);
-
-my %RGB = (
- white => [0xFF,0xFF,0xFF],
- lgray => [0xBF,0xBF,0xBF],
- gray => [0x7F,0x7F,0x7F],
- dgray => [0x3F,0x3F,0x3F],
- black => [0x00,0x00,0x00],
- lblue => [0x00,0x00,0xFF],
- blue => [0x00,0x00,0xBF],
- dblue => [0x00,0x00,0x7F],
- gold => [0xFF,0xD7,0x00],
- lyellow => [0xFF,0xFF,0x00],
- yellow => [0xBF,0xBF,0x00],
- dyellow => [0x7F,0x7F,0x00],
- lgreen => [0x00,0xFF,0x00],
- green => [0x00,0xBF,0x00],
- dgreen => [0x00,0x7F,0x00],
- lred => [0xFF,0x00,0x00],
- red => [0xBF,0x00,0x00],
- dred => [0x7F,0x00,0x00],
- lpurple => [0xFF,0x00,0xFF],
- purple => [0xBF,0x00,0xBF],
- dpurple => [0x7F,0x00,0x7F],
- lorange => [0xFF,0xB7,0x00],
- orange => [0xFF,0x7F,0x00],
- pink => [0xFF,0xB7,0xC1],
- dpink => [0xFF,0x69,0xB4],
- marine => [0x7F,0x7F,0xFF],
- cyan => [0x00,0xFF,0xFF],
- lbrown => [0xD2,0xB4,0x8C],
- dbrown => [0xA5,0x2A,0x2A],
-);
-
-=head1 FUNCTIONS
-
-=head2 colour_list( I<number of colours> )
-
-Returns a list of I<number of colours> colour names known to the package.
-Exported with the :lists tag.
-
-=cut
-
-sub colour_list
-{
- my $n = ( $_[0] ) ? $_[0] : keys %RGB;
- return (keys %RGB)[0 .. $n-1];
-}
-
-=head2 sorted_colour_list( I<number of colours> )
-
-Returns a list of I<number of colours> colour names known to the package,
-sorted by luminance or hue.
-B<NB.> Right now it always sorts by luminance. Will add an option in a later
-stage to decide sorting method at run time.
-Exported with the :lists tag.
-
-=cut
-
-sub sorted_colour_list
-{
- my $n = $_[0] ? $_[0] : keys %RGB;
- return (sort by_luminance keys %RGB)[0 .. $n-1];
- # return (sort by_hue keys %rgb)[0..$n-1];
-
- sub by_luminance { _luminance(@{$RGB{$b}}) <=> _luminance(@{$RGB{$a}}) }
- sub by_hue { _hue(@{$RGB{$b}}) <=> _hue(@{$RGB{$a}}) }
-}
-
-=head2 _rgb( I<colour name> )
-
-Returns a list of the RGB values of I<colour name>. if the colour name
-is a string of the form that is acceptable to the hex2rgb sub, then the
-colour will be added to the list dynamically.
-Exported with the :colours tag.
-
-=cut
-
-my %warned_clrs = ();
-
-# return the RGB values of the colour name
-sub _rgb
-{
- my $clr = shift or return;
-
- # Try adding the colour if it doesn't exist yet. It may be of a
- # parseable form
- add_colour($clr) unless exists $RGB{$clr};
-
- my $rgb_ref = $RGB{$clr};
- if (!defined $rgb_ref)
- {
- $rgb_ref = $RGB{'black'};
- unless ($warned_clrs{$clr})
- {
- $warned_clrs{$clr}++;
- carp "Colour $clr is not defined, reverting to black";
- }
- };
-
- @{$rgb_ref};
-}
-
-=head2 _hue( I<R,G,B> )
-
-Returns the hue of the colour with the specified RGB values.
-Exported with the :colours tag.
-
-=head2 _luminance( I<R,G,B> )
-
-Returns the luminance of the colour with the specified RGB values.
-Exported with the :colours tag.
-
-=cut
-
-# return the luminance of the colour (RGB)
-sub _luminance
-{
- (0.212671 * $_[0] + 0.715160 * $_[1] + 0.072169 * $_[2])/0xFF
-}
-
-# return the hue of the colour (RGB)
-sub _hue
-{
- ($_[0] + $_[1] + $_[2])/(3 * 0xFF)
-}
-
-=head2 add_colour(colourname => [$r, $g, $b]) or
-add_colour('#7fe310')
-
-Self-explanatory.
-Exported with the :colours tag.
-
-=cut
-
-sub add_colour
-{
- my $name = shift;
- my $val = shift;
-
- if (!defined $val)
- {
- my @rgb = hex2rgb($name) or return;
- $val = [@rgb];
- }
-
- if (ref $val && ref $val eq 'ARRAY')
- {
- $RGB{$name} = [@{$val}];
- return $name;
- }
-
- return;
-}
-
-=head2 rgb2hex($red, $green, $blue)
-
-=head2 hex2rgb('#7fe310')
-
-These functions translate a list of RGB values into a hexadecimal
-string, as is commonly used in HTML and the Image::Magick API, and vice
-versa.
-Exported with the :convert tag.
-
-=cut
-
-# Color translation
-sub rgb2hex
-{
- return unless @_ == 3;
- my $color = '#';
- foreach my $cc (@_)
- {
- $color .= sprintf("%02x", $cc);
- }
- return $color;
-}
-
-sub hex2rgb
-{
- my $clr = shift;
- my @rgb = $clr =~ /^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i;
- return unless @rgb;
- return map { hex $_ } @rgb;
-}
-
-=head2 read_rgb( F<file name> )
-
-Reads in colours from a rgb file as used by the X11 system.
-
-Doing something like:
-
- use GD::Graph::bars;
- use GD::Graph::colour;
-
- GD::Graph::colour::read_rgb("rgb.txt") or die "cannot read colours";
-
-Will allow you to use any colours defined in rgb.txt in your graph.
-Exported with the :files tag.
-
-=cut
-
-#
-# Read a rgb.txt file (X11)
-#
-# Expected format of the file:
-#
-# R G B colour name
-#
-# Fields can be separated by any number of whitespace
-# Lines starting with an exclamation mark (!) are comment and
-# will be ignored.
-#
-# returns number of colours read
-
-sub read_rgb($) # (filename)
-{
- my $fn = shift;
- my $n = 0;
- my $line;
-
- open(RGB, $fn) or return 0;
-
- while (defined($line = <RGB>))
- {
- next if ($line =~ /\s*!/);
- chomp($line);
-
- # remove leading white space
- $line =~ s/^\s+//;
-
- # get the colours
- my ($r, $g, $b, $name) = split(/\s+/, $line, 4);
-
- # Ignore bad lines
- next unless (defined $name);
-
- $RGB{$name} = [$r, $g, $b];
- $n++;
- }
-
- close(RGB);
-
- return $n;
-}
-
-sub version { $GD::Graph::colour::VERSION }
-
-sub dump_colours
-{
- my $max = $_[0] ? $_[0] : keys %RGB;
- my $n = 0;
-
- my $clr;
- foreach $clr (sorted_colour_list($max))
- {
- last if $n > $max;
- print "colour: $clr, " .
- "${$RGB{$clr}}[0], ${$RGB{$clr}}[1], ${$RGB{$clr}}[2]\n"
- }
-}
-
-
-"Just another true value";
-
-__END__
-
-=head1 PREDEFINED COLOUR NAMES
-
-white,
-lgray,
-gray,
-dgray,
-black,
-lblue,
-blue,
-dblue,
-gold,
-lyellow,
-yellow,
-dyellow,
-lgreen,
-green,
-dgreen,
-lred,
-red,
-dred,
-lpurple,
-purple,
-dpurple,
-lorange,
-orange,
-pink,
-dpink,
-marine,
-cyan,
-lbrown,
-dbrown.
-
-=head1 AUTHOR
-
-Martien Verbruggen E<lt>mgjv@tradingpost.com.auE<gt>
-
-=head2 Copyright
-
-GIFgraph: Copyright (c) 1995-1999 Martien Verbruggen.
-Chart::PNGgraph: Copyright (c) 1999 Steve Bonds.
-GD::Graph: Copyright (c) 1999 Martien Verbruggen.
-
-All rights reserved. This package is free software; you can redistribute
-it and/or modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<GD::Graph>,
-L<GD::Graph::FAQ>
-
diff --git a/lib/GD/Graph/cylinder.pm b/lib/GD/Graph/cylinder.pm
deleted file mode 100644
index ba8ab86..0000000
--- a/lib/GD/Graph/cylinder.pm
+++ /dev/null
@@ -1,126 +0,0 @@
-# $File: //depot/RG/rg/lib/RG/lib/GD/Graph/cylinder.pm $ $Author: autrijus $
-# $Revision: #3 $ $Change: 370 $ $DateTime: 2002/07/17 20:38:38 $
-
-package GD::Graph::cylinder;
-
-use strict;
-
-use GD::Graph::axestype3d;
-use GD::Graph::utils qw(:all);
-use GD::Graph::colour qw(:colours);
-
-use base qw/GD::Graph::bars3d/;
-$GD::Graph::cylinder::VERSION = '0.63';
-
-my %Defaults = (
- # Spacing between the bars
- bar_spacing => 0,
-
- # The 3-d extrusion depth of the bars
- bar_depth => 10,
-);
-
-sub initialise
-{
- my $self = shift;
-
- my $rc = $self->SUPER::initialise();
- $self->set(correct_width => 1);
-
- while( my($key, $val) = each %Defaults ) {
- $self->{$key} = $val
- } # end while
-
- return $rc;
-} # end initialise
-
-sub draw_bar_h {
- my $self = shift;
- my $g = shift;
- my( $l, $t, $r, $b, $dsci, $brci, $neg ) = @_;
- my $fnord = $g->colorAllocate(0,0,0);
-
- my $depth = $self->{bar_depth};
-
- my ($lighter, $darker) = ($dsci, $dsci);
- if ($self->{'3d_shading'}) {
- $lighter = $self->{'3d_highlights'}[$dsci];
- $darker = $self->{'3d_shadows'}[$dsci];
- }
- $g->line($l+$depth, $t+1, $r+$depth, $t+1, $dsci);
- $g->line($l+$depth, $b, $r+$depth, $b, $dsci);
- $g->arc($r+$depth, ($t+$b)/2, $depth*2, ($b-$t), 270, 90, $dsci);
- $g->arc($l+$depth, ($t+$b)/2, $depth*2, ($b-$t), 90, 270, $dsci);
- # find border
- my $foo = $l+$depth;
- --$foo
- until $foo == $l || $g->getPixel($foo, $t+($b-$t)/5) == $dsci;
- my $bar = $foo+1;
- ++$bar
- until $bar == $foo || $g->getPixel($bar, $t+($b-$t)/5) == $dsci;
- $g->line($foo, $t+($b-$t)/5, $bar, $t+($b-$t)/5, $dsci);
- $g->line($foo, $b-($b-$t)/5, $bar, $b-($b-$t)/5, $dsci);
- $g->fillToBorder($l+$depth, ($t+$b)/2, $dsci, $dsci);
- $g->arc($l+$depth, ($b+$t)/2, $depth*2, ($b-$t), 90, 270, $dsci);
- if ($foo < $bar + 3) {
- $g->fillToBorder(($l+$r)/2+$depth, $t+($b-$t)/5-1, $dsci, $lighter)
- unless $g->getPixel(($l+$r)/2+$depth, $t+($b-$t)/5-1) == $dsci;
- $g->fillToBorder(($l+$r)/2+$depth, $b-($b-$t)/5+1, $dsci, $darker)
- unless $g->getPixel(($l+$r)/2+$depth, $b-($b-$t)/5+1) == $dsci;
- $g->fillToBorder(($l+$r)/2, ($t+$b)/2, $dsci, $dsci);
- }
- $g->arc($l+$depth, ($b+$t)/2, $depth*2, ($b-$t), 90, 270, $brci);
- $g->arc($r+$depth, ($b+$t)/2, $depth*2, ($b-$t), 0, 360, $brci);
- $g->line($l+$depth, $t+1, $r+$depth, $t+1, $brci);
- $g->line($l+$depth, $b, $r+$depth, $b, $brci);
- $g->fillToBorder($r+$depth, ($b+$t)/2, $brci, $dsci);
-}
-
-sub draw_bar {
- my $self = shift;
- return $self->draw_bar_h(@_) if $self->{rotate_chart};
- my $g = shift;
- my( $l, $t, $r, $b, $dsci, $brci, $neg ) = @_;
- my $fnord = $g->colorAllocate(0,0,0);
-
- my $depth = $self->{bar_depth};
-
- my ($lighter, $darker) = ($dsci, $dsci);
- if ($self->{'3d_shading'}) {
- $lighter = $self->{'3d_highlights'}[$dsci];
- $darker = $self->{'3d_shadows'}[$dsci];
- }
-
- $g->line($l+1, $t-$depth, $l+1, $b-$depth, $dsci);
- $g->line($r, $t-$depth, $r, $b-$depth, $dsci);
-
- $g->arc(($l+$r)/2, $t-$depth, ($r-$l), $depth*2, 180, 360, $dsci);
- $g->arc(($l+$r)/2, $b-$depth, ($r-$l), $depth*2, 0, 180, $dsci);
- # find border
- my $foo = $b-$depth+1;
- ++$foo
- until $foo == $b || $g->getPixel($l+($r-$l)/5,$foo) == $dsci;
- my $bar = $foo-1;
- --$bar
- until $bar == $foo || $g->getPixel($l+($r-$l)/5,$bar) == $dsci;
- $g->line($l+($r-$l)/5, $bar, $l+($r-$l)/5, $foo, $dsci);
- $g->line($r-($r-$l)/5, $bar, $r-($r-$l)/5, $foo, $dsci);
- $g->fillToBorder(($l+$r)/2, $t-$depth, $dsci, $dsci);
- $g->arc(($l+$r)/2, $b-$depth, ($r-$l), $depth*2, 0, 180, $dsci);
- if ($foo > $bar + 3) {
- $g->fillToBorder($l+($r-$l)/5-1, ($foo+$bar)/2, $dsci, $lighter)
- unless $g->getPixel($l+($r-$l)/5-1, ($foo+$bar)/2) == $dsci;
- $g->fillToBorder($r-($r-$l)/5+1, ($foo+$bar)/2, $dsci, $darker)
- unless $g->getPixel($r-($r-$l)/5+1, ($foo+$bar)/2) == $dsci;
- $g->fillToBorder(($l+$r)/2, ($t+$b)/2, $dsci, $dsci);
- }
- $g->arc(($l+$r)/2, $b-$depth, ($r-$l), $depth*2, 0, 180, $brci);
- $g->arc(($l+$r)/2, $t-$depth, ($r-$l), $depth*2, 0, 360, $brci);
- $g->line($l+1, $t-$depth, $l+1, $b-$depth, $brci);
- $g->line($r, $t-$depth, $r, $b-$depth, $brci);
- $g->fillToBorder(($l+$r)/2, $t-$depth, $brci, $dsci);
-}
-
-1;
-
-
diff --git a/lib/GD/Graph/cylinder3d.pm b/lib/GD/Graph/cylinder3d.pm
deleted file mode 100644
index 7bc2490..0000000
--- a/lib/GD/Graph/cylinder3d.pm
+++ /dev/null
@@ -1,30 +0,0 @@
-############################################################
-#
-# Module: GD::Graph::cylinder3d
-#
-# Description:
-# This is merely a wrapper around GD::Graph::cylinder
-# to be used as an alias
-#
-# Created: 16 October 2002 by Jeremy Wadsack for Wadsack-Allen Digital Group
-# Copyright (C) 2002 Wadsack-Allen. All rights reserved.
-############################################################
-# Date Modification Author
-# ----------------------------------------------------------
-# #
-############################################################
-package GD::Graph::cylinder3d;
-
-use strict;
-use GD;
-use GD::Graph;
-use GD::Graph::cylinder;
-use Carp;
-
-@GD::Graph::cylinder3d::ISA = qw( GD::Graph::cylinder );
-$GD::Graph::cylinder3d::VERSION = '0.63';
-
-# Inherit everything from GD::Graph::cylinder
-
-
-1;
diff --git a/lib/GD/Graph/hbars.pm b/lib/GD/Graph/hbars.pm
deleted file mode 100644
index e2268b5..0000000
--- a/lib/GD/Graph/hbars.pm
+++ /dev/null
@@ -1,71 +0,0 @@
-#==========================================================================
-# Copyright (c) 1995-1998 Martien Verbruggen
-#--------------------------------------------------------------------------
-#
-# Name:
-# GD::Graph::hbars.pm
-#
-# $Id: hbars.pm,v 1.3 2003/02/10 22:12:41 mgjv Exp $
-#
-#==========================================================================
-
-package GD::Graph::hbars;
-
-($GD::Graph::hbars::VERSION) = '$Revision: 1.3 $' =~ /\s([.\d]+)/;
-
-use strict;
-
-use GD::Graph::bars;
-use GD::Graph::utils qw(:all);
-use GD::Graph::colour qw(:colours);
-
-@GD::Graph::hbars::ISA = qw(GD::Graph::bars);
-
-sub initialise
-{
- my $self = shift;
- $self->SUPER::initialise();
- $self->set(rotate_chart => 1);
-}
-
-"Just another true value";
-
-__END__
-
-=head1 NAME
-
-GD::Graph::hbars - make bar graphs with horizontal bars
-
-=head1 SYNOPSIS
-
-use GD::Graph::hbars;
-
-=head1 DESCRIPTION
-
-This is a wrapper module which is completely identical to creating a
-GD::Graph::bars object with the C<rotate_chart> attribute set to a true
-value.
-
-=head1 SEE ALSO
-
-L<GD::Graph>
-
-=head1 AUTHOR
-
-Martien Verbruggen E<lt>mgjv@tradingpost.com.auE<gt>
-
-=head2 Copyright
-
-(c) Martien Verbruggen
-
-=head2 Acknowledgements
-
-The original author of most of the code needed to implement this was
-brian d foy, who sent this module to me after I complained I didn't have
-the time to implement horizontal bar charts. I took the code that lived
-in here, and distributed it over axestype.pm and bars.pm, to allow for a
-better integration all around. His code, in turn, was mainly based on an
-earlier version of bars.pm and axestype.pm.
-
-=cut
-
diff --git a/lib/GD/Graph/lines.pm b/lib/GD/Graph/lines.pm
deleted file mode 100644
index 2dac4dd..0000000
--- a/lib/GD/Graph/lines.pm
+++ /dev/null
@@ -1,182 +0,0 @@
-#==========================================================================
-# Copyright (c) 1995-1998 Martien Verbruggen
-#--------------------------------------------------------------------------
-#
-# Name:
-# GD::Graph::lines.pm
-#
-# $Id: lines.pm,v 1.15 2003/02/10 22:12:41 mgjv Exp $
-#
-#==========================================================================
-
-package GD::Graph::lines;
-
-($GD::Graph::lines::VERSION) = '$Revision: 1.15 $' =~ /\s([\d.]+)/;
-
-use strict;
-
-use GD;
-use GD::Graph::axestype;
-
-@GD::Graph::lines::ISA = qw( GD::Graph::axestype );
-
-# PRIVATE
-
-sub draw_data_set
-{
- my $self = shift;
- my $ds = shift;
-
- my @values = $self->{_data}->y_values($ds) or
- return $self->_set_error("Impossible illegal data set: $ds",
- $self->{_data}->error);
-
- my $dsci = $self->set_clr($self->pick_data_clr($ds) );
- my $type = $self->pick_line_type($ds);
-
- my ($xb, $yb);
- if (defined $values[0])
- {
- if (defined($self->{x_min_value}) && defined($self->{x_max_value}))
- {
- ($xb, $yb) =
- $self->val_to_pixel($self->{_data}->get_x(0), $values[0], $ds);
- }
- else
- {
- ($xb, $yb) = $self->val_to_pixel(1, $values[0], $ds);
- }
- }
-
- for (my $i = 0; $i < @values; $i++)
- {
- if (!defined $values[$i])
- {
- ($xb, $yb) = () if $self->{skip_undef};
- next;
- }
-
- my ($xe, $ye);
-
- if (defined($self->{x_min_value}) && defined($self->{x_max_value}))
- {
- ($xe, $ye) = $self->val_to_pixel(
- $self->{_data}->get_x($i), $values[$i], $ds);
- }
- else
- {
- ($xe, $ye) = $self->val_to_pixel($i+1, $values[$i], $ds);
- }
-
- if (defined $xb)
- {
- $self->draw_line($xb, $yb, $xe, $ye, $type, $dsci)
- if defined $dsci;
- $self->{_hotspots}->[$ds]->[$i] =
- ['line', $xb, $yb, $xe, $ye, $self->{line_width}];
- }
- ($xb, $yb) = ($xe, $ye);
- }
-
- return $ds;
-}
-
-sub pick_line_type
-{
- my $self = shift;
- my $num = shift;
-
- ref $self->{line_types} ?
- $self->{line_types}[ $num % (1 + $#{$self->{line_types}}) - 1 ] :
- $num % 4 ? $num % 4 : 4
-}
-
-sub draw_line # ($xs, $ys, $xe, $ye, $type, $colour_index)
-{
- my $self = shift;
- my ($xs, $ys, $xe, $ye, $type, $clr) = @_;
-
- my $lw = $self->{line_width};
- my $lts = $self->{line_type_scale};
-
- my $style = gdStyled;
- my @pattern = ();
-
- LINE: {
-
- ($type == 2) && do {
- # dashed
-
- for (1 .. $lts) { push @pattern, $clr }
- for (1 .. $lts) { push @pattern, gdTransparent }
-
- $self->{graph}->setStyle(@pattern);
-
- last LINE;
- };
-
- ($type == 3) && do {
- # dotted,
-
- for (1 .. 2) { push @pattern, $clr }
- for (1 .. 2) { push @pattern, gdTransparent }
-
- $self->{graph}->setStyle(@pattern);
-
- last LINE;
- };
-
- ($type == 4) && do {
- # dashed and dotted
-
- for (1 .. $lts) { push @pattern, $clr }
- for (1 .. 2) { push @pattern, gdTransparent }
- for (1 .. 2) { push @pattern, $clr }
- for (1 .. 2) { push @pattern, gdTransparent }
-
- $self->{graph}->setStyle(@pattern);
-
- last LINE;
- };
-
- # default: solid
- $style = $clr;
- }
-
- # Tried the line_width thing with setBrush, ugly results
- # TODO: This loop probably should be around the datasets
- # for nicer results
- my $i;
- for $i (1..$lw)
- {
- my $yslw = $ys + int($lw/2) - $i;
- my $yelw = $ye + int($lw/2) - $i;
-
- # Need the setstyle to reset
- $self->{graph}->setStyle(@pattern) if (@pattern);
- $self->{graph}->line( $xs, $yslw, $xe, $yelw, $style );
- }
-}
-
-sub draw_legend_marker # (data_set_number, x, y)
-{
- my $self = shift;
- my ($n, $x, $y) = @_;
-
- my $ci = $self->set_clr($self->pick_data_clr($n));
- return unless defined $ci;
- my $type = $self->pick_line_type($n);
-
- $y += int($self->{lg_el_height}/2);
-
- # Joe Smith <jms@tardis.Tymnet.COM>
- local($self->{line_width}) = 2; # Make these show up better
-
- $self->draw_line(
- $x, $y,
- $x + $self->{legend_marker_width}, $y,
- $type, $ci
- );
-}
-
-"Just another true value";
diff --git a/lib/GD/Graph/lines3d.pm b/lib/GD/Graph/lines3d.pm
deleted file mode 100644
index dfd60c7..0000000
--- a/lib/GD/Graph/lines3d.pm
+++ /dev/null
@@ -1,522 +0,0 @@
-#==========================================================================
-# Module: GD::Graph::lines3d
-#
-# Copyright (C) 1999,2001 Wadsack-Allen. All Rights Reserved.
-#
-# Based on GD::Graph::lines.pm,v 1.10 2000/04/15 mgjv
-# Copyright (c) 1995-1998 Martien Verbruggen
-#
-#--------------------------------------------------------------------------
-# Date Modification Author
-# -------------------------------------------------------------------------
-# 1999SEP18 Created 3D line chart class (this module) JAW
-# 1999SEP19 Finished overwrite 1 style JAW
-# 1999SEP19 Polygon'd linewidth rendering JAW
-# 2000SEP19 Converted to a GD::Graph class JAW
-# 2000APR18 Modified for compatibility with GD::Graph 1.30 JAW
-# 2000APR24 Fixed a lot of rendering bugs JAW
-# 2000AUG19 Changed render code so lines have consitent width JAW
-# 2000AUG21 Added 3d shading JAW
-# 2000AUG24 Fixed shading top/botttom vs. postive/negative slope JAW
-# 2000SEP04 For single point "lines" made a short segment JAW
-# 2000OCT09 Fixed bug in rendering of legend JAW
-#==========================================================================
-# TODO
-# ** The new mitred corners don't work well at data anomlies. Like
-# the set (0,0,1,0,0,0,1,0,1) Looks really wrong!
-# * Write a draw_data_set that draws the line so they appear to pass
-# through one another. This means drawing a border edge at each
-# intersection of the data lines so the points of pass-through show.
-# Probably want to draw all filled polygons, then run through the data
-# again finding intersections of line segments and drawing those edges.
-#==========================================================================
-package GD::Graph::lines3d;
-
-use strict;
-
-use GD;
-use GD::Graph::axestype3d;
-use Data::Dumper;
-
-@GD::Graph::lines3d::ISA = qw( GD::Graph::axestype3d );
-$GD::Graph::lines3d::VERSION = '0.63';
-
-my $PI = 4 * atan2(1, 1);
-
-my %Defaults = (
- # The depth of the line in their extrusion
-
- line_depth => 10,
-);
-
-sub initialise()
-{
- my $self = shift;
-
- my $rc = $self->SUPER::initialise();
-
- while( my($key, $val) = each %Defaults ) {
- $self->{$key} = $val
-
- # *** [JAW]
- # Should we reset the depth_3d param based on the
- # line_depth, numsets and overwrite parameters, here?
- #
- } # end while
-
- return $rc;
-
-} # end initialize
-
-sub set
-{
- my $s = shift;
- my %args = @_;
-
- $s->{_set_error} = 0;
-
- for (keys %args)
- {
- /^line_depth$/ and do
- {
- $s->{line_depth} = $args{$_};
- delete $args{$_};
- next;
- };
- }
-
- return $s->SUPER::set(%args);
-} # end set
-
-# PRIVATE
-
-# [JAW] Changed to draw_data intead of
-# draw_data_set to allow better control
-# of multiple set rendering
-sub draw_data
-{
- my $self = shift;
- my $d = $self->{_data};
- my $g = $self->{graph};
-
- $self->draw_data_overwrite( $g, $d );
-
- # redraw the 'zero' axis, front and right
- if( $self->{zero_axis} ) {
- $g->line(
- $self->{left}, $self->{zeropoint},
- $self->{right}, $self->{zeropoint},
- $self->{fgci} );
- $g->line(
- $self->{right}, $self->{zeropoint},
- $self->{right} + $self->{depth_3d}, $self->{zeropoint} - $self->{depth_3d},
- $self->{fgci} );
- } # end if
-
- # redraw the box face
- if ( $self->{box_axis} ) {
- # Axes box
- $g->rectangle($self->{left}, $self->{top}, $self->{right}, $self->{bottom}, $self->{fgci});
- $g->line($self->{right}, $self->{top}, $self->{right} + $self->{depth_3d}, $self->{top} - $self->{depth_3d}, $self->{fgci});
- $g->line($self->{right}, $self->{bottom}, $self->{right} + $self->{depth_3d}, $self->{bottom} - $self->{depth_3d}, $self->{fgci});
- } # end if
-
- return $self;
-
-} # end draw_data
-
-# Copied from MVERB source
-sub pick_line_type
-{
- my $self = shift;
- my $num = shift;
-
- ref $self->{line_types} ?
- $self->{line_types}[ $num % (1 + $#{$self->{line_types}}) - 1 ] :
- $num % 4 ? $num % 4 : 4
-}
-
-# ----------------------------------------------------------
-# Sub: draw_data_overwrite
-#
-# Args: $gd
-# $gd The GD object to draw on
-#
-# Description: Draws each line segment for each set. Runs
-# over sets, then points so that the appearance is better.
-# ----------------------------------------------------------
-# Date Modification Author
-# ----------------------------------------------------------
-# 19SEP1999 Added this for overwrite support. JW
-# 20AUG2000 Changed structure to use points 'objects' JW
-# ----------------------------------------------------------
-sub draw_data_overwrite {
- my $self = shift;
- my $g = shift;
- my @points_cache;
-
- my $i;
- for $i (0 .. $self->{_data}->num_points())
- {
- my $j;
- for $j (1 .. $self->{_data}->num_sets())
- {
- my @values = $self->{_data}->y_values($j) or
- return $self->_set_error( "Impossible illegal data set: $j", $self->{_data}->error );
-
- if( $self->{_data}->num_points() == 1 && $i == 1 ) {
- # Copy the first point to the "second"
- $values[$i] = $values[0];
- } # end if
-
- next unless defined $values[$i];
-
- # calculate offset of this line
- # *** Should offset be the max of line_depth
- # and depth_3d/numsets? [JAW]
- #
- my $offset = $self->{line_depth} * ($self->{_data}->num_sets() - $j);
-
- # Get the coordinates of the previous point, if this is the first
- # point make a point object and start over (i.e. next;)
- unless( $i ) {
- my( $xb, $yb );
- if (defined($self->{x_min_value}) && defined($self->{x_max_value})) {
- ($xb, $yb) = $self->val_to_pixel( $self->{_data}->get_x($i), $values[$i], $j );
- } else {
- ($xb, $yb) = $self->val_to_pixel( $i + 1, $values[$i], $j );
- } # end if
- $xb += $offset;
- $yb -= $offset;
- $points_cache[$i][$j] = { coords => [$xb, $yb] };
- next;
- } # end unless
-
- # Pick a data colour, calc shading colors too, if requested
- my( @rgb ) = $self->pick_data_clr( $j );
- my $dsci = $self->set_clr( @rgb );
- if( $self->{'3d_shading'} ) {
- $self->{'3d_highlights'}[$dsci] = $self->set_clr( $self->_brighten( @rgb ) );
- $self->{'3d_shadows'}[$dsci] = $self->set_clr( $self->_darken( @rgb ) );
- } # end if
-
- # Get the type
- my $type = $self->pick_line_type($j);
-
- # Get the coordinates of the this point
- unless( ref $points_cache[$i][$j] ) {
- my( $xe, $ye );
- if( defined($self->{x_min_value}) && defined($self->{x_max_value}) ) {
- ( $xe, $ye ) = $self->val_to_pixel( $self->{_data}->get_x($i), $values[$i], $j );
- } else {
- ( $xe, $ye ) = $self->val_to_pixel($i + 1, $values[$i], $j);
- } # end if
- $xe += $offset;
- $ye -= $offset;
- $points_cache[$i][$j] = { coords => [$xe, $ye] };
- } # end if
-
- # Find the coordinates of the next point
- if( defined $values[$i + 1] ) {
- my( $xe, $ye );
- if( defined($self->{x_min_value}) && defined($self->{x_max_value}) ) {
- ( $xe, $ye ) = $self->val_to_pixel( $self->{_data}->get_x($i + 1), $values[$i + 1], $j );
- } else {
- ( $xe, $ye ) = $self->val_to_pixel($i + 2, $values[$i + 1], $j);
- } # end if
- $xe += $offset;
- $ye -= $offset;
- $points_cache[$i + 1][$j] = { coords => [$xe, $ye] };
- } # end if
-
- if( $self->{_data}->num_points() == 1 && $i == 1 ) {
- # Nudge the x coords back- and forwards
- my $n = int(($self->{right} - $self->{left}) / 30);
- $n = 2 if $n < 2;
- $points_cache[$i][$j]{coords}[0] = $points_cache[$i - 1][$j]{coords}[0] + $n;
- $points_cache[$i - 1][$j]{coords}[0] -= $n;
- } # end if
-
- # Draw the line segment
- $self->draw_line( $points_cache[$i - 1][$j],
- $points_cache[$i][$j],
- $points_cache[$i + 1][$j],
- $type,
- $dsci );
-
- # Draw the end cap if last segment
- if( $i >= $self->{_data}->num_points() - 1 ) {
- my $poly = new GD::Polygon;
- $poly->addPt( $points_cache[$i][$j]{face}[0], $points_cache[$i][$j]{face}[1] );
- $poly->addPt( $points_cache[$i][$j]{face}[2], $points_cache[$i][$j]{face}[3] );
- $poly->addPt( $points_cache[$i][$j]{face}[2] + $self->{line_depth}, $points_cache[$i][$j]{face}[3] - $self->{line_depth} );
- $poly->addPt( $points_cache[$i][$j]{face}[0] + $self->{line_depth}, $points_cache[$i][$j]{face}[1] - $self->{line_depth} );
- if( $self->{'3d_shading'} ) {
- $g->filledPolygon( $poly, $self->{'3d_shadows'}[$dsci] );
- } else {
- $g->filledPolygon( $poly, $dsci );
- } # end if
- $g->polygon( $poly, $self->{fgci} );
- } # end if
-
- } # end for -- $self->{_data}->num_sets()
- } # end for -- $self->{_data}->num_points()
-
-} # end sub draw_data_overwrite
-
-# ----------------------------------------------------------
-# Sub: draw_line
-#
-# Args: $prev, $this, $next, $type, $clr
-# $prev A hash ref for the prev point's object
-# $this A hash ref for this point's object
-# $next A hash ref for the next point's object
-# $type A predefined line type (2..4) = (dashed, dotted, dashed & dotted)
-# $clr The color (colour) index to use for the fill
-#
-# Point "Object" has these properties:
-# coords A 2 element array of the coordinates for the line
-# (this should be filled in before calling)
-# face An 4 element array of end points for the face
-# polygon. This will be populated by this method.
-#
-# Description: Draws a line segment in 3d extrusion that
-# connects the prev point the the this point. The next point
-# is used to calculate the mitre at the joint.
-# ----------------------------------------------------------
-# Date Modification Author
-# ----------------------------------------------------------
-# 18SEP1999 Modified MVERB source to work on data
-# point, not data set for better rendering JAW
-# 19SEP1999 Ploygon'd line rendering for better effect JAW
-# 19AUG2000 Made line width perpendicular JAW
-# 19AUG2000 Changed parameters to use %line_seg hash/obj JAW
-# 20AUG2000 Mitred joints of line segments JAW
-# ----------------------------------------------------------
-sub draw_line
-{
- my $self = shift;
- my( $prev, $this, $next, $type, $clr ) = @_;
- my $xs = $prev->{coords}[0];
- my $ys = $prev->{coords}[1];
- my $xe = $this->{coords}[0];
- my $ye = $this->{coords}[1];
-
- my $lw = $self->{line_width};
- my $lts = $self->{line_type_scale};
-
- my $style = gdStyled;
- my @pattern = ();
-
- LINE: {
-
- ($type == 2) && do {
- # dashed
-
- for (1 .. $lts) { push @pattern, $clr }
- for (1 .. $lts) { push @pattern, gdTransparent }
-
- $self->{graph}->setStyle(@pattern);
-
- last LINE;
- };
-
- ($type == 3) && do {
- # dotted,
-
- for (1 .. 2) { push @pattern, $clr }
- for (1 .. 2) { push @pattern, gdTransparent }
-
- $self->{graph}->setStyle(@pattern);
-
- last LINE;
- };
-
- ($type == 4) && do {
- # dashed and dotted
-
- for (1 .. $lts) { push @pattern, $clr }
- for (1 .. 2) { push @pattern, gdTransparent }
- for (1 .. 2) { push @pattern, $clr }
- for (1 .. 2) { push @pattern, gdTransparent }
-
- $self->{graph}->setStyle(@pattern);
-
- last LINE;
- };
-
- # default: solid
- $style = $clr;
- }
-
- # [JAW] Removed the dataset loop for better results.
-
- # Need the setstyle to reset
- $self->{graph}->setStyle(@pattern) if (@pattern);
-
- #
- # Find the x and y offsets for the edge of the front face
- # Do this by adjusting them perpendicularly from the line
- # half the line width in front and in back.
- #
- my( $lwyoff, $lwxoff );
- if( $xe == $xs ) {
- $lwxoff = $lw / 2;
- $lwyoff = 0;
- } elsif( $ye == $ys ) {
- $lwxoff = 0;
- $lwyoff = $lw / 2;
- } else {
- my $ln = sqrt( ($ys-$ye)**2 + ($xe-$xs)**2 );
- $lwyoff = ($xe-$xs) / $ln * $lw / 2;
- $lwxoff = ($ys-$ye) / $ln * $lw / 2;
- } # end if
-
- # For first line, figure beginning point
- unless( defined $prev->{face}[0] ) {
- $prev->{face} = [];
- $prev->{face}[0] = $xs - $lwxoff;
- $prev->{face}[1] = $ys - $lwyoff;
- $prev->{face}[2] = $xs + $lwxoff;
- $prev->{face}[3] = $ys + $lwyoff;
- } # end unless
-
- # Calc and store this point's face coords
- unless( defined $this->{face}[0] ) {
- $this->{face} = [];
- $this->{face}[0] = $xe - $lwxoff;
- $this->{face}[1] = $ye - $lwyoff;
- $this->{face}[2] = $xe + $lwxoff;
- $this->{face}[3] = $ye + $lwyoff;
- } # end if
-
- # Now find next point and nudge these coords to mitre
- if( ref $next->{coords} eq 'ARRAY' ) {
- my( $lwyo2, $lwxo2 );
- my( $x2, $y2 ) = @{$next->{coords}};
- if( $x2 == $xe ) {
- $lwxo2 = $lw / 2;
- $lwyo2 = 0;
- } elsif( $y2 == $ye ) {
- $lwxo2 = 0;
- $lwyo2 = $lw / 2;
- } else {
- my $ln2 = sqrt( ($ye-$y2)**2 + ($x2-$xe)**2 );
- $lwyo2 = ($x2-$xe) / $ln2 * $lw / 2;
- $lwxo2 = ($ye-$y2) / $ln2 * $lw / 2;
- } # end if
- $next->{face} = [];
- $next->{face}[0] = $x2 - $lwxo2;
- $next->{face}[1] = $y2 - $lwyo2;
- $next->{face}[2] = $x2 + $lwxo2;
- $next->{face}[3] = $y2 + $lwyo2;
-
- # Now get the intersecting coordinates
- my $mt = ($ye - $ys)/($xe - $xs);
- my $mn = ($y2 - $ye)/($x2 - $xe);
- my $bt = $this->{face}[1] - $this->{face}[0] * $mt;
- my $bn = $next->{face}[1] - $next->{face}[0] * $mn;
- if( $mt != $mn ) {
- $this->{face}[0] = ($bn - $bt) / ($mt - $mn);
- } # end if
- $this->{face}[1] = $mt * $this->{face}[0] + $bt;
- $bt = $this->{face}[3] - $this->{face}[2] * $mt;
- $bn = $next->{face}[3] - $next->{face}[2] * $mn;
- if( $mt != $mn ) {
- $this->{face}[2] = ($bn - $bt) / ($mt - $mn);
- } # end if
- $this->{face}[3] = $mt * $this->{face}[2] + $bt;
- } # end if
-
-
- # Make the top/bottom polygon
- my $poly = new GD::Polygon;
- if( ($ys-$ye)/($xe-$xs) > 1 ) {
- $poly->addPt( $prev->{face}[2], $prev->{face}[3] );
- $poly->addPt( $this->{face}[2], $this->{face}[3] );
- $poly->addPt( $this->{face}[2] + $self->{line_depth}, $this->{face}[3] - $self->{line_depth} );
- $poly->addPt( $prev->{face}[2] + $self->{line_depth}, $prev->{face}[3] - $self->{line_depth} );
- if( $self->{'3d_shading'} && $style == $clr ) {
- if( ($ys-$ye)/($xe-$xs) > 0 ) {
- $self->{graph}->filledPolygon( $poly, $self->{'3d_shadows'}[$clr] );
- } else {
- $self->{graph}->filledPolygon( $poly, $self->{'3d_highlights'}[$clr] );
- } # end if
- } else {
- $self->{graph}->filledPolygon( $poly, $style );
- } # end if
- } else {
- $poly->addPt( $prev->{face}[0], $prev->{face}[1] );
- $poly->addPt( $this->{face}[0], $this->{face}[1] );
- $poly->addPt( $this->{face}[0] + $self->{line_depth}, $this->{face}[1] - $self->{line_depth} );
- $poly->addPt( $prev->{face}[0] + $self->{line_depth}, $prev->{face}[1] - $self->{line_depth} );
- if( $self->{'3d_shading'} && $style == $clr ) {
- if( ($ys-$ye)/($xe-$xs) < 0 ) {
- $self->{graph}->filledPolygon( $poly, $self->{'3d_shadows'}[$clr] );
- } else {
- $self->{graph}->filledPolygon( $poly, $self->{'3d_highlights'}[$clr] );
- } # end if
- } else {
- $self->{graph}->filledPolygon( $poly, $style );
- } # end if
- } # end if
- $self->{graph}->polygon( $poly, $self->{fgci} );
-
- # *** This paints dashed and dotted patterns on the faces of
- # the polygons. They don't look very good though. Would it
- # be better to extrude the style as well as the lines?
- # Otherwise could also be improved by using gdTiled instead of
- # gdStyled and making the tile a transform of the line style
- # for each face. [JAW]
-
- # Make the face polygon
- $poly = new GD::Polygon;
- $poly->addPt( $prev->{face}[0], $prev->{face}[1] );
- $poly->addPt( $this->{face}[0], $this->{face}[1] );
- $poly->addPt( $this->{face}[2], $this->{face}[3] );
- $poly->addPt( $prev->{face}[2], $prev->{face}[3] );
-
- $self->{graph}->filledPolygon( $poly, $style );
- $self->{graph}->polygon( $poly, $self->{fgci} );
-
-} # end draw line
-
-# ----------------------------------------------------------
-# Sub: draw_legend_marker
-#
-# Args: $dsn, $x, $y
-# $dsn The dataset number to draw the marker for
-# $x The x position of the marker
-# $y The y position of the marker
-#
-# Description: Draws the legend marker for the specified
-# dataset number at the given coordinates
-# ----------------------------------------------------------
-# Date Modification Author
-# ----------------------------------------------------------
-# 2000OCT06 Fixed rendering bugs JW
-# ----------------------------------------------------------
-sub draw_legend_marker
-{
- my $self = shift;
- my ($n, $x, $y) = @_;
-
- my $ci = $self->set_clr($self->pick_data_clr($n));
- my $type = $self->pick_line_type($n);
-
- $y += int($self->{lg_el_height}/2);
-
- # Joe Smith <jms@tardis.Tymnet.COM>
- local($self->{line_width}) = 2; # Make these show up better
-
- $self->draw_line(
- { coords => [$x, $y] },
- { coords => [$x + $self->{legend_marker_width}, $y] },
- undef,
- $type,
- $ci
- );
-
-} # end draw_legend_marker
-
-1;
diff --git a/lib/GD/Graph/linespoints.pm b/lib/GD/Graph/linespoints.pm
deleted file mode 100644
index d913e2c..0000000
--- a/lib/GD/Graph/linespoints.pm
+++ /dev/null
@@ -1,46 +0,0 @@
-#==========================================================================
-# Copyright (c) 1995-1998 Martien Verbruggen
-#--------------------------------------------------------------------------
-#
-# Name:
-# GD::Graph::linespoints.pm
-#
-# $Id: linespoints.pm,v 1.8 2003/02/10 22:12:41 mgjv Exp $
-#
-#==========================================================================
-
-package GD::Graph::linespoints;
-
-($GD::Graph::linespoints::VERSION) = '$Revision: 1.8 $' =~ /\s([\d.]+)/;
-
-use strict;
-
-use GD::Graph::axestype;
-use GD::Graph::lines;
-use GD::Graph::points;
-
-# Even though multiple inheritance is not really a good idea,
-# since lines and points have the same parent class, I will do it here,
-# because I need the functionality of the markers and the line types
-
-@GD::Graph::linespoints::ISA = qw(GD::Graph::lines GD::Graph::points);
-
-# PRIVATE
-
-sub draw_data_set
-{
- my $self = shift;
-
- $self->GD::Graph::points::draw_data_set(@_) or return;
- $self->GD::Graph::lines::draw_data_set(@_);
-}
-
-sub draw_legend_marker
-{
- my $self = shift;
-
- $self->GD::Graph::points::draw_legend_marker(@_);
- $self->GD::Graph::lines::draw_legend_marker(@_);
-}
-
-"Just another true value";
diff --git a/lib/GD/Graph/mixed.pm b/lib/GD/Graph/mixed.pm
deleted file mode 100644
index daf192f..0000000
--- a/lib/GD/Graph/mixed.pm
+++ /dev/null
@@ -1,99 +0,0 @@
-#==========================================================================
-# Copyright (c) 1995-1998 Martien Verbruggen
-#--------------------------------------------------------------------------
-#
-# Name:
-# GD::Graph::mixed.pm
-#
-# $Id: mixed.pm,v 1.12 2003/02/10 22:12:41 mgjv Exp $
-#
-#==========================================================================
-
-package GD::Graph::mixed;
-
-($GD::Graph::mixed::VERSION) = '$Revision: 1.12 $' =~ /\s([\d.]+)/;
-
-use strict;
-
-use GD::Graph::axestype;
-use GD::Graph::lines;
-use GD::Graph::points;
-use GD::Graph::linespoints;
-use GD::Graph::bars;
-use GD::Graph::area;
-use Carp;
-
-# Even though multiple inheritance is not really a good idea, I will
-# do it here, because I need the functionality of the markers and the
-# line types We'll include axestype as the first one, to make sure
-# that's where we look first for methods.
-
-@GD::Graph::mixed::ISA = qw(
- GD::Graph::axestype
- GD::Graph::bars
- GD::Graph::lines
- GD::Graph::points
-);
-
-sub initialise
-{
- my $self = shift;
- $self->SUPER::initialise();
-}
-
-sub correct_width
-{
- my $self = shift;
-
- return $self->{correct_width} if defined $self->{correct_width};
-
- for my $type ($self->{default_type}, @{$self->{types}})
- {
- return 1 if $type eq 'bars';
- }
-}
-
-sub draw_data_set
-{
- my $self = shift;
- my $ds = $_[0];
-
- my $rc;
-
- my $type = $self->{types}->[$ds-1] || $self->{default_type};
-
- # Try to execute the draw_data_set function in the package
- # specified by type
- $rc = eval '$self->GD::Graph::'.$type.'::draw_data_set(@_)';
-
- # If we fail, we try it in the package specified by the
- # default_type, and warn the user
- if ($@)
- {
- carp "Set $ds, unknown type $type, assuming $self->{default_type}";
- #carp "Error message: $@";
-
- $rc = eval '$self->GD::Graph::'.
- $self->{default_type}.'::draw_data_set(@_)';
- }
-
- # If even that fails, we bail out
- croak "Set $ds: unknown default type $self->{default_type}" if $@;
-
- return $rc;
-}
-
-sub draw_legend_marker
-{
- my $self = shift;
- my $ds = $_[0];
-
- my $type = $self->{types}->[$ds-1] || $self->{default_type};
-
- eval '$self->GD::Graph::'.$type.'::draw_legend_marker(@_)';
-
- eval '$self->GD::Graph::'.
- $self->{default_type}.'::draw_legend_marker(@_)' if $@;
-}
-
-"Just another true value";
diff --git a/lib/GD/Graph/pie.pm b/lib/GD/Graph/pie.pm
deleted file mode 100644
index a945ba0..0000000
--- a/lib/GD/Graph/pie.pm
+++ /dev/null
@@ -1,446 +0,0 @@
-#==========================================================================
-# Copyright (c) 1995-1998 Martien Verbruggen
-#--------------------------------------------------------------------------
-#
-# Name:
-# GD::Graph::pie.pm
-#
-# $Id: pie.pm,v 1.20 2003/02/10 22:12:41 mgjv Exp $
-#
-#==========================================================================
-
-package GD::Graph::pie;
-
-($GD::Graph::pie::VERSION) = '$Revision: 1.20 $' =~ /\s([\d.]+)/;
-
-use strict;
-
-use constant PI => 4 * atan2(1,1);
-
-use GD;
-use GD::Graph;
-use GD::Graph::utils qw(:all);
-use GD::Graph::colour qw(:colours :lists);
-use GD::Text::Align;
-use Carp;
-
-@GD::Graph::pie::ISA = qw( GD::Graph );
-
-my $ANGLE_OFFSET = 90;
-
-my %Defaults = (
-
- # Set the height of the pie.
- # Because of the dependency of this on runtime information, this
- # is being set in GD::Graph::pie::initialise
-
- # pie_height => _round(0.1*${'width'}),
- pie_height => undef,
-
- # Do you want a 3D pie?
- '3d' => 1,
-
- # The angle at which to start the first data set
- # 0 is at the front/bottom
- start_angle => 0,
-
- # Angle below which a label on a pie slice is suppressed.
- suppress_angle => 0, # CONTRIB idea ryan <xomina@bitstream.net>
-
- # and some public attributes without defaults
- label => undef,
-
- # This misnamed attribute is used for pie marker colours
- axislabelclr => 'black',
-);
-
-# PRIVATE
-sub _has_default {
- my $self = shift;
- my $attr = shift || return;
- exists $Defaults{$attr} || $self->SUPER::_has_default($attr);
-}
-
-sub initialise
-{
- my $self = shift;
- $self->SUPER::initialise();
- while (my($key, $val) = each %Defaults)
- { $self->{$key} = $val }
- $self->set( pie_height => _round(0.1 * $self->{height}) );
- $self->set_value_font(gdTinyFont);
- $self->set_label_font(gdSmallFont);
-}
-
-# PUBLIC methods, documented in pod
-sub plot
-{
- my $self = shift;
- my $data = shift;
-
- $self->check_data($data) or return;
- $self->init_graph() or return;
- $self->setup_text() or return;
- $self->setup_coords() or return;
- $self->draw_text() or return;
- $self->draw_pie() or return;
- $self->draw_data() or return;
-
- return $self->{graph};
-}
-
-sub set_label_font # (fontname)
-{
- my $self = shift;
- $self->_set_font('gdta_label', @_) or return;
- $self->{gdta_label}->set_align('bottom', 'center');
-}
-
-sub set_value_font # (fontname)
-{
- my $self = shift;
- $self->_set_font('gdta_value', @_) or return;
- $self->{gdta_value}->set_align('center', 'center');
-}
-
-# Inherit defaults() from GD::Graph
-
-# inherit checkdata from GD::Graph
-
-# Setup the coordinate system and colours, calculate the
-# relative axis coordinates in respect to the canvas size.
-
-sub setup_coords()
-{
- my $self = shift;
-
- # Make sure we're not reserving space we don't need.
- $self->{'3d'} = 0 if $self->{pie_height} <= 0;
- $self->set(pie_height => 0) unless $self->{'3d'};
-
- my $tfh = $self->{title} ? $self->{gdta_title}->get('height') : 0;
- my $lfh = $self->{label} ? $self->{gdta_label}->get('height') : 0;
-
- # Calculate the bounding box for the pie, and
- # some width, height, and centre parameters
- $self->{bottom} =
- $self->{height} - $self->{pie_height} - $self->{b_margin} -
- ( $lfh ? $lfh + $self->{text_space} : 0 );
- $self->{top} =
- $self->{t_margin} + ( $tfh ? $tfh + $self->{text_space} : 0 );
-
- return $self->_set_error('Vertical size too small')
- if $self->{bottom} - $self->{top} <= 0;
-
- $self->{left} = $self->{l_margin};
- $self->{right} = $self->{width} - $self->{r_margin};
-
- return $self->_set_error('Horizontal size too small')
- if $self->{right} - $self->{left} <= 0;
-
- $self->{w} = $self->{right} - $self->{left};
- $self->{h} = $self->{bottom} - $self->{top};
-
- $self->{xc} = ($self->{right} + $self->{left})/2;
- $self->{yc} = ($self->{bottom} + $self->{top})/2;
-
- return $self;
-}
-
-# inherit open_graph from GD::Graph
-
-# Setup the parameters for the text elements
-sub setup_text
-{
- my $self = shift;
-
- if ( $self->{title} )
- {
- #print "'$s->{title}' at ($s->{xc},$s->{t_margin})\n";
- $self->{gdta_title}->set(colour => $self->{tci});
- $self->{gdta_title}->set_text($self->{title});
- }
-
- if ( $self->{label} )
- {
- $self->{gdta_label}->set(colour => $self->{lci});
- $self->{gdta_label}->set_text($self->{label});
- }
-
- $self->{gdta_value}->set(colour => $self->{alci});
-
- return $self;
-}
-
-# Put the text on the canvas.
-sub draw_text
-{
- my $self = shift;
-
- $self->{gdta_title}->draw($self->{xc}, $self->{t_margin})
- if $self->{title};
- $self->{gdta_label}->draw($self->{xc}, $self->{height} - $self->{b_margin})
- if $self->{label};
-
- return $self;
-}
-
-# draw the pie, without the data slices
-sub draw_pie
-{
- my $self = shift;
-
- my $left = $self->{xc} - $self->{w}/2;
-
- $self->{graph}->arc(
- $self->{xc}, $self->{yc},
- $self->{w}, $self->{h},
- 0, 360, $self->{acci}
- );
-
- $self->{graph}->arc(
- $self->{xc}, $self->{yc} + $self->{pie_height},
- $self->{w}, $self->{h},
- 0, 180, $self->{acci}
- ) if ( $self->{'3d'} );
-
- $self->{graph}->line(
- $left, $self->{yc},
- $left, $self->{yc} + $self->{pie_height},
- $self->{acci}
- );
-
- $self->{graph}->line(
- $left + $self->{w}, $self->{yc},
- $left + $self->{w}, $self->{yc} + $self->{pie_height},
- $self->{acci}
- );
-
- return $self;
-}
-
-# Draw the data slices
-
-sub draw_data
-{
- my $self = shift;
-
- my $total = 0;
- my @values = $self->{_data}->y_values(1); # for now, only one pie..
- for (@values)
- {
- $total += $_
- }
-
- return $self->_set_error("Pie data total is <= 0")
- unless $total > 0;
-
- my $ac = $self->{acci}; # Accent colour
- my $pb = $self->{start_angle};
-
- for (my $i = 0; $i < @values; $i++)
- {
- # Set the data colour
- my $dc = $self->set_clr_uniq($self->pick_data_clr($i + 1));
-
- # Set the angles of the pie slice
- # Angle 0 faces down, positive angles are clockwise
- # from there.
- # ---
- # / \
- # | |
- # \ | /
- # ---
- # 0
- # $pa/$pb include the start_angle (so if start_angle
- # is 90, there will be no pa/pb < 90.
- my $pa = $pb;
- $pb += my $slice_angle = 360 * $values[$i]/$total;
-
- # Calculate the end points of the lines at the boundaries of
- # the pie slice
- my ($xe, $ye) = cartesian(
- $self->{w}/2, $pa,
- $self->{xc}, $self->{yc}, $self->{h}/$self->{w}
- );
-
- $self->{graph}->line($self->{xc}, $self->{yc}, $xe, $ye, $ac);
-
- # Draw the lines on the front of the pie
- $self->{graph}->line($xe, $ye, $xe, $ye + $self->{pie_height}, $ac)
- if in_front($pa) && $self->{'3d'};
-
- # Make an estimate of a point in the middle of the pie slice
- # And fill it
- ($xe, $ye) = cartesian(
- 3 * $self->{w}/8, ($pa+$pb)/2,
- $self->{xc}, $self->{yc}, $self->{h}/$self->{w}
- );
-
- $self->{graph}->fillToBorder($xe, $ye, $ac, $dc);
-
- # If it's 3d, colour the front ones as well
- #
- # if one slice is very large (>180 deg) then we will need to
- # fill it twice. sbonds.
- #
- # Independently noted and fixed by Jeremy Wadsack, in a slightly
- # different way.
- if ($self->{'3d'})
- {
- foreach my $fill ($self->_get_pie_front_coords($pa, $pb))
- {
- $self->{graph}->fillToBorder(
- $fill->[0], $fill->[1] + $self->{pie_height}/2,
- $ac, $dc);
- }
- }
- }
-
- # CONTRIB Jeremy Wadsack
- #
- # Large text, sticking out over the pie edge, could cause 3D pies to
- # fill improperly: Drawing the text for a given slice before the
- # next slice was drawn and filled could make the slice boundary
- # disappear, causing the fill colour to flow out. With this
- # implementation, all the text is on top of the pie.
-
- $pb = $self->{start_angle};
- for (my $i = 0; $i < @values; $i++)
- {
- next unless $values[$i];
-
- my $pa = $pb;
- $pb += my $slice_angle = 360 * $values[$i]/$total;
-
- next if $slice_angle <= $self->{suppress_angle};
-
- my ($xe, $ye) =
- cartesian(
- 3 * $self->{w}/8, ($pa+$pb)/2,
- $self->{xc}, $self->{yc}, $self->{h}/$self->{w}
- );
-
- $self->put_slice_label($xe, $ye, $self->{_data}->get_x($i));
- }
-
- return $self;
-
-} #GD::Graph::pie::draw_data
-
-sub _get_pie_front_coords # (angle 1, angle 2)
-{
- my $self = shift;
- my $pa = level_angle(shift);
- my $pb = level_angle(shift);
- my @fills = ();
-
- if (in_front($pa))
- {
- if (in_front($pb))
- {
- # both in front
- # don't do anything
- # Ah, but if this wraps all the way around the back
- # then both pieces of the front need to be filled.
- # sbonds.
- if ($pa > $pb )
- {
- # This takes care of the left bit on the front
- # Since we know exactly where we are, and in which
- # direction this works, we can just get the coordinates
- # for $pa.
- my ($x, $y) = cartesian(
- $self->{w}/2, $pa,
- $self->{xc}, $self->{yc}, $self->{h}/$self->{w}
- );
-
- # and move one pixel to the left, but only if we don't
- # fall out of the pie!.
- push @fills, [$x - 1, $y]
- if $x - 1 > $self->{xc} - $self->{w}/2;
-
- # Reset $pa to the right edge of the front arc, to do
- # the right bit on the front.
- $pa = level_angle(-$ANGLE_OFFSET);
- }
- }
- else
- {
- # start in front, end in back
- $pb = $ANGLE_OFFSET;
- }
- }
- else
- {
- if (in_front($pb))
- {
- # start in back, end in front
- $pa = $ANGLE_OFFSET - 180;
- }
- else
- {
- # both in back
- return;
- }
- }
-
- my ($x, $y) = cartesian(
- $self->{w}/2, ($pa + $pb)/2,
- $self->{xc}, $self->{yc}, $self->{h}/$self->{w}
- );
-
- push @fills, [$x, $y];
-
- return @fills;
-}
-
-# return true if this angle is on the front of the pie
-# XXX UGLY! We need to leave a slight room for error because of rounding
-# problems
-sub in_front
-{
- my $a = level_angle(shift);
- return
- $a > ($ANGLE_OFFSET - 180 + 0.00000001) &&
- $a < $ANGLE_OFFSET - 0.000000001;
-}
-
-# XXX Ugh! I need to fix this. See the GD::Text module for better ways
-# of doing this.
-# return a value for angle between -180 and 180
-sub level_angle # (angle)
-{
- my $a = shift;
- return level_angle($a-360) if ( $a > 180 );
- return level_angle($a+360) if ( $a <= -180 );
- return $a;
-}
-
-# put the slice label on the pie
-sub put_slice_label
-{
- my $self = shift;
- my ($x, $y, $label) = @_;
-
- return unless defined $label;
-
- $self->{gdta_value}->set_text($label);
- $self->{gdta_value}->draw($x, $y);
-}
-
-# return x, y coordinates from input
-# radius, angle, center x and y and a scaling factor (height/width)
-#
-# $ANGLE_OFFSET is used to define where 0 is meant to be
-sub cartesian
-{
- my ($r, $phi, $xi, $yi, $cr) = @_;
-
- return (
- $xi + $r * cos(PI * ($phi + $ANGLE_OFFSET)/180),
- $yi + $cr * $r * sin(PI * ($phi + $ANGLE_OFFSET)/180)
- )
-}
-
-"Just another true value";
diff --git a/lib/GD/Graph/pie3d.pm b/lib/GD/Graph/pie3d.pm
deleted file mode 100644
index f1b0a76..0000000
--- a/lib/GD/Graph/pie3d.pm
+++ /dev/null
@@ -1,331 +0,0 @@
-############################################################
-#
-# Module: GD::Graph::pie3d
-#
-# Description:
-# This is merely a wrapper around GD::Graph::pie that forces
-# the 3d option for pie charts.
-#
-# Created: 2000.Jan.19 by Jeremy Wadsack for Wadsack-Allen Digital Group
-# Copyright (C) 2000,2001 Wadsack-Allen. All rights reserved.
-############################################################
-# Date Modification Author
-# ----------------------------------------------------------
-# 2000APR18 Modified to be compatible w/ GD::Graph 1.30 JW
-# 2000APR24 Set default slice label color to black JW
-# 2001Feb16 Added support for a legend JW
-############################################################
-package GD::Graph::pie3d;
-
-use strict;
-use GD;
-use GD::Graph;
-use GD::Graph::pie;
-use GD::Graph::utils qw(:all);
-use Carp;
-
-@GD::Graph::pie3d::ISA = qw( GD::Graph::pie );
-$GD::Graph::pie3d::VERSION = '0.63';
-
-my %Defaults = (
- '3d' => 1,
- axislabelclr => 'black', # values on slices. black because default colors use dblue
-
- # Size of the legend markers
- legend_marker_height => 8,
- legend_marker_width => 12,
- legend_spacing => 4,
- legend_placement => 'BC', # '[BR][LCR]'
- lg_cols => undef,
- legend_frame_margin => 4,
- legend_frame_size => undef,
-);
-
-# PRIVATE
-# Have to include because this is a different %Defaults hash
-sub _has_default {
- my $self = shift;
- my $attr = shift || return;
- exists $Defaults{$attr} || $self->SUPER::_has_default($attr);
-}
-
-sub initialise {
- my $self = shift;
- my $rc = $self->SUPER::initialise();
-
- while( my($key, $val) = each %Defaults ) {
- $self->{$key} = $val;
- } # end while
-
- $self->set_legend_font(GD::gdTinyFont);
- return $rc;
-} # end initialise
-
-# Add lengend calc and draw code
-sub plot
-{
- my $self = shift;
- my $data = shift;
-
- $self->check_data($data) or return;
- $self->init_graph() or return;
- $self->setup_text() or return;
- $self->setup_legend();
- $self->setup_coords() or return;
- $self->{b_margin} += 4 if $self->{label}; # Kludge for descenders
- $self->draw_text() or return;
- $self->draw_pie() or return;
- $self->draw_data() or return;
- $self->draw_legend();
-
- return $self->{graph};
-}
-
-# Added legend stuff
-sub setup_text
-{
- my $self = shift;
-
- my $rc = $self->SUPER::setup_text( @_ );
-
- $self->{gdta_legend}->set(colour => $self->{legendci});
- $self->{gdta_legend}->set_align('top', 'left');
- $self->{lgfh} = $self->{gdta_legend}->get('height');
-
- return $rc
-} # end setup_text
-
-# Inherit everything else from GD::Graph::pie
-
-
-# Legend Support. Added 16.Feb.2001 - JW/WADG
-
-sub set_legend # List of legend keys
-{
- my $self = shift;
- $self->{legend} = [@_];
-}
-
-sub set_legend_font # (font name)
-{
- my $self = shift;
- $self->_set_font('gdta_legend', @_);
-}
-
-
-
-#
-# Legend
-#
-sub setup_legend
-{
- my $self = shift;
-
- return unless defined $self->{legend};
-
- my $maxlen = 0;
- my $num = 0;
-
- # Save some variables
- $self->{r_margin_abs} = $self->{r_margin};
- $self->{b_margin_abs} = $self->{b_margin};
-
- foreach my $legend (@{$self->{legend}})
- {
- if (defined($legend) and $legend ne "")
- {
- $self->{gdta_legend}->set_text($legend);
- my $len = $self->{gdta_legend}->get('width');
- $maxlen = ($maxlen > $len) ? $maxlen : $len;
- $num++;
- }
- # Legend for Pie goes over first set, and all points
- last if $num >= $self->{_data}->num_points;
- }
-
- $self->{lg_num} = $num;
-
- # calculate the height and width of each element
- my $legend_height = _max($self->{lgfh}, $self->{legend_marker_height});
-
- $self->{lg_el_width} =
- $maxlen + $self->{legend_marker_width} + 3 * $self->{legend_spacing};
- $self->{lg_el_height} = $legend_height + 2 * $self->{legend_spacing};
-
- my ($lg_pos, $lg_align) = split(//, $self->{legend_placement});
-
- if ($lg_pos eq 'R')
- {
- # Always work in one column
- $self->{lg_cols} = 1;
- $self->{lg_rows} = $num;
-
- # Just for completeness, might use this in later versions
- $self->{lg_x_size} = $self->{lg_cols} * $self->{lg_el_width};
- $self->{lg_y_size} = $self->{lg_rows} * $self->{lg_el_height};
-
- # Adjust the right margin for the rest of the graph
- $self->{r_margin} += $self->{lg_x_size};
-
- # Adjust for frame if defined
- if( $self->{legend_frame_size} ) {
- $self->{r_margin} += 2 * ($self->{legend_frame_margin} + $self->{legend_frame_size});
- } # end if;
-
- # Set the x starting point
- $self->{lg_xs} = $self->{width} - $self->{r_margin};
-
- # Set the y starting point, depending on alignment
- if ($lg_align eq 'T')
- {
- $self->{lg_ys} = $self->{t_margin};
- }
- elsif ($lg_align eq 'B')
- {
- $self->{lg_ys} = $self->{height} - $self->{b_margin} -
- $self->{lg_y_size};
- }
- else # default 'C'
- {
- my $height = $self->{height} - $self->{t_margin} -
- $self->{b_margin};
-
- $self->{lg_ys} =
- int($self->{t_margin} + $height/2 - $self->{lg_y_size}/2) ;
- }
- }
- else # 'B' is the default
- {
- # What width can we use
- my $width = $self->{width} - $self->{l_margin} - $self->{r_margin};
-
- (!defined($self->{lg_cols})) and
- $self->{lg_cols} = int($width/$self->{lg_el_width});
-
- $self->{lg_cols} = _min($self->{lg_cols}, $num);
-
- $self->{lg_rows} =
- int($num / $self->{lg_cols}) + (($num % $self->{lg_cols}) ? 1 : 0);
-
- $self->{lg_x_size} = $self->{lg_cols} * $self->{lg_el_width};
- $self->{lg_y_size} = $self->{lg_rows} * $self->{lg_el_height};
-
- # Adjust the bottom margin for the rest of the graph
- $self->{b_margin} += $self->{lg_y_size};
- # Adjust for frame if defined
- if( $self->{legend_frame_size} ) {
- $self->{b_margin} += 2 * ($self->{legend_frame_margin} + $self->{legend_frame_size});
- } # end if;
-
- # Set the y starting point
- $self->{lg_ys} = $self->{height} - $self->{b_margin};
-
- # Set the x starting point, depending on alignment
- if ($lg_align eq 'R')
- {
- $self->{lg_xs} = $self->{width} - $self->{r_margin} -
- $self->{lg_x_size};
- }
- elsif ($lg_align eq 'L')
- {
- $self->{lg_xs} = $self->{l_margin};
- }
- else # default 'C'
- {
- $self->{lg_xs} =
- int($self->{l_margin} + $width/2 - $self->{lg_x_size}/2);
- }
- }
-}
-
-sub draw_legend
-{
- my $self = shift;
-
- return unless defined $self->{legend};
-
- my $xl = $self->{lg_xs} + $self->{legend_spacing};
- my $y = $self->{lg_ys} + $self->{legend_spacing} - 1;
-
- # If there's a frame, offset by the size and margin
- $xl += $self->{legend_frame_margin} + $self->{legend_frame_size} if $self->{legend_frame_size};
- $y += $self->{legend_frame_margin} + $self->{legend_frame_size} if $self->{legend_frame_size};
-
- my $i = 0;
- my $row = 1;
- my $x = $xl; # start position of current element
-
- foreach my $legend (@{$self->{legend}})
- {
- $i++;
- # Legend for Pie goes over first set, and all points
- last if $i > $self->{_data}->num_points;
-
- my $xe = $x; # position within an element
-
- next unless defined($legend) && $legend ne "";
-
- $self->draw_legend_marker($i, $xe, $y);
-
- $xe += $self->{legend_marker_width} + $self->{legend_spacing};
- my $ys = int($y + $self->{lg_el_height}/2 - $self->{lgfh}/2);
-
- $self->{gdta_legend}->set_text($legend);
- $self->{gdta_legend}->draw($xe, $ys);
-
- $x += $self->{lg_el_width};
-
- if (++$row > $self->{lg_cols})
- {
- $row = 1;
- $y += $self->{lg_el_height};
- $x = $xl;
- }
- }
-
- # If there's a frame, draw it now
- if( $self->{legend_frame_size} ) {
- $x = $self->{lg_xs} + $self->{legend_spacing};
- $y = $self->{lg_ys} + $self->{legend_spacing} - 1;
-
- for $i ( 0 .. $self->{legend_frame_size} - 1 ) {
- $self->{graph}->rectangle(
- $x + $i,
- $y + $i,
- $x + $self->{lg_x_size} + 2 * $self->{legend_frame_margin} - $i - 1,
- $y + $self->{lg_y_size} + 2 * $self->{legend_frame_margin} - $i - 1,
- $self->{acci},
- );
- } # end for
- } # end if
-
-}
-
-sub draw_legend_marker # data_set_number, x, y
-{
- my $s = shift;
- my $n = shift;
- my $x = shift;
- my $y = shift;
-
- my $g = $s->{graph};
-
- my $ci = $s->set_clr($s->pick_data_clr($n));
-
- $y += int($s->{lg_el_height}/2 - $s->{legend_marker_height}/2);
-
- $g->filledRectangle(
- $x, $y,
- $x + $s->{legend_marker_width}, $y + $s->{legend_marker_height},
- $ci
- );
-
- $g->rectangle(
- $x, $y,
- $x + $s->{legend_marker_width}, $y + $s->{legend_marker_height},
- $s->{acci}
- );
-}
-
-
-1;
diff --git a/lib/GD/Graph/points.pm b/lib/GD/Graph/points.pm
deleted file mode 100644
index 43b6825..0000000
--- a/lib/GD/Graph/points.pm
+++ /dev/null
@@ -1,183 +0,0 @@
-#==========================================================================
-# Copyright (c) 1995-1998 Martien Verbruggen
-#--------------------------------------------------------------------------
-#
-# Name:
-# GD::Graph::points.pm
-#
-# $Id: points.pm,v 1.13 2003/02/10 22:12:41 mgjv Exp $
-#
-#==========================================================================
-
-package GD::Graph::points;
-
-($GD::Graph::points::VERSION) = '$Revision: 1.13 $' =~ /\s([\d.]+)/;
-
-use strict;
-
-use GD::Graph::axestype;
-use GD::Graph::utils qw(:all);
-
-@GD::Graph::points::ISA = qw( GD::Graph::axestype );
-
-# PRIVATE
-sub draw_data_set
-{
- my $self = shift;
- my $ds = shift;
-
- my @values = $self->{_data}->y_values($ds) or
- return $self->_set_error("Impossible illegal data set: $ds",
- $self->{_data}->error);
-
- # Pick a colour
- my $dsci = $self->set_clr($self->pick_data_clr($ds));
- my $type = $self->pick_marker($ds);
-
- for (my $i = 0; $i < @values; $i++)
- {
- next unless defined $values[$i];
- my ($xp, $yp);
- if (defined($self->{x_min_value}) && defined($self->{x_max_value}))
- {
- ($xp, $yp) = $self->val_to_pixel(
- $self->{_data}->get_x($i), $values[$i], $ds);
- }
- else
- {
- ($xp, $yp) = $self->val_to_pixel($i+1, $values[$i], $ds);
- }
- $self->marker($xp, $yp, $type, $dsci );
- $self->{_hotspots}->[$ds]->[$i] =
- ['rect', $self->marker_coordinates($xp, $yp)];
- }
-
- return $ds;
-}
-
-# Pick a marker type
-
-sub pick_marker # number
-{
- my $self = shift;
- my $num = shift;
-
- ref $self->{markers} ?
- $self->{markers}[ $num % (1 + $#{$self->{markers}}) - 1 ] :
- ($num % 8) || 8;
-}
-
-# Draw a marker
-
-sub marker_coordinates
-{
- my $self = shift;
- my ($xp, $yp) = @_;
- return (
- $xp - $self->{marker_size},
- $xp + $self->{marker_size},
- $yp + $self->{marker_size},
- $yp - $self->{marker_size},
- );
-}
-
-sub marker # $xp, $yp, $type, $colourindex
-{
- my $self = shift;
- my ($xp, $yp, $mtype, $mclr) = @_;
- return unless defined $mclr;
-
- my ($l, $r, $b, $t) = $self->marker_coordinates($xp, $yp);
-
- MARKER: {
-
- ($mtype == 1) && do
- { # Square, filled
- $self->{graph}->filledRectangle($l, $t, $r, $b, $mclr);
- last MARKER;
- };
- ($mtype == 2) && do
- { # Square, open
- $self->{graph}->rectangle($l, $t, $r, $b, $mclr);
- last MARKER;
- };
- ($mtype == 3) && do
- { # Cross, horizontal
- $self->{graph}->line($l, $yp, $r, $yp, $mclr);
- $self->{graph}->line($xp, $t, $xp, $b, $mclr);
- last MARKER;
- };
- ($mtype == 4) && do
- { # Cross, diagonal
- $self->{graph}->line($l, $b, $r, $t, $mclr);
- $self->{graph}->line($l, $t, $r, $b, $mclr);
- last MARKER;
- };
- ($mtype == 5) && do
- { # Diamond, filled
- $self->{graph}->line($l, $yp, $xp, $t, $mclr);
- $self->{graph}->line($xp, $t, $r, $yp, $mclr);
- $self->{graph}->line($r, $yp, $xp, $b, $mclr);
- $self->{graph}->line($xp, $b, $l, $yp, $mclr);
- $self->{graph}->fillToBorder($xp, $yp, $mclr, $mclr);
- last MARKER;
- };
- ($mtype == 6) && do
- { # Diamond, open
- $self->{graph}->line($l, $yp, $xp, $t, $mclr);
- $self->{graph}->line($xp, $t, $r, $yp, $mclr);
- $self->{graph}->line($r, $yp, $xp, $b, $mclr);
- $self->{graph}->line($xp, $b, $l, $yp, $mclr);
- last MARKER;
- };
- ($mtype == 7) && do
- { # Circle, filled
- $self->{graph}->arc($xp, $yp, 2 * $self->{marker_size},
- 2 * $self->{marker_size}, 0, 360, $mclr);
- $self->{graph}->fillToBorder($xp, $yp, $mclr, $mclr);
- last MARKER;
- };
- ($mtype == 8) && do
- { # Circle, open
- $self->{graph}->arc($xp, $yp, 2 * $self->{marker_size},
- 2 * $self->{marker_size}, 0, 360, $mclr);
- last MARKER;
- };
- ($mtype == 9) && do
- { # Horizontal line
- $self->{graph}->line($l, $yp, $r, $yp, $mclr);
- last MARKER;
- };
- ($mtype == 10) && do
- { # vertical line
- $self->{graph}->line($xp, $t, $xp, $b, $mclr);
- last MARKER;
- };
- }
-}
-
-sub draw_legend_marker
-{
- my $self = shift;
- my $n = shift;
- my $x = shift;
- my $y = shift;
-
- my $ci = $self->set_clr($self->pick_data_clr($n));
-
- my $old_ms = $self->{marker_size};
- my $ms = _min($self->{legend_marker_height}, $self->{legend_marker_width});
-
- ($self->{marker_size} > $ms/2) and $self->{marker_size} = $ms/2;
-
- $x += int($self->{legend_marker_width}/2);
- $y += int($self->{lg_el_height}/2);
-
- $n = $self->pick_marker($n);
-
- $self->marker($x, $y, $n, $ci);
-
- $self->{marker_size} = $old_ms;
-}
-
-"Just another true value";
diff --git a/lib/GD/Graph/utils.pm b/lib/GD/Graph/utils.pm
deleted file mode 100644
index b24fc26..0000000
--- a/lib/GD/Graph/utils.pm
+++ /dev/null
@@ -1,49 +0,0 @@
-#==========================================================================
-# Copyright (c) 1995-1999 Martien Verbruggen
-#--------------------------------------------------------------------------
-#
-# Name:
-# GD::Graph::utils.pm
-#
-# Description:
-# Package of general utilities.
-#
-# $Id: utils.pm,v 1.7 2003/02/10 22:12:41 mgjv Exp $
-#
-#==========================================================================
-
-package GD::Graph::utils;
-
-($GD::Graph::utils::VERSION) = '$Revision: 1.7 $' =~ /\s([\d.]+)/;
-
-use strict;
-
-use vars qw( @EXPORT_OK %EXPORT_TAGS );
-require Exporter;
-
-@GD::Graph::utils::ISA = qw( Exporter );
-
-@EXPORT_OK = qw(_max _min _round);
-%EXPORT_TAGS = (all => [qw(_max _min _round)]);
-
-sub _max {
- my ($a, $b) = @_;
- return undef if (!defined($a) and !defined($b));
- return $a if (!defined($b));
- return $b if (!defined($a));
- ( $a >= $b ) ? $a : $b;
-}
-
-sub _min {
- my ($a, $b) = @_;
- return undef if (!defined($a) and !defined($b));
- return $a if (!defined($b));
- return $b if (!defined($a));
- ( $a <= $b ) ? $a : $b;
-}
-
-sub _round { sprintf "%.0f", shift }
-
-sub version { $GD::Graph::utils::VERSION }
-
-"Just another true value";
diff --git a/lib/GD/Graph3d.pm b/lib/GD/Graph3d.pm
deleted file mode 100644
index 3795689..0000000
--- a/lib/GD/Graph3d.pm
+++ /dev/null
@@ -1,157 +0,0 @@
-#==========================================================================
-# Module: GD::Graph3d
-#
-# Copyright (C) 2000 Wadsack-Allen. All Rights Reserved.
-#
-#--------------------------------------------------------------------------
-# Date Modification Author
-# -------------------------------------------------------------------------
-# 08Nov2001 Re-sourced to use standard module files and structure.
-# The package is now GD-Graph3d which us what people expect JW
-#==========================================================================
-package GD::Graph3d;
-$GD::Graph3d::VERSION = '0.63';
-1;
-
-=head1 NAME
-
-GD::Graph3D - Create 3D Graphs with GD and GD::Graph
-
-=head1 SYNOPSIS
-
- use GD::Graph::moduleName;
- my @data = (
- ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
- [ 1203, 3500, 3973, 2859, 3012, 3423, 1230]
- );
- my $graph = new GD::Graph::moduleName( 400, 300 );
- $graph->set(
- x_label => 'Day of the week',
- y_label => 'Number of hits',
- title => 'Daily Summary of Web Site',
- );
- my $gd = $graph->plot( \@data );
-
-Where I<moduleName> is one of C<bars3d>, C<lines3d> or C<pie3d>.
-
-=head1 DESCRIPTION
-
-This is the GD::Graph3d extensions module. It provides 3D graphs for the
-GD::Graph module by Martien Verbruggen, which in turn generates graph
-using Lincoln Stein's GD.pm.
-
-You use these modules just as you would any of the GD::Graph modules, except
-that they generate 3d-looking graphs. Each graph type is described below
-with only the options that are unique to the 3d version. The modules are
-based on their 2d versions (e.g. GD::Graph::bars3d works like
-GD::Graph::bars), and support all the options in those. Make sure to read
-the documentation on GD::Graph.
-
-=over 4
-
-=item GD::Graph::pie3d
-
-This is merely a wrapper around GD::Graph::pie for consistency. It also
-sets 3d pie mode by default (which GD::Graph does as of version 1.22).
-All options are exactly as in GD::Graph::pie.
-
-=item GD::Graph::bars3d
-
-This works like GD::Graph::bars, but draws 3d bars. The following settings
-are new or changed in GD::Graph::bars3d.
-
-=over 4
-
-=item bar_depth
-
-Sets the z-direction depth of the bars. This defaults to 10. If you have a
-large number of bars or a small chart width, you may want to change this.
-A visually good value for this is approximately
-width_of_chart / number_of_bars.
-
-=item overwrite
-
-In GD::Graph::bars, multiple series of bars are normally drawn side-by-side.
-You can set overwrite to 1 to tell it to draw each series behind the
-previous one. By setting overwrite to 2 you can have them drawn on top of
-each other, that is the series are stacked.
-
-=item shading
-
-By default this is set to '1' and will shade and highlight the bars (and axes).
-The light source is at top-left-center which scan well for most computer
-users. You can disable the shading of bars and axes by specifying a false
-value for this option.
-
-=back
-
-=item GD::Graph::lines3d
-
-This works like GD::Graph::lines, but draws 3d line. The following settings
-are new or changed in GD::Graph::line3d.
-
-=over 4
-
-=item line_depth
-
-Sets the z-direction depth of the lines. This defaults to 10. If you have a
-large number of bars or a small chart width, you may want to change this.
-A visually good value for this is approximately
-width_of_chart / number_of_bars.
-
-=item shading
-
-By default this is set to '1' and will shade and highlight the line (and axes).
-The light source is at top-left-center which scan well for most computer
-users. You can disable the shading of lines and axes by specifiying a false
-value for this option.
-
-=back
-
-=back
-
-=head1 VERSION
-
-0.63 (6 December 2002)
-
-=head1 INSTALLATION
-
-You will need to have the GD::Graph version 1.30 or later installed. You should also
-have Perl version 5.005 or 5.6 installed.
-
-To install, just do the normal:
-
- perl Makefile.PL
- make
- make install
-
-The documentation is in GD::Graph::Graph3d.pod.
-
-=head1 AUTHOR
-
-Jeremy Wadsack for Wadsack-Allen Digital Group.
-<F<dgsupport at wadsack-allen dot com>>
-
-Most of the modules are based on the GD::Graph modules by Martien Verbruggen.
-
-=head1 LATEST RELEASE
-
-The latest release is available from CPAN: http://www.cpan.org/.
-
-=head1 COPYRIGHT
-
-Copyright (c) 1999-2001 Wadsack-Allen. All rights reserved.
-
-Much of the original code is from GD::Graph:
-
-GIFgraph: Copyright (c) 1995-1999 Martien Verbruggen.
-
-Chart::PNGgraph: Copyright (c) 1999 Steve Bonds.
-
-GD::Graph: Copyright (c) 1999 Martien Verbruggen.
-
-This package is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=cut
-
diff --git a/lib/HTML/TextToHTML.pm b/lib/HTML/TextToHTML.pm
deleted file mode 100644
index 82f3dc2..0000000
--- a/lib/HTML/TextToHTML.pm
+++ /dev/null
@@ -1,5266 +0,0 @@
-package HTML::TextToHTML;
-use 5.006_001;
-use strict;
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-HTML::TextToHTML - convert plain text file to HTML.
-
-=head1 VERSION
-
-This describes version B<2.42> of HTML::TextToHTML.
-
-=cut
-
-our $VERSION = '2.42';
-
-=head1 SYNOPSIS
-
- From the command line:
-
- txt2html I<arguments>
-
- From Scripts:
-
- use HTML::TextToHTML;
-
- # create a new object
- my $conv = new HTML::TextToHTML();
-
- # convert a file
- $conv->txt2html(infile=>[$text_file],
- outfile=>$html_file,
- title=>"Wonderful Things",
- mail=>1,
- ]);
-
- # reset arguments
- $conv->args(infile=>[], mail=>0);
-
- # convert a string
- $newstring = $conv->process_chunk($mystring)
-
-=head1 DESCRIPTION
-
-HTML::TextToHTML converts plain text files to HTML. The txt2html script
-uses this module to do the same from the command-line.
-
-It supports headings, tables, lists, simple character markup, and
-hyperlinking, and is highly customizable. It recognizes some of the
-apparent structure of the source document (mostly whitespace and
-typographic layout), and attempts to mark that structure explicitly
-using HTML. The purpose for this tool is to provide an easier way of
-converting existing text documents to HTML format, giving something nicer
-than just whapping the text into a big PRE block.
-
-=head2 History
-
-The original txt2html script was written by Seth Golub (see
-http://www.aigeek.com/txt2html/), and converted to a perl module by
-Kathryn Andersen (see http://www.katspace.com/tools/text_to_html/) and
-made into a sourceforge project by Sun Tong (see
-http://sourceforge.net/projects/txt2html/). Earlier versions of the
-HTML::TextToHTML module called the included script texthyper so as not
-to clash with the original txt2html script, but now the projects have
-all been merged.
-
-=head1 REQUIRES
-
-HTML::TextToHTML requires Perl 5.6.1 or later.
-
-For installation, it needs:
-
- Module::Build
-
-The txt2html script needs:
-
- Getopt::Long
- Getopt::ArgvFile
- Pod::Usage
- File::Basename
-
-For testing, it also needs:
-
- Test::More
-
-For debugging, it also needs:
-
- Data::Dumper
-
-=head1 INSTALLATION
-
-Make sure you have the dependencies installed first!
-(see REQUIRES above)
-
-Some of those modules come standard with more recent versions of perl,
-but I thought I'd mention them anyway, just in case you may not have
-them.
-
-If you don't know how to install these, try using the CPAN module, an
-easy way of auto-installing modules from the Comprehensive Perl Archive
-Network, where the above modules reside.
-Do "perldoc perlmodinstall" or "perldoc CPAN" for more information.
-
-To install this module type the following:
-
- perl Build.PL
- ./Build
- ./Build test
- ./Build install
-
-Or, if you're on a platform (like DOS or Windows) that doesn't like the
-"./" notation, you can do this:
-
- perl Build.PL
- perl Build
- perl Build test
- perl Build install
-
-In order to install somewhere other than the default, such as
-in a directory under your home directory, like "/home/fred/perl"
-go
-
- perl Build.PL --install_base /home/fred/perl
-
-as the first step instead.
-
-This will install the files underneath /home/fred/perl.
-
-You will then need to make sure that you alter the PERL5LIB variable to
-find the modules, and the PATH variable to find the script.
-
-Therefore you will need to change:
-your path, to include /home/fred/perl/script (where the script will be)
-
- PATH=/home/fred/perl/script:${PATH}
-
-the PERL5LIB variable to add /home/fred/perl/lib
-
- PERL5LIB=/home/fred/perl/lib:${PERL5LIB}
-
-Note that the system links dictionary will be installed as
-"/home/fred/perl/share/txt2html/txt2html.dict"
-
-If you want to install in a temporary install directory (such as
-if you are building a package) then instead of going
-
- perl Build install
-
-go
-
- perl Build install destdir=/my/temp/dir
-
-and it will be installed there, with a directory structure under
-/my/temp/dir the same as it would be if it were installed plain.
-Note that this is NOT the same as setting --install_base, because
-certain things are done at build-time which use the install_base info.
-
-See "perldoc perlrun" for more information on PERL5LIB, and
-see "perldoc Module::Build" for more information on
-installation options.
-
-=head1 OPTIONS
-
-All arguments can be set when the object is created, and further options
-can be set when calling the actual txt2html method. Arguments
-to methods can take either a hash of arguments, or a reference to an
-array. Note that the reference-to-array method is depricated and is only
-retained for backwards compatibility.
-
-Note that all option-names must match exactly -- no abbreviations are
-allowed.
-
-The arguments get treated differently depending on whether they are
-given in a hash or a reference to an array. When the arguments are
-in a hash, the argument-keys are expected to have values matching
-those required for that argument -- whether that be a boolean, a string,
-a reference to an array or a reference to a hash. These will replace
-any value for that argument that might have been there before.
-
-When the arguments are in a reference to an array, it is treated
-somewhat as if it were a command-line: option names are expected to
-start with '--' or '-', boolean options are set to true as soon as the
-option is given (no value is expected to follow), boolean options with
-the word "no" prepended set the option to false, string options are
-expected to have a string value following, and those options which are
-internally arrays or hashes are treated as cumulative; that is, the
-value following the --option is added to the current set for that
-option, to add more, one just repeats the --option with the next value,
-and in order to reset that option to empty, the special value of "CLEAR"
-must be added to the list.
-
-NOTE: the reference-to-an-array usage is DEPRECATED and will be removed
-in the future.
-
-=over
-
-=item append_file
-
- append_file=>I<filename>
-
-If you want something appended by default, put the filename here.
-The appended text will not be processed at all, so make sure it's
-plain text or decent HTML. i.e. do not have things like:
- Mary Andersen E<lt>kitty@example.comE<gt>
-but instead, have:
- Mary Andersen &lt;kitty@example.com&gt;
-
-(default: nothing)
-
-=item append_head
-
- append_head=>I<filename>
-
-If you want something appended to the head by default, put the filename here.
-The appended text will not be processed at all, so make sure it's
-plain text or decent HTML. i.e. do not have things like:
- Mary Andersen E<lt>kitty@example.comE<gt>
-but instead, have:
- Mary Andersen &lt;kitty@example.com&gt;
-
-(default: nothing)
-
-=item body_deco
-
- body_deco=>I<string>
-
-Body decoration string: a string to be added to the BODY tag so that
-one can set attributes to the BODY (such as class, style, bgcolor etc)
-For example, "class='withimage'".
-
-=item bold_delimiter
-
- bold_delimiter=>I<string>
-
-This defines what character (or string) is taken to be the delimiter of
-text which is to be interpreted as bold (that is, to be given a STRONG
-tag). If this is empty, then no bolding of text will be done.
-(default: #)
-
-=item bullets
-
- bullets=>I<string>
-
-This defines what single characters are taken to be "bullet" characters
-for unordered lists. Note that because this is used as a character
-class, if you use '-' it must come first.
-(default:-=o*\267)
-
-=item bullets_ordered
-
- bullets_ordered=>I<string>
-
-This defines what single characters are taken to be "bullet" placeholder
-characters for ordered lists. Ordered lists are normally marked by
-a number or letter followed by '.' or ')' or ']' or ':'. If an ordered
-bullet is used, then it simply indicates that this is an ordered list,
-without giving explicit numbers.
-
-Note that because this is used as a character class, if you use '-' it
-must come first.
-(default:nothing)
-
-=item caps_tag
-
- caps_tag=>I<tag>
-
-Tag to put around all-caps lines
-(default: STRONG)
-If an empty tag is given, then no tag will be put around all-caps lines.
-
-=item custom_heading_regexp
-
- custom_heading_regexp=>I<regexp>
-
-Add a regexp for headings. Header levels are assigned by regexp
-in order seen When a line matches a custom header regexp, it is tagged as
-a header. If it's the first time that particular regexp has matched,
-the next available header level is associated with it and applied to
-the line. Any later matches of that regexp will use the same header level.
-Therefore, if you want to match numbered header lines, you could use
-something like this:
-
- -H '^ *\d+\. \w+' -H '^ *\d+\.\d+\. \w+' -H '^ *\d+\.\d+\.\d+\. \w+'
-
-Then lines like
-
- " 1. Examples "
- " 1.1. Things"
- and " 4.2.5. Cold Fusion"
-
-Would be marked as H1, H2, and H3 (assuming they were found in that
-order, and that no other header styles were encountered).
-If you prefer that the first one specified always be H1, the second
-always be H2, the third H3, etc, then use the -EH/--explicit-headings
-option.
-
-This is a multi-valued option.
-
-(default: none)
-
-=item debug
-
- debug=>1
-
-Enable copious script debugging output (don't bother, this is for the
-developer) (default: false)
-
-=item default_link_dict
-
- default_link_dict=>I<filename>
-
-The name of the default "user" link dictionary.
-(default: "$ENV{'HOME'}/.txt2html.dict" -- this is the same as for
-the txt2html script. If there is no $ENV{HOME} then it is just '.txt2html.dict')
-
-=item demoronize
-
- demoronize=>1
-
-Convert Microsoft-generated character codes that are non-ISO codes into
-something more reasonable.
-(default:true)
-
-=item dict_debug
-
- dict_debug=>I<n>
-
-Debug mode for link dictionaries Bitwise-Or what you want to see:
- 1: The parsing of the dictionary
- 2: The code that will make the links
- 4: When each rule matches something
- 8: When each tag is created
-
-(default: 0)
-
-=item doctype
-
- doctype=>I<doctype>
-
-This gets put in the DOCTYPE field at the top of the document, unless it's
-empty. (default : "-//W3C//DTD HTML 3.2 Final//EN")
-If --xhtml is true, the contents of this is ignored, unless it's
-empty, in which case no DOCTYPE declaration is output.
-
-=item eight_bit_clean
-
- eight_bit_clean=>1
-
-disable Latin-1 character entity naming
-(default: false)
-
-=item escape_HTML_chars
-
- escape_HTML_chars=>1
-
-turn & E<lt> E<gt> into &amp; &gt; &lt;
-(default: true)
-
-=item explicit_headings
-
- explicit_headings=>1
-
-Don't try to find any headings except the ones specified in the
---custom_heading_regexp option.
-Also, the custom headings will not be assigned levels in the order they
-are encountered in the document, but in the order they are specified on
-the command line.
-(default: false)
-
-=item extract
-
- extract=>1
-
-Extract Mode; don't put HTML headers or footers on the result, just
-the plain HTML (thus making the result suitable for inserting into
-another document (or as part of the output of a CGI script).
-(default: false)
-
-=item hrule_min
-
- hrule_min=>I<n>
-
-Min number of ---s for an HRule.
-(default: 4)
-
-=item indent_width
-
- indent_width=>I<n>
-
-Indents this many spaces for each level of a list.
-(default: 2)
-
-=item indent_par_break
-
- indent_par_break=>1
-
-Treat paragraphs marked solely by indents as breaks with indents.
-That is, instead of taking a three-space indent as a new paragraph,
-put in a <BR> and three non-breaking spaces instead.
-(see also --preserve_indent)
-(default: false)
-
-=item infile
-
- infile=>\@my_files
- infile=>['chapter1.txt', 'chapter2.txt']
- "--infile", "chapter1.txt", "--infile", "chapter2.txt"
-
-The name of the input file(s). When the arguments are given as a hash,
-this expects a reference to an array of filenames. When the arguments
-are given as a reference to an array, then the "--infile" option must
-be repeated for each new file added to the list. If you want to reset
-the list to be empty, give the special value of "CLEAR".
-
-The special filename '-' designates STDIN.
-
-See also L</inhandle> and L</instring>.
-
-(default:-)
-
-=item inhandle
-
- inhandle=>\@my_handles
- inhandle=>[\*MYINHANDLE, \*STDIN]
-
-An array of input filehandles; use this instead of
-L</infile> or L</instring> to use a filehandle or filehandles
-as input.
-
-=item instring
-
- instring=>\@my_strings
- instring=>[$string1, $string2]
-
-An array of input strings; use this instead of
-L</infile> or L</inhandle> to use a string or strings
-as input.
-
-=item italic_delimiter
-
- italic_delimiter=>I<string>
-
-This defines what character (or string) is taken to be the delimiter of
-text which is to be interpreted as italic (that is, to be given a EM
-tag). If this is empty, no italicising of text will be done.
-(default: *)
-
-=item links_dictionaries
-
- links_dictionaries=>\@my_link_dicts
- links_dictionaries=>['url_links.dict', 'format_links.dict']
- "--links_dictionaries", "url_links.dict", "--links_dictionaries", "format_links.dict"
-
-File(s) to use as a link-dictionary. There can be more than one of
-these. These are in addition to the Global Link Dictionary and the User
-Link Dictionary. When the arguments are given as a hash, this expects a
-reference to an array of filenames. When the arguments are given as a
-reference to an array, then the "--links_dictionaries" option must be
-repeated for each new file added to the list. If you want to reset the
-list to be empty, give the special value of "CLEAR".
-
-=item link_only
-
- link_only=>1
-
-Do no escaping or marking up at all, except for processing the links
-dictionary file and applying it. This is useful if you want to use
-the linking feature on an HTML document. If the HTML is a
-complete document (includes HTML,HEAD,BODY tags, etc) then you'll
-probably want to use the --extract option also.
-(default: false)
-
-=item lower_case_tags
-
- lower_case_tags=>1
-
-Force all tags to be in lower-case.
-
-=item mailmode
-
- mailmode=>1
-
-Deal with mail headers & quoted text. The mail header paragraph is
-given the class 'mail_header', and mail-quoted text is given the class
-'quote_mail'.
-(default: false)
-
-=item make_anchors
-
- make_anchors=>0
-
-Should we try to make anchors in headings?
-(default: true)
-
-=item make_links
-
- make_links=>0
-
-Should we try to build links? If this is false, then the links
-dictionaries are not consulted and only structural text-to-HTML
-conversion is done. (default: true)
-
-=item make_tables
-
- make_tables=>1
-
-Should we try to build tables? If true, spots tables and marks them up
-appropriately. See L</Input File Format> for information on how tables
-should be formatted.
-
-This overrides the detection of lists; if something looks like a table,
-it is taken as a table, and list-checking is not done for that
-paragraph.
-
-(default: false)
-
-=item min_caps_length
-
- min_caps_length=>I<n>
-
-min sequential CAPS for an all-caps line
-(default: 3)
-
-=item outfile
-
- outfile=>I<filename>
-
-The name of the output file. If it is "-" then the output goes
-to Standard Output.
-(default: - )
-
-=item outhandle
-
-The output filehandle; if this is given then the output goes
-to this filehandle instead of to the file given in L</outfile>.
-
-=item par_indent
-
- par_indent=>I<n>
-
-Minumum number of spaces indented in first lines of paragraphs.
- Only used when there's no blank line
-preceding the new paragraph.
-(default: 2)
-
-=item preformat_trigger_lines
-
- preformat_trigger_lines=>I<n>
-
-How many lines of preformatted-looking text are needed to switch to <PRE>
- <= 0 : Preformat entire document
- 1 : one line triggers
- >= 2 : two lines trigger
-
-(default: 2)
-
-=item endpreformat_trigger_lines
-
- endpreformat_trigger_lines=>I<n>
-
-How many lines of unpreformatted-looking text are needed to switch from <PRE>
- <= 0 : Never preformat within document
- 1 : one line triggers
- >= 2 : two lines trigger
-(default: 2)
-
-NOTE for preformat_trigger_lines and endpreformat_trigger_lines:
-A zero takes precedence. If one is zero, the other is ignored.
-If both are zero, entire document is preformatted.
-
-=item preformat_start_marker
-
- preformat_start_marker=>I<regexp>
-
-What flags the start of a preformatted section if --use_preformat_marker
-is true.
-
-(default: "^(:?(:?&lt;)|<)PRE(:?(:?&gt;)|>)\$")
-
-=item preformat_end_marker
-
- preformat_end_marker=>I<regexp>
-
-What flags the end of a preformatted section if --use_preformat_marker
-is true.
-
-(default: "^(:?(:?&lt;)|<)/PRE(:?(:?&gt;)|>)\$")
-
-=item preformat_whitespace_min
-
- preformat_whitespace_min=>I<n>
-
-Minimum number of consecutive whitespace characters to trigger
-normal preformatting.
-NOTE: Tabs are expanded to spaces before this check is made.
-That means if B<tab_width> is 8 and this is 5, then one tab may be
-expanded to 8 spaces, which is enough to trigger preformatting.
-(default: 5)
-
-=item prepend_file
-
- prepend_file=>I<filename>
-
-If you want something prepended to the processed body text, put the
-filename here. The prepended text will not be processed at all, so make
-sure it's plain text or decent HTML.
-
-(default: nothing)
-
-=item preserve_indent
-
- preserve_indent=>1
-
-Preserve the first-line indentation of paragraphs marked with indents
-by replacing the spaces of the first line with non-breaking spaces.
-(default: false)
-
-=item short_line_length
-
- short_line_length=>I<n>
-
-Lines this short (or shorter) must be intentionally broken and are kept
-that short.
-(default: 40)
-
-=item style_url
-
- style_url=>I<url>
-
-This gives the URL of a stylesheet; a LINK tag will be added to the
-output.
-
-=item tab_width
-
- tab_width=>I<n>
-
-How many spaces equal a tab?
-(default: 8)
-
-=item table_type
-
- table_type=>{ ALIGN=>0, PGSQL=>0, BORDER=>1, DELIM=>0 }
-
-This determines which types of tables will be recognised when "make_tables"
-is true. The possible types are ALIGN, PGSQL, BORDER and DELIM.
-(default: all types are true)
-
-=item title
-
- title=>I<title>
-
-You can specify a title. Otherwise it will use a blank one.
-(default: nothing)
-
-=item titlefirst
-
- titlefirst=>1
-
-Use the first non-blank line as the title.
-
-=item underline_length_tolerance
-
- underline_length_tolerance=>I<n>
-
-How much longer or shorter can underlines be and still be underlines?
-(default: 1)
-
-=item underline_offset_tolerance
-
- underline_offset_tolerance=>I<n>
-
-How far offset can underlines be and still be underlines?
-(default: 1)
-
-=item unhyphenation
-
- unhyphenation=>0
-
-Enables unhyphenation of text.
-(default: true)
-
-=item use_mosaic_header
-
- use_mosaic_header=>1
-
-Use this option if you want to force the heading styles to match what Mosaic
-outputs. (Underlined with "***"s is H1,
-with "==="s is H2, with "+++" is H3, with "---" is H4, with "~~~" is H5
-and with "..." is H6)
-This was the behavior of txt2html up to version 1.10.
-(default: false)
-
-=item use_preformat_marker
-
- use_preformat_marker=>1
-
-Turn on preformatting when encountering "<PRE>" on a line by itself, and turn
-it off when there's a line containing only "</PRE>".
-When such preformatted text is detected, the PRE tag will be given the
-class 'quote_explicit'.
-(default: off)
-
-=item xhtml
-
- xhtml=>1
-
-Try to make the output conform to the XHTML standard, including
-closing all open tags and marking empty tags correctly. This
-turns on --lower_case_tags and overrides the --doctype option.
-Note that if you add a header or a footer file, it is up to you
-to make it conform; the header/footer isn't touched by this.
-Likewise, if you make link-dictionary entries that break XHTML,
-then this won't fix them, except to the degree of putting all tags
-into lower-case.
-
-=back
-
-=head1 METHODS
-
-=cut
-
-#------------------------------------------------------------------------
-
-require Exporter;
-use Data::Dumper;
-
-our $PROG = 'HTML::TextToHTML';
-
-#------------------------------------------------------------------------
-use constant TEXT_TO_HTML => "TEXT_TO_HTML";
-
-########################################
-# Definitions (Don't change these)
-#
-
-# These are just constants I use for making bit vectors to keep track
-# of what modes I'm in and what actions I've taken on the current and
-# previous lines.
-
-our $NONE = 0;
-our $LIST = 1;
-our $HRULE = 2;
-our $PAR = 4;
-our $PRE = 8;
-our $END = 16;
-our $BREAK = 32;
-our $HEADER = 64;
-our $MAILHEADER = 128;
-our $MAILQUOTE = 256;
-our $CAPS = 512;
-our $LINK = 1024;
-our $PRE_EXPLICIT = 2048;
-our $TABLE = 4096;
-our $IND_BREAK = 8192;
-our $LIST_START = 16384;
-our $LIST_ITEM = 32768;
-
-# Constants for Link-processing
-# bit-vectors for what to do with a particular link-dictionary entry
-our $LINK_NOCASE = 1;
-our $LINK_EVAL = 2;
-our $LINK_HTML = 4;
-our $LINK_ONCE = 8;
-our $LINK_SECT_ONCE = 16;
-
-# Constants for Ordered Lists and Unordered Lists.
-# And Definition Lists.
-# I use this in the list stack to keep track of what's what.
-
-our $OL = 1;
-our $UL = 2;
-our $DL = 3;
-
-# Constants for table types
-our $TAB_ALIGN = 1;
-our $TAB_PGSQL = 2;
-our $TAB_BORDER = 3;
-our $TAB_DELIM = 4;
-
-# Character entity names
-# characters to replace with entities
-our %char_entities = (
- "\241", "&iexcl;", "\242", "&cent;", "\243", "&pound;",
- "\244", "&curren;", "\245", "&yen;", "\246", "&brvbar;",
- "\247", "&sect;", "\250", "&uml;", "\251", "&copy;",
- "\252", "&ordf;", "\253", "&laquo;", "\254", "&not;",
- "\255", "&shy;", "\256", "&reg;", "\257", "&hibar;",
- "\260", "&deg;", "\261", "&plusmn;", "\262", "&sup2;",
- "\263", "&sup3;", "\264", "&acute;", "\265", "&micro;",
- "\266", "&para;", "\270", "&cedil;", "\271", "&sup1;",
- "\272", "&ordm;", "\273", "&raquo;", "\274", "&frac14;",
- "\275", "&frac12;", "\276", "&frac34;", "\277", "&iquest;",
- "\300", "&Agrave;", "\301", "&Aacute;", "\302", "&Acirc;",
- "\303", "&Atilde;", "\304", "&Auml;", "\305", "&Aring;",
- "\306", "&AElig;", "\307", "&Ccedil;", "\310", "&Egrave;",
- "\311", "&Eacute;", "\312", "&Ecirc;", "\313", "&Euml;",
- "\314", "&Igrave;", "\315", "&Iacute;", "\316", "&Icirc;",
- "\317", "&Iuml;", "\320", "&ETH;", "\321", "&Ntilde;",
- "\322", "&Ograve;", "\323", "&Oacute;", "\324", "&Ocirc;",
- "\325", "&Otilde;", "\326", "&Ouml;", "\327", "&times;",
- "\330", "&Oslash;", "\331", "&Ugrave;", "\332", "&Uacute;",
- "\333", "&Ucirc;", "\334", "&Uuml;", "\335", "&Yacute;",
- "\336", "&THORN;", "\337", "&szlig;", "\340", "&agrave;",
- "\341", "&aacute;", "\342", "&acirc;", "\343", "&atilde;",
- "\344", "&auml;", "\345", "&aring;", "\346", "&aelig;",
- "\347", "&ccedil;", "\350", "&egrave;", "\351", "&eacute;",
- "\352", "&ecirc;", "\353", "&euml;", "\354", "&igrave;",
- "\355", "&iacute;", "\356", "&icirc;", "\357", "&iuml;",
- "\360", "&eth;", "\361", "&ntilde;", "\362", "&ograve;",
- "\363", "&oacute;", "\364", "&ocirc;", "\365", "&otilde;",
- "\366", "&ouml;", "\367", "&divide;", "\370", "&oslash;",
- "\371", "&ugrave;", "\372", "&uacute;", "\373", "&ucirc;",
- "\374", "&uuml;", "\375", "&yacute;", "\376", "&thorn;",
- "\377", "&yuml;", "\267", "&middot;",
-);
-
-# alignments for tables
-our @alignments = ('', '', ' ALIGN="RIGHT"', ' ALIGN="CENTER"');
-our @lc_alignments = ('', '', ' align="right"', ' align="center"');
-our @xhtml_alignments =
- ('', '', ' style="text-align: right;"', ' style="text-align: center;"');
-
-#---------------------------------------------------------------#
-# Object interface
-#---------------------------------------------------------------#
-
-=head2 new
-
- $conv = new HTML::TextToHTML()
-
- $conv = new HTML::TextToHTML(titlefirst=>1,
- ...
- );
-
-Create a new object with new. If one argument is given, it is assumed
-to be a reference to an array of arguments. If more than one argument
-is given, it is assumed to be a hash of arguments. These arguments will
-be used in invocations of other methods.
-
-See L</OPTIONS> for the possible values of the arguments.
-
-=cut
-
-sub new
-{
- my $invocant = shift;
- my $self = {};
-
- my $class = ref($invocant) || $invocant; # Object or class name
- init_our_data($self);
-
- # bless self
- bless($self, $class);
-
- $self->args(@_);
-
- return $self;
-} # new
-
-=head2 args
-
- $conv->args(short_line_length=>60,
- titlefirst=>1,
- ....
- );
-
-Updates the current arguments/options of the HTML::TextToHTML object.
-Takes either a hash, or a reference to an array of arguments, which will
-be used in invocations of other methods.
-See L</OPTIONS> for the possible values of the arguments.
-
-NOTE: the reference-to-an-array usage is DEPRECATED and will be removed
-in the future.
-
-=cut
-
-sub args
-{
- my $self = shift;
- my %args = ();
- my @arg_array = ();
- if ( @_
- && @_ == 1
- && ref $_[0] eq 'ARRAY')
- {
- # this is a reference to an array -- use the old style args
- my $aref = shift;
- @arg_array = @{$aref};
- }
- elsif (@_)
- {
- %args = @_;
- }
-
- if (%args)
- {
- if ($self->{debug})
- {
- print STDERR "========args(hash)========\n";
- print STDERR Dumper(%args);
- }
- foreach my $arg (keys %args)
- {
- if (defined $args{$arg})
- {
- if ($arg =~ /^-/)
- {
- $arg =~ s/^-//; # get rid of first dash
- $arg =~ s/^-//; # get rid of possible second dash
- }
- if ($self->{debug})
- {
- print STDERR "--", $arg;
- }
- $self->{$arg} = $args{$arg};
- if ($self->{debug})
- {
- print STDERR " ", $args{$arg}, "\n";
- }
- }
- }
- }
- elsif (@arg_array)
- {
- if ($self->{debug})
- {
- print STDERR "========args(array)========\n";
- print STDERR Dumper(@arg_array);
- }
- # the arg array may have filenames at the end of it,
- # so don't consume them
- my $look_at_args = 1;
- while (@arg_array && $look_at_args)
- {
- my $arg = shift @arg_array;
- # check for arguments which are bools,
- # and thus have no companion value
- if ($arg =~ /^-/)
- {
- $arg =~ s/^-//; # get rid of first dash
- $arg =~ s/^-//; # get rid of possible second dash
- if ($self->{debug})
- {
- print STDERR "--", $arg;
- }
- if ( $arg eq 'debug'
- || $arg eq 'demoronize'
- || $arg eq 'eight_bit_clean'
- || $arg eq 'escape_HTML_chars'
- || $arg eq 'explicit_headings'
- || $arg eq 'extract'
- || $arg eq 'link_only'
- || $arg eq 'lower_case_tags'
- || $arg eq 'mailmode'
- || $arg eq 'make_anchors'
- || $arg eq 'make_links'
- || $arg eq 'make_tables'
- || $arg eq 'preserve_indent'
- || $arg eq 'titlefirst'
- || $arg eq 'unhyphenation'
- || $arg eq 'use_mosaic_header'
- || $arg eq 'use_preformat_marker'
- || $arg eq 'verbose'
- || $arg eq 'xhtml')
- {
- $self->{$arg} = 1;
- if ($self->{debug})
- {
- print STDERR "=true\n";
- }
- }
- elsif ($arg eq 'nodebug'
- || $arg eq 'nodemoronize'
- || $arg eq 'noeight_bit_clean'
- || $arg eq 'noescape_HTML_chars'
- || $arg eq 'noexplicit_headings'
- || $arg eq 'noextract'
- || $arg eq 'nolink_only'
- || $arg eq 'nolower_case_tags'
- || $arg eq 'nomailmode'
- || $arg eq 'nomake_anchors'
- || $arg eq 'nomake_links'
- || $arg eq 'nomake_tables'
- || $arg eq 'nopreserve_indent'
- || $arg eq 'notitlefirst'
- || $arg eq 'nounhyphenation'
- || $arg eq 'nouse_mosaic_header'
- || $arg eq 'nouse_preformat_marker'
- || $arg eq 'noverbose'
- || $arg eq 'noxhtml')
- {
- $arg =~ s/^no//;
- $self->{$arg} = 0;
- if ($self->{debug})
- {
- print STDERR " $arg=false\n";
- }
- }
- else
- {
- my $val = shift @arg_array;
- if ($self->{debug})
- {
- print STDERR "=", $val, "\n";
- }
- # check the types
- if (defined $arg && defined $val)
- {
- if ( $arg eq 'infile'
- || $arg eq 'custom_heading_regexp'
- || $arg eq 'links_dictionaries')
- { # arrays
- if ($val eq 'CLEAR')
- {
- $self->{$arg} = [];
- }
- else
- {
- push @{$self->{$arg}}, $val;
- }
- }
- elsif ($arg eq 'file')
- { # alternate for 'infile'
- if ($val eq 'CLEAR')
- {
- $self->{infile} = [];
- }
- else
- {
- push @{$self->{infile}}, $val;
- }
- }
- elsif ($arg eq 'table_type')
- {
- # hash
- if ($val eq 'CLEAR')
- {
- $self->{$arg} = {};
- }
- else
- {
- my ($f1, $v1) = split(/=/, $val, 2);
- $self->{$arg}->{$f1} = $v1;
- }
- }
- else
- {
- $self->{$arg} = $val;
- }
- }
- }
- }
- else
- {
- # if an option don't start with - then we've
- # come to the end of the options
- $look_at_args = 0;
- }
- }
- }
- if ($self->{debug})
- {
- print STDERR Dumper($self);
- }
-
- return 1;
-} # args
-
-=head2 process_chunk
-
-$newstring = $conv->process_chunk($mystring);
-
-Convert a string to a HTML fragment. This assumes that this string is
-at the least, a single paragraph, but it can contain more than that.
-This returns the processed string. If you want to pass arguments to
-alter the behaviour of this conversion, you need to do that earlier,
-either when you create the object, or with the L</args> method.
-
- $newstring = $conv->process_chunk($mystring,
- close_tags=>0);
-
-If there are open tags (such as lists) in the input string,
-process_chunk will now automatically close them, unless you specify not
-to, with the close_tags option.
-
- $newstring = $conv->process_chunk($mystring,
- is_fragment=>1);
-
-If you want this string to be treated as a fragment, and not assumed to
-be a paragraph, set is_fragment to true. If there is more than one
-paragraph in the string (ie it contains blank lines) then this option
-will be ignored.
-
-=cut
-
-sub process_chunk ($$;%)
-{
- my $self = shift;
- my $chunk = shift;
- my %args = (
- close_tags => 1,
- is_fragment => 0,
- @_
- );
-
- my $ret_str = '';
- my @paras = split(/\r?\n\r?\n/, $chunk);
- my $ind = 0;
- if (@paras == 1) # just one paragraph
- {
- $ret_str .= $self->process_para(
- $chunk,
- close_tags => $args{close_tags},
- is_fragment => $args{is_fragment}
- );
- }
- else
- {
- my $ind = 0;
- foreach my $para (@paras)
- {
- # if the paragraph doesn't end with a newline, add one
- $para .= "\n" if ($para !~ /\n$/);
- if ($ind == @paras - 1) # last one
- {
- $ret_str .= $self->process_para(
- $para,
- close_tags => $args{close_tags},
- is_fragment => 0
- );
- }
- else
- {
- $ret_str .= $self->process_para(
- $para,
- close_tags => 0,
- is_fragment => 0
- );
- }
- $ind++;
- }
- }
- $ret_str;
-} # process_chunk
-
-=head2 process_para
-
-$newstring = $conv->process_para($mystring);
-
-Convert a string to a HTML fragment. This assumes that this string is
-at the most a single paragraph, with no blank lines in it. If you don't
-know whether your string will contain blank lines or not, use the
-L</process_chunk> method instead.
-
-This returns the processed string. If you want to pass arguments to
-alter the behaviour of this conversion, you need to do that earlier,
-either when you create the object, or with the L</args> method.
-
- $newstring = $conv->process_para($mystring,
- close_tags=>0);
-
-If there are open tags (such as lists) in the input string, process_para
-will now automatically close them, unless you specify not to, with the
-close_tags option.
-
- $newstring = $conv->process_para($mystring,
- is_fragment=>1);
-
-If you want this string to be treated as a fragment, and not assumed to be
-a paragraph, set is_fragment to true.
-
-=cut
-
-sub process_para ($$;%)
-{
- my $self = shift;
- my $para = shift;
- my %args = (
- close_tags => 1,
- is_fragment => 0,
- @_
- );
-
- # if this is an external call, do certain initializations
- $self->do_init_call();
-
- my $para_action = $NONE;
-
- # tables and mailheaders don't carry over from one para to the next
- if ($self->{__mode} & $TABLE)
- {
- $self->{__mode} ^= $TABLE;
- }
- if ($self->{__mode} & $MAILHEADER)
- {
- $self->{__mode} ^= $MAILHEADER;
- }
-
- # convert Microsoft character codes into sensible characters
- if ($self->{demoronize})
- {
- demoronize_char($para);
- }
-
- # if we are not just linking, we are discerning structure
- if (!$self->{link_only})
- {
-
- # Chop trailing whitespace and DOS CRs
- $para =~ s/[ \011]*\015$//;
- # Chop leading whitespace and DOS CRs
- $para =~ s/^[ \011]*\015//;
- $para =~ s/\r//g; # remove any stray carriage returns
-
- my @done_lines = (); # lines which have been processed
-
- # The PRE_EXPLICIT structure can carry over from one
- # paragraph to the next, but it is ended with the
- # explicit end-tag designated for it.
- # Therefore we can shortcut for this by checking
- # for the end of the PRE_EXPLICIT and chomping off
- # the preformatted string part of this para before
- # we have to split it into lines.
- # Note that after this check, we could *still* be
- # in PRE_EXPLICIT mode.
- if ($self->{__mode} & $PRE_EXPLICIT)
- {
- my $pre_str =
- $self->split_end_explicit_preformat(para_ref => \$para);
- if ($pre_str)
- {
- push @done_lines, $pre_str;
- }
- }
-
- if (defined $para && $para ne "")
- {
- #
- # Now we split the paragraph into lines
- #
- my $para_len = length($para);
- my @para_lines = split(/^/, $para);
- my @para_line_len = ();
- my @para_line_indent = ();
- my @para_line_action = ();
- my $i = 0;
- foreach my $line (@para_lines)
- {
- # Change all tabs to spaces
- while ($line =~ /\011/)
- {
- my $tw = $self->{tab_width};
- $line =~ s/\011/" " x ($tw - (length($`) % $tw))/e;
- }
- push @para_line_len, length($line);
- if ($line =~ /^\s*$/)
- {
- # if the line is blank, use the previous indent
- # if there is one
- push @para_line_indent,
- ($i == 0 ? 0 : $para_line_indent[$i - 1]);
- }
- else
- {
- # count the number of leading spaces
- my ($ws) = $line =~ /^( *)[^ ]/;
- push @para_line_indent, length($ws);
- }
- push @para_line_action, $NONE;
- $i++;
- }
-
- # There are two more structures which carry over from one
- # paragraph to the next: LIST, PRE
- # There are also certain things which will immediately end
- # multi-paragraph LIST and PRE, if found at the start
- # of a paragraph:
- # A list will be ended by
- # TABLE, MAILHEADER, HEADER, custom-header
- # A PRE will be ended by
- # TABLE, MAILHEADER and non-pre text
-
- my $is_table = 0;
- my $table_type = 0;
- my $is_mailheader = 0;
- my $is_header = 0;
- my $is_custom_header = 0;
- if (@{$self->{custom_heading_regexp}})
- {
- $is_custom_header =
- $self->is_custom_heading(line => $para_lines[0]);
- }
- if ( $self->{make_tables}
- && @para_lines > 1)
- {
- $table_type = $self->get_table_type(
- rows_ref => \@para_lines,
- para_len => $para_len
- );
- $is_table = ($table_type != 0);
- }
- if ( !$self->{explicit_headings}
- && @para_lines > 1
- && !$is_table)
- {
- $is_header = $self->is_heading(
- line_ref => \$para_lines[0],
- next_ref => \$para_lines[1]
- );
- }
- # Note that it is concievable that someone has
- # partially disabled mailmode by making a custom header
- # which matches the start of mail.
- # This is stupid, but allowable, so we check.
- if ( $self->{mailmode}
- && !$is_table
- && !$is_custom_header)
- {
- $is_mailheader = $self->is_mailheader(rows_ref => \@para_lines);
- }
-
- # end the list if we can end it
- if (
- ($self->{__mode} & $LIST)
- && ( $is_table
- || $is_mailheader
- || $is_header
- || $is_custom_header)
- )
- {
- my $list_end = '';
- my $action = 0;
- $self->endlist(
- num_lists => $self->{__listnum},
- prev_ref => \$list_end,
- line_action_ref => \$action
- );
- push @done_lines, $list_end;
- $self->{__prev_para_action} |= $END;
- }
-
- # end the PRE if we can end it
- if (
- ($self->{__mode} & $PRE)
- && !($self->{__mode} & $PRE_EXPLICIT)
- && ( $is_table
- || $is_mailheader
- || !$self->is_preformatted($para_lines[0]))
- && ($self->{preformat_trigger_lines} != 0)
- )
- {
- my $pre_end = '';
- my $tag = $self->close_tag('PRE');
- $pre_end = "${tag}\n";
- $self->{__mode} ^= ($PRE & $self->{__mode});
- push @done_lines, $pre_end;
- $self->{__prev_para_action} |= $END;
- }
-
- # The PRE and PRE_EXPLICIT structure can carry over
- # from one paragraph to the next, but because we don't
- # want trailing newlines, such newlines would have been
- # gotten rid of in the previous call. However, with
- # a preformatted text, we do want the blank lines in it
- # to be preserved, so let's add a blank line in here.
- if ($self->{__mode} & $PRE)
- {
- push @done_lines, "\n";
- }
-
- # Now, we do certain things which are only found at the
- # start of a paragraph:
- # HEADER, custom-header, TABLE and MAILHEADER
- # These could concievably eat the rest of the paragraph.
-
- if ($is_custom_header)
- {
- # custom header eats the first line
- my $header = shift @para_lines;
- shift @para_line_len;
- shift @para_line_indent;
- shift @para_line_action;
- $self->custom_heading(line_ref => \$header);
- push @done_lines, $header;
- $self->{__prev_para_action} |= $HEADER;
- }
- elsif ($is_header)
- {
- # normal header eats the first two lines
- my $header = shift @para_lines;
- shift @para_line_len;
- shift @para_line_indent;
- shift @para_line_action;
- my $underline = shift @para_lines;
- shift @para_line_len;
- shift @para_line_indent;
- shift @para_line_action;
- $self->heading(
- line_ref => \$header,
- next_ref => \$underline
- );
- push @done_lines, $header;
- $self->{__prev_para_action} |= $HEADER;
- }
-
- # do the table stuff on the array of lines
- if ($self->{make_tables} && $is_table)
- {
- if (
- $self->tablestuff(
- table_type => $table_type,
- rows_ref => \@para_lines,
- para_len => $para_len
- )
- )
- {
- # this has used up all the lines
- push @done_lines, @para_lines;
- @para_lines = ();
- }
- }
-
- # check of this para is a mail-header
- if ( $is_mailheader
- && !($self->{__mode} & $TABLE)
- && @para_lines)
- {
- $self->mailheader(rows_ref => \@para_lines);
- # this has used up all the lines
- push @done_lines, @para_lines;
- @para_lines = ();
- }
-
- #
- # Now go through the paragraph lines one at a time
- # Note that we won't have TABLE, MAILHEADER, HEADER modes
- # because they would have eaten the lines
- #
- my $prev = '';
- my $prev_action = $self->{__prev_para_action};
- for (my $i = 0; $i < @para_lines; $i++)
- {
- my $prev_ref;
- my $prev_action_ref;
- my $prev_line_indent;
- my $prev_line_len;
- if ($i == 0)
- {
- $prev_ref = \$prev;
- $prev_action_ref = \$prev_action;
- $prev_line_indent = 0;
- $prev_line_len = 0;
- }
- else
- {
- $prev_ref = \$para_lines[$i - 1];
- $prev_action_ref = \$para_line_action[$i - 1];
- $prev_line_indent = $para_line_indent[$i - 1];
- $prev_line_len = $para_line_len[$i - 1];
- }
- my $next_ref;
- if ($i == $#para_lines)
- {
- $next_ref = undef;
- }
- else
- {
- $next_ref = \$para_lines[$i + 1];
- }
-
- $para_lines[$i] = escape($para_lines[$i])
- if ($self->{escape_HTML_chars});
-
- if ($self->{mailmode}
- && !($self->{__mode} & ($PRE_EXPLICIT)))
- {
- $self->mailquote(
- line_ref => \$para_lines[$i],
- line_action_ref => \$para_line_action[$i],
- prev_ref => $prev_ref,
- prev_action_ref => $prev_action_ref,
- next_ref => $next_ref
- );
- }
-
- if ( ($self->{__mode} & $PRE)
- && ($self->{preformat_trigger_lines} != 0))
- {
- $self->endpreformat(
- para_lines_ref => \@para_lines,
- para_action_ref => \@para_line_action,
- ind => $i,
- prev_ref => $prev_ref
- );
- }
-
- if (!($self->{__mode} & $PRE))
- {
- $self->hrule(
- para_lines_ref => \@para_lines,
- para_action_ref => \@para_line_action,
- ind => $i
- );
- }
- if (!($self->{__mode} & ($PRE))
- && ($para_lines[$i] !~ /^\s*$/))
- {
- $self->liststuff(
- para_lines_ref => \@para_lines,
- para_action_ref => \@para_line_action,
- para_line_indent_ref => \@para_line_indent,
- ind => $i,
- prev_ref => $prev_ref
- );
- }
- if ( !($para_line_action[$i] & ($HEADER | $LIST))
- && !($self->{__mode} & ($LIST | $PRE))
- && $self->{__preformat_enabled})
- {
- $self->preformat(
- mode_ref => \$self->{__mode},
- line_ref => \$para_lines[$i],
- line_action_ref => \$para_line_action[$i],
- prev_ref => $prev_ref,
- next_ref => $next_ref,
- prev_action_ref => $prev_action_ref
- );
- }
- if (!($self->{__mode} & ($PRE)))
- {
- $self->paragraph(
- line_ref => \$para_lines[$i],
- line_action_ref => \$para_line_action[$i],
- prev_ref => $prev_ref,
- prev_action_ref => $prev_action_ref,
- line_indent => $para_line_indent[$i],
- prev_indent => $prev_line_indent,
- is_fragment => $args{is_fragment},
- ind => $i,
- );
- }
- if (!($self->{__mode} & ($PRE | $LIST)))
- {
- $self->shortline(
- line_ref => \$para_lines[$i],
- line_action_ref => \$para_line_action[$i],
- prev_ref => $prev_ref,
- prev_action_ref => $prev_action_ref,
- prev_line_len => $prev_line_len
- );
- }
- if (!($self->{__mode} & ($PRE)))
- {
- $self->caps(
- line_ref => \$para_lines[$i],
- line_action_ref => \$para_line_action[$i]
- );
- }
-
- # put the "prev" line in front of the first line
- $para_lines[$i] = $prev . $para_lines[$i]
- if ($i == 0 && ($prev !~ /^\s*$/));
- }
-
- # para action is the action of the last line of the para
- $para_action = $para_line_action[$#para_line_action];
- $para_action = $NONE if (!defined $para_action);
-
- # push them on the done lines
- push @done_lines, @para_lines;
- @para_lines = ();
-
- }
- # now put the para back together as one string
- $para = join('', @done_lines);
-
- # if this is a paragraph, and we are in XHTML mode,
- # close an open paragraph.
- if ($self->{xhtml})
- {
- my $open_tag = @{$self->{__tags}}[$#{$self->{__tags}}];
- if (defined $open_tag && $open_tag eq 'P')
- {
- $para .= $self->close_tag('P');
- }
- }
-
- if (
- $self->{unhyphenation}
-
- # ends in hyphen & next line starts w/letters
- && ($para =~ /[^\W\d_]\-\n\s*[^\W\d_]/s) && !(
- $self->{__mode} &
- ($PRE | $HEADER | $MAILHEADER | $TABLE | $BREAK)
- )
- )
- {
- $self->unhyphenate_para(\$para);
- }
- # chop trailing newlines for continuing lists and PRE
- if ( $self->{__mode} & $LIST
- || $self->{__mode} & $PRE)
- {
- $para =~ s/\n$//g;
- }
- }
-
- # apply links and bold/italic formatting
- if ($para !~ /^\s*$/)
- {
- $self->apply_links(
- para_ref => \$para,
- para_action_ref => \$para_action
- );
- }
-
- # close any open lists if required to
- if ( $args{close_tags}
- && $self->{__mode} & $LIST) # End all lists
- {
- $self->endlist(
- num_lists => $self->{__listnum},
- prev_ref => \$para,
- line_action_ref => \$para_action
- );
- }
- # close any open tags
- if ($args{close_tags} && $self->{xhtml})
- {
- while (@{$self->{__tags}})
- {
- $para .= $self->close_tag('');
- }
- }
-
- # convert remaining Microsoft character codes into sensible HTML
- if ($self->{demoronize})
- {
- $para = demoronize_code($para);
- }
- # All the matching and formatting is done. Now we can
- # replace non-ASCII characters with character entities.
- if (!$self->{eight_bit_clean})
- {
- my @chars = split(//, $para);
- foreach $_ (@chars)
- {
- $_ = $char_entities{$_} if defined($char_entities{$_});
- }
- $para = join('', @chars);
- }
-
- $self->{__prev_para_action} = $para_action;
-
- return $para;
-} # process_para
-
-=head2 txt2html
-
- $conv->txt2html(%args);
-
-Convert a text file to HTML. Takes a hash of arguments, or a reference
-to an array of arguments to customize the conversion; (this includes
-saying what file to convert!) See L</OPTIONS> for the possible values of
-the arguments. Arguments which have already been set with B<new> or
-B<args> will remain as they are, unless they are overridden.
-
-=cut
-
-sub txt2html ($;$)
-{
- my $self = shift;
-
- if (@_)
- {
- $self->args(@_);
- }
-
- $self->do_init_call();
-
- my $outhandle;
- my $outhandle_needs_closing;
-
- # set up the output
- if ($self->{outhandle})
- {
- $outhandle = $self->{outhandle};
- $outhandle_needs_closing = 1;
- }
- elsif ($self->{outfile} eq "-")
- {
- $outhandle = *STDOUT;
- $outhandle_needs_closing = 0;
- }
- else
- {
- open($outhandle, "> " . $self->{outfile})
- || die "Error: unable to open ", $self->{outfile}, ": $!\n";
- $outhandle_needs_closing = 1;
- }
-
- # slurp up a paragraph at a time, a file at a time
- local $/ = "";
- my $para = '';
- my $count = 0;
- my $print_count = 0;
- my @sources = ();
- my $source_type;
- if ($self->{infile} and @{$self->{infile}})
- {
- @sources = @{$self->{infile}};
- $source_type = 'file';
- }
- elsif ($self->{inhandle} and @{$self->{inhandle}})
- {
- @sources = @{$self->{inhandle}};
- $source_type = 'filehandle';
- }
- elsif ($self->{instring} and @{$self->{instring}})
- {
- @sources = @{$self->{instring}};
- $source_type = 'string';
- }
- my $inhandle;
- my $inhandle_needs_closing = 0;
- foreach my $source (@sources)
- {
- $inhandle = undef;
- if ($source_type eq 'file')
- {
- if (!$source or $source eq '-')
- {
- $inhandle = *STDIN;
- $inhandle_needs_closing = 0;
- }
- else
- {
- if (-f $source && open($inhandle, $source))
- {
- $inhandle_needs_closing = 1;
- }
- else # error
- {
- warn "Could not open $source\n";
- next;
- }
- }
- }
- elsif ($source_type eq 'filehandle')
- {
- $inhandle = $source;
- $inhandle_needs_closing = 1;
- }
- if ($source_type eq 'string')
- {
- # process the string
- $para = $_;
- $para =~ s/\n$//; # trim the endline
- if ($count == 0)
- {
- $self->do_file_start($outhandle, $para);
- }
- $self->{__done_with_sect_link} = [];
- $para = $self->process_chunk($para, close_tags => 0);
- print $outhandle $para, "\n";
- $print_count++;
- $count++;
- }
- else # file or filehandle
- {
- while (<$inhandle>)
- {
- $para = $_;
- $para =~ s/\n$//; # trim the endline
- if ($count == 0)
- {
- $self->do_file_start($outhandle, $para);
- }
- $self->{__done_with_sect_link} = [];
- $para = $self->process_chunk($para, close_tags => 0);
- print $outhandle $para, "\n";
- $print_count++;
- $count++;
- }
- if ($inhandle_needs_closing)
- {
- close($inhandle);
- }
- }
- } # for each file
-
- $self->{__prev} = "";
- if ($self->{__mode} & $LIST) # End all lists
- {
- $self->endlist(
- num_lists => $self->{__listnum},
- prev_ref => \$self->{__prev},
- line_action_ref => \$self->{__line_action}
- );
- }
- print $outhandle $self->{__prev};
-
- # end open preformats
- if ($self->{__mode} & $PRE)
- {
- my $tag = $self->close_tag('PRE');
- print $outhandle $tag;
- }
-
- # close all open tags
- if ( $self->{xhtml}
- && !$self->{extract}
- && @{$self->{__tags}})
- {
- if ($self->{dict_debug} & 8)
- {
- print STDERR "closing all tags at end\n";
- }
- # close any open tags (until we get to the body)
- my $open_tag = @{$self->{__tags}}[$#{$self->{__tags}}];
- while (@{$self->{__tags}}
- && $open_tag ne 'BODY'
- && $open_tag ne 'HTML')
- {
- print $outhandle $self->close_tag('');
- $open_tag = @{$self->{__tags}}[$#{$self->{__tags}}];
- }
- print $outhandle "\n";
- }
-
- if ($self->{append_file})
- {
- if (-r $self->{append_file})
- {
- open(APPEND, $self->{append_file});
- while (<APPEND>)
- {
- print $outhandle $_;
- $print_count++;
- }
- close(APPEND);
- }
- else
- {
- print STDERR "Can't find or read file ", $self->{append_file},
- " to append.\n";
- }
- }
-
- # print the closing tags (if we have printed stuff at all)
- if ($print_count && !$self->{extract})
- {
- print $outhandle $self->close_tag('BODY'), "\n";
- print $outhandle $self->close_tag('HTML'), "\n";
- }
- if ($outhandle_needs_closing)
- {
- close($outhandle);
- }
- return 1;
-}
-
-#---------------------------------------------------------------#
-# Init-related subroutines
-
-#--------------------------------#
-# Name: init_our_data
-# Args:
-# $self
-sub init_our_data ($)
-{
- my $self = shift;
-
- $self->{debug} = 0;
-
- #
- # All the options, in alphabetical order
- #
- $self->{append_file} = '';
- $self->{append_head} = '';
- $self->{body_deco} = '';
- $self->{bullets} = '-=o*\267';
- $self->{bullets_ordered} = '';
- $self->{bold_delimiter} = '#';
- $self->{caps_tag} = 'STRONG';
- $self->{custom_heading_regexp} = [];
- $self->{default_link_dict} =
- ($ENV{HOME} ? "$ENV{HOME}/.txt2html.dict" : '.txt2html.dict');
- $self->{dict_debug} = 0;
- $self->{doctype} = "-//W3C//DTD HTML 3.2 Final//EN";
- $self->{demoronize} = 1;
- $self->{eight_bit_clean} = 0;
- $self->{escape_HTML_chars} = 1;
- $self->{explicit_headings} = 0;
- $self->{extract} = 0;
- $self->{hrule_min} = 4;
- $self->{indent_width} = 2;
- $self->{indent_par_break} = 0;
- $self->{infile} = [];
- $self->{inhandle} = [];
- $self->{instring} = [];
- $self->{italic_delimiter} = '*';
- $self->{links_dictionaries} = [];
- $self->{link_only} = 0;
- $self->{lower_case_tags} = 0;
- $self->{mailmode} = 0;
- $self->{make_anchors} = 1;
- $self->{make_links} = 1;
- $self->{make_tables} = 0;
- $self->{min_caps_length} = 3;
- $self->{outfile} = '-';
- $self->{par_indent} = 2;
- $self->{preformat_trigger_lines} = 2;
- $self->{endpreformat_trigger_lines} = 2;
- $self->{preformat_start_marker} = "^(:?(:?&lt;)|<)PRE(:?(:?&gt;)|>)\$";
- $self->{preformat_end_marker} = "^(:?(:?&lt;)|<)/PRE(:?(:?&gt;)|>)\$";
- $self->{preformat_whitespace_min} = 5;
- $self->{prepend_file} = '';
- $self->{preserve_indent} = 0;
- $self->{short_line_length} = 40;
- $self->{style_url} = '';
- $self->{tab_width} = 8;
- $self->{table_type} = {
- ALIGN => 1,
- PGSQL => 1,
- BORDER => 1,
- DELIM => 1,
- };
- $self->{title} = '';
- $self->{titlefirst} = 0;
- $self->{underline_length_tolerance} = 1;
- $self->{underline_offset_tolerance} = 1;
- $self->{unhyphenation} = 1;
- $self->{use_mosaic_header} = 0;
- $self->{use_preformat_marker} = 0;
- $self->{xhtml} = 0;
-
- # accumulation variables
- $self->{__file} = ""; # Current file being processed
- $self->{__heading_styles} = {};
- $self->{__num_heading_styles} = 0;
- $self->{__links_table} = {};
- $self->{__links_table_order} = [];
- $self->{__search_patterns} = [];
- $self->{__repl_code} = [];
- $self->{__prev_para_action} = 0;
- $self->{__non_header_anchor} = 0;
- $self->{__mode} = 0;
- $self->{__listnum} = 0;
- $self->{__list_nice_indent} = "";
- $self->{__list_indent} = [];
-
- $self->{__call_init_done} = 0;
-
- #
- # The global links data
- #
- # This is stored in the DATA handle, after the __DATA__ at
- # the end of this file; but because the test scripts (and possibly
- # other scripts) don't just create one instance of this object,
- # we have to remember the position of the DATA handle
- # and reset it after we've read from it, just in case
- # we have to read from it again.
- # This also means that we don't close it, either. Hope that doesn't
- # cause a problem...
- #
- my $curpos = tell(DATA); # remember the __DATA__ position
- my @lines = ();
- while (<DATA>)
- {
- # skip lines that start with '#'
- next if /^\#/;
- # skip lines that end with unescaped ':'
- next if /^.*[^\\]:\s*$/;
- push @lines, $_;
- }
- # reset the data handle to the start, just in case
- seek(DATA, $curpos, 0);
- $self->{__global_links_data} = join('', @lines);
-} # init_our_data
-
-#---------------------------------------------------------------#
-# txt2html-related subroutines
-
-#--------------------------------#
-# Name: deal_with_options
-# do extra processing related to particular options
-# Args:
-# $self
-sub deal_with_options ($)
-{
- my $self = shift;
-
- if ($self->{links_dictionaries})
- {
- # only put into the links dictionaries files which are readable
- my @dict_files = @{$self->{links_dictionaries}};
- $self->args(links_dictionaries => []);
-
- foreach my $ld (@dict_files)
- {
- if (-r $ld)
- {
- $self->{'make_links'} = 1;
- $self->args(['--links_dictionaries', $ld]);
- }
- else
- {
- print STDERR "Can't find or read link-file $ld\n";
- }
- }
- }
- if (!$self->{make_links})
- {
- $self->{'links_dictionaries'} = 0;
- }
- if ($self->{append_file})
- {
- if (!-r $self->{append_file})
- {
- print STDERR "Can't find or read ", $self->{append_file}, "\n";
- $self->{append_file} = '';
- }
- }
- if ($self->{prepend_file})
- {
- if (!-r $self->{prepend_file})
- {
- print STDERR "Can't find or read ", $self->{prepend_file}, "\n";
- $self->{'prepend_file'} = '';
- }
- }
- if ($self->{append_head})
- {
- if (!-r $self->{append_head})
- {
- print STDERR "Can't find or read ", $self->{append_head}, "\n";
- $self->{'append_head'} = '';
- }
- }
-
- if (!$self->{outfile})
- {
- $self->{'outfile'} = "-";
- }
-
- $self->{'preformat_trigger_lines'} = 0
- if ($self->{preformat_trigger_lines} < 0);
- $self->{'preformat_trigger_lines'} = 2
- if ($self->{preformat_trigger_lines} > 2);
-
- $self->{'endpreformat_trigger_lines'} = 1
- if ($self->{preformat_trigger_lines} == 0);
- $self->{'endpreformat_trigger_lines'} = 0
- if ($self->{endpreformat_trigger_lines} < 0);
- $self->{'endpreformat_trigger_lines'} = 2
- if ($self->{endpreformat_trigger_lines} > 2);
-
- $self->{__preformat_enabled} =
- (($self->{endpreformat_trigger_lines} != 0)
- || $self->{use_preformat_marker});
-
- if ($self->{use_mosaic_header})
- {
- my $num_heading_styles = 0;
- my %heading_styles = ();
- $heading_styles{"*"} = ++$num_heading_styles;
- $heading_styles{"="} = ++$num_heading_styles;
- $heading_styles{"+"} = ++$num_heading_styles;
- $heading_styles{"-"} = ++$num_heading_styles;
- $heading_styles{"~"} = ++$num_heading_styles;
- $heading_styles{"."} = ++$num_heading_styles;
- $self->{__heading_styles} = \%heading_styles;
- $self->{__num_heading_styles} = $num_heading_styles;
- }
- # XHTML implies lower case
- $self->{'lower_case_tags'} = 1 if ($self->{xhtml});
-}
-
-sub escape ($)
-{
- my ($text) = @_;
- $text =~ s/&/&amp;/g;
- $text =~ s/>/&gt;/g;
- $text =~ s/</&lt;/g;
- return $text;
-}
-
-# Added by Alan Jackson, alan at ajackson dot org, and based
-# on the demoronize script by John Walker, http://www.fourmilab.ch/
-# Convert Microsoft character entities into characters.
-sub demoronize_char($)
-{
- my $s = shift;
- # Map strategically incompatible non-ISO characters in the
- # range 0x82 -- 0x9F into plausible substitutes where
- # possible.
-
- $s =~ s/\x82/,/g;
- $s =~ s/\x84/,,/g;
- $s =~ s/\x85/.../g;
-
- $s =~ s/\x88/^/g;
-
- $s =~ s/\x8B/</g;
- $s =~ s/\x8C/Oe/g;
-
- $s =~ s/\x91/`/g;
- $s =~ s/\x92/'/g;
- $s =~ s/\x93/"/g;
- $s =~ s/\x94/"/g;
- $s =~ s/\x95/*/g;
- $s =~ s/\x96/-/g;
- $s =~ s/\x97/--/g;
-
- $s =~ s/\x9B/>/g;
- $s =~ s/\x9C/oe/g;
-
- return $s;
-}
-
-# convert Microsoft character entities into HTML code
-sub demoronize_code($)
-{
- my $s = shift;
- # Map strategically incompatible non-ISO characters in the
- # range 0x82 -- 0x9F into plausible substitutes where
- # possible.
-
- $s =~ s-\x83-<em>f</em>-g;
-
- $s =~ s-\x98-<sup>~</sup>-g;
- $s =~ s-\x99-<sup>TM</sup>-g;
-
- return $s;
-}
-
-# output the tag wanted (add the <> and the / if necessary)
-# - output in lower or upper case
-# - do tag-related processing
-# options:
-# tag_type=>'start' | tag_type=>'end' | tag_type=>'empty'
-# (default start)
-# inside_tag=>string (default empty)
-sub get_tag ($$;%)
-{
- my $self = shift;
- my $in_tag = shift;
- my %args = (
- tag_type => 'start',
- inside_tag => '',
- @_
- );
- my $inside_tag = $args{inside_tag};
-
- my $open_tag = @{$self->{__tags}}[$#{$self->{__tags}}];
- if (!defined $open_tag)
- {
- $open_tag = '';
- }
- # close any open tags that need closing
- # Note that we only have to check for the structural tags we make,
- # not every possible HTML tag
- my $tag_prefix = '';
- if ($self->{xhtml})
- {
- if ( $open_tag eq 'P'
- and $in_tag eq 'P'
- and $args{tag_type} ne 'end')
- {
- $tag_prefix = $self->close_tag('P');
- }
- elsif ( $open_tag eq 'P'
- and $in_tag =~ /^(HR|UL|OL|DL|PRE|TABLE|H)/)
- {
- $tag_prefix = $self->close_tag('P');
- }
- elsif ( $open_tag eq 'LI'
- and $in_tag eq 'LI'
- and $args{tag_type} ne 'end')
- {
- # close a LI before the next LI
- $tag_prefix = $self->close_tag('LI');
- }
- elsif ( $open_tag eq 'LI'
- and $in_tag =~ /^(UL|OL)$/
- and $args{tag_type} eq 'end')
- {
- # close the LI before the list closes
- $tag_prefix = $self->close_tag('LI');
- }
- elsif ( $open_tag eq 'DT'
- and $in_tag eq 'DD'
- and $args{tag_type} ne 'end')
- {
- # close a DT before the next DD
- $tag_prefix = $self->close_tag('DT');
- }
- elsif ( $open_tag eq 'DD'
- and $in_tag eq 'DT'
- and $args{tag_type} ne 'end')
- {
- # close a DD before the next DT
- $tag_prefix = $self->close_tag('DD');
- }
- elsif ( $open_tag eq 'DD'
- and $in_tag eq 'DL'
- and $args{tag_type} eq 'end')
- {
- # close the DD before the list closes
- $tag_prefix = $self->close_tag('DD');
- }
- }
-
- my $out_tag = $in_tag;
- if ($args{tag_type} eq 'end')
- {
- $out_tag = $self->close_tag($in_tag);
- }
- else
- {
- if ($self->{lower_case_tags})
- {
- $out_tag =~ tr/A-Z/a-z/;
- }
- else # upper case
- {
- $out_tag =~ tr/a-z/A-Z/;
- }
- if ($args{tag_type} eq 'empty')
- {
- if ($self->{xhtml})
- {
- $out_tag = "<${out_tag}${inside_tag}/>";
- }
- else
- {
- $out_tag = "<${out_tag}${inside_tag}>";
- }
- }
- else
- {
- push @{$self->{__tags}}, $in_tag;
- $out_tag = "<${out_tag}${inside_tag}>";
- }
- }
- $out_tag = $tag_prefix . $out_tag if $tag_prefix;
- if ($self->{dict_debug} & 8)
- {
- print STDERR
- "open_tag = '${open_tag}', in_tag = '${in_tag}', tag_type = ",
- $args{tag_type},
- ", inside_tag = '${inside_tag}', out_tag = '$out_tag'\n";
- }
-
- return $out_tag;
-} # get_tag
-
-# close the open tag
-sub close_tag ($$)
-{
- my $self = shift;
- my $in_tag = shift;
-
- my $open_tag = pop @{$self->{__tags}};
- $in_tag ||= $open_tag;
- # put the open tag back on the stack if the in-tag is not the same
- if (defined $open_tag && $open_tag ne $in_tag)
- {
- push @{$self->{__tags}}, $open_tag;
- }
- my $out_tag = $in_tag;
- if ($self->{lower_case_tags})
- {
- $out_tag =~ tr/A-Z/a-z/;
- }
- else # upper case
- {
- $out_tag =~ tr/a-z/A-Z/;
- }
- $out_tag = "<\/${out_tag}>";
- if ($self->{dict_debug} & 8)
- {
- print STDERR
-"close_tag: open_tag = '${open_tag}', in_tag = '${in_tag}', out_tag = '$out_tag'\n";
- }
-
- return $out_tag;
-}
-
-sub hrule ($%)
-{
- my $self = shift;
- my %args = (
- para_lines_ref => undef,
- para_action_ref => undef,
- ind => 0,
- @_
- );
- my $para_lines_ref = $args{para_lines_ref};
- my $para_action_ref = $args{para_action_ref};
- my $ind = $args{ind};
-
- my $hrmin = $self->{hrule_min};
- if ($para_lines_ref->[$ind] =~ /^\s*([-_~=\*]\s*){$hrmin,}$/)
- {
- my $tag = $self->get_tag("HR", tag_type => 'empty');
- $para_lines_ref->[$ind] = "$tag\n";
- $para_action_ref->[$ind] |= $HRULE;
- }
- elsif ($para_lines_ref->[$ind] =~ /\014/)
- {
- # Linefeeds become horizontal rules
- $para_action_ref->[$ind] |= $HRULE;
- my $tag = $self->get_tag("HR", tag_type => 'empty');
- $para_lines_ref->[$ind] =~ s/\014/\n${tag}\n/g;
- }
-}
-
-sub shortline ($%)
-{
- my $self = shift;
- my %args = (
- line_ref => undef,
- line_action_ref => undef,
- prev_ref => undef,
- prev_action_ref => undef,
- prev_line_len => 0,
- @_
- );
- my $mode_ref = $args{mode_ref};
- my $line_ref = $args{line_ref};
- my $line_action_ref = $args{line_action_ref};
- my $prev_ref = $args{prev_ref};
- my $prev_action_ref = $args{prev_action_ref};
- my $prev_line_len = $args{prev_line_len};
-
- # Short lines should be broken even on list item lines iff the
- # following line is more text. I haven't figured out how to do
- # that yet. For now, I'll just not break on short lines in lists.
- # (sorry)
-
- my $tag = $self->get_tag('BR', tag_type => 'empty');
- if (
- ${$line_ref} !~ /^\s*$/
- && ${$prev_ref} !~ /^\s*$/
- && ($prev_line_len < $self->{short_line_length})
- && !(
- ${$line_action_ref} &
- ($END | $HEADER | $HRULE | $LIST | $IND_BREAK | $PAR)
- )
- && !(${$prev_action_ref} & ($HEADER | $HRULE | $BREAK | $IND_BREAK))
- )
- {
- ${$prev_ref} .= $tag . chop(${$prev_ref});
- ${$prev_action_ref} |= $BREAK;
- }
-}
-
-sub is_mailheader ($%)
-{
- my $self = shift;
- my %args = (
- rows_ref => undef,
- @_
- );
- my $rows_ref = $args{rows_ref};
-
- # a mail header is assumed to be the whole
- # paragraph which starts with a From , From: or Newsgroups: line
-
- if ($rows_ref->[0] =~ /^(From:?)|(Newsgroups:) /)
- {
- return 1;
- }
- return 0;
-
-} # is_mailheader
-
-sub mailheader ($%)
-{
- my $self = shift;
- my %args = (
- rows_ref => undef,
- @_
- );
- my $rows_ref = $args{rows_ref};
-
- # a mail header is assumed to be the whole
- # paragraph which starts with a From: or Newsgroups: line
- my $tag = '';
- my @rows = @{$rows_ref};
-
- if ($self->is_mailheader(%args))
- {
- $self->{__mode} |= $MAILHEADER;
- if ($self->{escape_HTML_chars})
- {
- $rows[0] = escape($rows[0]);
- }
- $self->anchor_mail(\$rows[0]);
- chomp ${rows}[0];
- $tag = $self->get_tag('P', inside_tag => " class='mail_header'");
- my $tag2 = $self->get_tag('BR', tag_type => 'empty');
- $rows[0] =
- join('', "<!-- New Message -->\n", $tag, $rows[0], $tag2, "\n");
- # now put breaks on the rest of the paragraph
- # apart from the last line
- for (my $rn = 1; $rn < @rows; $rn++)
- {
- if ($self->{escape_HTML_chars})
- {
- $rows[$rn] = escape($rows[$rn]);
- }
- if ($rn != (@rows - 1))
- {
- $tag = $self->get_tag('BR', tag_type => 'empty');
- chomp $rows[$rn];
- $rows[$rn] =~ s/$/${tag}\n/;
- }
- }
- }
- @{$rows_ref} = @rows;
-
-} # mailheader
-
-sub mailquote ($%)
-{
- my $self = shift;
- my %args = (
- line_ref => undef,
- line_action_ref => undef,
- prev_ref => undef,
- prev_action_ref => undef,
- next_ref => undef,
- @_
- );
- my $line_ref = $args{line_ref};
- my $line_action_ref = $args{line_action_ref};
- my $prev_ref = $args{prev_ref};
- my $prev_action_ref = $args{prev_action_ref};
- my $next_ref = $args{next_ref};
-
- my $tag = '';
- if (
- (
- (${$line_ref} =~ /^\w*&gt/) # Handle "FF> Werewolves."
- || (${$line_ref} =~ /^[\|:]/)
- ) # Handle "[|:] There wolves."
- && defined($next_ref) && (${$next_ref} !~ /^\s*$/)
- )
- {
- $tag = $self->get_tag('BR', tag_type => 'empty');
- ${$line_ref} =~ s/$/${tag}/;
- ${$line_action_ref} |= ($BREAK | $MAILQUOTE);
- if (!(${$prev_action_ref} & ($BREAK | $MAILQUOTE)))
- {
- $tag = $self->get_tag('P', inside_tag => " class='quote_mail'");
- ${$prev_ref} .= $tag;
- ${$line_action_ref} |= $PAR;
- }
- }
-}
-
-# Subtracts modes listed in $mask from $vector.
-sub subtract_modes ($$)
-{
- my ($vector, $mask) = @_;
- return ($vector | $mask) - $mask;
-}
-
-sub paragraph ($%)
-{
- my $self = shift;
- my %args = (
- line_ref => undef,
- line_action_ref => undef,
- prev_ref => undef,
- prev_action_ref => undef,
- line_indent => 0,
- prev_indent => 0,
- is_fragment => 0,
- ind => 0,
- @_
- );
- my $line_ref = $args{line_ref};
- my $line_action_ref = $args{line_action_ref};
- my $prev_ref = $args{prev_ref};
- my $prev_action_ref = $args{prev_action_ref};
- my $line_indent = $args{line_indent};
- my $prev_indent = $args{prev_indent};
- my $is_fragment = $args{is_fragment};
- my $line_no = $args{ind};
-
- my $tag = '';
- if (
- ${$line_ref} !~ /^\s*$/
- && !subtract_modes(
- ${$line_action_ref}, $END | $MAILQUOTE | $CAPS | $BREAK
- )
- && ( ${$prev_ref} =~ /^\s*$/
- || (${$line_action_ref} & $END)
- || ($line_indent > $prev_indent + $self->{par_indent}))
- && !($is_fragment && $line_no == 0)
- )
- {
-
- if ( $self->{indent_par_break}
- && ${$prev_ref} !~ /^\s*$/
- && !(${$line_action_ref} & $END)
- && ($line_indent > $prev_indent + $self->{par_indent}))
- {
- $tag = $self->get_tag('BR', tag_type => 'empty');
- ${$prev_ref} .= $tag;
- ${$prev_ref} .= "&nbsp;" x $line_indent;
- ${$line_ref} =~ s/^ {$line_indent}//;
- ${$prev_action_ref} |= $BREAK;
- ${$line_action_ref} |= $IND_BREAK;
- }
- elsif ($self->{preserve_indent})
- {
- $tag = $self->get_tag('P');
- ${$prev_ref} .= $tag;
- ${$prev_ref} .= "&nbsp;" x $line_indent;
- ${$line_ref} =~ s/^ {$line_indent}//;
- ${$line_action_ref} |= $PAR;
- }
- else
- {
- $tag = $self->get_tag('P');
- ${$prev_ref} .= $tag;
- ${$line_action_ref} |= $PAR;
- }
- }
- # detect also a continuing indentation at the same level
- elsif ($self->{indent_par_break}
- && !($self->{__mode} & ($PRE | $TABLE | $LIST))
- && ${$prev_ref} !~ /^\s*$/
- && !(${$line_action_ref} & $END)
- && (${$prev_action_ref} & ($IND_BREAK | $PAR))
- && !subtract_modes(${$line_action_ref}, $END | $MAILQUOTE | $CAPS)
- && ($line_indent > $self->{par_indent})
- && ($line_indent == $prev_indent))
- {
- $tag = $self->get_tag('BR', tag_type => 'empty');
- ${$prev_ref} .= $tag;
- ${$prev_ref} .= "&nbsp;" x $line_indent;
- ${$line_ref} =~ s/^ {$line_indent}//;
- ${$prev_action_ref} |= $BREAK;
- ${$line_action_ref} |= $IND_BREAK;
- }
-}
-
-sub listprefix ($$)
-{
- my $self = shift;
- my $line = shift;
-
- my ($prefix, $number, $rawprefix, $term);
-
- my $bullets = $self->{bullets};
- my $bullets_ordered = $self->{bullets_ordered};
- my $number_match = '(\d+|[^\W\d])';
- if ($bullets_ordered)
- {
- $number_match = '(\d+|[a-zA-Z]|[' . "${bullets_ordered}])";
- }
- $self->{__number_match} = $number_match;
- my $term_match = '(\w\w+)';
- $self->{__term_match} = $term_match;
- return (0, 0, 0, 0)
- if ( !($line =~ /^\s*[${bullets}]\s+\S/)
- && !($line =~ /^\s*${number_match}[\.\)\]:]\s+\S/)
- && !($line =~ /^\s*${term_match}:$/));
-
- ($term) = $line =~ /^\s*${term_match}:$/;
- ($number) = $line =~ /^\s*${number_match}\S\s+\S/;
- $number = 0 unless defined($number);
- if ( $bullets_ordered
- && $number =~ /[${bullets_ordered}]/)
- {
- $number = 1;
- }
-
- # That slippery exception of "o" as a bullet
- # (This ought to be determined using the context of what lists
- # we have in progress, but this will probably work well enough.)
- if ($bullets =~ /o/ && $line =~ /^\s*o\s/)
- {
- $number = 0;
- }
-
- if ($term)
- {
- ($rawprefix) = $line =~ /^(\s*${term_match}.)$/;
- $prefix = $rawprefix;
- $prefix =~ s/${term_match}//; # Take the term out
- }
- elsif ($number)
- {
- ($rawprefix) = $line =~ /^(\s*${number_match}.)/;
- $prefix = $rawprefix;
- $prefix =~ s/${number_match}//; # Take the number out
- }
- else
- {
- ($rawprefix) = $line =~ /^(\s*[${bullets}].)/;
- $prefix = $rawprefix;
- }
- ($prefix, $number, $rawprefix, $term);
-} # listprefix
-
-sub startlist ($%)
-{
- my $self = shift;
- my %args = (
- prefix => '',
- number => 0,
- rawprefix => '',
- term => '',
- para_lines_ref => undef,
- para_action_ref => undef,
- ind => 0,
- prev_ref => undef,
- total_prefix => '',
- @_
- );
- my $prefix = $args{prefix};
- my $number = $args{number};
- my $rawprefix = $args{rawprefix};
- my $term = $args{term};
- my $para_lines_ref = $args{para_lines_ref};
- my $para_action_ref = $args{para_action_ref};
- my $ind = $args{ind};
- my $prev_ref = $args{prev_ref};
-
- my $tag = '';
- $self->{__listprefix}->[$self->{__listnum}] = $prefix;
- if ($number)
- {
-
- # It doesn't start with 1,a,A. Let's not screw with it.
- if (($number ne "1") && ($number ne "a") && ($number ne "A"))
- {
- return 0;
- }
- $tag = $self->get_tag('OL');
- ${$prev_ref} .= join('', $self->{__list_nice_indent}, $tag, "\n");
- $self->{__list}->[$self->{__listnum}] = $OL;
- }
- elsif ($term)
- {
- $tag = $self->get_tag('DL');
- ${$prev_ref} .= join('', $self->{__list_nice_indent}, $tag, "\n");
- $self->{__list}->[$self->{__listnum}] = $DL;
- }
- else
- {
- $tag = $self->get_tag('UL');
- ${$prev_ref} .= join('', $self->{__list_nice_indent}, $tag, "\n");
- $self->{__list}->[$self->{__listnum}] = $UL;
- }
-
- $self->{__list_indent}->[$self->{__listnum}] = length($args{total_prefix});
- $self->{__listnum}++;
- $self->{__list_nice_indent} =
- " " x $self->{__listnum} x $self->{indent_width};
- $para_action_ref->[$ind] |= $LIST;
- $para_action_ref->[$ind] |= $LIST_START;
- $self->{__mode} |= $LIST;
- 1;
-} # startlist
-
-# End N lists
-sub endlist ($%)
-{
- my $self = shift;
- my %args = (
- num_lists => 0,
- prev_ref => undef,
- line_action_ref => undef,
- @_
- );
- my $n = $args{num_lists};
- my $prev_ref = $args{prev_ref};
- my $line_action_ref = $args{line_action_ref};
-
- my $tag = '';
- for (; $n > 0; $n--, $self->{__listnum}--)
- {
- $self->{__list_nice_indent} =
- " " x ($self->{__listnum} - 1) x $self->{indent_width};
- if ($self->{__list}->[$self->{__listnum} - 1] == $UL)
- {
- $tag = $self->get_tag('UL', tag_type => 'end');
- ${$prev_ref} .= join('', $self->{__list_nice_indent}, $tag, "\n");
- pop @{$self->{__list_indent}};
- }
- elsif ($self->{__list}->[$self->{__listnum} - 1] == $OL)
- {
- $tag = $self->get_tag('OL', tag_type => 'end');
- ${$prev_ref} .= join('', $self->{__list_nice_indent}, $tag, "\n");
- pop @{$self->{__list_indent}};
- }
- elsif ($self->{__list}->[$self->{__listnum} - 1] == $DL)
- {
- $tag = $self->get_tag('DL', tag_type => 'end');
- ${$prev_ref} .= join('', $self->{__list_nice_indent}, $tag, "\n");
- pop @{$self->{__list_indent}};
- }
- else
- {
- print STDERR "Encountered list of unknown type\n";
- }
- }
- ${$line_action_ref} |= $END;
- $self->{__mode} ^= $LIST if (!$self->{__listnum});
-} # endlist
-
-sub continuelist ($%)
-{
- my $self = shift;
- my %args = (
- para_lines_ref => undef,
- para_action_ref => undef,
- ind => 0,
- term => '',
- @_
- );
- my $para_lines_ref = $args{para_lines_ref};
- my $para_action_ref = $args{para_action_ref};
- my $ind = $args{ind};
- my $term = $args{term};
-
- my $list_indent = $self->{__list_nice_indent};
- my $bullets = $self->{bullets};
- my $num_match = $self->{__number_match};
- my $term_match = $self->{__term_match};
- my $tag = '';
- if ( $self->{__list}->[$self->{__listnum} - 1] == $UL
- && $para_lines_ref->[$ind] =~ /^\s*[${bullets}]\s*/)
- {
- $tag = $self->get_tag('LI');
- $para_lines_ref->[$ind] =~ s/^\s*[${bullets}]\s*/${list_indent}${tag}/;
- $para_action_ref->[$ind] |= $LIST_ITEM;
- }
- if ($self->{__list}->[$self->{__listnum} - 1] == $OL)
- {
- $tag = $self->get_tag('LI');
- $para_lines_ref->[$ind] =~ s/^\s*${num_match}.\s*/${list_indent}${tag}/;
- $para_action_ref->[$ind] |= $LIST_ITEM;
- }
- if ( $self->{__list}->[$self->{__listnum} - 1] == $DL
- && $term)
- {
- $tag = $self->get_tag('DT');
- my $tag2 = $self->get_tag('DT', tag_type => 'end');
- $term =~ s/_/ /g; # underscores are now spaces in the term
- $para_lines_ref->[$ind] =~
- s/^\s*${term_match}.$/${list_indent}${tag}${term}${tag2}/;
- $tag = $self->get_tag('DD');
- $para_lines_ref->[$ind] .= ${tag};
- $para_action_ref->[$ind] |= $LIST_ITEM;
- }
- $para_action_ref->[$ind] |= $LIST;
-} # continuelist
-
-sub liststuff ($%)
-{
- my $self = shift;
- my %args = (
- para_lines_ref => undef,
- para_action_ref => undef,
- para_line_indent_ref => undef,
- ind => 0,
- prev_ref => undef,
- @_
- );
- my $para_lines_ref = $args{para_lines_ref};
- my $para_action_ref = $args{para_action_ref};
- my $para_line_indent_ref = $args{para_line_indent_ref};
- my $ind = $args{ind};
- my $prev_ref = $args{prev_ref};
-
- my $i;
-
- my ($prefix, $number, $rawprefix, $term) =
- $self->listprefix($para_lines_ref->[$ind]);
-
- if (!$prefix)
- {
- # if the previous line is not blank
- if ($ind > 0 && $para_lines_ref->[$ind - 1] !~ /^\s*$/)
- {
- # inside a list item
- return;
- }
- # This might be a new paragraph within an existing list item;
- # It will be the first line, and have the same indentation
- # as the list's indentation.
- if ( $ind == 0
- && $self->{__listnum}
- && $para_line_indent_ref->[$ind] ==
- $self->{__list_indent}->[$self->{__listnum} - 1])
- {
- # start a paragraph
- my $tag = $self->get_tag('P');
- ${$prev_ref} .= $tag;
- $para_action_ref->[$ind] |= $PAR;
- return;
- }
- # This ain't no list. We'll want to end all of them.
- if ($self->{__listnum})
- {
- $self->endlist(
- num_lists => $self->{__listnum},
- prev_ref => $prev_ref,
- line_action_ref => \$para_action_ref->[$ind]
- );
- }
- return;
- }
-
- # If numbers with more than one digit grow to the left instead of
- # to the right, the prefix will shrink and we'll fail to match the
- # right list. We need to account for this.
- my $prefix_alternate;
- if (length("" . $number) > 1)
- {
- $prefix_alternate = (" " x (length("" . $number) - 1)) . $prefix;
- }
-
- # Maybe we're going back up to a previous list
- for (
- $i = $self->{__listnum} - 1;
- ($i >= 0) && ($prefix ne $self->{__listprefix}->[$i]);
- $i--
- )
- {
- if (length("" . $number) > 1)
- {
- last if $prefix_alternate eq $self->{__listprefix}->[$i];
- }
- }
-
- my $islist;
-
- # Measure the indent from where the text starts, not where the
- # prefix starts. This won't screw anything up, and if we don't do
- # it, the next line might appear to be indented relative to this
- # line, and get tagged as a new paragraph.
- my $bullets = $self->{bullets};
- my $bullets_ordered = $self->{bullets_ordered};
- my $term_match = $self->{__term_match};
- my ($total_prefix) =
- $para_lines_ref->[$ind] =~ /^(\s*[${bullets}${bullets_ordered}\w]+.\s*)/;
- # a DL indent starts from the edge of the term, plus indent_width
- if ($term)
- {
- ($total_prefix) = $para_lines_ref->[$ind] =~ /^(\s*)${term_match}.$/;
- $total_prefix .= " " x $self->{indent_width};
- }
-
- # Of course, we only use it if it really turns out to be a list.
-
- $islist = 1;
- $i++;
- if (($i > 0) && ($i != $self->{__listnum}))
- {
- $self->endlist(
- num_lists => $self->{__listnum} - $i,
- prev_ref => $prev_ref,
- line_action_ref => \$para_action_ref->[$ind]
- );
- $islist = 0;
- }
- elsif (!$self->{__listnum} || ($i != $self->{__listnum}))
- {
- if (
- ($para_line_indent_ref->[$ind] > 0)
- || $ind == 0
- || ($ind > 0 && ($para_lines_ref->[$ind - 1] =~ /^\s*$/))
- || ( $ind > 0
- && $para_action_ref->[$ind - 1] & ($BREAK | $HEADER | $CAPS))
- )
- {
- $islist = $self->startlist(
- prefix => $prefix,
- number => $number,
- rawprefix => $rawprefix,
- term => $term,
- para_lines_ref => $para_lines_ref,
- para_action_ref => $para_action_ref,
- ind => $ind,
- prev_ref => $prev_ref,
- total_prefix => $total_prefix
- );
- }
- else
- {
-
- # We have something like this: "- foo" which usually
- # turns out not to be a list.
- return;
- }
- }
-
- $self->continuelist(
- para_lines_ref => $para_lines_ref,
- para_action_ref => $para_action_ref,
- ind => $ind,
- term => $term
- )
- if ($self->{__mode} & $LIST);
- $para_line_indent_ref->[$ind] = length($total_prefix) if $islist;
-} # liststuff
-
-# figure out the table type of this table, if any
-sub get_table_type ($%)
-{
- my $self = shift;
- my %args = (
- rows_ref => undef,
- para_len => 0,
- @_
- );
- my $table_type = 0;
- if ( $self->{table_type}->{DELIM}
- && $self->is_delim_table(%args))
- {
- $table_type = $TAB_DELIM;
- }
- elsif ($self->{table_type}->{ALIGN}
- && $self->is_aligned_table(%args))
- {
- $table_type = $TAB_ALIGN;
- }
- elsif ($self->{table_type}->{PGSQL}
- && $self->is_pgsql_table(%args))
- {
- $table_type = $TAB_PGSQL;
- }
- elsif ($self->{table_type}->{BORDER}
- && $self->is_border_table(%args))
- {
- $table_type = $TAB_BORDER;
- }
-
- return $table_type;
-}
-
-# check if the given paragraph-array is an aligned table
-sub is_aligned_table ($%)
-{
- my $self = shift;
- my %args = (
- rows_ref => undef,
- para_len => 0,
- @_
- );
- my $rows_ref = $args{rows_ref};
- my $para_len = $args{para_len};
-
- # TABLES: spot and mark up tables. We combine the lines of the
- # paragraph using the string bitwise or (|) operator, the result
- # being in $spaces. A character in $spaces is a space only if
- # there was a space at that position in every line of the
- # paragraph. $space can be used to search for contiguous spaces
- # that occur on all lines of the paragraph. If this results in at
- # least two columns, the paragraph is identified as a table.
-
- # Note that this sub must be called before checking for preformatted
- # lines because a table may well have whitespace to the left, in
- # which case it must not be incorrectly recognised as a preformat.
- my @rows = @{$rows_ref};
- my @starts;
- my $spaces = '';
- my $max = 0;
- my $min = $para_len;
- foreach my $row (@rows)
- {
- ($spaces |= $row) =~ tr/ /\xff/c;
- $min = length $row if length $row < $min;
- $max = length $row if $max < length $row;
- }
- $spaces = substr $spaces, 0, $min;
- push(@starts, 0) unless $spaces =~ /^ /;
- while ($spaces =~ /((?:^| ) +)(?=[^ ])/g)
- {
- push @starts, pos($spaces);
- }
-
- if (2 <= @rows and 2 <= @starts)
- {
- return 1;
- }
- else
- {
- return 0;
- }
-}
-
-sub is_pgsql_table ($%)
-{
- my $self = shift;
- my %args = (
- rows_ref => undef,
- para_len => 0,
- @_
- );
- my $rows_ref = $args{rows_ref};
- my $para_len = $args{para_len};
-
- # a PGSQL table can start with an optional table-caption,
- # then it has a row of column headings separated by |
- # then it has a row of ------+-----
- # then it has one or more rows of column values separated by |
- # then it has a row-count (N rows)
- # Thus it must have at least 4 rows.
- if (@{$rows_ref} < 4)
- {
- return 0;
- }
-
- my @rows = @{$rows_ref};
- if ($rows[0] !~ /\|/ && $rows[0] =~ /^\s*\w+/) # possible caption
- {
- shift @rows;
- }
- if (@rows < 4)
- {
- return 0;
- }
- if ($rows[0] !~ /^\s*\w+\s+\|\s+/) # Colname |
- {
- return 0;
- }
- if ($rows[1] !~ /^\s*[-]+[+][-]+/) # ----+----
- {
- return 0;
- }
- if ($rows[2] !~ /^\s*[^|]*\s+\|\s+/) # value |
- {
- return 0;
- }
- # check the last row for rowcount
- if ($rows[$#rows] !~ /\(\d+\s+rows\)/)
- {
- return 0;
- }
-
- return 1;
-}
-
-sub is_border_table ($%)
-{
- my $self = shift;
- my %args = (
- rows_ref => undef,
- para_len => 0,
- @_
- );
- my $rows_ref = $args{rows_ref};
- my $para_len = $args{para_len};
-
- # a BORDER table can start with an optional table-caption,
- # then it has a row of +------+-----+
- # then it has a row of column headings separated by |
- # then it has a row of +------+-----+
- # then it has one or more rows of column values separated by |
- # then it has a row of +------+-----+
- # Thus it must have at least 5 rows.
- # And note that it could be indented with spaces
- if (@{$rows_ref} < 5)
- {
- return 0;
- }
-
- my @rows = @{$rows_ref};
- if ($rows[0] !~ /\|/ && $rows[0] =~ /^\s*\w+/) # possible caption
- {
- shift @rows;
- }
- if (@rows < 5)
- {
- return 0;
- }
- if ($rows[0] !~ /^\s*[+][-]+[+][-]+[+][-+]*$/) # +----+----+
- {
- return 0;
- }
- if ($rows[1] !~ /^\s*\|\s*\w+\s+\|\s+.*\|$/) # | Colname |
- {
- return 0;
- }
- if ($rows[2] !~ /^\s*[+][-]+[+][-]+[+][-+]*$/) # +----+----+
- {
- return 0;
- }
- if ($rows[3] !~ /^\s*\|\s*[^|]*\s+\|\s+.*\|$/) # | value |
- {
- return 0;
- }
- # check the last row for +------+------+
- if ($rows[$#rows] !~ /^\s*[+][-]+[+][-]+[+][-+]*$/) # +----+----+
- {
- return 0;
- }
-
- return 1;
-} # is_border_table
-
-sub is_delim_table ($%)
-{
- my $self = shift;
- my %args = (
- rows_ref => undef,
- para_len => 0,
- @_
- );
- my $rows_ref = $args{rows_ref};
- my $para_len = $args{para_len};
-
- # a DELIM table can start with an optional table-caption,
- # then it has at least two rows which start and end and are
- # punctuated by a non-alphanumeric delimiter.
- #
- # | val1 | val2 |
- # | val3 | val4 |
- #
- # And note that it could be indented with spaces
- if (@{$rows_ref} < 2)
- {
- return 0;
- }
-
- my @rows = @{$rows_ref};
- if ($rows[0] !~ /[^\w\s]/ && $rows[0] =~ /^\s*\w+/) # possible caption
- {
- shift @rows;
- }
- if (@rows < 2)
- {
- return 0;
- }
- # figure out if the row starts with a possible delimiter
- my $delim = '';
- if ($rows[0] =~ /^\s*([^a-zA-Z0-9])/)
- {
- $delim = $1;
- # have to get rid of ^ and []
- $delim =~ s/\^//g;
- $delim =~ s/\[//g;
- $delim =~ s/\]//g;
- if (!$delim) # no delimiter after all
- {
- return 0;
- }
- }
- else
- {
- return 0;
- }
- # There needs to be at least three delimiters in the row
- my @all_delims = ($rows[0] =~ /[${delim}]/g);
- my $total_num_delims = @all_delims;
- if ($total_num_delims < 3)
- {
- return 0;
- }
- # All rows must start and end with the delimiter
- # and have $total_num_delims number of them
- foreach my $row (@rows)
- {
- if ($row !~ /^\s*[${delim}]/)
- {
- return 0;
- }
- if ($row !~ /[${delim}]\s*$/)
- {
- return 0;
- }
- @all_delims = ($row =~ /[${delim}]/g);
- if (@all_delims != $total_num_delims)
- {
- return 0;
- }
- }
-
- return 1;
-} # is_delim_table
-
-sub tablestuff ($%)
-{
- my $self = shift;
- my %args = (
- table_type => 0,
- rows_ref => undef,
- para_len => 0,
- @_
- );
- my $table_type = $args{table_type};
- if ($table_type eq $TAB_ALIGN)
- {
- return $self->make_aligned_table(%args);
- }
- if ($table_type eq $TAB_PGSQL)
- {
- return $self->make_pgsql_table(%args);
- }
- if ($table_type eq $TAB_BORDER)
- {
- return $self->make_border_table(%args);
- }
- if ($table_type eq $TAB_DELIM)
- {
- return $self->make_delim_table(%args);
- }
-} # tablestuff
-
-sub make_aligned_table ($%)
-{
- my $self = shift;
- my %args = (
- rows_ref => undef,
- para_len => 0,
- @_
- );
- my $rows_ref = $args{rows_ref};
- my $para_len = $args{para_len};
-
- # TABLES: spot and mark up tables. We combine the lines of the
- # paragraph using the string bitwise or (|) operator, the result
- # being in $spaces. A character in $spaces is a space only if
- # there was a space at that position in every line of the
- # paragraph. $space can be used to search for contiguous spaces
- # that occur on all lines of the paragraph. If this results in at
- # least two columns, the paragraph is identified as a table.
-
- # Note that this sub must be called before checking for preformatted
- # lines because a table may well have whitespace to the left, in
- # which case it must not be incorrectly recognised as a preformat.
- my @rows = @{$rows_ref};
- my @starts;
- my @ends;
- my $spaces;
- my $max = 0;
- my $min = $para_len;
- foreach my $row (@rows)
- {
- ($spaces |= $row) =~ tr/ /\xff/c;
- $min = length $row if length $row < $min;
- $max = length $row if $max < length $row;
- }
- $spaces = substr $spaces, 0, $min;
- push(@starts, 0) unless $spaces =~ /^ /;
- while ($spaces =~ /((?:^| ) +)(?=[^ ])/g)
- {
- push @ends, pos($spaces) - length $1;
- push @starts, pos($spaces);
- }
- shift(@ends) if $spaces =~ /^ /;
- push(@ends, $max);
-
- # Two or more rows and two or more columns indicate a table.
- if (2 <= @rows and 2 <= @starts)
- {
- $self->{__mode} |= $TABLE;
-
- # For each column, guess whether it should be left, centre or
- # right aligned by examining all cells in that column for space
- # to the left or the right. A simple majority among those cells
- # that actually have space to one side or another decides (if no
- # alignment gets a majority, left alignment wins by default).
- my @align;
- my $cell = '';
- foreach my $col (0 .. $#starts)
- {
- my @count = (0, 0, 0, 0);
- foreach my $row (@rows)
- {
- my $width = $ends[$col] - $starts[$col];
- $cell = substr $row, $starts[$col], $width;
- ++$count[($cell =~ /^ / ? 2 : 0) +
- ($cell =~ / $/ || length($cell) < $width ? 1 : 0)];
- }
- $align[$col] = 0;
- my $population = $count[1] + $count[2] + $count[3];
- foreach (1 .. 3)
- {
- if ($count[$_] * 2 > $population)
- {
- $align[$col] = $_;
- last;
- }
- }
- }
-
- foreach my $row (@rows)
- {
- $row = join '', $self->get_tag('TR'), (
- map {
- $cell = substr $row, $starts[$_], $ends[$_] - $starts[$_];
- $cell =~ s/^ +//;
- $cell =~ s/ +$//;
-
- if ($self->{escape_HTML_chars})
- {
- $cell = escape($cell);
- }
-
- (
- $self->get_tag(
- 'TD',
- inside_tag => (
- $self->{xhtml} ? $xhtml_alignments[$align[$_]]
- : (
- $self->{lower_case_tags}
- ? $lc_alignments[$align[$_]]
- : $alignments[$align[$_]]
- )
- )
- ),
- $cell,
- $self->close_tag('TD')
- );
- } 0 .. $#starts
- ),
- $self->close_tag('TR');
- }
-
- # put the <TABLE> around the rows
- my $tag;
- if ($self->{xhtml})
- {
- $tag = $self->get_tag('TABLE', inside_tag => ' summary=""');
- }
- else
- {
- $tag = $self->get_tag('TABLE');
- }
- $rows[0] = join("\n", $tag, $rows[0]);
- $tag = $self->close_tag('TABLE', tag_type => 'end');
- $rows[$#rows] .= "\n${tag}";
- @{$rows_ref} = @rows;
- return 1;
- }
- else
- {
- return 0;
- }
-} # make_aligned_table
-
-sub make_pgsql_table ($%)
-{
- my $self = shift;
- my %args = (
- rows_ref => undef,
- para_len => 0,
- @_
- );
- my $rows_ref = $args{rows_ref};
- my $para_len = $args{para_len};
-
- # a PGSQL table can start with an optional table-caption,
- # then it has a row of column headings separated by |
- # then it has a row of ------+-----
- # then it has one or more rows of column values separated by |
- # then it has a row-count (N rows)
- # Thus it must have at least 4 rows.
- my @rows = @{$rows_ref};
- my $caption = '';
- if ($rows[0] !~ /\|/ && $rows[0] =~ /^\s*\w+/) # possible caption
- {
- $caption = shift @rows;
- }
- my @headings = split(/\s+\|\s+/, shift @rows);
- # skip the ----+--- line
- shift @rows;
- # grab the N rows line
- my $n_rows = pop @rows;
-
- # now start making the table
- my @tab_lines = ();
- my $tag;
- my $tag2;
- if ($self->{xhtml})
- {
- $tag = $self->get_tag('TABLE', inside_tag => ' border="1" summary=""');
- }
- else
- {
- $tag = $self->get_tag('TABLE', inside_tag => ' border="1"');
- }
- push @tab_lines, "$tag\n";
- if ($caption)
- {
- $caption =~ s/^\s+//;
- $caption =~ s/\s+$//;
- $tag = $self->get_tag('CAPTION');
- $tag2 = $self->close_tag('CAPTION');
- $caption = join('', $tag, $caption, $tag2, "\n");
- push @tab_lines, $caption;
- }
- # table header
- my $thead = '';
- $tag = $self->get_tag('THEAD');
- $thead .= $tag;
- $tag = $self->get_tag('TR');
- $thead .= $tag;
- foreach my $col (@headings)
- {
- $col =~ s/^\s+//;
- $col =~ s/\s+$//;
- $tag = $self->get_tag('TH');
- $tag2 = $self->close_tag('TH');
- $thead .= join('', $tag, $col, $tag2);
- }
- $tag = $self->close_tag('TR');
- $thead .= $tag;
- $tag = $self->close_tag('THEAD');
- $thead .= $tag;
- push @tab_lines, "${thead}\n";
- $tag = $self->get_tag('TBODY');
- push @tab_lines, "$tag\n";
-
- # each row
- foreach my $row (@rows)
- {
- my $this_row = '';
- $tag = $self->get_tag('TR');
- $this_row .= $tag;
- my @cols = split(/\|/, $row);
- foreach my $cell (@cols)
- {
- $cell =~ s/^\s+//;
- $cell =~ s/\s+$//;
- if ($self->{escape_HTML_chars})
- {
- $cell = escape($cell);
- }
- if (!$cell)
- {
- $cell = '&nbsp;';
- }
- $tag = $self->get_tag('TD');
- $tag2 = $self->close_tag('TD');
- $this_row .= join('', $tag, $cell, $tag2);
- }
- $tag = $self->close_tag('TR');
- $this_row .= $tag;
- push @tab_lines, "${this_row}\n";
- }
-
- # end the table
- $tag = $self->close_tag('TBODY');
- push @tab_lines, "$tag\n";
- $tag = $self->get_tag('TABLE', tag_type => 'end');
- push @tab_lines, "$tag\n";
-
- # and add the N rows line
- $tag = $self->get_tag('P');
- push @tab_lines, "${tag}${n_rows}\n";
- if ($self->{xhtml})
- {
- $tag = $self->get_tag('P', tag_type => 'end');
- $tab_lines[$#tab_lines] =~ s/\n/${tag}\n/;
- }
-
- # replace the rows
- @{$rows_ref} = @tab_lines;
-} # make_pgsql_table
-
-sub make_border_table ($%)
-{
- my $self = shift;
- my %args = (
- rows_ref => undef,
- para_len => 0,
- @_
- );
- my $rows_ref = $args{rows_ref};
- my $para_len = $args{para_len};
-
- # a BORDER table can start with an optional table-caption,
- # then it has a row of +------+-----+
- # then it has a row of column headings separated by |
- # then it has a row of +------+-----+
- # then it has one or more rows of column values separated by |
- # then it has a row of +------+-----+
- my @rows = @{$rows_ref};
- my $caption = '';
- if ($rows[0] !~ /\|/ && $rows[0] =~ /^\s*\w+/) # possible caption
- {
- $caption = shift @rows;
- }
- # skip the +----+---+ line
- shift @rows;
- # get the head row and cut off the start and end |
- my $head_row = shift @rows;
- $head_row =~ s/^\s*\|//;
- $head_row =~ s/\|$//;
- my @headings = split(/\s+\|\s+/, $head_row);
- # skip the +----+---+ line
- shift @rows;
- # skip the last +----+---+ line
- pop @rows;
-
- # now start making the table
- my @tab_lines = ();
- my $tag;
- if ($self->{xhtml})
- {
- $tag = $self->get_tag('TABLE', inside_tag => ' border="1" summary=""');
- }
- else
- {
- $tag = $self->get_tag('TABLE', inside_tag => ' border="1"');
- }
- push @tab_lines, "$tag\n";
- if ($caption)
- {
- $caption =~ s/^\s+//;
- $caption =~ s/\s+$//;
- $tag = $self->get_tag('CAPTION');
- $caption = $tag . $caption;
- $tag = $self->close_tag('CAPTION');
- $caption .= $tag;
- push @tab_lines, "$caption\n";
- }
- # table header
- my $thead = '';
- $tag = $self->get_tag('THEAD');
- $thead .= $tag;
- $tag = $self->get_tag('TR');
- $thead .= $tag;
- foreach my $col (@headings)
- {
- $col =~ s/^\s+//;
- $col =~ s/\s+$//;
- $tag = $self->get_tag('TH');
- $thead .= $tag;
- $thead .= $col;
- $tag = $self->close_tag('TH');
- $thead .= $tag;
- }
- $tag = $self->close_tag('TR');
- $thead .= $tag;
- $tag = $self->close_tag('THEAD');
- $thead .= $tag;
- push @tab_lines, "${thead}\n";
- $tag = $self->get_tag('TBODY');
- push @tab_lines, "$tag\n";
-
- # each row
- foreach my $row (@rows)
- {
- # cut off the start and end |
- $row =~ s/^\s*\|//;
- $row =~ s/\|$//;
- my $this_row = '';
- $tag = $self->get_tag('TR');
- $this_row .= $tag;
- my @cols = split(/\|/, $row);
- foreach my $cell (@cols)
- {
- $cell =~ s/^\s+//;
- $cell =~ s/\s+$//;
- if ($self->{escape_HTML_chars})
- {
- $cell = escape($cell);
- }
- if (!$cell)
- {
- $cell = '&nbsp;';
- }
- $tag = $self->get_tag('TD');
- $this_row .= $tag;
- $this_row .= $cell;
- $tag = $self->close_tag('TD');
- $this_row .= $tag;
- }
- $tag = $self->close_tag('TR');
- $this_row .= $tag;
- push @tab_lines, "${this_row}\n";
- }
-
- # end the table
- $tag = $self->close_tag('TBODY');
- push @tab_lines, "$tag\n";
- $tag = $self->get_tag('TABLE', tag_type => 'end');
- push @tab_lines, "$tag\n";
-
- # replace the rows
- @{$rows_ref} = @tab_lines;
-} # make_border_table
-
-sub make_delim_table ($%)
-{
- my $self = shift;
- my %args = (
- rows_ref => undef,
- para_len => 0,
- @_
- );
- my $rows_ref = $args{rows_ref};
- my $para_len = $args{para_len};
-
- # a DELIM table can start with an optional table-caption,
- # then it has at least two rows which start and end and are
- # punctuated by a non-alphanumeric delimiter.
- # A DELIM table has no table-header.
- my @rows = @{$rows_ref};
- my $caption = '';
- if ($rows[0] !~ /\|/ && $rows[0] =~ /^\s*\w+/) # possible caption
- {
- $caption = shift @rows;
- }
- # figure out the delimiter
- my $delim = '';
- if ($rows[0] =~ /^\s*([^a-zA-Z0-9])/)
- {
- $delim = $1;
- }
- else
- {
- return 0;
- }
-
- # now start making the table
- my @tab_lines = ();
- my $tag;
- if ($self->{xhtml})
- {
- $tag = $self->get_tag('TABLE', inside_tag => ' border="1" summary=""');
- }
- else
- {
- $tag = $self->get_tag('TABLE', inside_tag => ' border="1"');
- }
- push @tab_lines, "$tag\n";
- if ($caption)
- {
- $caption =~ s/^\s+//;
- $caption =~ s/\s+$//;
- $tag = $self->get_tag('CAPTION');
- $caption = $tag . $caption;
- $tag = $self->close_tag('CAPTION');
- $caption .= $tag;
- push @tab_lines, "$caption\n";
- }
-
- # each row
- foreach my $row (@rows)
- {
- # cut off the start and end delimiter
- $row =~ s/^\s*[${delim}]//;
- $row =~ s/[${delim}]$//;
- my $this_row = '';
- $tag = $self->get_tag('TR');
- $this_row .= $tag;
- my @cols = split(/[${delim}]/, $row);
- foreach my $cell (@cols)
- {
- $cell =~ s/^\s+//;
- $cell =~ s/\s+$//;
- if ($self->{escape_HTML_chars})
- {
- $cell = escape($cell);
- }
- if (!$cell)
- {
- $cell = '&nbsp;';
- }
- $tag = $self->get_tag('TD');
- $this_row .= $tag;
- $this_row .= $cell;
- $tag = $self->close_tag('TD');
- $this_row .= $tag;
- }
- $tag = $self->close_tag('TR');
- $this_row .= $tag;
- push @tab_lines, "${this_row}\n";
- }
-
- # end the table
- $tag = $self->get_tag('TABLE', tag_type => 'end');
- push @tab_lines, "$tag\n";
-
- # replace the rows
- @{$rows_ref} = @tab_lines;
-} # make_delim_table
-
-# Returns true if the passed string is considered to be preformatted
-sub is_preformatted ($$)
-{
- my $self = shift;
- my $line = shift;
-
- my $pre_white_min = $self->{preformat_whitespace_min};
- my $result = (
- ($line =~ /\s{$pre_white_min,}\S+/o) # whitespaces
- || ($line =~ /\.{$pre_white_min,}\S+/o)
- ); # dots
- return $result;
-}
-
-# modifies the given string,
-# and returns the front preformatted part
-sub split_end_explicit_preformat ($%)
-{
- my $self = shift;
- my %args = (
- para_ref => undef,
- @_
- );
- my $para_ref = $args{para_ref};
-
- my $tag = '';
- my $pre_str = '';
- my $post_str = '';
- if ($self->{__mode} & $PRE_EXPLICIT)
- {
- my $pe_mark = $self->{preformat_end_marker};
- if (${para_ref} =~ /$pe_mark/io)
- {
- ($pre_str, $post_str) = split(/$pe_mark/, ${$para_ref}, 2);
- if ($self->{escape_HTML_chars})
- {
- $pre_str = escape($pre_str);
- }
- $tag = $self->close_tag('PRE');
- $pre_str .= "${tag}\n";
- $self->{__mode} ^= (($PRE | $PRE_EXPLICIT) & $self->{__mode});
- }
- else # no end -- the whole thing is preformatted
- {
- $pre_str = ${$para_ref};
- if ($self->{escape_HTML_chars})
- {
- $pre_str = escape($pre_str);
- }
- ${$para_ref} = '';
- }
- }
- return $pre_str;
-} # split_end_explicit_preformat
-
-sub endpreformat ($%)
-{
- my $self = shift;
- my %args = (
- para_lines_ref => undef,
- para_action_ref => undef,
- ind => 0,
- prev_ref => undef,
- @_
- );
- my $para_lines_ref = $args{para_lines_ref};
- my $para_action_ref = $args{para_action_ref};
- my $ind = $args{ind};
- my $prev_ref = $args{prev_ref};
-
- my $tag = '';
- if ($self->{__mode} & $PRE_EXPLICIT)
- {
- my $pe_mark = $self->{preformat_end_marker};
- if ($para_lines_ref->[$ind] =~ /$pe_mark/io)
- {
- if ($ind == 0)
- {
- $tag = $self->close_tag('PRE');
- $para_lines_ref->[$ind] = "${tag}\n";
- }
- else
- {
- $tag = $self->close_tag('PRE');
- $para_lines_ref->[$ind - 1] .= "${tag}\n";
- $para_lines_ref->[$ind] = "";
- }
- $self->{__mode} ^= (($PRE | $PRE_EXPLICIT) & $self->{__mode});
- $para_action_ref->[$ind] |= $END;
- }
- return;
- }
-
- if (
- !$self->is_preformatted($para_lines_ref->[$ind])
- && (
- $self->{endpreformat_trigger_lines} == 1
- || ($ind + 1 < @{$para_lines_ref}
- && !$self->is_preformatted($para_lines_ref->[$ind + 1]))
- || $ind + 1 >= @{$para_lines_ref} # last line of para
- )
- )
- {
- if ($ind == 0)
- {
- $tag = $self->close_tag('PRE');
- ${$prev_ref} = "${tag}\n";
- }
- else
- {
- $tag = $self->close_tag('PRE');
- $para_lines_ref->[$ind - 1] .= "${tag}\n";
- }
- $self->{__mode} ^= ($PRE & $self->{__mode});
- $para_action_ref->[$ind] |= $END;
- }
-} # endpreformat
-
-sub preformat ($%)
-{
- my $self = shift;
- my %args = (
- mode_ref => undef,
- line_ref => undef,
- line_action_ref => undef,
- prev_ref => undef,
- next_ref => undef,
- prev_action_ref => undef,
- @_
- );
- my $mode_ref = $args{mode_ref};
- my $line_ref = $args{line_ref};
- my $line_action_ref = $args{line_action_ref};
- my $prev_ref = $args{prev_ref};
- my $next_ref = $args{next_ref};
- my $prev_action_ref = $args{prev_action_ref};
-
- my $tag = '';
- if ($self->{use_preformat_marker})
- {
- my $pstart = $self->{preformat_start_marker};
- if (${$line_ref} =~ /$pstart/io)
- {
- if (${$prev_ref} =~ s/<P>$//)
- {
- pop @{$self->{__tags}};
- }
- $tag =
- $self->get_tag('PRE', inside_tag => " class='quote_explicit'");
- ${$line_ref} = "${tag}\n";
- ${$mode_ref} |= $PRE | $PRE_EXPLICIT;
- ${$line_action_ref} |= $PRE;
- return;
- }
- }
-
- if (
- !(${$line_action_ref} & $MAILQUOTE)
- && !(${$prev_action_ref} & $MAILQUOTE)
- && (
- $self->{preformat_trigger_lines} == 0
- || (
- $self->is_preformatted(${$line_ref})
- && (
- $self->{preformat_trigger_lines} == 1
- || (defined $next_ref
- && $self->is_preformatted(${$next_ref}))
- )
- )
- )
- )
- {
- if (${$prev_ref} =~ s/<P>$//)
- {
- pop @{$self->{__tags}};
- }
- $tag = $self->get_tag('PRE');
- ${$line_ref} =~ s/^/${tag}\n/;
- ${$mode_ref} |= $PRE;
- ${$line_action_ref} |= $PRE;
- }
-} # preformat
-
-sub make_new_anchor ($$)
-{
- my $self = shift;
- my $heading_level = shift;
-
- my ($anchor, $i);
-
- return sprintf("%d", $self->{__non_header_anchor}++) if (!$heading_level);
-
- $anchor = "section";
- $self->{__heading_count}->[$heading_level - 1]++;
-
- # Reset lower order counters
- for ($i = @{$self->{__heading_count}}; $i > $heading_level; $i--)
- {
- $self->{__heading_count}->[$i - 1] = 0;
- }
-
- for ($i = 0; $i < $heading_level; $i++)
- {
- $self->{__heading_count}->[$i] = 1
- if !$self->{__heading_count}->[$i]; # In case they skip any
- $anchor .= sprintf("_%d", $self->{__heading_count}->[$i]);
- }
- chomp($anchor);
- $anchor;
-} # make_new_anchor
-
-sub anchor_mail ($$)
-{
- my $self = shift;
- my $line_ref = shift;
-
- if ($self->{make_anchors})
- {
- my ($anchor) = $self->make_new_anchor(0);
- if ($self->{lower_case_tags})
- {
- ${$line_ref} =~ s/([^ ]*)/<a name="$anchor">$1<\/a>/;
- }
- else
- {
- ${$line_ref} =~ s/([^ ]*)/<A NAME="$anchor">$1<\/A>/;
- }
- }
-} # anchor_mail
-
-sub anchor_heading ($$$)
-{
- my $self = shift;
- my $level = shift;
- my $line_ref = shift;
-
- if ($self->{dict_debug} & 8)
- {
- print STDERR "anchor_heading: ", ${$line_ref}, "\n";
- }
- if ($self->{make_anchors})
- {
- my ($anchor) = $self->make_new_anchor($level);
- if ($self->{lower_case_tags})
- {
- ${$line_ref} =~ s/(<h.>)(.*)(<\/h.>)/$1<a name="$anchor">$2<\/a>$3/;
- }
- else
- {
- ${$line_ref} =~ s/(<H.>)(.*)(<\/H.>)/$1<A NAME="$anchor">$2<\/A>$3/;
- }
- }
- if ($self->{dict_debug} & 8)
- {
- print STDERR "anchor_heading(after): ", ${$line_ref}, "\n";
- }
-} # anchor_heading
-
-sub heading_level ($$)
-{
- my $self = shift;
-
- my ($style) = @_;
- $self->{__heading_styles}->{$style} = ++$self->{__num_heading_styles}
- if !$self->{__heading_styles}->{$style};
- $self->{__heading_styles}->{$style};
-} # heading_level
-
-sub is_ul_list_line ($%)
-{
- my $self = shift;
- my %args = (
- line => undef,
- @_
- );
- my $line = $args{line};
-
- my ($prefix, $number, $rawprefix, $term) = $self->listprefix($line);
- if ($prefix && !$number)
- {
- return 1;
- }
- return 0;
-}
-
-sub is_heading ($%)
-{
- my $self = shift;
- my %args = (
- line_ref => undef,
- next_ref => undef,
- @_
- );
- my $line_ref = $args{line_ref};
- my $next_ref = $args{next_ref};
-
- if ( ${$line_ref} !~ /^\s*$/
- && !$self->is_ul_list_line(line => ${$line_ref})
- && defined $next_ref
- && ${$next_ref} =~ /^\s*[-=*.~+]+\s*$/)
- {
- my ($hoffset, $heading) = ${$line_ref} =~ /^(\s*)(.+)$/;
- $hoffset = "" unless defined($hoffset);
- $heading = "" unless defined($heading);
- # Unescape chars so we get an accurate length
- $heading =~ s/&[^;]+;/X/g;
- my ($uoffset, $underline) = ${$next_ref} =~ /^(\s*)(\S+)\s*$/;
- $uoffset = "" unless defined($uoffset);
- $underline = "" unless defined($underline);
- my ($lendiff, $offsetdiff);
- $lendiff = length($heading) - length($underline);
- $lendiff *= -1 if $lendiff < 0;
-
- $offsetdiff = length($hoffset) - length($uoffset);
- $offsetdiff *= -1 if $offsetdiff < 0;
- if ( ($lendiff <= $self->{underline_length_tolerance})
- || ($offsetdiff <= $self->{underline_offset_tolerance}))
- {
- return 1;
- }
- }
-
- return 0;
-
-} # is_heading
-
-# make a heading
-# assumes is_heading is true
-sub heading ($%)
-{
- my $self = shift;
- my %args = (
- line_ref => undef,
- next_ref => undef,
- @_
- );
- my $line_ref = $args{line_ref};
- my $next_ref = $args{next_ref};
-
- my ($hoffset, $heading) = ${$line_ref} =~ /^(\s*)(.+)$/;
- $hoffset = "" unless defined($hoffset);
- $heading = "" unless defined($heading);
- $heading =~ s/&[^;]+;/X/g; # Unescape chars so we get an accurate length
- my ($uoffset, $underline) = ${$next_ref} =~ /^(\s*)(\S+)\s*$/;
- $uoffset = "" unless defined($uoffset);
- $underline = "" unless defined($underline);
-
- $underline = substr($underline, 0, 1);
-
- # Call it a different style if the heading is in all caps.
- $underline .= "C" if $self->iscaps(${$line_ref});
- ${$next_ref} = " "; # Eat the underline
- $self->{__heading_level} = $self->heading_level($underline);
- if ($self->{escape_HTML_chars})
- {
- ${$line_ref} = escape(${$line_ref});
- }
- $self->tagline("H" . $self->{__heading_level}, $line_ref);
- $self->anchor_heading($self->{__heading_level}, $line_ref);
-} # heading
-
-# check if the given line matches a custom heading
-sub is_custom_heading ($%)
-{
- my $self = shift;
- my %args = (
- line => undef,
- @_
- );
- my $line = $args{line};
-
- foreach my $reg (@{$self->{custom_heading_regexp}})
- {
- return 1 if ($line =~ /$reg/);
- }
- return 0;
-} # is_custom_heading
-
-sub custom_heading ($%)
-{
- my $self = shift;
- my %args = (
- line_ref => undef,
- @_
- );
- my $line_ref = $args{line_ref};
-
- my $level;
- my $i = 0;
- foreach my $reg (@{$self->{custom_heading_regexp}})
- {
- if (${$line_ref} =~ /$reg/)
- {
- if ($self->{explicit_headings})
- {
- $level = $i + 1;
- }
- else
- {
- $level = $self->heading_level("Cust" . $i);
- }
- if ($self->{escape_HTML_chars})
- {
- ${$line_ref} = escape(${$line_ref});
- }
- $self->tagline("H" . $level, $line_ref);
- $self->anchor_heading($level, $line_ref);
- last;
- }
- $i++;
- }
-} # custom_heading
-
-sub unhyphenate_para ($$)
-{
- my $self = shift;
- my $para_ref = shift;
-
- # Treating this whole paragraph as one string, look for
- # 1 - whitespace
- # 2 - a word (ending in a hyphen, followed by a newline)
- # 3 - whitespace (starting on the next line)
- # 4 - a word with its punctuation
- # Substitute this with
- # 1-whitespace 2-word 4-word newline 3-whitespace
- # We preserve the 3-whitespace because we don't want to mess up
- # our existing indentation.
- ${$para_ref} =~
- /(\s*)([^\W\d_]*)\-\n(\s*)([^\W\d_]+[\)\}\]\.,:;\'\"\>]*\s*)/s;
- ${$para_ref} =~
-s/(\s*)([^\W\d_]*)\-\n(\s*)([^\W\d_]+[\)\}\]\.,:;\'\"\>]*\s*)/$1$2$4\n$3/gs;
-} # unhyphenate_para
-
-sub tagline ($$$)
-{
- my $self = shift;
- my $tag = shift;
- my $line_ref = shift;
-
- chomp ${$line_ref}; # Drop newline
- my $tag1 = $self->get_tag($tag);
- my $tag2 = $self->close_tag($tag);
- ${$line_ref} =~ s/^\s*(.*)$/${tag1}$1${tag2}\n/;
-} # tagline
-
-sub iscaps
-{
- my $self = shift;
- local ($_) = @_;
-
- my $min_caps_len = $self->{min_caps_length};
-
- # This is ugly, but I don't know a better way to do it.
- # (And, yes, I could use the literal characters instead of the
- # numeric codes, but this keeps the script 8-bit clean, which will
- # save someone a big headache when they transfer via ASCII ftp.
-/^[^a-z\341\343\344\352\353\354\363\370\337\373\375\342\345\347\350\355\357\364\365\376\371\377\340\346\351\360\356\361\362\366\372\374<]*[A-Z\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\330\331\332\333\334\335\336]{$min_caps_len,}[^a-z\341\343\344\352\353\354\363\370\337\373\375\342\345\347\350\355\357\364\365\376\371\377\340\346\351\360\356\361\362\366\372\374<]*$/;
-} # iscaps
-
-sub caps
-{
- my $self = shift;
- my %args = (
- line_ref => undef,
- line_action_ref => undef,
- @_
- );
- my $line_ref = $args{line_ref};
- my $line_action_ref = $args{line_action_ref};
-
- if ( $self->{caps_tag}
- && $self->iscaps(${$line_ref}))
- {
- $self->tagline($self->{caps_tag}, $line_ref);
- ${$line_action_ref} |= $CAPS;
- }
-} # caps
-
-sub do_delim
-{
- my $self = shift;
- my %args = (
- line_ref => undef,
- line_action_ref => undef,
- delim => '*',
- tag => 'STRONG',
- @_
- );
- my $line_ref = $args{line_ref};
- my $line_action_ref = $args{line_action_ref};
- my $delim = $args{delim};
- my $tag = $args{tag};
-
- if ($delim eq '#') # special treatment of # for the #num case
- {
- ${$line_ref} =~
-s/#([^0-9#](?![^#]*(?:<li>|<LI>|<P>|<p>))[^#]*[^# \t\n])#/<${tag}>$1<\/${tag}>/gs;
- ${$line_ref} =~ s/\B#([a-zA-Z])#\B/<${tag}>$1<\/${tag}>/gs;
- }
- elsif ($delim eq '^')
- {
- ${$line_ref} =~
-s/\^((?![^^]*(?:<li>|<LI>|<p>|<P>))(\w|["'<>])[^^]*)\^/<${tag}>$1<\/${tag}>/gs;
- ${$line_ref} =~ s/\B\^([a-zA-Z])\^\B/<${tag}>$1<\/${tag}>/gs;
- }
- elsif (length($delim) eq 1) # one-character, general
- {
- ${$line_ref} =~
-s/(?<![${delim}])[${delim}](?![^${delim}]*(?:<li>|<LI>|<p>|<P>))((\w|["'<>])[^${delim}]*)[${delim}]/<${tag}>$1<\/${tag}>/gs;
- ${$line_ref} =~
- s/\B[${delim}]([a-zA-Z])[${delim}]\B/<${tag}>$1<\/${tag}>/gs;
- }
- else
- {
- ${$line_ref} =~
-s/(?<!${delim})${delim}((\w|["'])(\w|[-\s\.;:,!?"'])*[^\s])${delim}/<${tag}>$1<\/${tag}>/gs;
- ${$line_ref} =~ s/${delim}]([a-zA-Z])${delim}/<${tag}>$1<\/${tag}>/gs;
- }
-} # do_delim
-
-# Convert very simple globs to regexps
-sub glob2regexp
-{
- my ($glob) = @_;
-
- # Escape funky chars
- $glob =~ s/[^\w\[\]\*\?\|\\]/\\$&/g;
- my ($regexp, $i, $len, $escaped) = ("", 0, length($glob), 0);
-
- for (; $i < $len; $i++)
- {
- my $char = substr($glob, $i, 1);
- if ($escaped)
- {
- $escaped = 0;
- $regexp .= $char;
- next;
- }
- if ($char eq "\\")
- {
- $escaped = 1;
- next;
- $regexp .= $char;
- }
- if ($char eq "?")
- {
- $regexp .= ".";
- next;
- }
- if ($char eq "*")
- {
- $regexp .= ".*";
- next;
- }
- $regexp .= $char; # Normal character
- }
- join('', "\\b", $regexp, "\\b");
-} # glob2regexp
-
-sub add_regexp_to_links_table ($$$$)
-{
- my $self = shift;
- my ($key, $URL, $switches) = @_;
-
- # No sense adding a second one if it's already in there.
- # It would never get used.
- if (!$self->{__links_table}->{$key})
- {
-
- # Keep track of the order they were added so we can
- # look for matches in the same order
- push(@{$self->{__links_table_order}}, ($key));
-
- $self->{__links_table}->{$key} = $URL; # Put it in The Table
- $self->{__links_switch_table}->{$key} = $switches;
- my $ind = @{$self->{__links_table_order}} - 1;
- print STDERR " (", $ind,
- ")\tKEY: $key\n\tVALUE: $URL\n\tSWITCHES: $switches\n\n"
- if ($self->{dict_debug} & 1);
- }
- else
- {
- if ($self->{dict_debug} & 1)
- {
- print STDERR " Skipping entry. Key already in table.\n";
- print STDERR "\tKEY: $key\n\tVALUE: $URL\n\n";
- }
- }
-} # add_regexp_to_links_table
-
-sub add_literal_to_links_table ($$$$)
-{
- my $self = shift;
- my ($key, $URL, $switches) = @_;
-
- $key =~ s/(\W)/\\$1/g; # Escape non-alphanumeric chars
- $key = "\\b$key\\b"; # Make a regexp out of it
- $self->add_regexp_to_links_table($key, $URL, $switches);
-} # add_literal_to_links_table
-
-sub add_glob_to_links_table ($$$$)
-{
- my $self = shift;
- my ($key, $URL, $switches) = @_;
-
- $self->add_regexp_to_links_table(glob2regexp($key), $URL, $switches);
-} # add_glob_to_links_table
-
-# Parse the dictionary file.
-# (see also load_dictionary_links, for things that were stripped)
-sub parse_dict ($$$)
-{
- my $self = shift;
-
- my ($dictfile, $dict) = @_;
-
- print STDERR "Parsing dictionary file $dictfile\n"
- if ($self->{dict_debug} & 1);
-
- if ($dict =~ /->\s*->/)
- {
- my $message = "Two consecutive '->'s found in $dictfile\n";
- my $near;
-
- # Print out any useful context so they can find it.
- ($near) = $dict =~ /([\S ]*\s*->\s*->\s*\S*)/;
- $message .= "\n$near\n" if $near =~ /\S/;
- die $message;
- }
-
- my ($key, $URL, $switches, $options);
- while ($dict =~ /\s*(.+)\s+\-+([iehos]+\-+)?\>\s*(.*\S+)\s*\n/ig)
- {
- $key = $1;
- $options = $2;
- $options = "" unless defined($options);
- $URL = $3;
- $switches = 0;
- # Case insensitivity
- $switches += $LINK_NOCASE if $options =~ /i/i;
- # Evaluate as Perl code
- $switches += $LINK_EVAL if $options =~ /e/i;
- # provides HTML, not just URL
- $switches += $LINK_HTML if $options =~ /h/i;
- # Only do this link once
- $switches += $LINK_ONCE if $options =~ /o/i;
- # Only do this link once per section
- $switches += $LINK_SECT_ONCE if $options =~ /s/i;
-
- $key =~ s/\s*$//; # Chop trailing whitespace
-
- if ($key =~ m|^/|) # Regexp
- {
- $key = substr($key, 1);
- $key =~ s|/$||; # Allow them to forget the closing /
- $self->add_regexp_to_links_table($key, $URL, $switches);
- }
- elsif ($key =~ /^\|/) # alternate regexp format
- {
- $key = substr($key, 1);
- $key =~ s/\|$//; # Allow them to forget the closing |
- $key =~ s|/|\\/|g; # Escape all slashes
- $self->add_regexp_to_links_table($key, $URL, $switches);
- }
- elsif ($key =~ /\"/)
- {
- $key = substr($key, 1);
- $key =~ s/\"$//; # Allow them to forget the closing "
- $self->add_literal_to_links_table($key, $URL, $switches);
- }
- else
- {
- $self->add_glob_to_links_table($key, $URL, $switches);
- }
- }
-
-} # parse_dict
-
-sub setup_dict_checking ($)
-{
- my $self = shift;
-
- # now create the replace funcs and precomile the regexes
- my ($URL, $switches, $options, $tag1, $tag2);
- my ($href, $r_sw);
- my @subs;
- my $i = 0;
- foreach my $pattern (@{$self->{__links_table_order}})
- {
- $switches = $self->{__links_switch_table}->{$pattern};
-
- $href = $self->{__links_table}->{$pattern};
-
- if (!($switches & $LINK_HTML))
- {
- $href =~ s#/#\\/#g;
- $href = (
- $self->{lower_case_tags}
- ? join('', '<a href="', $href, '">$&<\\/a>')
- : join('', '<A HREF="', $href, '">$&<\\/A>')
- );
- }
- else
- {
- # change the uppercase tags to lower case
- if ($self->{lower_case_tags})
- {
- $href =~ s#(</)([A-Z]*)(>)#${1}\L${2}${3}#g;
- $href =~ s/(<)([A-Z]*)(>)/${1}\L${2}${3}/g;
- # and the anchors
- $href =~ s/(<)(A\s*HREF)([^>]*>)/$1\L$2$3/g;
- }
- $href =~ s#/#\\/#g;
- }
-
- $r_sw = "s"; # Options for replacing
- $r_sw .= "i" if ($switches & $LINK_NOCASE);
- $r_sw .= "e" if ($switches & $LINK_EVAL);
-
- # Generate code for replacements.
- # Create an anonymous subroutine for each replacement,
- # and store its reference in an array.
- # We need to do an "eval" to create these because we need to
- # be able to treat the *contents* of the $href variable
- # as if it were perl code, because sometimes the $href
- # contains things which need to be evaluated, such as $& or $1,
- # not just those cases where we have a "e" switch.
- my $code = <<EOT;
-\$self->{__repl_code}->[$i] =
-sub {
-my \$al = shift;
-\$al =~ s/$pattern/$href/$r_sw;
-return \$al;
-};
-EOT
- print STDERR $code if ($self->{dict_debug} & 2);
- push @subs, $code;
-
- # compile searching pattern
- if ($switches & $LINK_NOCASE) # i
- {
- $self->{__search_patterns}->[$i] = qr/$pattern/si;
- }
- else
- {
- $self->{__search_patterns}->[$i] = qr/$pattern/s;
- }
- $i++;
- }
- # now eval the replacements code string
- my $codes = join('', @subs);
- eval "$codes";
-} # setup_dict_checking
-
-sub in_link_context ($$$)
-{
- my $self = shift;
- my ($match, $before) = @_;
- return 1 if $match =~ m@</?A>@i; # No links allowed inside match
-
- my ($final_open, $final_close);
- if ($self->{lower_case_tags})
- {
- $final_open = rindex($before, "<a ") - $[;
- $final_close = rindex($before, "</a>") - $[;
- }
- else
- {
- $final_open = rindex($before, "<A ") - $[;
- $final_close = rindex($before, "</A>") - $[;
- }
-
- return 1 if ($final_open >= 0) # Link opened
- && (
- ($final_close < 0) # and not closed or
- || ($final_open > $final_close)
- ); # one opened after last close
-
- # Now check to see if we're inside a tag, matching a tag name,
- # or attribute name or value
- $final_open = rindex($before, "<") - $[;
- $final_close = rindex($before, ">") - $[;
- ($final_open >= 0) # Tag opened
- && (
- ($final_close < 0) # and not closed or
- || ($final_open > $final_close)
- ); # one opened after last close
-} # in_link_context
-
-# apply links and formatting to this paragraph
-sub apply_links ($%)
-{
- my $self = shift;
- my %args = (
- para_ref => undef,
- para_action_ref => undef,
- @_
- );
- my $para_ref = $args{para_ref};
- my $para_action_ref = $args{para_action_ref};
-
- if ($self->{make_links}
- && @{$self->{__links_table_order}})
- {
- $self->check_dictionary_links(
- line_ref => $para_ref,
- line_action_ref => $para_action_ref
- );
- }
- if ($self->{bold_delimiter})
- {
- my $tag = ($self->{lower_case_tags} ? 'strong' : 'STRONG');
- $self->do_delim(
- line_ref => $para_ref,
- line_action_ref => $para_action_ref,
- delim => $self->{bold_delimiter},
- tag => $tag
- );
- }
- if ($self->{italic_delimiter})
- {
- my $tag = ($self->{lower_case_tags} ? 'em' : 'EM');
- $self->do_delim(
- line_ref => $para_ref,
- line_action_ref => $para_action_ref,
- delim => $self->{italic_delimiter},
- tag => $tag
- );
- }
-
-} # apply_links
-
-# Check (and alter if need be) the bits in this line matching
-# the patterns in the link dictionary.
-sub check_dictionary_links ($%)
-{
- my $self = shift;
- my %args = (
- line_ref => undef,
- line_action_ref => undef,
- @_
- );
- my $line_ref = $args{line_ref};
- my $line_action_ref = $args{line_action_ref};
-
- my ($switches, $options, $repl_func);
- my ($linkme, $line_with_links);
-
- # for each pattern, check and alter the line
- my $i = 0;
- foreach my $pattern (@{$self->{__links_table_order}})
- {
- $switches = $self->{__links_switch_table}->{$pattern};
-
- # check the pattern
- if ($switches & $LINK_ONCE) # Do link only once
- {
- $line_with_links = '';
- if (!$self->{__done_with_link}->[$i]
- && ${$line_ref} =~ $self->{__search_patterns}->[$i])
- {
- $self->{__done_with_link}->[$i] = 1;
- $line_with_links .= $`;
- $linkme = $&;
-
- ${$line_ref} = $';
- if (!$self->in_link_context($linkme, $line_with_links))
- {
- print STDERR "Link rule $i matches $linkme\n"
- if ($self->{dict_debug} & 4);
-
- # call the special subroutine already created to do
- # this replacement
- $repl_func = $self->{__repl_code}->[$i];
- $linkme = &$repl_func($linkme);
- }
- $line_with_links .= $linkme;
- }
- ${$line_ref} = $line_with_links . ${$line_ref};
- }
- elsif ($switches & $LINK_SECT_ONCE) # Do link only once per section
- {
- $line_with_links = '';
- if (!$self->{__done_with_sect_link}->[$i]
- && ${$line_ref} =~ $self->{__search_patterns}->[$i])
- {
- $self->{__done_with_sect_link}->[$i] = 1;
- $line_with_links .= $`;
- $linkme = $&;
-
- ${$line_ref} = $';
- if (!$self->in_link_context($linkme, $line_with_links))
- {
- print STDERR "Link rule $i matches $linkme\n"
- if ($self->{dict_debug} & 4);
-
- # call the special subroutine already created to do
- # this replacement
- $repl_func = $self->{__repl_code}->[$i];
- $linkme = &$repl_func($linkme);
- }
- $line_with_links .= $linkme;
- }
- ${$line_ref} = $line_with_links . ${$line_ref};
- }
- else
- {
- $line_with_links = '';
- while (${$line_ref} =~ $self->{__search_patterns}->[$i])
- {
- $line_with_links .= $`;
- $linkme = $&;
-
- ${$line_ref} = $';
- if (!$self->in_link_context($linkme, $line_with_links))
- {
- print STDERR "Link rule $i matches $linkme\n"
- if ($self->{dict_debug} & 4);
-
- # call the special subroutine already created to do
- # this replacement
- $repl_func = $self->{__repl_code}->[$i];
- $linkme = &$repl_func($linkme);
- }
- $line_with_links .= $linkme;
- }
- ${$line_ref} = $line_with_links . ${$line_ref};
- }
- $i++;
- }
- ${$line_action_ref} |= $LINK;
-} # check_dictionary_links
-
-sub load_dictionary_links ($)
-{
- my $self = shift;
-
- @{$self->{__links_table_order}} = ();
- %{$self->{__links_table}} = ();
-
- my $dict;
- foreach $dict (@{$self->{links_dictionaries}})
- {
- next unless $dict;
- open(DICT, "$dict") || die "Can't open Dictionary file $dict\n";
-
- my @lines = ();
- while (<DICT>)
- {
- # skip lines that start with '#'
- next if /^\#/;
- # skip lines that end with unescaped ':'
- next if /^.*[^\\]:\s*$/;
- push @lines, $_;
- }
- close(DICT);
- my $contents = join('', @lines);
- $self->parse_dict($dict, $contents);
- }
- # last of all, do the system dictionary, already read in from DATA
- if ($self->{__global_links_data})
- {
- $self->parse_dict("DATA", $self->{__global_links_data});
- }
-
- $self->setup_dict_checking();
-} # load_dictionary_links
-
-# do_file_start
-# extra stuff needed for the beginning
-# Args:
-# $self
-# $para
-# Return:
-# processed $para string
-sub do_file_start ($$$)
-{
- my $self = shift;
- my $outhandle = shift;
- my $para = shift;
-
- if (!$self->{extract})
- {
- my @para_lines = split(/\n/, $para);
- my $first_line = $para_lines[0];
-
- if ($self->{doctype})
- {
- if ($self->{xhtml})
- {
- print $outhandle
-'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"',
- "\n";
- print $outhandle
- '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
- "\n";
- }
- else
- {
- print $outhandle '<!DOCTYPE HTML PUBLIC "', $self->{doctype},
- "\">\n";
- }
- }
- print $outhandle $self->get_tag('HTML'), "\n";
- print $outhandle $self->get_tag('HEAD'), "\n";
-
- # if --titlefirst is set and --title isn't, use the first line
- # as the title.
- if ($self->{titlefirst} && !$self->{title})
- {
- my ($tit) = $first_line =~ /^ *(.*)/; # grab first line
- $tit =~ s/ *$//; # strip trailing whitespace
- $tit = escape($tit) if $self->{escape_HTML_chars};
- $self->{'title'} = $tit;
- }
- if (!$self->{title})
- {
- $self->{'title'} = "";
- }
- print $outhandle $self->get_tag('TITLE'), $self->{title},
- $self->close_tag('TITLE'), "\n";
-
- if ($self->{append_head})
- {
- open(APPEND, $self->{append_head})
- || die "Failed to open ", $self->{append_head}, "\n";
- while (<APPEND>)
- {
- print $outhandle $_;
- }
- close(APPEND);
- }
-
- if ($self->{lower_case_tags})
- {
- print $outhandle $self->get_tag(
- 'META',
- tag_type => 'empty',
- inside_tag => " name=\"generator\" content=\"$PROG v$VERSION\""
- ),
- "\n";
- }
- else
- {
- print $outhandle $self->get_tag(
- 'META',
- tag_type => 'empty',
- inside_tag => " NAME=\"generator\" CONTENT=\"$PROG v$VERSION\""
- ),
- "\n";
- }
- if ($self->{style_url})
- {
- my $style_url = $self->{style_url};
- if ($self->{lower_case_tags})
- {
- print $outhandle $self->get_tag(
- 'LINK',
- tag_type => 'empty',
- inside_tag =>
-" rel=\"stylesheet\" type=\"text/css\" href=\"$style_url\""
- ),
- "\n";
- }
- else
- {
- print $outhandle $self->get_tag(
- 'LINK',
- tag_type => 'empty',
- inside_tag =>
-" REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"$style_url\""
- ),
- "\n";
- }
- }
- print $outhandle $self->close_tag('HEAD'), "\n";
- if ($self->{body_deco})
- {
- print $outhandle $self->get_tag('BODY',
- inside_tag => $self->{body_deco}), "\n";
- }
- else
- {
- print $outhandle $self->get_tag('BODY'), "\n";
- }
- }
-
- if ($self->{prepend_file})
- {
- if (-r $self->{prepend_file})
- {
- open(PREPEND, $self->{prepend_file});
- while (<PREPEND>)
- {
- print $outhandle $_;
- }
- close(PREPEND);
- }
- else
- {
- print STDERR "Can't find or read file ", $self->{prepend_file},
- " to prepend.\n";
- }
- }
-} # do_file_start
-
-# do_init_call
-# certain things, like reading link dictionaries, need to be
-# done once
-sub do_init_call ($)
-{
- my $self = shift;
-
- if (!$self->{__call_init_done})
- {
- push(@{$self->{links_dictionaries}}, ($self->{default_link_dict}))
- if ($self->{make_links} && (-f $self->{default_link_dict}));
- $self->deal_with_options();
- if ($self->{make_links})
- {
- $self->load_dictionary_links();
- }
-
- # various initializations
- $self->{__non_header_anchor} = 0;
- $self->{__mode} = 0;
- $self->{__listnum} = 0;
- $self->{__list_nice_indent} = '';
- $self->{__list_indent} = [];
- $self->{__tags} = [];
-
- $self->{__call_init_done} = 1;
- }
-} # do_init_call
-
-=head1 FILE FORMATS
-
-There are two files which are used which can affect the outcome of the
-conversion. One is the link dictionary, which contains patterns (of how
-to recognise http links and other things) and how to convert them. The
-other is, naturally, the format of the input file itself.
-
-=head2 Link Dictionary
-
-A link dictionary file contains patterns to match, and what to convert
-them to. It is called a "link" dictionary because it was intended to be
-something which defined what a href link was, but it can be used for
-more than that. However, if you wish to define your own links, it is
-strongly advised to read up on regular expressions (regexes) because
-this relies heavily on them.
-
-The file consists of comments (which are lines starting with #)
-and blank lines, and link entries.
-Each entry consists of a regular expression, a -> separator (with
-optional flags), and a link "result".
-
-In the simplest case, with no flags, the regular expression
-defines the pattern to look for, and the result says what part
-of the regular expression is the actual link, and the link which
-is generated has the href as the link, and the whole matched pattern
-as the visible part of the link. The first character of the regular
-expression is taken to be the separator for the regex, so one
-could either use the traditional / separator, or something else
-such as | (which can be helpful with URLs which are full of / characters).
-
-So, for example, an ftp URL might be defined as:
-
- |ftp:[\w/\.:+\-]+| -> $&
-
-This takes the whole pattern as the href, and the resultant link
-has the same thing in the href as in the contents of the anchor.
-
-But sometimes the href isn't the whole pattern.
-
- /&lt;URL:\s*(\S+?)\s*&gt;/ --> $1
-
-With the above regex, a () grouping marks the first subexpression,
-which is represented as $1 (rather than $& the whole expression).
-This entry matches a URL which was marked explicity as a URL
-with the pattern <URL:foo> (note the &lt; is shown as the
-entity, not the actual character. This is because by the
-time the links dictionary is checked, all such things have
-already been converted to their HTML entity forms, unless, of course,
-the escape_HTML_chars option was turned off)
-This would give us a link in the form
-<A HREF="foo">&lt;URL:foo&gt;</A>
-
-B<The h flag>
-
-However, if we want more control over the way the link is constructed,
-we can construct it ourself. If one gives the h flag, then the
-"result" part of the entry is taken not to contain the href part of
-the link, but the whole link.
-
-For example, the entry:
-
- /&lt;URL:\s*(\S+?)\s*&gt;/ -h-> <A HREF="$1">$1</A>
-
-will take <URL:foo> and give us <A HREF="foo">foo</A>
-
-However, this is a very powerful mechanism, because it
-can be used to construct custom tags which aren't links at all.
-For example, to flag *italicised words* the following
-entry will surround the words with EM tags.
-
- /\B\*([a-z][a-z -]*[a-z])\*\B/ -hi-> <EM>$1</EM>
-
-B<The i flag>
-
-This turns on ignore case in the pattern matching.
-
-B<The e flag>
-
-This turns on execute in the pattern substitution. This really
-only makes sense if h is turned on too. In that case, the "result"
-part of the entry is taken as perl code to be executed, and the
-result of that code is what replaces the pattern.
-
-B<The o flag>
-
-This marks the entry as a once-only link. This will convert the
-first instance of a matching pattern, and ignore any others
-further on.
-
-For example, the following pattern will take the first mention
-of HTML::TextToHTML and convert it to a link to the module's home page.
-
- "HTML::TextToHTML" -io-> http://www.katspace.com/tools/text_to_html/
-
-=head2 Input File Format
-
-For the most part, this module tries to use intuitive conventions for
-determining the structure of the text input. Unordered lists are
-marked by bullets; ordered lists are marked by numbers or letters;
-in either case, an increase in indentation marks a sub-list contained
-in the outer list.
-
-Headers (apart from custom headers) are distinguished by "underlines"
-underneath them; headers in all-capitals are distinguished from
-those in mixed case. All headers, both normal and custom headers,
-are expected to start at the first line in a "paragraph".
-
-In other words, the following is a header:
-
- I am Head Man
- -------------
-
-But the following does not have a header:
-
- I am not a head Man, man
- I am Head Man
- -------------
-
-Tables require a more rigid convention. A table must be marked as a
-separate paragraph, that is, it must be surrounded by blank lines.
-Tables come in different types. For a table to be parsed, its
---table_type option must be on, and the --make_tables option must be true.
-
-B<ALIGN Table Type>
-
-Columns must be separated by two or more spaces (this prevents
-accidental incorrect recognition of a paragraph where interword spaces
-happen to line up). If there are two or more rows in a paragraph and
-all rows share the same set of (two or more) columns, the paragraph is
-assumed to be a table. For example
-
- -e File exists.
- -z File has zero size.
- -s File has nonzero size (returns size).
-
-becomes
-
- <TABLE>
- <TR><TD>-e</TD><TD>File exists.</TD></TR>
- <TR><TD>-z</TD><TD>File has zero size.</TD></TR>
- <TR><TD>-s</TD><TD>File has nonzero size (returns size).</TD></TR>
- </TABLE>
-
-This guesses for each column whether it is intended to be left,
-centre or right aligned.
-
-B<BORDER Table Type>
-
-This table type has nice borders around it, and will be rendered
-with a border, like so:
-
- +---------+---------+
- | Column1 | Column2 |
- +---------+---------+
- | val1 | val2 |
- | val3 | val3 |
- +---------+---------+
-
-The above becomes
-
- <TABLE border="1">
- <THEAD><TR><TH>Column1</TH><TH>Column2</TH></TR></THEAD>
- <TBODY>
- <TR><TD>val1</TD><TD>val2</TD></TR>
- <TR><TD>val3</TD><TD>val3</TD></TR>
- </TBODY>
- </TABLE>
-
-It can also have an optional caption at the start.
-
- My Caption
- +---------+---------+
- | Column1 | Column2 |
- +---------+---------+
- | val1 | val2 |
- | val3 | val3 |
- +---------+---------+
-
-B<PGSQL Table Type>
-
-This format of table is what one gets from the output of a Postgresql
-query.
-
- Column1 | Column2
- ---------+---------
- val1 | val2
- val3 | val3
- (2 rows)
-
-This can also have an optional caption at the start.
-This table is also rendered with a border and table-headers like
-the BORDER type.
-
-B<DELIM Table Type>
-
-This table type is delimited by non-alphanumeric characters, and has to
-have at least two rows and two columns before it's recognised as a table.
-
-This one is delimited by the '| character:
-
- | val1 | val2 |
- | val3 | val3 |
-
-But one can use almost any suitable character such as : # $ % + and so on.
-This is clever enough to figure out what you are using as the delimiter
-if you have your data set up like a table. Note that the line has to
-both begin and end with the delimiter, as well as using it to separate
-values.
-
-This can also have an optional caption at the start.
-
-=head1 EXAMPLES
-
- use HTML::TextToHTML;
-
-=head2 Create a new object
-
- my $conv = new HTML::TextToHTML();
-
- my $conv = new HTML::TextToHTML(title=>"Wonderful Things",
- default_link_dict=>$my_link_file,
- );
-
-=head2 Add further arguments
-
- $conv->args(short_line_length=>60,
- preformat_trigger_lines=>4,
- caps_tag=>"strong",
- );
-
-=head2 Convert a file
-
- $conv->txt2html(infile=>[$text_file],
- outfile=>$html_file,
- title=>"Wonderful Things",
- mail=>1
- );
-
-=head2 Make a pipleline
-
- open(IN, "ls |") or die "could not open!";
- $conv->txt2html(inhandle=>[\*IN],
- outfile=>'-',
- );
-
-=head1 NOTES
-
-=over
-
-=item *
-
-One cannot use "CLEAR" as a value for the cumulative arguments.
-
-=item *
-
-If the underline used to mark a header is off by more than 1, then
-that part of the text will not be picked up as a header unless you
-change the value of --underline_length_tolerance and/or
---underline_offset_tolerance. People tend to forget this.
-
-=back
-
-=head1 BUGS
-
-Tell me about them.
-
-=head1 SEE ALSO
-
-perl
-L<txt2html>.
-Data::Dumper
-
-=head1 AUTHOR
-
- Kathryn Andersen (RUBYKAT)
- perlkat AT katspace dot com
- http//www.katspace.com/
-
-based on txt2html by Seth Golub
-
-=head1 COPYRIGHT AND LICENCE
-
-Original txt2html script copyright (c) 1994-2000 Seth Golub <seth AT aigeek.com>
-
-Copyright (c) 2002-2005 by Kathryn Andersen
-
-This program is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=cut
-
-#------------------------------------------------------------------------
-1;
-__DATA__
-#
-# Global links dictionary file for HTML::TextToHTML
-# http://www.katspace.com/tools/text_to_html
-# http://txt2html.sourceforge.net/
-# based on links dictionary for Seth Golub's txt2html
-# http://www.aigeek.com/txt2html/
-#
-# This dictionary contains some patterns for converting obvious URLs,
-# ftp sites, hostnames, email addresses and the like to hrefs.
-#
-# Original adapted from the html.pl package by Oscar Nierstrasz in
-# the Software Archive of the Software Composition Group
-# http://iamwww.unibe.ch/~scg/Src/
-#
-
-# Some people even like to mark the URL label explicitly <URL:foo:label>
-/&lt;URL:([-\w\.\/:~_\@]+):([a-zA-Z0-9'() ]+)&gt;/ -h-> <A HREF="$1">$2</A>
-
-# Some people like to mark URLs explicitly <URL:foo>
-/&lt;URL:\s*(\S+?)\s*&gt;/ -h-> <A HREF="$1">$1</A>
-
-# <http://site>
-/&lt;(http:\S+?)\s*&gt;/ -h-> &lt;<A HREF="$1">$1</A>&gt;
-
-# Urls: <service>:<rest-of-url>
-
-|snews:[\w\.]+| -> $&
-|news:[\w\.]+| -> $&
-|nntp:[\w/\.:+\-]+| -> $&
-|http:[\w/\.:\@+\-~\%#?=&;,]+[\w/]| -> $&
-|shttp:[\w/\.:+\-~\%#?=&;,]+| -> $&
-|https:[\w/\.:+\-~\%#?=&;,]+| -> $&
-|file:[\w/\.:+\-]+| -> $&
-|ftp:[\w/\.:+\-]+| -> $&
-|wais:[\w/\.:+\-]+| -> $&
-|gopher:[\w/\.:+\-]+| -> $&
-|telnet:[\w/\@\.:+\-]+| -> $&
-
-
-# catch some newsgroups to avoid confusion with sites:
-|([^\w\-/\.:\@>])(alt\.[\w\.+\-]+[\w+\-]+)| -h-> $1<A HREF="news:$2">$2</A>
-|([^\w\-/\.:\@>])(bionet\.[\w\.+\-]+[\w+\-]+)| -h-> $1<A HREF="news:$2">$2</A>
-|([^\w\-/\.:\@>])(bit\.[\w\.+\-]+[\w+\-]+)| -h-> $1<A HREF="news:$2">$2</A>
-|([^\w\-/\.:\@>])(biz\.[\w\.+\-]+[\w+\-]+)| -h-> $1<A HREF="news:$2">$2</A>
-|([^\w\-/\.:\@>])(clari\.[\w\.+\-]+[\w+\-]+)| -h-> $1<A HREF="news:$2">$2</A>
-|([^\w\-/\.:\@>])(comp\.[\w\.+\-]+[\w+\-]+)| -h-> $1<A HREF="news:$2">$2</A>
-|([^\w\-/\.:\@>])(gnu\.[\w\.+\-]+[\w+\-]+)| -h-> $1<A HREF="news:$2">$2</A>
-|([^\w\-/\.:\@>])(humanities\.[\w\.+\-]+[\w+\-]+)|
- -h-> $1<A HREF="news:$2">$2</A>
-|([^\w\-/\.:\@>])(k12\.[\w\.+\-]+[\w+\-]+)| -h-> $1<A HREF="news:$2">$2</A>
-|([^\w\-/\.:\@>])(misc\.[\w\.+\-]+[\w+\-]+)| -h-> $1<A HREF="news:$2">$2</A>
-|([^\w\-/\.:\@>])(news\.[\w\.+\-]+[\w+\-]+)| -h-> $1<A HREF="news:$2">$2</A>
-|([^\w\-/\.:\@>])(rec\.[\w\.+\-]+[\w+\-]+)| -h-> $1<A HREF="news:$2">$2</A>
-|([^\w\-/\.:\@>])(soc\.[\w\.+\-]+[\w+\-]+)| -h-> $1<A HREF="news:$2">$2</A>
-|([^\w\-/\.:\@>])(talk\.[\w\.+\-]+[\w+\-]+)| -h-> $1<A HREF="news:$2">$2</A>
-|([^\w\-/\.:\@>])(us\.[\w\.+\-]+[\w+\-]+)| -h-> $1<A HREF="news:$2">$2</A>
-|([^\w\-/\.:\@>])(ch\.[\w\.+\-]+[\w+\-]+)| -h-> $1<A HREF="news:$2">$2</A>
-|([^\w\-/\.:\@>])(de\.[\w\.+\-]+[\w+\-]+)| -h-> $1<A HREF="news:$2">$2</A>
-
-# FTP locations (with directory):
-# anonymous@<site>:<path>
-|(anonymous\@)([a-zA-Z][\w\.+\-]+\.[a-zA-Z]{2,}):(\s*)([\w\d+\-/\.]+)|
- -h-> $1<A HREF="ftp://$2/$4">$2:$4</A>$3
-
-# ftp@<site>:<path>
-|(ftp\@)([a-zA-Z][\w\.+\-]+\.[a-zA-Z]{2,}):(\s*)([\w\d+\-/\.]+)|
- -h-> $1<A HREF="ftp://$2/$4">$2:$4</A>$3
-
-# Email address
-|[a-zA-Z0-9_\+\-\.]+\@([a-zA-Z0-9][\w\.+\-]+\.[a-zA-Z]{2,})|
- -> mailto:$&
-
-# <site>:<path>
-|([^\w\-/\.:\@>])([a-zA-Z][\w\.+\-]+\.[a-zA-Z]{2,}):(\s*)([\w\d+\-/\.]+)|
- -h-> $1<A HREF="ftp://$2/$4">$2:$4</A>$3
-
-# NB: don't confuse an http server with a port number for
-# an FTP location!
-# internet number version: <internet-num>:<path>
-|([^\w\-/\.:\@])(\d{2,}\.\d{2,}\.\d+\.\d+):([\w\d+\-/\.]+)|
- -h-> $1<A HREF="ftp://$2/$3">$2:$3</A>
-
-# telnet <site> <port>
-|telnet ([a-zA-Z][\w+\-]+(\.[\w\.+\-]+)+\.[a-zA-Z]{2,})\s+(\d{2,4})|
- -h-> telnet <A HREF="telnet://$1:$3/">$1 $3</A>
-
-# ftp <site>
-|ftp ([a-zA-Z][\w+\-]+(\.[\w\.+\-]+)+\.[a-zA-Z]{2,})|
- -h-> ftp <A HREF="ftp://$1/">$1</A>
-
-# host with "ftp" in the machine name
-|\b([a-zA-Z][\w])*ftp[\w]*(\.[\w+\-]+){2,}| -h-> ftp <A HREF="ftp://$&/">$&</A>
-
-# ftp.foo.net/blah/
-|ftp(\.[a-zA-Z0-9_\@:-]+)+/\S+| -> ftp://$&
-
-# www.thehouse.org/txt2html/
-|www(\.[a-zA-Z0-9_\@:-]+)+/\S+| -> http://$&
-
-# host with "www" in the machine name
-|\b([a-zA-Z][\w])*www[\w]*(\.[\w+\-]+){2,}| -> http://$&/
-
-# <site> <port>
-|([a-zA-Z][\w+\-]+\.[\w+\-]+\.[a-zA-Z]{2,})\s+(\d{2,4})|
- -h-> <A HREF="telnet://$1:$2/">$1 $2</A>
-
-# just internet numbers with port:
-|([^\w\-/\.:\@])(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+(\d{1,4})|
- -h-> $1<A HREF="telnet://$2:$3">$2 $3</A>
-
-# just internet numbers:
-|([^\w\-/\.:\@])(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|
- -h-> $1<A HREF="telnet://$2">$2</A>
-
-# RFCs
-/RFC ?(\d+)/ -i-> http://www.cis.ohio-state.edu/rfc/rfc$1.txt
-
-# This would turn "f^H_o^H_o^H_" into "<U>foo</U>". Gross, isn't it?
-# Thanks to Mark O'Dell <emark@cns.caltech.edu> for fixing this.
-#
-# /(.\\010_)+/ -he-> $tmp = $&;$tmp =~ s@\010_@@g;"<U>$tmp</U>"
-# /(_\\010.)+/ -he-> $tmp = $&;$tmp =~ s@_\010@@g;"<U>$tmp</U>"
-# /(.\^H_)+/ -he-> $tmp = $&;$tmp =~ s@\^H_@@g;"<U>$tmp</U>"
-# /(_\^H.)+/ -he-> $tmp = $&;$tmp =~ s@_\^H@@g;"<U>$tmp</U>"
-
-# Mark _underlined stuff_ as <U>underlined stuff</U>
-# Don't mistake variable names for underlines, and
-# take account of possible trailing punctuation
-/([ \t\n])_([a-z][a-z0-9 -]*[a-z])_([ \t\n\.;:,\!\?])/ -hi-> $1<U>$2</U>$3
-
-# Seth and his amazing conversion program :-)
-
-"Seth Golub" -io-> http://www.aigeek.com/
-"txt2html" -io-> http://txt2html.sourceforge.net/
-
-# Kathryn and her amazing modules 8-)
-"Kathryn Andersen" -io-> http://www.katspace.com/
-"HTML::TextToHTML" -io-> http://www.katspace.com/tools/text_to_html/
-"hypertoc" -io-> http://www.katspace.com/tools/hypertoc/
-"HTML::GenToc" -io-> http://www.katspace.com/tools/hypertoc/
-
-# End of global dictionary
-
diff --git a/lib/MP3/Info.pm b/lib/MP3/Info.pm
deleted file mode 100644
index 3303ac5..0000000
--- a/lib/MP3/Info.pm
+++ /dev/null
@@ -1,1563 +0,0 @@
-package MP3::Info;
-use overload;
-use strict;
-use Carp;
-use Symbol;
-
-use vars qw(
- @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION $REVISION
- @mp3_genres %mp3_genres @winamp_genres %winamp_genres $try_harder
- @t_bitrate @t_sampling_freq @frequency_tbl %v1_tag_fields
- @v1_tag_names %v2_tag_names %v2_to_v1_names $AUTOLOAD
- @mp3_info_fields
-);
-
-@ISA = 'Exporter';
-@EXPORT = qw(
- set_mp3tag get_mp3tag get_mp3info remove_mp3tag
- use_winamp_genres
-);
-@EXPORT_OK = qw(@mp3_genres %mp3_genres use_mp3_utf8);
-%EXPORT_TAGS = (
- genres => [qw(@mp3_genres %mp3_genres)],
- utf8 => [qw(use_mp3_utf8)],
- all => [@EXPORT, @EXPORT_OK]
-);
-
-# $Id: Info.pm,v 1.15 2003/03/02 19:16:43 pudge Exp $
-($REVISION) = ' $Revision: 1.15 $ ' =~ /\$Revision:\s+([^\s]+)/;
-$VERSION = '1.02';
-
-=pod
-
-=head1 NAME
-
-MP3::Info - Manipulate / fetch info from MP3 audio files
-
-=head1 SYNOPSIS
-
- #!perl -w
- use MP3::Info;
- my $file = 'Pearls_Before_Swine.mp3';
- set_mp3tag($file, 'Pearls Before Swine', q"77's",
- 'Sticks and Stones', '1990',
- q"(c) 1990 77's LTD.", 'rock & roll');
-
- my $tag = get_mp3tag($file) or die "No TAG info";
- $tag->{GENRE} = 'rock';
- set_mp3tag($file, $tag);
-
- my $info = get_mp3info($file);
- printf "$file length is %d:%d\n", $info->{MM}, $info->{SS};
-
-=cut
-
-{
- my $c = -1;
- # set all lower-case and regular-cased versions of genres as keys
- # with index as value of each key
- %mp3_genres = map {($_, ++$c, lc, $c)} @mp3_genres;
-
- # do it again for winamp genres
- $c = -1;
- %winamp_genres = map {($_, ++$c, lc, $c)} @winamp_genres;
-}
-
-=pod
-
- my $mp3 = new MP3::Info $file;
- $mp3->title('Perls Before Swine');
- printf "$file length is %s, title is %s\n",
- $mp3->time, $mp3->title;
-
-
-=head1 DESCRIPTION
-
-=over 4
-
-=item $mp3 = MP3::Info-E<gt>new(FILE)
-
-OOP interface to the rest of the module. The same keys
-available via get_mp3info and get_mp3tag are available
-via the returned object (using upper case or lower case;
-but note that all-caps "VERSION" will return the module
-version, not the MP3 version).
-
-Passing a value to one of the methods will set the value
-for that tag in the MP3 file, if applicable.
-
-=cut
-
-sub new {
- my($pack, $file) = @_;
-
- my $info = get_mp3info($file) or return undef;
- my $tags = get_mp3tag($file) || { map { ($_ => undef) } @v1_tag_names };
- my %self = (
- FILE => $file,
- TRY_HARDER => 0
- );
-
- @self{@mp3_info_fields, @v1_tag_names, 'file'} = (
- @{$info}{@mp3_info_fields},
- @{$tags}{@v1_tag_names},
- $file
- );
-
- return bless \%self, $pack;
-}
-
-sub can {
- my $self = shift;
- return $self->SUPER::can(@_) unless ref $self;
- my $name = uc shift;
- return sub { $self->$name(@_) } if exists $self->{$name};
- return undef;
-}
-
-sub AUTOLOAD {
- my($self) = @_;
- (my $name = uc $AUTOLOAD) =~ s/^.*://;
-
- if (exists $self->{$name}) {
- my $sub = exists $v1_tag_fields{$name}
- ? sub {
- if (defined $_[1]) {
- $_[0]->{$name} = $_[1];
- set_mp3tag($_[0]->{FILE}, $_[0]);
- }
- return $_[0]->{$name};
- }
- : sub {
- return $_[0]->{$name}
- };
-
- no strict 'refs';
- *{$AUTOLOAD} = $sub;
- goto &$AUTOLOAD;
-
- } else {
- carp(sprintf "No method '$name' available in package %s.",
- __PACKAGE__);
- }
-}
-
-sub DESTROY {
-
-}
-
-
-=item use_mp3_utf8([STATUS])
-
-Tells MP3::Info to (or not) return TAG info in UTF-8.
-TRUE is 1, FALSE is 0. Default is FALSE.
-
-Will only be able to it on if Unicode::String is available. ID3v2
-tags will be converted to UTF-8 according to the encoding specified
-in each tag; ID3v1 tags will be assumed Latin-1 and converted
-to UTF-8.
-
-Function returns status (TRUE/FALSE). If no argument is supplied,
-or an unaccepted argument is supplied, function merely returns status.
-
-This function is not exported by default, but may be exported
-with the C<:utf8> or C<:all> export tag.
-
-=cut
-
-my $unicode_module = 0; #eval { require Unicode::String };
-my $UNICODE = 0;
-
-sub use_mp3_utf8 {
- my($val) = @_;
- if ($val == 1) {
- $UNICODE = 1 if $unicode_module;
- } elsif ($val == 0) {
- $UNICODE = 0;
- }
- return $UNICODE;
-}
-
-=pod
-
-=item use_winamp_genres()
-
-Puts WinAmp genres into C<@mp3_genres> and C<%mp3_genres>
-(adds 68 additional genres to the default list of 80).
-This is a separate function because these are non-standard
-genres, but they are included because they are widely used.
-
-You can import the data structures with one of:
-
- use MP3::Info qw(:genres);
- use MP3::Info qw(:DEFAULT :genres);
- use MP3::Info qw(:all);
-
-=cut
-
-sub use_winamp_genres {
- %mp3_genres = %winamp_genres;
- @mp3_genres = @winamp_genres;
- return 1;
-}
-
-=pod
-
-=item remove_mp3tag (FILE [, VERSION, BUFFER])
-
-Can remove ID3v1 or ID3v2 tags. VERSION should be C<1> for ID3v1,
-C<2> for ID3v2, and C<ALL> for both.
-
-For ID3v1, removes last 128 bytes from file if those last 128 bytes begin
-with the text 'TAG'. File will be 128 bytes shorter.
-
-For ID3v2, removes ID3v2 tag. Because an ID3v2 tag is at the
-beginning of the file, we rewrite the file after removing the tag data.
-The buffer for rewriting the file is 4MB. BUFFER (in bytes) ca
-change the buffer size.
-
-Returns the number of bytes removed, or -1 if no tag removed,
-or undef if there is an error.
-
-=cut
-
-sub remove_mp3tag {
- my($file, $version, $buf) = @_;
- my($fh, $return);
-
- $buf ||= 4096*1024; # the bigger the faster
- $version ||= 1;
-
- if (not (defined $file && $file ne '')) {
- $@ = "No file specified";
- return undef;
- }
-
- if (not -s $file) {
- $@ = "File is empty";
- return undef;
- }
-
- if (ref $file) { # filehandle passed
- $fh = $file;
- } else {
- $fh = gensym;
- if (not open $fh, "+< $file\0") {
- $@ = "Can't open $file: $!";
- return undef;
- }
- }
-
- binmode $fh;
-
- if ($version eq 1 || $version eq 'ALL') {
- seek $fh, -128, 2;
- my $tell = tell $fh;
- if (<$fh> =~ /^TAG/) {
- truncate $fh, $tell or carp "Can't truncate '$file': $!";
- $return += 128;
- }
- }
-
- if ($version eq 2 || $version eq 'ALL') {
- my $h = _get_v2head($fh);
- if ($h) {
- local $\;
- seek $fh, 0, 2;
- my $eof = tell $fh;
- my $off = $h->{tag_size};
-
- while ($off < $eof) {
- seek $fh, $off, 0;
- read $fh, my($bytes), $buf;
- seek $fh, $off - $h->{tag_size}, 0;
- print $fh $bytes;
- $off += $buf;
- }
-
- truncate $fh, $eof - $h->{tag_size}
- or carp "Can't truncate '$file': $!";
- $return += $h->{tag_size};
- }
- }
-
- _close($file, $fh);
-
- return $return || -1;
-}
-
-
-=pod
-
-=item set_mp3tag (FILE, TITLE, ARTIST, ALBUM, YEAR, COMMENT, GENRE [, TRACKNUM])
-
-=item set_mp3tag (FILE, $HASHREF)
-
-Adds/changes tag information in an MP3 audio file. Will clobber
-any existing information in file.
-
-Fields are TITLE, ARTIST, ALBUM, YEAR, COMMENT, GENRE. All fields have
-a 30-byte limit, except for YEAR, which has a four-byte limit, and GENRE,
-which is one byte in the file. The GENRE passed in the function is a
-case-insensitive text string representing a genre found in C<@mp3_genres>.
-
-Will accept either a list of values, or a hashref of the type
-returned by C<get_mp3tag>.
-
-If TRACKNUM is present (for ID3v1.1), then the COMMENT field can only be
-28 bytes.
-
-ID3v2 support may come eventually. Note that if you set a tag on a file
-with ID3v2, the set tag will be for ID3v1[.1] only, and if you call
-C<get_mp3_tag> on the file, it will show you the (unchanged) ID3v2 tags,
-unless you specify ID3v1.
-
-=cut
-
-sub set_mp3tag {
- my($file, $title, $artist, $album, $year, $comment, $genre, $tracknum) = @_;
- my(%info, $oldfh, $ref, $fh);
- local %v1_tag_fields = %v1_tag_fields;
-
- # set each to '' if undef
- for ($title, $artist, $album, $year, $comment, $tracknum, $genre,
- (@info{@v1_tag_names}))
- {$_ = defined() ? $_ : ''}
-
- ($ref) = (overload::StrVal($title) =~ /^(?:.*\=)?([^=]*)\((?:[^\(]*)\)$/)
- if ref $title;
- # populate data to hashref if hashref is not passed
- if (!$ref) {
- (@info{@v1_tag_names}) =
- ($title, $artist, $album, $year, $comment, $tracknum, $genre);
-
- # put data from hashref into hashref if hashref is passed
- } elsif ($ref eq 'HASH') {
- %info = %$title;
-
- # return otherwise
- } else {
- carp(<<'EOT');
-Usage: set_mp3tag (FILE, TITLE, ARTIST, ALBUM, YEAR, COMMENT, GENRE [, TRACKNUM])
- set_mp3tag (FILE, $HASHREF)
-EOT
- return undef;
- }
-
- if (not (defined $file && $file ne '')) {
- $@ = "No file specified";
- return undef;
- }
-
- if (not -s $file) {
- $@ = "File is empty";
- return undef;
- }
-
- # comment field length 28 if ID3v1.1
- $v1_tag_fields{COMMENT} = 28 if $info{TRACKNUM};
-
-
- # only if -w is on
- if ($^W) {
- # warn if fields too long
- foreach my $field (keys %v1_tag_fields) {
- $info{$field} = '' unless defined $info{$field};
- if (length($info{$field}) > $v1_tag_fields{$field}) {
- carp "Data too long for field $field: truncated to " .
- "$v1_tag_fields{$field}";
- }
- }
-
- if ($info{GENRE}) {
- carp "Genre `$info{GENRE}' does not exist\n"
- unless exists $mp3_genres{$info{GENRE}};
- }
- }
-
- if ($info{TRACKNUM}) {
- $info{TRACKNUM} =~ s/^(\d+)\/(\d+)$/$1/;
- unless ($info{TRACKNUM} =~ /^\d+$/ &&
- $info{TRACKNUM} > 0 && $info{TRACKNUM} < 256) {
- carp "Tracknum `$info{TRACKNUM}' must be an integer " .
- "from 1 and 255\n" if $^W;
- $info{TRACKNUM} = '';
- }
- }
-
- if (ref $file) { # filehandle passed
- $fh = $file;
- } else {
- $fh = gensym;
- if (not open $fh, "+< $file\0") {
- $@ = "Can't open $file: $!";
- return undef;
- }
- }
-
- binmode $fh;
- $oldfh = select $fh;
- seek $fh, -128, 2;
- # go to end of file if no tag, beginning of file if tag
- seek $fh, (<$fh> =~ /^TAG/ ? -128 : 0), 2;
-
- # get genre value
- $info{GENRE} = $info{GENRE} && exists $mp3_genres{$info{GENRE}} ?
- $mp3_genres{$info{GENRE}} : 255; # some default genre
-
- local $\;
- # print TAG to file
- if ($info{TRACKNUM}) {
- print pack "a3a30a30a30a4a28xCC", 'TAG', @info{@v1_tag_names};
- } else {
- print pack "a3a30a30a30a4a30C", 'TAG', @info{@v1_tag_names[0..4, 6]};
- }
-
- select $oldfh;
-
- _close($file, $fh);
-
- return 1;
-}
-
-=pod
-
-=item get_mp3tag (FILE [, VERSION, RAW_V2])
-
-Returns hash reference containing tag information in MP3 file. The keys
-returned are the same as those supplied for C<set_mp3tag>, except in the
-case of RAW_V2 being set.
-
-If VERSION is C<1>, the information is taken from the ID3v1 tag (if present).
-If VERSION is C<2>, the information is taken from the ID3v2 tag (if present).
-If VERSION is not supplied, or is false, the ID3v1 tag is read if present, and
-then, if present, the ID3v2 tag information will override any existing ID3v1
-tag info.
-
-If RAW_V2 is C<1>, the raw ID3v2 tag data is returned, without any manipulation
-of text encoding. The key name is the same as the frame ID (ID to name mappings
-are in the global %v2_tag_names).
-
-If RAW_V2 is C<2>, the ID3v2 tag data is returned, manipulating for Unicode if
-necessary, etc. It also takes multiple values for a given key (such as comments)
-and puts them in an arrayref.
-
-If the ID3v2 version is older than ID3v2.2.0 or newer than ID3v2.4.0, it will
-not be read.
-
-Strings returned will be in Latin-1, unless UTF-8 is specified (L<use_mp3_utf8>),
-(unless RAW_V2 is C<1>).
-
-Also returns a TAGVERSION key, containing the ID3 version used for the returned
-data (if TAGVERSION argument is C<0>, may contain two versions).
-
-=cut
-
-sub get_mp3tag {
- my($file, $ver, $raw_v2) = @_;
- my($tag, $v1, $v2, $v2h, %info, @array, $fh);
- $raw_v2 ||= 0;
- $ver = !$ver ? 0 : ($ver == 2 || $ver == 1) ? $ver : 0;
-
- if (not (defined $file && $file ne '')) {
- $@ = "No file specified";
- return undef;
- }
-
- if (not -s $file) {
- $@ = "File is empty";
- return undef;
- }
-
- if (ref $file) { # filehandle passed
- $fh = $file;
- } else {
- $fh = gensym;
- if (not open $fh, "< $file\0") {
- $@ = "Can't open $file: $!";
- return undef;
- }
- }
-
- binmode $fh;
-
- if ($ver < 2) {
- seek $fh, -128, 2;
- while(defined(my $line = <$fh>)) { $tag .= $line }
-
- if ($tag =~ /^TAG/) {
- $v1 = 1;
- if (substr($tag, -3, 2) =~ /\000[^\000]/) {
- (undef, @info{@v1_tag_names}) =
- (unpack('a3a30a30a30a4a28', $tag),
- ord(substr($tag, -2, 1)),
- $mp3_genres[ord(substr $tag, -1)]);
- $info{TAGVERSION} = 'ID3v1.1';
- } else {
- (undef, @info{@v1_tag_names[0..4, 6]}) =
- (unpack('a3a30a30a30a4a30', $tag),
- $mp3_genres[ord(substr $tag, -1)]);
- $info{TAGVERSION} = 'ID3v1';
- }
- if ($UNICODE) {
- for my $key (keys %info) {
- next unless $info{$key};
- my $u = Unicode::String::latin1($info{$key});
- $info{$key} = $u->utf8;
- }
- }
- } elsif ($ver == 1) {
- _close($file, $fh);
- $@ = "No ID3v1 tag found";
- return undef;
- }
- }
-
- ($v2, $v2h) = _get_v2tag($fh);
-
- unless ($v1 || $v2) {
- _close($file, $fh);
- $@ = "No ID3 tag found";
- return undef;
- }
-
- if (($ver == 0 || $ver == 2) && $v2) {
- if ($raw_v2 == 1 && $ver == 2) {
- %info = %$v2;
- $info{TAGVERSION} = $v2h->{version};
- } else {
- my $hash = $raw_v2 == 2 ? { map { ($_, $_) } keys %v2_tag_names } : \%v2_to_v1_names;
- for my $id (keys %$hash) {
- if (exists $v2->{$id}) {
- if ($id =~ /^TCON?$/ && $v2->{$id} =~ /^.?\((\d+)\)/) {
- $info{$hash->{$id}} = $mp3_genres[$1];
- } else {
- my $data1 = $v2->{$id};
-
- # this is tricky ... if this is an arrayref,
- # we want to only return one, so we pick the
- # first one. but if it is a comment, we pick
- # the first one where the first charcter after
- # the language is NULL and not an additional
- # sub-comment, because that is most likely to be
- # the user-supplied comment
- if (ref $data1 && !$raw_v2) {
- if ($id =~ /^COMM?$/) {
- my($newdata) = grep /^(....\000)/, @{$data1};
- $data1 = $newdata || $data1->[0];
- } else {
- $data1 = $data1->[0];
- }
- }
-
- $data1 = [ $data1 ] if ! ref $data1;
-
- for my $data (@$data1) {
- $data =~ s/^(.)//; # strip first char (text encoding)
- my $encoding = $1;
- my $desc;
- if ($id =~ /^COM[M ]?$/) {
- $data =~ s/^(?:...)//; # strip language
- $data =~ s/^(.*?)\000+//; # strip up to first NULL(s),
- # for sub-comment
- $desc = $1;
- }
-
- if ($UNICODE) {
- if ($encoding eq "\001" || $encoding eq "\002") { # UTF-16, UTF-16BE
- my $u = Unicode::String::utf16($data);
- $data = $u->utf8;
- $data =~ s/^\xEF\xBB\xBF//; # strip BOM
- } elsif ($encoding eq "\000") {
- my $u = Unicode::String::latin1($data);
- $data = $u->utf8;
- }
- }
-
- if ($raw_v2 == 2 && $desc) {
- $data = { $desc => $data };
- }
-
- if ($raw_v2 == 2 && exists $info{$hash->{$id}}) {
- if (ref $info{$hash->{$id}} eq 'ARRAY') {
- push @{$info{$hash->{$id}}}, $data;
- } else {
- $info{$hash->{$id}} = [ $info{$hash->{$id}}, $data ];
- }
- } else {
- $info{$hash->{$id}} = $data;
- }
- }
- }
- }
- }
- if ($ver == 0 && $info{TAGVERSION}) {
- $info{TAGVERSION} .= ' / ' . $v2h->{version};
- } else {
- $info{TAGVERSION} = $v2h->{version};
- }
- }
- }
-
- unless ($raw_v2 && $ver == 2) {
- foreach my $key (keys %info) {
- if (defined $info{$key}) {
- $info{$key} =~ s/\000+.*//g;
- $info{$key} =~ s/\s+$//;
- }
- }
-
- for (@v1_tag_names) {
- $info{$_} = '' unless defined $info{$_};
- }
- }
-
- if (keys %info && exists $info{GENRE} && ! defined $info{GENRE}) {
- $info{GENRE} = '';
- }
-
- _close($file, $fh);
-
- return keys %info ? {%info} : undef;
-}
-
-sub _get_v2tag {
- my($fh) = @_;
- my($off, $myseek, $myseek_22, $myseek_23, $v2, $h, $hlen, $num);
- $h = {};
-
- $v2 = _get_v2head($fh) or return;
- if ($v2->{major_version} < 2) {
- carp "This is $v2->{version}; " .
- "ID3v2 versions older than ID3v2.2.0 not supported\n"
- if $^W;
- return;
- }
-
- if ($v2->{major_version} == 2) {
- $hlen = 6;
- $num = 3;
- } else {
- $hlen = 10;
- $num = 4;
- }
-
- $myseek = sub {
- seek $fh, $off, 0;
- read $fh, my($bytes), $hlen;
- return unless $bytes =~ /^([A-Z0-9]{$num})/
- || ($num == 4 && $bytes =~ /^(COM )/); # stupid iTunes
- my($id, $size) = ($1, $hlen);
- my @bytes = reverse unpack "C$num", substr($bytes, $num, $num);
- for my $i (0 .. ($num - 1)) {
- $size += $bytes[$i] * 256 ** $i;
- }
- return($id, $size);
- };
-
- $off = $v2->{ext_header_size} + 10;
-
- while ($off < $v2->{tag_size}) {
- my($id, $size) = &$myseek or last;
- seek $fh, $off + $hlen, 0;
- read $fh, my($bytes), $size - $hlen;
- if (exists $h->{$id}) {
- if (ref $h->{$id} eq 'ARRAY') {
- push @{$h->{$id}}, $bytes;
- } else {
- $h->{$id} = [$h->{$id}, $bytes];
- }
- } else {
- $h->{$id} = $bytes;
- }
- $off += $size;
- }
-
- return($h, $v2);
-}
-
-
-=pod
-
-=item get_mp3info (FILE)
-
-Returns hash reference containing file information for MP3 file.
-This data cannot be changed. Returned data:
-
- VERSION MPEG audio version (1, 2, 2.5)
- LAYER MPEG layer description (1, 2, 3)
- STEREO boolean for audio is in stereo
-
- VBR boolean for variable bitrate
- BITRATE bitrate in kbps (average for VBR files)
- FREQUENCY frequency in kHz
- SIZE bytes in audio stream
-
- SECS total seconds
- MM minutes
- SS leftover seconds
- MS leftover milliseconds
- TIME time in MM:SS
-
- COPYRIGHT boolean for audio is copyrighted
- PADDING boolean for MP3 frames are padded
- MODE channel mode (0 = stereo, 1 = joint stereo,
- 2 = dual channel, 3 = single channel)
- FRAMES approximate number of frames
- FRAME_LENGTH approximate length of a frame
- VBR_SCALE VBR scale from VBR header
-
-On error, returns nothing and sets C<$@>.
-
-=cut
-
-sub get_mp3info {
- my($file) = @_;
- my($off, $myseek, $byte, $eof, $h, $tot, $fh);
-
- if (not (defined $file && $file ne '')) {
- $@ = "No file specified";
- return undef;
- }
-
- if (not -s $file) {
- $@ = "File is empty";
- return undef;
- }
-
- if (ref $file) { # filehandle passed
- $fh = $file;
- } else {
- $fh = gensym;
- if (not open $fh, "< $file\0") {
- $@ = "Can't open $file: $!";
- return undef;
- }
- }
-
- $off = 0;
- $tot = 4096;
-
- $myseek = sub {
- seek $fh, $off, 0;
- read $fh, $byte, 4;
- };
-
- binmode $fh;
- &$myseek;
-
- if ($off == 0) {
- if (my $id3v2 = _get_v2head($fh)) {
- $tot += $off += $id3v2->{tag_size};
- &$myseek;
- }
- }
-
- $h = _get_head($byte);
- until (_is_mp3($h)) {
- $off++;
- &$myseek;
- $h = _get_head($byte);
- if ($off > $tot && !$try_harder) {
- _close($file, $fh);
- $@ = "Couldn't find MP3 header (perhaps set " .
- '$MP3::Info::try_harder and retry)';
- return undef;
- }
- }
-
- my $vbr = _get_vbr($fh, $h, \$off);
-
- seek $fh, 0, 2;
- $eof = tell $fh;
- seek $fh, -128, 2;
- $off += 128 if <$fh> =~ /^TAG/ ? 1 : 0;
-
- _close($file, $fh);
-
- $h->{size} = $eof - $off;
-
- return _get_info($h, $vbr);
-}
-
-sub _get_info {
- my($h, $vbr) = @_;
- my $i;
-
- $i->{VERSION} = $h->{IDR} == 2 ? 2 : $h->{IDR} == 3 ? 1 :
- $h->{IDR} == 0 ? 2.5 : 0;
- $i->{LAYER} = 4 - $h->{layer};
- $i->{VBR} = defined $vbr ? 1 : 0;
-
- $i->{COPYRIGHT} = $h->{copyright} ? 1 : 0;
- $i->{PADDING} = $h->{padding_bit} ? 1 : 0;
- $i->{STEREO} = $h->{mode} == 3 ? 0 : 1;
- $i->{MODE} = $h->{mode};
-
- $i->{SIZE} = $vbr && $vbr->{bytes} ? $vbr->{bytes} : $h->{size};
-
- my $mfs = $h->{fs} / ($h->{ID} ? 144000 : 72000);
- $i->{FRAMES} = int($vbr && $vbr->{frames}
- ? $vbr->{frames}
- : $i->{SIZE} / $h->{bitrate} / $mfs
- );
-
- if ($vbr) {
- $i->{VBR_SCALE} = $vbr->{scale} if $vbr->{scale};
- $h->{bitrate} = $i->{SIZE} / $i->{FRAMES} * $mfs;
- if (not $h->{bitrate}) {
- $@ = "Couldn't determine VBR bitrate";
- return undef;
- }
- }
-
- $h->{'length'} = ($i->{SIZE} * 8) / $h->{bitrate} / 10;
- $i->{SECS} = $h->{'length'} / 100;
- $i->{MM} = int $i->{SECS} / 60;
- $i->{SS} = int $i->{SECS} % 60;
- $i->{MS} = (($i->{SECS} - ($i->{MM} * 60) - $i->{SS}) * 1000);
-# $i->{LF} = ($i->{MS} / 1000) * ($i->{FRAMES} / $i->{SECS});
-# int($i->{MS} / 100 * 75); # is this right?
- $i->{TIME} = sprintf "%.2d:%.2d", @{$i}{'MM', 'SS'};
-
- $i->{BITRATE} = int $h->{bitrate};
- # should we just return if ! FRAMES?
- $i->{FRAME_LENGTH} = int($h->{size} / $i->{FRAMES}) if $i->{FRAMES};
- $i->{FREQUENCY} = $frequency_tbl[3 * $h->{IDR} + $h->{sampling_freq}];
-
- return $i;
-}
-
-sub _get_head {
- my($byte) = @_;
- my($bytes, $h);
-
- $bytes = _unpack_head($byte);
- @$h{qw(IDR ID layer protection_bit
- bitrate_index sampling_freq padding_bit private_bit
- mode mode_extension copyright original
- emphasis version_index bytes)} = (
- ($bytes>>19)&3, ($bytes>>19)&1, ($bytes>>17)&3, ($bytes>>16)&1,
- ($bytes>>12)&15, ($bytes>>10)&3, ($bytes>>9)&1, ($bytes>>8)&1,
- ($bytes>>6)&3, ($bytes>>4)&3, ($bytes>>3)&1, ($bytes>>2)&1,
- $bytes&3, ($bytes>>19)&3, $bytes
- );
-
- $h->{bitrate} = $t_bitrate[$h->{ID}][3 - $h->{layer}][$h->{bitrate_index}];
- $h->{fs} = $t_sampling_freq[$h->{IDR}][$h->{sampling_freq}];
-
- return $h;
-}
-
-sub _is_mp3 {
- my $h = $_[0] or return undef;
- return ! ( # all below must be false
- $h->{bitrate_index} == 0
- ||
- $h->{version_index} == 1
- ||
- ($h->{bytes} & 0xFFE00000) != 0xFFE00000
- ||
- !$h->{fs}
- ||
- !$h->{bitrate}
- ||
- $h->{bitrate_index} == 15
- ||
- !$h->{layer}
- ||
- $h->{sampling_freq} == 3
- ||
- $h->{emphasis} == 2
- ||
- !$h->{bitrate_index}
- ||
- ($h->{bytes} & 0xFFFF0000) == 0xFFFE0000
- ||
- ($h->{ID} == 1 && $h->{layer} == 3 && $h->{protection_bit} == 1)
- ||
- ($h->{mode_extension} != 0 && $h->{mode} != 1)
- );
-}
-
-sub _get_vbr {
- my($fh, $h, $roff) = @_;
- my($off, $bytes, @bytes, $myseek, %vbr);
-
- $off = $$roff;
- @_ = (); # closure confused if we don't do this
-
- $myseek = sub {
- my $n = $_[0] || 4;
- seek $fh, $off, 0;
- read $fh, $bytes, $n;
- $off += $n;
- };
-
- $off += 4;
-
- if ($h->{ID}) { # MPEG1
- $off += $h->{mode} == 3 ? 17 : 32;
- } else { # MPEG2
- $off += $h->{mode} == 3 ? 9 : 17;
- }
-
- &$myseek;
- return unless $bytes eq 'Xing';
-
- &$myseek;
- $vbr{flags} = _unpack_head($bytes);
-
- if ($vbr{flags} & 1) {
- &$myseek;
- $vbr{frames} = _unpack_head($bytes);
- }
-
- if ($vbr{flags} & 2) {
- &$myseek;
- $vbr{bytes} = _unpack_head($bytes);
- }
-
- if ($vbr{flags} & 4) {
- $myseek->(100);
-# Not used right now ...
-# $vbr{toc} = _unpack_head($bytes);
- }
-
- if ($vbr{flags} & 8) { # (quality ind., 0=best 100=worst)
- &$myseek;
- $vbr{scale} = _unpack_head($bytes);
- } else {
- $vbr{scale} = -1;
- }
-
- $$roff = $off;
- return \%vbr;
-}
-
-sub _get_v2head {
- my $fh = $_[0] or return;
- my($h, $bytes, @bytes);
-
- # check first three bytes for 'ID3'
- seek $fh, 0, 0;
- read $fh, $bytes, 3;
- return unless $bytes eq 'ID3';
-
- # get version
- read $fh, $bytes, 2;
- $h->{version} = sprintf "ID3v2.%d.%d",
- @$h{qw[major_version minor_version]} =
- unpack 'c2', $bytes;
-
- # get flags
- read $fh, $bytes, 1;
- if ($h->{major_version} == 2) {
- @$h{qw[unsync compression]} =
- (unpack 'b8', $bytes)[7, 6];
- $h->{ext_header} = 0;
- $h->{experimental} = 0;
- } else {
- @$h{qw[unsync ext_header experimental]} =
- (unpack 'b8', $bytes)[7, 6, 5];
- }
-
- # get ID3v2 tag length from bytes 7-10
- $h->{tag_size} = 10; # include ID3v2 header size
- read $fh, $bytes, 4;
- @bytes = reverse unpack 'C4', $bytes;
- foreach my $i (0 .. 3) {
- # whoaaaaaa nellllllyyyyyy!
- $h->{tag_size} += $bytes[$i] * 128 ** $i;
- }
-
- # get extended header size
- $h->{ext_header_size} = 0;
- if ($h->{ext_header}) {
- $h->{ext_header_size} += 10;
- read $fh, $bytes, 4;
- @bytes = reverse unpack 'C4', $bytes;
- for my $i (0..3) {
- $h->{ext_header_size} += $bytes[$i] * 256 ** $i;
- }
- }
-
- return $h;
-}
-
-sub _unpack_head {
- unpack('l', pack('L', unpack('N', $_[0])));
-}
-
-sub _close {
- my($file, $fh) = @_;
- unless (ref $file) { # filehandle not passed
- close $fh or carp "Problem closing '$file': $!";
- }
-}
-
-BEGIN {
- @mp3_genres = (
- 'Blues',
- 'Classic Rock',
- 'Country',
- 'Dance',
- 'Disco',
- 'Funk',
- 'Grunge',
- 'Hip-Hop',
- 'Jazz',
- 'Metal',
- 'New Age',
- 'Oldies',
- 'Other',
- 'Pop',
- 'R&B',
- 'Rap',
- 'Reggae',
- 'Rock',
- 'Techno',
- 'Industrial',
- 'Alternative',
- 'Ska',
- 'Death Metal',
- 'Pranks',
- 'Soundtrack',
- 'Euro-Techno',
- 'Ambient',
- 'Trip-Hop',
- 'Vocal',
- 'Jazz+Funk',
- 'Fusion',
- 'Trance',
- 'Classical',
- 'Instrumental',
- 'Acid',
- 'House',
- 'Game',
- 'Sound Clip',
- 'Gospel',
- 'Noise',
- 'AlternRock',
- 'Bass',
- 'Soul',
- 'Punk',
- 'Space',
- 'Meditative',
- 'Instrumental Pop',
- 'Instrumental Rock',
- 'Ethnic',
- 'Gothic',
- 'Darkwave',
- 'Techno-Industrial',
- 'Electronic',
- 'Pop-Folk',
- 'Eurodance',
- 'Dream',
- 'Southern Rock',
- 'Comedy',
- 'Cult',
- 'Gangsta',
- 'Top 40',
- 'Christian Rap',
- 'Pop/Funk',
- 'Jungle',
- 'Native American',
- 'Cabaret',
- 'New Wave',
- 'Psychadelic',
- 'Rave',
- 'Showtunes',
- 'Trailer',
- 'Lo-Fi',
- 'Tribal',
- 'Acid Punk',
- 'Acid Jazz',
- 'Polka',
- 'Retro',
- 'Musical',
- 'Rock & Roll',
- 'Hard Rock',
- );
-
- @winamp_genres = (
- @mp3_genres,
- 'Folk',
- 'Folk-Rock',
- 'National Folk',
- 'Swing',
- 'Fast Fusion',
- 'Bebob',
- 'Latin',
- 'Revival',
- 'Celtic',
- 'Bluegrass',
- 'Avantgarde',
- 'Gothic Rock',
- 'Progressive Rock',
- 'Psychedelic Rock',
- 'Symphonic Rock',
- 'Slow Rock',
- 'Big Band',
- 'Chorus',
- 'Easy Listening',
- 'Acoustic',
- 'Humour',
- 'Speech',
- 'Chanson',
- 'Opera',
- 'Chamber Music',
- 'Sonata',
- 'Symphony',
- 'Booty Bass',
- 'Primus',
- 'Porn Groove',
- 'Satire',
- 'Slow Jam',
- 'Club',
- 'Tango',
- 'Samba',
- 'Folklore',
- 'Ballad',
- 'Power Ballad',
- 'Rhythmic Soul',
- 'Freestyle',
- 'Duet',
- 'Punk Rock',
- 'Drum Solo',
- 'Acapella',
- 'Euro-House',
- 'Dance Hall',
- 'Goa',
- 'Drum & Bass',
- 'Club-House',
- 'Hardcore',
- 'Terror',
- 'Indie',
- 'BritPop',
- 'Negerpunk',
- 'Polsk Punk',
- 'Beat',
- 'Christian Gangsta Rap',
- 'Heavy Metal',
- 'Black Metal',
- 'Crossover',
- 'Contemporary Christian',
- 'Christian Rock',
- 'Merengue',
- 'Salsa',
- 'Thrash Metal',
- 'Anime',
- 'JPop',
- 'Synthpop',
- );
-
- @t_bitrate = ([
- [0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256],
- [0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160],
- [0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160]
- ],[
- [0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448],
- [0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384],
- [0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320]
- ]);
-
- @t_sampling_freq = (
- [11025, 12000, 8000],
- [undef, undef, undef], # reserved
- [22050, 24000, 16000],
- [44100, 48000, 32000]
- );
-
- @frequency_tbl = map { $_ ? eval "${_}e-3" : 0 }
- map { @$_ } @t_sampling_freq;
-
- @mp3_info_fields = qw(
- VERSION
- LAYER
- STEREO
- VBR
- BITRATE
- FREQUENCY
- SIZE
- SECS
- MM
- SS
- MS
- TIME
- COPYRIGHT
- PADDING
- MODE
- FRAMES
- FRAME_LENGTH
- VBR_SCALE
- );
-
- %v1_tag_fields =
- (TITLE => 30, ARTIST => 30, ALBUM => 30, COMMENT => 30, YEAR => 4);
-
- @v1_tag_names = qw(TITLE ARTIST ALBUM YEAR COMMENT TRACKNUM GENRE);
-
- %v2_to_v1_names = (
- # v2.2 tags
- 'TT2' => 'TITLE',
- 'TP1' => 'ARTIST',
- 'TAL' => 'ALBUM',
- 'TYE' => 'YEAR',
- 'COM' => 'COMMENT',
- 'TRK' => 'TRACKNUM',
- 'TCO' => 'GENRE', # not clean mapping, but ...
- # v2.3 tags
- 'TIT2' => 'TITLE',
- 'TPE1' => 'ARTIST',
- 'TALB' => 'ALBUM',
- 'TYER' => 'YEAR',
- 'COMM' => 'COMMENT',
- 'TRCK' => 'TRACKNUM',
- 'TCON' => 'GENRE',
- );
-
- %v2_tag_names = (
- # v2.2 tags
- 'BUF' => 'Recommended buffer size',
- 'CNT' => 'Play counter',
- 'COM' => 'Comments',
- 'CRA' => 'Audio encryption',
- 'CRM' => 'Encrypted meta frame',
- 'ETC' => 'Event timing codes',
- 'EQU' => 'Equalization',
- 'GEO' => 'General encapsulated object',
- 'IPL' => 'Involved people list',
- 'LNK' => 'Linked information',
- 'MCI' => 'Music CD Identifier',
- 'MLL' => 'MPEG location lookup table',
- 'PIC' => 'Attached picture',
- 'POP' => 'Popularimeter',
- 'REV' => 'Reverb',
- 'RVA' => 'Relative volume adjustment',
- 'SLT' => 'Synchronized lyric/text',
- 'STC' => 'Synced tempo codes',
- 'TAL' => 'Album/Movie/Show title',
- 'TBP' => 'BPM (Beats Per Minute)',
- 'TCM' => 'Composer',
- 'TCO' => 'Content type',
- 'TCR' => 'Copyright message',
- 'TDA' => 'Date',
- 'TDY' => 'Playlist delay',
- 'TEN' => 'Encoded by',
- 'TFT' => 'File type',
- 'TIM' => 'Time',
- 'TKE' => 'Initial key',
- 'TLA' => 'Language(s)',
- 'TLE' => 'Length',
- 'TMT' => 'Media type',
- 'TOA' => 'Original artist(s)/performer(s)',
- 'TOF' => 'Original filename',
- 'TOL' => 'Original Lyricist(s)/text writer(s)',
- 'TOR' => 'Original release year',
- 'TOT' => 'Original album/Movie/Show title',
- 'TP1' => 'Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group',
- 'TP2' => 'Band/Orchestra/Accompaniment',
- 'TP3' => 'Conductor/Performer refinement',
- 'TP4' => 'Interpreted, remixed, or otherwise modified by',
- 'TPA' => 'Part of a set',
- 'TPB' => 'Publisher',
- 'TRC' => 'ISRC (International Standard Recording Code)',
- 'TRD' => 'Recording dates',
- 'TRK' => 'Track number/Position in set',
- 'TSI' => 'Size',
- 'TSS' => 'Software/hardware and settings used for encoding',
- 'TT1' => 'Content group description',
- 'TT2' => 'Title/Songname/Content description',
- 'TT3' => 'Subtitle/Description refinement',
- 'TXT' => 'Lyricist/text writer',
- 'TXX' => 'User defined text information frame',
- 'TYE' => 'Year',
- 'UFI' => 'Unique file identifier',
- 'ULT' => 'Unsychronized lyric/text transcription',
- 'WAF' => 'Official audio file webpage',
- 'WAR' => 'Official artist/performer webpage',
- 'WAS' => 'Official audio source webpage',
- 'WCM' => 'Commercial information',
- 'WCP' => 'Copyright/Legal information',
- 'WPB' => 'Publishers official webpage',
- 'WXX' => 'User defined URL link frame',
-
- # v2.3 tags
- 'AENC' => 'Audio encryption',
- 'APIC' => 'Attached picture',
- 'COMM' => 'Comments',
- 'COMR' => 'Commercial frame',
- 'ENCR' => 'Encryption method registration',
- 'EQUA' => 'Equalization',
- 'ETCO' => 'Event timing codes',
- 'GEOB' => 'General encapsulated object',
- 'GRID' => 'Group identification registration',
- 'IPLS' => 'Involved people list',
- 'LINK' => 'Linked information',
- 'MCDI' => 'Music CD identifier',
- 'MLLT' => 'MPEG location lookup table',
- 'OWNE' => 'Ownership frame',
- 'PCNT' => 'Play counter',
- 'POPM' => 'Popularimeter',
- 'POSS' => 'Position synchronisation frame',
- 'PRIV' => 'Private frame',
- 'RBUF' => 'Recommended buffer size',
- 'RVAD' => 'Relative volume adjustment',
- 'RVRB' => 'Reverb',
- 'SYLT' => 'Synchronized lyric/text',
- 'SYTC' => 'Synchronized tempo codes',
- 'TALB' => 'Album/Movie/Show title',
- 'TBPM' => 'BPM (beats per minute)',
- 'TCOM' => 'Composer',
- 'TCON' => 'Content type',
- 'TCOP' => 'Copyright message',
- 'TDAT' => 'Date',
- 'TDLY' => 'Playlist delay',
- 'TENC' => 'Encoded by',
- 'TEXT' => 'Lyricist/Text writer',
- 'TFLT' => 'File type',
- 'TIME' => 'Time',
- 'TIT1' => 'Content group description',
- 'TIT2' => 'Title/songname/content description',
- 'TIT3' => 'Subtitle/Description refinement',
- 'TKEY' => 'Initial key',
- 'TLAN' => 'Language(s)',
- 'TLEN' => 'Length',
- 'TMED' => 'Media type',
- 'TOAL' => 'Original album/movie/show title',
- 'TOFN' => 'Original filename',
- 'TOLY' => 'Original lyricist(s)/text writer(s)',
- 'TOPE' => 'Original artist(s)/performer(s)',
- 'TORY' => 'Original release year',
- 'TOWN' => 'File owner/licensee',
- 'TPE1' => 'Lead performer(s)/Soloist(s)',
- 'TPE2' => 'Band/orchestra/accompaniment',
- 'TPE3' => 'Conductor/performer refinement',
- 'TPE4' => 'Interpreted, remixed, or otherwise modified by',
- 'TPOS' => 'Part of a set',
- 'TPUB' => 'Publisher',
- 'TRCK' => 'Track number/Position in set',
- 'TRDA' => 'Recording dates',
- 'TRSN' => 'Internet radio station name',
- 'TRSO' => 'Internet radio station owner',
- 'TSIZ' => 'Size',
- 'TSRC' => 'ISRC (international standard recording code)',
- 'TSSE' => 'Software/Hardware and settings used for encoding',
- 'TXXX' => 'User defined text information frame',
- 'TYER' => 'Year',
- 'UFID' => 'Unique file identifier',
- 'USER' => 'Terms of use',
- 'USLT' => 'Unsychronized lyric/text transcription',
- 'WCOM' => 'Commercial information',
- 'WCOP' => 'Copyright/Legal information',
- 'WOAF' => 'Official audio file webpage',
- 'WOAR' => 'Official artist/performer webpage',
- 'WOAS' => 'Official audio source webpage',
- 'WORS' => 'Official internet radio station homepage',
- 'WPAY' => 'Payment',
- 'WPUB' => 'Publishers official webpage',
- 'WXXX' => 'User defined URL link frame',
-
- # v2.4 additional tags
- # note that we don't restrict tags from 2.3 or 2.4,
- 'ASPI' => 'Audio seek point index',
- 'EQU2' => 'Equalisation (2)',
- 'RVA2' => 'Relative volume adjustment (2)',
- 'SEEK' => 'Seek frame',
- 'SIGN' => 'Signature frame',
- 'TDEN' => 'Encoding time',
- 'TDOR' => 'Original release time',
- 'TDRC' => 'Recording time',
- 'TDRL' => 'Release time',
- 'TDTG' => 'Tagging time',
- 'TIPL' => 'Involved people list',
- 'TMCL' => 'Musician credits list',
- 'TMOO' => 'Mood',
- 'TPRO' => 'Produced notice',
- 'TSOA' => 'Album sort order',
- 'TSOP' => 'Performer sort order',
- 'TSOT' => 'Title sort order',
- 'TSST' => 'Set subtitle',
-
- # grrrrrrr
- 'COM ' => 'Broken iTunes comments',
- );
-}
-
-1;
-
-__END__
-
-=pod
-
-=back
-
-=head1 TROUBLESHOOTING
-
-If you find a bug, please send me a patch (see the project page in L<"SEE ALSO">).
-If you cannot figure out why it does not work for you, please put the MP3 file in
-a place where I can get it (preferably via FTP, or HTTP, or .Mac iDisk) and send me
-mail regarding where I can get the file, with a detailed description of the problem.
-
-If I download the file, after debugging the problem I will not keep the MP3 file
-if it is not legal for me to have it. Just let me know if it is legal for me to
-keep it or not.
-
-
-=head1 TODO
-
-=over 4
-
-=item ID3v2 Support
-
-Still need to do more for reading tags, such as using Compress::Zlib to decompress
-compressed tags. But until I see this in use more, I won't bother. If something
-does not work properly with reading, follow the instructions above for
-troubleshooting.
-
-ID3v2 I<writing> is coming soon.
-
-=item Get data from scalar
-
-Instead of passing a file spec or filehandle, pass the
-data itself. Would take some work, converting the seeks, etc.
-
-=item Padding bit ?
-
-Do something with padding bit.
-
-=item Test suite
-
-Test suite could use a bit of an overhaul and update. Patches very welcome.
-
-=over 4
-
-=item *
-
-Revamp getset.t. Test all the various get_mp3tag args.
-
-=item *
-
-Test Unicode.
-
-=item *
-
-Test OOP API.
-
-=item *
-
-Test error handling, check more for missing files, bad MP3s, etc.
-
-=back
-
-=item Other VBR
-
-Right now, only Xing VBR is supported.
-
-=back
-
-
-=head1 THANKS
-
-Edward Allen E<lt>allenej@c51844-a.spokn1.wa.home.comE<gt>,
-Vittorio Bertola E<lt>v.bertola@vitaminic.comE<gt>,
-Michael Blakeley E<lt>mike@blakeley.comE<gt>,
-Per Bolmstedt E<lt>tomten@kol14.comE<gt>,
-Tony Bowden E<lt>tony@tmtm.comE<gt>,
-Tom Brown E<lt>thecap@usa.netE<gt>,
-Sergio Camarena E<lt>scamarena@users.sourceforge.netE<gt>,
-Chris Dawson E<lt>cdawson@webiphany.comE<gt>,
-Luke Drumm E<lt>lukedrumm@mypad.comE<gt>,
-Kyle Farrell E<lt>kyle@cantametrix.comE<gt>,
-Jeffrey Friedl E<lt>jfriedl@yahoo.comE<gt>,
-brian d foy E<lt>comdog@panix.comE<gt>,
-Ben Gertzfield E<lt>che@debian.orgE<gt>,
-Brian Goodwin E<lt>brian@fuddmain.comE<gt>,
-Todd Hanneken E<lt>thanneken@hds.harvard.eduE<gt>,
-Todd Harris E<lt>harris@cshl.orgE<gt>,
-Woodrow Hill E<lt>asim@mindspring.comE<gt>,
-Kee Hinckley E<lt>nazgul@somewhere.comE<gt>,
-Roman Hodek E<lt>Roman.Hodek@informatik.uni-erlangen.deE<gt>,
-Peter Kovacs E<lt>kovacsp@egr.uri.eduE<gt>,
-Johann Lindvall,
-Peter Marschall E<lt>peter.marschall@mayn.deE<gt>,
-Trond Michelsen E<lt>mike@crusaders.noE<gt>,
-Dave O'Neill E<lt>dave@nexus.carleton.caE<gt>,
-Christoph Oberauer E<lt>christoph.oberauer@sbg.ac.atE<gt>,
-Jake Palmer E<lt>jake.palmer@db.comE<gt>,
-Andrew Phillips E<lt>asp@wasteland.orgE<gt>,
-David Reuteler E<lt>reuteler@visi.comE<gt>,
-John Ruttenberg E<lt>rutt@chezrutt.comE<gt>,
-Matthew Sachs E<lt>matthewg@zevils.comE<gt>,
-E<lt>scfc_de@users.sf.netE<gt>,
-Hermann Schwaerzler E<lt>Hermann.Schwaerzler@uibk.ac.atE<gt>,
-Chris Sidi E<lt>sidi@angband.orgE<gt>,
-Roland Steinbach E<lt>roland@support-system.comE<gt>,
-Stuart E<lt>schneis@users.sourceforge.netE<gt>,
-Jeffery Sumler E<lt>jsumler@mediaone.netE<gt>,
-Predrag Supurovic E<lt>mpgtools@dv.co.yuE<gt>,
-Bogdan Surdu E<lt>tim@go.roE<gt>,
-E<lt>tim@tim-landscheidt.deE<gt>,
-Pass F. B. Travis E<lt>pftravis@bellsouth.netE<gt>,
-Tobias Wagener E<lt>tobias@wagener.nuE<gt>,
-Ronan Waide E<lt>waider@stepstone.ieE<gt>,
-Andy Waite E<lt>andy@mailroute.comE<gt>,
-Ken Williams E<lt>ken@forum.swarthmore.eduE<gt>,
-Meng Weng Wong E<lt>mengwong@pobox.comE<gt>.
-
-
-=head1 AUTHOR AND COPYRIGHT
-
-Chris Nandor E<lt>pudge@pobox.comE<gt>, http://pudge.net/
-
-Copyright (c) 1998-2003 Chris Nandor. All rights reserved. This program is
-free software; you can redistribute it and/or modify it under the terms
-of the Artistic License, distributed with Perl.
-
-
-=head1 SEE ALSO
-
-=over 4
-
-=item MP3::Info Project Page
-
- http://projects.pudge.net/
-
-=item mp3tools
-
- http://www.zevils.com/linux/mp3tools/
-
-=item mpgtools
-
- http://www.dv.co.yu/mpgscript/mpgtools.htm
- http://www.dv.co.yu/mpgscript/mpeghdr.htm
-
-=item mp3tool
-
- http://www.dtek.chalmers.se/~d2linjo/mp3/mp3tool.html
-
-=item ID3v2
-
- http://www.id3.org/
-
-=item Xing Variable Bitrate
-
- http://www.xingtech.com/support/partner_developer/mp3/vbr_sdk/
-
-=item MP3Ext
-
- http://rupert.informatik.uni-stuttgart.de/~mutschml/MP3ext/
-
-=item Xmms
-
- http://www.xmms.org/
-
-
-=back
-
-=head1 VERSION
-
-v1.02, Sunday, March 2, 2003
-
-=cut
diff --git a/lib/Mail/SendEasy.pm b/lib/Mail/SendEasy.pm
index c7d5064..5b7cc43 100644
--- a/lib/Mail/SendEasy.pm
+++ b/lib/Mail/SendEasy.pm
@@ -110,7 +110,7 @@ sub send {
{
my @from = &_check_emails( $mail{from} ) ; return( undef ) if $ER ;
if ($#from > 0) { $ER = "More than one From: " . join(" ; ", @from) ; return( undef ) ;}
- $mail{from} = @from[0] ;
+ $mail{from} = $from[0] ;
my @to = &_check_emails( $mail{to} ) ; return( undef ) if $ER ;
$mail{to} = \@to ;
@@ -122,12 +122,12 @@ sub send {
if ( defined $mail{reply} ) {
my @reply = &_check_emails( $mail{reply} ) ; return( undef ) if $ER ;
- $mail{reply} = @reply[0] ; delete $mail{reply} if $mail{reply} eq '' ;
+ $mail{reply} = $reply[0] ; delete $mail{reply} if $mail{reply} eq '' ;
}
if ( defined $mail{error} ) {
my @error = &_check_emails( $mail{error} ) ; return( undef ) if $ER ;
- $mail{error} = @error[0] ; delete $mail{error} if $mail{error} eq '' ;
+ $mail{error} = $error[0] ; delete $mail{error} if $mail{error} eq '' ;
}
}
diff --git a/lib/Net/Amazon.pm b/lib/Net/Amazon.pm
deleted file mode 100644
index 4630c11..0000000
--- a/lib/Net/Amazon.pm
+++ /dev/null
@@ -1,1255 +0,0 @@
-#####################################################################
-package Net::Amazon;
-######################################################################
-# Mike Schilli <m@perlmeister.com>, 2003
-######################################################################
-
-use 5.006;
-use strict;
-use warnings;
-
-our $VERSION = '0.34';
-our @CANNED_RESPONSES = ();
-
-use LWP::UserAgent;
-use HTTP::Request::Common;
-use XML::Simple;
-use Data::Dumper;
-use URI;
-use Log::Log4perl qw(:easy get_logger);
-use Time::HiRes qw(usleep gettimeofday tv_interval);
-
-# Each key represents a search() type, and each value indicates which
-# Net::Amazon::Request:: class to use to handle it.
-use constant SEARCH_TYPE_CLASS_MAP => {
- artist => 'Artist',
- asin => 'ASIN',
- blended => 'Blended',
- browsenode => 'BrowseNode',
- exchange => 'Exchange',
- keyword => 'Keyword',
- manufacturer => 'Manufacturer',
- power => 'Power',
- seller => 'Seller',
- similar => 'Similar',
- textstream => 'TextStream',
- upc => 'UPC',
- wishlist => 'Wishlist',
-};
-
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- if(! exists $options{token}) {
- die "Mandatory paramter 'token' not defined";
- }
-
- if(! exists $options{affiliate_id}) {
- $options{affiliate_id} = "webservices-20";
- }
-
- my $self = {
- strict => 1,
- response_dump => 0,
- rate_limit => 1.0, # 1 req/sec
- max_pages => 5,
- ua => LWP::UserAgent->new(),
- %options,
- };
-
- help_xml_simple_choose_a_parser();
-
- bless $self, $class;
-}
-
-##################################################
-sub search {
-##################################################
- my($self, %params) = @_;
-
- foreach my $key ( keys %params ) {
- next unless ( my $class = SEARCH_TYPE_CLASS_MAP->{$key} );
-
- return $self->_make_request($class, \%params);
- }
-
- # FIX?
- # This seems like it really should be a die() instead...this is
- # indicative of a programming problem. Generally speaking, it's
- # best to issue warnings from a module--you can't be sure that the
- # client has a stderr to begin with, or that he wants errors
- # spewed to it.
- warn "No Net::Amazon::Request type could be determined";
-
- return undef;
-}
-
-##################################################
-sub intl_url {
-##################################################
- my($self, $url) = @_;
-
- # Every time Amazon is adding a new country to the web service,
- # they're rolling a dice on what the new URL is going to be.
- # This method will try to keep up with their crazy mappings.
-
- if(! exists $self->{locale}) {
- return $url;
- }
-
- if ($self->{locale} eq "jp") {
- $url =~ s/\.com/.co.jp/;
- return $url;
- }
-
- if($self->{locale} eq "uk" or
- $self->{locale} eq "de") {
- $url =~ s/xml/xml-eu/;
- return $url;
- }
-
- return $url;
-}
-
-##################################################
-sub request {
-##################################################
- my($self, $request) = @_;
-
- my $AMZN_WISHLIST_BUG_ENCOUNTERED = 0;
-
- my $resp_class = $request->response_class();
-
- eval "require $resp_class;" or
- die "Cannot find '$resp_class'";
-
- my $res = $resp_class->new();
-
- my $url = URI->new($self->intl_url($request->amzn_xml_url()));
- my $page = $request->{page};
- my $ref;
-
- {
- my %params = $request->params();
- $params{page} = $page;
- $params{locale} = $self->{locale} if exists $self->{locale};
-
- $url->query_form(
- 'dev-t' => $self->{token},
- 't' => $self->{affiliate_id},
- map { $_, $params{$_} } sort keys %params,
- );
-
- my $urlstr = $url->as_string;
- my $xml = fetch_url($self, $urlstr, $res);
-
- if(!defined $xml) {
- return $res;
- }
-
- DEBUG(sub { "Received [ " . $xml . "]" });
-
- # Let the response class parse the XML
- $ref = $res->xml_parse($xml);
-
- # DEBUG(sub { Data::Dumper::Dumper($ref) });
-
- if(! defined $ref) {
- ERROR("Invalid XML");
- $res->messages( [ "Invalid XML" ]);
- $res->status("");
- return $res;
- }
-
- if(exists $ref->{TotalPages}) {
- INFO("Page $page/$ref->{TotalPages}");
- }
-
- if(exists $ref->{TotalResults}) {
- $res->total_results( $ref->{TotalResults} );
- }
-
- if(exists $ref->{ErrorMsg}) {
-
- if($AMZN_WISHLIST_BUG_ENCOUNTERED &&
- $ref->{ErrorMsg} =~ /no exact matches/) {
- DEBUG("End of buggy wishlist detected");
- last;
- }
-
- if (ref($ref->{ErrorMsg}) eq "ARRAY") {
- # multiple errors, set arrary ref
- $res->messages( $ref->{ErrorMsg} );
- } else {
- # single error, create array
- $res->messages( [ $ref->{ErrorMsg} ] );
- }
-
- ERROR("Fetch Error: " . $res->message );
- $res->status("");
- return $res;
- }
-
- my $new_items = $res->xmlref_add($ref);
- DEBUG("Received valid XML ($new_items items)");
-
- # Stop if we've fetched max_pages already
- if($self->{max_pages} <= $page) {
- DEBUG("Fetched max_pages ($self->{max_pages}) -- stopping");
- last;
- }
-
- # Work around the Amazon bug not setting TotalPages properly
- # for wishlists
- if(ref($res) =~ /Wishlist/ and
- !exists $ref->{TotalPages} and
- $new_items == 10
- ) {
- $AMZN_WISHLIST_BUG_ENCOUNTERED = 1;
- DEBUG("Trying to fetch additional wishlist page (AMZN bug)");
- $page++;
- redo;
- }
-
- if(exists $ref->{TotalPages} and
- $ref->{TotalPages} > $page) {
- DEBUG("Page $page of $ref->{TotalPages} fetched - continuing");
- $page++;
- redo;
- }
-
- # We're gonna fall out of this loop here.
- }
-
- $res->status(1);
- # We have a valid response, so if TotalResults isn't set,
- # we most likely have a single response
- $res->total_results(1) unless defined $res->total_results();
- return $res;
-}
-
-##################################################
-sub fetch_url {
-##################################################
- my($self, $url, $res) = @_;
-
- my $max_retries = 2;
-
- INFO("Fetching $url");
-
- if(@CANNED_RESPONSES) {
- INFO("Serving canned response (testing)");
- return shift @CANNED_RESPONSES;
- }
-
- if(exists $self->{cache}) {
- my $resp = $self->{cache}->get($url);
- if(defined $resp) {
- INFO("Serving from cache");
- return $resp;
- }
-
- INFO("Cache miss");
- }
-
- my $ua = $self->{ua};
- $ua->env_proxy();
-
- my $resp;
-
- {
- # wait up to a second before the next request so
- # as to not violate Amazon's 1 query per second
- # rule (or the configured rate_limit).
- $self->pause() if $self->{strict};
-
- $resp = $ua->request(GET $url);
-
- $self->reset_timer() if $self->{strict};
-
- if($resp->is_error) {
- # retry on 503 Service Unavailable errors
- if ($resp->code == 503) {
- if ($max_retries-- >= 0) {
- INFO("Temporary Amazon error 503, retrying");
- redo;
- } else {
- INFO("Out of retries, giving up");
- $res->status("");
- $res->messages( [ "Too many temporary Amazon errors" ] );
- return undef;
- }
- } else {
- $res->status("");
- $res->messages( [ $resp->message ] );
- return undef;
- }
- }
-
- if($self->{response_dump}) {
- my $dumpfile = "response-$self->{response_dump}.txt";
- open FILE, ">$dumpfile" or die "Cannot open $dumpfile";
- print FILE $resp->content();
- close FILE;
- $self->{response_dump}++;
- }
-
- if($resp->content =~ /<ErrorMsg>/ &&
- $resp->content =~ /Please retry/i) {
- if($max_retries-- >= 0) {
- INFO("Temporary Amazon error, retrying");
- redo;
- } else {
- INFO("Out of retries, giving up");
- $res->status("");
- $res->messages( [ "Too many temporary Amazon errors" ] );
- return undef;
- }
- }
- }
-
- if(exists $self->{cache}) {
- $self->{cache}->set($url, $resp->content());
- }
-
- return $resp->content();
-}
-
-##################################################
-# Poor man's Class::Struct
-##################################################
-sub make_accessor {
-##################################################
- my($package, $name) = @_;
-
- no strict qw(refs);
-
- my $code = <<EOT;
- *{"$package\\::$name"} = sub {
- my(\$self, \$value) = \@_;
-
- if(defined \$value) {
- \$self->{$name} = \$value;
- }
- if(exists \$self->{$name}) {
- return (\$self->{$name});
- } else {
- return "";
- }
- }
-EOT
- if(! defined *{"$package\::$name"}) {
- eval $code or die "$@";
- }
-}
-
-##################################################
-# Make accessors for arrays
-##################################################
-sub make_array_accessor {
-##################################################
- my($package, $name) = @_;
-
- no strict qw(refs);
-
- my $code = <<EOT;
- *{"$package\\::$name"} = sub {
- my(\$self, \$nameref) = \@_;
- if(defined \$nameref) {
- if(ref \$nameref eq "ARRAY") {
- \$self->{$name} = \$nameref;
- } else {
- \$self->{$name} = [\$nameref];
- }
- }
- # Return a list
- if(exists \$self->{$name} and
- ref \$self->{$name} eq "ARRAY") {
- return \@{\$self->{$name}};
- }
-
- return undef;
- }
-EOT
-
- if(! defined *{"$package\::$name"}) {
- eval $code or die "$@";
- }
-}
-
-##################################################
-sub artist {
-##################################################
- my($self, $nameref) = @_;
-
- # Only return the first artist
- return ($self->artists($nameref))[0];
-}
-
-
-##################################################
-sub xmlref_add {
-##################################################
- my($self, $xmlref) = @_;
-
- my $nof_items_added = 0;
-
- # Push a nested hash structure, retrieved via XMLSimple, onto the
- # object's internal 'xmlref' entry, which holds a ref to an array,
- # whichs elements are refs to hashes holding an item's attributes
- # (like OurPrice etc.)
-
- #DEBUG("xmlref_add ", Data::Dumper::Dumper($xmlref));
-
- unless(ref($self->{xmlref}) eq "HASH" &&
- ref($self->{xmlref}->{Details}) eq "ARRAY") {
- $self->{xmlref}->{Details} = [];
- }
-
- if(ref($xmlref->{Details}) eq "ARRAY") {
- # Is it an array of items?
- push @{$self->{xmlref}->{Details}}, @{$xmlref->{Details}};
- $nof_items_added = scalar @{$xmlref->{Details}};
- } else {
- # It is a single item
- push @{$self->{xmlref}->{Details}}, $xmlref->{Details};
- $nof_items_added = 1;
- }
-
- #DEBUG("xmlref_add (after):", Data::Dumper::Dumper($self));
- return $nof_items_added;
-}
-
-##################################################
-sub help_xml_simple_choose_a_parser {
-##################################################
-
- eval "require XML::Parser";
- unless($@) {
- $XML::Simple::PREFERRED_PARSER = "XML::Parser";
- return;
- }
-
- eval "require XML::SAX::PurePerl";
- unless($@) {
- $XML::Simple::PREFERRED_PARSER = "XML::SAX::PurePerl";
- return;
- }
-}
-
-##################################################
-# This timer makes sure we don't query Amazon more
-# than once a second.
-##################################################
-sub reset_timer {
-##################################################
-
- my $self = shift;
- $self->{t0} = [gettimeofday];
-}
-
-##################################################
-# Pause for up to a second if necessary.
-##################################################
-sub pause {
-##################################################
-
- my $self = shift;
- return unless ($self->{t0});
-
- my $t1 = [gettimeofday];
- my $dur = (1.0/$self->{rate_limit} -
- tv_interval($self->{t0}, $t1)) * 1000000;
- if($dur > 0) {
- # Use a pseudo subclass for the logger, since the app
- # might not want to log that as 'ERROR'. Log4perl's
- # inheritance mechanism makes sure it does the right
- # thing for the current class.
- my $logger = get_logger(__PACKAGE__ . "::RateLimit");
- $logger->error("Ratelimiting: Sleeping $dur microseconds");
- usleep($dur);
- }
-}
-
-##
-## 'PRIVATE' METHODS
-##
-
-# $self->_make_request( TYPE, PARAMS )
-#
-# Takes a TYPE that corresponds to a Net::Amazon::Request
-# class, require()s that class, instantiates it, and returns
-# the result of that instance's request() method.
-#
-sub _make_request {
- my ($self, $type, $params) = @_;
-
- my $class = "Net::Amazon::Request::$type";
-
- eval "require $class";
-
- my $req = $class->new(%{$params});
-
- return $self->request($req);
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon - Framework for accessing amazon.com via SOAP and XML/HTTP
-
-=head1 SYNOPSIS
-
- use Net::Amazon;
-
- my $ua = Net::Amazon->new(token => 'YOUR_AMZN_TOKEN');
-
- # Get a request object
- my $response = $ua->search(asin => '0201360683');
-
- if($response->is_success()) {
- print $response->as_string(), "\n";
- } else {
- print "Error: ", $response->message(), "\n";
- }
-
-=head1 ABSTRACT
-
- Net::Amazon provides an object-oriented interface to amazon.com's
- SOAP and XML/HTTP interfaces. This way it's possible to create applications
- using Amazon's vast amount of data via a functional interface, without
- having to worry about the underlying communication mechanism.
-
-=head1 DESCRIPTION
-
-C<Net::Amazon> works very much like C<LWP>: First you define a useragent
-like
-
- my $ua = Net::Amazon->new(
- token => 'YOUR_AMZN_TOKEN',
- max_pages => 3,
- );
-
-which you pass your personal amazon developer's token (can be obtained
-from L<http://amazon.com/soap>) and (optionally) the maximum number of
-result pages the agent is going to request from Amazon in case all
-results don't fit on a single page (typically holding 20 items). Note that
-each new page requires a minimum delay of 1 second to comply with Amazon's
-one-query-per-second policy.
-
-According to the different search methods on Amazon, there's a bunch
-of different request types in C<Net::Amazon>. The user agent's
-convenience method C<search()> triggers different request objects,
-depending on which parameters you pass to it:
-
-=over 4
-
-=item C<< $ua->search(asin => "0201360683") >>
-
-The C<asin> parameter has Net::Amazon search for an item with the
-specified ASIN. If the specified value is an arrayref instead of a single
-scalar, like in
-
- $ua->search(asin => ["0201360683", "0596005083"])
-
-then a search for multiple ASINs is performed, returning a list of
-results.
-
-=item C<< $ua->search(artist => "Rolling Stones") >>
-
-The C<artist> parameter has the user agent search for items created by
-the specified artist. Can return many results.
-
-=item C<< $ua->search(browsenode=>"4025", mode=>"books" [, keywords=>"perl"]) >>
-
-Returns a list of items by category ID (node). For example node "4025"
-is the CGI books category. You can add a keywords parameter to filter
-the results by that keyword.
-
-=item C<< $ua->search(exchange => 'Y04Y3424291Y2398445') >>
-
-Returns an item offered by a third-party seller. The item is referenced
-by the so-called I<exchange ID>.
-
-=item C<< $ua->search(keyword => "perl xml", mode => "books") >>
-
-Search by keyword, mandatory parameters C<keyword> and C<mode>.
-Can return many results.
-
-=item C<< $ua->search(wishlist => "1XL5DWOUFMFVJ") >>
-
-Search for all items in a specified wishlist.
-Can return many results.
-
-=item C<< $ua->search(upc => "075596278324", mode => "music") >>
-
-Music search by UPC (product barcode), mandatory parameter C<upc>.
-C<mode> has to be set to C<music>. Returns at most one result.
-
-=item C<< $ua->search(similar => "0201360683") >>
-
-Search for all items similar to the one represented by the ASIN provided.
-Can return many results.
-
-=item C<< $ua->search(power => "subject: perl and author: schwartz", mode => "books") >>
-
-Initiate a power search for all books matching the power query.
-Can return many results. See L<Net::Amazon::Request::Power> for details.
-
-=item C<< $ua->search(manufacturer => "o'reilly", mode => "books") >>
-
-Initiate a search for all items made by a given manufacturrer.
-Can return many results. See L<Net::Amazon::Request::Manufacturer>
-for details.
-
-=item C<< $ua->search(blended => "Perl") >>
-
-Initiate a search for items in all categories.
-
-=item C<< $ua->search(seller => "A2GXAGU54VOP7") >>
-
-Start a search on items sold by a specific third-party seller, referenced
-by its ID (not seller name).
-
-=item C<< $ua->search(textstream => "Blah blah Rolling Stones blah blah") >>
-
-Find items related to keywords within a text stream.
-
-=back
-
-The user agent's C<search> method returns a response object, which can be
-checked for success or failure:
-
- if($resp->is_success()) {
- print $resp->as_string();
- } else {
- print "Error: ", $resp->message(), "\n";
- }
-
-In case the request for an item search
-succeeds, the response contains one or more
-Amazon 'properties', as it calls the products found.
-All matches can be retrieved from the Response
-object using it's C<properties()> method.
-
-In case the request fails, the response contains one or more
-error messages. The response object's C<message()> method will
-return it (or them) as a single string, while C<messages()> (notice
-the plural) will
-return a reference to an array of message strings.
-
-Response objects always have the methods
-C<is_success()>,
-C<is_error()>,
-C<message()>,
-C<total_results()>,
-C<as_string()> and
-C<properties()> available.
-
-C<total_results()> returns the total number of results the search
-yielded.
-C<properties()> returns one or more C<Net::Amazon::Property> objects of type
-C<Net::Amazon::Property> (or one of its subclasses like
-C<Net::Amazon::Property::Book>, C<Net::Amazon::Property::Music>
-or Net::Amazon::Property::DVD), each
-of which features accessors named after the attributes of the product found
-in Amazon's database:
-
- for ($resp->properties) {
- print $_->Asin(), " ",
- $_->OurPrice(), "\n";
- }
-
-In scalar context, C<properties()> just returns the I<first>
-C<Net::Amazon::Property> object found.
-Commonly available accessors to C<Net::Amazon::Property> objects are
-C<OurPrice()>,
-C<ImageUrlLarge()>,
-C<ImageUrlMedium()>,
-C<ImageUrlSmall()>,
-C<ReleaseDate()>,
-C<Catalog()>,
-C<Asin()>,
-C<url()>,
-C<Manufacturer()>,
-C<UsedPrice()>,
-C<ListPrice()>,
-C<ProductName()>,
-C<Availability()>,
-C<SalesRank()>,
-C<CollectiblePrice()>,
-C<CollectibleCount()>,
-C<NumberOfOfferings()>,
-C<UsedCount()>,
-C<ThirdPartyNewPrice()>,
-C<ThirdPartyNewCount()>,
-C<similar_asins()>.
-For details, check L<Net::Amazon::Property>.
-
-Also, the specialized classes C<Net::Amazon::Property::Book> and
-C<Net::Amazon::Property::Music> feature convenience methods like
-C<authors()> (returning the list of authors of a book) or
-C<album()> for CDs, returning the album title.
-
-Customer reviews:
-Every property features a C<review_set()> method which returns a
-C<Net::Amazon::Attribute::ReviewSet> object, which in turn offers
-a list of C<Net::Amazon::Attribute::Review> objects. Check the respective
-man pages for details on what's available.
-
-=head2 Requests behind the scenes
-
-C<Net::Amazon>'s C<search()> method is just a convenient way to
-create different kinds of request objects behind the scenes and
-trigger them to send requests to Amazon.
-
-Depending on the parameters fed to the C<search> method, C<Net::Amazon> will
-determine the kind of search requested and create one of the following
-request objects:
-
-=over 4
-
-=item Net::Amazon::Request::ASIN
-
-Search by ASIN, mandatory parameter C<asin>.
-Returns at most one result.
-
-=item Net::Amazon::Request::Artist
-
-Music search by Artist, mandatory parameter C<artist>.
-Can return many results.
-
-=item Net::Amazon::Request::BrowseNode
-
-Returns category (node) listing. Mandatory parameters C<browsenode>
-(must be numeric) and C<mode>. Can return many results.
-
-=item Net::Amazon::Request::Keyword
-
-Keyword search, mandatory parameters C<keyword> and C<mode>.
-Can return many results.
-
-=item Net::Amazon::Request::UPC
-
-Music search by UPC (product barcode), mandatory parameter C<upc>.
-C<mode> has to be set to C<music>. Returns at most one result.
-
-=item Net::Amazon::Request::Blended
-
-'Blended' search on a keyword, resulting in matches across the board.
-No 'mode' parameter is allowed. According to Amazon's developer's kit,
-this will result in up to three matches per category and can yield
-a total of 45 matches.
-
-=item Net::Amazon::Request::Power
-
-Understands power search strings. See L<Net::Amazon::Request::Power>
-for details. Mandatory parameter C<power>.
-
-=item Net::Amazon::Request::Manufacturer
-
-Searches for all items made by a given manufacturer. Mandatory parameter
-C<manufacturer>.
-
-=item Net::Amazon::Request::Similar
-
-Finds items similar to a given one.
-
-=item Net::Amazon::Request::Wishlist
-
-Find item on someone's wish list.
-
-=item Net::Amazon::Request::Seller
-
-Searches for a third-party seller on Amazon by seller ID. This search
-is different than the previous ones, since it doesn't return Amazon
-items, but a single seller record. Don't use the C<properties()> method
-on the response, use C<result()> instead, which returns a
-L<Net::Amazon::Result::Seller> object. Check the manpage for details.
-
-=item Net::Amazon::Request::Exchange
-
-Searches for items offered by third-party sellers. Items are referenced
-by their so-called I<Exchange ID>.
-Similar to L<Net::Amazon::Request::Seller>,
-this request doesn't return a list of Amazon properties, so please use
-C<result()> instead, which will return a I<single>
-L<Net::Amazon::Result::Seller::Listing> item.
-Check the manpage for details on what attributes are available there.
-
-=back
-
-Check the respective man pages for details on these request objects.
-Request objects are typically created like this (with a Keyword query
-as an example):
-
- my $req = Net::Amazon::Request::Keyword->new(
- keyword => 'perl',
- mode => 'books',
- );
-
-and are handed over to the user agent like that:
-
- # Response is of type Net::Amazon::Response::ASIN
- my $resp = $ua->request($req);
-
-The convenient C<search()> method just does these two steps in one.
-
-=head2 METHODS
-
-=over 4
-
-=item $ua = Net::Amazon->new(token => $token, ...)
-
-Create a new Net::Amazon useragent. C<$token> is the value of
-the mandatory Amazon developer's token, which can be obtained from
-L<http://amazon.com/soap>.
-
-Additional optional parameters:
-
-=over 4
-
-=item C<< max_pages => $max_pages >>
-
-Sets how many
-result pages the module is supposed to fetch back from Amazon, which
-only sends back 10 results per page.
-Since each page requires a new query to Amazon, at most one query
-per second will be made in C<strict> mode to comply with Amazon's terms
-of service. This will impact performance if you perform a search
-returning many pages of results.
-
-=item C<< affiliate_id => $affiliate_id >>
-
-your Amazon affiliate ID, if you have one. It defaults to
-C<webservices-20> which is currently (as of 06/2003)
-required by Amazon.
-
-=item C<< strict => 1 >>
-
-Makes sure that C<Net::Amazon> complies with Amazon's terms of service
-by limiting the number of outgoing requests to 1 per second. Defaults
-to C<1>, enabling rate limiting as defined via C<rate_limit>.
-
-=item C<< rate_limit => $reqs_per_sec >>
-
-Sets the rate limit to C<$reqs_per_sec> requests per second if
-rate limiting has been enabled with C<strict> (see above).
-Defaults to C<1>, limiting the number of outgoing requests to
-1 per second.
-
-=item C<< $resp = $ua->request($request) >>
-
-Sends a request to the Amazon web service. C<$request> is of a
-C<Net::Amazon::Request::*> type and C<$response> will be of the
-corresponding C<Net::Amazon::Response::*> type.
-
-=back
-
-=head2 Accessing foreign Amazon Catalogs
-
-As of this writing (07/2003), Amazon also offers its web service for
-the UK, Germany, and Japan. Just pass in
-
- locale => 'uk'
- locale => 'de'
- locale => 'jp'
-
-respectively to C<Net::Amazon>'s constructor C<new()> and instead of returning
-results sent by the US mothership, it will query the particular country's
-catalog and show prices in (gack!) local currencies.
-
-=head2 EXAMPLE
-
-Here's a full-fledged example doing a artist search:
-
- use Net::Amazon;
- use Net::Amazon::Request::Artist;
- use Data::Dumper;
-
- die "usage: $0 artist\n(use Zwan as an example)\n"
- unless defined $ARGV[0];
-
- my $ua = Net::Amazon->new(
- token => 'YOUR_AMZN_TOKEN',
- );
-
- my $req = Net::Amazon::Request::Artist->new(
- artist => $ARGV[0],
- );
-
- # Response is of type Net::Amazon::Artist::Response
- my $resp = $ua->request($req);
-
- if($resp->is_success()) {
- print $resp->as_string, "\n";
- } else {
- print $resp->message(), "\n";
- }
-
-And here's one displaying someone's wishlist:
-
- use Net::Amazon;
- use Net::Amazon::Request::Wishlist;
-
- die "usage: $0 wishlist_id\n" .
- "(use 1XL5DWOUFMFVJ as an example)\n" unless $ARGV[0];
-
- my $ua = Net::Amazon->new(
- token => 'YOUR_AMZN_TOKEN',
- );
-
- my $req = Net::Amazon::Request::Wishlist->new(
- id => $ARGV[0]
- );
-
- # Response is of type Net::Amazon::ASIN::Response
- my $resp = $ua->request($req);
-
- if($resp->is_success()) {
- print $resp->as_string, "\n";
- } else {
- print $resp->message(), "\n";
- }
-
-=head1 CACHING
-
-Responses returned by Amazon's web service can be cached locally.
-C<Net::Amazon>'s C<new> method accepts a reference to a C<Cache>
-object. C<Cache> (or one of its companions like C<Cache::Memory>,
-C<Cache::File>, etc.) can be downloaded from CPAN, please check their
-documentation for details. In fact, any other type of cache
-implementation will do as well, see the requirements below.
-
-Here's an example utilizing a file cache which causes C<Net::Amazon> to
-cache responses for 30 minutes:
-
- use Cache::File;
-
- my $cache = Cache::File->new(
- cache_root => '/tmp/mycache',
- default_expires => '30 min',
- );
-
- my $ua = Net::Amazon->new(
- token => 'YOUR_AMZN_TOKEN',
- cache => $cache,
- );
-
-C<Net::Amazon> uses I<positive> caching only, errors won't be cached.
-Erroneous requests will be sent to Amazon every time. Positive cache
-entries are keyed by the full URL used internally by requests submitted
-to Amazon.
-
-Caching isn't limited to the C<Cache> class. Any cache object which
-adheres to the following interface can be used:
-
- # Set a cache value
- $cache->set($key, $value);
-
- # Return a cached value, 'undef' if it doesn't exist
- $cache->get($key);
-
-=head1 PROXY SETTINGS
-
-C<Net::Amazon> uses C<LWP::UserAgent> under the hood to send
-web requests to Amazon's web site. If you're in an environment where
-all Web traffic goes through a proxy, there's two ways to configure that.
-
-First, C<Net::Amazon> picks up proxy settings from environment variables:
-
- export http_proxy=http://proxy.my.place:8080
-
-in the surrounding shell or setting
-
- $ENV{http_proxy} = "http://proxy.my.place:8080";
-
-in your Perl script
-will route all requests through the specified proxy.
-
-Secondly, you can
-pass a user agent instance to Net::Amazon's constructor:
-
- use Net::Amazon;
- use LWP::UserAgent;
-
- my $ua = LWP::UserAgent->new();
- my $na = Net::Amazon->new(ua => $ua, token => 'YOUR_AMZN_TOKEN');
- # ...
-
-This way, you can configure C<$ua> up front before Net::Amazon will use it.
-
-=head1 DEBUGGING
-
-If something's going wrong and you want more verbosity, just bump up
-C<Net::Amazon>'s logging level. C<Net::Amazon> comes with C<Log::Log4perl>
-statements embedded, which are disabled by default. However, if you initialize
-C<Log::Log4perl>, e.g. like
-
- use Net::Amazon;
- use Log::Log4perl qw(:easy);
-
- Log::Log4perl->easy_init($DEBUG);
- my Net::Amazon->new();
- # ...
-
-you'll see what's going on behind the scenes, what URLs the module
-is requesting from Amazon and so forth. Log::Log4perl allows all kinds
-of fancy stuff, like writing to a file or enabling verbosity in certain
-parts only -- check http://log4perl.sourceforge.net for details.
-
-=head1 LIVE TESTING
-
-Results returned by Amazon can be incomplete or simply wrong at times,
-due to their "best effort" design of the service. This is why the test
-suite that comes with this module has been changed to perform its test
-cases against canned data. If you want to perform the tests against
-the live Amazon servers instead, just set the environment variable
-
- NET_AMAZON_LIVE_TESTS=1
-
-=head1 WHY ISN'T THERE SUPPORT FOR METHOD XYZ?
-
-Because nobody wrote it yet. If Net::Amazon doesn't yet support a method
-advertised on Amazon's web service, you could help us out. Net::Amazon
-has been designed to be expanded over time, usually it only takes a couple
-of lines to support a new method, the rest is done via inheritance within
-Net::Amazon.
-
-Here's the basic plot:
-
-=over 4
-
-=item *
-
-Get Net::Amazon from CVS. Use
-
- # (Just hit enter when prompted for a password)
- cvs -d:pserver:anonymous@cvs.net-amazon.sourceforge.net:/cvsroot/net-amazon login
- cvs -z3 -d:pserver:anonymous@cvs.net-amazon.sourceforge.net:/cvsroot/net-amazon co Net-Amazon
-
-If this doesn't work, just use the latest distribution from
-net-amazon.sourceforge.net.
-
-=item *
-
-Write a new Net::Amazon::Request::XYZ package, start with this template
-
- ######################################
- package Net::Amazon::Request::XYZ;
- ######################################
- use base qw(Net::Amazon::Request);
-
- ######################################
- sub new {
- ######################################
- my($class, %options) = @_;
-
- if(!exists $options{XYZ_option}) {
- die "Mandatory parameter 'XYZ_option' not defined";
- }
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
- }
-
-and add documentation. Then, create a new Net::Amazon::Response::XYZ module:
-
- ##############################
- package Net::Amazon::Response;
- ##############################
- use base qw(Net::Amazon::Response);
-
- use Net::Amazon::Property;
-
- ##############################
- sub new {
- ##############################
- my($class, %options) = @_;
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
- }
-
-and also add documentation to it. Then, add the line
-
- use Net::Amazon::Request::XYZ;
-
-to Net/Amazon.pm.
-
-=back
-
-And that's it! Again, don't forget the I<add documentation> part. Modules
-without documentation are of no use to anybody but yourself.
-
-Check out the different Net::Amazon::Request::*
-and Net::Amazon::Response modules in the distribution if you need to adapt
-your new module to fulfil any special needs, like a different Amazon URL
-or a different way to handle the as_string() method. Also, post
-and problems you might encounter to the mailing list, we're gonna help you
-out.
-
-If possible, provide a test case for your extension. When finished, send
-a patch to the mailing list at
-
- net-amazon-devel@lists.sourceforge.net
-
-and if it works, I'll accept it and will work it into the main distribution.
-Your name will show up in the contributor's list below (unless you tell
-me otherwise).
-
-=head2 SAMPLE SCRIPTS
-
-There's a number of useful scripts in the distribution's eg/ directory.
-Take C<power> for example, written by Martin Streicher
-E<lt>martin.streicher@apress.comE<gt>: I lets you perform
-a I<power search> using Amazon's query language. To search for all books
-written by Randal Schwartz about Perl, call this from the command line:
-
- power 'author: schwartz subject: perl'
-
-Note that you need to quote the query string to pass it as one argument
-to C<power>. If a power search returns more results than you want to
-process at a time, just limit the number of pages, telling C<power>
-which page to start at (C<-s>) and which one to finish with (C<-f>).
-Here's a search for all books on the subject C<computer>, limited
-to the first 10 pages:
-
- power -s 1 -f 10 'subject: computer'
-
-Check out the script C<power> in eg/ for more options.
-
-=head2 HOW TO SEND ME PATCHES
-
-If you want me to include your modification or enhancement
-in the distribution of Net::Amazon, please do the following:
-
-=over 4
-
-=item *
-
-Work off the latest CVS version. Here's the steps to get it:
-
- CVSROOT=:pserver:anonymous@cvs.net-amazon.sourceforge.net:/cvsroot/net-amazon
- export CVSROOT
- cvs login (just hit Enter)
- cvs co Net-Amazon
-
-This will create a new C<Net-Amazon> directory with the latest
-development version of C<Net::Amazon> on your local machine.
-
-=item *
-
-Apply your changes to this development tree.
-
-=item *
-
-Run a diff between the tree and your changes it in this way:
-
- cd Net-Amazon
- cvs diff -Nau >patch_to_mike.txt
-
-=item *
-
-Email me C<patch_to_mike.txt>. If your patch works (and you've included
-test cases and documentation), I'll apply it on the spot.
-
-=back
-
-=head1 INSTALLATION
-
-C<Net::Amazon> depends on Log::Log4perl, which can be pulled from CPAN by
-simply saying
-
- perl -MCPAN -eshell 'install Log::Log4perl'
-
-Also, it needs LWP::UserAgent and XML::Simple 2.x, which can be obtained
-in a similar way.
-
-Once all dependencies have been resolved, C<Net::Amazon> installs with
-the typical sequence
-
- perl Makefile.PL
- make
- make test
- make install
-
-Make sure you're connected to the Internet while running C<make test>
-because it will actually contact amazon.com and run a couple of live tests.
-
-The module's distribution tarball and documentation are available at
-
- http://perlmeister.com/devel/#amzn
-
-and on CPAN.
-
-=head1 SEE ALSO
-
-The following modules play well within the C<Net::Amazon> framework:
-
-=over 4
-
-=item C<Net::Amazon::RemoteCart>
-
-by David Emery E<lt>dave@skiddlydee.comE<gt> provides a complete API for
-creating Amazon shopping carts on a local site, managing them and finally
-submitting them to Amazon for checkout. It is available on CPAN.
-
-=back
-
-=head1 CONTACT
-
-The C<Net::Amazon> project's home page is hosted on
-
- http://net-amazon.sourceforge.net
-
-where you can find documentation, news and the latest development and
-stable releases for download. If you have questions about how to
-use C<Net::Amazon>, want to report a bug or just participate in its
-development, please send a message to the mailing
-list net-amazon-devel@lists.sourceforge.net
-
-=head1 AUTHOR
-
-Mike Schilli, E<lt>na@perlmeister.comE<gt> (Please contact me via the mailing list: net-amazon-devel@lists.sourceforge.net )
-
-Contributors (thanks y'all!):
-
- Andy Grundman <andy@hybridized.org>
- Barnaby Claydon <bclaydon@perseus.com>
- Batara Kesuma <bkesuma@gaijinweb.com>
- Bill Fitzpatrick
- Brian <brianbrian@gmail.com>
- Brian Hirt <bhirt@mobygames.com>
- Dan Kreft <dan@kreft.net>
- Dan Sully <daniel@electricrain.com>
- Jackie Hamilton <kira@cgi101.com>
- Konstantin Gredeskoul <kig@get.topica.com>
- Lance Cleveland <lancec@proactivewm.com>
- Martha Greenberg <marthag@mit.edu>
- Martin Streicher <martin.streicher@apress.com>
- Mike Evron <evronm@dtcinc.net>
- Padraic Renaghan <padraic@renaghan.com>
- rayg <rayg@varchars.com>
- Robert Graff <rgraff@workingdemo.com>
- Robert Rothenberg <wlkngowl@i-2000.com>
- Steve Rushe <steve@deeden.co.uk>
- Tatsuhiko Miyagawa <miyagawa@livedoor.jp>
- Tony Bowden <tony@kasei.com>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2003, 2004 by Mike Schilli E<lt>na@perlmeister.comE<gt>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/Net/Amazon/Attribute/Review.pm b/lib/Net/Amazon/Attribute/Review.pm
deleted file mode 100644
index 5a5d094..0000000
--- a/lib/Net/Amazon/Attribute/Review.pm
+++ /dev/null
@@ -1,104 +0,0 @@
-######################################################################
-package Net::Amazon::Attribute::Review;
-######################################################################
-use warnings;
-use strict;
-use Log::Log4perl qw(:easy);
-use base qw(Net::Amazon);
-
-__PACKAGE__->make_accessor($_) for qw(rating summary comment);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- my $self = {
- rating => "",
- summary => "",
- comment => "",
- %options,
- };
-
- bless $self, $class;
-}
-
-##################################################
-sub init_via_xmlref {
-##################################################
- my($self, $xmlref) = @_;
-
- for(qw(Rating Summary Comment)) {
- my $method = lc($_);
- if($xmlref->{$_}) {
- $self->$method($xmlref->{$_});
- } else {
- #LOGWARN "No '$_'";
- return undef;
- }
- }
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Attribute::Review - Customer Review Class
-
-=head1 SYNOPSIS
-
- use Net::Amazon::Attribute::Review;
- my $rev = Net::Amazon::Attribute::Review->new(
- 'rating' => $rating,
- 'summary' => $summary,
- 'comment' => $comment,
- );
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Attribute::Review> holds customer reviews.
-
-=head2 METHODS
-
-=over 4
-
-=item rating()
-
-Accessor for the numeric value of the rating.
-
-=item summary()
-
-Accessor for the string value of the summary.
-
-=item comment()
-
-Accessor for the string value of the customer comment.
-
-=back
-
-=head1 SEE ALSO
-
-=head1 AUTHOR
-
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
-
-__END__
- <Reviews>
- <AvgCustomerRating>4.33</AvgCustomerRating>
- <TotalCustomerReviews>6</TotalCustomerReviews>
- <CustomerReview>
- <Rating>4</Rating>
- <Summary>Good introduction to Perl, and great reference</Summary>
- <Comment>From its corny title you might expect another one of those
-
diff --git a/lib/Net/Amazon/Attribute/ReviewSet.pm b/lib/Net/Amazon/Attribute/ReviewSet.pm
deleted file mode 100644
index 29a34e6..0000000
--- a/lib/Net/Amazon/Attribute/ReviewSet.pm
+++ /dev/null
@@ -1,137 +0,0 @@
-######################################################################
-package Net::Amazon::Attribute::ReviewSet;
-######################################################################
-use warnings;
-use strict;
-use Log::Log4perl qw(:easy);
-use Net::Amazon::Attribute::Review;
-use base qw(Net::Amazon);
-
-__PACKAGE__->make_accessor($_) for qw(average_customer_rating total_reviews);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- my $self = {
- reviews => [], # list of reviews
- };
-
- bless $self, $class;
-}
-
-###########################################
-sub add_review {
-###########################################
- my($self, $review) = @_;
-
- if(ref $review ne "Net::Amazon::Attribute::Review") {
- warn "add_review called with type ", ref $review;
- return undef;
- }
-
- push @{$self->{reviews}}, $review;
-}
-
-###########################################
-sub reviews {
-###########################################
- my($self) = @_;
-
- return @{$self->{reviews}};
-}
-
-##################################################
-sub init_via_xmlref {
-##################################################
- my($self, $xmlref) = @_;
-
- my @pairs = qw(AvgCustomerRating average_customer_rating
- TotalCustomerReviews total_reviews);
-
- while(my($field, $method) = splice @pairs, 0, 2) {
-
- if(defined $xmlref->{$field}) {
- DEBUG "Setting $field via $method to $xmlref->{$field}";
- $self->$method($xmlref->{$field});
- } else {
- LOGWARN "No '$field'";
- return undef;
- }
- }
-
- if(ref $xmlref->{CustomerReview} ne "ARRAY") {
- $xmlref->{CustomerReview} = [$xmlref->{CustomerReview}];
- }
-
- for my $review_xmlref (@{$xmlref->{CustomerReview}}) {
- my $review = Net::Amazon::Attribute::Review->new();
- $review->init_via_xmlref($review_xmlref);
- DEBUG "Adding review ", $review->summary();
- $self->add_review($review);
- }
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Attribute::ReviewSet - A set of customer reviews
-
-=head1 SYNOPSIS
-
- use Net::Amazon::Attribute::ReviewSet;
- my $rev = Net::Amazon::Attribute::Review->new(
- average_customer_rating => $avg,
- total_reviews => $total,
- );
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Attribute::ReviewSet> holds a list of customer
-reviews, each of type C<Net::Amazon::Attribute::Review>.
-
-=head2 METHODS
-
-=over 4
-
-=item C<< $self->reviews() >>
-
-Returns a list of C<Net::Amazon::Attribute::Review> objects.
-
-=item C<< $self->average_customer_rating() >>
-
-Accessor for the average customer rating, a numeric value.
-
-=item C<< $self->total_reviews() >>
-
-Accessor for the total number of reviews. Please note that this
-might not be equal to the number of reviews held in the list, since
-there might be less customer reviews than total reviews (reviews
-can also be non-customer-reviews, but they're not available by
-the web service as of Aug 2003).
-
-=item C<< $self->add_review($rev) >>
-
-Add a C<Net::Amazon::Attribute::Review> object to the list.
-(Used internally only).
-
-=back
-
-=head1 SEE ALSO
-
-=head1 AUTHOR
-
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/Net/Amazon/Property.pm b/lib/Net/Amazon/Property.pm
deleted file mode 100644
index 6c06957..0000000
--- a/lib/Net/Amazon/Property.pm
+++ /dev/null
@@ -1,320 +0,0 @@
-######################################################################
-package Net::Amazon::Property;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon);
-
-use Net::Amazon::Property::DVD;
-use Net::Amazon::Property::Book;
-use Net::Amazon::Property::Music;
-use Net::Amazon::Attribute::ReviewSet;
-use Data::Dumper;
-use Log::Log4perl qw(:easy);
-
-use warnings;
-use strict;
-
-our @DEFAULT_ATTRIBUTES = qw(
- OurPrice ImageUrlLarge ImageUrlMedium ImageUrlSmall
- ReleaseDate Catalog Asin url Manufacturer UsedPrice
- ListPrice ProductName Availability SalesRank
- Media NumMedia ProductDescription
- CollectiblePrice CollectibleCount NumberOfOfferings
- UsedCount ThirdPartyNewPrice ThirdPartyNewCount
- ThirdPartyProductInfo
-);
-
-__PACKAGE__->make_accessor($_) for @DEFAULT_ATTRIBUTES;
-__PACKAGE__->make_accessor($_) for qw(year review_set);
-__PACKAGE__->make_array_accessor($_) for qw(browse_nodes similar_asins);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- if(!$options{xmlref}) {
- die "Mandatory param xmlref missing";
- }
-
- my $self = {
- %options,
- };
-
- bless $self, $class;
-
- # Set default attributes
- for my $attr (@DEFAULT_ATTRIBUTES) {
- $self->$attr($options{xmlref}->{$attr});
- }
-
- # The release date is sometimes missing
- if($options{xmlref}->{ReleaseDate}) {
- my ($year) = ($options{xmlref}->{ReleaseDate} =~ /(\d{4})/);
- $self->year($year);
- } else {
- $self->year("");
- }
-
- my $browse_nodes = $options{xmlref}->{BrowseList}->{BrowseNode};
- if(ref($browse_nodes) eq "ARRAY") {
- my @nodes = map {
- $_->{BrowseName}
- } @{ $browse_nodes };
- $self->browse_nodes(\@nodes);
- } elsif (ref($browse_nodes) eq "HASH") {
- $self->browse_nodes([ $browse_nodes->{BrowseName} ]);
- } else {
- $self->browse_nodes([ ]);
- }
-
- my $similar = $options{xmlref}->{SimilarProducts};
- if(ref($similar) eq "HASH") {
- $self->similar_asins($similar->{Product});
- } else {
- $self->similar_asins([ ]);
- }
-
- return $self;
-}
-
-##################################################
-sub as_string {
-##################################################
- my($self) = @_;
-
- my $result = "\"$self->{xmlref}->{ProductName}\", ";
-
- if($self->{xmlref}->{Manufacturer}) {
- $result .= "$self->{xmlref}->{Manufacturer}, ";
- }
-
- $result .= $self->year() . ", " if $self->year();
-
- $result .= $self->OurPrice() . ", ";
- $result .= $self->Asin();
- return $result;
-}
-
-##################################################
-sub factory {
-##################################################
- my(%options) = @_;
-
- my $xmlref = $options{xmlref};
- die "Called factory without xmlref" unless $xmlref;
-
- # DEBUG(sub {"factory xmlref=" . Data::Dumper::Dumper($xmlref)});
-
- my $catalog = $xmlref->{Catalog};
- my $obj;
-
- if(0) {
- } elsif($catalog eq "Book") {
- DEBUG("Creating new Book Property");
- $obj = Net::Amazon::Property::Book->new(xmlref => $xmlref);
- } elsif($catalog eq "Music") {
- DEBUG("Creating new Music Property");
- $obj = Net::Amazon::Property::Music->new(xmlref => $xmlref);
- } elsif($catalog eq "DVD") {
- DEBUG("Creating new DVD Property");
- $obj = Net::Amazon::Property::DVD->new(xmlref => $xmlref);
- } else {
- DEBUG("Creating new Default Property ($catalog)");
- $obj = Net::Amazon::Property->new(xmlref => $xmlref);
- }
-
- return $obj;
-}
-
-##################################################
-sub init_via_xmlref {
-##################################################
- my($self, $xmlref) = @_;
-
- my $reviewset = Net::Amazon::Attribute::ReviewSet->new();
-
- if(exists $xmlref->{Reviews}) {
- $reviewset->init_via_xmlref($xmlref->{Reviews});
- }
-
- $self->review_set($reviewset);
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Property - Baseclass for products on amazon.com
-
-=head1 SYNOPSIS
-
- use Net::Amazon;
-
- # ...
-
- if($resp->is_success()) {
- for my $prop ($resp->properties) {
- print $_->ProductName(), " ",
- $_->Manufacturer(), " ",
- $_->OurPrice(), "\n";
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Property> is the baseclass for results returned
-from Amazon web service queries. The term 'properties' is used as
-a generic description for an item on amazon.com.
-
-Typically, the C<properties()> method of a C<Net::Amazon::Response::*> object
-will return one or more objects of class C<Net::Amazon::Property> or
-one of its subclasses, e.g. C<Net::Amazon::Property::Book> or
-C<Net::Amazon::Property::CD>.
-
-While C<Net::Amazon::Property> objects expose accessors for all
-fields returned in the XML response (like C<OurPrice()>, C<ListPrice()>,
-C<Manufacturer()>, C<Asin()>, C<Catalog()>, C<ProductName()>, subclasses
-might define their own accessors to more class-specific fields
-(like the iC<Net::Amazon::Property::Book>'s C<authors()> method returning
-a list of authors, while C<Net::Amazon::Property>'s C<Authors()> method
-will return a reference to a sub-hash containing a C<Author> field, just like
-the response's XML contained it).
-
-=head2 METHODS
-
-Methods vary, depending on the item returned from a query. Here's the most
-common ones. They're all accessors, meaning they can be used like C<Method()>
-to retrieve the value or like C<Method($value)> to set the value of the
-field.
-
-=over 4
-
-=item Asin()
-
-The item's ASIN number.
-
-=item ProductName()
-
-Book title, CD album name or item name
-
-=item Availability()
-
-Text string describing if the item is available. Examples:
-C<"Usually ships within 24 hours"> or
-C<"Out of Print--Limited Availability">.
-
-=item Catalog()
-
-Shows the catalog the item was found in: C<Book>, C<Music>, C<Classical>,
-C<Electronics> etc.
-
-=item Authors()
-
-Returns a sub-hash with a C<Author> key, which points to either a single
-$scalar or to a reference of an array containing author names as scalars.
-
-=item ReleaseDate()
-
-Item's release date, format is "NN Monthname, Year".
-
-=item Manufacturer()
-
-Music label, publishing company or manufacturer
-
-=item ImageUrlSmall()
-
-URL to a small (thumbnail) image of the item
-
-=item ImageUrlMedium()
-
-URL to a medium-size image of the item
-
-=item ImageUrlLarge()
-
-URL to a large image of the item
-
-=item ListPrice()
-
-List price of the item
-
-=item OurPrice()
-
-Amazon price of the item
-
-=item UsedPrice()
-
-Used price of the item
-
-=item SalesRank()
-
-Sales rank of the item (contains digits and commas, like 1,000,001)
-
-=item Media()
-
-Type of media (Paperback, etc.).
-
-=item NumMedia()
-
-Number of media the item carries (1,2 CDs etc.).
-
-=item ProductDescription()
-
-Lengthy textual description of the product.
-
-=item CollectiblePrice()
-
-Lowest price in "Collectible" category.
-
-=item CollectibleCount()
-
-Number of offerings in "Collectible" category.
-
-=item NumberOfOfferings()
-
-Total number of offerings in all categories.
-
-=item UsedCount()
-
-Number of offerings in "Used" category.
-
-=item ThirdPartyNewPrice()
-
-Lowest price in "Third Party New" category.
-
-=item ThirdPartyNewCount()
-
-Number of offerings in "Third Party New" category.
-
-=item year()
-
-The release year extracted from ReleaseDate().
-
-=item browse_nodes()
-
-Returns a list of browse nodes (text string categories) for this item.
-
-=item similar_asins()
-
-Returns a list of ASINs of similar items for this item.
-
-=back
-
-Please check the subclasses of C<Net::Amazon::Property> for specialized
-methods.
-
-=head1 SEE ALSO
-
-=head1 AUTHOR
-
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/Net/Amazon/Property/Book.pm b/lib/Net/Amazon/Property/Book.pm
deleted file mode 100644
index 8a01756..0000000
--- a/lib/Net/Amazon/Property/Book.pm
+++ /dev/null
@@ -1,152 +0,0 @@
-######################################################################
-package Net::Amazon::Property::Book;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Property);
-
-__PACKAGE__->make_accessor($_) for qw(title publisher binding isbn);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- my $self = $class->SUPER::new(%options);
- bless $self, $class; # Bless into this class
-
- if(exists $options{xmlref}) {
- $self->init_via_xmlref($options{xmlref});
- }
-
- return $self;
-}
-
-##################################################
-sub init_via_xmlref {
-##################################################
- my($self, $xmlref) = @_;
-
- $self->SUPER::init_via_xmlref($xmlref);
-
- $self->authors($xmlref->{Authors}->{Author});
- $self->title($xmlref->{ProductName});
- $self->publisher($xmlref->{Manufacturer});
- $self->binding($xmlref->{Media});
- $self->isbn($xmlref->{Isbn});
-}
-
-##################################################
-sub author {
-##################################################
- my($self, $nameref) = @_;
-
- # Only return the first author
- return ($self->authors($nameref))[0];
-}
-
-##################################################
-sub authors {
-##################################################
- my($self, $nameref) = @_;
-
- if(defined $nameref) {
- if(ref $nameref eq "ARRAY") {
- $self->{authors} = $nameref;
- } else {
- $self->{authors} = [$nameref];
- }
- }
-
- # Return a list
- return $self->{authors} ? @{$self->{authors}} : ();
-}
-
-##################################################
-sub as_string {
-##################################################
- my($self) = @_;
-
- return join('/', $self->authors) . ", " .
- '"' . $self->title . '"' . ", " .
- $self->year . ", " .
- $self->OurPrice . ", " .
- $self->Asin;
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Property::Book - Class for books on amazon.com
-
-=head1 SYNOPSIS
-
- use Net::Amazon;
-
- # ...
-
- if($resp->is_success()) {
- for my $prop ($resp->properties) {
- print join("/", $prop->authors(), " ",
- $prop->title(), " ",
- $prop->publisher(), " ",
- $prop->year(), "\n";
- }
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Property::Book> is derived from
-C<Net::Amazon::Property> and on top of the all-purpose
-methods the base class provides, it offers specialized accessors for
-book parameters.
-
-=head2 METHODS
-
-=over 4
-
-=item authors()
-
-Returns a list of the book's authors. There's also a C<author()> method
-which just returns the I<first> author.
-
-=item publisher()
-
-Returns the book's publishing company as a string.
-
-=item title()
-
-Returns the book's title as a string.
-
-=item isbn()
-
-Returns the book's ISBN number.
-
-=item new(xmlref => $xmlref)
-
-Initializes an object by passing a hash of hashes structure containing
-the XML data returned from the service. Usually, this is just used by
-C<Net::Amazon> internally to initialize objects for on backcoming
-data.
-
-=back
-
-Check out L<Net::Amazon::Property> for all-purpose accessors, like
-C<year>, C<OurPrice>, C<ListPrice>, etc.
-
-=head1 SEE ALSO
-
-=head1 AUTHOR
-
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/Net/Amazon/Property/DVD.pm b/lib/Net/Amazon/Property/DVD.pm
deleted file mode 100644
index dc7fd5a..0000000
--- a/lib/Net/Amazon/Property/DVD.pm
+++ /dev/null
@@ -1,156 +0,0 @@
-######################################################################
-package Net::Amazon::Property::DVD;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Property);
-
-__PACKAGE__->make_accessor($_) for qw(title studio theatrical_release_date
- media nummedia upc mpaa_rating);
-__PACKAGE__->make_array_accessor($_) for qw(directors starring features);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- my $self = $class->SUPER::new(%options);
- bless $self, $class; # Bless into this class
-
- if(exists $options{xmlref}) {
- $self->init_via_xmlref($options{xmlref});
- }
-
- return $self;
-}
-
-##################################################
-sub director {
-##################################################
- my($self, $nameref) = @_;
-
- # Only return the first director
- return ($self->directors($nameref))[0];
-}
-
-##################################################
-sub init_via_xmlref {
-##################################################
- my($self, $xmlref) = @_;
-
- $self->SUPER::init_via_xmlref($xmlref);
-
- $self->title($xmlref->{ProductName});
- $self->studio($xmlref->{Manufacturer});
- $self->directors($xmlref->{Directors}->{Director});
- $self->starring($xmlref->{Starring}->{Actor});
- $self->media($xmlref->{Media});
- $self->nummedia($xmlref->{NumMedia});
- $self->upc($xmlref->{Upc});
- $self->theatrical_release_date($xmlref->{TheatricalReleaseDate});
- $self->mpaa_rating($xmlref->{MpaaRating});
- $self->features($xmlref->{Features}->{Feature});
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Property::DVD - Class for DVDs on amazon.com
-
-=head1 SYNOPSIS
-
- use Net::Amazon;
-
- # ...
-
- if($resp->is_success()) {
- for my $prop ($resp->properties) {
- print $_->title(), " ",
- $_->studio(), " ",
- $_->year(), "\n";
- }
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Property::DVD> is derived from
-C<Net::Amazon::Property> and on top of the all-purpose
-methods the base class provides, it offers specialized accessors for
-DVD parameters.
-
-=head2 METHODS
-
-=over 4
-
-=item title()
-
-Returns the title of the DVD.
-
-=item studio()
-
-Returns the studio.
-
-=item directors()
-
-Returns a list of directors. Note that there's also a director() method
-only returning the first director.
-
-=item starring()
-
-Returns a list of actors starring in the movie.
-
-=item upc()
-
-Returns the DVD's UPC as a string.
-
-=item media()
-
-Returns the DVD's media type as a string.
-
-=item nummedia()
-
-Returns the DVD's number of media (number of discs) as a string.
-Amazon doesn't always send this back, so if you get undef assume it
-is 1.
-
-=item theatrical_release_date()
-
-Returns the DVD's theatrical release date.
-
-=item mpaa_rating()
-
-Returns the DVD's MPAA rating.
-
-=item features()
-
-Returns the DVD's features as a list of strings. Examples:
-"Color", "Closed-captioned", "Widescreen".
-
-=item new(xmlref => $xmlref)
-
-Initializes an object by passing a hash of hashes structure containing
-the XML data returned from the service. Usually, this is just used by
-C<Net::Amazon> internally to initialize objects for on backcoming
-data.
-
-=back
-
-Check out L<Net::Amazon::Property> for all-purpose accessors, like
-C<year>, C<OurPrice>, C<ListPrice>, etc.
-
-=head1 SEE ALSO
-
-=head1 AUTHOR
-
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/Net/Amazon/Property/Music.pm b/lib/Net/Amazon/Property/Music.pm
deleted file mode 100644
index 59807be..0000000
--- a/lib/Net/Amazon/Property/Music.pm
+++ /dev/null
@@ -1,161 +0,0 @@
-######################################################################
-package Net::Amazon::Property::Music;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Property);
-
-__PACKAGE__->make_accessor($_) for qw(album label media nummedia upc);
-__PACKAGE__->make_array_accessor($_) for qw(artists tracks);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- my $self = $class->SUPER::new(%options);
- bless $self, $class; # Bless into this class
-
- if(exists $options{xmlref}) {
- $self->init_via_xmlref($options{xmlref});
- }
-
- return $self;
-}
-
-##################################################
-sub artist {
-##################################################
- my($self, $nameref) = @_;
-
- # Only return the first artist
- return ($self->artists($nameref))[0];
-}
-
-##################################################
-sub init_via_xmlref {
-##################################################
- my($self, $xmlref) = @_;
-
- $self->SUPER::init_via_xmlref($xmlref);
-
- $self->artists($xmlref->{Artists}->{Artist});
- $self->tracks($xmlref->{Tracks}->{Track});
- $self->album($xmlref->{ProductName});
- $self->label($xmlref->{Manufacturer});
- $self->upc($xmlref->{Upc});
- $self->media($xmlref->{Media});
- $self->nummedia($xmlref->{NumMedia});
-}
-
-##################################################
-sub as_string {
-##################################################
- my($self) = @_;
-
- return join('/', $self->artists) . ", " .
- '"' . $self->album . '"' . ", " .
- $self->year . ", " .
- $self->OurPrice . ", " .
- $self->Asin;
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Property::Music - Class for pop CDs on amazon.com
-
-=head1 SYNOPSIS
-
- use Net::Amazon;
-
- # ...
-
- if($resp->is_success()) {
- for my $prop ($resp->properties) {
- print join("/", $_->artists(), " ",
- $_->album(), " ",
- $_->label(), " ",
- $_->year(), " ";
- $_->upc(), " ";
- $_->media(), " ";
- $_->nummedia(), "\n";
- }
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Property::Music> is derived from
-C<Net::Amazon::Property> and on top of the all-purpose
-methods the base class provides, it offers specialized accessors for
-popular music CD parameters.
-
-=head2 METHODS
-
-=over 4
-
-=item artists()
-
-Returns a list of the CD's artists. There's also a C<artist()> method
-which just returns the first artist.
-
-=item tracks()
-
-Returns a list of the CD's track titles.
-
-=item label()
-
-Returns the music label as a string.
-
-=item album()
-
-Returns the CD's title as a string.
-
-=item upc()
-
-Returns the CD's UPC as a string.
-
-=item media()
-
-Returns the CD's media type as a string.
-
-=item nummedia()
-
-Returns the CD's number of media (number of discs) as a string.
-Amazon doesn't always send this back, so if you get undef assume it
-is 1.
-
-=item new(xmlref => $xmlref)
-
-Initializes an object by passing a hash of hashes structure containing
-the XML data returned from the service. Usually, this is just used by
-C<Net::Amazon> internally to initialize objects for on backcoming
-data.
-
-=back
-
-Check out L<Net::Amazon::Property> for all-purpose accessors, like
-C<year>, C<OurPrice>, C<ListPrice>, etc.
-
-=head1 SEE ALSO
-
-=head1 AUTHOR
-
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=head1 THANKS
-
-Thanks to Padraic Renaghan E<lt>padraic@renaghan.com<gt> for adding
-the upc/media/nummedia fields.
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
-
diff --git a/lib/Net/Amazon/Request.pm b/lib/Net/Amazon/Request.pm
deleted file mode 100644
index 962d7bf..0000000
--- a/lib/Net/Amazon/Request.pm
+++ /dev/null
@@ -1,221 +0,0 @@
-######################################################################
-package Net::Amazon::Request;
-######################################################################
-
-use warnings;
-use strict;
-
-use constant DEFAULT_MODE => 'books';
-use constant DEFAULT_TYPE => 'heavy';
-use constant DEFAULT_PAGE_COUNT => 1;
-use constant DEFAULT_FORMAT => 'xml';
-use constant DEFAULT_SORT_CRITERIA => '+salesrank';
-
-use constant VALID_TYPES => { map { $_ => 1 } qw(heavy lite) };
-
-our $AMZN_XML_URL = "http://xml.amazon.com/onca/xml3";
-
-##################################################
-sub amzn_xml_url {
-##################################################
- return $AMZN_XML_URL;
-}
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- my $self = {
- mode => DEFAULT_MODE,
- type => DEFAULT_TYPE,
- page => DEFAULT_PAGE_COUNT,
- f => DEFAULT_FORMAT,
- sort => DEFAULT_SORT_CRITERIA,
- %options,
- };
-
- die "Unknown type in ", __PACKAGE__, " constructor: ",
- $self->{type} unless exists VALID_TYPES->{$self->{type}};
-
- bless $self, $class;
-}
-
-##################################################
-sub params {
-##################################################
- my($self) = @_;
-
- return(%$self);
-}
-
-##################################################
-# Figure out the Response class to a given Request
-# class. To be used by sub classes.
-##################################################
-sub response_class {
-##################################################
- my($self) = @_;
-
- my $response_class = ref($self);
- $response_class =~ s/Request/Response/;
- return $response_class;
-}
-
-##
-## 'PRIVATE' METHODS
-##
-
-# CLASS->_convert_option( OPTIONS, ORIGINAL, TARGET [, CALLBACK] )
-#
-# Takes a reference to a hash of OPTIONS and renames the
-# ORIGINAL key name to the TARGET key name. If the optional
-# CALLBACK subroutine reference is defined, that subroutine
-# is invoked with two arguments:
-#
-# CALLBACK->( OPTIONS, TARGET )
-#
-# The result of the CALLBACK's execution is then returned to
-# the caller. No assumptions are made about what the CALLBACK
-# should return (or even *if* is should return)--that's the
-# caller's responsibility.
-#
-# Returns 1 in the absensence of a CALLBACK.
-#
-sub _convert_option {
- my ($class, $options, $original, $target, $callback) = @_;
-
- if ( exists $options->{$original} ) {
- $options->{$target} = $options->{$original};
- delete $options->{$original};
- }
-
- return 1 unless ( $callback );
-
- # The key name is explicitly passed-in so that the caller doesn't
- # have think "Hrmm.. now which key am I working on, the original
- # or the target key?" Confusion is bad.
- return $callback->($options, $target);
-}
-
-# CLASS->_assert_options_defined( OPTIONS, KEYS )
-#
-# Takes a reference to a hash of OPTIONS and a list of
-# one or more KEYS. Tests to see if each key in KEYS
-# has a defined value. Calls die() upon the first
-# missing key. Otherwise, returns undef.
-#
-sub _assert_options_defined {
- my ($class, $options, @keys) = @_;
-
- foreach my $key ( @keys ) {
- die "Mandatory parameter '$key' not defined"
- unless ( defined $options->{$key} );
- }
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Request - Baseclass for requests to Amazon's web service
-
-=head1 SYNOPSIS
-
- my $req = Net::Amazon::Request::XXX->new(
- [ type => 'heavy', ]
- [ page => $start_page, ]
- [ mode => $mode, ]
- [ offer => 'All', ]
- [ sort => $sort_type, ]
- );
-
-=head1 DESCRIPTION
-
-Don't use this class directly, use derived classes
-(like C<Net::Amazon::Request::ASIN>, C<Net::Amazon::Request::Wishlist>
-etc.) instead to specify the type of request and its parameters.
-
-However, there's a bunch of parameters to the constructor
-that all request types have in common, here they are:
-
-=over 4
-
-=item type
-
-Defaults to C<heavy>, but can be set to C<lite> if no reviews etc.
-on a product are wanted. Some fields (e.g. C<isbn>) are not going to be
-available in C<lite> mode, though.
-
-=item mode
-
-Defaults to C<books>, but can be set to other catalog values.
-
-=item page
-
-Defaults to C<1>, but can be set to a different number to
-start with a different result page. Used in conjunction with the
-C<max_pages> parameter of the C<Net::Amazon> object. C<page> is the
-offset, C<max_pages> is the maximum number of pages pulled in starting
-at C<page>.
-
-=item sort
-
-Defaults to C<+salesrank>, but search results can be sorted in various
-ways, depending on the type of product returned by the search. Search
-results may be sorted by the following criteria:
-
-=over 8
-
-=item *
-Featured Items
-
-=item *
-Bestselling
-
-=item *
-Alphabetical (A-Z and Z-A)
-
-=item *
-Price (High to Low and Low to High)
-
-=item *
-Publication or Release Date
-
-=item *
-Manufacturer
-
-=item *
-Average Customer Review
-
-=item *
-Artist Name
-
-=back
-
-Consult L<Net::Amazon::Request::Sort> for details.
-
-=item offer
-
-To receive values for the fields
-C<CollectibleCount>, C<NumberOfOfferings>, C<UsedCount>,
-specify C<offer =E<gt> "All">.
-
-=back
-
-=head1 SEE ALSO
-
-=head1 AUTHOR
-
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/Net/Amazon/Request/ASIN.pm b/lib/Net/Amazon/Request/ASIN.pm
deleted file mode 100644
index 4d8f752..0000000
--- a/lib/Net/Amazon/Request/ASIN.pm
+++ /dev/null
@@ -1,139 +0,0 @@
-######################################################################
-package Net::Amazon::Request::ASIN;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Request);
-
-# These values are defined in the AWS SDK
-# (http://amazon.com/webservices) under
-# "Product and Catalog Data" / "ASIN and ISBN Searches"
-use constant MAX_ASINS_PER_TYPE => {
- heavy => 10,
- lite => 30,
-};
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- $class->_assert_options_defined(\%options, 'asin');
-
- $class->_convert_option(\%options,
- 'asin',
- 'AsinSearch',
- \&_process_asin_option);
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-##
-## PRIVATE FUNCTIONS
-##
-
-# _process_asin_option( OPTIONS, KEY )
-#
-# Takes a reference to a hash of OPTIONS and checks the value keyed by
-# KEY to make sure it looks legitimate. If the value associated with
-# KEY is an array, we check to make sure that we're not asking for
-# too many asins at once.
-#
-# Returns true if all goes well. If any problems are encountered,
-# die() will be called.
-#
-sub _process_asin_option {
- my ($options, $key) = @_;
-
- # If the asins are supplied in the form of an array, we have to
- # make sure that the caller isn't trying to ask for too many at a
- # time. If we don't make this test, those excessive asins will be
- # silently ignored by the AWS servers...resulting in potentially
- # confusing results for the user.
- if ( ref $options->{$key} eq 'ARRAY' ) {
- my $type = $options->{'type'} || __PACKAGE__->SUPER::DEFAULT_TYPE;
- my $max_asins = MAX_ASINS_PER_TYPE->{$type};
-
- # Dying is the right thing to do here because this is
- # indicative of a programming error.
- die "Only $max_asins may be requested at a time using type '$type'"
- if ( @{$options->{$key}} > $max_asins );
-
- $options->{$key} = join ',', @{$options->{$key}};
- } elsif ( ref $options->{$key} ) {
- die "The 'asin' parameter must either be a scalar or an array";
- }
-
- return 1;
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Request::ASIN - Class for submitting ASIN requests
-
-=head1 SYNOPSIS
-
- use Net::Amazon;
- use Net::Amazon::Request::ASIN;
-
- my $ua = Net::Amazon->new(
- token => 'YOUR_AMZN_TOKEN'
- );
-
- my $req = Net::Amazon::Request::ASIN->new(
- asin => '0201360683'
- );
-
- # Response is of type Net::Amazon::Response::ASIN
- my $resp = $ua->request($req);
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Request::ASIN> is a class used to submit ASIN requests
-to the Amazon web service.
-
-The ASIN of the item to look is specified in the C<asin> parameter.
-
-Upon success, the responses' C<properties()> method will return one
-single C<Net::Amazon::Property::*> object.
-
-=head2 METHODS
-
-=over 4
-
-=item new( asin => $asin )
-
-Constructs a new C<Net::Amazon::Request::ASIN> object, used to query
-the Amazon web service for an item with the specified ASIN number.
-
-C<$asin> can also be a reference to an array of ASINs, like in
-
- $ua->search(asin => ["0201360683", "0596005083"])
-
-in which case a search for multiple ASINs is performed, returning a list of
-results.
-
-=back
-
-Check L<Net::Amazon::Request> for common request parameters not listed here.
-
-=head1 SEE ALSO
-
-=head1 AUTHOR
-
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/Net/Amazon/Request/Artist.pm b/lib/Net/Amazon/Request/Artist.pm
deleted file mode 100644
index 4c111f8..0000000
--- a/lib/Net/Amazon/Request/Artist.pm
+++ /dev/null
@@ -1,86 +0,0 @@
-######################################################################
-package Net::Amazon::Request::Artist;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Request);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- if(exists $options{artist}) {
- $options{ArtistSearch} = $options{artist};
- delete $options{artist};
- $options{mode} = "music";
- } else {
- die "Mandatory parameter 'artist' not defined";
- }
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Request::Artist - Class for submitting Artist requests
-
-=head1 SYNOPSIS
-
- use Net::Amazon;
- use Net::Amazon::Request::Artist;
-
- my $ua = Net::Amazon->new(
- token => 'YOUR_AMZN_TOKEN'
- );
-
- my $req = Net::Amazon::Request::Artist->new(
- artist => 'Zwan'
- );
-
- # Response is of type Net::Amazon::Response::Artist
- my $resp = $ua->request($req);
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Request::Artist> is a class used to submit Artist search
-requests to the Amazon web service.
-
-The artist to search for is specified in the C<artist> parameter.
-
-Upon success, the responses' C<properties()> method will return a list of
-C<Net::Amazon::Property::Music> objects.
-
-Check L<Net::Amazon::Request> for common request parameters not listed here.
-
-=head2 METHODS
-
-=over 4
-
-=item new( artist => $artist )
-
-Constructs a new C<Net::Amazon::Request::Artist> object, used to query
-the Amazon web service for items of a given artist.
-
-=back
-
-=head1 SEE ALSO
-
-=head1 AUTHOR
-
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/Net/Amazon/Request/Blended.pm b/lib/Net/Amazon/Request/Blended.pm
deleted file mode 100644
index 1000eec..0000000
--- a/lib/Net/Amazon/Request/Blended.pm
+++ /dev/null
@@ -1,80 +0,0 @@
-######################################################################
-package Net::Amazon::Request::Blended;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Request);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- $class->_assert_options_defined(\%options, 'blended');
-
- $class->_convert_option(\%options,
- 'blended',
- 'BlendedSearch');
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Request::Blended - request class for 'Blended Search'
-
-=head1 SYNOPSIS
-
- use Net::Amazon;
- use Net::Amazon::Request::Blended;
-
- my $ua = Net::Amazon->new(
- token => 'YOUR_AMZN_TOKEN'
- );
-
- my $req = Net::Amazon::Request::Blended->new(
- blended => 'perl'
- );
-
- # Response is of type Net::Amazon::Response::Blended
- my $resp = $ua->request($req);
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Request::Blended> is a class used to request
-I<Blended Searches> from the Amazon web service.
-
-The C<blended> parameter specifies the keyword search string
-for the blended query. C<mode> is not applicable to blended
-searches which returns books, music, etc all at once.
-
-Upon success, the response's C<properties()> method will return a list
-of C<Net::Amazon::Property::*> objects.
-
-=head2 METHODS
-
-=over 4
-
-=item new(keyword => $search_string)
-
-Constructs a new C<Net::Amazon::Request::Blended> object.
-
-See the "Amazon Web Services 2.1 API and Integration Guide" for details.
-
-=back
-
-Check L<Net::Amazon::Request> for common request parameters not listed here.
-
-=head1 SEE ALSO
-
-=head1 AUTHORS
-
-Robert Graff, E<lt>rgraff@workingdemo.comE<gt>
-
-=cut
diff --git a/lib/Net/Amazon/Request/BrowseNode.pm b/lib/Net/Amazon/Request/BrowseNode.pm
deleted file mode 100644
index 2f8d92f..0000000
--- a/lib/Net/Amazon/Request/BrowseNode.pm
+++ /dev/null
@@ -1,137 +0,0 @@
-######################################################################
-package Net::Amazon::Request::BrowseNode;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Request);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- $class->_assert_options_defined(\%options,
- qw(browsenode mode));
-
- $class->_convert_option(\%options,
- 'browsenode',
- 'BrowseNodeSearch',
- \&_assert_node_is_numeric);
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-##
-## 'PRIVATE' FUNCTIONS
-##
-
-# _assert_node_is_numeric( OPTIONS, KEY )
-#
-# Takes a reference to a hash of OPTIONS and makes sure
-# that the browse node id keyed by KEY is numeric.
-#
-# Returns if all is well, dies otherwise.
-#
-sub _assert_node_is_numeric {
- my ($options, $key) = @_;
-
- die "Browse Node ID must be numeric."
- if ( $options->{$key} =~ /\D/ );
-}
-
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Request::BrowseNode - request class for browse node search
-
-=head1 SYNOPSIS
-
- use Net::Amazon;
- use Net::Amazon::Request::BrowseNode;
-
- my $ua = Net::Amazon->new(
- token => 'YOUR_AMZN_TOKEN'
- );
-
- my $req = Net::Amazon::Request::BrowseNode->new(
- browsenode => 30,
- mode => 'books'
- );
-
- # Response is of type Net::Amazon::Response::BrowseNode
- my $resp = $ua->request($req);
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Request::BrowseNode> is a class used to submit node search
-requests to the Amazon web service.
-
-The node to search for is specified in the C<browsenode> parameter. The
-browse node ID is a number that corresponds to a general subject area
-of Amazon.com.
-
-To find browse node IDs, the best way is to visit the "browse" area
-of the various product lines at Amazon.com. When you find a subject area
-that you would like to generate XML for, look at the web page URL. The
-browse ID should appear after the string "/tg/browse/-/". Here are some
-examples of URLs that contain browse IDs:
-
-=over 8
-
-http://www.amazon.com/exec/obidos/tg/browse/-/30
-(In this example, the browse ID = 30)
-
-http://www.amazon.com/exec/obidos/tg/browse/-/467970
-(In this example, the browse ID = 467970)
-
-http://www.amazon.com/exec/obidos/tg/browse/-/602314
-(In this example, the browse ID = 60231
-
-=back
-
-Please be aware that some nodes cannot be used with a
-BrowseNodeSearch. (The vast majority of them can, but you
-may run across a few that simply will not work). It is also
-important to point out that from time to time, some browse
-nodes are deprecated or are changed without notice.
-
-The catalog to search in is specified in the C<mode> parameter,
-typical values are C<books>, C<music>, C<classical> or C<electronics>.
-
-An optional C<keywords> parameter may be added to filter the results by that keyword.
-
-Upon success, the responses' C<properties()> method will return a list of
-C<Net::Amazon::Properties::*> objects.
-
-=head2 METHODS
-
-=over 4
-
-=item new( browsenode => $nodeID, mode => $mode [, keywords => $keywords] )
-
-Constructs a new C<Net::Amazon::Request::BrowseNode> object, used to query
-the Amazon web service for items in a particular category (node) in the
-mode (catalog) specified.
-
-=back
-
-Check L<Net::Amazon::Request> for common request parameters not listed here.
-
-=head1 AUTHOR
-
-Net::Amazon framework by Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-BrowseNode.pm by Jackie Hamilton, E<lt>kira@cgi101.comE<gt>
-
-=head1 LICENSE
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/Net/Amazon/Request/Exchange.pm b/lib/Net/Amazon/Request/Exchange.pm
deleted file mode 100644
index df75549..0000000
--- a/lib/Net/Amazon/Request/Exchange.pm
+++ /dev/null
@@ -1,91 +0,0 @@
-######################################################################
-package Net::Amazon::Request::Exchange;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Request);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- if(exists $options{exchange}) {
- $options{ExchangeSearch} = $options{exchange};
- delete $options{exchange};
- $options{type} = "lite";
- $options{mode} = "";
- } else {
- die "Mandatory parameter 'exchange' not defined";
- }
-
-# if(!exists $options{exchange}) {
-# die "Mandatory parameter 'exchange' not defined";
-# }
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Request::Exchange - Class for submitting Exchange requests
-
-=head1 SYNOPSIS
-
- use Net::Amazon;
- use Net::Amazon::Request::Exchange;
-
- my $ua = Net::Amazon->new(
- token => 'YOUR_AMZN_TOKEN'
- );
-
- my $req = Net::Amazon::Request::Exchange->new(
- exchange => 'Y04Y3424291Y2398445'
- );
-
- # Response is of type Net::Amazon::Response::Seller
- my $resp = $ua->request($req);
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Request::Exchange> is a class used to submit Exchange search
-requests to the Amazon web service. Exchange requests send an item's
-exchange ID and retrieve a description of the item, offered by a third
-party seller on Amazon.
-
-Upon success, the responses' C<result()> method will return a single
-C<Net::Amazon::Result::Seller::Listing> object.
-
-Check L<Net::Amazon::Request> for common request parameters not listed here.
-
-=head2 METHODS
-
-=over 4
-
-=item new( exchange => $exchange_id )
-
-Constructs a new C<Net::Amazon::Request::Exchange> object, used to query
-the Amazon web service with the given seller id.
-
-=back
-
-=head1 SEE ALSO
-
-=head1 AUTHOR
-
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2005 by Mike Schilli E<lt>m@perlmeister.comE<gt>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/Net/Amazon/Request/Keyword.pm b/lib/Net/Amazon/Request/Keyword.pm
deleted file mode 100644
index 0b15d1d..0000000
--- a/lib/Net/Amazon/Request/Keyword.pm
+++ /dev/null
@@ -1,90 +0,0 @@
-######################################################################
-package Net::Amazon::Request::Keyword;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Request);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- $class->_assert_options_defined(\%options,
- qw(keyword mode));
-
- $class->_convert_option(\%options,
- 'keyword',
- 'KeywordSearch');
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Request::Keyword - request class for keyword search
-
-=head1 SYNOPSIS
-
- use Net::Amazon;
- use Net::Amazon::Request::Keyword;
-
- my $ua = Net::Amazon->new(
- token => 'YOUR_AMZN_TOKEN'
- );
-
- my $req = Net::Amazon::Request::Keyword->new(
- keyword => 'Zwan',
- mode => 'books'
- );
-
- # Response is of type Net::Amazon::Response::Keyword
- my $resp = $ua->request($req);
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Request::Keyword> is a class used to submit keyword search
-requests to the Amazon web service.
-
-The keyword to search for is specified in the C<keyword> parameter.
-
-The catalog to search in is specified in the C<mode> parameter,
-typical values are C<books>, C<music>, C<classical> or C<electronics>.
-
-Upon success, the responses' C<properties()> method will return a list of
-C<Net::Amazon::Property::*> objects.
-
-=head2 METHODS
-
-=over 4
-
-=item new( keyword => $keyword, mode => $mode )
-
-Constructs a new C<Net::Amazon::Request::Keyword> object, used to query
-the Amazon web service for items matching a given keyword in the
-mode (catalog) specified.
-
-=back
-
-Check L<Net::Amazon::Request> for common request parameters not listed here.
-
-=head1 SEE ALSO
-
-=head1 AUTHOR
-
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/Net/Amazon/Request/Manufacturer.pm b/lib/Net/Amazon/Request/Manufacturer.pm
deleted file mode 100644
index 0e8adb8..0000000
--- a/lib/Net/Amazon/Request/Manufacturer.pm
+++ /dev/null
@@ -1,78 +0,0 @@
-######################################
-package Net::Amazon::Request::Manufacturer;
-######################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Request);
-
-######################################
-sub new {
-######################################
- my($class, %options) = @_;
-
- $class->_assert_options_defined(\%options,
- 'manufacturer');
-
- $class->_convert_option(\%options,
- 'manufacturer',
- 'ManufacturerSearch');
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Request::Manufacturer - Class for submitting Manufacturer requests
-
-=head1 SYNOPSIS
-
- use Net::Amazon;
- use Net::Amazon::Request::Manufacturer;
-
- my $ua = Net::Amazon->new(
- token => 'YOUR_AMZN_TOKEN'
- );
-
- my $req = Net::Amazon::Request::Manufacturer->new(
- manufacturer => 'Disney'
- );
-
- # Response is of type Net::Amazon::Response::Manufacturer
- my $resp = $ua->request($req);
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Request::Manufacturer> is a class used to submit
-searches for items made by a given manufacturer.
-
-The manufacturer to search for is specified in the C<manufacturer> parameter.
-
-Upon success, the responses' C<properties()> method will return one
-or more C<Net::Amazon::Property::*> objects.
-
-=head2 METHODS
-
-=over 4
-
-=item new( manufacturer => $manufacturer )
-
-Constructs a new C<Net::Amazon::Request::Manufacturer> object, used to query
-the Amazon web service for an item with the specified manufacturer name.
-
-=back
-
-Check L<Net::Amazon::Request> for common request parameters not listed here.
-
-=head1 SEE ALSO
-
-=head1 AUTHORS
-
-Bill Fitzpatrick
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=cut
diff --git a/lib/Net/Amazon/Request/Power.pm b/lib/Net/Amazon/Request/Power.pm
deleted file mode 100644
index fdfd74e..0000000
--- a/lib/Net/Amazon/Request/Power.pm
+++ /dev/null
@@ -1,95 +0,0 @@
-######################################################################
-package Net::Amazon::Request::Power;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Request);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- $class->_assert_options_defined(\%options,
- qw(power mode));
-
- $class->_convert_option(\%options,
- 'power',
- 'PowerSearch');
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Request::Power - request class for 'Power Search'
-
-=head1 SYNOPSIS
-
- use Net::Amazon;
- use Net::Amazon::Request::Power;
-
- my $ua = Net::Amazon->new(
- token => 'YOUR_AMZN_TOKEN'
- );
-
- my $req = Net::Amazon::Request::Power->new(
- power => 'subject: perl and author: schwartz',
- mode => 'books',
- );
-
- # Response is of type Net::Amazon::Response::Power
- my $resp = $ua->request($req);
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Request::Power> is a class used to request
-so-called I<Power Searches> from the Amazon web service.
-
-The C<power> parameter specifies the power search string, C<mode>
-defines which properties to look for.
-
-Upon success, the response's C<properties()> method will return a list
-of C<Net::Amazon::Property::*> objects.
-
-=head2 METHODS
-
-=over 4
-
-=item new(power => $search_string, mode => $property)
-
-Constructs a new C<Net::Amazon::Request::Power> object. C<$property>
-is typically C<"books">. Examples for C<$search_string> are:
-
- author: schwartz
-
- author: schwartz and pubdate: after 10-2002
-
- subject: perl and (objects or object-oriented)
-
- keywords: "high tech*" and not fiction and pubdate: during 1999
-
- power "author: randal schwartz and publisher: Addison Wesley"
-
- author: randal schwartz and title: object books
-
-See the "Amazon Web Services 2.1 API and Integration Guide" for details.
-
-=back
-
-Check L<Net::Amazon::Request> for common request parameters not listed here.
-
-=head1 SEE ALSO
-
-=head1 AUTHORS
-
-Martin Streicher, E<lt>martin.streicher@apress.comE<gt>
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=cut
diff --git a/lib/Net/Amazon/Request/Seller.pm b/lib/Net/Amazon/Request/Seller.pm
deleted file mode 100644
index 54e1930..0000000
--- a/lib/Net/Amazon/Request/Seller.pm
+++ /dev/null
@@ -1,84 +0,0 @@
-######################################################################
-package Net::Amazon::Request::Seller;
-######################################################################
-use base qw(Net::Amazon::Request);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- if(exists $options{seller}) {
- $options{SellerSearch} = $options{seller};
- delete $options{seller};
- } else {
- die "Mandatory parameter 'seller' not defined";
- }
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Request::Seller - Class for submitting Seller requests
-
-=head1 SYNOPSIS
-
- use Net::Amazon;
- use Net::Amazon::Request::Seller;
-
- my $ua = Net::Amazon->new(
- token => 'YOUR_AMZN_TOKEN'
- );
-
- my $req = Net::Amazon::Request::Seller->new(
- seller => 'A2GXAGU54VOP7'
- );
-
- # Response is of type Net::Amazon::Response::Seller
- my $resp = $ua->request($req);
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Request::Seller> is a class used to submit Seller search
-requests to the Amazon web service.
-
-The seller to search for is specified in the C<seller> parameter, which
-contains the seller's ID (not the seller's nickname!).
-
-Upon success, the responses' C<result()> method will return a single
-C<Net::Amazon::Result::Seller> object.
-
-Check L<Net::Amazon::Request> for common request parameters not listed here.
-
-=head2 METHODS
-
-=over 4
-
-=item new( seller => $seller_id )
-
-Constructs a new C<Net::Amazon::Request::Seller> object, used to query
-the Amazon web service with the given seller id.
-
-=back
-
-=head1 SEE ALSO
-
-=head1 AUTHOR
-
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2004 by Mike Schilli E<lt>m@perlmeister.comE<gt>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/Net/Amazon/Request/Similar.pm b/lib/Net/Amazon/Request/Similar.pm
deleted file mode 100644
index c5b5a53..0000000
--- a/lib/Net/Amazon/Request/Similar.pm
+++ /dev/null
@@ -1,95 +0,0 @@
-######################################################################
-package Net::Amazon::Request::Similar;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Request);
-
-our $AMZN_XML_URL = "http://xml.amazon.com/onca/xml3";
-
-##################################################
-sub amzn_xml_url {
-##################################################
- return $AMZN_XML_URL;
-}
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- # For backwards compatibility
- $class->_convert_option(\%options, 'asin', 'similar');
-
- $class->_assert_options_defined(\%options, 'similar');
-
- $class->_convert_option(\%options,
- 'similar',
- 'SimilaritySearch');
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Request::Similar - request class for 'Similarities Search'
-
-=head1 SYNOPSIS
-
- use Net::Amazon;
- use Net::Amazon::Request::Similar;
-
- my $ua = Net::Amazon->new(
- token => 'YOUR_AMZN_TOKEN'
- );
-
- my $req = Net::Amazon::Request::Similar->new(
- similar => 'B00005B6TL',
- );
-
- # Response is of type Net::Amazon::Response::Similar
- my $resp = $ua->request($req);
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Request::Similar> is a class used to request
-so-called I<Similarities Searches> from the Amazon web service.
-
-The C<asin> parameter specifies the ASIN of the item which you want
-to get similar items for.
-
-Upon success, the response's C<properties()> method will return a list
-of C<Net::Amazon::Property::*> objects.
-
-=head2 METHODS
-
-=over 4
-
-=item new(similar => $asin)
-
-Constructs a new C<Net::Amazon::Request::Similar> object.
-
-=back
-
-Check L<Net::Amazon::Request> for common request parameters not listed here.
-
-=head1 SEE ALSO
-
-=head1 AUTHOR
-
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/Net/Amazon/Request/Sort.pm b/lib/Net/Amazon/Request/Sort.pm
deleted file mode 100644
index 059845d..0000000
--- a/lib/Net/Amazon/Request/Sort.pm
+++ /dev/null
@@ -1,246 +0,0 @@
-=pod
-
-=head1 SORT TYPES
-
-Search results can be sorted in various ways, depending on the type of
-product returned by the search. If a sort parameter isn't specified in
-the request, the results will be ordered as if the +salesrank value is
-specified.
-
-=head2 Sorting Books Results
-
- +---------------------------------------------------+
- | Sort Type | Value |
- |-------------------------+-------------------------+
- | Featured Items | +pmrank |
- |-------------------------+-------------------------+
- | Bestselling | +salesrank |
- |-------------------------+-------------------------+
- | Average Customer Review | +reviewrank |
- |-------------------------+-------------------------+
- | Price (Low to High) | +pricerank |
- |-------------------------+-------------------------+
- | Price (High to Low) | +inverse-pricerank |
- |-------------------------+-------------------------+
- | Publication Date | +daterank |
- |-------------------------+-------------------------+
- | Alphabetical (A-Z) | +titlerank |
- |-------------------------+-------------------------+
- | Alphabetical (Z-A) | -titlerank |
- +---------------------------------------------------+
-
-=head2 Sorting Software Results
-
- +---------------------------------------------------+
- | Sort Type | Value |
- |-------------------------+-------------------------+
- | Featured items | +pmrank |
- |-------------------------+-------------------------+
- | Bestselling | +salesrank |
- |-------------------------+-------------------------+
- | Alphabetical | +titlerank |
- |-------------------------+-------------------------+
- | Price (High to Low) | +price |
- |-------------------------+-------------------------+
- | Price (Low to High) | -price |
- +---------------------------------------------------+
-
-=head2 Sorting Outdoor Living Results
-
- +---------------------------------------------------+
- | Sort Type | Value |
- |-------------------------+-------------------------+
- | Featured Items | +psrank |
- |-------------------------+-------------------------+
- | Bestselling | +salesrank |
- |-------------------------+-------------------------+
- | Alphabetical (A-Z) | +titlerank |
- |-------------------------+-------------------------+
- | Alphabetical (Z-A) | -titlerank |
- |-------------------------+-------------------------+
- | Manufacturer (A-Z) | +manufactrank |
- |-------------------------+-------------------------+
- | Manufacturer (Z-A) | -manufactrank |
- |-------------------------+-------------------------+
- | Price (Low to High) | +price |
- |-------------------------+-------------------------+
- | Price (High to Low) | -price |
- +---------------------------------------------------+
-
-=head2 Sorting Tools Results
-
- +---------------------------------------------------+
- | Sort Type | Value |
- |-------------------------+-------------------------+
- | Featured Items | +psrank |
- |-------------------------+-------------------------+
- | Bestselling | +salesrank |
- |-------------------------+-------------------------+
- | Alphabetical (A-Z) | +titlerank |
- |-------------------------+-------------------------+
- | Alphabetical (Z-A) | -titlerank |
- |-------------------------+-------------------------+
- | Manufacturer (A-Z) | +manufactrank |
- |-------------------------+-------------------------+
- | Manufacturer (Z-A) | -manufactrank |
- |-------------------------+-------------------------+
- | Price (Low to High) | +price |
- |-------------------------+-------------------------+
- | Price (High to Low) | -price |
- +---------------------------------------------------+
-
-=head2 Sorting Camera and Photo Results
-
- +---------------------------------------------------+
- | Sort Type | Value |
- |-------------------------+-------------------------+
- | Featured Items | +pmrank |
- |-------------------------+-------------------------+
- | Bestselling | +salesrank |
- |-------------------------+-------------------------+
- | Alphabetical (A-Z) | +titlerank |
- |-------------------------+-------------------------+
- | Alphabetical (Z-A) | -titlerank |
- +---------------------------------------------------+
-
-=head2 Sorting Computers Results
-
- +---------------------------------------------------+
- | Sort Type | Value |
- |-------------------------+-------------------------+
- | Featured Items | +psrank |
- |-------------------------+-------------------------+
- | Bestselling | +salesrank |
- |-------------------------+-------------------------+
- | Alphabetical (A-Z) | +titlerank |
- |-------------------------+-------------------------+
- | Alphabetical (Z-A) | -titlerank |
- +---------------------------------------------------+
-
-=head2 Sorting Video Games Results
-
- +---------------------------------------------------+
- | Sort Type | Value |
- |-------------------------+-------------------------+
- | Featured Items | +pmrank |
- |-------------------------+-------------------------+
- | Bestselling | +salesrank |
- |-------------------------+-------------------------+
- | Alphabetical | +titlerank |
- |-------------------------+-------------------------+
- | Price (Low to High) | +price |
- |-------------------------+-------------------------+
- | Price (High to Low) | -price |
- +---------------------------------------------------+
-
-=head2 Sorting Music Results
-
- +---------------------------------------------------+
- | Sort Type | Value |
- |-------------------------+-------------------------+
- | Featured Items | +psrank |
- |-------------------------+-------------------------+
- | Bestselling | +salesrank |
- |-------------------------+-------------------------+
- | Artist Name | +artistrank |
- |-------------------------+-------------------------+
- | Original Release Date | +orig-rel-date |
- |-------------------------+-------------------------+
- | Alphabetical | +titlerank |
- +---------------------------------------------------+
-
-=head2 Sorting Office Products Results
-
- +---------------------------------------------------+
- | Sort Type | Value |
- |-------------------------+-------------------------+
- | Featured Items | +pmrank |
- |-------------------------+-------------------------+
- | Bestselling | +salesrank |
- |-------------------------+-------------------------+
- | Alphabetical (A-Z) | +titlerank |
- |-------------------------+-------------------------+
- | Alphabetical (Z-A) | -titlerank |
- |-------------------------+-------------------------+
- | Price (Low to High) | +price |
- |-------------------------+-------------------------+
- | Price (High to Low) | -price |
- |-------------------------+-------------------------+
- | Review | +reviewrank |
- +---------------------------------------------------+
-
-=head2 Sorting Video Results
-
- +---------------------------------------------------+
- | Sort Type | Value |
- |-------------------------+-------------------------+
- | Featured Items | +psrank |
- |-------------------------+-------------------------+
- | Bestselling | +salesrank |
- |-------------------------+-------------------------+
- | Alphabetical | +titlerank |
- +---------------------------------------------------+
-
-=head2 Sorting Electronics Results
-
- +---------------------------------------------------+
- | Type | Value |
- |-------------------------+-------------------------+
- | Featured Items | +pmrank |
- |-------------------------+-------------------------+
- | Bestselling | +salesrank |
- |-------------------------+-------------------------+
- | Alphabetical | +titlerank |
- |-------------------------+-------------------------+
- | Review | +reviewrank |
- +---------------------------------------------------+
-
-=head2 Sorting DVDs Results
-
- +---------------------------------------------------+
- | Type | Value |
- |-------------------------+-------------------------+
- | Bestselling | +salesrank |
- |-------------------------+-------------------------+
- | Alphabetical | +titlerank |
- +---------------------------------------------------+
-
-=head2 Sorting Kitchen Results
-
- +---------------------------------------------------+
- | Type | Value |
- |-------------------------+-------------------------+
- | Featured Items | +pmrank |
- |-------------------------+-------------------------+
- | Bestselling | +salesrank |
- |-------------------------+-------------------------+
- | Alphabetical (A-Z) | +titlerank |
- |-------------------------+-------------------------+
- | Alphabetical (Z-A) | -titlerank |
- |-------------------------+-------------------------+
- | Manufacturer (A-Z) | +manufactrank |
- |-------------------------+-------------------------+
- | Manufacturer (Z-A) | -manufactrank |
- |-------------------------+-------------------------+
- | Price (Low to High) | +price |
- |-------------------------+-------------------------+
- | Price (High to Low) | -price |
- +---------------------------------------------------+
-
-=head2 Sorting Toys Results
-
- +---------------------------------------------------+
- | Type | Value |
- |-------------------------+-------------------------+
- | Featured Items | +pmrank |
- |-------------------------+-------------------------+
- | Bestselling | +salesrank |
- |-------------------------+-------------------------+
- | Price (Low to High) | +pricerank |
- |-------------------------+-------------------------+
- | Price (High to Low) | +inverse-pricerank |
- |-------------------------+-------------------------+
- | Alphabetical (A-Z) | +titlerank |
- +---------------------------------------------------+
-
-=cut
diff --git a/lib/Net/Amazon/Request/TextStream.pm b/lib/Net/Amazon/Request/TextStream.pm
deleted file mode 100644
index 62a0717..0000000
--- a/lib/Net/Amazon/Request/TextStream.pm
+++ /dev/null
@@ -1,76 +0,0 @@
-######################################################################
-package Net::Amazon::Request::TextStream;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Request);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- $class->_assert_options_defined(\%options,
- 'textstream');
-
- $class->_convert_option(\%options,
- 'textstream',
- 'TextStreamSearch');
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Request::TextStream - request class for text stream search
-
-=head1 SYNOPSIS
-
- use Net::Amazon;
- use Net::Amazon::Request::TextStream;
-
- my $ua = Net::Amazon->new(
- token => 'YOUR_AMZN_TOKEN'
- );
-
- my $req = Net::Amazon::Request::TextStream->new(
- textstream => 'Here is some text that mentions the Rolling Stones.',
- );
-
- # Response is of type Net::Amazon::Response::TextStream
- my $resp = $ua->request($req);
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Request::TextStream> is a class used to perform a search on
-a block of text. Amazon extracts keywords from the given block of text,
-but note that conjunctions and helper words, such as "and", "or", "the",
-etc. are not excluded, so strip them out yourself if need be.
-
-TextStream searching is only available for the US service.
-
-Upon success, the response's C<properties()> method will return a list
-of C<Net::Amazon::Property::*> objects.
-
-=head2 METHODS
-
-=over 4
-
-=item new(textstream => $text)
-
-Constructs a new C<Net::Amazon::Request::TextStream> object, used to query
-the Amazon web service with a block of text.
-
-=back
-
-Check L<Net::Amazon::Request> for common request parameters not listed here.
-
-=head1 SEE ALSO
-
-=cut
diff --git a/lib/Net/Amazon/Request/UPC.pm b/lib/Net/Amazon/Request/UPC.pm
deleted file mode 100644
index ae77645..0000000
--- a/lib/Net/Amazon/Request/UPC.pm
+++ /dev/null
@@ -1,94 +0,0 @@
-######################################################################
-package Net::Amazon::Request::UPC;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Request);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- $class->_assert_options_defined(\%options, 'upc');
-
- $class->_convert_option(\%options,
- 'upc',
- 'UpcSearch');
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Request::UPC - request class for UPC search
-
-=head1 SYNOPSIS
-
- use Net::Amazon;
- use Net::Amazon::Request::UPC;
-
- my $ua = Net::Amazon->new(
- token => 'YOUR_AMZN_TOKEN'
- );
-
- my $req = Net::Amazon::Request::UPC->new(
- upc => '724381198421',
- mode => 'music',
-
- );
-
- # Response is of type Net::Amazon::Response::UPC
- my $resp = $ua->request($req);
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Request::UPC> is a class used to submit UPC (product barcode)
-search requests to the Amazon web service.
-
-The UPC number to search for is specified in the C<upc> parameter.
-It currently works with the following values of the C<mode> parameter:
-C<music>,
-C<classical>,
-C<software>,
-C<dvd>,
-C<video>,
-C<vhs>,
-C<electronics>,
-C<pc-hardware>, and
-C<photo>.
-
-Upon success, the response's C<properties()> method will return a single
-C<Net::Amazon::Property::Music> object.
-
-=head2 METHODS
-
-=over 4
-
-=item new(upc => $upc)
-
-Constructs a new C<Net::Amazon::Request::UPC> object, used to query
-the Amazon web service for an item with the given UPC number.
-
-=back
-
-=head1 SEE ALSO
-
-=head1 AUTHOR
-
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/Net/Amazon/Request/Wishlist.pm b/lib/Net/Amazon/Request/Wishlist.pm
deleted file mode 100644
index 824d5d4..0000000
--- a/lib/Net/Amazon/Request/Wishlist.pm
+++ /dev/null
@@ -1,89 +0,0 @@
-######################################################################
-package Net::Amazon::Request::Wishlist;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Request);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- # For backwards compatibility:
- $class->_convert_option(\%options, 'id', 'wishlist');
-
- $class->_assert_options_defined(\%options, 'wishlist');
-
- $class->_convert_option(\%options,
- 'wishlist',
- 'WishlistSearch');
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Request::Wishlist - request class for wishlist search
-
-=head1 SYNOPSIS
-
- use Net::Amazon;
- use Net::Amazon::Request::Wishlist;
-
- my $ua = Net::Amazon->new(
- token => 'YOUR_AMZN_TOKEN'
- );
-
- my $req = Net::Amazon::Request::Wishlist->new(
- wishlist => '1XL5DWOUFMFVJ',
- );
-
- # Response is of type Net::Amazon::Response::Wishlist
- my $resp = $ua->request($req);
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Request::Wishlist> is a class used to request
-a specified wishlist.
-
-The wishlist ID (can be found as parameters in URLs when a customer's
-Amazon wishlist is being pulled up) is specified in the C<id> parameter.
-
-Upon success, the response's C<properties()> method will return a list
-of C<Net::Amazon::Property::*> objects.
-
-=head2 METHODS
-
-=over 4
-
-=item new(wishlist => $id)
-
-Constructs a new C<Net::Amazon::Request::Wishlist> object, used to query
-the Amazon web service for a specific wishlist, identified by the wishlist
-ID.
-
-=back
-
-Check L<Net::Amazon::Request> for common request parameters not listed here.
-
-=head1 SEE ALSO
-
-=head1 AUTHOR
-
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/Net/Amazon/Response.pm b/lib/Net/Amazon/Response.pm
deleted file mode 100644
index 6147e0e..0000000
--- a/lib/Net/Amazon/Response.pm
+++ /dev/null
@@ -1,214 +0,0 @@
-######################################################################
-package Net::Amazon::Response;
-######################################################################
-use warnings;
-use strict;
-
-use base qw(Net::Amazon);
-
-use Text::Wrap qw($columns wrap);
-use XML::Simple;
-
-our @FORCE_ARRAY_FIELDS = ();
-
-__PACKAGE__->make_accessor($_) for qw(
- status messages items xmlref total_results);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- my $self = {
- status => "",
- messages => [],
- items => [],
- xmlref => {},
- total_results => undef,
- };
-
- bless $self, $class;
-}
-
-sub message {
- my($self) = @_;
-
- return join(";",@{$self->{messages}});
-}
-
-###########################################
-sub is_success {
-###########################################
- my($self) = @_;
-
- return $self->{status} ? 1 : "";
-}
-
-###########################################
-sub is_error {
-###########################################
- my($self) = @_;
-
- return !$self->is_success();
-}
-
-###########################################
-sub push_item {
-###########################################
- my($self, $item) = @_;
-
- push @{$self->{items}}, $item;
-}
-
-###########################################
-sub as_string {
-###########################################
- my($self) = @_;
-
- return Data::Dumper::Dumper($self);
-}
-
-###########################################
-sub list_as_string {
-###########################################
- my($self, @properties) = @_;
-
- my $full = "";
-
- # Column with
- $columns = 60;
- my $bullet = 1;
-
- foreach my $property (@properties) {
- $full .= "\n" if $full;
- my $bullet_string = sprintf("[%d]%s",
- $bullet, (" " x (3-length($bullet))));
- $full .= wrap("", " ", $bullet_string . $property->as_string());
- $bullet++;
- }
-
- return $full;
-}
-
-##################################################
-sub properties {
-##################################################
- my($self) = @_;
-
- my @properties = ();
-
- if($self->is_success && ref($self->{xmlref}->{Details}) eq 'ARRAY') {
- foreach my $xmlref (@{$self->{xmlref}->{Details}}) {
- my $property = Net::Amazon::Property::factory(xmlref => $xmlref);
- push @properties, $property;
- }
- }
-
- if(wantarray) {
- return (@properties);
- }
-
- if(@properties) {
- # Scalar context and we've got results. Return the first one.
- return $properties[0];
- }
-
- # Scalar context and we don't have anything.
- return undef;
-}
-
-##################################################
-sub xml_parse {
-##################################################
- my($self, $xml) = @_;
-
- my $xs = XML::Simple->new();
- return $xs->XMLin($xml, ForceArray => [ @FORCE_ARRAY_FIELDS ]);
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Response - Baseclass for responses from Amazon's web service
-
-=head1 SYNOPSIS
-
- $resp = $ua->request($request);
-
- if($resp->is_success()) {
- print $resp->as_string();
- }
-
- if($resp->is_error()) {
- print $resp->message();
- }
-
- if($resp->is_success()) {
- for my $property ($resp->properties) {
- print $property->as_string(), "\n";
- }
- }
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Response> is the baseclass for responses coming back
-from the useragent's C<request> method. Responses are typically
-not of type C<Net::Amazon::Response> but one of its subclasses
-C<Net::Amazon::Response::*>. However, for basic error handling and
-dumping content, C<Net::Amazon::Response>'s methods are typically used,
-because we typically don't know what type of object we're
-actually dealing with.
-
-=head2 METHODS
-
-=over 4
-
-=item is_success()
-
-Returns true if the request was successful. This doesn't mean any objects
-have been found, it just indicates a successful roundtrip.
-
-=item is_error()
-
-Returns true if an error occurred. Use C<message()> to determine what
-kind of error.
-
-=item properties()
-
-Returns the list of C<Net::Amazon::Property> objects which were found
-by the query.
-
-=item as_string()
-
-Dumps the content of the response.
-
-=item message()
-
-Returns the error message as a string in case an error occurred. In case
-several errors occurred, they're stringed together. Look up C<messages()>
-if you need them separated.
-
-=item messages()
-
-Returns all error messages for a response as a reference to an array
-of string messages.
-
-=back
-
-=head1 SEE ALSO
-
-=head1 AUTHOR
-
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2003 by Mike Schilli E<lt>m@perlmeister.comE<gt>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/Net/Amazon/Response/ASIN.pm b/lib/Net/Amazon/Response/ASIN.pm
deleted file mode 100644
index 32bad76..0000000
--- a/lib/Net/Amazon/Response/ASIN.pm
+++ /dev/null
@@ -1,28 +0,0 @@
-######################################################################
-package Net::Amazon::Response::ASIN;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Response);
-
-use Net::Amazon::Property;
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-##################################################
-sub as_string {
-##################################################
- my($self) = @_;
-
- return $self->SUPER::list_as_string($self->properties);
-}
-
-1;
diff --git a/lib/Net/Amazon/Response/Artist.pm b/lib/Net/Amazon/Response/Artist.pm
deleted file mode 100644
index 0ee653b..0000000
--- a/lib/Net/Amazon/Response/Artist.pm
+++ /dev/null
@@ -1,29 +0,0 @@
-######################################################################
-package Net::Amazon::Response::Artist;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Response);
-
-use Net::Amazon::Property;
-use Data::Dumper;
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-##################################################
-sub as_string {
-##################################################
- my($self) = @_;
-
- return $self->SUPER::list_as_string($self->properties);
-}
-
-1;
diff --git a/lib/Net/Amazon/Response/Blended.pm b/lib/Net/Amazon/Response/Blended.pm
deleted file mode 100644
index 3c75ded..0000000
--- a/lib/Net/Amazon/Response/Blended.pm
+++ /dev/null
@@ -1,73 +0,0 @@
-######################################################################
-package Net::Amazon::Response::Blended;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Response);
-
-use Net::Amazon::Property;
-use XML::Simple;
-
-our @FORCE_ARRAY_FIELDS = qw(ProductLine);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-##################################################
-sub as_string {
-##################################################
- my($self) = @_;
-
- return $self->SUPER::list_as_string($self->properties);
-}
-
-##################################################
-sub xmlref_add {
-##################################################
- my($self, $xmlref) = @_;
-
- my $nof_items_added = 0;
-
- unless(ref($self->{xmlref}) eq "HASH" &&
- ref($self->{xmlref}->{Details}) eq "ARRAY") {
- $self->{xmlref}->{Details} = [];
- }
-
- if ($xmlref->{ProductLine} && (ref($xmlref->{ProductLine}) eq "ARRAY")) {
- my @lines = @{$xmlref->{ProductLine}}; # Copy the lines
- # sort the copies by relevance
- @lines = sort { $a->{RelevanceRank} <=> $b->{RelevanceRank} } @lines;
-
- foreach (@lines) {
- next unless $_->{ProductInfo}->{Details};
- my $details = $_->{ProductInfo}->{Details};
- if (ref($details) eq "ARRAY") {
- push @{$self->{xmlref}->{Details}}, @$details;
- $nof_items_added += scalar @$details;
- } else {
- push @{$self->{xmlref}->{Details}}, $details;
- $nof_items_added++;
- }
- }
- }
-
- return $nof_items_added;
-}
-
-##################################################
-sub xml_parse {
-##################################################
- my($self, $xml) = @_;
-
- my $xs = XML::Simple->new();
- return $xs->XMLin($xml, ForceArray => [ @FORCE_ARRAY_FIELDS ]);
-}
-
-1;
diff --git a/lib/Net/Amazon/Response/BrowseNode.pm b/lib/Net/Amazon/Response/BrowseNode.pm
deleted file mode 100644
index 8f40a63..0000000
--- a/lib/Net/Amazon/Response/BrowseNode.pm
+++ /dev/null
@@ -1,29 +0,0 @@
-######################################################################
-package Net::Amazon::Response::BrowseNode;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Response);
-
-use Net::Amazon::Property;
-use Data::Dumper;
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-##################################################
-sub as_string {
-##################################################
- my($self) = @_;
-
- return $self->SUPER::list_as_string($self->properties);
-}
-
-1;
diff --git a/lib/Net/Amazon/Response/Exchange.pm b/lib/Net/Amazon/Response/Exchange.pm
deleted file mode 100644
index 56852fe..0000000
--- a/lib/Net/Amazon/Response/Exchange.pm
+++ /dev/null
@@ -1,81 +0,0 @@
-######################################################################
-package Net::Amazon::Response::Exchange;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Response);
-
-use Net::Amazon::Property;
-use Net::Amazon::Result::Seller::Listing;
-use Log::Log4perl qw(:easy);
-
-__PACKAGE__->make_array_accessor($_) for qw(listings);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-##################################################
-sub result {
-##################################################
- my($self) = @_;
-
- if($self->is_success()) {
- return Net::Amazon::Result::Seller::Listing->new(
- xmlref => $self->{xmlref}->{ListingProductDetails}->[0],
- );
- }
-
- return undef;
-}
-
-##################################################
-sub as_string {
-##################################################
- my($self) = @_;
-
- return "TODO: as_string not defined yet in ", __PACKAGE__;
-}
-
-##################################################
-sub xmlref_add {
-##################################################
- my($self, $xmlref) = @_;
-
- my $nof_items_added = 0;
-
- unless(ref($self->{xmlref}) eq "HASH" &&
- ref($self->{xmlref}->{ListingProductDetails}) eq "ARRAY") {
- $self->{xmlref}->{Details} = [];
- }
-
- if(ref($xmlref->{ListingProductDetails}) eq "ARRAY") {
- # Is it an array of items?
- push @{$self->{xmlref}->{ListingProductDetails}},
- @{$xmlref->{ListingProductDetails}};
- $nof_items_added = scalar @{$xmlref->{ListingProductDetails}};
- } else {
- # It is a single item
- push @{$self->{xmlref}->{ListingProductDetails}},
- $xmlref->{ListingProductDetails};
- $nof_items_added = 1;
- }
-
- return $nof_items_added;
-}
-
-##################################################
-sub properties {
-##################################################
- my($self) = @_;
-
- die "properties() not defined in ", __PACKAGE__, ". Use result() instead";
-}
-
-1;
diff --git a/lib/Net/Amazon/Response/Keyword.pm b/lib/Net/Amazon/Response/Keyword.pm
deleted file mode 100644
index f6277d6..0000000
--- a/lib/Net/Amazon/Response/Keyword.pm
+++ /dev/null
@@ -1,29 +0,0 @@
-######################################################################
-package Net::Amazon::Response::Keyword;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Response);
-
-use Net::Amazon::Property;
-use Data::Dumper;
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-##################################################
-sub as_string {
-##################################################
- my($self) = @_;
-
- return $self->SUPER::list_as_string($self->properties);
-}
-
-1;
diff --git a/lib/Net/Amazon/Response/Manufacturer.pm b/lib/Net/Amazon/Response/Manufacturer.pm
deleted file mode 100644
index 97ceebf..0000000
--- a/lib/Net/Amazon/Response/Manufacturer.pm
+++ /dev/null
@@ -1,29 +0,0 @@
-######################################################################
-package Net::Amazon::Response::Manufacturer;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Response);
-
-use Net::Amazon::Property;
-use Data::Dumper;
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-##################################################
-sub as_string {
-##################################################
- my($self) = @_;
-
- return $self->SUPER::list_as_string($self->properties);
-}
-
-1;
diff --git a/lib/Net/Amazon/Response/Power.pm b/lib/Net/Amazon/Response/Power.pm
deleted file mode 100644
index 88cdd2d..0000000
--- a/lib/Net/Amazon/Response/Power.pm
+++ /dev/null
@@ -1,28 +0,0 @@
-######################################################################
-package Net::Amazon::Response::Power;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Response);
-
-use Net::Amazon::Property;
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-##################################################
-sub as_string {
-##################################################
- my($self) = @_;
-
- return $self->SUPER::list_as_string($self->properties);
-}
-
-1;
diff --git a/lib/Net/Amazon/Response/Seller.pm b/lib/Net/Amazon/Response/Seller.pm
deleted file mode 100644
index f33ed50..0000000
--- a/lib/Net/Amazon/Response/Seller.pm
+++ /dev/null
@@ -1,78 +0,0 @@
-#############################################
-package Net::Amazon::Response::Seller;
-#############################################
-use base qw(Net::Amazon::Response);
-
-use Net::Amazon::Result::Seller;
-use Data::Dumper;
-use Log::Log4perl qw(:easy);
-
-##############################
-sub new {
-##############################
- my($class, %options) = @_;
-
- my $self = $class->SUPER::new(%options);
- bless $self, $class; # reconsecrate
-}
-
-##################################################
-sub result {
-##################################################
- my($self) = @_;
-
- if($self->is_success()) {
- DEBUG "Calling Seller constructor with ", Dumper($self);
- return Net::Amazon::Result::Seller->new(
- xmlref => $self->{xmlref}->{SellerSearchDetails}->[0],
- );
- }
-
- return undef;
-}
-
-##################################################
-sub properties {
-##################################################
- my($self) = @_;
-
- die "properties() not defined in ", __PACKAGE__, ". Use result() instead";
-}
-
-##################################################
-sub as_string {
-##################################################
- my($self) = @_;
-
- return $self->result()->as_string();
-}
-
-##################################################
-sub xmlref_add {
-##################################################
- my($self, $xmlref) = @_;
-
- my $nof_items_added = 0;
-
- unless(ref($self->{xmlref}) eq "HASH" &&
- ref($self->{xmlref}->{SellerSearchDetails}) eq "ARRAY") {
- $self->{xmlref}->{Details} = [];
- }
-
- if(ref($xmlref->{SellerSearchDetails}) eq "ARRAY") {
- # Is it an array of items?
- push @{$self->{xmlref}->{SellerSearchDetails}},
- @{$xmlref->{SellerSearchDetails}};
- $nof_items_added = scalar @{$xmlref->{SellerSearchDetails}};
- } else {
- # It is a single item
- push @{$self->{xmlref}->{SellerSearchDetails}},
- $xmlref->{SellerSearchDetails};
- $nof_items_added = 1;
- }
-
- #DEBUG("xmlref_add (after):", Data::Dumper::Dumper($self));
- return $nof_items_added;
-}
-
-1;
diff --git a/lib/Net/Amazon/Response/Similar.pm b/lib/Net/Amazon/Response/Similar.pm
deleted file mode 100644
index 27add88..0000000
--- a/lib/Net/Amazon/Response/Similar.pm
+++ /dev/null
@@ -1,28 +0,0 @@
-######################################################################
-package Net::Amazon::Response::Similar;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Response);
-
-use Net::Amazon::Property;
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-##################################################
-sub as_string {
-##################################################
- my($self) = @_;
-
- return $self->SUPER::list_as_string($self->properties);
-}
-
-1;
diff --git a/lib/Net/Amazon/Response/TextStream.pm b/lib/Net/Amazon/Response/TextStream.pm
deleted file mode 100644
index 0cee872..0000000
--- a/lib/Net/Amazon/Response/TextStream.pm
+++ /dev/null
@@ -1,28 +0,0 @@
-######################################################################
-package Net::Amazon::Response::TextStream;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Response);
-
-use Net::Amazon::Property;
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-##################################################
-sub as_string {
-##################################################
- my($self) = @_;
-
- return $self->SUPER::list_as_string($self->properties);
-}
-
-1;
diff --git a/lib/Net/Amazon/Response/UPC.pm b/lib/Net/Amazon/Response/UPC.pm
deleted file mode 100644
index 4fba4ad..0000000
--- a/lib/Net/Amazon/Response/UPC.pm
+++ /dev/null
@@ -1,40 +0,0 @@
-######################################################################
-package Net::Amazon::Response::UPC;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Response);
-
-use Net::Amazon::Property;
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-##################################################
-sub as_string {
-##################################################
- my($self) = @_;
-
- my($property) = $self->properties;
- return $property->as_string();
-}
-
-##################################################
-sub properties {
-##################################################
- my($self) = @_;
-
- my $property = Net::Amazon::Property::factory(
- xmlref => $self->{xmlref}->{Details}->[0]);
-
- return ($property);
-}
-
-1;
diff --git a/lib/Net/Amazon/Response/Wishlist.pm b/lib/Net/Amazon/Response/Wishlist.pm
deleted file mode 100644
index 15fd999..0000000
--- a/lib/Net/Amazon/Response/Wishlist.pm
+++ /dev/null
@@ -1,29 +0,0 @@
-######################################################################
-package Net::Amazon::Response::Wishlist;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon::Response);
-
-use Net::Amazon::Property;
-use Data::Dumper;
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- my $self = $class->SUPER::new(%options);
-
- bless $self, $class; # reconsecrate
-}
-
-##################################################
-sub as_string {
-##################################################
- my($self) = @_;
-
- return $self->SUPER::list_as_string($self->properties);
-}
-
-1;
diff --git a/lib/Net/Amazon/Result/Seller.pm b/lib/Net/Amazon/Result/Seller.pm
deleted file mode 100644
index cb876a6..0000000
--- a/lib/Net/Amazon/Result/Seller.pm
+++ /dev/null
@@ -1,130 +0,0 @@
-######################################################################
-package Net::Amazon::Result::Seller;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon);
-
-use Data::Dumper;
-use Log::Log4perl qw(:easy);
-use Net::Amazon::Result::Seller::Listing;
-
-our @DEFAULT_ATTRIBUTES = qw(StoreName SellerNickname
- NumberOfOpenListings StoreId);
-__PACKAGE__->make_accessor($_) for @DEFAULT_ATTRIBUTES;
-__PACKAGE__->make_array_accessor($_) for qw(listings);
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- if(!$options{xmlref}) {
- die "Mandatory param xmlref missing";
- }
-
- my @listings = ();
-
- my $self = {
- %options,
- };
-
- bless $self, $class;
-
- # Set default attributes
- for my $attr (@DEFAULT_ATTRIBUTES) {
- DEBUG "Setting attribute $attr to $options{xmlref}->{$attr}";
- $self->$attr($options{xmlref}->{$attr});
- }
-
- for my $listing (@{$options{xmlref}->{ListingProductInfo}->{ListingProductDetails}}) {
- push @listings,
- Net::Amazon::Result::Seller::Listing->new(
- xmlref => $listing);
- }
-
- $self->listings(\@listings);
-
- return $self;
-}
-
-##################################################
-sub as_string {
-##################################################
- my($self) = @_;
-
- my $result = $self->StoreName() .
- " (" .
- $self->SellerNickname() .
- "): " .
- $self->NumberOfOpenListings() .
- "";
-
- return $result;
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Result::Seller - Class for Seller info
-
-=head1 SYNOPSIS
-
- use Net::Amazon;
-
- # ...
-
- if($resp->is_success()) {
- print $resp->result()->as_string();
- }
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Result::Seller> is a container for results on a seller
-search. It contains data on one particular seller (the one turned up by
-the previous search) and the listings this seller is currently running.
-
-=head2 METHODS
-
-=over 4
-
-=item StoreName()
-
-Name of the seller's store.
-
-=item SellerNickname()
-
-Seller's nickname.
-
-=item StoreId()
-
-ID of seller's store.
-
-=item NumberOfOpenListings()
-
-Number of listings the seller has currently open.
-
-=item listings()
-
-Returns an array of C<Net::Amazon::Result::Seller::Listing> objects.
-See the documentation of this class for details.
-
-=back
-
-=head1 SEE ALSO
-
-=head1 AUTHOR
-
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2004 by Mike Schilli E<lt>m@perlmeister.comE<gt>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/Net/Amazon/Result/Seller/Listing.pm b/lib/Net/Amazon/Result/Seller/Listing.pm
deleted file mode 100644
index c09ec08..0000000
--- a/lib/Net/Amazon/Result/Seller/Listing.pm
+++ /dev/null
@@ -1,146 +0,0 @@
-######################################################################
-package Net::Amazon::Result::Seller::Listing;
-######################################################################
-use warnings;
-use strict;
-use base qw(Net::Amazon);
-
-use Data::Dumper;
-use Log::Log4perl qw(:easy);
-
-our @DEFAULT_ATTRIBUTES = qw(
- ExchangeStartDate ExchangeConditionType
- ExchangeAsin ExchangeSellerId ExchangeEndDate ExchangePrice
- ExchangeSellerRating ExchangeStatus ExchangeId ExchangeTitle
- ExchangeQuantityAllocated ExchangeQuantity ExchangeSellerCountry
- ExchangeSellerState ExchangeSellerNickname ExchangeFeaturedCategory
- ExchangeAvailability ExchangeOfferingType ListingId ExchangeCondition
- ExchangeDescription
-);
-
-__PACKAGE__->make_accessor($_) for @DEFAULT_ATTRIBUTES;
-
-##################################################
-sub new {
-##################################################
- my($class, %options) = @_;
-
- if(!$options{xmlref}) {
- die "Mandatory param xmlref missing";
- }
-
- my $self = {
- %options,
- };
-
- bless $self, $class;
-
- DEBUG "Calling Listing with xmlref=", Dumper($options{xmlref});
-
- # Set default attributes
- for my $attr (@DEFAULT_ATTRIBUTES) {
- $self->$attr($options{xmlref}->{$attr});
- }
-
- return $self;
-}
-
-##################################################
-sub as_string {
-##################################################
- my($self) = @_;
-
- my $result =
- $self->ExchangeTitle() .
- " (" .
- $self->ExchangeAsin() .
- "): " .
- $self->ExchangePrice() .
- "";
-
- return $result;
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-Net::Amazon::Result::Seller::Listing - Class for a single Listing of a Seller
-
-=head1 SYNOPSIS
-
- for($seller_search_resp->result()->seller()->listings()) {
- print $_->as_string(), "\n";
- }
-
-=head1 DESCRIPTION
-
-C<Net::Amazon::Result::Seller::Listing> is a container for a single listing
-owned by a third-party seller, who is represented by a
-C<Net::Amazon::Result::Seller> object.
-
-An object of this class is also returned by an C<Exchange> request, using
-C<Net::Amazon::Response::Exchange>'s C<result> method.
-
-=head2 METHODS
-
-=over 4
-
-=item ExchangeStartDate()
-
-=item ExchangeConditionType()
-
-=item ExchangeAsin()
-
-=item ExchangeSellerId()
-
-=item ExchangeEndDate()
-
-=item ExchangePrice()
-
-=item ExchangeSellerRating()
-
-=item ExchangeStatus()
-
-=item ExchangeId()
-
-=item ExchangeTitle()
-
-=item ExchangeQuantityAllocated()
-
-=item ExchangeQuantity()
-
-=item ExchangeSellerCountry()
-
-=item ExchangeSellerState()
-
-=item ExchangeSellerNickname()
-
-=item ExchangeFeaturedCategory()
-
-=item ExchangeAvailability()
-
-=item ExchangeOfferingType()
-
-=item ListingId()
-
-=item ExchangeCondition()
-
-=back
-
-=head1 SEE ALSO
-
-=head1 AUTHOR
-
-Mike Schilli, E<lt>m@perlmeister.comE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2004 by Mike Schilli E<lt>m@perlmeister.comE<gt>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/Template.pm b/lib/Template.pm
deleted file mode 100644
index bd56cc5..0000000
--- a/lib/Template.pm
+++ /dev/null
@@ -1,961 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template
-#
-# DESCRIPTION
-# Module implementing a simple, user-oriented front-end to the Template
-# Toolkit.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2002 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.
-#
-# REVISION
-# $Id: Template.pm,v 2.76 2004/01/13 15:27:35 abw Exp $
-#
-#========================================================================
-
-package Template;
-use base qw( Template::Base );
-
-require 5.005;
-
-use strict;
-use vars qw( $VERSION $AUTOLOAD $ERROR $DEBUG $BINMODE );
-use Template::Base;
-use Template::Config;
-use Template::Constants;
-use Template::Provider;
-use Template::Service;
-use File::Basename;
-use File::Path;
-
-## This is the main version number for the Template Toolkit.
-## It is extracted by ExtUtils::MakeMaker and inserted in various places.
-$VERSION = '2.13';
-$ERROR = '';
-$DEBUG = 0;
-
-# we used to default to binary mode for all win32 files but that make
-# line endings strange, so we're turning it off and letting users set
-# it explicitly as an argument to process()
-# $BINMODE = ($^O eq 'MSWin32') ? 1 : 0;
-$BINMODE = 0 unless defined $BINMODE;
-
-# preload all modules if we're running under mod_perl
-Template::Config->preload() if $ENV{ MOD_PERL };
-
-
-#------------------------------------------------------------------------
-# process($input, \%replace, $output)
-#
-# Main entry point for the Template Toolkit. The Template module
-# delegates most of the processing effort to the underlying SERVICE
-# object, an instance of the Template::Service class.
-#------------------------------------------------------------------------
-
-sub process {
- my ($self, $template, $vars, $outstream, @opts) = @_;
- my ($output, $error);
- my $options = (@opts == 1) && UNIVERSAL::isa($opts[0], 'HASH')
- ? shift(@opts) : { @opts };
-
- $options->{ binmode } = $BINMODE
- unless defined $options->{ binmode };
-
- # we're using this for testing in t/output.t and t/filter.t so
- # don't remove it if you don't want tests to fail...
- $self->DEBUG("set binmode\n") if $DEBUG && $options->{ binmode };
-
- $output = $self->{ SERVICE }->process($template, $vars);
-
- if (defined $output) {
- $outstream ||= $self->{ OUTPUT };
- unless (ref $outstream) {
- my $outpath = $self->{ OUTPUT_PATH };
- $outstream = "$outpath/$outstream" if $outpath;
- }
-
- # send processed template to output stream, checking for error
- return ($self->error($error))
- if ($error = &_output($outstream, \$output, $options));
-
- return 1;
- }
- else {
- return $self->error($self->{ SERVICE }->error);
- }
-}
-
-
-#------------------------------------------------------------------------
-# service()
-#
-# Returns a reference to the the internal SERVICE object which handles
-# all requests for this Template object
-#------------------------------------------------------------------------
-
-sub service {
- my $self = shift;
- return $self->{ SERVICE };
-}
-
-
-#------------------------------------------------------------------------
-# context()
-#
-# Returns a reference to the the CONTEXT object withint the SERVICE
-# object.
-#------------------------------------------------------------------------
-
-sub context {
- my $self = shift;
- return $self->{ SERVICE }->{ CONTEXT };
-}
-
-
-#========================================================================
-# -- PRIVATE METHODS --
-#========================================================================
-
-#------------------------------------------------------------------------
-# _init(\%config)
-#------------------------------------------------------------------------
-sub _init {
- my ($self, $config) = @_;
-
- # convert any textual DEBUG args to numerical form
- my $debug = $config->{ DEBUG };
- $config->{ DEBUG } = Template::Constants::debug_flags($self, $debug)
- || return if defined $debug && $debug !~ /^\d+$/;
-
- # prepare a namespace handler for any CONSTANTS definition
- if (my $constants = $config->{ CONSTANTS }) {
- my $ns = $config->{ NAMESPACE } ||= { };
- my $cns = $config->{ CONSTANTS_NAMESPACE } || 'constants';
- $constants = Template::Config->constants($constants)
- || return $self->error(Template::Config->error);
- $ns->{ $cns } = $constants;
- }
-
- $self->{ SERVICE } = $config->{ SERVICE }
- || Template::Config->service($config)
- || return $self->error(Template::Config->error);
-
- $self->{ OUTPUT } = $config->{ OUTPUT } || \*STDOUT;
- $self->{ OUTPUT_PATH } = $config->{ OUTPUT_PATH };
-
- return $self;
-}
-
-
-#------------------------------------------------------------------------
-# _output($where, $text)
-#------------------------------------------------------------------------
-
-sub _output {
- my ($where, $textref, $options) = @_;
- my $reftype;
- my $error = 0;
-
- # call a CODE reference
- if (($reftype = ref($where)) eq 'CODE') {
- &$where($$textref);
- }
- # print to a glob (such as \*STDOUT)
- elsif ($reftype eq 'GLOB') {
- print $where $$textref;
- }
- # append output to a SCALAR ref
- elsif ($reftype eq 'SCALAR') {
- $$where .= $$textref;
- }
- # push onto ARRAY ref
- elsif ($reftype eq 'ARRAY') {
- push @$where, $$textref;
- }
- # call the print() method on an object that implements the method
- # (e.g. IO::Handle, Apache::Request, etc)
- elsif (UNIVERSAL::can($where, 'print')) {
- $where->print($$textref);
- }
- # a simple string is taken as a filename
- elsif (! $reftype) {
- local *FP;
- # make destination directory if it doesn't exist
- my $dir = dirname($where);
- eval { mkpath($dir) unless -d $dir; };
- if ($@) {
- # strip file name and line number from error raised by die()
- ($error = $@) =~ s/ at \S+ line \d+\n?$//;
- }
- elsif (open(FP, ">$where")) {
- binmode FP if $options->{ binmode };
- print FP $$textref;
- close FP;
- }
- else {
- $error = "$where: $!";
- }
- }
- # give up, we've done our best
- else {
- $error = "output_handler() cannot determine target type ($where)\n";
- }
-
- return $error;
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template - Front-end module to the Template Toolkit
-
-=head1 SYNOPSIS
-
- use Template;
-
- # some useful options (see below for full list)
- my $config = {
- INCLUDE_PATH => '/search/path', # or list ref
- INTERPOLATE => 1, # expand "$var" in plain text
- POST_CHOMP => 1, # cleanup whitespace
- PRE_PROCESS => 'header', # prefix each template
- EVAL_PERL => 1, # evaluate Perl code blocks
- };
-
- # create Template object
- my $template = Template->new($config);
-
- # define template variables for replacement
- my $vars = {
- var1 => $value,
- var2 => \%hash,
- var3 => \@list,
- var4 => \&code,
- var5 => $object,
- };
-
- # specify input filename, or file handle, text reference, etc.
- my $input = 'myfile.html';
-
- # process input template, substituting variables
- $template->process($input, $vars)
- || die $template->error();
-
-=head1 DESCRIPTION
-
-This documentation describes the Template module which is the direct
-Perl interface into the Template Toolkit. It covers the use of the
-module and gives a brief summary of configuration options and template
-directives. Please see L<Template::Manual> for the complete reference
-manual which goes into much greater depth about the features and use
-of the Template Toolkit. The L<Template::Tutorial> is also available
-as an introductory guide to using the Template Toolkit.
-
-=head1 METHODS
-
-=head2 new(\%config)
-
-The new() constructor method (implemented by the Template::Base base
-class) instantiates a new Template object. A reference to a hash
-array of configuration items may be passed as a parameter.
-
- my $tt = Template->new({
- INCLUDE_PATH => '/usr/local/templates',
- EVAL_PERL => 1,
- }) || die $Template::ERROR, "\n";
-
-A reference to a new Template object is returned, or undef on error.
-In the latter case, the error message can be retrieved by calling
-error() as a class method (e.g. C<Template-E<gt>error()>) or by
-examining the $ERROR package variable directly
-(e.g. C<$Template::ERROR>).
-
- my $tt = Template->new(\%config)
- || die Template->error(), "\n";
-
- my $tt = Template->new(\%config)
- || die $Template::ERROR, "\n";
-
-For convenience, configuration items may also be specified as a list
-of items instead of a hash array reference. These are automatically
-folded into a hash array by the constructor.
-
- my $tt = Template->new(INCLUDE_PATH => '/tmp', POST_CHOMP => 1)
- || die $Template::ERROR, "\n";
-
-=head2 process($template, \%vars, $output, %options)
-
-The process() method is called to process a template. The first
-parameter indicates the input template as one of: a filename relative
-to INCLUDE_PATH, if defined; a reference to a text string containing
-the template text; or a file handle reference (e.g. IO::Handle or
-sub-class) or GLOB (e.g. \*STDIN), from which the template can be
-read. A reference to a hash array may be passed as the second
-parameter, containing definitions of template variables.
-
- $text = "[% INCLUDE header %]\nHello world!\n[% INCLUDE footer %]";
-
- # filename
- $tt->process('welcome.tt2')
- || die $tt->error(), "\n";
-
- # text reference
- $tt->process(\$text)
- || die $tt->error(), "\n";
-
- # GLOB
- $tt->process(\*DATA)
- || die $tt->error(), "\n";
-
- __END__
- [% INCLUDE header %]
- This is a template defined in the __END__ section which is
- accessible via the DATA "file handle".
- [% INCLUDE footer %]
-
-By default, the processed template output is printed to STDOUT. The
-process() method then returns 1 to indicate success. A third
-parameter may be passed to the process() method to specify a different
-output location. This value may be one of: a plain string indicating
-a filename which will be opened (relative to OUTPUT_PATH, if defined)
-and the output written to; a file GLOB opened ready for output; a
-reference to a scalar (e.g. a text string) to which output/error is
-appended; a reference to a subroutine which is called, passing the
-output as a parameter; or any object reference which implements a
-'print' method (e.g. IO::Handle, Apache::Request, etc.) which will
-be called, passing the generated output as a parameter.
-
-Examples:
-
- # output filename
- $tt->process('welcome.tt2', $vars, 'welcome.html')
- || die $tt->error(), "\n";
-
- # reference to output subroutine
- sub myout {
- my $output = shift;
- ...
- }
- $tt->process('welcome.tt2', $vars, \&myout)
- || die $tt->error(), "\n";
-
- # reference to output text string
- my $output = '';
- $tt->process('welcome.tt2', $vars, \$output)
- || die $tt->error(), "\n";
-
- print "output: $output\n";
-
-In an Apache/mod_perl handler:
-
- sub handler {
- my $req = shift;
-
- ...
-
- # direct output to Apache::Request via $req->print($output)
- $tt->process($file, $vars, $req) || do {
- $req->log_reason($tt->error());
- return SERVER_ERROR;
- };
-
- return OK;
- }
-
-After the optional third output argument can come an optional
-reference to a hash or a list of (name, value) pairs providing further
-options for the output. The only option currently supported is
-"binmode" which, when set to any true value will ensure that files
-created (but not any existing file handles passed) will be set to
-binary mode.
-
- # either: hash reference of options
- $tt->process($infile, $vars, $outfile, { binmode => 1 })
- || die $tt->error(), "\n";
-
- # or: list of name, value pairs
- $tt->process($infile, $vars, $outfile, binmode => 1)
- || die $tt->error(), "\n";
-
-The OUTPUT configuration item can be used to specify a default output
-location other than \*STDOUT. The OUTPUT_PATH specifies a directory
-which should be prefixed to all output locations specified as filenames.
-
- my $tt = Template->new({
- OUTPUT => sub { ... }, # default
- OUTPUT_PATH => '/tmp',
- ...
- }) || die Template->error(), "\n";
-
- # use default OUTPUT (sub is called)
- $tt->process('welcome.tt2', $vars)
- || die $tt->error(), "\n";
-
- # write file to '/tmp/welcome.html'
- $tt->process('welcome.tt2', $vars, 'welcome.html')
- || die $tt->error(), "\n";
-
-The process() method returns 1 on success or undef on error. The error
-message generated in the latter case can be retrieved by calling the
-error() method. See also L<CONFIGURATION SUMMARY> which describes how
-error handling may be further customised.
-
-=head2 error()
-
-When called as a class method, it returns the value of the $ERROR package
-variable. Thus, the following are equivalent.
-
- my $tt = Template->new()
- || die Template->error(), "\n";
-
- my $tt = Template->new()
- || die $Template::ERROR, "\n";
-
-When called as an object method, it returns the value of the internal
-_ERROR variable, as set by an error condition in a previous call to
-process().
-
- $tt->process('welcome.tt2')
- || die $tt->error(), "\n";
-
-Errors are represented in the Template Toolkit by objects of the
-Template::Exception class. If the process() method returns a false
-value then the error() method can be called to return an object of
-this class. The type() and info() methods can called on the object to
-retrieve the error type and information string, respectively. The
-as_string() method can be called to return a string of the form "$type
-- $info". This method is also overloaded onto the stringification
-operator allowing the object reference itself to be printed to return
-the formatted error string.
-
- $tt->process('somefile') || do {
- my $error = $tt->error();
- print "error type: ", $error->type(), "\n";
- print "error info: ", $error->info(), "\n";
- print $error, "\n";
- };
-
-=head2 service()
-
-The Template module delegates most of the effort of processing templates
-to an underlying Template::Service object. This method returns a reference
-to that object.
-
-=head2 context()
-
-The Template::Service module uses a core Template::Context object for
-runtime processing of templates. This method returns a reference to
-that object and is equivalent to $template-E<gt>service-E<gt>context();
-
-=head1 CONFIGURATION SUMMARY
-
-The following list gives a short summary of each Template Toolkit
-configuration option. See L<Template::Manual::Config> for full details.
-
-=head2 Template Style and Parsing Options
-
-=over 4
-
-=item START_TAG, END_TAG
-
-Define tokens that indicate start and end of directives (default: '[%' and
-'%]').
-
-=item TAG_STYLE
-
-Set START_TAG and END_TAG according to a pre-defined style (default:
-'template', as above).
-
-=item PRE_CHOMP, POST_CHOMP
-
-Remove whitespace before/after directives (default: 0/0).
-
-=item TRIM
-
-Remove leading and trailing whitespace from template output (default: 0).
-
-=item INTERPOLATE
-
-Interpolate variables embedded like $this or ${this} (default: 0).
-
-=item ANYCASE
-
-Allow directive keywords in lower case (default: 0 - UPPER only).
-
-=back
-
-=head2 Template Files and Blocks
-
-=over 4
-
-=item INCLUDE_PATH
-
-One or more directories to search for templates.
-
-=item DELIMITER
-
-Delimiter for separating paths in INCLUDE_PATH (default: ':').
-
-=item ABSOLUTE
-
-Allow absolute file names, e.g. /foo/bar.html (default: 0).
-
-=item RELATIVE
-
-Allow relative filenames, e.g. ../foo/bar.html (default: 0).
-
-=item DEFAULT
-
-Default template to use when another not found.
-
-=item BLOCKS
-
-Hash array pre-defining template blocks.
-
-=item AUTO_RESET
-
-Enabled by default causing BLOCK definitions to be reset each time a
-template is processed. Disable to allow BLOCK definitions to persist.
-
-=item RECURSION
-
-Flag to permit recursion into templates (default: 0).
-
-=back
-
-=head2 Template Variables
-
-=over 4
-
-=item VARIABLES, PRE_DEFINE
-
-Hash array of variables and values to pre-define in the stash.
-
-=back
-
-=head2 Runtime Processing Options
-
-=over 4
-
-=item EVAL_PERL
-
-Flag to indicate if PERL/RAWPERL blocks should be processed (default: 0).
-
-=item PRE_PROCESS, POST_PROCESS
-
-Name of template(s) to process before/after main template.
-
-=item PROCESS
-
-Name of template(s) to process instead of main template.
-
-=item ERROR
-
-Name of error template or reference to hash array mapping error types to
-templates.
-
-=item OUTPUT
-
-Default output location or handler.
-
-=item OUTPUT_PATH
-
-Directory into which output files can be written.
-
-=item DEBUG
-
-Enable debugging messages.
-
-=back
-
-=head2 Caching and Compiling Options
-
-=over 4
-
-=item CACHE_SIZE
-
-Maximum number of compiled templates to cache in memory (default:
-undef - cache all)
-
-=item COMPILE_EXT
-
-Filename extension for compiled template files (default: undef - don't
-compile).
-
-=item COMPILE_DIR
-
-Root of directory in which compiled template files should be written
-(default: undef - don't compile).
-
-=back
-
-=head2 Plugins and Filters
-
-=over 4
-
-=item PLUGINS
-
-Reference to a hash array mapping plugin names to Perl packages.
-
-=item PLUGIN_BASE
-
-One or more base classes under which plugins may be found.
-
-=item LOAD_PERL
-
-Flag to indicate regular Perl modules should be loaded if a named plugin
-can't be found (default: 0).
-
-=item FILTERS
-
-Hash array mapping filter names to filter subroutines or factories.
-
-=back
-
-=head2 Compatibility, Customisation and Extension
-
-=over 4
-
-=item V1DOLLAR
-
-Backwards compatibility flag enabling version 1.* handling (i.e. ignore it)
-of leading '$' on variables (default: 0 - '$' indicates interpolation).
-
-=item LOAD_TEMPLATES
-
-List of template providers.
-
-=item LOAD_PLUGINS
-
-List of plugin providers.
-
-=item LOAD_FILTERS
-
-List of filter providers.
-
-=item TOLERANT
-
-Set providers to tolerate errors as declinations (default: 0).
-
-=item SERVICE
-
-Reference to a custom service object (default: Template::Service).
-
-=item CONTEXT
-
-Reference to a custom context object (default: Template::Context).
-
-=item STASH
-
-Reference to a custom stash object (default: Template::Stash).
-
-=item PARSER
-
-Reference to a custom parser object (default: Template::Parser).
-
-=item GRAMMAR
-
-Reference to a custom grammar object (default: Template::Grammar).
-
-=back
-
-=head1 DIRECTIVE SUMMARY
-
-The following list gives a short summary of each Template Toolkit directive.
-See L<Template::Manual::Directives> for full details.
-
-=over 4
-
-=item GET
-
-Evaluate and print a variable or value.
-
- [% GET variable %] # 'GET' keyword is optional
-
- [% variable %]
- [% hash.key %]
- [% list.n %]
- [% code(args) %]
- [% obj.meth(args) %]
- [% "value: $var" %]
-
-=item CALL
-
-As per GET but without printing result (e.g. call code)
-
- [% CALL variable %]
-
-=item SET
-
-Assign a values to variables.
-
- [% SET variable = value %] # 'SET' also optional
-
- [% variable = other_variable
- variable = 'literal text @ $100'
- variable = "interpolated text: $var"
- list = [ val, val, val, val, ... ]
- list = [ val..val ]
- hash = { var => val, var => val, ... }
- %]
-
-=item DEFAULT
-
-Like SET above, but variables are only set if currently unset (i.e. have no
-true value).
-
- [% DEFAULT variable = value %]
-
-=item INSERT
-
-Insert a file without any processing performed on the contents.
-
- [% INSERT legalese.txt %]
-
-=item INCLUDE
-
-Process another template file or block and include the output. Variables
-are localised.
-
- [% INCLUDE template %]
- [% INCLUDE template var = val, ... %]
-
-=item PROCESS
-
-As INCLUDE above, but without localising variables.
-
- [% PROCESS template %]
- [% PROCESS template var = val, ... %]
-
-=item WRAPPER
-
-Process the enclosed block WRAPPER ... END block then INCLUDE the
-named template, passing the block output in the 'content' variable.
-
- [% WRAPPER template %]
- content...
- [% END %]
-
-=item BLOCK
-
-Define a named template block for subsequent INCLUDE, PROCESS, etc.,
-
- [% BLOCK template %]
- content
- [% END %]
-
-=item FOREACH
-
-Repeat the enclosed FOREACH ... END block for each value in the list.
-
- [% FOREACH variable = [ val, val, val ] %] # either
- [% FOREACH variable = list %] # or
- [% FOREACH list %] # or
- content...
- [% variable %]
- [% END %]
-
-=item WHILE
-
-Enclosed WHILE ... END block is processed while condition is true.
-
- [% WHILE condition %]
- content
- [% END %]
-
-=item IF / UNLESS / ELSIF / ELSE
-
-Enclosed block is processed if the condition is true / false.
-
- [% IF condition %]
- content
- [% ELSIF condition %]
- content
- [% ELSE %]
- content
- [% END %]
-
- [% UNLESS condition %]
- content
- [% # ELSIF/ELSE as per IF, above %]
- content
- [% END %]
-
-=item SWITCH / CASE
-
-Multi-way switch/case statement.
-
- [% SWITCH variable %]
- [% CASE val1 %]
- content
- [% CASE [ val2, val3 ] %]
- content
- [% CASE %] # or [% CASE DEFAULT %]
- content
- [% END %]
-
-=item MACRO
-
-Define a named macro.
-
- [% MACRO name <directive> %]
- [% MACRO name(arg1, arg2) <directive> %]
- ...
- [% name %]
- [% name(val1, val2) %]
-
-=item FILTER
-
-Process enclosed FILTER ... END block then pipe through a filter.
-
- [% FILTER name %] # either
- [% FILTER name( params ) %] # or
- [% FILTER alias = name( params ) %] # or
- content
- [% END %]
-
-=item USE
-
-Load a "plugin" module, or any regular Perl module if LOAD_PERL option is
-set.
-
- [% USE name %] # either
- [% USE name( params ) %] # or
- [% USE var = name( params ) %] # or
- ...
- [% name.method %]
- [% var.method %]
-
-=item PERL / RAWPERL
-
-Evaluate enclosed blocks as Perl code (requires EVAL_PERL option to be set).
-
- [% PERL %]
- # perl code goes here
- $stash->set('foo', 10);
- print "set 'foo' to ", $stash->get('foo'), "\n";
- print $context->include('footer', { var => $val });
- [% END %]
-
- [% RAWPERL %]
- # raw perl code goes here, no magic but fast.
- $output .= 'some output';
- [% END %]
-
-=item TRY / THROW / CATCH / FINAL
-
-Exception handling.
-
- [% TRY %]
- content
- [% THROW type info %]
- [% CATCH type %]
- catch content
- [% error.type %] [% error.info %]
- [% CATCH %] # or [% CATCH DEFAULT %]
- content
- [% FINAL %]
- this block is always processed
- [% END %]
-
-=item NEXT
-
-Jump straight to the next item in a FOREACH/WHILE loop.
-
- [% NEXT %]
-
-=item LAST
-
-Break out of FOREACH/WHILE loop.
-
- [% LAST %]
-
-=item RETURN
-
-Stop processing current template and return to including templates.
-
- [% RETURN %]
-
-=item STOP
-
-Stop processing all templates and return to caller.
-
- [% STOP %]
-
-=item TAGS
-
-Define new tag style or characters (default: [% %]).
-
- [% TAGS html %]
- [% TAGS <!-- --> %]
-
-=item COMMENTS
-
-Ignored and deleted.
-
- [% # this is a comment to the end of line
- foo = 'bar'
- %]
-
- [%# placing the '#' immediately inside the directive
- tag comments out the entire directive
- %]
-
-=back
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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:
diff --git a/lib/Template/Base.pm b/lib/Template/Base.pm
deleted file mode 100644
index 5f19d78..0000000
--- a/lib/Template/Base.pm
+++ /dev/null
@@ -1,314 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Base
-#
-# DESCRIPTION
-# Base class module implementing common functionality for various other
-# Template Toolkit modules.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-#------------------------------------------------------------------------
-#
-# $Id: Base.pm,v 2.69 2004/01/13 16:19:09 abw Exp $
-#
-#========================================================================
-
-package Template::Base;
-
-require 5.004;
-
-use strict;
-use vars qw( $VERSION );
-use Template::Constants;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.69 $ =~ /(\d+)\.(\d+)/);
-
-
-#------------------------------------------------------------------------
-# new(\%params)
-#
-# General purpose constructor method which expects a hash reference of
-# configuration parameters, or a list of name => value pairs which are
-# folded into a hash. Blesses a hash into an object and calls its
-# _init() method, passing the parameter hash reference. Returns a new
-# object derived from Template::Base, or undef on error.
-#------------------------------------------------------------------------
-
-sub new {
- my $class = shift;
- my ($argnames, @args, $arg, $cfg);
-# $class->error(''); # always clear package $ERROR var?
-
- { no strict qw( refs );
- $argnames = \@{"$class\::BASEARGS"} || [ ];
- }
-
- # shift off all mandatory args, returning error if undefined or null
- foreach $arg (@$argnames) {
- return $class->error("no $arg specified")
- unless ($cfg = shift);
- push(@args, $cfg);
- }
-
- # fold all remaining args into a hash, or use provided hash ref
-# local $" = ', ';
-# print STDERR "args: [@_]\n";
- $cfg = defined $_[0] && UNIVERSAL::isa($_[0], 'HASH') ? shift : { @_ };
-
- my $self = bless {
- map { ($_ => shift @args) } @$argnames,
- _ERROR => '',
- DEBUG => 0,
- }, $class;
-
- return $self->_init($cfg) ? $self : $class->error($self->error);
-}
-
-
-#------------------------------------------------------------------------
-# error()
-# error($msg, ...)
-#
-# May be called as a class or object method to set or retrieve the
-# package variable $ERROR (class method) or internal member
-# $self->{ _ERROR } (object method). The presence of parameters indicates
-# that the error value should be set. Undef is then returned. In the
-# abscence of parameters, the current error value is returned.
-#------------------------------------------------------------------------
-
-sub error {
- my $self = shift;
- my $errvar;
-
- {
- no strict qw( refs );
- $errvar = ref $self ? \$self->{ _ERROR } : \${"$self\::ERROR"};
- }
- if (@_) {
- $$errvar = ref($_[0]) ? shift : join('', @_);
- return undef;
- }
- else {
- return $$errvar;
- }
-}
-
-
-#------------------------------------------------------------------------
-# _init()
-#
-# Initialisation method called by the new() constructor and passing a
-# reference to a hash array containing any configuration items specified
-# as constructor arguments. Should return $self on success or undef on
-# error, via a call to the error() method to set the error message.
-#------------------------------------------------------------------------
-
-sub _init {
- my ($self, $config) = @_;
- return $self;
-}
-
-
-sub DEBUG {
- my $self = shift;
- print STDERR "DEBUG: ", @_;
-}
-
-sub debug {
- my $self = shift;
- my $msg = join('', @_);
- my ($pkg, $file, $line) = caller();
-
- unless ($msg =~ /\n$/) {
- $msg .= ($self->{ DEBUG } & Template::Constants::DEBUG_CALLER)
- ? " at $file line $line\n"
- : "\n";
- }
-
- print STDERR "[$pkg] $msg";
-}
-
-
-#------------------------------------------------------------------------
-# module_version()
-#
-# Returns the current version number.
-#------------------------------------------------------------------------
-
-sub module_version {
- my $self = shift;
- my $class = ref $self || $self;
- no strict 'refs';
- return ${"${class}::VERSION"};
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Base - Base class module implementing common functionality
-
-=head1 SYNOPSIS
-
- package My::Module;
- use base qw( Template::Base );
-
- sub _init {
- my ($self, $config) = @_;
- $self->{ doodah } = $config->{ doodah }
- || return $self->error("No 'doodah' specified");
- return $self;
- }
-
- package main;
-
- my $object = My::Module->new({ doodah => 'foobar' })
- || die My::Module->error();
-
-=head1 DESCRIPTION
-
-Base class module which implements a constructor and error reporting
-functionality for various Template Toolkit modules.
-
-=head1 PUBLIC METHODS
-
-=head2 new(\%config)
-
-Constructor method which accepts a reference to a hash array or a list
-of C<name =E<gt> value> parameters which are folded into a hash. The
-_init() method is then called, passing the configuration hash and should
-return true/false to indicate success or failure. A new object reference
-is returned, or undef on error. Any error message raised can be examined
-via the error() class method or directly via the package variable ERROR
-in the derived class.
-
- my $module = My::Module->new({ ... })
- || die My::Module->error(), "\n";
-
- my $module = My::Module->new({ ... })
- || die "constructor error: $My::Module::ERROR\n";
-
-=head2 error($msg, ...)
-
-May be called as an object method to get/set the internal _ERROR member
-or as a class method to get/set the $ERROR variable in the derived class's
-package.
-
- my $module = My::Module->new({ ... })
- || die My::Module->error(), "\n";
-
- $module->do_something()
- || die $module->error(), "\n";
-
-When called with parameters (multiple params are concatenated), this
-method will set the relevant variable and return undef. This is most
-often used within object methods to report errors to the caller.
-
- package My::Module;
-
- sub foobar {
- my $self = shift;
-
- # some other code...
-
- return $self->error('some kind of error...')
- if $some_condition;
- }
-
-=head2 debug($msg, ...)
-
-Generates a debugging message by concatenating all arguments
-passed into a string and printing it to STDERR. A prefix is
-added to indicate the module of the caller.
-
- package My::Module;
-
- sub foobar {
- my $self = shift;
-
- $self->debug('called foobar()');
-
- # some other code...
- }
-
-When the foobar() method is called, the following message
-is sent to STDERR:
-
- [My::Module] called foobar()
-
-Objects can set an internal DEBUG value which the debug()
-method will examine. If this value sets the relevant bits
-to indicate DEBUG_CALLER then the file and line number of
-the caller will be appened to the message.
-
- use Template::Constants qw( :debug );
-
- my $module = My::Module->new({
- DEBUG => DEBUG_SERVICE | DEBUG_CONTEXT | DEBUG_CALLER,
- });
-
- $module->foobar();
-
-This generates an error message such as:
-
- [My::Module] called foobar() at My/Module.pm line 6
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.69, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template|Template>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Config.pm b/lib/Template/Config.pm
deleted file mode 100644
index 9a3f378..0000000
--- a/lib/Template/Config.pm
+++ /dev/null
@@ -1,467 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Config
-#
-# DESCRIPTION
-# Template Toolkit configuration module.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-#------------------------------------------------------------------------
-#
-# $Id: Config.pm,v 2.67 2004/01/13 16:19:10 abw Exp $
-#
-#========================================================================
-
-package Template::Config;
-
-require 5.004;
-
-use strict;
-use base qw( Template::Base );
-use vars qw( $VERSION $DEBUG $ERROR $INSTDIR
- $PARSER $PROVIDER $PLUGINS $FILTERS $ITERATOR
- $LATEX_PATH $PDFLATEX_PATH $DVIPS_PATH
- $STASH $SERVICE $CONTEXT $CONSTANTS @PRELOAD );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.67 $ =~ /(\d+)\.(\d+)/);
-$DEBUG = 0 unless defined $DEBUG;
-$ERROR = '';
-$CONTEXT = 'Template::Context';
-$FILTERS = 'Template::Filters';
-$ITERATOR = 'Template::Iterator';
-$PARSER = 'Template::Parser';
-$PLUGINS = 'Template::Plugins';
-$PROVIDER = 'Template::Provider';
-$SERVICE = 'Template::Service';
-$STASH = 'Template::Stash';
-$CONSTANTS = 'Template::Namespace::Constants';
-
-@PRELOAD = ( $CONTEXT, $FILTERS, $ITERATOR, $PARSER,
- $PLUGINS, $PROVIDER, $SERVICE, $STASH );
-
-# the following is set at installation time by the Makefile.PL
-$INSTDIR = '';
-
-# LaTeX executable paths set at installation time by the Makefile.PL
-# Empty strings cause the latex(pdf|dvi|ps) filters to throw an error.
-$LATEX_PATH = '';
-$PDFLATEX_PATH = '';
-$DVIPS_PATH = '';
-
-#========================================================================
-# --- CLASS METHODS ---
-#========================================================================
-
-#------------------------------------------------------------------------
-# preload($module, $module, ...)
-#
-# Preloads all the standard TT modules that are likely to be used, along
-# with any other passed as arguments.
-#------------------------------------------------------------------------
-
-sub preload {
- my $class = shift;
-
- foreach my $module (@PRELOAD, @_) {
- $class->load($module) || return;
- };
- return 1;
-}
-
-
-#------------------------------------------------------------------------
-# load($module)
-#
-# Load a module via require(). Any occurences of '::' in the module name
-# are be converted to '/' and '.pm' is appended. Returns 1 on success
-# or undef on error. Use $class->error() to examine the error string.
-#------------------------------------------------------------------------
-
-sub load {
- my ($class, $module) = @_;
- $module =~ s[::][/]g;
- $module .= '.pm';
-# print STDERR "loading $module\n"
-# if $DEBUG;
- eval {
- require $module;
- };
- return $@ ? $class->error("failed to load $module: $@") : 1;
-}
-
-
-#------------------------------------------------------------------------
-# parser(\%params)
-#
-# Instantiate a new parser object of the class whose name is denoted by
-# the package variable $PARSER (default: Template::Parser). Returns
-# a reference to a newly instantiated parser object or undef on error.
-# The class error() method can be called without arguments to examine
-# the error message generated by this failure.
-#------------------------------------------------------------------------
-
-sub parser {
- my $class = shift;
- my $params = defined($_[0]) && UNIVERSAL::isa($_[0], 'HASH')
- ? shift : { @_ };
-
- return undef unless $class->load($PARSER);
- return $PARSER->new($params)
- || $class->error("failed to create parser: ", $PARSER->error);
-}
-
-
-#------------------------------------------------------------------------
-# provider(\%params)
-#
-# Instantiate a new template provider object (default: Template::Provider).
-# Returns an object reference or undef on error, as above.
-#------------------------------------------------------------------------
-
-sub provider {
- my $class = shift;
- my $params = defined($_[0]) && UNIVERSAL::isa($_[0], 'HASH')
- ? shift : { @_ };
-
- return undef unless $class->load($PROVIDER);
- return $PROVIDER->new($params)
- || $class->error("failed to create template provider: ",
- $PROVIDER->error);
-}
-
-
-#------------------------------------------------------------------------
-# plugins(\%params)
-#
-# Instantiate a new plugins provider object (default: Template::Plugins).
-# Returns an object reference or undef on error, as above.
-#------------------------------------------------------------------------
-
-sub plugins {
- my $class = shift;
- my $params = defined($_[0]) && UNIVERSAL::isa($_[0], 'HASH')
- ? shift : { @_ };
-
- return undef unless $class->load($PLUGINS);
- return $PLUGINS->new($params)
- || $class->error("failed to create plugin provider: ",
- $PLUGINS->error);
-}
-
-
-#------------------------------------------------------------------------
-# filters(\%params)
-#
-# Instantiate a new filters provider object (default: Template::Filters).
-# Returns an object reference or undef on error, as above.
-#------------------------------------------------------------------------
-
-sub filters {
- my $class = shift;
- my $params = defined($_[0]) && UNIVERSAL::isa($_[0], 'HASH')
- ? shift : { @_ };
-
- return undef unless $class->load($FILTERS);
- return $FILTERS->new($params)
- || $class->error("failed to create filter provider: ",
- $FILTERS->error);
-}
-
-
-#------------------------------------------------------------------------
-# iterator(\@list)
-#
-# Instantiate a new Template::Iterator object (default: Template::Iterator).
-# Returns an object reference or undef on error, as above.
-#------------------------------------------------------------------------
-
-sub iterator {
- my $class = shift;
- my $list = shift;
-
- return undef unless $class->load($ITERATOR);
- return $ITERATOR->new($list, @_)
- || $class->error("failed to create iterator: ", $ITERATOR->error);
-}
-
-
-#------------------------------------------------------------------------
-# stash(\%vars)
-#
-# Instantiate a new template variable stash object (default:
-# Template::Stash). Returns object or undef, as above.
-#------------------------------------------------------------------------
-
-sub stash {
- my $class = shift;
- my $params = defined($_[0]) && UNIVERSAL::isa($_[0], 'HASH')
- ? shift : { @_ };
-
- return undef unless $class->load($STASH);
- return $STASH->new($params)
- || $class->error("failed to create stash: ", $STASH->error);
-}
-
-
-#------------------------------------------------------------------------
-# context(\%params)
-#
-# Instantiate a new template context object (default: Template::Context).
-# Returns object or undef, as above.
-#------------------------------------------------------------------------
-
-sub context {
- my $class = shift;
- my $params = defined($_[0]) && UNIVERSAL::isa($_[0], 'HASH')
- ? shift : { @_ };
-
- return undef unless $class->load($CONTEXT);
- return $CONTEXT->new($params)
- || $class->error("failed to create context: ", $CONTEXT->error);
-}
-
-
-#------------------------------------------------------------------------
-# service(\%params)
-#
-# Instantiate a new template context object (default: Template::Service).
-# Returns object or undef, as above.
-#------------------------------------------------------------------------
-
-sub service {
- my $class = shift;
- my $params = defined($_[0]) && UNIVERSAL::isa($_[0], 'HASH')
- ? shift : { @_ };
-
- return undef unless $class->load($SERVICE);
- return $SERVICE->new($params)
- || $class->error("failed to create context: ", $SERVICE->error);
-}
-
-
-#------------------------------------------------------------------------
-# constants(\%params)
-#
-# Instantiate a new namespace handler for compile time constant folding
-# (default: Template::Namespace::Constants).
-# Returns object or undef, as above.
-#------------------------------------------------------------------------
-
-sub constants {
- my $class = shift;
- my $params = defined($_[0]) && UNIVERSAL::isa($_[0], 'HASH')
- ? shift : { @_ };
-
- return undef unless $class->load($CONSTANTS);
- return $CONSTANTS->new($params)
- || $class->error("failed to create constants namespace: ",
- $CONSTANTS->error);
-}
-
-
-#------------------------------------------------------------------------
-# instdir($dir)
-#
-# Returns the root installation directory appended with any local
-# component directory passed as an argument.
-#------------------------------------------------------------------------
-
-sub instdir {
- my ($class, $dir) = @_;
- my $inst = $INSTDIR
- || return $class->error("no installation directory");
- $inst =~ s[/$][]g;
- $inst .= "/$dir" if $dir;
- return $inst;
-}
-
-#------------------------------------------------------------------------
-# latexpaths()
-#
-# Returns a reference to a three element array:
-# [latex_path, pdf2latex_path, dvips_path]
-# These values are determined by Makefile.PL at installation time
-# and are used by the latex(pdf|dvi|ps) filters.
-#------------------------------------------------------------------------
-
-sub latexpaths {
- return [$LATEX_PATH, $PDFLATEX_PATH, $DVIPS_PATH];
-}
-
-#========================================================================
-# This should probably be moved somewhere else in the long term, but for
-# now it ensures that Template::TieString is available even if the
-# Template::Directive module hasn't been loaded, as is the case when
-# using compiled templates and Template::Parser hasn't yet been loaded
-# on demand.
-#========================================================================
-
-#------------------------------------------------------------------------
-# simple package for tying $output variable to STDOUT, used by perl()
-#------------------------------------------------------------------------
-
-package Template::TieString;
-
-sub TIEHANDLE {
- my ($class, $textref) = @_;
- bless $textref, $class;
-}
-sub PRINT {
- my $self = shift;
- $$self .= join('', @_);
-}
-
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Config - Factory module for instantiating other TT2 modules
-
-=head1 SYNOPSIS
-
- use Template::Config;
-
-=head1 DESCRIPTION
-
-This module implements various methods for loading and instantiating
-other modules that comprise the Template Toolkit. It provides a consistent
-way to create toolkit components and allows custom modules to be used in
-place of the regular ones.
-
-Package variables such as $STASH, $SERVICE, $CONTEXT, etc., contain
-the default module/package name for each component (Template::Stash,
-Template::Service and Template::Context, respectively) and are used by
-the various factory methods (stash(), service() and context()) to load
-the appropriate module. Changing these package variables will cause
-subsequent calls to the relevant factory method to load and instantiate
-an object from the new class.
-
-=head1 PUBLIC METHODS
-
-=head2 load($module)
-
-Load a module via require(). Any occurences of '::' in the module name
-are be converted to '/' and '.pm' is appended. Returns 1 on success
-or undef on error. Use $class-E<gt>error() to examine the error string.
-
-=head2 preload()
-
-This method preloads all the other Template::* modules that are likely
-to be used. It is called by the Template module when running under
-mod_perl ($ENV{MOD_PERL} is set).
-
-=head2 parser(\%config)
-
-Instantiate a new parser object of the class whose name is denoted by
-the package variable $PARSER (default: Template::Parser). Returns
-a reference to a newly instantiated parser object or undef on error.
-
-=head2 provider(\%config)
-
-Instantiate a new template provider object (default: Template::Provider).
-Returns an object reference or undef on error, as above.
-
-=head2 plugins(\%config)
-
-Instantiate a new plugins provider object (default: Template::Plugins).
-Returns an object reference or undef on error, as above.
-
-=head2 filters(\%config)
-
-Instantiate a new filter provider object (default: Template::Filters).
-Returns an object reference or undef on error, as above.
-
-=head2 stash(\%vars)
-
-Instantiate a new stash object (Template::Stash or Template::Stash::XS
-depending on the default set at installation time) using the contents
-of the optional hash array passed by parameter as initial variable
-definitions. Returns an object reference or undef on error, as above.
-
-=head2 context(\%config)
-
-Instantiate a new template context object (default: Template::Context).
-Returns an object reference or undef on error, as above.
-
-=head2 service(\%config)
-
-Instantiate a new template service object (default: Template::Service).
-Returns an object reference or undef on error, as above.
-
-=head2 instdir($dir)
-
-Returns the root directory of the Template Toolkit installation under
-which optional components are installed. Any relative directory specified
-as an argument will be appended to the returned directory.
-
- # e.g. returns '/usr/local/tt2'
- my $ttroot = Template::Config->instdir()
- || die "$Template::Config::ERROR\n";
-
- # e.g. returns '/usr/local/tt2/templates'
- my $template = Template::Config->instdir('templates')
- || die "$Template::Config::ERROR\n";
-
-Returns undef and sets $Template::Config::ERROR appropriately if the
-optional components of the Template Toolkit have not been installed.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.67, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template|Template>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Constants.pm b/lib/Template/Constants.pm
deleted file mode 100644
index b227467..0000000
--- a/lib/Template/Constants.pm
+++ /dev/null
@@ -1,287 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Constants.pm
-#
-# DESCRIPTION
-# Definition of constants for the Template Toolkit.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Constants.pm,v 2.67 2004/01/13 16:19:10 abw Exp $
-#
-#============================================================================
-
-package Template::Constants;
-
-require 5.004;
-require Exporter;
-
-use strict;
-use vars qw( $VERSION @ISA @EXPORT_OK %EXPORT_TAGS );
-use vars qw( $DEBUG_OPTIONS @STATUS @ERROR @CHOMP @DEBUG);
-
-@ISA = qw( Exporter );
-$VERSION = sprintf("%d.%02d", q$Revision: 2.67 $ =~ /(\d+)\.(\d+)/);
-
-
-#========================================================================
-# ----- EXPORTER -----
-#========================================================================
-
-# STATUS constants returned by directives
-use constant STATUS_OK => 0; # ok
-use constant STATUS_RETURN => 1; # ok, block ended by RETURN
-use constant STATUS_STOP => 2; # ok, stoppped by STOP
-use constant STATUS_DONE => 3; # ok, iterator done
-use constant STATUS_DECLINED => 4; # ok, declined to service request
-use constant STATUS_ERROR => 255; # error condition
-
-# ERROR constants for indicating exception types
-use constant ERROR_RETURN => 'return'; # return a status code
-use constant ERROR_FILE => 'file'; # file error: I/O, parse, recursion
-use constant ERROR_VIEW => 'view'; # view error
-use constant ERROR_UNDEF => 'undef'; # undefined variable value used
-use constant ERROR_PERL => 'perl'; # error in [% PERL %] block
-use constant ERROR_FILTER => 'filter'; # filter error
-use constant ERROR_PLUGIN => 'plugin'; # plugin error
-
-# CHOMP constants for PRE_CHOMP and POST_CHOMP
-use constant CHOMP_NONE => 0; # do not remove whitespace
-use constant CHOMP_ALL => 1; # remove whitespace
-use constant CHOMP_COLLAPSE => 2; # collapse whitespace to a single space
-
-# DEBUG constants to enable various debugging options
-use constant DEBUG_OFF => 0; # do nothing
-use constant DEBUG_ON => 1; # basic debugging flag
-use constant DEBUG_UNDEF => 2; # throw undef on undefined variables
-use constant DEBUG_VARS => 4; # general variable debugging
-use constant DEBUG_DIRS => 8; # directive debugging
-use constant DEBUG_STASH => 16; # general stash debugging
-use constant DEBUG_CONTEXT => 32; # context debugging
-use constant DEBUG_PARSER => 64; # parser debugging
-use constant DEBUG_PROVIDER => 128; # provider debugging
-use constant DEBUG_PLUGINS => 256; # plugins debugging
-use constant DEBUG_FILTERS => 512; # filters debugging
-use constant DEBUG_SERVICE => 1024; # context debugging
-use constant DEBUG_ALL => 2047; # everything
-
-# extra debugging flags
-use constant DEBUG_CALLER => 4096; # add caller file/line
-use constant DEBUG_FLAGS => 4096; # bitmask to extraxt flags
-
-$DEBUG_OPTIONS = {
- &DEBUG_OFF => off => off => &DEBUG_OFF,
- &DEBUG_ON => on => on => &DEBUG_ON,
- &DEBUG_UNDEF => undef => undef => &DEBUG_UNDEF,
- &DEBUG_VARS => vars => vars => &DEBUG_VARS,
- &DEBUG_DIRS => dirs => dirs => &DEBUG_DIRS,
- &DEBUG_STASH => stash => stash => &DEBUG_STASH,
- &DEBUG_CONTEXT => context => context => &DEBUG_CONTEXT,
- &DEBUG_PARSER => parser => parser => &DEBUG_PARSER,
- &DEBUG_PROVIDER => provider => provider => &DEBUG_PROVIDER,
- &DEBUG_PLUGINS => plugins => plugins => &DEBUG_PLUGINS,
- &DEBUG_FILTERS => filters => filters => &DEBUG_FILTERS,
- &DEBUG_SERVICE => service => service => &DEBUG_SERVICE,
- &DEBUG_ALL => all => all => &DEBUG_ALL,
- &DEBUG_CALLER => caller => caller => &DEBUG_CALLER,
-};
-
-@STATUS = qw( STATUS_OK STATUS_RETURN STATUS_STOP STATUS_DONE
- STATUS_DECLINED STATUS_ERROR );
-@ERROR = qw( ERROR_FILE ERROR_VIEW ERROR_UNDEF ERROR_PERL
- ERROR_RETURN ERROR_FILTER ERROR_PLUGIN );
-@CHOMP = qw( CHOMP_NONE CHOMP_ALL CHOMP_COLLAPSE );
-@DEBUG = qw( DEBUG_OFF DEBUG_ON DEBUG_UNDEF DEBUG_VARS
- DEBUG_DIRS DEBUG_STASH DEBUG_CONTEXT DEBUG_PARSER
- DEBUG_PROVIDER DEBUG_PLUGINS DEBUG_FILTERS DEBUG_SERVICE
- DEBUG_ALL DEBUG_CALLER DEBUG_FLAGS );
-
-@EXPORT_OK = ( @STATUS, @ERROR, @CHOMP, @DEBUG );
-%EXPORT_TAGS = (
- 'all' => [ @EXPORT_OK ],
- 'status' => [ @STATUS ],
- 'error' => [ @ERROR ],
- 'chomp' => [ @CHOMP ],
- 'debug' => [ @DEBUG ],
-);
-
-
-sub debug_flags {
- my ($self, $debug) = @_;
- my (@flags, $flag, $value);
- $debug = $self unless defined($debug) || ref($self);
-
- if ($debug =~ /^\d+$/) {
- foreach $flag (@DEBUG) {
- next if $flag =~ /^DEBUG_(OFF|ALL|FLAGS)$/;
-
- # don't trash the original
- my $copy = $flag;
- $flag =~ s/^DEBUG_//;
- $flag = lc $flag;
- return $self->error("no value for flag: $flag")
- unless defined($value = $DEBUG_OPTIONS->{ $flag });
- $flag = $value;
-
- if ($debug & $flag) {
- $value = $DEBUG_OPTIONS->{ $flag };
- return $self->error("no value for flag: $flag") unless defined $value;
- push(@flags, $value);
- }
- }
- return wantarray ? @flags : join(', ', @flags);
- }
- else {
- @flags = split(/\W+/, $debug);
- $debug = 0;
- foreach $flag (@flags) {
- $value = $DEBUG_OPTIONS->{ $flag };
- return $self->error("unknown debug flag: $flag") unless defined $value;
- $debug |= $value;
- }
- return $debug;
- }
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Constants - Defines constants for the Template Toolkit
-
-=head1 SYNOPSIS
-
- use Template::Constants qw( :status :error :all );
-
-=head1 DESCRIPTION
-
-The Template::Constants modules defines, and optionally exports into the
-caller's namespace, a number of constants used by the Template package.
-
-Constants may be used by specifying the Template::Constants package
-explicitly:
-
- use Template::Constants;
-
- print Template::Constants::STATUS_DECLINED;
-
-Constants may be imported into the caller's namespace by naming them as
-options to the C<use Template::Constants> statement:
-
- use Template::Constants qw( STATUS_DECLINED );
-
- print STATUS_DECLINED;
-
-Alternatively, one of the following tagset identifiers may be specified
-to import sets of constants; :status, :error, :all.
-
- use Template::Constants qw( :status );
-
- print STATUS_DECLINED;
-
-See L<Exporter> for more information on exporting variables.
-
-=head1 EXPORTABLE TAG SETS
-
-The following tag sets and associated constants are defined:
-
- :status
- STATUS_OK # no problem, continue
- STATUS_RETURN # ended current block then continue (ok)
- STATUS_STOP # controlled stop (ok)
- STATUS_DONE # iterator is all done (ok)
- STATUS_DECLINED # provider declined to service request (ok)
- STATUS_ERROR # general error condition (not ok)
-
- :error
- ERROR_RETURN # return a status code (e.g. 'stop')
- ERROR_FILE # file error: I/O, parse, recursion
- ERROR_UNDEF # undefined variable value used
- ERROR_PERL # error in [% PERL %] block
- ERROR_FILTER # filter error
- ERROR_PLUGIN # plugin error
-
- :chomp # for PRE_CHOMP and POST_CHOMP
- CHOMP_NONE # do not remove whitespace
- CHOMP_ALL # remove whitespace
- CHOMP_COLLAPSE # collapse whitespace to a single space
-
- :debug
- DEBUG_OFF # do nothing
- DEBUG_ON # basic debugging flag
- DEBUG_UNDEF # throw undef on undefined variables
- DEBUG_VARS # general variable debugging
- DEBUG_DIRS # directive debugging
- DEBUG_STASH # general stash debugging
- DEBUG_CONTEXT # context debugging
- DEBUG_PARSER # parser debugging
- DEBUG_PROVIDER # provider debugging
- DEBUG_PLUGINS # plugins debugging
- DEBUG_FILTERS # filters debugging
- DEBUG_SERVICE # context debugging
- DEBUG_ALL # everything
- DEBUG_CALLER # add caller file/line info
- DEBUG_FLAGS # bitmap used internally
-
- :all All the above constants.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.67, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template|Template>, L<Exporter|Exporter>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Context.pm b/lib/Template/Context.pm
deleted file mode 100644
index cdc699e..0000000
--- a/lib/Template/Context.pm
+++ /dev/null
@@ -1,1570 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Context
-#
-# DESCRIPTION
-# Module defining a context in which a template document is processed.
-# This is the runtime processing interface through which templates
-# can access the functionality of the Template Toolkit.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-# REVISION
-# $Id: Context.pm,v 2.89 2004/01/30 18:37:47 abw Exp $
-#
-#============================================================================
-
-package Template::Context;
-
-require 5.004;
-
-use strict;
-use vars qw( $VERSION $DEBUG $AUTOLOAD $DEBUG_FORMAT );
-use base qw( Template::Base );
-
-use Template::Base;
-use Template::Config;
-use Template::Constants;
-use Template::Exception;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.89 $ =~ /(\d+)\.(\d+)/);
-$DEBUG_FORMAT = "\n## \$file line \$line : [% \$text %] ##\n";
-
-
-#========================================================================
-# ----- PUBLIC METHODS -----
-#========================================================================
-
-#------------------------------------------------------------------------
-# template($name)
-#
-# General purpose method to fetch a template and return it in compiled
-# form. In the usual case, the $name parameter will be a simple string
-# containing the name of a template (e.g. 'header'). It may also be
-# a reference to Template::Document object (or sub-class) or a Perl
-# sub-routine. These are considered to be compiled templates and are
-# returned intact. Finally, it may be a reference to any other kind
-# of valid input source accepted by Template::Provider (e.g. scalar
-# ref, glob, IO handle, etc).
-#
-# Templates may be cached at one of 3 different levels. The internal
-# BLOCKS member is a local cache which holds references to all
-# template blocks used or imported via PROCESS since the context's
-# reset() method was last called. This is checked first and if the
-# template is not found, the method then walks down the BLOCKSTACK
-# list. This contains references to the block definition tables in
-# any enclosing Template::Documents that we're visiting (e.g. we've
-# been called via an INCLUDE and we want to access a BLOCK defined in
-# the template that INCLUDE'd us). If nothing is defined, then we
-# iterate through the LOAD_TEMPLATES providers list as a 'chain of
-# responsibility' (see Design Patterns) asking each object to fetch()
-# the template if it can.
-#
-# Returns the compiled template. On error, undef is returned and
-# the internal ERROR value (read via error()) is set to contain an
-# error message of the form "$name: $error".
-#------------------------------------------------------------------------
-
-sub template {
- my ($self, $name) = @_;
- my ($prefix, $blocks, $defblocks, $provider, $template, $error);
- my ($shortname, $blockname, $providers);
-
- $self->debug("template($name)") if $self->{ DEBUG };
-
- # references to Template::Document (or sub-class) objects objects, or
- # CODE references are assumed to be pre-compiled templates and are
- # returned intact
- return $name
- if UNIVERSAL::isa($name, 'Template::Document')
- || ref($name) eq 'CODE';
-
- $shortname = $name;
-
- unless (ref $name) {
-
- $self->debug("looking for block [$name]") if $self->{ DEBUG };
-
- # we first look in the BLOCKS hash for a BLOCK that may have
- # been imported from a template (via PROCESS)
- return $template
- if ($template = $self->{ BLOCKS }->{ $name });
-
- # then we iterate through the BLKSTACK list to see if any of the
- # Template::Documents we're visiting define this BLOCK
- foreach $blocks (@{ $self->{ BLKSTACK } }) {
- return $template
- if $blocks && ($template = $blocks->{ $name });
- }
-
- # now it's time to ask the providers, so we look to see if any
- # prefix is specified to indicate the desired provider set.
- if ($^O eq 'MSWin32') {
- # let C:/foo through
- $prefix = $1 if $shortname =~ s/^(\w{2,})://o;
- }
- else {
- $prefix = $1 if $shortname =~ s/^(\w+)://;
- }
-
- if (defined $prefix) {
- $providers = $self->{ PREFIX_MAP }->{ $prefix }
- || return $self->throw( Template::Constants::ERROR_FILE,
- "no providers for template prefix '$prefix'");
- }
- }
- $providers = $self->{ PREFIX_MAP }->{ default }
- || $self->{ LOAD_TEMPLATES }
- unless $providers;
-
-
- # Finally we try the regular template providers which will
- # handle references to files, text, etc., as well as templates
- # reference by name. If
-
- $blockname = '';
- while ($shortname) {
- $self->debug("asking providers for [$shortname] [$blockname]")
- if $self->{ DEBUG };
-
- foreach my $provider (@$providers) {
- ($template, $error) = $provider->fetch($shortname, $prefix);
- if ($error) {
- if ($error == Template::Constants::STATUS_ERROR) {
- # $template contains exception object
- if (UNIVERSAL::isa($template, 'Template::Exception')
- && $template->type() eq Template::Constants::ERROR_FILE) {
- $self->throw($template);
- }
- else {
- $self->throw( Template::Constants::ERROR_FILE, $template );
- }
- }
- # DECLINE is ok, carry on
- }
- elsif (length $blockname) {
- return $template
- if $template = $template->blocks->{ $blockname };
- }
- else {
- return $template;
- }
- }
-
- last if ref $shortname || ! $self->{ EXPOSE_BLOCKS };
- $shortname =~ s{/([^/]+)$}{} || last;
- $blockname = length $blockname ? "$1/$blockname" : $1;
- }
-
- $self->throw(Template::Constants::ERROR_FILE, "$name: not found");
-}
-
-
-#------------------------------------------------------------------------
-# plugin($name, \@args)
-#
-# Calls on each of the LOAD_PLUGINS providers in turn to fetch() (i.e. load
-# and instantiate) a plugin of the specified name. Additional parameters
-# passed are propagated to the new() constructor for the plugin.
-# Returns a reference to a new plugin object or other reference. On
-# error, undef is returned and the appropriate error message is set for
-# subsequent retrieval via error().
-#------------------------------------------------------------------------
-
-sub plugin {
- my ($self, $name, $args) = @_;
- my ($provider, $plugin, $error);
-
- $self->debug("plugin($name, ", defined $args ? @$args : '[ ]', ')')
- if $self->{ DEBUG };
-
- # request the named plugin from each of the LOAD_PLUGINS providers in turn
- foreach my $provider (@{ $self->{ LOAD_PLUGINS } }) {
- ($plugin, $error) = $provider->fetch($name, $args, $self);
- return $plugin unless $error;
- if ($error == Template::Constants::STATUS_ERROR) {
- $self->throw($plugin) if ref $plugin;
- $self->throw(Template::Constants::ERROR_PLUGIN, $plugin);
- }
- }
-
- $self->throw(Template::Constants::ERROR_PLUGIN, "$name: plugin not found");
-}
-
-
-#------------------------------------------------------------------------
-# filter($name, \@args, $alias)
-#
-# Similar to plugin() above, but querying the LOAD_FILTERS providers to
-# return filter instances. An alias may be provided which is used to
-# save the returned filter in a local cache.
-#------------------------------------------------------------------------
-
-sub filter {
- my ($self, $name, $args, $alias) = @_;
- my ($provider, $filter, $error);
-
- $self->debug("filter($name, ",
- defined $args ? @$args : '[ ]',
- defined $alias ? $alias : '<no alias>', ')')
- if $self->{ DEBUG };
-
- # use any cached version of the filter if no params provided
- return $filter
- if ! $args && ! ref $name
- && ($filter = $self->{ FILTER_CACHE }->{ $name });
-
- # request the named filter from each of the FILTERS providers in turn
- foreach my $provider (@{ $self->{ LOAD_FILTERS } }) {
- ($filter, $error) = $provider->fetch($name, $args, $self);
- last unless $error;
- if ($error == Template::Constants::STATUS_ERROR) {
- $self->throw($filter) if ref $filter;
- $self->throw(Template::Constants::ERROR_FILTER, $filter);
- }
- # return $self->error($filter)
- # if $error == &Template::Constants::STATUS_ERROR;
- }
-
- return $self->error("$name: filter not found")
- unless $filter;
-
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- # commented out by abw on 19 Nov 2001 to fix problem with xmlstyle
- # plugin which may re-define a filter by calling define_filter()
- # multiple times. With the automatic aliasing/caching below, any
- # new filter definition isn't seen. Don't think this will cause
- # any problems as filters explicitly supplied with aliases will
- # still work as expected.
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- # alias defaults to name if undefined
- # $alias = $name
- # unless defined($alias) or ref($name) or $args;
-
- # cache FILTER if alias is valid
- $self->{ FILTER_CACHE }->{ $alias } = $filter
- if $alias;
-
- return $filter;
-}
-
-
-#------------------------------------------------------------------------
-# view(\%config)
-#
-# Create a new Template::View bound to this context.
-#------------------------------------------------------------------------
-
-sub view {
- my $self = shift;
- require Template::View;
- return Template::View->new($self, @_)
- || $self->throw(&Template::Constants::ERROR_VIEW,
- $Template::View::ERROR);
-}
-
-
-#------------------------------------------------------------------------
-# process($template, \%params) [% PROCESS template var=val ... %]
-# process($template, \%params, $local) [% INCLUDE template var=val ... %]
-#
-# Processes the template named or referenced by the first parameter.
-# The optional second parameter may reference a hash array of variable
-# definitions. These are set before the template is processed by
-# calling update() on the stash. Note that, unless the third parameter
-# is true, the context is not localised and these, and any other
-# variables set in the template will retain their new values after this
-# method returns. The third parameter is in place so that this method
-# can handle INCLUDE calls: the stash will be localized.
-#
-# Returns the output of processing the template. Errors are thrown
-# as Template::Exception objects via die().
-#------------------------------------------------------------------------
-
-sub process {
- my ($self, $template, $params, $localize) = @_;
- my ($trim, $blocks) = @$self{ qw( TRIM BLOCKS ) };
- my (@compiled, $name, $compiled);
- my ($stash, $component, $tblocks, $error, $tmpout);
- my $output = '';
-
- $template = [ $template ] unless ref $template eq 'ARRAY';
-
- $self->debug("process([ ", join(', '), @$template, ' ], ',
- defined $params ? $params : '<no params>', ', ',
- $localize ? '<localized>' : '<unlocalized>', ')')
- if $self->{ DEBUG };
-
- # fetch compiled template for each name specified
- foreach $name (@$template) {
- push(@compiled, $self->template($name));
- }
-
- if ($localize) {
- # localise the variable stash with any parameters passed
- $stash = $self->{ STASH } = $self->{ STASH }->clone($params);
- } else {
- # update stash with any new parameters passed
- $self->{ STASH }->update($params);
- $stash = $self->{ STASH };
- }
-
- eval {
- # save current component
- eval { $component = $stash->get('component') };
-
- foreach $name (@$template) {
- $compiled = shift @compiled;
- my $element = ref $compiled eq 'CODE'
- ? { (name => (ref $name ? '' : $name), modtime => time()) }
- : $compiled;
-
- if (UNIVERSAL::isa($component, 'Template::Document')) {
- $element->{ caller } = $component->{ name };
- $element->{ callers } = $component->{ callers } || [];
- push(@{$element->{ callers }}, $element->{ caller });
- }
-
- $stash->set('component', $element);
-
- unless ($localize) {
- # merge any local blocks defined in the Template::Document
- # into our local BLOCKS cache
- @$blocks{ keys %$tblocks } = values %$tblocks
- if UNIVERSAL::isa($compiled, 'Template::Document')
- && ($tblocks = $compiled->blocks());
- }
-
- if (ref $compiled eq 'CODE') {
- $tmpout = &$compiled($self);
- }
- elsif (ref $compiled) {
- $tmpout = $compiled->process($self);
- }
- else {
- $self->throw('file',
- "invalid template reference: $compiled");
- }
-
- if ($trim) {
- for ($tmpout) {
- s/^\s+//;
- s/\s+$//;
- }
- }
- $output .= $tmpout;
- }
- $stash->set('component', $component);
- };
- $error = $@;
-
- if ($localize) {
- # ensure stash is delocalised before dying
- $self->{ STASH } = $self->{ STASH }->declone();
- }
-
- $self->throw(ref $error
- ? $error : (Template::Constants::ERROR_FILE, $error))
- if $error;
-
- return $output;
-}
-
-
-#------------------------------------------------------------------------
-# include($template, \%params) [% INCLUDE template var = val, ... %]
-#
-# Similar to process() above but processing the template in a local
-# context. Any variables passed by reference to a hash as the second
-# parameter will be set before the template is processed and then
-# revert to their original values before the method returns. Similarly,
-# any changes made to non-global variables within the template will
-# persist only until the template is processed.
-#
-# Returns the output of processing the template. Errors are thrown
-# as Template::Exception objects via die().
-#------------------------------------------------------------------------
-
-sub include {
- my ($self, $template, $params) = @_;
- return $self->process($template, $params, 'localize me!');
-}
-
-#------------------------------------------------------------------------
-# insert($file)
-#
-# Insert the contents of a file without parsing.
-#------------------------------------------------------------------------
-
-sub insert {
- my ($self, $file) = @_;
- my ($prefix, $providers, $text, $error);
- my $output = '';
-
- my $files = ref $file eq 'ARRAY' ? $file : [ $file ];
-
- $self->debug("insert([ ", join(', '), @$files, " ])")
- if $self->{ DEBUG };
-
-
- FILE: foreach $file (@$files) {
- my $name = $file;
-
- if ($^O eq 'MSWin32') {
- # let C:/foo through
- $prefix = $1 if $name =~ s/^(\w{2,})://o;
- }
- else {
- $prefix = $1 if $name =~ s/^(\w+)://;
- }
-
- if (defined $prefix) {
- $providers = $self->{ PREFIX_MAP }->{ $prefix }
- || return $self->throw(Template::Constants::ERROR_FILE,
- "no providers for file prefix '$prefix'");
- }
- else {
- $providers = $self->{ PREFIX_MAP }->{ default }
- || $self->{ LOAD_TEMPLATES };
- }
-
- foreach my $provider (@$providers) {
- ($text, $error) = $provider->load($name, $prefix);
- next FILE unless $error;
- if ($error == Template::Constants::STATUS_ERROR) {
- $self->throw($text) if ref $text;
- $self->throw(Template::Constants::ERROR_FILE, $text);
- }
- }
- $self->throw(Template::Constants::ERROR_FILE, "$file: not found");
- }
- continue {
- $output .= $text;
- }
- return $output;
-}
-
-
-#------------------------------------------------------------------------
-# throw($type, $info, \$output) [% THROW errtype "Error info" %]
-#
-# Throws a Template::Exception object by calling die(). This method
-# may be passed a reference to an existing Template::Exception object;
-# a single value containing an error message which is used to
-# instantiate a Template::Exception of type 'undef'; or a pair of
-# values representing the exception type and info from which a
-# Template::Exception object is instantiated. e.g.
-#
-# $context->throw($exception);
-# $context->throw("I'm sorry Dave, I can't do that");
-# $context->throw('denied', "I'm sorry Dave, I can't do that");
-#
-# An optional third parameter can be supplied in the last case which
-# is a reference to the current output buffer containing the results
-# of processing the template up to the point at which the exception
-# was thrown. The RETURN and STOP directives, for example, use this
-# to propagate output back to the user, but it can safely be ignored
-# in most cases.
-#
-# This method rides on a one-way ticket to die() oblivion. It does not
-# return in any real sense of the word, but should get caught by a
-# surrounding eval { } block (e.g. a BLOCK or TRY) and handled
-# accordingly, or returned to the caller as an uncaught exception.
-#------------------------------------------------------------------------
-
-sub throw {
- my ($self, $error, $info, $output) = @_;
- local $" = ', ';
-
- # die! die! die!
- if (UNIVERSAL::isa($error, 'Template::Exception')) {
- die $error;
- }
- elsif (defined $info) {
- die (Template::Exception->new($error, $info, $output));
- }
- else {
- $error ||= '';
- die (Template::Exception->new('undef', $error, $output));
- }
-
- # not reached
-}
-
-
-#------------------------------------------------------------------------
-# catch($error, \$output)
-#
-# Called by various directives after catching an error thrown via die()
-# from within an eval { } block. The first parameter contains the errror
-# which may be a sanitized reference to a Template::Exception object
-# (such as that raised by the throw() method above, a plugin object,
-# and so on) or an error message thrown via die from somewhere in user
-# code. The latter are coerced into 'undef' Template::Exception objects.
-# Like throw() above, a reference to a scalar may be passed as an
-# additional parameter to represent the current output buffer
-# localised within the eval block. As exceptions are thrown upwards
-# and outwards from nested blocks, the catch() method reconstructs the
-# correct output buffer from these fragments, storing it in the
-# exception object for passing further onwards and upwards.
-#
-# Returns a reference to a Template::Exception object..
-#------------------------------------------------------------------------
-
-sub catch {
- my ($self, $error, $output) = @_;
-
- if (UNIVERSAL::isa($error, 'Template::Exception')) {
- $error->text($output) if $output;
- return $error;
- }
- else {
- return Template::Exception->new('undef', $error, $output);
- }
-}
-
-
-#------------------------------------------------------------------------
-# localise(\%params)
-# delocalise()
-#
-# The localise() method creates a local copy of the current stash,
-# allowing the existing state of variables to be saved and later
-# restored via delocalise().
-#
-# A reference to a hash array may be passed containing local variable
-# definitions which should be added to the cloned namespace. These
-# values persist until delocalisation.
-#------------------------------------------------------------------------
-
-sub localise {
- my $self = shift;
- $self->{ STASH } = $self->{ STASH }->clone(@_);
-}
-
-sub delocalise {
- my $self = shift;
- $self->{ STASH } = $self->{ STASH }->declone();
-}
-
-
-#------------------------------------------------------------------------
-# visit($document, $blocks)
-#
-# Each Template::Document calls the visit() method on the context
-# before processing itself. It passes a reference to the hash array
-# of named BLOCKs defined within the document, allowing them to be
-# added to the internal BLKSTACK list which is subsequently used by
-# template() to resolve templates.
-# from a provider.
-#------------------------------------------------------------------------
-
-sub visit {
- my ($self, $document, $blocks) = @_;
- unshift(@{ $self->{ BLKSTACK } }, $blocks)
-}
-
-
-#------------------------------------------------------------------------
-# leave()
-#
-# The leave() method is called when the document has finished
-# processing itself. This removes the entry from the BLKSTACK list
-# that was added visit() above. For persistance of BLOCK definitions,
-# the process() method (i.e. the PROCESS directive) does some extra
-# magic to copy BLOCKs into a shared hash.
-#------------------------------------------------------------------------
-
-sub leave {
- my $self = shift;
- shift(@{ $self->{ BLKSTACK } });
-}
-
-
-#------------------------------------------------------------------------
-# define_block($name, $block)
-#
-# Adds a new BLOCK definition to the local BLOCKS cache. $block may
-# be specified as a reference to a sub-routine or Template::Document
-# object or as text which is compiled into a template. Returns a true
-# value (the $block reference or compiled block reference) if
-# succesful or undef on failure. Call error() to retrieve the
-# relevent error message (i.e. compilation failure).
-#------------------------------------------------------------------------
-
-sub define_block {
- my ($self, $name, $block) = @_;
- $block = $self->template(\$block)
- || return undef
- unless ref $block;
- $self->{ BLOCKS }->{ $name } = $block;
-}
-
-
-#------------------------------------------------------------------------
-# define_filter($name, $filter, $is_dynamic)
-#
-# Adds a new FILTER definition to the local FILTER_CACHE.
-#------------------------------------------------------------------------
-
-sub define_filter {
- my ($self, $name, $filter, $is_dynamic) = @_;
- my ($result, $error);
- $filter = [ $filter, 1 ] if $is_dynamic;
-
- foreach my $provider (@{ $self->{ LOAD_FILTERS } }) {
- ($result, $error) = $provider->store($name, $filter);
- return 1 unless $error;
- $self->throw(&Template::Constants::ERROR_FILTER, $result)
- if $error == &Template::Constants::STATUS_ERROR;
- }
- $self->throw(&Template::Constants::ERROR_FILTER,
- "FILTER providers declined to store filter $name");
-}
-
-
-#------------------------------------------------------------------------
-# reset()
-#
-# Reset the state of the internal BLOCKS hash to clear any BLOCK
-# definitions imported via the PROCESS directive. Any original
-# BLOCKS definitions passed to the constructor will be restored.
-#------------------------------------------------------------------------
-
-sub reset {
- my ($self, $blocks) = @_;
- $self->{ BLKSTACK } = [ ];
- $self->{ BLOCKS } = { %{ $self->{ INIT_BLOCKS } } };
-}
-
-
-#------------------------------------------------------------------------
-# stash()
-#
-# Simple accessor methods to return the STASH values. This is likely
-# to be called quite often so we provide a direct method rather than
-# relying on the slower AUTOLOAD.
-#------------------------------------------------------------------------
-
-sub stash {
- return $_[0]->{ STASH };
-}
-
-
-#------------------------------------------------------------------------
-# define_vmethod($type, $name, \&sub)
-#
-# Passes $type, $name, and &sub on to stash->define_vmethod().
-#------------------------------------------------------------------------
-sub define_vmethod {
- my $self = shift;
- $self->stash->define_vmethod(@_);
-}
-
-
-#------------------------------------------------------------------------
-# debugging($command, @args, \%params)
-#
-# Method for controlling the debugging status of the context. The first
-# argument can be 'on' or 'off' to enable/disable debugging, 'format'
-# to define the format of the debug message, or 'msg' to generate a
-# debugging message reporting the file, line, message text, etc.,
-# according to the current debug format.
-#------------------------------------------------------------------------
-
-sub debugging {
- my $self = shift;
- my $hash = ref $_[-1] eq 'HASH' ? pop : { };
- my @args = @_;
-
-# print "*** debug(@args)\n";
- if (@args) {
- if ($args[0] =~ /^on|1$/i) {
- $self->{ DEBUG_DIRS } = 1;
- shift(@args);
- }
- elsif ($args[0] =~ /^off|0$/i) {
- $self->{ DEBUG_DIRS } = 0;
- shift(@args);
- }
- }
-
- if (@args) {
- if ($args[0] =~ /^msg$/i) {
- return unless $self->{ DEBUG_DIRS };
- my $format = $self->{ DEBUG_FORMAT };
- $format = $DEBUG_FORMAT unless defined $format;
- $format =~ s/\$(\w+)/$hash->{ $1 }/ge;
- return $format;
- }
- elsif ($args[0] =~ /^format$/i) {
- $self->{ DEBUG_FORMAT } = $args[1];
- }
- # else ignore
- }
-
- return '';
-}
-
-
-#------------------------------------------------------------------------
-# AUTOLOAD
-#
-# Provides pseudo-methods for read-only access to various internal
-# members. For example, templates(), plugins(), filters(),
-# eval_perl(), load_perl(), etc. These aren't called very often, or
-# may never be called at all.
-#------------------------------------------------------------------------
-
-sub AUTOLOAD {
- my $self = shift;
- my $method = $AUTOLOAD;
- my $result;
-
- $method =~ s/.*:://;
- return if $method eq 'DESTROY';
-
- warn "no such context method/member: $method\n"
- unless defined ($result = $self->{ uc $method });
-
- return $result;
-}
-
-
-#------------------------------------------------------------------------
-# DESTROY
-#
-# Stash may contain references back to the Context via macro closures,
-# etc. This breaks the circular references.
-#------------------------------------------------------------------------
-
-sub DESTROY {
- my $self = shift;
- undef $self->{ STASH };
-}
-
-
-
-#========================================================================
-# -- PRIVATE METHODS --
-#========================================================================
-
-#------------------------------------------------------------------------
-# _init(\%config)
-#
-# Initialisation method called by Template::Base::new()
-#------------------------------------------------------------------------
-
-sub _init {
- my ($self, $config) = @_;
- my ($name, $item, $method, $block, $blocks);
- my @itemlut = (
- LOAD_TEMPLATES => 'provider',
- LOAD_PLUGINS => 'plugins',
- LOAD_FILTERS => 'filters'
- );
-
- # LOAD_TEMPLATE, LOAD_PLUGINS, LOAD_FILTERS - lists of providers
- while (($name, $method) = splice(@itemlut, 0, 2)) {
- $item = $config->{ $name }
- || Template::Config->$method($config)
- || return $self->error($Template::Config::ERROR);
- $self->{ $name } = ref $item eq 'ARRAY' ? $item : [ $item ];
- }
-
- my $providers = $self->{ LOAD_TEMPLATES };
- my $prefix_map = $self->{ PREFIX_MAP } = $config->{ PREFIX_MAP } || { };
- while (my ($key, $val) = each %$prefix_map) {
- $prefix_map->{ $key } = [ ref $val ? $val :
- map { $providers->[$_] }
- split(/\D+/, $val) ]
- unless ref $val eq 'ARRAY';
-# print(STDERR "prefix $key => $val => [",
-# join(', ', @{ $prefix_map->{ $key } }), "]\n");
- }
-
- # STASH
- $self->{ STASH } = $config->{ STASH } || do {
- my $predefs = $config->{ VARIABLES }
- || $config->{ PRE_DEFINE }
- || { };
-
- # hack to get stash to know about debug mode
- $predefs->{ _DEBUG } = ( ($config->{ DEBUG } || 0)
- & &Template::Constants::DEBUG_UNDEF ) ? 1 : 0
- unless defined $predefs->{ _DEBUG };
-
- Template::Config->stash($predefs)
- || return $self->error($Template::Config::ERROR);
- };
-
- # compile any template BLOCKS specified as text
- $blocks = $config->{ BLOCKS } || { };
- $self->{ INIT_BLOCKS } = $self->{ BLOCKS } = {
- map {
- $block = $blocks->{ $_ };
- $block = $self->template(\$block)
- || return undef
- unless ref $block;
- ($_ => $block);
- }
- keys %$blocks
- };
-
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- # RECURSION - flag indicating is recursion into templates is supported
- # EVAL_PERL - flag indicating if PERL blocks should be processed
- # TRIM - flag to remove leading and trailing whitespace from output
- # BLKSTACK - list of hashes of BLOCKs defined in current template(s)
- # CONFIG - original configuration hash
- # EXPOSE_BLOCKS - make blocks visible as pseudo-files
- # DEBUG_FORMAT - format for generating template runtime debugging messages
- # DEBUG - format for generating template runtime debugging messages
-
- $self->{ RECURSION } = $config->{ RECURSION } || 0;
- $self->{ EVAL_PERL } = $config->{ EVAL_PERL } || 0;
- $self->{ TRIM } = $config->{ TRIM } || 0;
- $self->{ BLKSTACK } = [ ];
- $self->{ CONFIG } = $config;
- $self->{ EXPOSE_BLOCKS } = defined $config->{ EXPOSE_BLOCKS }
- ? $config->{ EXPOSE_BLOCKS }
- : 0;
-
- $self->{ DEBUG_FORMAT } = $config->{ DEBUG_FORMAT };
- $self->{ DEBUG_DIRS } = ($config->{ DEBUG } || 0)
- & Template::Constants::DEBUG_DIRS;
- $self->{ DEBUG } = defined $config->{ DEBUG }
- ? $config->{ DEBUG } & ( Template::Constants::DEBUG_CONTEXT
- | Template::Constants::DEBUG_FLAGS )
- : $DEBUG;
-
- return $self;
-}
-
-
-#------------------------------------------------------------------------
-# _dump()
-#
-# Debug method which returns a string representing the internal state
-# of the context object.
-#------------------------------------------------------------------------
-
-sub _dump {
- my $self = shift;
- my $output = "[Template::Context] {\n";
- my $format = " %-16s => %s\n";
- my $key;
-
- foreach $key (qw( RECURSION EVAL_PERL TRIM )) {
- $output .= sprintf($format, $key, $self->{ $key });
- }
- foreach my $pname (qw( LOAD_TEMPLATES LOAD_PLUGINS LOAD_FILTERS )) {
- my $provtext = "[\n";
- foreach my $prov (@{ $self->{ $pname } }) {
- $provtext .= $prov->_dump();
-# $provtext .= ",\n";
- }
- $provtext =~ s/\n/\n /g;
- $provtext =~ s/\s+$//;
- $provtext .= ",\n ]";
- $output .= sprintf($format, $pname, $provtext);
- }
- $output .= sprintf($format, STASH => $self->{ STASH }->_dump());
- $output .= '}';
- return $output;
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Context - Runtime context in which templates are processed
-
-=head1 SYNOPSIS
-
- use Template::Context;
-
- # constructor
- $context = Template::Context->new(\%config)
- || die $Template::Context::ERROR;
-
- # fetch (load and compile) a template
- $template = $context->template($template_name);
-
- # fetch (load and instantiate) a plugin object
- $plugin = $context->plugin($name, \@args);
-
- # fetch (return or create) a filter subroutine
- $filter = $context->filter($name, \@args, $alias);
-
- # process/include a template, errors are thrown via die()
- $output = $context->process($template, \%vars);
- $output = $context->include($template, \%vars);
-
- # raise an exception via die()
- $context->throw($error_type, $error_message, \$output_buffer);
-
- # catch an exception, clean it up and fix output buffer
- $exception = $context->catch($exception, \$output_buffer);
-
- # save/restore the stash to effect variable localisation
- $new_stash = $context->localise(\%vars);
- $old_stash = $context->delocalise();
-
- # add new BLOCK or FILTER definitions
- $context->define_block($name, $block);
- $context->define_filter($name, \&filtersub, $is_dynamic);
-
- # reset context, clearing any imported BLOCK definitions
- $context->reset();
-
- # methods for accessing internal items
- $stash = $context->stash();
- $tflag = $context->trim();
- $epflag = $context->eval_perl();
- $providers = $context->templates();
- $providers = $context->plugins();
- $providers = $context->filters();
- ...
-
-=head1 DESCRIPTION
-
-The Template::Context module defines an object class for representing
-a runtime context in which templates are processed. It provides an
-interface to the fundamental operations of the Template Toolkit
-processing engine through which compiled templates (i.e. Perl code
-constructed from the template source) can process templates, load
-plugins and filters, raise exceptions and so on.
-
-A default Template::Context object is created by the Template module.
-Any Template::Context options may be passed to the Template new()
-constructor method and will be forwarded to the Template::Context
-constructor.
-
- use Template;
-
- my $template = Template->new({
- TRIM => 1,
- EVAL_PERL => 1,
- BLOCKS => {
- header => 'This is the header',
- footer => 'This is the footer',
- },
- });
-
-Similarly, the Template::Context constructor will forward all configuration
-parameters onto other default objects (e.g. Template::Provider, Template::Plugins,
-Template::Filters, etc.) that it may need to instantiate.
-
- $context = Template::Context->new({
- INCLUDE_PATH => '/home/abw/templates', # provider option
- TAG_STYLE => 'html', # parser option
- });
-
-A Template::Context object (or subclass/derivative) can be explicitly
-instantiated and passed to the Template new() constructor method as
-the CONTEXT item.
-
- use Template;
- use Template::Context;
-
- my $context = Template::Context->new({ TRIM => 1 });
- my $template = Template->new({ CONTEXT => $context });
-
-The Template module uses the Template::Config context() factory method
-to create a default context object when required. The
-$Template::Config::CONTEXT package variable may be set to specify an
-alternate context module. This will be loaded automatically and its
-new() constructor method called by the context() factory method when
-a default context object is required.
-
- use Template;
-
- $Template::Config::CONTEXT = 'MyOrg::Template::Context';
-
- my $template = Template->new({
- EVAL_PERL => 1,
- EXTRA_MAGIC => 'red hot', # your extra config items
- ...
- });
-
-=head1 METHODS
-
-=head2 new(\%params)
-
-The new() constructor method is called to instantiate a Template::Context
-object. Configuration parameters may be specified as a HASH reference or
-as a list of (name =E<gt> value) pairs.
-
- my $context = Template::Context->new({
- INCLUDE_PATH => 'header',
- POST_PROCESS => 'footer',
- });
-
- my $context = Template::Context->new( EVAL_PERL => 1 );
-
-The new() method returns a Template::Context object (or sub-class) or
-undef on error. In the latter case, a relevant error message can be
-retrieved by the error() class method or directly from the
-$Template::Context::ERROR package variable.
-
- my $context = Template::Context->new(\%config)
- || die Template::Context->error();
-
- my $context = Template::Context->new(\%config)
- || die $Template::Context::ERROR;
-
-The following configuration items may be specified.
-
-=over 4
-
-
-=item VARIABLES, PRE_DEFINE
-
-The VARIABLES option (or PRE_DEFINE - they're equivalent) can be used
-to specify a hash array of template variables that should be used to
-pre-initialise the stash when it is created. These items are ignored
-if the STASH item is defined.
-
- my $context = Template::Context->new({
- VARIABLES => {
- title => 'A Demo Page',
- author => 'Joe Random Hacker',
- version => 3.14,
- },
- };
-
-or
-
- my $context = Template::Context->new({
- PRE_DEFINE => {
- title => 'A Demo Page',
- author => 'Joe Random Hacker',
- version => 3.14,
- },
- };
-
-
-
-
-
-=item BLOCKS
-
-The BLOCKS option can be used to pre-define a default set of template
-blocks. These should be specified as a reference to a hash array
-mapping template names to template text, subroutines or Template::Document
-objects.
-
- my $context = Template::Context->new({
- BLOCKS => {
- header => 'The Header. [% title %]',
- footer => sub { return $some_output_text },
- another => Template::Document->new({ ... }),
- },
- });
-
-
-
-
-
-=item TRIM
-
-The TRIM option can be set to have any leading and trailing whitespace
-automatically removed from the output of all template files and BLOCKs.
-
-By example, the following BLOCK definition
-
- [% BLOCK foo %]
- Line 1 of foo
- [% END %]
-
-will be processed is as "\nLine 1 of foo\n". When INCLUDEd, the surrounding
-newlines will also be introduced.
-
- before
- [% INCLUDE foo %]
- after
-
-output:
- before
-
- Line 1 of foo
-
- after
-
-With the TRIM option set to any true value, the leading and trailing
-newlines (which count as whitespace) will be removed from the output
-of the BLOCK.
-
- before
- Line 1 of foo
- after
-
-The TRIM option is disabled (0) by default.
-
-
-
-
-
-
-=item EVAL_PERL
-
-This flag is used to indicate if PERL and/or RAWPERL blocks should be
-evaluated. By default, it is disabled and any PERL or RAWPERL blocks
-encountered will raise exceptions of type 'perl' with the message
-'EVAL_PERL not set'. Note however that any RAWPERL blocks should
-always contain valid Perl code, regardless of the EVAL_PERL flag. The
-parser will fail to compile templates that contain invalid Perl code
-in RAWPERL blocks and will throw a 'file' exception.
-
-When using compiled templates (see
-L<COMPILE_EXT|Template::Manual::Config/Caching_and_Compiling_Options> and
-L<COMPILE_DIR|Template::Manual::Config/Caching_and_Compiling_Options>),
-the EVAL_PERL has an affect when the template is compiled, and again
-when the templates is subsequently processed, possibly in a different
-context to the one that compiled it.
-
-If the EVAL_PERL is set when a template is compiled, then all PERL and
-RAWPERL blocks will be included in the compiled template. If the
-EVAL_PERL option isn't set, then Perl code will be generated which
-B<always> throws a 'perl' exception with the message 'EVAL_PERL not
-set' B<whenever> the compiled template code is run.
-
-Thus, you must have EVAL_PERL set if you want your compiled templates
-to include PERL and RAWPERL blocks.
-
-At some point in the future, using a different invocation of the
-Template Toolkit, you may come to process such a pre-compiled
-template. Assuming the EVAL_PERL option was set at the time the
-template was compiled, then the output of any RAWPERL blocks will be
-included in the compiled template and will get executed when the
-template is processed. This will happen regardless of the runtime
-EVAL_PERL status.
-
-Regular PERL blocks are a little more cautious, however. If the
-EVAL_PERL flag isn't set for the I<current> context, that is, the
-one which is trying to process it, then it will throw the familiar 'perl'
-exception with the message, 'EVAL_PERL not set'.
-
-Thus you can compile templates to include PERL blocks, but optionally
-disable them when you process them later. Note however that it is
-possible for a PERL block to contain a Perl "BEGIN { # some code }"
-block which will always get run regardless of the runtime EVAL_PERL
-status. Thus, if you set EVAL_PERL when compiling templates, it is
-assumed that you trust the templates to Do The Right Thing. Otherwise
-you must accept the fact that there's no bulletproof way to prevent
-any included code from trampling around in the living room of the
-runtime environment, making a real nuisance of itself if it really
-wants to. If you don't like the idea of such uninvited guests causing
-a bother, then you can accept the default and keep EVAL_PERL disabled.
-
-
-
-
-
-
-
-=item RECURSION
-
-The template processor will raise a file exception if it detects
-direct or indirect recursion into a template. Setting this option to
-any true value will allow templates to include each other recursively.
-
-
-
-=item LOAD_TEMPLATES
-
-The LOAD_TEMPLATE option can be used to provide a reference to a list
-of Template::Provider objects or sub-classes thereof which will take
-responsibility for loading and compiling templates.
-
- my $context = Template::Context->new({
- LOAD_TEMPLATES => [
- MyOrg::Template::Provider->new({ ... }),
- Template::Provider->new({ ... }),
- ],
- });
-
-When a PROCESS, INCLUDE or WRAPPER directive is encountered, the named
-template may refer to a locally defined BLOCK or a file relative to
-the INCLUDE_PATH (or an absolute or relative path if the appropriate
-ABSOLUTE or RELATIVE options are set). If a BLOCK definition can't be
-found (see the Template::Context template() method for a discussion of
-BLOCK locality) then each of the LOAD_TEMPLATES provider objects is
-queried in turn via the fetch() method to see if it can supply the
-required template. Each provider can return a compiled template, an
-error, or decline to service the request in which case the
-responsibility is passed to the next provider. If none of the
-providers can service the request then a 'not found' error is
-returned. The same basic provider mechanism is also used for the
-INSERT directive but it bypasses any BLOCK definitions and doesn't
-attempt is to parse or process the contents of the template file.
-
-This is an implementation of the 'Chain of Responsibility'
-design pattern as described in
-"Design Patterns", Erich Gamma, Richard Helm, Ralph Johnson, John
-Vlissides), Addision-Wesley, ISBN 0-201-63361-2, page 223
-.
-
-If LOAD_TEMPLATES is undefined, a single default provider will be
-instantiated using the current configuration parameters. For example,
-the Template::Provider INCLUDE_PATH option can be specified in the Template::Context configuration and will be correctly passed to the provider's
-constructor method.
-
- my $context = Template::Context->new({
- INCLUDE_PATH => '/here:/there',
- });
-
-
-
-
-
-=item LOAD_PLUGINS
-
-The LOAD_PLUGINS options can be used to specify a list of provider
-objects (i.e. they implement the fetch() method) which are responsible
-for loading and instantiating template plugin objects. The
-Template::Content plugin() method queries each provider in turn in a
-"Chain of Responsibility" as per the template() and filter() methods.
-
- my $context = Template::Context->new({
- LOAD_PLUGINS => [
- MyOrg::Template::Plugins->new({ ... }),
- Template::Plugins->new({ ... }),
- ],
- });
-
-By default, a single Template::Plugins object is created using the
-current configuration hash. Configuration items destined for the
-Template::Plugins constructor may be added to the Template::Context
-constructor.
-
- my $context = Template::Context->new({
- PLUGIN_BASE => 'MyOrg::Template::Plugins',
- LOAD_PERL => 1,
- });
-
-
-
-
-
-=item LOAD_FILTERS
-
-The LOAD_FILTERS option can be used to specify a list of provider
-objects (i.e. they implement the fetch() method) which are responsible
-for returning and/or creating filter subroutines. The
-Template::Context filter() method queries each provider in turn in a
-"Chain of Responsibility" as per the template() and plugin() methods.
-
- my $context = Template::Context->new({
- LOAD_FILTERS => [
- MyTemplate::Filters->new(),
- Template::Filters->new(),
- ],
- });
-
-By default, a single Template::Filters object is created for the
-LOAD_FILTERS list.
-
-
-
-=item STASH
-
-A reference to a Template::Stash object or sub-class which will take
-responsibility for managing template variables.
-
- my $stash = MyOrg::Template::Stash->new({ ... });
- my $context = Template::Context->new({
- STASH => $stash,
- });
-
-If unspecified, a default stash object is created using the VARIABLES
-configuration item to initialise the stash variables. These may also
-be specified as the PRE_DEFINE option for backwards compatibility with
-version 1.
-
- my $context = Template::Context->new({
- VARIABLES => {
- id => 'abw',
- name => 'Andy Wardley',
- },
- };
-
-
-
-=item DEBUG
-
-The DEBUG option can be used to enable various debugging features
-of the Template::Context module.
-
- use Template::Constants qw( :debug );
-
- my $template = Template->new({
- DEBUG => DEBUG_CONTEXT | DEBUG_DIRS,
- });
-
-The DEBUG value can include any of the following. Multiple values
-should be combined using the logical OR operator, '|'.
-
-=over 4
-
-=item DEBUG_CONTEXT
-
-Enables general debugging messages for the
-L<Template::Context|Template::Context> module.
-
-=item DEBUG_DIRS
-
-This option causes the Template Toolkit to generate comments
-indicating the source file, line and original text of each directive
-in the template. These comments are embedded in the template output
-using the format defined in the DEBUG_FORMAT configuration item, or a
-simple default format if unspecified.
-
-For example, the following template fragment:
-
-
- Hello World
-
-would generate this output:
-
- ## input text line 1 : ##
- Hello
- ## input text line 2 : World ##
- World
-
-
-=back
-
-
-
-
-
-=back
-
-=head2 template($name)
-
-Returns a compiled template by querying each of the LOAD_TEMPLATES providers
-(instances of Template::Provider, or sub-class) in turn.
-
- $template = $context->template('header');
-
-On error, a Template::Exception object of type 'file' is thrown via
-die(). This can be caught by enclosing the call to template() in an
-eval block and examining $@.
-
- eval {
- $template = $context->template('header');
- };
- if ($@) {
- print "failed to fetch template: $@\n";
- }
-
-=head2 plugin($name, \@args)
-
-Instantiates a plugin object by querying each of the LOAD_PLUGINS
-providers. The default LOAD_PLUGINS provider is a Template::Plugins
-object which attempts to load plugin modules, according the various
-configuration items such as PLUGIN_BASE, LOAD_PERL, etc., and then
-instantiate an object via new(). A reference to a list of constructor
-arguments may be passed as the second parameter. These are forwarded
-to the plugin constructor.
-
-Returns a reference to a plugin (which is generally an object, but
-doesn't have to be). Errors are thrown as Template::Exception objects
-of type 'plugin'.
-
- $plugin = $context->plugin('DBI', 'dbi:msql:mydbname');
-
-=head2 filter($name, \@args, $alias)
-
-Instantiates a filter subroutine by querying the LOAD_FILTERS providers.
-The default LOAD_FILTERS providers is a Template::Filters object.
-Additional arguments may be passed by list reference along with an
-optional alias under which the filter will be cached for subsequent
-use. The filter is cached under its own $name if $alias is undefined.
-Subsequent calls to filter($name) will return the cached entry, if
-defined. Specifying arguments bypasses the caching mechanism and
-always creates a new filter. Errors are thrown as Template::Exception
-objects of typre 'filter'.
-
- # static filter (no args)
- $filter = $context->filter('html');
-
- # dynamic filter (args) aliased to 'padright'
- $filter = $context->filter('format', '%60s', 'padright');
-
- # retrieve previous filter via 'padright' alias
- $filter = $context->filter('padright');
-
-=head2 process($template, \%vars)
-
-Processes a template named or referenced by the first parameter and returns
-the output generated. An optional reference to a hash array may be passed
-as the second parameter, containing variable definitions which will be set
-before the template is processed. The template is processed in the current
-context, with no localisation of variables performed. Errors are thrown
-as Template::Exception objects via die().
-
- $output = $context->process('header', { title => 'Hello World' });
-
-=head2 include($template, \%vars)
-
-Similar to process() above, but using localised variables. Changes made to
-any variables will only persist until the include() method completes.
-
- $output = $context->include('header', { title => 'Hello World' });
-
-=head2 throw($error_type, $error_message, \$output)
-
-Raises an exception in the form of a Template::Exception object by
-calling die(). This method may be passed a reference to an existing
-Template::Exception object; a single value containing an error message
-which is used to instantiate a Template::Exception of type 'undef'; or
-a pair of values representing the exception type and info from which a
-Template::Exception object is instantiated. e.g.
-
- $context->throw($exception);
- $context->throw("I'm sorry Dave, I can't do that");
- $context->throw('denied', "I'm sorry Dave, I can't do that");
-
-The optional third parameter may be a reference to the current output
-buffer. This is then stored in the exception object when created,
-allowing the catcher to examine and use the output up to the point at
-which the exception was raised.
-
- $output .= 'blah blah blah';
- $output .= 'more rhubarb';
- $context->throw('yack', 'Too much yacking', \$output);
-
-=head2 catch($exception, \$output)
-
-Catches an exception thrown, either as a reference to a
-Template::Exception object or some other value. In the latter case,
-the error string is promoted to a Template::Exception object of
-'undef' type. This method also accepts a reference to the current
-output buffer which is passed to the Template::Exception constructor,
-or is appended to the output buffer stored in an existing
-Template::Exception object, if unique (i.e. not the same reference).
-By this process, the correct state of the output buffer can be
-reconstructed for simple or nested throws.
-
-=head2 define_block($name, $block)
-
-Adds a new block definition to the internal BLOCKS cache. The first
-argument should contain the name of the block and the second a reference
-to a Template::Document object or template sub-routine, or template text
-which is automatically compiled into a template sub-routine. Returns
-a true value (the sub-routine or Template::Document reference) on
-success or undef on failure. The relevant error message can be
-retrieved by calling the error() method.
-
-=head2 define_filter($name, \&filter, $is_dynamic)
-
-Adds a new filter definition by calling the store() method on each of
-the LOAD_FILTERS providers until accepted (in the usual case, this is
-accepted straight away by the one and only Template::Filters
-provider). The first argument should contain the name of the filter
-and the second a reference to a filter subroutine. The optional
-third argument can be set to any true value to indicate that the
-subroutine is a dynamic filter factory. Returns a true value or
-throws a 'filter' exception on error.
-
-=head2 localise(\%vars)
-
-Clones the stash to create a context with localised variables. Returns a
-reference to the newly cloned stash object which is also stored
-internally.
-
- $stash = $context->localise();
-
-=head2 delocalise()
-
-Restore the stash to its state prior to localisation.
-
- $stash = $context->delocalise();
-
-=head2 visit(\%blocks)
-
-This method is called by Template::Document objects immediately before
-they process their content. It is called to register any local BLOCK
-definitions with the context object so that they may be subsequently
-delivered on request.
-
-=head2 leave()
-
-Compliment to visit(), above. Called by Template::Document objects
-immediately after they process their content.
-
-=head2 reset()
-
-Clears the local BLOCKS cache of any BLOCK definitions. Any initial set of
-BLOCKS specified as a configuration item to the constructor will be reinstated.
-
-=head2 AUTOLOAD
-
-An AUTOLOAD method provides access to context configuration items.
-
- $stash = $context->stash();
- $tflag = $context->trim();
- $epflag = $context->eval_perl();
- ...
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.89, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template|Template>, L<Template::Document|Template::Document>, L<Template::Exception|Template::Exception>, L<Template::Filters|Template::Filters>, L<Template::Plugins|Template::Plugins>, L<Template::Provider|Template::Provider>, L<Template::Service|Template::Service>, L<Template::Stash|Template::Stash>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Directive.pm b/lib/Template/Directive.pm
deleted file mode 100644
index c3f86a9..0000000
--- a/lib/Template/Directive.pm
+++ /dev/null
@@ -1,1004 +0,0 @@
-#================================================================= -*-Perl-*-
-#
-# Template::Directive
-#
-# DESCRIPTION
-# Factory module for constructing templates from Perl code.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# WARNING
-# Much of this module is hairy, even furry in places. It needs
-# a lot of tidying up and may even be moved into a different place
-# altogether. The generator code is often inefficient, particulary in
-# being very anal about pretty-printing the Perl code all neatly, but
-# at the moment, that's still high priority for the sake of easier
-# debugging.
-#
-# COPYRIGHT
-# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Directive.pm,v 2.18 2003/10/08 09:34:41 abw Exp $
-#
-#============================================================================
-
-package Template::Directive;
-
-require 5.004;
-
-use strict;
-use Template::Base;
-use Template::Constants;
-use Template::Exception;
-
-use base qw( Template::Base );
-use vars qw( $VERSION $DEBUG $PRETTY $WHILE_MAX $OUTPUT );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.18 $ =~ /(\d+)\.(\d+)/);
-
-$WHILE_MAX = 1000 unless defined $WHILE_MAX;
-$PRETTY = 0 unless defined $PRETTY;
-$OUTPUT = '$output .= ';
-
-
-sub _init {
- my ($self, $config) = @_;
- $self->{ NAMESPACE } = $config->{ NAMESPACE };
- return $self;
-}
-
-
-sub pad {
- my ($text, $pad) = @_;
- $pad = ' ' x ($pad * 4);
- $text =~ s/^(?!#line)/$pad/gm;
- $text;
-}
-
-#========================================================================
-# FACTORY METHODS
-#
-# These methods are called by the parser to construct directive instances.
-#========================================================================
-
-#------------------------------------------------------------------------
-# template($block)
-#------------------------------------------------------------------------
-
-sub template {
- my ($class, $block) = @_;
- $block = pad($block, 2) if $PRETTY;
-
- return "sub { return '' }" unless $block =~ /\S/;
-
- return <<EOF;
-sub {
- my \$context = shift || die "template sub called without context\\n";
- my \$stash = \$context->stash;
- my \$output = '';
- my \$error;
-
- eval { BLOCK: {
-$block
- } };
- if (\$@) {
- \$error = \$context->catch(\$@, \\\$output);
- die \$error unless \$error->type eq 'return';
- }
-
- return \$output;
-}
-EOF
-}
-
-
-#------------------------------------------------------------------------
-# anon_block($block) [% BLOCK %] ... [% END %]
-#------------------------------------------------------------------------
-
-sub anon_block {
- my ($class, $block) = @_;
- $block = pad($block, 2) if $PRETTY;
-
- return <<EOF;
-
-# BLOCK
-$OUTPUT do {
- my \$output = '';
- my \$error;
-
- eval { BLOCK: {
-$block
- } };
- if (\$@) {
- \$error = \$context->catch(\$@, \\\$output);
- die \$error unless \$error->type eq 'return';
- }
-
- \$output;
-};
-EOF
-}
-
-
-#------------------------------------------------------------------------
-# block($blocktext)
-#------------------------------------------------------------------------
-
-sub block {
- my ($class, $block) = @_;
- return join("\n", @{ $block || [] });
-}
-
-
-#------------------------------------------------------------------------
-# textblock($text)
-#------------------------------------------------------------------------
-
-sub textblock {
- my ($class, $text) = @_;
- return "$OUTPUT " . &text($class, $text) . ';';
-}
-
-
-#------------------------------------------------------------------------
-# text($text)
-#------------------------------------------------------------------------
-
-sub text {
- my ($class, $text) = @_;
- for ($text) {
- s/(["\$\@\\])/\\$1/g;
- s/\n/\\n/g;
- }
- return '"' . $text . '"';
-}
-
-
-#------------------------------------------------------------------------
-# quoted(\@items) "foo$bar"
-#------------------------------------------------------------------------
-
-sub quoted {
- my ($class, $items) = @_;
- return '' unless @$items;
- return ("('' . " . $items->[0] . ')') if scalar @$items == 1;
- return '(' . join(' . ', @$items) . ')';
-# my $r = '(' . join(' . ', @$items) . ' . "")';
-# print STDERR "[$r]\n";
-# return $r;
-}
-
-
-#------------------------------------------------------------------------
-# ident(\@ident) foo.bar(baz)
-#------------------------------------------------------------------------
-
-sub ident {
- my ($class, $ident) = @_;
- return "''" unless @$ident;
- my $ns;
-
- # does the first element of the identifier have a NAMESPACE
- # handler defined?
- if (ref $class && @$ident > 2 && ($ns = $class->{ NAMESPACE })) {
- my $key = $ident->[0];
- $key =~ s/^'(.+)'$/$1/s;
- if ($ns = $ns->{ $key }) {
- return $ns->ident($ident);
- }
- }
-
- if (scalar @$ident <= 2 && ! $ident->[1]) {
- $ident = $ident->[0];
- }
- else {
- $ident = '[' . join(', ', @$ident) . ']';
- }
- return "\$stash->get($ident)";
-}
-
-#------------------------------------------------------------------------
-# identref(\@ident) \foo.bar(baz)
-#------------------------------------------------------------------------
-
-sub identref {
- my ($class, $ident) = @_;
- return "''" unless @$ident;
- if (scalar @$ident <= 2 && ! $ident->[1]) {
- $ident = $ident->[0];
- }
- else {
- $ident = '[' . join(', ', @$ident) . ']';
- }
- return "\$stash->getref($ident)";
-}
-
-
-#------------------------------------------------------------------------
-# assign(\@ident, $value, $default) foo = bar
-#------------------------------------------------------------------------
-
-sub assign {
- my ($class, $var, $val, $default) = @_;
-
- if (ref $var) {
- if (scalar @$var == 2 && ! $var->[1]) {
- $var = $var->[0];
- }
- else {
- $var = '[' . join(', ', @$var) . ']';
- }
- }
- $val .= ', 1' if $default;
- return "\$stash->set($var, $val)";
-}
-
-
-#------------------------------------------------------------------------
-# args(\@args) foo, bar, baz = qux
-#------------------------------------------------------------------------
-
-sub args {
- my ($class, $args) = @_;
- my $hash = shift @$args;
- push(@$args, '{ ' . join(', ', @$hash) . ' }')
- if @$hash;
-
- return '0' unless @$args;
- return '[ ' . join(', ', @$args) . ' ]';
-}
-
-#------------------------------------------------------------------------
-# filenames(\@names)
-#------------------------------------------------------------------------
-
-sub filenames {
- my ($class, $names) = @_;
- if (@$names > 1) {
- $names = '[ ' . join(', ', @$names) . ' ]';
- }
- else {
- $names = shift @$names;
- }
- return $names;
-}
-
-
-#------------------------------------------------------------------------
-# get($expr) [% foo %]
-#------------------------------------------------------------------------
-
-sub get {
- my ($class, $expr) = @_;
- return "$OUTPUT $expr;";
-}
-
-
-#------------------------------------------------------------------------
-# call($expr) [% CALL bar %]
-#------------------------------------------------------------------------
-
-sub call {
- my ($class, $expr) = @_;
- $expr .= ';';
- return $expr;
-}
-
-
-#------------------------------------------------------------------------
-# set(\@setlist) [% foo = bar, baz = qux %]
-#------------------------------------------------------------------------
-
-sub set {
- my ($class, $setlist) = @_;
- my $output;
- while (my ($var, $val) = splice(@$setlist, 0, 2)) {
- $output .= &assign($class, $var, $val) . ";\n";
- }
- chomp $output;
- return $output;
-}
-
-
-#------------------------------------------------------------------------
-# default(\@setlist) [% DEFAULT foo = bar, baz = qux %]
-#------------------------------------------------------------------------
-
-sub default {
- my ($class, $setlist) = @_;
- my $output;
- while (my ($var, $val) = splice(@$setlist, 0, 2)) {
- $output .= &assign($class, $var, $val, 1) . ";\n";
- }
- chomp $output;
- return $output;
-}
-
-
-#------------------------------------------------------------------------
-# insert(\@nameargs) [% INSERT file %]
-# # => [ [ $file, ... ], \@args ]
-#------------------------------------------------------------------------
-
-sub insert {
- my ($class, $nameargs) = @_;
- my ($file, $args) = @$nameargs;
- $file = $class->filenames($file);
- return "$OUTPUT \$context->insert($file);";
-}
-
-
-#------------------------------------------------------------------------
-# include(\@nameargs) [% INCLUDE template foo = bar %]
-# # => [ [ $file, ... ], \@args ]
-#------------------------------------------------------------------------
-
-sub include {
- my ($class, $nameargs) = @_;
- my ($file, $args) = @$nameargs;
- my $hash = shift @$args;
- $file = $class->filenames($file);
- $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';
- return "$OUTPUT \$context->include($file);";
-}
-
-
-#------------------------------------------------------------------------
-# process(\@nameargs) [% PROCESS template foo = bar %]
-# # => [ [ $file, ... ], \@args ]
-#------------------------------------------------------------------------
-
-sub process {
- my ($class, $nameargs) = @_;
- my ($file, $args) = @$nameargs;
- my $hash = shift @$args;
- $file = $class->filenames($file);
- $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';
- return "$OUTPUT \$context->process($file);";
-}
-
-
-#------------------------------------------------------------------------
-# if($expr, $block, $else) [% IF foo < bar %]
-# ...
-# [% ELSE %]
-# ...
-# [% END %]
-#------------------------------------------------------------------------
-
-sub if {
- my ($class, $expr, $block, $else) = @_;
- my @else = $else ? @$else : ();
- $else = pop @else;
- $block = pad($block, 1) if $PRETTY;
-
- my $output = "if ($expr) {\n$block\n}\n";
-
- foreach my $elsif (@else) {
- ($expr, $block) = @$elsif;
- $block = pad($block, 1) if $PRETTY;
- $output .= "elsif ($expr) {\n$block\n}\n";
- }
- if (defined $else) {
- $else = pad($else, 1) if $PRETTY;
- $output .= "else {\n$else\n}\n";
- }
-
- return $output;
-}
-
-
-#------------------------------------------------------------------------
-# foreach($target, $list, $args, $block) [% FOREACH x = [ foo bar ] %]
-# ...
-# [% END %]
-#------------------------------------------------------------------------
-
-sub foreach {
- my ($class, $target, $list, $args, $block) = @_;
- $args = shift @$args;
- $args = @$args ? ', { ' . join(', ', @$args) . ' }' : '';
-
- my ($loop_save, $loop_set, $loop_restore, $setiter);
- if ($target) {
- $loop_save = 'eval { $oldloop = ' . &ident($class, ["'loop'"]) . ' }';
- $loop_set = "\$stash->{'$target'} = \$value";
- $loop_restore = "\$stash->set('loop', \$oldloop)";
- }
- else {
- $loop_save = '$stash = $context->localise()';
-# $loop_set = "\$stash->set('import', \$value) "
-# . "if ref \$value eq 'HASH'";
- $loop_set = "\$stash->get(['import', [\$value]]) "
- . "if ref \$value eq 'HASH'";
- $loop_restore = '$stash = $context->delocalise()';
- }
- $block = pad($block, 3) if $PRETTY;
-
- return <<EOF;
-
-# FOREACH
-do {
- my (\$value, \$error, \$oldloop);
- my \$list = $list;
-
- unless (UNIVERSAL::isa(\$list, 'Template::Iterator')) {
- \$list = Template::Config->iterator(\$list)
- || die \$Template::Config::ERROR, "\\n";
- }
-
- (\$value, \$error) = \$list->get_first();
- $loop_save;
- \$stash->set('loop', \$list);
- eval {
-LOOP: while (! \$error) {
- $loop_set;
-$block;
- (\$value, \$error) = \$list->get_next();
- }
- };
- $loop_restore;
- die \$@ if \$@;
- \$error = 0 if \$error && \$error eq Template::Constants::STATUS_DONE;
- die \$error if \$error;
-};
-EOF
-}
-
-#------------------------------------------------------------------------
-# next() [% NEXT %]
-#
-# Next iteration of a FOREACH loop (experimental)
-#------------------------------------------------------------------------
-
-sub next {
- return <<EOF;
-(\$value, \$error) = \$list->get_next();
-next LOOP;
-EOF
-}
-
-
-#------------------------------------------------------------------------
-# wrapper(\@nameargs, $block) [% WRAPPER template foo = bar %]
-# # => [ [$file,...], \@args ]
-#------------------------------------------------------------------------
-
-sub wrapper {
- my ($class, $nameargs, $block) = @_;
- my ($file, $args) = @$nameargs;
- my $hash = shift @$args;
-
- local $" = ', ';
-# print STDERR "wrapper([@$file], { @$hash })\n";
-
- return $class->multi_wrapper($file, $hash, $block)
- if @$file > 1;
- $file = shift @$file;
-
- $block = pad($block, 1) if $PRETTY;
- push(@$hash, "'content'", '$output');
- $file .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';
-
- return <<EOF;
-
-# WRAPPER
-$OUTPUT do {
- my \$output = '';
-$block
- \$context->include($file);
-};
-EOF
-}
-
-
-sub multi_wrapper {
- my ($class, $file, $hash, $block) = @_;
- $block = pad($block, 1) if $PRETTY;
-
- push(@$hash, "'content'", '$output');
- $hash = @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';
-
- $file = join(', ', reverse @$file);
-# print STDERR "multi wrapper: $file\n";
-
- return <<EOF;
-
-# WRAPPER
-$OUTPUT do {
- my \$output = '';
-$block
- foreach ($file) {
- \$output = \$context->include(\$_$hash);
- }
- \$output;
-};
-EOF
-}
-
-
-#------------------------------------------------------------------------
-# while($expr, $block) [% WHILE x < 10 %]
-# ...
-# [% END %]
-#------------------------------------------------------------------------
-
-sub while {
- my ($class, $expr, $block) = @_;
- $block = pad($block, 2) if $PRETTY;
-
- return <<EOF;
-
-# WHILE
-do {
- my \$failsafe = $WHILE_MAX;
-LOOP:
- while (--\$failsafe && ($expr)) {
-$block
- }
- die "WHILE loop terminated (> $WHILE_MAX iterations)\\n"
- unless \$failsafe;
-};
-EOF
-}
-
-
-#------------------------------------------------------------------------
-# switch($expr, \@case) [% SWITCH %]
-# [% CASE foo %]
-# ...
-# [% END %]
-#------------------------------------------------------------------------
-
-sub switch {
- my ($class, $expr, $case) = @_;
- my @case = @$case;
- my ($match, $block, $default);
- my $caseblock = '';
-
- $default = pop @case;
-
- foreach $case (@case) {
- $match = $case->[0];
- $block = $case->[1];
- $block = pad($block, 1) if $PRETTY;
- $caseblock .= <<EOF;
-\$match = $match;
-\$match = [ \$match ] unless ref \$match eq 'ARRAY';
-if (grep(/^\$result\$/, \@\$match)) {
-$block
- last SWITCH;
-}
-EOF
- }
-
- $caseblock .= $default
- if defined $default;
- $caseblock = pad($caseblock, 2) if $PRETTY;
-
-return <<EOF;
-
-# SWITCH
-do {
- my \$result = $expr;
- my \$match;
- SWITCH: {
-$caseblock
- }
-};
-EOF
-}
-
-
-#------------------------------------------------------------------------
-# try($block, \@catch) [% TRY %]
-# ...
-# [% CATCH %]
-# ...
-# [% END %]
-#------------------------------------------------------------------------
-
-sub try {
- my ($class, $block, $catch) = @_;
- my @catch = @$catch;
- my ($match, $mblock, $default, $final, $n);
- my $catchblock = '';
- my $handlers = [];
-
- $block = pad($block, 2) if $PRETTY;
- $final = pop @catch;
- $final = "# FINAL\n" . ($final ? "$final\n" : '')
- . 'die $error if $error;' . "\n" . '$output;';
- $final = pad($final, 1) if $PRETTY;
-
- $n = 0;
- foreach $catch (@catch) {
- $match = $catch->[0] || do {
- $default ||= $catch->[1];
- next;
- };
- $mblock = $catch->[1];
- $mblock = pad($mblock, 1) if $PRETTY;
- push(@$handlers, "'$match'");
- $catchblock .= $n++
- ? "elsif (\$handler eq '$match') {\n$mblock\n}\n"
- : "if (\$handler eq '$match') {\n$mblock\n}\n";
- }
- $catchblock .= "\$error = 0;";
- $catchblock = pad($catchblock, 3) if $PRETTY;
- if ($default) {
- $default = pad($default, 1) if $PRETTY;
- $default = "else {\n # DEFAULT\n$default\n \$error = '';\n}";
- }
- else {
- $default = '# NO DEFAULT';
- }
- $default = pad($default, 2) if $PRETTY;
-
- $handlers = join(', ', @$handlers);
-return <<EOF;
-
-# TRY
-$OUTPUT do {
- my \$output = '';
- my (\$error, \$handler);
- eval {
-$block
- };
- if (\$@) {
- \$error = \$context->catch(\$@, \\\$output);
- die \$error if \$error->type =~ /^return|stop\$/;
- \$stash->set('error', \$error);
- \$stash->set('e', \$error);
- if (defined (\$handler = \$error->select_handler($handlers))) {
-$catchblock
- }
-$default
- }
-$final
-};
-EOF
-}
-
-
-#------------------------------------------------------------------------
-# throw(\@nameargs) [% THROW foo "bar error" %]
-# # => [ [$type], \@args ]
-#------------------------------------------------------------------------
-
-sub throw {
- my ($class, $nameargs) = @_;
- my ($type, $args) = @$nameargs;
- my $hash = shift(@$args);
- my $info = shift(@$args);
- $type = shift @$type; # uses same parser production as INCLUDE
- # etc., which allow multiple names
- # e.g. INCLUDE foo+bar+baz
-
- if (! $info) {
- $args = "$type, undef";
- }
- elsif (@$hash || @$args) {
- local $" = ', ';
- my $i = 0;
- $args = "$type, { args => [ "
- . join(', ', $info, @$args)
- . ' ], '
- . join(', ',
- (map { "'" . $i++ . "' => $_" } ($info, @$args)),
- @$hash)
- . ' }';
- }
- else {
- $args = "$type, $info";
- }
-
- return "\$context->throw($args, \\\$output);";
-}
-
-
-#------------------------------------------------------------------------
-# clear() [% CLEAR %]
-#
-# NOTE: this is redundant, being hard-coded (for now) into Parser.yp
-#------------------------------------------------------------------------
-
-sub clear {
- return "\$output = '';";
-}
-
-#------------------------------------------------------------------------
-# break() [% BREAK %]
-#
-# NOTE: this is redundant, being hard-coded (for now) into Parser.yp
-#------------------------------------------------------------------------
-
-sub break {
- return 'last LOOP;';
-}
-
-#------------------------------------------------------------------------
-# return() [% RETURN %]
-#------------------------------------------------------------------------
-
-sub return {
- return "\$context->throw('return', '', \\\$output);";
-}
-
-#------------------------------------------------------------------------
-# stop() [% STOP %]
-#------------------------------------------------------------------------
-
-sub stop {
- return "\$context->throw('stop', '', \\\$output);";
-}
-
-
-#------------------------------------------------------------------------
-# use(\@lnameargs) [% USE alias = plugin(args) %]
-# # => [ [$file, ...], \@args, $alias ]
-#------------------------------------------------------------------------
-
-sub use {
- my ($class, $lnameargs) = @_;
- my ($file, $args, $alias) = @$lnameargs;
- $file = shift @$file; # same production rule as INCLUDE
- $alias ||= $file;
- $args = &args($class, $args);
- $file .= ", $args" if $args;
-# my $set = &assign($class, $alias, '$plugin');
- return "# USE\n"
- . "\$stash->set($alias,\n"
- . " \$context->plugin($file));";
-}
-
-#------------------------------------------------------------------------
-# view(\@nameargs, $block) [% VIEW name args %]
-# # => [ [$file, ... ], \@args ]
-#------------------------------------------------------------------------
-
-sub view {
- my ($class, $nameargs, $block, $defblocks) = @_;
- my ($name, $args) = @$nameargs;
- my $hash = shift @$args;
- $name = shift @$name; # same production rule as INCLUDE
- $block = pad($block, 1) if $PRETTY;
-
- if (%$defblocks) {
- $defblocks = join(",\n", map { "'$_' => $defblocks->{ $_ }" }
- keys %$defblocks);
- $defblocks = pad($defblocks, 1) if $PRETTY;
- $defblocks = "{\n$defblocks\n}";
- push(@$hash, "'blocks'", $defblocks);
- }
- $hash = @$hash ? '{ ' . join(', ', @$hash) . ' }' : '';
-
- return <<EOF;
-# VIEW
-do {
- my \$output = '';
- my \$oldv = \$stash->get('view');
- my \$view = \$context->view($hash);
- \$stash->set($name, \$view);
- \$stash->set('view', \$view);
-
-$block
-
- \$stash->set('view', \$oldv);
- \$view->seal();
- \$output;
-};
-EOF
-}
-
-
-#------------------------------------------------------------------------
-# perl($block)
-#------------------------------------------------------------------------
-
-sub perl {
- my ($class, $block) = @_;
- $block = pad($block, 1) if $PRETTY;
-
- return <<EOF;
-
-# PERL
-\$context->throw('perl', 'EVAL_PERL not set')
- unless \$context->eval_perl();
-
-$OUTPUT do {
- my \$output = "package Template::Perl;\\n";
-
-$block
-
- local(\$Template::Perl::context) = \$context;
- local(\$Template::Perl::stash) = \$stash;
-
- my \$result = '';
- tie *Template::Perl::PERLOUT, 'Template::TieString', \\\$result;
- my \$save_stdout = select *Template::Perl::PERLOUT;
-
- eval \$output;
- select \$save_stdout;
- \$context->throw(\$@) if \$@;
- \$result;
-};
-EOF
-}
-
-
-#------------------------------------------------------------------------
-# no_perl()
-#------------------------------------------------------------------------
-
-sub no_perl {
- my $class = shift;
- return "\$context->throw('perl', 'EVAL_PERL not set');";
-}
-
-
-#------------------------------------------------------------------------
-# rawperl($block)
-#
-# NOTE: perhaps test context EVAL_PERL switch at compile time rather than
-# runtime?
-#------------------------------------------------------------------------
-
-sub rawperl {
- my ($class, $block, $line) = @_;
- for ($block) {
- s/^\n+//;
- s/\n+$//;
- }
- $block = pad($block, 1) if $PRETTY;
- $line = $line ? " (starting line $line)" : '';
-
- return <<EOF;
-# RAWPERL
-#line 1 "RAWPERL block$line"
-$block
-EOF
-}
-
-
-
-#------------------------------------------------------------------------
-# filter()
-#------------------------------------------------------------------------
-
-sub filter {
- my ($class, $lnameargs, $block) = @_;
- my ($name, $args, $alias) = @$lnameargs;
- $name = shift @$name;
- $args = &args($class, $args);
- $args = $args ? "$args, $alias" : ", undef, $alias"
- if $alias;
- $name .= ", $args" if $args;
- $block = pad($block, 1) if $PRETTY;
-
- return <<EOF;
-
-# FILTER
-$OUTPUT do {
- my \$output = '';
- my \$filter = \$context->filter($name)
- || \$context->throw(\$context->error);
-
-$block
-
- &\$filter(\$output);
-};
-EOF
-}
-
-
-#------------------------------------------------------------------------
-# capture($name, $block)
-#------------------------------------------------------------------------
-
-sub capture {
- my ($class, $name, $block) = @_;
-
- if (ref $name) {
- if (scalar @$name == 2 && ! $name->[1]) {
- $name = $name->[0];
- }
- else {
- $name = '[' . join(', ', @$name) . ']';
- }
- }
- $block = pad($block, 1) if $PRETTY;
-
- return <<EOF;
-
-# CAPTURE
-\$stash->set($name, do {
- my \$output = '';
-$block
- \$output;
-});
-EOF
-
-}
-
-
-#------------------------------------------------------------------------
-# macro($name, $block, \@args)
-#------------------------------------------------------------------------
-
-sub macro {
- my ($class, $ident, $block, $args) = @_;
- $block = pad($block, 2) if $PRETTY;
-
- if ($args) {
- my $nargs = scalar @$args;
- $args = join(', ', map { "'$_'" } @$args);
- $args = $nargs > 1
- ? "\@args{ $args } = splice(\@_, 0, $nargs)"
- : "\$args{ $args } = shift";
-
- return <<EOF;
-
-# MACRO
-\$stash->set('$ident', sub {
- my \$output = '';
- my (%args, \$params);
- $args;
- \$params = shift;
- \$params = { } unless ref(\$params) eq 'HASH';
- \$params = { \%args, %\$params };
-
- my \$stash = \$context->localise(\$params);
- eval {
-$block
- };
- \$stash = \$context->delocalise();
- die \$@ if \$@;
- return \$output;
-});
-EOF
-
- }
- else {
- return <<EOF;
-
-# MACRO
-\$stash->set('$ident', sub {
- my \$params = \$_[0] if ref(\$_[0]) eq 'HASH';
- my \$output = '';
-
- my \$stash = \$context->localise(\$params);
- eval {
-$block
- };
- \$stash = \$context->delocalise();
- die \$@ if \$@;
- return \$output;
-});
-EOF
- }
-}
-
-
-sub debug {
- my ($class, $nameargs) = @_;
- my ($file, $args) = @$nameargs;
- my $hash = shift @$args;
- $args = join(', ', @$file, @$args);
- $args .= @$hash ? ', { ' . join(', ', @$hash) . ' }' : '';
- return "$OUTPUT \$context->debugging($args); ## DEBUG ##";
-}
-
-
-1;
-
-__END__
-
diff --git a/lib/Template/Document.pm b/lib/Template/Document.pm
deleted file mode 100644
index ce3beb2..0000000
--- a/lib/Template/Document.pm
+++ /dev/null
@@ -1,492 +0,0 @@
-##============================================================= -*-Perl-*-
-#
-# Template::Document
-#
-# DESCRIPTION
-# Module defining a class of objects which encapsulate compiled
-# templates, storing additional block definitions and metadata
-# as well as the compiled Perl sub-routine representing the main
-# template content.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Document.pm,v 2.71 2004/01/13 16:19:10 abw Exp $
-#
-#============================================================================
-
-package Template::Document;
-
-require 5.004;
-
-use strict;
-use vars qw( $VERSION $ERROR $COMPERR $DEBUG $AUTOLOAD );
-use base qw( Template::Base );
-use Template::Constants;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.71 $ =~ /(\d+)\.(\d+)/);
-
-
-#========================================================================
-# ----- PUBLIC METHODS -----
-#========================================================================
-
-#------------------------------------------------------------------------
-# new(\%document)
-#
-# Creates a new self-contained Template::Document object which
-# encapsulates a compiled Perl sub-routine, $block, any additional
-# BLOCKs defined within the document ($defblocks, also Perl sub-routines)
-# and additional $metadata about the document.
-#------------------------------------------------------------------------
-
-sub new {
- my ($class, $doc) = @_;
- my ($block, $defblocks, $metadata) = @$doc{ qw( BLOCK DEFBLOCKS METADATA ) };
- $defblocks ||= { };
- $metadata ||= { };
-
- # evaluate Perl code in $block to create sub-routine reference if necessary
- unless (ref $block) {
- local $SIG{__WARN__} = \&catch_warnings;
- $COMPERR = '';
-
- # DON'T LOOK NOW! - blindly untainting can make you go blind!
- $block =~ /(.*)/s;
- $block = $1;
-
- $block = eval $block;
- return $class->error($@)
- unless defined $block;
- }
-
- # same for any additional BLOCK definitions
- @$defblocks{ keys %$defblocks } =
- # MORE BLIND UNTAINTING - turn away if you're squeamish
- map {
- ref($_)
- ? $_
- : ( /(.*)/s && eval($1) or return $class->error($@) )
- } values %$defblocks;
-
- bless {
- %$metadata,
- _BLOCK => $block,
- _DEFBLOCKS => $defblocks,
- _HOT => 0,
- }, $class;
-}
-
-
-#------------------------------------------------------------------------
-# block()
-#
-# Returns a reference to the internal sub-routine reference, _BLOCK,
-# that constitutes the main document template.
-#------------------------------------------------------------------------
-
-sub block {
- return $_[0]->{ _BLOCK };
-}
-
-
-#------------------------------------------------------------------------
-# blocks()
-#
-# Returns a reference to a hash array containing any BLOCK definitions
-# from the template. The hash keys are the BLOCK nameand the values
-# are references to Template::Document objects. Returns 0 (# an empty hash)
-# if no blocks are defined.
-#------------------------------------------------------------------------
-
-sub blocks {
- return $_[0]->{ _DEFBLOCKS };
-}
-
-
-#------------------------------------------------------------------------
-# process($context)
-#
-# Process the document in a particular context. Checks for recursion,
-# registers the document with the context via visit(), processes itself,
-# and then unwinds with a large gin and tonic.
-#------------------------------------------------------------------------
-
-sub process {
- my ($self, $context) = @_;
- my $defblocks = $self->{ _DEFBLOCKS };
- my $output;
-
-
- # check we're not already visiting this template
- return $context->throw(Template::Constants::ERROR_FILE,
- "recursion into '$self->{ name }'")
- if $self->{ _HOT } && ! $context->{ RECURSION }; ## RETURN ##
-
- $context->visit($self, $defblocks);
-
- $self->{ _HOT } = 1;
- eval {
- my $block = $self->{ _BLOCK };
- $output = &$block($context);
- };
- $self->{ _HOT } = 0;
-
- $context->leave();
-
- die $context->catch($@)
- if $@;
-
- return $output;
-}
-
-
-#------------------------------------------------------------------------
-# AUTOLOAD
-#
-# Provides pseudo-methods for read-only access to various internal
-# members.
-#------------------------------------------------------------------------
-
-sub AUTOLOAD {
- my $self = shift;
- my $method = $AUTOLOAD;
-
- $method =~ s/.*:://;
- return if $method eq 'DESTROY';
-# my ($pkg, $file, $line) = caller();
-# print STDERR "called $self->AUTOLOAD($method) from $file line $line\n";
- return $self->{ $method };
-}
-
-
-#========================================================================
-# ----- PRIVATE METHODS -----
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# _dump()
-#
-# Debug method which returns a string representing the internal state
-# of the object.
-#------------------------------------------------------------------------
-
-sub _dump {
- my $self = shift;
- my $dblks;
- my $output = "$self : $self->{ name }\n";
-
- $output .= "BLOCK: $self->{ _BLOCK }\nDEFBLOCKS:\n";
-
- if ($dblks = $self->{ _DEFBLOCKS }) {
- foreach my $b (keys %$dblks) {
- $output .= " $b: $dblks->{ $b }\n";
- }
- }
-
- return $output;
-}
-
-
-#========================================================================
-# ----- CLASS METHODS -----
-#========================================================================
-
-#------------------------------------------------------------------------
-# as_perl($content)
-#
-# This method expects a reference to a hash passed as the first argument
-# containing 3 items:
-# METADATA # a hash of template metadata
-# BLOCK # string containing Perl sub definition for main block
-# DEFBLOCKS # hash containing further subs for addional BLOCK defs
-# It returns a string containing Perl code which, when evaluated and
-# executed, will instantiate a new Template::Document object with the
-# above data. On error, it returns undef with an appropriate error
-# message set in $ERROR.
-#------------------------------------------------------------------------
-
-sub as_perl {
- my ($class, $content) = @_;
- my ($block, $defblocks, $metadata) = @$content{ qw( BLOCK DEFBLOCKS METADATA ) };
-
- $block =~ s/\n/\n /g;
- $block =~ s/\s+$//;
-
- $defblocks = join('', map {
- my $code = $defblocks->{ $_ };
- $code =~ s/\n/\n /g;
- $code =~ s/\s*$//;
- " '$_' => $code,\n";
- } keys %$defblocks);
- $defblocks =~ s/\s+$//;
-
- $metadata = join('', map {
- my $x = $metadata->{ $_ };
- $x =~ s/(['\\])/\\$1/g;
- " '$_' => '$x',\n";
- } keys %$metadata);
- $metadata =~ s/\s+$//;
-
- return <<EOF
-#------------------------------------------------------------------------
-# Compiled template generated by the Template Toolkit version $Template::VERSION
-#------------------------------------------------------------------------
-
-$class->new({
- METADATA => {
-$metadata
- },
- BLOCK => $block,
- DEFBLOCKS => {
-$defblocks
- },
-});
-EOF
-}
-
-
-#------------------------------------------------------------------------
-# write_perl_file($filename, \%content)
-#
-# This method calls as_perl() to generate the Perl code to represent a
-# compiled template with the content passed as the second argument.
-# It then writes this to the file denoted by the first argument.
-#
-# Returns 1 on success. On error, sets the $ERROR package variable
-# to contain an error message and returns undef.
-#------------------------------------------------------------------------
-
-sub write_perl_file {
- my ($class, $file, $content) = @_;
- my ($fh, $tmpfile);
-
- return $class->error("invalid filename: $file")
- unless $file =~ /^(.+)$/s;
-
- eval {
- require File::Temp;
- require File::Basename;
- ($fh, $tmpfile) = File::Temp::tempfile(
- DIR => File::Basename::dirname($file)
- );
- print $fh $class->as_perl($content) || die $!;
- close($fh);
- };
- return $class->error($@) if $@;
- return rename($tmpfile, $file)
- || $class->error($!);
-}
-
-
-#------------------------------------------------------------------------
-# catch_warnings($msg)
-#
-# Installed as
-#------------------------------------------------------------------------
-
-sub catch_warnings {
- $COMPERR .= join('', @_);
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Document - Compiled template document object
-
-=head1 SYNOPSIS
-
- use Template::Document;
-
- $doc = Template::Document->new({
- BLOCK => sub { # some perl code; return $some_text },
- DEFBLOCKS => {
- header => sub { # more perl code; return $some_text },
- footer => sub { # blah blah blah; return $some_text },
- },
- METADATA => {
- author => 'Andy Wardley',
- version => 3.14,
- }
- }) || die $Template::Document::ERROR;
-
- print $doc->process($context);
-
-=head1 DESCRIPTION
-
-This module defines an object class whose instances represent compiled
-template documents. The Template::Parser module creates a
-Template::Document instance to encapsulate a template as it is compiled
-into Perl code.
-
-The constructor method, new(), expects a reference to a hash array
-containing the BLOCK, DEFBLOCKS and METADATA items. The BLOCK item
-should contain a reference to a Perl subroutine or a textual
-representation of Perl code, as generated by the Template::Parser
-module, which is then evaluated into a subroutine reference using
-eval(). The DEFLOCKS item should reference a hash array containing
-further named BLOCKs which may be defined in the template. The keys
-represent BLOCK names and the values should be subroutine references
-or text strings of Perl code as per the main BLOCK item. The METADATA
-item should reference a hash array of metadata items relevant to the
-document.
-
-The process() method can then be called on the instantiated
-Template::Document object, passing a reference to a Template::Content
-object as the first parameter. This will install any locally defined
-blocks (DEFBLOCKS) in the the contexts() BLOCKS cache (via a call to
-visit()) so that they may be subsequently resolved by the context. The
-main BLOCK subroutine is then executed, passing the context reference
-on as a parameter. The text returned from the template subroutine is
-then returned by the process() method, after calling the context leave()
-method to permit cleanup and de-registration of named BLOCKS previously
-installed.
-
-An AUTOLOAD method provides access to the METADATA items for the document.
-The Template::Service module installs a reference to the main
-Template::Document object in the stash as the 'template' variable.
-This allows metadata items to be accessed from within templates,
-including PRE_PROCESS templates.
-
-header:
-
- <html>
- <head>
- <title>[% template.title %]
- </head>
- ...
-
-Template::Document objects are usually created by the Template::Parser
-but can be manually instantiated or sub-classed to provide custom
-template components.
-
-=head1 METHODS
-
-=head2 new(\%config)
-
-Constructor method which accept a reference to a hash array containing the
-structure as shown in this example:
-
- $doc = Template::Document->new({
- BLOCK => sub { # some perl code; return $some_text },
- DEFBLOCKS => {
- header => sub { # more perl code; return $some_text },
- footer => sub { # blah blah blah; return $some_text },
- },
- METADATA => {
- author => 'Andy Wardley',
- version => 3.14,
- }
- }) || die $Template::Document::ERROR;
-
-BLOCK and DEFBLOCKS items may be expressed as references to Perl subroutines
-or as text strings containing Perl subroutine definitions, as is generated
-by the Template::Parser module. These are evaluated into subroutine references
-using eval().
-
-Returns a new Template::Document object or undef on error. The error() class
-method can be called, or the $ERROR package variable inspected to retrieve
-the relevant error message.
-
-=head2 process($context)
-
-Main processing routine for the compiled template document. A reference to
-a Template::Context object should be passed as the first parameter. The
-method installs any locally defined blocks via a call to the context
-visit() method, processes it's own template, passing the context reference
-by parameter and then calls leave() in the context to allow cleanup.
-
- print $doc->process($context);
-
-Returns a text string representing the generated output for the template.
-Errors are thrown via die().
-
-=head2 block()
-
-Returns a reference to the main BLOCK subroutine.
-
-=head2 blocks()
-
-Returns a reference to the hash array of named DEFBLOCKS subroutines.
-
-=head2 AUTOLOAD
-
-An autoload method returns METADATA items.
-
- print $doc->author();
-
-=head1 PACKAGE SUB-ROUTINES
-
-=head2 write_perl_file(\%config)
-
-This package subroutine is provided to effect persistance of compiled
-templates. If the COMPILE_EXT option (to indicate a file extension
-for saving compiled templates) then the Template::Parser module calls
-this subroutine before calling the new() constructor. At this stage,
-the parser has a representation of the template as text strings
-containing Perl code. We can write that to a file, enclosed in a
-small wrapper which will allow us to susequently require() the file
-and have Perl parse and compile it into a Template::Document. Thus we
-have persistance of compiled templates.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.71, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template|Template>, L<Template::Parser|Template::Parser>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Exception.pm b/lib/Template/Exception.pm
deleted file mode 100644
index 9a95af7..0000000
--- a/lib/Template/Exception.pm
+++ /dev/null
@@ -1,254 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Exception
-#
-# DESCRIPTION
-# Module implementing a generic exception class used for error handling
-# in the Template Toolkit.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-#------------------------------------------------------------------------
-#
-# $Id: Exception.pm,v 2.64 2004/01/13 16:19:10 abw Exp $
-#
-#========================================================================
-
-
-package Template::Exception;
-
-require 5.005;
-
-use strict;
-use vars qw( $VERSION );
-
-use constant TYPE => 0;
-use constant INFO => 1;
-use constant TEXT => 2;
-use overload q|""| => "as_string", fallback => 1;
-
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.64 $ =~ /(\d+)\.(\d+)/);
-
-
-#------------------------------------------------------------------------
-# new($type, $info, \$text)
-#
-# Constructor method used to instantiate a new Template::Exception
-# object. The first parameter should contain the exception type. This
-# can be any arbitrary string of the caller's choice to represent a
-# specific exception. The second parameter should contain any
-# information (i.e. error message or data reference) relevant to the
-# specific exception event. The third optional parameter may be a
-# reference to a scalar containing output text from the template
-# block up to the point where the exception was thrown.
-#------------------------------------------------------------------------
-
-sub new {
- my ($class, $type, $info, $textref) = @_;
- bless [ $type, $info, $textref ], $class;
-}
-
-
-#------------------------------------------------------------------------
-# type()
-# info()
-# type_info()
-#
-# Accessor methods to return the internal TYPE and INFO fields.
-#------------------------------------------------------------------------
-
-sub type {
- $_[0]->[ TYPE ];
-}
-
-sub info {
- $_[0]->[ INFO ];
-}
-
-sub type_info {
- my $self = shift;
- @$self[ TYPE, INFO ];
-}
-
-#------------------------------------------------------------------------
-# text()
-# text(\$pretext)
-#
-# Method to return the text referenced by the TEXT member. A text
-# reference may be passed as a parameter to supercede the existing
-# member. The existing text is added to the *end* of the new text
-# before being stored. This facility is provided for template blocks
-# to gracefully de-nest when an exception occurs and allows them to
-# reconstruct their output in the correct order.
-#------------------------------------------------------------------------
-
-sub text {
- my ($self, $newtextref) = @_;
- my $textref = $self->[ TEXT ];
-
- if ($newtextref) {
- $$newtextref .= $$textref if $textref && $textref ne $newtextref;
- $self->[ TEXT ] = $newtextref;
- return '';
-
- }
- elsif ($textref) {
- return $$textref;
- }
- else {
- return '';
- }
-}
-
-
-#------------------------------------------------------------------------
-# as_string()
-#
-# Accessor method to return a string indicating the exception type and
-# information.
-#------------------------------------------------------------------------
-
-sub as_string {
- my $self = shift;
- return $self->[ TYPE ] . ' error - ' . $self->[ INFO ];
-}
-
-
-#------------------------------------------------------------------------
-# select_handler(@types)
-#
-# Selects the most appropriate handler for the exception TYPE, from
-# the list of types passed in as parameters. The method returns the
-# item which is an exact match for TYPE or the closest, more
-# generic handler (e.g. foo being more generic than foo.bar, etc.)
-#------------------------------------------------------------------------
-
-sub select_handler {
- my ($self, @options) = @_;
- my $type = $self->[ TYPE ];
- my %hlut;
- @hlut{ @options } = (1) x @options;
-
- while ($type) {
- return $type if $hlut{ $type };
-
- # strip .element from the end of the exception type to find a
- # more generic handler
- $type =~ s/\.?[^\.]*$//;
- }
- return undef;
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Exception - Exception handling class module
-
-=head1 SYNOPSIS
-
- use Template::Exception;
-
- my $exception = Template::Exception->new($type, $info);
- $type = $exception->type;
- $info = $exception->info;
- ($type, $info) = $exception->type_info;
-
- print $exception->as_string();
-
- $handler = $exception->select_handler(\@candidates);
-
-=head1 DESCRIPTION
-
-The Template::Exception module defines an object class for
-representing exceptions within the template processing life cycle.
-Exceptions can be raised by modules within the Template Toolkit, or
-can be generated and returned by user code bound to template
-variables.
-
-
-Exceptions can be raised in a template using the THROW directive,
-
- [% THROW user.login 'no user id: please login' %]
-
-or by calling the throw() method on the current Template::Context object,
-
- $context->throw('user.passwd', 'Incorrect Password');
- $context->throw('Incorrect Password'); # type 'undef'
-
-or from Perl code by calling die() with a Template::Exception object,
-
- die (Template::Exception->new('user.denied', 'Invalid User ID'));
-
-or by simply calling die() with an error string. This is
-automagically caught and converted to an exception of 'undef'
-type which can then be handled in the usual way.
-
- die "I'm sorry Dave, I can't do that";
-
-
-
-Each exception is defined by its type and a information component
-(e.g. error message). The type can be any identifying string and may
-contain dotted components (e.g. 'foo', 'foo.bar', 'foo.bar.baz').
-Exception types are considered to be hierarchical such that 'foo.bar'
-would be a specific type of the more general 'foo' type.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.64, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template|Template>, L<Template::Context|Template::Context>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/FAQ.pod b/lib/Template/FAQ.pod
deleted file mode 100644
index 0807ace..0000000
--- a/lib/Template/FAQ.pod
+++ /dev/null
@@ -1,329 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::FAQ
-#
-# DESCRIPTION
-# This is the Frequently Asked Questions list for the Template
-# Toolkit. More accurately, it's a very thin placeholder for where
-# the FAQ will soon be.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-# 2.69
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::FAQ - Frequently Asked Questions about the Template Toolkit
-
-=head1 DESCRIPTION
-
-This is the Frequently Asked Questions list for the Template Toolkit.
-More accurately, it's a very thin placeholder for where the FAQ will
-soon be.
-
-
-=head1 Template Toolkit Language
-
-=head2 Why doesn't [% a = b IF c %] work as expected?
-
-Because the parser interprets it as
-
- [% a = (b IF c) %]
-
-Do this instead:
-
- [% SET a = b IF c %]
-
-=head2 If I'm using TT to write out a TT template, is there a good way to escape [% and %]?
-
-You can do this:
-
- [% stag = "[\%"
- etag = "%\]"
- %]
-
-and then:
-
- [% stag; 'hello'; etag %]
-
-Or something like:
-
- [% TAGS [- -] %]
- [- INCLUDE foo -] # is a directive
- [% INCLUDE foo %] # not a directive, just plain text, passed through
-
-=head2 How do I iterate over a hash?
-
-This is covered in the L<Template::Manual::VMethods|VMethods> section
-of the manual page. A list of all the keys that are in the hash can
-be obtained with the 'keys' virtual method. You can then iterate
-over that list and by looking up each key in turn get the value.
-
- [% FOREACH key = product.keys %]
- [% key %] => [% product.$key %]
- [% END %]
-
-=head1 Plugins
-
-=head2 How do I get the Table plugin to order data across rather than down?
-
-Order the data into rows:
-
- Steve Karen Jeff
- Brooklyn Nantucket Fairfax
- NY MA VA
-
- [% USE table(data, rows=3) %]
-
-Then ask for each column
-
- [% FOREACH column = table.cols %]
-
-And then print each item in the column going across the output rows
-
- [% FOREACH item = column %]
- <td>[% item %]</td>
- [% END %]
-
-=head2 Accessing Cookies
-
-Jeff Boes E<lt>jboes@nexcerpt.comE<gt> asks:
-
- Does anyone have a quick-n-dirty approach to accessing
- cookies from templates?
-
-Jonas Liljegren answers:
-
- [% USE CGI %]
-
- <p>The value is [% CGI.cookie('cookie_name') | html %]
-
-
-=head1 Extending the Template Toolkit
-
-=head2 Can I serve templates from a database?
-
-Short answer: yes, Chris Nandor has done this for Slash. You need to
-subclass Template::Provider. See the mailing list archives for further
-info.
-
-=head2 Can I fetch templates via http?
-
-To do the job properly, you should sublcass Template::Provider to
-Template::Provider::HTTP and use a PREFIX_MAP option to bind the
-'http' template prefix to that particular provider (you may want to
-go digging around in the F<Changes> file around version 2.01 for
-more info on PREFIX_MAP - it may not be properly documented anywhere
-else...yet!). e.g. (untested due to lack of existing HTTP Provider
-- patches welcome!).
-
- use Template::Provider::HTTP;
-
- my $file = Template::Provider( INCLUDE_PATH => [...] );
- my $http = Template::Provider::HTTP->new(...);
- my $tt2 = Template->new({
- LOAD_TEMPLATES => [ $file, $http ],
- PREFIX_MAP => {
- file => '0', # file:foo.html
- http => '1', # http:foo.html
- default => '0', # foo.html => file:foo.html
- }
- });
-
-Now a template specified as:
-
- [% INCLUDE foo %]
-
-will be served by the 'file' provider (the default). Otherwise you
-can explicitly add a prefix:
-
- [% INCLUDE file:foo.html %]
- [% INCLUDE http:foo.html %]
- [% INCLUDE http://www.xyz.com/tt2/header.tt2 %]
-
-This same principal can be used to create a DBI template provider. e.g.
-
- [% INCLUDE dbi:foo.html %]
-
-But similarly, alas, we don't yet have a DBI provider as part of the
-Template Toolkit. There has been some talk on the mailing list about
-efforts to develop DBI and/or HTTP providers but as yet no-one has
-stepped forward to take up the challenge...
-
-In the mean time, Craig's post from the mailing list has some useful
-pointers on how to acheive this using existing modules:
-
- To: Adam Theo <adamtheo@theoretic.com>
- From: Craig Barratt <craig@arraycomm.com>
- Date: Fri, 18 May 2001 17:06:59 -0700
-
- > i was wondering if there is anyway to fetch a file using http:// or
- > ftp:// and include that?
-
- Here's one way. Set the LOAD_PERL option:
-
- use Template;
-
- my $template = Template->new({
- LOAD_PERL => 1
- });
- $template->process("example.tt", { stdout => *STDOUT })
- || die $template->error();
-
- and then use LWP::UserAgent and HTTP::Request:
-
- [%
- USE ua = LWP.UserAgent;
- ua.proxy("http", "http://your_proxy/");
- USE req = HTTP.Request("GET", "http://www.cpan.org");
- ua.request(req).content;
- -%]
-
- For FTP use Net::FTP:
-
- [%
- USE ftp = Net.FTP("ftp.cpan.org");
- x = ftp.login("anonymous", "me@here.there");
- x = ftp.cwd("/");
- x = ftp.get("welcome.msg", stdout);
- x = ftp.quit;
- -%]
-
- Normally ftp.get would write the file into the current directory.
- Instead we pass stdout as a second argument so that it is written
- to stdout. We set stdout to STDOUT in the variables we pass to
- process.
-
- Craig
-
-=head1 Miscellaneous
-
-=head2 How can I configure variables on a per-request basis?
-
-One easy way to acheive this is to define a single PRE_PROCESS template which
-loads in other configuration files based on variables defined or other
-conditions.
-
-For example, my setup usually looks something like this:
-
- PRE_PROCESS => 'config/main'
-
-config/main:
-
- [% DEFAULT style = 'text'
- section = template.section or 'home';
-
- PROCESS config/site
- + config/urls
- + config/macros
- + "config/style/$style"
- + "config/section/$section"
- + ...
- %]
-
-This allows me to set a single 'style' variable to control which config
-file gets pre-processed to set my various style options (colours, img paths,
-etc). For example:
-
-config/style/basic:
-
- [% style = {
- name = style # save existing 'style' var as 'style.name'
-
- # define various other style variables....
- col = {
- back => '#ffffff'
- text => '#000000'
- # ...etc...
- }
-
- logo = {
- # ...etc...
- }
-
- # ...etc...
- }
- %]
-
-Each source template can declare which section it's in via a META
-directive:
-
- [% META
- title = 'General Information'
- section = 'info'
- %]
-
- ...
-
-This controls which section configuration file gets loaded to set various
-other variables for defining the section title, menu, etc.
-
-config/section/info:
-
- [% section = {
- name = section # save 'section' var as 'section.name'
- title = 'Information'
- menu = [ ... ]
- # ...etc...
- }
- %]
-
-This illustrates the basic principal but you can extend it to perform
-pretty much any kind of per-document initialisation that you require.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.69, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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:
diff --git a/lib/Template/Filters.pm b/lib/Template/Filters.pm
deleted file mode 100644
index a9c4846..0000000
--- a/lib/Template/Filters.pm
+++ /dev/null
@@ -1,1448 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Filters
-#
-# DESCRIPTION
-# Defines filter plugins as used by the FILTER directive.
-#
-# AUTHORS
-# Andy Wardley <abw@kfs.org>, with a number of filters contributed
-# by Leslie Michael Orchard <deus_x@nijacode.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Filters.pm,v 2.77 2004/01/13 16:19:10 abw Exp $
-#
-#============================================================================
-
-package Template::Filters;
-
-require 5.004;
-
-use strict;
-use base qw( Template::Base );
-use vars qw( $VERSION $DEBUG $FILTERS $URI_ESCAPES $PLUGIN_FILTER );
-use Template::Constants;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.77 $ =~ /(\d+)\.(\d+)/);
-
-
-#------------------------------------------------------------------------
-# standard filters, defined in one of the following forms:
-# name => \&static_filter
-# name => [ \&subref, $is_dynamic ]
-# If the $is_dynamic flag is set then the sub-routine reference
-# is called to create a new filter each time it is requested; if
-# not set, then it is a single, static sub-routine which is returned
-# for every filter request for that name.
-#------------------------------------------------------------------------
-
-$FILTERS = {
- # static filters
- 'html' => \&html_filter,
- 'html_para' => \&html_paragraph,
- 'html_break' => \&html_para_break,
- 'html_para_break' => \&html_para_break,
- 'html_line_break' => \&html_line_break,
- 'uri' => \&uri_filter,
- 'upper' => sub { uc $_[0] },
- 'lower' => sub { lc $_[0] },
- 'ucfirst' => sub { ucfirst $_[0] },
- 'lcfirst' => sub { lcfirst $_[0] },
- 'stderr' => sub { print STDERR @_; return '' },
- 'trim' => sub { for ($_[0]) { s/^\s+//; s/\s+$// }; $_[0] },
- 'null' => sub { return '' },
- 'collapse' => sub { for ($_[0]) { s/^\s+//; s/\s+$//; s/\s+/ /g };
- $_[0] },
-
- # dynamic filters
- 'html_entity' => [ \&html_entity_filter_factory, 1 ],
- 'indent' => [ \&indent_filter_factory, 1 ],
- 'format' => [ \&format_filter_factory, 1 ],
- 'truncate' => [ \&truncate_filter_factory, 1 ],
- 'repeat' => [ \&repeat_filter_factory, 1 ],
- 'replace' => [ \&replace_filter_factory, 1 ],
- 'remove' => [ \&remove_filter_factory, 1 ],
- 'eval' => [ \&eval_filter_factory, 1 ],
- 'evaltt' => [ \&eval_filter_factory, 1 ], # alias
- 'perl' => [ \&perl_filter_factory, 1 ],
- 'evalperl' => [ \&perl_filter_factory, 1 ], # alias
- 'redirect' => [ \&redirect_filter_factory, 1 ],
- 'file' => [ \&redirect_filter_factory, 1 ], # alias
- 'stdout' => [ \&stdout_filter_factory, 1 ],
- 'latex' => [ \&latex_filter_factory, 1 ],
-};
-
-# name of module implementing plugin filters
-$PLUGIN_FILTER = 'Template::Plugin::Filter';
-
-
-#========================================================================
-# -- PUBLIC METHODS --
-#========================================================================
-
-#------------------------------------------------------------------------
-# fetch($name, \@args, $context)
-#
-# Attempts to instantiate or return a reference to a filter sub-routine
-# named by the first parameter, $name, with additional constructor
-# arguments passed by reference to a list as the second parameter,
-# $args. A reference to the calling Template::Context object is
-# passed as the third paramter.
-#
-# Returns a reference to a filter sub-routine or a pair of values
-# (undef, STATUS_DECLINED) or ($error, STATUS_ERROR) to decline to
-# deliver the filter or to indicate an error.
-#------------------------------------------------------------------------
-
-sub fetch {
- my ($self, $name, $args, $context) = @_;
- my ($factory, $is_dynamic, $filter, $error);
-
- $self->debug("fetch($name, ",
- defined $args ? ('[ ', join(', ', @$args), ' ]') : '<no args>', ', ',
- defined $context ? $context : '<no context>',
- ')') if $self->{ DEBUG };
-
- # allow $name to be specified as a reference to
- # a plugin filter object; any other ref is
- # assumed to be a coderef and hence already a filter;
- # non-refs are assumed to be regular name lookups
-
- if (ref $name) {
- if (UNIVERSAL::isa($name, $PLUGIN_FILTER)) {
- $factory = $name->factory()
- || return $self->error($name->error());
- }
- else {
- return $name;
- }
- }
- else {
- return (undef, Template::Constants::STATUS_DECLINED)
- unless ($factory = $self->{ FILTERS }->{ $name }
- || $FILTERS->{ $name });
- }
-
- # factory can be an [ $code, $dynamic ] or just $code
- if (ref $factory eq 'ARRAY') {
- ($factory, $is_dynamic) = @$factory;
- }
- else {
- $is_dynamic = 0;
- }
-
- if (ref $factory eq 'CODE') {
- if ($is_dynamic) {
- # if the dynamic flag is set then the sub-routine is a
- # factory which should be called to create the actual
- # filter...
- eval {
- ($filter, $error) = &$factory($context, $args ? @$args : ());
- };
- $error ||= $@;
- $error = "invalid FILTER for '$name' (not a CODE ref)"
- unless $error || ref($filter) eq 'CODE';
- }
- else {
- # ...otherwise, it's a static filter sub-routine
- $filter = $factory;
- }
- }
- else {
- $error = "invalid FILTER entry for '$name' (not a CODE ref)";
- }
-
- if ($error) {
- return $self->{ TOLERANT }
- ? (undef, Template::Constants::STATUS_DECLINED)
- : ($error, Template::Constants::STATUS_ERROR) ;
- }
- else {
- return $filter;
- }
-}
-
-
-#------------------------------------------------------------------------
-# store($name, \&filter)
-#
-# Stores a new filter in the internal FILTERS hash. The first parameter
-# is the filter name, the second a reference to a subroutine or
-# array, as per the standard $FILTERS entries.
-#------------------------------------------------------------------------
-
-sub store {
- my ($self, $name, $filter) = @_;
-
- $self->debug("store($name, $filter)") if $self->{ DEBUG };
-
- $self->{ FILTERS }->{ $name } = $filter;
- return 1;
-}
-
-
-#========================================================================
-# -- PRIVATE METHODS --
-#========================================================================
-
-#------------------------------------------------------------------------
-# _init(\%config)
-#
-# Private initialisation method.
-#------------------------------------------------------------------------
-
-sub _init {
- my ($self, $params) = @_;
-
- $self->{ FILTERS } = $params->{ FILTERS } || { };
- $self->{ TOLERANT } = $params->{ TOLERANT } || 0;
- $self->{ DEBUG } = ( $params->{ DEBUG } || 0 )
- & Template::Constants::DEBUG_FILTERS;
-
-
- return $self;
-}
-
-
-
-#------------------------------------------------------------------------
-# _dump()
-#
-# Debug method
-#------------------------------------------------------------------------
-
-sub _dump {
- my $self = shift;
- my $output = "[Template::Filters] {\n";
- my $format = " %-16s => %s\n";
- my $key;
-
- foreach $key (qw( TOLERANT )) {
- my $val = $self->{ $key };
- $val = '<undef>' unless defined $val;
- $output .= sprintf($format, $key, $val);
- }
-
- my $filters = $self->{ FILTERS };
- $filters = join('', map {
- sprintf(" $format", $_, $filters->{ $_ });
- } keys %$filters);
- $filters = "{\n$filters }";
-
- $output .= sprintf($format, 'FILTERS (local)' => $filters);
-
- $filters = $FILTERS;
- $filters = join('', map {
- my $f = $filters->{ $_ };
- my ($ref, $dynamic) = ref $f eq 'ARRAY' ? @$f : ($f, 0);
- sprintf(" $format", $_, $dynamic ? 'dynamic' : 'static');
- } sort keys %$filters);
- $filters = "{\n$filters }";
-
- $output .= sprintf($format, 'FILTERS (global)' => $filters);
-
- $output .= '}';
- return $output;
-}
-
-
-#========================================================================
-# -- STATIC FILTER SUBS --
-#========================================================================
-
-#------------------------------------------------------------------------
-# uri_filter() [% FILTER uri %]
-#
-# URI escape a string. This code is borrowed from Gisle Aas' URI::Escape
-# module. For something so simple, I can't see any validation in making
-# the user install the URI modules just for this, so we cut and paste.
-#
-# URI::Escape is Copyright 1995-2000 Gisle Aas.
-#------------------------------------------------------------------------
-
-sub uri_filter {
- my $text = shift;
-
- # construct and cache a lookup table for escapes (faster than
- # doing a sprintf() for every character in every string each
- # time)
- $URI_ESCAPES ||= {
- map { ( chr($_), sprintf("%%%02X", $_) ) } (0..255),
- };
-
- $text =~ s/([^;\/?:@&=+\$,A-Za-z0-9\-_.!~*'()])/$URI_ESCAPES->{$1}/g;
- $text;
-}
-
-
-#------------------------------------------------------------------------
-# html_filter() [% FILTER html %]
-#
-# Convert any '<', '>' or '&' characters to the HTML equivalents, '&lt;',
-# '&gt;' and '&amp;', respectively.
-#------------------------------------------------------------------------
-
-sub html_filter {
- my $text = shift;
- for ($text) {
- s/&/&amp;/g;
- s/</&lt;/g;
- s/>/&gt;/g;
- s/"/&quot;/g;
- }
- return $text;
-}
-
-
-#------------------------------------------------------------------------
-# html_paragraph() [% FILTER html_para %]
-#
-# Wrap each paragraph of text (delimited by two or more newlines) in the
-# <p>...</p> HTML tags.
-#------------------------------------------------------------------------
-
-sub html_paragraph {
- my $text = shift;
- return "<p>\n"
- . join("\n</p>\n\n<p>\n", split(/(?:\r?\n){2,}/, $text))
- . "</p>\n";
-}
-
-
-#------------------------------------------------------------------------
-# html_para_break() [% FILTER html_para_break %]
-#
-# Join each paragraph of text (delimited by two or more newlines) with
-# <br><br> HTML tags.
-#------------------------------------------------------------------------
-
-sub html_para_break {
- my $text = shift;
- $text =~ s|(\r?\n){2,}|$1<br />$1<br />$1|g;
- return $text;
-}
-
-#------------------------------------------------------------------------
-# html_line_break() [% FILTER html_line_break %]
-#
-# replaces any newlines with <br> HTML tags.
-#------------------------------------------------------------------------
-
-sub html_line_break {
- my $text = shift;
- $text =~ s|(\r?\n)|<br />$1|g;
- return $text;
-}
-
-#========================================================================
-# -- DYNAMIC FILTER FACTORIES --
-#========================================================================
-
-#------------------------------------------------------------------------
-# html_entity_filter_factory(\%options) [% FILTER html %]
-#
-# Dynamic version of the static html filter which attempts to locate the
-# Apache::Util or HTML::Entities modules to perform full entity encoding
-# of the text passed. Returns an exception if one or other of the
-# modules can't be located.
-#------------------------------------------------------------------------
-
-sub html_entity_filter_factory {
- my $context = shift;
-
- # if Apache::Util is installed then we use it
- eval {
- require Apache::Util;
- Apache::Util::escape_html('');
- };
- return \&Apache::Util::escape_html
- unless $@;
-
- # otherwise if HTML::Entities is installed then we use that
- eval {
- require HTML::Entities;
- };
- return \&HTML::Entities::encode_entities
- unless $@;
-
- return (undef, Template::Exception->new( html_entity =>
- 'cannot locate Apache::Util or HTML::Entities' ));
-
-}
-
-
-#------------------------------------------------------------------------
-# indent_filter_factory($pad) [% FILTER indent(pad) %]
-#
-# Create a filter to indent text by a fixed pad string or when $pad is
-# numerical, a number of space.
-#------------------------------------------------------------------------
-
-sub indent_filter_factory {
- my ($context, $pad) = @_;
- $pad = 4 unless defined $pad;
- $pad = ' ' x $pad if $pad =~ /^\d+$/;
-
- return sub {
- my $text = shift;
- $text = '' unless defined $text;
- $text =~ s/^/$pad/mg;
- return $text;
- }
-}
-
-#------------------------------------------------------------------------
-# format_filter_factory() [% FILTER format(format) %]
-#
-# Create a filter to format text according to a printf()-like format
-# string.
-#------------------------------------------------------------------------
-
-sub format_filter_factory {
- my ($context, $format) = @_;
- $format = '%s' unless defined $format;
-
- return sub {
- my $text = shift;
- $text = '' unless defined $text;
- return join("\n", map{ sprintf($format, $_) } split(/\n/, $text));
- }
-}
-
-
-#------------------------------------------------------------------------
-# repeat_filter_factory($n) [% FILTER repeat(n) %]
-#
-# Create a filter to repeat text n times.
-#------------------------------------------------------------------------
-
-sub repeat_filter_factory {
- my ($context, $iter) = @_;
- $iter = 1 unless defined $iter and length $iter;
-
- return sub {
- my $text = shift;
- $text = '' unless defined $text;
- return join('\n', $text) x $iter;
- }
-}
-
-
-#------------------------------------------------------------------------
-# replace_filter_factory($s, $r) [% FILTER replace(search, replace) %]
-#
-# Create a filter to replace 'search' text with 'replace'
-#------------------------------------------------------------------------
-
-sub replace_filter_factory {
- my ($context, $search, $replace) = @_;
- $search = '' unless defined $search;
- $replace = '' unless defined $replace;
-
- return sub {
- my $text = shift;
- $text = '' unless defined $text;
- $text =~ s/$search/$replace/g;
- return $text;
- }
-}
-
-
-#------------------------------------------------------------------------
-# remove_filter_factory($text) [% FILTER remove(text) %]
-#
-# Create a filter to remove 'search' string from the input text.
-#------------------------------------------------------------------------
-
-sub remove_filter_factory {
- my ($context, $search) = @_;
-
- return sub {
- my $text = shift;
- $text = '' unless defined $text;
- $text =~ s/$search//g;
- return $text;
- }
-}
-
-
-#------------------------------------------------------------------------
-# truncate_filter_factory($n) [% FILTER truncate(n) %]
-#
-# Create a filter to truncate text after n characters.
-#------------------------------------------------------------------------
-
-sub truncate_filter_factory {
- my ($context, $len) = @_;
- $len = 32 unless defined $len;
-
- return sub {
- my $text = shift;
- return $text if length $text < $len;
- return substr($text, 0, $len - 3) . "...";
- }
-}
-
-
-#------------------------------------------------------------------------
-# eval_filter_factory [% FILTER eval %]
-#
-# Create a filter to evaluate template text.
-#------------------------------------------------------------------------
-
-sub eval_filter_factory {
- my $context = shift;
-
- return sub {
- my $text = shift;
- $context->process(\$text);
- }
-}
-
-
-#------------------------------------------------------------------------
-# perl_filter_factory [% FILTER perl %]
-#
-# Create a filter to process Perl text iff the context EVAL_PERL flag
-# is set.
-#------------------------------------------------------------------------
-
-sub perl_filter_factory {
- my $context = shift;
- my $stash = $context->stash;
-
- return (undef, Template::Exception->new('perl', 'EVAL_PERL is not set'))
- unless $context->eval_perl();
-
- return sub {
- my $text = shift;
- local($Template::Perl::context) = $context;
- local($Template::Perl::stash) = $stash;
- my $out = eval <<EOF;
-package Template::Perl;
-\$stash = \$context->stash();
-$text
-EOF
- $context->throw($@) if $@;
- return $out;
- }
-}
-
-
-#------------------------------------------------------------------------
-# redirect_filter_factory($context, $file) [% FILTER redirect(file) %]
-#
-# Create a filter to redirect the block text to a file.
-#------------------------------------------------------------------------
-
-sub redirect_filter_factory {
- my ($context, $file, $options) = @_;
- my $outpath = $context->config->{ OUTPUT_PATH };
-
- return (undef, Template::Exception->new('redirect',
- 'OUTPUT_PATH is not set'))
- unless $outpath;
-
- $options = { binmode => $options } unless ref $options;
-
- sub {
- my $text = shift;
- my $outpath = $context->config->{ OUTPUT_PATH }
- || return '';
- $outpath .= "/$file";
- my $error = Template::_output($outpath, \$text, $options);
- die Template::Exception->new('redirect', $error)
- if $error;
- return '';
- }
-}
-
-
-#------------------------------------------------------------------------
-# stdout_filter_factory($context, $binmode) [% FILTER stdout(binmode) %]
-#
-# Create a filter to print a block to stdout, with an optional binmode.
-#------------------------------------------------------------------------
-
-sub stdout_filter_factory {
- my ($context, $options) = @_;
-
- $options = { binmode => $options } unless ref $options;
-
- sub {
- my $text = shift;
- binmode(STDOUT) if $options->{ binmode };
- print STDOUT $text;
- return '';
- }
-}
-
-
-#------------------------------------------------------------------------
-# latex_filter_factory($context, $outputType) [% FILTER latex(outputType) %]
-#
-# Return a filter sub that converts a (hopefully) complete LaTeX source
-# file to either "ps", "dvi", or "pdf". Output type should be "ps", "dvi"
-# or "pdf" (pdf is default).
-#
-# Creates a temporary directory below File::Spec->tmpdir() (often /tmp)
-# and writes the text into doc.tex. It then runs either pdflatex or
-# latex and optionally dvips. Based on the exit status either returns
-# the entire doc.(pdf|ps|dvi) output or throws an error with a summary
-# of the error messages from doc.log.
-#
-# Written by Craig Barratt, Apr 28 2001.
-# Win32 additions by Richard Tietjen.
-#------------------------------------------------------------------------
-use File::Path;
-use File::Spec;
-use Cwd;
-
-sub latex_filter_factory
-{
- my($context, $output) = @_;
-
- $output = lc($output);
- my $fName = "latex";
- my($LaTeXPath, $PdfLaTeXPath, $DviPSPath)
- = @{Template::Config->latexpaths()};
- if ( $output eq "ps" || $output eq "dvi" ) {
- $context->throw($fName,
- "latex not installed (see Template::Config::LATEX_PATH)")
- if ( $LaTeXPath eq "" );
- } else {
- $output = "pdf";
- $LaTeXPath = $PdfLaTeXPath;
- $context->throw($fName,
- "pdflatex not installed (see Template::Config::PDFLATEX_PATH)")
- if ( $LaTeXPath eq "" );
- }
- if ( $output eq "ps" && $DviPSPath eq "" ) {
- $context->throw($fName,
- "dvips not installed (see Template::Config::DVIPS_PATH)");
- }
- if ( $^O !~ /^(MacOS|os2|VMS)$/i ) {
- return sub {
- local(*FH);
- my $text = shift;
- my $tmpRootDir = File::Spec->tmpdir();
- my $cnt = 0;
- my($tmpDir, $fileName, $devnull);
- my $texDoc = 'doc';
-
- do {
- $tmpDir = File::Spec->catdir($tmpRootDir,
- "tt2latex$$" . "_$cnt");
- $cnt++;
- } while ( -e $tmpDir );
- mkpath($tmpDir, 0, 0700);
- $context->throw($fName, "can't create temp dir $tmpDir")
- if ( !-d $tmpDir );
- $fileName = File::Spec->catfile($tmpDir, "$texDoc.tex");
- $devnull = File::Spec->devnull();
- if ( !open(FH, ">$fileName") ) {
- rmtree($tmpDir);
- $context->throw($fName, "can't open $fileName for output");
- }
- print(FH $text);
- close(FH);
-
- # latex must run in tmpDir directory
- my $currDir = cwd();
- if ( !chdir($tmpDir) ) {
- rmtree($tmpDir);
- $context->throw($fName, "can't chdir $tmpDir");
- }
- #
- # We don't need to quote the backslashes on windows, but we
- # do on other OSs
- #
- my $LaTeX_arg = "\\nonstopmode\\input{$texDoc}";
- $LaTeX_arg = "'$LaTeX_arg'" if ( $^O ne 'MSWin32' );
- if ( system("$LaTeXPath $LaTeX_arg"
- . " 1>$devnull 2>$devnull 0<$devnull") ) {
- my $texErrs = "";
- $fileName = File::Spec->catfile($tmpDir, "$texDoc.log");
- if ( open(FH, "<$fileName") ) {
- my $state = 0;
- #
- # Try to extract just the interesting errors from
- # the verbose log file
- #
- while ( <FH> ) {
- #
- # TeX errors seems to start with a "!" at the
- # start of the line, and are followed several
- # lines later by a line designator of the
- # form "l.nnn" where nnn is the line number.
- # We make sure we pick up every /^!/ line, and
- # the first /^l.\d/ line after each /^!/ line.
- #
- if ( /^(!.*)/ ) {
- $texErrs .= $1 . "\n";
- $state = 1;
- }
- if ( $state == 1 && /^(l\.\d.*)/ ) {
- $texErrs .= $1 . "\n";
- $state = 0;
- }
- }
- close(FH);
- } else {
- $texErrs = "Unable to open $fileName\n";
- }
- my $ok = chdir($currDir);
- rmtree($tmpDir);
- $context->throw($fName, "can't chdir $currDir") if ( !$ok );
- $context->throw($fName, "latex exited with errors:\n$texErrs");
- }
- if ( $output eq "ps" ) {
- $fileName = File::Spec->catfile($tmpDir, "$texDoc.dvi");
- if ( system("$DviPSPath $texDoc -o"
- . " 1>$devnull 2>$devnull 0<$devnull") ) {
- my $ok = chdir($currDir);
- rmtree($tmpDir);
- $context->throw($fName, "can't chdir $currDir") if ( !$ok );
- $context->throw($fName, "can't run $DviPSPath $fileName");
- }
- }
- if ( !chdir($currDir) ) {
- rmtree($tmpDir);
- $context->throw($fName, "can't chdir $currDir");
- }
-
- my $retStr;
- $fileName = File::Spec->catfile($tmpDir, "$texDoc.$output");
- if ( open(FH, $fileName) ) {
- local $/ = undef; # slurp file in one go
- binmode(FH);
- $retStr = <FH>;
- close(FH);
- } else {
- rmtree($tmpDir);
- $context->throw($fName, "Can't open output file $fileName");
- }
- rmtree($tmpDir);
- return $retStr;
- }
- } else {
- $context->throw("$fName not yet supported on $^O OS."
- . " Please contribute code!!");
- }
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Filters - Post-processing filters for template blocks
-
-=head1 SYNOPSIS
-
- use Template::Filters;
-
- $filters = Template::Filters->new(\%config);
-
- ($filter, $error) = $filters->fetch($name, \@args, $context);
-
-=head1 DESCRIPTION
-
-The Template::Filters module implements a provider for creating and/or
-returning subroutines that implement the standard filters. Additional
-custom filters may be provided via the FILTERS options.
-
-=head1 METHODS
-
-=head2 new(\%params)
-
-Constructor method which instantiates and returns a reference to a
-Template::Filters object. A reference to a hash array of configuration
-items may be passed as a parameter. These are described below.
-
- my $filters = Template::Filters->new({
- FILTERS => { ... },
- });
-
- my $template = Template->new({
- LOAD_FILTERS => [ $filters ],
- });
-
-A default Template::Filters module is created by the Template.pm module
-if the LOAD_FILTERS option isn't specified. All configuration parameters
-are forwarded to the constructor.
-
- $template = Template->new({
- FILTERS => { ... },
- });
-
-=head2 fetch($name, \@args, $context)
-
-Called to request that a filter of a given name be provided. The name
-of the filter should be specified as the first parameter. This should
-be one of the standard filters or one specified in the FILTERS
-configuration hash. The second argument should be a reference to an
-array containing configuration parameters for the filter. This may be
-specified as 0, or undef where no parameters are provided. The third
-argument should be a reference to the current Template::Context
-object.
-
-The method returns a reference to a filter sub-routine on success. It
-may also return (undef, STATUS_DECLINE) to decline the request, to allow
-delegation onto other filter providers in the LOAD_FILTERS chain of
-responsibility. On error, ($error, STATUS_ERROR) is returned where $error
-is an error message or Template::Exception object indicating the error
-that occurred.
-
-When the TOLERANT option is set, errors are automatically downgraded to
-a STATUS_DECLINE response.
-
-
-=head1 CONFIGURATION OPTIONS
-
-The following list details the configuration options that can be provided
-to the Template::Filters new() constructor.
-
-=over 4
-
-
-
-
-=item FILTERS
-
-The FILTERS option can be used to specify custom filters which can
-then be used with the FILTER directive like any other. These are
-added to the standard filters which are available by default. Filters
-specified via this option will mask any standard filters of the same
-name.
-
-The FILTERS option should be specified as a reference to a hash array
-in which each key represents the name of a filter. The corresponding
-value should contain a reference to an array containing a subroutine
-reference and a flag which indicates if the filter is static (0) or
-dynamic (1). A filter may also be specified as a solitary subroutine
-reference and is assumed to be static.
-
- $filters = Template::Filters->new({
- FILTERS => {
- 'sfilt1' => \&static_filter, # static
- 'sfilt2' => [ \&static_filter, 0 ], # same as above
- 'dfilt1' => [ \&dyanamic_filter_factory, 1 ],
- },
- });
-
-Additional filters can be specified at any time by calling the
-define_filter() method on the current Template::Context object.
-The method accepts a filter name, a reference to a filter
-subroutine and an optional flag to indicate if the filter is
-dynamic.
-
- my $context = $template->context();
- $context->define_filter('new_html', \&new_html);
- $context->define_filter('new_repeat', \&new_repeat, 1);
-
-Static filters are those where a single subroutine reference is used
-for all invocations of a particular filter. Filters that don't accept
-any configuration parameters (e.g. 'html') can be implemented
-statically. The subroutine reference is simply returned when that
-particular filter is requested. The subroutine is called to filter
-the output of a template block which is passed as the only argument.
-The subroutine should return the modified text.
-
- sub static_filter {
- my $text = shift;
- # do something to modify $text...
- return $text;
- }
-
-The following template fragment:
-
- [% FILTER sfilt1 %]
- Blah blah blah.
- [% END %]
-
-is approximately equivalent to:
-
- &static_filter("\nBlah blah blah.\n");
-
-Filters that can accept parameters (e.g. 'truncate') should be
-implemented dynamically. In this case, the subroutine is taken to be
-a filter 'factory' that is called to create a unique filter subroutine
-each time one is requested. A reference to the current
-Template::Context object is passed as the first parameter, followed by
-any additional parameters specified. The subroutine should return
-another subroutine reference (usually a closure) which implements the
-filter.
-
- sub dynamic_filter_factory {
- my ($context, @args) = @_;
-
- return sub {
- my $text = shift;
- # do something to modify $text...
- return $text;
- }
- }
-
-The following template fragment:
-
- [% FILTER dfilt1(123, 456) %]
- Blah blah blah
- [% END %]
-
-is approximately equivalent to:
-
- my $filter = &dynamic_filter_factory($context, 123, 456);
- &$filter("\nBlah blah blah.\n");
-
-See the FILTER directive for further examples.
-
-
-
-
-=item TOLERANT
-
-The TOLERANT flag is used by the various Template Toolkit provider
-modules (Template::Provider, Template::Plugins, Template::Filters) to
-control their behaviour when errors are encountered. By default, any
-errors are reported as such, with the request for the particular
-resource (template, plugin, filter) being denied and an exception
-raised. When the TOLERANT flag is set to any true values, errors will
-be silently ignored and the provider will instead return
-STATUS_DECLINED. This allows a subsequent provider to take
-responsibility for providing the resource, rather than failing the
-request outright. If all providers decline to service the request,
-either through tolerated failure or a genuine disinclination to
-comply, then a 'E<lt>resourceE<gt> not found' exception is raised.
-
-
-
-
-=item DEBUG
-
-The DEBUG option can be used to enable debugging messages from the
-Template::Filters module by setting it to include the DEBUG_FILTERS
-value.
-
- use Template::Constants qw( :debug );
-
- my $template = Template->new({
- DEBUG => DEBUG_FILTERS | DEBUG_PLUGINS,
- });
-
-
-
-
-=back
-
-=head1 TEMPLATE TOOLKIT FILTERS
-
-The following standard filters are distributed with the Template Toolkit.
-
-
-
-=head2 format(format)
-
-The 'format' filter takes a format string as a parameter (as per
-printf()) and formats each line of text accordingly.
-
- [% FILTER format('<!-- %-40s -->') %]
- This is a block of text filtered
- through the above format.
- [% END %]
-
-output:
-
- <!-- This is a block of text filtered -->
- <!-- through the above format. -->
-
-=head2 upper
-
-Folds the input to UPPER CASE.
-
- [% "hello world" FILTER upper %]
-
-output:
-
- HELLO WORLD
-
-=head2 lower
-
-Folds the input to lower case.
-
- [% "Hello World" FILTER lower %]
-
-output:
-
- hello world
-
-=head2 ucfirst
-
-Folds the first character of the input to UPPER CASE.
-
- [% "hello" FILTER ucfirst %]
-
-output:
-
- Hello
-
-=head2 lcfirst
-
-Folds the first character of the input to lower case.
-
- [% "HELLO" FILTER lcfirst %]
-
-output:
-
- hELLO
-
-=head2 trim
-
-Trims any leading or trailing whitespace from the input text. Particularly
-useful in conjunction with INCLUDE, PROCESS, etc., having the same effect
-as the TRIM configuration option.
-
- [% INCLUDE myfile | trim %]
-
-=head2 collapse
-
-Collapse any whitespace sequences in the input text into a single space.
-Leading and trailing whitespace (which would be reduced to a single space)
-is removed, as per trim.
-
- [% FILTER collapse %]
-
- The cat
-
- sat on
-
- the mat
-
- [% END %]
-
-output:
-
- The cat sat on the mat
-
-=head2 html
-
-Converts the characters 'E<lt>', 'E<gt>' and '&' to '&lt;', '&gt;' and
-'&amp;', respectively, protecting them from being interpreted as
-representing HTML tags or entities.
-
- [% FILTER html %]
- Binary "<=>" returns -1, 0, or 1 depending on...
- [% END %]
-
-output:
-
- Binary "&lt;=&gt;" returns -1, 0, or 1 depending on...
-
-=head2 html_entity
-
-The html filter is fast and simple but it doesn't encode the full
-range of HTML entities that your text may contain. The html_entity
-filter uses either the Apache::Util module (which is written in C and
-is therefore faster) or the HTML::Entities module (written in Perl but
-equally as comprehensive) to perform the encoding. If one or other of
-these modules are installed on your system then the text will be
-encoded (via the escape_html() or encode_entities() subroutines
-respectively) to convert all extended characters into their
-appropriate HTML entities (e.g. converting 'é' to '&eacute;'). If
-neither module is available on your system then an 'html_entity' exception
-will be thrown reporting an appropriate message.
-
-For further information on HTML entity encoding, see
-http://www.w3.org/TR/REC-html40/sgml/entities.html.
-
-=head2 html_para
-
-This filter formats a block of text into HTML paragraphs. A sequence of
-two or more newlines is used as the delimiter for paragraphs which are
-then wrapped in HTML E<lt>pE<gt>...E<lt>/pE<gt> tags.
-
- [% FILTER html_para %]
- The cat sat on the mat.
-
- Mary had a little lamb.
- [% END %]
-
-output:
-
- <p>
- The cat sat on the mat.
- </p>
-
- <p>
- Mary had a little lamb.
- </p>
-
-=head2 html_break / html_para_break
-
-Similar to the html_para filter described above, but uses the HTML tag
-sequence E<lt>brE<gt>E<lt>brE<gt> to join paragraphs.
-
- [% FILTER html_break %]
- The cat sat on the mat.
-
- Mary had a little lamb.
- [% END %]
-
-output:
-
- The cat sat on the mat.
- <br>
- <br>
- Mary had a little lamb.
-
-=head2 html_line_break
-
-This filter replaces any newlines with E<lt>brE<gt> HTML tags,
-thus preserving the line breaks of the original text in the
-HTML output.
-
- [% FILTER html_line_break %]
- The cat sat on the mat.
- Mary had a little lamb.
- [% END %]
-
-output:
-
- The cat sat on the mat.<br>
- Mary had a little lamb.<br>
-
-=head2 uri
-
-This filter URI escapes the input text, converting any characters
-outside of the permitted URI character set (as defined by RFC 2396)
-into a C<%nn> hex escape.
-
- [% 'my file.html' | uri %]
-
-output:
-
- my%20file.html
-
-Note that URI escaping isn't always enough when generating hyperlinks in
-an HTML document. The C<&> character, for example, is valid in a URI and
-will not be escaped by the URI filter. In this case you should also filter
-the text through the 'html' filter.
-
- <a href="[% filename | uri | html %]">click here</a>
-
-=head2 indent(pad)
-
-Indents the text block by a fixed pad string or width. The 'pad' argument
-can be specified as a string, or as a numerical value to indicate a pad
-width (spaces). Defaults to 4 spaces if unspecified.
-
- [% FILTER indent('ME> ') %]
- blah blah blah
- cabbages, rhubard, onions
- [% END %]
-
-output:
-
- ME> blah blah blah
- ME> cabbages, rhubard, onions
-
-=head2 truncate(length)
-
-Truncates the text block to the length specified, or a default length of
-32. Truncated text will be terminated with '...' (i.e. the '...' falls
-inside the required length, rather than appending to it).
-
- [% FILTER truncate(21) %]
- I have much to say on this matter that has previously
- been said on more than one occasion.
- [% END %]
-
-output:
-
- I have much to say...
-
-=head2 repeat(iterations)
-
-Repeats the text block for as many iterations as are specified (default: 1).
-
- [% FILTER repeat(3) %]
- We want more beer and we want more beer,
- [% END %]
- We are the more beer wanters!
-
-output:
-
- We want more beer and we want more beer,
- We want more beer and we want more beer,
- We want more beer and we want more beer,
- We are the more beer wanters!
-
-=head2 remove(string)
-
-Searches the input text for any occurrences of the specified string and
-removes them. A Perl regular expression may be specified as the search
-string.
-
- [% "The cat sat on the mat" FILTER remove('\s+') %]
-
-output:
-
- Thecatsatonthemat
-
-=head2 replace(search, replace)
-
-Similar to the remove filter described above, but taking a second parameter
-which is used as a replacement string for instances of the search string.
-
- [% "The cat sat on the mat" | replace('\s+', '_') %]
-
-output:
-
- The_cat_sat_on_the_mat
-
-=head2 redirect(file, options)
-
-The 'redirect' filter redirects the output of the block into a separate
-file, specified relative to the OUTPUT_PATH configuration item.
-
- [% FOREACH user = myorg.userlist %]
- [% FILTER redirect("users/${user.id}.html") %]
- [% INCLUDE userinfo %]
- [% END %]
- [% END %]
-
-or more succinctly, using side-effect notation:
-
- [% INCLUDE userinfo
- FILTER redirect("users/${user.id}.html")
- FOREACH user = myorg.userlist
- %]
-
-A 'file' exception will be thrown if the OUTPUT_PATH option is undefined.
-
-An optional 'binmode' argument can follow the filename to explicitly set
-the output file to binary mode.
-
- [% PROCESS my/png/generator
- FILTER redirect("images/logo.png", binmode=1) %]
-
-For backwards compatibility with earlier versions, a single true/false
-value can be used to set binary mode.
-
- [% PROCESS my/png/generator
- FILTER redirect("images/logo.png", 1) %]
-
-For the sake of future compatibility and clarity, if nothing else, we
-would strongly recommend you explicitly use the named 'binmode' option
-as shown in the first example.
-
-=head2 eval / evaltt
-
-The 'eval' filter evaluates the block as template text, processing
-any directives embedded within it. This allows template variables to
-contain template fragments, or for some method to be provided for
-returning template fragments from an external source such as a
-database, which can then be processed in the template as required.
-
- my $vars = {
- fragment => "The cat sat on the [% place %]",
- };
- $template->process($file, $vars);
-
-The following example:
-
- [% fragment | eval %]
-
-is therefore equivalent to
-
- The cat sat on the [% place %]
-
-The 'evaltt' filter is provided as an alias for 'eval'.
-
-=head2 perl / evalperl
-
-The 'perl' filter evaluates the block as Perl code. The EVAL_PERL
-option must be set to a true value or a 'perl' exception will be
-thrown.
-
- [% my_perl_code | perl %]
-
-In most cases, the [% PERL %] ... [% END %] block should suffice for
-evaluating Perl code, given that template directives are processed
-before being evaluate as Perl. Thus, the previous example could have
-been written in the more verbose form:
-
- [% PERL %]
- [% my_perl_code %]
- [% END %]
-
-as well as
-
- [% FILTER perl %]
- [% my_perl_code %]
- [% END %]
-
-The 'evalperl' filter is provided as an alias for 'perl' for backwards
-compatibility.
-
-=head2 stdout(options)
-
-The stdout filter prints the output generated by the enclosing block to
-STDOUT. The 'binmode' option can be passed as either a named parameter
-or a single argument to set STDOUT to binary mode (see the
-binmode perl function).
-
- [% PROCESS something/cool
- FILTER stdout(binmode=1) # recommended %]
-
- [% PROCESS something/cool
- FILTER stdout(1) # alternate %]
-
-The stdout filter can be used to force binmode on STDOUT, or also inside
-redirect, null or stderr blocks to make sure that particular output goes
-to stdout. See the null filter below for an example.
-
-=head2 stderr
-
-The stderr filter prints the output generated by the enclosing block to
-STDERR.
-
-=head2 null
-
-The null filter prints nothing. This is useful for plugins whose
-methods return values that you don't want to appear in the output.
-Rather than assigning every plugin method call to a dummy variable
-to silence it, you can wrap the block in a null filter:
-
- [% FILTER null;
- USE im = GD.Image(100,100);
- black = im.colorAllocate(0, 0, 0);
- red = im.colorAllocate(255,0, 0);
- blue = im.colorAllocate(0, 0, 255);
- im.arc(50,50,95,75,0,360,blue);
- im.fill(50,50,red);
- im.png | stdout(1);
- END;
- -%]
-
-Notice the use of the stdout filter to ensure that a particular expression
-generates output to stdout (in this case in binary mode).
-
-=head2 latex(outputType)
-
-Passes the text block to LaTeX and produces either PDF, DVI or
-PostScript output. The 'outputType' argument determines the output
-format and it should be set to one of the strings: "pdf" (default),
-"dvi", or "ps".
-
-The text block should be a complete LaTeX source file.
-
- [% FILTER latex("pdf") -%]
- \documentclass{article}
-
- \begin{document}
-
- \title{A Sample TT2 \LaTeX\ Source File}
- \author{Craig Barratt}
- \maketitle
-
- \section{Introduction}
- This is some text.
-
- \end{document}
- [% END -%]
-
-The output will be a PDF file. You should be careful not to prepend or
-append any extraneous characters or text outside the FILTER block,
-since this text will wrap the (binary) output of the latex filter.
-Notice the END directive uses '-%]' for the END_TAG to remove the
-trailing new line.
-
-One example where you might prepend text is in a CGI script where
-you might include the Content-Type before the latex output, eg:
-
- Content-Type: application/pdf
-
- [% FILTER latex("pdf") -%]
- \documentclass{article}
- \begin{document}
- ...
- \end{document}
- [% END -%]
-
-In other cases you might use the redirect filter to put the output
-into a file, rather than delivering it to stdout. This might be
-suitable for batch scripts:
-
- [% output = FILTER latex("pdf") -%]
- \documentclass{article}
- \begin{document}
- ...
- \end{document}
- [% END; output | redirect("document.pdf", 1) -%]
-
-(Notice the second argument to redirect to force binary mode.)
-
-Note that the latex filter runs one or two external programs, so it
-isn't very fast. But for modest documents the performance is adequate,
-even for interactive applications.
-
-A error of type 'latex' will be thrown if there is an error reported
-by latex, pdflatex or dvips.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.77, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template|Template>, L<Template::Context|Template::Context>, L<Template::Manual::Filters|Template::Manual::Filters>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Grammar.pm b/lib/Template/Grammar.pm
deleted file mode 100644
index 8635426..0000000
--- a/lib/Template/Grammar.pm
+++ /dev/null
@@ -1,6179 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Grammar
-#
-# DESCRIPTION
-# Grammar file for the Template Toolkit language containing token
-# definitions and parser state/rules tables generated by Parse::Yapp.
-#
-# AUTHOR
-# Andy Wardley <abw@wardley.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-#------------------------------------------------------------------------
-#
-# NOTE: this module is constructed from the parser/Grammar.pm.skel
-# file by running the parser/yc script. You only need to do this if
-# you have modified the grammar in the parser/Parser.yp file and need
-# to-recompile it. See the README in the 'parser' directory for more
-# information (sub-directory of the Template distribution).
-#
-#------------------------------------------------------------------------
-#
-# $Id: Grammar.pm,v 2.22 2004/01/13 16:19:10 abw Exp $
-#
-#========================================================================
-
-package Template::Grammar;
-
-require 5.004;
-
-use strict;
-use vars qw( $VERSION );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.22 $ =~ /(\d+)\.(\d+)/);
-
-my (@RESERVED, %CMPOP, $LEXTABLE, $RULES, $STATES);
-my ($factory, $rawstart);
-
-
-#========================================================================
-
-# Reserved words, comparison and binary operators
-#========================================================================
-
-@RESERVED = qw(
- GET CALL SET DEFAULT INSERT INCLUDE PROCESS WRAPPER BLOCK END
- USE PLUGIN FILTER MACRO PERL RAWPERL TO STEP AND OR NOT DIV MOD
- IF UNLESS ELSE ELSIF FOR NEXT WHILE SWITCH CASE META IN
- TRY THROW CATCH FINAL LAST RETURN STOP CLEAR VIEW DEBUG
- );
-
-# for historical reasons, != and == are converted to ne and eq to perform
-# stringwise comparison (mainly because it doesn't generate "non-numerical
-# comparison" warnings which != and == can) but the others (e.g. < > <= >=)
-# are not converted to their stringwise equivalents. I added 'gt' et al,
-# briefly for v2.04d and then took them out again in 2.04e.
-
-%CMPOP = qw(
- != ne
- == eq
- < <
- > >
- >= >=
- <= <=
-);
-
-
-#========================================================================
-# Lexer Token Table
-#========================================================================
-
-# lookup table used by lexer is initialised with special-cases
-$LEXTABLE = {
- 'FOREACH' => 'FOR',
- 'BREAK' => 'LAST',
- '&&' => 'AND',
- '||' => 'OR',
- '!' => 'NOT',
- '|' => 'FILTER',
- '.' => 'DOT',
- '_' => 'CAT',
- '..' => 'TO',
-# ':' => 'MACRO',
- '=' => 'ASSIGN',
- '=>' => 'ASSIGN',
-# '->' => 'ARROW',
- ',' => 'COMMA',
- '\\' => 'REF',
- 'and' => 'AND', # explicitly specified so that qw( and or
- 'or' => 'OR', # not ) can always be used in lower case,
- 'not' => 'NOT', # regardless of ANYCASE flag
- 'mod' => 'MOD',
- 'div' => 'DIV',
-};
-
-# localise the temporary variables needed to complete lexer table
-{
-# my @tokens = qw< ( ) [ ] { } ${ $ / ; : ? >;
- my @tokens = qw< ( ) [ ] { } ${ $ + / ; : ? >;
- my @cmpop = keys %CMPOP;
-# my @binop = qw( + - * % ); # '/' above, in @tokens
- my @binop = qw( - * % ); # '+' and '/' above, in @tokens
-
- # fill lexer table, slice by slice, with reserved words and operators
- @$LEXTABLE{ @RESERVED, @cmpop, @binop, @tokens }
- = ( @RESERVED, ('CMPOP') x @cmpop, ('BINOP') x @binop, @tokens );
-}
-
-
-#========================================================================
-# CLASS METHODS
-#========================================================================
-
-sub new {
- my $class = shift;
- bless {
- LEXTABLE => $LEXTABLE,
- STATES => $STATES,
- RULES => $RULES,
- }, $class;
-}
-
-# update method to set package-scoped $factory lexical
-sub install_factory {
- my ($self, $new_factory) = @_;
- $factory = $new_factory;
-}
-
-
-#========================================================================
-# States
-#========================================================================
-
-$STATES = [
- {#State 0
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'template' => 52,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'switch' => 34,
- 'try' => 35,
- 'assign' => 19,
- 'block' => 72,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 1
- ACTIONS => {
- "\$" => 43,
- 'LITERAL' => 75,
- 'IDENT' => 2,
- "\${" => 37
- },
- GOTOS => {
- 'setlist' => 76,
- 'item' => 39,
- 'assign' => 19,
- 'node' => 23,
- 'ident' => 74
- }
- },
- {#State 2
- DEFAULT => -130
- },
- {#State 3
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 79,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 4
- DEFAULT => -23
- },
- {#State 5
- ACTIONS => {
- ";" => 80
- }
- },
- {#State 6
- DEFAULT => -37
- },
- {#State 7
- DEFAULT => -14
- },
- {#State 8
- ACTIONS => {
- "\"" => 89,
- "\$" => 86,
- 'LITERAL' => 88,
- 'FILENAME' => 83,
- 'IDENT' => 81,
- 'NUMBER' => 84
- },
- GOTOS => {
- 'filepart' => 87,
- 'names' => 91,
- 'nameargs' => 90,
- 'filename' => 85,
- 'name' => 82
- }
- },
- {#State 9
- ACTIONS => {
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "]" => 94,
- "\${" => 37
- },
- GOTOS => {
- 'sterm' => 96,
- 'item' => 39,
- 'range' => 93,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 95,
- 'list' => 92,
- 'lterm' => 56
- }
- },
- {#State 10
- ACTIONS => {
- ";" => 97
- }
- },
- {#State 11
- DEFAULT => -5
- },
- {#State 12
- ACTIONS => {
- ";" => -20
- },
- DEFAULT => -27
- },
- {#State 13
- DEFAULT => -78,
- GOTOS => {
- '@5-1' => 98
- }
- },
- {#State 14
- ACTIONS => {
- 'IDENT' => 99
- },
- DEFAULT => -87,
- GOTOS => {
- 'blockargs' => 102,
- 'metadata' => 101,
- 'meta' => 100
- }
- },
- {#State 15
- ACTIONS => {
- 'IDENT' => 99
- },
- GOTOS => {
- 'metadata' => 103,
- 'meta' => 100
- }
- },
- {#State 16
- ACTIONS => {
- 'DOT' => 104,
- 'ASSIGN' => 105
- },
- DEFAULT => -109
- },
- {#State 17
- ACTIONS => {
- "\"" => 89,
- "\$" => 86,
- 'LITERAL' => 88,
- 'FILENAME' => 83,
- 'IDENT' => 81,
- 'NUMBER' => 84
- },
- GOTOS => {
- 'filepart' => 87,
- 'names' => 91,
- 'nameargs' => 106,
- 'filename' => 85,
- 'name' => 82
- }
- },
- {#State 18
- ACTIONS => {
- 'IDENT' => 107
- }
- },
- {#State 19
- DEFAULT => -149
- },
- {#State 20
- DEFAULT => -12
- },
- {#State 21
- ACTIONS => {
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 108,
- "\"" => 60,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'sterm' => 68,
- 'item' => 39,
- 'loopvar' => 110,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 109,
- 'lterm' => 56
- }
- },
- {#State 22
- DEFAULT => -40
- },
- {#State 23
- DEFAULT => -127
- },
- {#State 24
- DEFAULT => -6
- },
- {#State 25
- ACTIONS => {
- "\"" => 117,
- "\$" => 114,
- 'LITERAL' => 116,
- 'FILENAME' => 83,
- 'IDENT' => 111,
- 'NUMBER' => 84,
- "\${" => 37
- },
- GOTOS => {
- 'filepart' => 87,
- 'names' => 91,
- 'nameargs' => 118,
- 'filename' => 85,
- 'lvalue' => 112,
- 'lnameargs' => 115,
- 'item' => 113,
- 'name' => 82
- }
- },
- {#State 26
- DEFAULT => -113
- },
- {#State 27
- ACTIONS => {
- "\$" => 43,
- 'IDENT' => 2,
- "\${" => 37
- },
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'ident' => 119
- }
- },
- {#State 28
- ACTIONS => {
- 'LITERAL' => 124,
- 'FILENAME' => 83,
- 'IDENT' => 120,
- 'NUMBER' => 84
- },
- DEFAULT => -87,
- GOTOS => {
- 'blockargs' => 123,
- 'filepart' => 87,
- 'filename' => 122,
- 'blockname' => 121,
- 'metadata' => 101,
- 'meta' => 100
- }
- },
- {#State 29
- DEFAULT => -43
- },
- {#State 30
- ACTIONS => {
- "\$" => 43,
- 'LITERAL' => 129,
- 'IDENT' => 2,
- "\${" => 37
- },
- DEFAULT => -119,
- GOTOS => {
- 'params' => 128,
- 'hash' => 125,
- 'item' => 126,
- 'param' => 127
- }
- },
- {#State 31
- DEFAULT => -25
- },
- {#State 32
- ACTIONS => {
- "\"" => 117,
- "\$" => 114,
- 'LITERAL' => 116,
- 'FILENAME' => 83,
- 'IDENT' => 111,
- 'NUMBER' => 84,
- "\${" => 37
- },
- GOTOS => {
- 'filepart' => 87,
- 'names' => 91,
- 'nameargs' => 118,
- 'filename' => 85,
- 'lvalue' => 112,
- 'lnameargs' => 130,
- 'item' => 113,
- 'name' => 82
- }
- },
- {#State 33
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -2,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 131,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 34
- DEFAULT => -22
- },
- {#State 35
- DEFAULT => -24
- },
- {#State 36
- ACTIONS => {
- "\"" => 89,
- "\$" => 86,
- 'LITERAL' => 88,
- 'FILENAME' => 83,
- 'IDENT' => 81,
- 'NUMBER' => 84
- },
- GOTOS => {
- 'filepart' => 87,
- 'names' => 91,
- 'nameargs' => 132,
- 'filename' => 85,
- 'name' => 82
- }
- },
- {#State 37
- ACTIONS => {
- "\"" => 60,
- "\$" => 43,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- 'REF' => 27,
- 'NUMBER' => 26,
- "\${" => 37
- },
- GOTOS => {
- 'sterm' => 133,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77
- }
- },
- {#State 38
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 134,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 39
- ACTIONS => {
- "(" => 135
- },
- DEFAULT => -128
- },
- {#State 40
- ACTIONS => {
- ";" => 136
- }
- },
- {#State 41
- DEFAULT => -38
- },
- {#State 42
- DEFAULT => -11
- },
- {#State 43
- ACTIONS => {
- 'IDENT' => 137
- }
- },
- {#State 44
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 138,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 45
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 139,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 46
- DEFAULT => -42
- },
- {#State 47
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 140,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 48
- ACTIONS => {
- 'IF' => 144,
- 'FILTER' => 143,
- 'FOR' => 142,
- 'WHILE' => 146,
- 'WRAPPER' => 145,
- 'UNLESS' => 141
- }
- },
- {#State 49
- DEFAULT => -39
- },
- {#State 50
- DEFAULT => -10
- },
- {#State 51
- ACTIONS => {
- "\"" => 89,
- "\$" => 86,
- 'LITERAL' => 88,
- 'FILENAME' => 83,
- 'IDENT' => 81,
- 'NUMBER' => 84
- },
- GOTOS => {
- 'filepart' => 87,
- 'names' => 91,
- 'nameargs' => 147,
- 'filename' => 85,
- 'name' => 82
- }
- },
- {#State 52
- ACTIONS => {
- '' => 148
- }
- },
- {#State 53
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 57,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 149,
- 'term' => 58,
- 'expr' => 151,
- 'assign' => 150,
- 'lterm' => 56
- }
- },
- {#State 54
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 152,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 55
- ACTIONS => {
- "\"" => 89,
- "\$" => 86,
- 'LITERAL' => 88,
- 'FILENAME' => 83,
- 'IDENT' => 81,
- 'NUMBER' => 84
- },
- GOTOS => {
- 'filepart' => 87,
- 'names' => 91,
- 'nameargs' => 153,
- 'filename' => 85,
- 'name' => 82
- }
- },
- {#State 56
- DEFAULT => -103
- },
- {#State 57
- ACTIONS => {
- 'ASSIGN' => 154
- },
- DEFAULT => -112
- },
- {#State 58
- DEFAULT => -146
- },
- {#State 59
- DEFAULT => -15
- },
- {#State 60
- DEFAULT => -176,
- GOTOS => {
- 'quoted' => 155
- }
- },
- {#State 61
- ACTIONS => {
- "\"" => 89,
- "\$" => 86,
- 'LITERAL' => 88,
- 'FILENAME' => 83,
- 'IDENT' => 81,
- 'NUMBER' => 84
- },
- GOTOS => {
- 'filepart' => 87,
- 'names' => 91,
- 'nameargs' => 156,
- 'filename' => 85,
- 'name' => 82
- }
- },
- {#State 62
- ACTIONS => {
- ";" => -16,
- "+" => 157,
- 'CAT' => 163,
- 'CMPOP' => 164,
- "?" => 158,
- 'DIV' => 159,
- 'MOD' => 165,
- "/" => 166,
- 'AND' => 160,
- 'BINOP' => 161,
- 'OR' => 162
- },
- DEFAULT => -26
- },
- {#State 63
- DEFAULT => -13
- },
- {#State 64
- DEFAULT => -36
- },
- {#State 65
- ACTIONS => {
- "\"" => 89,
- "\$" => 86,
- 'LITERAL' => 88,
- 'FILENAME' => 83,
- 'IDENT' => 81,
- 'NUMBER' => 84
- },
- GOTOS => {
- 'filepart' => 87,
- 'names' => 91,
- 'nameargs' => 167,
- 'filename' => 85,
- 'name' => 82
- }
- },
- {#State 66
- DEFAULT => -9
- },
- {#State 67
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 168,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 68
- DEFAULT => -104
- },
- {#State 69
- ACTIONS => {
- "\$" => 43,
- 'LITERAL' => 75,
- 'IDENT' => 2,
- "\${" => 37
- },
- GOTOS => {
- 'setlist' => 169,
- 'item' => 39,
- 'assign' => 19,
- 'node' => 23,
- 'ident' => 74
- }
- },
- {#State 70
- ACTIONS => {
- "\$" => 43,
- 'COMMA' => 171,
- 'LITERAL' => 75,
- 'IDENT' => 2,
- "\${" => 37
- },
- DEFAULT => -19,
- GOTOS => {
- 'item' => 39,
- 'assign' => 170,
- 'node' => 23,
- 'ident' => 74
- }
- },
- {#State 71
- DEFAULT => -8
- },
- {#State 72
- DEFAULT => -1
- },
- {#State 73
- DEFAULT => -21
- },
- {#State 74
- ACTIONS => {
- 'ASSIGN' => 172,
- 'DOT' => 104
- }
- },
- {#State 75
- ACTIONS => {
- 'ASSIGN' => 154
- }
- },
- {#State 76
- ACTIONS => {
- "\$" => 43,
- 'COMMA' => 171,
- 'LITERAL' => 75,
- 'IDENT' => 2,
- "\${" => 37
- },
- DEFAULT => -30,
- GOTOS => {
- 'item' => 39,
- 'assign' => 170,
- 'node' => 23,
- 'ident' => 74
- }
- },
- {#State 77
- ACTIONS => {
- 'DOT' => 104
- },
- DEFAULT => -109
- },
- {#State 78
- DEFAULT => -112
- },
- {#State 79
- ACTIONS => {
- 'CMPOP' => 164,
- "?" => 158,
- ";" => 173,
- "+" => 157,
- 'MOD' => 165,
- 'DIV' => 159,
- "/" => 166,
- 'AND' => 160,
- 'CAT' => 163,
- 'BINOP' => 161,
- 'OR' => 162
- }
- },
- {#State 80
- DEFAULT => -7
- },
- {#State 81
- DEFAULT => -173
- },
- {#State 82
- DEFAULT => -166
- },
- {#State 83
- DEFAULT => -172
- },
- {#State 84
- DEFAULT => -174
- },
- {#State 85
- ACTIONS => {
- 'DOT' => 174
- },
- DEFAULT => -168
- },
- {#State 86
- ACTIONS => {
- "\$" => 43,
- 'IDENT' => 2,
- "\${" => 37
- },
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'ident' => 175
- }
- },
- {#State 87
- DEFAULT => -171
- },
- {#State 88
- DEFAULT => -169
- },
- {#State 89
- DEFAULT => -176,
- GOTOS => {
- 'quoted' => 176
- }
- },
- {#State 90
- DEFAULT => -35
- },
- {#State 91
- ACTIONS => {
- "+" => 177,
- "(" => 178
- },
- DEFAULT => -156,
- GOTOS => {
- 'args' => 179
- }
- },
- {#State 92
- ACTIONS => {
- "{" => 30,
- 'COMMA' => 182,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "]" => 180,
- "\${" => 37
- },
- GOTOS => {
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 181,
- 'lterm' => 56
- }
- },
- {#State 93
- ACTIONS => {
- "]" => 183
- }
- },
- {#State 94
- DEFAULT => -107
- },
- {#State 95
- DEFAULT => -116
- },
- {#State 96
- ACTIONS => {
- 'TO' => 184
- },
- DEFAULT => -104
- },
- {#State 97
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 185,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 98
- ACTIONS => {
- ";" => 186
- }
- },
- {#State 99
- ACTIONS => {
- 'ASSIGN' => 187
- }
- },
- {#State 100
- DEFAULT => -99
- },
- {#State 101
- ACTIONS => {
- 'COMMA' => 189,
- 'IDENT' => 99
- },
- DEFAULT => -86,
- GOTOS => {
- 'meta' => 188
- }
- },
- {#State 102
- ACTIONS => {
- ";" => 190
- }
- },
- {#State 103
- ACTIONS => {
- 'COMMA' => 189,
- 'IDENT' => 99
- },
- DEFAULT => -17,
- GOTOS => {
- 'meta' => 188
- }
- },
- {#State 104
- ACTIONS => {
- "\$" => 43,
- 'IDENT' => 2,
- 'NUMBER' => 192,
- "\${" => 37
- },
- GOTOS => {
- 'item' => 39,
- 'node' => 191
- }
- },
- {#State 105
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'WRAPPER' => 55,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- "\"" => 60,
- 'PROCESS' => 61,
- 'FILTER' => 25,
- 'RETURN' => 64,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 193,
- 'DEFAULT' => 69,
- "{" => 30,
- "\${" => 37
- },
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'term' => 58,
- 'loop' => 4,
- 'expr' => 195,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'atomdir' => 12,
- 'mdir' => 194,
- 'sterm' => 68,
- 'filter' => 29,
- 'ident' => 149,
- 'perl' => 31,
- 'setlist' => 70,
- 'switch' => 34,
- 'try' => 35,
- 'assign' => 19,
- 'directive' => 196,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 106
- DEFAULT => -33
- },
- {#State 107
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'INCLUDE' => 17,
- "(" => 198,
- 'SWITCH' => 54,
- 'WRAPPER' => 55,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- "\"" => 60,
- 'PROCESS' => 61,
- 'FILTER' => 25,
- 'RETURN' => 64,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 193,
- 'DEFAULT' => 69,
- "{" => 30,
- "\${" => 37
- },
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'term' => 58,
- 'loop' => 4,
- 'expr' => 199,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'atomdir' => 12,
- 'mdir' => 197,
- 'sterm' => 68,
- 'filter' => 29,
- 'ident' => 149,
- 'perl' => 31,
- 'setlist' => 70,
- 'switch' => 34,
- 'try' => 35,
- 'assign' => 19,
- 'directive' => 196,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 108
- ACTIONS => {
- 'IN' => 201,
- 'ASSIGN' => 200
- },
- DEFAULT => -130
- },
- {#State 109
- DEFAULT => -156,
- GOTOS => {
- 'args' => 202
- }
- },
- {#State 110
- ACTIONS => {
- ";" => 203
- }
- },
- {#State 111
- ACTIONS => {
- 'ASSIGN' => -130
- },
- DEFAULT => -173
- },
- {#State 112
- ACTIONS => {
- 'ASSIGN' => 204
- }
- },
- {#State 113
- DEFAULT => -159
- },
- {#State 114
- ACTIONS => {
- "\$" => 43,
- 'IDENT' => 205,
- "\${" => 37
- },
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'ident' => 175
- }
- },
- {#State 115
- ACTIONS => {
- ";" => 206
- }
- },
- {#State 116
- ACTIONS => {
- 'ASSIGN' => -161
- },
- DEFAULT => -169
- },
- {#State 117
- DEFAULT => -176,
- GOTOS => {
- 'quoted' => 207
- }
- },
- {#State 118
- DEFAULT => -158
- },
- {#State 119
- ACTIONS => {
- 'DOT' => 104
- },
- DEFAULT => -110
- },
- {#State 120
- ACTIONS => {
- 'ASSIGN' => 187
- },
- DEFAULT => -173
- },
- {#State 121
- DEFAULT => -83
- },
- {#State 122
- ACTIONS => {
- 'DOT' => 174
- },
- DEFAULT => -84
- },
- {#State 123
- ACTIONS => {
- ";" => 208
- }
- },
- {#State 124
- DEFAULT => -85
- },
- {#State 125
- ACTIONS => {
- "}" => 209
- }
- },
- {#State 126
- ACTIONS => {
- 'ASSIGN' => 210
- }
- },
- {#State 127
- DEFAULT => -122
- },
- {#State 128
- ACTIONS => {
- "\$" => 43,
- 'COMMA' => 212,
- 'LITERAL' => 129,
- 'IDENT' => 2,
- "\${" => 37
- },
- DEFAULT => -118,
- GOTOS => {
- 'item' => 126,
- 'param' => 211
- }
- },
- {#State 129
- ACTIONS => {
- 'ASSIGN' => 213
- }
- },
- {#State 130
- DEFAULT => -73
- },
- {#State 131
- DEFAULT => -4
- },
- {#State 132
- ACTIONS => {
- ";" => 214
- }
- },
- {#State 133
- ACTIONS => {
- "}" => 215
- }
- },
- {#State 134
- ACTIONS => {
- "+" => 157,
- 'CAT' => 163,
- 'CMPOP' => 164,
- 'DIV' => 159,
- 'MOD' => 165,
- "/" => 166,
- 'BINOP' => 161
- },
- DEFAULT => -142
- },
- {#State 135
- DEFAULT => -156,
- GOTOS => {
- 'args' => 216
- }
- },
- {#State 136
- DEFAULT => -76,
- GOTOS => {
- '@4-2' => 217
- }
- },
- {#State 137
- DEFAULT => -132
- },
- {#State 138
- ACTIONS => {
- 'CMPOP' => 164,
- "?" => 158,
- ";" => 218,
- "+" => 157,
- 'MOD' => 165,
- 'DIV' => 159,
- "/" => 166,
- 'AND' => 160,
- 'CAT' => 163,
- 'BINOP' => 161,
- 'OR' => 162
- }
- },
- {#State 139
- ACTIONS => {
- "+" => 157,
- 'CAT' => 163,
- 'CMPOP' => 164,
- "?" => 158,
- 'DIV' => 159,
- 'MOD' => 165,
- "/" => 166,
- 'AND' => 160,
- 'BINOP' => 161,
- 'OR' => 162
- },
- DEFAULT => -29
- },
- {#State 140
- ACTIONS => {
- "+" => 157,
- 'CAT' => 163,
- 'CMPOP' => 164,
- "?" => 158,
- 'DIV' => 159,
- 'MOD' => 165,
- "/" => 166,
- 'AND' => 160,
- 'BINOP' => 161,
- 'OR' => 162
- },
- DEFAULT => -28
- },
- {#State 141
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 219,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 142
- ACTIONS => {
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 108,
- "\"" => 60,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'sterm' => 68,
- 'item' => 39,
- 'loopvar' => 220,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 109,
- 'lterm' => 56
- }
- },
- {#State 143
- ACTIONS => {
- "\"" => 117,
- "\$" => 114,
- 'LITERAL' => 116,
- 'FILENAME' => 83,
- 'IDENT' => 111,
- 'NUMBER' => 84,
- "\${" => 37
- },
- GOTOS => {
- 'filepart' => 87,
- 'names' => 91,
- 'nameargs' => 118,
- 'filename' => 85,
- 'lvalue' => 112,
- 'lnameargs' => 221,
- 'item' => 113,
- 'name' => 82
- }
- },
- {#State 144
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 222,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 145
- ACTIONS => {
- "\"" => 89,
- "\$" => 86,
- 'LITERAL' => 88,
- 'FILENAME' => 83,
- 'IDENT' => 81,
- 'NUMBER' => 84
- },
- GOTOS => {
- 'filepart' => 87,
- 'names' => 91,
- 'nameargs' => 223,
- 'filename' => 85,
- 'name' => 82
- }
- },
- {#State 146
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 224,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 147
- DEFAULT => -41
- },
- {#State 148
- DEFAULT => 0
- },
- {#State 149
- ACTIONS => {
- 'DOT' => 104,
- 'ASSIGN' => 172
- },
- DEFAULT => -109
- },
- {#State 150
- ACTIONS => {
- ")" => 225
- }
- },
- {#State 151
- ACTIONS => {
- 'CMPOP' => 164,
- "?" => 158,
- "+" => 157,
- 'MOD' => 165,
- 'DIV' => 159,
- "/" => 166,
- 'AND' => 160,
- 'CAT' => 163,
- 'BINOP' => 161,
- ")" => 226,
- 'OR' => 162
- }
- },
- {#State 152
- ACTIONS => {
- 'CMPOP' => 164,
- "?" => 158,
- ";" => 227,
- "+" => 157,
- 'MOD' => 165,
- 'DIV' => 159,
- "/" => 166,
- 'AND' => 160,
- 'CAT' => 163,
- 'BINOP' => 161,
- 'OR' => 162
- }
- },
- {#State 153
- ACTIONS => {
- ";" => 228
- }
- },
- {#State 154
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 229,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 155
- ACTIONS => {
- "\"" => 234,
- 'TEXT' => 231,
- ";" => 233,
- "\$" => 43,
- 'IDENT' => 2,
- "\${" => 37
- },
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'ident' => 230,
- 'quotable' => 232
- }
- },
- {#State 156
- DEFAULT => -34
- },
- {#State 157
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 235,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 158
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 236,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 159
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 237,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 160
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 238,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 161
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 239,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 162
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 240,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 163
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 241,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 164
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 242,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 165
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 243,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 166
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 244,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 167
- DEFAULT => -32
- },
- {#State 168
- ACTIONS => {
- 'CMPOP' => 164,
- "?" => 158,
- ";" => 245,
- "+" => 157,
- 'MOD' => 165,
- 'DIV' => 159,
- "/" => 166,
- 'AND' => 160,
- 'CAT' => 163,
- 'BINOP' => 161,
- 'OR' => 162
- }
- },
- {#State 169
- ACTIONS => {
- "\$" => 43,
- 'COMMA' => 171,
- 'LITERAL' => 75,
- 'IDENT' => 2,
- "\${" => 37
- },
- DEFAULT => -31,
- GOTOS => {
- 'item' => 39,
- 'assign' => 170,
- 'node' => 23,
- 'ident' => 74
- }
- },
- {#State 170
- DEFAULT => -147
- },
- {#State 171
- DEFAULT => -148
- },
- {#State 172
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 246,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 173
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 247,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 174
- ACTIONS => {
- 'FILENAME' => 83,
- 'IDENT' => 81,
- 'NUMBER' => 84
- },
- GOTOS => {
- 'filepart' => 248
- }
- },
- {#State 175
- ACTIONS => {
- 'DOT' => 104
- },
- DEFAULT => -156,
- GOTOS => {
- 'args' => 249
- }
- },
- {#State 176
- ACTIONS => {
- "\"" => 250,
- 'TEXT' => 231,
- ";" => 233,
- "\$" => 43,
- 'IDENT' => 2,
- "\${" => 37
- },
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'ident' => 230,
- 'quotable' => 232
- }
- },
- {#State 177
- ACTIONS => {
- "\"" => 89,
- 'LITERAL' => 88,
- 'FILENAME' => 83,
- 'IDENT' => 81,
- 'NUMBER' => 84
- },
- GOTOS => {
- 'filepart' => 87,
- 'filename' => 85,
- 'name' => 251
- }
- },
- {#State 178
- DEFAULT => -156,
- GOTOS => {
- 'args' => 252
- }
- },
- {#State 179
- ACTIONS => {
- "{" => 30,
- 'COMMA' => 258,
- 'LITERAL' => 256,
- 'IDENT' => 2,
- "\"" => 60,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- DEFAULT => -163,
- GOTOS => {
- 'sterm' => 68,
- 'item' => 254,
- 'param' => 255,
- 'node' => 23,
- 'ident' => 253,
- 'term' => 257,
- 'lterm' => 56
- }
- },
- {#State 180
- DEFAULT => -105
- },
- {#State 181
- DEFAULT => -114
- },
- {#State 182
- DEFAULT => -115
- },
- {#State 183
- DEFAULT => -106
- },
- {#State 184
- ACTIONS => {
- "\"" => 60,
- "\$" => 43,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- 'REF' => 27,
- 'NUMBER' => 26,
- "\${" => 37
- },
- GOTOS => {
- 'sterm' => 259,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77
- }
- },
- {#State 185
- ACTIONS => {
- 'FINAL' => 260,
- 'CATCH' => 262
- },
- DEFAULT => -72,
- GOTOS => {
- 'final' => 261
- }
- },
- {#State 186
- ACTIONS => {
- 'TEXT' => 263
- }
- },
- {#State 187
- ACTIONS => {
- "\"" => 266,
- 'LITERAL' => 265,
- 'NUMBER' => 264
- }
- },
- {#State 188
- DEFAULT => -97
- },
- {#State 189
- DEFAULT => -98
- },
- {#State 190
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'template' => 267,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 72,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 191
- DEFAULT => -125
- },
- {#State 192
- DEFAULT => -126
- },
- {#State 193
- ACTIONS => {
- ";" => 268
- }
- },
- {#State 194
- DEFAULT => -89
- },
- {#State 195
- ACTIONS => {
- ";" => -150,
- "+" => 157,
- 'LITERAL' => -150,
- 'IDENT' => -150,
- 'CAT' => 163,
- "\$" => -150,
- 'CMPOP' => 164,
- "?" => 158,
- 'DIV' => 159,
- 'MOD' => 165,
- 'COMMA' => -150,
- "/" => 166,
- 'AND' => 160,
- 'BINOP' => 161,
- 'OR' => 162,
- "\${" => -150
- },
- DEFAULT => -26
- },
- {#State 196
- DEFAULT => -92
- },
- {#State 197
- DEFAULT => -91
- },
- {#State 198
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 57,
- 'IDENT' => 269,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'sterm' => 68,
- 'item' => 39,
- 'margs' => 270,
- 'node' => 23,
- 'ident' => 149,
- 'term' => 58,
- 'expr' => 151,
- 'assign' => 150,
- 'lterm' => 56
- }
- },
- {#State 199
- ACTIONS => {
- "+" => 157,
- 'CAT' => 163,
- 'CMPOP' => 164,
- "?" => 158,
- 'DIV' => 159,
- 'MOD' => 165,
- "/" => 166,
- 'AND' => 160,
- 'BINOP' => 161,
- 'OR' => 162
- },
- DEFAULT => -26
- },
- {#State 200
- ACTIONS => {
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 271,
- 'lterm' => 56
- }
- },
- {#State 201
- ACTIONS => {
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 272,
- 'lterm' => 56
- }
- },
- {#State 202
- ACTIONS => {
- "{" => 30,
- 'COMMA' => 258,
- 'LITERAL' => 256,
- 'IDENT' => 2,
- "\"" => 60,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- DEFAULT => -64,
- GOTOS => {
- 'sterm' => 68,
- 'item' => 254,
- 'param' => 255,
- 'node' => 23,
- 'ident' => 253,
- 'term' => 257,
- 'lterm' => 56
- }
- },
- {#State 203
- DEFAULT => -56,
- GOTOS => {
- '@1-3' => 273
- }
- },
- {#State 204
- ACTIONS => {
- "\"" => 89,
- "\$" => 86,
- 'LITERAL' => 88,
- 'FILENAME' => 83,
- 'IDENT' => 81,
- 'NUMBER' => 84
- },
- GOTOS => {
- 'filepart' => 87,
- 'names' => 91,
- 'nameargs' => 274,
- 'filename' => 85,
- 'name' => 82
- }
- },
- {#State 205
- ACTIONS => {
- 'ASSIGN' => -132
- },
- DEFAULT => -130
- },
- {#State 206
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 275,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 207
- ACTIONS => {
- "\"" => 276,
- 'TEXT' => 231,
- ";" => 233,
- "\$" => 43,
- 'IDENT' => 2,
- "\${" => 37
- },
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'ident' => 230,
- 'quotable' => 232
- }
- },
- {#State 208
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 277,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 209
- DEFAULT => -108
- },
- {#State 210
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 278,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 211
- DEFAULT => -120
- },
- {#State 212
- DEFAULT => -121
- },
- {#State 213
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 279,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 214
- DEFAULT => -74,
- GOTOS => {
- '@3-3' => 280
- }
- },
- {#State 215
- DEFAULT => -131
- },
- {#State 216
- ACTIONS => {
- "{" => 30,
- 'COMMA' => 258,
- 'LITERAL' => 256,
- 'IDENT' => 2,
- "\"" => 60,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- ")" => 281,
- "\${" => 37
- },
- GOTOS => {
- 'sterm' => 68,
- 'item' => 254,
- 'param' => 255,
- 'node' => 23,
- 'ident' => 253,
- 'term' => 257,
- 'lterm' => 56
- }
- },
- {#State 217
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 282,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 218
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 283,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 219
- ACTIONS => {
- 'CMPOP' => 164,
- "?" => 158,
- "+" => 157,
- 'MOD' => 165,
- 'DIV' => 159,
- "/" => 166,
- 'AND' => 160,
- 'CAT' => 163,
- 'BINOP' => 161,
- 'OR' => 162
- },
- DEFAULT => -47
- },
- {#State 220
- DEFAULT => -58
- },
- {#State 221
- DEFAULT => -81
- },
- {#State 222
- ACTIONS => {
- 'CMPOP' => 164,
- "?" => 158,
- "+" => 157,
- 'MOD' => 165,
- 'DIV' => 159,
- "/" => 166,
- 'AND' => 160,
- 'CAT' => 163,
- 'BINOP' => 161,
- 'OR' => 162
- },
- DEFAULT => -45
- },
- {#State 223
- DEFAULT => -66
- },
- {#State 224
- ACTIONS => {
- 'CMPOP' => 164,
- "?" => 158,
- "+" => 157,
- 'MOD' => 165,
- 'DIV' => 159,
- "/" => 166,
- 'AND' => 160,
- 'CAT' => 163,
- 'BINOP' => 161,
- 'OR' => 162
- },
- DEFAULT => -61
- },
- {#State 225
- DEFAULT => -144
- },
- {#State 226
- DEFAULT => -145
- },
- {#State 227
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 284,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 228
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 285,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 229
- ACTIONS => {
- "+" => 157,
- 'CAT' => 163,
- 'CMPOP' => 164,
- "?" => 158,
- 'DIV' => 159,
- 'MOD' => 165,
- "/" => 166,
- 'AND' => 160,
- 'BINOP' => 161,
- 'OR' => 162
- },
- DEFAULT => -151
- },
- {#State 230
- ACTIONS => {
- 'DOT' => 104
- },
- DEFAULT => -177
- },
- {#State 231
- DEFAULT => -178
- },
- {#State 232
- DEFAULT => -175
- },
- {#State 233
- DEFAULT => -179
- },
- {#State 234
- DEFAULT => -111
- },
- {#State 235
- ACTIONS => {
- 'DIV' => 159,
- 'MOD' => 165,
- "/" => 166
- },
- DEFAULT => -135
- },
- {#State 236
- ACTIONS => {
- ":" => 286,
- 'CMPOP' => 164,
- "?" => 158,
- "+" => 157,
- 'MOD' => 165,
- 'DIV' => 159,
- "/" => 166,
- 'AND' => 160,
- 'CAT' => 163,
- 'BINOP' => 161,
- 'OR' => 162
- }
- },
- {#State 237
- ACTIONS => {
- 'MOD' => 165
- },
- DEFAULT => -136
- },
- {#State 238
- ACTIONS => {
- "+" => 157,
- 'CAT' => 163,
- 'CMPOP' => 164,
- 'DIV' => 159,
- 'MOD' => 165,
- "/" => 166,
- 'BINOP' => 161
- },
- DEFAULT => -140
- },
- {#State 239
- ACTIONS => {
- "+" => 157,
- 'DIV' => 159,
- 'MOD' => 165,
- "/" => 166
- },
- DEFAULT => -133
- },
- {#State 240
- ACTIONS => {
- "+" => 157,
- 'CAT' => 163,
- 'CMPOP' => 164,
- 'DIV' => 159,
- 'MOD' => 165,
- "/" => 166,
- 'BINOP' => 161
- },
- DEFAULT => -141
- },
- {#State 241
- ACTIONS => {
- "+" => 157,
- 'CMPOP' => 164,
- 'DIV' => 159,
- 'MOD' => 165,
- "/" => 166,
- 'BINOP' => 161
- },
- DEFAULT => -139
- },
- {#State 242
- ACTIONS => {
- "+" => 157,
- 'DIV' => 159,
- 'MOD' => 165,
- "/" => 166,
- 'BINOP' => 161
- },
- DEFAULT => -138
- },
- {#State 243
- DEFAULT => -137
- },
- {#State 244
- ACTIONS => {
- 'DIV' => 159,
- 'MOD' => 165
- },
- DEFAULT => -134
- },
- {#State 245
- DEFAULT => -59,
- GOTOS => {
- '@2-3' => 287
- }
- },
- {#State 246
- ACTIONS => {
- "+" => 157,
- 'CAT' => 163,
- 'CMPOP' => 164,
- "?" => 158,
- 'DIV' => 159,
- 'MOD' => 165,
- "/" => 166,
- 'AND' => 160,
- 'BINOP' => 161,
- 'OR' => 162
- },
- DEFAULT => -150
- },
- {#State 247
- ACTIONS => {
- 'ELSIF' => 290,
- 'ELSE' => 288
- },
- DEFAULT => -50,
- GOTOS => {
- 'else' => 289
- }
- },
- {#State 248
- DEFAULT => -170
- },
- {#State 249
- ACTIONS => {
- "{" => 30,
- 'COMMA' => 258,
- 'LITERAL' => 256,
- 'IDENT' => 2,
- "\"" => 60,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- DEFAULT => -162,
- GOTOS => {
- 'sterm' => 68,
- 'item' => 254,
- 'param' => 255,
- 'node' => 23,
- 'ident' => 253,
- 'term' => 257,
- 'lterm' => 56
- }
- },
- {#State 250
- DEFAULT => -167
- },
- {#State 251
- DEFAULT => -165
- },
- {#State 252
- ACTIONS => {
- "{" => 30,
- 'COMMA' => 258,
- 'LITERAL' => 256,
- 'IDENT' => 2,
- "\"" => 60,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- ")" => 291,
- "\${" => 37
- },
- GOTOS => {
- 'sterm' => 68,
- 'item' => 254,
- 'param' => 255,
- 'node' => 23,
- 'ident' => 253,
- 'term' => 257,
- 'lterm' => 56
- }
- },
- {#State 253
- ACTIONS => {
- 'DOT' => 104,
- 'ASSIGN' => 292
- },
- DEFAULT => -109
- },
- {#State 254
- ACTIONS => {
- "(" => 135,
- 'ASSIGN' => 210
- },
- DEFAULT => -128
- },
- {#State 255
- DEFAULT => -153
- },
- {#State 256
- ACTIONS => {
- 'ASSIGN' => 213
- },
- DEFAULT => -112
- },
- {#State 257
- DEFAULT => -152
- },
- {#State 258
- DEFAULT => -155
- },
- {#State 259
- DEFAULT => -117
- },
- {#State 260
- ACTIONS => {
- ";" => 293
- }
- },
- {#State 261
- ACTIONS => {
- 'END' => 294
- }
- },
- {#State 262
- ACTIONS => {
- ";" => 296,
- 'DEFAULT' => 297,
- 'FILENAME' => 83,
- 'IDENT' => 81,
- 'NUMBER' => 84
- },
- GOTOS => {
- 'filepart' => 87,
- 'filename' => 295
- }
- },
- {#State 263
- ACTIONS => {
- 'END' => 298
- }
- },
- {#State 264
- DEFAULT => -102
- },
- {#State 265
- DEFAULT => -100
- },
- {#State 266
- ACTIONS => {
- 'TEXT' => 299
- }
- },
- {#State 267
- ACTIONS => {
- 'END' => 300
- }
- },
- {#State 268
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 301,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 269
- ACTIONS => {
- 'COMMA' => -96,
- 'IDENT' => -96,
- ")" => -96
- },
- DEFAULT => -130
- },
- {#State 270
- ACTIONS => {
- 'COMMA' => 304,
- 'IDENT' => 302,
- ")" => 303
- }
- },
- {#State 271
- DEFAULT => -156,
- GOTOS => {
- 'args' => 305
- }
- },
- {#State 272
- DEFAULT => -156,
- GOTOS => {
- 'args' => 306
- }
- },
- {#State 273
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 307,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 274
- DEFAULT => -157
- },
- {#State 275
- ACTIONS => {
- 'END' => 308
- }
- },
- {#State 276
- ACTIONS => {
- 'ASSIGN' => -160
- },
- DEFAULT => -167
- },
- {#State 277
- ACTIONS => {
- 'END' => 309
- }
- },
- {#State 278
- ACTIONS => {
- "+" => 157,
- 'CAT' => 163,
- 'CMPOP' => 164,
- "?" => 158,
- 'DIV' => 159,
- 'MOD' => 165,
- "/" => 166,
- 'AND' => 160,
- 'BINOP' => 161,
- 'OR' => 162
- },
- DEFAULT => -124
- },
- {#State 279
- ACTIONS => {
- "+" => 157,
- 'CAT' => 163,
- 'CMPOP' => 164,
- "?" => 158,
- 'DIV' => 159,
- 'MOD' => 165,
- "/" => 166,
- 'AND' => 160,
- 'BINOP' => 161,
- 'OR' => 162
- },
- DEFAULT => -123
- },
- {#State 280
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 310,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 281
- DEFAULT => -129
- },
- {#State 282
- ACTIONS => {
- 'END' => 311
- }
- },
- {#State 283
- ACTIONS => {
- 'ELSIF' => 290,
- 'ELSE' => 288
- },
- DEFAULT => -50,
- GOTOS => {
- 'else' => 312
- }
- },
- {#State 284
- ACTIONS => {
- 'CASE' => 313
- },
- DEFAULT => -55,
- GOTOS => {
- 'case' => 314
- }
- },
- {#State 285
- ACTIONS => {
- 'END' => 315
- }
- },
- {#State 286
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 316,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 287
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 317,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 288
- ACTIONS => {
- ";" => 318
- }
- },
- {#State 289
- ACTIONS => {
- 'END' => 319
- }
- },
- {#State 290
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 320,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 291
- DEFAULT => -164
- },
- {#State 292
- ACTIONS => {
- 'NOT' => 38,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "(" => 53,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'expr' => 321,
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 58,
- 'lterm' => 56
- }
- },
- {#State 293
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 322,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 294
- DEFAULT => -67
- },
- {#State 295
- ACTIONS => {
- 'DOT' => 174,
- ";" => 323
- }
- },
- {#State 296
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 324,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 297
- ACTIONS => {
- ";" => 325
- }
- },
- {#State 298
- DEFAULT => -79
- },
- {#State 299
- ACTIONS => {
- "\"" => 326
- }
- },
- {#State 300
- DEFAULT => -82
- },
- {#State 301
- ACTIONS => {
- 'END' => 327
- }
- },
- {#State 302
- DEFAULT => -94
- },
- {#State 303
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'WRAPPER' => 55,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- "\"" => 60,
- 'PROCESS' => 61,
- 'FILTER' => 25,
- 'RETURN' => 64,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 193,
- 'DEFAULT' => 69,
- "{" => 30,
- "\${" => 37
- },
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'term' => 58,
- 'loop' => 4,
- 'expr' => 199,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'atomdir' => 12,
- 'mdir' => 328,
- 'sterm' => 68,
- 'filter' => 29,
- 'ident' => 149,
- 'perl' => 31,
- 'setlist' => 70,
- 'switch' => 34,
- 'try' => 35,
- 'assign' => 19,
- 'directive' => 196,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 304
- DEFAULT => -95
- },
- {#State 305
- ACTIONS => {
- "{" => 30,
- 'COMMA' => 258,
- 'LITERAL' => 256,
- 'IDENT' => 2,
- "\"" => 60,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- DEFAULT => -62,
- GOTOS => {
- 'sterm' => 68,
- 'item' => 254,
- 'param' => 255,
- 'node' => 23,
- 'ident' => 253,
- 'term' => 257,
- 'lterm' => 56
- }
- },
- {#State 306
- ACTIONS => {
- "{" => 30,
- 'COMMA' => 258,
- 'LITERAL' => 256,
- 'IDENT' => 2,
- "\"" => 60,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- DEFAULT => -63,
- GOTOS => {
- 'sterm' => 68,
- 'item' => 254,
- 'param' => 255,
- 'node' => 23,
- 'ident' => 253,
- 'term' => 257,
- 'lterm' => 56
- }
- },
- {#State 307
- ACTIONS => {
- 'END' => 329
- }
- },
- {#State 308
- DEFAULT => -80
- },
- {#State 309
- DEFAULT => -88
- },
- {#State 310
- ACTIONS => {
- 'END' => 330
- }
- },
- {#State 311
- DEFAULT => -77
- },
- {#State 312
- ACTIONS => {
- 'END' => 331
- }
- },
- {#State 313
- ACTIONS => {
- ";" => 332,
- 'DEFAULT' => 334,
- "{" => 30,
- 'LITERAL' => 78,
- 'IDENT' => 2,
- "\"" => 60,
- "\$" => 43,
- "[" => 9,
- 'NUMBER' => 26,
- 'REF' => 27,
- "\${" => 37
- },
- GOTOS => {
- 'sterm' => 68,
- 'item' => 39,
- 'node' => 23,
- 'ident' => 77,
- 'term' => 333,
- 'lterm' => 56
- }
- },
- {#State 314
- ACTIONS => {
- 'END' => 335
- }
- },
- {#State 315
- DEFAULT => -65
- },
- {#State 316
- ACTIONS => {
- "+" => 157,
- 'CAT' => 163,
- 'CMPOP' => 164,
- "?" => 158,
- 'DIV' => 159,
- 'MOD' => 165,
- "/" => 166,
- 'AND' => 160,
- 'BINOP' => 161,
- 'OR' => 162
- },
- DEFAULT => -143
- },
- {#State 317
- ACTIONS => {
- 'END' => 336
- }
- },
- {#State 318
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 337,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 319
- DEFAULT => -46
- },
- {#State 320
- ACTIONS => {
- 'CMPOP' => 164,
- "?" => 158,
- ";" => 338,
- "+" => 157,
- 'MOD' => 165,
- 'DIV' => 159,
- "/" => 166,
- 'AND' => 160,
- 'CAT' => 163,
- 'BINOP' => 161,
- 'OR' => 162
- }
- },
- {#State 321
- ACTIONS => {
- "+" => 157,
- 'CAT' => 163,
- 'CMPOP' => 164,
- "?" => 158,
- 'DIV' => 159,
- 'MOD' => 165,
- "/" => 166,
- 'AND' => 160,
- 'BINOP' => 161,
- 'OR' => 162
- },
- DEFAULT => -154
- },
- {#State 322
- DEFAULT => -71
- },
- {#State 323
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 339,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 324
- ACTIONS => {
- 'FINAL' => 260,
- 'CATCH' => 262
- },
- DEFAULT => -72,
- GOTOS => {
- 'final' => 340
- }
- },
- {#State 325
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 341,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 326
- DEFAULT => -101
- },
- {#State 327
- DEFAULT => -93
- },
- {#State 328
- DEFAULT => -90
- },
- {#State 329
- DEFAULT => -57
- },
- {#State 330
- DEFAULT => -75
- },
- {#State 331
- DEFAULT => -44
- },
- {#State 332
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 342,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 333
- ACTIONS => {
- ";" => 343
- }
- },
- {#State 334
- ACTIONS => {
- ";" => 344
- }
- },
- {#State 335
- DEFAULT => -51
- },
- {#State 336
- DEFAULT => -60
- },
- {#State 337
- DEFAULT => -49
- },
- {#State 338
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 345,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 339
- ACTIONS => {
- 'FINAL' => 260,
- 'CATCH' => 262
- },
- DEFAULT => -72,
- GOTOS => {
- 'final' => 346
- }
- },
- {#State 340
- DEFAULT => -70
- },
- {#State 341
- ACTIONS => {
- 'FINAL' => 260,
- 'CATCH' => 262
- },
- DEFAULT => -72,
- GOTOS => {
- 'final' => 347
- }
- },
- {#State 342
- DEFAULT => -54
- },
- {#State 343
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 348,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 344
- ACTIONS => {
- 'SET' => 1,
- 'PERL' => 40,
- 'NOT' => 38,
- 'IDENT' => 2,
- 'CLEAR' => 41,
- 'UNLESS' => 3,
- 'IF' => 44,
- "\$" => 43,
- 'STOP' => 6,
- 'CALL' => 45,
- 'THROW' => 8,
- 'GET' => 47,
- "[" => 9,
- 'TRY' => 10,
- 'LAST' => 49,
- 'DEBUG' => 51,
- 'RAWPERL' => 13,
- 'META' => 15,
- 'INCLUDE' => 17,
- "(" => 53,
- 'SWITCH' => 54,
- 'MACRO' => 18,
- 'WRAPPER' => 55,
- ";" => -18,
- 'FOR' => 21,
- 'NEXT' => 22,
- 'LITERAL' => 57,
- 'TEXT' => 24,
- "\"" => 60,
- 'PROCESS' => 61,
- 'RETURN' => 64,
- 'FILTER' => 25,
- 'INSERT' => 65,
- 'NUMBER' => 26,
- 'REF' => 27,
- 'WHILE' => 67,
- 'BLOCK' => 28,
- 'DEFAULT' => 69,
- "{" => 30,
- 'USE' => 32,
- 'VIEW' => 36,
- "\${" => 37
- },
- DEFAULT => -3,
- GOTOS => {
- 'item' => 39,
- 'node' => 23,
- 'rawperl' => 59,
- 'term' => 58,
- 'loop' => 4,
- 'use' => 63,
- 'expr' => 62,
- 'capture' => 42,
- 'statement' => 5,
- 'view' => 7,
- 'wrapper' => 46,
- 'atomexpr' => 48,
- 'chunk' => 11,
- 'defblock' => 66,
- 'atomdir' => 12,
- 'anonblock' => 50,
- 'sterm' => 68,
- 'defblockname' => 14,
- 'filter' => 29,
- 'ident' => 16,
- 'perl' => 31,
- 'setlist' => 70,
- 'chunks' => 33,
- 'try' => 35,
- 'switch' => 34,
- 'assign' => 19,
- 'block' => 349,
- 'directive' => 71,
- 'macro' => 20,
- 'condition' => 73,
- 'lterm' => 56
- }
- },
- {#State 345
- ACTIONS => {
- 'ELSIF' => 290,
- 'ELSE' => 288
- },
- DEFAULT => -50,
- GOTOS => {
- 'else' => 350
- }
- },
- {#State 346
- DEFAULT => -68
- },
- {#State 347
- DEFAULT => -69
- },
- {#State 348
- ACTIONS => {
- 'CASE' => 313
- },
- DEFAULT => -55,
- GOTOS => {
- 'case' => 351
- }
- },
- {#State 349
- DEFAULT => -53
- },
- {#State 350
- DEFAULT => -48
- },
- {#State 351
- DEFAULT => -52
- }
-];
-
-
-#========================================================================
-# Rules
-#========================================================================
-
-$RULES = [
- [#Rule 0
- '$start', 2, undef
- ],
- [#Rule 1
- 'template', 1,
-sub
-#line 64 "Parser.yp"
-{ $factory->template($_[1]) }
- ],
- [#Rule 2
- 'block', 1,
-sub
-#line 67 "Parser.yp"
-{ $factory->block($_[1]) }
- ],
- [#Rule 3
- 'block', 0,
-sub
-#line 68 "Parser.yp"
-{ $factory->block() }
- ],
- [#Rule 4
- 'chunks', 2,
-sub
-#line 71 "Parser.yp"
-{ push(@{$_[1]}, $_[2])
- if defined $_[2]; $_[1] }
- ],
- [#Rule 5
- 'chunks', 1,
-sub
-#line 73 "Parser.yp"
-{ defined $_[1] ? [ $_[1] ] : [ ] }
- ],
- [#Rule 6
- 'chunk', 1,
-sub
-#line 76 "Parser.yp"
-{ $factory->textblock($_[1]) }
- ],
- [#Rule 7
- 'chunk', 2,
-sub
-#line 77 "Parser.yp"
-{ return '' unless $_[1];
- $_[0]->location() . $_[1];
- }
- ],
- [#Rule 8
- 'statement', 1, undef
- ],
- [#Rule 9
- 'statement', 1, undef
- ],
- [#Rule 10
- 'statement', 1, undef
- ],
- [#Rule 11
- 'statement', 1, undef
- ],
- [#Rule 12
- 'statement', 1, undef
- ],
- [#Rule 13
- 'statement', 1, undef
- ],
- [#Rule 14
- 'statement', 1, undef
- ],
- [#Rule 15
- 'statement', 1, undef
- ],
- [#Rule 16
- 'statement', 1,
-sub
-#line 90 "Parser.yp"
-{ $factory->get($_[1]) }
- ],
- [#Rule 17
- 'statement', 2,
-sub
-#line 91 "Parser.yp"
-{ $_[0]->add_metadata($_[2]); }
- ],
- [#Rule 18
- 'statement', 0, undef
- ],
- [#Rule 19
- 'directive', 1,
-sub
-#line 95 "Parser.yp"
-{ $factory->set($_[1]) }
- ],
- [#Rule 20
- 'directive', 1, undef
- ],
- [#Rule 21
- 'directive', 1, undef
- ],
- [#Rule 22
- 'directive', 1, undef
- ],
- [#Rule 23
- 'directive', 1, undef
- ],
- [#Rule 24
- 'directive', 1, undef
- ],
- [#Rule 25
- 'directive', 1, undef
- ],
- [#Rule 26
- 'atomexpr', 1,
-sub
-#line 109 "Parser.yp"
-{ $factory->get($_[1]) }
- ],
- [#Rule 27
- 'atomexpr', 1, undef
- ],
- [#Rule 28
- 'atomdir', 2,
-sub
-#line 113 "Parser.yp"
-{ $factory->get($_[2]) }
- ],
- [#Rule 29
- 'atomdir', 2,
-sub
-#line 114 "Parser.yp"
-{ $factory->call($_[2]) }
- ],
- [#Rule 30
- 'atomdir', 2,
-sub
-#line 115 "Parser.yp"
-{ $factory->set($_[2]) }
- ],
- [#Rule 31
- 'atomdir', 2,
-sub
-#line 116 "Parser.yp"
-{ $factory->default($_[2]) }
- ],
- [#Rule 32
- 'atomdir', 2,
-sub
-#line 117 "Parser.yp"
-{ $factory->insert($_[2]) }
- ],
- [#Rule 33
- 'atomdir', 2,
-sub
-#line 118 "Parser.yp"
-{ $factory->include($_[2]) }
- ],
- [#Rule 34
- 'atomdir', 2,
-sub
-#line 119 "Parser.yp"
-{ $factory->process($_[2]) }
- ],
- [#Rule 35
- 'atomdir', 2,
-sub
-#line 120 "Parser.yp"
-{ $factory->throw($_[2]) }
- ],
- [#Rule 36
- 'atomdir', 1,
-sub
-#line 121 "Parser.yp"
-{ $factory->return() }
- ],
- [#Rule 37
- 'atomdir', 1,
-sub
-#line 122 "Parser.yp"
-{ $factory->stop() }
- ],
- [#Rule 38
- 'atomdir', 1,
-sub
-#line 123 "Parser.yp"
-{ "\$output = '';"; }
- ],
- [#Rule 39
- 'atomdir', 1,
-sub
-#line 124 "Parser.yp"
-{ $_[0]->{ INFOR } || $_[0]->{ INWHILE }
- ? 'last LOOP;'
- : 'last;' }
- ],
- [#Rule 40
- 'atomdir', 1,
-sub
-#line 127 "Parser.yp"
-{ $_[0]->{ INFOR }
- ? $factory->next()
- : ($_[0]->{ INWHILE }
- ? 'next LOOP;'
- : 'next;') }
- ],
- [#Rule 41
- 'atomdir', 2,
-sub
-#line 132 "Parser.yp"
-{ if ($_[2]->[0]->[0] =~ /^'(on|off)'$/) {
- $_[0]->{ DEBUG_DIRS } = ($1 eq 'on');
- $factory->debug($_[2]);
- }
- else {
- $_[0]->{ DEBUG_DIRS } ? $factory->debug($_[2]) : '';
- }
- }
- ],
- [#Rule 42
- 'atomdir', 1, undef
- ],
- [#Rule 43
- 'atomdir', 1, undef
- ],
- [#Rule 44
- 'condition', 6,
-sub
-#line 145 "Parser.yp"
-{ $factory->if(@_[2, 4, 5]) }
- ],
- [#Rule 45
- 'condition', 3,
-sub
-#line 146 "Parser.yp"
-{ $factory->if(@_[3, 1]) }
- ],
- [#Rule 46
- 'condition', 6,
-sub
-#line 148 "Parser.yp"
-{ $factory->if("!($_[2])", @_[4, 5]) }
- ],
- [#Rule 47
- 'condition', 3,
-sub
-#line 149 "Parser.yp"
-{ $factory->if("!($_[3])", $_[1]) }
- ],
- [#Rule 48
- 'else', 5,
-sub
-#line 153 "Parser.yp"
-{ unshift(@{$_[5]}, [ @_[2, 4] ]);
- $_[5]; }
- ],
- [#Rule 49
- 'else', 3,
-sub
-#line 155 "Parser.yp"
-{ [ $_[3] ] }
- ],
- [#Rule 50
- 'else', 0,
-sub
-#line 156 "Parser.yp"
-{ [ undef ] }
- ],
- [#Rule 51
- 'switch', 6,
-sub
-#line 160 "Parser.yp"
-{ $factory->switch(@_[2, 5]) }
- ],
- [#Rule 52
- 'case', 5,
-sub
-#line 164 "Parser.yp"
-{ unshift(@{$_[5]}, [ @_[2, 4] ]);
- $_[5]; }
- ],
- [#Rule 53
- 'case', 4,
-sub
-#line 166 "Parser.yp"
-{ [ $_[4] ] }
- ],
- [#Rule 54
- 'case', 3,
-sub
-#line 167 "Parser.yp"
-{ [ $_[3] ] }
- ],
- [#Rule 55
- 'case', 0,
-sub
-#line 168 "Parser.yp"
-{ [ undef ] }
- ],
- [#Rule 56
- '@1-3', 0,
-sub
-#line 171 "Parser.yp"
-{ $_[0]->{ INFOR }++ }
- ],
- [#Rule 57
- 'loop', 6,
-sub
-#line 172 "Parser.yp"
-{ $_[0]->{ INFOR }--;
- $factory->foreach(@{$_[2]}, $_[5]) }
- ],
- [#Rule 58
- 'loop', 3,
-sub
-#line 176 "Parser.yp"
-{ $factory->foreach(@{$_[3]}, $_[1]) }
- ],
- [#Rule 59
- '@2-3', 0,
-sub
-#line 177 "Parser.yp"
-{ $_[0]->{ INWHILE }++ }
- ],
- [#Rule 60
- 'loop', 6,
-sub
-#line 178 "Parser.yp"
-{ $_[0]->{ INWHILE }--;
- $factory->while(@_[2, 5]) }
- ],
- [#Rule 61
- 'loop', 3,
-sub
-#line 180 "Parser.yp"
-{ $factory->while(@_[3, 1]) }
- ],
- [#Rule 62
- 'loopvar', 4,
-sub
-#line 183 "Parser.yp"
-{ [ @_[1, 3, 4] ] }
- ],
- [#Rule 63
- 'loopvar', 4,
-sub
-#line 184 "Parser.yp"
-{ [ @_[1, 3, 4] ] }
- ],
- [#Rule 64
- 'loopvar', 2,
-sub
-#line 185 "Parser.yp"
-{ [ 0, @_[1, 2] ] }
- ],
- [#Rule 65
- 'wrapper', 5,
-sub
-#line 189 "Parser.yp"
-{ $factory->wrapper(@_[2, 4]) }
- ],
- [#Rule 66
- 'wrapper', 3,
-sub
-#line 191 "Parser.yp"
-{ $factory->wrapper(@_[3, 1]) }
- ],
- [#Rule 67
- 'try', 5,
-sub
-#line 195 "Parser.yp"
-{ $factory->try(@_[3, 4]) }
- ],
- [#Rule 68
- 'final', 5,
-sub
-#line 199 "Parser.yp"
-{ unshift(@{$_[5]}, [ @_[2,4] ]);
- $_[5]; }
- ],
- [#Rule 69
- 'final', 5,
-sub
-#line 202 "Parser.yp"
-{ unshift(@{$_[5]}, [ undef, $_[4] ]);
- $_[5]; }
- ],
- [#Rule 70
- 'final', 4,
-sub
-#line 205 "Parser.yp"
-{ unshift(@{$_[4]}, [ undef, $_[3] ]);
- $_[4]; }
- ],
- [#Rule 71
- 'final', 3,
-sub
-#line 207 "Parser.yp"
-{ [ $_[3] ] }
- ],
- [#Rule 72
- 'final', 0,
-sub
-#line 208 "Parser.yp"
-{ [ 0 ] }
- ],
- [#Rule 73
- 'use', 2,
-sub
-#line 211 "Parser.yp"
-{ $factory->use($_[2]) }
- ],
- [#Rule 74
- '@3-3', 0,
-sub
-#line 214 "Parser.yp"
-{ $_[0]->push_defblock(); }
- ],
- [#Rule 75
- 'view', 6,
-sub
-#line 215 "Parser.yp"
-{ $factory->view(@_[2,5],
- $_[0]->pop_defblock) }
- ],
- [#Rule 76
- '@4-2', 0,
-sub
-#line 219 "Parser.yp"
-{ ${$_[0]->{ INPERL }}++; }
- ],
- [#Rule 77
- 'perl', 5,
-sub
-#line 220 "Parser.yp"
-{ ${$_[0]->{ INPERL }}--;
- $_[0]->{ EVAL_PERL }
- ? $factory->perl($_[4])
- : $factory->no_perl(); }
- ],
- [#Rule 78
- '@5-1', 0,
-sub
-#line 226 "Parser.yp"
-{ ${$_[0]->{ INPERL }}++;
- $rawstart = ${$_[0]->{'LINE'}}; }
- ],
- [#Rule 79
- 'rawperl', 5,
-sub
-#line 228 "Parser.yp"
-{ ${$_[0]->{ INPERL }}--;
- $_[0]->{ EVAL_PERL }
- ? $factory->rawperl($_[4], $rawstart)
- : $factory->no_perl(); }
- ],
- [#Rule 80
- 'filter', 5,
-sub
-#line 235 "Parser.yp"
-{ $factory->filter(@_[2,4]) }
- ],
- [#Rule 81
- 'filter', 3,
-sub
-#line 237 "Parser.yp"
-{ $factory->filter(@_[3,1]) }
- ],
- [#Rule 82
- 'defblock', 5,
-sub
-#line 242 "Parser.yp"
-{ my $name = join('/', @{ $_[0]->{ DEFBLOCKS } });
- pop(@{ $_[0]->{ DEFBLOCKS } });
- $_[0]->define_block($name, $_[4]);
- undef
- }
- ],
- [#Rule 83
- 'defblockname', 2,
-sub
-#line 249 "Parser.yp"
-{ push(@{ $_[0]->{ DEFBLOCKS } }, $_[2]);
- $_[2];
- }
- ],
- [#Rule 84
- 'blockname', 1, undef
- ],
- [#Rule 85
- 'blockname', 1,
-sub
-#line 255 "Parser.yp"
-{ $_[1] =~ s/^'(.*)'$/$1/; $_[1] }
- ],
- [#Rule 86
- 'blockargs', 1, undef
- ],
- [#Rule 87
- 'blockargs', 0, undef
- ],
- [#Rule 88
- 'anonblock', 5,
-sub
-#line 263 "Parser.yp"
-{ local $" = ', ';
- print STDERR "experimental block args: [@{ $_[2] }]\n"
- if $_[2];
- $factory->anon_block($_[4]) }
- ],
- [#Rule 89
- 'capture', 3,
-sub
-#line 269 "Parser.yp"
-{ $factory->capture(@_[1, 3]) }
- ],
- [#Rule 90
- 'macro', 6,
-sub
-#line 273 "Parser.yp"
-{ $factory->macro(@_[2, 6, 4]) }
- ],
- [#Rule 91
- 'macro', 3,
-sub
-#line 274 "Parser.yp"
-{ $factory->macro(@_[2, 3]) }
- ],
- [#Rule 92
- 'mdir', 1, undef
- ],
- [#Rule 93
- 'mdir', 4,
-sub
-#line 278 "Parser.yp"
-{ $_[3] }
- ],
- [#Rule 94
- 'margs', 2,
-sub
-#line 281 "Parser.yp"
-{ push(@{$_[1]}, $_[2]); $_[1] }
- ],
- [#Rule 95
- 'margs', 2,
-sub
-#line 282 "Parser.yp"
-{ $_[1] }
- ],
- [#Rule 96
- 'margs', 1,
-sub
-#line 283 "Parser.yp"
-{ [ $_[1] ] }
- ],
- [#Rule 97
- 'metadata', 2,
-sub
-#line 286 "Parser.yp"
-{ push(@{$_[1]}, @{$_[2]}); $_[1] }
- ],
- [#Rule 98
- 'metadata', 2, undef
- ],
- [#Rule 99
- 'metadata', 1, undef
- ],
- [#Rule 100
- 'meta', 3,
-sub
-#line 291 "Parser.yp"
-{ for ($_[3]) { s/^'//; s/'$//;
- s/\\'/'/g };
- [ @_[1,3] ] }
- ],
- [#Rule 101
- 'meta', 5,
-sub
-#line 294 "Parser.yp"
-{ [ @_[1,4] ] }
- ],
- [#Rule 102
- 'meta', 3,
-sub
-#line 295 "Parser.yp"
-{ [ @_[1,3] ] }
- ],
- [#Rule 103
- 'term', 1, undef
- ],
- [#Rule 104
- 'term', 1, undef
- ],
- [#Rule 105
- 'lterm', 3,
-sub
-#line 307 "Parser.yp"
-{ "[ $_[2] ]" }
- ],
- [#Rule 106
- 'lterm', 3,
-sub
-#line 308 "Parser.yp"
-{ "[ $_[2] ]" }
- ],
- [#Rule 107
- 'lterm', 2,
-sub
-#line 309 "Parser.yp"
-{ "[ ]" }
- ],
- [#Rule 108
- 'lterm', 3,
-sub
-#line 310 "Parser.yp"
-{ "{ $_[2] }" }
- ],
- [#Rule 109
- 'sterm', 1,
-sub
-#line 313 "Parser.yp"
-{ $factory->ident($_[1]) }
- ],
- [#Rule 110
- 'sterm', 2,
-sub
-#line 314 "Parser.yp"
-{ $factory->identref($_[2]) }
- ],
- [#Rule 111
- 'sterm', 3,
-sub
-#line 315 "Parser.yp"
-{ $factory->quoted($_[2]) }
- ],
- [#Rule 112
- 'sterm', 1, undef
- ],
- [#Rule 113
- 'sterm', 1, undef
- ],
- [#Rule 114
- 'list', 2,
-sub
-#line 320 "Parser.yp"
-{ "$_[1], $_[2]" }
- ],
- [#Rule 115
- 'list', 2, undef
- ],
- [#Rule 116
- 'list', 1, undef
- ],
- [#Rule 117
- 'range', 3,
-sub
-#line 325 "Parser.yp"
-{ $_[1] . '..' . $_[3] }
- ],
- [#Rule 118
- 'hash', 1, undef
- ],
- [#Rule 119
- 'hash', 0,
-sub
-#line 330 "Parser.yp"
-{ "" }
- ],
- [#Rule 120
- 'params', 2,
-sub
-#line 333 "Parser.yp"
-{ "$_[1], $_[2]" }
- ],
- [#Rule 121
- 'params', 2, undef
- ],
- [#Rule 122
- 'params', 1, undef
- ],
- [#Rule 123
- 'param', 3,
-sub
-#line 338 "Parser.yp"
-{ "$_[1] => $_[3]" }
- ],
- [#Rule 124
- 'param', 3,
-sub
-#line 339 "Parser.yp"
-{ "$_[1] => $_[3]" }
- ],
- [#Rule 125
- 'ident', 3,
-sub
-#line 342 "Parser.yp"
-{ push(@{$_[1]}, @{$_[3]}); $_[1] }
- ],
- [#Rule 126
- 'ident', 3,
-sub
-#line 343 "Parser.yp"
-{ push(@{$_[1]},
- map {($_, 0)} split(/\./, $_[3]));
- $_[1]; }
- ],
- [#Rule 127
- 'ident', 1, undef
- ],
- [#Rule 128
- 'node', 1,
-sub
-#line 349 "Parser.yp"
-{ [ $_[1], 0 ] }
- ],
- [#Rule 129
- 'node', 4,
-sub
-#line 350 "Parser.yp"
-{ [ $_[1], $factory->args($_[3]) ] }
- ],
- [#Rule 130
- 'item', 1,
-sub
-#line 353 "Parser.yp"
-{ "'$_[1]'" }
- ],
- [#Rule 131
- 'item', 3,
-sub
-#line 354 "Parser.yp"
-{ $_[2] }
- ],
- [#Rule 132
- 'item', 2,
-sub
-#line 355 "Parser.yp"
-{ $_[0]->{ V1DOLLAR }
- ? "'$_[2]'"
- : $factory->ident(["'$_[2]'", 0]) }
- ],
- [#Rule 133
- 'expr', 3,
-sub
-#line 360 "Parser.yp"
-{ "$_[1] $_[2] $_[3]" }
- ],
- [#Rule 134
- 'expr', 3,
-sub
-#line 361 "Parser.yp"
-{ "$_[1] $_[2] $_[3]" }
- ],
- [#Rule 135
- 'expr', 3,
-sub
-#line 362 "Parser.yp"
-{ "$_[1] $_[2] $_[3]" }
- ],
- [#Rule 136
- 'expr', 3,
-sub
-#line 363 "Parser.yp"
-{ "int($_[1] / $_[3])" }
- ],
- [#Rule 137
- 'expr', 3,
-sub
-#line 364 "Parser.yp"
-{ "$_[1] % $_[3]" }
- ],
- [#Rule 138
- 'expr', 3,
-sub
-#line 365 "Parser.yp"
-{ "$_[1] $CMPOP{ $_[2] } $_[3]" }
- ],
- [#Rule 139
- 'expr', 3,
-sub
-#line 366 "Parser.yp"
-{ "$_[1] . $_[3]" }
- ],
- [#Rule 140
- 'expr', 3,
-sub
-#line 367 "Parser.yp"
-{ "$_[1] && $_[3]" }
- ],
- [#Rule 141
- 'expr', 3,
-sub
-#line 368 "Parser.yp"
-{ "$_[1] || $_[3]" }
- ],
- [#Rule 142
- 'expr', 2,
-sub
-#line 369 "Parser.yp"
-{ "! $_[2]" }
- ],
- [#Rule 143
- 'expr', 5,
-sub
-#line 370 "Parser.yp"
-{ "$_[1] ? $_[3] : $_[5]" }
- ],
- [#Rule 144
- 'expr', 3,
-sub
-#line 371 "Parser.yp"
-{ $factory->assign(@{$_[2]}) }
- ],
- [#Rule 145
- 'expr', 3,
-sub
-#line 372 "Parser.yp"
-{ "($_[2])" }
- ],
- [#Rule 146
- 'expr', 1, undef
- ],
- [#Rule 147
- 'setlist', 2,
-sub
-#line 376 "Parser.yp"
-{ push(@{$_[1]}, @{$_[2]}); $_[1] }
- ],
- [#Rule 148
- 'setlist', 2, undef
- ],
- [#Rule 149
- 'setlist', 1, undef
- ],
- [#Rule 150
- 'assign', 3,
-sub
-#line 382 "Parser.yp"
-{ [ $_[1], $_[3] ] }
- ],
- [#Rule 151
- 'assign', 3,
-sub
-#line 383 "Parser.yp"
-{ [ @_[1,3] ] }
- ],
- [#Rule 152
- 'args', 2,
-sub
-#line 390 "Parser.yp"
-{ push(@{$_[1]}, $_[2]); $_[1] }
- ],
- [#Rule 153
- 'args', 2,
-sub
-#line 391 "Parser.yp"
-{ push(@{$_[1]->[0]}, $_[2]); $_[1] }
- ],
- [#Rule 154
- 'args', 4,
-sub
-#line 392 "Parser.yp"
-{ push(@{$_[1]->[0]}, "'', " .
- $factory->assign(@_[2,4])); $_[1] }
- ],
- [#Rule 155
- 'args', 2,
-sub
-#line 394 "Parser.yp"
-{ $_[1] }
- ],
- [#Rule 156
- 'args', 0,
-sub
-#line 395 "Parser.yp"
-{ [ [ ] ] }
- ],
- [#Rule 157
- 'lnameargs', 3,
-sub
-#line 405 "Parser.yp"
-{ push(@{$_[3]}, $_[1]); $_[3] }
- ],
- [#Rule 158
- 'lnameargs', 1, undef
- ],
- [#Rule 159
- 'lvalue', 1, undef
- ],
- [#Rule 160
- 'lvalue', 3,
-sub
-#line 410 "Parser.yp"
-{ $factory->quoted($_[2]) }
- ],
- [#Rule 161
- 'lvalue', 1, undef
- ],
- [#Rule 162
- 'nameargs', 3,
-sub
-#line 414 "Parser.yp"
-{ [ [$factory->ident($_[2])], $_[3] ] }
- ],
- [#Rule 163
- 'nameargs', 2,
-sub
-#line 415 "Parser.yp"
-{ [ @_[1,2] ] }
- ],
- [#Rule 164
- 'nameargs', 4,
-sub
-#line 416 "Parser.yp"
-{ [ @_[1,3] ] }
- ],
- [#Rule 165
- 'names', 3,
-sub
-#line 419 "Parser.yp"
-{ push(@{$_[1]}, $_[3]); $_[1] }
- ],
- [#Rule 166
- 'names', 1,
-sub
-#line 420 "Parser.yp"
-{ [ $_[1] ] }
- ],
- [#Rule 167
- 'name', 3,
-sub
-#line 423 "Parser.yp"
-{ $factory->quoted($_[2]) }
- ],
- [#Rule 168
- 'name', 1,
-sub
-#line 424 "Parser.yp"
-{ "'$_[1]'" }
- ],
- [#Rule 169
- 'name', 1, undef
- ],
- [#Rule 170
- 'filename', 3,
-sub
-#line 436 "Parser.yp"
-{ "$_[1].$_[3]" }
- ],
- [#Rule 171
- 'filename', 1, undef
- ],
- [#Rule 172
- 'filepart', 1, undef
- ],
- [#Rule 173
- 'filepart', 1, undef
- ],
- [#Rule 174
- 'filepart', 1, undef
- ],
- [#Rule 175
- 'quoted', 2,
-sub
-#line 450 "Parser.yp"
-{ push(@{$_[1]}, $_[2])
- if defined $_[2]; $_[1] }
- ],
- [#Rule 176
- 'quoted', 0,
-sub
-#line 452 "Parser.yp"
-{ [ ] }
- ],
- [#Rule 177
- 'quotable', 1,
-sub
-#line 455 "Parser.yp"
-{ $factory->ident($_[1]) }
- ],
- [#Rule 178
- 'quotable', 1,
-sub
-#line 456 "Parser.yp"
-{ $factory->text($_[1]) }
- ],
- [#Rule 179
- 'quotable', 1,
-sub
-#line 457 "Parser.yp"
-{ undef }
- ]
-];
-
-
-
-1;
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/Template/Iterator.pm b/lib/Template/Iterator.pm
deleted file mode 100644
index 710ecdc..0000000
--- a/lib/Template/Iterator.pm
+++ /dev/null
@@ -1,456 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Iterator
-#
-# DESCRIPTION
-#
-# Module defining an iterator class which is used by the FOREACH
-# directive for iterating through data sets. This may be
-# sub-classed to define more specific iterator types.
-#
-# An iterator is an object which provides a consistent way to
-# navigate through data which may have a complex underlying form.
-# This implementation uses the get_first() and get_next() methods to
-# iterate through a dataset. The get_first() method is called once
-# to perform any data initialisation and return the first value,
-# then get_next() is called repeatedly to return successive values.
-# Both these methods return a pair of values which are the data item
-# itself and a status code. The default implementation handles
-# iteration through an array (list) of elements which is passed by
-# reference to the constructor. An empty list is used if none is
-# passed. The module may be sub-classed to provide custom
-# implementations which iterate through any kind of data in any
-# manner as long as it can conforms to the get_first()/get_next()
-# interface. The object also implements the get_all() method for
-# returning all remaining elements as a list reference.
-#
-# For further information on iterators see "Design Patterns", by the
-# "Gang of Four" (Erich Gamma, Richard Helm, Ralph Johnson, John
-# Vlissides), Addision-Wesley, ISBN 0-201-63361-2.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Iterator.pm,v 2.64 2004/01/13 16:19:15 abw Exp $
-#
-#============================================================================
-
-package Template::Iterator;
-
-require 5.004;
-
-use strict;
-use vars qw( $VERSION $DEBUG $AUTOLOAD ); # AUTO?
-use base qw( Template::Base );
-use Template::Constants;
-use Template::Exception;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.64 $ =~ /(\d+)\.(\d+)/);
-$DEBUG = 0 unless defined $DEBUG;
-
-
-#========================================================================
-# ----- CLASS METHODS -----
-#========================================================================
-
-#------------------------------------------------------------------------
-# new(\@target, \%options)
-#
-# Constructor method which creates and returns a reference to a new
-# Template::Iterator object. A reference to the target data (array
-# or hash) may be passed for the object to iterate through.
-#------------------------------------------------------------------------
-
-sub new {
- my $class = shift;
- my $data = shift || [ ];
- my $params = shift || { };
-
- if (ref $data eq 'HASH') {
- # map a hash into a list of { key => ???, value => ??? } hashes,
- # one for each key, sorted by keys
- $data = [ map { { key => $_, value => $data->{ $_ } } }
- sort keys %$data ];
- }
- elsif (UNIVERSAL::can($data, 'as_list')) {
- $data = $data->as_list();
- }
- elsif (ref $data ne 'ARRAY') {
- # coerce any non-list data into an array reference
- $data = [ $data ] ;
- }
-
- bless {
- _DATA => $data,
- _ERROR => '',
- }, $class;
-}
-
-
-#========================================================================
-# ----- PUBLIC OBJECT METHODS -----
-#========================================================================
-
-#------------------------------------------------------------------------
-# get_first()
-#
-# Initialises the object for iterating through the target data set. The
-# first record is returned, if defined, along with the STATUS_OK value.
-# If there is no target data, or the data is an empty set, then undef
-# is returned with the STATUS_DONE value.
-#------------------------------------------------------------------------
-
-sub get_first {
- my $self = shift;
- my $data = $self->{ _DATA };
-
- $self->{ _DATASET } = $self->{ _DATA };
- my $size = scalar @$data;
- my $index = 0;
-
- return (undef, Template::Constants::STATUS_DONE) unless $size;
-
- # initialise various counters, flags, etc.
- @$self{ qw( SIZE MAX INDEX COUNT FIRST LAST ) }
- = ( $size, $size - 1, $index, 1, 1, $size > 1 ? 0 : 1, undef );
- @$self{ qw( PREV NEXT ) } = ( undef, $self->{ _DATASET }->[ $index + 1 ]);
-
- return $self->{ _DATASET }->[ $index ];
-}
-
-
-
-#------------------------------------------------------------------------
-# get_next()
-#
-# Called repeatedly to access successive elements in the data set.
-# Should only be called after calling get_first() or a warning will
-# be raised and (undef, STATUS_DONE) returned.
-#------------------------------------------------------------------------
-
-sub get_next {
- my $self = shift;
- my ($max, $index) = @$self{ qw( MAX INDEX ) };
- my $data = $self->{ _DATASET };
-
- # warn about incorrect usage
- unless (defined $index) {
- my ($pack, $file, $line) = caller();
- warn("iterator get_next() called before get_first() at $file line $line\n");
- return (undef, Template::Constants::STATUS_DONE); ## RETURN ##
- }
-
- # if there's still some data to go...
- if ($index < $max) {
- # update counters and flags
- $index++;
- @$self{ qw( INDEX COUNT FIRST LAST ) }
- = ( $index, $index + 1, 0, $index == $max ? 1 : 0 );
- @$self{ qw( PREV NEXT ) } = @$data[ $index - 1, $index + 1 ];
- return $data->[ $index ]; ## RETURN ##
- }
- else {
- return (undef, Template::Constants::STATUS_DONE); ## RETURN ##
- }
-}
-
-
-#------------------------------------------------------------------------
-# get_all()
-#
-# Method which returns all remaining items in the iterator as a Perl list
-# reference. May be called at any time in the life-cycle of the iterator.
-# The get_first() method will be called automatically if necessary, and
-# then subsequent get_next() calls are made, storing each returned
-# result until the list is exhausted.
-#------------------------------------------------------------------------
-
-sub get_all {
- my $self = shift;
- my ($max, $index) = @$self{ qw( MAX INDEX ) };
- my @data;
-
- # if there's still some data to go...
- if ($index < $max) {
- $index++;
- @data = @{ $self->{ _DATASET } } [ $index..$max ];
-
- # update counters and flags
- @$self{ qw( INDEX COUNT FIRST LAST ) }
- = ( $max, $max + 1, 0, 1 );
-
- return \@data; ## RETURN ##
- }
- else {
- return (undef, Template::Constants::STATUS_DONE); ## RETURN ##
- }
-}
-
-
-#------------------------------------------------------------------------
-# AUTOLOAD
-#
-# Provides access to internal fields (e.g. size, first, last, max, etc)
-#------------------------------------------------------------------------
-
-sub AUTOLOAD {
- my $self = shift;
- my $item = $AUTOLOAD;
- $item =~ s/.*:://;
- return if $item eq 'DESTROY';
-
- # alias NUMBER to COUNT for backwards compatability
- $item = 'COUNT' if $item =~ /NUMBER/i;
-
- return $self->{ uc $item };
-}
-
-
-#========================================================================
-# ----- PRIVATE DEBUG METHODS -----
-#========================================================================
-
-#------------------------------------------------------------------------
-# _dump()
-#
-# Debug method which returns a string detailing the internal state of
-# the iterator object.
-#------------------------------------------------------------------------
-
-sub _dump {
- my $self = shift;
- join('',
- " Data: ", $self->{ _DATA }, "\n",
- " Index: ", $self->{ INDEX }, "\n",
- "Number: ", $self->{ NUMBER }, "\n",
- " Max: ", $self->{ MAX }, "\n",
- " Size: ", $self->{ SIZE }, "\n",
- " First: ", $self->{ FIRST }, "\n",
- " Last: ", $self->{ LAST }, "\n",
- "\n"
- );
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Iterator - Data iterator used by the FOREACH directive
-
-=head1 SYNOPSIS
-
- my $iter = Template::Iterator->new(\@data, \%options);
-
-=head1 DESCRIPTION
-
-The Template::Iterator module defines a generic data iterator for use
-by the FOREACH directive.
-
-It may be used as the base class for custom iterators.
-
-=head1 PUBLIC METHODS
-
-=head2 new($data)
-
-Constructor method. A reference to a list of values is passed as the
-first parameter. Subsequent calls to get_first() and get_next() calls
-will return each element from the list.
-
- my $iter = Template::Iterator->new([ 'foo', 'bar', 'baz' ]);
-
-The constructor will also accept a reference to a hash array and will
-expand it into a list in which each entry is a hash array containing
-a 'key' and 'value' item, sorted according to the hash keys.
-
- my $iter = Template::Iterator->new({
- foo => 'Foo Item',
- bar => 'Bar Item',
- });
-
-This is equivalent to:
-
- my $iter = Template::Iterator->new([
- { key => 'bar', value => 'Bar Item' },
- { key => 'foo', value => 'Foo Item' },
- ]);
-
-When passed a single item which is not an array reference, the constructor
-will automatically create a list containing that single item.
-
- my $iter = Template::Iterator->new('foo');
-
-This is equivalent to:
-
- my $iter = Template::Iterator->new([ 'foo' ]);
-
-Note that a single item which is an object based on a blessed ARRAY
-references will NOT be treated as an array and will be folded into
-a list containing that one object reference.
-
- my $list = bless [ 'foo', 'bar' ], 'MyListClass';
- my $iter = Template::Iterator->new($list);
-
-equivalent to:
-
- my $iter = Template::Iterator->new([ $list ]);
-
-If the object provides an as_list() method then the Template::Iterator
-constructor will call that method to return the list of data. For example:
-
- package MyListObject;
-
- sub new {
- my $class = shift;
- bless [ @_ ], $class;
- }
-
- package main;
-
- my $list = MyListObject->new('foo', 'bar');
- my $iter = Template::Iterator->new($list);
-
-This is then functionally equivalent to:
-
- my $iter = Template::Iterator->new([ $list ]);
-
-The iterator will return only one item, a reference to the MyListObject
-object, $list.
-
-By adding an as_list() method to the MyListObject class, we can force
-the Template::Iterator constructor to treat the object as a list and
-use the data contained within.
-
- package MyListObject;
-
- ...
-
- sub as_list {
- my $self = shift;
- return $self;
- }
-
- package main;
-
- my $list = MyListObject->new('foo', 'bar');
- my $iter = Template::Iterator->new($list);
-
-The iterator will now return the two item, 'foo' and 'bar', which the
-MyObjectList encapsulates.
-
-=head2 get_first()
-
-Returns a ($value, $error) pair for the first item in the iterator set.
-The $error returned may be zero or undefined to indicate a valid datum
-was successfully returned. Returns an error of STATUS_DONE if the list
-is empty.
-
-=head2 get_next()
-
-Returns a ($value, $error) pair for the next item in the iterator set.
-Returns an error of STATUS_DONE if all items in the list have been
-visited.
-
-=head2 get_all()
-
-Returns a (\@values, $error) pair for all remaining items in the iterator
-set. Returns an error of STATUS_DONE if all items in the list have been
-visited.
-
-=head2 size()
-
-Returns the size of the data set or undef if unknown.
-
-=head2 max()
-
-Returns the maximum index number (i.e. the index of the last element)
-which is equivalent to size() - 1.
-
-=head2 index()
-
-Returns the current index number which is in the range 0 to max().
-
-=head2 count()
-
-Returns the current iteration count in the range 1 to size(). This is
-equivalent to index() + 1. Note that number() is supported as an alias
-for count() for backwards compatability.
-
-=head2 first()
-
-Returns a boolean value to indicate if the iterator is currently on
-the first iteration of the set.
-
-=head2 last()
-
-Returns a boolean value to indicate if the iterator is currently on
-the last iteration of the set.
-
-=head2 prev()
-
-Returns the previous item in the data set, or undef if the iterator is
-on the first item.
-
-=head2 next()
-
-Returns the next item in the data set or undef if the iterator is on the
-last item.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.64, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template|Template>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Library/HTML.pod b/lib/Template/Library/HTML.pod
deleted file mode 100644
index e39c120..0000000
--- a/lib/Template/Library/HTML.pod
+++ /dev/null
@@ -1,316 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Library::HTML
-#
-# DESCRIPTION
-# The HTML library provides a number of basic templates for use in
-# building HTML pages.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-# 2.69
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Library::HTML - Template library for building basic HTML pages
-
-=head1 DESCRIPTION
-
-B<NOTE:> This documentation is incomplete and may be incorrect
-in places.
-
-The 'html' template library is distributed as part of the Template
-Toolkit. It can be found in the 'templates' sub-directory of the
-installation directory.
-
- use Template;
-
- my $tt2 = Template->new({
- INCLUDE_PATH => '/usr/local/tt2/templates',
- });
-
-For a portable way to determine the installation 'templates' directory,
-you can use the C<Template::Config-E<gt>instdir()> class method.
-
- use Template;
-
- my $tt2 = Template->new({
- INCLUDE_PATH => Template::Config->instdir('templates'),
- });
-
-You should now be able to access the html library as, for example:
-
- [% INCLUDE html/header %]
-
-Note that some of the more basic elements don't give you much more
-than the raw HTML tags. In many cases you might be well advised to
-stick to regular HTML rather than complicating matters by the use
-of template elements.
-
-e.g.
-
- <table>
- . . .
- </table>
-
-vs
-
- [% WRAPPER html/table %]
- . . .
- [% END %]
-
-However, the use of template elements to generate the underlying HTML
-does have some important benefits, particularly as the constructs start
-to get more complicated and more magical.
-
-See the example in the 'examples' sub-directory of the distribution
-directory for further examples and enlightenment on using this library.
-
-=head2 Headers, Footers and Pages
-
-=over 4
-
-=item header
-
-The 'header' element generates the regular header required as the
-pre-amble for an HTML document. That is, everything from the initial
-E<lt>htmlE<gt> to the opening E<lt>bodyE<gt>.
-
- [% INCLUDE html/header
- title = 'This is a Test'
- bgcol = '#ffffff'
- %]
-
-Additional header items can be provided by explicitly setting the 'headers'
-variable, e.g.
-
- [% headers = BLOCK %]
- <META name="description" content="Template Toolkit">
- <META name="REVISIT-AFTER" content="14 days">
- <META name="keywords" content="Templates, Web, ...etc...">
- [% END %]
-
- [% INCLUDE html/header
- title = 'This is a Test'
- bgcol = '#ffffff'
- %]
-
-=item footer
-
-The 'footer' element generates the terminating E<lt>/bodyE<gt> and
-E<lt>/htmlE<gt> element to balance the header.
-
- [% PROCESS html/header %]
-
- ...page content here...
-
- [% PROCESS html/footer %]
-
-=item page
-
-The 'page' element combines the 'html/header' and 'html/footer' elements.
-
- [% WRAPPER html/page %]
-
- ...page content here...
-
- [% END %]
-
-Page content should be defined in the 'content' variable (e.g. via WRAPPER).
-Additional HTML headers should be defined in the 'headers' variable.
-
- [% WRAPPER html/page
- headers = '<META name="keywords" content="foo, bar, ...">'
- %]
-
- ...page content here...
-
- [% END %]
-
-=back
-
-=head2 Tables, Bars and Boxes
-
-=over 4
-
-=item table
-
-A basic element for creating HTML tables.
-
- [% WRAPPER html/table pad=10 space=4 col='#404040' %]
- <tr>
- <td>Hello</td> <td>World</td>
- </tr>
- [% END %]
-
-The following variables may be defined:
-
-=over 4
-
-=item border
-
-Set the border width (default: 0)
-
-=item col
-
-Set the background colour (default: none).
-
-=item width
-
-Set a fixed table width.
-
-=item pad
-
-Set the cellpadding.
-
-=item space
-
-Set the cellspacing.
-
-=item content
-
-Content for the box. Supplied automatically if used via WRAPPER.
-
-=back
-
-=item row
-
-A basic element for creating HTML table rows.
-
- [% WRAPPER html/table %]
- [% WRAPPER html/row %]
- <td>Hello</td> <td>World</td>
- [% END %]
- [% END %]
-
-The following variables may be defined:
-
-=over 4
-
-=item col
-
-Set the background colour (default: none).
-
-=item valign
-
-Set the vertical alignment.
-
-=item rowspan
-
-Specify the number of rows to span.
-
-=item content
-
-Content for the box. Supplied automatically if used via WRAPPER.
-
-=back
-
-=item cell
-
-A basic element for creating HTML table cells.
-
- [% WRAPPER html/table %]
- [% WRAPPER html/row %]
- [% INCLUDE html/cell
- FOREACH content = ['Hello', 'World'] %]
- [% END %]
- [% END %]
-
-The following variables may be defined:
-
-=over 4
-
-=item col
-
-Set the background colour (default: none).
-
-=item align
-
-Set the horizontal alignment.
-
-=item colspan
-
-Specify the number of columns to span.
-
-=item content
-
-Content for the cell. Supplied automatically if used via WRAPPER.
-
-=back
-
-=item bar
-
-The bar element is a wrapping of html/table + html/row.
-
- [% WRAPPER html/bar %]
- <td>Foo</td> <td>Bar</td>
- [% END %]
-
-=item box
-
-The box element is a wrapping of html/table + html/row + html/cell
-
- [% WRAPPER html/box %]
- Hello World!
- [% END %]
-
-=back
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.69, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Library::Splash|Template::Library::Splash>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Library/PostScript.pod b/lib/Template/Library/PostScript.pod
deleted file mode 100644
index c30246c..0000000
--- a/lib/Template/Library/PostScript.pod
+++ /dev/null
@@ -1,78 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Library::PostScript
-#
-# DESCRIPTION
-# This library contains a number of useful templates for generating
-# PostScript pages.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-# 2.69
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Library::PostScript - Template library for generating PostScript
-
-=head1 DESCRIPTION
-
-The PostScript library contains a number of templates for generating
-PostScript pages. It's very new, very incomplete, very ad-hoc and
-isn't yet documented.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.69, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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:
diff --git a/lib/Template/Library/Splash.pod b/lib/Template/Library/Splash.pod
deleted file mode 100644
index e8c4f8b..0000000
--- a/lib/Template/Library/Splash.pod
+++ /dev/null
@@ -1,1030 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Library::Splash
-#
-# DESCRIPTION
-# The Splash! library is built on top of the HTML library and
-# implements a set of widgets for easy construction of stylish HTML
-# pages
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-# 2.69
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Library::Splash - Template library for building stylish HTML user interfaces
-
-=head1 DESCRIPTION
-
-B<NOTE:> This documentation is incomplete, incorrect and outdated.
-The Splash! library is still evolving and subject to change. See
-the examples for a much more recent and accurate demonstration of
-use.
-
-=head2 Introduction
-
-The 'Splash' template library is distributed as part of the Template
-Toolkit. It can be found in the 'templates' sub-directory of the
-installation directory.
-
- /your/tt2/installation
- |
- +-- docs
- | ...
- |
- +-- images
- | ...
- |
- +-- examples
- | ...
- |
- +-- templates
- |
- +-- html
- | ...
- +-- pod
- | ...
- +-- splash <<<< YOU ARE HERE
- ...
-
-
-To use the Splash library, you first need to tell the Template Toolkit
-where to find the template files.
-
- use Template;
-
- my $tt2 = Template->new({
- INCLUDE_PATH => '/usr/local/tt2/templates',
- });
-
-For a portable way to determine the installation 'templates' directory,
-you can use the C<Template::Config-E<gt>instdir()> class method.
-
- use Template;
-
- my $tt2 = Template->new({
- INCLUDE_PATH => Template::Config->instdir('templates'),
- });
-
-Note that you should set the INCLUDE_PATH to the 'templates' directory
-as shown here and don't be tempted to set the INCLUDE_PATH to
-'templates/splash'. Many of the Splash! components use elements in
-the 'html' directory and contain directives of the form:
-
- [% INCLUDE html/something %].
-
-=head2 Configuration
-
-The 'splash/config' template defines a 'splash' hash array which
-contains numerous configuration items for the Splash library. You
-must PROCESS this template to ensure that the hash definition is
-imported into your calling template. An INCLUDE is not sufficient as
-it localises variables and prevents the 'splash' hash array from
-existing outside the splash/config template.
-
- [% PROCESS splash/config %]
-
-Alternately, you can define the splash/config template as a PRE_PROCESS
-item when you create the Template processor.
-
- use Template;
-
- my $tt2 = Template->new({
- INCLUDE_PATH => Template::Config->instdir('templates'),
- PRE_PROCESS => 'splash/config',
- });
-
-You can modify the default configuration by creating your own
-PRE_PROCESS config file which loads the 'splash/config' and then
-tweaks the settings to your own preferences.
-
- my $tt2 = Template->new({
- INCLUDE_PATH => [ '/home/abw/tt2/templates',
- Template::Config->instdir('templates') ],
- PRE_PROCESS => 'config'
- });
-
-/home/abw/tt2/templates/config:
-
- [% # load the 'splash' configuration
- PROCESS splash/config;
-
- # tweak values to personal preferences
- splash.images = '/~abw/tt2/images/splash'
- splash.select.col = 'leaf'
- splash.unselect.col = 'bud'
- %]
-
-The splash/config file includes some instructional comments on
-things you might like to tweak.
-
-=head2 Colours
-
-The Splash! library uses the colours defined in the html/rgb template.
-The 'rgb' hash defined therein is imported as the 'splash.rgb' hash.
-
- [% INCLUDE splash/box col='grey75' %]
-
-See the examples for further enlightenment on using colour.
-
-=head2 Style
-
-There are two very primitive "styles" implemented called "select" and
-"unselect". These are used to indicate which item on a menu is
-selected, for example. Each style defines characteristics like
-background colour, font face, size and colour, text alignment, and so
-on.
-
-The styles are implemented as hashes within the 'splash' hash. Many
-of the components respond to a 'style' variable being set and you can
-pass a direct reference to splash.select or splash.unselect (or your
-own styles). e.g.
-
- [% INCLUDE splash/button
- content = "Unselected"
- style = splash.unselect
- %]
- [% INCLUDE splash/button
- content ="Selected"
- style = splash.select
- %]
-
-Alternately, you can use the 'select' variable to indicate either
-of the inbuilt styles: splash.select or splash.unselect.
-
- [% INCLUDE splash/button
- content = "Unselected"
- select = 0
- %]
- [% INCLUDE splash/button
- content = "Selected"
- select = 1
- %]
-
-=head1 COMPONENT TEMPLATES
-
-This section describes some of the component templates in the Splash!
-library. This documentation is incomplete and may also be inaccurate
-in places. The examples in the 'examples' directory are likely to be
-a much better reference.
-
-
-=head2 splash/text
-
-Simple template to format text according to a selected/unselected style,
-adding links, etc.
-
- [% INCLUDE splash/text
- content = 'Template Toolkit'
- link = 'http://www.template-toolkit.org'
- select = 0
- bold = 1
- %]
-
-
-Configuration items:
-
-=over 4
-
-
-=item content
-
-Text content.
-
-
-=item link
-
-URL which can be defined to make the text a link.
-
-
-=item style
-
-Reference to a style hash.
-
-
-=item select
-
-Flag to default the style to splash.select (select == true value) or
-splash.unselect (select == false value).
-
-
-=back
-
-The following items default to the relevant style values:
-
-=over 4
-
-
-=item col (style.col.text)
-
-
-=item font (style.font.face)
-
-
-=item bold (style.font.bold)
-
-
-=item size (style.font.size)
-
-
-=back
-
-
-
-=head2 splash/table
-
-A thin wrapper around html/table, allowing a colour to be specified
-by name.
-
- [% WRAPPER splash/table
- col = 'aqua'
- pad = 4
- width = '100%'
- %]
- <tr>
- <td>Foo</td>
- <td>Bar</td>
- </tr>
- [% END %]
-
-
-Configuration items:
-
-=over 4
-
-
-=item content
-
-Table content.
-
-
-=item col
-
-Background colour.
-
-
-=item border
-
-Border width (default: 0)
-
-
-=item width
-
-Width in absolute pixels (e.g. '100') or as a percentage (e.g. '50%').
-
-=item pad
-
-Cell padding.
-
-
-=item space
-
-Cell padding.
-
-
-=back
-
-
-
-=head2 splash/row
-
-Creates a row for an HTML table.
-
- [% WRAPPER splash/table %]
-
- [% WRAPPER splash/row col='marine' %]
- <td>Foo</td><td>Bar</td>
- [% END %]
-
- [% WRAPPER splash/row col='aqua' %]
- <td>Foo</td><td>Bar</td>
- [% END %]
-
- [% END %]
-
-
-Configuration items:
-
-=over 4
-
-
-=item content
-
-Row content.
-
-
-=item col
-
-Background colour.
-
-
-=item valign
-
-Vertical alignment
-
-
-=item rowspan
-
-Number of rows to span.
-
-
-=back
-
-
-
-=head2 splash/cell
-
-Creates a cell for an HTML table.
-
- [% WRAPPER splash/table + splash/row + splash/cell col='grey75' %]
- Hello World
- [% END %]
-
-
-Configuration items:
-
-=over 4
-
-
-=item content
-
-Cell content.
-
-
-=item col
-
-Background colour.
-
-
-=item align
-
-Horizontal alignment
-
-
-=item colspan
-
-Number of columns to span.
-
-
-=back
-
-
-
-=head2 splash/box
-
-A box created from a union of splash/table, splash/row and splash/cell.
-The following is equivalent to the previous example.
-
- [% WRAPPER splash/box col='grey75' %]
- Hello World
- [% END %]
-
-Configuration items are as per the individual templates.
-
-
-=head2 splash/button
-
-Creates a small button with rounded corners.
-
- [% INCLUDE splash/button
- content = 'Template Toolkit'
- select = 1
- width = '50%'
- %]
-
-
-Configuration items:
-
-=over 4
-
-
-=item content
-
-Button content.
-
-
-=item style
-
-Reference to a style hash.
-
-
-=item select
-
-Flag to default the style to splash.select (select == true value) or
-splash.unselect (select == false value).
-
-
-=item width
-
-Width in absolute pixels (e.g. '100') or as a percentage (e.g. '50%').
-
-=back
-
-The following items default to the relevant style values:
-
-=over 4
-
-
-=item col (style.col.text)
-
-
-=item textcol (style.col.text)
-
-
-=item font (style.font.face)
-
-
-=item size (style.font.size)
-
-
-=item bold (style.font.bold)
-
-
-=item width (style.button.width)
-
-
-=item align (style.button.align)
-
-
-=back
-
-
-
-=head2 splash/bar
-
-Creates a bar with rounded corners at either the top or bottom, and
-square corners on the other. Default has rounded at the top, set
-'invert' to select bottom.
-
- [% INCLUDE splash/bar
- content = 'Hello World',
- select = 1
- %]
-
-
-Configuration items:
-
-=over 4
-
-
-=item content
-
-Bar content.
-
-
-=item style
-
-Reference to a style hash.
-
-
-=item select
-
-Flag to default the style to splash.select (select == true value) or
-splash.unselect (select == false value).
-
-
-=item width
-
-Width in absolute pixels (e.g. '100') or as a percentage (e.g. '50%').
-
-=item invert
-
-Flag to invert bar to hang down instead of sitting
-upright.
-
-
-=back
-
-The following items default to the relevant style values:
-
-=over 4
-
-
-=item col (style.col.text)
-
-
-=item textcol (style.col.text)
-
-
-=item font (style.font.face)
-
-
-=item size (style.font.size)
-
-
-=item bold (style.font.bold)
-
-
-=item width (style.button.width)
-
-
-=item align (style.button.align)
-
-
-=back
-
-
-=head2 splash/hair
-
-Generates a frame enclosing the content within crosshair corners.
-
- [% INCLUDE splash/hair
- content = 'Template Toolkit'
- %]
-
-
-Configuration items:
-
-=over 4
-
-
-=item content
-
-Hair content.
-
-
-=item style
-
-Reference to a style hash.
-
-
-=back
-
-The following items default to the relevant style values:
-
-=over 4
-
-
-=item col (style.col.text)
-
-
-=item bgcol (style.col.back)
-
-
-=item align (style.button.align)
-
-
-=back
-
-
-=head2 splash/menu
-
-Creates a menu as a series of splash/button elements.
-
- [% buttons = [
- { text => 'One', link => 'one.html' }
- { text => 'Two', link => 'two.html' }
- ]
- %]
-
- [% INCLUDE splash/menu
- select = 2 # Two
- %]
-
-
-Configuration items:
-
-=over 4
-
-
-=item buttons
-
-A reference to a list of hash arrays containing 'text' and 'link' items.
-
-
-=item select (n or 0)
-
-Indicates which button should be selected. First item is 1. 0 indicates
-no button selected.
-
-
-=item width
-
-Width in absolute pixels (e.g. '100') or as a percentage (e.g. '50%').
-
-=item align
-
-Horizontal alignment
-
-
-=back
-
-
-
-=head2 splash/menubar
-
-As above, but incorporated into a wider bar.
-
- [% WRAPPER splash/menubar %]
- Section Title
- [% END %]
-
-
-Configuration items:
-
-=over 4
-
-
-=item buttons
-
-A reference to a list of hash arrays containing 'text' and 'link' items.
-
-
-=item select (n or 0)
-
-Indicates which button should be selected. First item is 1. 0 indicates
-no button selected.
-
-
-=item width
-
-Width in absolute pixels (e.g. '100') or as a percentage (e.g. '50%').
-
-=item align
-
-Horizontal alignment
-
-
-=back
-
-
-
-=head2 splash/panel
-
-A table with a coloured edge.
-
- [% WRAPPER splash/panel edge='black' fill='grey75' border=2 %]
- <tr>
- <td>Hello World</td>
- </tr>
- [% END %]
-
-
-Configuration items:
-
-=over 4
-
-
-=item content
-
-Panel content.
-
-
-=item style
-
-Reference to a style hash.
-
-
-=item select
-
-Flag to default the style to splash.select (select == true value) or
-splash.unselect (select == false value).
-
-
-=item width
-
-Width in absolute pixels (e.g. '100') or as a percentage (e.g. '50%').
-
-=item align
-
-Horizontal alignment
-
-
-=item border
-
-Border width (default: 0)
-
-
-=back
-
-The following items default to the relevant style values:
-
-=over 4
-
-
-=item edge (style.col.edge)
-
-
-=item fill (style.col.fill)
-
-
-=item pad (style.pad)
-
-
-=back
-
-
-
-=head2 splash/pane
-
-A union of splash/row + splash/cell.
-
- [% WRAPPER splash/panel select=1 %]
- [% WRAPPER splash/pane col='grey75' %]
- Hello World
- [% END %]
-
- [% WRAPPER splash/pane col='grey50' %]
- Hello Again
- [% END %]
- [% END %]
-
-
-=head2 splash/tab
-
-A simple button looking like a page tab.
-
- [% INCLUDE splash/tab
- content = 'Option 1'
- col = 'aqua'
- %]
-
-
-Configuration items:
-
-=over 4
-
-
-=item content
-
-Tab content.
-
-
-=item style
-
-Reference to a style hash.
-
-
-=item select
-
-Flag to default the style to splash.select (select == true value) or
-splash.unselect (select == false value).
-
-
-=item width
-
-Width in absolute pixels (e.g. '100') or as a percentage (e.g. '50%').
-
-=item align
-
-Horizontal alignment
-
-
-=back
-
-The following items default to the relevant style values:
-
-=over 4
-
-
-=item col (style.col.text)
-
-
-=item textcol (style.col.text)
-
-
-=item font (style.font.face)
-
-
-=item size (style.font.size)
-
-
-=item bold (style.font.bold)
-
-
-=item tabalign (style.tab.align)
-
-
-=back
-
-
-
-=head2 splash/tabset
-
-A set of splash/tab components, similar to a menu.
-
-
-Configuration items:
-
-=over 4
-
-
-=item tabs
-
-List of hash references containing text/link entries, as per
-menu buttons.
-
-
-=item select
-
-Flag to default the style to splash.select (select == true value) or
-splash.unselect (select == false value).
-
-
-=item invert
-
-Flag to invert tab to hang down instead of sitting
-upright.
-
-
-=back
-
-
-
-=head2 splash/tabbox
-
-Add a splash/tab to the top of a splash/box.
-
-
-Configuration items:
-
-=over 4
-
-
-=item title
-
- title.
-
-
-=item content
-
- content.
-
-
-=item width
-
-Width in absolute pixels (e.g. '100') or as a percentage (e.g. '50%').
-
-=item tabwidth
-
-Width of tabs.
-
-
-=item select
-
-Flag to default the style to splash.select (select == true value) or
-splash.unselect (select == false value).
-
-
-=item border
-
-Border width (default: 0)
-
-
-=back
-
-The following items default to the relevant style values:
-
-=over 4
-
-
-=item col (style.col.text)
-
-
-=item fill (style.col.fill)
-
-
-=item tabalign (style.tab.align)
-
-
-=item tablocate (style.tab.locate)
-
-
-=back
-
-
-
-=head2 splash/tabsbox
-
-Add a splash/tabset to the top of a splash/box.
-
-
-Configuration items:
-
-=over 4
-
-
-=item tabs
-
-List of hash references containing text/link entries, as per
-menu buttons.
-
-
-=item select
-
-Flag to default the style to splash.select (select == true value) or
-splash.unselect (select == false value).
-
-
-=item content
-
- content.
-
-
-=item width
-
-Width in absolute pixels (e.g. '100') or as a percentage (e.g. '50%').
-
-=item border
-
-Border width (default: 0)
-
-
-=item invert
-
-Flag to invert to hang down instead of sitting
-upright.
-
-
-=back
-
-The following items default to the relevant style values:
-
-=over 4
-
-
-=item col (style.col.text)
-
-
-=item fill (style.col.fill)
-
-
-=item tabalign (style.tab.align)
-
-
-=item tablocate (style.tab.locate)
-
-
-=back
-
-
-=head2 splash/tabspanel
-
-As per splash/tabsbox, but attached to a splash/panel instead of a
-splash/box.
-
-
-=head1 EXAMPLES
-
-See the examples in the 'examples' sub-directory of the installation
-for comprehensive examples showing use of the Splash! library.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.69, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Library::HTML|Template::Library::HTML>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Manual.pod b/lib/Template/Manual.pod
deleted file mode 100644
index 8775a5b..0000000
--- a/lib/Template/Manual.pod
+++ /dev/null
@@ -1,180 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Manual
-#
-# DESCRIPTION
-# This is the comprehensive user guide and reference manual for the
-# Template Toolkit.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-#
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Manual - User guide and reference manual for the Template Toolkit
-
-=head1 DESCRIPTION
-
-This is the comprehensive user guide and reference manual for the
-Template Toolkit.
-
-=over 4
-
-=item L<Template::Manual::Intro|Template::Manual::Intro>
-
-Introduction to the Template Toolkit
-
-This section provides a general introduction to the Template Toolkit,
-giving a quick overview of features, examples of template directives
-and use of the Template.pm module. It also described the basic concept
-underlying the toolkit: the separation of presentation elements from
-application logic and data.
-
-=item L<Template::Manual::Syntax|Template::Manual::Syntax>
-
-Directive syntax, structure and semantics
-
-This section describes the syntax, structure and semantics of the
-Template Toolkit directives and general presentation language.
-
-=item L<Template::Manual::Directives|Template::Manual::Directives>
-
-Template directives
-
-This section provides a reference of all Template Toolkit directives,
-complete with examples of use.
-
-=item L<Template::Manual::Variables|Template::Manual::Variables>
-
-Template variables and code bindings
-
-This section describes the different ways in which Perl data can be
-bound to template variables and accessed via Template Toolkit
-directives.
-
-=item L<Template::Manual::VMethods|Template::Manual::VMethods>
-
-Virtual Methods
-
-The Template Toolkit provides virtual methods for manipulating variable
-values. Most of them are analogous to regular Perl functions of the
-same names. This section describes the different virtual methods that
-can be applied to scalar, list and hash values.
-
-=item L<Template::Manual::Config|Template::Manual::Config>
-
-Configuration options
-
-This section contains details of all the configuration options that can
-be used to customise the behaviour and extend the features of the
-Template Toolkit.
-
-=item L<Template::Manual::Filters|Template::Manual::Filters>
-
-Standard filters
-
-This section lists all the standard filters distributed with the
-Template Toolkit for post-processing output.
-
-=item L<Template::Manual::Plugins|Template::Manual::Plugins>
-
-Standard plugins
-
-This section lists the standard plugins which can be used to extend the
-runtime functionality of the Template Toolkit. The plugins are
-distributed with the Template Toolkit but may required additional
-modules from CPAN.
-
-=item L<Template::Manual::Internals|Template::Manual::Internals>
-
-Template Toolkit internals
-
-This document provides an overview of the internal architecture of the
-Template Toolkit. It is a work in progress and is far from complete,
-currently providing little more than an overview of how the major
-components fit together. Nevertheless, it's a good starting point for
-anyone wishing to delve into the source code to find out how it all
-works.
-
-=item L<Template::Manual::Views|Template::Manual::Views>
-
-Template Toolkit views (experimental)
-
-This section describes dynamic views: a powerful but experimental new
-feature in version 2.01 of the Template Toolkit.
-
-=item L<Template::Manual::Refs|Template::Manual::Refs>
-
-Related modules, projects and other resources
-
-This section provides references to external modules, projects and
-other resources related to the Template Toolkit.
-
-=item L<Template::Manual::Credits|Template::Manual::Credits>
-
-Author and contributor credits
-
-This section provides a brief history of the Template Toolkit and
-details the primary author and numerous other people who have
-contributed to it.
-
-
-
-=back
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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:
diff --git a/lib/Template/Manual/Config.pod b/lib/Template/Manual/Config.pod
deleted file mode 100644
index 5020556..0000000
--- a/lib/Template/Manual/Config.pod
+++ /dev/null
@@ -1,2122 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Manual::Config
-#
-# DESCRIPTION
-# This section contains details of all the configuration options that
-# can be used to customise the behaviour and extend the features of
-# the Template Toolkit.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-#
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Manual::Config - Configuration options
-
-=head1 DESCRIPTION
-
-This section contains details of all the configuration options that can
-be used to customise the behaviour and extend the features of the
-Template Toolkit.
-
-=head2 Template Style and Parsing Options
-
-=over 4
-
-
-
-=item START_TAG, END_TAG
-
-The START_TAG and END_TAG options are used to specify character
-sequences or regular expressions that mark the start and end of a
-template directive. The default values for START_TAG and END_TAG are
-'[%' and '%]' respectively, giving us the familiar directive style:
-
- [% example %]
-
-Any Perl regex characters can be used and therefore should be escaped
-(or use the Perl C<quotemeta> function) if they are intended to
-represent literal characters.
-
- my $template = Template->new({
- START_TAG => quotemeta('<+'),
- END_TAG => quotemeta('+>'),
- });
-
-example:
-
- <+ INCLUDE foobar +>
-
-The TAGS directive can also be used to set the START_TAG and END_TAG values
-on a per-template file basis.
-
- [% TAGS <+ +> %]
-
-
-
-
-
-
-=item TAG_STYLE
-
-The TAG_STYLE option can be used to set both START_TAG and END_TAG
-according to pre-defined tag styles.
-
- my $template = Template->new({
- TAG_STYLE => 'star',
- });
-
-Available styles are:
-
- template [% ... %] (default)
- template1 [% ... %] or %% ... %% (TT version 1)
- metatext %% ... %% (Text::MetaText)
- star [* ... *] (TT alternate)
- php <? ... ?> (PHP)
- asp <% ... %> (ASP)
- mason <% ... > (HTML::Mason)
- html <!-- ... --> (HTML comments)
-
-Any values specified for START_TAG and/or END_TAG will over-ride
-those defined by a TAG_STYLE.
-
-The TAGS directive may also be used to set a TAG_STYLE
-
- [% TAGS html %]
- <!-- INCLUDE header -->
-
-
-
-
-
-
-=item PRE_CHOMP, POST_CHOMP
-
-Anything outside a directive tag is considered plain text and is
-generally passed through unaltered (but see the INTERPOLATE option).
-This includes all whitespace and newlines characters surrounding
-directive tags. Directives that don't generate any output will leave
-gaps in the output document.
-
-Example:
-
- Foo
- [% a = 10 %]
- Bar
-
-Output:
-
- Foo
-
- Bar
-
-The PRE_CHOMP and POST_CHOMP options can help to clean up some of this
-extraneous whitespace. Both are disabled by default.
-
- my $template = Template->new({
- PRE_CHOMP => 1,
- POST_CHOMP => 1,
- });
-
-With PRE_CHOMP set to 1, the newline and whitespace preceding a directive
-at the start of a line will be deleted. This has the effect of
-concatenating a line that starts with a directive onto the end of the
-previous line.
-
- Foo <----------.
- |
- ,---(PRE_CHOMP)----'
- |
- `-- [% a = 10 %] --.
- |
- ,---(POST_CHOMP)---'
- |
- `-> Bar
-
-With POST_CHOMP set to 1, any whitespace after a directive up to and
-including the newline will be deleted. This has the effect of joining
-a line that ends with a directive onto the start of the next line.
-
-If PRE_CHOMP or POST_CHOMP is set to 2, then instead of removing all
-the whitespace, the whitespace will be collapsed to a single space.
-This is useful for HTML, where (usually) a contiguous block of
-whitespace is rendered the same as a single space.
-
-You may use the CHOMP_NONE, CHOMP_ALL, and CHOMP_COLLAPSE constants
-from the Template::Constants module to deactivate chomping, remove
-all whitespace, or collapse whitespace to a single space.
-
-PRE_CHOMP and POST_CHOMP can be activated for individual directives by
-placing a '-' immediately at the start and/or end of the directive.
-
- [% FOREACH user = userlist %]
- [%- user -%]
- [% END %]
-
-The '-' characters activate both PRE_CHOMP and POST_CHOMP for the one
-directive '[%- name -%]'. Thus, the template will be processed as if
-written:
-
- [% FOREACH user = userlist %][% user %][% END %]
-
-Note that this is the same as if PRE_CHOMP and POST_CHOMP were set
-to CHOMP_ALL; the only way to get the CHOMP_COLLAPSE behavior is
-to set PRE_CHOMP or POST_CHOMP accordingly. If PRE_CHOMP or POST_CHOMP
-is already set to CHOMP_COLLAPSE, using '-' will give you CHOMP_COLLAPSE
-behavior, not CHOMP_ALL behavior.
-
-Similarly, '+' characters can be used to disable PRE_CHOMP or
-POST_CHOMP (i.e. leave the whitespace/newline intact) options on a
-per-directive basis.
-
- [% FOREACH user = userlist %]
- User: [% user +%]
- [% END %]
-
-With POST_CHOMP enabled, the above example would be parsed as if written:
-
- [% FOREACH user = userlist %]User: [% user %]
- [% END %]
-
-
-
-
-
-=item TRIM
-
-The TRIM option can be set to have any leading and trailing whitespace
-automatically removed from the output of all template files and BLOCKs.
-
-By example, the following BLOCK definition
-
- [% BLOCK foo %]
- Line 1 of foo
- [% END %]
-
-will be processed is as "\nLine 1 of foo\n". When INCLUDEd, the surrounding
-newlines will also be introduced.
-
- before
- [% INCLUDE foo %]
- after
-
-output:
- before
-
- Line 1 of foo
-
- after
-
-With the TRIM option set to any true value, the leading and trailing
-newlines (which count as whitespace) will be removed from the output
-of the BLOCK.
-
- before
- Line 1 of foo
- after
-
-The TRIM option is disabled (0) by default.
-
-
-
-
-
-=item INTERPOLATE
-
-The INTERPOLATE flag, when set to any true value will cause variable
-references in plain text (i.e. not surrounded by START_TAG and END_TAG)
-to be recognised and interpolated accordingly.
-
- my $template = Template->new({
- INTERPOLATE => 1,
- });
-
-Variables should be prefixed by a '$' to identify them. Curly braces
-can be used in the familiar Perl/shell style to explicitly scope the
-variable name where required.
-
- # INTERPOLATE => 0
- <a href="http://[% server %]/[% help %]">
- <img src="[% images %]/help.gif"></a>
- [% myorg.name %]
-
- # INTERPOLATE => 1
- <a href="http://$server/$help">
- <img src="$images/help.gif"></a>
- $myorg.name
-
- # explicit scoping with { }
- <img src="$images/${icon.next}.gif">
-
-Note that a limitation in Perl's regex engine restricts the maximum length
-of an interpolated template to around 32 kilobytes or possibly less. Files
-that exceed this limit in size will typically cause Perl to dump core with
-a segmentation fault. If you routinely process templates of this size
-then you should disable INTERPOLATE or split the templates in several
-smaller files or blocks which can then be joined backed together via
-PROCESS or INCLUDE.
-
-
-
-
-
-
-
-=item ANYCASE
-
-By default, directive keywords should be expressed in UPPER CASE. The
-ANYCASE option can be set to allow directive keywords to be specified
-in any case.
-
- # ANYCASE => 0 (default)
- [% INCLUDE foobar %] # OK
- [% include foobar %] # ERROR
- [% include = 10 %] # OK, 'include' is a variable
-
- # ANYCASE => 1
- [% INCLUDE foobar %] # OK
- [% include foobar %] # OK
- [% include = 10 %] # ERROR, 'include' is reserved word
-
-One side-effect of enabling ANYCASE is that you cannot use a variable
-of the same name as a reserved word, regardless of case. The reserved
-words are currently:
-
- GET CALL SET DEFAULT INSERT INCLUDE PROCESS WRAPPER
- IF UNLESS ELSE ELSIF FOR FOREACH WHILE SWITCH CASE
- USE PLUGIN FILTER MACRO PERL RAWPERL BLOCK META
- TRY THROW CATCH FINAL NEXT LAST BREAK RETURN STOP
- CLEAR TO STEP AND OR NOT MOD DIV END
-
-
-The only lower case reserved words that cannot be used for variables,
-regardless of the ANYCASE option, are the operators:
-
- and or not mod div
-
-
-
-
-
-
-=back
-
-=head2 Template Files and Blocks
-
-=over 4
-
-
-
-=item INCLUDE_PATH
-
-The INCLUDE_PATH is used to specify one or more directories in which
-template files are located. When a template is requested that isn't
-defined locally as a BLOCK, each of the INCLUDE_PATH directories is
-searched in turn to locate the template file. Multiple directories
-can be specified as a reference to a list or as a single string where
-each directory is delimited by ':'.
-
- my $template = Template->new({
- INCLUDE_PATH => '/usr/local/templates',
- });
-
- my $template = Template->new({
- INCLUDE_PATH => '/usr/local/templates:/tmp/my/templates',
- });
-
- my $template = Template->new({
- INCLUDE_PATH => [ '/usr/local/templates',
- '/tmp/my/templates' ],
- });
-
-On Win32 systems, a little extra magic is invoked, ignoring delimiters
-that have ':' followed by a '/' or '\'. This avoids confusion when using
-directory names like 'C:\Blah Blah'.
-
-When specified as a list, the INCLUDE_PATH path can contain elements
-which dynamically generate a list of INCLUDE_PATH directories. These
-generator elements can be specified as a reference to a subroutine or
-an object which implements a paths() method.
-
- my $template = Template->new({
- INCLUDE_PATH => [ '/usr/local/templates',
- \&incpath_generator,
- My::IncPath::Generator->new( ... ) ],
- });
-
-Each time a template is requested and the INCLUDE_PATH examined, the
-subroutine or object method will be called. A reference to a list of
-directories should be returned. Generator subroutines should report
-errors using die(). Generator objects should return undef and make an
-error available via its error() method.
-
-For example:
-
- sub incpath_generator {
-
- # ...some code...
-
- if ($all_is_well) {
- return \@list_of_directories;
- }
- else {
- die "cannot generate INCLUDE_PATH...\n";
- }
- }
-
-or:
-
- package My::IncPath::Generator;
-
- # Template::Base (or Class::Base) provides error() method
- use Template::Base;
- use base qw( Template::Base );
-
- sub paths {
- my $self = shift;
-
- # ...some code...
-
- if ($all_is_well) {
- return \@list_of_directories;
- }
- else {
- return $self->error("cannot generate INCLUDE_PATH...\n");
- }
- }
-
- 1;
-
-
-
-
-
-=item DELIMITER
-
-Used to provide an alternative delimiter character sequence for
-separating paths specified in the INCLUDE_PATH. The default
-value for DELIMITER is ':'.
-
- # tolerate Silly Billy's file system conventions
- my $template = Template->new({
- DELIMITER => '; ',
- INCLUDE_PATH => 'C:/HERE/NOW; D:/THERE/THEN',
- });
-
- # better solution: install Linux! :-)
-
-On Win32 systems, the default delimiter is a little more intelligent,
-splitting paths only on ':' characters that aren't followed by a '/'.
-This means that the following should work as planned, splitting the
-INCLUDE_PATH into 2 separate directories, C:/foo and C:/bar.
-
- # on Win32 only
- my $template = Template->new({
- INCLUDE_PATH => 'C:/Foo:C:/Bar'
- });
-
-However, if you're using Win32 then it's recommended that you
-explicitly set the DELIMITER character to something else (e.g. ';')
-rather than rely on this subtle magic.
-
-
-
-
-=item ABSOLUTE
-
-The ABSOLUTE flag is used to indicate if templates specified with
-absolute filenames (e.g. '/foo/bar') should be processed. It is
-disabled by default and any attempt to load a template by such a
-name will cause a 'file' exception to be raised.
-
- my $template = Template->new({
- ABSOLUTE => 1,
- });
-
- # this is why it's disabled by default
- [% INSERT /etc/passwd %]
-
-On Win32 systems, the regular expression for matching absolute
-pathnames is tweaked slightly to also detect filenames that start
-with a driver letter and colon, such as:
-
- C:/Foo/Bar
-
-
-
-
-
-
-=item RELATIVE
-
-The RELATIVE flag is used to indicate if templates specified with
-filenames relative to the current directory (e.g. './foo/bar' or
-'../../some/where/else') should be loaded. It is also disabled by
-default, and will raise a 'file' error if such template names are
-encountered.
-
- my $template = Template->new({
- RELATIVE => 1,
- });
-
- [% INCLUDE ../logs/error.log %]
-
-
-
-
-
-=item DEFAULT
-
-The DEFAULT option can be used to specify a default template which should
-be used whenever a specified template can't be found in the INCLUDE_PATH.
-
- my $template = Template->new({
- DEFAULT => 'notfound.html',
- });
-
-If a non-existant template is requested through the Template process()
-method, or by an INCLUDE, PROCESS or WRAPPER directive, then the
-DEFAULT template will instead be processed, if defined. Note that the
-DEFAULT template is not used when templates are specified with
-absolute or relative filenames, or as a reference to a input file
-handle or text string.
-
-
-
-
-
-=item BLOCKS
-
-The BLOCKS option can be used to pre-define a default set of template
-blocks. These should be specified as a reference to a hash array
-mapping template names to template text, subroutines or Template::Document
-objects.
-
- my $template = Template->new({
- BLOCKS => {
- header => 'The Header. [% title %]',
- footer => sub { return $some_output_text },
- another => Template::Document->new({ ... }),
- },
- });
-
-
-
-
-=item AUTO_RESET
-
-The AUTO_RESET option is set by default and causes the local BLOCKS
-cache for the Template::Context object to be reset on each call to the
-Template process() method. This ensures that any BLOCKs defined
-within a template will only persist until that template is finished
-processing. This prevents BLOCKs defined in one processing request
-from interfering with other independent requests subsequently
-processed by the same context object.
-
-The BLOCKS item may be used to specify a default set of block definitions
-for the Template::Context object. Subsequent BLOCK definitions in templates
-will over-ride these but they will be reinstated on each reset if AUTO_RESET
-is enabled (default), or if the Template::Context reset() method is called.
-
-
-
-
-
-
-
-
-
-=item RECURSION
-
-The template processor will raise a file exception if it detects
-direct or indirect recursion into a template. Setting this option to
-any true value will allow templates to include each other recursively.
-
-
-
-=back
-
-=head2 Template Variables
-
-=over 4
-
-=item VARIABLES, PRE_DEFINE
-
-The VARIABLES option (or PRE_DEFINE - they're equivalent) can be used
-to specify a hash array of template variables that should be used to
-pre-initialise the stash when it is created. These items are ignored
-if the STASH item is defined.
-
- my $template = Template->new({
- VARIABLES => {
- title => 'A Demo Page',
- author => 'Joe Random Hacker',
- version => 3.14,
- },
- };
-
-or
-
- my $template = Template->new({
- PRE_DEFINE => {
- title => 'A Demo Page',
- author => 'Joe Random Hacker',
- version => 3.14,
- },
- };
-
-
-
-
-=item CONSTANTS
-
-The CONSTANTS option can be used to specify a hash array of template
-variables that are compile-time constants. These variables are
-resolved once when the template is compiled, and thus don't require
-further resolution at runtime. This results in significantly faster
-processing of the compiled templates and can be used for variables that
-don't change from one request to the next.
-
- my $template = Template->new({
- CONSTANTS => {
- title => 'A Demo Page',
- author => 'Joe Random Hacker',
- version => 3.14,
- },
- };
-
-=item CONSTANT_NAMESPACE
-
-Constant variables are accessed via the 'constants' namespace by
-default.
-
- [% constants.title %]
-
-The CONSTANTS_NAMESPACE option can be set to specify an alternate
-namespace.
-
- my $template = Template->new({
- CONSTANTS => {
- title => 'A Demo Page',
- # ...etc...
- },
- CONSTANTS_NAMESPACE => 'const',
- };
-
-In this case the constants would then be accessed as:
-
- [% const.title %]
-
-=item NAMESPACE
-
-The constant folding mechanism described above is an example of a
-namespace handler. Namespace handlers can be defined to provide
-alternate parsing mechanisms for variables in different namespaces.
-
-Under the hood, the Template module converts a constructor configuration
-such as:
-
- my $template = Template->new({
- CONSTANTS => {
- title => 'A Demo Page',
- # ...etc...
- },
- CONSTANTS_NAMESPACE => 'const',
- };
-
-into one like:
-
- my $template = Template->new({
- NAMESPACE => {
- const => Template:::Namespace::Constants->new({
- title => 'A Demo Page',
- # ...etc...
- }),
- },
- };
-
-You can use this mechanism to define multiple constant namespaces, or
-to install custom handlers of your own.
-
- my $template = Template->new({
- NAMESPACE => {
- site => Template:::Namespace::Constants->new({
- title => "Wardley's Widgets",
- version => 2.718,
- }),
- author => Template:::Namespace::Constants->new({
- name => 'Andy Wardley',
- email => 'abw@andywardley.com',
- }),
- voodoo => My::Namespace::Handler->new( ... ),
- },
- };
-
-Now you have 2 constant namespaces, for example:
-
- [% site.title %]
- [% author.name %]
-
-as well as your own custom namespace handler installed for the 'voodoo'
-namespace.
-
- [% voodoo.magic %]
-
-See L<Template::Namespace::Constants|Template::Namespace::Constants>
-for an example of what a namespace handler looks like on the inside.
-
-
-
-
-
-=back
-
-=head2 Template Processing Options
-
-
-The following options are used to specify any additional templates
-that should be processed before, after, around or instead of the
-template passed as the first argument to the Template process()
-method. These options can be perform various useful tasks such as
-adding standard headers or footers to all pages, wrapping page output
-in other templates, pre-defining variables or performing
-initialisation or cleanup tasks, automatically generating page summary
-information, navigation elements, and so on.
-
-The task of processing the template is delegated internally to the
-Template::Service module which, unsurprisingly, also has a process()
-method. Any templates defined by the PRE_PROCESS option are processed
-first and any output generated is added to the output buffer. Then
-the main template is processed, or if one or more PROCESS templates
-are defined then they are instead processed in turn. In this case,
-one of the PROCESS templates is responsible for processing the main
-template, by a directive such as:
-
- [% PROCESS $template %]
-
-The output of processing the main template or the PROCESS template(s)
-is then wrapped in any WRAPPER templates, if defined. WRAPPER
-templates don't need to worry about explicitly processing the template
-because it will have been done for them already. Instead WRAPPER
-templates access the content they are wrapping via the 'content'
-variable.
-
- wrapper before
- [% content %]
- wrapper after
-
-This output generated from processing the main template, and/or any
-PROCESS or WRAPPER templates is added to the output buffer. Finally,
-any POST_PROCESS templates are processed and their output is also
-added to the output buffer which is then returned.
-
-If the main template throws an exception during processing then any
-relevant template(s) defined via the ERROR option will be processed
-instead. If defined and successfully processed, the output from the
-error template will be added to the output buffer in place of the
-template that generated the error and processing will continue,
-applying any WRAPPER and POST_PROCESS templates. If no relevant ERROR
-option is defined, or if the error occurs in one of the PRE_PROCESS,
-WRAPPER or POST_PROCESS templates, then the process will terminate
-immediately and the error will be returned.
-
-
-
-=over 4
-
-
-
-=item PRE_PROCESS, POST_PROCESS
-
-These values may be set to contain the name(s) of template files
-(relative to INCLUDE_PATH) which should be processed immediately
-before and/or after each template. These do not get added to
-templates processed into a document via directives such as INCLUDE,
-PROCESS, WRAPPER etc.
-
- my $template = Template->new({
- PRE_PROCESS => 'header',
- POST_PROCESS => 'footer',
- };
-
-Multiple templates may be specified as a reference to a list. Each is
-processed in the order defined.
-
- my $template = Template->new({
- PRE_PROCESS => [ 'config', 'header' ],
- POST_PROCESS => 'footer',
- };
-
-Alternately, multiple template may be specified as a single string,
-delimited by ':'. This delimiter string can be changed via the
-DELIMITER option.
-
- my $template = Template->new({
- PRE_PROCESS => 'config:header',
- POST_PROCESS => 'footer',
- };
-
-The PRE_PROCESS and POST_PROCESS templates are evaluated in the same
-variable context as the main document and may define or update
-variables for subsequent use.
-
-config:
-
- [% # set some site-wide variables
- bgcolor = '#ffffff'
- version = 2.718
- %]
-
-header:
-
- [% DEFAULT title = 'My Funky Web Site' %]
- <html>
- <head>
- <title>[% title %]</title>
- </head>
- <body bgcolor="[% bgcolor %]">
-
-footer:
-
- <hr>
- Version [% version %]
- </body>
- </html>
-
-The Template::Document object representing the main template being processed
-is available within PRE_PROCESS and POST_PROCESS templates as the 'template'
-variable. Metadata items defined via the META directive may be accessed
-accordingly.
-
- $template->process('mydoc.html', $vars);
-
-mydoc.html:
-
- [% META title = 'My Document Title' %]
- blah blah blah
- ...
-
-header:
-
- <html>
- <head>
- <title>[% template.title %]</title></head>
- <body bgcolor="[% bgcolor %]">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-=item PROCESS
-
-The PROCESS option may be set to contain the name(s) of template files
-(relative to INCLUDE_PATH) which should be processed instead of the
-main template passed to the Template process() method. This can
-be used to apply consistent wrappers around all templates, similar to
-the use of PRE_PROCESS and POST_PROCESS templates.
-
- my $template = Template->new({
- PROCESS => 'content',
- };
-
- # processes 'content' instead of 'foo.html'
- $template->process('foo.html');
-
-A reference to the original template is available in the 'template'
-variable. Metadata items can be inspected and the template can be
-processed by specifying it as a variable reference (i.e. prefixed by
-'$') to an INCLUDE, PROCESS or WRAPPER directive.
-
-content:
-
- <html>
- <head>
- <title>[% template.title %]</title>
- </head>
-
- <body>
- [% PROCESS $template %]
- <hr>
- &copy; Copyright [% template.copyright %]
- </body>
- </html>
-
-foo.html:
-
- [% META
- title = 'The Foo Page'
- author = 'Fred Foo'
- copyright = '2000 Fred Foo'
- %]
- <h1>[% template.title %]</h1>
- Welcome to the Foo Page, blah blah blah
-
-output:
-
- <html>
- <head>
- <title>The Foo Page</title>
- </head>
-
- <body>
- <h1>The Foo Page</h1>
- Welcome to the Foo Page, blah blah blah
- <hr>
- &copy; Copyright 2000 Fred Foo
- </body>
- </html>
-
-
-
-
-
-
-
-=item WRAPPER
-
-The WRAPPER option can be used to specify one or more templates which
-should be used to wrap around the output of the main page template.
-The main template is processed first (or any PROCESS template(s)) and
-the output generated is then passed as the 'content' variable to the
-WRAPPER template(s) as they are processed.
-
- my $template = Template->new({
- WRAPPER => 'wrapper',
- };
-
- # process 'foo' then wrap in 'wrapper'
- $template->process('foo', { message => 'Hello World!' });
-
-wrapper:
-
- <wrapper>
- [% content %]
- </wrapper>
-
-foo:
-
- This is the foo file!
- Message: [% message %]
-
-The output generated from this example is:
-
- <wrapper>
- This is the foo file!
- Message: Hello World!
- </wrapper>
-
-You can specify more than one WRAPPER template by setting the value to
-be a reference to a list of templates. The WRAPPER templates will be
-processed in reverse order with the output of each being passed to the
-next (or previous, depending on how you look at it) as the 'content'
-variable. It sounds complicated, but the end result is that it just
-"Does The Right Thing" to make wrapper templates nest in the order you
-specify.
-
- my $template = Template->new({
- WRAPPER => [ 'outer', 'inner' ],
- };
-
- # process 'foo' then wrap in 'inner', then in 'outer'
- $template->process('foo', { message => 'Hello World!' });
-
-outer:
-
- <outer>
- [% content %]
- </outer>
-
-inner:
-
- <inner>
- [% content %]
- </inner>
-
-The output generated is then:
-
- <outer>
- <inner>
- This is the foo file!
- Message: Hello World!
- </inner>
- </outer>
-
-One side-effect of the "inside-out" processing of the WRAPPER
-configuration item (and also the WRAPPER directive) is that any
-variables set in the template being wrapped will be visible to the
-template doing the wrapping, but not the other way around.
-
-You can use this to good effect in allowing page templates to set
-pre-defined values which are then used in the wrapper templates. For
-example, our main page template 'foo' might look like this:
-
-foo:
-
- [% page = {
- title = 'Foo Page'
- subtitle = 'Everything There is to Know About Foo'
- author = 'Frank Oliver Octagon'
- }
- %]
-
- <p>
- Welcome to the page that tells you everything about foo
- blah blah blah...
- </p>
-
-The 'foo' template is processed before the wrapper template meaning
-that the 'page' data structure will be defined for use in the wrapper
-template.
-
-wrapper:
-
- <html>
- <head>
- <title>[% page.title %]</title>
- </head>
- <body>
- <h1>[% page.title %]</h1>
- <h2>[% page.subtitle %]</h1>
- <h3>by [% page.author %]</h3>
-
- [% content %]
- </body>
- </html>
-
-It achieves the same effect as defining META items which are then
-accessed via the 'template' variable (which you are still free to
-use within WRAPPER templates), but gives you more flexibility in
-the type and complexity of data that you can define.
-
-
-
-
-
-=item ERROR
-
-The ERROR (or ERRORS if you prefer) configuration item can be used to
-name a single template or specify a hash array mapping exception types
-to templates which should be used for error handling. If an uncaught
-exception is raised from within a template then the appropriate error
-template will instead be processed.
-
-If specified as a single value then that template will be processed
-for all uncaught exceptions.
-
- my $template = Template->new({
- ERROR => 'error.html'
- });
-
-If the ERROR item is a hash reference the keys are assumed to be
-exception types and the relevant template for a given exception will
-be selected. A 'default' template may be provided for the general
-case. Note that 'ERROR' can be pluralised to 'ERRORS' if you find
-it more appropriate in this case.
-
- my $template = Template->new({
- ERRORS => {
- user => 'user/index.html',
- dbi => 'error/database',
- default => 'error/default',
- },
- });
-
-In this example, any 'user' exceptions thrown will cause the
-'user/index.html' template to be processed, 'dbi' errors are handled
-by 'error/database' and all others by the 'error/default' template.
-Any PRE_PROCESS and/or POST_PROCESS templates will also be applied
-to these error templates.
-
-Note that exception types are hierarchical and a 'foo' handler will
-catch all 'foo.*' errors (e.g. foo.bar, foo.bar.baz) if a more
-specific handler isn't defined. Be sure to quote any exception types
-that contain periods to prevent Perl concatenating them into a single
-string (i.e. C<user.passwd> is parsed as 'user'.'passwd').
-
- my $template = Template->new({
- ERROR => {
- 'user.login' => 'user/login.html',
- 'user.passwd' => 'user/badpasswd.html',
- 'user' => 'user/index.html',
- 'default' => 'error/default',
- },
- });
-
-In this example, any template processed by the $template object, or
-other templates or code called from within, can raise a 'user.login'
-exception and have the service redirect to the 'user/login.html'
-template. Similarly, a 'user.passwd' exception has a specific
-handling template, 'user/badpasswd.html', while all other 'user' or
-'user.*' exceptions cause a redirection to the 'user/index.html' page.
-All other exception types are handled by 'error/default'.
-
-
-Exceptions can be raised in a template using the THROW directive,
-
- [% THROW user.login 'no user id: please login' %]
-
-or by calling the throw() method on the current Template::Context object,
-
- $context->throw('user.passwd', 'Incorrect Password');
- $context->throw('Incorrect Password'); # type 'undef'
-
-or from Perl code by calling die() with a Template::Exception object,
-
- die (Template::Exception->new('user.denied', 'Invalid User ID'));
-
-or by simply calling die() with an error string. This is
-automagically caught and converted to an exception of 'undef'
-type which can then be handled in the usual way.
-
- die "I'm sorry Dave, I can't do that";
-
-
-
-
-
-
-=back
-
-=head2 Template Runtime Options
-
-=over 4
-
-
-
-
-=item EVAL_PERL
-
-This flag is used to indicate if PERL and/or RAWPERL blocks should be
-evaluated. By default, it is disabled and any PERL or RAWPERL blocks
-encountered will raise exceptions of type 'perl' with the message
-'EVAL_PERL not set'. Note however that any RAWPERL blocks should
-always contain valid Perl code, regardless of the EVAL_PERL flag. The
-parser will fail to compile templates that contain invalid Perl code
-in RAWPERL blocks and will throw a 'file' exception.
-
-When using compiled templates (see
-L<COMPILE_EXT|Template::Manual::Config/Caching_and_Compiling_Options> and
-L<COMPILE_DIR|Template::Manual::Config/Caching_and_Compiling_Options>),
-the EVAL_PERL has an affect when the template is compiled, and again
-when the templates is subsequently processed, possibly in a different
-context to the one that compiled it.
-
-If the EVAL_PERL is set when a template is compiled, then all PERL and
-RAWPERL blocks will be included in the compiled template. If the
-EVAL_PERL option isn't set, then Perl code will be generated which
-B<always> throws a 'perl' exception with the message 'EVAL_PERL not
-set' B<whenever> the compiled template code is run.
-
-Thus, you must have EVAL_PERL set if you want your compiled templates
-to include PERL and RAWPERL blocks.
-
-At some point in the future, using a different invocation of the
-Template Toolkit, you may come to process such a pre-compiled
-template. Assuming the EVAL_PERL option was set at the time the
-template was compiled, then the output of any RAWPERL blocks will be
-included in the compiled template and will get executed when the
-template is processed. This will happen regardless of the runtime
-EVAL_PERL status.
-
-Regular PERL blocks are a little more cautious, however. If the
-EVAL_PERL flag isn't set for the I<current> context, that is, the
-one which is trying to process it, then it will throw the familiar 'perl'
-exception with the message, 'EVAL_PERL not set'.
-
-Thus you can compile templates to include PERL blocks, but optionally
-disable them when you process them later. Note however that it is
-possible for a PERL block to contain a Perl "BEGIN { # some code }"
-block which will always get run regardless of the runtime EVAL_PERL
-status. Thus, if you set EVAL_PERL when compiling templates, it is
-assumed that you trust the templates to Do The Right Thing. Otherwise
-you must accept the fact that there's no bulletproof way to prevent
-any included code from trampling around in the living room of the
-runtime environment, making a real nuisance of itself if it really
-wants to. If you don't like the idea of such uninvited guests causing
-a bother, then you can accept the default and keep EVAL_PERL disabled.
-
-
-
-
-
-
-
-=item OUTPUT
-
-Default output location or handler. This may be specified as one of:
-a file name (relative to OUTPUT_PATH, if defined, or the current
-working directory if not specified absolutely); a file handle
-(e.g. GLOB or IO::Handle) opened for writing; a reference to a text
-string to which the output is appended (the string isn't cleared); a
-reference to a subroutine which is called, passing the output text as
-an argument; as a reference to an array, onto which the content will be
-push()ed; or as a reference to any object that supports the print()
-method. This latter option includes the Apache::Request object which
-is passed as the argument to Apache/mod_perl handlers.
-
-example 1 (file name):
-
- my $template = Template->new({
- OUTPUT => "/tmp/foo",
- });
-
-example 2 (text string):
-
- my $output = '';
-
- my $template = Template->new({
- OUTPUT => \$output,
- });
-
-example 3 (file handle):
-
- open (TOUT, "> $file") || die "$file: $!\n";
-
- my $template = Template->new({
- OUTPUT => \*TOUT,
- });
-
-example 4 (subroutine):
-
- sub output { my $out = shift; print "OUTPUT: $out" }
-
- my $template = Template->new({
- OUTPUT => \&output,
- });
-
-example 5 (array reference):
-
- my $template = Template->new({
- OUTPUT => \@output,
- })
-
-example 6 (Apache/mod_perl handler):
-
- sub handler {
- my $r = shift;
-
- my $t = Template->new({
- OUTPUT => $r,
- });
- ...
- }
-
-The default OUTPUT location be overridden by passing a third parameter
-to the Template process() method. This can be specified as any of the
-above argument types.
-
- $t->process($file, $vars, "/tmp/foo");
- $t->process($file, $vars, "bar");
- $t->process($file, $vars, \*MYGLOB);
- $t->process($file, $vars, \@output);
- $t->process($file, $vars, $r); # Apache::Request
- ...
-
-
-
-
-
-
-
-
-=item OUTPUT_PATH
-
-The OUTPUT_PATH allows a directory to be specified into which output
-files should be written. An output file can be specified by the
-OUTPUT option, or passed by name as the third parameter to the
-Template process() method.
-
- my $template = Template->new({
- INCLUDE_PATH => "/tmp/src",
- OUTPUT_PATH => "/tmp/dest",
- });
-
- my $vars = {
- ...
- };
-
- foreach my $file ('foo.html', 'bar.html') {
- $template->process($file, $vars, $file)
- || die $template->error();
- }
-
-This example will read the input files '/tmp/src/foo.html' and
-'/tmp/src/bar.html' and write the processed output to '/tmp/dest/foo.html'
-and '/tmp/dest/bar.html', respectively.
-
-
-
-
-
-
-
-
-=item DEBUG
-
-The DEBUG option can be used to enable debugging within the various
-different modules that comprise the Template Toolkit. The
-L<Template::Constants|Template::Constants> module defines a set of
-DEBUG_XXXX constants which can be combined using the logical OR
-operator, '|'.
-
- use Template::Constants qw( :debug );
-
- my $template = Template->new({
- DEBUG => DEBUG_PARSER | DEBUG_PROVIDER,
- });
-
-For convenience, you can also provide a string containing a list
-of lower case debug options, separated by any non-word characters.
-
- my $template = Template->new({
- DEBUG => 'parser, provider',
- });
-
-The following DEBUG_XXXX flags can be used:
-
-=over 4
-
-=item DEBUG_SERVICE
-
-Enables general debugging messages for the
-L<Template::Service|Template::Service> module.
-
-=item DEBUG_CONTEXT
-
-Enables general debugging messages for the
-L<Template::Context|Template::Context> module.
-
-=item DEBUG_PROVIDER
-
-Enables general debugging messages for the
-L<Template::Provider|Template::Provider> module.
-
-=item DEBUG_PLUGINS
-
-Enables general debugging messages for the
-L<Template::Plugins|Template::Plugins> module.
-
-=item DEBUG_FILTERS
-
-Enables general debugging messages for the
-L<Template::Filters|Template::Filters> module.
-
-=item DEBUG_PARSER
-
-This flag causes the L<Template::Parser|Template::Parser> to generate
-debugging messages that show the Perl code generated by parsing and
-compiling each template.
-
-=item DEBUG_UNDEF
-
-This option causes the Template Toolkit to throw an 'undef' error
-whenever it encounters an undefined variable value.
-
-=item DEBUG_DIRS
-
-This option causes the Template Toolkit to generate comments
-indicating the source file, line and original text of each directive
-in the template. These comments are embedded in the template output
-using the format defined in the DEBUG_FORMAT configuration item, or a
-simple default format if unspecified.
-
-For example, the following template fragment:
-
-
- Hello World
-
-would generate this output:
-
- ## input text line 1 : ##
- Hello
- ## input text line 2 : World ##
- World
-
-=item DEBUG_ALL
-
-Enables all debugging messages.
-
-=item DEBUG_CALLER
-
-This option causes all debug messages that aren't newline terminated
-to have the file name and line number of the caller appended to them.
-
-
-=back
-
-=item DEBUG_FORMAT
-
-The DEBUG_FORMAT option can be used to specify a format string for the
-debugging messages generated via the DEBUG_DIRS option described
-above. Any occurances of C<$file>, C<$line> or C<$text> will be
-replaced with the current file name, line or directive text,
-respectively. Notice how the format is single quoted to prevent Perl
-from interpolating those tokens as variables.
-
- my $template = Template->new({
- DEBUG => 'dirs',
- DEBUG_FORMAT => '<!-- $file line $line : [% $text %] -->',
- });
-
-The following template fragment:
-
- [% foo = 'World' %]
- Hello [% foo %]
-
-would then generate this output:
-
- <!-- input text line 2 : [% foo = 'World' %] -->
- Hello <!-- input text line 3 : [% foo %] -->World
-
-The DEBUG directive can also be used to set a debug format within
-a template.
-
- [% DEBUG format '<!-- $file line $line : [% $text %] -->' %]
-
-
-=back
-
-=head2 Caching and Compiling Options
-
-=over 4
-
-
-
-=item CACHE_SIZE
-
-The Template::Provider module caches compiled templates to avoid the need
-to re-parse template files or blocks each time they are used. The CACHE_SIZE
-option is used to limit the number of compiled templates that the module
-should cache.
-
-By default, the CACHE_SIZE is undefined and all compiled templates are
-cached. When set to any positive value, the cache will be limited to
-storing no more than that number of compiled templates. When a new
-template is loaded and compiled and the cache is full (i.e. the number
-of entries == CACHE_SIZE), the least recently used compiled template
-is discarded to make room for the new one.
-
-The CACHE_SIZE can be set to 0 to disable caching altogether.
-
- my $template = Template->new({
- CACHE_SIZE => 64, # only cache 64 compiled templates
- });
-
- my $template = Template->new({
- CACHE_SIZE => 0, # don't cache any compiled templates
- });
-
-
-
-
-
-
-=item COMPILE_EXT
-
-From version 2 onwards, the Template Toolkit has the ability to
-compile templates to Perl code and save them to disk for subsequent
-use (i.e. cache persistence). The COMPILE_EXT option may be
-provided to specify a filename extension for compiled template files.
-It is undefined by default and no attempt will be made to read or write
-any compiled template files.
-
- my $template = Template->new({
- COMPILE_EXT => '.ttc',
- });
-
-If COMPILE_EXT is defined (and COMPILE_DIR isn't, see below) then compiled
-template files with the COMPILE_EXT extension will be written to the same
-directory from which the source template files were loaded.
-
-Compiling and subsequent reuse of templates happens automatically
-whenever the COMPILE_EXT or COMPILE_DIR options are set. The Template
-Toolkit will automatically reload and reuse compiled files when it
-finds them on disk. If the corresponding source file has been modified
-since the compiled version as written, then it will load and re-compile
-the source and write a new compiled version to disk.
-
-This form of cache persistence offers significant benefits in terms of
-time and resources required to reload templates. Compiled templates can
-be reloaded by a simple call to Perl's require(), leaving Perl to handle
-all the parsing and compilation. This is a Good Thing.
-
-=item COMPILE_DIR
-
-The COMPILE_DIR option is used to specify an alternate directory root
-under which compiled template files should be saved.
-
- my $template = Template->new({
- COMPILE_DIR => '/tmp/ttc',
- });
-
-The COMPILE_EXT option may also be specified to have a consistent file
-extension added to these files.
-
- my $template1 = Template->new({
- COMPILE_DIR => '/tmp/ttc',
- COMPILE_EXT => '.ttc1',
- });
-
- my $template2 = Template->new({
- COMPILE_DIR => '/tmp/ttc',
- COMPILE_EXT => '.ttc2',
- });
-
-
-When COMPILE_EXT is undefined, the compiled template files have the
-same name as the original template files, but reside in a different
-directory tree.
-
-Each directory in the INCLUDE_PATH is replicated in full beneath the
-COMPILE_DIR directory. This example:
-
- my $template = Template->new({
- COMPILE_DIR => '/tmp/ttc',
- INCLUDE_PATH => '/home/abw/templates:/usr/share/templates',
- });
-
-would create the following directory structure:
-
- /tmp/ttc/home/abw/templates/
- /tmp/ttc/usr/share/templates/
-
-Files loaded from different INCLUDE_PATH directories will have their
-compiled forms save in the relevant COMPILE_DIR directory.
-
-On Win32 platforms a filename may by prefixed by a drive letter and
-colon. e.g.
-
- C:/My Templates/header
-
-The colon will be silently stripped from the filename when it is added
-to the COMPILE_DIR value(s) to prevent illegal filename being generated.
-Any colon in COMPILE_DIR elements will be left intact. For example:
-
- # Win32 only
- my $template = Template->new({
- DELIMITER => ';',
- COMPILE_DIR => 'C:/TT2/Cache',
- INCLUDE_PATH => 'C:/TT2/Templates;D:/My Templates',
- });
-
-This would create the following cache directories:
-
- C:/TT2/Cache/C/TT2/Templates
- C:/TT2/Cache/D/My Templates
-
-
-=back
-
-=head2 Plugins and Filters
-
-=over 4
-
-
-
-=item PLUGINS
-
-The PLUGINS options can be used to provide a reference to a hash array
-that maps plugin names to Perl module names. A number of standard
-plugins are defined (e.g. 'table', 'cgi', 'dbi', etc.) which map to
-their corresponding Template::Plugin::* counterparts. These can be
-redefined by values in the PLUGINS hash.
-
- my $template = Template->new({
- PLUGINS => {
- cgi => 'MyOrg::Template::Plugin::CGI',
- foo => 'MyOrg::Template::Plugin::Foo',
- bar => 'MyOrg::Template::Plugin::Bar',
- },
- });
-
-The USE directive is used to create plugin objects and does so by
-calling the plugin() method on the current Template::Context object.
-If the plugin name is defined in the PLUGINS hash then the
-corresponding Perl module is loaded via require(). The context then
-calls the load() class method which should return the class name
-(default and general case) or a prototype object against which the
-new() method can be called to instantiate individual plugin objects.
-
-If the plugin name is not defined in the PLUGINS hash then the PLUGIN_BASE
-and/or LOAD_PERL options come into effect.
-
-
-
-
-
-=item PLUGIN_BASE
-
-If a plugin is not defined in the PLUGINS hash then the PLUGIN_BASE is used
-to attempt to construct a correct Perl module name which can be successfully
-loaded.
-
-The PLUGIN_BASE can be specified as a single value or as a reference
-to an array of multiple values. The default PLUGIN_BASE value,
-'Template::Plugin', is always added the the end of the PLUGIN_BASE
-list (a single value is first converted to a list). Each value should
-contain a Perl package name to which the requested plugin name is
-appended.
-
-example 1:
-
- my $template = Template->new({
- PLUGIN_BASE => 'MyOrg::Template::Plugin',
- });
-
- [% USE Foo %] # => MyOrg::Template::Plugin::Foo
- or Template::Plugin::Foo
-
-example 2:
-
- my $template = Template->new({
- PLUGIN_BASE => [ 'MyOrg::Template::Plugin',
- 'YourOrg::Template::Plugin' ],
- });
-
- [% USE Foo %] # => MyOrg::Template::Plugin::Foo
- or YourOrg::Template::Plugin::Foo
- or Template::Plugin::Foo
-
-
-
-
-
-
-=item LOAD_PERL
-
-If a plugin cannot be loaded using the PLUGINS or PLUGIN_BASE
-approaches then the provider can make a final attempt to load the
-module without prepending any prefix to the module path. This allows
-regular Perl modules (i.e. those that don't reside in the
-Template::Plugin or some other such namespace) to be loaded and used
-as plugins.
-
-By default, the LOAD_PERL option is set to 0 and no attempt will be made
-to load any Perl modules that aren't named explicitly in the PLUGINS
-hash or reside in a package as named by one of the PLUGIN_BASE
-components.
-
-Plugins loaded using the PLUGINS or PLUGIN_BASE receive a reference to
-the current context object as the first argument to the new()
-constructor. Modules loaded using LOAD_PERL are assumed to not
-conform to the plugin interface. They must provide a new() class
-method for instantiating objects but it will not receive a reference
-to the context as the first argument. Plugin modules should provide a
-load() class method (or inherit the default one from the
-Template::Plugin base class) which is called the first time the plugin
-is loaded. Regular Perl modules need not. In all other respects,
-regular Perl objects and Template Toolkit plugins are identical.
-
-If a particular Perl module does not conform to the common, but not
-unilateral, new() constructor convention then a simple plugin wrapper
-can be written to interface to it.
-
-
-
-
-=item FILTERS
-
-The FILTERS option can be used to specify custom filters which can
-then be used with the FILTER directive like any other. These are
-added to the standard filters which are available by default. Filters
-specified via this option will mask any standard filters of the same
-name.
-
-The FILTERS option should be specified as a reference to a hash array
-in which each key represents the name of a filter. The corresponding
-value should contain a reference to an array containing a subroutine
-reference and a flag which indicates if the filter is static (0) or
-dynamic (1). A filter may also be specified as a solitary subroutine
-reference and is assumed to be static.
-
- $template = Template->new({
- FILTERS => {
- 'sfilt1' => \&static_filter, # static
- 'sfilt2' => [ \&static_filter, 0 ], # same as above
- 'dfilt1' => [ \&dyanamic_filter_factory, 1 ],
- },
- });
-
-Additional filters can be specified at any time by calling the
-define_filter() method on the current Template::Context object.
-The method accepts a filter name, a reference to a filter
-subroutine and an optional flag to indicate if the filter is
-dynamic.
-
- my $context = $template->context();
- $context->define_filter('new_html', \&new_html);
- $context->define_filter('new_repeat', \&new_repeat, 1);
-
-Static filters are those where a single subroutine reference is used
-for all invocations of a particular filter. Filters that don't accept
-any configuration parameters (e.g. 'html') can be implemented
-statically. The subroutine reference is simply returned when that
-particular filter is requested. The subroutine is called to filter
-the output of a template block which is passed as the only argument.
-The subroutine should return the modified text.
-
- sub static_filter {
- my $text = shift;
- # do something to modify $text...
- return $text;
- }
-
-The following template fragment:
-
- [% FILTER sfilt1 %]
- Blah blah blah.
- [% END %]
-
-is approximately equivalent to:
-
- &static_filter("\nBlah blah blah.\n");
-
-Filters that can accept parameters (e.g. 'truncate') should be
-implemented dynamically. In this case, the subroutine is taken to be
-a filter 'factory' that is called to create a unique filter subroutine
-each time one is requested. A reference to the current
-Template::Context object is passed as the first parameter, followed by
-any additional parameters specified. The subroutine should return
-another subroutine reference (usually a closure) which implements the
-filter.
-
- sub dynamic_filter_factory {
- my ($context, @args) = @_;
-
- return sub {
- my $text = shift;
- # do something to modify $text...
- return $text;
- }
- }
-
-The following template fragment:
-
- [% FILTER dfilt1(123, 456) %]
- Blah blah blah
- [% END %]
-
-is approximately equivalent to:
-
- my $filter = &dynamic_filter_factory($context, 123, 456);
- &$filter("\nBlah blah blah.\n");
-
-See the FILTER directive for further examples.
-
-
-=back
-
-=head2 Compatibility, Customisation and Extension
-
-=over 4
-
-
-
-=item V1DOLLAR
-
-In version 1 of the Template Toolkit, an optional leading '$' could be placed
-on any template variable and would be silently ignored.
-
- # VERSION 1
- [% $foo %] === [% foo %]
- [% $hash.$key %] === [% hash.key %]
-
-To interpolate a variable value the '${' ... '}' construct was used.
-Typically, one would do this to index into a hash array when the key
-value was stored in a variable.
-
-example:
-
- my $vars = {
- users => {
- aba => { name => 'Alan Aardvark', ... },
- abw => { name => 'Andy Wardley', ... },
- ...
- },
- uid => 'aba',
- ...
- };
-
- $template->process('user/home.html', $vars)
- || die $template->error(), "\n";
-
-'user/home.html':
-
- [% user = users.${uid} %] # users.aba
- Name: [% user.name %] # Alan Aardvark
-
-This was inconsistent with double quoted strings and also the
-INTERPOLATE mode, where a leading '$' in text was enough to indicate a
-variable for interpolation, and the additional curly braces were used
-to delimit variable names where necessary. Note that this use is
-consistent with UNIX and Perl conventions, among others.
-
- # double quoted string interpolation
- [% name = "$title ${user.name}" %]
-
- # INTERPOLATE = 1
- <img src="$images/help.gif"></a>
- <img src="$images/${icon.next}.gif">
-
-For version 2, these inconsistencies have been removed and the syntax
-clarified. A leading '$' on a variable is now used exclusively to
-indicate that the variable name should be interpolated
-(e.g. subsituted for its value) before being used. The earlier example
-from version 1:
-
- # VERSION 1
- [% user = users.${uid} %]
- Name: [% user.name %]
-
-can now be simplified in version 2 as:
-
- # VERSION 2
- [% user = users.$uid %]
- Name: [% user.name %]
-
-The leading dollar is no longer ignored and has the same effect of
-interpolation as '${' ... '}' in version 1. The curly braces may
-still be used to explicitly scope the interpolated variable name
-where necessary.
-
-e.g.
-
- [% user = users.${me.id} %]
- Name: [% user.name %]
-
-The rule applies for all variables, both within directives and in
-plain text if processed with the INTERPOLATE option. This means that
-you should no longer (if you ever did) add a leading '$' to a variable
-inside a directive, unless you explicitly want it to be interpolated.
-
-One obvious side-effect is that any version 1 templates with variables
-using a leading '$' will no longer be processed as expected. Given
-the following variable definitions,
-
- [% foo = 'bar'
- bar = 'baz'
- %]
-
-version 1 would interpret the following as:
-
- # VERSION 1
- [% $foo %] => [% GET foo %] => bar
-
-whereas version 2 interprets it as:
-
- # VERSION 2
- [% $foo %] => [% GET $foo %] => [% GET bar %] => baz
-
-In version 1, the '$' is ignored and the value for the variable 'foo' is
-retrieved and printed. In version 2, the variable '$foo' is first interpolated
-to give the variable name 'bar' whose value is then retrieved and printed.
-
-The use of the optional '$' has never been strongly recommended, but
-to assist in backwards compatibility with any version 1 templates that
-may rely on this "feature", the V1DOLLAR option can be set to 1
-(default: 0) to revert the behaviour and have leading '$' characters
-ignored.
-
- my $template = Template->new({
- V1DOLLAR => 1,
- });
-
-
-
-
-=item LOAD_TEMPLATES
-
-The LOAD_TEMPLATE option can be used to provide a reference to a list
-of Template::Provider objects or sub-classes thereof which will take
-responsibility for loading and compiling templates.
-
- my $template = Template->new({
- LOAD_TEMPLATES => [
- MyOrg::Template::Provider->new({ ... }),
- Template::Provider->new({ ... }),
- ],
- });
-
-When a PROCESS, INCLUDE or WRAPPER directive is encountered, the named
-template may refer to a locally defined BLOCK or a file relative to
-the INCLUDE_PATH (or an absolute or relative path if the appropriate
-ABSOLUTE or RELATIVE options are set). If a BLOCK definition can't be
-found (see the Template::Context template() method for a discussion of
-BLOCK locality) then each of the LOAD_TEMPLATES provider objects is
-queried in turn via the fetch() method to see if it can supply the
-required template. Each provider can return a compiled template, an
-error, or decline to service the request in which case the
-responsibility is passed to the next provider. If none of the
-providers can service the request then a 'not found' error is
-returned. The same basic provider mechanism is also used for the
-INSERT directive but it bypasses any BLOCK definitions and doesn't
-attempt is to parse or process the contents of the template file.
-
-This is an implementation of the 'Chain of Responsibility'
-design pattern as described in
-"Design Patterns", Erich Gamma, Richard Helm, Ralph Johnson, John
-Vlissides), Addision-Wesley, ISBN 0-201-63361-2, page 223
-.
-
-If LOAD_TEMPLATES is undefined, a single default provider will be
-instantiated using the current configuration parameters. For example,
-the Template::Provider INCLUDE_PATH option can be specified in the Template configuration and will be correctly passed to the provider's
-constructor method.
-
- my $template = Template->new({
- INCLUDE_PATH => '/here:/there',
- });
-
-
-
-
-
-=item LOAD_PLUGINS
-
-The LOAD_PLUGINS options can be used to specify a list of provider
-objects (i.e. they implement the fetch() method) which are responsible
-for loading and instantiating template plugin objects. The
-Template::Content plugin() method queries each provider in turn in a
-"Chain of Responsibility" as per the template() and filter() methods.
-
- my $template = Template->new({
- LOAD_PLUGINS => [
- MyOrg::Template::Plugins->new({ ... }),
- Template::Plugins->new({ ... }),
- ],
- });
-
-By default, a single Template::Plugins object is created using the
-current configuration hash. Configuration items destined for the
-Template::Plugins constructor may be added to the Template
-constructor.
-
- my $template = Template->new({
- PLUGIN_BASE => 'MyOrg::Template::Plugins',
- LOAD_PERL => 1,
- });
-
-
-
-
-
-=item LOAD_FILTERS
-
-The LOAD_FILTERS option can be used to specify a list of provider
-objects (i.e. they implement the fetch() method) which are responsible
-for returning and/or creating filter subroutines. The
-Template::Context filter() method queries each provider in turn in a
-"Chain of Responsibility" as per the template() and plugin() methods.
-
- my $template = Template->new({
- LOAD_FILTERS => [
- MyTemplate::Filters->new(),
- Template::Filters->new(),
- ],
- });
-
-By default, a single Template::Filters object is created for the
-LOAD_FILTERS list.
-
-
-
-
-
-=item TOLERANT
-
-The TOLERANT flag is used by the various Template Toolkit provider
-modules (Template::Provider, Template::Plugins, Template::Filters) to
-control their behaviour when errors are encountered. By default, any
-errors are reported as such, with the request for the particular
-resource (template, plugin, filter) being denied and an exception
-raised. When the TOLERANT flag is set to any true values, errors will
-be silently ignored and the provider will instead return
-STATUS_DECLINED. This allows a subsequent provider to take
-responsibility for providing the resource, rather than failing the
-request outright. If all providers decline to service the request,
-either through tolerated failure or a genuine disinclination to
-comply, then a 'E<lt>resourceE<gt> not found' exception is raised.
-
-
-
-
-
-
-=item SERVICE
-
-A reference to a Template::Service object, or sub-class thereof, to which
-the Template module should delegate. If unspecified, a Template::Service
-object is automatically created using the current configuration hash.
-
- my $template = Template->new({
- SERVICE => MyOrg::Template::Service->new({ ... }),
- });
-
-
-
-
-
-=item CONTEXT
-
-A reference to a Template::Context object which is used to define a
-specific environment in which template are processed. A Template::Context
-object is passed as the only parameter to the Perl subroutines that
-represent "compiled" template documents. Template subroutines make
-callbacks into the context object to access Template Toolkit functionality,
-for example, to to INCLUDE or PROCESS another template (include() and
-process() methods, respectively), to USE a plugin (plugin()) or
-instantiate a filter (filter()) or to access the stash (stash()) which
-manages variable definitions via the get() and set() methods.
-
- my $template = Template->new({
- CONTEXT => MyOrg::Template::Context->new({ ... }),
- });
-
-
-
-=item STASH
-
-A reference to a Template::Stash object or sub-class which will take
-responsibility for managing template variables.
-
- my $stash = MyOrg::Template::Stash->new({ ... });
- my $template = Template->new({
- STASH => $stash,
- });
-
-If unspecified, a default stash object is created using the VARIABLES
-configuration item to initialise the stash variables. These may also
-be specified as the PRE_DEFINE option for backwards compatibility with
-version 1.
-
- my $template = Template->new({
- VARIABLES => {
- id => 'abw',
- name => 'Andy Wardley',
- },
- };
-
-
-
-
-
-=item PARSER
-
-The Template::Parser module implements a parser object for compiling
-templates into Perl code which can then be executed. A default object
-of this class is created automatically and then used by the
-Template::Provider whenever a template is loaded and requires
-compilation. The PARSER option can be used to provide a reference to
-an alternate parser object.
-
- my $template = Template->new({
- PARSER => MyOrg::Template::Parser->new({ ... }),
- });
-
-
-
-
-
-=item GRAMMAR
-
-The GRAMMAR configuration item can be used to specify an alternate
-grammar for the parser. This allows a modified or entirely new
-template language to be constructed and used by the Template Toolkit.
-
-Source templates are compiled to Perl code by the Template::Parser
-using the Template::Grammar (by default) to define the language
-structure and semantics. Compiled templates are thus inherently
-"compatible" with each other and there is nothing to prevent any
-number of different template languages being compiled and used within
-the same Template Toolkit processing environment (other than the usual
-time and memory constraints).
-
-The Template::Grammar file is constructed from a YACC like grammar
-(using Parse::YAPP) and a skeleton module template. These files are
-provided, along with a small script to rebuild the grammar, in the
-'parser' sub-directory of the distribution. You don't have to know or
-worry about these unless you want to hack on the template language or
-define your own variant. There is a README file in the same directory
-which provides some small guidance but it is assumed that you know
-what you're doing if you venture herein. If you grok LALR parsers,
-then you should find it comfortably familiar.
-
-By default, an instance of the default Template::Grammar will be
-created and used automatically if a GRAMMAR item isn't specified.
-
- use MyOrg::Template::Grammar;
-
- my $template = Template->new({
- GRAMMAR = MyOrg::Template::Grammar->new();
- });
-
-
-
-=back
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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:
diff --git a/lib/Template/Manual/Credits.pod b/lib/Template/Manual/Credits.pod
deleted file mode 100644
index 64999ac..0000000
--- a/lib/Template/Manual/Credits.pod
+++ /dev/null
@@ -1,188 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Manual::Credits
-#
-# DESCRIPTION
-# This section provides a brief history of the Template Toolkit and
-# details the primary author and numerous other people who have
-# contributed to it.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-#
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Manual::Credits - Author and contributor credits
-
-=head1 DESCRIPTION
-
-This section provides a brief history of the Template Toolkit and
-details the primary author and numerous other people who have
-contributed to it.
-
-=head1 HISTORY
-
-The Template Toolkit began its life as the Text::MetaText module,
-originally released to CPAN around 1996. This itself was the public
-manifestation of an earlier template processing system I developed
-while working at Peritas (now Knowledge Pool -
- http://www.knowledgepool.com/)
-
-Text::MetaText was the prototype - the one we always planned to throw
-away. It did the job well, showing us what worked and what didn't, what
-was good and what was bad, and gave us some ideas about what could be
-done better, given the chance to start again from scratch.
-
-Some time late in 1998 I threw away the prototype and started work on
-the Template Toolkit. By then I was working at Canon Research Centre
-Europe Ltd. (http://www.cre.canon.co.uk), involved in a general
-research programme related to web publishing and dynamic content
-generation. The first alpha release was in June 1999, followed by
-numerous more alpha and beta releases culminating in 1.00 being
-released on 2nd December 1999.
-
-A month or so later, work had begun on version 2.00. The plan was to
-get the template language relatively stable in version 1.00 and not
-worry too much about performance or other internal matters. Then,
-version 2.00 would follow to improve performance, clean up the
-architecture and fix anything that, with the benefit of hindsight, we
-thought could be improved. As it happens, me starting work on version
-2.00 coincided with Doug Steinwand sending me his parser variant which
-compiled templates to Perl code, giving a major performance boost.
-As well as the speedups, there are a whole host of significant new
-features in version 2.00, and a greatly improved internal architecture.
-Apart from a few minor "fixups" the template directives and language
-have remained the same as in version 1.00
-
-Version 2.00 was available in beta release form in July 2000, just
-in time for the 4th Perl Conference where version 1.00 was awarded
-"Best New Perl Module". After another extended beta release period,
-version 2.00 was released on 1st December 2000.
-
-
-
-
-=head1 CONTRIBUTORS
-
-Many people have contributed ideas, inspiration, fixes and features to
-the Template Toolkit. Their efforts continue to be very much appreciated.
-Please let me know if you think anyone is missing from this list.
-
- Chuck Adams <scrytch@uswest.net>
- Stephen Adkins <stephen.adkins@officevision.com>
- Ivan Adzhubey <iadzhubey@rics.bwh.harvard.edu>
- Mark Anderson <mda@discerning.com>
- Bradley Baetz <bbaetz@student.usyd.edu.au>
- Thierry-Michel Barral <kktos@electron-libre.com>
- Craig Barratt <craig@arraycomm.com>
- Stas Bekman <stas@stason.org>
- Tony Bowden <tony-tt@kasei.com>
- Neil Bowers <neilb@cre.canon.co.uk>
- Leon Brocard <acme@astray.com>
- Lyle Brooks <brooks@deseret.com>
- Dave Cash <dave@gnofn.org>
- Piers Cawley <pdcawley@bofh.org.uk>
- Darren Chamberlain <dlc@users.sourceforge.net>
- Eric Cholet <cholet@logilune.com>
- Dave Cross <dave@dave.org.uk>
- Chris Dean <ctdean@babycenter.com>
- Francois Desarmenien <desar@club-internet.fr>
- Horst Dumcke <hdumcke@cisco.com>
- Mark Fowler <mark@indicosoftware.com>
- Michael Fowler <michael@shoebox.net>
- Axel Gerstmair <anthill@web.de>
- Dylan William Hardison <dylanwh@tampabay.rr.com>
- Perrin Harkins <pharkins@etoys.com>
- Bryce Harrington <bryce@osdl.org>
- Dave Hodgkinson <daveh@davehodgkinson.com>
- Harald Joerg <Harald.Joerg@fujitsu-siemens.com>
- Colin Johnson <colin@knowledgepool.com>
- Vivek Khera <khera@kciLink.com>
- Rafael Kitover <caelum@debian.org>
- Ivan Kurmanov <http://www.ahinea.com>
- Hans von Lengerke <hans@lengerke.org>
- Jonas Liljegren <jonas@paranormal.se>
- Simon Luff <simon@sports.com>
- Paul Makepeace <Paul.Makepeace@realprogrammers.com>
- Gervase Markham <gerv@mozilla.org>
- Simon Matthews <sam@knowledgepool.com>
- Robert McArthur <mcarthur@dstc.edu.au>
- Craig McLane <mclanec@oxy.edu>
- Leslie Michael Orchard <deus_x@ninjacode.com>
- Eugene Miretskiy <eugene@invision.net>
- Tatsuhiko Miyagawa <miyagawa@edge.co.jp>
- Keith G. Murphy <keithmur@mindspring.com>
- Chris Nandor <pudge@pobox.com>
- Briac Pilpré <briac@pilpre.com>
- Martin Portman <mrp@cre.canon.co.uk>
- Slaven Rezic <slaven.rezic@berlin.de>
- Christian Schaffner <schaffner@eeh.ee.ethz.ch>
- Randal L. Schwartz <merlyn@stonehenge.com>
- Paul Sharpe <paul@miraclefish.com>
- Ville Skyttä <ville.skytta@iki.fi>
- Doug Steinwand <dsteinwand@etoys.com>
- Michael Stevens <michael@etla.org>
- Drew Taylor <dtaylor@vialogix.com>
- Swen Thuemmler <Swen.Thuemmler@paderlinx.de>
- Richard Tietjen <Richard_Tietjen@mcgraw-hill.com>
- Stathy G. Touloumis <stathy.touloumis@edventions.com>
- Jim Vaughan <jim@mrjim.com>
- Simon Wilcox <simonw@simonwilcox.co.uk>
- Chris Winters <cwinters@intes.net>
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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:
diff --git a/lib/Template/Manual/Directives.pod b/lib/Template/Manual/Directives.pod
deleted file mode 100644
index 3b8af3e..0000000
--- a/lib/Template/Manual/Directives.pod
+++ /dev/null
@@ -1,2179 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Manual::Directives
-#
-# DESCRIPTION
-# This section provides a reference of all Template Toolkit
-# directives, complete with examples of use.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-#
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Manual::Directives - Template directives
-
-=head1 DESCRIPTION
-
-This section provides a reference of all Template Toolkit directives,
-complete with examples of use.
-
-=head2 Accessing and Updating Template Variables
-
-=over 4
-
-
-=item GET
-
-The GET directive retrieves and outputs the value of the named variable.
-
- [% GET foo %]
-
-The GET keyword is optional. A variable can be specified in a directive
-tag by itself.
-
- [% foo %]
-
-The variable can have an unlimited number of elements, each separated
-by a dot '.'. Each element can have arguments specified within
-parentheses.
-
- [% foo %]
- [% bar.baz %]
- [% biz.baz(10) %]
- ...etc...
-
-See L<Template::Manual::Variables> for a full discussion on template
-variables.
-
-You can also specify expressions using the logical (and, or, not, ?:) and
-mathematic operators (+ - * / % mod div).
-
- [% template.title or default.title %]
-
- [% score * 100 %]
-
- [% order.nitems ? checkout(order.total) : 'no items' %]
-
-The 'div' operator returns the integer result of division. Both '%' and
-'mod' return the modulus (i.e. remainder) of division. 'mod' is provided
-as an alias for '%' for backwards compatibility with version 1.
-
- [% 15 / 6 %] # 2.5
- [% 15 div 6 %] # 2
- [% 15 mod 6 %] # 3
-
-
-
-=item CALL
-
-The CALL directive is similar to GET in evaluating the variable named,
-but doesn't print the result returned. This can be useful when a
-variable is bound to a sub-routine or object method which you want to
-call but aren't interested in the value returned.
-
- [% CALL dbi.disconnect %]
-
- [% CALL inc_page_counter(page_count) %]
-
-
-
-
-=item SET
-
-The SET directive allows you to assign new values to existing variables
-or create new temporary variables.
-
- [% SET title = 'Hello World' %]
-
-The SET keyword is also optional.
-
- [% title = 'Hello World' %]
-
-Variables may be assigned the values of other variables, unquoted
-numbers (digits), literal text ('single quotes') or quoted text
-("double quotes"). In the latter case, any variable references within
-the text will be interpolated when the string is evaluated. Variables
-should be prefixed by '$', using curly braces to explicitly scope
-the variable name where necessary.
-
- [% foo = 'Foo' %] # literal value 'Foo'
- [% bar = foo %] # value of variable 'foo'
- [% cost = '$100' %] # literal value '$100'
- [% item = "$bar: ${cost}.00" %] # value "Foo: $100.00"
-
-Multiple variables may be assigned in the same directive and are
-evaluated in the order specified. Thus, the above could have been
-written:
-
- [% foo = 'Foo'
- bar = foo
- cost = '$100'
- item = "$bar: ${cost}.00"
- %]
-
-Simple expressions can also be used, as per GET.
-
- [% ten = 10
- twenty = 20
- thirty = twenty + ten
- forty = 2 * twenty
- fifty = 100 div 2
- six = twenty mod 7
- %]
-
-You can concatenate strings together using the ' _ ' operator. In Perl 5,
-the '.' is used for string concatenation, but in Perl 6, as in the Template
-Toolkit, the '.' will be used as the method calling operator and ' _ ' will
-be used for string concatenation. Note that the operator must be
-specified with surrounding whitespace which, as Larry says, is construed as
-a feature:
-
- [% copyright = '(C) Copyright' _ year _ ' ' _ author %]
-
-You can, of course, achieve a similar effect with double quoted string
-interpolation.
-
- [% copyright = "(C) Copyright $year $author" %]
-
-
-
-
-
-=item DEFAULT
-
-The DEFAULT directive is similar to SET but only updates variables
-that are currently undefined or have no "true" value (in the Perl
-sense).
-
- [% DEFAULT
- name = 'John Doe'
- id = 'jdoe'
- %]
-
-This can be particularly useful in common template components to
-ensure that some sensible default are provided for otherwise
-undefined variables.
-
- [% DEFAULT
- title = 'Hello World'
- bgcol = '#ffffff'
- %]
- <html>
- <head>
- <title>[% title %]</title>
- </head>
-
- <body bgcolor="[% bgcol %]">
-
-
-=back
-
-=head2 Processing Other Template Files and Blocks
-
-=over 4
-
-
-=item INSERT
-
-The INSERT directive is used to insert the contents of an external file
-at the current position.
-
- [% INSERT myfile %]
-
-No attempt to parse or process the file is made. The contents,
-possibly including any embedded template directives, are inserted
-intact.
-
-The filename specified should be relative to one of the INCLUDE_PATH
-directories. Absolute (i.e. starting with C</>) and relative
-(i.e. starting with C<.>) filenames may be used if the ABSOLUTE and
-RELATIVE options are set, respectively. Both these options are
-disabled by default.
-
- my $template = Template->new({
- INCLUDE_PATH => '/here:/there',
- });
-
- $template->process('myfile');
-
-'myfile':
-
- [% INSERT foo %] # looks for /here/foo then /there/foo
- [% INSERT /etc/passwd %] # file error: ABSOLUTE not set
- [% INSERT ../secret %] # file error: RELATIVE not set
-
-For convenience, the filename does not need to be quoted as long as it
-contains only alphanumeric characters, underscores, dots or forward
-slashes. Names containing any other characters should be quoted.
-
- [% INSERT misc/legalese.txt %]
- [% INSERT 'dos98/Program Files/stupid' %]
-
-To evaluate a variable to specify a filename, you should explicitly
-prefix it with a '$' or use double-quoted string interpolation.
-
- [% language = 'en'
- legalese = 'misc/legalese.txt'
- %]
-
- [% INSERT $legalese %] # 'misc/legalese.txt'
- [% INSERT "$language/$legalese" %] # 'en/misc/legalese.txt'
-
-Multiple files can be specified using '+' as a delimiter. All files
-should be unquoted names or quoted strings. Any variables should be
-interpolated into double-quoted strings.
-
- [% INSERT legalese.txt + warning.txt %]
- [% INSERT "$legalese" + warning.txt %] # requires quoting
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-=item INCLUDE
-
-The INCLUDE directive is used to process and include the output of
-another template file or block.
-
- [% INCLUDE header %]
-
-If a BLOCK of the specified name is defined in the same file, or in a file
-from which the current template has been called (i.e. a parent template)
-then it will be used in preference to any file of the same name.
-
- [% INCLUDE table %] # uses BLOCK defined below
-
- [% BLOCK table %]
- <table>
- ...
- </table>
- [% END %]
-
-If a BLOCK definition is not currently visible then the template name
-should be a file relative to one of the INCLUDE_PATH directories, or
-an absolute or relative file name if the ABSOLUTE/RELATIVE options are
-appropriately enabled. The INCLUDE directive automatically quotes the
-filename specified, as per INSERT described above. When a variable
-contains the name of the template for the INCLUDE directive, it should
-be explicitly prefixed by '$' or double-quoted
-
- [% myheader = 'my/misc/header' %]
- [% INCLUDE myheader %] # 'myheader'
- [% INCLUDE $myheader %] # 'my/misc/header'
- [% INCLUDE "$myheader" %] # 'my/misc/header'
-
-Any template directives embedded within the file will be processed
-accordingly. All variables currently defined will be visible and
-accessible from within the included template.
-
- [% title = 'Hello World' %]
- [% INCLUDE header %]
- <body>
- ...
-
-'header':
-
- <html>
- <title>[% title %]</title>
-
-output:
-
- <html>
- <title>Hello World</title>
- <body>
- ...
-
-Local variable definitions may be specified after the template name,
-temporarily masking any existing variables. Insignificant whitespace
-is ignored within directives so you can add variable definitions on the
-same line, the next line or split across several line with comments
-interspersed, if you prefer.
-
- [% INCLUDE table %]
-
- [% INCLUDE table title="Active Projects" %]
-
- [% INCLUDE table
- title = "Active Projects"
- bgcolor = "#80ff00" # chartreuse
- border = 2
- %]
-
-The INCLUDE directive localises (i.e. copies) all variables before
-processing the template. Any changes made within the included
-template will not affect variables in the including template.
-
- [% foo = 10 %]
-
- foo is originally [% foo %]
- [% INCLUDE bar %]
- foo is still [% foo %]
-
- [% BLOCK bar %]
- foo was [% foo %]
- [% foo = 20 %]
- foo is now [% foo %]
- [% END %]
-
-output:
- foo is originally 10
- foo was 10
- foo is now 20
- foo is still 10
-
-Technical Note: the localisation of the stash (that is, the process by
-which variables are copied before an INCLUDE to prevent being
-overwritten) is only skin deep. The top-level variable namespace
-(hash) is copied, but no attempt is made to perform a deep-copy of
-other structures (hashes, arrays, objects, etc.) Therefore, a 'foo'
-variable referencing a hash will be copied to create a new 'foo'
-variable but which points to the same hash array. Thus, if you update
-compound variables (e.g. foo.bar) then you will change the original
-copy, regardless of any stash localisation. If you're not worried
-about preserving variable values, or you trust the templates you're
-including then you might prefer to use the PROCESS directive which is
-faster by virtue of not performing any localisation.
-
-From version 2.04 onwards, you can specify dotted variables as "local"
-variables to an INCLUDE directive. However, be aware that because of
-the localisation issues explained above (if you skipped the previous
-Technical Note above then you might want to go back and read it or
-skip this section too), the variables might not actualy be "local".
-If the first element of the variable name already references a hash
-array then the variable update will affect the original variable.
-
- [% foo = {
- bar = 'Baz'
- }
- %]
-
- [% INCLUDE somefile foo.bar='Boz' %]
-
- [% foo.bar %] # Boz
-
-This behaviour can be a little unpredictable (and may well be improved
-upon in a future version). If you know what you're doing with it and
-you're sure that the variables in question are defined (nor not) as you
-expect them to be, then you can rely on this feature to implement some
-powerful "global" data sharing techniques. Otherwise, you might prefer
-to steer well clear and always pass simple (undotted) variables as
-parameters to INCLUDE and other similar directives.
-
-If you want to process several templates in one go then you can
-specify each of their names (quoted or unquoted names only, no unquoted
-'$variables') joined together by '+'. The INCLUDE directive
-will then process them in order.
-
- [% INCLUDE html/header + "site/$header" + site/menu
- title = "My Groovy Web Site"
- %]
-
-The variable stash is localised once and then the templates specified
-are processed in order, all within that same variable context. This
-makes it slightly faster than specifying several separate INCLUDE
-directives (because you only clone the variable stash once instead of
-n times), but not quite as "safe" because any variable changes in the
-first file will be visible in the second, third and so on. This
-might be what you want, of course, but then again, it might not.
-
-
-
-=item PROCESS
-
-The PROCESS directive is similar to INCLUDE but does not perform any
-localisation of variables before processing the template. Any changes
-made to variables within the included template will be visible in the
-including template.
-
- [% foo = 10 %]
-
- foo is [% foo %]
- [% PROCESS bar %]
- foo is [% foo %]
-
- [% BLOCK bar %]
- [% foo = 20 %]
- changed foo to [% foo %]
- [% END %]
-
-output:
-
- foo is 10
- changed foo to 20
- foo is 20
-
-Parameters may be specified in the PROCESS directive, but these too will
-become visible changes to current variable values.
-
- [% foo = 10 %]
- foo is [% foo %]
- [% PROCESS bar
- foo = 20
- %]
- foo is [% foo %]
-
- [% BLOCK bar %]
- this is bar, foo is [% foo %]
- [% END %]
-
-output:
-
- foo is 10
- this is bar, foo is 20
- foo is 20
-
-The PROCESS directive is slightly faster than INCLUDE because it
-avoids the need to localise (i.e. copy) the variable stash before
-processing the template. As with INSERT and INCLUDE, the first
-parameter does not need to be quoted as long as it contains only
-alphanumeric characters, underscores, periods or forward slashes.
-A '$' prefix can be used to explicitly indicate a variable which
-should be interpolated to provide the template name:
-
- [% myheader = 'my/misc/header' %]
- [% PROCESS myheader %] # 'myheader'
- [% PROCESS $myheader %] # 'my/misc/header'
-
-As with INCLUDE, multiple templates can be specified, delimited by
-'+', and are processed in order.
-
- [% PROCESS html/header + my/header %]
-
-
-
-
-
-=item WRAPPER
-
-It's not unusual to find yourself adding common headers and footers to
-pages or sub-sections within a page. Something like this:
-
- [% INCLUDE section/header
- title = 'Quantum Mechanics'
- %]
- Quantum mechanics is a very interesting subject wish
- should prove easy for the layman to fully comprehend.
- [% INCLUDE section/footer %]
-
- [% INCLUDE section/header
- title = 'Desktop Nuclear Fusion for under $50'
- %]
- This describes a simple device which generates significant
- sustainable electrical power from common tap water by process
- of nuclear fusion.
- [% INCLUDE section/footer %]
-
-The individual template components being included might look like these:
-
-section/header:
-
- <p>
- <h2>[% title %]</h2>
-
-section/footer:
-
- </p>
-
-The WRAPPER directive provides a way of simplifying this a little. It
-encloses a block up to a matching END directive, which is first
-processed to generate some output. This is then passed to the named
-template file or BLOCK as the 'content' variable.
-
- [% WRAPPER section
- title = 'Quantum Mechanics'
- %]
- Quantum mechanics is a very interesting subject wish
- should prove easy for the layman to fully comprehend.
- [% END %]
-
- [% WRAPPER section
- title = 'Desktop Nuclear Fusion for under $50'
- %]
- This describes a simple device which generates significant
- sustainable electrical power from common tap water by process
- of nuclear fusion.
- [% END %]
-
-The single 'section' template can then be defined as:
-
- <p>
- <h2>[% title %]</h2>
- [% content %]
- </p>
-
-Like other block directives, it can be used in side-effect notation:
-
- [% INSERT legalese.txt WRAPPER big_bold_table %]
-
-It's also possible to specify multiple templates to a WRAPPER directive.
-The specification order indicates outermost to innermost wrapper templates.
-For example, given the following template block definitions:
-
- [% BLOCK bold %]<b>[% content %]</b>[% END %]
- [% BLOCK italic %]<i>[% content %]</i>[% END %]
-
-the directive
-
- [% WRAPPER bold+italic %]Hello World[% END %]
-
-would generate the following output:
-
- <b><i>Hello World</i></b>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-=item BLOCK
-
-The BLOCK ... END construct can be used to define template component
-blocks which can be processed with the INCLUDE, PROCESS and WRAPPER
-directives.
-
- [% BLOCK tabrow %]
- <tr><td>[% name %]<td><td>[% email %]</td></tr>
- [% END %]
-
- <table>
- [% PROCESS tabrow name='Fred' email='fred@nowhere.com' %]
- [% PROCESS tabrow name='Alan' email='alan@nowhere.com' %]
- </table>
-
-A BLOCK definition can be used before it is defined, as long as the
-definition resides in the same file. The block definition itself does
-not generate any output.
-
- [% PROCESS tmpblk %]
-
- [% BLOCK tmpblk %] This is OK [% END %]
-
-You can use an anonymous BLOCK to capture the output of a template
-fragment.
-
- [% julius = BLOCK %]
- And Caesar's spirit, ranging for revenge,
- With Ate by his side come hot from hell,
- Shall in these confines with a monarch's voice
- Cry 'Havoc', and let slip the dogs of war;
- That this foul deed shall smell above the earth
- With carrion men, groaning for burial.
- [% END %]
-
-Like a named block, it can contain any other template directives which
-are processed when the block is defined. The output generated by the
-block is then assigned to the variable 'julius'.
-
-Anonymous BLOCKs can also be used to define block macros. The
-enclosing block is processed each time the macro is called.
-
- [% MACRO locate BLOCK %]
- The [% animal %] sat on the [% place %].
- [% END %]
-
- [% locate(animal='cat', place='mat') %] # The cat sat on the mat
- [% locate(animal='dog', place='log') %] # The dog sat on the log
-
-
-
-=back
-
-=head2 Conditional Processing
-
-=over 4
-
-
-=item IF / UNLESS / ELSIF / ELSE
-
-The IF and UNLESS directives can be used to process or ignore a
-block based on some run-time condition.
-
- [% IF frames %]
- [% INCLUDE frameset %]
- [% END %]
-
- [% UNLESS text_mode %]
- [% INCLUDE biglogo %]
- [% END %]
-
-Multiple conditions may be joined with ELSIF and/or ELSE blocks.
-
- [% IF age < 10 %]
- Hello [% name %], does your mother know you're
- using her AOL account?
- [% ELSIF age < 18 %]
- Sorry, you're not old enough to enter
- (and too dumb to lie about your age)
- [% ELSE %]
- Welcome [% name %].
- [% END %]
-
-The following conditional and boolean operators may be used:
-
- == != < <= > >= && || ! and or not
-
-Note that C<and>, C<or> and C<not> are also provided as aliases for
-C<&&>, C<||> and C<!>, respectively.
-
-Conditions may be arbitrarily complex and are evaluated with the same
-precedence as in Perl. Parenthesis may be used to explicitly
-determine evaluation order.
-
- # ridiculously contrived complex example
- [% IF (name == 'admin' || uid <= 0) && mode == 'debug' %]
- I'm confused.
- [% ELSIF more > less %]
- That's more or less correct.
- [% END %]
-
-
-
-
-
-
-=item SWITCH / CASE
-
-The SWITCH / CASE construct can be used to perform a multi-way
-conditional test. The SWITCH directive expects an expression which is
-first evaluated and then compared against each CASE statement in turn.
-Each CASE directive should contain a single value or a list of values
-which should match. CASE may also be left blank or written as [% CASE
-DEFAULT %] to specify a default match. Only one CASE matches, there
-is no drop-through between CASE statements.
-
- [% SWITCH myvar %]
- [% CASE value1 %]
- ...
- [% CASE [ value2 value3 ] %] # multiple values
- ...
- [% CASE myhash.keys %] # ditto
- ...
- [% CASE %] # default
- ...
- [% END %]
-
-
-
-
-=back
-
-=head2 Loop Processing
-
-=over 4
-
-
-=item FOREACH
-
-The FOREACH directive will iterate through the items in a list, processing
-the enclosed block for each one.
-
- my $vars = {
- foo => 'Foo',
- items => [ 'one', 'two', 'three' ],
- };
-
-template:
-
- Things:
- [% FOREACH thing = [ foo 'Bar' "$foo Baz" ] %]
- * [% thing %]
- [% END %]
-
- Items:
- [% FOREACH i = items %]
- * [% i %]
- [% END %]
-
- Stuff:
- [% stuff = [ foo "$foo Bar" ] %]
- [% FOREACH s = stuff %]
- * [% s %]
- [% END %]
-
-output:
-
- Things:
- * Foo
- * Bar
- * Foo Baz
-
- Items:
- * one
- * two
- * three
-
- Stuff:
- * Foo
- * Foo Bar
-
-You can use also use 'IN' instead of '=' if you prefer.
-
- [% FOREACH crook IN government %]
-
-When the FOREACH directive is used without specifying a target variable,
-any iterated values which are hash references will be automatically
-imported.
-
- [% userlist = [
- { id => 'tom', name => 'Thomas' },
- { id => 'dick', name => 'Richard' },
- { id => 'larry', name => 'Lawrence' },
- ]
- %]
-
- [% FOREACH user IN userlist %]
- [% user.id %] [% user.name %]
- [% END %]
-
-short form:
-
- [% FOREACH userlist %]
- [% id %] [% name %]
- [% END %]
-
-Note that this particular usage creates a localised variable context
-to prevent the imported hash keys from overwriting any existing
-variables. The imported definitions and any other variables defined
-in such a FOREACH loop will be lost at the end of the loop, when the
-previous context and variable values are restored.
-
-However, under normal operation, the loop variable remains in scope
-after the FOREACH loop has ended (caveat: overwriting any variable
-previously in scope). This is useful as the loop variable is secretly
-an iterator object (see below) and can be used to analyse the last
-entry processed by the loop.
-
-The FOREACH directive can also be used to iterate through the entries
-in a hash array. Each entry in the hash is returned in sorted order
-(based on the key) as a hash array containing 'key' and 'value' items.
-
- [% users = {
- tom => 'Thomas',
- dick => 'Richard',
- larry => 'Lawrence',
- }
- %]
-
- [% FOREACH u IN users %]
- * [% u.key %] : [% u.value %]
- [% END %]
-
-Output:
-
- * dick : Richard
- * larry : Lawrence
- * tom : Thomas
-
-The NEXT directive starts the next iteration in the FOREACH loop.
-
- [% FOREACH user IN userlist %]
- [% NEXT IF user.isguest %]
- Name: [% user.name %] Email: [% user.email %]
- [% END %]
-
-The LAST directive can be used to prematurely exit the loop. BREAK is
-also provided as an alias for LAST.
-
- [% FOREACH match IN results.nsort('score').reverse %]
- [% LAST IF match.score < 50 %]
- [% match.score %] : [% match.url %]
- [% END %]
-
-The FOREACH directive is implemented using the Template::Iterator
-module. A reference to the iterator object for a FOREACH directive is
-implicitly available in the 'loop' variable. The following methods
-can be called on the 'loop' iterator.
-
- size() number of elements in the list
- max() index number of last element (size - 1)
- index() index of current iteration from 0 to max()
- count() iteration counter from 1 to size() (i.e. index() + 1)
- first() true if the current iteration is the first
- last() true if the current iteration is the last
- prev() return the previous item in the list
- next() return the next item in the list
-
-See L<Template::Iterator> for further details.
-
-Example:
-
- [% FOREACH item IN [ 'foo', 'bar', 'baz' ] -%]
- [%- "<ul>\n" IF loop.first %]
- <li>[% loop.count %]/[% loop.size %]: [% item %]
- [%- "</ul>\n" IF loop.last %]
- [% END %]
-
-Output:
-
- <ul>
- <li>1/3: foo
- <li>2/3: bar
- <li>3/3: baz
- </ul>
-
-Note that the number() method is supported as an alias for count() for
-backwards compatibility but may be deprecated in some future version.
-
-Nested loops will work as expected, with the 'loop' variable correctly
-referencing the innermost loop and being restored to any previous
-value (i.e. an outer loop) at the end of the loop.
-
- [% FOREACH group IN grouplist;
- # loop => group iterator
- "Groups:\n" IF loop.first;
-
- FOREACH user IN group.userlist;
- # loop => user iterator
- "$loop.count: $user.name\n";
- END;
-
- # loop => group iterator
- "End of Groups\n" IF loop.last;
- END
- %]
-
-The 'iterator' plugin can also be used to explicitly create an
-iterator object. This can be useful within nested loops where you
-need to keep a reference to the outer iterator within the inner loop.
-The iterator plugin effectively allows you to create an iterator by a
-name other than 'loop'. See Template::Plugin::Iterator for further
-details.
-
- [% USE giter = iterator(grouplist) %]
-
- [% FOREACH group IN giter %]
- [% FOREACH user IN group.userlist %]
- user #[% loop.count %] in
- group [% giter.count %] is
- named [% user.name %]
- [% END %]
- [% END %]
-
-
-
-
-=item WHILE
-
-The WHILE directive can be used to repeatedly process a template block
-while a conditional expression evaluates true. The expression may
-be arbitrarily complex as per IF / UNLESS.
-
- [% WHILE total < 100 %]
- ...
- [% total = calculate_new_total %]
- [% END %]
-
-An assignment can be enclosed in parenthesis to evaluate the assigned
-value.
-
- [% WHILE (user = get_next_user_record) %]
- [% user.name %]
- [% END %]
-
-The NEXT directive can be used to start the next iteration of a
-WHILE loop and BREAK can be used to exit the loop, both as per FOREACH.
-
-The Template Toolkit uses a failsafe counter to prevent runaway WHILE
-loops which would otherwise never terminate. If the loop exceeds 1000
-iterations then an 'undef' exception will be thrown, reporting the
-error:
-
- WHILE loop terminated (> 1000 iterations)
-
-The $Template::Directive::WHILE_MAX variable controls this behaviour
-and can be set to a higher value if necessary.
-
-
-=back
-
-=head2 Filters, Plugins, Macros and Perl
-
-=over 4
-
-
-=item FILTER
-
-The FILTER directive can be used to post-process the output of a
-block. A number of standard filters are provided with the Template
-Toolkit. The 'html' filter, for example, escapes the 'E<lt>', 'E<gt>'
-and '&' characters to prevent them from being interpreted as HTML tags
-or entity reference markers.
-
- [% FILTER html %]
- HTML text may have < and > characters embedded
- which you want converted to the correct HTML entities.
- [% END %]
-
-output:
-
- HTML text may have &lt; and &gt; characters embedded
- which you want converted to the correct HTML entities.
-
-The FILTER directive can also follow various other non-block directives.
-For example:
-
- [% INCLUDE mytext FILTER html %]
-
-The '|' character can also be used as an alias for 'FILTER'.
-
- [% INCLUDE mytext | html %]
-
-Multiple filters can be chained together and will be called in sequence.
-
- [% INCLUDE mytext FILTER html FILTER html_para %]
-
-or
-
- [% INCLUDE mytext | html | html_para %]
-
-Filters come in two flavours, known as 'static' or 'dynamic'. A
-static filter is a simple subroutine which accepts a text string as
-the only argument and returns the modified text. The 'html' filter is
-an example of a static filter, implemented as:
-
- sub html_filter {
- my $text = shift;
- for ($text) {
- s/&/&amp;/g;
- s/</&lt;/g;
- s/>/&gt;/g;
- }
- return $text;
- }
-
-Dynamic filters can accept arguments which are specified when the filter
-is called from a template. The 'repeat' filter is such an example,
-accepting a numerical argument which specifies the number of times
-that the input text should be repeated.
-
- [% FILTER repeat(3) %]blah [% END %]
-
-output:
-
- blah blah blah
-
-These are implemented as filter 'factories'. The factory subroutine
-is passed a reference to the current Template::Context object along
-with any additional arguments specified. It should then return a
-subroutine reference (e.g. a closure) which implements the filter.
-The 'repeat' filter factory is implemented like this:
-
- sub repeat_filter_factory {
- my ($context, $iter) = @_;
- $iter = 1 unless defined $iter;
-
- return sub {
- my $text = shift;
- $text = '' unless defined $text;
- return join('\n', $text) x $iter;
- }
- }
-
-The FILTERS option, described in L<Template::Manual::Config>, allows
-custom filters to be defined when a Template object is instantiated.
-The Template::Context define_filter() method allows further filters
-to be defined at any time.
-
-When using a filter, it is possible to assign an alias to it for
-further use. This is most useful for dynamic filters that you want
-to re-use with the same configuration.
-
- [% FILTER echo = repeat(2) %]
- Is there anybody out there?
- [% END %]
-
- [% FILTER echo %]
- Mother, should I build a wall?
- [% END %]
-
-Output:
-
- Is there anybody out there?
- Is there anybody out there?
-
- Mother, should I build a wall?
- Mother, should I build a wall?
-
-The FILTER directive automatically quotes the name of the filter. As
-with INCLUDE et al, you can use a variable to provide the name of the
-filter, prefixed by '$'.
-
- [% myfilter = 'html' %]
- [% FILTER $myfilter %] # same as [% FILTER html %]
- ...
- [% END %]
-
-A template variable can also be used to define a static filter
-subroutine. However, the Template Toolkit will automatically call any
-subroutine bound to a variable and use the value returned. Thus, the
-above example could be implemented as:
-
- my $vars = {
- myfilter => sub { return 'html' },
- };
-
-template:
-
- [% FILTER $myfilter %] # same as [% FILTER html %]
- ...
- [% END %]
-
-To define a template variable that evaluates to a subroutine reference
-that can be used by the FILTER directive, you should create a
-subroutine that, when called automatically by the Template Toolkit,
-returns another subroutine reference which can then be used to perform
-the filter operation. Note that only static filters can be
-implemented in this way.
-
- my $vars = {
- myfilter => sub { \&my_filter_sub },
- };
-
- sub my_filter_sub {
- my $text = shift;
- # do something
- return $text;
- }
-
-template:
-
- [% FILTER $myfilter %]
- ...
- [% END %]
-
-Alternately, you can bless a subroutine reference into a class (any
-class will do) to fool the Template Toolkit into thinking it's an
-object rather than a subroutine. This will then bypass the automatic
-"call-a-subroutine-to-return-a-value" magic.
-
- my $vars = {
- myfilter => bless(\&my_filter_sub, 'anything_you_like'),
- };
-
-template:
-
- [% FILTER $myfilter %]
- ...
- [% END %]
-
-Filters bound to template variables remain local to the variable
-context in which they are defined. That is, if you define a filter in
-a PERL block within a template that is loaded via INCLUDE, then the
-filter definition will only exist until the end of that template when
-the stash is delocalised, restoring the previous variable state. If
-you want to define a filter which persists for the lifetime of the
-processor, or define additional dynamic filter factories, then you can
-call the define_filter() method on the current Template::Context
-object.
-
-See L<Template::Manual::Filters> for a complete list of available filters,
-their descriptions and examples of use.
-
-
-
-
-
-
-=item USE
-
-The USE directive can be used to load and initialise "plugin"
-extension modules.
-
- [% USE myplugin %]
-
-A plugin is a regular Perl module that conforms to a particular
-object-oriented interface, allowing it to be loaded into and used
-automatically by the Template Toolkit. For details of this interface
-and information on writing plugins, consult L<Template::Plugin>.
-
-The plugin name is case-sensitive and will be appended to the
-PLUGIN_BASE value (default: 'Template::Plugin') to construct a full
-module name. Any periods, '.', in the name will be converted to '::'.
-
- [% USE MyPlugin %] # => Template::Plugin::MyPlugin
- [% USE Foo.Bar %] # => Template::Plugin::Foo::Bar
-
-Various standard plugins are included with the Template Toolkit (see
-below and L<Template::Manual::Plugins>). These can be specified in lower
-case and are mapped to the appropriate name.
-
- [% USE cgi %] # => Template::Plugin::CGI
- [% USE table %] # => Template::Plugin::Table
-
-Any additional parameters supplied in parenthesis after the plugin
-name will be also be passed to the new() constructor. A reference to
-the current Template::Context object is always passed as the first
-parameter.
-
- [% USE MyPlugin('foo', 123) %]
-
-equivalent to:
-
- Template::Plugin::MyPlugin->new($context, 'foo', 123);
-
-Named parameters may also be specified. These are collated into a
-hash which is passed by reference as the last parameter to the
-constructor, as per the general code calling interface.
-
- [% USE url('/cgi-bin/foo', mode='submit', debug=1) %]
-
-equivalent to:
-
- Template::Plugin::URL->new($context, '/cgi-bin/foo'
- { mode => 'submit', debug => 1 });
-
-The plugin may represent any data type; a simple variable, hash, list or
-code reference, but in the general case it will be an object reference.
-Methods can be called on the object (or the relevant members of the
-specific data type) in the usual way:
-
- [% USE table(mydata, rows=3) %]
-
- [% FOREACH row = table.rows %]
- <tr>
- [% FOREACH item = row %]
- <td>[% item %]</td>
- [% END %]
- </tr>
- [% END %]
-
-An alternative name may be provided for the plugin by which it can be
-referenced:
-
- [% USE scores = table(myscores, cols=5) %]
-
- [% FOREACH row = scores.rows %]
- ...
- [% END %]
-
-You can use this approach to create multiple plugin objects with
-different configurations. This example shows how the 'format' plugin
-is used to create sub-routines bound to variables for formatting text
-as per printf().
-
- [% USE bold = format('<b>%s</b>') %]
- [% USE ital = format('<i>%s</i>') %]
-
- [% bold('This is bold') %]
- [% ital('This is italic') %]
-
-Output:
-
- <b>This is bold</b>
- <i>This is italic</i>
-
-This next example shows how the URL plugin can be used to build
-dynamic URLs from a base part and optional query parameters.
-
- [% USE mycgi = URL('/cgi-bin/foo.pl', debug=1) %]
- <a href="[% mycgi %]">...
- <a href="[% mycgi(mode='submit') %]"...
-
-Output:
-
- <a href="/cgi-bin/foo.pl?debug=1">...
- <a href="/cgi-bin/foo.pl?mode=submit&debug=1">...
-
-The CGI plugin is an example of one which delegates to another Perl
-module. In this this case, it is to Lincoln Stein's CGI.pm module.
-All of the methods provided by CGI.pm are available via the plugin.
-
- [% USE CGI %]
-
- [% CGI.start_form %]
-
- [% CGI.checkbox_group(name => 'colours',
- values => [ 'red' 'green' 'blue' ])
- %]
-
- [% CGI.popup_menu(name => 'items',
- values => [ 'foo' 'bar' 'baz' ])
- %]
-
- [% CGI.end_form %]
-
-Simon Matthews has written the DBI plugin which provides an interface
-to Tim Bunce's DBI module (available from CPAN). Here's a short
-example:
-
- [% USE DBI('DBI:mSQL:mydbname') %]
-
- [% FOREACH user = DBI.query('SELECT * FROM users') %]
- [% user.id %] [% user.name %] [% user.etc.etc %]
- [% END %]
-
-See L<Template::Manual::Plugins> for more information on the plugins
-distributed with the toolkit or available from CPAN.
-
-The LOAD_PERL option (disabled by default) provides a further way by
-which external Perl modules may be loaded. If a regular Perl module
-(i.e. not a Template::Plugin::* or other module relative to some
-PLUGIN_BASE) supports an object-oriented interface and a new()
-constructor then it can be loaded and instantiated automatically. The
-following trivial example shows how the IO::File module might be used.
-
- [% USE file = IO.File('/tmp/mydata') %]
-
- [% WHILE (line = file.getline) %]
- <!-- [% line %] -->
- [% END %]
-
-
-
-
-
-
-=item MACRO
-
-The MACRO directive allows you to define a directive or directive block
-which is then evaluated each time the macro is called.
-
- [% MACRO header INCLUDE header %]
-
-Calling the macro as:
-
- [% header %]
-
-is then equivalent to:
-
- [% INCLUDE header %]
-
-Macros can be passed named parameters when called. These values remain
-local to the macro.
-
- [% header(title='Hello World') %]
-
-equivalent to:
-
- [% INCLUDE header title='Hello World' %]
-
-A MACRO definition may include parameter names. Values passed to the
-macros are then mapped to these local variables. Other named parameters
-may follow these.
-
- [% MACRO header(title) INCLUDE header %]
-
- [% header('Hello World') %]
- [% header('Hello World', bgcol='#123456') %]
-
-equivalent to:
-
- [% INCLUDE header title='Hello World' %]
- [% INCLUDE header title='Hello World' bgcol='#123456' %]
-
-Here's another example, defining a macro for display numbers
-in comma-delimited groups of 3, using the chunk and join virtual
-method.
-
- [% MACRO number(n) GET n.chunk(-3).join(',') %]
-
- [% number(1234567) %] # 1,234,567
-
-A MACRO may precede any directive and must conform to the structure
-of the directive.
-
- [% MACRO header IF frames %]
- [% INCLUDE frames/header %]
- [% ELSE %]
- [% INCLUDE header %]
- [% END %]
-
- [% header %]
-
-A MACRO may also be defined as an anonymous BLOCK. The block will be
-evaluated each time the macro is called.
-
- [% MACRO header BLOCK %]
- ...content...
- [% END %]
-
- [% header %]
-
-If you've got the EVAL_PERL option set, then you can even define a
-MACRO as a PERL block (see below):
-
- [% MACRO triple(n) PERL %]
- my $n = $stash->get('n');
- print $n * 3;
- [% END -%]
-
-
-
-
-
-
-
-=item PERL
-
-(for the advanced reader)
-
-The PERL directive is used to mark the start of a block which contains
-Perl code for evaluation. The EVAL_PERL option must be enabled for Perl
-code to be evaluated or a 'perl' exception will be thrown with the
-message 'EVAL_PERL not set'.
-
-Perl code is evaluated in the Template::Perl package. The $context
-package variable contains a reference to the current Template::Context
-object. This can be used to access the functionality of the Template
-Toolkit to process other templates, load plugins, filters, etc.
-See L<Template::Context> for further details.
-
- [% PERL %]
- print $context->include('myfile');
- [% END %]
-
-The $stash variable contains a reference to the top-level stash object
-which manages template variables. Through this, variable values can
-be retrieved and updated. See L<Template::Stash> for further details.
-
- [% PERL %]
- $stash->set(foo => 'bar');
- print "foo value: ", $stash->get('foo');
- [% END %]
-
-Output
- foo value: bar
-
-Output is generated from the PERL block by calling print(). Note that
-the Template::Perl::PERLOUT handle is selected (tied to an output
-buffer) instead of STDOUT.
-
- [% PERL %]
- print "foo\n"; # OK
- print PERLOUT "bar\n"; # OK, same as above
- print Template::Perl::PERLOUT "baz\n"; # OK, same as above
- print STDOUT "qux\n"; # WRONG!
- [% END %]
-
-The PERL block may contain other template directives. These are
-processed before the Perl code is evaluated.
-
- [% name = 'Fred Smith' %]
-
- [% PERL %]
- print "[% name %]\n";
- [% END %]
-
-Thus, the Perl code in the above example is evaluated as:
-
- print "Fred Smith\n";
-
-Exceptions may be thrown from within PERL blocks via die() and will be
-correctly caught by enclosing TRY blocks.
-
- [% TRY %]
- [% PERL %]
- die "nothing to live for\n";
- [% END %]
- [% CATCH %]
- error: [% error.info %]
- [% END %]
-
-output:
- error: nothing to live for
-
-
-
-
-=item RAWPERL
-
-(for the very advanced reader)
-
-The Template Toolkit parser reads a source template and generates the
-text of a Perl subroutine as output. It then uses eval() to evaluate
-it into a subroutine reference. This subroutine is then called to
-process the template, passing a reference to the current
-Template::Context object through which the functionality of the
-Template Toolkit can be accessed. The subroutine reference can be
-cached, allowing the template to be processed repeatedly without
-requiring any further parsing.
-
-For example, a template such as:
-
- [% PROCESS header %]
- The [% animal %] sat on the [% location %]
- [% PROCESS footer %]
-
-is converted into the following Perl subroutine definition:
-
- sub {
- my $context = shift;
- my $stash = $context->stash;
- my $output = '';
- my $error;
-
- eval { BLOCK: {
- $output .= $context->process('header');
- $output .= "The ";
- $output .= $stash->get('animal');
- $output .= " sat on the ";
- $output .= $stash->get('location');
- $output .= $context->process('footer');
- $output .= "\n";
- } };
- if ($@) {
- $error = $context->catch($@, \$output);
- die $error unless $error->type eq 'return';
- }
-
- return $output;
- }
-
-To examine the Perl code generated, such as in the above example, set
-the $Template::Parser::DEBUG package variable to any true value. You
-can also set the $Template::Directive::PRETTY variable true to have
-the code formatted in a readable manner for human consumption. The
-source code for each generated template subroutine will be printed to
-STDERR on compilation (i.e. the first time a template is used).
-
- $Template::Parser::DEBUG = 1;
- $Template::Directive::PRETTY = 1;
-
- ...
-
- $template->process($file, $vars)
- || die $template->error(), "\n";
-
-The PERL ... END construct allows Perl code to be embedded into a
-template (when the EVAL_PERL option is set), but it is evaluated at
-"runtime" using eval() each time the template subroutine is called.
-This is inherently flexible, but not as efficient as it could be,
-especially in a persistent server environment where a template may be
-processed many times.
-
-The RAWPERL directive allows you to write Perl code that is integrated
-directly into the generated Perl subroutine text. It is evaluated
-once at compile time and is stored in cached form as part of the
-compiled template subroutine. This makes RAWPERL blocks more
-efficient than PERL blocks.
-
-The downside is that you must code much closer to the metal. Within
-PERL blocks, you can call print() to generate some output. RAWPERL
-blocks don't afford such luxury. The code is inserted directly into
-the generated subroutine text and should conform to the convention of
-appending to the '$output' variable.
-
- [% PROCESS header %]
-
- [% RAWPERL %]
- $output .= "Some output\n";
- ...
- $output .= "Some more output\n";
- [% END %]
-
-The critical section of the generated subroutine for this example would
-then look something like:
-
- ...
- eval { BLOCK: {
- $output .= $context->process('header');
- $output .= "\n";
- $output .= "Some output\n";
- ...
- $output .= "Some more output\n";
- $output .= "\n";
- } };
- ...
-
-As with PERL blocks, the $context and $stash references are pre-defined
-and available for use within RAWPERL code.
-
-
-=back
-
-=head2 Exception Handling and Flow Control
-
-=over 4
-
-
-=item TRY / THROW / CATCH / FINAL
-
-(more advanced material)
-
-The Template Toolkit supports fully functional, nested exception
-handling. The TRY directive introduces an exception handling scope
-which continues until the matching END directive. Any errors that
-occur within that block will be caught and can be handled by one
-of the CATCH blocks defined.
-
- [% TRY %]
- ...blah...blah...
- [% CALL somecode %]
- ...etc...
- [% INCLUDE someblock %]
- ...and so on...
- [% CATCH %]
- An error occurred!
- [% END %]
-
-Errors are raised as exceptions (objects of the Template::Exception
-class) and contain two fields, 'type' and 'info'. The exception
-'type' can be any string containing letters, numbers, '_' or '.', and
-is used to indicate the kind of error that occurred. The 'info' field
-contains an error message indicating what actually went wrong. Within
-a catch block, the exception object is aliased to the 'error' variable.
-You can access the 'type' and 'info' fields directly.
-
- [% mydsn = 'dbi:MySQL:foobar' %]
- ...
-
- [% TRY %]
- [% USE DBI(mydsn) %]
- [% CATCH %]
- ERROR! Type: [% error.type %]
- Info: [% error.info %]
- [% END %]
-
-output (assuming a non-existant database called 'foobar'):
-
- ERROR! Type: DBI
- Info: Unknown database "foobar"
-
-The 'error' variable can also be specified by itself and will return a
-string of the form "$type error - $info".
-
- ...
- [% CATCH %]
- ERROR: [% error %]
- [% END %]
-
-output:
-
- ERROR: DBI error - Unknown database "foobar"
-
-Each CATCH block may be specified with a particular exception type
-denoting the kind of error that it should catch. Multiple CATCH
-blocks can be provided to handle different types of exception that may
-be thrown in the TRY block. A CATCH block specified without any type,
-as in the previous example, is a default handler which will catch any
-otherwise uncaught exceptions. This can also be specified as
-[% CATCH DEFAULT %].
-
- [% TRY %]
- [% INCLUDE myfile %]
- [% USE DBI(mydsn) %]
- [% CALL somecode %]
- ...
- [% CATCH file %]
- File Error! [% error.info %]
- [% CATCH DBI %]
- [% INCLUDE database/error.html %]
- [% CATCH %]
- [% error %]
- [% END %]
-
-Remember that you can specify multiple directives within a single tag,
-each delimited by ';'. Thus, you might prefer to write your simple
-CATCH blocks more succinctly as:
-
- [% TRY %]
- ...
- [% CATCH file; "File Error! $error.info" %]
- [% CATCH DBI; INCLUDE database/error.html %]
- [% CATCH; error %]
- [% END %]
-
-or even:
-
- [% TRY %]
- ...
- [% CATCH file ;
- "File Error! $error.info" ;
- CATCH DBI ;
- INCLUDE database/error.html ;
- CATCH ;
- error ;
- END
- %]
-
-The DBI plugin throws exceptions of the 'DBI' type (in case that
-wasn't already obvious). The other specific exception caught here is
-of the 'file' type.
-
-A 'file' error is automatically thrown by the Template Toolkit when it
-can't find a file, or fails to load, parse or process a file that has
-been requested by an INCLUDE, PROCESS, INSERT or WRAPPER directive.
-If 'myfile' can't be found in the example above, the [% INCLUDE myfile
-%] directive will raise a 'file' exception which is then caught by the
-[% CATCH file %] block, generating the output:
-
- File Error! myfile: not found
-
-Note that the DEFAULT option (disabled by default) allows you to
-specify a default file to be used any time a template file can't be
-found. This will prevent file exceptions from ever being raised when
-a non-existant file is requested (unless, of course, the DEFAULT file
-doesn't exist). Errors encountered once the file has been found
-(i.e. read error, parse error) will be raised as file exceptions as per
-usual.
-
-Uncaught exceptions (i.e. the TRY block doesn't have a type specific
-or default CATCH handler) may be caught by enclosing TRY blocks which
-can be nested indefinitely across multiple templates. If the error
-isn't caught at any level then processing will stop and the Template
-process() method will return a false value to the caller. The
-relevant Template::Exception object can be retrieved by calling the
-error() method.
-
- [% TRY %]
- ...
- [% TRY %]
- [% INCLUDE $user.header %]
- [% CATCH file %]
- [% INCLUDE header %]
- [% END %]
- ...
- [% CATCH DBI %]
- [% INCLUDE database/error.html %]
- [% END %]
-
-In this example, the inner TRY block is used to ensure that the first
-INCLUDE directive works as expected. We're using a variable to
-provide the name of the template we want to include, user.header, and
-it's possible this contains the name of a non-existant template, or
-perhaps one containing invalid template directives. If the INCLUDE fails
- with a 'file' error then we CATCH it in the inner block and INCLUDE
-the default 'header' file instead. Any DBI errors that occur within
-the scope of the outer TRY block will be caught in the relevant CATCH
-block, causing the 'database/error.html' template to be processed.
-Note that included templates inherit all currently defined template
-variable so these error files can quite happily access the 'error'
-variable to retrieve information about the currently caught exception.
-e.g.
-
-'database/error.html':
-
- <h2>Database Error</h2>
- A database error has occurred: [% error.info %]
-
-You can also specify a FINAL block. This is always processed
-regardless of the outcome of the TRY and/or CATCH block. If an
-exception is uncaught then the FINAL block is processed before jumping
-to the enclosing block or returning to the caller.
-
- [% TRY %]
- ...
- [% CATCH this %]
- ...
- [% CATCH that %]
- ...
- [% FINAL %]
- All done!
- [% END %]
-
-The output from the TRY block is left intact up to the point where an
-exception occurs. For example, this template:
-
- [% TRY %]
- This gets printed
- [% THROW food 'carrots' %]
- This doesn't
- [% CATCH food %]
- culinary delights: [% error.info %]
- [% END %]
-
-generates the following output:
-
- This gets printed
- culinary delights: carrots
-
-The CLEAR directive can be used in a CATCH or FINAL block to clear
-any output created in the TRY block.
-
- [% TRY %]
- This gets printed
- [% THROW food 'carrots' %]
- This doesn't
- [% CATCH food %]
- [% CLEAR %]
- culinary delights: [% error.info %]
- [% END %]
-
-output:
-
- culinary delights: carrots
-
-Exception types are hierarchical, with each level being separated by
-the familiar dot operator. A 'DBI.connect' exception is a more
-specific kind of 'DBI' error. Similarly, a 'myown.error.barf' is a
-more specific kind of 'myown.error' type which itself is also a
-'myown' error. A CATCH handler that specifies a general exception
-type (such as 'DBI' or 'myown.error') will also catch more specific
-types that have the same prefix as long as a more specific handler
-isn't defined. Note that the order in which CATCH handlers are
-defined is irrelevant; a more specific handler will always catch an
-exception in preference to a more generic or default one.
-
- [% TRY %]
- ...
- [% CATCH DBI ;
- INCLUDE database/error.html ;
- CATCH DBI.connect ;
- INCLUDE database/connect.html ;
- CATCH ;
- INCLUDE error.html ;
- END
- %]
-
-In this example, a 'DBI.connect' error has it's own handler, a more
-general 'DBI' block is used for all other DBI or DBI.* errors and a
-default handler catches everything else.
-
-Exceptions can be raised in a template using the THROW directive. The
-first parameter is the exception type which doesn't need to be quoted
-(but can be, it's the same as INCLUDE) followed by the relevant error
-message which can be any regular value such as a quoted string,
-variable, etc.
-
- [% THROW food "Missing ingredients: $recipe.error" %]
-
- [% THROW user.login 'no user id: please login' %]
-
- [% THROW $myerror.type "My Error: $myerror.info" %]
-
-It's also possible to specify additional positional or named
-parameters to the THROW directive if you want to pass more than
-just a simple message back as the error info field.
-
- [% THROW food 'eggs' 'flour' msg='Missing Ingredients' %]
-
-In this case, the error 'info' field will be a hash array containing
-the named arguments, in this case 'msg' =E<gt> 'Missing Ingredients',
-and an 'args' item which contains a list of the positional arguments,
-in this case 'eggs' and 'flour'. The error 'type' field remains
-unchanged, here set to 'food'.
-
- [% CATCH food %]
- [% error.info.msg %]
- [% FOREACH item = error.info.args %]
- * [% item %]
- [% END %]
- [% END %]
-
-This produces the output:
-
- Missing Ingredients
- * eggs
- * flour
-
-In addition to specifying individual positional arguments as
-[% error.info.args.n %], the 'info' hash contains keys directly
-pointing to the positional arguments, as a convenient shortcut.
-
- [% error.info.0 %] # same as [% error.info.args.0 %]
-
-Exceptions can also be thrown from Perl code which you've bound to
-template variables, or defined as a plugin or other extension. To
-raise an exception, call die() passing a reference to a
-Template::Exception object as the argument. This will then be caught
-by any enclosing TRY blocks from where the code was called.
-
- use Template::Exception;
- ...
-
- my $vars = {
- foo => sub {
- # ... do something ...
- die Template::Exception->new('myerr.naughty',
- 'Bad, bad error');
- },
- };
-
-template:
-
- [% TRY %]
- ...
- [% foo %]
- ...
- [% CATCH myerr ;
- "Error: $error" ;
- END
- %]
-
-output:
-
- Error: myerr.naughty error - Bad, bad error
-
-The 'info' field can also be a reference to another object or data
-structure, if required.
-
- die Template::Exception->new('myerror', {
- module => 'foo.pl',
- errors => [ 'bad permissions', 'naughty boy' ],
- });
-
-Later, in a template:
-
- [% TRY %]
- ...
- [% CATCH myerror %]
- [% error.info.errors.size or 'no';
- error.info.errors.size == 1 ? ' error' : ' errors' %]
- in [% error.info.module %]:
- [% error.info.errors.join(', ') %].
- [% END %]
-
-Generating the output:
-
- 2 errors in foo.pl:
- bad permissions, naughty boy.
-
-You can also call die() with a single string, as is common in much
-existing Perl code. This will automatically be converted to an
-exception of the 'undef' type (that's the literal string 'undef',
-not the undefined value). If the string isn't terminated with a
-newline then Perl will append the familiar " at $file line $line"
-message.
-
- sub foo {
- # ... do something ...
- die "I'm sorry, Dave, I can't do that\n";
- }
-
-If you're writing a plugin, or some extension code that has the
-current Template::Context in scope (you can safely skip this section
-if this means nothing to you) then you can also raise an exception by
-calling the context throw() method. You can pass it an
-Template::Exception object reference, a pair of ($type, $info) parameters
-or just an $info string to create an exception of 'undef' type.
-
- $context->throw($e); # exception object
- $context->throw('Denied'); # 'undef' type
- $context->throw('user.passwd', 'Bad Password');
-
-
-
-
-
-
-
-=item NEXT
-
-The NEXT directive can be used to start the next iteration of a FOREACH
-or WHILE loop.
-
- [% FOREACH user = userlist %]
- [% NEXT IF user.isguest %]
- Name: [% user.name %] Email: [% user.email %]
- [% END %]
-
-
-
-
-
-=item LAST
-
-The LAST directive can be used to prematurely exit a FOREACH or WHILE
-loop.
-
- [% FOREACH user = userlist %]
- Name: [% user.name %] Email: [% user.email %]
- [% LAST IF some.condition %]
- [% END %]
-
-BREAK can also be used as an alias for LAST.
-
-
-
-
-=item RETURN
-
-The RETURN directive can be used to stop processing the current
-template and return to the template from which it was called, resuming
-processing at the point immediately after the INCLUDE, PROCESS or
-WRAPPER directive. If there is no enclosing template then the
-Template process() method will return to the calling code with a
-true value.
-
- Before
- [% INCLUDE half_wit %]
- After
-
- [% BLOCK half_wit %]
- This is just half...
- [% RETURN %]
- ...a complete block
- [% END %]
-
-output:
-
- Before
- This is just half...
- After
-
-
-
-
-=item STOP
-
-The STOP directive can be used to indicate that the processor should
-stop gracefully without processing any more of the template document.
-This is a planned stop and the Template process() method will return a
-B<true> value to the caller. This indicates that the template was
-processed successfully according to the directives within it.
-
- [% IF something.terrible.happened %]
- [% INCLUDE fatal/error.html %]
- [% STOP %]
- [% END %]
-
- [% TRY %]
- [% USE DBI(mydsn) %]
- ...
- [% CATCH DBI.connect %]
- <p>Cannot connect to the database: [% error.info %]</p>
- <br>
- We apologise for the inconvenience. The cleaning lady
- has removed the server power to plug in her vacuum cleaner.
- Please try again later.
- </p>
- [% INCLUDE footer %]
- [% STOP %]
- [% END %]
-
-
-
-
-=item CLEAR
-
-The CLEAR directive can be used to clear the output buffer for the current
-enclosing block. It is most commonly used to clear the output generated
-from a TRY block up to the point where the error occurred.
-
- [% TRY %]
- blah blah blah # this is normally left intact
- [% THROW some 'error' %] # up to the point of error
- ...
- [% CATCH %]
- [% CLEAR %] # clear the TRY output
- [% error %] # print error string
- [% END %]
-
-
-
-
-=back
-
-=head2 Miscellaneous
-
-=over 4
-
-
-=item META
-
-The META directive allows simple metadata items to be defined within a
-template. These are evaluated when the template is parsed and as such
-may only contain simple values (e.g. it's not possible to interpolate
-other variables values into META variables).
-
- [% META
- title = 'The Cat in the Hat'
- author = 'Dr. Seuss'
- version = 1.23
- %]
-
-The 'template' variable contains a reference to the main template
-being processed. These metadata items may be retrieved as attributes
-of the template.
-
- <h1>[% template.title %]</h1>
- <h2>[% template.author %]</h2>
-
-The 'name' and 'modtime' metadata items are automatically defined for
-each template to contain its name and modification time in seconds
-since the epoch.
-
- [% USE date %] # use Date plugin to format time
- ...
- [% template.name %] last modified
- at [% date.format(template.modtime) %]
-
-The PRE_PROCESS and POST_PROCESS options allow common headers and
-footers to be added to all templates. The 'template' reference is
-correctly defined when these templates are processed, allowing headers
-and footers to reference metadata items from the main template.
-
- $template = Template->new({
- PRE_PROCESS => 'header',
- POST_PROCESS => 'footer',
- });
-
- $template->process('cat_in_hat');
-
-header:
-
- <html>
- <head>
- <title>[% template.title %]</title>
- </head>
- <body>
-
-cat_in_hat:
-
- [% META
- title = 'The Cat in the Hat'
- author = 'Dr. Seuss'
- version = 1.23
- year = 2000
- %]
-
- The cat in the hat sat on the mat.
-
-footer:
-
- <hr>
- &copy; [% template.year %] [% template.author %]
- </body>
- </html>
-
-The output generated from the above example is:
-
- <html>
- <head>
- <title>The Cat in the Hat</title>
- </head>
- <body>
-
- The cat in the hat sat on the mat.
-
- <hr>
- &copy; 2000 Dr. Seuss
- </body>
- </html>
-
-
-
-=item TAGS
-
-The TAGS directive can be used to set the START_TAG and END_TAG values
-on a per-template file basis.
-
- [% TAGS <+ +> %]
-
- <+ INCLUDE header +>
-
-The TAGS directive may also be used to set a named TAG_STYLE
-
- [% TAGS html %]
- <!-- INCLUDE header -->
-
-See the TAGS and TAG_STYLE configuration options for further details.
-
-
-
-
-
-
-
-
-=item DEBUG
-
-The DEBUG directive can be used to enable or disable directive debug
-messages within a template. The DEBUG configuration option must be
-set to include DEBUG_DIRS for the DEBUG directives to have any effect.
-If DEBUG_DIRS is not set then the parser will automatically ignore and
-remove any DEBUG directives.
-
-The DEBUG directive can be used with an 'on' or 'off' parameter to
-enable or disable directive debugging messages from that point
-forward. When enabled, the output of each directive in the generated
-output will be prefixed by a comment indicate the file, line and
-original directive text.
-
- [% DEBUG on %]
- directive debugging is on (assuming DEBUG option is set true)
- [% DEBUG off %]
- directive debugging is off
-
-The 'format' parameter can be used to change the format of the debugging
-message.
-
- [% DEBUG format '<!-- $file line $line : [% $text %] -->' %]
-
-
-
-
-
-=back
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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:
diff --git a/lib/Template/Manual/Filters.pod b/lib/Template/Manual/Filters.pod
deleted file mode 100644
index c42f2ef..0000000
--- a/lib/Template/Manual/Filters.pod
+++ /dev/null
@@ -1,529 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Manual::Filters
-#
-# DESCRIPTION
-# This section lists all the standard filters distributed with the
-# Template Toolkit for post-processing output.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-#
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Manual::Filters - Standard filters
-
-=head1 DESCRIPTION
-
-This section lists all the standard filters distributed with the
-Template Toolkit for post-processing output.
-
-=head1 STANDARD FILTERS
-
-
-
-=head2 format(format)
-
-The 'format' filter takes a format string as a parameter (as per
-printf()) and formats each line of text accordingly.
-
- [% FILTER format('<!-- %-40s -->') %]
- This is a block of text filtered
- through the above format.
- [% END %]
-
-output:
-
- <!-- This is a block of text filtered -->
- <!-- through the above format. -->
-
-=head2 upper
-
-Folds the input to UPPER CASE.
-
- [% "hello world" FILTER upper %]
-
-output:
-
- HELLO WORLD
-
-=head2 lower
-
-Folds the input to lower case.
-
- [% "Hello World" FILTER lower %]
-
-output:
-
- hello world
-
-=head2 ucfirst
-
-Folds the first character of the input to UPPER CASE.
-
- [% "hello" FILTER ucfirst %]
-
-output:
-
- Hello
-
-=head2 lcfirst
-
-Folds the first character of the input to lower case.
-
- [% "HELLO" FILTER lcfirst %]
-
-output:
-
- hELLO
-
-=head2 trim
-
-Trims any leading or trailing whitespace from the input text. Particularly
-useful in conjunction with INCLUDE, PROCESS, etc., having the same effect
-as the TRIM configuration option.
-
- [% INCLUDE myfile | trim %]
-
-=head2 collapse
-
-Collapse any whitespace sequences in the input text into a single space.
-Leading and trailing whitespace (which would be reduced to a single space)
-is removed, as per trim.
-
- [% FILTER collapse %]
-
- The cat
-
- sat on
-
- the mat
-
- [% END %]
-
-output:
-
- The cat sat on the mat
-
-=head2 html
-
-Converts the characters 'E<lt>', 'E<gt>' and '&' to '&lt;', '&gt;' and
-'&amp;', respectively, protecting them from being interpreted as
-representing HTML tags or entities.
-
- [% FILTER html %]
- Binary "<=>" returns -1, 0, or 1 depending on...
- [% END %]
-
-output:
-
- Binary "&lt;=&gt;" returns -1, 0, or 1 depending on...
-
-=head2 html_entity
-
-The html filter is fast and simple but it doesn't encode the full
-range of HTML entities that your text may contain. The html_entity
-filter uses either the Apache::Util module (which is written in C and
-is therefore faster) or the HTML::Entities module (written in Perl but
-equally as comprehensive) to perform the encoding. If one or other of
-these modules are installed on your system then the text will be
-encoded (via the escape_html() or encode_entities() subroutines
-respectively) to convert all extended characters into their
-appropriate HTML entities (e.g. converting 'é' to '&eacute;'). If
-neither module is available on your system then an 'html_entity' exception
-will be thrown reporting an appropriate message.
-
-For further information on HTML entity encoding, see
-http://www.w3.org/TR/REC-html40/sgml/entities.html.
-
-=head2 html_para
-
-This filter formats a block of text into HTML paragraphs. A sequence of
-two or more newlines is used as the delimiter for paragraphs which are
-then wrapped in HTML E<lt>pE<gt>...E<lt>/pE<gt> tags.
-
- [% FILTER html_para %]
- The cat sat on the mat.
-
- Mary had a little lamb.
- [% END %]
-
-output:
-
- <p>
- The cat sat on the mat.
- </p>
-
- <p>
- Mary had a little lamb.
- </p>
-
-=head2 html_break / html_para_break
-
-Similar to the html_para filter described above, but uses the HTML tag
-sequence E<lt>brE<gt>E<lt>brE<gt> to join paragraphs.
-
- [% FILTER html_break %]
- The cat sat on the mat.
-
- Mary had a little lamb.
- [% END %]
-
-output:
-
- The cat sat on the mat.
- <br>
- <br>
- Mary had a little lamb.
-
-=head2 html_line_break
-
-This filter replaces any newlines with E<lt>brE<gt> HTML tags,
-thus preserving the line breaks of the original text in the
-HTML output.
-
- [% FILTER html_line_break %]
- The cat sat on the mat.
- Mary had a little lamb.
- [% END %]
-
-output:
-
- The cat sat on the mat.<br>
- Mary had a little lamb.<br>
-
-=head2 uri
-
-This filter URI escapes the input text, converting any characters
-outside of the permitted URI character set (as defined by RFC 2396)
-into a C<%nn> hex escape.
-
- [% 'my file.html' | uri %]
-
-output:
-
- my%20file.html
-
-Note that URI escaping isn't always enough when generating hyperlinks in
-an HTML document. The C<&> character, for example, is valid in a URI and
-will not be escaped by the URI filter. In this case you should also filter
-the text through the 'html' filter.
-
- <a href="[% filename | uri | html %]">click here</a>
-
-=head2 indent(pad)
-
-Indents the text block by a fixed pad string or width. The 'pad' argument
-can be specified as a string, or as a numerical value to indicate a pad
-width (spaces). Defaults to 4 spaces if unspecified.
-
- [% FILTER indent('ME> ') %]
- blah blah blah
- cabbages, rhubard, onions
- [% END %]
-
-output:
-
- ME> blah blah blah
- ME> cabbages, rhubard, onions
-
-=head2 truncate(length)
-
-Truncates the text block to the length specified, or a default length of
-32. Truncated text will be terminated with '...' (i.e. the '...' falls
-inside the required length, rather than appending to it).
-
- [% FILTER truncate(21) %]
- I have much to say on this matter that has previously
- been said on more than one occasion.
- [% END %]
-
-output:
-
- I have much to say...
-
-=head2 repeat(iterations)
-
-Repeats the text block for as many iterations as are specified (default: 1).
-
- [% FILTER repeat(3) %]
- We want more beer and we want more beer,
- [% END %]
- We are the more beer wanters!
-
-output:
-
- We want more beer and we want more beer,
- We want more beer and we want more beer,
- We want more beer and we want more beer,
- We are the more beer wanters!
-
-=head2 remove(string)
-
-Searches the input text for any occurrences of the specified string and
-removes them. A Perl regular expression may be specified as the search
-string.
-
- [% "The cat sat on the mat" FILTER remove('\s+') %]
-
-output:
-
- Thecatsatonthemat
-
-=head2 replace(search, replace)
-
-Similar to the remove filter described above, but taking a second parameter
-which is used as a replacement string for instances of the search string.
-
- [% "The cat sat on the mat" | replace('\s+', '_') %]
-
-output:
-
- The_cat_sat_on_the_mat
-
-=head2 redirect(file, options)
-
-The 'redirect' filter redirects the output of the block into a separate
-file, specified relative to the OUTPUT_PATH configuration item.
-
- [% FOREACH user = myorg.userlist %]
- [% FILTER redirect("users/${user.id}.html") %]
- [% INCLUDE userinfo %]
- [% END %]
- [% END %]
-
-or more succinctly, using side-effect notation:
-
- [% INCLUDE userinfo
- FILTER redirect("users/${user.id}.html")
- FOREACH user = myorg.userlist
- %]
-
-A 'file' exception will be thrown if the OUTPUT_PATH option is undefined.
-
-An optional 'binmode' argument can follow the filename to explicitly set
-the output file to binary mode.
-
- [% PROCESS my/png/generator
- FILTER redirect("images/logo.png", binmode=1) %]
-
-For backwards compatibility with earlier versions, a single true/false
-value can be used to set binary mode.
-
- [% PROCESS my/png/generator
- FILTER redirect("images/logo.png", 1) %]
-
-For the sake of future compatibility and clarity, if nothing else, we
-would strongly recommend you explicitly use the named 'binmode' option
-as shown in the first example.
-
-=head2 eval / evaltt
-
-The 'eval' filter evaluates the block as template text, processing
-any directives embedded within it. This allows template variables to
-contain template fragments, or for some method to be provided for
-returning template fragments from an external source such as a
-database, which can then be processed in the template as required.
-
- my $vars = {
- fragment => "The cat sat on the [% place %]",
- };
- $template->process($file, $vars);
-
-The following example:
-
- [% fragment | eval %]
-
-is therefore equivalent to
-
- The cat sat on the [% place %]
-
-The 'evaltt' filter is provided as an alias for 'eval'.
-
-=head2 perl / evalperl
-
-The 'perl' filter evaluates the block as Perl code. The EVAL_PERL
-option must be set to a true value or a 'perl' exception will be
-thrown.
-
- [% my_perl_code | perl %]
-
-In most cases, the [% PERL %] ... [% END %] block should suffice for
-evaluating Perl code, given that template directives are processed
-before being evaluate as Perl. Thus, the previous example could have
-been written in the more verbose form:
-
- [% PERL %]
- [% my_perl_code %]
- [% END %]
-
-as well as
-
- [% FILTER perl %]
- [% my_perl_code %]
- [% END %]
-
-The 'evalperl' filter is provided as an alias for 'perl' for backwards
-compatibility.
-
-=head2 stdout(options)
-
-The stdout filter prints the output generated by the enclosing block to
-STDOUT. The 'binmode' option can be passed as either a named parameter
-or a single argument to set STDOUT to binary mode (see the
-binmode perl function).
-
- [% PROCESS something/cool
- FILTER stdout(binmode=1) # recommended %]
-
- [% PROCESS something/cool
- FILTER stdout(1) # alternate %]
-
-The stdout filter can be used to force binmode on STDOUT, or also inside
-redirect, null or stderr blocks to make sure that particular output goes
-to stdout. See the null filter below for an example.
-
-=head2 stderr
-
-The stderr filter prints the output generated by the enclosing block to
-STDERR.
-
-=head2 null
-
-The null filter prints nothing. This is useful for plugins whose
-methods return values that you don't want to appear in the output.
-Rather than assigning every plugin method call to a dummy variable
-to silence it, you can wrap the block in a null filter:
-
- [% FILTER null;
- USE im = GD.Image(100,100);
- black = im.colorAllocate(0, 0, 0);
- red = im.colorAllocate(255,0, 0);
- blue = im.colorAllocate(0, 0, 255);
- im.arc(50,50,95,75,0,360,blue);
- im.fill(50,50,red);
- im.png | stdout(1);
- END;
- -%]
-
-Notice the use of the stdout filter to ensure that a particular expression
-generates output to stdout (in this case in binary mode).
-
-=head2 latex(outputType)
-
-Passes the text block to LaTeX and produces either PDF, DVI or
-PostScript output. The 'outputType' argument determines the output
-format and it should be set to one of the strings: "pdf" (default),
-"dvi", or "ps".
-
-The text block should be a complete LaTeX source file.
-
- [% FILTER latex("pdf") -%]
- \documentclass{article}
-
- \begin{document}
-
- \title{A Sample TT2 \LaTeX\ Source File}
- \author{Craig Barratt}
- \maketitle
-
- \section{Introduction}
- This is some text.
-
- \end{document}
- [% END -%]
-
-The output will be a PDF file. You should be careful not to prepend or
-append any extraneous characters or text outside the FILTER block,
-since this text will wrap the (binary) output of the latex filter.
-Notice the END directive uses '-%]' for the END_TAG to remove the
-trailing new line.
-
-One example where you might prepend text is in a CGI script where
-you might include the Content-Type before the latex output, eg:
-
- Content-Type: application/pdf
-
- [% FILTER latex("pdf") -%]
- \documentclass{article}
- \begin{document}
- ...
- \end{document}
- [% END -%]
-
-In other cases you might use the redirect filter to put the output
-into a file, rather than delivering it to stdout. This might be
-suitable for batch scripts:
-
- [% output = FILTER latex("pdf") -%]
- \documentclass{article}
- \begin{document}
- ...
- \end{document}
- [% END; output | redirect("document.pdf", 1) -%]
-
-(Notice the second argument to redirect to force binary mode.)
-
-Note that the latex filter runs one or two external programs, so it
-isn't very fast. But for modest documents the performance is adequate,
-even for interactive applications.
-
-A error of type 'latex' will be thrown if there is an error reported
-by latex, pdflatex or dvips.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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:
diff --git a/lib/Template/Manual/Internals.pod b/lib/Template/Manual/Internals.pod
deleted file mode 100644
index b8cf80b..0000000
--- a/lib/Template/Manual/Internals.pod
+++ /dev/null
@@ -1,556 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Manual::Internals
-#
-# DESCRIPTION
-# This document provides an overview of the internal architecture of
-# the Template Toolkit. It is a work in progress and is far from
-# complete, currently providing little more than an overview of how
-# the major components fit together. Nevertheless, it's a good
-# starting point for anyone wishing to delve into the source code to
-# find out how it all works.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-#
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Manual::Internals - Template Toolkit internals
-
-=head1 DESCRIPTION
-
-This document provides an overview of the internal architecture of the
-Template Toolkit. It is a work in progress and is far from complete,
-currently providing little more than an overview of how the major
-components fit together. Nevertheless, it's a good starting point for
-anyone wishing to delve into the source code to find out how it all
-works.
-
-=head2 Outside Looking In
-
-The B<Template> module is simply a front end module which creates and
-uses a Template::Service and pipes the output wherever you want it to
-go (STDOUT by default, or maybe a file, scalar, etc). The
-Apache::Template module (available separately from CPAN) is another
-front end. That creates a Template::Service::Apache object, calls on
-it as required and sends the output back to the relevant
-Apache::Request object.
-
-These front-end modules are really only there to handle any specifics
-of the environment in which they're being used. The Apache::Template
-front end, for example, handles Apache::Request specifics and
-configuration via the httpd.conf. The regular Template front-end
-deals with STDOUT, variable refs, etc. Otherwise it is
-Template::Service (or subclass) which does all the work.
-
-The B<Template::Service> module provides a high-quality template
-delivery service, with bells, whistles, signed up service level
-agreement and a 30-day no quibble money back guarantee. "Have
-a good time, all the time", that's our motto.
-
-Within the lower levels of the Template Toolkit, there are lots of
-messy details that we generally don't want to have to worry about most
-of the time. Things like templates not being found, or failing to
-parse correctly, uncaught exceptions being thrown, missing plugin
-modules or dependencies, and so on. Template::Service hides that all
-away and makes everything look simple to the outsider. It provides
-extra features, like PRE_PROCESS, PROCESS and POST_PROCESS, and also
-provides the error recovery mechanism via ERROR. You ask it to
-process a template and it takes care of everything for you. The
-Template::Service::Apache module goes a little bit further, adding
-some extra headers to the Apache::Request, setting a few extra template
-variables, and so on.
-
-For the most part, the job of a service is really just one of
-scheduling and dispatching. It receives a request in the form of a
-call to its process() method and schedules the named template
-specified as an argument, and possibly several other templates
-(PRE_PROCESS, etc) to be processed in order. It doesn't actually
-process the templates itself, but instead makes a process() call
-against a Template::Context object.
-
-B<Template::Context> is the runtime engine for the Template Toolkit -
-the module that hangs everything together in the lower levels of the
-Template Toolkit and that one that does most of the real work, albeit
-by crafty delegation to various other friendly helper modules.
-
-Given a template name (or perhaps a reference to a scalar or file
-handle) the context process() method must load and compile, or fetch a
-cached copy of a previously compiled template, corresponding to that
-name. It does this by calling on a list of one or more
-Template::Provider objects (the LOAD_TEMPLATES posse) who themselves
-might get involved with a Template::Parser to help turn source
-templates into executable Perl code (but more on that later). Thankfully,
-all of this complexity is hidden away behind a simple template()
-method. You call it passing a template name as an argument, and it
-returns a compiled template in the form of a Template::Document
-object, or otherwise raises an exception.
-
-A B<Template::Document> is a thin object wrapper around a compiled
-template subroutine. The object implements a process() method which
-performs a little bit of housekeeping and then calls the template
-subroutine. The object also defines template metadata (defined in
-C<[% META ... %]> directives) and has a block() method which returns
-a hash of any additional C<[% BLOCK xxxx %]> definitions found in the
-template source.
-
-So the context fetches a compiled document via its own template()
-method and then gets ready to process it. It first updates the stash
-(the place where template variables get defined - more on that
-shortly) to set any template variable definitions specified as the
-second argument by reference to hash array. Then, it calls the
-document process() method, passing a reference to itself, the context
-object, as an argument. In doing this, it provides itself as an
-object against which template code can make callbacks to access
-runtime resources and Template Toolkit functionality.
-
-What we're trying to say here is this: not only does the Template::Context
-object receive calls from the I<outside>, i.e. those originating in user
-code calling the process() method on a Template object, but it also
-receives calls from the I<inside>, i.e. those originating in template
-directives of the form C<[% PROCESS template %]>.
-
-Before we move on to that, here's a simple structure diagram showing
-the outer layers of the Template Toolkit heading inwards, with pseudo
-code annotations showing a typical invocation sequence.
-
- ,--------.
- | Caller | use Template;
- `--------' my $tt = Template->new( ... );
- | $tt->process($template, \%vars);
- | Outside
- - - - - | - - - - - - - - - - - - - - - - - - - - - - - - - - - - T T
- | package Template; Inside
- V
- +----------+ sub process($template, \%vars) {
- | Template | $out = $self->SERVICE->process($template, $vars);
- +----------+ print $out or send it to $self->OUTPUT;
- | }
- |
- | package Template::Service;
- |
- | sub process($template, \%vars) {
- | try {
- +----------+ foreach $p in @self->PRE_PROCESS
- | Service | $self->CONTEXT->process($p, $vars);
- +----------+
- | $self->CONTEXT->process($template, $vars);
- |
- | foreach $p @self->POST_PROCESS
- | $self->CONTEXT->process($p, $vars);
- | }
- | catch {
- | $self->CONTEXT->process($self->ERROR);
- | }
- | }
- |
- V package Template::Context;
- +----------+
- | Context | sub process($template, \%vars) {
- +----------+ # fetch compiled template
- | $template = $self->template($template)
- | # update stash
- | $self->STASH->update($vars);
- | # process template
- | $template->process($self)
- | }
- V
- +----------+ package Template::Document;
- | Document |
- +----------+ sub process($context) {
- $output = &{ $self->BLOCK }($context);
- }
-
-
-=head2 Inside Looking Out
-
-To understand more about what's going on in these lower levels, we
-need to look at what a compiled template looks like. In fact, a
-compiled template is just a regular Perl sub-routine. Here's a very
-simple one.
-
- sub my_compiled_template {
- return "This is a compiled template.\n";
- }
-
-You're unlikely to see a compiled template this simple unless you
-wrote it yourself but it is entirely valid. All a template subroutine
-is obliged to do is return some output (which may be an empty of
-course). If it can't for some reason, then it should raise an error
-via die().
-
- sub my_todo_template {
- die "This template not yet implemented\n";
- }
-
-If it wants to get fancy, it can raise an error as a
-Template::Exception object. An exception object is really just a
-convenient wrapper for the 'type' and 'info' fields.
-
- sub my_solilique_template {
- die (Template::Exception->new('yorrick', 'Fellow of infinite jest'));
- }
-
-Templates generally need to do a lot more than just generate static
-output or raise errors. They may want to inspect variable values,
-process another template, load a plugin, run a filter, and so on.
-Whenever a template subroutine is called, it gets passed a reference
-to a Template::Context object. It is through this context object that
-template code can access the features of the Template Toolkit.
-
-We described earlier how the Template::Service object calls on
-Template::Context to handle a process() request from the I<outside>.
-We can make a similar request on a context to process a template, but
-from within the code of another template. This is a call from the
-I<inside>.
-
- sub my_process_template {
- my $context = shift;
-
- my $output = $context->process('header', { title => 'Hello World' })
- . "\nsome content\n"
- . $context->process('footer');
- }
-
-This is then roughly equivalent to a source template something
-like this:
-
- [% PROCESS header
- title = 'Hello World'
- %]
- some content
- [% PROCESS footer %]
-
-Template variables are stored in, and managed by a B<Template::Stash>
-object. This is a blessed hash array in which template variables are
-defined. The object wrapper provides get() and set() method which
-implement all the magical.variable.features of the Template Toolkit.
-
-Each context object has its own stash, a reference to which can be
-returned by the appropriately named stash() method. So to print the
-value of some template variable, or for example, to represent the
-following source template:
-
- <title>[% title %]</title>
-
-we might have a subroutine definition something like this:
-
- sub {
- my $context = shift;
- my $stash = $context->stash();
- return '<title>' . $stash->get('title') . '</title>';
- }
-
-The stash get() method hides the details of the underlying variable
-types, automatically calling code references, checking return values,
-and performing other such tricks. If 'title' happens to be bound to a
-subroutine then we can specify additional parameters as a list
-reference passed as the second argument to get().
-
- [% title('The Cat Sat on the Mat') %]
-
-This translates to the stash get() call:
-
- $stash->get([ 'title', ['The Cat Sat on the Mat'] ]);
-
-Dotted compound variables can be requested by passing a single
-list reference to the get() method in place of the variable
-name. Each pair of elements in the list should correspond to the
-variable name and reference to a list of arguments for each
-dot-delimited element of the variable.
-
- [% foo(1, 2).bar(3, 4).baz(5) %]
-
-is thus equivalent to
-
- $stash->get([ foo => [1,2], bar => [3,4], baz => [5] ]);
-
-If there aren't any arguments for an element, you can specify an
-empty, zero or null argument list.
-
- [% foo.bar %]
- $stash->get([ 'foo', 0, 'bar', 0 ]);
-
-The set() method works in a similar way. It takes a variable
-name and a variable value which should be assigned to it.
-
- [% x = 10 %]
- $stash->set('x', 10);
-
- [% x.y = 10 %]
- $stash->set([ 'x', 0, 'y', 0 ], 10);
-
-So the stash gives us access to template variables and the context
-provides the higher level functionality. Alongside the process()
-method lies the include() method. Just as with the PROCESS / INCLUDE
-directives, the key difference is in variable localisation. Before
-processing a template, the process() method simply updates the stash
-to set any new variable definitions, overwriting any existing values.
-In contrast, the include() method creates a copy of the existing
-stash, in a process known as I<cloning> the stash, and then uses that
-as a temporary variable store. Any previously existing variables are
-still defined, but any changes made to variables, including setting
-the new variable values passed aas arguments will affect only the
-local copy of the stash (although note that it's only a shallow copy,
-so it's not foolproof). When the template has been processed, the include()
-method restores the previous variable state by I<decloning> the stash.
-
-The context also provides an insert() method to implement the INSERT
-directive, but no wrapper() method. This functionality can be implemented
-by rewriting the Perl code and calling include().
-
- [% WRAPPER foo -%]
- blah blah [% x %]
- [%- END %]
-
- $context->include('foo', {
- content => 'blah blah ' . $stash->get('x'),
- });
-
-Other than the template processing methods process(), include() and insert(),
-the context defines methods for fetching plugin objects, plugin(), and
-filters, filter().
-
- [% USE foo = Bar(10) %]
-
- $stash->set('foo', $context->plugin('Bar', [10]));
-
- [% FILTER bar(20) %]
- blah blah blah
- [% END %]
-
- my $filter = $context->filter('bar', [20]);
- &$filter('blah blah blah');
-
-Pretty much everything else you might want to do in a template can be done
-in Perl code. Things like IF, UNLESS, FOREACH and so on all have direct
-counterparts in Perl.
-
- [% IF msg %]
- Message: [% msg %]
- [% END %];
-
- if ($stash->get('msg')) {
- $output .= 'Message: ';
- $output .= $stash->get('msg');
- }
-
-The best way to get a better understanding of what's going on underneath
-the hood is to set the C<$Template::Parser::DEBUG> flag to a true value
-and start processing templates. This will cause the parser to print the
-generated Perl code for each template it compiles to STDERR. You'll
-probably also want to set the C<$Template::Directive::PRETTY> option to
-have the Perl pretty-printed for human consumption.
-
- use Template;
- use Template::Parser;
- use Template::Directive;
-
- $Template::Parser::DEBUG = 1;
- $Template::Directive::PRETTY = 1;
-
- my $template = Template->new();
- $template->process(\*DATA, { cat => 'dog', mat => 'log' });
-
- __DATA__
- The [% cat %] sat on the [% mat %]
-
-The output sent to STDOUT remains as you would expect:
-
- The dog sat on the log
-
-The output sent to STDERR would look something like this:
-
- compiled main template document block:
- sub {
- my $context = shift || die "template sub called without context\n";
- my $stash = $context->stash;
- my $output = '';
- my $error;
-
- eval { BLOCK: {
- $output .= "The ";
- $output .= $stash->get('cat');
- $output .= " sat on the ";
- $output .= $stash->get('mat');
- $output .= "\n";
- } };
- if ($@) {
- $error = $context->catch($@, \$output);
- die $error unless $error->type eq 'return';
- }
-
- return $output;
- }
-
-
-=head1 HACKING ON THE TEMPLATE TOOLKIT
-
-Please feel free to hack on the Template Toolkit. If you find a bug
-that needs fixing, if you have an idea for something that's missing,
-or you feel inclined to tackle something on the TODO list, then by all
-means go ahead and do it!
-
-If you're contemplating something non-trivial then you'll probably
-want to bring it up on the mailing list first to get an idea about the
-current state of play, find out if anyone's already working on it, and
-so on.
-
-When you start to hack on the Template Toolkit, please make sure you
-start from the latest developer release. Stable releases are uploaded
-to CPAN and have all-numerical version numbers, e.g. 2.04, 2.05.
-Developer releases are available from the Template Toolkit web site
-and have a character suffix on the version, e.g. 2.04a, 2.04b, etc.
-
-Once you've made your changes, please remember to update the test
-suite by adding extra tests to one of the existing test scripts in
-the 't' sub-directory, or by adding a new test script of your own.
-And of course, run C<make test> to ensure that all the tests pass
-with your new code.
-
-Don't forget that any files you do add will need to be added to the
-MANIFEST. Running 'make manifest' will do this for you, but you need
-to make sure you haven't got any other temporary files lying around
-that might also get added to it.
-
-Documentation is often something that gets overlooked but it's just
-as important as the code. If you're updating existing documentation
-then you should download the 'docsrc' bundle from which all the
-Template Toolkit documentation is built and make your changes in there.
-It's also available from the Template Toolkit web site. See the
-README distributed in the archive for further information.
-
-If you're adding a new module, a plugin module, for example, then it's
-OK to include the POD documentation in with the module, but I<please>
-write it all in one piece at the end of the file, I<after> the code
-(just look at any other Template::* module for an example). It's a
-religious issue, I know, but I have a strong distaste for POD documentation
-interspersed throughout the code. In my not-so-humble opinion, it makes
-both the code and the documentation harder to read (same kinda problem
-as embedding Perl in HTML).
-
-Aesthetics aside, if I do want to extract the documentation into the
-docsrc bundle then it's easy for me to do it if it's all written in
-one chunk and extremely tedious if not. So for practical reasons
-alone, please keep Perl and POD sections separate. Comment blocks
-within the code are of course welcome.
-
-To share your changes with the rest of the world, you'll need to
-prepare a patch file. To do this you should have 2 directories
-side-by-side, one which is the original, unmodified distribution
-directory for the latest developer release, and the other is a
-copy of that same directory which includes your changes.
-
-The following example shows a typical hacking session. First we
-unpack the latest developer release.
-
- $ tar zxf Template-Toolkit-2.05c.tar.gz
-
-At this point, it's a good idea to rename the directory to give
-some indicate of what it contains.
-
- $ mv Template-Toolkit-2.05c Template-Toolkit-2.05c-abw-xyz-hack
-
-Then go hack!
-
- $ cd Template-Toolkit-2.05c-abw-xyz-hack
-
- [ hacking ]
-
- $ cd ..
-
-When you're all done and ready to prepare a patch, unpack the
-distribution archive again so that you've got the original to
-diff against your new code.
-
- $ tar zxf Template-Toolkit-2.05c.tar.gz
-
-You should now have an original distribution directory and a modified
-version of that same directory, side-by-side.
-
- $ ls
- Template-Toolkit-2.05c Template-Toolkit-2.05c-abw-xyz-hack
-
-Now run diff and save the output into an appropriately named patch
-file.
-
- $ diff -Naur Template-Toolkit-2.05c Template-Toolkit-2.05c-abw-xyz-hack > patch-TT205c-abw-xyz-hack
-
-You can then post the generated patch file to the mailing list,
-describing what it does, why it does it, how it does it and any
-other relevant information.
-
-If you want to apply someone else's patch then you should start with the
-same original distribution source on which the patch is based. From within
-the root of the distribution, run 'patch' feeding in the patch file as
-standard input. The 'p1' option is required to strip the first element
-of the path name (e.g. Template-Toolkit-2.05c/README becomes README which
-is then the correct path).
-
- $ tar zxf Template-Toolkit-2.05c.tar.gz
- $ cd Template-Toolkit-2.05c
- $ patch -p1 < ../patch-TT205c-abw-xyz-hack
-
-The output generated by 'patch' should be something like the following:
-
- patching file README
- patching file lib/Template.pm
- patching file lib/Template/Provider.pm
- patching file t/provider.t
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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:
diff --git a/lib/Template/Manual/Intro.pod b/lib/Template/Manual/Intro.pod
deleted file mode 100644
index c50c9e8..0000000
--- a/lib/Template/Manual/Intro.pod
+++ /dev/null
@@ -1,295 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Manual::Intro
-#
-# DESCRIPTION
-# This section provides a general introduction to the Template
-# Toolkit, giving a quick overview of features, examples of template
-# directives and use of the Template.pm module. It also described the
-# basic concept underlying the toolkit: the separation of
-# presentation elements from application logic and data.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-#
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Manual::Intro - Introduction to the Template Toolkit
-
-=head1 DESCRIPTION
-
-This section provides a general introduction to the Template Toolkit,
-giving a quick overview of features, examples of template directives
-and use of the Template.pm module. It also described the basic concept
-underlying the toolkit: the separation of presentation elements from
-application logic and data.
-
-The Template Toolkit is a collection of modules which implement a
-fast, flexible, powerful and extensible template processing system.
-It was originally designed and remains primarily useful for generating
-dynamic web content, but it can be used equally well for processing
-any kind of text documents. This POD documentation is all generated
-using the Template Toolkit batch mode utility F<ttree>, for example.
-
-At the simplest level it provides an easy way to process template
-files, filling in embedded variable references with their equivalent
-values.
-
- Dear [% name %],
-
- It has come to our attention that your account is in
- arrears to the sum of [% debt %].
-
- Please settle your account before [% deadline %] or we
- will be forced to revoke your Licence to Thrill.
-
- The Management.
-
-By default, template directives are embedded within the character
-sequences '[%' ... '%]' but you can change these and various other
-options to configure how the Template Toolkit looks, feels and works.
-You can set the INTERPOLATE option, for example, if you prefer to
-embed your variables in Perl style:
-
- Dear $name,
-
- It has come to our attention that your account is in
- arrears to the sum of $debt.
- ...
-
-=head2 Template.pm
-
-The Template.pm module is the front end to the Template Toolkit,
-providing access to the full range of functionality through a single
-module with a simple interface. It loads the other modules as
-required and instantiates a default set of objects to handle
-subsequent template processing requests. Configuration parameters may
-be passed to the Template.pm constructor, new(), which are then used
-to configure the underlying objects.
-
- use Template;
-
- my $tt = Template->new({
- INCLUDE_PATH => '/usr/local/templates',
- INTERPOLATE => 1,
- }) || die "$Template::ERROR\n";
-
-The Template object implements a process() method for processing template
-files or text. The name of the input template (or various other sources)
-is passed as the first argument, followed by a reference to a hash array
-of variable definitions for substitution in the template.
-
- my $vars = {
- name => 'Count Edward van Halen',
- debt => '3 riffs and a solo',
- deadline => 'the next chorus',
- };
-
- $tt->process('letters/overdrawn', $vars)
- || die $tt->error(), "\n";
-
-
-The process() method returns true (1) on success and prints the
-template output to STDOUT, by default. On error, the process() method
-returns false (undef). The error() method can then be called to
-retrieve details of the error.
-
-=head2 Component Based Content Construction
-
-A number of special directives are provided, such as INSERT, INCLUDE
-and PROCESS, which allow content to be built up from smaller template
-components. This permits a modular approach to building a web site or
-other content repository, promoting reusability, cross-site
-consistency, ease of construction and subsequent maintenance. Common
-elements such as headers, footers, menu bars, tables, and so on, can
-be created as separate template files which can then be processed into
-other documents as required. All defined variables are inherited by
-these templates along with any additional "local" values specified.
-
- [% PROCESS header
- title = "The Cat Sat on the Mat"
- %]
-
- [% PROCESS menu %]
-
- The location of the missing feline has now been established.
- Thank you for your assistance.
-
- [% INSERT legal/disclaimer %]
-
- [% PROCESS footer %]
-
-You can also define a template as a BLOCK within the same file and
-PROCESS it just like any other template file. This can be invaluable
-for building up repetitive elements such as tables, menus, etc.
-
- [% BLOCK tabrow %]
- <tr><td>[% name %]</td><td>[% email %]</td></tr>
- [% END %]
-
- <table>
- [% PROCESS tabrow name="tom" email="tom@here.org" %]
- [% PROCESS tabrow name="dick" email="disk@there.org" %]
- [% PROCESS tabrow name="larry" email="larry@where.org" %]
- </table>
-
-=head2 Data and Code Binding
-
-One of the key features that sets the Template Toolkit apart from
-other template processors is the ability to bind template variables to
-any kind of Perl data: scalars, lists, hash arrays, sub-routines and
-objects.
-
- my $vars = {
- root => 'http://here.com/there',
- menu => [ 'modules', 'authors', 'scripts' ],
- client => {
- name => 'Doctor Joseph von Satriani',
- id => 'JVSAT',
- },
- checkout => sub { my $total = shift; ...; return $something },
- shopcart => My::Cool::Shopping::Cart->new(),
- };
-
-The Template Toolkit will automatically Do The Right Thing to access
-the data in an appropriate manner to return some value which can then
-be output. The dot operator '.' is used to access into lists and
-hashes or to call object methods. The FOREACH directive is provided for
-iterating through lists, and various logical tests are available using
-directives such as IF, UNLESS, ELSIF, ELSE, SWITCH, CASE, etc.
-
- [% FOREACH section = menu %]
- <a href="[% root %]/[% section %]/index.html">[% section %]</a>
- [% END %]
-
- <b>Client</a>: [% client.name %] (id: [% client.id %])
-
- [% IF shopcart.nitems %]
- Your shopping cart contains the following items:
- <ul>
- [% FOREACH item = shopcart.contents %]
- <li>[% item.name %] : [% item.qty %] @ [% item.price %]
- [% END %]
- </ul>
-
- [% checkout(shopcart.total) %]
-
- [% ELSE %]
- No items currently in shopping cart.
- [% END %]
-
-=head2 Advanced Features: Filters, Macros, Exceptions, Plugins
-
-The Template Toolkit also provides a number of additional directives
-for advanced processing and programmatical functionality. It supports
-output filters (FILTER), allows custom macros to be defined (MACRO),
-has a fully-featured exception handling system (TRY, THROW, CATCH,
-FINAL) and supports a plugin architecture (USE) which allows special
-plugin modules and even regular Perl modules to be loaded and used
-with the minimum of fuss. The Template Toolkit is "just" a template
-processor but you can trivially extend it to incorporate the
-functionality of any Perl module you can get your hands on. Thus, it
-is also a scalable and extensible template framework, ideally suited
-for managing the presentation layer for application servers, content
-management systems and other web applications.
-
-=head2 Separating Presentation and Application Logic
-
-Rather than embedding Perl code or some other scripting language
-directly into template documents, it encourages you to keep functional
-components (i.e. Perl code) separate from presentation components
-(e.g. HTML templates). The template variables provide the interface
-between the two layers, allowing data to be generated in code and then
-passed to a template component for displaying (pipeline model) or for
-sub-routine or object references to be bound to variables which can
-then be called from the template as and when required (callback
-model).
-
-The directives that the Template Toolkit provide implement their own
-mini programming language, but they're not really designed for
-serious, general purpose programming. Perl is a far more appropriate
-language for that. If you embed application logic (e.g. Perl or other
-scripting language fragments) in HTML templates then you risk losing
-the clear separation of concerns between functionality and
-presentation. It becomes harder to maintain the two elements in
-isolation and more difficult, if not impossible, to reuse code or
-presentation elements by themselves. It is far better to write your
-application code in separate Perl modules, libraries or scripts and
-then use templates to control how the resulting data is presented as
-output. Thus you should think of the Template Toolkit language as a
-set of layout directives for displaying data, not calculating it.
-
-Having said that, the Template Toolkit doesn't force you into one
-approach or the other. It attempts to be pragmatic rather than
-dogmatic in allowing you to do whatever best gets the job done.
-Thus, if you enable the EVAL_PERL option then you can happily embed
-real Perl code in your templates within PERL ... END directives.
-
-=head2 Performance
-
-The Template Toolkit uses a fast YACC-like parser which compiles
-templates into Perl code for maximum runtime efficiency. It also has
-an advanced caching mechanism which manages in-memory and on-disk
-(i.e. persistent) versions of compiled templates. The modules that
-comprise the toolkit are highly configurable and the architecture
-around which they're built is designed to be extensible. The Template
-Toolkit provides a powerful framework around which content creation
-and delivery systems can be built while also providing a simple
-interface through the Template front-end module for general use.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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:
diff --git a/lib/Template/Manual/Plugins.pod b/lib/Template/Manual/Plugins.pod
deleted file mode 100644
index 7955640..0000000
--- a/lib/Template/Manual/Plugins.pod
+++ /dev/null
@@ -1,552 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Manual::Plugins
-#
-# DESCRIPTION
-# This section lists the standard plugins which can be used to extend
-# the runtime functionality of the Template Toolkit. The plugins are
-# distributed with the Template Toolkit but may required additional
-# modules from CPAN.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-#
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Manual::Plugins - Standard plugins
-
-=head1 DESCRIPTION
-
-This section lists the standard plugins which can be used to extend the
-runtime functionality of the Template Toolkit. The plugins are
-distributed with the Template Toolkit but may required additional
-modules from CPAN.
-
-
-
-=head1 TEMPLATE TOOLKIT PLUGINS
-
-The following plugin modules are distributed with the Template
-Toolkit. Some of the plugins interface to external modules (detailed
-below) which should be downloaded from any CPAN site and installed
-before using the plugin.
-
-=head2 Autoformat
-
-The Autoformat plugin is an interface to Damian Conway's Text::Autoformat
-Perl module which provides advanced text wrapping and formatting. See
-L<Template::Plugin::Autoformat> and L<Text::Autoformat> for further
-details.
-
- [% USE autoformat(left=10, right=20) %]
- [% autoformat(mytext) %] # call autoformat sub
- [% mytext FILTER autoformat %] # or use autoformat filter
-
-The Text::Autoformat module is available from CPAN:
-
- http://www.cpan.org/modules/by-module/Text/
-
-=head2 CGI
-
-The CGI plugin is a wrapper around Lincoln Stein's
-E<lt>lstein@genome.wi.mit.eduE<gt> CGI.pm module. The plugin is
-distributed with the Template Toolkit (see L<Template::Plugin::CGI>)
-and the CGI module itself is distributed with recent versions Perl,
-or is available from CPAN.
-
- [% USE CGI %]
- [% CGI.param('param_name') %]
- [% CGI.start_form %]
- [% CGI.popup_menu( Name => 'color',
- Values => [ 'Green', 'Brown' ] ) %]
- [% CGI.end_form %]
-
-=head2 Datafile
-
-Provides an interface to data stored in a plain text file in a simple
-delimited format. The first line in the file specifies field names
-which should be delimiter by any non-word character sequence.
-Subsequent lines define data using the same delimiter as int he first
-line. Blank lines and comments (lines starting '#') are ignored. See
-L<Template::Plugin::Datafile> for further details.
-
-/tmp/mydata:
-
- # define names for each field
- id : email : name : tel
- # here's the data
- fred : fred@here.com : Fred Smith : 555-1234
- bill : bill@here.com : Bill White : 555-5678
-
-example:
-
- [% USE userlist = datafile('/tmp/mydata') %]
-
- [% FOREACH user = userlist %]
- [% user.name %] ([% user.id %])
- [% END %]
-
-=head2 Date
-
-The Date plugin provides an easy way to generate formatted time and date
-strings by delegating to the POSIX strftime() routine. See
-L<Template::Plugin::Date> and L<POSIX> for further details.
-
- [% USE date %]
- [% date.format %] # current time/date
-
- File last modified: [% date.format(template.modtime) %]
-
-=head2 Directory
-
-The Directory plugin provides a simple interface to a directory and
-the files within it. See L<Template::Plugin::Directory> for further
-details.
-
- [% USE dir = Directory('/tmp') %]
- [% FOREACH file = dir.files %]
- # all the plain files in the directory
- [% END %]
- [% FOREACH file = dir.dirs %]
- # all the sub-directories
- [% END %]
-
-=head2 DBI
-
-The DBI plugin, developed by Simon Matthews
-E<lt>sam@knowledgepool.comE<gt>, brings the full power of Tim Bunce's
-E<lt>Tim.Bunce@ig.co.ukE<gt> database interface module (DBI) to your
-templates. See L<Template::Plugin::DBI> and L<DBI> for further details.
-
- [% USE DBI('dbi:driver:database', 'user', 'pass') %]
-
- [% FOREACH user = DBI.query( 'SELECT * FROM users' ) %]
- [% user.id %] [% user.name %]
- [% END %]
-
-The DBI and relevant DBD modules are available from CPAN:
-
- http://www.cpan.org/modules/by-module/DBI/
-
-=head2 Dumper
-
-The Dumper plugin provides an interface to the Data::Dumper module. See
-L<Template::Plugin::Dumper> and L<Data::Dumper> for futher details.
-
- [% USE dumper(indent=0, pad="<br>") %]
- [% dumper.dump(myvar, yourvar) %]
-
-=head2 File
-
-The File plugin provides a general abstraction for files and can be
-used to fetch information about specific files within a filesystem.
-See L<Template::Plugin::File> for further details.
-
- [% USE File('/tmp/foo.html') %]
- [% File.name %] # foo.html
- [% File.dir %] # /tmp
- [% File.mtime %] # modification time
-
-=head2 Filter
-
-This module implements a base class plugin which can be subclassed
-to easily create your own modules that define and install new filters.
-
- package MyOrg::Template::Plugin::MyFilter;
-
- use Template::Plugin::Filter;
- use base qw( Template::Plugin::Filter );
-
- sub filter {
- my ($self, $text) = @_;
-
- # ...mungify $text...
-
- return $text;
- }
-
- # now load it...
- [% USE MyFilter %]
-
- # ...and use the returned object as a filter
- [% FILTER $MyFilter %]
- ...
- [% END %]
-
-See L<Template::Plugin::Filter> for further details.
-
-=head2 Format
-
-The Format plugin provides a simple way to format text according to a
-printf()-like format. See L<Template::Plugin::Format> for further
-details.
-
- [% USE bold = format('<b>%s</b>') %]
- [% bold('Hello') %]
-
-=head2 GD::Image, GD::Polygon, GD::Constants
-
-These plugins provide access to the GD graphics library via Lincoln
-D. Stein's GD.pm interface. These plugins allow PNG, JPEG and other
-graphical formats to be generated.
-
- [% FILTER null;
- USE im = GD.Image(100,100);
- # allocate some colors
- black = im.colorAllocate(0, 0, 0);
- red = im.colorAllocate(255,0, 0);
- blue = im.colorAllocate(0, 0, 255);
- # Draw a blue oval
- im.arc(50,50,95,75,0,360,blue);
- # And fill it with red
- im.fill(50,50,red);
- # Output image in PNG format
- im.png | stdout(1);
- END;
- -%]
-
-See L<Template::Plugin::GD::Image> for further details.
-
-=head2 GD::Text, GD::Text::Align, GD::Text::Wrap
-
-These plugins provide access to Martien Verbruggen's GD::Text,
-GD::Text::Align and GD::Text::Wrap modules. These plugins allow the
-layout, alignment and wrapping of text when drawing text in GD images.
-
- [% FILTER null;
- USE gd = GD.Image(200,400);
- USE gdc = GD.Constants;
- black = gd.colorAllocate(0, 0, 0);
- green = gd.colorAllocate(0, 255, 0);
- txt = "This is some long text. " | repeat(10);
- USE wrapbox = GD.Text.Wrap(gd,
- line_space => 4,
- color => green,
- text => txt,
- );
- wrapbox.set_font(gdc.gdMediumBoldFont);
- wrapbox.set(align => 'center', width => 160);
- wrapbox.draw(20, 20);
- gd.png | stdout(1);
- END;
- -%]
-
-See L<Template::Plugin::GD::Text>, L<Template::Plugin::GD::Text::Align>
-and L<Template::Plugin::GD::Text::Wrap> for further details.
-
-=head2 GD::Graph::lines, GD::Graph::bars, GD::Graph::points, GD::Graph::linespoin
-ts, GD::Graph::area, GD::Graph::mixed, GD::Graph::pie
-
-These plugins provide access to Martien Verbruggen's GD::Graph module
-that allows graphs, plots and charts to be created. These plugins allow
-graphs, plots and charts to be generated in PNG, JPEG and other
-graphical formats.
-
- [% FILTER null;
- data = [
- ["1st","2nd","3rd","4th","5th","6th"],
- [ 4, 2, 3, 4, 3, 3.5]
- ];
- USE my_graph = GD.Graph.pie(250, 200);
- my_graph.set(
- title => 'A Pie Chart',
- label => 'Label',
- axislabelclr => 'black',
- pie_height => 36,
- transparent => 0,
- );
- my_graph.plot(data).png | stdout(1);
- END;
- -%]
-
-See
-L<Template::Plugin::GD::Graph::lines>,
-L<Template::Plugin::GD::Graph::bars>,
-L<Template::Plugin::GD::Graph::points>,
-L<Template::Plugin::GD::Graph::linespoints>,
-L<Template::Plugin::GD::Graph::area>,
-L<Template::Plugin::GD::Graph::mixed>,
-L<Template::Plugin::GD::Graph::pie>, and
-L<GD::Graph>,
-for more details.
-
-=head2 GD::Graph::bars3d, GD::Graph::lines3d, GD::Graph::pie3d
-
-These plugins provide access to Jeremy Wadsack's GD::Graph3d
-module. This allows 3D bar charts and 3D lines plots to
-be generated.
-
- [% FILTER null;
- data = [
- ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"],
- [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4],
- ];
- USE my_graph = GD.Graph.bars3d();
- my_graph.set(
- x_label => 'X Label',
- y_label => 'Y label',
- title => 'A 3d Bar Chart',
- y_max_value => 8,
- y_tick_number => 8,
- y_label_skip => 2,
- # shadows
- bar_spacing => 8,
- shadow_depth => 4,
- shadowclr => 'dred',
- transparent => 0,
- my_graph.plot(data).png | stdout(1);
- END;
- -%]
-
-See
-L<Template::Plugin::GD::Graph::lines3d>,
-L<Template::Plugin::GD::Graph::bars3d>, and
-L<Template::Plugin::GD::Graph::pie3d>
-for more details.
-
-=head2 HTML
-
-The HTML plugin is very new and very basic, implementing a few useful
-methods for generating HTML. It is likely to be extended in the future
-or integrated with a larger project to generate HTML elements in a generic
-way (as discussed recently on the mod_perl mailing list).
-
- [% USE HTML %]
- [% HTML.escape("if (a < b && c > d) ..." %]
- [% HTML.attributes(border => 1, cellpadding => 2) %]
- [% HTML.element(table => { border => 1, cellpadding => 2 }) %]
-
-See L<Template::Plugin::HTML> for further details.
-
-=head2 Iterator
-
-The Iterator plugin provides a way to create a Template::Iterator
-object to iterate over a data set. An iterator is created
-automatically by the FOREACH directive and is aliased to the 'loop'
-variable. This plugin allows an iterator to be explicitly created
-with a given name, or the default plugin name, 'iterator'. See
-L<Template::Plugin::Iterator> for further details.
-
- [% USE iterator(list, args) %]
-
- [% FOREACH item = iterator %]
- [% '<ul>' IF iterator.first %]
- <li>[% item %]
- [% '</ul>' IF iterator.last %]
- [% END %]
-
-=head2 Pod
-
-This plugin provides an interface to the L<Pod::POM|Pod::POM> module
-which parses POD documents into an internal object model which can
-then be traversed and presented through the Template Toolkit.
-
- [% USE Pod(podfile) %]
-
- [% FOREACH head1 = Pod.head1;
- FOREACH head2 = head1/head2;
- ...
- END;
- END
- %]
-
-=head2 String
-
-The String plugin implements an object-oriented interface for
-manipulating strings. See L<Template::Plugin::String> for further
-details.
-
- [% USE String 'Hello' %]
- [% String.append(' World') %]
-
- [% msg = String.new('Another string') %]
- [% msg.replace('string', 'text') %]
-
- The string "[% msg %]" is [% msg.length %] characters long.
-
-=head2 Table
-
-The Table plugin allows you to format a list of data items into a
-virtual table by specifying a fixed number of rows or columns, with
-an optional overlap. See L<Template::Plugin::Table> for further
-details.
-
- [% USE table(list, rows=10, overlap=1) %]
-
- [% FOREACH item = table.col(3) %]
- [% item %]
- [% END %]
-
-=head2 URL
-
-The URL plugin provides a simple way of contructing URLs from a base
-part and a variable set of parameters. See L<Template::Plugin::URL>
-for further details.
-
- [% USE mycgi = url('/cgi-bin/bar.pl', debug=1) %]
-
- [% mycgi %]
- # ==> /cgi/bin/bar.pl?debug=1
-
- [% mycgi(mode='submit') %]
- # ==> /cgi/bin/bar.pl?mode=submit&debug=1
-
-=head2 Wrap
-
-The Wrap plugin uses the Text::Wrap module by David Muir Sharnoff
-E<lt>muir@idiom.comE<gt> (with help from Tim Pierce and many many others)
-to provide simple paragraph formatting. See L<Template::Plugin::Wrap>
-and L<Text::Wrap> for further details.
-
- [% USE wrap %]
- [% wrap(mytext, 40, '* ', ' ') %] # use wrap sub
- [% mytext FILTER wrap(40) -%] # or wrap FILTER
-
-The Text::Wrap module is available from CPAN:
-
- http://www.cpan.org/modules/by-module/Text/
-
-=head2 XML::DOM
-
-The XML::DOM plugin gives access to the XML Document Object Module via
-Clark Cooper E<lt>cooper@sch.ge.comE<gt> and Enno Derksen's
-E<lt>enno@att.comE<gt> XML::DOM module. See L<Template::Plugin::XML::DOM>
-and L<XML::DOM> for further details.
-
- [% USE dom = XML.DOM %]
- [% doc = dom.parse(filename) %]
-
- [% FOREACH node = doc.getElementsByTagName('CODEBASE') %]
- * [% node.getAttribute('href') %]
- [% END %]
-
-The plugin requires the XML::DOM module, available from CPAN:
-
- http://www.cpan.org/modules/by-module/XML/
-
-=head2 XML::RSS
-
-The XML::RSS plugin is a simple interface to Jonathan Eisenzopf's
-E<lt>eisen@pobox.comE<gt> XML::RSS module. A RSS (Rich Site Summary)
-file is typically used to store short news 'headlines' describing
-different links within a site. This plugin allows you to parse RSS
-files and format the contents accordingly using templates.
-See L<Template::Plugin::XML::RSS> and L<XML::RSS> for further details.
-
- [% USE news = XML.RSS(filename) %]
-
- [% FOREACH item = news.items %]
- <a href="[% item.link %]">[% item.title %]</a>
- [% END %]
-
-The XML::RSS module is available from CPAN:
-
- http://www.cpan.org/modules/by-module/XML/
-
-=head2 XML::Simple
-
-This plugin implements an interface to the L<XML::Simple|XML::Simple>
-module.
-
- [% USE xml = XML.Simple(xml_file_or_text) %]
-
- [% xml.head.title %]
-
-See L<Template::Plugin::XML::Simple> for further details.
-
-=head2 XML::Style
-
-This plugin defines a filter for performing simple stylesheet based
-transformations of XML text.
-
- [% USE xmlstyle
- table = {
- attributes = {
- border = 0
- cellpadding = 4
- cellspacing = 1
- }
- }
- %]
-
- [% FILTER xmlstyle %]
- <table>
- <tr>
- <td>Foo</td> <td>Bar</td> <td>Baz</td>
- </tr>
- </table>
- [% END %]
-
-See L<Template::Plugin::XML::Style> for further details.
-
-=head2 XML::XPath
-
-The XML::XPath plugin provides an interface to Matt Sergeant's
-E<lt>matt@sergeant.orgE<gt> XML::XPath module. See
-L<Template::Plugin::XML::XPath> and L<XML::XPath> for further details.
-
- [% USE xpath = XML.XPath(xmlfile) %]
- [% FOREACH page = xpath.findnodes('/html/body/page') %]
- [% page.getAttribute('title') %]
- [% END %]
-
-The plugin requires the XML::XPath module, available from CPAN:
-
- http://www.cpan.org/modules/by-module/XML/
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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:
diff --git a/lib/Template/Manual/Refs.pod b/lib/Template/Manual/Refs.pod
deleted file mode 100644
index b0c9719..0000000
--- a/lib/Template/Manual/Refs.pod
+++ /dev/null
@@ -1,171 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Manual::Refs
-#
-# DESCRIPTION
-# This section provides references to external modules, projects and
-# other resources related to the Template Toolkit.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-#
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Manual::Refs - Related modules, projects and other resources
-
-=head1 DESCRIPTION
-
-This section provides references to external modules, projects and
-other resources related to the Template Toolkit.
-
-=head2 Resources
-
-The Template Toolkit web site contains the latest information, news and
-other resources.
-
- http://www.template-toolkit.org/
-
-A mailing list exists for up-to-date information on the Template Toolkit
-and for following and contributing to the development process. To
-subscribe, send an email to
-
- templates-request@template-toolkit.org
-
-with the message 'subscribe' in the body. You can also use the web
-interface to subscribe or browse the archives:
-
- http://www.template-toolkit.org/mailman/listinfo/templates
-
-The F<tpage> and F<ttree> scripts are distributed and installed along
-with the Template Toolkit. The F<tpage> script simply processes named
-files or STDIN if unspecified, using a default Template object. The
-F<ttree> script can be used to process entire directory trees of templates,
-allowing large content systems such as web sites to be rebuilt from a
-single command or configuration file.
-
- perldoc tpage
- perldoc ttree
-
-The F<Template::Tutorial> document provides an introduction to the Template
-Toolkit and shows some typical examples of usage.
-
- perldoc Template::Tutorial
-
-You may also like to consult the paper 'Building and Managing Web Systems
-with the Template Toolkit' and accompanying slides from the presentation
-at the 4th Perl Conference. These are available from the Template
-Toolkit web site:
-
- http://www.template-toolkit.org/docs.html
-
-
-
-=head2 Projects
-
-There are a number of other projects related to the Template Toolkit.
-
-=over 4
-
-=item OpenInteract
-
-OpenInteract is a robust web application framework built to run under
-Apache and mod_perl using the Template Toolkit as a foundation.
-
- http://www.openinteract.org/
-
-=item Apache::Template
-
-This is an Apache/mod_perl interface to the Template Toolkit. Available
-from CPAN in the directory:
-
- http://www.cpan.org/modules/by-module/Apache/
-
-=item AxKit::Template
-
-AxKit is Matt Sergeant's Apache XML Delivery Toolkit. AxKit::Template
-provides an interface between AxKit and the Template Toolkit. Available
-from CPAN in the directory:
-
- http://www.cpan.org/modules/by-module/Apache/
-
-=item Slashcode
-
-Slashcode is the code which runs Slashdot. Version 2 uses the
-Template Toolkit for generating the user interface from database
-driven template.
-
- http://slashcode.org/
-
-=item OpenFrame
-
-OpenFrame is an open source application framework for distributed
-media applications. It ships with a generator for the Template
-Toolkit.
-
- http://openframe.fotango.com/
-
-=item PCMT
-
-PCMT is the Personal Content Management Toolkit. It uses the Template
-Toolkit as the presentation engine.
-
- http://pcmt.sf.net/
-
-=back
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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:
diff --git a/lib/Template/Manual/Syntax.pod b/lib/Template/Manual/Syntax.pod
deleted file mode 100644
index cc1b6c8..0000000
--- a/lib/Template/Manual/Syntax.pod
+++ /dev/null
@@ -1,306 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Manual::Syntax
-#
-# DESCRIPTION
-# This section describes the syntax, structure and semantics of the
-# Template Toolkit directives and general presentation language.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-#
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Manual::Syntax - Directive syntax, structure and semantics
-
-=head1 DESCRIPTION
-
-This section describes the syntax, structure and semantics of the
-Template Toolkit directives and general presentation language.
-
-=head2 Tag Styles
-
-By default, template directives are embedded within the character sequences
-'[%' and '%]'. e.g.
-
- [% PROCESS header %]
-
- <h1>Hello World!</h1>
- <a href="[% page.next %]"><img src="[% icon.next %].gif"></a>
-
- [% PROCESS footer %]
-
-You can change the tag characters using the START_TAG, END_TAG and
-TAG_STYLE configuration options. You can also use the TAGS directive
-to define a new tag style for the current template file.
-
-You can also set the INTERPOLATE option to allow simple variable
-references to be embedded directly in templates, prefixed by a '$'.
-
- # INTERPOLATE => 0
- <td>[% name %]</td> <td>[% email %]</td>
-
- # INTERPOLATE => 1
- <td>$name</td> <td>$email</td>
-
-Directives may be embedded anywhere in a line of text and can be split
-across several lines. Insignificant whitespace is generally ignored
-within the directive.
-
- [% INCLUDE header
- title = 'Hello World'
- bgcol = '#ffffff'
- %]
-
- [%INCLUDE menu align='right'%]
-
- Name: [% name %] ([%id%])
-
-=head2 Comments
-
-The '#' character is used to indicate comments within a directive.
-When placed immediately inside the opening directive tag, it causes
-the entire directive to be ignored.
-
- [%# this entire directive is ignored no
- matter how many lines it wraps onto
- %]
-
-In any other position, it causes the remainder of the current line to
-be treated as a comment.
-
- [% # this is a comment
- theta = 20 # so is this
- rho = 30 # <aol>me too!</aol>
- %]
-
-=head2 Chomping Whitespace
-
-You can add '-' or '+' to the immediate start or end of a directive
-tag to control the whitespace chomping options. See the PRE_CHOMP and
-POST_CHOMP options for further details.
-
- [% BLOCK foo -%] # remove trailing newline
- This is block foo
- [%- END %] # remove leading newline
-
-=head2 Implicit Directives: GET and SET
-
-The simplest directives are GET and SET which retrieve and update
-variable values respectively. The GET and SET keywords are actually
-optional as the parser is smart enough to see them for what they
-really are (but note the caveat below on using side-effect notation).
-Thus, you'll generally see:
-
- [% SET foo = 10 %]
- [% GET foo %]
-
-written as:
-
- [% foo = 10 %]
- [% foo %]
-
-You can also express simple logical statements as implicit GET directives:
-
- [% title or template.title or 'Default Title' %]
-
- [% mode == 'graphics' ? "Graphics Mode Enabled" : "Text Mode" %]
-
-All other directives should start with a keyword specified in UPPER
-CASE (but see the ANYCASE option). All directives keywords are in
-UPPER CASE to make them visually distinctive and to distinguish them
-from variables of the same name but different case. It is perfectly
-valid, for example, to define a variable called 'stop' which is
-entirely separate from the STOP directive.
-
- [% stop = 'Clackett Lane Bus Depot' %]
-
- The bus will next stop at [% stop %] # variable
-
- [% STOP %] # directive
-
-=head2 Block Directives
-
-Directives such as FOREACH, WHILE, BLOCK, FILTER, etc., mark the start
-of a block which may contain text or other directives up to the
-matching END directive. Blocks may be nested indefinitely. The
-IF, UNLESS, ELSIF and ELSE directives also define blocks and may be
-grouped together in the usual manner.
-
- [% FOREACH item = [ 'foo' 'bar' 'baz' ] %]
- * Item: [% item %]
- [% END %]
-
- [% BLOCK footer %]
- Copyright 2000 [% me %]
- [% INCLUDE company/logo %]
- [% END %]
-
- [% IF foo %]
- [% FOREACH thing = foo.things %]
- [% thing %]
- [% END %]
- [% ELSIF bar %]
- [% INCLUDE barinfo %]
- [% ELSE %]
- do nothing...
- [% END %]
-
-Block directives can also be used in a convenient side-effect notation.
-
- [% INCLUDE userinfo FOREACH user = userlist %]
-
- [% INCLUDE debugtxt msg="file: $error.info"
- IF debugging %]
-
- [% "Danger Will Robinson" IF atrisk %]
-
-versus:
-
- [% FOREACH user = userlist %]
- [% INCLUDE userinfo %]
- [% END %]
-
- [% IF debugging %]
- [% INCLUDE debugtxt msg="file: $error.info" %]
- [% END %]
-
- [% IF atrisk %]
- Danger Will Robinson
- [% END %]
-
-=head2 Capturing Block Output
-
-The output of a directive can be captured by simply assigning the directive
-to a variable.
-
- [% headtext = PROCESS header title="Hello World" %]
-
- [% people = PROCESS userinfo FOREACH user = userlist %]
-
-This can be used in conjunction with the BLOCK directive for defining large
-blocks of text or other content.
-
- [% poem = BLOCK %]
- The boy stood on the burning deck,
- His fleece was white as snow.
- A rolling stone gathers no moss,
- And Keith is sure to follow.
- [% END %]
-
-Note one important caveat of using this syntax in conjunction with side-effect
-notation. The following directive does not behave as might be expected:
-
- [% var = 'value' IF some_condition %]
-
-In this case, the directive is interpreted as (spacing added for clarity)
-
- [% var = IF some_condition %]
- value
- [% END %]
-
-rather than
-
- [% IF some_condition %]
- [% var = 'value' %]
- [% END %]
-
-The variable is assigned the output of the IF block which returns
-'value' if true, but nothing if false. In other words, the following
-directive will always cause 'var' to be cleared.
-
- [% var = 'value' IF 0 %]
-
-To achieve the expected behaviour, the directive should be written as:
-
- [% SET var = 'value' IF some_condition %]
-
-=head2 Chaining Filters
-
-Multiple FILTER directives can be chained together in sequence. They
-are called in the order defined, piping the output of one into the
-input of the next.
-
- [% PROCESS somefile FILTER truncate(100) FILTER html %]
-
-The pipe character, '|', can also be used as an alias for FILTER.
-
- [% PROCESS somefile | truncate(100) | html %]
-
-=head2 Multiple Directive Blocks
-
-Multiple directives can be included within a single tag when delimited
-by semi-colons, ';'. Note however that the TAGS directive must always
-be specified in a tag by itself.
-
- [% IF title;
- INCLUDE header;
- ELSE;
- INCLUDE other/header title="Some Other Title";
- END
- %]
-
-versus
-
- [% IF title %]
- [% INCLUDE header %]
- [% ELSE %]
- [% INCLUDE other/header title="Some Other Title" %]
- [% END %]
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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:
diff --git a/lib/Template/Manual/VMethods.pod b/lib/Template/Manual/VMethods.pod
deleted file mode 100644
index 7e380fa..0000000
--- a/lib/Template/Manual/VMethods.pod
+++ /dev/null
@@ -1,529 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Manual::VMethods
-#
-# DESCRIPTION
-# The Template Toolkit provides virtual methods for manipulating
-# variable values. Most of them are analogous to regular Perl
-# functions of the same names. This section describes the different
-# virtual methods that can be applied to scalar, list and hash
-# values.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-#
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Manual::VMethods - Virtual Methods
-
-=head1 DESCRIPTION
-
-The Template Toolkit provides virtual methods for manipulating variable
-values. Most of them are analogous to regular Perl functions of the
-same names. This section describes the different virtual methods that
-can be applied to scalar, list and hash values.
-
-=head2 Scalar Virtual Methods
-
-=over 4
-
-=item defined
-
-Returns true if the value is defined.
-
- [% user = get_user(uid) IF uid.defined %]
-
-=item length
-
-Returns the length of the string representation of the item:
-
- [% IF password.length < 8 %]
- Password too short, dumbass!
- [% END %]
-
-=item repeat(n)
-
-Repeat the string a specified number of times.
-
- [% name = 'foo' %]
- [% name.repeat(3) %] # foofoofoo
-
-=item replace(search, replace)
-
-Outputs the string with all instances of the first argument (specified
-as a Perl regular expression) with the second.
-
- [% name = 'foo, bar & baz' %]
- [% name.replace('\W+', '_') %] # foo_bar_baz
-
-=item match(pattern)
-
-Performs a regular expression match on the string using the pattern
-passed as an argument. If the pattern matches the string then the
-method returns a reference to a list of any strings captured within
-parenthesis in the pattern.
-
- [% name = 'Larry Wall' %]
- [% matches = name.match('(\w+) (\w+)') %]
- [% matches.1 %], [% matches.0 %] # Wall, Larry
-
-If the pattern does not match then the method returns false, rather
-than returning an empty list which Perl and the Template Toolkit both
-consider to be a true value. This allows you to write expression like
-this.
-
- [% "We're not worthy!" IF name.match('Larry Wall') %]
-
- [% IF (matches = name.match('(\w+) (\w+)')) %]
- pattern matches: [% matches.join(', ') %]
- [% ELSE %]
- pattern does not match
- [% END %]
-
-Any regex modifiers, like C</s>, should be added in the regex using
-the C<(?s)> syntax. For example, to modify the regex to disregard
-whitespace (the C</x> switch), use:
-
- [% re = '(?x)
- (\w+)
- [ ]
- (\w+)
- ';
- matches = name.match(re);
- %]
-
-=item search(pattern)
-
-Performs a similar function to 'match' but simply returns true if the
-string matches the regular expression pattern passed as an argument.
-
- [% name = 'foo bar baz' %]
- [% name.search('bar') ? 'bar' : 'no bar' %] # bar
-
-This virtual method is now deprecated in favour of 'match'. Move along
-now, there's nothing more to see here.
-
-=item split(pattern)
-
-Calls Perl's split() function to split a string into a list of
-strings.
-
- [% FOREACH dir = mypath.split(':') %]
- [% dir %]
- [% END %]
-
-=item chunk(size)
-
-Splits the value into a list of chunks of a certain size.
-
- [% ccard_no = "1234567824683579";
- ccard_no.chunk(4).join
- %]
-
-Output:
-
- 1234 5678 2468 3579
-
-If the size is specified as a negative number then the text will
-be chunked from right-to-left. This gives the correct grouping
-for numbers, for example.
-
- [% number = 1234567;
- number.chunk(-3).join(',')
- %]
-
-Output:
-
- 1,234,567
-
-=item list
-
-Return the value as a single element list. This can be useful if you
-have a variable which may contain a single item or a list and you want
-to treat them equally. The 'list' method can be called against a list
-reference and will simply return the original reference, effectively
-a no-op.
-
- [% thing.list.size %] # thing can be a scalar or a list
-
-=item hash
-
-Return the value as a hash reference containing a single entry with
-the key 'value' indicating the original scalar value. As with the
-'list' virtual method, this is generally used to help massage data
-into different formats.
-
-=item size
-
-Always returns 1 for scalar values. This method is provided for
-consistency with the hash and list size methods.
-
-=back
-
-
-=head2 Hash Virtual Methods
-
-=over 4
-
-=item keys, values, each
-
-The regular hash operators returning lists of keys, values or both.
-Note how we use a '$' prefix on the 'key' variable in this example to
-have it interpolated (i.e. replaced with its value) before use.
-
- [% FOREACH key = product.keys %]
- [% key %] => [% product.$key %]
- [% END %]
-
-=item sort, nsort
-
-Return a list of the keys, sorted alphabetically (sort) or numerically
-(nsort) according to the corresponding values in the hash.
-
- [% FOREACH n = phones.sort %]
- [% phones.$n %] is [% n %],
- [% END %]
-
-=item import
-
-The import method can be called on a hash array to import the contents
-of another hash array.
-
- [% hash1 = {
- foo => 'Foo',
- bar => 'Bar',
- }
- hash2 = {
- wiz => 'Wiz',
- woz => 'Woz',
- }
- %]
-
- [% hash1.import(hash2) %]
- [% hash1.wiz %] # Wiz
-
-You can also call the import() method by itself to import a hash array
-into the current namespace hash.
-
- [% user = { id => 'lwall', name => 'Larry Wall' } %]
- [% import(user) %]
- [% id %]: [% name %] # lwall: Larry Wall
-
-=item defined, exists
-
-Returns a true or false value if an item in the hash denoted by the key
-passed as an argument is defined or exists, respectively.
-
- [% hash.defined('somekey') ? 'yes' : 'no' %]
- [% hash.exists('somekey') ? 'yes' : 'no' %]
-
-=item size
-
-Returns the number of key =E<gt> value pairs in the hash.
-
-=item item
-
-Returns an item from the hash using a key passed as an argument.
-
- [% hash.item('foo') %] # same as hash.foo
-
-=item list
-
-Returns the contents of the hash in list form. An argument can be
-passed to indicate the desired items required in the list: 'keys' to
-return a list of the keys (same as hash.keys), 'values' to return a
-list of the values (same as hash.values), or 'each' to return as list
-of (key, value) pairs (same as hash.each). When called without an
-argument it returns a list of hash references, each of which contains
-a 'key' and 'value' item representing a single key =E<gt> value pair
-in the hash.
-
-=back
-
-
-=head2 List Virtual Methods
-
-=over 4
-
-=item first, last
-
-Returns the first/last item in the list. The item is not removed from the
-list.
-
- [% results.first %] to [% results.last %]
-
-If either is given a numeric argument C<n>, they return the first or
-last C<n> elements:
-
- The first 5 results are [% results.first(5).join(", ") %].
-
-=item size, max
-
-Returns the size of a list (number of elements) and the maximum
-index number (size - 1), respectively.
-
- [% results.size %] search results matched your query
-
-=item reverse
-
-Returns the items of the list in reverse order.
-
- [% FOREACH s = scores.reverse %]
- ...
- [% END %]
-
-=item join
-
-Joins the items in the list into a single string, using Perl's join
-function.
-
- [% items.join(', ') %]
-
-=item grep
-
-Returns a list of the items in the list that match a regular expression
-pattern.
-
- [% FOREACH directory.files.grep('\.txt$') %]
- ...
- [% END %]
-
-=item sort, nsort
-
-Returns the items in alpha (sort) or numerical (nsort) order.
-
- [% library = books.sort %]
-
-An argument can be provided to specify a search key. Where an item in
-the list is a hash reference, the search key will be used to retrieve a
-value from the hash which will then be used as the comparison value.
-Where an item is an object which implements a method of that name, the
-method will be called to return a comparison value.
-
- [% library = books.sort('author') %]
-
-In the example, the 'books' list can contains hash references with
-an 'author' key or objects with an 'author' method.
-
-=item unshift(item), push(item)
-
-Adds an item to the start/end of a list.
-
- [% mylist.unshift('prev item') %]
- [% mylist.push('next item') %]
-
-=item shift, pop
-
-Removes the first/last item from the list and returns it.
-
- [% first = mylist.shift %]
- [% last = mylist.pop %]
-
-=item unique
-
-Returns a list of the unique elements in a list, in the same order
-as in the list itself.
-
- [% mylist = [ 1, 2, 3, 2, 3, 4, 1, 4, 3, 4, 5 ] %]
- [% numbers = mylist.unique %]
-
-While this can be explicitly sorted, it is not required that the list
-be sorted before the unique elements are pulled out (unlike the Unix
-command line utility).
-
- [% numbers = mylist.unique.sort %]
-
-=item merge
-
-Returns a list composed of zero or more other lists:
-
- [% list_one = [ 1 2 3 ];
- list_two = [ 4 5 6 ];
- list_three = [ 7 8 9 ];
- list_four = list_one.merge(list_two, list_three);
- %]
-
-The original lists are not modified.
-
-=item slice(from, to)
-
-Returns a slice of items in the list between the bounds passed as
-arguments. If the second argument, 'to', isn't specified, then it
-defaults to the last item in the list. The original list is not
-modified.
-
- [% first_three = list.slice(0,2) %]
-
- [% last_three = list.slice(-3, -1) %]
-
-=item splice(offset, length, list)
-
-Behaves just like Perl's splice() function allowing you to selectively
-remove and/or replace elements in a list. It removes 'length' items
-from the list, starting at 'offset' and replaces them with the items
-in 'list'.
-
- [% play_game = [ 'play', 'scrabble' ];
- ping_pong = [ 'ping', 'pong' ];
- redundant = play_game.splice(1, 1, ping_pong);
-
- redundant.join; # scrabble
- play_game.join; # play ping pong
- %]
-
-The method returns a list of the items removed by the splice.
-You can use the CALL directive to ignore the output if you're
-not planning to do anything with it.
-
- [% CALL play_game.splice(1, 1, ping_pong) %]
-
-As well as providing a reference to a list of replacement values,
-you can pass in a list of items.
-
- [% CALL list.splice(-1, 0, 'foo', 'bar') %]
-
-Be careful about passing just one item in as a replacement value.
-If it is a reference to a list then the contents of the list will
-be used. If it's not a list, then it will be treated as a single
-value. You can use square brackets around a single item if you
-need to be explicit:
-
- [% # push a single item, an_item
- CALL list.splice(-1, 0, an_item);
-
- # push the items from another_list
- CALL list.splice(-1, 0, another_list);
-
- # push a reference to another_list
- CALL list.splice(-1, 0, [ another_list ]);
- %]
-
-=back
-
-=head2 Automagic Promotion of Scalar to List for Virtual Methods
-
-In addition to the scalar virtual methods listed in the previous
-section, you can also call any list virtual method against a scalar.
-The item will be automagically promoted to a single element list and
-the appropriate list virtual method will be called.
-
-One particular benefit of this comes when calling subroutines or
-object methods that return a list of items, rather than the
-preferred reference to a list of items. In this case, the
-Template Toolkit automatically folds the items returned into
-a list.
-
-The upshot is that you can continue to use existing Perl modules or
-code that returns lists of items, without having to refactor it
-just to keep the Template Toolkit happy (by returning references
-to list). Class::DBI module is just one example of a particularly
-useful module which returns values this way.
-
-If only a single item is returned from a subroutine then the
-Template Toolkit assumes it meant to return a single item (rather
-than a list of 1 item) and leaves it well alone, returning the
-single value as it is. If you're executing a database query,
-for example, you might get 1 item returned, or perhaps many
-items which are then folded into a list.
-
-The FOREACH directive will happily accept either a list or a single
-item which it will treat as a list. So it's safe to write directives
-like this, where we assume that 'something' is bound to a subroutine
-which might return 1 or more items:
-
- [% FOREACH item = something %]
- ...
- [% END %]
-
-The automagic promotion of scalars to single item lists means
-that you can also use list virtual methods safely, even if you
-only get one item returned. For example:
-
- [% something.first %]
- [% something.join %]
- [% something.reverse.join(', ') %]
-
-Note that this is very much a last-ditch behaviour. If the single
-item return is an object with a 'first' method, for example, then that
-will be called, as expected, in preference to the list virtual method.
-
-=head2 Defining Custom Virtual Methods
-
-You can define your own virtual methods for scalars, lists and hash
-arrays. The Template::Stash package variables $SCALAR_OPS, $LIST_OPS
-and $HASH_OPS are references to hash arrays that define these virtual
-methods. HASH_OPS and LIST_OPS methods are subroutines that accept a
-hash/list reference as the first item. SCALAR_OPS are subroutines
-that accept a scalar value as the first item. Any other arguments
-specified when the method is called will be passed to the subroutine.
-
- # load Template::Stash to make method tables visible
- use Template::Stash;
-
- # define list method to return new list of odd numbers only
- $Template::Stash::LIST_OPS->{ odd } = sub {
- my $list = shift;
- return [ grep { $_ % 2 } @$list ];
- };
-
-template:
-
- [% primes = [ 2, 3, 5, 7, 9 ] %]
- [% primes.odd.join(', ') %] # 3, 5, 7, 9
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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:
diff --git a/lib/Template/Manual/Variables.pod b/lib/Template/Manual/Variables.pod
deleted file mode 100644
index e8d998c..0000000
--- a/lib/Template/Manual/Variables.pod
+++ /dev/null
@@ -1,868 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Manual::Variables
-#
-# DESCRIPTION
-# This section describes the different ways in which Perl data can be
-# bound to template variables and accessed via Template Toolkit
-# directives.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-#
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Manual::Variables - Template variables and code bindings
-
-=head1 DESCRIPTION
-
-This section describes the different ways in which Perl data can be
-bound to template variables and accessed via Template Toolkit
-directives.
-
-=head2 Template Variables
-
-A reference to a hash array may be passed as the second argument to
-the process() method, containing definitions of template variables.
-The VARIABLES (a.k.a. PRE_DEFINE) option can also be used to pre-define
-variables for all templates processed by the object.
-
- my $tt = Template->new({
- VARIABLES => {
- version => 3.14,
- release => 'Sahara',
- },
- });
-
- my $vars = {
- serial_no => 271828,
- };
-
- $tt->process('myfile', $vars);
-
-'myfile':
-
- This is version [% version %] ([% release %]).
- Serial number: [% serial_no %]
-
-output:
-
- This is version 3.14 (Sahara)
- Serial number: 271828
-
-Variable names may contain any alphanumeric characters or underscores.
-They may be lower, upper or mixed case although the usual convention
-is to use lower case. The case I<is> significant however, and 'foo',
-'Foo' and 'FOO' are all different variables. Upper case variable
-names are permitted, but not recommended due to a possible conflict
-with an existing or future reserved word. As of version 2.00, these
-are:
-
- GET CALL SET DEFAULT INSERT INCLUDE PROCESS WRAPPER
- IF UNLESS ELSE ELSIF FOR FOREACH WHILE SWITCH CASE
- USE PLUGIN FILTER MACRO PERL RAWPERL BLOCK META
- TRY THROW CATCH FINAL NEXT LAST BREAK RETURN STOP
- CLEAR TO STEP AND OR NOT MOD DIV END
-
-
-The variable values may be of virtually any Perl type, including
-simple scalars, references to lists, hash arrays, subroutines or
-objects. The Template Toolkit will automatically apply the correct
-procedure to accessing these values as they are used in the template.
-
-Example:
-
- my $vars = {
- article => 'The Third Shoe',
- person => {
- id => 314,
- name => 'Mr. Blue',
- email => 'blue@nowhere.org',
- },
- primes => [ 2, 3, 5, 7, 11, 13 ],
- wizard => sub { return join(' ', 'Abracadabra!', @_) },
- cgi => CGI->new('mode=submit&debug=1'),
- };
-
-template:
-
- [% article %]
-
- [% person.id %]: [% person.name %] <[% person.email %]>
-
- [% primes.first %] - [% primes.last %], including [% primes.3 %]
- [% primes.size %] prime numbers: [% primes.join(', ') %]
-
- [% wizard %]
- [% wizard('Hocus Pocus!') %]
-
- [% cgi.param('mode') %]
-
-output:
-
- The Third Shoe
-
- 314: Mr. Blue <blue@nowhere.org>
-
- 2 - 13, including 7
- 6 prime numbers: 2, 3, 5, 7, 11, 13
-
- Abracadabra!
- Abracadabra! Hocus Pocus!
-
- submit
-
-=head2 Scalar Values
-
-Regular scalar variables are accessed by simply specifying their name.
-As these are just entries in the top-level variable hash they can be
-considered special cases of hash array referencing as described below,
-with the main namespace hash automatically implied.
-
- [% article %]
-
-=head2 Hash Array References
-
-Members of hash arrays are accessed by specifying the hash reference
-and key separated by the dot '.' operator.
-
- my $vars = {
- 'home' => 'http://www.myserver.com/homepage.html',
- 'page' => {
- 'this' => 'mypage.html',
- 'next' => 'nextpage.html',
- 'prev' => 'prevpage.html',
- },
- };
-
-template:
-
- <a href="[% home %]">Home</a>
- <a href="[% page.prev %]">Previous Page</a>
- <a href="[% page.next %]">Next Page</a>
-
-output:
-
- <a href="http://www.myserver.com/homepage.html">Home</a>
- <a href="prevpage.html">Previous Page</a>
- <a href="nextpage.html">Next Page</a>
-
-Any key in a hash which starts with a '_' or '.' character will be
-considered private and cannot be evaluated or updated from within a
-template. The undefined value will be returned for any such variable
-accessed which the Template Toolkit will silently ignore (unless the
-DEBUG option is enabled).
-
- my $vars = {
- message => 'Hello World!',
- _secret => "On the Internet, no-one knows you're a dog",
- thing => {
- public => 123,
- _private => 456,
- '.hidden' => 789,
- },
- };
-
-template:
-
- [% message %] # outputs "Hello World!"
- [% _secret %] # no output
- [% thing.public %] # outputs "123"
- [% thing._private %] # no output
- [% thing..hidden %] # ERROR: unexpected token (..)
-
-To access a hash entry using a key stored in another variable, prefix
-the key variable with '$' to have it interpolated before use (see
-L<Variable Interpolation>).
-
- [% pagename = 'next' %]
- [% page.$pagename %] # same as [% page.next %]
-
-When you assign to a variable that contains multiple namespace
-elements (i.e. it has one or more '.' characters in the name),
-any hashes required to represent intermediate namespaces will be
-created automatically. In this following example, the 'product'
-variable automatically springs into life as a hash array unless
-otherwise defined.
-
- [% product.id = 'XYZ-2000'
- product.desc = 'Bogon Generator'
- product.price = 666
- %]
-
- The [% product.id %] [% product.desc %]
- costs $[% product.price %].00
-
-output:
-
- The XYZ-2000 Bogon Generator
- costs $666.00
-
-You can use Perl's familiar '{' ... '}' construct to explicitly create
-a hash and assign it to a variable. Note that commas are optional
-between key/value pairs and '=' can be used in place of '=E<gt>'.
-
- [% product = {
- id => 'XYZ-2000',
- desc => 'Bogon Generator',
- price => 666,
- }
- %]
-
-=head2 List References
-
-Items in lists are also accessed by use of the dot operator.
-
- my $vars = {
- 'people' => [ 'Tom', 'Dick', 'Larry' ],
- };
-
-template:
-
- [% people.0 %] # Tom
- [% people.1 %] # Dick
- [% people.2 %] # Larry
-
-The FOREACH directive can be used to iterate through items in a list.
-
- [% FOREACH person = people %]
- Hello [% person %]
- [% END %]
-
-output:
-
- Hello Tom
- Hello Dick
- Hello Larry
-
-Lists can be constructed in-situ using the regular anonymous list
-'[' ... ']' construct. Commas between items are optional.
-
- [% cols = [ 'red', 'green', 'blue' ] %]
-
- [% FOREACH c = cols %]
- ...
-
-or:
-
- [% FOREACH c = [ 'red', 'green', 'blue' ] %]
- ...
-
-You can also create simple numerical sequences using the familiar '..'
-operator:
-
- [% n = [ 1 .. 4 ] %] # n is [ 1, 2, 3, 4 ]
-
- [% x = 4
- y = 8
- z = [x..y] # z is [ 4, 5, 6, 7, 8 ]
- %]
-
-=head2 Subroutines
-
-Template variables can contain references to Perl subroutines. When
-the variable is used, the Template Toolkit will automatically call the
-subroutine, passing any additional arguments specified. The return
-value from the subroutine is used as the variable value and inserted
-into the document output.
-
- my $vars = {
- wizard => sub { return join(' ', 'Abracadabra!', @_) },
- };
-
-template:
-
- [% wizard %] # Abracadabra!
- [% wizard('Hocus Pocus!') %] # Abracadabra! Hocus Pocus!
-
-
-=head2 Objects
-
-Template variables can also contain references to Perl objects.
-Methods are called using the dot operator to specify the method
-against the object variable. Additional arguments can be specified
-as with subroutines.
-
- use CGI;
-
- ...
-
- my $vars = {
- # hard coded CGI params for purpose of example
- cgi => CGI->new('mode=submit&debug=1'),
- };
-
-template:
-
- [% FOREACH p = cgi.param %] # returns list of param keys
- [% p %] => [% cgi.param(p) %] # fetch each param value
- [% END %]
-
-output:
-
- mode => submit
- debug => 1
-
-Object methods can also be called as lvalues. That is, they can appear on
-the left side of an assignment. The method will be called passing the
-assigning value as an argument.
-
- [% myobj.method = 10 %]
-
-equivalent to:
-
- [% myobj.method(10) %]
-
-=head2 Parameters and Return Values
-
-Subroutines and methods will be passed any arguments specified in the
-template. Any template variables in the argument list will first be
-evaluated and their resultant values passed to the code.
-
- my $vars = {
- mycode => sub { return 'received ' . join(', ', @_) },
- };
-
-template:
-
- [% foo = 10 %]
- [% mycode(foo, 20) %] # received 10, 20
-
-Named parameters may also be specified. These are automatically collected
-into a single hash array which is passed by reference as the B<last>
-parameter to the sub-routine. Named parameters can be specified using
-either '=E<gt>' or '=' and can appear anywhere in the argument list.
-
- my $vars = {
- myjoin => \&myjoin,
- };
-
- sub myjoin {
- # look for hash ref as last argument
- my $params = ref $_[-1] eq 'HASH' ? pop : { };
- return join($params->{ joint } || ' + ', @_);
- }
-
-template:
-
- [% myjoin(10, 20, 30) %]
- [% myjoin(10, 20, 30, joint = ' - ' %]
- [% myjoin(joint => ' * ', 10, 20, 30 %]
-
-output:
-
- 10 + 20 + 30
- 10 - 20 - 30
- 10 * 20 * 30
-
-Parenthesised parameters may be added to any element of a variable,
-not just those that are bound to code or object methods. At present,
-parameters will be ignored if the variable isn't "callable" but are
-supported for future extensions. Think of them as "hints" to that
-variable, rather than just arguments passed to a function.
-
- [% r = 'Romeo' %]
- [% r(100, 99, s, t, v) %] # outputs "Romeo"
-
-User code should return a value for the variable it represents. This
-can be any of the Perl data types described above: a scalar, or
-reference to a list, hash, subroutine or object. Where code returns a
-list of multiple values the items will automatically be folded into a
-list reference which can be accessed as per normal.
-
- my $vars = {
- # either is OK, first is recommended
- items1 => sub { return [ 'foo', 'bar', 'baz' ] },
- items2 => sub { return ( 'foo', 'bar', 'baz' ) },
- };
-
-template:
-
- [% FOREACH i = items1 %]
- ...
- [% END %]
-
- [% FOREACH i = items2 %]
- ...
- [% END %]
-
-=head2 Error Handling
-
-Errors can be reported from user code by calling die(). Errors raised
-in this way are caught by the Template Toolkit and converted to
-structured exceptions which can be handled from within the template.
-A reference to the exception object is then available as the 'error'
-variable.
-
- my $vars = {
- barf => sub {
- die "a sick error has occurred\n";
- },
- };
-
-template:
-
- [% TRY %]
- [% barf %] # calls sub which throws error via die()
- [% CATCH %]
- [% error.info %] # outputs "a sick error has occurred\n"
- [% END %]
-
-Error messages thrown via die() are converted to exceptions of type
-'undef'. Exceptions of user-defined types can be thrown by calling
-die() with a reference to a Template::Exception object.
-
- use Template::Exception;
-
- ...
-
- my $vars = {
- login => sub {
- ...
- die Template::Exception->new('badpwd',
- 'password too silly');
- },
- };
-
-template:
-
- [% TRY %]
- [% login %]
- [% CATCH badpwd %]
- Bad password: [% error.info %]
- [% CATCH %]
- Some other '[% error.type %]' error: [% error.info %]
- [% END %]
-
-The exception types 'stop' and 'return' are used to implement the
-STOP and RETURN directives. Throwing an exception as:
-
- die (Template::Exception->new('stop'));
-
-has the same effect as the directive:
-
- [% STOP %]
-
-Subroutines and methods can also raise errors by returning a list or
-reference to a list containing the undefined value (undef) followed by
-an exception object or error message. This is supported for backwards
-compatibility with version 1 but may be deprecated in some future
-version.
-
- my $vars = {
- # currently equivalent
- barf => sub {
- die "I'm sorry Dave, I can't do that";
- },
- yack => sub {
- return (undef, "I'm sorry Dave, I can't do that");
- },
- };
-
-=head2 Virtual Methods
-
-The Template Toolkit implements a number of "virtual methods" which
-can be applied to scalars, hashes or lists. For example:
-
- [% mylist = [ 'foo', 'bar', 'baz' ] %]
- [% newlist = mylist.sort %]
-
-Here 'mylist' is a regular reference to a list, and 'sort' is
-a virtual method that returns a new list of the items in sorted
-order. You can chain multiple virtual methods together. For
-example:
-
- [% mylist.sort.join(', ') %]
-
-Here the 'join' virtual method is called to join the sorted list into
-a single string, generating the following output:
-
- bar, baz, foo
-
-See L<Template::Manual::VMethods> for details of all the virtual
-methods available.
-
-=head2 Variable Interpolation
-
-The Template Toolkit uses '$' consistently to indicate that a variable
-should be interpolated in position. Most frequently, you see this in
-double-quoted strings:
-
- [% fullname = "$honorific $firstname $surname" %]
-
-Or embedded in plain text when the INTERPOLATE option is set:
-
- Dear $honorific $firstname $surname,
-
-The same rules apply within directives. If a variable is prefixed
-with a '$' then it is replaced with its value before being used. The
-most common use is to retrieve an element from a hash where the key is
-stored in a variable.
-
- [% uid = 'abw' %]
- [% userlist.$uid %] # same as 'userlist.abw'
-
-Curly braces can be used to delimit interpolated variable names where
-necessary.
-
- [% userlist.${me.id}.name %]
-
-Directives such as INCLUDE, PROCESS, etc., that accept a template name
-as the first argument, will automatically quote it for convenience.
-
- [% INCLUDE foo/bar.txt %]
-
-equivalent to:
-
- [% INCLUDE "foo/bar.txt" %]
-
-To INCLUDE a template whose name is stored in a variable, simply
-prefix the variable name with '$' to have it interpolated.
-
- [% myfile = 'header' %]
- [% INCLUDE $myfile %]
-
-equivalent to:
-
- [% INCLUDE header %]
-
-Note also that a variable containing a reference to a Template::Document
-object can also be processed in this way.
-
- my $vars = {
- header => Template::Document->new({ ... }),
- };
-
-template:
-
- [% INCLUDE $header %]
-
-=head2 Local and Global Variables
-
-Any simple variables that you create, or any changes you make to
-existing variables, will only persist while the template is being
-processed. The top-level variable hash is copied before processing
-begins and any changes to variables are made in this copy, leaving the
-original intact. The same thing happens when you INCLUDE another
-template. The current namespace hash is cloned to prevent any
-variable changes made in the included template from interfering with
-existing variables. The PROCESS option bypasses the localisation step
-altogether making it slightly faster, but requiring greater attention
-to the possibility of side effects caused by creating or changing any
-variables within the processed template.
-
- [% BLOCK change_name %]
- [% name = 'bar' %]
- [% END %]
-
- [% name = 'foo' %]
- [% INCLUDE change_name %]
- [% name %] # foo
- [% PROCESS change_name %]
- [% name %] # bar
-
-Dotted compound variables behave slightly differently because the
-localisation process is only skin deep. The current variable
-namespace hash is copied, but no attempt is made to perform a
-deep-copy of other structures within it (hashes, arrays, objects,
-etc). A variable referencing a hash, for example, will be copied to
-create a new reference but which points to the same hash. Thus, the
-general rule is that simple variables (undotted variables) are
-localised, but existing complex structures (dotted variables) are not.
-
- [% BLOCK all_change %]
- [% x = 20 %] # changes copy
- [% y.z = 'zulu' %] # changes original
- [% END %]
-
- [% x = 10
- y = { z => 'zebra' }
- %]
- [% INCLUDE all_change %]
- [% x %] # still '10'
- [% y.z %] # now 'zulu'
-
-
-If you create a complex structure such as a hash or list reference
-within a local template context then it will cease to exist when
-the template is finished processing.
-
- [% BLOCK new_stuff %]
- [% # define a new 'y' hash array in local context
- y = { z => 'zulu' }
- %]
- [% END %]
-
- [% x = 10 %]
- [% INCLUDE new_stuff %]
- [% x %] # outputs '10'
- [% y %] # nothing, y is undefined
-
-Similarly, if you update an element of a compound variable which
-I<doesn't> already exists then a hash will be created automatically
-and deleted again at the end of the block.
-
- [% BLOCK new_stuff %]
- [% y.z = 'zulu' %]
- [% END %]
-
-However, if the hash I<does> already exist then you will modify the
-original with permanent effect. To avoid potential confusion, it is
-recommended that you don't update elements of complex variables from
-within blocks or templates included by another.
-
-If you want to create or update truly global variables then you can
-use the 'global' namespace. This is a hash array automatically created
-in the top-level namespace which all templates, localised or otherwise
-see the same reference to. Changes made to variables within this
-hash are visible across all templates.
-
- [% global.version = 123 %]
-
-=head2 Compile Time Constant Folding
-
-In addition to variables that get resolved each time a template is
-processed, you can also define variables that get resolved just once
-when the template is compiled. This generally results in templates
-processing faster because there is less work to be done.
-
-To define compile-time constants, specify a CONSTANTS hash as a
-constructor item as per VARIABLES. The CONSTANTS hash can contain any
-kind of complex, nested, or dynamic data structures, just like regular
-variables.
-
- my $tt = Template->new({
- CONSTANTS => {
- version => 3.14,
- release => 'skyrocket',
- col => {
- back => '#ffffff',
- fore => '#000000',
- },
- myobj => My::Object->new(),
- mysub => sub { ... },
- joint => ', ',
- },
- });
-
-Within a template, you access these variables using the 'constants'
-namespace prefix.
-
- Version [% constants.version %] ([% constants.release %])
-
- Background: [% constants.col.back %]
-
-When the template is compiled, these variable references are replaced
-with the corresponding value. No further variable lookup is then
-required when the template is processed.
-
-You can call subroutines, object methods, and even virtual methods on
-constant variables.
-
- [% constants.mysub(10, 20) %]
- [% constants.myobj(30, 40) %]
- [% constants.col.keys.sort.join(', ') %]
-
-One important proviso is that any arguments you pass to subroutines
-or methods must also be literal values or compile time constants.
-
-For example, these are both fine:
-
- # literal argument
- [% constants.col.keys.sort.join(', ') %]
-
- # constant argument
- [% constants.col.keys.sort.join(constants.joint) %]
-
-But this next example will raise an error at parse time because
-'joint' is a runtime variable and cannot be determined at compile
-time.
-
- # ERROR: runtime variable argument!
- [% constants.col.keys.sort.join(joint) %]
-
-The CONSTANTS_NAMESPACE option can be used to provide a different
-namespace prefix for constant variables. For example:
-
- my $tt = Template->new({
- CONSTANTS => {
- version => 3.14,
- # ...etc...
- },
- CONSTANTS_NAMESPACE => 'const',
- });
-
-Constants would then be referenced in templates as:
-
- [% const.version %]
-
-=head2 Special Variables
-
-A number of special variables are automatically defined by the Template
-Toolkit.
-
-=over 4
-
-=item template
-
-The 'template' variable contains a reference to the main template
-being processed, in the form of a Template::Document object. This
-variable is correctly defined within PRE_PROCESS, PROCESS and
-POST_PROCESS templates, allowing standard headers, footers, etc., to
-access metadata items from the main template. The 'name' and
-'modtime' metadata items are automatically provided, giving the
-template name and modification time in seconds since the epoch.
-
-Note that the 'template' variable always references the top-level
-template, even when processing other template components via INCLUDE,
-PROCESS, etc.
-
-=item component
-
-The 'component' variable is like 'template' but always contains a
-reference to the current, innermost template component being processed.
-In the main template, the 'template' and 'component' variable will
-reference the same Template::Document object. In any other template
-component called from the main template, the 'template' variable
-will remain unchanged, but 'component' will contain a new reference
-to the current component.
-
-This example should demonstrate the difference:
-
- $template->process('foo')
- || die $template->error(), "\n";
-
-'foo':
-
- [% template.name %] # foo
- [% component.name %] # foo
- [% PROCESS footer %]
-
-'footer':
-
- [% template.name %] # foo
- [% component.name %] # footer
-
-=item loop
-
-Within a FOREACH loop, the 'loop' variable references the Template::Iterator
-object responsible for controlling the loop.
-
- [% FOREACH item = [ 'foo', 'bar', 'baz' ] -%]
- [% "Items:\n" IF loop.first -%]
- [% loop.count %]/[% loop.size %]: [% item %]
- [% END %]
-
-=item error
-
-Within a CATCH block, the 'error' variable contains a reference to the
-Template::Exception object thrown from within the TRY block. The
-'type' and 'info' methods can be called or the variable itself can
-be printed for automatic stringification into a message of the form
-"$type error - $info". See L<Template::Exception> for further details.
-
- [% TRY %]
- ...
- [% CATCH %]
- [% error %]
- [% END %]
-
-=item content
-
-The WRAPPER method captures the output from a template block and then
-includes a named template, passing the captured output as the 'content'
-variable.
-
- [% WRAPPER box %]
- Be not afeard; the isle is full of noises,
- Sounds and sweet airs, that give delight and hurt not.
- [% END %]
-
- [% BLOCK box %]
- <table border=1>
- <tr>
- <td>
- [% content %]
- </td>
- </tr>
- </table>
- [% END %]
-
-=back
-
-=head2 Compound Variables
-
-Compound 'dotted' variables may contain any number of separate
-elements. Each element may evaluate to any of the permitted variable
-types and the processor will then correctly use this value to evaluate
-the rest of the variable. Arguments may be passed to any of the
-intermediate elements.
-
- [% myorg.people.sort('surname').first.fullname %]
-
-Intermediate variables may be used and will behave entirely as expected.
-
- [% sorted = myorg.people.sort('surname') %]
- [% sorted.first.fullname %]
-
-This simplified dotted notation has the benefit of hiding the
-implementation details of your data. For example, you could implement
-a data structure as a hash array one day and then change it to an
-object the next without requiring any change to the templates.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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:
diff --git a/lib/Template/Manual/Views.pod b/lib/Template/Manual/Views.pod
deleted file mode 100644
index 7bc53b0..0000000
--- a/lib/Template/Manual/Views.pod
+++ /dev/null
@@ -1,642 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Manual::Views
-#
-# DESCRIPTION
-# This section describes dynamic views: a powerful but experimental
-# new feature in version 2.01 of the Template Toolkit.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-#
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Manual::Views - Template Toolkit views (experimental)
-
-=head1 DESCRIPTION
-
-This section describes dynamic views: a powerful but experimental new
-feature in version 2.01 of the Template Toolkit.
-
-A view is effectively a collection of templates and/or variable
-definitions which can be passed around as a self-contained unit. This
-then represents a particular interface or presentation style for other
-objects or items of data.
-
-You can use views to implement custom "skins" for an application or
-content set. You can use them to help simplify the presentation of
-common objects or data types. You can even use then to automate the
-presentation of complex data structures such as that generated in an
-XML::DOM tree or similar. You let an iterator do the walking, and the
-view does the talking (or in this case, the presenting). Voila - you
-have view independant, structure shy traversal using templates.
-
-In general, views can be used in a number of different ways to achieve
-several different things. They elegantly solve some problems which
-were otherwise difficult or complicated, and make easy some things
-that were previously hard.
-
-At the moment, they're still very experimental. The directive syntax
-and underlying API are likely to change quite considerably over the
-next version or two. Please be very wary about building your
-multi-million dollar e-commerce solutions based around this feature.
-
-=head2 Views as Template Collectors/Providers
-
-The VIEW directive starts a view definition and includes a name by
-which the view can be referenced. The view definition continues up to
-the matching END directive.
-
- [% VIEW myview %]
- ...
- [% END %]
-
-The first role of a view is to act as a collector and provider of templates.
-The include() method can be called on a view to effectively do the same
-thing as the INCLUDE directive. The template name is passed as the first
-argument, followed by any local variable definitions for the template.
-
- [% myview.include('header', title='The Title') %]
-
- # equivalent to
- [% INCLUDE header title='The Title' %]
-
-Views accept a number of configuration options which can be used to control
-different aspects of their behaviour. The 'prefix' and 'suffix' options
-can be specified to add a fixed prefix and/or suffix to the name of each template.
-
- [% VIEW myview
- prefix = 'my/'
- suffix = '.tt2' ;
- END
- %]
-
-Now the call
-
- [% myview.include('header', title='The Title') %]
-
-is equivalent to
-
- [% INCLUDE my/header.tt2 title='The Title' %]
-
-Views provide an AUTOLOAD method which maps method names to the
-include() method. Thus, the following are all equivalent:
-
- [% myview.include('header', title='Hello World') %]
- [% myview.include_header(title='Hello World') %]
- [% myview.header(title='Hello World') %]
-
-=head2 Local BLOCK Definitions
-
-A VIEW definition can include BLOCK definitions which remain local to
-the view. A request for a particular template will return a BLOCK,
-if defined, in preference to any other template of the same name.
-
- [% BLOCK foo %]
- public foo block
- [% END %]
-
- [% VIEW plain %]
- [% BLOCK foo %]
- plain foo block
- [% END %]
- [% END %]
-
- [% VIEW fancy %]
- [% BLOCK foo %]
- fancy foo block
- [% END %]
- [% END %]
-
- [% INCLUDE foo %] # public foo block
- [% plain.foo %] # plain foo block
- [% fancy.foo %] # fancy foo block
-
-In addition to BLOCK definitions, a VIEW can contain any other
-template directives. The entire VIEW definition block is processed to
-initialise the view but no output is generated (this may change RSN -
-and get stored as 'output' item, subsequently accessible as [%
-view.output %]). However, directives that have side-effects, such as
-those that update a variable, will have noticable consequences.
-
-=head2 Preserving Variable State within Views
-
-Views can also be used to save the values of any existing variables,
-or to create new ones at the point at which the view is defined.
-Unlike simple template metadata (META) which can only contain static
-string values, the view initialisation block can contain any template
-directives and generate any kind of dynamic output and/or data items.
-
- [% VIEW my_web_site %]
- [% view.title = title or 'My Cool Web Site' %]
- [% view.author = "$abw.name, $abw.email" %]
- [% view.sidebar = INCLUDE my/sidebar.tt2 %]
- [% END %]
-
-Note that additional data items can be specified as arguments to the VIEW
-directive. Anything that doesn't look like a configuration parameter is
-assumed to be a data item. This can be a little hazardous, of course, because
-you never know when a new configuration item might get added which interferes
-with your data.
-
- [% VIEW my_web_site
- # config options
- prefix = 'my/'
- # misc data
- title = title or 'My Cool Web Site'
- author = "$abw.name, $abw.email"
- sidebar = INCLUDE my/sidebar.tt2
- %]
- ...
- [% END %]
-
-Outside of the view definition you can access the view variables as, for
-example:
-
- [% my_web_site.title %]
-
-One important feature is the equivalence of simple variables and templates.
-You can implement the view item 'title' as a simple variable, a template
-defined in an external file, possibly with a prefix/suffix automatically
-appended, or as a local BLOCK definition within the [% VIEW %] ... [% END %]
-definition. If you use the syntax above then the view will Do The Right
-Thing to return the appropriate output.
-
-At the END of the VIEW definition the view is "sealed" to prevent you
-from accidentally updating any variable values. If you attempt to change
-the value of a variable after the END of the VIEW definition block then
-an 'view' error will be thrown.
-
- [% TRY;
- my_web_site.title = 'New Title';
- CATCH;
- error;
- END
- %]
-
-The error above will be reported as:
-
- view error - cannot update item in sealed view: title
-
-The same is true if you pass a parameter to a view variable. This is
-interpreted as an attempt to update the variable and will raise the same
-warning.
-
- [% my_web_site.title('New Title') %] # view error!
-
-You can set the 'silent' parameter to have the view ignore these
-parameters and simply return the variable value.
-
- [% VIEW my_web_site
- silent = 1
- title = title or 'My Cool Web Site'
- # ... ;
- END
- %]
-
- [% my_web_site.title('Blah Blah') %] # My Cool Web Site
-
-Alternately, you can specify that a view is unsealed allowing existing
-variables to be updated and new variables defined.
-
- [% VIEW my_web_site
- sealed = 0
- title = title or 'My Cool Web Site'
- # ... ;
- END
- %]
-
- [% my_web_site.title('Blah Blah') %] # Blah Blah
- [% my_web_site.title %] # Blah Blah
-
-=head2 Inheritance, Delegation and Reuse
-
-Views can be inherited from previously defined views by use of the 'base'
-parameter. This example shows how a base class view is defined which
-applies a 'view/default/' prefix to all template names.
-
- [% VIEW my.view.default
- prefix = 'view/default/';
- END
- %]
-
-Thus the directive:
-
- [% my.view.default.header(title='Hello World') %]
-
-is now equivalent to:
-
- [% INCLUDE view/default/header title='Hello World' %]
-
-A second view can be defined which specifies the default view as a
-base.
-
- [% VIEW my.view.fancy
- base = my.view.default
- prefix = 'view/fancy/';
- END
- %]
-
-Now the directive:
-
- [% my.view.fancy.header(title='Hello World') %]
-
-will resolve to:
-
- [% INCLUDE view/fancy/header title='Hello World' %]
-
-or if that doesn't exist, it will be handled by the base view as:
-
- [% INCLUDE view/default/header title='Hello World' %]
-
-When a parent view is specified via the 'base' parameter, the
-delegation of a view to its parent for fetching templates and accessing
-user defined variables is automatic. You can also implement your own
-inheritance, delegation or other reuse patterns by explicitly
-delegating to other views.
-
- [% BLOCK foo %]
- public foo block
- [% END %]
-
- [% VIEW plain %]
- [% BLOCK foo %]
- <plain>[% PROCESS foo %]</plain>
- [% END %]
- [% END %]
-
- [% VIEW fancy %]
- [% BLOCK foo %]
- [% plain.foo | replace('plain', 'fancy') %]
- [% END %]
- [% END %]
-
- [% plain.foo %] # <plain>public foo block</plain>
- [% fancy.foo %] # <fancy>public foo block</fancy>
-
-Note that the regular INCLUDE/PROCESS/WRAPPER directives work entirely
-independantly of views and will always get the original, unaltered
-template name rather than any local per-view definition.
-
-=head2 Self-Reference
-
-A reference to the view object under definition is available with the
-VIEW ... END block by its specified name and also by the special name
-'view' (similar to the C<my $self = shift;> in a Perl method or the
-'this' pointer in C++, etc). The view is initially unsealed allowing
-any data items to be defined and updated within the VIEW ... END
-block. The view is automatically sealed at the end of the definition
-block, preventing any view data from being subsequently changed.
-
-(NOTE: sealing should be optional. As well as sealing a view to prevent
-updates (SEALED), it should be possible to set an option in the view to
-allow external contexts to update existing variables (UPDATE) or even
-create totally new view variables (CREATE)).
-
- [% VIEW fancy %]
- [% fancy.title = 'My Fancy Title' %]
- [% fancy.author = 'Frank Open' %]
- [% fancy.col = { bg => '#ffffff', bar => '#a0a0ff' } %]
- [% END %]
-
-or
-
- [% VIEW fancy %]
- [% view.title = 'My Fancy Title' %]
- [% view.author = 'Frank Open' %]
- [% view.col = { bg => '#ffffff', bar => '#a0a0ff' } %]
- [% END %]
-
-It makes no real difference in this case if you refer to the view by
-its name, 'fancy', or by the general name, 'view'. Outside of the
-view block, however, you should always use the given name, 'fancy':
-
- [% fancy.title %]
- [% fancy.author %]
- [% fancy.col.bg %]
-
-The choice of given name or 'view' is much more important when it
-comes to BLOCK definitions within a VIEW. It is generally recommended
-that you use 'view' inside a VIEW definition because this is guaranteed
-to be correctly defined at any point in the future when the block gets
-called. The original name of the view might have long since been changed
-or reused but the self-reference via 'view' should always be intact and
-valid.
-
-Take the following VIEW as an example:
-
- [% VIEW foo %]
- [% view.title = 'Hello World' %]
- [% BLOCK header %]
- Title: [% view.title %]
- [% END %]
- [% END %]
-
-Even if we rename the view, or create a new 'foo' variable, the header
-block still correctly accesses the 'title' attribute of the view to
-which it belongs. Whenever a view BLOCK is processed, the 'view'
-variable is always updated to contain the correct reference to the
-view object to which it belongs.
-
- [% bar = foo %]
- [% foo = { title => "New Foo" } %] # no problem
- [% bar.header %] # => Title: Hello World
-
-=head2 Saving References to External Views
-
-When it comes to view inheritance, it's always a good idea to take a
-local copy of a parent or delegate view and store it as an attribute
-within the view for later use. This ensures that the correct view
-reference is always available, even if the external name of a view
-has been changed.
-
- [% VIEW plain %]
- ...
- [% END %]
-
- [% VIEW fancy %]
- [% view.plain = plain %]
- [% BLOCK foo %]
- [% view.plain.foo | replace('plain', 'fancy') %]
- [% END %]
- [% END %]
-
- [% plain.foo %] # => <plain>public foo block</plain>
- [% plain = 'blah' %] # no problem
- [% fancy.foo %] # => <fancy>public foo block</fancy>
-
-
-=head2 Views as Data Presenters
-
-Another key role of a view is to act as a dispatcher to automatically
-apply the correct template to present a particular object or data
-item. This is handled via the print() method.
-
-Here's an example:
-
- [% VIEW foo %]
-
- [% BLOCK text %]
- Some text: [% item %]
- [% END %]
-
- [% BLOCK hash %]
- a hash:
- [% FOREACH key = item.keys.sort -%]
- [% key %] => [% item.$key %]
- [% END -%]
- [% END %]
-
- [% BLOCK list %]
- a list: [% item.sort.join(', ') %]
- [% END %]
-
- [% END %]
-
-We can now use the view to print text, hashes or lists. The print()
-method includes the right template depending on the typing of the
-argument (or arguments) passed.
-
- [% some_text = 'I read the news today, oh boy.' %]
- [% a_hash = { house => 'Lords', hall => 'Albert' } %]
- [% a_list = [ 'sure', 'Nobody', 'really' ] %]
-
- [% view.print(some_text) %]
- # Some text: I read the news today, oh boy.
-
- [% view.print(a_hash) %]
- # a hash:
- hall => Albert
- house => Lords
- [% view.print(a_list) %]
- # a list: Nobody, really, sure
-
-
-You can also provide templates to print objects of any other class.
-The class name is mapped to a template name with all non-word
-character sequences such as '::' converted to a single '_'.
-
- [% VIEW foo %]
- [% BLOCK Foo_Bar %]
- a Foo::Bar object:
- thingies: [% view.print(item.thingies) %]
- doodahs: [% view.print(item.doodahs) %]
- [% END %]
- [% END %]
-
- [% USE fubar = Foo::Bar(...) %]
-
- [% foo.print(fubar) %]
-
-Note how we use the view object to display various items within the
-objects ('thingies' and 'doodahs'). We don't need to worry what
-kind of data these represent (text, list, hash, etc) because we can
-let the view worry about it, automatically mapping the data type to
-the correct template.
-
-Views may define their own type =E<gt> template map.
-
- [% VIEW foo
- map = { TEXT => 'plain_text',
- ARRAY => 'show_list',
- HASH => 'show_hash',
- My::Module => 'template_name'
- default => 'any_old_data'
- }
- %]
- [% BLOCK plain_text %]
- ...
- [% END %]
-
- ...
-
- [% END %]
-
-They can also provide a 'default' map entry, specified as part of the 'map'
-hash or as a parameter by itself.
-
-
- [% VIEW foo
- map = { ... },
- default = 'whatever'
- %]
- ...
- [% END %]
-
-or
-
- [% VIEW foo %]
- [% view.map = { ... }
- view.default = 'whatever'
- %]
- ...
- [% END %]
-
-The print() method provides one more piece of magic. If you pass it a
-reference to an object which provides a present() method, then the
-method will be called passing the view as an argument. This then gives
-any object a chance to determine how it should be presented via the
-view.
-
- package Foo::Bar;
-
- ...
-
- sub present {
- my ($self, $view) = @_;
- return "a Foo::Bar object:\n"
- . "thingies: " . $view.print($self->{ _THINGIES }) . "\n"
- . "doodahs: " . $view.print($self->{ _DOODAHS }) . "\n";
- }
-
-The object is free to delve deeply into its innards and mess around with
-its own private data, before presenting the relevant data via the view.
-In a more complex example, a present() method might walk part of a tree
-making calls back against the view to present different nodes within the
-tree. We may not want to expose the internal structure of the tree
-(because that would break encapsulation and make our presentation code
-dependant on it) but we want to have some way of walking the tree and
-presenting items found in a particular manner.
-
-This is known as Structure Shy Traversal. Our view object doesn't require
-prior knowledge about the internal structure of any data set to be able
-to traverse it and present the data contained therein. The data items
-themselves, via the present() method, can implement the internal iterators
-to guide the view along the right path to presentation happiness.
-
-The upshot is that you can use views to greatly simplify the display
-of data structures like XML::DOM trees. The documentation for the
-Template::Plugins::XML::DOM module contains an example of this. In
-essence, it looks something like this:
-
-XML source:
-
- <user name="Andy Wardley">
- <project id="iCan" title="iCan, but theyCan't"/>
- <project id="p45" title="iDid, but theyDidn't"/>
- </user>
-
-TT View:
-
- [% VIEW fancy %]
- [% BLOCK user %]
- User: [% item.name %]
- [% item.content(myview) %]
- [% END %]
-
- [% BLOCK project %]
- Project: [% project.id %] - [% project.name %]
- [% END %]
- [% END %]
-
-Generate view:
-
- [% USE dom = XML.DOM %]
- [% fancy.print(dom.parse(xml_source)) %]
-
-Output:
-
- User: Andy Wardley
- Project: iCan - iCan, but theyCan't
- Project: p45 - iDid, but theyDidn't
-
-The same approach can be applied to many other areas. Here's an example from
-the File/Directory plugins.
-
- [% VIEW myview %]
- [% BLOCK file %]
- - [% item.name %]
- [% END %]
-
- [% BLOCK directory %]
- * [% item.name %]
- [% item.content(myview) FILTER indent %]
- [% END %]
- [% END %]
-
- [% USE dir = Directory(dirpath) %]
- [% myview.print(dir) %]
-
-And here's the same approach use to convert Pod documentation to any
-other format via template.
-
- [% # load Pod plugin and parse source file into Pod Object Model
- USE Pod;
- pom = Pod.parse_file(my_pod_file);
-
- # define view to map all Pod elements to "pod/html/xxx" templates
- VIEW pod2html
- prefix='pod/html';
- END;
-
- # now print document via view (i.e. as HTML)
- pod2html.print(pom)
- %]
-
-Here we simply define a template prefix for the view which causes the
-view to look for 'pod/html/head1', 'pod/html/head2', 'pod/html/over'
-as templates to present the different sections of the parsed Pod document.
-
-There are some examples in the Template Toolkit test suite: t/pod.t and
-t/view.t which may shed some more light on this. See the distribution
-sub-directory 'examples/pod/html' for examples of Pod -E<gt> HTML templates.
-
-(This documentation is incomplete but I'm not going to get it 100% pefect
-until the syntax and API stabilise).
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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:
diff --git a/lib/Template/Modules.pod b/lib/Template/Modules.pod
deleted file mode 100644
index 78dadb8..0000000
--- a/lib/Template/Modules.pod
+++ /dev/null
@@ -1,448 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Modules
-#
-# DESCRIPTION
-# This section contains the documentation for the modules that
-# comprise the Template Toolkit.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-#
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Modules - Core modules comprising the Template Toolkit
-
-=head1 DESCRIPTION
-
-This section contains the documentation for the modules that comprise
-the Template Toolkit.
-
-=over 4
-
-=item L<Template|Template>
-
-Front-end module to the Template Toolkit
-
-
-
-=item L<Template::Base|Template::Base>
-
-Base class module implementing common functionality
-
-
-
-=item L<Template::Config|Template::Config>
-
-Factory module for instantiating other TT2 modules
-
-
-
-=item L<Template::Constants|Template::Constants>
-
-Defines constants for the Template Toolkit
-
-
-
-=item L<Template::Context|Template::Context>
-
-Runtime context in which templates are processed
-
-
-
-=item L<Template::Document|Template::Document>
-
-Compiled template document object
-
-
-
-=item L<Template::Exception|Template::Exception>
-
-Exception handling class module
-
-
-
-=item L<Template::Filters|Template::Filters>
-
-Post-processing filters for template blocks
-
-
-
-=item L<Template::Iterator|Template::Iterator>
-
-Data iterator used by the FOREACH directive
-
-
-
-=item L<Template::Namespace::Constants|Template::Namespace::Constants>
-
-Compile time constant folding
-
-
-
-=item L<Template::Parser|Template::Parser>
-
-LALR(1) parser for compiling template documents
-
-
-
-=item L<Template::Plugin|Template::Plugin>
-
-Base class for Template Toolkit plugins
-
-
-
-=item L<Template::Plugins|Template::Plugins>
-
-Plugin provider module
-
-
-
-=item L<Template::Provider|Template::Provider>
-
-Provider module for loading/compiling templates
-
-
-
-=item L<Template::Service|Template::Service>
-
-General purpose template processing service
-
-
-
-=item L<Template::Stash|Template::Stash>
-
-Magical storage for template variables
-
-
-
-=item L<Template::Stash::Context|Template::Stash::Context>
-
-Experimetal stash allowing list/scalar context definition
-
-
-
-=item L<Template::Stash::XS|Template::Stash::XS>
-
-Experimetal high-speed stash written in XS
-
-
-
-=item L<Template::Test|Template::Test>
-
-Module for automating TT2 test scripts
-
-
-
-=item L<Template::Plugin::Autoformat|Template::Plugin::Autoformat>
-
-Interface to Text::Autoformat module
-
-
-
-=item L<Template::Plugin::CGI|Template::Plugin::CGI>
-
-Interface to the CGI module
-
-
-
-=item L<Template::Plugin::DBI|Template::Plugin::DBI>
-
-Template interface to the DBI module
-
-
-
-=item L<Template::Plugin::Datafile|Template::Plugin::Datafile>
-
-Plugin to construct records from a simple data file
-
-
-
-=item L<Template::Plugin::Date|Template::Plugin::Date>
-
-Plugin to generate formatted date strings
-
-
-
-=item L<Template::Plugin::Directory|Template::Plugin::Directory>
-
-Plugin for generating directory listings
-
-
-
-=item L<Template::Plugin::Dumper|Template::Plugin::Dumper>
-
-Plugin interface to Data::Dumper
-
-
-
-=item L<Template::Plugin::File|Template::Plugin::File>
-
-Plugin providing information about files
-
-
-
-=item L<Template::Plugin::Filter|Template::Plugin::Filter>
-
-Base class for plugin filters
-
-
-
-=item L<Template::Plugin::Format|Template::Plugin::Format>
-
-Plugin to create formatting functions
-
-
-
-=item L<Template::Plugin::GD::Image|Template::Plugin::GD::Image>
-
-Interface to GD Graphics Library
-
-
-
-=item L<Template::Plugin::GD::Polygon|Template::Plugin::GD::Polygon>
-
-Interface to GD module Polygon class
-
-
-
-=item L<Template::Plugin::GD::Constants|Template::Plugin::GD::Constants>
-
-Interface to GD module constants
-
-
-
-=item L<Template::Plugin::GD::Text|Template::Plugin::GD::Text>
-
-Text utilities for use with GD
-
-
-
-=item L<Template::Plugin::GD::Text::Align|Template::Plugin::GD::Text::Align>
-
-Draw aligned strings in GD images
-
-
-
-=item L<Template::Plugin::GD::Text::Wrap|Template::Plugin::GD::Text::Wrap>
-
-Break and wrap strings in GD images
-
-
-
-=item L<Template::Plugin::GD::Graph::lines|Template::Plugin::GD::Graph::lines>
-
-Create line graphs with axes and legends
-
-
-
-=item L<Template::Plugin::GD::Graph::lines3d|Template::Plugin::GD::Graph::lines3d>
-
-Create 3D line graphs with axes and legends
-
-
-
-=item L<Template::Plugin::GD::Graph::bars|Template::Plugin::GD::Graph::bars>
-
-Create bar graphs with axes and legends
-
-
-
-=item L<Template::Plugin::GD::Graph::bars3d|Template::Plugin::GD::Graph::bars3d>
-
-Create 3D bar graphs with axes and legends
-
-
-
-=item L<Template::Plugin::GD::Graph::points|Template::Plugin::GD::Graph::points>
-
-Create point graphs with axes and legends
-
-
-
-=item L<Template::Plugin::GD::Graph::linespoints|Template::Plugin::GD::Graph::linespoints>
-
-Create line/point graphs with axes and legends
-
-
-
-=item L<Template::Plugin::GD::Graph::area|Template::Plugin::GD::Graph::area>
-
-Create area graphs with axes and legends
-
-
-
-=item L<Template::Plugin::GD::Graph::mixed|Template::Plugin::GD::Graph::mixed>
-
-Create mixed graphs with axes and legends
-
-
-
-=item L<Template::Plugin::GD::Graph::pie|Template::Plugin::GD::Graph::pie>
-
-Create pie charts with legends
-
-
-
-=item L<Template::Plugin::GD::Graph::pie3d|Template::Plugin::GD::Graph::pie3d>
-
-Create 3D pie charts with legends
-
-
-
-=item L<Template::Plugin::HTML|Template::Plugin::HTML>
-
-Plugin to create HTML elements
-
-
-
-=item L<Template::Plugin::Image|Template::Plugin::Image>
-
-Plugin access to image sizes
-
-
-
-=item L<Template::Plugin::Iterator|Template::Plugin::Iterator>
-
-Plugin to create iterators (Template::Iterator)
-
-
-
-=item L<Template::Plugin::Math|Template::Plugin::Math>
-
-Plugin interface to mathematical functions
-
-
-
-=item L<Template::Plugin::Pod|Template::Plugin::Pod>
-
-Plugin interface to Pod::POM (Pod Object Model)
-
-
-
-=item L<Template::Plugin::Procedural|Template::Plugin::Procedural>
-
-Base class for procedural plugins
-
-
-
-=item L<Template::Plugin::String|Template::Plugin::String>
-
-Object oriented interface for string manipulation
-
-
-
-=item L<Template::Plugin::Table|Template::Plugin::Table>
-
-Plugin to present data in a table
-
-
-
-=item L<Template::Plugin::URL|Template::Plugin::URL>
-
-Plugin to construct complex URLs
-
-
-
-=item L<Template::Plugin::View|Template::Plugin::View>
-
-Plugin to create views (Template::View)
-
-
-
-=item L<Template::Plugin::Wrap|Template::Plugin::Wrap>
-
-Plugin interface to Text::Wrap
-
-
-
-=item L<Template::Plugin::XML::DOM|Template::Plugin::XML::DOM>
-
-Plugin interface to XML::DOM
-
-
-
-=item L<Template::Plugin::XML::RSS|Template::Plugin::XML::RSS>
-
-Plugin interface to XML::RSS
-
-
-
-=item L<Template::Plugin::XML::Simple|Template::Plugin::XML::Simple>
-
-Plugin interface to XML::Simple
-
-
-
-=item L<Template::Plugin::XML::Style|Template::Plugin::XML::Style>
-
-Simple XML stylesheet transfomations
-
-
-
-=item L<Template::Plugin::XML::XPath|Template::Plugin::XML::XPath>
-
-Plugin interface to XML::XPath
-
-
-
-
-
-=back
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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:
diff --git a/lib/Template/Namespace/Constants.pm b/lib/Template/Namespace/Constants.pm
deleted file mode 100644
index e1b5114..0000000
--- a/lib/Template/Namespace/Constants.pm
+++ /dev/null
@@ -1,205 +0,0 @@
-#================================================================= -*-Perl-*-
-#
-# Template::Namespace::Constants
-#
-# DESCRIPTION
-# Plugin compiler module for performing constant folding at compile time
-# on variables in a particular namespace.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2002 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.
-#
-# REVISION
-# $Id: Constants.pm,v 1.22 2004/01/13 16:20:36 abw Exp $
-#
-#============================================================================
-
-package Template::Namespace::Constants;
-
-use strict;
-use Template::Base;
-use Template::Config;
-use Template::Directive;
-use Template::Exception;
-
-use base qw( Template::Base );
-use vars qw( $VERSION $DEBUG );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.22 $ =~ /(\d+)\.(\d+)/);
-$DEBUG = 0 unless defined $DEBUG;
-
-
-sub _init {
- my ($self, $config) = @_;
- $self->{ STASH } = Template::Config->stash($config)
- || return $self->error(Template::Config->error());
- return $self;
-}
-
-
-
-#------------------------------------------------------------------------
-# ident(\@ident) foo.bar(baz)
-#------------------------------------------------------------------------
-
-sub ident {
- my ($self, $ident) = @_;
- my @save = @$ident;
-
- # discard first node indicating constants namespace
- splice(@$ident, 0, 2);
-
- my $nelems = @$ident / 2;
- my ($e, $result);
- local $" = ', ';
-
- print STDERR "constant ident [ @$ident ] " if $DEBUG;
-
- foreach $e (0..$nelems-1) {
- # node name must be a constant
- unless ($ident->[$e * 2] =~ s/^'(.+)'$/$1/s) {
- $self->DEBUG(" * deferred (non-constant item: ", $ident->[$e * 2], ")\n")
- if $DEBUG;
- return Template::Directive->ident(\@save);
- }
-
- # if args is non-zero then it must be eval'ed
- if ($ident->[$e * 2 + 1]) {
- my $args = $ident->[$e * 2 + 1];
- my $comp = eval "$args";
- if ($@) {
- $self->DEBUG(" * deferred (non-constant args: $args)\n") if $DEBUG;
- return Template::Directive->ident(\@save);
- }
- $self->DEBUG("($args) ") if $comp && $DEBUG;
- $ident->[$e * 2 + 1] = $comp;
- }
- }
-
-
- $result = $self->{ STASH }->get($ident);
-
- if (! length $result || ref $result) {
- my $reason = length $result ? 'reference' : 'no result';
- $self->DEBUG(" * deferred ($reason)\n") if $DEBUG;
- return Template::Directive->ident(\@save);
- }
-
- $result =~ s/'/\\'/g;
-
- $self->DEBUG(" * resolved => '$result'\n") if $DEBUG;
-
- return "'$result'";
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Namespace::Constants - Compile time constant folding
-
-=head1 SYNOPSIS
-
- # easy way to define constants
- use Template;
-
- my $tt = Template->new({
- CONSTANTS => {
- pi => 3.14,
- e => 2.718,
- },
- });
-
- # nitty-gritty, hands-dirty way
- use Template::Namespace::Constants;
-
- my $tt = Template->new({
- NAMESPACE => {
- constants => Template::Namespace::Constants->new({
- pi => 3.14,
- e => 2.718,
- },
- },
- });
-
-=head1 DESCRIPTION
-
-The Template::Namespace::Constants module implements a namespace handler
-which is plugged into the Template::Directive compiler module. This then
-performs compile time constant folding of variables in a particular namespace.
-
-=head1 PUBLIC METHODS
-
-=head2 new(\%constants)
-
-The new() constructor method creates and returns a reference to a new
-Template::Namespace::Constants object. This creates an internal stash
-to store the constant variable definitions passed as arguments.
-
- my $handler = Template::Namespace::Constants->new({
- pi => 3.14,
- e => 2.718,
- });
-
-=head2 ident(\@ident)
-
-Method called to resolve a variable identifier into a compiled form. In this
-case, the method fetches the corresponding constant value from its internal
-stash and returns it.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-1.22, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Directive|Template::Directive>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Parser.pm b/lib/Template/Parser.pm
deleted file mode 100644
index 68bf9e0..0000000
--- a/lib/Template/Parser.pm
+++ /dev/null
@@ -1,1446 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Parser
-#
-# DESCRIPTION
-# This module implements a LALR(1) parser and assocated support
-# methods to parse template documents into the appropriate "compiled"
-# format. Much of the parser DFA code (see _parse() method) is based
-# on Francois Desarmenien's Parse::Yapp module. Kudos to him.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-# The following copyright notice appears in the Parse::Yapp
-# documentation.
-#
-# The Parse::Yapp module and its related modules and shell
-# scripts are copyright (c) 1998 Francois Desarmenien,
-# France. All rights reserved.
-#
-# You may use and distribute them under the terms of either
-# the GNU General Public License or the Artistic License, as
-# specified in the Perl README file.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Parser.pm,v 2.81 2004/01/13 16:19:15 abw Exp $
-#
-#============================================================================
-
-package Template::Parser;
-
-require 5.004;
-
-use strict;
-use vars qw( $VERSION $DEBUG $ERROR );
-use base qw( Template::Base );
-use vars qw( $TAG_STYLE $DEFAULT_STYLE $QUOTED_ESCAPES );
-
-use Template::Constants qw( :status :chomp );
-use Template::Directive;
-use Template::Grammar;
-
-# parser state constants
-use constant CONTINUE => 0;
-use constant ACCEPT => 1;
-use constant ERROR => 2;
-use constant ABORT => 3;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.81 $ =~ /(\d+)\.(\d+)/);
-$DEBUG = 0 unless defined $DEBUG;
-$ERROR = '';
-
-
-#========================================================================
-# -- COMMON TAG STYLES --
-#========================================================================
-
-$TAG_STYLE = {
- 'default' => [ '\[%', '%\]' ],
- 'template1' => [ '[\[%]%', '%[\]%]' ],
- 'metatext' => [ '%%', '%%' ],
- 'html' => [ '<!--', '-->' ],
- 'mason' => [ '<%', '>' ],
- 'asp' => [ '<%', '%>' ],
- 'php' => [ '<\?', '\?>' ],
- 'star' => [ '\[\*', '\*\]' ],
-};
-$TAG_STYLE->{ template } = $TAG_STYLE->{ tt2 } = $TAG_STYLE->{ default };
-
-
-$DEFAULT_STYLE = {
- START_TAG => $TAG_STYLE->{ default }->[0],
- END_TAG => $TAG_STYLE->{ default }->[1],
-# TAG_STYLE => 'default',
- ANYCASE => 0,
- INTERPOLATE => 0,
- PRE_CHOMP => 0,
- POST_CHOMP => 0,
- V1DOLLAR => 0,
- EVAL_PERL => 0,
-};
-
-$QUOTED_ESCAPES = {
- n => "\n",
- r => "\r",
- t => "\t",
-};
-
-
-#========================================================================
-# ----- PUBLIC METHODS -----
-#========================================================================
-
-#------------------------------------------------------------------------
-# new(\%config)
-#
-# Constructor method.
-#------------------------------------------------------------------------
-
-sub new {
- my $class = shift;
- my $config = $_[0] && UNIVERSAL::isa($_[0], 'HASH') ? shift(@_) : { @_ };
- my ($tagstyle, $debug, $start, $end, $defaults, $grammar, $hash, $key, $udef);
-
- my $self = bless {
- START_TAG => undef,
- END_TAG => undef,
- TAG_STYLE => 'default',
- ANYCASE => 0,
- INTERPOLATE => 0,
- PRE_CHOMP => 0,
- POST_CHOMP => 0,
- V1DOLLAR => 0,
- EVAL_PERL => 0,
- FILE_INFO => 1,
- GRAMMAR => undef,
- _ERROR => '',
- FACTORY => 'Template::Directive',
- }, $class;
-
- # update self with any relevant keys in config
- foreach $key (keys %$self) {
- $self->{ $key } = $config->{ $key } if defined $config->{ $key };
- }
- $self->{ FILEINFO } = [ ];
-
- # DEBUG config item can be a bitmask
- if (defined ($debug = $config->{ DEBUG })) {
- $self->{ DEBUG } = $debug & ( Template::Constants::DEBUG_PARSER
- | Template::Constants::DEBUG_FLAGS );
- $self->{ DEBUG_DIRS } = $debug & Template::Constants::DEBUG_DIRS;
- }
- # package variable can be set to 1 to support previous behaviour
- elsif ($DEBUG == 1) {
- $self->{ DEBUG } = Template::Constants::DEBUG_PARSER;
- $self->{ DEBUG_DIRS } = 0;
- }
- # otherwise let $DEBUG be a bitmask
- else {
- $self->{ DEBUG } = $DEBUG & ( Template::Constants::DEBUG_PARSER
- | Template::Constants::DEBUG_FLAGS );
- $self->{ DEBUG_DIRS } = $DEBUG & Template::Constants::DEBUG_DIRS;
- }
-
- $grammar = $self->{ GRAMMAR } ||= do {
- require Template::Grammar;
- Template::Grammar->new();
- };
-
- # build a FACTORY object to include any NAMESPACE definitions,
- # but only if FACTORY isn't already an object
- if ($config->{ NAMESPACE } && ! ref $self->{ FACTORY }) {
- my $fclass = $self->{ FACTORY };
- $self->{ FACTORY } = $fclass->new( NAMESPACE => $config->{ NAMESPACE } )
- || return $class->error($fclass->error());
- }
-
- # load grammar rules, states and lex table
- @$self{ qw( LEXTABLE STATES RULES ) }
- = @$grammar{ qw( LEXTABLE STATES RULES ) };
-
- $self->new_style($config)
- || return $class->error($self->error());
-
- return $self;
-}
-
-
-#------------------------------------------------------------------------
-# new_style(\%config)
-#
-# Install a new (stacked) parser style. This feature is currently
-# experimental but should mimic the previous behaviour with regard to
-# TAG_STYLE, START_TAG, END_TAG, etc.
-#------------------------------------------------------------------------
-
-sub new_style {
- my ($self, $config) = @_;
- my $styles = $self->{ STYLE } ||= [ ];
- my ($tagstyle, $tags, $start, $end, $key);
-
- # clone new style from previous or default style
- my $style = { %{ $styles->[-1] || $DEFAULT_STYLE } };
-
- # expand START_TAG and END_TAG from specified TAG_STYLE
- if ($tagstyle = $config->{ TAG_STYLE }) {
- return $self->error("Invalid tag style: $tagstyle")
- unless defined ($tags = $TAG_STYLE->{ $tagstyle });
- ($start, $end) = @$tags;
- $config->{ START_TAG } ||= $start;
- $config->{ END_TAG } ||= $end;
- }
-
- foreach $key (keys %$DEFAULT_STYLE) {
- $style->{ $key } = $config->{ $key } if defined $config->{ $key };
- }
- push(@$styles, $style);
- return $style;
-}
-
-
-#------------------------------------------------------------------------
-# old_style()
-#
-# Pop the current parser style and revert to the previous one. See
-# new_style(). ** experimental **
-#------------------------------------------------------------------------
-
-sub old_style {
- my $self = shift;
- my $styles = $self->{ STYLE };
- return $self->error('only 1 parser style remaining')
- unless (@$styles > 1);
- pop @$styles;
- return $styles->[-1];
-}
-
-
-#------------------------------------------------------------------------
-# parse($text, $data)
-#
-# Parses the text string, $text and returns a hash array representing
-# the compiled template block(s) as Perl code, in the format expected
-# by Template::Document.
-#------------------------------------------------------------------------
-
-sub parse {
- my ($self, $text, $info) = @_;
- my ($tokens, $block);
-
- $info->{ DEBUG } = $self->{ DEBUG_DIRS }
- unless defined $info->{ DEBUG };
-
-# print "info: { ", join(', ', map { "$_ => $info->{ $_ }" } keys %$info), " }\n";
-
- # store for blocks defined in the template (see define_block())
- my $defblock = $self->{ DEFBLOCK } = { };
- my $metadata = $self->{ METADATA } = [ ];
-
- $self->{ _ERROR } = '';
-
- # split file into TEXT/DIRECTIVE chunks
- $tokens = $self->split_text($text)
- || return undef; ## RETURN ##
-
- push(@{ $self->{ FILEINFO } }, $info);
-
- # parse chunks
- $block = $self->_parse($tokens, $info);
-
- pop(@{ $self->{ FILEINFO } });
-
- return undef unless $block; ## RETURN ##
-
- $self->debug("compiled main template document block:\n$block")
- if $self->{ DEBUG } & Template::Constants::DEBUG_PARSER;
-
- return {
- BLOCK => $block,
- DEFBLOCKS => $defblock,
- METADATA => { @$metadata },
- };
-}
-
-
-
-#------------------------------------------------------------------------
-# split_text($text)
-#
-# Split input template text into directives and raw text chunks.
-#------------------------------------------------------------------------
-
-sub split_text {
- my ($self, $text) = @_;
- my ($pre, $dir, $prelines, $dirlines, $postlines, $chomp, $tags, @tags);
- my $style = $self->{ STYLE }->[-1];
- my ($start, $end, $prechomp, $postchomp, $interp ) =
- @$style{ qw( START_TAG END_TAG PRE_CHOMP POST_CHOMP INTERPOLATE ) };
-
- my @tokens = ();
- my $line = 1;
-
- return \@tokens ## RETURN ##
- unless defined $text && length $text;
-
- # extract all directives from the text
- while ($text =~ s/
- ^(.*?) # $1 - start of line up to directive
- (?:
- $start # start of tag
- (.*?) # $2 - tag contents
- $end # end of tag
- )
- //sx) {
-
- ($pre, $dir) = ($1, $2);
- $pre = '' unless defined $pre;
- $dir = '' unless defined $dir;
-
- $postlines = 0; # denotes lines chomped
- $prelines = ($pre =~ tr/\n//); # NULL - count only
- $dirlines = ($dir =~ tr/\n//); # ditto
-
- # the directive CHOMP options may modify the preceding text
- for ($dir) {
- # remove leading whitespace and check for a '-' chomp flag
- s/^([-+\#])?\s*//s;
- if ($1 && $1 eq '#') {
- # comment out entire directive except for any chomp flag
- $dir = ($dir =~ /([-+])$/) ? $1 : '';
- }
- else {
- $chomp = ($1 && $1 eq '+') ? 0 : ($1 || $prechomp);
-# my $space = $prechomp == &Template::Constants::CHOMP_COLLAPSE
- my $space = $prechomp == CHOMP_COLLAPSE
- ? ' ' : '';
-
- # chomp off whitespace and newline preceding directive
- $chomp and $pre =~ s/(\n|^)([ \t]*)\Z/($1||$2) ? $space : ''/me
- and $1 eq "\n"
- and $prelines++;
- }
-
- # remove trailing whitespace and check for a '-' chomp flag
- s/\s*([-+])?\s*$//s;
- $chomp = ($1 && $1 eq '+') ? 0 : ($1 || $postchomp);
- my $space = $postchomp == &Template::Constants::CHOMP_COLLAPSE
- ? ' ' : '';
-
- $postlines++
- if $chomp and $text =~ s/
- ^
- ([ \t]*)\n # whitespace to newline
- (?:(.|\n)|$) # any char (not EOF)
- /
- (($1||$2) ? $space : '') . (defined $2 ? $2 : '')
- /ex;
- }
-
- # any text preceding the directive can now be added
- if (length $pre) {
- push(@tokens, $interp
- ? [ $pre, $line, 'ITEXT' ]
- : ('TEXT', $pre) );
- $line += $prelines;
- }
-
- # and now the directive, along with line number information
- if (length $dir) {
- # the TAGS directive is a compile-time switch
- if ($dir =~ /^TAGS\s+(.*)/i) {
- my @tags = split(/\s+/, $1);
- if (scalar @tags > 1) {
- ($start, $end) = map { quotemeta($_) } @tags;
- }
- elsif ($tags = $TAG_STYLE->{ $tags[0] }) {
- ($start, $end) = @$tags;
- }
- else {
- warn "invalid TAGS style: $tags[0]\n";
- }
- }
- else {
- # DIRECTIVE is pushed as:
- # [ $dirtext, $line_no(s), \@tokens ]
- push(@tokens,
- [ $dir,
- ($dirlines
- ? sprintf("%d-%d", $line, $line + $dirlines)
- : $line),
- $self->tokenise_directive($dir) ]);
- }
- }
-
- # update line counter to include directive lines and any extra
- # newline chomped off the start of the following text
- $line += $dirlines + $postlines;
- }
-
- # anything remaining in the string is plain text
- push(@tokens, $interp
- ? [ $text, $line, 'ITEXT' ]
- : ( 'TEXT', $text) )
- if length $text;
-
- return \@tokens; ## RETURN ##
-}
-
-
-
-#------------------------------------------------------------------------
-# interpolate_text($text, $line)
-#
-# Examines $text looking for any variable references embedded like
-# $this or like ${ this }.
-#------------------------------------------------------------------------
-
-sub interpolate_text {
- my ($self, $text, $line) = @_;
- my @tokens = ();
- my ($pre, $var, $dir);
-
-
- while ($text =~
- /
- ( (?: \\. | [^\$] ){1,3000} ) # escaped or non-'$' character [$1]
- |
- ( \$ (?: # embedded variable [$2]
- (?: \{ ([^\}]*) \} ) # ${ ... } [$3]
- |
- ([\w\.]+) # $word [$4]
- )
- )
- /gx) {
-
- ($pre, $var, $dir) = ($1, $3 || $4, $2);
-
- # preceding text
- if (defined($pre) && length($pre)) {
- $line += $pre =~ tr/\n//;
- $pre =~ s/\\\$/\$/g;
- push(@tokens, 'TEXT', $pre);
- }
- # $variable reference
- if ($var) {
- $line += $dir =~ tr/\n/ /;
- push(@tokens, [ $dir, $line, $self->tokenise_directive($var) ]);
- }
- # other '$' reference - treated as text
- elsif ($dir) {
- $line += $dir =~ tr/\n//;
- push(@tokens, 'TEXT', $dir);
- }
- }
-
- return \@tokens;
-}
-
-
-
-#------------------------------------------------------------------------
-# tokenise_directive($text)
-#
-# Called by the private _parse() method when it encounters a DIRECTIVE
-# token in the list provided by the split_text() or interpolate_text()
-# methods. The directive text is passed by parameter.
-#
-# The method splits the directive into individual tokens as recognised
-# by the parser grammar (see Template::Grammar for details). It
-# constructs a list of tokens each represented by 2 elements, as per
-# split_text() et al. The first element contains the token type, the
-# second the token itself.
-#
-# The method tokenises the string using a complex (but fast) regex.
-# For a deeper understanding of the regex magic at work here, see
-# Jeffrey Friedl's excellent book "Mastering Regular Expressions",
-# from O'Reilly, ISBN 1-56592-257-3
-#
-# Returns a reference to the list of chunks (each one being 2 elements)
-# identified in the directive text. On error, the internal _ERROR string
-# is set and undef is returned.
-#------------------------------------------------------------------------
-
-sub tokenise_directive {
- my ($self, $text, $line) = @_;
- my ($token, $uctoken, $type, $lookup);
- my $lextable = $self->{ LEXTABLE };
- my $style = $self->{ STYLE }->[-1];
- my ($anycase, $start, $end) = @$style{ qw( ANYCASE START_TAG END_TAG ) };
- my @tokens = ( );
-
- while ($text =~
- /
- # strip out any comments
- (\#[^\n]*)
- |
- # a quoted phrase matches in $3
- (["']) # $2 - opening quote, ' or "
- ( # $3 - quoted text buffer
- (?: # repeat group (no backreference)
- \\\\ # an escaped backslash \\
- | # ...or...
- \\\2 # an escaped quote \" or \' (match $1)
- | # ...or...
- . # any other character
- | \n
- )*? # non-greedy repeat
- ) # end of $3
- \2 # match opening quote
- |
- # an unquoted number matches in $4
- (-?\d+(?:\.\d+)?) # numbers
- |
- # filename matches in $5
- ( \/?\w+(?:(?:\/|::?)\w*)+ | \/\w+)
- |
- # an identifier matches in $6
- (\w+) # variable identifier
- |
- # an unquoted word or symbol matches in $7
- ( [(){}\[\]:;,\/\\] # misc parenthesis and symbols
-# | \-> # arrow operator (for future?)
- | [+\-*] # math operations
- | \$\{? # dollar with option left brace
- | => # like '='
- | [=!<>]?= | [!<>] # eqality tests
- | &&? | \|\|? # boolean ops
- | \.\.? # n..n sequence
- | \S+ # something unquoted
- ) # end of $7
- /gmxo) {
-
- # ignore comments to EOL
- next if $1;
-
- # quoted string
- if (defined ($token = $3)) {
- # double-quoted string may include $variable references
- if ($2 eq '"') {
- if ($token =~ /[\$\\]/) {
- $type = 'QUOTED';
- # unescape " and \ but leave \$ escaped so that
- # interpolate_text() doesn't incorrectly treat it
- # as a variable reference
-# $token =~ s/\\([\\"])/$1/g;
- for ($token) {
- s/\\([^\$nrt])/$1/g;
- s/\\([nrt])/$QUOTED_ESCAPES->{ $1 }/ge;
- }
- push(@tokens, ('"') x 2,
- @{ $self->interpolate_text($token) },
- ('"') x 2);
- next;
- }
- else {
- $type = 'LITERAL';
- $token =~ s['][\\']g;
- $token = "'$token'";
- }
- }
- else {
- $type = 'LITERAL';
- $token = "'$token'";
- }
- }
- # number
- elsif (defined ($token = $4)) {
- $type = 'NUMBER';
- }
- elsif (defined($token = $5)) {
- $type = 'FILENAME';
- }
- elsif (defined($token = $6)) {
- # reserved words may be in lower case unless case sensitive
- $uctoken = $anycase ? uc $token : $token;
- if (defined ($type = $lextable->{ $uctoken })) {
- $token = $uctoken;
- }
- else {
- $type = 'IDENT';
- }
- }
- elsif (defined ($token = $7)) {
- # reserved words may be in lower case unless case sensitive
- $uctoken = $anycase ? uc $token : $token;
- unless (defined ($type = $lextable->{ $uctoken })) {
- $type = 'UNQUOTED';
- }
- }
-
- push(@tokens, $type, $token);
-
-# print(STDERR " +[ $type, $token ]\n")
-# if $DEBUG;
- }
-
-# print STDERR "tokenise directive() returning:\n [ @tokens ]\n"
-# if $DEBUG;
-
- return \@tokens; ## RETURN ##
-}
-
-
-#------------------------------------------------------------------------
-# define_block($name, $block)
-#
-# Called by the parser 'defblock' rule when a BLOCK definition is
-# encountered in the template. The name of the block is passed in the
-# first parameter and a reference to the compiled block is passed in
-# the second. This method stores the block in the $self->{ DEFBLOCK }
-# hash which has been initialised by parse() and will later be used
-# by the same method to call the store() method on the calling cache
-# to define the block "externally".
-#------------------------------------------------------------------------
-
-sub define_block {
- my ($self, $name, $block) = @_;
- my $defblock = $self->{ DEFBLOCK }
- || return undef;
-
- $self->debug("compiled block '$name':\n$block")
- if $self->{ DEBUG } & Template::Constants::DEBUG_PARSER;
-
- $defblock->{ $name } = $block;
-
- return undef;
-}
-
-sub push_defblock {
- my $self = shift;
- my $stack = $self->{ DEFBLOCK_STACK } ||= [];
- push(@$stack, $self->{ DEFBLOCK } );
- $self->{ DEFBLOCK } = { };
-}
-
-sub pop_defblock {
- my $self = shift;
- my $defs = $self->{ DEFBLOCK };
- my $stack = $self->{ DEFBLOCK_STACK } || return $defs;
- return $defs unless @$stack;
- $self->{ DEFBLOCK } = pop @$stack;
- return $defs;
-}
-
-
-#------------------------------------------------------------------------
-# add_metadata(\@setlist)
-#------------------------------------------------------------------------
-
-sub add_metadata {
- my ($self, $setlist) = @_;
- my $metadata = $self->{ METADATA }
- || return undef;
-
- push(@$metadata, @$setlist);
-
- return undef;
-}
-
-
-#------------------------------------------------------------------------
-# location()
-#
-# Return Perl comment indicating current parser file and line
-#------------------------------------------------------------------------
-
-sub location {
- my $self = shift;
- return "\n" unless $self->{ FILE_INFO };
- my $line = ${ $self->{ LINE } };
- my $info = $self->{ FILEINFO }->[-1];
- my $file = $info->{ path } || $info->{ name }
- || '(unknown template)';
- $line =~ s/\-.*$//; # might be 'n-n'
- return "#line $line \"$file\"\n";
-}
-
-
-#========================================================================
-# ----- PRIVATE METHODS -----
-#========================================================================
-
-#------------------------------------------------------------------------
-# _parse(\@tokens, \@info)
-#
-# Parses the list of input tokens passed by reference and returns a
-# Template::Directive::Block object which contains the compiled
-# representation of the template.
-#
-# This is the main parser DFA loop. See embedded comments for
-# further details.
-#
-# On error, undef is returned and the internal _ERROR field is set to
-# indicate the error. This can be retrieved by calling the error()
-# method.
-#------------------------------------------------------------------------
-
-sub _parse {
- my ($self, $tokens, $info) = @_;
- my ($token, $value, $text, $line, $inperl);
- my ($state, $stateno, $status, $action, $lookup, $coderet, @codevars);
- my ($lhs, $len, $code); # rule contents
- my $stack = [ [ 0, undef ] ]; # DFA stack
-
-# DEBUG
-# local $" = ', ';
-
- # retrieve internal rule and state tables
- my ($states, $rules) = @$self{ qw( STATES RULES ) };
-
- # call the grammar set_factory method to install emitter factory
- $self->{ GRAMMAR }->install_factory($self->{ FACTORY });
-
- $line = $inperl = 0;
- $self->{ LINE } = \$line;
- $self->{ FILE } = $info->{ name };
- $self->{ INPERL } = \$inperl;
-
- $status = CONTINUE;
- my $in_string = 0;
-
- while(1) {
- # get state number and state
- $stateno = $stack->[-1]->[0];
- $state = $states->[$stateno];
-
- # see if any lookaheads exist for the current state
- if (exists $state->{'ACTIONS'}) {
-
- # get next token and expand any directives (i.e. token is an
- # array ref) onto the front of the token list
- while (! defined $token && @$tokens) {
- $token = shift(@$tokens);
- if (ref $token) {
- ($text, $line, $token) = @$token;
- if (ref $token) {
- if ($info->{ DEBUG } && ! $in_string) {
- # - - - - - - - - - - - - - - - - - - - - - - - - -
- # This is gnarly. Look away now if you're easily
- # frightened. We're pushing parse tokens onto the
- # pending list to simulate a DEBUG directive like so:
- # [% DEBUG msg line='20' text='INCLUDE foo' %]
- # - - - - - - - - - - - - - - - - - - - - - - - - -
- my $dtext = $text;
- $dtext =~ s[(['\\])][\\$1]g;
- unshift(@$tokens,
- DEBUG => 'DEBUG',
- IDENT => 'msg',
- IDENT => 'line',
- ASSIGN => '=',
- LITERAL => "'$line'",
- IDENT => 'text',
- ASSIGN => '=',
- LITERAL => "'$dtext'",
- IDENT => 'file',
- ASSIGN => '=',
- LITERAL => "'$info->{ name }'",
- (';') x 2,
- @$token,
- (';') x 2);
- }
- else {
- unshift(@$tokens, @$token, (';') x 2);
- }
- $token = undef; # force redo
- }
- elsif ($token eq 'ITEXT') {
- if ($inperl) {
- # don't perform interpolation in PERL blocks
- $token = 'TEXT';
- $value = $text;
- }
- else {
- unshift(@$tokens,
- @{ $self->interpolate_text($text, $line) });
- $token = undef; # force redo
- }
- }
- }
- else {
- # toggle string flag to indicate if we're crossing
- # a string boundary
- $in_string = ! $in_string if $token eq '"';
- $value = shift(@$tokens);
- }
- };
- # clear undefined token to avoid 'undefined variable blah blah'
- # warnings and let the parser logic pick it up in a minute
- $token = '' unless defined $token;
-
- # get the next state for the current lookahead token
- $action = defined ($lookup = $state->{'ACTIONS'}->{ $token })
- ? $lookup
- : defined ($lookup = $state->{'DEFAULT'})
- ? $lookup
- : undef;
- }
- else {
- # no lookahead actions
- $action = $state->{'DEFAULT'};
- }
-
- # ERROR: no ACTION
- last unless defined $action;
-
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- # shift (+ive ACTION)
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- if ($action > 0) {
- push(@$stack, [ $action, $value ]);
- $token = $value = undef;
- redo;
- };
-
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- # reduce (-ive ACTION)
- # - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ($lhs, $len, $code) = @{ $rules->[ -$action ] };
-
- # no action imples ACCEPTance
- $action
- or $status = ACCEPT;
-
- # use dummy sub if code ref doesn't exist
- $code = sub { $_[1] }
- unless $code;
-
- @codevars = $len
- ? map { $_->[1] } @$stack[ -$len .. -1 ]
- : ();
-
- eval {
- $coderet = &$code( $self, @codevars );
- };
- if ($@) {
- my $err = $@;
- chomp $err;
- return $self->_parse_error($err);
- }
-
- # reduce stack by $len
- splice(@$stack, -$len, $len);
-
- # ACCEPT
- return $coderet ## RETURN ##
- if $status == ACCEPT;
-
- # ABORT
- return undef ## RETURN ##
- if $status == ABORT;
-
- # ERROR
- last
- if $status == ERROR;
- }
- continue {
- push(@$stack, [ $states->[ $stack->[-1][0] ]->{'GOTOS'}->{ $lhs },
- $coderet ]),
- }
-
- # ERROR ## RETURN ##
- return $self->_parse_error('unexpected end of input')
- unless defined $value;
-
- # munge text of last directive to make it readable
-# $text =~ s/\n/\\n/g;
-
- return $self->_parse_error("unexpected end of directive", $text)
- if $value eq ';'; # end of directive SEPARATOR
-
- return $self->_parse_error("unexpected token ($value)", $text);
-}
-
-
-
-#------------------------------------------------------------------------
-# _parse_error($msg, $dirtext)
-#
-# Method used to handle errors encountered during the parse process
-# in the _parse() method.
-#------------------------------------------------------------------------
-
-sub _parse_error {
- my ($self, $msg, $text) = @_;
- my $line = $self->{ LINE };
- $line = ref($line) ? $$line : $line;
- $line = 'unknown' unless $line;
-
- $msg .= "\n [% $text %]"
- if defined $text;
-
- return $self->error("line $line: $msg");
-}
-
-
-#------------------------------------------------------------------------
-# _dump()
-#
-# Debug method returns a string representing the internal state of the
-# object.
-#------------------------------------------------------------------------
-
-sub _dump {
- my $self = shift;
- my $output = "[Template::Parser] {\n";
- my $format = " %-16s => %s\n";
- my $key;
-
- foreach $key (qw( START_TAG END_TAG TAG_STYLE ANYCASE INTERPOLATE
- PRE_CHOMP POST_CHOMP V1DOLLAR )) {
- my $val = $self->{ $key };
- $val = '<undef>' unless defined $val;
- $output .= sprintf($format, $key, $val);
- }
-
- $output .= '}';
- return $output;
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Parser - LALR(1) parser for compiling template documents
-
-=head1 SYNOPSIS
-
- use Template::Parser;
-
- $parser = Template::Parser->new(\%config);
- $template = $parser->parse($text)
- || die $parser->error(), "\n";
-
-=head1 DESCRIPTION
-
-The Template::Parser module implements a LALR(1) parser and associated methods
-for parsing template documents into Perl code.
-
-=head1 PUBLIC METHODS
-
-=head2 new(\%params)
-
-The new() constructor creates and returns a reference to a new
-Template::Parser object. A reference to a hash may be supplied as a
-parameter to provide configuration values. These may include:
-
-=over
-
-
-
-
-=item START_TAG, END_TAG
-
-The START_TAG and END_TAG options are used to specify character
-sequences or regular expressions that mark the start and end of a
-template directive. The default values for START_TAG and END_TAG are
-'[%' and '%]' respectively, giving us the familiar directive style:
-
- [% example %]
-
-Any Perl regex characters can be used and therefore should be escaped
-(or use the Perl C<quotemeta> function) if they are intended to
-represent literal characters.
-
- my $parser = Template::Parser->new({
- START_TAG => quotemeta('<+'),
- END_TAG => quotemeta('+>'),
- });
-
-example:
-
- <+ INCLUDE foobar +>
-
-The TAGS directive can also be used to set the START_TAG and END_TAG values
-on a per-template file basis.
-
- [% TAGS <+ +> %]
-
-
-
-
-
-
-=item TAG_STYLE
-
-The TAG_STYLE option can be used to set both START_TAG and END_TAG
-according to pre-defined tag styles.
-
- my $parser = Template::Parser->new({
- TAG_STYLE => 'star',
- });
-
-Available styles are:
-
- template [% ... %] (default)
- template1 [% ... %] or %% ... %% (TT version 1)
- metatext %% ... %% (Text::MetaText)
- star [* ... *] (TT alternate)
- php <? ... ?> (PHP)
- asp <% ... %> (ASP)
- mason <% ... > (HTML::Mason)
- html <!-- ... --> (HTML comments)
-
-Any values specified for START_TAG and/or END_TAG will over-ride
-those defined by a TAG_STYLE.
-
-The TAGS directive may also be used to set a TAG_STYLE
-
- [% TAGS html %]
- <!-- INCLUDE header -->
-
-
-
-
-
-
-=item PRE_CHOMP, POST_CHOMP
-
-Anything outside a directive tag is considered plain text and is
-generally passed through unaltered (but see the INTERPOLATE option).
-This includes all whitespace and newlines characters surrounding
-directive tags. Directives that don't generate any output will leave
-gaps in the output document.
-
-Example:
-
- Foo
- [% a = 10 %]
- Bar
-
-Output:
-
- Foo
-
- Bar
-
-The PRE_CHOMP and POST_CHOMP options can help to clean up some of this
-extraneous whitespace. Both are disabled by default.
-
- my $parser = Template::Parser->new({
- PRE_CHOMP => 1,
- POST_CHOMP => 1,
- });
-
-With PRE_CHOMP set to 1, the newline and whitespace preceding a directive
-at the start of a line will be deleted. This has the effect of
-concatenating a line that starts with a directive onto the end of the
-previous line.
-
- Foo <----------.
- |
- ,---(PRE_CHOMP)----'
- |
- `-- [% a = 10 %] --.
- |
- ,---(POST_CHOMP)---'
- |
- `-> Bar
-
-With POST_CHOMP set to 1, any whitespace after a directive up to and
-including the newline will be deleted. This has the effect of joining
-a line that ends with a directive onto the start of the next line.
-
-If PRE_CHOMP or POST_CHOMP is set to 2, then instead of removing all
-the whitespace, the whitespace will be collapsed to a single space.
-This is useful for HTML, where (usually) a contiguous block of
-whitespace is rendered the same as a single space.
-
-You may use the CHOMP_NONE, CHOMP_ALL, and CHOMP_COLLAPSE constants
-from the Template::Constants module to deactivate chomping, remove
-all whitespace, or collapse whitespace to a single space.
-
-PRE_CHOMP and POST_CHOMP can be activated for individual directives by
-placing a '-' immediately at the start and/or end of the directive.
-
- [% FOREACH user = userlist %]
- [%- user -%]
- [% END %]
-
-The '-' characters activate both PRE_CHOMP and POST_CHOMP for the one
-directive '[%- name -%]'. Thus, the template will be processed as if
-written:
-
- [% FOREACH user = userlist %][% user %][% END %]
-
-Note that this is the same as if PRE_CHOMP and POST_CHOMP were set
-to CHOMP_ALL; the only way to get the CHOMP_COLLAPSE behavior is
-to set PRE_CHOMP or POST_CHOMP accordingly. If PRE_CHOMP or POST_CHOMP
-is already set to CHOMP_COLLAPSE, using '-' will give you CHOMP_COLLAPSE
-behavior, not CHOMP_ALL behavior.
-
-Similarly, '+' characters can be used to disable PRE_CHOMP or
-POST_CHOMP (i.e. leave the whitespace/newline intact) options on a
-per-directive basis.
-
- [% FOREACH user = userlist %]
- User: [% user +%]
- [% END %]
-
-With POST_CHOMP enabled, the above example would be parsed as if written:
-
- [% FOREACH user = userlist %]User: [% user %]
- [% END %]
-
-
-
-
-
-=item INTERPOLATE
-
-The INTERPOLATE flag, when set to any true value will cause variable
-references in plain text (i.e. not surrounded by START_TAG and END_TAG)
-to be recognised and interpolated accordingly.
-
- my $parser = Template::Parser->new({
- INTERPOLATE => 1,
- });
-
-Variables should be prefixed by a '$' to identify them. Curly braces
-can be used in the familiar Perl/shell style to explicitly scope the
-variable name where required.
-
- # INTERPOLATE => 0
- <a href="http://[% server %]/[% help %]">
- <img src="[% images %]/help.gif"></a>
- [% myorg.name %]
-
- # INTERPOLATE => 1
- <a href="http://$server/$help">
- <img src="$images/help.gif"></a>
- $myorg.name
-
- # explicit scoping with { }
- <img src="$images/${icon.next}.gif">
-
-Note that a limitation in Perl's regex engine restricts the maximum length
-of an interpolated template to around 32 kilobytes or possibly less. Files
-that exceed this limit in size will typically cause Perl to dump core with
-a segmentation fault. If you routinely process templates of this size
-then you should disable INTERPOLATE or split the templates in several
-smaller files or blocks which can then be joined backed together via
-PROCESS or INCLUDE.
-
-
-
-
-
-
-
-=item ANYCASE
-
-By default, directive keywords should be expressed in UPPER CASE. The
-ANYCASE option can be set to allow directive keywords to be specified
-in any case.
-
- # ANYCASE => 0 (default)
- [% INCLUDE foobar %] # OK
- [% include foobar %] # ERROR
- [% include = 10 %] # OK, 'include' is a variable
-
- # ANYCASE => 1
- [% INCLUDE foobar %] # OK
- [% include foobar %] # OK
- [% include = 10 %] # ERROR, 'include' is reserved word
-
-One side-effect of enabling ANYCASE is that you cannot use a variable
-of the same name as a reserved word, regardless of case. The reserved
-words are currently:
-
- GET CALL SET DEFAULT INSERT INCLUDE PROCESS WRAPPER
- IF UNLESS ELSE ELSIF FOR FOREACH WHILE SWITCH CASE
- USE PLUGIN FILTER MACRO PERL RAWPERL BLOCK META
- TRY THROW CATCH FINAL NEXT LAST BREAK RETURN STOP
- CLEAR TO STEP AND OR NOT MOD DIV END
-
-
-The only lower case reserved words that cannot be used for variables,
-regardless of the ANYCASE option, are the operators:
-
- and or not mod div
-
-
-
-
-
-
-
-
-=item V1DOLLAR
-
-In version 1 of the Template Toolkit, an optional leading '$' could be placed
-on any template variable and would be silently ignored.
-
- # VERSION 1
- [% $foo %] === [% foo %]
- [% $hash.$key %] === [% hash.key %]
-
-To interpolate a variable value the '${' ... '}' construct was used.
-Typically, one would do this to index into a hash array when the key
-value was stored in a variable.
-
-example:
-
- my $vars = {
- users => {
- aba => { name => 'Alan Aardvark', ... },
- abw => { name => 'Andy Wardley', ... },
- ...
- },
- uid => 'aba',
- ...
- };
-
- $template->process('user/home.html', $vars)
- || die $template->error(), "\n";
-
-'user/home.html':
-
- [% user = users.${uid} %] # users.aba
- Name: [% user.name %] # Alan Aardvark
-
-This was inconsistent with double quoted strings and also the
-INTERPOLATE mode, where a leading '$' in text was enough to indicate a
-variable for interpolation, and the additional curly braces were used
-to delimit variable names where necessary. Note that this use is
-consistent with UNIX and Perl conventions, among others.
-
- # double quoted string interpolation
- [% name = "$title ${user.name}" %]
-
- # INTERPOLATE = 1
- <img src="$images/help.gif"></a>
- <img src="$images/${icon.next}.gif">
-
-For version 2, these inconsistencies have been removed and the syntax
-clarified. A leading '$' on a variable is now used exclusively to
-indicate that the variable name should be interpolated
-(e.g. subsituted for its value) before being used. The earlier example
-from version 1:
-
- # VERSION 1
- [% user = users.${uid} %]
- Name: [% user.name %]
-
-can now be simplified in version 2 as:
-
- # VERSION 2
- [% user = users.$uid %]
- Name: [% user.name %]
-
-The leading dollar is no longer ignored and has the same effect of
-interpolation as '${' ... '}' in version 1. The curly braces may
-still be used to explicitly scope the interpolated variable name
-where necessary.
-
-e.g.
-
- [% user = users.${me.id} %]
- Name: [% user.name %]
-
-The rule applies for all variables, both within directives and in
-plain text if processed with the INTERPOLATE option. This means that
-you should no longer (if you ever did) add a leading '$' to a variable
-inside a directive, unless you explicitly want it to be interpolated.
-
-One obvious side-effect is that any version 1 templates with variables
-using a leading '$' will no longer be processed as expected. Given
-the following variable definitions,
-
- [% foo = 'bar'
- bar = 'baz'
- %]
-
-version 1 would interpret the following as:
-
- # VERSION 1
- [% $foo %] => [% GET foo %] => bar
-
-whereas version 2 interprets it as:
-
- # VERSION 2
- [% $foo %] => [% GET $foo %] => [% GET bar %] => baz
-
-In version 1, the '$' is ignored and the value for the variable 'foo' is
-retrieved and printed. In version 2, the variable '$foo' is first interpolated
-to give the variable name 'bar' whose value is then retrieved and printed.
-
-The use of the optional '$' has never been strongly recommended, but
-to assist in backwards compatibility with any version 1 templates that
-may rely on this "feature", the V1DOLLAR option can be set to 1
-(default: 0) to revert the behaviour and have leading '$' characters
-ignored.
-
- my $parser = Template::Parser->new({
- V1DOLLAR => 1,
- });
-
-
-
-
-
-
-=item GRAMMAR
-
-The GRAMMAR configuration item can be used to specify an alternate
-grammar for the parser. This allows a modified or entirely new
-template language to be constructed and used by the Template Toolkit.
-
-Source templates are compiled to Perl code by the Template::Parser
-using the Template::Grammar (by default) to define the language
-structure and semantics. Compiled templates are thus inherently
-"compatible" with each other and there is nothing to prevent any
-number of different template languages being compiled and used within
-the same Template Toolkit processing environment (other than the usual
-time and memory constraints).
-
-The Template::Grammar file is constructed from a YACC like grammar
-(using Parse::YAPP) and a skeleton module template. These files are
-provided, along with a small script to rebuild the grammar, in the
-'parser' sub-directory of the distribution. You don't have to know or
-worry about these unless you want to hack on the template language or
-define your own variant. There is a README file in the same directory
-which provides some small guidance but it is assumed that you know
-what you're doing if you venture herein. If you grok LALR parsers,
-then you should find it comfortably familiar.
-
-By default, an instance of the default Template::Grammar will be
-created and used automatically if a GRAMMAR item isn't specified.
-
- use MyOrg::Template::Grammar;
-
- my $parser = Template::Parser->new({
- GRAMMAR = MyOrg::Template::Grammar->new();
- });
-
-
-
-=item DEBUG
-
-The DEBUG option can be used to enable various debugging features
-of the Template::Parser module.
-
- use Template::Constants qw( :debug );
-
- my $template = Template->new({
- DEBUG => DEBUG_PARSER | DEBUG_DIRS,
- });
-
-The DEBUG value can include any of the following. Multiple values
-should be combined using the logical OR operator, '|'.
-
-=over 4
-
-=item DEBUG_PARSER
-
-This flag causes the L<Template::Parser|Template::Parser> to generate
-debugging messages that show the Perl code generated by parsing and
-compiling each template.
-
-=item DEBUG_DIRS
-
-This option causes the Template Toolkit to generate comments
-indicating the source file, line and original text of each directive
-in the template. These comments are embedded in the template output
-using the format defined in the DEBUG_FORMAT configuration item, or a
-simple default format if unspecified.
-
-For example, the following template fragment:
-
-
- Hello World
-
-would generate this output:
-
- ## input text line 1 : ##
- Hello
- ## input text line 2 : World ##
- World
-
-
-=back
-
-
-
-
-=back
-
-=head2 parse($text)
-
-The parse() method parses the text passed in the first parameter and
-returns a reference to a Template::Document object which contains the
-compiled representation of the template text. On error, undef is
-returned.
-
-Example:
-
- $doc = $parser->parse($text)
- || die $parser->error();
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-
-
-=head1 VERSION
-
-2.81, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-
-
-The original Template::Parser module was derived from a standalone
-parser generated by version 0.16 of the Parse::Yapp module. The
-following copyright notice appears in the Parse::Yapp documentation.
-
- The Parse::Yapp module and its related modules and shell
- scripts are copyright (c) 1998 Francois Desarmenien,
- France. All rights reserved.
-
- You may use and distribute them under the terms of either
- the GNU General Public License or the Artistic License, as
- specified in the Perl README file.
-
-=head1 SEE ALSO
-
-L<Template|Template>, L<Template::Grammar|Template::Grammar>, L<Template::Directive|Template::Directive>
-
diff --git a/lib/Template/Plugin.pm b/lib/Template/Plugin.pm
deleted file mode 100644
index a6c9df2..0000000
--- a/lib/Template/Plugin.pm
+++ /dev/null
@@ -1,409 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin
-#
-# DESCRIPTION
-#
-# Module defining a base class for a plugin object which can be loaded
-# and instantiated via the USE directive.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Plugin.pm,v 2.65 2004/01/13 16:19:15 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin;
-
-require 5.004;
-
-use strict;
-use Template::Base;
-
-use vars qw( $VERSION $DEBUG $ERROR $AUTOLOAD );
-use base qw( Template::Base );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.65 $ =~ /(\d+)\.(\d+)/);
-$DEBUG = 0;
-
-
-#========================================================================
-# ----- CLASS METHODS -----
-#========================================================================
-
-#------------------------------------------------------------------------
-# load()
-#
-# Class method called when the plugin module is first loaded. It
-# returns the name of a class (by default, its own class) or a prototype
-# object which will be used to instantiate new objects. The new()
-# method is then called against the class name (class method) or
-# prototype object (object method) to create a new instances of the
-# object.
-#------------------------------------------------------------------------
-
-sub load {
- return $_[0];
-}
-
-
-#------------------------------------------------------------------------
-# new($context, $delegate, @params)
-#
-# Object constructor which is called by the Template::Context to
-# instantiate a new Plugin object. This base class constructor is
-# used as a general mechanism to load and delegate to other Perl
-# modules. The context is passed as the first parameter, followed by
-# a reference to a delegate object or the name of the module which
-# should be loaded and instantiated. Any additional parameters passed
-# to the USE directive are forwarded to the new() constructor.
-#
-# A plugin object is returned which has an AUTOLOAD method to delegate
-# requests to the underlying object.
-#------------------------------------------------------------------------
-
-sub new {
- my $class = shift;
- bless {
- }, $class;
-}
-
-sub old_new {
- my ($class, $context, $delclass, @params) = @_;
- my ($delegate, $delmod);
-
- return $class->error("no context passed to $class constructor\n")
- unless defined $context;
-
- if (ref $delclass) {
- # $delclass contains a reference to a delegate object
- $delegate = $delclass;
- }
- else {
- # delclass is the name of a module to load and instantiate
- ($delmod = $delclass) =~ s|::|/|g;
-
- eval {
- require "$delmod.pm";
- $delegate = $delclass->new(@params)
- || die "failed to instantiate $delclass object\n";
- };
- return $class->error($@) if $@;
- }
-
- bless {
- _CONTEXT => $context,
- _DELEGATE => $delegate,
- _PARAMS => \@params,
- }, $class;
-}
-
-
-#------------------------------------------------------------------------
-# fail($error)
-#
-# Version 1 error reporting function, now replaced by error() inherited
-# from Template::Base. Raises a "deprecated function" warning and then
-# calls error().
-#------------------------------------------------------------------------
-
-sub fail {
- my $class = shift;
- my ($pkg, $file, $line) = caller();
- warn "Template::Plugin::fail() is deprecated at $file line $line. Please use error()\n";
- $class->error(@_);
-}
-
-
-#========================================================================
-# ----- OBJECT METHODS -----
-#========================================================================
-
-#------------------------------------------------------------------------
-# AUTOLOAD
-#
-# General catch-all method which delegates all calls to the _DELEGATE
-# object.
-#------------------------------------------------------------------------
-
-sub OLD_AUTOLOAD {
- my $self = shift;
- my $method = $AUTOLOAD;
-
- $method =~ s/.*:://;
- return if $method eq 'DESTROY';
-
- if (ref $self eq 'HASH') {
- my $delegate = $self->{ _DELEGATE } || return;
- return $delegate->$method(@_);
- }
- my ($pkg, $file, $line) = caller();
-# warn "no such '$method' method called on $self at $file line $line\n";
- return undef;
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin - Base class for Template Toolkit plugins
-
-=head1 SYNOPSIS
-
- package MyOrg::Template::Plugin::MyPlugin;
- use base qw( Template::Plugin );
- use Template::Plugin;
- use MyModule;
-
- sub new {
- my $class = shift;
- my $context = shift;
- bless {
- ...
- }, $class;
- }
-
-=head1 DESCRIPTION
-
-A "plugin" for the Template Toolkit is simply a Perl module which
-exists in a known package location (e.g. Template::Plugin::*) and
-conforms to a regular standard, allowing it to be loaded and used
-automatically.
-
-The Template::Plugin module defines a base class from which other
-plugin modules can be derived. A plugin does not have to be derived
-from Template::Plugin but should at least conform to its object-oriented
-interface.
-
-It is recommended that you create plugins in your own package namespace
-to avoid conflict with toolkit plugins. e.g.
-
- package MyOrg::Template::Plugin::FooBar;
-
-Use the PLUGIN_BASE option to specify the namespace that you use. e.g.
-
- use Template;
- my $template = Template->new({
- PLUGIN_BASE => 'MyOrg::Template::Plugin',
- });
-
-=head1 PLUGIN API
-
-The following methods form the basic interface between the Template
-Toolkit and plugin modules.
-
-=over 4
-
-=item load($context)
-
-This method is called by the Template Toolkit when the plugin module
-is first loaded. It is called as a package method and thus implicitly
-receives the package name as the first parameter. A reference to the
-Template::Context object loading the plugin is also passed. The
-default behaviour for the load() method is to simply return the class
-name. The calling context then uses this class name to call the new()
-package method.
-
- package MyPlugin;
-
- sub load { # called as MyPlugin->load($context)
- my ($class, $context) = @_;
- return $class; # returns 'MyPlugin'
- }
-
-=item new($context, @params)
-
-This method is called to instantiate a new plugin object for the USE
-directive. It is called as a package method against the class name
-returned by load(). A reference to the Template::Context object creating
-the plugin is passed, along with any additional parameters specified in
-the USE directive.
-
- sub new { # called as MyPlugin->new($context)
- my ($class, $context, @params) = @_;
- bless {
- _CONTEXT => $context,
- }, $class; # returns blessed MyPlugin object
- }
-
-=item error($error)
-
-This method, inherited from the Template::Base module, is used for
-reporting and returning errors. It can be called as a package method
-to set/return the $ERROR package variable, or as an object method to
-set/return the object _ERROR member. When called with an argument, it
-sets the relevant variable and returns undef. When called without an
-argument, it returns the value of the variable.
-
- sub new {
- my ($class, $context, $dsn) = @_;
-
- return $class->error('No data source specified')
- unless $dsn;
-
- bless {
- _DSN => $dsn,
- }, $class;
- }
-
- ...
-
- my $something = MyModule->new()
- || die MyModule->error(), "\n";
-
- $something->do_something()
- || die $something->error(), "\n";
-
-=back
-
-=head1 DEEPER MAGIC
-
-The Template::Context object that handles the loading and use of
-plugins calls the new() and error() methods against the package name
-returned by the load() method. In pseudo-code terms, it might look
-something like this:
-
- $class = MyPlugin->load($context); # returns 'MyPlugin'
-
- $object = $class->new($context, @params) # MyPlugin->new(...)
- || die $class->error(); # MyPlugin->error()
-
-The load() method may alterately return a blessed reference to an
-object instance. In this case, new() and error() are then called as
-I<object> methods against that prototype instance.
-
- package YourPlugin;
-
- sub load {
- my ($class, $context) = @_;
- bless {
- _CONTEXT => $context,
- }, $class;
- }
-
- sub new {
- my ($self, $context, @params) = @_;
- return $self;
- }
-
-In this example, we have implemented a 'Singleton' plugin. One object
-gets created when load() is called and this simply returns itself for
-each call to new().
-
-Another implementation might require individual objects to be created
-for every call to new(), but with each object sharing a reference to
-some other object to maintain cached data, database handles, etc.
-This pseudo-code example demonstrates the principle.
-
- package MyServer;
-
- sub load {
- my ($class, $context) = @_;
- bless {
- _CONTEXT => $context,
- _CACHE => { },
- }, $class;
- }
-
- sub new {
- my ($self, $context, @params) = @_;
- MyClient->new($self, @params);
- }
-
- sub add_to_cache { ... }
-
- sub get_from_cache { ... }
-
-
- package MyClient;
-
- sub new {
- my ($class, $server, $blah) = @_;
- bless {
- _SERVER => $server,
- _BLAH => $blah,
- }, $class;
- }
-
- sub get {
- my $self = shift;
- $self->{ _SERVER }->get_from_cache(@_);
- }
-
- sub put {
- my $self = shift;
- $self->{ _SERVER }->add_to_cache(@_);
- }
-
-When the plugin is loaded, a MyServer instance is created. The new()
-method is called against this object which instantiates and returns a
-MyClient object, primed to communicate with the creating MyServer.
-
-=head1 Template::Plugin Delegation
-
-As of version 2.01, the Template::Plugin module no longer provides an
-AUTOLOAD method to delegate to other objects or classes. This was a
-badly designed feature that caused more trouble than good. You can
-easily add your own AUTOLOAD method to perform delegation if you
-require this kind of functionality.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.65, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template|Template>, L<Template::Plugins|Template::Plugins>, L<Template::Context|Template::Context>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/Autoformat.pm b/lib/Template/Plugin/Autoformat.pm
deleted file mode 100644
index b7153e4..0000000
--- a/lib/Template/Plugin/Autoformat.pm
+++ /dev/null
@@ -1,242 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::Autoformat
-#
-# DESCRIPTION
-# Plugin interface to Damian Conway's Text::Autoformat module.
-#
-# AUTHORS
-# Robert McArthur <mcarthur@dstc.edu.au>
-# - original plugin code
-#
-# Andy Wardley <abw@kfs.org>
-# - added FILTER registration, support for forms and some additional
-# documentation
-#
-# COPYRIGHT
-# Copyright (C) 2000 Robert McArthur & Andy Wardley. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Autoformat.pm,v 2.64 2004/01/13 16:20:38 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::Autoformat;
-
-require 5.004;
-
-use strict;
-use vars qw( $VERSION );
-use base qw( Template::Plugin );
-use Template::Plugin;
-use Text::Autoformat;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.64 $ =~ /(\d+)\.(\d+)/);
-
-sub new {
- my ($class, $context, $options) = @_;
- my $filter_factory;
- my $plugin;
-
- if ($options) {
- # create a closure to generate filters with additional options
- $filter_factory = sub {
- my $context = shift;
- my $filtopt = ref $_[-1] eq 'HASH' ? pop : { };
- @$filtopt{ keys %$options } = values %$options;
- return sub {
- tt_autoformat(@_, $filtopt);
- };
- };
-
- # and a closure to represent the plugin
- $plugin = sub {
- my $plugopt = ref $_[-1] eq 'HASH' ? pop : { };
- @$plugopt{ keys %$options } = values %$options;
- tt_autoformat(@_, $plugopt);
- };
- }
- else {
- # simple filter factory closure (no legacy options from constructor)
- $filter_factory = sub {
- my $context = shift;
- my $filtopt = ref $_[-1] eq 'HASH' ? pop : { };
- return sub {
- tt_autoformat(@_, $filtopt);
- };
- };
-
- # plugin without options can be static
- $plugin = \&tt_autoformat;
- }
-
- # now define the filter and return the plugin
- $context->define_filter('autoformat', [ $filter_factory => 1 ]);
- return $plugin;
-}
-
-sub tt_autoformat {
- my $options = ref $_[-1] eq 'HASH' ? pop : { };
- my $form = $options->{ form };
- my $out = $form ? Text::Autoformat::form($options, $form, @_)
- : Text::Autoformat::autoformat(join('', @_), $options);
- return $out;
-}
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::Autoformat - Interface to Text::Autoformat module
-
-=head1 SYNOPSIS
-
- [% USE autoformat(options) %]
-
- [% autoformat(text, more_text, ..., options) %]
-
- [% FILTER autoformat(options) %]
- a block of text
- [% END %]
-
-=head1 EXAMPLES
-
- # define some text for the examples
- [% text = BLOCK %]
- Be not afeard. The isle is full of noises, sounds and sweet
- airs that give delight but hurt not.
- [% END %]
-
- # pass options to constructor...
- [% USE autoformat(case => 'upper') %]
- [% autoformat(text) %]
-
- # and/or pass options to the autoformat subroutine itself
- [% USE autoformat %]
- [% autoformat(text, case => 'upper') %]
-
- # using the autoformat filter
- [% USE autoformat(left => 10, right => 30) %]
- [% FILTER autoformat %]
- Be not afeard. The isle is full of noises, sounds and sweet
- airs that give delight but hurt not.
- [% END %]
-
- # another filter example with configuration options
- [% USE autoformat %]
- [% FILTER autoformat(left => 20) %]
- Be not afeard. The isle is full of noises, sounds and sweet
- airs that give delight but hurt not.
- [% END %]
-
- # another FILTER example, defining a 'poetry' filter alias
- [% USE autoformat %]
- [% text FILTER poetry = autoformat(left => 20, right => 40) %]
-
- # reuse the 'poetry' filter alias
- [% text FILTER poetry %]
-
- # shorthand form ('|' is an alias for 'FILTER')
- [% text | autoformat %]
-
- # using forms
- [% USE autoformat(form => '>>>>.<<<', numeric => 'AllPlaces') %]
- [% autoformat(10, 20.32, 11.35) %]
-
-=head1 DESCRIPTION
-
-The autoformat plugin is an interface to Damian Conway's Text::Autoformat
-Perl module which provides advanced text wrapping and formatting.
-
-Configuration options may be passed to the plugin constructor via the
-USE directive.
-
- [% USE autoformat(right => 30) %]
-
-The autoformat subroutine can then be called, passing in text items which
-will be wrapped and formatted according to the current configuration.
-
- [% autoformat('The cat sat on the mat') %]
-
-Additional configuration items can be passed to the autoformat subroutine
-and will be merged with any existing configuration specified via the
-constructor.
-
- [% autoformat(text, left => 20) %]
-
-Configuration options are passed directly to the Text::Autoformat plugin.
-At the time of writing, the basic configuration items are:
-
- left left margin (default: 1)
- right right margin (default 72)
- justify justification as one of 'left', 'right', 'full'
- or 'centre' (default: left)
- case case conversion as one of 'lower', 'upper',
- 'sentence', 'title', or 'highlight' (default: none)
- squeeze squeeze whitespace (default: enabled)
-
-The plugin also accepts a 'form' item which can be used to define a
-format string. When a form is defined, the plugin will call the
-underlying form() subroutine in preference to autoformat().
-
- [% USE autoformat(form => '>>>>.<<') %]
- [% autoformat(123.45, 666, 3.14) %]
-
-Additional configuration items relevant to forms can also be specified.
-
- [% USE autoformat(form => '>>>>.<<', numeric => 'AllPlaces') %]
- [% autoformat(123.45, 666, 3.14) %]
-
-These can also be passed directly to the autoformat subroutine.
-
- [% USE autoformat %]
- [% autoformat( 123.45, 666, 3.14,
- form => '>>>>.<<',
- numeric => 'AllPlaces' )
- %]
-
-See L<Text::Autoformat> for further details.
-
-=head1 AUTHORS
-
-Robert McArthur E<lt>mcarthur@dstc.edu.auE<gt> wrote the original plugin
-code, with some modifications and additions from Andy Wardley
-E<lt>abw@wardley.orgE<gt>.
-
-Damian Conway E<lt>damian@conway.orgE<gt> wrote the Text::Autoformat
-module (in his copious spare time :-) which does all the clever stuff.
-
-=head1 VERSION
-
-2.64, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-
-
-=head1 COPYRIGHT
-
-Copyright (C) 2000 Robert McArthur & Andy Wardley. All Rights Reserved.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Text::Autoformat|Text::Autoformat>
-
diff --git a/lib/Template/Plugin/CGI.pm b/lib/Template/Plugin/CGI.pm
deleted file mode 100644
index 53b19d8..0000000
--- a/lib/Template/Plugin/CGI.pm
+++ /dev/null
@@ -1,168 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::CGI
-#
-# DESCRIPTION
-#
-# Simple Template Toolkit plugin interfacing to the CGI.pm module.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: CGI.pm,v 2.64 2004/01/13 16:20:38 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::CGI;
-
-require 5.004;
-
-use strict;
-use vars qw( $VERSION );
-use base qw( Template::Plugin );
-use Template::Plugin;
-use CGI;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.64 $ =~ /(\d+)\.(\d+)/);
-
-sub new {
- my $class = shift;
- my $context = shift;
- CGI->new(@_);
-}
-
-package CGI;
-
-sub params {
- my $self = shift;
- local $" = ', ';
-
- return $self->{ _TT_PARAMS } ||= do {
- # must call Vars() in a list context to receive
- # plain list of key/vals rather than a tied hash
- my $params = { $self->Vars() };
-
- # convert any null separated values into lists
- @$params{ keys %$params } = map {
- /\0/ ? [ split /\0/ ] : $_
- } values %$params;
-
- $params;
- };
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::CGI - Interface to the CGI module
-
-=head1 SYNOPSIS
-
- [% USE CGI %]
- [% CGI.param('parameter') %]
-
- [% USE things = CGI %]
- [% things.param('name') %]
-
- # see CGI docs for other methods provided by the CGI object
-
-=head1 DESCRIPTION
-
-This is a very simple Template Toolkit Plugin interface to the CGI module.
-A CGI object will be instantiated via the following directive:
-
- [% USE CGI %]
-
-CGI methods may then be called as follows:
-
- [% CGI.header %]
- [% CGI.param('parameter') %]
-
-An alias can be used to provide an alternate name by which the object should
-be identified.
-
- [% USE mycgi = CGI %]
- [% mycgi.start_form %]
- [% mycgi.popup_menu({ Name => 'Color'
- Values => [ 'Green' 'Black' 'Brown' ] }) %]
-
-Parenthesised parameters to the USE directive will be passed to the plugin
-constructor:
-
- [% USE cgiprm = CGI('uid=abw&name=Andy+Wardley') %]
- [% cgiprm.param('uid') %]
-
-=head1 METHODS
-
-In addition to all the methods supported by the CGI module, this
-plugin defines the following.
-
-=head2 params()
-
-This method returns a reference to a hash of all the CGI parameters.
-Any parameters that have multiple values will be returned as lists.
-
- [% USE CGI('user=abw&item=foo&item=bar') %]
-
- [% CGI.params.user %] # abw
- [% CGI.params.item.join(', ') %] # foo, bar
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.64, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<CGI|CGI>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/DBI.pm b/lib/Template/Plugin/DBI.pm
deleted file mode 100644
index b916bfc..0000000
--- a/lib/Template/Plugin/DBI.pm
+++ /dev/null
@@ -1,947 +0,0 @@
-#==============================================================================
-#
-# Template::Plugin::DBI
-#
-# DESCRIPTION
-# A Template Toolkit plugin to provide access to a DBI data source.
-#
-# AUTHORS
-# Original version by Simon Matthews <sam@knowledgepool.com>
-# with some reworking by Andy Wardley <abw@kfs.org> and other
-# contributions from Craig Barratt <craig@arraycomm.com>,
-# Dave Hodgkinson <daveh@davehodgkinson.com> and Rafael Kitover
-# <caelum@debian.org>
-#
-# COPYRIGHT
-# Copyright (C) 1999-2000 Simon Matthews. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-# REVISION
-# $Id: DBI.pm,v 2.62 2004/01/13 16:20:38 abw Exp $
-#
-#==============================================================================
-
-package Template::Plugin::DBI;
-
-require 5.004;
-
-use strict;
-use Template::Plugin;
-use Template::Exception;
-use DBI;
-
-use vars qw( $VERSION $DEBUG $QUERY $ITERATOR );
-use base qw( Template::Plugin );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.62 $ =~ /(\d+)\.(\d+)/);
-$DEBUG = 0 unless defined $DEBUG;
-$QUERY = 'Template::Plugin::DBI::Query';
-$ITERATOR = 'Template::Plugin::DBI::Iterator';
-
-# alias _connect() to connect() for backwards compatability
-*_connect = \*connect;
-
-
-#------------------------------------------------------------------------
-# new($context, @params)
-#
-# Constructor which returns a reference to a new DBI plugin object.
-# A connection string (dsn), user name and password may be passed as
-# positional arguments or a hash array of connection parameters can be
-# passed to initialise a connection. Otherwise, an unconnected DBI
-# plugin object is returned.
-#------------------------------------------------------------------------
-
-sub new {
- my $class = shift;
- my $context = shift;
- my $self = ref $class ? $class : bless {
- _CONTEXT => $context,
- _STH => [ ],
- }, $class;
-
- $self->connect(@_) if @_;
-
- return $self;
-}
-
-
-#------------------------------------------------------------------------
-# connect( $data_source, $username, $password, $attributes )
-# connect( { data_source => 'dbi:driver:database'
-# username => 'foo'
-# password => 'bar' } )
-#
-# Opens a DBI connection for the plugin.
-#------------------------------------------------------------------------
-
-sub connect {
- my $self = shift;
- my $params = ref $_[-1] eq 'HASH' ? pop(@_) : { };
- my ($dbh, $dsn, $user, $pass, $klobs);
-
- # set debug flag
- $DEBUG = $params->{ debug } if exists $params->{ debug };
- $self->{ _DEBUG } = $params->{ debug } || 0;
-
- # fetch 'dbh' named paramater or use positional arguments or named
- # parameters to specify 'dsn', 'user' and 'pass'
-
- if ($dbh = $params->{ dbh }) {
- # disconnect any existing database handle that we previously opened
- $self->{ _DBH }->disconnect()
- if $self->{ _DBH } && $self->{ _DBH_CONNECT };
-
- # store new dbh but leave _DBH_CONNECT false to prevent us
- # from automatically closing it in the future
- $self->{ _DBH } = $dbh;
- $self->{ _DBH_CONNECT } = 0;
- }
- else {
-
- # certain Perl programmers are known to have problems with short
- # term memory loss (see Tie::Hash::Cannabinol) so we let the poor
- # blighters fumble any kind of argument that looks like it might
- # identify the database
-
- $dsn = shift
- || $params->{ data_source }
- || $params->{ database }
- || $params->{ connect }
- || $params->{ dsn }
- || $params->{ db }
- || $ENV{DBI_DSN}
- || return $self->_throw('data source not defined');
-
- # add 'dbi:' prefix if it's not there
- $dsn = "dbi:$dsn" unless $dsn =~ /^dbi:/i;
-
- $user = shift
- || $params->{ username }
- || $params->{ user };
-
- $pass = shift
- || $params->{ password }
- || $params->{ pass };
-
- # save connection data because we might need it later to do a tie()
- @$self{ qw( _DSN _USER _PASS ) } = ($dsn, $user, $pass);
-
- # reuse existing database handle if connection params match
- my $connect = join(':', $dsn || '', $user || '', $pass || '');
- return ''
- if $self->{ _DBH } && $self->{ _DBH_CONNECT } eq $connect;
-
- # otherwise disconnect any existing database handle that we opened
- $self->{ _DBH }->disconnect()
- if $self->{ _DBH } && $self->{ _DBH_CONNECT };
-
- # don't need DBI to automatically print errors because all calls go
- # via this plugin interface and we always check return values
- $params->{ PrintError } = 0
- unless defined $params->{ PrintError };
-
- $self->{ _DBH } = DBI->connect_cached( $dsn, $user, $pass, $params )
- || return $self->_throw("DBI connect failed: $DBI::errstr");
-
- # store the connection parameters
- $self->{ _DBH_CONNECT } = $connect;
- }
-
- return '';
-}
-
-
-#------------------------------------------------------------------------
-# disconnect()
-#
-# Disconnects the current active database connection.
-#------------------------------------------------------------------------
-
-sub disconnect {
- my $self = shift;
- $self->{ _DBH }->disconnect()
- if $self->{ _DBH };
- delete $self->{ _DBH };
- return '';
-}
-
-
-#------------------------------------------------------------------------
-# tie( $table, $key )
-#
-# Return a hash tied to a table in the database, indexed by the specified
-# key.
-#------------------------------------------------------------------------
-
-sub tie {
- my $self = shift;
- my $params = ref $_[-1] eq 'HASH' ? pop(@_) : { };
- my ($table, $key, $klobs, $debug, %hash);
-
- eval { require Tie::DBI };
- $self->_throw("failed to load Tie::DBI module: $@") if $@;
-
- $table = shift
- || $params->{ table }
- || $self->_throw('table not defined');
-
- $key = shift
- || $params->{ key }
- || $self->_throw('key not defined');
-
- # Achtung der Klobberman!
- $klobs = $params->{ clobber };
- $klobs = $params->{ CLOBBER } unless defined $klobs;
-
- # going the extra mile to allow user to use UPPER or lower case or
- # inherit internel debug flag set by connect()
- $debug = $params->{ debug };
- $debug = $params->{ DEBUG } unless defined $debug;
- $debug = $self->{ _DEBUG } unless defined $debug;
-
- tie %hash, 'Tie::DBI', {
- %$params, # any other Tie::DBI options like DEBUG, WARN, etc
- db => $self->{ _DBH } || $self->{ _DSN },
- user => $self->{ _USER },
- password => $self->{ _PASS },
- table => $table,
- key => $key,
- CLOBBER => $klobs || 0,
- DEBUG => $debug || 0,
- };
-
- return \%hash;
-}
-
-
-#------------------------------------------------------------------------
-# prepare($sql)
-#
-# Prepare a query and store the live statement handle internally for
-# subsequent execute() calls.
-#------------------------------------------------------------------------
-
-sub prepare {
- my $self = shift;
- my $sql = shift || return undef;
-
- my $sth = $self->dbh->prepare($sql)
- || return $self->_throw("DBI prepare failed: $DBI::errstr");
-
- # create wrapper object around handle to return to template client
- $sth = $QUERY->new($sth);
- push(@{ $self->{ _STH } }, $sth);
-
- return $sth;
-}
-
-
-#------------------------------------------------------------------------
-# execute()
-#
-# Calls execute() on the most recent statement created via prepare().
-#------------------------------------------------------------------------
-
-sub execute {
- my $self = shift;
-
- my $sth = $self->{ _STH }->[-1]
- || return $self->_throw('no query prepared');
-
- $sth->execute(@_);
-}
-
-
-#------------------------------------------------------------------------
-# query($sql, @params)
-#
-# Prepares and executes a SQL query.
-#------------------------------------------------------------------------
-
-sub query {
- my $self = shift;
- my $sql = shift;
-
- $self->prepare($sql)->execute(@_);
-}
-
-
-#------------------------------------------------------------------------
-# do($sql, \%attr, @bind)
-#
-# Prepares and executes a SQL statement.
-#------------------------------------------------------------------------
-
-sub do {
- my $self = shift;
-
- return $self->dbh->do(@_)
- || $self->_throw("DBI do failed: $DBI::errstr");
-}
-
-
-#------------------------------------------------------------------------
-# quote($value [, $data_type ])
-#
-# Returns a quoted string (correct for the connected database) from the
-# value passed in.
-#------------------------------------------------------------------------
-
-sub quote {
- my $self = shift;
- $self->dbh->quote(@_);
-}
-
-
-#------------------------------------------------------------------------
-# dbh()
-#
-# Internal method to retrieve the database handle belonging to the
-# instance or attempt to create a new one using connect.
-#------------------------------------------------------------------------
-
-sub dbh {
- my $self = shift;
-
- return $self->{ _DBH } || do {
- $self->connect;
- $self->{ _DBH };
- };
-}
-
-
-#------------------------------------------------------------------------
-# DESTROY
-#
-# Called automatically when the plugin object goes out of scope to
-# disconnect the database handle cleanly
-#------------------------------------------------------------------------
-
-sub DESTROY {
- my $self = shift;
- delete($self->{ _STH }); # first DESTROY any queries
- $self->{ _DBH }->disconnect()
- if $self->{ _DBH } && $self->{ _DBH_CONNECT };
-}
-
-
-#------------------------------------------------------------------------
-# _throw($error)
-#
-# Raise an error by throwing it via die() as a Template::Exception
-# object of type 'DBI'.
-#------------------------------------------------------------------------
-
-sub _throw {
- my $self = shift;
- my $error = shift || die "DBI throw() called without an error string\n";
-
- # throw error as DBI exception
- die (Template::Exception->new('DBI', $error));
-}
-
-
-#========================================================================
-# Template::Plugin::DBI::Query
-#========================================================================
-
-package Template::Plugin::DBI::Query;
-use vars qw( $DEBUG $ITERATOR );
-
-*DEBUG = \$Template::Plugin::DBI::DEBUG;
-*ITERATOR = \$Template::Plugin::DBI::ITERATOR;
-
-
-sub new {
- my ($class, $sth) = @_;
- bless \$sth, $class;
-}
-
-sub execute {
- my $self = shift;
-
- $$self->execute(@_)
- || return Template::Plugin::DBI->_throw("execute failed: $DBI::errstr");
-
- $ITERATOR->new($$self);
-}
-
-sub DESTROY {
- my $self = shift;
- $$self->finish();
-}
-
-
-#========================================================================
-# Template::Plugin::DBI::Iterator;
-#========================================================================
-
-package Template::Plugin::DBI::Iterator;
-
-use Template::Iterator;
-use base qw( Template::Iterator );
-use vars qw( $DEBUG );
-
-*DEBUG = \$Template::Plugin::DBI::DEBUG;
-
-
-sub new {
- my ($class, $sth, $params) = @_;
-
- my $rows = $sth->rows();
-
- my $self = bless {
- _STH => $sth,
- SIZE => $rows,
- MAX => $rows - 1,
- }, $class;
-
-
- return $self;
-}
-
-
-#------------------------------------------------------------------------
-# get_first()
-#
-# Initialises iterator to read from statement handle. We maintain a
-# one-record lookahead buffer to allow us to detect if the current
-# record is the last in the series.
-#------------------------------------------------------------------------
-
-sub get_first {
- my $self = shift;
- $self->{ _STARTED } = 1;
-
- # set some status variables into $self
- @$self{ qw( PREV ITEM FIRST LAST COUNT INDEX ) }
- = ( undef, undef, 2, 0, 0, -1 );
-
- # support 'number' as an alias for 'count' for backwards compatability
- $self->{ NUMBER } = 0;
-
- print STDERR "get_first() called\n" if $DEBUG;
-
- # get the first row
- $self->_fetchrow();
-
- print STDERR "get_first() calling get_next()\n" if $DEBUG;
-
- return $self->get_next();
-}
-
-
-#------------------------------------------------------------------------
-# get_next()
-#
-# Called to read remaining result records from statement handle.
-#------------------------------------------------------------------------
-
-sub get_next {
- my $self = shift;
- my ($data, $fixup);
-
- # increment the 'index' and 'count' counts
- $self->{ INDEX }++;
- $self->{ COUNT }++;
- $self->{ NUMBER }++; # 'number' is old name for 'count'
-
- # decrement the 'first-record' flag
- $self->{ FIRST }-- if $self->{ FIRST };
-
- # we should have a row already cache in NEXT
- return (undef, Template::Constants::STATUS_DONE)
- unless $data = $self->{ NEXT };
-
- # set PREV to be current ITEM from last iteration
- $self->{ PREV } = $self->{ ITEM };
-
- # look ahead to the next row so that the rowcache is refilled
- $self->_fetchrow();
-
- $self->{ ITEM } = $data;
- return ($data, Template::Constants::STATUS_OK);
-}
-
-
-sub get {
- my $self = shift;
- my ($data, $error);
-
- ($data, $error) = $self->{ _STARTED }
- ? $self->get_next() : $self->get_first();
-
- return $data;
-}
-
-
-sub get_all {
- my $self = shift;
- my $sth = $self->{ _STH };
- my $error;
-
- my $data = $sth->fetchall_arrayref({});
- $self->throw($error) if ($error = $sth->err());
- unshift(@$data, $self->{ NEXT }) if $self->{ NEXT };
- $self->{ LAST } = 1;
- $self->{ NEXT } = undef;
- $sth->finish();
-
- return $data;
-}
-
-
-#------------------------------------------------------------------------
-# _fetchrow()
-#
-# Retrieve a record from the statement handle and store in row cache.
-#------------------------------------------------------------------------
-
-sub _fetchrow {
- my $self = shift;
- my $sth = $self->{ _STH };
-
- my $data = $sth->fetchrow_hashref() || do {
- $self->{ LAST } = 1;
- $self->{ NEXT } = undef;
- $sth->finish();
- return;
- };
- $self->{ NEXT } = $data;
- return;
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::DBI - Template interface to the DBI module
-
-=head1 SYNOPSIS
-
-Making an implicit database connection:
-
- # ...using positional arguments
- [% USE DBI('dbi:driver:dbname', 'user', 'pass') %]
-
- # ...using named parameters
- [% USE DBI( database = 'dbi:driver:dbname',
- username = 'user',
- password = 'pass' )
- %]
-
- # ...using short named parameters (4 lzy ppl and bad typsits)
- [% USE DBI( db = 'driver:dbname',
- user = 'user',
- pass = 'pass' )
- %]
-
- # ...or an existing DBI database handle
- [% USE DBI( dbh = my_dbh_ref ) %]
-
-Making explicit database connections:
-
- [% USE DBI %]
-
- [% DBI.connect(db, user, pass) %]
- ...
-
- [% DBI.connect(new_db, new_user, new_pass) %]
- ...
-
- [% DBI.disconnect %] # final disconnect is optional
-
-Making an automagical database connection using DBI_DSN environment variable:
-
- [% USE DBI %]
-
-Making database queries:
-
- # single step query
- [% FOREACH user = DBI.query('SELECT * FROM users') %]
- [% user.uid %] blah blah [% user.name %] etc. etc.
- [% END %]
-
- # two stage prepare/execute
- [% query = DBI.prepare('SELECT * FROM users WHERE uid = ?') %]
-
- [% FOREACH user = query.execute('sam') %]
- ...
- [% END %]
-
- [% FOREACH user = query.execute('abw') %]
- ...
- [% END %]
-
-Making non-SELECT statements:
-
- [% IF DBI.do("DELETE FROM users WHERE uid = '$uid'") %]
- The user '[% uid %]' was successfully deleted.
- [% END %]
-
-Using named DBI connections:
-
- [% USE one = DBI(...) %]
- [% USE two = DBI(...) %]
-
- [% FOREACH item = one.query("SELECT ...etc...") %]
- ...
- [% END %]
-
- [% FOREACH item = two.query("SELECT ...etc...") %]
- ...
- [% END %]
-
-Tieing to a database table (via Tie::DBI):
-
- [% people = DBI.tie('users', 'uid') %]
-
- [% me = people.abw %] # => SELECT * FROM users WHERE uid='abw'
-
- I am [% me.name %]
-
- # clobber option allows table updates (see Tie::DBI)
- [% people = DBI.tie('users', 'uid', clobber=1) %]
-
- [% people.abw.name = 'not a number' %]
-
- I am [% people.abw.name %] # I am a free man!
-
-=head1 DESCRIPTION
-
-This Template Toolkit plugin module provides an interface to the Perl
-DBI/DBD modules, allowing you to integrate SQL queries into your
-template documents. It also provides an interface via the Tie::DBI
-module (if installed on your system) so that you can access database
-records without having to embed any SQL in your templates.
-
-A DBI plugin object can be created as follows:
-
- [% USE DBI %]
-
-This creates an uninitialised DBI object. You can then open a connection
-to a database using the connect() method.
-
- [% DBI.connect('dbi:driver:dbname', 'user', 'pass') %]
-
-The DBI connection can be opened when the plugin is created by passing
-arguments to the constructor, called from the USE directive.
-
- [% USE DBI('dbi:driver:dbname', 'user', 'pass') %]
-
-You can also use named parameters to provide the data source connection
-string, user name and password.
-
- [% USE DBI(database => 'dbi:driver:dbname',
- username => 'user',
- password => 'pass') %]
-
-For backwards compatability with previous versions of this plugin, you can
-also spell 'database' as 'data_source'.
-
- [% USE DBI(data_source => 'dbi:driver:dbname',
- username => 'user',
- password => 'pass') %]
-
-Lazy Template hackers may prefer to use 'db', 'dsn' or 'connect' as a
-shorthand form of the 'database' parameter, and 'user' and 'pass' as
-shorthand forms of 'username' and 'password', respectively. You can
-also drop the 'dbi:' prefix from the database connect string because
-the plugin will add it on for you automagically.
-
- [% USE DBI(db => 'driver:dbname',
- user => 'user',
- pass => 'pass') %]
-
-Any additional DBI attributes can be specified as named parameters.
-The 'PrintError' attribute defaults to 0 unless explicitly set true.
-
- [% USE DBI(db, user, pass, ChopBlanks=1) %]
-
-An alternate variable name can be provided for the plugin as per regular
-Template Toolkit syntax:
-
- [% USE mydb = DBI('dbi:driver:dbname', 'user', 'pass') %]
-
- [% FOREACH item = mydb.query('SELECT * FROM users') %]
- ...
- [% END %]
-
-You can also specify the DBI plugin name in lower case if you prefer:
-
- [% USE dbi(dsn, user, pass) %]
-
- [% FOREACH item = dbi.query('SELECT * FROM users') %]
- ...
- [% END %]
-
-The disconnect() method can be called to explicitly disconnect the
-current database, but this generally shouldn't be necessary as it is
-called automatically when the plugin goes out of scope. You can call
-connect() at any time to open a connection to another database. The
-previous connection will be closed automatically.
-
-Internally, the DBI connect_cached() method is used instead of the
-connect() method. This allows for connection caching in a server
-environment, such as when the Template Toolkit is used from an Apache
-mod_perl handler. In such a case, simply enable the mod_env module
-and put in a line such as:
-
- SetEnv DBI_DSN "dbi:mysql:dbname;host=dbhost;
- user=uname;password=pword"
-
-(NOTE: the string shown here is split across 2 lines for the sake of
-reasonable page formatting, but you should specify it all as one long
-string with no spaces or newlines).
-
-You can then use the DBI plugin without any parameters or the need
-to explicitly call connect().
-
-Once you've loaded a DBI plugin and opened a database connection using
-one of the techniques shown above, you can then make queries on the database
-using the familiar dotted notation:
-
- [% FOREACH user = DBI.query('SELECT * FROM users') %]
- [% user.uid %] blah blah [% user.name %] etc. etc.
- [% END %]
-
-The query() method prepares a query and executes it all in one go.
-If you want to repeat a query with different parameters then you
-can use a separate prepare/execute cycle.
-
- [% query = DBI.prepare('SELECT * FROM users WHERE uid = ?') %]
-
- [% FOREACH user = query.execute('sam') %]
- ...
- [% END %]
-
- [% FOREACH user = query.execute('abw') %]
- ...
- [% END %]
-
-The query() and execute() methods return an iterator object which
-manages the result set returned. You can save a reference to the
-iterator and access methods like size() to determine the number of
-rows returned by a query.
-
- [% users = DBI.query('SELECT * FROM users') %]
- [% users.size %] records returned
-
-or even
-
- [% DBI.query('SELECT * FROM users').size %]
-
-When used within a FOREACH loop, the iterator is always aliased to the
-special C<loop> variable. This makes it possible to do things like this:
-
- [% FOREACH user = DBI.query('SELECT * FROM users') %]
- [% loop.count %]/[% loop.size %]: [% user.name %]
- [% END %]
-
-to generate a result set of the form:
-
- 1/3: Jerry Garcia
- 2/3: Kurt Cobain
- 3/3: Freddie Mercury
-
-See L<Template::Iterator> for further details on iterators and the
-methods that they implement.
-
-The DBI plugin also provides the do() method to execute non-SELECT
-statements like this:
-
- [% IF DBI.do("DELETE FROM users WHERE uid = '$uid'") %]
- The user '[% uid %]' was successfully deleted.
- [% END %]
-
-The plugin also allows you to create a tie to a table in the database
-using the Tie::DBI module. Simply call the tie() method, passing the
-name of the table and the primary key as arguments.
-
- [% people = DBI.tie('person', 'uid') %]
-
-You can then access records in the database table as if they were
-entries in the 'people' hash.
-
- My name is [% people.abw.name %]
-
-IMPORTANT NOTE: the XS Stash (Template::Stash::XS) does not currently
-support access to tied hashes. If you are using the XS stash and having
-problems then you should try enabling the regular stash instead. You
-can do this by setting $Template::Config::STASH to 'Template::Stash'
-before instantiating the Template object.
-
-=head1 OBJECT METHODS
-
-=head2 connect($database, $username, $password)
-
-Establishes a database connection. This method accepts both positional
-and named parameter syntax. e.g.
-
- [% DBI.connect( 'dbi:driver:dbname', 'timmy', 'sk8D00Dz' ) %]
-
- [% DBI.connect( database = 'dbi:driver:dbname'
- username = 'timmy'
- password = 'sk8D00Dz' ) %]
-
-The connect method allows you to connect to a data source explicitly.
-It can also be used to reconnect an exisiting object to a different
-data source.
-
-If you already have a database handle then you can instruct the plugin
-to reuse it by passing it as the 'dbh' parameter.
-
- [% DBI.connect( dbh = my_dbh_ref ) %]
-
-=head2 query($sql)
-
-This method submits an SQL query to the database and creates an iterator
-object to return the results. This may be used directly in a FOREACH
-directive as shown below. Data is automatically fetched a row at a time
-from the query result set as required for memory efficiency.
-
- [% FOREACH user = DBI.query('SELECT * FROM users') %]
- Each [% user.field %] can be printed here
- [% END %]
-
-=head2 prepare($sql)
-
-Prepare a query for later execution. This returns a compiled query
-object (of the Template::Plugin::DBI::Query class) on which the
-execute() method can subsequently be called.
-
- [% query = DBI.prepare('SELECT * FROM users WHERE id = ?') %]
-
-=head2 execute(@args)
-
-Execute a previously prepared query. This method should be called on
-the query object returned by the prepare() method. Returns an
-iterator object which can be used directly in a FOREACH directive.
-
- [% query = DBI.prepare('SELECT * FROM users WHERE manager = ?') %]
-
- [% FOREACH minion = query.execute('abw') %]
- [% minion.name %]
- [% END %]
-
- [% FOREACH minion = query.execute('sam') %]
- [% minion.name %]
- [% END %]
-
-=head2 do($sql)
-
-The do() method executes a sql statement from which no records are
-returned. It will return true if the statement was successful
-
- [% IF DBI.do("DELETE FROM users WHERE uid = 'sam'") %]
- The user was successfully deleted.
- [% END %]
-
-=head2 tie($table, $key, \%args)
-
-Returns a reference to a hash array tied to a table in the database,
-implemented using the Tie::DBI module. You should pass the name of
-the table and the key field as arguments.
-
- [% people = DBI.tie('users', 'uid') %]
-
-Or if you prefer, you can use the 'table' and 'key' named parameters.
-
- [% people = DBI.tie(table='users', key='uid') %]
-
-In this example, the Tie::DBI module will convert the accesses into
-the 'people' hash into SQL queries of the form:
-
- SELECT * FROM users WHERE uid=?
-
-For example:
-
- [% me = people.abw %]
-
-The record returned can then be accessed just like a normal hash.
-
- I am [% me.name %]
-
-You can also do things like this to iterate through all the records
-in a table.
-
- [% FOREACH uid = people.keys.sort;
- person = people.$uid
- %]
- * [% person.id %] : [% person.name %]
- [% END %]
-
-With the 'clobber' (or 'CLOBBER') option set you can update the record
-and have those changes automatically permeated back into the database.
-
- [% people = DBI.tie('users', 'uid', clobber=1) %]
-
- [% people.abw.name = 'not a number' %]
-
- I am [% people.abw.name %] # I am a free man!
-
-And you can also add new records.
-
- [% people.newguy = {
- name = 'Nobby Newguy'
- ...other fields...
- }
- %]
-
-See L<Tie::DBI> for further information on the 'CLOBBER' option.
-
-=head2 quote($value, $type)
-
-Calls the quote() method on the underlying DBI handle to quote the value
-specified in the appropriate manner for its type.
-
-=head2 dbh()
-
-Return the database handle currently in use by the plugin.
-
-=head2 disconnect()
-
-Disconnects the current database.
-
-=head1 AUTHORS
-
-The DBI plugin was originally written by Simon A Matthews, and
-distributed as a separate module. It was integrated into the Template
-Toolkit distribution for version 2.00 and includes contributions from
-Andy Wardley, Craig Barratt, Dave Hodgkinson and Rafael Kitover.
-
-=head1 VERSION
-
-2.62, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-
-
-=head1 COPYRIGHT
-
-Copyright (C) 1999-2001 Simon Matthews. All Rights Reserved
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<DBI|DBI>, L<Tie::DBI|Tie::DBI>
-
diff --git a/lib/Template/Plugin/Datafile.pm b/lib/Template/Plugin/Datafile.pm
deleted file mode 100644
index 5cf53af..0000000
--- a/lib/Template/Plugin/Datafile.pm
+++ /dev/null
@@ -1,198 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::Datafile
-#
-# DESCRIPTION
-#
-# Template Toolkit Plugin which reads a datafile and constructs a
-# list object containing hashes representing records in the file.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Datafile.pm,v 2.66 2004/01/13 16:20:38 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::Datafile;
-
-require 5.004;
-
-use strict;
-use vars qw( @ISA $VERSION );
-use base qw( Template::Plugin );
-use Template::Plugin;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.66 $ =~ /(\d+)\.(\d+)/);
-
-sub new {
- my ($class, $context, $filename, $params) = @_;
- my ($delim, $line, @fields, @data, @results);
- my $self = [ ];
- local *FD;
- local $/ = "\n";
-
- $params ||= { };
- $delim = $params->{'delim'} || ':';
- $delim = quotemeta($delim);
-
- return $class->fail("No filename specified")
- unless $filename;
-
- open(FD, $filename)
- || return $class->fail("$filename: $!");
-
- # first line of file should contain field definitions
- while (! $line || $line =~ /^#/) {
- $line = <FD>;
- chomp $line;
- $line =~ s/\r$//;
- }
-
- (@fields = split(/\s*$delim\s*/, $line))
- || return $class->fail("first line of file must contain field names");
-
- # read each line of the file
- while (<FD>) {
- chomp;
- s/\r$//;
-
- # ignore comments and blank lines
- next if /^#/ || /^\s*$/;
-
- # split line into fields
- @data = split(/\s*$delim\s*/);
-
- # create hash record to represent data
- my %record;
- @record{ @fields } = @data;
-
- push(@$self, \%record);
- }
-
-# return $self;
- bless $self, $class;
-}
-
-
-sub as_list {
- return $_[0];
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::Datafile - Plugin to construct records from a simple data file
-
-=head1 SYNOPSIS
-
- [% USE mydata = datafile('/path/to/datafile') %]
- [% USE mydata = datafile('/path/to/datafile', delim = '|') %]
-
- [% FOREACH record = mydata %]
- [% record.this %] [% record.that %]
- [% END %]
-
-=head1 DESCRIPTION
-
-This plugin provides a simple facility to construct a list of hash
-references, each of which represents a data record of known structure,
-from a data file.
-
- [% USE datafile(filename) %]
-
-A absolute filename must be specified (for this initial implementation at
-least - in a future version it might also use the INCLUDE_PATH). An
-optional 'delim' parameter may also be provided to specify an alternate
-delimiter character.
-
- [% USE userlist = datafile('/path/to/file/users') %]
- [% USE things = datafile('items', delim = '|') %]
-
-The format of the file is intentionally simple. The first line
-defines the field names, delimited by colons with optional surrounding
-whitespace. Subsequent lines then defines records containing data
-items, also delimited by colons. e.g.
-
- id : name : email : tel
- abw : Andy Wardley : abw@cre.canon.co.uk : 555-1234
- neilb : Neil Bowers : neilb@cre.canon.co.uk : 555-9876
-
-Each line is read, split into composite fields, and then used to
-initialise a hash array containing the field names as relevant keys.
-The plugin returns a blessed list reference containing the hash
-references in the order as defined in the file.
-
- [% FOREACH user = userlist %]
- [% user.id %]: [% user.name %]
- [% END %]
-
-The first line of the file B<must> contain the field definitions.
-After the first line, blank lines will be ignored, along with comment
-line which start with a '#'.
-
-=head1 BUGS
-
-Should handle file names relative to INCLUDE_PATH.
-Doesn't permit use of ':' in a field. Some escaping mechanism is required.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.66, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/Date.pm b/lib/Template/Plugin/Date.pm
deleted file mode 100644
index 7351686..0000000
--- a/lib/Template/Plugin/Date.pm
+++ /dev/null
@@ -1,361 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::Date
-#
-# DESCRIPTION
-#
-# Plugin to generate formatted date strings.
-#
-# AUTHORS
-# Thierry-Michel Barral <kktos@electron-libre.com>
-# Andy Wardley <abw@cre.canon.co.uk>
-#
-# COPYRIGHT
-# Copyright (C) 2000 Thierry-Michel Barral, Andy Wardley.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Date.pm,v 2.71 2004/01/13 16:20:38 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::Date;
-
-use strict;
-use vars qw( $VERSION $FORMAT @LOCALE_SUFFIX );
-use base qw( Template::Plugin );
-use Template::Plugin;
-
-use POSIX ();
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.71 $ =~ /(\d+)\.(\d+)/);
-$FORMAT = '%H:%M:%S %d-%b-%Y'; # default strftime() format
-@LOCALE_SUFFIX = qw( .ISO8859-1 .ISO_8859-15 .US-ASCII .UTF-8 );
-
-#------------------------------------------------------------------------
-# new(\%options)
-#------------------------------------------------------------------------
-
-sub new {
- my ($class, $context, $params) = @_;
- bless {
- $params ? %$params : ()
- }, $class;
-}
-
-
-#------------------------------------------------------------------------
-# now()
-#
-# Call time() to return the current system time in seconds since the epoch.
-#------------------------------------------------------------------------
-
-sub now {
- return time();
-}
-
-
-#------------------------------------------------------------------------
-# format()
-# format($time)
-# format($time, $format)
-# format($time, $format, $locale)
-# format($time, $format, $locale, $gmt_flag)
-# format(\%named_params);
-#
-# Returns a formatted time/date string for the specified time, $time,
-# (or the current system time if unspecified) using the $format, $locale,
-# and $gmt values specified as arguments or internal values set defined
-# at construction time). Specifying a Perl-true value for $gmt will
-# override the local time zone and force the output to be for GMT.
-# Any or all of the arguments may be specified as named parameters which
-# get passed as a hash array reference as the final argument.
-# ------------------------------------------------------------------------
-
-sub format {
- my $self = shift;
- my $params = ref($_[$#_]) eq 'HASH' ? pop(@_) : { };
- my $time = shift(@_) || $params->{ time } || $self->{ time }
- || $self->now();
- my $format = @_ ? shift(@_)
- : ($params->{ format } || $self->{ format } || $FORMAT);
- my $locale = @_ ? shift(@_)
- : ($params->{ locale } || $self->{ locale });
- my $gmt = @_ ? shift(@_)
- : ($params->{ gmt } || $self->{ gmt });
- my (@date, $datestr);
-
- if ($time =~ /^\d+$/) {
- # $time is now in seconds since epoch
- if ($gmt) {
- @date = (gmtime($time))[0..6];
- }
- else {
- @date = (localtime($time))[0..6];
- }
- }
- else {
- # if $time is numeric, then we assume it's seconds since the epoch
- # otherwise, we try to parse it as a 'H:M:S D:M:Y' string
- @date = (split(/(?:\/| |:|-)/, $time))[2,1,0,3..5];
- return (undef, Template::Exception->new('date',
- "bad time/date string: expects 'h:m:s d:m:y' got: '$time'"))
- unless @date >= 6 && defined $date[5];
- $date[4] -= 1; # correct month number 1-12 to range 0-11
- $date[5] -= 1900; # convert absolute year to years since 1900
- $time = &POSIX::mktime(@date);
- }
-
- if ($locale) {
- # format the date in a specific locale, saving and subsequently
- # restoring the current locale.
- my $old_locale = &POSIX::setlocale(&POSIX::LC_ALL);
-
- # some systems expect locales to have a particular suffix
- for my $suffix ('', @LOCALE_SUFFIX) {
- my $try_locale = $locale.$suffix;
- my $setlocale = &POSIX::setlocale(&POSIX::LC_ALL, $try_locale);
- if (defined $setlocale && $try_locale eq $setlocale) {
- $locale = $try_locale;
- last;
- }
- }
- $datestr = &POSIX::strftime($format, @date);
- &POSIX::setlocale(&POSIX::LC_ALL, $old_locale);
- }
- else {
- $datestr = &POSIX::strftime($format, @date);
- }
-
- return $datestr;
-}
-
-sub calc {
- my $self = shift;
- eval { require "Date/Calc.pm" };
- $self->throw("failed to load Date::Calc: $@") if $@;
- return Template::Plugin::Date::Calc->new('no context');
-}
-
-sub manip {
- my $self = shift;
- eval { require "Date/Manip.pm" };
- $self->throw("failed to load Date::Manip: $@") if $@;
- return Template::Plugin::Date::Manip->new('no context');
-}
-
-
-sub throw {
- my $self = shift;
- die (Template::Exception->new('date', join(', ', @_)));
-}
-
-
-package Template::Plugin::Date::Calc;
-use base qw( Template::Plugin );
-use vars qw( $AUTOLOAD );
-*throw = \&Template::Plugin::Date::throw;
-
-sub AUTOLOAD {
- my $self = shift;
- my $method = $AUTOLOAD;
-
- $method =~ s/.*:://;
- return if $method eq 'DESTROY';
-
- my $sub = \&{"Date::Calc::$method"};
- $self->throw("no such Date::Calc method: $method")
- unless $sub;
-
- &$sub(@_);
-}
-
-package Template::Plugin::Date::Manip;
-use base qw( Template::Plugin );
-use vars qw( $AUTOLOAD );
-*throw = \&Template::Plugin::Date::throw;
-
-sub AUTOLOAD {
- my $self = shift;
- my $method = $AUTOLOAD;
-
- $method =~ s/.*:://;
- return if $method eq 'DESTROY';
-
- my $sub = \&{"Date::Manip::$method"};
- $self->throw("no such Date::Manip method: $method")
- unless $sub;
-
- &$sub(@_);
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::Date - Plugin to generate formatted date strings
-
-=head1 SYNOPSIS
-
- [% USE date %]
-
- # use current time and default format
- [% date.format %]
-
- # specify time as seconds since epoch or 'h:m:s d-m-y' string
- [% date.format(960973980) %]
- [% date.format('4:20:36 21/12/2000') %]
-
- # specify format
- [% date.format(mytime, '%H:%M:%S') %]
-
- # specify locale
- [% date.format(date.now, '%a %d %b %y', 'en_GB') %]
-
- # named parameters
- [% date.format(mytime, format = '%H:%M:%S') %]
- [% date.format(locale = 'en_GB') %]
- [% date.format(time = date.now,
- format = '%H:%M:%S',
- locale = 'en_GB) %]
-
- # specify default format to plugin
- [% USE date(format = '%H:%M:%S', locale = 'de_DE') %]
-
- [% date.format %]
- ...
-
-=head1 DESCRIPTION
-
-The Date plugin provides an easy way to generate formatted time and date
-strings by delegating to the POSIX strftime() routine.
-
-The plugin can be loaded via the familiar USE directive.
-
- [% USE date %]
-
-This creates a plugin object with the default name of 'date'. An alternate
-name can be specified as such:
-
- [% USE myname = date %]
-
-The plugin provides the format() method which accepts a time value, a
-format string and a locale name. All of these parameters are optional
-with the current system time, default format ('%H:%M:%S %d-%b-%Y') and
-current locale being used respectively, if undefined. Default values
-for the time, format and/or locale may be specified as named parameters
-in the USE directive.
-
- [% USE date(format = '%a %d-%b-%Y', locale = 'fr_FR') %]
-
-When called without any parameters, the format() method returns a string
-representing the current system time, formatted by strftime() according
-to the default format and for the default locale (which may not be the
-current one, if locale is set in the USE directive).
-
- [% date.format %]
-
-The plugin allows a time/date to be specified as seconds since the epoch,
-as is returned by time().
-
- File last modified: [% date.format(filemod_time) %]
-
-The time/date can also be specified as a string of the form 'h:m:s d/m/y'.
-Any of the characters : / - or space may be used to delimit fields.
-
- [% USE day = date(format => '%A', locale => 'en_GB') %]
- [% day.format('4:20:00 9-13-2000') %]
-
-Output:
-
- Tuesday
-
-A format string can also be passed to the format() method, and a locale
-specification may follow that.
-
- [% date.format(filemod, '%d-%b-%Y') %]
- [% date.format(filemod, '%d-%b-%Y', 'en_GB') %]
-
-A fourth parameter allows you to force output in GMT, in the case of
-seconds-since-the-epoch input:
-
- [% date.format(filemod, '%d-%b-%Y', 'en_GB', 1) %]
-
-Note that in this case, if the local time is not GMT, then also specifying
-'%Z' (time zone) in the format parameter will lead to an extremely
-misleading result.
-
-Any or all of these parameters may be named. Positional parameters
-should always be in the order ($time, $format, $locale).
-
- [% date.format(format => '%H:%M:%S') %]
- [% date.format(time => filemod, format => '%H:%M:%S') %]
- [% date.format(mytime, format => '%H:%M:%S') %]
- [% date.format(mytime, format => '%H:%M:%S', locale => 'fr_FR') %]
- [% date.format(mytime, format => '%H:%M:%S', gmt => 1) %]
- ...etc...
-
-The now() method returns the current system time in seconds since the
-epoch.
-
- [% date.format(date.now, '%A') %]
-
-The calc() method can be used to create an interface to the Date::Calc
-module (if installed on your system).
-
- [% calc = date.calc %]
- [% calc.Monday_of_Week(22, 2001).join('/') %]
-
-The manip() method can be used to create an interface to the Date::Manip
-module (if installed on your system).
-
- [% manip = date.manip %]
- [% manip.UnixDate("Noon Yesterday","%Y %b %d %H:%M") %]
-
-=head1 AUTHORS
-
-Thierry-Michel Barral E<lt>kktos@electron-libre.comE<gt> wrote the original
-plugin.
-
-Andy Wardley E<lt>abw@cre.canon.co.ukE<gt> provided some minor
-fixups/enhancements, a test script and documentation.
-
-Mark D. Mills E<lt>mark@hostile.orgE<gt> cloned Date::Manip from the
-cute Date::Calc sub-plugin.
-
-=head1 VERSION
-
-2.71, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-
-
-=head1 COPYRIGHT
-
-Copyright (C) 2000 Thierry-Michel Barral, Andy Wardley.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<POSIX|POSIX>
-
diff --git a/lib/Template/Plugin/Directory.pm b/lib/Template/Plugin/Directory.pm
deleted file mode 100644
index ec6247e..0000000
--- a/lib/Template/Plugin/Directory.pm
+++ /dev/null
@@ -1,410 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::Directory
-#
-# DESCRIPTION
-# Plugin for encapsulating information about a file system directory.
-#
-# AUTHORS
-# Michael Stevens <michael@etla.org>, with some mutilations from
-# Andy Wardley <abw@kfs.org>.
-#
-# COPYRIGHT
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-# REVISION
-# $Id: Directory.pm,v 2.64 2004/01/13 16:20:38 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::Directory;
-
-require 5.004;
-
-use strict;
-use Cwd;
-use File::Spec;
-use Template::Plugin::File;
-use vars qw( $VERSION );
-use base qw( Template::Plugin::File );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.64 $ =~ /(\d+)\.(\d+)/);
-
-
-#------------------------------------------------------------------------
-# new(\%config)
-#
-# Constructor method.
-#------------------------------------------------------------------------
-
-sub new {
- my $config = ref($_[-1]) eq 'HASH' ? pop(@_) : { };
- my ($class, $context, $path) = @_;
-
- return $class->throw('no directory specified')
- unless defined $path and length $path;
-
- my $self = $class->SUPER::new($context, $path, $config);
- my ($dir, @files, $name, $item, $abs, $rel, $check);
- $self->{ files } = [ ];
- $self->{ dirs } = [ ];
- $self->{ list } = [ ];
- $self->{ _dir } = { };
-
- # don't read directory if 'nostat' or 'noscan' set
- return $self if $config->{ nostat } || $config->{ noscan };
-
- $self->throw("$path: not a directory")
- unless $self->{ isdir };
-
- $self->scan($config);
-
- return $self;
-}
-
-
-#------------------------------------------------------------------------
-# scan(\%config)
-#
-# Scan directory for files and sub-directories.
-#------------------------------------------------------------------------
-
-sub scan {
- my ($self, $config) = @_;
- $config ||= { };
- local *DH;
- my ($dir, @files, $name, $abs, $rel, $item);
-
- # set 'noscan' in config if recurse isn't set, to ensure Directories
- # created don't try to scan deeper
- $config->{ noscan } = 1 unless $config->{ recurse };
-
- $dir = $self->{ abs };
- opendir(DH, $dir) or return $self->throw("$dir: $!");
-
- @files = readdir DH;
- closedir(DH)
- or return $self->throw("$dir close: $!");
-
- my ($path, $files, $dirs, $list) = @$self{ qw( path files dirs list ) };
- @$files = @$dirs = @$list = ();
-
- foreach $name (sort @files) {
- next if $name =~ /^\./;
- $abs = File::Spec->catfile($dir, $name);
- $rel = File::Spec->catfile($path, $name);
-
- if (-d $abs) {
- $item = Template::Plugin::Directory->new(undef, $rel, $config);
- push(@$dirs, $item);
- }
- else {
- $item = Template::Plugin::File->new(undef, $rel, $config);
- push(@$files, $item);
- }
- push(@$list, $item);
- $self->{ _dir }->{ $name } = $item;
- }
-
- return '';
-}
-
-
-#------------------------------------------------------------------------
-# file($filename)
-#
-# Fetch a named file from this directory.
-#------------------------------------------------------------------------
-
-sub file {
- my ($self, $name) = @_;
- return $self->{ _dir }->{ $name };
-}
-
-
-#------------------------------------------------------------------------
-# present($view)
-#
-# Present self to a Template::View
-#------------------------------------------------------------------------
-
-sub present {
- my ($self, $view) = @_;
- $view->view_directory($self);
-}
-
-
-#------------------------------------------------------------------------
-# content($view)
-#
-# Present directory content to a Template::View.
-#------------------------------------------------------------------------
-
-sub content {
- my ($self, $view) = @_;
- return $self->{ list } unless $view;
- my $output = '';
- foreach my $file (@{ $self->{ list } }) {
- $output .= $file->present($view);
- }
- return $output;
-}
-
-
-#------------------------------------------------------------------------
-# throw($msg)
-#
-# Throw a 'Directory' exception.
-#------------------------------------------------------------------------
-
-sub throw {
- my ($self, $error) = @_;
- die (Template::Exception->new('Directory', $error));
-}
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::Directory - Plugin for generating directory listings
-
-=head1 SYNOPSIS
-
- [% USE dir = Directory(dirpath) %]
-
- # files returns list of regular files
- [% FOREACH file = dir.files %]
- [% file.name %] [% file.path %] ...
- [% END %]
-
- # dirs returns list of sub-directories
- [% FOREACH subdir = dir.dirs %]
- [% subdir.name %] [% subdir.path %] ...
- [% END %]
-
- # list returns both interleaved in order
- [% FOREACH item = dir.list %]
- [% IF item.isdir %]
- Directory: [% item.name %]
- [% ELSE
- File: [% item.name %]
- [% END %]
- [% END %]
-
- # define a VIEW to display dirs/files
- [% VIEW myview %]
- [% BLOCK file %]
- File: [% item.name %]
- [% END %]
-
- [% BLOCK directory %]
- Directory: [% item.name %]
- [% item.content(myview) | indent -%]
- [% END %]
- [% END %]
-
- # display directory content using view
- [% myview.print(dir) %]
-
-=head1 DESCRIPTION
-
-This Template Toolkit plugin provides a simple interface to directory
-listings. It is derived from the Template::Plugin::File module and
-uses Template::Plugin::File object instances to represent files within
-a directory. Sub-directories within a directory are represented by
-further Template::Plugin::Directory instances.
-
-The constructor expects a directory name as an argument.
-
- [% USE dir = Directory('/tmp') %]
-
-It then provides access to the files and sub-directories contained within
-the directory.
-
- # regular files (not directories)
- [% FOREACH file = dir.files %]
- [% file.name %]
- [% END %]
-
- # directories only
- [% FOREACH file = dir.dirs %]
- [% file.name %]
- [% END %]
-
- # files and/or directories
- [% FOREACH file = dir.list %]
- [% file.name %] ([% file.isdir ? 'directory' : 'file' %])
- [% END %]
-
- [% USE Directory('foo/baz') %]
-
-The plugin constructor will throw a 'Directory' error if the specified
-path does not exist, is not a directory or fails to stat() (see
-L<Template::Plugin::File>). Otherwise, it will scan the directory and
-create lists named 'files' containing files, 'dirs' containing
-directories and 'list' containing both files and directories combined.
-The 'nostat' option can be set to disable all file/directory checks
-and directory scanning.
-
-Each file in the directory will be represented by a
-Template::Plugin::File object instance, and each directory by another
-Template::Plugin::Directory. If the 'recurse' flag is set, then those
-directories will contain further nested entries, and so on. With the
-'recurse' flag unset, as it is by default, then each is just a place
-marker for the directory and does not contain any further content
-unless its scan() method is explicitly called. The 'isdir' flag can
-be tested against files and/or directories, returning true if the item
-is a directory or false if it is a regular file.
-
- [% FOREACH file = dir.list %]
- [% IF file.isdir %]
- * Directory: [% file.name %]
- [% ELSE %]
- * File: [% file.name %]
- [% END %]
- [% END %]
-
-This example shows how you might walk down a directory tree, displaying
-content as you go. With the recurse flag disabled, as is the default,
-we need to explicitly call the scan() method on each directory, to force
-it to lookup files and further sub-directories contained within.
-
- [% USE dir = Directory(dirpath) %]
- * [% dir.path %]
- [% INCLUDE showdir %]
-
- [% BLOCK showdir -%]
- [% FOREACH file = dir.list -%]
- [% IF file.isdir -%]
- * [% file.name %]
- [% file.scan -%]
- [% INCLUDE showdir dir=file FILTER indent(4) -%]
- [% ELSE -%]
- - [% f.name %]
- [% END -%]
- [% END -%]
- [% END %]
-
-This example is adapted (with some re-formatting for clarity) from
-a test in F<t/directry.t> which produces the following output:
-
- * test/dir
- - file1
- - file2
- * sub_one
- - bar
- - foo
- * sub_two
- - waz.html
- - wiz.html
- - xyzfile
-
-The 'recurse' flag can be set (disabled by default) to cause the
-constructor to automatically recurse down into all sub-directories,
-creating a new Template::Plugin::Directory object for each one and
-filling it with any further content. In this case there is no need
-to explicitly call the scan() method.
-
- [% USE dir = Directory(dirpath, recurse=1) %]
- ...
-
- [% IF file.isdir -%]
- * [% file.name %]
- [% INCLUDE showdir dir=file FILTER indent(4) -%]
- [% ELSE -%]
- ...
-
-From version 2.01, the Template Toolkit provides support for views.
-A view can be defined as a VIEW ... END block and should contain
-BLOCK definitions for files ('file') and directories ('directory').
-
- [% VIEW myview %]
- [% BLOCK file %]
- - [% item.name %]
- [% END %]
-
- [% BLOCK directory %]
- * [% item.name %]
- [% item.content(myview) FILTER indent %]
- [% END %]
- [% END %]
-
-Then the view print() method can be called, passing the
-Directory object as an argument.
-
- [% USE dir = Directory(dirpath, recurse=1) %]
- [% myview.print(dir) %]
-
-When a directory is presented to a view, either as [% myview.print(dir) %]
-or [% dir.present(view) %], then the 'directory' BLOCK within the 'myview'
-VIEW is processed, with the 'item' variable set to alias the Directory object.
-
- [% BLOCK directory %]
- * [% item.name %]
- [% item.content(myview) FILTER indent %]
- [% END %]
-
-The directory name is first printed and the content(view) method is
-then called to present each item within the directory to the view.
-Further directories will be mapped to the 'directory' block, and files
-will be mapped to the 'file' block.
-
-With the recurse option disabled, as it is by default, the 'directory'
-block should explicitly call a scan() on each directory.
-
- [% VIEW myview %]
- [% BLOCK file %]
- - [% item.name %]
- [% END %]
-
- [% BLOCK directory %]
- * [% item.name %]
- [% item.scan %]
- [% item.content(myview) FILTER indent %]
- [% END %]
- [% END %]
-
- [% USE dir = Directory(dirpath) %]
- [% myview.print(dir) %]
-
-=head1 TODO
-
-Might be nice to be able to specify accept/ignore options to catch
-a subset of files.
-
-=head1 AUTHORS
-
-Michael Stevens E<lt>michael@etla.orgE<gt> wrote the original Directory plugin
-on which this is based. Andy Wardley E<lt>abw@wardley.orgE<gt> split it into
-separate File and Directory plugins, added some extra code and documentation
-for VIEW support, and made a few other minor tweaks.
-
-=head1 VERSION
-
-2.64, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-
-
-=head1 COPYRIGHT
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Plugin::File|Template::Plugin::File>, L<Template::View|Template::View>
-
diff --git a/lib/Template/Plugin/Dumper.pm b/lib/Template/Plugin/Dumper.pm
deleted file mode 100644
index 5dbf1f6..0000000
--- a/lib/Template/Plugin/Dumper.pm
+++ /dev/null
@@ -1,179 +0,0 @@
-#==============================================================================
-#
-# Template::Plugin::Dumper
-#
-# DESCRIPTION
-#
-# A Template Plugin to provide a Template Interface to Data::Dumper
-#
-# AUTHOR
-# Simon Matthews <sam@knowledgepool.com>
-#
-# COPYRIGHT
-#
-# Copyright (C) 2000 Simon Matthews. All Rights Reserved
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#------------------------------------------------------------------------------
-#
-# $Id: Dumper.pm,v 2.64 2004/01/13 16:20:38 abw Exp $
-#
-#==============================================================================
-
-package Template::Plugin::Dumper;
-
-require 5.004;
-
-use strict;
-use Template::Plugin;
-use Data::Dumper;
-
-use vars qw( $VERSION $DEBUG @DUMPER_ARGS $AUTOLOAD );
-use base qw( Template::Plugin );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.64 $ =~ /(\d+)\.(\d+)/);
-$DEBUG = 0 unless defined $DEBUG;
-@DUMPER_ARGS = qw( Indent Pad Varname Purity Useqq Terse Freezer
- Toaster Deepcopy Quotekeys Bless Maxdepth );
-
-#==============================================================================
-# ----- CLASS METHODS -----
-#==============================================================================
-
-#------------------------------------------------------------------------
-# new($context, \@params)
-#------------------------------------------------------------------------
-
-sub new {
- my ($class, $context, $params) = @_;
- my ($key, $val);
- $params ||= { };
-
-
- foreach my $arg (@DUMPER_ARGS) {
- no strict 'refs';
- if (defined ($val = $params->{ lc $arg })
- or defined ($val = $params->{ $arg })) {
- ${"Data\::Dumper\::$arg"} = $val;
- }
- }
-
- bless {
- _CONTEXT => $context,
- }, $class;
-}
-
-sub dump {
- my $self = shift;
- my $content = Dumper @_;
- return $content;
-}
-
-
-sub dump_html {
- my $self = shift;
- my $content = Dumper @_;
- for ($content) {
- s/&/&amp;/g;
- s/</&lt;/g;
- s/>/&gt;/g;
- s/\n/<br>\n/g;
- }
- return $content;
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::Dumper - Plugin interface to Data::Dumper
-
-=head1 SYNOPSIS
-
- [% USE Dumper %]
-
- [% Dumper.dump(variable) %]
- [% Dumper.dump_html(variable) %]
-
-=head1 DESCRIPTION
-
-This is a very simple Template Toolkit Plugin Interface to the Data::Dumper
-module. A Dumper object will be instantiated via the following directive:
-
- [% USE Dumper %]
-
-As a standard plugin, you can also specify its name in lower case:
-
- [% USE dumper %]
-
-The Data::Dumper 'Pad', 'Indent' and 'Varname' options are supported
-as constructor arguments to affect the output generated. See L<Data::Dumper>
-for further details.
-
- [% USE dumper(Indent=0, Pad="<br>") %]
-
-These options can also be specified in lower case.
-
- [% USE dumper(indent=0, pad="<br>") %]
-
-=head1 METHODS
-
-There are two methods supported by the Dumper object. Each will
-output into the template the contents of the variables passed to the
-object method.
-
-=head2 dump()
-
-Generates a raw text dump of the data structure(s) passed
-
- [% USE Dumper %]
- [% Dumper.dump(myvar) %]
- [% Dumper.dump(myvar, yourvar) %]
-
-=head2 dump_html()
-
-Generates a dump of the data structures, as per dump(), but with the
-characters E<lt>, E<gt> and E<amp> converted to their equivalent HTML
-entities and newlines converted to E<lt>brE<gt>.
-
- [% USE Dumper %]
- [% Dumper.dump_html(myvar) %]
-
-=head1 AUTHOR
-
-Simon Matthews E<lt>sam@knowledgepool.comE<gt>
-
-=head1 VERSION
-
-2.64, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-
-
-=head1 COPYRIGHT
-
-Copyright (C) 2000 Simon Matthews All Rights Reserved.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Data::Dumper|Data::Dumper>
-
diff --git a/lib/Template/Plugin/File.pm b/lib/Template/Plugin/File.pm
deleted file mode 100644
index d1d542e..0000000
--- a/lib/Template/Plugin/File.pm
+++ /dev/null
@@ -1,416 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::File
-#
-# DESCRIPTION
-# Plugin for encapsulating information about a system file.
-#
-# AUTHOR
-# Originally written by Michael Stevens <michael@etla.org> as the
-# Directory plugin, then mutilated by Andy Wardley <abw@kfs.org>
-# into separate File and Directory plugins, with some additional
-# code for working with views, etc.
-#
-# COPYRIGHT
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-# REVISION
-# $Id: File.pm,v 2.64 2004/01/13 16:20:38 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::File;
-
-require 5.004;
-
-use strict;
-use Cwd;
-use File::Spec;
-use File::Basename;
-use Template::Plugin;
-
-use vars qw( $VERSION );
-use base qw( Template::Plugin );
-use vars qw( @STAT_KEYS );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.64 $ =~ /(\d+)\.(\d+)/);
-
-@STAT_KEYS = qw( dev ino mode nlink uid gid rdev size
- atime mtime ctime blksize blocks );
-
-
-#------------------------------------------------------------------------
-# new($context, $file, \%config)
-#
-# Create a new File object. Takes the pathname of the file as
-# the argument following the context and an optional
-# hash reference of configuration parameters.
-#------------------------------------------------------------------------
-
-sub new {
- my $config = ref($_[-1]) eq 'HASH' ? pop(@_) : { };
- my ($class, $context, $path) = @_;
- my ($root, $home, @stat, $abs);
-
- return $class->throw('no file specified')
- unless defined $path and length $path;
-
- # path, dir, name, root, home
-
- if (File::Spec->file_name_is_absolute($path)) {
- $root = '';
- }
- elsif (($root = $config->{ root })) {
- # strip any trailing '/' from root
- $root =~ s[/$][];
- }
- else {
- $root = '';
- }
-
- my ($name, $dir, $ext) = fileparse($path, '\.\w+');
- # fixup various items
- $dir =~ s[/$][];
- $dir = '' if $dir eq '.';
- $name = $name . $ext;
- $ext =~ s/^\.//g;
- my @fields = File::Spec->splitdir($dir);
- shift @fields if @fields && ! length $fields[0];
- $home = join('/', ('..') x @fields);
- $abs = File::Spec->catfile($root ? $root : (), $path);
-
- my $self = {
- path => $path,
- name => $name,
- root => $root,
- home => $home,
- dir => $dir,
- ext => $ext,
- abs => $abs,
- user => '',
- group => '',
- isdir => '',
- stat => defined $config->{ stat } ? $config->{ stat }
- : ! $config->{ nostat },
- map { ($_ => '') } @STAT_KEYS,
- };
-
- if ($self->{ stat }) {
- (@stat = stat( $abs ))
- || return $class->throw("$abs: $!");
- @$self{ @STAT_KEYS } = @stat;
- unless ($config->{ noid }) {
- $self->{ user } = eval { getpwuid( $self->{ uid }) || $self->{ uid } };
- $self->{ group } = eval { getgrgid( $self->{ gid }) || $self->{ gid } };
- }
- $self->{ isdir } = -d $abs;
- }
-
- bless $self, $class;
-}
-
-
-#-------------------------------------------------------------------------
-# rel($file)
-#
-# Generate a relative filename for some other file relative to this one.
-#------------------------------------------------------------------------
-
-sub rel {
- my ($self, $path) = @_;
- $path = $path->{ path } if ref $path eq ref $self; # assumes same root
- return $path if $path =~ m[^/];
- return $path unless $self->{ home };
- return $self->{ home } . '/' . $path;
-}
-
-
-#------------------------------------------------------------------------
-# present($view)
-#
-# Present self to a Template::View.
-#------------------------------------------------------------------------
-
-sub present {
- my ($self, $view) = @_;
- $view->view_file($self);
-}
-
-
-sub throw {
- my ($self, $error) = @_;
- die (Template::Exception->new('File', $error));
-}
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::File - Plugin providing information about files
-
-=head1 SYNOPSIS
-
- [% USE File(filepath) %]
- [% File.path %] # full path
- [% File.name %] # filename
- [% File.dir %] # directory
-
-=head1 DESCRIPTION
-
-This plugin provides an abstraction of a file. It can be used to
-fetch details about files from the file system, or to represent abstract
-files (e.g. when creating an index page) that may or may not exist on
-a file system.
-
-A file name or path should be specified as a constructor argument. e.g.
-
- [% USE File('foo.html') %]
- [% USE File('foo/bar/baz.html') %]
- [% USE File('/foo/bar/baz.html') %]
-
-The file should exist on the current file system (unless 'nostat'
-option set, see below) as an absolute file when specified with as
-leading '/' as per '/foo/bar/baz.html', or otherwise as one relative
-to the current working directory. The constructor performs a stat()
-on the file and makes the 13 elements returned available as the plugin
-items:
-
- dev ino mode nlink uid gid rdev size
- atime mtime ctime blksize blocks
-
-e.g.
-
- [% USE File('/foo/bar/baz.html') %]
-
- [% File.mtime %]
- [% File.mode %]
- ...
-
-In addition, the 'user' and 'group' items are set to contain the user
-and group names as returned by calls to getpwuid() and getgrgid() for
-the file 'uid' and 'gid' elements, respectively. On Win32 platforms
-on which getpwuid() and getgrid() are not available, these values are
-undefined.
-
- [% USE File('/tmp/foo.html') %]
- [% File.uid %] # e.g. 500
- [% File.user %] # e.g. abw
-
-This user/group lookup can be disabled by setting the 'noid' option.
-
- [% USE File('/tmp/foo.html', noid=1) %]
- [% File.uid %] # e.g. 500
- [% File.user %] # nothing
-
-The 'isdir' flag will be set if the file is a directory.
-
- [% USE File('/tmp') %]
- [% File.isdir %] # 1
-
-If the stat() on the file fails (e.g. file doesn't exists, bad
-permission, etc) then the constructor will throw a 'File' exception.
-This can be caught within a TRY...CATCH block.
-
- [% TRY %]
- [% USE File('/tmp/myfile') %]
- File exists!
- [% CATCH File %]
- File error: [% error.info %]
- [% END %]
-
-Note the capitalisation of the exception type, 'File' to indicate an
-error thrown by the 'File' plugin, to distinguish it from a regular
-'file' exception thrown by the Template Toolkit.
-
-Note that the 'File' plugin can also be referenced by the lower case
-name 'file'. However, exceptions are always thrown of the 'File'
-type, regardless of the capitalisation of the plugin named used.
-
- [% USE file('foo.html') %]
- [% file.mtime %]
-
-As with any other Template Toolkit plugin, an alternate name can be
-specified for the object created.
-
- [% USE foo = file('foo.html') %]
- [% foo.mtime %]
-
-The 'nostat' option can be specified to prevent the plugin constructor
-from performing a stat() on the file specified. In this case, the
-file does not have to exist in the file system, no attempt will be made
-to verify that it does, and no error will be thrown if it doesn't.
-The entries for the items usually returned by stat() will be set
-empty.
-
- [% USE file('/some/where/over/the/rainbow.html', nostat=1)
- [% file.mtime %] # nothing
-
-All File plugins, regardless of the nostat option, have set a number
-of items relating to the original path specified.
-
-=over 4
-
-=item path
-
-The full, original file path specified to the constructor.
-
- [% USE file('/foo/bar.html') %]
- [% file.path %] # /foo/bar.html
-
-=item name
-
-The name of the file without any leading directories.
-
- [% USE file('/foo/bar.html') %]
- [% file.name %] # bar.html
-
-=item dir
-
-The directory element of the path with the filename removed.
-
- [% USE file('/foo/bar.html') %]
- [% file.name %] # /foo
-
-=item ext
-
-The file extension, if any, appearing at the end of the path following
-a '.' (not included in the extension).
-
- [% USE file('/foo/bar.html') %]
- [% file.ext %] # html
-
-=item home
-
-This contains a string of the form '../..' to represent the upward path
-from a file to its root directory.
-
- [% USE file('bar.html') %]
- [% file.home %] # nothing
-
- [% USE file('foo/bar.html') %]
- [% file.home %] # ..
-
- [% USE file('foo/bar/baz.html') %]
- [% file.home %] # ../..
-
-=item root
-
-The 'root' item can be specified as a constructor argument, indicating
-a root directory in which the named file resides. This is otherwise
-set empty.
-
- [% USE file('foo/bar.html', root='/tmp') %]
- [% file.root %] # /tmp
-
-=item abs
-
-This returns the absolute file path by constructing a path from the
-'root' and 'path' options.
-
- [% USE file('foo/bar.html', root='/tmp') %]
- [% file.path %] # foo/bar.html
- [% file.root %] # /tmp
- [% file.abs %] # /tmp/foo/bar.html
-
-=back
-
-In addition, the following method is provided:
-
-=over 4
-
-=item rel(path)
-
-This returns a relative path from the current file to another path specified
-as an argument. It is constructed by appending the path to the 'home'
-item.
-
- [% USE file('foo/bar/baz.html') %]
- [% file.rel('wiz/waz.html') %] # ../../wiz/waz.html
-
-=back
-
-=head1 EXAMPLES
-
- [% USE file('/foo/bar/baz.html') %]
-
- [% file.path %] # /foo/bar/baz.html
- [% file.dir %] # /foo/bar
- [% file.name %] # baz.html
- [% file.home %] # ../..
- [% file.root %] # ''
- [% file.abspath %] # /foo/bar/baz.html
- [% file.ext %] # html
- [% file.mtime %] # 987654321
- [% file.atime %] # 987654321
- [% file.uid %] # 500
- [% file.user %] # abw
-
- [% USE file('foo.html') %]
-
- [% file.path %] # foo.html
- [% file.dir %] # ''
- [% file.name %] # foo.html
- [% file.root %] # ''
- [% file.home %] # ''
- [% file.abspath %] # foo.html
-
- [% USE file('foo/bar/baz.html') %]
-
- [% file.path %] # foo/bar/baz.html
- [% file.dir %] # foo/bar
- [% file.name %] # baz.html
- [% file.root %] # ''
- [% file.home %] # ../..
- [% file.abspath %] # foo/bar/baz.html
-
- [% USE file('foo/bar/baz.html', root='/tmp') %]
-
- [% file.path %] # foo/bar/baz.html
- [% file.dir %] # foo/bar
- [% file.name %] # baz.html
- [% file.root %] # /tmp
- [% file.home %] # ../..
- [% file.abspath %] # /tmp/foo/bar/baz.html
-
- # calculate other file paths relative to this file and its root
- [% USE file('foo/bar/baz.html', root => '/tmp/tt2') %]
- [% file.path('baz/qux.html') %] # ../../baz/qux.html
- [% file.dir('wiz/woz.html') %] # ../../wiz/woz.html
-
-
-=head1 AUTHORS
-
-Michael Stevens E<lt>michael@etla.orgE<gt> wrote the original Directory plugin
-on which this is based. Andy Wardley E<lt>abw@wardley.orgE<gt> split it into
-separate File and Directory plugins, added some extra code and documentation
-for VIEW support, and made a few other minor tweaks.
-
-=head1 VERSION
-
-2.64, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-
-
-=head1 COPYRIGHT
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Plugin::Directory|Template::Plugin::Directory>, L<Template::View|Template::View>
-
diff --git a/lib/Template/Plugin/Filter.pm b/lib/Template/Plugin/Filter.pm
deleted file mode 100644
index 38da7ba..0000000
--- a/lib/Template/Plugin/Filter.pm
+++ /dev/null
@@ -1,436 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::Filter
-#
-# DESCRIPTION
-# Template Toolkit module implementing a base class plugin
-# object which acts like a filter and can be used with the
-# FILTER directive.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Andy Wardley. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-# REVISION
-# $Id: Filter.pm,v 1.30 2004/01/13 16:20:38 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::Filter;
-
-require 5.004;
-
-use strict;
-use Template::Plugin;
-
-use base qw( Template::Plugin );
-use vars qw( $VERSION $DYNAMIC );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.30 $ =~ /(\d+)\.(\d+)/);
-$DYNAMIC = 0 unless defined $DYNAMIC;
-
-
-sub new {
- my ($class, $context, @args) = @_;
- my $config = @args && ref $args[-1] eq 'HASH' ? pop(@args) : { };
-
- # look for $DYNAMIC
- my $dynamic;
- {
- no strict 'refs';
- $dynamic = ${"$class\::DYNAMIC"};
- }
- $dynamic = $DYNAMIC unless defined $dynamic;
-
- my $self = bless {
- _CONTEXT => $context,
- _DYNAMIC => $dynamic,
- _ARGS => \@args,
- _CONFIG => $config,
- }, $class;
-
- return $self->init($config)
- || $class->error($self->error());
-}
-
-
-sub init {
- my ($self, $config) = @_;
- return $self;
-}
-
-
-sub factory {
- my $self = shift;
-
- if ($self->{ _DYNAMIC }) {
- return $self->{ _DYNAMIC_FILTER } ||= [ sub {
- my ($context, @args) = @_;
- my $config = ref $args[-1] eq 'HASH' ? pop(@args) : { };
-
- return sub {
- $self->filter(shift, \@args, $config);
- };
- }, 1 ];
- }
- else {
- return $self->{ _STATIC_FILTER } ||= sub {
- $self->filter(shift);
- };
- }
-}
-
-
-sub filter {
- my ($self, $text, $args, $config) = @_;
- return $text;
-}
-
-
-sub merge_config {
- my ($self, $newcfg) = @_;
- my $owncfg = $self->{ _CONFIG };
- return $owncfg unless $newcfg;
- return { %$owncfg, %$newcfg };
-}
-
-
-sub merge_args {
- my ($self, $newargs) = @_;
- my $ownargs = $self->{ _ARGS };
- return $ownargs unless $newargs;
- return [ @$ownargs, @$newargs ];
-}
-
-
-sub install_filter {
- my ($self, $name) = @_;
- $self->{ _CONTEXT }->define_filter( $name => $self->factory() );
- return $self;
-}
-
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::Filter - Base class for plugin filters
-
-=head1 SYNOPSIS
-
- package MyOrg::Template::Plugin::MyFilter;
-
- use Template::Plugin::Filter;
- use base qw( Template::Plugin::Filter );
-
- sub filter {
- my ($self, $text) = @_;
-
- # ...mungify $text...
-
- return $text;
- }
-
- # now load it...
- [% USE MyFilter %]
-
- # ...and use the returned object as a filter
- [% FILTER $MyFilter %]
- ...
- [% END %]
-
-=head1 DESCRIPTION
-
-This module implements a base class for plugin filters. It hides
-the underlying complexity involved in creating and using filters
-that get defined and made available by loading a plugin.
-
-To use the module, simply create your own plugin module that is
-inherited from the Template::Plugin::Filter class.
-
- package MyOrg::Template::Plugin::MyFilter;
-
- use Template::Plugin::Filter;
- use base qw( Template::Plugin::Filter );
-
-Then simply define your filter() method. When called, you get
-passed a reference to your plugin object ($self) and the text
-to be filtered.
-
- sub filter {
- my ($self, $text) = @_;
-
- # ...mungify $text...
-
- return $text;
- }
-
-To use your custom plugin, you have to make sure that the Template
-Toolkit knows about your plugin namespace.
-
- my $tt2 = Template->new({
- PLUGIN_BASE => 'MyOrg::Template::Plugin',
- });
-
-Or for individual plugins you can do it like this:
-
- my $tt2 = Template->new({
- PLUGINS => {
- MyFilter => 'MyOrg::Template::Plugin::MyFilter',
- },
- });
-
-Then you USE your plugin in the normal way.
-
- [% USE MyFilter %]
-
-The object returned is stored in the variable of the same name,
-'MyFilter'. When you come to use it as a FILTER, you should add
-a dollar prefix. This indicates that you want to use the filter
-stored in the variable 'MyFilter' rather than the filter named
-'MyFilter', which is an entirely different thing (see later for
-information on defining filters by name).
-
- [% FILTER $MyFilter %]
- ...text to be filtered...
- [% END %]
-
-You can, of course, assign it to a different variable.
-
- [% USE blat = MyFilter %]
-
- [% FILTER $blat %]
- ...text to be filtered...
- [% END %]
-
-Any configuration parameters passed to the plugin constructor from the
-USE directive are stored internally in the object for inspection by
-the filter() method (or indeed any other method). Positional
-arguments are stored as a reference to a list in the _ARGS item while
-named configuration parameters are stored as a reference to a hash
-array in the _CONFIG item.
-
-For example, loading a plugin as shown here:
-
- [% USE blat = MyFilter 'foo' 'bar' baz = 'blam' %]
-
-would allow the filter() method to do something like this:
-
- sub filter {
- my ($self, $text) = @_;
-
- my $args = $self->{ _ARGS }; # [ 'foo', 'bar' ]
- my $conf = $self->{ _CONFIG }; # { baz => 'blam' }
-
- # ...munge $text...
-
- return $text;
- }
-
-By default, plugins derived from this module will create static
-filters. A static filter is created once when the plugin gets
-loaded via the USE directive and re-used for all subsequent
-FILTER operations. That means that any argument specified with
-the FILTER directive are ignored.
-
-Dynamic filters, on the other hand, are re-created each time
-they are used by a FILTER directive. This allows them to act
-on any parameters passed from the FILTER directive and modify
-their behaviour accordingly.
-
-There are two ways to create a dynamic filter. The first is to
-define a $DYNAMIC class variable set to a true value.
-
- package MyOrg::Template::Plugin::MyFilter;
-
- use Template::Plugin::Filter;
- use base qw( Template::Plugin::Filter );
- use vars qw( $DYNAMIC );
-
- $DYNAMIC = 1;
-
-The other way is to set the internal _DYNAMIC value within the init()
-method which gets called by the new() constructor.
-
- sub init {
- my $self = shift;
- $self->{ _DYNAMIC } = 1;
- return $self;
- }
-
-When this is set to a true value, the plugin will automatically
-create a dynamic filter. The outcome is that the filter() method
-will now also get passed a reference to an array of postional
-arguments and a reference to a hash array of named parameters.
-
-So, using a plugin filter like this:
-
- [% FILTER $blat 'foo' 'bar' baz = 'blam' %]
-
-would allow the filter() method to work like this:
-
- sub filter {
- my ($self, $text, $args, $conf) = @_;
-
- # $args = [ 'foo', 'bar' ]
- # $conf = { baz => 'blam' }
-
- }
-
-In this case can pass parameters to both the USE and FILTER directives,
-so your filter() method should probably take that into account.
-
- [% USE MyFilter 'foo' wiz => 'waz' %]
-
- [% FILTER $MyFilter 'bar' biz => 'baz' %]
- ...
- [% END %]
-
-You can use the merge_args() and merge_config() methods to do a quick
-and easy job of merging the local (e.g. FILTER) parameters with the
-internal (e.g. USE) values and returning new sets of conglomerated
-data.
-
- sub filter {
- my ($self, $text, $args, $conf) = @_;
-
- $args = $self->merge_args($args);
- $conf = $self->merge_config($conf);
-
- # $args = [ 'foo', 'bar' ]
- # $conf = { wiz => 'waz', biz => 'baz' }
- ...
- }
-
-You can also have your plugin install itself as a named filter by
-calling the install_filter() method from the init() method. You
-should provide a name for the filter, something that you might
-like to make a configuration option.
-
- sub init {
- my $self = shift;
- my $name = $self->{ _CONFIG }->{ name } || 'myfilter';
- $self->install_filter($name);
- return $self;
- }
-
-This allows the plugin filter to be used as follows:
-
- [% USE MyFilter %]
-
- [% FILTER myfilter %]
- ...
- [% END %]
-
-or
-
- [% USE MyFilter name = 'swipe' %]
-
- [% FILTER swipe %]
- ...
- [% END %]
-
-Alternately, you can allow a filter name to be specified as the
-first positional argument.
-
- sub init {
- my $self = shift;
- my $name = $self->{ _ARGS }->[0] || 'myfilter';
- $self->install_filter($name);
- return $self;
- }
-
- [% USE MyFilter 'swipe' %]
-
- [% FILTER swipe %]
- ...
- [% END %]
-
-=head1 EXAMPLE
-
-Here's a complete example of a plugin filter module.
-
- package My::Template::Plugin::Change;
- use Template::Plugin::Filter;
- use base qw( Template::Plugin::Filter );
-
- sub init {
- my $self = shift;
-
- $self->{ _DYNAMIC } = 1;
-
- # first arg can specify filter name
- $self->install_filter($self->{ _ARGS }->[0] || 'change');
-
- return $self;
- }
-
-
- sub filter {
- my ($self, $text, $args, $config) = @_;
-
- $config = $self->merge_config($config);
- my $regex = join('|', keys %$config);
-
- $text =~ s/($regex)/$config->{ $1 }/ge;
-
- return $text;
- }
-
- 1;
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-1.30, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Filters|Template::Filters>, L<Template::Manual::Filters|Template::Manual::Filters>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/Format.pm b/lib/Template/Plugin/Format.pm
deleted file mode 100644
index bba55d2..0000000
--- a/lib/Template/Plugin/Format.pm
+++ /dev/null
@@ -1,124 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::Format
-#
-# DESCRIPTION
-#
-# Simple Template Toolkit Plugin which creates formatting functions.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Format.pm,v 2.64 2004/01/13 16:20:38 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::Format;
-
-require 5.004;
-
-use strict;
-use vars qw( @ISA $VERSION );
-use base qw( Template::Plugin );
-use Template::Plugin;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.64 $ =~ /(\d+)\.(\d+)/);
-
-
-sub new {
- my ($class, $context, $format) = @_;;
- return defined $format
- ? make_formatter($format)
- : \&make_formatter;
-}
-
-
-sub make_formatter {
- my $format = shift;
- $format = '%s' unless defined $format;
- return sub {
- my @args = @_;
- push(@args, '') unless @args;
- return sprintf($format, @args);
- }
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::Format - Plugin to create formatting functions
-
-=head1 SYNOPSIS
-
- [% USE format %]
- [% commented = format('# %s') %]
- [% commented('The cat sat on the mat') %]
-
- [% USE bold = format('<b>%s</b>') %]
- [% bold('Hello') %]
-
-=head1 DESCRIPTION
-
-The format plugin constructs sub-routines which format text according to
-a printf()-like format string.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.64, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/GD/Constants.pm b/lib/Template/Plugin/GD/Constants.pm
deleted file mode 100644
index 6fc8e7c..0000000
--- a/lib/Template/Plugin/GD/Constants.pm
+++ /dev/null
@@ -1,138 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::GD::Constants
-#
-# DESCRIPTION
-#
-# Simple Template Toolkit plugin interfacing to the GD constants
-# in the GD.pm module.
-#
-# AUTHOR
-# Craig Barratt <craig@arraycomm.com>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Craig Barratt. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Constants.pm,v 1.55 2004/01/13 16:20:46 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::GD::Constants;
-
-require 5.004;
-
-use strict;
-use GD qw(/^gd/ /^GD/);
-use Template::Plugin;
-use base qw( Template::Plugin );
-use vars qw( @ISA $VERSION );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.55 $ =~ /(\d+)\.(\d+)/);
-
-sub new
-{
- my $class = shift;
- my $context = shift;
- my $self = { };
- bless $self, $class;
-
- #
- # GD has exported various gd* and GD_* contstants. Find them.
- #
- foreach my $v ( keys(%Template::Plugin::GD::Constants::) ) {
- $self->{$v} = eval($v) if ( $v =~ /^gd/ || $v =~ /^GD_/ );
- }
- return $self;
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::GD::Constants - Interface to GD module constants
-
-=head1 SYNOPSIS
-
- [% USE gdc = GD.Constants %]
-
- # --> the constants gdc.gdBrushed, gdc.gdSmallFont, gdc.GD_CMP_IMAGE
- # are now available
-
-=head1 EXAMPLES
-
- [% FILTER null;
- USE gdc = GD.Constants;
- USE im = GD.Image(200,100);
- black = im.colorAllocate(0 ,0, 0);
- red = im.colorAllocate(255,0, 0);
- r = im.string(gdc.gdLargeFont, 10, 10, "Large Red Text", red);
- im.png | stdout(1);
- END;
- -%]
-
-=head1 DESCRIPTION
-
-The GD.Constants plugin provides access to the various GD module's
-constants (such as gdBrushed, gdSmallFont, gdTransparent, GD_CMP_IMAGE
-etc). When GD.pm is used in perl it exports various contstants
-into the caller's namespace. This plugin makes those exported
-constants available as template variables.
-
-See L<Template::Plugin::GD::Image> and L<GD> for further examples and
-details.
-
-=head1 AUTHOR
-
-Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-
-Lincoln D. Stein wrote the GD.pm interface to the GD library.
-
-
-=head1 VERSION
-
-1.55, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
-
-Copyright (C) 2001 Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-The GD.pm interface is copyright 1995-2000, Lincoln D. Stein.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Plugin::GD|Template::Plugin::GD>, L<Template::Plugin::GD::Image|Template::Plugin::GD::Image>, L<Template::Plugin::GD::Polygon|Template::Plugin::GD::Polygon>, L<GD|GD>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/GD/Graph/area.pm b/lib/Template/Plugin/GD/Graph/area.pm
deleted file mode 100644
index d09d024..0000000
--- a/lib/Template/Plugin/GD/Graph/area.pm
+++ /dev/null
@@ -1,148 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::GD::Graph::area
-#
-# DESCRIPTION
-#
-# Simple Template Toolkit plugin interfacing to the GD::Graph::area
-# package in the GD::Graph.pm module.
-#
-# AUTHOR
-# Craig Barratt <craig@arraycomm.com>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Craig Barratt. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: area.pm,v 1.57 2004/01/13 16:20:51 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::GD::Graph::area;
-
-require 5.004;
-
-use strict;
-use GD::Graph::area;
-use Template::Plugin;
-use base qw( GD::Graph::area Template::Plugin );
-use vars qw( $VERSION );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.57 $ =~ /(\d+)\.(\d+)/);
-
-sub new
-{
- my $class = shift;
- my $context = shift;
- return $class->SUPER::new(@_);
-}
-
-sub set
-{
- my $self = shift;
-
- push(@_, %{pop(@_)}) if ( @_ & 1 && ref($_[@_-1]) eq "HASH" );
- $self->SUPER::set(@_);
-}
-
-
-sub set_legend
-{
- my $self = shift;
-
- $self->SUPER::set_legend(ref $_[0] ? @{$_[0]} : @_);
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::GD::Graph::area - Create area graphs with axes and legends
-
-=head1 SYNOPSIS
-
- [% USE g = GD.Graph.area(x_size, y_size); %]
-
-=head1 EXAMPLES
-
- [% FILTER null;
- data = [
- ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"],
- [ 5, 12, 24, 33, 19, 8, 6, 15, 21],
- [ -1, -2, -5, -6, -3, 1.5, 1, 1.3, 2]
- ];
-
- USE my_graph = GD.Graph.area();
- my_graph.set(
- two_axes => 1,
- zero_axis => 1,
- transparent => 0,
- );
- my_graph.set_legend('left axis', 'right axis' );
- my_graph.plot(data).png | stdout(1);
- END;
- -%]
-
-=head1 DESCRIPTION
-
-The GD.Graph.area plugin provides an interface to the GD::Graph::area
-class defined by the GD::Graph module. It allows one or more (x,y) data
-sets to be plotted as lines with the area between the line and x-axis
-shaded, in addition to axes and legends.
-
-See L<GD::Graph> for more details.
-
-=head1 AUTHOR
-
-Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-
-The GD::Graph module was written by Martien Verbruggen.
-
-
-=head1 VERSION
-
-1.57, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
-
-Copyright (C) 2001 Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-GD::Graph is copyright 1999 Martien Verbruggen.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Plugin::GD|Template::Plugin::GD>, L<Template::Plugin::GD::Graph::lines|Template::Plugin::GD::Graph::lines>, L<Template::Plugin::GD::Graph::lines3d|Template::Plugin::GD::Graph::lines3d>, L<Template::Plugin::GD::Graph::bars|Template::Plugin::GD::Graph::bars>, L<Template::Plugin::GD::Graph::bars3d|Template::Plugin::GD::Graph::bars3d>, L<Template::Plugin::GD::Graph::points|Template::Plugin::GD::Graph::points>, L<Template::Plugin::GD::Graph::linespoints|Template::Plugin::GD::Graph::linespoints>, L<Template::Plugin::GD::Graph::mixed|Template::Plugin::GD::Graph::mixed>, L<Template::Plugin::GD::Graph::pie|Template::Plugin::GD::Graph::pie>, L<Template::Plugin::GD::Graph::pie3d|Template::Plugin::GD::Graph::pie3d>, L<GD::Graph|GD::Graph>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/GD/Graph/bars.pm b/lib/Template/Plugin/GD/Graph/bars.pm
deleted file mode 100644
index 9bc08c5..0000000
--- a/lib/Template/Plugin/GD/Graph/bars.pm
+++ /dev/null
@@ -1,191 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::GD::Graph::bars
-#
-# DESCRIPTION
-#
-# Simple Template Toolkit plugin interfacing to the GD::Graph::bars
-# package in the GD::Graph.pm module.
-#
-# AUTHOR
-# Craig Barratt <craig@arraycomm.com>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Craig Barratt. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: bars.pm,v 1.57 2004/01/13 16:20:56 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::GD::Graph::bars;
-
-require 5.004;
-
-use strict;
-use GD::Graph::bars;
-use Template::Plugin;
-use base qw( GD::Graph::bars Template::Plugin );
-use vars qw( $VERSION );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.57 $ =~ /(\d+)\.(\d+)/);
-
-sub new
-{
- my $class = shift;
- my $context = shift;
- return $class->SUPER::new(@_);
-}
-
-sub set
-{
- my $self = shift;
-
- push(@_, %{pop(@_)}) if ( @_ & 1 && ref($_[@_-1]) eq "HASH" );
- $self->SUPER::set(@_);
-}
-
-
-sub set_legend
-{
- my $self = shift;
-
- $self->SUPER::set_legend(ref $_[0] ? @{$_[0]} : @_);
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::GD::Graph::bars - Create bar graphs with axes and legends
-
-=head1 SYNOPSIS
-
- [% USE g = GD.Graph.bars(x_size, y_size); %]
-
-=head1 EXAMPLES
-
- [% FILTER null;
- data = [
- ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"],
- [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4],
- ];
-
- USE my_graph = GD.Graph.bars();
-
- my_graph.set(
- x_label => 'X Label',
- y_label => 'Y label',
- title => 'A Simple Bar Chart',
- y_max_value => 8,
- y_tick_number => 8,
- y_label_skip => 2,
-
- # shadows
- bar_spacing => 8,
- shadow_depth => 4,
- shadowclr => 'dred',
-
- transparent => 0,
- );
- my_graph.plot(data).png | stdout(1);
- END;
- -%]
-
- [% FILTER null;
- data = [
- ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"],
- [ 5, 12, 24, 33, 19, 8, 6, 15, 21],
- [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4],
- ];
-
- USE my_graph = GD.Graph.bars();
-
- my_graph.set(
- x_label => 'X Label',
- y_label => 'Y label',
- title => 'Two data sets',
-
- # shadows
- bar_spacing => 8,
- shadow_depth => 4,
- shadowclr => 'dred',
-
- long_ticks => 1,
- y_max_value => 40,
- y_tick_number => 8,
- y_label_skip => 2,
- bar_spacing => 3,
-
- accent_treshold => 200,
-
- transparent => 0,
- );
- my_graph.set_legend( 'Data set 1', 'Data set 2' );
- my_graph.plot(data).png | stdout(1);
- END;
- -%]
-
-=head1 DESCRIPTION
-
-The GD.Graph.bars plugin provides an interface to the GD::Graph::bars
-class defined by the GD::Graph module. It allows one or more (x,y) data
-sets to be plotted with each point represented by a bar, in addition
-to axes and legends.
-
-See L<GD::Graph> for more details.
-
-=head1 AUTHOR
-
-Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-
-The GD::Graph module was written by Martien Verbruggen.
-
-
-=head1 VERSION
-
-1.57, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
-
-Copyright (C) 2001 Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-GD::Graph is copyright 1999 Martien Verbruggen.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Plugin::GD|Template::Plugin::GD>, L<Template::Plugin::GD::Graph::lines|Template::Plugin::GD::Graph::lines>, L<Template::Plugin::GD::Graph::lines3d|Template::Plugin::GD::Graph::lines3d>, L<Template::Plugin::GD::Graph::bars3d|Template::Plugin::GD::Graph::bars3d>, L<Template::Plugin::GD::Graph::points|Template::Plugin::GD::Graph::points>, L<Template::Plugin::GD::Graph::linespoints|Template::Plugin::GD::Graph::linespoints>, L<Template::Plugin::GD::Graph::area|Template::Plugin::GD::Graph::area>, L<Template::Plugin::GD::Graph::mixed|Template::Plugin::GD::Graph::mixed>, L<Template::Plugin::GD::Graph::pie|Template::Plugin::GD::Graph::pie>, L<Template::Plugin::GD::Graph::pie3d|Template::Plugin::GD::Graph::pie3d>, L<GD::Graph|GD::Graph>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/GD/Graph/bars3d.pm b/lib/Template/Plugin/GD/Graph/bars3d.pm
deleted file mode 100644
index 79a930b..0000000
--- a/lib/Template/Plugin/GD/Graph/bars3d.pm
+++ /dev/null
@@ -1,166 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::GD::Graph::bars3d
-#
-# DESCRIPTION
-#
-# Simple Template Toolkit plugin interfacing to the GD::Graph::bars3d
-# package in the GD::Graph3D.pm module.
-#
-# AUTHOR
-# Craig Barratt <craig@arraycomm.com>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Craig Barratt. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: bars3d.pm,v 1.57 2004/01/13 16:20:56 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::GD::Graph::bars3d;
-
-require 5.004;
-
-use strict;
-use GD::Graph::bars3d;
-use Template::Plugin;
-use base qw( GD::Graph::bars3d Template::Plugin );
-use vars qw( $VERSION );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.57 $ =~ /(\d+)\.(\d+)/);
-
-sub new
-{
- my $class = shift;
- my $context = shift;
- return $class->SUPER::new(@_);
-}
-
-sub set
-{
- my $self = shift;
-
- push(@_, %{pop(@_)}) if ( @_ & 1 && ref($_[@_-1]) eq "HASH" );
- $self->SUPER::set(@_);
-}
-
-
-sub set_legend
-{
- my $self = shift;
-
- $self->SUPER::set_legend(ref $_[0] ? @{$_[0]} : @_);
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::GD::Graph::bars3d - Create 3D bar graphs with axes and legends
-
-=head1 SYNOPSIS
-
- [% USE g = GD.Graph.bars3d(x_size, y_size); %]
-
-=head1 EXAMPLES
-
- [% FILTER null;
- data = [
- ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
- "Sep", "Oct", "Nov", "Dec", ],
- [-5, -4, -3, -3, -1, 0, 2, 1, 3, 4, 6, 7],
- [4, 3, 5, 6, 3,1.5, -1, -3, -4, -6, -7, -8],
- [1, 2, 2, 3, 4, 3, 1, -1, 0, 2, 3, 2],
- ];
-
- USE my_graph = GD.Graph.bars3d();
-
- my_graph.set(
- x_label => 'Month',
- y_label => 'Measure of success',
- title => 'A 3d Bar Chart',
-
- y_max_value => 8,
- y_min_value => -8,
- y_tick_number => 16,
- y_label_skip => 2,
- box_axis => 0,
- line_width => 3,
- zero_axis_only => 1,
- x_label_position => 1,
- y_label_position => 1,
-
- x_label_skip => 3,
- x_tick_offset => 2,
-
- transparent => 0,
- );
- my_graph.set_legend("Us", "Them", "Others");
- my_graph.plot(data).png | stdout(1);
- END;
- -%]
-
-=head1 DESCRIPTION
-
-The GD.Graph.bars3d plugin provides an interface to the GD::Graph::bars3d
-class defined by the GD::Graph3d module. It allows one or more (x,y) data
-sets to be plotted as y versus x bars with a 3-dimensional appearance,
-together with axes and legends.
-
-See L<GD::Graph3d> for more details.
-
-=head1 AUTHOR
-
-Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-
-The GD::Graph3d module was written by Jeremy Wadsack.
-
-
-=head1 VERSION
-
-1.57, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
-
-Copyright (C) 2001 Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-GD::Graph3d is copyright (C) 1999,2000 Wadsack-Allen. All Rights Reserved.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Plugin::GD|Template::Plugin::GD>, L<Template::Plugin::GD::Graph::lines|Template::Plugin::GD::Graph::lines>, L<Template::Plugin::GD::Graph::lines3d|Template::Plugin::GD::Graph::lines3d>, L<Template::Plugin::GD::Graph::bars|Template::Plugin::GD::Graph::bars>, L<Template::Plugin::GD::Graph::points|Template::Plugin::GD::Graph::points>, L<Template::Plugin::GD::Graph::linespoints|Template::Plugin::GD::Graph::linespoints>, L<Template::Plugin::GD::Graph::area|Template::Plugin::GD::Graph::area>, L<Template::Plugin::GD::Graph::mixed|Template::Plugin::GD::Graph::mixed>, L<Template::Plugin::GD::Graph::pie|Template::Plugin::GD::Graph::pie>, L<Template::Plugin::GD::Graph::pie3d|Template::Plugin::GD::Graph::pie3d>, L<GD::Graph|GD::Graph>, L<GD::Graph3d|GD::Graph3d>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/GD/Graph/lines.pm b/lib/Template/Plugin/GD/Graph/lines.pm
deleted file mode 100644
index 678cc64..0000000
--- a/lib/Template/Plugin/GD/Graph/lines.pm
+++ /dev/null
@@ -1,178 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::GD::Graph::lines
-#
-# DESCRIPTION
-#
-# Simple Template Toolkit plugin interfacing to the GD::Graph::lines
-# package in the GD::Graph.pm module.
-#
-# AUTHOR
-# Craig Barratt <craig@arraycomm.com>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Craig Barratt. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: lines.pm,v 1.57 2004/01/13 16:20:56 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::GD::Graph::lines;
-
-require 5.004;
-
-use strict;
-use GD::Graph::lines;
-use Template::Plugin;
-use base qw( GD::Graph::lines Template::Plugin );
-use vars qw( $VERSION );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.57 $ =~ /(\d+)\.(\d+)/);
-
-sub new
-{
- my $class = shift;
- my $context = shift;
- return $class->SUPER::new(@_);
-}
-
-sub set
-{
- my $self = shift;
-
- push(@_, %{pop(@_)}) if ( @_ & 1 && ref($_[@_-1]) eq "HASH" );
- $self->SUPER::set(@_);
-}
-
-
-sub set_legend
-{
- my $self = shift;
-
- $self->SUPER::set_legend(ref $_[0] ? @{$_[0]} : @_);
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::GD::Graph::lines - Create line graphs with axes and legends
-
-=head1 SYNOPSIS
-
- [% USE g = GD.Graph.lines(x_size, y_size); %]
-
-=head1 EXAMPLES
-
- [% FILTER null;
- USE g = GD.Graph.lines(300,200);
- x = [1, 2, 3, 4];
- y = [5, 4, 2, 3];
- g.set(
- x_label => 'X Label',
- y_label => 'Y label',
- title => 'Title'
- );
- g.plot([x, y]).png | stdout(1);
- END;
- -%]
-
- [% FILTER null;
- data = [
- ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
- "Sep", "Oct", "Nov", "Dec", ],
- [-5, -4, -3, -3, -1, 0, 2, 1, 3, 4, 6, 7],
- [4, 3, 5, 6, 3,1.5, -1, -3, -4, -6, -7, -8],
- [1, 2, 2, 3, 4, 3, 1, -1, 0, 2, 3, 2],
- ];
-
- USE my_graph = GD.Graph.lines();
-
- my_graph.set(
- x_label => 'Month',
- y_label => 'Measure of success',
- title => 'A Simple Line Graph',
-
- y_max_value => 8,
- y_min_value => -8,
- y_tick_number => 16,
- y_label_skip => 2,
- box_axis => 0,
- line_width => 3,
- zero_axis_only => 1,
- x_label_position => 1,
- y_label_position => 1,
-
- x_label_skip => 3,
- x_tick_offset => 2,
-
- transparent => 0,
- );
- my_graph.set_legend("Us", "Them", "Others");
- my_graph.plot(data).png | stdout(1);
- END;
- -%]
-
-=head1 DESCRIPTION
-
-The GD.Graph.lines plugin provides an interface to the GD::Graph::lines
-class defined by the GD::Graph module. It allows one or more (x,y) data
-sets to be plotted as y versus x lines with axes and legends.
-
-See L<GD::Graph> for more details.
-
-=head1 AUTHOR
-
-Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-
-The GD::Graph module was written by Martien Verbruggen.
-
-
-=head1 VERSION
-
-1.57, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
-
-Copyright (C) 2001 Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-GD::Graph is copyright 1999 Martien Verbruggen.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Plugin::GD|Template::Plugin::GD>, L<Template::Plugin::GD::Graph::lines3d|Template::Plugin::GD::Graph::lines3d>, L<Template::Plugin::GD::Graph::bars|Template::Plugin::GD::Graph::bars>, L<Template::Plugin::GD::Graph::bars3d|Template::Plugin::GD::Graph::bars3d>, L<Template::Plugin::GD::Graph::points|Template::Plugin::GD::Graph::points>, L<Template::Plugin::GD::Graph::linespoints|Template::Plugin::GD::Graph::linespoints>, L<Template::Plugin::GD::Graph::area|Template::Plugin::GD::Graph::area>, L<Template::Plugin::GD::Graph::mixed|Template::Plugin::GD::Graph::mixed>, L<Template::Plugin::GD::Graph::pie|Template::Plugin::GD::Graph::pie>, L<Template::Plugin::GD::Graph::pie3d|Template::Plugin::GD::Graph::pie3d>, L<GD::Graph|GD::Graph>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/GD/Graph/lines3d.pm b/lib/Template/Plugin/GD/Graph/lines3d.pm
deleted file mode 100644
index 1f12715..0000000
--- a/lib/Template/Plugin/GD/Graph/lines3d.pm
+++ /dev/null
@@ -1,166 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::GD::Graph::lines3d
-#
-# DESCRIPTION
-#
-# Simple Template Toolkit plugin interfacing to the GD::Graph::lines3d
-# package in the GD::Graph3D.pm module.
-#
-# AUTHOR
-# Craig Barratt <craig@arraycomm.com>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Craig Barratt. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: lines3d.pm,v 1.57 2004/01/13 16:20:56 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::GD::Graph::lines3d;
-
-require 5.004;
-
-use strict;
-use GD::Graph::lines3d;
-use Template::Plugin;
-use base qw( GD::Graph::lines3d Template::Plugin );
-use vars qw( $VERSION );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.57 $ =~ /(\d+)\.(\d+)/);
-
-sub new
-{
- my $class = shift;
- my $context = shift;
- return $class->SUPER::new(@_);
-}
-
-sub set
-{
- my $self = shift;
-
- push(@_, %{pop(@_)}) if ( @_ & 1 && ref($_[@_-1]) eq "HASH" );
- $self->SUPER::set(@_);
-}
-
-
-sub set_legend
-{
- my $self = shift;
-
- $self->SUPER::set_legend(ref $_[0] ? @{$_[0]} : @_);
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::GD::Graph::lines3d - Create 3D line graphs with axes and legends
-
-=head1 SYNOPSIS
-
- [% USE g = GD.Graph.lines3d(x_size, y_size); %]
-
-=head1 EXAMPLES
-
- [% FILTER null;
- data = [
- ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
- "Sep", "Oct", "Nov", "Dec", ],
- [-5, -4, -3, -3, -1, 0, 2, 1, 3, 4, 6, 7],
- [4, 3, 5, 6, 3,1.5, -1, -3, -4, -6, -7, -8],
- [1, 2, 2, 3, 4, 3, 1, -1, 0, 2, 3, 2],
- ];
-
- USE my_graph = GD.Graph.lines3d();
-
- my_graph.set(
- x_label => 'Month',
- y_label => 'Measure of success',
- title => 'A 3d Line Graph',
-
- y_max_value => 8,
- y_min_value => -8,
- y_tick_number => 16,
- y_label_skip => 2,
- box_axis => 0,
- line_width => 3,
- zero_axis_only => 1,
- x_label_position => 1,
- y_label_position => 1,
-
- x_label_skip => 3,
- x_tick_offset => 2,
-
- transparent => 0,
- );
- my_graph.set_legend("Us", "Them", "Others");
- my_graph.plot(data).png | stdout(1);
- END;
- -%]
-
-=head1 DESCRIPTION
-
-The GD.Graph.lines3d plugin provides an interface to the GD::Graph::lines3d
-class defined by the GD::Graph3d module. It allows one or more (x,y) data
-sets to be plotted as y versus x lines with a 3-dimensional appearance,
-together with axes and legends.
-
-See L<GD::Graph3d> for more details.
-
-=head1 AUTHOR
-
-Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-
-The GD::Graph3d module was written by Jeremy Wadsack.
-
-
-=head1 VERSION
-
-1.57, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
-
-Copyright (C) 2001 Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-GD::Graph3d is copyright (C) 1999,2000 Wadsack-Allen. All Rights Reserved.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Plugin::GD|Template::Plugin::GD>, L<Template::Plugin::GD::Graph::lines|Template::Plugin::GD::Graph::lines>, L<Template::Plugin::GD::Graph::bars|Template::Plugin::GD::Graph::bars>, L<Template::Plugin::GD::Graph::bars3d|Template::Plugin::GD::Graph::bars3d>, L<Template::Plugin::GD::Graph::points|Template::Plugin::GD::Graph::points>, L<Template::Plugin::GD::Graph::linespoints|Template::Plugin::GD::Graph::linespoints>, L<Template::Plugin::GD::Graph::area|Template::Plugin::GD::Graph::area>, L<Template::Plugin::GD::Graph::mixed|Template::Plugin::GD::Graph::mixed>, L<Template::Plugin::GD::Graph::pie|Template::Plugin::GD::Graph::pie>, L<Template::Plugin::GD::Graph::pie3d|Template::Plugin::GD::Graph::pie3d>, L<GD::Graph|GD::Graph>, L<GD::Graph3d|GD::Graph3d>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/GD/Graph/linespoints.pm b/lib/Template/Plugin/GD/Graph/linespoints.pm
deleted file mode 100644
index 8dc48d9..0000000
--- a/lib/Template/Plugin/GD/Graph/linespoints.pm
+++ /dev/null
@@ -1,158 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::GD::Graph::linespoints
-#
-# DESCRIPTION
-#
-# Simple Template Toolkit plugin interfacing to the GD::Graph::linespoints
-# package in the GD::Graph.pm module.
-#
-# AUTHOR
-# Craig Barratt <craig@arraycomm.com>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Craig Barratt. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: linespoints.pm,v 1.57 2004/01/13 16:20:56 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::GD::Graph::linespoints;
-
-require 5.004;
-
-use strict;
-use GD::Graph::linespoints;
-use Template::Plugin;
-use base qw( GD::Graph::linespoints Template::Plugin );
-use vars qw( $VERSION );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.57 $ =~ /(\d+)\.(\d+)/);
-
-sub new
-{
- my $class = shift;
- my $context = shift;
- return $class->SUPER::new(@_);
-}
-
-sub set
-{
- my $self = shift;
-
- push(@_, %{pop(@_)}) if ( @_ & 1 && ref($_[@_-1]) eq "HASH" );
- $self->SUPER::set(@_);
-}
-
-
-sub set_legend
-{
- my $self = shift;
-
- $self->SUPER::set_legend(ref $_[0] ? @{$_[0]} : @_);
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::GD::Graph::linespoints - Create line/point graphs with axes and legends
-
-=head1 SYNOPSIS
-
- [% USE g = GD.Graph.linespoints(x_size, y_size); %]
-
-=head1 EXAMPLES
-
- [% FILTER null;
- data = [
- ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"],
- [50, 52, 53, 54, 55, 56, 57, 58, 59],
- [60, 61, 61, 63, 68, 66, 65, 61, 58],
- [70, 72, 71, 74, 78, 73, 75, 71, 68],
- ];
-
- USE my_graph = GD.Graph.linespoints;
-
- my_graph.set(
- x_label => 'X Label',
- y_label => 'Y label',
- title => 'A Lines and Points Graph',
- y_max_value => 80,
- y_tick_number => 6,
- y_label_skip => 2,
- y_long_ticks => 1,
- x_tick_length => 2,
- markers => [ 1, 5 ],
- skip_undef => 1,
- transparent => 0,
- );
- my_graph.set_legend('data set 1', 'data set 2', 'data set 3');
- my_graph.plot(data).png | stdout(1);
- END;
- -%]
-
-=head1 DESCRIPTION
-
-The GD.Graph.linespoints plugin provides an interface to the
-GD::Graph::linespoints class defined by the GD::Graph module. It allows
-one or more (x,y) data sets to be plotted as y versus x lines, plus
-symbols placed at each point, in addition to axes and legends.
-
-See L<GD::Graph> for more details.
-
-=head1 AUTHOR
-
-Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-
-The GD::Graph module was written by Martien Verbruggen.
-
-
-=head1 VERSION
-
-1.57, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
-
-Copyright (C) 2001 Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-GD::Graph is copyright 1999 Martien Verbruggen.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Plugin::GD|Template::Plugin::GD>, L<Template::Plugin::GD::Graph::lines|Template::Plugin::GD::Graph::lines>, L<Template::Plugin::GD::Graph::lines3d|Template::Plugin::GD::Graph::lines3d>, L<Template::Plugin::GD::Graph::bars|Template::Plugin::GD::Graph::bars>, L<Template::Plugin::GD::Graph::bars3d|Template::Plugin::GD::Graph::bars3d>, L<Template::Plugin::GD::Graph::points|Template::Plugin::GD::Graph::points>, L<Template::Plugin::GD::Graph::area|Template::Plugin::GD::Graph::area>, L<Template::Plugin::GD::Graph::mixed|Template::Plugin::GD::Graph::mixed>, L<Template::Plugin::GD::Graph::pie|Template::Plugin::GD::Graph::pie>, L<Template::Plugin::GD::Graph::pie3d|Template::Plugin::GD::Graph::pie3d>, L<GD::Graph|GD::Graph>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/GD/Graph/mixed.pm b/lib/Template/Plugin/GD/Graph/mixed.pm
deleted file mode 100644
index 10dd533..0000000
--- a/lib/Template/Plugin/GD/Graph/mixed.pm
+++ /dev/null
@@ -1,176 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::GD::Graph::mixed
-#
-# DESCRIPTION
-#
-# Simple Template Toolkit plugin interfacing to the GD::Graph::mixed
-# package in the GD::Graph.pm module.
-#
-# AUTHOR
-# Craig Barratt <craig@arraycomm.com>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Craig Barratt. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: mixed.pm,v 1.57 2004/01/13 16:20:56 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::GD::Graph::mixed;
-
-require 5.004;
-
-use strict;
-use GD::Graph::mixed;
-use Template::Plugin;
-use base qw( GD::Graph::mixed Template::Plugin );
-use vars qw( $VERSION );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.57 $ =~ /(\d+)\.(\d+)/);
-
-sub new
-{
- my $class = shift;
- my $context = shift;
- return $class->SUPER::new(@_);
-}
-
-sub set
-{
- my $self = shift;
-
- push(@_, %{pop(@_)}) if ( @_ & 1 && ref($_[@_-1]) eq "HASH" );
- $self->SUPER::set(@_);
-}
-
-
-sub set_legend
-{
- my $self = shift;
-
- $self->SUPER::set_legend(ref $_[0] ? @{$_[0]} : @_);
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::GD::Graph::mixed - Create mixed graphs with axes and legends
-
-=head1 SYNOPSIS
-
- [% USE g = GD.Graph.mixed(x_size, y_size); %]
-
-=head1 EXAMPLES
-
- [% FILTER null;
- data = [
- ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"],
- [ 1, 2, 5, 6, 3, 1.5, -1, -3, -4],
- [ -4, -3, 1, 1, -3, -1.5, -2, -1, 0],
- [ 9, 8, 9, 8.4, 7.1, 7.5, 8, 3, -3],
- [ 0.1, 0.2, 0.5, 0.4, 0.3, 0.5, 0.1, 0, 0.4],
- [ -0.1, 2, 5, 4, -3, 2.5, 3.2, 4, -4],
- ];
-
- USE my_graph = GD.Graph.mixed();
-
- my_graph.set(
- types => ['lines', 'lines', 'points', 'area', 'linespoints'],
- default_type => 'points',
- );
-
- my_graph.set(
-
- x_label => 'X Label',
- y_label => 'Y label',
- title => 'A Mixed Type Graph',
-
- y_max_value => 10,
- y_min_value => -5,
- y_tick_number => 3,
- y_label_skip => 0,
- x_plot_values => 0,
- y_plot_values => 0,
-
- long_ticks => 1,
- x_ticks => 0,
-
- legend_marker_width => 24,
- line_width => 3,
- marker_size => 5,
-
- bar_spacing => 8,
-
- transparent => 0,
- );
-
- my_graph.set_legend('one', 'two', 'three', 'four', 'five', 'six');
- my_graph.plot(data).png | stdout(1);
- END;
- -%]
-
-=head1 DESCRIPTION
-
-The GD.Graph.mixed plugin provides an interface to the GD::Graph::mixed
-class defined by the GD::Graph module. It allows one or more (x,y) data
-sets to be plotted with various styles (lines, points, bars, areas etc).
-
-See L<GD::Graph> for more details.
-
-=head1 AUTHOR
-
-Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-
-The GD::Graph module was written by Martien Verbruggen.
-
-
-=head1 VERSION
-
-1.57, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
-
-Copyright (C) 2001 Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-GD::Graph is copyright 1999 Martien Verbruggen.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Plugin::GD|Template::Plugin::GD>, L<Template::Plugin::GD::Graph::lines|Template::Plugin::GD::Graph::lines>, L<Template::Plugin::GD::Graph::lines3d|Template::Plugin::GD::Graph::lines3d>, L<Template::Plugin::GD::Graph::bars|Template::Plugin::GD::Graph::bars>, L<Template::Plugin::GD::Graph::bars3d|Template::Plugin::GD::Graph::bars3d>, L<Template::Plugin::GD::Graph::points|Template::Plugin::GD::Graph::points>, L<Template::Plugin::GD::Graph::linespoints|Template::Plugin::GD::Graph::linespoints>, L<Template::Plugin::GD::Graph::area|Template::Plugin::GD::Graph::area>, L<Template::Plugin::GD::Graph::pie|Template::Plugin::GD::Graph::pie>, L<Template::Plugin::GD::Graph::pie3d|Template::Plugin::GD::Graph::pie3d>, L<GD::Graph|GD::Graph>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/GD/Graph/pie.pm b/lib/Template/Plugin/GD/Graph/pie.pm
deleted file mode 100644
index e72e26c..0000000
--- a/lib/Template/Plugin/GD/Graph/pie.pm
+++ /dev/null
@@ -1,141 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::GD::Graph::pie
-#
-# DESCRIPTION
-#
-# Simple Template Toolkit plugin interfacing to the GD::Graph::pie
-# package in the GD::Graph.pm module.
-#
-# AUTHOR
-# Craig Barratt <craig@arraycomm.com>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Craig Barratt. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: pie.pm,v 1.55 2004/01/13 16:20:56 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::GD::Graph::pie;
-
-require 5.004;
-
-use strict;
-use GD::Graph::pie;
-use Template::Plugin;
-use base qw( GD::Graph::pie Template::Plugin );
-use vars qw( $VERSION );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.55 $ =~ /(\d+)\.(\d+)/);
-
-sub new
-{
- my $class = shift;
- my $context = shift;
- return $class->SUPER::new(@_);
-}
-
-sub set
-{
- my $self = shift;
-
- push(@_, %{pop(@_)}) if ( @_ & 1 && ref($_[@_-1]) eq "HASH" );
- $self->SUPER::set(@_);
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::GD::Graph::pie - Create pie charts with legends
-
-=head1 SYNOPSIS
-
- [% USE g = GD.Graph.pie(x_size, y_size); %]
-
-=head1 EXAMPLES
-
- [% FILTER null;
- data = [
- ["1st","2nd","3rd","4th","5th","6th"],
- [ 4, 2, 3, 4, 3, 3.5]
- ];
-
- USE my_graph = GD.Graph.pie( 250, 200 );
-
- my_graph.set(
- title => 'A Pie Chart',
- label => 'Label',
- axislabelclr => 'black',
- pie_height => 36,
-
- transparent => 0,
- );
- my_graph.plot(data).png | stdout(1);
- END;
- -%]
-
-=head1 DESCRIPTION
-
-The GD.Graph.pie plugin provides an interface to the GD::Graph::pie
-class defined by the GD::Graph module. It allows an (x,y) data set to
-be plotted as a pie chart. The x values are typically strings.
-
-See L<GD::Graph> for more details.
-
-=head1 AUTHOR
-
-Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-
-The GD::Graph module was written by Martien Verbruggen.
-
-
-=head1 VERSION
-
-1.55, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
-
-Copyright (C) 2001 Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-GD::Graph is copyright 1999 Martien Verbruggen.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Plugin::GD|Template::Plugin::GD>, L<Template::Plugin::GD::Graph::lines|Template::Plugin::GD::Graph::lines>, L<Template::Plugin::GD::Graph::lines3d|Template::Plugin::GD::Graph::lines3d>, L<Template::Plugin::GD::Graph::bars|Template::Plugin::GD::Graph::bars>, L<Template::Plugin::GD::Graph::bars3d|Template::Plugin::GD::Graph::bars3d>, L<Template::Plugin::GD::Graph::points|Template::Plugin::GD::Graph::points>, L<Template::Plugin::GD::Graph::linespoints|Template::Plugin::GD::Graph::linespoints>, L<Template::Plugin::GD::Graph::area|Template::Plugin::GD::Graph::area>, L<Template::Plugin::GD::Graph::mixed|Template::Plugin::GD::Graph::mixed>, L<Template::Plugin::GD::Graph::pie3d|Template::Plugin::GD::Graph::pie3d>, L<GD::Graph|GD::Graph>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/GD/Graph/pie3d.pm b/lib/Template/Plugin/GD/Graph/pie3d.pm
deleted file mode 100644
index 5f677e0..0000000
--- a/lib/Template/Plugin/GD/Graph/pie3d.pm
+++ /dev/null
@@ -1,145 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::GD::Graph::pie3d
-#
-# DESCRIPTION
-#
-# Simple Template Toolkit plugin interfacing to the GD::Graph::pie3d
-# package in the GD::Graph3D.pm module.
-#
-# AUTHOR
-# Craig Barratt <craig@arraycomm.com>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Craig Barratt. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: pie3d.pm,v 1.55 2004/01/13 16:20:56 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::GD::Graph::pie3d;
-
-require 5.004;
-
-use strict;
-use GD::Graph::pie3d;
-use Template::Plugin;
-use base qw( GD::Graph::pie3d Template::Plugin );
-use vars qw( $VERSION );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.55 $ =~ /(\d+)\.(\d+)/);
-
-sub new
-{
- my $class = shift;
- my $context = shift;
- return $class->SUPER::new(@_);
-}
-
-sub set
-{
- my $self = shift;
-
- push(@_, %{pop(@_)}) if ( @_ & 1 && ref($_[@_-1]) eq "HASH" );
- $self->SUPER::set(@_);
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::GD::Graph::pie3d - Create 3D pie charts with legends
-
-=head1 SYNOPSIS
-
- [% USE g = GD.Graph.pie3d(x_size, y_size); %]
-
-=head1 EXAMPLES
-
- [% FILTER null;
- data = [
- ["1st","2nd","3rd","4th","5th","6th"],
- [ 4, 2, 3, 4, 3, 3.5]
- ];
-
- USE my_graph = GD.Graph.pie3d( 250, 200 );
-
- my_graph.set(
- title => 'A Pie Chart',
- label => 'Label',
- axislabelclr => 'black',
- pie_height => 36,
-
- transparent => 0,
- );
- my_graph.plot(data).png | stdout(1);
- END;
- -%]
-
-=head1 DESCRIPTION
-
-The GD.Graph.pie3d plugin provides an interface to the GD::Graph::pie3d
-class defined by the GD::Graph module. It allows an (x,y) data set to
-be plotted as a 3d pie chart. The x values are typically strings.
-
-Note that GD::Graph::pie already produces a 3d effect, so GD::Graph::pie3d
-is just a wrapper around GD::Graph::pie. Similarly, the plugin
-GD.Graph.pie3d is effectively the same as the plugin GD.Graph.pie.
-
-See L<GD::Graph3d> for more details.
-
-=head1 AUTHOR
-
-Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-
-The GD::Graph3d module was written by Jeremy Wadsack. The GD::Graph module was written by Martien Verbruggen.
-
-
-=head1 VERSION
-
-1.55, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
-
-Copyright (C) 2001 Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-GD::Graph3d is copyright (c) 1999,2000 Wadsack-Allen. All Rights Reserved. GD::Graph is copyright 1999 Martien Verbruggen.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Plugin::GD|Template::Plugin::GD>, L<Template::Plugin::GD::Graph::lines|Template::Plugin::GD::Graph::lines>, L<Template::Plugin::GD::Graph::lines3d|Template::Plugin::GD::Graph::lines3d>, L<Template::Plugin::GD::Graph::bars|Template::Plugin::GD::Graph::bars>, L<Template::Plugin::GD::Graph::bars3d|Template::Plugin::GD::Graph::bars3d>, L<Template::Plugin::GD::Graph::points|Template::Plugin::GD::Graph::points>, L<Template::Plugin::GD::Graph::linespoints|Template::Plugin::GD::Graph::linespoints>, L<Template::Plugin::GD::Graph::area|Template::Plugin::GD::Graph::area>, L<Template::Plugin::GD::Graph::mixed|Template::Plugin::GD::Graph::mixed>, L<Template::Plugin::GD::Graph::pie|Template::Plugin::GD::Graph::pie>, L<GD::Graph|GD::Graph>, L<GD::Graph3d|GD::Graph3d>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/GD/Graph/points.pm b/lib/Template/Plugin/GD/Graph/points.pm
deleted file mode 100644
index 97acf51..0000000
--- a/lib/Template/Plugin/GD/Graph/points.pm
+++ /dev/null
@@ -1,155 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::GD::Graph::points
-#
-# DESCRIPTION
-#
-# Simple Template Toolkit plugin interfacing to the GD::Graph::points
-# package in the GD::Graph.pm module.
-#
-# AUTHOR
-# Craig Barratt <craig@arraycomm.com>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Craig Barratt. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: points.pm,v 1.57 2004/01/13 16:20:56 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::GD::Graph::points;
-
-require 5.004;
-
-use strict;
-use GD::Graph::points;
-use Template::Plugin;
-use base qw( GD::Graph::points Template::Plugin );
-use vars qw( $VERSION );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.57 $ =~ /(\d+)\.(\d+)/);
-
-sub new
-{
- my $class = shift;
- my $context = shift;
- return $class->SUPER::new(@_);
-}
-
-sub set
-{
- my $self = shift;
-
- push(@_, %{pop(@_)}) if ( @_ & 1 && ref($_[@_-1]) eq "HASH" );
- $self->SUPER::set(@_);
-}
-
-
-sub set_legend
-{
- my $self = shift;
-
- $self->SUPER::set_legend(ref $_[0] ? @{$_[0]} : @_);
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::GD::Graph::points - Create point graphs with axes and legends
-
-=head1 SYNOPSIS
-
- [% USE g = GD.Graph.points(x_size, y_size); %]
-
-=head1 EXAMPLES
-
- [% FILTER null;
- data = [
- ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"],
- [ 5, 12, 24, 33, 19, 8, 6, 15, 21],
- [ 1, 2, 5, 6, 3, 1.5, 2, 3, 4],
- ];
- USE my_graph = GD.Graph.points();
- my_graph.set(
- x_label => 'X Label',
- y_label => 'Y label',
- title => 'A Points Graph',
- y_max_value => 40,
- y_tick_number => 8,
- y_label_skip => 2,
- legend_placement => 'RC',
- long_ticks => 1,
- marker_size => 6,
- markers => [ 1, 7, 5 ],
-
- transparent => 0,
- );
- my_graph.set_legend('one', 'two');
- my_graph.plot(data).png | stdout(1);
- END;
- -%]
-
-=head1 DESCRIPTION
-
-The GD.Graph.points plugin provides an interface to the GD::Graph::points
-class defined by the GD::Graph module. It allows one or more (x,y) data
-sets to be plotted as points, in addition to axes and legends.
-
-See L<GD::Graph> for more details.
-
-=head1 AUTHOR
-
-Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-
-The GD::Graph module was written by Martien Verbruggen.
-
-
-=head1 VERSION
-
-1.57, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
-
-Copyright (C) 2001 Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-GD::Graph is copyright 1999 Martien Verbruggen.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Plugin::GD|Template::Plugin::GD>, L<Template::Plugin::GD::Graph::lines|Template::Plugin::GD::Graph::lines>, L<Template::Plugin::GD::Graph::lines3d|Template::Plugin::GD::Graph::lines3d>, L<Template::Plugin::GD::Graph::bars|Template::Plugin::GD::Graph::bars>, L<Template::Plugin::GD::Graph::bars3d|Template::Plugin::GD::Graph::bars3d>, L<Template::Plugin::GD::Graph::linespoints|Template::Plugin::GD::Graph::linespoints>, L<Template::Plugin::GD::Graph::area|Template::Plugin::GD::Graph::area>, L<Template::Plugin::GD::Graph::mixed|Template::Plugin::GD::Graph::mixed>, L<Template::Plugin::GD::Graph::pie|Template::Plugin::GD::Graph::pie>, L<Template::Plugin::GD::Graph::pie3d|Template::Plugin::GD::Graph::pie3d>, L<GD::Graph|GD::Graph>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/GD/Image.pm b/lib/Template/Plugin/GD/Image.pm
deleted file mode 100644
index 46a06d7..0000000
--- a/lib/Template/Plugin/GD/Image.pm
+++ /dev/null
@@ -1,184 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::GD::Image
-#
-# DESCRIPTION
-#
-# Simple Template Toolkit plugin interfacing to the GD::Image
-# class in the GD.pm module.
-#
-# AUTHOR
-# Craig Barratt <craig@arraycomm.com>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Craig Barratt. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Image.pm,v 1.55 2004/01/13 16:20:46 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::GD::Image;
-
-require 5.004;
-
-use strict;
-use GD;
-use Template::Plugin;
-use base qw( GD Template::Plugin );
-use vars qw( $VERSION );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.55 $ =~ /(\d+)\.(\d+)/);
-
-sub new
-{
- my $class = shift;
- my $context = shift;
- return new GD::Image(@_);
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::GD::Image - Interface to GD Graphics Library
-
-=head1 SYNOPSIS
-
- [% USE im = GD.Image(x_size, y_size) %]
-
-=head1 EXAMPLES
-
- [% FILTER null;
- USE gdc = GD.Constants;
- USE im = GD.Image(200,100);
- black = im.colorAllocate(0 ,0, 0);
- red = im.colorAllocate(255,0, 0);
- r = im.string(gdc.gdLargeFont, 10, 10, "Large Red Text", red);
- im.png | stdout(1);
- END;
- -%]
-
- [% FILTER null;
- USE im = GD.Image(100,100);
- # allocate some colors
- black = im.colorAllocate(0, 0, 0);
- red = im.colorAllocate(255,0, 0);
- blue = im.colorAllocate(0, 0, 255);
- # Draw a blue oval
- im.arc(50,50,95,75,0,360,blue);
- # And fill it with red
- im.fill(50,50,red);
- # Output binary image in PNG format
- im.png | stdout(1);
- END;
- -%]
-
- [% FILTER null;
- USE im = GD.Image(100,100);
- USE c = GD.Constants;
- USE poly = GD.Polygon;
-
- # allocate some colors
- white = im.colorAllocate(255,255,255);
- black = im.colorAllocate(0, 0, 0);
- red = im.colorAllocate(255,0, 0);
- blue = im.colorAllocate(0, 0,255);
- green = im.colorAllocate(0, 255,0);
-
- # make the background transparent and interlaced
- im.transparent(white);
- im.interlaced('true');
-
- # Put a black frame around the picture
- im.rectangle(0,0,99,99,black);
-
- # Draw a blue oval
- im.arc(50,50,95,75,0,360,blue);
-
- # And fill it with red
- im.fill(50,50,red);
-
- # Draw a blue triangle
- poly.addPt(50,0);
- poly.addPt(99,99);
- poly.addPt(0,99);
- im.filledPolygon(poly, blue);
-
- # Output binary image in PNG format
- im.png | stdout(1);
- END;
- -%]
-
-=head1 DESCRIPTION
-
-The GD.Image plugin provides an interface to GD.pm's GD::Image class.
-The GD::Image class is the main interface to GD.pm.
-
-It is very important that no extraneous template output appear before or
-after the image. Since some methods return values that would otherwise
-appear in the output, it is recommended that GD.Image code be wrapped in
-a null filter. The methods that produce the final output (eg, png, jpeg,
-gd etc) can then explicitly make their output appear by using the
-stdout filter, with a non-zero argument to force binary mode (required
-for non-modern operating systems).
-
-See L<GD> for a complete description of the GD library and all the
-methods that can be called via the GD.Image plugin.
-See L<Template::Plugin::GD::Constants> for a plugin that allows you
-access to GD.pm's constants.
-
-=head1 AUTHOR
-
-Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-
-Lincoln D. Stein wrote the GD.pm interface to the GD library.
-
-
-=head1 VERSION
-
-1.55, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
-
-Copyright (C) 2001 Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-The GD.pm interface is copyright 1995-2000, Lincoln D. Stein.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Plugin::GD|Template::Plugin::GD>, L<Template::Plugin::GD::Polygon|Template::Plugin::GD::Polygon>, L<Template::Plugin::GD::Constants|Template::Plugin::GD::Constants>, L<GD|GD>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/GD/Polygon.pm b/lib/Template/Plugin/GD/Polygon.pm
deleted file mode 100644
index 0d1d5c6..0000000
--- a/lib/Template/Plugin/GD/Polygon.pm
+++ /dev/null
@@ -1,155 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::GD::Polygon
-#
-# DESCRIPTION
-#
-# Simple Template Toolkit plugin interfacing to the GD::Polygon
-# class in the GD.pm module.
-#
-# AUTHOR
-# Craig Barratt <craig@arraycomm.com>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Craig Barratt. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Polygon.pm,v 1.55 2004/01/13 16:20:46 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::GD::Polygon;
-
-require 5.004;
-
-use strict;
-use GD;
-use Template::Plugin;
-use base qw( Template::Plugin );
-use vars qw( $VERSION );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.55 $ =~ /(\d+)\.(\d+)/);
-
-sub new
-{
- my $class = shift;
- my $context = shift;
- return new GD::Polygon(@_);
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::GD::Polygon - Interface to GD module Polygon class
-
-=head1 SYNOPSIS
-
- [% USE poly = GD.Polygon;
- poly.addPt(50,0);
- poly.addPt(99,99);
- %]
-
-=head1 EXAMPLES
-
- [% FILTER null;
- USE im = GD.Image(100,100);
- USE c = GD.Constants;
-
- # allocate some colors
- white = im.colorAllocate(255,255,255);
- black = im.colorAllocate(0, 0, 0);
- red = im.colorAllocate(255,0, 0);
- blue = im.colorAllocate(0, 0,255);
- green = im.colorAllocate(0, 255,0);
-
- # make the background transparent and interlaced
- im.transparent(white);
- im.interlaced('true');
-
- # Put a black frame around the picture
- im.rectangle(0,0,99,99,black);
-
- # Draw a blue oval
- im.arc(50,50,95,75,0,360,blue);
-
- # And fill it with red
- im.fill(50,50,red);
-
- # Draw a blue triangle by defining a polygon
- USE poly = GD.Polygon;
- poly.addPt(50,0);
- poly.addPt(99,99);
- poly.addPt(0,99);
- im.filledPolygon(poly, blue);
-
- # Output binary image in PNG format
- im.png | stdout(1);
- END;
- -%]
-
-=head1 DESCRIPTION
-
-The GD.Polygon plugin provides an interface to GD.pm's GD::Polygon class.
-
-See L<GD> for a complete description of the GD library and all the
-methods that can be called via the GD.Polygon plugin.
-See L<Template::Plugin::GD::Image> for the main interface to the
-GD functions.
-See L<Template::Plugin::GD::Constants> for a plugin that allows you
-access to GD.pm's constants.
-
-=head1 AUTHOR
-
-Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-
-Lincoln D. Stein wrote the GD.pm interface to the GD library.
-
-
-=head1 VERSION
-
-1.55, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
-
-Copyright (C) 2001 Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-The GD.pm interface is copyright 1995-2000, Lincoln D. Stein.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Plugin::GD|Template::Plugin::GD>, L<Template::Plugin::GD::Image|Template::Plugin::GD::Image>, L<Template::Plugin::GD::Constants|Template::Plugin::GD::Constants>, L<GD|GD>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/GD/Text.pm b/lib/Template/Plugin/GD/Text.pm
deleted file mode 100644
index f18b2e0..0000000
--- a/lib/Template/Plugin/GD/Text.pm
+++ /dev/null
@@ -1,140 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::GD::Text
-#
-# DESCRIPTION
-#
-# Simple Template Toolkit plugin interfacing to the GD::Text
-# module.
-#
-# AUTHOR
-# Craig Barratt <craig@arraycomm.com>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Craig Barratt. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Text.pm,v 1.55 2004/01/13 16:20:46 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::GD::Text;
-
-require 5.004;
-
-use strict;
-use GD::Text;
-use Template::Plugin;
-use base qw( GD::Text Template::Plugin );
-use vars qw( $VERSION );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.55 $ =~ /(\d+)\.(\d+)/);
-
-sub new
-{
- my $class = shift;
- my $context = shift;
-
- push(@_, %{pop(@_)}) if ( @_ & 1 && ref($_[@_-1]) eq "HASH" );
- return new GD::Text(@_);
-}
-
-sub set
-{
- my $self = shift;
-
- push(@_, %{pop(@_)}) if ( @_ & 1 && ref($_[@_-1]) eq "HASH" );
- $self->SUPER::set(@_);
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::GD::Text - Text utilities for use with GD
-
-=head1 SYNOPSIS
-
- [% USE gd_text = GD.Text %]
-
-=head1 EXAMPLES
-
- [%
- USE gd_c = GD.Constants;
- USE t = GD.Text;
- x = t.set_text('Some text');
- r = t.get('width', 'height', 'char_up', 'char_down');
- r.join(":"); "\n"; # returns 54:13:13:0.
- -%]
-
- [%
- USE gd_c = GD.Constants;
- USE t = GD.Text(text => 'FooBar Banana', font => gd_c.gdGiantFont);
- t.get('width'); "\n"; # returns 117.
- -%]
-
-=head1 DESCRIPTION
-
-The GD.Text plugin provides an interface to the GD::Text module.
-It allows attributes of strings such as width and height in pixels
-to be computed.
-
-See L<GD::Text> for more details. See
-L<Template::Plugin::GD::Text::Align> and
-L<Template::Plugin::GD::Text::Wrap> for plugins that
-allow you to render aligned or wrapped text in GD images.
-
-=head1 AUTHOR
-
-Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-
-The GD::Text module was written by Martien Verbruggen.
-
-
-=head1 VERSION
-
-1.55, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
-
-Copyright (C) 2001 Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-GD::Text is copyright 1999 Martien Verbruggen.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Plugin::GD|Template::Plugin::GD>, L<Template::Plugin::GD::Text::Wrap|Template::Plugin::GD::Text::Wrap>, L<Template::Plugin::GD::Text::Align|Template::Plugin::GD::Text::Align>, L<GD|GD>, L<GD::Text|GD::Text>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/GD/Text/Align.pm b/lib/Template/Plugin/GD/Text/Align.pm
deleted file mode 100644
index 8b79069..0000000
--- a/lib/Template/Plugin/GD/Text/Align.pm
+++ /dev/null
@@ -1,147 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::GD::Text::Align
-#
-# DESCRIPTION
-#
-# Simple Template Toolkit plugin interfacing to the GD::Text::Align
-# module.
-#
-# AUTHOR
-# Craig Barratt <craig@arraycomm.com>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Craig Barratt. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Align.pm,v 1.55 2004/01/13 16:21:46 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::GD::Text::Align;
-
-require 5.004;
-
-use strict;
-use GD::Text::Align;
-use Template::Plugin;
-use base qw( GD::Text::Align Template::Plugin );
-use vars qw( $VERSION );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.55 $ =~ /(\d+)\.(\d+)/);
-
-sub new
-{
- my $class = shift;
- my $context = shift;
- my $gd = shift;
-
- push(@_, %{pop(@_)}) if ( @_ & 1 && ref($_[@_-1]) eq "HASH" );
- return $class->SUPER::new($gd, @_);
-}
-
-sub set
-{
- my $self = shift;
-
- push(@_, %{pop(@_)}) if ( @_ & 1 && ref($_[@_-1]) eq "HASH" );
- $self->SUPER::set(@_);
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::GD::Text::Align - Draw aligned strings in GD images
-
-=head1 SYNOPSIS
-
- [% USE align = GD.Text.Align(gd_image); %]
-
-=head1 EXAMPLES
-
- [% FILTER null;
- USE im = GD.Image(100,100);
- USE gdc = GD.Constants;
- # allocate some colors
- black = im.colorAllocate(0, 0, 0);
- red = im.colorAllocate(255,0, 0);
- blue = im.colorAllocate(0, 0, 255);
- # Draw a blue oval
- im.arc(50,50,95,75,0,360,blue);
-
- USE a = GD.Text.Align(im);
- a.set_font(gdc.gdLargeFont);
- a.set_text("Hello");
- a.set(colour => red, halign => "center");
- a.draw(50,70,0);
-
- # Output image in PNG format
- im.png | stdout(1);
- END;
- -%]
-
-=head1 DESCRIPTION
-
-The GD.Text.Align plugin provides an interface to the GD::Text::Align
-module. It allows text to be drawn in GD images with various alignments
-and orientations.
-
-See L<GD::Text::Align> for more details. See
-L<Template::Plugin::GD::Text::Wrap> for a plugin
-that allow you to render wrapped text in GD images.
-
-=head1 AUTHOR
-
-Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-
-The GD::Text module was written by Martien Verbruggen.
-
-
-=head1 VERSION
-
-1.55, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
-
-Copyright (C) 2001 Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-GD::Text is copyright 1999 Martien Verbruggen.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Plugin::GD|Template::Plugin::GD>, L<Template::Plugin::GD::Text|Template::Plugin::GD::Text>, L<Template::Plugin::GD::Text::Wrap|Template::Plugin::GD::Text::Wrap>, L<GD|GD>, L<GD::Text::Align|GD::Text::Align>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/GD/Text/Wrap.pm b/lib/Template/Plugin/GD/Text/Wrap.pm
deleted file mode 100644
index 0438599..0000000
--- a/lib/Template/Plugin/GD/Text/Wrap.pm
+++ /dev/null
@@ -1,183 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::GD::Text::Wrap
-#
-# DESCRIPTION
-#
-# Simple Template Toolkit plugin interfacing to the GD::Text::Wrap
-# module.
-#
-# AUTHOR
-# Craig Barratt <craig@arraycomm.com>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Craig Barratt. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Wrap.pm,v 1.55 2004/01/13 16:21:46 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::GD::Text::Wrap;
-
-require 5.004;
-
-use strict;
-use GD::Text::Wrap;
-use Template::Plugin;
-use base qw( GD::Text::Wrap Template::Plugin );
-use vars qw( $VERSION );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.55 $ =~ /(\d+)\.(\d+)/);
-
-sub new
-{
- my $class = shift;
- my $context = shift;
- my $gd = shift;
-
- push(@_, %{pop(@_)}) if ( @_ & 1 && ref($_[@_-1]) eq "HASH" );
- return $class->SUPER::new($gd, @_);
-}
-
-sub set
-{
- my $self = shift;
-
- push(@_, %{pop(@_)}) if ( @_ & 1 && ref($_[@_-1]) eq "HASH" );
- $self->SUPER::set(@_);
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::GD::Text::Wrap - Break and wrap strings in GD images
-
-=head1 SYNOPSIS
-
- [% USE align = GD.Text.Wrap(gd_image); %]
-
-=head1 EXAMPLES
-
- [% FILTER null;
- USE gd = GD.Image(200,400);
- USE gdc = GD.Constants;
- black = gd.colorAllocate(0, 0, 0);
- green = gd.colorAllocate(0, 255, 0);
- txt = "This is some long text. " | repeat(10);
- USE wrapbox = GD.Text.Wrap(gd,
- line_space => 4,
- color => green,
- text => txt,
- );
- wrapbox.set_font(gdc.gdMediumBoldFont);
- wrapbox.set(align => 'center', width => 160);
- wrapbox.draw(20, 20);
- gd.png | stdout(1);
- END;
- -%]
-
- [% txt = BLOCK -%]
- Lorem ipsum dolor sit amet, consectetuer adipiscing elit,
- sed diam nonummy nibh euismod tincidunt ut laoreet dolore
- magna aliquam erat volutpat.
- [% END -%]
- [% FILTER null;
- #
- # This example follows the example in GD::Text::Wrap, except
- # we create a second image that is a copy just enough of the
- # first image to hold the final text, plus a border.
- #
- USE gd = GD.Image(400,400);
- USE gdc = GD.Constants;
- green = gd.colorAllocate(0, 255, 0);
- blue = gd.colorAllocate(0, 0, 255);
- USE wrapbox = GD.Text.Wrap(gd,
- line_space => 4,
- color => green,
- text => txt,
- );
- wrapbox.set_font(gdc.gdMediumBoldFont);
- wrapbox.set(align => 'center', width => 140);
- rect = wrapbox.get_bounds(5, 5);
- x0 = rect.0;
- y0 = rect.1;
- x1 = rect.2 + 9;
- y1 = rect.3 + 9;
- gd.filledRectangle(0, 0, x1, y1, blue);
- gd.rectangle(0, 0, x1, y1, green);
- wrapbox.draw(x0, y0);
- nx = x1 + 1;
- ny = y1 + 1;
- USE gd2 = GD.Image(nx, ny);
- gd2.copy(gd, 0, 0, 0, 0, x1, y1);
- gd2.png | stdout(1);
- END;
- -%]
-
-=head1 DESCRIPTION
-
-The GD.Text.Wrap plugin provides an interface to the GD::Text::Wrap
-module. It allows multiples line of text to be drawn in GD images with
-various wrapping and alignment.
-
-See L<GD::Text::Wrap> for more details. See
-L<Template::Plugin::GD::Text::Align> for a plugin
-that allow you to draw text with various alignment
-and orientation.
-
-=head1 AUTHOR
-
-Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-
-The GD::Text module was written by Martien Verbruggen.
-
-
-=head1 VERSION
-
-1.55, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
-
-Copyright (C) 2001 Craig Barratt E<lt>craig@arraycomm.comE<gt>
-
-GD::Text is copyright 1999 Martien Verbruggen.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Plugin::GD|Template::Plugin::GD>, L<Template::Plugin::GD::Text::Align|Template::Plugin::GD::Text::Align>, L<GD|GD>, L<GD::Text::Wrap|GD::Text::Wrap>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/HTML.pm b/lib/Template/Plugin/HTML.pm
deleted file mode 100644
index 5cb63e0..0000000
--- a/lib/Template/Plugin/HTML.pm
+++ /dev/null
@@ -1,197 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::HTML
-#
-# DESCRIPTION
-#
-# Template Toolkit plugin providing useful functionality for generating
-# HTML.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: HTML.pm,v 2.56 2004/01/13 16:20:38 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::HTML;
-
-require 5.004;
-
-use strict;
-use vars qw( $VERSION );
-use base qw( Template::Plugin );
-use Template::Plugin;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.56 $ =~ /(\d+)\.(\d+)/);
-
-sub new {
- my ($class, $context, @args) = @_;
- my $hash = ref $args[-1] eq 'HASH' ? pop @args : { };
- bless {
- _SORTED => $hash->{ sorted } || 0,
- }, $class;
-}
-
-sub element {
- my ($self, $name, $attr) = @_;
- ($name, $attr) = %$name if ref $name eq 'HASH';
- return '' unless defined $name and length $name;
- $attr = $self->attributes($attr);
- $attr = " $attr" if $attr;
- return "<$name$attr>";
-}
-
-sub attributes {
- my ($self, $hash) = @_;
- return '' unless UNIVERSAL::isa($hash, 'HASH');
-
- my @keys = keys %$hash;
- @keys = sort @keys if $self->{ _SORTED };
-
- join(' ', map {
- "$_=\"" . $self->escape( $hash->{ $_ } ) . '"';
- } @keys);
-}
-
-sub escape {
- my ($self, $text) = @_;
- for ($text) {
- s/&/&amp;/g;
- s/</&lt;/g;
- s/>/&gt;/g;
- s/"/&quot;/g;
- }
- $text;
-}
-
-sub url {
- my ($self, $text) = @_;
- return undef unless defined $text;
- $text =~ s/([^a-zA-Z0-9_.-])/uc sprintf("%%%02x",ord($1))/eg;
- return $text;
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::HTML - Plugin to create HTML elements
-
-=head1 SYNOPSIS
-
- [% USE HTML %]
-
- [% HTML.escape("if (a < b && c > d) ..." %]
-
- [% HTML.element(table => { border => 1, cellpadding => 2 }) %]
-
- [% HTML.attributes(border => 1, cellpadding => 2) %]
-
-=head1 DESCRIPTION
-
-The HTML plugin is very new and very basic, implementing a few useful
-methods for generating HTML. It is likely to be extended in the future
-or integrated with a larger project to generate HTML elements in a generic
-way (as discussed recently on the mod_perl mailing list).
-
-=head1 METHODS
-
-=head2 escape(text)
-
-Returns the source text with any HTML reserved characters such as
-E<lt>, E<gt>, etc., correctly esacped to their entity equivalents.
-
-=head2 attributes(hash)
-
-Returns the elements of the hash array passed by reference correctly
-formatted (e.g. values quoted and correctly escaped) as attributes for
-an HTML element.
-
-=head2 element(type, attributes)
-
-Generates an HTML element of the specified type and with the attributes
-provided as an optional hash array reference as the second argument or
-as named arguments.
-
- [% HTML.element(table => { border => 1, cellpadding => 2 }) %]
- [% HTML.element('table', border=1, cellpadding=2) %]
- [% HTML.element(table => attribs) %]
-
-=head1 DEBUGGING
-
-The HTML plugin accepts a 'sorted' option as a constructor argument
-which, when set to any true value, causes the attributes generated by
-the attributes() method (either directly or via element()) to be
-returned in sorted order. Order of attributes isn't important in
-HTML, but this is provided mainly for the purposes of debugging where
-it is useful to have attributes generated in a deterministic order
-rather than whatever order the hash happened to feel like returning
-the keys in.
-
- [% USE HTML(sorted=1) %]
- [% HTML.element( foo => { charlie => 1, bravo => 2, alpha => 3 } ) %]
-
-generates:
-
- <foo alpha="3" bravo="2" charlie="1">
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.56, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/Image.pm b/lib/Template/Plugin/Image.pm
deleted file mode 100644
index 4eb509c..0000000
--- a/lib/Template/Plugin/Image.pm
+++ /dev/null
@@ -1,425 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::Image
-#
-# DESCRIPTION
-# Plugin for encapsulating information about an image.
-#
-# AUTHOR
-# Andy Wardley <abw@wardley.org>
-#
-# COPYRIGHT
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-# REVISION
-# $Id: Image.pm,v 1.13 2004/01/13 16:20:38 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::Image;
-
-require 5.004;
-
-use strict;
-use Template::Exception;
-use Template::Plugin;
-use File::Spec;
-#use Image::Info;
-#use Image::Size;
-
-use base qw( Template::Plugin );
-use vars qw( $VERSION $AUTOLOAD );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.13 $ =~ /(\d+)\.(\d+)/);
-
-BEGIN {
- if (eval { require Image::Info; }) {
- *img_info = \&Image::Info::image_info;
- }
- elsif (eval { require Image::Size; }) {
- *img_info = sub {
- my $file = shift;
- my @stuff = Image::Size::imgsize($file);
- return { "width" => $stuff[0],
- "height" => $stuff[1],
- "error" =>
- # imgsize returns either a three letter file type
- # or an error message as third value
- (defined($stuff[2]) && length($stuff[2]) > 3
- ? $stuff[2]
- : undef),
- };
- }
- }
- else {
- die(Template::Exception->new("image",
- "Couldn't load Image::Info or Image::Size: $@"));
- }
-
-}
-
-#------------------------------------------------------------------------
-# new($context, $name, \%config)
-#
-# Create a new Image object. Takes the pathname of the file as
-# the argument following the context and an optional
-# hash reference of configuration parameters.
-#------------------------------------------------------------------------
-
-sub new {
- my $config = ref($_[-1]) eq 'HASH' ? pop(@_) : { };
- my ($class, $context, $name) = @_;
- my ($root, $file, $type);
-
- # name can be a positional or named argument
- $name = $config->{ name } unless defined $name;
-
- return $class->throw('no image file specified')
- unless defined $name and length $name;
-
- # name can be specified as an absolute path or relative
- # to a root directory
-
- if ($root = $config->{ root }) {
- $file = File::Spec->catfile($root, $name);
- }
- else {
- $file = $name;
- }
-
- # Make a note of whether we are using Image::Size or
- # Image::Info -- at least for the test suite
- $type = $INC{"Image/Size.pm"} ? "Image::Size" : "Image::Info";
-
- # do we want to check to see if file exists?
-
- bless {
- name => $name,
- file => $file,
- root => $root,
- type => $type,
- }, $class;
-}
-
-#------------------------------------------------------------------------
-# init()
-#
-# Calls image_info on $self->{ file }
-#------------------------------------------------------------------------
-
-sub init {
- my $self = shift;
- return $self if $self->{ size };
-
- my $image = img_info($self->{ file });
- return $self->throw($image->{ error }) if defined $image->{ error };
-
- @$self{ keys %$image } = values %$image;
- $self->{ size } = [ $image->{ width }, $image->{ height } ];
-
- $self->{ modtime } = (stat $self->{ file })[10];
-
- return $self;
-}
-
-#------------------------------------------------------------------------
-# attr()
-#
-# Return the width and height as HTML/XML attributes.
-#------------------------------------------------------------------------
-
-sub attr {
- my $self = shift;
- my $size = $self->size();
- return "width=\"$size->[0]\" height=\"$size->[1]\"";
-}
-
-#------------------------------------------------------------------------
-# modtime()
-#
-# Return last modification time as a time_t:
-#
-# [% date.format(image.modtime, "%Y/%m/%d") %]
-#------------------------------------------------------------------------
-
-sub modtime {
- my $self = shift;
- $self->init;
- return $self->{ modtime };
-}
-
-#------------------------------------------------------------------------
-# tag(\%options)
-#
-# Return an XHTML img tag.
-#------------------------------------------------------------------------
-
-sub tag {
- my $self = shift;
- my $options = ref $_[0] eq 'HASH' ? shift : { @_ };
-
- my $tag = "<img src=\"$self->{ name }\" " . $self->attr();
-
- if (%$options) {
- while (my ($key, $val) = each %$options) {
- $tag .= " $key=\"$val\"";
- }
- }
-
- $tag .= ' />';
-
- return $tag;
-}
-
-
-sub throw {
- my ($self, $error) = @_;
- die (Template::Exception->new('Image', $error));
-}
-
-sub AUTOLOAD {
- my $self = shift;
- (my $a = $AUTOLOAD) =~ s/.*:://;
-
- $self->init;
- return $self->{ $a };
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::Image - Plugin access to image sizes
-
-=head1 SYNOPSIS
-
- [% USE Image(filename) %]
- [% Image.width %]
- [% Image.height %]
- [% Image.size.join(', ') %]
- [% Image.attr %]
- [% Image.tag %]
-
-=head1 DESCRIPTION
-
-This plugin provides an interface to the Image::Info or Image::Size
-modules for determining the size of image files.
-
-You can specify the plugin name as either 'Image' or 'image'. The
-plugin object created will then have the same name. The file name of
-the image should be specified as a positional or named argument.
-
- [% # all these are valid, take your pick %]
- [% USE Image('foo.gif') %]
- [% USE image('bar.gif') %]
- [% USE Image 'ping.gif' %]
- [% USE image(name='baz.gif') %]
- [% USE Image name='pong.gif' %]
-
-You can also provide an alternate name for an Image plugin object.
-
- [% USE img1 = image 'foo.gif' %]
- [% USE img2 = image 'bar.gif' %]
-
-The 'width' and 'height' methods return the width and height of the
-image, respectively. The 'size' method returns a reference to a 2
-element list containing the width and height.
-
- [% USE image 'foo.gif' %]
- width: [% image.width %]
- height: [% image.height %]
- size: [% image.size.join(', ') %]
-
-The 'attr' method returns the height and width as HTML/XML attributes.
-
- [% USE image 'foo.gif' %]
- [% image.attr %]
-
-Typical output:
-
- width="60" height="20"
-
-The 'tag' method returns a complete XHTML tag referencing the image.
-
- [% USE image 'foo.gif' %]
- [% image.tag %]
-
-Typical output:
-
- <img src="foo.gif" width="60" height="20" />
-
-You can provide any additional attributes that should be added to the
-XHTML tag.
-
-
- [% USE image 'foo.gif' %]
- [% image.tag(border=0, class="logo") %]
-
-Typical output:
-
- <img src="foo.gif" width="60" height="20" border="0" class="logo" />
-
-The 'modtime' method returns the ctime of the file in question, suitable
-for use with date.format:
-
- [% USE image 'foo.gif' %]
- [% USE date %]
- [% date.format(image.modtime, "%B, %e %Y") %]
-
-=head1 CATCHING ERRORS
-
-If the image file cannot be found then the above methods will throw an
-'Image' error. You can enclose calls to these methods in a
-TRY...CATCH block to catch any potential errors.
-
- [% TRY;
- image.width;
- CATCH;
- error; # print error
- END
- %]
-
-=head1 USING Image::Info
-
-At run time, the plugin tries to load Image::Info in preference to
-Image::Size. If Image::Info is found, then some additional methods are
-available, in addition to 'size', 'width', 'height', 'attr', and 'tag'.
-These additional methods are named after the elements that Image::Info
-retrieves from the image itself; see L<Image::Info> for more details
--- the types of methods available depend on the type of image.
-These additional methods will always include the following:
-
-=over 4
-
-=item file_media_type
-
-This is the MIME type that is appropriate for the given file format.
-The corresponding value is a string like: "image/png" or "image/jpeg".
-
-=item file_ext
-
-The is the suggested file name extention for a file of the given
-file format. The value is a 3 letter, lowercase string like
-"png", "jpg".
-
-
-=item color_type
-
-The value is a short string describing what kind of values the pixels
-encode. The value can be one of the following:
-
- Gray
- GrayA
- RGB
- RGBA
- CMYK
- YCbCr
- CIELab
-
-These names can also be prefixed by "Indexed-" if the image is
-composed of indexes into a palette. Of these, only "Indexed-RGB" is
-likely to occur.
-
-(It is similar to the TIFF field PhotometricInterpretation, but this
-name was found to be too long, so we used the PNG inpired term
-instead.)
-
-=item resolution
-
-The value of this field normally gives the physical size of the image
-on screen or paper. When the unit specifier is missing then this field
-denotes the squareness of pixels in the image.
-
-The syntax of this field is:
-
- <res> <unit>
- <xres> "/" <yres> <unit>
- <xres> "/" <yres>
-
-The E<lt>resE<gt>, E<lt>xresE<gt> and E<lt>yresE<gt> fields are
-numbers. The E<lt>unitE<gt> is a string like C<dpi>, C<dpm> or
-C<dpcm> (denoting "dots per inch/cm/meter).
-
-=item SamplesPerPixel
-
-This says how many channels there are in the image. For some image
-formats this number might be higher than the number implied from the
-C<color_type>.
-
-=item BitsPerSample
-
-This says how many bits are used to encode each of samples. The value
-is a reference to an array containing numbers. The number of elements
-in the array should be the same as C<SamplesPerPixel>.
-
-=item Comment
-
-Textual comments found in the file. The value is a reference to an
-array if there are multiple comments found.
-
-=item Interlace
-
-If the image is interlaced, then this tell which interlace method is
-used.
-
-=item Compression
-
-This tell which compression algorithm is used.
-
-=item Gamma
-
-A number.
-
-
-=back
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-1.13, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/Iterator.pm b/lib/Template/Plugin/Iterator.pm
deleted file mode 100644
index 0f33b2f..0000000
--- a/lib/Template/Plugin/Iterator.pm
+++ /dev/null
@@ -1,118 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::Iterator
-#
-# DESCRIPTION
-#
-# Plugin to create a Template::Iterator from a list of items and optional
-# configuration parameters.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 2000 Andy Wardley. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Iterator.pm,v 2.62 2004/01/13 16:20:38 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::Iterator;
-
-require 5.004;
-
-use strict;
-use vars qw( $VERSION );
-use base qw( Template::Plugin );
-use Template::Plugin;
-use Template::Iterator;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.62 $ =~ /(\d+)\.(\d+)/);
-
-#------------------------------------------------------------------------
-# new($context, \@data, \%args)
-#------------------------------------------------------------------------
-
-sub new {
- my $class = shift;
- my $context = shift;
- Template::Iterator->new(@_);
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::Iterator - Plugin to create iterators (Template::Iterator)
-
-=head1 SYNOPSIS
-
- [% USE iterator(list, args) %]
-
- [% FOREACH item = iterator %]
- [% '<ul>' IF iterator.first %]
- <li>[% item %]
- [% '</ul>' IF iterator.last %]
- [% END %]
-
-=head1 DESCRIPTION
-
-The iterator plugin provides a way to create a Template::Iterator object
-to iterate over a data set. An iterator is implicitly automatically by the
-FOREACH directive. This plugin allows the iterator to be explicitly created
-with a given name.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.62, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::Iterator|Template::Iterator>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/Pod.pm b/lib/Template/Plugin/Pod.pm
deleted file mode 100644
index e5f82c2..0000000
--- a/lib/Template/Plugin/Pod.pm
+++ /dev/null
@@ -1,116 +0,0 @@
-#==============================================================================
-#
-# Template::Plugin::Pod
-#
-# DESCRIPTION
-# Pod parser and object model.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 2000 Andy Wardley. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-# REVISION
-# $Id: Pod.pm,v 2.62 2004/01/13 16:20:38 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::Pod;
-
-require 5.004;
-
-use strict;
-use Template::Plugin;
-use vars qw( $VERSION );
-use base qw( Template::Plugin );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.62 $ =~ /(\d+)\.(\d+)/);
-
-use Pod::POM;
-
-#------------------------------------------------------------------------
-# new($context, \%config)
-#------------------------------------------------------------------------
-
-sub new {
- my $class = shift;
- my $context = shift;
-
- Pod::POM->new(@_);
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::Pod - Plugin interface to Pod::POM (Pod Object Model)
-
-=head1 SYNOPSIS
-
- [% USE Pod(podfile) %]
-
- [% FOREACH head1 = Pod.head1;
- FOREACH head2 = head1/head2;
- ...
- END;
- END
- %]
-
-=head1 DESCRIPTION
-
-This plugin is an interface to the Pod::POM module.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.62, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Pod::POM|Pod::POM>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/Procedural.pm b/lib/Template/Plugin/Procedural.pm
deleted file mode 100644
index 8601225..0000000
--- a/lib/Template/Plugin/Procedural.pm
+++ /dev/null
@@ -1,170 +0,0 @@
-#==============================================================================
-#
-# Template::Plugin::Procedural
-#
-# DESCRIPTION
-#
-# A Template Plugin to provide a Template Interface to Data::Dumper
-#
-# AUTHOR
-# Mark Fowler <mark@twoshortplanks.com>
-#
-# COPYRIGHT
-#
-# Copyright (C) 2002 Mark Fowler. All Rights Reserved
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#------------------------------------------------------------------------------
-#
-# $Id: Procedural.pm,v 1.11 2004/01/13 16:20:38 abw Exp $
-#
-#==============================================================================
-
-package Template::Plugin::Procedural;
-
-require 5.004;
-
-use strict;
-
-use vars qw( $VERSION $DEBUG $AUTOLOAD );
-use base qw( Template::Plugin );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.11 $ =~ /(\d+)\.(\d+)/);
-$DEBUG = 0 unless defined $DEBUG;
-
-#------------------------------------------------------------------------
-# load
-#------------------------------------------------------------------------
-
-sub load
-{
- my ($class, $context) = @_;
-
- # create a proxy namespace that will be used for objects
- my $proxy = "Template::Plugin::" . $class;
-
- # okay, in our proxy create the autoload routine that will
- # call the right method in the real class
- no strict "refs";
- *{ $proxy . "::AUTOLOAD" } =
- sub
- {
- # work out what the method is called
- $AUTOLOAD =~ s!^.*::!!;
-
- print STDERR "Calling '$AUTOLOAD' in '$class'\n"
- if $DEBUG;
-
- # look up the sub for that method (but in a OO way)
- my $uboat = $class->can($AUTOLOAD);
-
- # if it existed call it as a subroutine, not as a method
- if ($uboat)
- {
- shift @_;
- return $uboat->(@_);
- }
-
- print STDERR "Eeek, no such method '$AUTOLOAD'\n"
- if $DEBUG;
-
- return "";
- };
-
- # create a simple new method that simply returns a blessed
- # scalar as the object.
- *{ $proxy . "::new" } =
- sub
- {
- my $this;
- return bless \$this, $_[0];
- };
-
- return $proxy;
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::Procedural - Base class for procedural plugins
-
-=head1 SYNOPSIS
-
- package Template::Plugin::LWPSimple;
- use base qw(Template::Plugin::Procedural);
- use LWP::Simple; # exports 'get'
- 1;
-
- [% USE LWPSimple %]
- [% LWPSimple.get("http://www.tt2.org/") %]
-
-=head1 DESCRIPTION
-
-B<Template::Plugin::Procedural> is a base class for Template Toolkit
-plugins that causes defined subroutines to be called directly rather
-than as a method. Essentially this means that subroutines will not
-receive the class name or object as its first argument.
-
-This is most useful when creating plugins for modules that normally
-work by exporting subroutines that do not expect such additional
-arguments.
-
-Despite the fact that subroutines will not be called in an OO manner,
-inheritance still function as normal. A class that uses
-B<Template::Plugin::Procedural> can be subclassed and both subroutines
-defined in the subclass and subroutines defined in the original class
-will be available to the Template Toolkit and will be called without
-the class/object argument.
-
-=head1 AUTHOR
-
-Mark Fowler E<lt>mark@twoshortplanks.comE<gt>
-
-L<http://www.twoshortplanks.com|http://www.twoshortplanks.com>
-
-
-
-
-=head1 VERSION
-
-1.11, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
-
-Copyright (C) 2002 Mark Fowler E<lt>mark@twoshortplanks.comE<gt>
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template|Template>, L<Template::Plugin|Template::Plugin>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/String.pm b/lib/Template/Plugin/String.pm
deleted file mode 100644
index 34dd007..0000000
--- a/lib/Template/Plugin/String.pm
+++ /dev/null
@@ -1,796 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::String
-#
-# DESCRIPTION
-# Template Toolkit plugin to implement a basic String object.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Andy Wardley. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-# REVISION
-# $Id: String.pm,v 2.33 2004/01/13 16:20:38 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::String;
-
-require 5.004;
-
-use strict;
-use Template::Plugin;
-use Template::Exception;
-
-use base qw( Template::Plugin );
-use vars qw( $VERSION $ERROR);
-use overload q|""| => "text",
- fallback => 1;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.33 $ =~ /(\d+)\.(\d+)/);
-$ERROR = '';
-
-*centre = \*center;
-*append = \*push;
-*prepend = \*unshift;
-
-#------------------------------------------------------------------------
-
-sub new {
- my ($class, @args) = @_;
- my $context = ref $class ? undef : shift(@args);
- my $config = @args && ref $args[-1] eq 'HASH' ? pop(@args) : { };
-
- $class = ref($class) || $class;
-
- my $text = defined $config->{ text }
- ? $config->{ text }
- : (@args ? shift(@args) : '');
-
-# print STDERR "text: [$text]\n";
-# print STDERR "class: [$class]\n";
-
- my $self = bless {
- text => $text,
- filters => [ ],
- _CONTEXT => $context,
- }, $class;
-
- my $filter = $config->{ filter } || $config->{ filters };
-
- # install any output filters specified as 'filter' or 'filters' option
- $self->output_filter($filter)
- if $filter;
-
- return $self;
-}
-
-
-sub text {
- my $self = shift;
- return $self->{ text } unless @{ $self->{ filters } };
-
- my $text = $self->{ text };
- my $context = $self->{ _CONTEXT };
-
- foreach my $dispatch (@{ $self->{ filters } }) {
- my ($name, $args) = @$dispatch;
- my $code = $context->filter($name, $args)
- || $self->throw($context->error());
- $text = &$code($text);
- }
- return $text;
-}
-
-
-sub copy {
- my $self = shift;
- $self->new($self->{ text });
-}
-
-
-sub throw {
- my $self = shift;
-
- die (Template::Exception->new('String', join('', @_)));
-}
-
-
-#------------------------------------------------------------------------
-# output_filter($filter)
-#
-# Install automatic output filter(s) for the string. $filter can a list:
-# [ 'name1', 'name2' => [ ..args.. ], name4 => { ..args.. } ] or a hash
-# { name1 => '', name2 => [ args ], name3 => { args } }
-#------------------------------------------------------------------------
-
-sub output_filter {
- my ($self, $filter) = @_;
- my ($name, $args, $dispatch);
- my $filters = $self->{ filters };
- my $count = 0;
-
- if (ref $filter eq 'HASH') {
- $filter = [ %$filter ];
- }
- elsif (ref $filter ne 'ARRAY') {
- $filter = [ split(/\s*\W+\s*/, $filter) ];
- }
-
- while (@$filter) {
- $name = shift @$filter;
-
- # args may follow as a reference (or empty string, e.g. { foo => '' }
- if (@$filter && (ref($filter->[0]) || ! length $filter->[0])) {
- $args = shift @$filter;
- if ($args) {
- $args = [ $args ] unless ref $args eq 'ARRAY';
- }
- else {
- $args = [ ];
- }
- }
- else {
- $args = [ ];
- }
-
-# $self->DEBUG("adding output filter $name(@$args)\n");
-
- push(@$filters, [ $name, $args ]);
- $count++;
- }
-
- return '';
-}
-
-
-#------------------------------------------------------------------------
-
-sub push {
- my $self = shift;
- $self->{ text } .= join('', @_);
- return $self;
-}
-
-
-sub unshift {
- my $self = shift;
- $self->{ text } = join('', @_) . $self->{ text };
- return $self;
-}
-
-
-sub pop {
- my $self = shift;
- my $strip = shift || return $self;
- $self->{ text } =~ s/$strip$//;
- return $self;
-}
-
-
-sub shift {
- my $self = shift;
- my $strip = shift || return $self;
- $self->{ text } =~ s/^$strip//;
- return $self;
-}
-
-#------------------------------------------------------------------------
-
-sub center {
- my ($self, $width) = @_;
- my $text = $self->{ text };
- my $len = length $text;
- $width ||= 0;
-
- if ($len < $width) {
- my $lpad = int(($width - $len) / 2);
- my $rpad = $width - $len - $lpad;
- $self->{ text } = (' ' x $lpad) . $self->{ text } . (' ' x $rpad);
- }
-
- return $self;
-}
-
-
-sub left {
- my ($self, $width) = @_;
- my $len = length $self->{ text };
- $width ||= 0;
-
- $self->{ text } .= (' ' x ($width - $len))
- if $width > $len;
-
- return $self;
-}
-
-
-sub right {
- my ($self, $width) = @_;
- my $len = length $self->{ text };
- $width ||= 0;
-
- $self->{ text } = (' ' x ($width - $len)) . $self->{ text }
- if $width > $len;
-
- return $self;
-}
-
-
-sub format {
- my ($self, $format) = @_;
- $format = '%s' unless defined $format;
- $self->{ text } = sprintf($format, $self->{ text });
- return $self;
-}
-
-
-sub filter {
- my ($self, $name, @args) = @_;
-
- my $context = $self->{ _CONTEXT };
-
- my $code = $context->filter($name, \@args)
- || $self->throw($context->error());
- return &$code($self->{ text });
-}
-
-
-#------------------------------------------------------------------------
-
-sub upper {
- my $self = CORE::shift;
- $self->{ text } = uc $self->{ text };
- return $self;
-}
-
-
-sub lower {
- my $self = CORE::shift;
- $self->{ text } = lc $self->{ text };
- return $self;
-}
-
-
-sub capital {
- my $self = CORE::shift;
- $self->{ text } =~ s/^(.)/\U$1/;
- return $self;
-}
-
-#------------------------------------------------------------------------
-
-sub chop {
- my $self = CORE::shift;
- chop $self->{ text };
- return $self;
-}
-
-
-sub chomp {
- my $self = CORE::shift;
- chomp $self->{ text };
- return $self;
-}
-
-
-sub trim {
- my $self = CORE::shift;
- for ($self->{ text }) {
- s/^\s+//;
- s/\s+$//;
- }
- return $self;
-}
-
-
-sub collapse {
- my $self = CORE::shift;
- for ($self->{ text }) {
- s/^\s+//;
- s/\s+$//;
- s/\s+/ /g
- }
- return $self;
-
-}
-
-#------------------------------------------------------------------------
-
-sub length {
- my $self = CORE::shift;
- return length $self->{ text };
-}
-
-
-sub truncate {
- my ($self, $length, $suffix) = @_;
- return $self unless defined $length;
- $suffix ||= '';
- return $self if CORE::length $self->{ text } <= $length;
- $self->{ text } = substr($self->{ text }, 0,
- $length - CORE::length($suffix)) . $suffix;
- return $self;
-}
-
-
-sub repeat {
- my ($self, $n) = @_;
- return $self unless defined $n;
- $self->{ text } = $self->{ text } x $n;
- return $self;
-}
-
-
-sub replace {
- my ($self, $search, $replace) = @_;
- return $self unless defined $search;
- $replace = '' unless defined $replace;
- $self->{ text } =~ s/$search/$replace/g;
- return $self;
-}
-
-
-sub remove {
- my ($self, $search) = @_;
- $search = '' unless defined $search;
- $self->{ text } =~ s/$search//g;
- return $self;
-}
-
-
-sub split {
- my $self = CORE::shift;
- my $split = CORE::shift;
- my $limit = CORE::shift || 0;
- $split = '\s+' unless defined $split;
- return [ split($split, $self->{ text }, $limit) ];
-}
-
-
-sub search {
- my ($self, $pattern) = @_;
- return $self->{ text } =~ /$pattern/;
-}
-
-
-sub equals {
- my ($self, $comparison) = @_;
- return $self->{ text } eq $comparison;
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::String - Object oriented interface for string manipulation
-
-=head1 SYNOPSIS
-
- # create String objects via USE directive
- [% USE String %]
- [% USE String 'initial text' %]
- [% USE String text => 'initial text' %]
-
- # or from an existing String via new()
- [% newstring = String.new %]
- [% newstring = String.new('newstring text') %]
- [% newstring = String.new( text => 'newstring text' ) %]
-
- # or from an existing String via copy()
- [% newstring = String.copy %]
-
- # append text to string
- [% String.append('text to append') %]
-
- # format left, right or center/centre padded
- [% String.left(20) %]
- [% String.right(20) %]
- [% String.center(20) %] # American spelling
- [% String.centre(20) %] # European spelling
-
- # and various other methods...
-
-=head1 DESCRIPTION
-
-This module implements a String class for doing stringy things to
-text in an object-oriented way.
-
-You can create a String object via the USE directive, adding any
-initial text value as an argument or as the named parameter 'text'.
-
- [% USE String %]
- [% USE String 'initial text' %]
- [% USE String text='initial text' %]
-
-The object created will be referenced as 'String' by default, but you
-can provide a different variable name for the object to be assigned
-to:
-
- [% USE greeting = String 'Hello World' %]
-
-Once you've got a String object, you can use it as a prototype to
-create other String objects with the new() method.
-
- [% USE String %]
- [% greeting = String.new('Hello World') %]
-
-The new() method also accepts an initial text string as an argument
-or the named parameter 'text'.
-
- [% greeting = String.new( text => 'Hello World' ) %]
-
-You can also call copy() to create a new String as a copy of the
-original.
-
- [% greet2 = greeting.copy %]
-
-The String object has a text() method to return the content of the
-string.
-
- [% greeting.text %]
-
-However, it is sufficient to simply print the string and let the
-overloaded stringification operator call the text() method
-automatically for you.
-
- [% greeting %]
-
-Thus, you can treat String objects pretty much like any regular piece
-of text, interpolating it into other strings, for example:
-
- [% msg = "It printed '$greeting' and then dumped core\n" %]
-
-You also have the benefit of numerous other methods for manipulating
-the string.
-
- [% msg.append("PS Don't eat the yellow snow") %]
-
-Note that all methods operate on and mutate the contents of the string
-itself. If you want to operate on a copy of the string then simply
-take a copy first:
-
- [% msg.copy.append("PS Don't eat the yellow snow") %]
-
-These methods return a reference to the String object itself. This
-allows you to chain multiple methods together.
-
- [% msg.copy.append('foo').right(72) %]
-
-It also means that in the above examples, the String is returned which
-causes the text() method to be called, which results in the new value of
-the string being printed. To suppress printing of the string, you can
-use the CALL directive.
-
- [% foo = String.new('foo') %]
-
- [% foo.append('bar') %] # prints "foobar"
-
- [% CALL foo.append('bar') %] # nothing
-
-=head1 METHODS
-
-=head2 Construction Methods
-
-The following methods are used to create new String objects.
-
-=over 4
-
-=item new()
-
-Creates a new string using an initial value passed as a positional
-argument or the named parameter 'text'.
-
- [% USE String %]
- [% msg = String.new('Hello World') %]
- [% msg = String.new( text => 'Hello World' ) %]
-
-=item copy()
-
-Creates a new String object which contains a copy of the original string.
-
- [% msg2 = msg.copy %]
-
-=back
-
-=head2 Inspection Methods
-
-These methods are used to inspect the string content or other parameters
-relevant to the string.
-
-=over 4
-
-=item text()
-
-Returns the internal text value of the string. The stringification
-operator is overloaded to call this method. Thus the following are
-equivalent:
-
- [% msg.text %]
- [% msg %]
-
-=item length()
-
-Returns the length of the string.
-
- [% USE String("foo") %]
-
- [% String.length %] # => 3
-
-=item search($pattern)
-
-Searches the string for the regular expression specified in $pattern
-returning true if found or false otherwise.
-
- [% item = String.new('foo bar baz wiz waz woz') %]
-
- [% item.search('wiz') ? 'WIZZY! :-)' : 'not wizzy :-(' %]
-
-=item split($pattern, $limit)
-
-Splits the string based on the delimiter $pattern and optional $limit.
-Delegates to Perl's internal split() so the parameters are exactly the same.
-
- [% FOREACH item.split %]
- ...
- [% END %]
-
- [% FOREACH item.split('baz|waz') %]
- ...
- [% END %]
-
-=back
-
-=head2 Mutation Methods
-
-These methods modify the internal value of the string. For example:
-
- [% USE str=String('foobar') %]
-
- [% str.append('.html') %] # str => 'foobar.html'
-
-The value of the String 'str' is now 'foobar.html'. If you don't want
-to modify the string then simply take a copy first.
-
- [% str.copy.append('.html') %]
-
-These methods all return a reference to the String object itself. This
-has two important benefits. The first is that when used as above, the
-String object 'str' returned by the append() method will be stringified
-with a call to its text() method. This will return the newly modified
-string content. In other words, a directive like:
-
- [% str.append('.html') %]
-
-will update the string and also print the new value. If you just want
-to update the string but not print the new value then use CALL.
-
- [% CALL str.append('.html') %]
-
-The other benefit of these methods returning a reference to the String
-is that you can chain as many different method calls together as you
-like. For example:
-
- [% String.append('.html').trim.format(href) %]
-
-Here are the methods:
-
-=over 4
-
-=item push($suffix, ...) / append($suffix, ...)
-
-Appends all arguments to the end of the string. The
-append() method is provided as an alias for push().
-
- [% msg.push('foo', 'bar') %]
- [% msg.append('foo', 'bar') %]
-
-=item pop($suffix)
-
-Removes the suffix passed as an argument from the end of the String.
-
- [% USE String 'foo bar' %]
- [% String.pop(' bar') %] # => 'foo'
-
-=item unshift($prefix, ...) / prepend($prefix, ...)
-
-Prepends all arguments to the beginning of the string. The
-prepend() method is provided as an alias for unshift().
-
- [% msg.unshift('foo ', 'bar ') %]
- [% msg.prepend('foo ', 'bar ') %]
-
-=item shift($prefix)
-
-Removes the prefix passed as an argument from the start of the String.
-
- [% USE String 'foo bar' %]
- [% String.shift('foo ') %] # => 'bar'
-
-=item left($pad)
-
-If the length of the string is less than $pad then the string is left
-formatted and padded with spaces to $pad length.
-
- [% msg.left(20) %]
-
-=item right($pad)
-
-As per left() but right padding the String to a length of $pad.
-
- [% msg.right(20) %]
-
-=item center($pad) / centre($pad)
-
-As per left() and right() but formatting the String to be centered within
-a space padded string of length $pad. The centre() method is provided as
-an alias for center() to keep Yanks and Limeys happy.
-
- [% msg.center(20) %] # American spelling
- [% msg.centre(20) %] # European spelling
-
-=item format($format)
-
-Apply a format in the style of sprintf() to the string.
-
- [% USE String("world") %]
- [% String.format("Hello %s\n") %] # => "Hello World\n"
-
-=item upper()
-
-Converts the string to upper case.
-
- [% USE String("foo") %]
-
- [% String.upper %] # => 'FOO'
-
-=item lower()
-
-Converts the string to lower case
-
- [% USE String("FOO") %]
-
- [% String.lower %] # => 'foo'
-
-=item capital()
-
-Converts the first character of the string to upper case.
-
- [% USE String("foo") %]
-
- [% String.capital %] # => 'Foo'
-
-The remainder of the string is left untouched. To force the string to
-be all lower case with only the first letter capitalised, you can do
-something like this:
-
- [% USE String("FOO") %]
-
- [% String.lower.capital %] # => 'Foo'
-
-=item chop()
-
-Removes the last character from the string.
-
- [% USE String("foop") %]
-
- [% String.chop %] # => 'foo'
-
-=item chomp()
-
-Removes the trailing newline from the string.
-
- [% USE String("foo\n") %]
-
- [% String.chomp %] # => 'foo'
-
-=item trim()
-
-Removes all leading and trailing whitespace from the string
-
- [% USE String(" foo \n\n ") %]
-
- [% String.trim %] # => 'foo'
-
-=item collapse()
-
-Removes all leading and trailing whitespace and collapses any sequences
-of multiple whitespace to a single space.
-
- [% USE String(" \n\r \t foo \n \n bar \n") %]
-
- [% String.collapse %] # => "foo bar"
-
-=item truncate($length, $suffix)
-
-Truncates the string to $length characters.
-
- [% USE String('long string') %]
- [% String.truncate(4) %] # => 'long'
-
-If $suffix is specified then it will be appended to the truncated
-string. In this case, the string will be further shortened by the
-length of the suffix to ensure that the newly constructed string
-complete with suffix is exactly $length characters long.
-
- [% USE msg = String('Hello World') %]
- [% msg.truncate(8, '...') %] # => 'Hello...'
-
-=item replace($search, $replace)
-
-Replaces all occurences of $search in the string with $replace.
-
- [% USE String('foo bar foo baz') %]
- [% String.replace('foo', 'wiz') %] # => 'wiz bar wiz baz'
-
-=item remove($search)
-
-Remove all occurences of $search in the string.
-
- [% USE String('foo bar foo baz') %]
- [% String.remove('foo ') %] # => 'bar baz'
-
-=item repeat($count)
-
-Repeats the string $count times.
-
- [% USE String('foo ') %]
- [% String.repeat(3) %] # => 'foo foo foo '
-
-=back
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.33, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/Table.pm b/lib/Template/Plugin/Table.pm
deleted file mode 100644
index c1fd79a..0000000
--- a/lib/Template/Plugin/Table.pm
+++ /dev/null
@@ -1,464 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::Table
-#
-# DESCRIPTION
-#
-# Plugin to order a linear data set into a virtual 2-dimensional table
-# from which row and column permutations can be fetched.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 2000 Andy Wardley. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Table.pm,v 2.64 2004/01/13 16:20:38 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::Table;
-
-require 5.004;
-
-use strict;
-use vars qw( @ISA $VERSION $AUTOLOAD );
-use base qw( Template::Plugin );
-use Template::Plugin;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.64 $ =~ /(\d+)\.(\d+)/);
-
-
-#------------------------------------------------------------------------
-# new($context, \@data, \%args)
-#
-# This constructor method initialises the object to iterate through
-# the data set passed by reference to a list as the first parameter.
-# It calculates the shape of the permutation table based on the ROWS
-# or COLS parameters specified in the $args hash reference. The
-# OVERLAP parameter may be provided to specify the number of common
-# items that should be shared between subseqent columns.
-#------------------------------------------------------------------------
-
-sub new {
- my ($class, $context, $data, $params) = @_;
- my ($size, $rows, $cols, $coloff, $overlap, $error);
-
- # if the data item is a reference to a Template::Iterator object,
- # or subclass thereof, we call its get_all() method to extract all
- # the data it contains
- if (UNIVERSAL::isa($data, 'Template::Iterator')) {
- ($data, $error) = $data->get_all();
- return $class->error("iterator failed to provide data for table: ",
- $error)
- if $error;
- }
-
- return $class->error('invalid table data, expecting a list')
- unless ref $data eq 'ARRAY';
-
- $params ||= { };
- return $class->error('invalid table parameters, expecting a hash')
- unless ref $params eq 'HASH';
-
- # ensure keys are folded to upper case
- @$params{ map { uc } keys %$params } = values %$params;
-
- $size = scalar @$data;
- $overlap = $params->{ OVERLAP } || 0;
-
- # calculate number of columns based on a specified number of rows
- if ($rows = $params->{ ROWS }) {
- if ($size < $rows) {
- $rows = $size; # pad?
- $cols = 1;
- $coloff = 0;
- }
- else {
- $coloff = $rows - $overlap;
- $cols = int ($size / $coloff)
- + ($size % $coloff > $overlap ? 1 : 0)
- }
- }
- # calculate number of rows based on a specified number of columns
- elsif ($cols = $params->{ COLS }) {
- if ($size < $cols) {
- $cols = $size;
- $rows = 1;
- $coloff = 1;
- }
- else {
- $coloff = int ($size / $cols)
- + ($size % $cols > $overlap ? 1 : 0);
- $rows = $coloff + $overlap;
- }
- }
- else {
- $rows = $size;
- $cols = 1;
- $coloff = 0;
- }
-
- bless {
- _DATA => $data,
- _SIZE => $size,
- _NROWS => $rows,
- _NCOLS => $cols,
- _COLOFF => $coloff,
- _OVERLAP => $overlap,
- _PAD => defined $params->{ PAD } ? $params->{ PAD } : 1,
- }, $class;
-}
-
-
-#------------------------------------------------------------------------
-# row($n)
-#
-# Returns a reference to a list containing the items in the row whose
-# number is specified by parameter. If the row number is undefined,
-# it calls rows() to return a list of all rows.
-#------------------------------------------------------------------------
-
-sub row {
- my ($self, $row) = @_;
- my ($data, $cols, $offset, $size, $pad)
- = @$self{ qw( _DATA _NCOLS _COLOFF _SIZE _PAD) };
- my @set;
-
- # return all rows if row number not specified
- return $self->rows()
- unless defined $row;
-
- return () if $row >= $self->{ _NROWS } || $row < 0;
-
- my $index = $row;
-
- for (my $c = 0; $c < $cols; $c++) {
- push(@set, $index < $size
- ? $data->[$index]
- : ($pad ? undef : ()));
- $index += $offset;
- }
- return \@set;
-}
-
-
-#------------------------------------------------------------------------
-# col($n)
-#
-# Returns a reference to a list containing the items in the column whose
-# number is specified by parameter. If the column number is undefined,
-# it calls cols() to return a list of all columns.
-#------------------------------------------------------------------------
-
-sub col {
- my ($self, $col) = @_;
- my ($data, $size) = @$self{ qw( _DATA _SIZE ) };
- my ($start, $end);
- my $blanks = 0;
-
- # return all cols if row number not specified
- return $self->cols()
- unless defined $col;
-
- return () if $col >= $self->{ _NCOLS } || $col < 0;
-
- $start = $self->{ _COLOFF } * $col;
- $end = $start + $self->{ _NROWS } - 1;
- $end = $start if $end < $start;
- if ($end >= $size) {
- $blanks = ($end - $size) + 1;
- $end = $size - 1;
- }
- return () if $start >= $size;
- return [ @$data[$start..$end],
- $self->{ _PAD } ? ((undef) x $blanks) : () ];
-}
-
-
-#------------------------------------------------------------------------
-# rows()
-#
-# Returns all rows as a reference to a list of rows.
-#------------------------------------------------------------------------
-
-sub rows {
- my $self = shift;
- return [ map { $self->row($_) } (0..$self->{ _NROWS }-1) ];
-}
-
-
-#------------------------------------------------------------------------
-# cols()
-#
-# Returns all rows as a reference to a list of rows.
-#------------------------------------------------------------------------
-
-sub cols {
- my $self = shift;
- return [ map { $self->col($_) } (0..$self->{ _NCOLS }-1) ];
-}
-
-
-#------------------------------------------------------------------------
-# AUTOLOAD
-#
-# Provides read access to various internal data members.
-#------------------------------------------------------------------------
-
-sub AUTOLOAD {
- my $self = shift;
- my $item = $AUTOLOAD;
- $item =~ s/.*:://;
- return if $item eq 'DESTROY';
-
- if ($item =~ /^data|size|nrows|ncols|overlap|pad$/) {
- return $self->{ $item };
- }
- else {
- return (undef, "no such table method: $item");
- }
-}
-
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::Table - Plugin to present data in a table
-
-=head1 SYNOPSIS
-
- [% USE table(list, rows=n, cols=n, overlap=n, pad=0) %]
-
- [% FOREACH item = table.row(n) %]
- [% item %]
- [% END %]
-
- [% FOREACH item = table.col(n) %]
- [% item %]
- [% END %]
-
- [% FOREACH row = table.rows %]
- [% FOREACH item = row %]
- [% item %]
- [% END %]
- [% END %]
-
- [% FOREACH col = table.cols %]
- [% col.first %] - [% col.last %] ([% col.size %] entries)
- [% END %]
-
-=head1 DESCRIPTION
-
-The Table plugin allows you to format a list of data items into a
-virtual table. When you create a Table plugin via the USE directive,
-simply pass a list reference as the first parameter and then specify
-a fixed number of rows or columns.
-
- [% USE Table(list, rows=5) %]
- [% USE table(list, cols=5) %]
-
-The 'Table' plugin name can also be specified in lower case as shown
-in the second example above. You can also specify an alternative variable
-name for the plugin as per regular Template Toolkit syntax.
-
- [% USE mydata = table(list, rows=5) %]
-
-The plugin then presents a table based view on the data set. The data
-isn't actually reorganised in any way but is available via the row(),
-col(), rows() and cols() as if formatted into a simple two dimensional
-table of n rows x n columns. Thus, if our sample 'alphabet' list
-contained the letters 'a' to 'z', the above USE directives would
-create plugins that represented the following views of the alphabet.
-
- [% USE table(alphabet, ... %]
-
- rows=5 cols=5
- a f k p u z a g m s y
- b g l q v b h n t z
- c h m r w c i o u
- d i n s x d j p v
- e j o t y e k q w
- f l r x
-
-We can request a particular row or column using the row() and col()
-methods.
-
- [% USE table(alphabet, rows=5) %]
- [% FOREACH item = table.row(0) %]
- # [% item %] set to each of [ a f k p u z ] in turn
- [% END %]
-
- [% FOREACH item = table.col(2) %]
- # [% item %] set to each of [ m n o p q r ] in turn
- [% END %]
-
-Data in rows is returned from left to right, columns from top to
-bottom. The first row/column is 0. By default, rows or columns that
-contain empty values will be padded with the undefined value to fill
-it to the same size as all other rows or columns. For example, the
-last row (row 4) in the first example would contain the values [ e j o
-t y undef ]. The Template Toolkit will safely accept these undefined
-values and print a empty string. You can also use the IF directive to
-test if the value is set.
-
- [% FOREACH item = table.row(4) %]
- [% IF item %]
- Item: [% item %]
- [% END %]
- [% END %]
-
-You can explicitly disable the 'pad' option when creating the plugin to
-returned shortened rows/columns where the data is empty.
-
- [% USE table(alphabet, cols=5, pad=0) %]
- [% FOREACH item = table.col(4) %]
- # [% item %] set to each of 'y z'
- [% END %]
-
-The rows() method returns all rows/columns in the table as a reference
-to a list of rows (themselves list references). The row() methods
-when called without any arguments calls rows() to return all rows in
-the table.
-
-Ditto for cols() and col().
-
- [% USE table(alphabet, cols=5) %]
- [% FOREACH row = table.rows %]
- [% FOREACH item = row %]
- [% item %]
- [% END %]
- [% END %]
-
-The Template Toolkit provides the first(), last() and size() methods
-that can be called on list references to return the first/last entry
-or the number of entried. The following example shows how we might
-use this to provide an alphabetical index split into 3 even parts.
-
- [% USE table(alphabet, cols=3, pad=0) %]
- [% FOREACH group = table.col %]
- [ [% group.first %] - [% group.last %] ([% group.size %] letters) ]
- [% END %]
-
-This produces the following output:
-
- [ a - i (9 letters) ]
- [ j - r (9 letters) ]
- [ s - z (8 letters) ]
-
-We can also use the general purpose join() list method which joins
-the items of the list using the connecting string specified.
-
- [% USE table(alphabet, cols=5) %]
- [% FOREACH row = table.rows %]
- [% row.join(' - ') %]
- [% END %]
-
-Data in the table is ordered downwards rather than across but can easily
-be transformed on output. For example, to format our data in 5 columns
-with data ordered across rather than down, we specify 'rows=5' to order
-the data as such:
-
- a f . .
- b g .
- c h
- d i
- e j
-
-and then iterate down through each column (a-e, f-j, etc.) printing
-the data across.
-
- a b c d e
- f g h i j
- . .
- .
-
-Example code to do so would be much like the following:
-
- [% USE table(alphabet, rows=3) %]
- [% FOREACH cols = table.cols %]
- [% FOREACH item = cols %]
- [% item %]
- [% END %]
- [% END %]
-
- a b c
- d e f
- g h i
- j . .
- .
-
-In addition to a list reference, the Table plugin constructor may be
-passed a reference to a Template::Iterator object or subclass thereof.
-The get_all() method is first called on the iterator to return all
-remaining items. These are then available via the usual Table interface.
-
- [% USE DBI(dsn,user,pass) -%]
-
- # query() returns an iterator
- [% results = DBI.query('SELECT * FROM alphabet ORDER BY letter') %]
-
- # pass into Table plugin
- [% USE table(results, rows=8 overlap=1 pad=0) -%]
-
- [% FOREACH row = table.cols -%]
- [% row.first.letter %] - [% row.last.letter %]:
- [% row.join(', ') %]
- [% END %]
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.64, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/URL.pm b/lib/Template/Plugin/URL.pm
deleted file mode 100644
index c2246b7..0000000
--- a/lib/Template/Plugin/URL.pm
+++ /dev/null
@@ -1,236 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::URL
-#
-# DESCRIPTION
-#
-# Template Toolkit Plugin for constructing URL's from a base stem
-# and adaptable parameters.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 2000 Andy Wardley. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: URL.pm,v 2.64 2004/01/13 16:20:39 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::URL;
-
-require 5.004;
-
-use strict;
-use vars qw( @ISA $VERSION );
-use Template::Plugin;
-
-@ISA = qw( Template::Plugin );
-$VERSION = sprintf("%d.%02d", q$Revision: 2.64 $ =~ /(\d+)\.(\d+)/);
-
-
-#------------------------------------------------------------------------
-# new($context, $baseurl, \%url_params)
-#
-# Constructor method which returns a sub-routine closure for constructing
-# complex URL's from a base part and hash of additional parameters.
-#------------------------------------------------------------------------
-
-sub new {
- my ($class, $context, $base, $args) = @_;
- $args ||= { };
-
- return sub {
- my $newbase = shift unless ref $_[0] eq 'HASH';
- my $newargs = shift || { };
- my $combo = { %$args, %$newargs };
- my $urlargs = join('&amp;',
-# map { "$_=" . escape($combo->{ $_ }) }
- map { args($_, $combo->{ $_ }) }
- grep { defined $combo->{ $_ } }
- sort keys %$combo);
-
- my $query = $newbase || $base || '';
- $query .= '?' if length $query && length $urlargs;
- $query .= $urlargs if length $urlargs;
-
- return $query
- }
-}
-
-
-sub args {
- my ($key, $val) = @_;
- $key = escape($key);
- return map {
- "$key=" . escape($_);
- } ref $val eq 'ARRAY' ? @$val : $val;
-
-}
-
-#------------------------------------------------------------------------
-# escape($url)
-#
-# URL-encode data. Borrowed with minor modifications from CGI.pm.
-# Kudos to Lincold Stein.
-#------------------------------------------------------------------------
-
-sub escape {
- my $toencode = shift;
- return undef unless defined($toencode);
- $toencode=~s/([^a-zA-Z0-9_.-])/uc sprintf("%%%02x",ord($1))/eg;
- return $toencode;
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::URL - Plugin to construct complex URLs
-
-=head1 SYNOPSIS
-
- [% USE url('/cgi-bin/foo.pl') %]
-
- [% url(debug = 1, id = 123) %]
- # ==> /cgi/bin/foo.pl?debug=1&amp;id=123
-
-
- [% USE mycgi = url('/cgi-bin/bar.pl', mode='browse', debug=1) %]
-
- [% mycgi %]
- # ==> /cgi/bin/bar.pl?mode=browse&amp;debug=1
-
- [% mycgi(mode='submit') %]
- # ==> /cgi/bin/bar.pl?mode=submit&amp;debug=1
-
- [% mycgi(debug='d2 p0', id='D4-2k[4]') %]
- # ==> /cgi-bin/bar.pl?mode=browse&amp;debug=d2%20p0&amp;id=D4-2k%5B4%5D
-
-
-=head1 DESCRIPTION
-
-The URL plugin can be used to construct complex URLs from a base stem
-and a hash array of additional query parameters.
-
-The constructor should be passed a base URL and optionally, a hash array
-reference of default parameters and values. Used from with a Template
-Documents, this would look something like the following:
-
- [% USE url('http://www.somewhere.com/cgi-bin/foo.pl') %]
- [% USE url('/cgi-bin/bar.pl', mode='browse') %]
- [% USE url('/cgi-bin/baz.pl', mode='browse', debug=1) %]
-
-When the plugin is then called without any arguments, the default base
-and parameters are returned as a formatted query string.
-
- [% url %]
-
-For the above three examples, these will produce the following outputs:
-
- http://www.somewhere.com/cgi-bin/foo.pl
- /cgi-bin/bar.pl?mode=browse
- /cgi-bin/baz.pl?mode=browse&amp;debug=1
-
-Additional parameters may be also be specified:
-
- [% url(mode='submit', id='wiz') %]
-
-Which, for the same three examples, produces:
-
- http://www.somewhere.com/cgi-bin/foo.pl?mode=submit&amp;id=wiz
- /cgi-bin/bar.pl?mode=browse&amp;id=wiz
- /cgi-bin/baz.pl?mode=browse&amp;debug=1&amp;id=wiz
-
-A new base URL may also be specified as the first option:
-
- [% url('/cgi-bin/waz.pl', test=1) %]
-
-producing
-
- /cgi-bin/waz.pl?test=1
- /cgi-bin/waz.pl?mode=browse&amp;test=1
- /cgi-bin/waz.pl?mode=browse&amp;debug=1&amp;test=1
-
-
-The ordering of the parameters is non-deterministic due to fact that
-Perl's hashes themselves are unordered. This isn't a problem as the
-ordering of CGI parameters is insignificant (to the best of my knowledge).
-All values will be properly escaped thanks to some code borrowed from
-Lincoln Stein's CGI.pm. e.g.
-
- [% USE url('/cgi-bin/woz.pl') %]
- [% url(name="Elrich von Benjy d'Weiro") %]
-
-Here the spaces and "'" character are escaped in the output:
-
- /cgi-bin/woz.pl?name=Elrich%20von%20Benjy%20d%27Weiro
-
-Alternate name may be provided for the plugin at construction time
-as per regular Template Toolkit syntax.
-
- [% USE mycgi = url('cgi-bin/min.pl') %]
-
- [% mycgi(debug=1) %]
-
-Note that in the following line, additional parameters are seperated
-by '&amp;', while common usage on the Web is to just use '&'. '&amp;'
-is actually the Right Way to do it. See this URL for more information:
-http://ppewww.ph.gla.ac.uk/~flavell/www/formgetbyurl.html
-
- /cgi-bin/waz.pl?mode=browse&amp;debug=1&amp;test=1
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.64, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/View.pm b/lib/Template/Plugin/View.pm
deleted file mode 100644
index c22ba16..0000000
--- a/lib/Template/Plugin/View.pm
+++ /dev/null
@@ -1,127 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::View
-#
-# DESCRIPTION
-# A user-definable view based on templates. Similar to the concept of
-# a "Skin".
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 2000 Andy Wardley. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-# REVISION
-# $Id: View.pm,v 2.63 2004/01/13 16:20:39 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::View;
-
-require 5.004;
-
-use strict;
-use Template::Plugin;
-use vars qw( $VERSION );
-use base qw( Template::Plugin );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.63 $ =~ /(\d+)\.(\d+)/);
-
-use Template::View;
-
-#------------------------------------------------------------------------
-# new($context, \%config)
-#------------------------------------------------------------------------
-
-sub new {
- my $class = shift;
- my $context = shift;
- my $view = Template::View->new($context, @_)
- || return $class->error($Template::View::ERROR);
- $view->seal();
- return $view;
-}
-
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::View - Plugin to create views (Template::View)
-
-=head1 SYNOPSIS
-
- [% USE view(
- prefix = 'splash/' # template prefix/suffix
- suffix = '.tt2'
- bgcol = '#ffffff' # and any other variables you
- style = 'Fancy HTML' # care to define as view metadata,
- items = [ foo, bar.baz ] # including complex data and
- foo = bar ? baz : x.y.z # expressions
- %]
-
- [% view.title %] # access view metadata
-
- [% view.header(title = 'Foo!') %] # view "methods" process blocks or
- [% view.footer %] # templates with prefix/suffix added
-
-=head1 DESCRIPTION
-
-This plugin module creates Template::View objects. Views are an
-experimental feature and are subject to change in the near future.
-In the mean time, please consult L<Template::View> for further info.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.63, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Template::View|Template::View>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/Wrap.pm b/lib/Template/Plugin/Wrap.pm
deleted file mode 100644
index 96c600a..0000000
--- a/lib/Template/Plugin/Wrap.pm
+++ /dev/null
@@ -1,162 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::Wrap
-#
-# DESCRIPTION
-# Plugin for wrapping text via the Text::Wrap module.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Wrap.pm,v 2.63 2004/01/13 16:20:40 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::Wrap;
-
-require 5.004;
-
-use strict;
-use vars qw( @ISA $VERSION );
-use base qw( Template::Plugin );
-use Template::Plugin;
-use Text::Wrap;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.63 $ =~ /(\d+)\.(\d+)/);
-
-sub new {
- my ($class, $context, $format) = @_;;
- $context->define_filter('wrap', [ \&wrap_filter_factory => 1 ]);
- return \&tt_wrap;
-}
-
-sub tt_wrap {
- my $text = shift;
- my $width = shift || 72;
- my $itab = shift;
- my $ntab = shift;
- $itab = '' unless defined $itab;
- $ntab = '' unless defined $ntab;
- $Text::Wrap::columns = $width;
- Text::Wrap::wrap($itab, $ntab, $text);
-}
-
-sub wrap_filter_factory {
- my ($context, @args) = @_;
- return sub {
- my $text = shift;
- tt_wrap($text, @args);
- }
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::Wrap - Plugin interface to Text::Wrap
-
-=head1 SYNOPSIS
-
- [% USE wrap %]
-
- # call wrap subroutine
- [% wrap(mytext, width, initial_tab, subsequent_tab) %]
-
- # or use wrap FILTER
- [% mytext FILTER wrap(width, initital_tab, subsequent_tab) %]
-
-=head1 DESCRIPTION
-
-This plugin provides an interface to the Text::Wrap module which
-provides simple paragraph formatting.
-
-It defines a 'wrap' subroutine which can be called, passing the input
-text and further optional parameters to specify the page width (default:
-72), and tab characters for the first and subsequent lines (no defaults).
-
- [% USE wrap %]
-
- [% text = BLOCK %]
- First, attach the transmutex multiplier to the cross-wired
- quantum homogeniser.
- [% END %]
-
- [% wrap(text, 40, '* ', ' ') %]
-
-Output:
-
- * First, attach the transmutex
- multiplier to the cross-wired quantum
- homogeniser.
-
-It also registers a 'wrap' filter which accepts the same three optional
-arguments but takes the input text directly via the filter input.
-
- [% FILTER bullet = wrap(40, '* ', ' ') -%]
- First, attach the transmutex multiplier to the cross-wired quantum
- homogeniser.
- [%- END %]
-
- [% FILTER bullet -%]
- Then remodulate the shield to match the harmonic frequency, taking
- care to correct the phase difference.
- [% END %]
-
-Output:
-
- * First, attach the transmutex
- multiplier to the cross-wired quantum
- homogeniser.
-
- * Then remodulate the shield to match
- the harmonic frequency, taking
- care to correct the phase difference.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@wardley.orgE<gt>
-
-The Text::Wrap module was written by David Muir Sharnoff
-E<lt>muir@idiom.comE<gt> with help from Tim Pierce and many
-others.
-
-=head1 VERSION
-
-2.63, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<Text::Wrap|Text::Wrap>
-
diff --git a/lib/Template/Plugin/XML/DOM.pm b/lib/Template/Plugin/XML/DOM.pm
deleted file mode 100644
index 30bac3b..0000000
--- a/lib/Template/Plugin/XML/DOM.pm
+++ /dev/null
@@ -1,841 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::XML::DOM
-#
-# DESCRIPTION
-#
-# Simple Template Toolkit plugin interfacing to the XML::DOM.pm module.
-#
-# AUTHORS
-# Andy Wardley <abw@kfs.org>
-# Simon Matthews <sam@knowledgepool.com>
-#
-# COPYRIGHT
-# Copyright (C) 2000 Andy Wardley, Simon Matthews. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: DOM.pm,v 2.54 2004/01/13 16:21:50 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::XML::DOM;
-
-require 5.004;
-
-use strict;
-use Template::Plugin;
-use XML::DOM;
-
-use base qw( Template::Plugin );
-use vars qw( $VERSION $DEBUG );
-
-$VERSION = 2.6;
-$DEBUG = 0 unless defined $DEBUG;
-
-
-#------------------------------------------------------------------------
-# new($context, \%config)
-#
-# Constructor method for XML::DOM plugin. Creates an XML::DOM::Parser
-# object and initialise plugin configuration.
-#------------------------------------------------------------------------
-
-sub new {
- my $class = shift;
- my $context = shift;
- my $args = ref $_[-1] eq 'HASH' ? pop(@_) : { };
-
- my $parser ||= XML::DOM::Parser->new(%$args)
- || return $class->_throw("failed to create XML::DOM::Parser\n");
-
- # we've had to deprecate the old usage because it broke things big time
- # with DOM trees never getting cleaned up.
- return $class->_throw("XML::DOM usage has changed - you must now call parse()\n")
- if @_;
-
- bless {
- _PARSER => $parser,
- _DOCS => [ ],
- _CONTEXT => $context,
- _PREFIX => $args->{ prefix } || '',
- _SUFFIX => $args->{ suffix } || '',
- _DEFAULT => $args->{ default } || '',
- _VERBOSE => $args->{ verbose } || 0,
- _NOSPACE => $args->{ nospace } || 0,
- _DEEP => $args->{ deep } || 0,
- }, $class;
-}
-
-
-#------------------------------------------------------------------------
-# parse($content, \%named_params)
-#
-# Parses an XML stream, provided as the first positional argument (assumed
-# to be a filename unless it contains a '<' character) or specified in
-# the named parameter hash as one of 'text', 'xml' (same as text), 'file'
-# or 'filename'.
-#------------------------------------------------------------------------
-
-sub parse {
- my $self = shift;
- my $args = ref $_[-1] eq 'HASH' ? pop(@_) : { };
- my $parser = $self->{ _PARSER };
- my ($content, $about, $method, $doc);
-
- # determine the input source from a positional parameter (may be a
- # filename or XML text if it contains a '<' character) or by using
- # named parameters which may specify one of 'file', 'filename', 'text'
- # or 'xml'
-
- if ($content = shift) {
- if ($content =~ /\</) {
- $about = 'xml text';
- $method = 'parse';
- }
- else {
- $about = "xml file $content";
- $method = 'parsefile';
- }
- }
- elsif ($content = $args->{ text } || $args->{ xml }) {
- $about = 'xml text';
- $method = 'parse';
- }
- elsif ($content = $args->{ file } || $args->{ filename }) {
- $about = "xml file $content";
- $method = 'parsefile';
- }
- else {
- return $self->_throw('no filename or xml text specified');
- }
-
- # parse the input source using the appropriate method determined above
- eval { $doc = $parser->$method($content) } and not $@
- or return $self->_throw("failed to parse $about: $@");
-
- # update XML::DOM::Document _UserData to contain config details
- $doc->[ XML::DOM::Node::_UserData ] = {
- map { ( $_ => $self->{ $_ } ) }
- qw( _CONTEXT _PREFIX _SUFFIX _VERBOSE _NOSPACE _DEEP _DEFAULT ),
- };
-
- # keep track of all DOM docs for subsequent dispose()
-# print STDERR "DEBUG: $self adding doc: $doc\n"
-# if $DEBUG;
-
- push(@{ $self->{ _DOCS } }, $doc);
-
- return $doc;
-}
-
-
-#------------------------------------------------------------------------
-# _throw($errmsg)
-#
-# Raised a Template::Exception of type XML.DOM via die().
-#------------------------------------------------------------------------
-
-sub _throw {
- my ($self, $error) = @_;
- die (Template::Exception->new('XML.DOM', $error));
-}
-
-
-#------------------------------------------------------------------------
-# DESTROY
-#
-# Cleanup method which calls dispose() on any and all DOM documents
-# created by this object. Also breaks any circular references that
-# may exist with the context object.
-#------------------------------------------------------------------------
-
-sub DESTROY {
- my $self = shift;
-
- # call dispose() on each document produced by this parser
- foreach my $doc (@{ $self->{ _DOCS } }) {
-# print STDERR "DEBUG: $self destroying $doc\n"
-# if $DEBUG;
- if (ref $doc) {
-# print STDERR "disposing of $doc\n";
- undef $doc->[ XML::DOM::Node::_UserData ]->{ _CONTEXT };
- $doc->dispose();
- }
- }
- delete $self->{ _CONTEXT };
- delete $self->{ _PARSER };
-}
-
-
-
-#========================================================================
-package XML::DOM::Node;
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# present($view)
-#
-# Method to present node via a view (supercedes all that messy toTemplate
-# stuff below).
-#------------------------------------------------------------------------
-
-sub present {
- my ($self, $view) = @_;
-
- if ($self->getNodeType() == XML::DOM::ELEMENT_NODE) {
- # it's an element
- $view->view($self->getTagName(), $self);
- }
- else {
- my $text = $self->toString();
- $view->view('text', $text);
- }
-}
-
-sub content {
- my ($self, $view) = @_;
- my $output = '';
- foreach my $node (@{ $self->getChildNodes }) {
- $output .= $node->present($view);
-
-# abw test passing args, Aug 2001
-# $output .= $view->print($node);
- }
- return $output;
-}
-
-
-#------------------------------------------------------------------------
-# toTemplate($prefix, $suffix, \%named_params)
-#
-# Process the current node as a template.
-#------------------------------------------------------------------------
-
-sub toTemplate {
- my $self = shift;
- _template_node($self, $self->_args(@_));
-}
-
-
-#------------------------------------------------------------------------
-# childrenToTemplate($prefix, $suffix, \%named_params)
-#
-# Process all the current node's children as templates.
-#------------------------------------------------------------------------
-
-sub childrenToTemplate {
- my $self = shift;
- _template_kids($self, $self->_args(@_));
-}
-
-
-#------------------------------------------------------------------------
-# allChildrenToTemplate($prefix, $suffix, \%named_params)
-#
-# Process all the current node's children, and their children, and
-# their children, etc., etc., as templates. Same effect as calling the
-# childrenToTemplate() method with the 'deep' option set.
-#------------------------------------------------------------------------
-
-sub allChildrenToTemplate {
- my $self = shift;
- my $args = $self->_args(@_);
- $args->{ deep } = 1;
- _template_kids($self, $args);
-}
-
-
-#------------------------------------------------------------------------
-# _args($prefix, $suffix, \%name_params)
-#
-# Reads the optional positional parameters, $prefix and $suffix, and
-# also examines any named parameters hash to construct a set of
-# current configuration parameters. Where not specified directly, the
-# object defaults are used.
-#------------------------------------------------------------------------
-
-sub _args {
- my $self = shift;
- my $args = ref $_[-1] eq 'HASH' ? pop(@_) : { };
- my $doc = $self->getOwnerDocument() || $self;
- my $data = $doc->[ XML::DOM::Node::_UserData ];
-
- return {
- prefix => @_ ? shift : $args->{ prefix } || $data->{ _PREFIX },
- suffix => @_ ? shift : $args->{ suffix } || $data->{ _SUFFIX },
- verbose => $args->{ verbose } || $data->{ _VERBOSE },
- nospace => $args->{ nospace } || $data->{ _NOSPACE },
- deep => $args->{ deep } || $data->{ _DEEP },
- default => $args->{ default } || $data->{ _DEFAULT },
- context => $data->{ _CONTEXT },
- };
-}
-
-
-
-#------------------------------------------------------------------------
-# _template_node($node, $args, $vars)
-#
-# Process a template for the current DOM node where the template name
-# is taken from the node TagName, with any specified 'prefix' and/or
-# 'suffix' applied. The 'default' argument can also be provided to
-# specify a default template to be used when a specific template can't
-# be found. The $args parameter referenced a hash array through which
-# these configuration items are passed (see _args()). The current DOM
-# node is made available to the template as the variable 'node', along
-# with any other variables passed in the optional $vars hash reference.
-# To permit the 'children' and 'prune' callbacks to be raised as node
-# methods (see _template_kids() below), these items, if defined in the
-# $vars hash, are copied into the node object where its AUTOLOAD method
-# can find them.
-#------------------------------------------------------------------------
-
-sub _template_node {
- my $node = shift || die "no XML::DOM::Node reference\n";
- my $args = shift || die "no XML::DOM args passed to _template_node\n";
- my $vars = shift || { };
- my $context = $args->{ context } || die "no context in XML::DOM args\n";
- my $template;
- my $output = '';
-
- # if this is not an element then it is text so output it
- unless ($node->getNodeType() == XML::DOM::ELEMENT_NODE ) {
- if ($args->{ verbose }) {
- $output = $node->toString();
- $output =~ s/\s+$// if $args->{ nospace };
- }
- }
- else {
- my $element = ( $args->{ prefix } || '' )
- . $node->getTagName()
- . ( $args->{ suffix } || '' );
-
- # locate a template by name built from prefix, tagname and suffix
- # or fall back on any default template specified
- eval { $template = $context->template($element) };
- eval { $template = $context->template($args->{ default }) }
- if $@ && $args->{ default };
- $template = $element unless $template;
-
- # copy 'children' and 'prune' callbacks into node object (see AUTOLOAD)
- my $doc = $node->getOwnerDocument() || $node;
- my $data = $doc->[ XML::DOM::Node::_UserData ];
-
- $data->{ _TT_CHILDREN } = $vars->{ children };
- $data->{ _TT_PRUNE } = $vars->{ prune };
-
- # add node reference to existing vars hash
- $vars->{ node } = $node;
-
- $output = $context->include($template, $vars);
-
- # break any circular references
- delete $vars->{ node };
- delete $data->{ _TT_CHILDREN };
- delete $data->{ _TT_PRUNE };
- }
-
- return $output;
-}
-
-
-#------------------------------------------------------------------------
-# _template_kids($node, $args)
-#
-# Process all the children of the current node as templates, via calls
-# to _template_node(). If the 'deep' argument is set, then the process
-# will continue recursively. In this case, the node template is first
-# processed, followed by any children of that node (i.e. depth first,
-# parent before). A closure called 'children' is created and added
-# to the Stash variables passed to _template_node(). This can be called
-# from the parent template to process all child nodes at the current point.
-# This then "prunes" the tree preventing the children from being processed
-# after the parent template. A 'prune' callback is also added to prune
-# the tree without processing the children. Note that _template_node()
-# copies these callbacks into each parent node, allowing them to be called
-# as [% node.
-#------------------------------------------------------------------------
-
-sub _template_kids {
- my $node = shift || die "no XML::DOM::Node reference\n";
- my $args = shift || die "no XML::DOM args passed to _template_kids\n";
- my $context = $args->{ context } || die "no context in XML::DOM args\n";
- my $output = '';
-
- foreach my $kid ( $node->getChildNodes() ) {
- # define some callbacks to allow template to call [% content %]
- # or [% prune %]. They are also inserted into each node reference
- # so they can be called as [% node.content %] and [% node.prune %]
- my $prune = 0;
- my $vars = { };
- $vars->{ children } = sub {
- $prune = 1;
- _template_kids($kid, $args);
- };
- $vars->{ prune } = sub {
- $prune = 1;
- return '';
- };
-
- $output .= _template_node($kid, $args, $vars);
- $output .= _template_kids($kid, $args)
- if $args->{ deep } && ! $prune;
- }
- return $output;
-}
-
-
-#========================================================================
-package XML::DOM::Element;
-#========================================================================
-
-use vars qw( $AUTOLOAD );
-
-sub AUTOLOAD {
- my $self = shift;
- my $method = $AUTOLOAD;
- my $attrib;
-
- $method =~ s/.*:://;
- return if $method eq 'DESTROY';
-
- my $doc = $self->getOwnerDocument() || $self;
- my $data = $doc->[ XML::DOM::Node::_UserData ];
-
- # call 'content' or 'prune' callbacks, if defined (see _template_node())
- return &$attrib()
- if ($method =~ /^children|prune$/)
- && defined($attrib = $data->{ "_TT_\U$method" })
- && ref $attrib eq 'CODE';
-
- return $attrib
- if defined ($attrib = $self->getAttribute($method));
-
- return '';
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::XML::DOM - Plugin interface to XML::DOM
-
-=head1 SYNOPSIS
-
- # load plugin
- [% USE dom = XML.DOM %]
-
- # also provide XML::Parser options
- [% USE dom = XML.DOM(ProtocolEncoding =E<gt> 'ISO-8859-1') %]
-
- # parse an XML file
- [% doc = dom.parse(filename) %]
- [% doc = dom.parse(file => filename) %]
-
- # parse XML text
- [% doc = dom.parse(xmltext) %]
- [% doc = dom.parse(text => xmltext) %]
-
- # call any XML::DOM methods on document/element nodes
- [% FOREACH node = doc.getElementsByTagName('report') %]
- * [% node.getAttribute('title') %] # or just '[% node.title %]'
- [% END %]
-
- # define VIEW to present node(s)
- [% VIEW report notfound='xmlstring' %]
- # handler block for a <report>...</report> element
- [% BLOCK report %]
- [% item.content(view) %]
- [% END %]
-
- # handler block for a <section title="...">...</section> element
- [% BLOCK section %]
- <h1>[% item.title %]</h1>
- [% item.content(view) %]
- [% END %]
-
- # default template block converts item to string representation
- [% BLOCK xmlstring; item.toString; END %]
-
- # block to generate simple text
- [% BLOCK text; item; END %]
- [% END %]
-
- # now present node (and children) via view
- [% report.print(node) %]
-
- # or print node content via view
- [% node.content(report) %]
-
- # following methods are soon to be deprecated in favour of views
- [% node.toTemplate %]
- [% node.childrenToTemplate %]
- [% node.allChildrenToTemplate %]
-
-=head1 PRE-REQUISITES
-
-This plugin requires that the XML::Parser (2.19 or later) and XML::DOM
-(1.27 or later) modules be installed. These are available from CPAN:
-
- http://www.cpan.org/modules/by-module/XML
-
-Note that the XML::DOM module is now distributed as part of the
-'libxml-enno' bundle.
-
-=head1 DESCRIPTION
-
-This is a Template Toolkit plugin interfacing to the XML::DOM module.
-The plugin loads the XML::DOM module and creates an XML::DOM::Parser
-object which is stored internally. The parse() method can then be
-called on the plugin to parse an XML stream into a DOM document.
-
- [% USE dom = XML.DOM %]
- [% doc = dom.parse('/tmp/myxmlfile') %]
-
-NOTE: earlier versions of this XML::DOM plugin expected a filename to
-be passed as an argument to the constructor. This is no longer
-supported due to the fact that it caused a serious memory leak. We
-apologise for the inconvenience but must insist that you change your
-templates as shown:
-
- # OLD STYLE: now fails with a warning
- [% USE dom = XML.DOM('tmp/myxmlfile') %]
-
- # NEW STYLE: do this instead
- [% USE dom = XML.DOM %]
- [% doc = dom.parse('tmp/myxmlfile') %]
-
-The root of the problem lies in XML::DOM creating massive circular
-references in the object models it constructs. The dispose() method
-must be called on each document to release the memory that it would
-otherwise hold indefinately. The XML::DOM plugin object (i.e. 'dom'
-in these examples) acts as a sentinel for the documents it creates
-('doc' and any others). When the plugin object goes out of scope at
-the end of the current template, it will automatically call dispose()
-on any documents that it has created. Note that if you dispose of the
-the plugin object before the end of the block (i.e. by assigning a
-new value to the 'dom' variable) then the documents will also be
-disposed at that point and should not be used thereafter.
-
- [% USE dom = XML.DOM %]
- [% doc = dom.parse('/tmp/myfile') %]
- [% dom = 'new value' %] # releases XML.DOM plugin and calls
- # dispose() on 'doc', so don't use it!
-
-Any template processing parameters (see toTemplate() method and
-friends, below) can be specified with the constructor and will be used
-to define defaults for the object.
-
- [% USE dom = XML.DOM(prefix => 'theme1/') %]
-
-The plugin constructor will also accept configuration options destined
-for the XML::Parser object:
-
- [% USE dom = XML.DOM(ProtocolEncoding => 'ISO-8859-1') %]
-
-=head1 METHODS
-
-=head2 parse()
-
-The parse() method accepts a positional parameter which contains a filename
-or XML string. It is assumed to be a filename unless it contains a E<lt>
-character.
-
- [% xmlfile = '/tmp/foo.xml' %]
- [% doc = dom.parse(xmlfile) %]
-
- [% xmltext = BLOCK %]
- <xml>
- <blah><etc/></blah>
- ...
- </xml>
- [% END %]
- [% doc = dom.parse(xmltext) %]
-
-The named parameters 'file' (or 'filename') and 'text' (or 'xml') can also
-be used:
-
- [% doc = dom.parse(file = xmlfile) %]
- [% doc = dom.parse(text = xmltext) %]
-
-The parse() method returns an instance of the XML::DOM::Document object
-representing the parsed document in DOM form. You can then call any
-XML::DOM methods on the document node and other nodes that its methods
-may return. See L<XML::DOM> for full details.
-
- [% FOREACH node = doc.getElementsByTagName('CODEBASE') %]
- * [% node.getAttribute('href') %]
- [% END %]
-
-This plugin also provides an AUTOLOAD method for XML::DOM::Node which
-calls getAttribute() for any undefined methods. Thus, you can use the
-short form of
-
- [% node.attrib %]
-
-in place of
-
- [% node.getAttribute('attrib') %]
-
-=head2 toTemplate()
-
-B<NOTE: This method will soon be deprecated in favour of the VIEW based
-approach desribed below.>
-
-This method will process a template for the current node on which it is
-called. The template name is constructed from the node TagName with any
-optional 'prefix' and/or 'suffix' options applied. A 'default' template
-can be named to be used when the specific template cannot be found. The
-node object is available to the template as the 'node' variable.
-
-Thus, for this XML fragment:
-
- <page title="Hello World!">
- ...
- </page>
-
-and this template definition:
-
- [% BLOCK page %]
- Page: [% node.title %]
- [% END %]
-
-the output of calling toTemplate() on the E<lt>pageE<gt> node would be:
-
- Page: Hello World!
-
-=head2 childrenToTemplate()
-
-B<NOTE: This method will soon be deprecated in favour of the VIEW based
-approach desribed below.>
-
-Effectively calls toTemplate() for the current node and then for each of
-the node's children. By default, the parent template is processed first,
-followed by each of the children. The 'children' closure can be called
-from within the parent template to have them processed and output
-at that point. This then suppresses the children from being processed
-after the parent template.
-
-Thus, for this XML fragment:
-
- <foo>
- <bar id="1"/>
- <bar id="2"/>
- </foo>
-
-and these template definitions:
-
- [% BLOCK foo %]
- start of foo
- end of foo
- [% END %]
-
- [% BLOCK bar %]
- bar [% node.id %]
- [% END %]
-
-the output of calling childrenToTemplate() on the parent E<lt>fooE<gt> node
-would be:
-
- start of foo
- end of foo
- bar 1
- bar 2
-
-Adding a call to [% children %] in the 'foo' template:
-
- [% BLOCK foo %]
- start of foo
- [% children %]
- end of foo
- [% END %]
-
-then creates output as:
-
- start of foo
- bar 1
- bar 2
- end of foo
-
-The 'children' closure can also be called as a method of the node, if you
-prefer:
-
- [% BLOCK foo %]
- start of foo
- [% node.children %]
- end of foo
- [% END %]
-
-The 'prune' closure is also defined and can be called as [% prune %] or
-[% node.prune %]. It prunes the currrent node, preventing any descendants
-from being further processed.
-
- [% BLOCK anynode %]
- [% node.toString; node.prune %]
- [% END %]
-
-=head2 allChildrenToTemplate()
-
-B<NOTE: This method will soon be deprecated in favour of the VIEW based
-approach desribed below.>
-
-Similar to childrenToTemplate() but processing all descendants (i.e. children
-of children and so on) recursively. This is identical to calling the
-childrenToTemplate() method with the 'deep' flag set to any true value.
-
-=head1 PRESENTING DOM NODES USING VIEWS
-
-You can define a VIEW to present all or part of a DOM tree by automatically
-mapping elements onto templates. Consider a source document like the
-following:
-
- <report>
- <section title="Introduction">
- <p>
- Blah blah.
- <ul>
- <li>Item 1</li>
- <li>item 2</li>
- </ul>
- </p>
- </section>
- <section title="The Gory Details">
- ...
- </section>
- </report>
-
-We can load it up via the XML::DOM plugin and fetch the node for the
-E<lt>reportE<gt> element.
-
- [% USE dom = XML.DOM;
- doc = dom.parse(file => filename);
- report = doc.getElementsByTagName('report')
- %]
-
-We can then define a VIEW as follows to present this document fragment in
-a particular way. The L<Template::Manual::Views> documentation
-contains further details on the VIEW directive and various configuration
-options it supports.
-
- [% VIEW report_view notfound='xmlstring' %]
- # handler block for a <report>...</report> element
- [% BLOCK report %]
- [% item.content(view) %]
- [% END %]
-
- # handler block for a <section title="...">...</section> element
- [% BLOCK section %]
- <h1>[% item.title %]</h1>
- [% item.content(view) %]
- [% END %]
-
- # default template block converts item to string representation
- [% BLOCK xmlstring; item.toString; END %]
-
- # block to generate simple text
- [% BLOCK text; item; END %]
- [% END %]
-
-Each BLOCK defined within the VIEW represents a presentation style for
-a particular element or elements. The current node is available via the
-'item' variable. Elements that contain other content can generate it
-according to the current view by calling [% item.content(view) %].
-Elements that don't have a specific template defined are mapped to the
-'xmlstring' template via the 'notfound' parameter specified in the VIEW
-header. This replicates the node as an XML string, effectively allowing
-general XML/XHTML markup to be passed through unmodified.
-
-To present the report node via the view, we simply call:
-
- [% report_view.print(report) %]
-
-The output from the above example would look something like this:
-
- <h1>Introduction</h1>
- <p>
- Blah blah.
- <ul>
- <li>Item 1</li>
- <li>item 2</li>
- </ul>
- </p>
-
- <h1>The Gory Details</h1>
- ...
-
-To print just the content of the report node (i.e. don't process the
-'report' template for the report node), you can call:
-
- [% report.content(report_view) %]
-
-=head1 AUTHORS
-
-This plugin module was written by Andy Wardley E<lt>abw@wardley.orgE<gt>
-and Simon Matthews E<lt>sam@knowledgepool.comE<gt>.
-
-The XML::DOM module is by Enno Derksen E<lt>enno@att.comE<gt> and Clark
-Cooper E<lt>coopercl@sch.ge.comE<gt>. It extends the the XML::Parser
-module, also by Clark Cooper which itself is built on James Clark's expat
-library.
-
-=head1 VERSION
-
-2.6, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-
-
-=head1 HISTORY
-
-Version 2.5 : updated for use with version 1.27 of the XML::DOM module.
-
-=over 4
-
-=item *
-
-XML::DOM 1.27 now uses array references as the underlying data type
-for DOM nodes instead of hash array references. User data is now
-bound to the _UserData node entry instead of being forced directly
-into the node hash.
-
-=back
-
-=head1 BUGS
-
-The childrenToTemplate() and allChildrenToTemplate() methods can easily
-slip into deep recursion.
-
-The 'verbose' and 'nospace' options are not documented. They may
-change in the near future.
-
-=head1 COPYRIGHT
-
-Copyright (C) 2000-2001 Andy Wardley, Simon Matthews. All Rights Reserved.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<XML::DOM|XML::DOM>, L<XML::Parser|XML::Parser>
-
diff --git a/lib/Template/Plugin/XML/RSS.pm b/lib/Template/Plugin/XML/RSS.pm
deleted file mode 100644
index 32da7d8..0000000
--- a/lib/Template/Plugin/XML/RSS.pm
+++ /dev/null
@@ -1,194 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::XML::RSS
-#
-# DESCRIPTION
-#
-# Template Toolkit plugin which interfaces to Jonathan Eisenzopf's XML::RSS
-# module. RSS is the Rich Site Summary format.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 2000 Andy Wardley. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: RSS.pm,v 2.64 2004/01/13 16:21:50 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::XML::RSS;
-
-require 5.004;
-
-use strict;
-use vars qw( $VERSION );
-use base qw( Template::Plugin );
-use Template::Plugin;
-use XML::RSS;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.64 $ =~ /(\d+)\.(\d+)/);
-
-sub load {
- return $_[0];
-}
-
-sub new {
- my ($class, $context, $filename) = @_;
-
- return $class->fail('No filename specified')
- unless $filename;
-
- my $rss = XML::RSS->new
- or return $class->fail('failed to create XML::RSS');
-
- # Attempt to determine if $filename is an XML string or
- # a filename. Based on code from the XML.XPath plugin.
- eval {
- if ($filename =~ /\</) {
- $rss->parse($filename);
- }
- else {
- $rss->parsefile($filename)
- }
- } and not $@
- or return $class->fail("failed to parse $filename: $@");
-
- return $rss;
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::XML::RSS - Plugin interface to XML::RSS
-
-=head1 SYNOPSIS
-
- [% USE news = XML.RSS($filename) %]
-
- [% FOREACH item = news.items %]
- [% item.title %]
- [% item.link %]
- [% END %]
-
-=head1 PRE-REQUISITES
-
-This plugin requires that the XML::Parser and XML::RSS modules be
-installed. These are available from CPAN:
-
- http://www.cpan.org/modules/by-module/XML
-
-=head1 DESCRIPTION
-
-This Template Toolkit plugin provides a simple interface to the
-XML::RSS module.
-
- [% USE news = XML.RSS('mysite.rdf') %]
-
-It creates an XML::RSS object, which is then used to parse the RSS
-file specified as a parameter in the USE directive. A reference to
-the XML::RSS object is then returned.
-
-An RSS (Rich Site Summary) file is typically used to store short news
-'headlines' describing different links within a site. This example is
-extracted from http://slashdot.org/slashdot.rdf.
-
- <?xml version="1.0"?><rdf:RDF
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns="http://my.netscape.com/rdf/simple/0.9/">
-
- <channel>
- <title>Slashdot:News for Nerds. Stuff that Matters.</title>
- <link>http://slashdot.org</link>
- <description>News for Nerds. Stuff that Matters</description>
- </channel>
-
- <image>
- <title>Slashdot</title>
- <url>http://slashdot.org/images/slashdotlg.gif</url>
- <link>http://slashdot.org</link>
- </image>
-
- <item>
- <title>DVD CCA Battle Continues Next Week</title>
- <link>http://slashdot.org/article.pl?sid=00/01/12/2051208</link>
- </item>
-
- <item>
- <title>Matrox to fund DRI Development</title>
- <link>http://slashdot.org/article.pl?sid=00/01/13/0718219</link>
- </item>
-
- <item>
- <title>Mike Shaver Leaving Netscape</title>
- <link>http://slashdot.org/article.pl?sid=00/01/13/0711258</link>
- </item>
-
- </rdf:RDF>
-
-The attributes of the channel and image elements can be retrieved directly
-from the plugin object using the familiar dotted compound notation:
-
- [% news.channel.title %]
- [% news.channel.link %]
- [% news.channel.etc... %]
-
- [% news.image.title %]
- [% news.image.url %]
- [% news.image.link %]
- [% news.image.etc... %]
-
-The list of news items can be retrieved using the 'items' method:
-
- [% FOREACH item = news.items %]
- [% item.title %]
- [% item.link %]
- [% END %]
-
-=head1 AUTHORS
-
-This plugin was written by Andy Wardley E<lt>abw@wardley.orgE<gt>,
-inspired by an article in Web Techniques by Randal Schwartz
-E<lt>merlyn@stonehenge.comE<gt>.
-
-The XML::RSS module, which implements all of the functionality that
-this plugin delegates to, was written by Jonathan Eisenzopf
-E<lt>eisen@pobox.comE<gt>.
-
-=head1 VERSION
-
-2.64, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<XML::RSS|XML::RSS>, L<XML::Parser|XML::Parser>
-
diff --git a/lib/Template/Plugin/XML/Simple.pm b/lib/Template/Plugin/XML/Simple.pm
deleted file mode 100644
index aaa4479..0000000
--- a/lib/Template/Plugin/XML/Simple.pm
+++ /dev/null
@@ -1,124 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::XML::Simple
-#
-# DESCRIPTION
-# Template Toolkit plugin interfacing to the XML::Simple.pm module.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Andy Wardley. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Simple.pm,v 2.63 2004/01/13 16:21:50 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::XML::Simple;
-
-require 5.004;
-
-use strict;
-use Template::Plugin;
-use XML::Simple;
-
-use base qw( Template::Plugin );
-use vars qw( $VERSION );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.63 $ =~ /(\d+)\.(\d+)/);
-
-
-#------------------------------------------------------------------------
-# new($context, $file_or_text, \%config)
-#------------------------------------------------------------------------
-
-sub new {
- my $class = shift;
- my $context = shift;
- my $input = shift;
- my $args = ref $_[-1] eq 'HASH' ? pop(@_) : { };
-
- XMLin($input, %$args);
-}
-
-
-
-#------------------------------------------------------------------------
-# _throw($errmsg)
-#
-# Raise a Template::Exception of type XML.Simple via die().
-#------------------------------------------------------------------------
-
-sub _throw {
- my ($self, $error) = @_;
- die (Template::Exception->new('XML.Simple', $error));
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::XML::Simple - Plugin interface to XML::Simple
-
-=head1 SYNOPSIS
-
- # load plugin and specify XML file to parse
- [% USE xml = XML.Simple(xml_file_or_text) %]
-
-=head1 DESCRIPTION
-
-This is a Template Toolkit plugin interfacing to the XML::Simple module.
-
-=head1 PRE-REQUISITES
-
-This plugin requires that the XML::Parser and XML::Simple modules be
-installed. These are available from CPAN:
-
- http://www.cpan.org/modules/by-module/XML
-
-=head1 AUTHORS
-
-This plugin wrapper module was written by Andy Wardley
-E<lt>abw@wardley.orgE<gt>.
-
-The XML::Simple module which implements all the core functionality
-was written by Grant McLean E<lt>grantm@web.co.nzE<gt>.
-
-=head1 VERSION
-
-2.63, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<XML::Simple|XML::Simple>, L<XML::Parser|XML::Parser>
-
diff --git a/lib/Template/Plugin/XML/Style.pm b/lib/Template/Plugin/XML/Style.pm
deleted file mode 100644
index 7613f2f..0000000
--- a/lib/Template/Plugin/XML/Style.pm
+++ /dev/null
@@ -1,357 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::XML::Style
-#
-# DESCRIPTION
-# Template Toolkit plugin which performs some basic munging of XML
-# to perform simple stylesheet like transformations.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 2001 Andy Wardley. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-# REVISION
-# $Id: Style.pm,v 2.34 2004/01/13 16:21:50 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::XML::Style;
-
-require 5.004;
-
-use strict;
-use Template::Plugin::Filter;
-
-use base qw( Template::Plugin::Filter );
-use vars qw( $VERSION $DYNAMIC $FILTER_NAME );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.34 $ =~ /(\d+)\.(\d+)/);
-$DYNAMIC = 1;
-$FILTER_NAME = 'xmlstyle';
-
-
-#------------------------------------------------------------------------
-# new($context, \%config)
-#------------------------------------------------------------------------
-
-sub init {
- my $self = shift;
- my $name = $self->{ _ARGS }->[0] || $FILTER_NAME;
- $self->install_filter($name);
- return $self;
-}
-
-
-sub filter {
- my ($self, $text, $args, $config) = @_;
-
- # munge start tags
- $text =~ s/ < ([\w\.\:]+) ( \s+ [^>]+ )? >
- / $self->start_tag($1, $2, $config)
- /gsex;
-
- # munge end tags
- $text =~ s/ < \/ ([\w\.\:]+) >
- / $self->end_tag($1, $config)
- /gsex;
-
- return $text;
-
-}
-
-
-sub start_tag {
- my ($self, $elem, $textattr, $config) = @_;
- $textattr ||= '';
- my ($pre, $post);
-
- # look for an element match in the stylesheet
- my $match = $config->{ $elem }
- || $self->{ _CONFIG }->{ $elem }
- || return "<$elem$textattr>";
-
- # merge element attributes into copy of stylesheet attributes
- my $attr = { %{ $match->{ attributes } || { } } };
- while ($textattr =~ / \s* ([\w\.\:]+) = " ([^"]+) " /gsx ) {
- $attr->{ $1 } = $2;
- }
- $textattr = join(' ', map { "$_=\"$attr->{$_}\"" } keys %$attr);
- $textattr = " $textattr" if $textattr;
-
- $elem = $match->{ element } || $elem;
- $pre = $match->{ pre_start } || '';
- $post = $match->{ post_start } || '';
-
- return "$pre<$elem$textattr>$post";
-}
-
-
-sub end_tag {
- my ($self, $elem, $config) = @_;
- my ($pre, $post);
-
- # look for an element match in the stylesheet
- my $match = $config->{ $elem }
- || $self->{ _CONFIG }->{ $elem }
- || return "</$elem>";
-
- $elem = $match->{ element } || $elem;
- $pre = $match->{ pre_end } || '';
- $post = $match->{ post_end } || '';
-
- return "$pre</$elem>$post";
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::XML::Style - Simple XML stylesheet transfomations
-
-=head1 SYNOPSIS
-
- [% USE xmlstyle
- table = {
- attributes = {
- border = 0
- cellpadding = 4
- cellspacing = 1
- }
- }
- %]
-
- [% FILTER xmlstyle %]
- <table>
- <tr>
- <td>Foo</td> <td>Bar</td> <td>Baz</td>
- </tr>
- </table>
- [% END %]
-
-=head1 DESCRIPTION
-
-This plugin defines a filter for performing simple stylesheet based
-transformations of XML text.
-
-Named parameters are used to define those XML elements which require
-transformation. These may be specified with the USE directive when
-the plugin is loaded and/or with the FILTER directive when the plugin
-is used.
-
-This example shows how the default attributes C<border="0"> and
-C<cellpadding="4"> can be added to E<lt>tableE<gt> elements.
-
- [% USE xmlstyle
- table = {
- attributes = {
- border = 0
- cellpadding = 4
- }
- }
- %]
-
- [% FILTER xmlstyle %]
- <table>
- ...
- </table>
- [% END %]
-
-This produces the output:
-
- <table border="0" cellpadding="4">
- ...
- </table>
-
-Parameters specified within the USE directive are applied automatically each
-time the C<xmlstyle> FILTER is used. Additional parameters passed to the
-FILTER directive apply for only that block.
-
- [% USE xmlstyle
- table = {
- attributes = {
- border = 0
- cellpadding = 4
- }
- }
- %]
-
- [% FILTER xmlstyle
- tr = {
- attributes = {
- valign="top"
- }
- }
- %]
- <table>
- <tr>
- ...
- </tr>
- </table>
- [% END %]
-
-Of course, you may prefer to define your stylesheet structures once and
-simply reference them by name. Passing a hash reference of named parameters
-is just the same as specifying the named parameters as far as the Template
-Toolkit is concerned.
-
- [% style_one = {
- table = { ... }
- tr = { ... }
- }
- style_two = {
- table = { ... }
- td = { ... }
- }
- style_three = {
- th = { ... }
- tv = { ... }
- }
- %]
-
- [% USE xmlstyle style_one %]
-
- [% FILTER xmlstyle style_two %]
- # style_one and style_two applied here
- [% END %]
-
- [% FILTER xmlstyle style_three %]
- # style_one and style_three applied here
- [% END %]
-
-Any attributes defined within the source tags will override those specified
-in the style sheet.
-
- [% USE xmlstyle
- div = { attributes = { align = 'left' } }
- %]
-
-
- [% FILTER xmlstyle %]
- <div>foo</div>
- <div align="right">bar</div>
- [% END %]
-
-The output produced is:
-
- <div align="left">foo</div>
- <div align="right">bar</div>
-
-The filter can also be used to change the element from one type to another.
-
- [% FILTER xmlstyle
- th = {
- element = 'td'
- attributes = { bgcolor='red' }
- }
- %]
- <tr>
- <th>Heading</th>
- </tr>
- <tr>
- <td>Value</td>
- </tr>
- [% END %]
-
-The output here is as follows. Notice how the end tag C<E<lt>/thE<gt>> is
-changed to C<E<lt>/tdE<gt>> as well as the start tag.
-
- <tr>
- <td bgcolor="red">Heading</td>
- </tr>
- <tr>
- <td>Value</td>
- </tr>
-
-You can also define text to be added immediately before or after the
-start or end tags. For example:
-
- [% FILTER xmlstyle
- table = {
- pre_start = '<div align="center">'
- post_end = '</div>'
- }
- th = {
- element = 'td'
- attributes = { bgcolor='red' }
- post_start = '<b>'
- pre_end = '</b>'
- }
- %]
- <table>
- <tr>
- <th>Heading</th>
- </tr>
- <tr>
- <td>Value</td>
- </tr>
- </table>
- [% END %]
-
-The output produced is:
-
- <div align="center">
- <table>
- <tr>
- <td bgcolor="red"><b>Heading</b></td>
- </tr>
- <tr>
- <td>Value</td>
- </tr>
- </table>
- </div>
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.34, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Plugin/XML/XPath.pm b/lib/Template/Plugin/XML/XPath.pm
deleted file mode 100644
index adf9292..0000000
--- a/lib/Template/Plugin/XML/XPath.pm
+++ /dev/null
@@ -1,284 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugin::XML::XPath
-#
-# DESCRIPTION
-#
-# Template Toolkit plugin interfacing to the XML::XPath.pm module.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 2000 Andy Wardley. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: XPath.pm,v 2.69 2004/01/13 16:21:50 abw Exp $
-#
-#============================================================================
-
-package Template::Plugin::XML::XPath;
-
-require 5.004;
-
-use strict;
-use Template::Exception;
-use Template::Plugin;
-use XML::XPath;
-
-use base qw( Template::Plugin );
-use vars qw( $VERSION );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.69 $ =~ /(\d+)\.(\d+)/);
-
-
-#------------------------------------------------------------------------
-# new($context, \%config)
-#
-# Constructor method for XML::XPath plugin. Creates an XML::XPath
-# object and initialises plugin configuration.
-#------------------------------------------------------------------------
-
-sub new {
- my $class = shift;
- my $context = shift;
- my $args = ref $_[-1] eq 'HASH' ? pop(@_) : { };
- my ($content, $about);
-
- # determine the input source from a positional parameter (may be a
- # filename or XML text if it contains a '<' character) or by using
- # named parameters which may specify one of 'file', 'filename', 'text'
- # or 'xml'
-
- if ($content = shift) {
- if ($content =~ /\</) {
- $about = 'xml text';
- $args->{ xml } = $content;
- }
- else {
- $about = "xml file $content";
- $args->{ filename } = $content;
- }
- }
- elsif ($content = $args->{ text } || $args->{ xml }) {
- $about = 'xml text';
- $args->{ xml } = $content;
- }
- elsif ($content = $args->{ file } || $args->{ filename }) {
- $about = "xml file $content";
- $args->{ filename } = $content;
- }
- else {
- return $class->_throw('no filename or xml text specified');
- }
-
- return XML::XPath->new(%$args)
- or $class->_throw("failed to create XML::XPath::Parser\n");
-}
-
-
-
-#------------------------------------------------------------------------
-# _throw($errmsg)
-#
-# Raise a Template::Exception of type XML.XPath via die().
-#------------------------------------------------------------------------
-
-sub _throw {
- my ($self, $error) = @_;
-# print STDERR "about to throw $error\n";
- die (Template::Exception->new('XML.XPath', $error));
-}
-
-
-#========================================================================
-package XML::XPath::Node::Element;
-#========================================================================
-
-#------------------------------------------------------------------------
-# present($view)
-#
-# Method to present an element node via a view.
-#------------------------------------------------------------------------
-
-sub present {
- my ($self, $view) = @_;
- $view->view($self->getName(), $self);
-}
-
-sub content {
- my ($self, $view) = @_;
- my $output = '';
- foreach my $node (@{ $self->getChildNodes }) {
- $output .= $node->present($view);
- }
- return $output;
-}
-
-#----------------------------------------------------------------------
-# starttag(), endtag()
-#
-# Methods to output the start & end tag, e.g. <foo bar="baz"> & </foo>
-#----------------------------------------------------------------------
-
-sub starttag {
- my ($self) = @_;
- my $output = "<". $self->getName();
- foreach my $attr ($self->getAttributes())
- {
- $output .= $attr->toString();
- }
- $output .= ">";
- return $output;
-}
-
-sub endtag {
- my ($self) = @_;
- return "</". $self->getName() . ">";
-}
-
-#========================================================================
-package XML::XPath::Node::Text;
-#========================================================================
-
-#------------------------------------------------------------------------
-# present($view)
-#
-# Method to present a text node via a view.
-#------------------------------------------------------------------------
-
-sub present {
- my ($self, $view) = @_;
- $view->view('text', $self->string_value);
-}
-
-
-#========================================================================
-package XML::XPath::Node::Comment;
-#========================================================================
-
-sub present { return ''; }
-sub starttag { return ''; }
-sub endtag { return ''; }
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugin::XML::XPath - Plugin interface to XML::XPath
-
-=head1 SYNOPSIS
-
- # load plugin and specify XML file to parse
- [% USE xpath = XML.XPath(xmlfile) %]
- [% USE xpath = XML.XPath(file => xmlfile) %]
- [% USE xpath = XML.XPath(filename => xmlfile) %]
-
- # load plugin and specify XML text to parse
- [% USE xpath = XML.XPath(xmltext) %]
- [% USE xpath = XML.XPath(xml => xmltext) %]
- [% USE xpath = XML.XPath(text => xmltext) %]
-
- # then call any XPath methods (see XML::XPath docs)
- [% FOREACH page = xpath.findnodes('/html/body/page') %]
- [% page.getAttribute('title') %]
- [% END %]
-
- # define VIEW to present node(s)
- [% VIEW repview notfound='xmlstring' %]
- # handler block for a <report>...</report> element
- [% BLOCK report %]
- [% item.content(view) %]
- [% END %]
-
- # handler block for a <section title="...">...</section> element
- [% BLOCK section %]
- <h1>[% item.getAttribute('title') | html %]</h1>
- [% item.content(view) %]
- [% END %]
-
- # default template block passes tags through and renders
- # out the children recursivly
- [% BLOCK xmlstring;
- item.starttag; item.content(view); item.endtag;
- END %]
-
- # block to generate simple text
- [% BLOCK text; item | html; END %]
- [% END %]
-
- # now present node (and children) via view
- [% repview.print(page) %]
-
- # or print node content via view
- [% page.content(repview) %]
-
-=head1 PRE-REQUISITES
-
-This plugin requires that the XML::Parser and XML::XPath modules be
-installed. These are available from CPAN:
-
- http://www.cpan.org/modules/by-module/XML
-
-=head1 DESCRIPTION
-
-This is a Template Toolkit plugin interfacing to the XML::XPath module.
-
-All methods implemented by the XML::XPath modules are available. In
-addition, the XML::XPath::Node::Element module implements
-present($view) and content($view) methods method for seamless
-integration with Template Toolkit VIEWs. The XML::XPath::Node::Text
-module is also adorned with a present($view) method which presents
-itself via the view using the 'text' template.
-
-To aid the reconstruction of XML, methods starttag and endtag are
-added to XML::XPath::Node::Element which return the start and
-end tag for that element. This means that you can easily do:
-
- [% item.starttag %][% item.content(view) %][% item.endtag %]
-
-To render out the start tag, followed by the content rendered in the
-view "view", followed by the end tag.
-
-=head1 AUTHORS
-
-This plugin module was written by Andy Wardley E<lt>abw@wardley.orgE<gt>.
-
-The XML::XPath module is by Matt Sergeant E<lt>matt@sergeant.orgE<gt>.
-
-=head1 VERSION
-
-2.69, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>, L<XML::XPath|XML::XPath>, L<XML::Parser|XML::Parser>
-
diff --git a/lib/Template/Plugins.pm b/lib/Template/Plugins.pm
deleted file mode 100644
index 1904efc..0000000
--- a/lib/Template/Plugins.pm
+++ /dev/null
@@ -1,1041 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Plugins
-#
-# DESCRIPTION
-# Plugin provider which handles the loading of plugin modules and
-# instantiation of plugin objects.
-#
-# AUTHORS
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Plugins.pm,v 2.70 2004/01/13 16:19:15 abw Exp $
-#
-#============================================================================
-
-package Template::Plugins;
-
-require 5.004;
-
-use strict;
-use base qw( Template::Base );
-use vars qw( $VERSION $DEBUG $STD_PLUGINS );
-use Template::Constants;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.70 $ =~ /(\d+)\.(\d+)/);
-
-$STD_PLUGINS = {
- 'autoformat' => 'Template::Plugin::Autoformat',
- 'cgi' => 'Template::Plugin::CGI',
- 'datafile' => 'Template::Plugin::Datafile',
- 'date' => 'Template::Plugin::Date',
- 'debug' => 'Template::Plugin::Debug',
- 'directory' => 'Template::Plugin::Directory',
- 'dbi' => 'Template::Plugin::DBI',
- 'dumper' => 'Template::Plugin::Dumper',
- 'file' => 'Template::Plugin::File',
- 'format' => 'Template::Plugin::Format',
- 'html' => 'Template::Plugin::HTML',
- 'image' => 'Template::Plugin::Image',
- 'iterator' => 'Template::Plugin::Iterator',
- 'pod' => 'Template::Plugin::Pod',
- 'table' => 'Template::Plugin::Table',
- 'url' => 'Template::Plugin::URL',
- 'view' => 'Template::Plugin::View',
- 'wrap' => 'Template::Plugin::Wrap',
- 'xmlstyle' => 'Template::Plugin::XML::Style',
-};
-
-
-#========================================================================
-# -- PUBLIC METHODS --
-#========================================================================
-
-#------------------------------------------------------------------------
-# fetch($name, \@args, $context)
-#
-# General purpose method for requesting instantiation of a plugin
-# object. The name of the plugin is passed as the first parameter.
-# The internal FACTORY lookup table is consulted to retrieve the
-# appropriate factory object or class name. If undefined, the _load()
-# method is called to attempt to load the module and return a factory
-# class/object which is then cached for subsequent use. A reference
-# to the calling context should be passed as the third parameter.
-# This is passed to the _load() class method. The new() method is
-# then called against the factory class name or prototype object to
-# instantiate a new plugin object, passing any arguments specified by
-# list reference as the second parameter. e.g. where $factory is the
-# class name 'MyClass', the new() method is called as a class method,
-# $factory->new(...), equivalent to MyClass->new(...) . Where
-# $factory is a prototype object, the new() method is called as an
-# object method, $myobject->new(...). This latter approach allows
-# plugins to act as Singletons, cache shared data, etc.
-#
-# Returns a reference to a plugin, (undef, STATUS_DECLINE) to decline
-# the request or ($error, STATUS_ERROR) on error.
-#------------------------------------------------------------------------
-
-sub fetch {
- my ($self, $name, $args, $context) = @_;
- my ($factory, $plugin, $error);
-
- $self->debug("fetch($name, ",
- defined $args ? ('[ ', join(', ', @$args), ' ]') : '<no args>', ', ',
- defined $context ? $context : '<no context>',
- ')') if $self->{ DEBUG };
-
- # NOTE:
- # the $context ref gets passed as the first parameter to all regular
- # plugins, but not to those loaded via LOAD_PERL; to hack around
- # this until we have a better implementation, we pass the $args
- # reference to _load() and let it unshift the first args in the
- # LOAD_PERL case
-
- $args ||= [ ];
- unshift @$args, $context;
-
- $factory = $self->{ FACTORY }->{ $name } ||= do {
- ($factory, $error) = $self->_load($name, $context);
- return ($factory, $error) if $error; ## RETURN
- $factory;
- };
-
- # call the new() method on the factory object or class name
- eval {
- if (ref $factory eq 'CODE') {
- defined( $plugin = &$factory(@$args) )
- || die "$name plugin failed\n";
- }
- else {
- defined( $plugin = $factory->new(@$args) )
- || die "$name plugin failed: ", $factory->error(), "\n";
- }
- };
- if ($error = $@) {
-# chomp $error;
- return $self->{ TOLERANT }
- ? (undef, Template::Constants::STATUS_DECLINED)
- : ($error, Template::Constants::STATUS_ERROR);
- }
-
- return $plugin;
-}
-
-
-
-#========================================================================
-# -- PRIVATE METHODS --
-#========================================================================
-
-#------------------------------------------------------------------------
-# _init(\%config)
-#
-# Private initialisation method.
-#------------------------------------------------------------------------
-
-sub _init {
- my ($self, $params) = @_;
- my ($pbase, $plugins, $factory) =
- @$params{ qw( PLUGIN_BASE PLUGINS PLUGIN_FACTORY ) };
-
- $plugins ||= { };
- if (ref $pbase ne 'ARRAY') {
- $pbase = $pbase ? [ $pbase ] : [ ];
- }
- push(@$pbase, 'Template::Plugin');
-
- $self->{ PLUGIN_BASE } = $pbase;
- $self->{ PLUGINS } = { %$STD_PLUGINS, %$plugins };
- $self->{ TOLERANT } = $params->{ TOLERANT } || 0;
- $self->{ LOAD_PERL } = $params->{ LOAD_PERL } || 0;
- $self->{ FACTORY } = $factory || { };
- $self->{ DEBUG } = ( $params->{ DEBUG } || 0 )
- & Template::Constants::DEBUG_PLUGINS;
-
- return $self;
-}
-
-
-
-#------------------------------------------------------------------------
-# _load($name, $context)
-#
-# Private method which attempts to load a plugin module and determine the
-# correct factory name or object by calling the load() class method in
-# the loaded module.
-#------------------------------------------------------------------------
-
-sub _load {
- my ($self, $name, $context) = @_;
- my ($factory, $module, $base, $pkg, $file, $ok, $error);
-
- if ($module = $self->{ PLUGINS }->{ $name }) {
- # plugin module name is explicitly stated in PLUGIN_NAME
- $pkg = $module;
- ($file = $module) =~ s|::|/|g;
- $file =~ s|::|/|g;
- $self->debug("loading $module.pm (PLUGIN_NAME)")
- if $self->{ DEBUG };
- $ok = eval { require "$file.pm" };
- $error = $@;
- }
- else {
- # try each of the PLUGIN_BASE values to build module name
- ($module = $name) =~ s/\./::/g;
-
- foreach $base (@{ $self->{ PLUGIN_BASE } }) {
- $pkg = $base . '::' . $module;
- ($file = $pkg) =~ s|::|/|g;
-
- $self->debug("loading $file.pm (PLUGIN_BASE)")
- if $self->{ DEBUG };
-
- $ok = eval { require "$file.pm" };
- last unless $@;
-
- $error .= "$@\n"
- unless ($@ =~ /^Can\'t locate $file\.pm/);
- }
- }
-
- if ($ok) {
- $self->debug("calling $pkg->load()") if $self->{ DEBUG };
-
- $factory = eval { $pkg->load($context) };
- $error = '';
- if ($@ || ! $factory) {
- $error = $@ || 'load() returned a false value';
- }
- }
- elsif ($self->{ LOAD_PERL }) {
- # fallback - is it a regular Perl module?
- ($file = $module) =~ s|::|/|g;
- eval { require "$file.pm" };
- if ($@) {
- $error = $@;
- }
- else {
- # this is a regular Perl module so the new() constructor
- # isn't expecting a $context reference as the first argument;
- # so we construct a closure which removes it before calling
- # $module->new(@_);
- $factory = sub {
- shift;
- $module->new(@_);
- };
- $error = '';
- }
- }
-
- if ($factory) {
- $self->debug("$name => $factory") if $self->{ DEBUG };
- return $factory;
- }
- elsif ($error) {
- return $self->{ TOLERANT }
- ? (undef, Template::Constants::STATUS_DECLINED)
- : ($error, Template::Constants::STATUS_ERROR);
- }
- else {
- return (undef, Template::Constants::STATUS_DECLINED);
- }
-}
-
-
-#------------------------------------------------------------------------
-# _dump()
-#
-# Debug method which constructs and returns text representing the current
-# state of the object.
-#------------------------------------------------------------------------
-
-sub _dump {
- my $self = shift;
- my $output = "[Template::Plugins] {\n";
- my $format = " %-16s => %s\n";
- my $key;
-
- foreach $key (qw( TOLERANT LOAD_PERL )) {
- $output .= sprintf($format, $key, $self->{ $key });
- }
-
- local $" = ', ';
- my $fkeys = join(", ", keys %{$self->{ FACTORY }});
- my $plugins = $self->{ PLUGINS };
- $plugins = join('', map {
- sprintf(" $format", $_, $plugins->{ $_ });
- } keys %$plugins);
- $plugins = "{\n$plugins }";
-
- $output .= sprintf($format, 'PLUGIN_BASE', "[ @{ $self->{ PLUGIN_BASE } } ]");
- $output .= sprintf($format, 'PLUGINS', $plugins);
- $output .= sprintf($format, 'FACTORY', $fkeys);
- $output .= '}';
- return $output;
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Plugins - Plugin provider module
-
-=head1 SYNOPSIS
-
- use Template::Plugins;
-
- $plugin_provider = Template::Plugins->new(\%options);
-
- ($plugin, $error) = $plugin_provider->fetch($name, @args);
-
-=head1 DESCRIPTION
-
-The Template::Plugins module defines a provider class which can be used
-to load and instantiate Template Toolkit plugin modules.
-
-=head1 METHODS
-
-=head2 new(\%params)
-
-Constructor method which instantiates and returns a reference to a
-Template::Plugins object. A reference to a hash array of configuration
-items may be passed as a parameter. These are described below.
-
-Note that the Template.pm front-end module creates a Template::Plugins
-provider, passing all configuration items. Thus, the examples shown
-below in the form:
-
- $plugprov = Template::Plugins->new({
- PLUGIN_BASE => 'MyTemplate::Plugin',
- LOAD_PERL => 1,
- ...
- });
-
-can also be used via the Template module as:
-
- $ttengine = Template->new({
- PLUGIN_BASE => 'MyTemplate::Plugin',
- LOAD_PERL => 1,
- ...
- });
-
-as well as the more explicit form of:
-
- $plugprov = Template::Plugins->new({
- PLUGIN_BASE => 'MyTemplate::Plugin',
- LOAD_PERL => 1,
- ...
- });
-
- $ttengine = Template->new({
- LOAD_PLUGINS => [ $plugprov ],
- });
-
-=head2 fetch($name, @args)
-
-Called to request that a plugin of a given name be provided. The relevant
-module is first loaded (if necessary) and the load() class method called
-to return the factory class name (usually the same package name) or a
-factory object (a prototype). The new() method is then called as a
-class or object method against the factory, passing all remaining
-parameters.
-
-Returns a reference to a new plugin object or ($error, STATUS_ERROR)
-on error. May also return (undef, STATUS_DECLINED) to decline to
-serve the request. If TOLERANT is set then all errors will be
-returned as declines.
-
-=head1 CONFIGURATION OPTIONS
-
-The following list details the configuration options that can be provided
-to the Template::Plugins new() constructor.
-
-=over 4
-
-
-
-
-=item PLUGINS
-
-The PLUGINS options can be used to provide a reference to a hash array
-that maps plugin names to Perl module names. A number of standard
-plugins are defined (e.g. 'table', 'cgi', 'dbi', etc.) which map to
-their corresponding Template::Plugin::* counterparts. These can be
-redefined by values in the PLUGINS hash.
-
- my $plugins = Template::Plugins->new({
- PLUGINS => {
- cgi => 'MyOrg::Template::Plugin::CGI',
- foo => 'MyOrg::Template::Plugin::Foo',
- bar => 'MyOrg::Template::Plugin::Bar',
- },
- });
-
-The USE directive is used to create plugin objects and does so by
-calling the plugin() method on the current Template::Context object.
-If the plugin name is defined in the PLUGINS hash then the
-corresponding Perl module is loaded via require(). The context then
-calls the load() class method which should return the class name
-(default and general case) or a prototype object against which the
-new() method can be called to instantiate individual plugin objects.
-
-If the plugin name is not defined in the PLUGINS hash then the PLUGIN_BASE
-and/or LOAD_PERL options come into effect.
-
-
-
-
-
-=item PLUGIN_BASE
-
-If a plugin is not defined in the PLUGINS hash then the PLUGIN_BASE is used
-to attempt to construct a correct Perl module name which can be successfully
-loaded.
-
-The PLUGIN_BASE can be specified as a single value or as a reference
-to an array of multiple values. The default PLUGIN_BASE value,
-'Template::Plugin', is always added the the end of the PLUGIN_BASE
-list (a single value is first converted to a list). Each value should
-contain a Perl package name to which the requested plugin name is
-appended.
-
-example 1:
-
- my $plugins = Template::Plugins->new({
- PLUGIN_BASE => 'MyOrg::Template::Plugin',
- });
-
- [% USE Foo %] # => MyOrg::Template::Plugin::Foo
- or Template::Plugin::Foo
-
-example 2:
-
- my $plugins = Template::Plugins->new({
- PLUGIN_BASE => [ 'MyOrg::Template::Plugin',
- 'YourOrg::Template::Plugin' ],
- });
-
- [% USE Foo %] # => MyOrg::Template::Plugin::Foo
- or YourOrg::Template::Plugin::Foo
- or Template::Plugin::Foo
-
-
-
-
-
-
-=item LOAD_PERL
-
-If a plugin cannot be loaded using the PLUGINS or PLUGIN_BASE
-approaches then the provider can make a final attempt to load the
-module without prepending any prefix to the module path. This allows
-regular Perl modules (i.e. those that don't reside in the
-Template::Plugin or some other such namespace) to be loaded and used
-as plugins.
-
-By default, the LOAD_PERL option is set to 0 and no attempt will be made
-to load any Perl modules that aren't named explicitly in the PLUGINS
-hash or reside in a package as named by one of the PLUGIN_BASE
-components.
-
-Plugins loaded using the PLUGINS or PLUGIN_BASE receive a reference to
-the current context object as the first argument to the new()
-constructor. Modules loaded using LOAD_PERL are assumed to not
-conform to the plugin interface. They must provide a new() class
-method for instantiating objects but it will not receive a reference
-to the context as the first argument. Plugin modules should provide a
-load() class method (or inherit the default one from the
-Template::Plugin base class) which is called the first time the plugin
-is loaded. Regular Perl modules need not. In all other respects,
-regular Perl objects and Template Toolkit plugins are identical.
-
-If a particular Perl module does not conform to the common, but not
-unilateral, new() constructor convention then a simple plugin wrapper
-can be written to interface to it.
-
-
-
-
-=item TOLERANT
-
-The TOLERANT flag is used by the various Template Toolkit provider
-modules (Template::Provider, Template::Plugins, Template::Filters) to
-control their behaviour when errors are encountered. By default, any
-errors are reported as such, with the request for the particular
-resource (template, plugin, filter) being denied and an exception
-raised. When the TOLERANT flag is set to any true values, errors will
-be silently ignored and the provider will instead return
-STATUS_DECLINED. This allows a subsequent provider to take
-responsibility for providing the resource, rather than failing the
-request outright. If all providers decline to service the request,
-either through tolerated failure or a genuine disinclination to
-comply, then a 'E<lt>resourceE<gt> not found' exception is raised.
-
-
-
-
-=item DEBUG
-
-The DEBUG option can be used to enable debugging messages from the
-Template::Plugins module by setting it to include the DEBUG_PLUGINS
-value.
-
- use Template::Constants qw( :debug );
-
- my $template = Template->new({
- DEBUG => DEBUG_FILTERS | DEBUG_PLUGINS,
- });
-
-
-
-
-=back
-
-
-
-=head1 TEMPLATE TOOLKIT PLUGINS
-
-The following plugin modules are distributed with the Template
-Toolkit. Some of the plugins interface to external modules (detailed
-below) which should be downloaded from any CPAN site and installed
-before using the plugin.
-
-=head2 Autoformat
-
-The Autoformat plugin is an interface to Damian Conway's Text::Autoformat
-Perl module which provides advanced text wrapping and formatting. See
-L<Template::Plugin::Autoformat> and L<Text::Autoformat> for further
-details.
-
- [% USE autoformat(left=10, right=20) %]
- [% autoformat(mytext) %] # call autoformat sub
- [% mytext FILTER autoformat %] # or use autoformat filter
-
-The Text::Autoformat module is available from CPAN:
-
- http://www.cpan.org/modules/by-module/Text/
-
-=head2 CGI
-
-The CGI plugin is a wrapper around Lincoln Stein's
-E<lt>lstein@genome.wi.mit.eduE<gt> CGI.pm module. The plugin is
-distributed with the Template Toolkit (see L<Template::Plugin::CGI>)
-and the CGI module itself is distributed with recent versions Perl,
-or is available from CPAN.
-
- [% USE CGI %]
- [% CGI.param('param_name') %]
- [% CGI.start_form %]
- [% CGI.popup_menu( Name => 'color',
- Values => [ 'Green', 'Brown' ] ) %]
- [% CGI.end_form %]
-
-=head2 Datafile
-
-Provides an interface to data stored in a plain text file in a simple
-delimited format. The first line in the file specifies field names
-which should be delimiter by any non-word character sequence.
-Subsequent lines define data using the same delimiter as int he first
-line. Blank lines and comments (lines starting '#') are ignored. See
-L<Template::Plugin::Datafile> for further details.
-
-/tmp/mydata:
-
- # define names for each field
- id : email : name : tel
- # here's the data
- fred : fred@here.com : Fred Smith : 555-1234
- bill : bill@here.com : Bill White : 555-5678
-
-example:
-
- [% USE userlist = datafile('/tmp/mydata') %]
-
- [% FOREACH user = userlist %]
- [% user.name %] ([% user.id %])
- [% END %]
-
-=head2 Date
-
-The Date plugin provides an easy way to generate formatted time and date
-strings by delegating to the POSIX strftime() routine. See
-L<Template::Plugin::Date> and L<POSIX> for further details.
-
- [% USE date %]
- [% date.format %] # current time/date
-
- File last modified: [% date.format(template.modtime) %]
-
-=head2 Directory
-
-The Directory plugin provides a simple interface to a directory and
-the files within it. See L<Template::Plugin::Directory> for further
-details.
-
- [% USE dir = Directory('/tmp') %]
- [% FOREACH file = dir.files %]
- # all the plain files in the directory
- [% END %]
- [% FOREACH file = dir.dirs %]
- # all the sub-directories
- [% END %]
-
-=head2 DBI
-
-The DBI plugin, developed by Simon Matthews
-E<lt>sam@knowledgepool.comE<gt>, brings the full power of Tim Bunce's
-E<lt>Tim.Bunce@ig.co.ukE<gt> database interface module (DBI) to your
-templates. See L<Template::Plugin::DBI> and L<DBI> for further details.
-
- [% USE DBI('dbi:driver:database', 'user', 'pass') %]
-
- [% FOREACH user = DBI.query( 'SELECT * FROM users' ) %]
- [% user.id %] [% user.name %]
- [% END %]
-
-The DBI and relevant DBD modules are available from CPAN:
-
- http://www.cpan.org/modules/by-module/DBI/
-
-=head2 Dumper
-
-The Dumper plugin provides an interface to the Data::Dumper module. See
-L<Template::Plugin::Dumper> and L<Data::Dumper> for futher details.
-
- [% USE dumper(indent=0, pad="<br>") %]
- [% dumper.dump(myvar, yourvar) %]
-
-=head2 File
-
-The File plugin provides a general abstraction for files and can be
-used to fetch information about specific files within a filesystem.
-See L<Template::Plugin::File> for further details.
-
- [% USE File('/tmp/foo.html') %]
- [% File.name %] # foo.html
- [% File.dir %] # /tmp
- [% File.mtime %] # modification time
-
-=head2 Filter
-
-This module implements a base class plugin which can be subclassed
-to easily create your own modules that define and install new filters.
-
- package MyOrg::Template::Plugin::MyFilter;
-
- use Template::Plugin::Filter;
- use base qw( Template::Plugin::Filter );
-
- sub filter {
- my ($self, $text) = @_;
-
- # ...mungify $text...
-
- return $text;
- }
-
- # now load it...
- [% USE MyFilter %]
-
- # ...and use the returned object as a filter
- [% FILTER $MyFilter %]
- ...
- [% END %]
-
-See L<Template::Plugin::Filter> for further details.
-
-=head2 Format
-
-The Format plugin provides a simple way to format text according to a
-printf()-like format. See L<Template::Plugin::Format> for further
-details.
-
- [% USE bold = format('<b>%s</b>') %]
- [% bold('Hello') %]
-
-=head2 GD::Image, GD::Polygon, GD::Constants
-
-These plugins provide access to the GD graphics library via Lincoln
-D. Stein's GD.pm interface. These plugins allow PNG, JPEG and other
-graphical formats to be generated.
-
- [% FILTER null;
- USE im = GD.Image(100,100);
- # allocate some colors
- black = im.colorAllocate(0, 0, 0);
- red = im.colorAllocate(255,0, 0);
- blue = im.colorAllocate(0, 0, 255);
- # Draw a blue oval
- im.arc(50,50,95,75,0,360,blue);
- # And fill it with red
- im.fill(50,50,red);
- # Output image in PNG format
- im.png | stdout(1);
- END;
- -%]
-
-See L<Template::Plugin::GD::Image> for further details.
-
-=head2 GD::Text, GD::Text::Align, GD::Text::Wrap
-
-These plugins provide access to Martien Verbruggen's GD::Text,
-GD::Text::Align and GD::Text::Wrap modules. These plugins allow the
-layout, alignment and wrapping of text when drawing text in GD images.
-
- [% FILTER null;
- USE gd = GD.Image(200,400);
- USE gdc = GD.Constants;
- black = gd.colorAllocate(0, 0, 0);
- green = gd.colorAllocate(0, 255, 0);
- txt = "This is some long text. " | repeat(10);
- USE wrapbox = GD.Text.Wrap(gd,
- line_space => 4,
- color => green,
- text => txt,
- );
- wrapbox.set_font(gdc.gdMediumBoldFont);
- wrapbox.set(align => 'center', width => 160);
- wrapbox.draw(20, 20);
- gd.png | stdout(1);
- END;
- -%]
-
-See L<Template::Plugin::GD::Text>, L<Template::Plugin::GD::Text::Align>
-and L<Template::Plugin::GD::Text::Wrap> for further details.
-
-=head2 GD::Graph::lines, GD::Graph::bars, GD::Graph::points, GD::Graph::linespoin
-ts, GD::Graph::area, GD::Graph::mixed, GD::Graph::pie
-
-These plugins provide access to Martien Verbruggen's GD::Graph module
-that allows graphs, plots and charts to be created. These plugins allow
-graphs, plots and charts to be generated in PNG, JPEG and other
-graphical formats.
-
- [% FILTER null;
- data = [
- ["1st","2nd","3rd","4th","5th","6th"],
- [ 4, 2, 3, 4, 3, 3.5]
- ];
- USE my_graph = GD.Graph.pie(250, 200);
- my_graph.set(
- title => 'A Pie Chart',
- label => 'Label',
- axislabelclr => 'black',
- pie_height => 36,
- transparent => 0,
- );
- my_graph.plot(data).png | stdout(1);
- END;
- -%]
-
-See
-L<Template::Plugin::GD::Graph::lines>,
-L<Template::Plugin::GD::Graph::bars>,
-L<Template::Plugin::GD::Graph::points>,
-L<Template::Plugin::GD::Graph::linespoints>,
-L<Template::Plugin::GD::Graph::area>,
-L<Template::Plugin::GD::Graph::mixed>,
-L<Template::Plugin::GD::Graph::pie>, and
-L<GD::Graph>,
-for more details.
-
-=head2 GD::Graph::bars3d, GD::Graph::lines3d, GD::Graph::pie3d
-
-These plugins provide access to Jeremy Wadsack's GD::Graph3d
-module. This allows 3D bar charts and 3D lines plots to
-be generated.
-
- [% FILTER null;
- data = [
- ["1st","2nd","3rd","4th","5th","6th","7th", "8th", "9th"],
- [ 1, 2, 5, 6, 3, 1.5, 1, 3, 4],
- ];
- USE my_graph = GD.Graph.bars3d();
- my_graph.set(
- x_label => 'X Label',
- y_label => 'Y label',
- title => 'A 3d Bar Chart',
- y_max_value => 8,
- y_tick_number => 8,
- y_label_skip => 2,
- # shadows
- bar_spacing => 8,
- shadow_depth => 4,
- shadowclr => 'dred',
- transparent => 0,
- my_graph.plot(data).png | stdout(1);
- END;
- -%]
-
-See
-L<Template::Plugin::GD::Graph::lines3d>,
-L<Template::Plugin::GD::Graph::bars3d>, and
-L<Template::Plugin::GD::Graph::pie3d>
-for more details.
-
-=head2 HTML
-
-The HTML plugin is very new and very basic, implementing a few useful
-methods for generating HTML. It is likely to be extended in the future
-or integrated with a larger project to generate HTML elements in a generic
-way (as discussed recently on the mod_perl mailing list).
-
- [% USE HTML %]
- [% HTML.escape("if (a < b && c > d) ..." %]
- [% HTML.attributes(border => 1, cellpadding => 2) %]
- [% HTML.element(table => { border => 1, cellpadding => 2 }) %]
-
-See L<Template::Plugin::HTML> for further details.
-
-=head2 Iterator
-
-The Iterator plugin provides a way to create a Template::Iterator
-object to iterate over a data set. An iterator is created
-automatically by the FOREACH directive and is aliased to the 'loop'
-variable. This plugin allows an iterator to be explicitly created
-with a given name, or the default plugin name, 'iterator'. See
-L<Template::Plugin::Iterator> for further details.
-
- [% USE iterator(list, args) %]
-
- [% FOREACH item = iterator %]
- [% '<ul>' IF iterator.first %]
- <li>[% item %]
- [% '</ul>' IF iterator.last %]
- [% END %]
-
-=head2 Pod
-
-This plugin provides an interface to the L<Pod::POM|Pod::POM> module
-which parses POD documents into an internal object model which can
-then be traversed and presented through the Template Toolkit.
-
- [% USE Pod(podfile) %]
-
- [% FOREACH head1 = Pod.head1;
- FOREACH head2 = head1/head2;
- ...
- END;
- END
- %]
-
-=head2 String
-
-The String plugin implements an object-oriented interface for
-manipulating strings. See L<Template::Plugin::String> for further
-details.
-
- [% USE String 'Hello' %]
- [% String.append(' World') %]
-
- [% msg = String.new('Another string') %]
- [% msg.replace('string', 'text') %]
-
- The string "[% msg %]" is [% msg.length %] characters long.
-
-=head2 Table
-
-The Table plugin allows you to format a list of data items into a
-virtual table by specifying a fixed number of rows or columns, with
-an optional overlap. See L<Template::Plugin::Table> for further
-details.
-
- [% USE table(list, rows=10, overlap=1) %]
-
- [% FOREACH item = table.col(3) %]
- [% item %]
- [% END %]
-
-=head2 URL
-
-The URL plugin provides a simple way of contructing URLs from a base
-part and a variable set of parameters. See L<Template::Plugin::URL>
-for further details.
-
- [% USE mycgi = url('/cgi-bin/bar.pl', debug=1) %]
-
- [% mycgi %]
- # ==> /cgi/bin/bar.pl?debug=1
-
- [% mycgi(mode='submit') %]
- # ==> /cgi/bin/bar.pl?mode=submit&debug=1
-
-=head2 Wrap
-
-The Wrap plugin uses the Text::Wrap module by David Muir Sharnoff
-E<lt>muir@idiom.comE<gt> (with help from Tim Pierce and many many others)
-to provide simple paragraph formatting. See L<Template::Plugin::Wrap>
-and L<Text::Wrap> for further details.
-
- [% USE wrap %]
- [% wrap(mytext, 40, '* ', ' ') %] # use wrap sub
- [% mytext FILTER wrap(40) -%] # or wrap FILTER
-
-The Text::Wrap module is available from CPAN:
-
- http://www.cpan.org/modules/by-module/Text/
-
-=head2 XML::DOM
-
-The XML::DOM plugin gives access to the XML Document Object Module via
-Clark Cooper E<lt>cooper@sch.ge.comE<gt> and Enno Derksen's
-E<lt>enno@att.comE<gt> XML::DOM module. See L<Template::Plugin::XML::DOM>
-and L<XML::DOM> for further details.
-
- [% USE dom = XML.DOM %]
- [% doc = dom.parse(filename) %]
-
- [% FOREACH node = doc.getElementsByTagName('CODEBASE') %]
- * [% node.getAttribute('href') %]
- [% END %]
-
-The plugin requires the XML::DOM module, available from CPAN:
-
- http://www.cpan.org/modules/by-module/XML/
-
-=head2 XML::RSS
-
-The XML::RSS plugin is a simple interface to Jonathan Eisenzopf's
-E<lt>eisen@pobox.comE<gt> XML::RSS module. A RSS (Rich Site Summary)
-file is typically used to store short news 'headlines' describing
-different links within a site. This plugin allows you to parse RSS
-files and format the contents accordingly using templates.
-See L<Template::Plugin::XML::RSS> and L<XML::RSS> for further details.
-
- [% USE news = XML.RSS(filename) %]
-
- [% FOREACH item = news.items %]
- <a href="[% item.link %]">[% item.title %]</a>
- [% END %]
-
-The XML::RSS module is available from CPAN:
-
- http://www.cpan.org/modules/by-module/XML/
-
-=head2 XML::Simple
-
-This plugin implements an interface to the L<XML::Simple|XML::Simple>
-module.
-
- [% USE xml = XML.Simple(xml_file_or_text) %]
-
- [% xml.head.title %]
-
-See L<Template::Plugin::XML::Simple> for further details.
-
-=head2 XML::Style
-
-This plugin defines a filter for performing simple stylesheet based
-transformations of XML text.
-
- [% USE xmlstyle
- table = {
- attributes = {
- border = 0
- cellpadding = 4
- cellspacing = 1
- }
- }
- %]
-
- [% FILTER xmlstyle %]
- <table>
- <tr>
- <td>Foo</td> <td>Bar</td> <td>Baz</td>
- </tr>
- </table>
- [% END %]
-
-See L<Template::Plugin::XML::Style> for further details.
-
-=head2 XML::XPath
-
-The XML::XPath plugin provides an interface to Matt Sergeant's
-E<lt>matt@sergeant.orgE<gt> XML::XPath module. See
-L<Template::Plugin::XML::XPath> and L<XML::XPath> for further details.
-
- [% USE xpath = XML.XPath(xmlfile) %]
- [% FOREACH page = xpath.findnodes('/html/body/page') %]
- [% page.getAttribute('title') %]
- [% END %]
-
-The plugin requires the XML::XPath module, available from CPAN:
-
- http://www.cpan.org/modules/by-module/XML/
-
-
-
-
-=head1 BUGS / ISSUES
-
-=over 4
-
-=item *
-
-It might be worthwhile being able to distinguish between absolute
-module names and those which should be applied relative to PLUGIN_BASE
-directories. For example, use 'MyNamespace::MyModule' to denote
-absolute module names (e.g. LOAD_PERL), and 'MyNamespace.MyModule' to
-denote relative to PLUGIN_BASE.
-
-=back
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.70, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template|Template>, L<Template::Plugin|Template::Plugin>, L<Template::Context|Template::Context>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Provider.pm b/lib/Template/Provider.pm
deleted file mode 100644
index 0826a18..0000000
--- a/lib/Template/Provider.pm
+++ /dev/null
@@ -1,1449 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Provider
-#
-# DESCRIPTION
-# This module implements a class which handles the loading, compiling
-# and caching of templates. Multiple Template::Provider objects can
-# be stacked and queried in turn to effect a Chain-of-Command between
-# them. A provider will attempt to return the requested template,
-# an error (STATUS_ERROR) or decline to provide the template
-# (STATUS_DECLINE), allowing subsequent providers to attempt to
-# deliver it. See 'Design Patterns' for further details.
-#
-# AUTHOR
-# Andy Wardley <abw@wardley.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2003 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-# TODO:
-# * optional provider prefix (e.g. 'http:')
-# * fold ABSOLUTE and RELATIVE test cases into one regex?
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Provider.pm,v 2.79 2004/01/13 16:19:16 abw Exp $
-#
-#============================================================================
-
-package Template::Provider;
-
-require 5.004;
-
-use strict;
-use vars qw( $VERSION $DEBUG $ERROR $DOCUMENT $STAT_TTL $MAX_DIRS );
-use base qw( Template::Base );
-use Template::Config;
-use Template::Constants;
-use Template::Document;
-use File::Basename;
-use File::Spec;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.79 $ =~ /(\d+)\.(\d+)/);
-
-# name of document class
-$DOCUMENT = 'Template::Document' unless defined $DOCUMENT;
-
-# maximum time between performing stat() on file to check staleness
-$STAT_TTL = 1 unless defined $STAT_TTL;
-
-# maximum number of directories in an INCLUDE_PATH, to prevent runaways
-$MAX_DIRS = 64 unless defined $MAX_DIRS;
-
-use constant PREV => 0;
-use constant NAME => 1;
-use constant DATA => 2;
-use constant LOAD => 3;
-use constant NEXT => 4;
-use constant STAT => 5;
-
-$DEBUG = 0 unless defined $DEBUG;
-
-#========================================================================
-# -- PUBLIC METHODS --
-#========================================================================
-
-#------------------------------------------------------------------------
-# fetch($name)
-#
-# Returns a compiled template for the name specified by parameter.
-# The template is returned from the internal cache if it exists, or
-# loaded and then subsequently cached. The ABSOLUTE and RELATIVE
-# configuration flags determine if absolute (e.g. '/something...')
-# and/or relative (e.g. './something') paths should be honoured. The
-# INCLUDE_PATH is otherwise used to find the named file. $name may
-# also be a reference to a text string containing the template text,
-# or a file handle from which the content is read. The compiled
-# template is not cached in these latter cases given that there is no
-# filename to cache under. A subsequent call to store($name,
-# $compiled) can be made to cache the compiled template for future
-# fetch() calls, if necessary.
-#
-# Returns a compiled template or (undef, STATUS_DECLINED) if the
-# template could not be found. On error (e.g. the file was found
-# but couldn't be read or parsed), the pair ($error, STATUS_ERROR)
-# is returned. The TOLERANT configuration option can be set to
-# downgrade any errors to STATUS_DECLINE.
-#------------------------------------------------------------------------
-
-sub fetch {
- my ($self, $name) = @_;
- my ($data, $error);
-
- if (ref $name) {
- # $name can be a reference to a scalar, GLOB or file handle
- ($data, $error) = $self->_load($name);
- ($data, $error) = $self->_compile($data)
- unless $error;
- $data = $data->{ data }
- unless $error;
- }
- elsif (File::Spec->file_name_is_absolute($name)) {
- # absolute paths (starting '/') allowed if ABSOLUTE set
- ($data, $error) = $self->{ ABSOLUTE }
- ? $self->_fetch($name)
- : $self->{ TOLERANT }
- ? (undef, Template::Constants::STATUS_DECLINED)
- : ("$name: absolute paths are not allowed (set ABSOLUTE option)",
- Template::Constants::STATUS_ERROR);
- }
- elsif ($name =~ m[^\.+/]) {
- # anything starting "./" is relative to cwd, allowed if RELATIVE set
- ($data, $error) = $self->{ RELATIVE }
- ? $self->_fetch($name)
- : $self->{ TOLERANT }
- ? (undef, Template::Constants::STATUS_DECLINED)
- : ("$name: relative paths are not allowed (set RELATIVE option)",
- Template::Constants::STATUS_ERROR);
- }
- else {
- # otherwise, it's a file name relative to INCLUDE_PATH
- ($data, $error) = $self->{ INCLUDE_PATH }
- ? $self->_fetch_path($name)
- : (undef, Template::Constants::STATUS_DECLINED);
- }
-
-# $self->_dump_cache()
-# if $DEBUG > 1;
-
- return ($data, $error);
-}
-
-
-#------------------------------------------------------------------------
-# store($name, $data)
-#
-# Store a compiled template ($data) in the cached as $name.
-#------------------------------------------------------------------------
-
-sub store {
- my ($self, $name, $data) = @_;
- $self->_store($name, {
- data => $data,
- load => 0,
- });
-}
-
-
-#------------------------------------------------------------------------
-# load($name)
-#
-# Load a template without parsing/compiling it, suitable for use with
-# the INSERT directive. There's some duplication with fetch() and at
-# some point this could be reworked to integrate them a little closer.
-#------------------------------------------------------------------------
-
-sub load {
- my ($self, $name) = @_;
- my ($data, $error);
- my $path = $name;
-
- if (File::Spec->file_name_is_absolute($name)) {
- # absolute paths (starting '/') allowed if ABSOLUTE set
- $error = "$name: absolute paths are not allowed (set ABSOLUTE option)"
- unless $self->{ ABSOLUTE };
- }
- elsif ($name =~ m[^\.+/]) {
- # anything starting "./" is relative to cwd, allowed if RELATIVE set
- $error = "$name: relative paths are not allowed (set RELATIVE option)"
- unless $self->{ RELATIVE };
- }
- else {
- INCPATH: {
- # otherwise, it's a file name relative to INCLUDE_PATH
- my $paths = $self->paths()
- || return ($self->error(), Template::Constants::STATUS_ERROR);
-
- foreach my $dir (@$paths) {
- $path = "$dir/$name";
- last INCPATH
- if -f $path;
- }
- undef $path; # not found
- }
- }
-
- if (defined $path && ! $error) {
- local $/ = undef; # slurp files in one go
- local *FH;
- if (open(FH, $path)) {
- $data = <FH>;
- close(FH);
- }
- else {
- $error = "$name: $!";
- }
- }
-
- if ($error) {
- return $self->{ TOLERANT }
- ? (undef, Template::Constants::STATUS_DECLINED)
- : ($error, Template::Constants::STATUS_ERROR);
- }
- elsif (! defined $path) {
- return (undef, Template::Constants::STATUS_DECLINED);
- }
- else {
- return ($data, Template::Constants::STATUS_OK);
- }
-}
-
-
-
-#------------------------------------------------------------------------
-# include_path(\@newpath)
-#
-# Accessor method for the INCLUDE_PATH setting. If called with an
-# argument, this method will replace the existing INCLUDE_PATH with
-# the new value.
-#------------------------------------------------------------------------
-
-sub include_path {
- my ($self, $path) = @_;
- $self->{ INCLUDE_PATH } = $path if $path;
- return $self->{ INCLUDE_PATH };
-}
-
-
-#------------------------------------------------------------------------
-# paths()
-#
-# Evaluates the INCLUDE_PATH list, ignoring any blank entries, and
-# calling and subroutine or object references to return dynamically
-# generated path lists. Returns a reference to a new list of paths
-# or undef on error.
-#------------------------------------------------------------------------
-
-sub paths {
- my $self = shift;
- my @ipaths = @{ $self->{ INCLUDE_PATH } };
- my (@opaths, $dpaths, $dir);
- my $count = $MAX_DIRS;
-
- while (@ipaths && --$count) {
- $dir = shift @ipaths || next;
-
- # $dir can be a sub or object ref which returns a reference
- # to a dynamically generated list of search paths.
-
- if (ref $dir eq 'CODE') {
- eval { $dpaths = &$dir() };
- if ($@) {
- chomp $@;
- return $self->error($@);
- }
- unshift(@ipaths, @$dpaths);
- next;
- }
- elsif (UNIVERSAL::can($dir, 'paths')) {
- $dpaths = $dir->paths()
- || return $self->error($dir->error());
- unshift(@ipaths, @$dpaths);
- next;
- }
- else {
- push(@opaths, $dir);
- }
- }
- return $self->error("INCLUDE_PATH exceeds $MAX_DIRS directories")
- if @ipaths;
-
- return \@opaths;
-}
-
-
-#------------------------------------------------------------------------
-# DESTROY
-#
-# The provider cache is implemented as a doubly linked list which Perl
-# cannot free by itself due to the circular references between NEXT <=>
-# PREV items. This cleanup method walks the list deleting all the NEXT/PREV
-# references, allowing the proper cleanup to occur and memory to be
-# repooled.
-#------------------------------------------------------------------------
-
-sub DESTROY {
- my $self = shift;
- my ($slot, $next);
-
- $slot = $self->{ HEAD };
- while ($slot) {
- $next = $slot->[ NEXT ];
- undef $slot->[ PREV ];
- undef $slot->[ NEXT ];
- $slot = $next;
- }
- undef $self->{ HEAD };
- undef $self->{ TAIL };
-}
-
-
-
-
-#========================================================================
-# -- PRIVATE METHODS --
-#========================================================================
-
-#------------------------------------------------------------------------
-# _init()
-#
-# Initialise the cache.
-#------------------------------------------------------------------------
-
-sub _init {
- my ($self, $params) = @_;
- my $size = $params->{ CACHE_SIZE };
- my $path = $params->{ INCLUDE_PATH } || '.';
- my $cdir = $params->{ COMPILE_DIR } || '';
- my $dlim = $params->{ DELIMITER };
- my $debug;
-
- # tweak delim to ignore C:/
- unless (defined $dlim) {
- $dlim = ($^O eq 'MSWin32') ? ':(?!\\/)' : ':';
- }
-
- # coerce INCLUDE_PATH to an array ref, if not already so
- $path = [ split(/$dlim/, $path) ]
- unless ref $path eq 'ARRAY';
-
- # don't allow a CACHE_SIZE 1 because it breaks things and the
- # additional checking isn't worth it
- $size = 2
- if defined $size && ($size == 1 || $size < 0);
-
- if (defined ($debug = $params->{ DEBUG })) {
- $self->{ DEBUG } = $debug & ( Template::Constants::DEBUG_PROVIDER
- | Template::Constants::DEBUG_FLAGS );
- }
- else {
- $self->{ DEBUG } = $DEBUG;
- }
-
- if ($self->{ DEBUG }) {
- local $" = ', ';
- $self->debug("creating cache of ",
- defined $size ? $size : 'unlimited',
- " slots for [ @$path ]");
- }
-
- # create COMPILE_DIR and sub-directories representing each INCLUDE_PATH
- # element in which to store compiled files
- if ($cdir) {
-
-# Stas' hack
-# # this is a hack to solve the problem with INCLUDE_PATH using
-# # relative dirs
-# my $segments = 0;
-# for (@$path) {
-# my $c = 0;
-# $c++ while m|\.\.|g;
-# $segments = $c if $c > $segments;
-# }
-# $cdir .= "/".join "/",('hack') x $segments if $segments;
-#
-
- require File::Path;
- foreach my $dir (@$path) {
- next if ref $dir;
- my $wdir = $dir;
- $wdir =~ s[:][]g if $^O eq 'MSWin32';
- $wdir =~ /(.*)/; # untaint
- &File::Path::mkpath(File::Spec->catfile($cdir, $1));
- }
- }
-
- $self->{ LOOKUP } = { };
- $self->{ SLOTS } = 0;
- $self->{ SIZE } = $size;
- $self->{ INCLUDE_PATH } = $path;
- $self->{ DELIMITER } = $dlim;
- $self->{ COMPILE_DIR } = $cdir;
- $self->{ COMPILE_EXT } = $params->{ COMPILE_EXT } || '';
- $self->{ ABSOLUTE } = $params->{ ABSOLUTE } || 0;
- $self->{ RELATIVE } = $params->{ RELATIVE } || 0;
- $self->{ TOLERANT } = $params->{ TOLERANT } || 0;
- $self->{ DOCUMENT } = $params->{ DOCUMENT } || $DOCUMENT;
- $self->{ PARSER } = $params->{ PARSER };
- $self->{ DEFAULT } = $params->{ DEFAULT };
-# $self->{ PREFIX } = $params->{ PREFIX };
- $self->{ PARAMS } = $params;
-
- return $self;
-}
-
-
-#------------------------------------------------------------------------
-# _fetch($name)
-#
-# Fetch a file from cache or disk by specification of an absolute or
-# relative filename. No search of the INCLUDE_PATH is made. If the
-# file is found and loaded, it is compiled and cached.
-#------------------------------------------------------------------------
-
-sub _fetch {
- my ($self, $name) = @_;
- my $size = $self->{ SIZE };
- my ($slot, $data, $error);
-
- $self->debug("_fetch($name)") if $self->{ DEBUG };
-
- my $compiled = $self->_compiled_filename($name);
-
- if (defined $size && ! $size) {
- # caching disabled so load and compile but don't cache
- if ($compiled && -f $compiled
- && (stat($name))[9] <= (stat($compiled))[9]) {
- $data = $self->_load_compiled($compiled);
- $error = $self->error() unless $data;
- }
- else {
- ($data, $error) = $self->_load($name);
- ($data, $error) = $self->_compile($data, $compiled)
- unless $error;
- $data = $data->{ data }
- unless $error;
- }
- }
- elsif ($slot = $self->{ LOOKUP }->{ $name }) {
- # cached entry exists, so refresh slot and extract data
- ($data, $error) = $self->_refresh($slot);
- $data = $slot->[ DATA ]
- unless $error;
- }
- else {
- # nothing in cache so try to load, compile and cache
- if ($compiled && -f $compiled
- && (stat($name))[9] <= (stat($compiled))[9]) {
- $data = $self->_load_compiled($compiled);
- $error = $self->error() unless $data;
- $self->store($name, $data) unless $error;
- }
- else {
- ($data, $error) = $self->_load($name);
- ($data, $error) = $self->_compile($data, $compiled)
- unless $error;
- $data = $self->_store($name, $data)
- unless $error;
- }
- }
-
- return ($data, $error);
-}
-
-
-#------------------------------------------------------------------------
-# _fetch_path($name)
-#
-# Fetch a file from cache or disk by specification of an absolute cache
-# name (e.g. 'header') or filename relative to one of the INCLUDE_PATH
-# directories. If the file isn't already cached and can be found and
-# loaded, it is compiled and cached under the full filename.
-#------------------------------------------------------------------------
-
-sub _fetch_path {
- my ($self, $name) = @_;
- my ($size, $compext, $compdir) =
- @$self{ qw( SIZE COMPILE_EXT COMPILE_DIR ) };
- my ($dir, $paths, $path, $compiled, $slot, $data, $error);
- local *FH;
-
- $self->debug("_fetch_path($name)") if $self->{ DEBUG };
-
- # caching is enabled if $size is defined and non-zero or undefined
- my $caching = (! defined $size || $size);
-
- INCLUDE: {
-
- # the template may have been stored using a non-filename name
- if ($caching && ($slot = $self->{ LOOKUP }->{ $name })) {
- # cached entry exists, so refresh slot and extract data
- ($data, $error) = $self->_refresh($slot);
- $data = $slot->[ DATA ]
- unless $error;
- last INCLUDE;
- }
-
- $paths = $self->paths() || do {
- $error = Template::Constants::STATUS_ERROR;
- $data = $self->error();
- last INCLUDE;
- };
-
- # search the INCLUDE_PATH for the file, in cache or on disk
- foreach $dir (@$paths) {
- $path = File::Spec->catfile($dir, $name);
-
- $self->debug("searching path: $path\n") if $self->{ DEBUG };
-
- if ($caching && ($slot = $self->{ LOOKUP }->{ $path })) {
- # cached entry exists, so refresh slot and extract data
- ($data, $error) = $self->_refresh($slot);
- $data = $slot->[ DATA ]
- unless $error;
- last INCLUDE;
- }
- elsif (-f $path) {
- $compiled = $self->_compiled_filename($path)
- if $compext || $compdir;
-
- if ($compiled && -f $compiled
- && (stat($path))[9] <= (stat($compiled))[9]) {
- if ($data = $self->_load_compiled($compiled)) {
- # store in cache
- $data = $self->store($path, $data);
- $error = Template::Constants::STATUS_OK;
- last INCLUDE;
- }
- else {
- warn($self->error(), "\n");
- }
- }
- # $compiled is set if an attempt to write the compiled
- # template to disk should be made
-
- ($data, $error) = $self->_load($path, $name);
- ($data, $error) = $self->_compile($data, $compiled)
- unless $error;
- $data = $self->_store($path, $data)
- unless $error || ! $caching;
- $data = $data->{ data } if ! $caching;
- # all done if $error is OK or ERROR
- last INCLUDE if ! $error
- || $error == Template::Constants::STATUS_ERROR;
- }
- }
- # template not found, so look for a DEFAULT template
- my $default;
- if (defined ($default = $self->{ DEFAULT }) && $name ne $default) {
- $name = $default;
- redo INCLUDE;
- }
- ($data, $error) = (undef, Template::Constants::STATUS_DECLINED);
- } # INCLUDE
-
- return ($data, $error);
-}
-
-
-
-sub _compiled_filename {
- my ($self, $file) = @_;
- my ($compext, $compdir) = @$self{ qw( COMPILE_EXT COMPILE_DIR ) };
- my ($path, $compiled);
-
- return undef
- unless $compext || $compdir;
-
- $path = $file;
- $path =~ /^(.+)$/s or die "invalid filename: $path";
- $path =~ s[:][]g if $^O eq 'MSWin32';
-
- $compiled = "$path$compext";
- $compiled = File::Spec->catfile($compdir, $compiled) if length $compdir;
-
- return $compiled;
-}
-
-
-sub _load_compiled {
- my ($self, $file) = @_;
- my $compiled;
-
- # load compiled template via require(); we zap any
- # %INC entry to ensure it is reloaded (we don't
- # want 1 returned by require() to say it's in memory)
- delete $INC{ $file };
- eval { $compiled = require $file; };
- return $@
- ? $self->error("compiled template $compiled: $@")
- : $compiled;
-}
-
-
-
-#------------------------------------------------------------------------
-# _load($name, $alias)
-#
-# Load template text from a string ($name = scalar ref), GLOB or file
-# handle ($name = ref), or from an absolute filename ($name = scalar).
-# Returns a hash array containing the following items:
-# name filename or $alias, if provided, or 'input text', etc.
-# text template text
-# time modification time of file, or current time for handles/strings
-# load time file was loaded (now!)
-#
-# On error, returns ($error, STATUS_ERROR), or (undef, STATUS_DECLINED)
-# if TOLERANT is set.
-#------------------------------------------------------------------------
-
-sub _load {
- my ($self, $name, $alias) = @_;
- my ($data, $error);
- my $tolerant = $self->{ TOLERANT };
- my $now = time;
- local $/ = undef; # slurp files in one go
- local *FH;
-
- $alias = $name unless defined $alias or ref $name;
-
- $self->debug("_load($name, ", defined $alias ? $alias : '<no alias>',
- ')') if $self->{ DEBUG };
-
- LOAD: {
- if (ref $name eq 'SCALAR') {
- # $name can be a SCALAR reference to the input text...
- $data = {
- name => defined $alias ? $alias : 'input text',
- text => $$name,
- time => $now,
- load => 0,
- };
- }
- elsif (ref $name) {
- # ...or a GLOB or file handle...
- my $text = <$name>;
- $data = {
- name => defined $alias ? $alias : 'input file handle',
- text => $text,
- time => $now,
- load => 0,
- };
- }
- elsif (-f $name) {
- if (open(FH, $name)) {
- my $text = <FH>;
- $data = {
- name => $alias,
- path => $name,
- text => $text,
- time => (stat $name)[9],
- load => $now,
- };
- }
- elsif ($tolerant) {
- ($data, $error) = (undef, Template::Constants::STATUS_DECLINED);
- }
- else {
- $data = "$alias: $!";
- $error = Template::Constants::STATUS_ERROR;
- }
- }
- else {
- ($data, $error) = (undef, Template::Constants::STATUS_DECLINED);
- }
- }
-
- $data->{ path } = $data->{ name }
- if $data and ! defined $data->{ path };
-
- return ($data, $error);
-}
-
-
-#------------------------------------------------------------------------
-# _refresh(\@slot)
-#
-# Private method called to mark a cache slot as most recently used.
-# A reference to the slot array should be passed by parameter. The
-# slot is relocated to the head of the linked list. If the file from
-# which the data was loaded has been upated since it was compiled, then
-# it is re-loaded from disk and re-compiled.
-#------------------------------------------------------------------------
-
-sub _refresh {
- my ($self, $slot) = @_;
- my ($head, $file, $data, $error);
-
-
- $self->debug("_refresh([ ",
- join(', ', map { defined $_ ? $_ : '<undef>' } @$slot),
- '])') if $self->{ DEBUG };
-
- # if it's more than $STAT_TTL seconds since we last performed a
- # stat() on the file then we need to do it again and see if the file
- # time has changed
- if ( (time - $slot->[ STAT ]) > $STAT_TTL && stat $slot->[ NAME ] ) {
- $slot->[ STAT ] = time;
-
- if ( (stat(_))[9] != $slot->[ LOAD ]) {
-
- $self->debug("refreshing cache file ", $slot->[ NAME ])
- if $self->{ DEBUG };
-
- ($data, $error) = $self->_load($slot->[ NAME ],
- $slot->[ DATA ]->{ name });
- ($data, $error) = $self->_compile($data)
- unless $error;
-
- unless ($error) {
- $slot->[ DATA ] = $data->{ data };
- $slot->[ LOAD ] = $data->{ time };
- }
- }
- }
-
- unless( $self->{ HEAD } == $slot ) {
- # remove existing slot from usage chain...
- if ($slot->[ PREV ]) {
- $slot->[ PREV ]->[ NEXT ] = $slot->[ NEXT ];
- }
- else {
- $self->{ HEAD } = $slot->[ NEXT ];
- }
- if ($slot->[ NEXT ]) {
- $slot->[ NEXT ]->[ PREV ] = $slot->[ PREV ];
- }
- else {
- $self->{ TAIL } = $slot->[ PREV ];
- }
-
- # ..and add to start of list
- $head = $self->{ HEAD };
- $head->[ PREV ] = $slot if $head;
- $slot->[ PREV ] = undef;
- $slot->[ NEXT ] = $head;
- $self->{ HEAD } = $slot;
- }
-
- return ($data, $error);
-}
-
-
-#------------------------------------------------------------------------
-# _store($name, $data)
-#
-# Private method called to add a data item to the cache. If the cache
-# size limit has been reached then the oldest entry at the tail of the
-# list is removed and its slot relocated to the head of the list and
-# reused for the new data item. If the cache is under the size limit,
-# or if no size limit is defined, then the item is added to the head
-# of the list.
-#------------------------------------------------------------------------
-
-sub _store {
- my ($self, $name, $data, $compfile) = @_;
- my $size = $self->{ SIZE };
- my ($slot, $head);
-
- # extract the load time and compiled template from the data
-# my $load = $data->{ load };
- my $load = (stat($name))[9];
- $data = $data->{ data };
-
- $self->debug("_store($name, $data)") if $self->{ DEBUG };
-
- if (defined $size && $self->{ SLOTS } >= $size) {
- # cache has reached size limit, so reuse oldest entry
-
- $self->debug("reusing oldest cache entry (size limit reached: $size)\nslots: $self->{ SLOTS }") if $self->{ DEBUG };
-
- # remove entry from tail of list
- $slot = $self->{ TAIL };
- $slot->[ PREV ]->[ NEXT ] = undef;
- $self->{ TAIL } = $slot->[ PREV ];
-
- # remove name lookup for old node
- delete $self->{ LOOKUP }->{ $slot->[ NAME ] };
-
- # add modified node to head of list
- $head = $self->{ HEAD };
- $head->[ PREV ] = $slot if $head;
- @$slot = ( undef, $name, $data, $load, $head, time );
- $self->{ HEAD } = $slot;
-
- # add name lookup for new node
- $self->{ LOOKUP }->{ $name } = $slot;
- }
- else {
- # cache is under size limit, or none is defined
-
- $self->debug("adding new cache entry") if $self->{ DEBUG };
-
- # add new node to head of list
- $head = $self->{ HEAD };
- $slot = [ undef, $name, $data, $load, $head, time ];
- $head->[ PREV ] = $slot if $head;
- $self->{ HEAD } = $slot;
- $self->{ TAIL } = $slot unless $self->{ TAIL };
-
- # add lookup from name to slot and increment nslots
- $self->{ LOOKUP }->{ $name } = $slot;
- $self->{ SLOTS }++;
- }
-
- return $data;
-}
-
-
-#------------------------------------------------------------------------
-# _compile($data)
-#
-# Private method called to parse the template text and compile it into
-# a runtime form. Creates and delegates a Template::Parser object to
-# handle the compilation, or uses a reference passed in PARSER. On
-# success, the compiled template is stored in the 'data' item of the
-# $data hash and returned. On error, ($error, STATUS_ERROR) is returned,
-# or (undef, STATUS_DECLINED) if the TOLERANT flag is set.
-# The optional $compiled parameter may be passed to specify
-# the name of a compiled template file to which the generated Perl
-# code should be written. Errors are (for now...) silently
-# ignored, assuming that failures to open a file for writing are
-# intentional (e.g directory write permission).
-#------------------------------------------------------------------------
-
-sub _compile {
- my ($self, $data, $compfile) = @_;
- my $text = $data->{ text };
- my ($parsedoc, $error);
-
- $self->debug("_compile($data, ",
- defined $compfile ? $compfile : '<no compfile>', ')')
- if $self->{ DEBUG };
-
- my $parser = $self->{ PARSER }
- ||= Template::Config->parser($self->{ PARAMS })
- || return (Template::Config->error(), Template::Constants::STATUS_ERROR);
-
- # discard the template text - we don't need it any more
- delete $data->{ text };
-
- # call parser to compile template into Perl code
- if ($parsedoc = $parser->parse($text, $data)) {
-
- $parsedoc->{ METADATA } = {
- 'name' => $data->{ name },
- 'modtime' => $data->{ time },
- %{ $parsedoc->{ METADATA } },
- };
-
- # write the Perl code to the file $compfile, if defined
- if ($compfile) {
- my $basedir = &File::Basename::dirname($compfile);
- $basedir =~ /(.*)/;
- $basedir = $1;
- &File::Path::mkpath($basedir) unless -d $basedir;
-
- my $docclass = $self->{ DOCUMENT };
- $error = 'cache failed to write '
- . &File::Basename::basename($compfile)
- . ': ' . $docclass->error()
- unless $docclass->write_perl_file($compfile, $parsedoc);
-
- # set atime and mtime of newly compiled file, don't bother
- # if time is undef
- if (!defined($error) && defined $data->{ time }) {
- my ($cfile) = $compfile =~ /^(.+)$/s or do {
- return("invalid filename: $compfile",
- Template::Constants::STATUS_ERROR);
- };
-
- my ($ctime) = $data->{ time } =~ /^(\d+)$/;
- unless ($ctime || $ctime eq 0) {
- return("invalid time: $ctime",
- Template::Constants::STATUS_ERROR);
- }
- utime($ctime, $ctime, $cfile);
- }
- }
-
- unless ($error) {
- return $data ## RETURN ##
- if $data->{ data } = $DOCUMENT->new($parsedoc);
- $error = $Template::Document::ERROR;
- }
- }
- else {
- $error = Template::Exception->new( 'parse', "$data->{ name } " .
- $parser->error() );
- }
-
- # return STATUS_ERROR, or STATUS_DECLINED if we're being tolerant
- return $self->{ TOLERANT }
- ? (undef, Template::Constants::STATUS_DECLINED)
- : ($error, Template::Constants::STATUS_ERROR)
-}
-
-
-#------------------------------------------------------------------------
-# _dump()
-#
-# Debug method which returns a string representing the internal object
-# state.
-#------------------------------------------------------------------------
-
-sub _dump {
- my $self = shift;
- my $size = $self->{ SIZE };
- my $parser = $self->{ PARSER };
- $parser = $parser ? $parser->_dump() : '<no parser>';
- $parser =~ s/\n/\n /gm;
- $size = 'unlimited' unless defined $size;
-
- my $output = "[Template::Provider] {\n";
- my $format = " %-16s => %s\n";
- my $key;
-
- $output .= sprintf($format, 'INCLUDE_PATH',
- '[ ' . join(', ', @{ $self->{ INCLUDE_PATH } }) . ' ]');
- $output .= sprintf($format, 'CACHE_SIZE', $size);
-
- foreach $key (qw( ABSOLUTE RELATIVE TOLERANT DELIMITER
- COMPILE_EXT COMPILE_DIR )) {
- $output .= sprintf($format, $key, $self->{ $key });
- }
- $output .= sprintf($format, 'PARSER', $parser);
-
-
- local $" = ', ';
- my $lookup = $self->{ LOOKUP };
- $lookup = join('', map {
- sprintf(" $format", $_, defined $lookup->{ $_ }
- ? ('[ ' . join(', ', map { defined $_ ? $_ : '<undef>' }
- @{ $lookup->{ $_ } }) . ' ]') : '<undef>');
- } sort keys %$lookup);
- $lookup = "{\n$lookup }";
-
- $output .= sprintf($format, LOOKUP => $lookup);
-
- $output .= '}';
- return $output;
-}
-
-
-#------------------------------------------------------------------------
-# _dump_cache()
-#
-# Debug method which prints the current state of the cache to STDERR.
-#------------------------------------------------------------------------
-
-sub _dump_cache {
- my $self = shift;
- my ($node, $lut, $count);
-
- $count = 0;
- if ($node = $self->{ HEAD }) {
- while ($node) {
- $lut->{ $node } = $count++;
- $node = $node->[ NEXT ];
- }
- $node = $self->{ HEAD };
- print STDERR "CACHE STATE:\n";
- print STDERR " HEAD: ", $self->{ HEAD }->[ NAME ], "\n";
- print STDERR " TAIL: ", $self->{ TAIL }->[ NAME ], "\n";
- while ($node) {
- my ($prev, $name, $data, $load, $next) = @$node;
-# $name = '...' . substr($name, -10) if length $name > 10;
- $prev = $prev ? "#$lut->{ $prev }<-": '<undef>';
- $next = $next ? "->#$lut->{ $next }": '<undef>';
- print STDERR " #$lut->{ $node } : [ $prev, $name, $data, $load, $next ]\n";
- $node = $node->[ NEXT ];
- }
- }
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Provider - Provider module for loading/compiling templates
-
-=head1 SYNOPSIS
-
- $provider = Template::Provider->new(\%options);
-
- ($template, $error) = $provider->fetch($name);
-
-=head1 DESCRIPTION
-
-The Template::Provider is used to load, parse, compile and cache template
-documents. This object may be sub-classed to provide more specific
-facilities for loading, or otherwise providing access to templates.
-
-The Template::Context objects maintain a list of Template::Provider
-objects which are polled in turn (via fetch()) to return a requested
-template. Each may return a compiled template, raise an error, or
-decline to serve the reqest, giving subsequent providers a chance to
-do so.
-
-This is the "Chain of Responsiblity" pattern. See 'Design Patterns' for
-further information.
-
-This documentation needs work.
-
-=head1 PUBLIC METHODS
-
-=head2 new(\%options)
-
-Constructor method which instantiates and returns a new Template::Provider
-object. The optional parameter may be a hash reference containing any of
-the following items:
-
-=over 4
-
-
-
-
-=item INCLUDE_PATH
-
-The INCLUDE_PATH is used to specify one or more directories in which
-template files are located. When a template is requested that isn't
-defined locally as a BLOCK, each of the INCLUDE_PATH directories is
-searched in turn to locate the template file. Multiple directories
-can be specified as a reference to a list or as a single string where
-each directory is delimited by ':'.
-
- my $provider = Template::Provider->new({
- INCLUDE_PATH => '/usr/local/templates',
- });
-
- my $provider = Template::Provider->new({
- INCLUDE_PATH => '/usr/local/templates:/tmp/my/templates',
- });
-
- my $provider = Template::Provider->new({
- INCLUDE_PATH => [ '/usr/local/templates',
- '/tmp/my/templates' ],
- });
-
-On Win32 systems, a little extra magic is invoked, ignoring delimiters
-that have ':' followed by a '/' or '\'. This avoids confusion when using
-directory names like 'C:\Blah Blah'.
-
-When specified as a list, the INCLUDE_PATH path can contain elements
-which dynamically generate a list of INCLUDE_PATH directories. These
-generator elements can be specified as a reference to a subroutine or
-an object which implements a paths() method.
-
- my $provider = Template::Provider->new({
- INCLUDE_PATH => [ '/usr/local/templates',
- \&incpath_generator,
- My::IncPath::Generator->new( ... ) ],
- });
-
-Each time a template is requested and the INCLUDE_PATH examined, the
-subroutine or object method will be called. A reference to a list of
-directories should be returned. Generator subroutines should report
-errors using die(). Generator objects should return undef and make an
-error available via its error() method.
-
-For example:
-
- sub incpath_generator {
-
- # ...some code...
-
- if ($all_is_well) {
- return \@list_of_directories;
- }
- else {
- die "cannot generate INCLUDE_PATH...\n";
- }
- }
-
-or:
-
- package My::IncPath::Generator;
-
- # Template::Base (or Class::Base) provides error() method
- use Template::Base;
- use base qw( Template::Base );
-
- sub paths {
- my $self = shift;
-
- # ...some code...
-
- if ($all_is_well) {
- return \@list_of_directories;
- }
- else {
- return $self->error("cannot generate INCLUDE_PATH...\n");
- }
- }
-
- 1;
-
-
-
-
-
-=item DELIMITER
-
-Used to provide an alternative delimiter character sequence for
-separating paths specified in the INCLUDE_PATH. The default
-value for DELIMITER is ':'.
-
- # tolerate Silly Billy's file system conventions
- my $provider = Template::Provider->new({
- DELIMITER => '; ',
- INCLUDE_PATH => 'C:/HERE/NOW; D:/THERE/THEN',
- });
-
- # better solution: install Linux! :-)
-
-On Win32 systems, the default delimiter is a little more intelligent,
-splitting paths only on ':' characters that aren't followed by a '/'.
-This means that the following should work as planned, splitting the
-INCLUDE_PATH into 2 separate directories, C:/foo and C:/bar.
-
- # on Win32 only
- my $provider = Template::Provider->new({
- INCLUDE_PATH => 'C:/Foo:C:/Bar'
- });
-
-However, if you're using Win32 then it's recommended that you
-explicitly set the DELIMITER character to something else (e.g. ';')
-rather than rely on this subtle magic.
-
-
-
-
-=item ABSOLUTE
-
-The ABSOLUTE flag is used to indicate if templates specified with
-absolute filenames (e.g. '/foo/bar') should be processed. It is
-disabled by default and any attempt to load a template by such a
-name will cause a 'file' exception to be raised.
-
- my $provider = Template::Provider->new({
- ABSOLUTE => 1,
- });
-
- # this is why it's disabled by default
- [% INSERT /etc/passwd %]
-
-On Win32 systems, the regular expression for matching absolute
-pathnames is tweaked slightly to also detect filenames that start
-with a driver letter and colon, such as:
-
- C:/Foo/Bar
-
-
-
-
-
-
-=item RELATIVE
-
-The RELATIVE flag is used to indicate if templates specified with
-filenames relative to the current directory (e.g. './foo/bar' or
-'../../some/where/else') should be loaded. It is also disabled by
-default, and will raise a 'file' error if such template names are
-encountered.
-
- my $provider = Template::Provider->new({
- RELATIVE => 1,
- });
-
- [% INCLUDE ../logs/error.log %]
-
-
-
-
-
-=item DEFAULT
-
-The DEFAULT option can be used to specify a default template which should
-be used whenever a specified template can't be found in the INCLUDE_PATH.
-
- my $provider = Template::Provider->new({
- DEFAULT => 'notfound.html',
- });
-
-If a non-existant template is requested through the Template process()
-method, or by an INCLUDE, PROCESS or WRAPPER directive, then the
-DEFAULT template will instead be processed, if defined. Note that the
-DEFAULT template is not used when templates are specified with
-absolute or relative filenames, or as a reference to a input file
-handle or text string.
-
-
-
-
-
-=item CACHE_SIZE
-
-The Template::Provider module caches compiled templates to avoid the need
-to re-parse template files or blocks each time they are used. The CACHE_SIZE
-option is used to limit the number of compiled templates that the module
-should cache.
-
-By default, the CACHE_SIZE is undefined and all compiled templates are
-cached. When set to any positive value, the cache will be limited to
-storing no more than that number of compiled templates. When a new
-template is loaded and compiled and the cache is full (i.e. the number
-of entries == CACHE_SIZE), the least recently used compiled template
-is discarded to make room for the new one.
-
-The CACHE_SIZE can be set to 0 to disable caching altogether.
-
- my $provider = Template::Provider->new({
- CACHE_SIZE => 64, # only cache 64 compiled templates
- });
-
- my $provider = Template::Provider->new({
- CACHE_SIZE => 0, # don't cache any compiled templates
- });
-
-
-
-
-
-
-=item COMPILE_EXT
-
-From version 2 onwards, the Template Toolkit has the ability to
-compile templates to Perl code and save them to disk for subsequent
-use (i.e. cache persistence). The COMPILE_EXT option may be
-provided to specify a filename extension for compiled template files.
-It is undefined by default and no attempt will be made to read or write
-any compiled template files.
-
- my $provider = Template::Provider->new({
- COMPILE_EXT => '.ttc',
- });
-
-If COMPILE_EXT is defined (and COMPILE_DIR isn't, see below) then compiled
-template files with the COMPILE_EXT extension will be written to the same
-directory from which the source template files were loaded.
-
-Compiling and subsequent reuse of templates happens automatically
-whenever the COMPILE_EXT or COMPILE_DIR options are set. The Template
-Toolkit will automatically reload and reuse compiled files when it
-finds them on disk. If the corresponding source file has been modified
-since the compiled version as written, then it will load and re-compile
-the source and write a new compiled version to disk.
-
-This form of cache persistence offers significant benefits in terms of
-time and resources required to reload templates. Compiled templates can
-be reloaded by a simple call to Perl's require(), leaving Perl to handle
-all the parsing and compilation. This is a Good Thing.
-
-=item COMPILE_DIR
-
-The COMPILE_DIR option is used to specify an alternate directory root
-under which compiled template files should be saved.
-
- my $provider = Template::Provider->new({
- COMPILE_DIR => '/tmp/ttc',
- });
-
-The COMPILE_EXT option may also be specified to have a consistent file
-extension added to these files.
-
- my $provider1 = Template::Provider->new({
- COMPILE_DIR => '/tmp/ttc',
- COMPILE_EXT => '.ttc1',
- });
-
- my $provider2 = Template::Provider->new({
- COMPILE_DIR => '/tmp/ttc',
- COMPILE_EXT => '.ttc2',
- });
-
-
-When COMPILE_EXT is undefined, the compiled template files have the
-same name as the original template files, but reside in a different
-directory tree.
-
-Each directory in the INCLUDE_PATH is replicated in full beneath the
-COMPILE_DIR directory. This example:
-
- my $provider = Template::Provider->new({
- COMPILE_DIR => '/tmp/ttc',
- INCLUDE_PATH => '/home/abw/templates:/usr/share/templates',
- });
-
-would create the following directory structure:
-
- /tmp/ttc/home/abw/templates/
- /tmp/ttc/usr/share/templates/
-
-Files loaded from different INCLUDE_PATH directories will have their
-compiled forms save in the relevant COMPILE_DIR directory.
-
-On Win32 platforms a filename may by prefixed by a drive letter and
-colon. e.g.
-
- C:/My Templates/header
-
-The colon will be silently stripped from the filename when it is added
-to the COMPILE_DIR value(s) to prevent illegal filename being generated.
-Any colon in COMPILE_DIR elements will be left intact. For example:
-
- # Win32 only
- my $provider = Template::Provider->new({
- DELIMITER => ';',
- COMPILE_DIR => 'C:/TT2/Cache',
- INCLUDE_PATH => 'C:/TT2/Templates;D:/My Templates',
- });
-
-This would create the following cache directories:
-
- C:/TT2/Cache/C/TT2/Templates
- C:/TT2/Cache/D/My Templates
-
-
-
-
-=item TOLERANT
-
-The TOLERANT flag is used by the various Template Toolkit provider
-modules (Template::Provider, Template::Plugins, Template::Filters) to
-control their behaviour when errors are encountered. By default, any
-errors are reported as such, with the request for the particular
-resource (template, plugin, filter) being denied and an exception
-raised. When the TOLERANT flag is set to any true values, errors will
-be silently ignored and the provider will instead return
-STATUS_DECLINED. This allows a subsequent provider to take
-responsibility for providing the resource, rather than failing the
-request outright. If all providers decline to service the request,
-either through tolerated failure or a genuine disinclination to
-comply, then a 'E<lt>resourceE<gt> not found' exception is raised.
-
-
-
-
-
-
-=item PARSER
-
-The Template::Parser module implements a parser object for compiling
-templates into Perl code which can then be executed. A default object
-of this class is created automatically and then used by the
-Template::Provider whenever a template is loaded and requires
-compilation. The PARSER option can be used to provide a reference to
-an alternate parser object.
-
- my $provider = Template::Provider->new({
- PARSER => MyOrg::Template::Parser->new({ ... }),
- });
-
-
-
-=item DEBUG
-
-The DEBUG option can be used to enable debugging messages from the
-Template::Provider module by setting it to include the DEBUG_PROVIDER
-value.
-
- use Template::Constants qw( :debug );
-
- my $template = Template->new({
- DEBUG => DEBUG_PROVIDER,
- });
-
-
-
-=back
-
-=head2 fetch($name)
-
-Returns a compiled template for the name specified. If the template
-cannot be found then (undef, STATUS_DECLINED) is returned. If an error
-occurs (e.g. read error, parse error) then ($error, STATUS_ERROR) is
-returned, where $error is the error message generated. If the TOLERANT
-flag is set the the method returns (undef, STATUS_DECLINED) instead of
-returning an error.
-
-=head2 store($name, $template)
-
-Stores the compiled template, $template, in the cache under the name,
-$name. Susbequent calls to fetch($name) will return this template in
-preference to any disk-based file.
-
-=head2 include_path(\@newpath))
-
-Accessor method for the INCLUDE_PATH setting. If called with an
-argument, this method will replace the existing INCLUDE_PATH with
-the new value.
-
-=head2 paths()
-
-This method generates a copy of the INCLUDE_PATH list. Any elements in the
-list which are dynamic generators (e.g. references to subroutines or objects
-implementing a paths() method) will be called and the list of directories
-returned merged into the output list.
-
-It is possible to provide a generator which returns itself, thus sending
-this method into an infinite loop. To detect and prevent this from happening,
-the C<$MAX_DIRS> package variable, set to 64 by default, limits the maximum
-number of paths that can be added to, or generated for the output list. If
-this number is exceeded then the method will immediately return an error
-reporting as much.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.79, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template|Template>, L<Template::Parser|Template::Parser>, L<Template::Context|Template::Context>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Service.pm b/lib/Template/Service.pm
deleted file mode 100644
index fb5590a..0000000
--- a/lib/Template/Service.pm
+++ /dev/null
@@ -1,775 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Service
-#
-# DESCRIPTION
-# Module implementing a template processing service which wraps a
-# template within PRE_PROCESS and POST_PROCESS templates and offers
-# ERROR recovery.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Service.pm,v 2.75 2004/01/13 16:19:16 abw Exp $
-#
-#============================================================================
-
-package Template::Service;
-
-require 5.004;
-
-use strict;
-use vars qw( $VERSION $DEBUG $ERROR );
-use base qw( Template::Base );
-use Template::Base;
-use Template::Config;
-use Template::Exception;
-use Template::Constants;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.75 $ =~ /(\d+)\.(\d+)/);
-$DEBUG = 0 unless defined $DEBUG;
-
-
-#========================================================================
-# ----- PUBLIC METHODS -----
-#========================================================================
-
-#------------------------------------------------------------------------
-# process($template, \%params)
-#
-# Process a template within a service framework. A service may encompass
-# PRE_PROCESS and POST_PROCESS templates and an ERROR hash which names
-# templates to be substituted for the main template document in case of
-# error. Each service invocation begins by resetting the state of the
-# context object via a call to reset(). The AUTO_RESET option may be set
-# to 0 (default: 1) to bypass this step.
-#------------------------------------------------------------------------
-
-sub process {
- my ($self, $template, $params) = @_;
- my $context = $self->{ CONTEXT };
- my ($name, $output, $procout, $error);
- $output = '';
-
- $self->debug("process($template, ",
- defined $params ? $params : '<no params>',
- ')') if $self->{ DEBUG };
-
- $context->reset()
- if $self->{ AUTO_RESET };
-
- # pre-request compiled template from context so that we can alias it
- # in the stash for pre-processed templates to reference
- eval { $template = $context->template($template) };
- return $self->error($@)
- if $@;
-
- # localise the variable stash with any parameters passed
- # and set the 'template' variable
- $params ||= { };
- $params->{ template } = $template
- unless ref $template eq 'CODE';
- $context->localise($params);
-
- SERVICE: {
- # PRE_PROCESS
- eval {
- foreach $name (@{ $self->{ PRE_PROCESS } }) {
- $self->debug("PRE_PROCESS: $name") if $self->{ DEBUG };
- $output .= $context->process($name);
- }
- };
- last SERVICE if ($error = $@);
-
- # PROCESS
- eval {
- foreach $name (@{ $self->{ PROCESS } || [ $template ] }) {
- $self->debug("PROCESS: $name") if $self->{ DEBUG };
- $procout .= $context->process($name);
- }
- };
- if ($error = $@) {
- last SERVICE
- unless defined ($procout = $self->_recover(\$error));
- }
-
- if (defined $procout) {
- # WRAPPER
- eval {
- foreach $name (reverse @{ $self->{ WRAPPER } }) {
- $self->debug("WRAPPER: $name") if $self->{ DEBUG };
- $procout = $context->process($name, { content => $procout });
- }
- };
- last SERVICE if ($error = $@);
- $output .= $procout;
- }
-
- # POST_PROCESS
- eval {
- foreach $name (@{ $self->{ POST_PROCESS } }) {
- $self->debug("POST_PROCESS: $name") if $self->{ DEBUG };
- $output .= $context->process($name);
- }
- };
- last SERVICE if ($error = $@);
- }
-
- $context->delocalise();
- delete $params->{ template };
-
- if ($error) {
-# $error = $error->as_string if ref $error;
- return $self->error($error);
- }
-
- return $output;
-}
-
-
-#------------------------------------------------------------------------
-# context()
-#
-# Returns the internal CONTEXT reference.
-#------------------------------------------------------------------------
-
-sub context {
- return $_[0]->{ CONTEXT };
-}
-
-
-#========================================================================
-# -- PRIVATE METHODS --
-#========================================================================
-
-sub _init {
- my ($self, $config) = @_;
- my ($item, $data, $context, $block, $blocks);
- my $delim = $config->{ DELIMITER };
- $delim = ':' unless defined $delim;
-
- # coerce PRE_PROCESS, PROCESS and POST_PROCESS to arrays if necessary,
- # by splitting on non-word characters
- foreach $item (qw( PRE_PROCESS PROCESS POST_PROCESS WRAPPER )) {
- $data = $config->{ $item };
- $self->{ $item } = [ ], next unless (defined $data);
- $data = [ split($delim, $data || '') ]
- unless ref $data eq 'ARRAY';
- $self->{ $item } = $data;
- }
- # unset PROCESS option unless explicitly specified in config
- $self->{ PROCESS } = undef
- unless defined $config->{ PROCESS };
-
- $self->{ ERROR } = $config->{ ERROR } || $config->{ ERRORS };
- $self->{ AUTO_RESET } = defined $config->{ AUTO_RESET }
- ? $config->{ AUTO_RESET } : 1;
- $self->{ DEBUG } = ( $config->{ DEBUG } || 0 )
- & Template::Constants::DEBUG_SERVICE;
-
- $context = $self->{ CONTEXT } = $config->{ CONTEXT }
- || Template::Config->context($config)
- || return $self->error(Template::Config->error);
-
- return $self;
-}
-
-
-#------------------------------------------------------------------------
-# _recover(\$exception)
-#
-# Examines the internal ERROR hash array to find a handler suitable
-# for the exception object passed by reference. Selecting the handler
-# is done by delegation to the exception's select_handler() method,
-# passing the set of handler keys as arguments. A 'default' handler
-# may also be provided. The handler value represents the name of a
-# template which should be processed.
-#------------------------------------------------------------------------
-
-sub _recover {
- my ($self, $error) = @_;
- my $context = $self->{ CONTEXT };
- my ($hkey, $handler, $output);
-
- # there shouldn't ever be a non-exception object received at this
- # point... unless a module like CGI::Carp messes around with the
- # DIE handler.
- return undef
- unless (ref $$error);
-
- # a 'stop' exception is thrown by [% STOP %] - we return the output
- # buffer stored in the exception object
- return $$error->text()
- if $$error->type() eq 'stop';
-
- my $handlers = $self->{ ERROR }
- || return undef; ## RETURN
-
- if (ref $handlers eq 'HASH') {
- if ($hkey = $$error->select_handler(keys %$handlers)) {
- $handler = $handlers->{ $hkey };
- $self->debug("using error handler for $hkey") if $self->{ DEBUG };
- }
- elsif ($handler = $handlers->{ default }) {
- # use default handler
- $self->debug("using default error handler") if $self->{ DEBUG };
- }
- else {
- return undef; ## RETURN
- }
- }
- else {
- $handler = $handlers;
- $self->debug("using default error handler") if $self->{ DEBUG };
- }
-
- eval { $handler = $context->template($handler) };
- if ($@) {
- $$error = $@;
- return undef; ## RETURN
- };
-
- $context->stash->set('error', $$error);
- eval {
- $output .= $context->process($handler);
- };
- if ($@) {
- $$error = $@;
- return undef; ## RETURN
- }
-
- return $output;
-}
-
-
-
-#------------------------------------------------------------------------
-# _dump()
-#
-# Debug method which return a string representing the internal object
-# state.
-#------------------------------------------------------------------------
-
-sub _dump {
- my $self = shift;
- my $context = $self->{ CONTEXT }->_dump();
- $context =~ s/\n/\n /gm;
-
- my $error = $self->{ ERROR };
- $error = join('',
- "{\n",
- (map { " $_ => $error->{ $_ }\n" }
- keys %$error),
- "}\n")
- if ref $error;
-
- local $" = ', ';
- return <<EOF;
-$self
-PRE_PROCESS => [ @{ $self->{ PRE_PROCESS } } ]
-POST_PROCESS => [ @{ $self->{ POST_PROCESS } } ]
-ERROR => $error
-CONTEXT => $context
-EOF
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Service - General purpose template processing service
-
-=head1 SYNOPSIS
-
- use Template::Service;
-
- my $service = Template::Service->new({
- PRE_PROCESS => [ 'config', 'header' ],
- POST_PROCESS => 'footer',
- ERROR => {
- user => 'user/index.html',
- dbi => 'error/database',
- default => 'error/default',
- },
- });
-
- my $output = $service->process($template_name, \%replace)
- || die $service->error(), "\n";
-
-=head1 DESCRIPTION
-
-The Template::Service module implements an object class for providing
-a consistent template processing service.
-
-Standard header (PRE_PROCESS) and footer (POST_PROCESS) templates may
-be specified which are prepended and appended to all templates
-processed by the service (but not any other templates or blocks
-INCLUDEd or PROCESSed from within). An ERROR hash may be specified
-which redirects the service to an alternate template file in the case
-of uncaught exceptions being thrown. This allows errors to be
-automatically handled by the service and a guaranteed valid response
-to be generated regardless of any processing problems encountered.
-
-A default Template::Service object is created by the Template module.
-Any Template::Service options may be passed to the Template new()
-constructor method and will be forwarded to the Template::Service
-constructor.
-
- use Template;
-
- my $template = Template->new({
- PRE_PROCESS => 'header',
- POST_PROCESS => 'footer',
- });
-
-Similarly, the Template::Service constructor will forward all configuration
-parameters onto other default objects (e.g. Template::Context) that it may
-need to instantiate.
-
-A Template::Service object (or subclass/derivative) can be explicitly
-instantiated and passed to the Template new() constructor method as
-the SERVICE item.
-
- use Template;
- use Template::Service;
-
- my $service = Template::Service->new({
- PRE_PROCESS => 'header',
- POST_PROCESS => 'footer',
- });
-
- my $template = Template->new({
- SERVICE => $service,
- });
-
-The Template::Service module can be sub-classed to create custom service
-handlers.
-
- use Template;
- use MyOrg::Template::Service;
-
- my $service = MyOrg::Template::Service->new({
- PRE_PROCESS => 'header',
- POST_PROCESS => 'footer',
- COOL_OPTION => 'enabled in spades',
- });
-
- my $template = Template->new({
- SERVICE => $service,
- });
-
-The Template module uses the Template::Config service() factory method
-to create a default service object when required. The
-$Template::Config::SERVICE package variable may be set to specify an
-alternate service module. This will be loaded automatically and its
-new() constructor method called by the service() factory method when
-a default service object is required. Thus the previous example could
-be written as:
-
- use Template;
-
- $Template::Config::SERVICE = 'MyOrg::Template::Service';
-
- my $template = Template->new({
- PRE_PROCESS => 'header',
- POST_PROCESS => 'footer',
- COOL_OPTION => 'enabled in spades',
- });
-
-=head1 METHODS
-
-=head2 new(\%config)
-
-The new() constructor method is called to instantiate a Template::Service
-object. Configuration parameters may be specified as a HASH reference or
-as a list of (name =E<gt> value) pairs.
-
- my $service1 = Template::Service->new({
- PRE_PROCESS => 'header',
- POST_PROCESS => 'footer',
- });
-
- my $service2 = Template::Service->new( ERROR => 'error.html' );
-
-The new() method returns a Template::Service object (or sub-class) or
-undef on error. In the latter case, a relevant error message can be
-retrieved by the error() class method or directly from the
-$Template::Service::ERROR package variable.
-
- my $service = Template::Service->new(\%config)
- || die Template::Service->error();
-
- my $service = Template::Service->new(\%config)
- || die $Template::Service::ERROR;
-
-The following configuration items may be specified:
-
-=over 4
-
-
-
-
-=item PRE_PROCESS, POST_PROCESS
-
-These values may be set to contain the name(s) of template files
-(relative to INCLUDE_PATH) which should be processed immediately
-before and/or after each template. These do not get added to
-templates processed into a document via directives such as INCLUDE,
-PROCESS, WRAPPER etc.
-
- my $service = Template::Service->new({
- PRE_PROCESS => 'header',
- POST_PROCESS => 'footer',
- };
-
-Multiple templates may be specified as a reference to a list. Each is
-processed in the order defined.
-
- my $service = Template::Service->new({
- PRE_PROCESS => [ 'config', 'header' ],
- POST_PROCESS => 'footer',
- };
-
-Alternately, multiple template may be specified as a single string,
-delimited by ':'. This delimiter string can be changed via the
-DELIMITER option.
-
- my $service = Template::Service->new({
- PRE_PROCESS => 'config:header',
- POST_PROCESS => 'footer',
- };
-
-The PRE_PROCESS and POST_PROCESS templates are evaluated in the same
-variable context as the main document and may define or update
-variables for subsequent use.
-
-config:
-
- [% # set some site-wide variables
- bgcolor = '#ffffff'
- version = 2.718
- %]
-
-header:
-
- [% DEFAULT title = 'My Funky Web Site' %]
- <html>
- <head>
- <title>[% title %]</title>
- </head>
- <body bgcolor="[% bgcolor %]">
-
-footer:
-
- <hr>
- Version [% version %]
- </body>
- </html>
-
-The Template::Document object representing the main template being processed
-is available within PRE_PROCESS and POST_PROCESS templates as the 'template'
-variable. Metadata items defined via the META directive may be accessed
-accordingly.
-
- $service->process('mydoc.html', $vars);
-
-mydoc.html:
-
- [% META title = 'My Document Title' %]
- blah blah blah
- ...
-
-header:
-
- <html>
- <head>
- <title>[% template.title %]</title></head>
- <body bgcolor="[% bgcolor %]">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-=item PROCESS
-
-The PROCESS option may be set to contain the name(s) of template files
-(relative to INCLUDE_PATH) which should be processed instead of the
-main template passed to the Template::Service process() method. This can
-be used to apply consistent wrappers around all templates, similar to
-the use of PRE_PROCESS and POST_PROCESS templates.
-
- my $service = Template::Service->new({
- PROCESS => 'content',
- };
-
- # processes 'content' instead of 'foo.html'
- $service->process('foo.html');
-
-A reference to the original template is available in the 'template'
-variable. Metadata items can be inspected and the template can be
-processed by specifying it as a variable reference (i.e. prefixed by
-'$') to an INCLUDE, PROCESS or WRAPPER directive.
-
-content:
-
- <html>
- <head>
- <title>[% template.title %]</title>
- </head>
-
- <body>
- [% PROCESS $template %]
- <hr>
- &copy; Copyright [% template.copyright %]
- </body>
- </html>
-
-foo.html:
-
- [% META
- title = 'The Foo Page'
- author = 'Fred Foo'
- copyright = '2000 Fred Foo'
- %]
- <h1>[% template.title %]</h1>
- Welcome to the Foo Page, blah blah blah
-
-output:
-
- <html>
- <head>
- <title>The Foo Page</title>
- </head>
-
- <body>
- <h1>The Foo Page</h1>
- Welcome to the Foo Page, blah blah blah
- <hr>
- &copy; Copyright 2000 Fred Foo
- </body>
- </html>
-
-
-
-
-
-
-
-=item ERROR
-
-The ERROR (or ERRORS if you prefer) configuration item can be used to
-name a single template or specify a hash array mapping exception types
-to templates which should be used for error handling. If an uncaught
-exception is raised from within a template then the appropriate error
-template will instead be processed.
-
-If specified as a single value then that template will be processed
-for all uncaught exceptions.
-
- my $service = Template::Service->new({
- ERROR => 'error.html'
- });
-
-If the ERROR item is a hash reference the keys are assumed to be
-exception types and the relevant template for a given exception will
-be selected. A 'default' template may be provided for the general
-case. Note that 'ERROR' can be pluralised to 'ERRORS' if you find
-it more appropriate in this case.
-
- my $service = Template::Service->new({
- ERRORS => {
- user => 'user/index.html',
- dbi => 'error/database',
- default => 'error/default',
- },
- });
-
-In this example, any 'user' exceptions thrown will cause the
-'user/index.html' template to be processed, 'dbi' errors are handled
-by 'error/database' and all others by the 'error/default' template.
-Any PRE_PROCESS and/or POST_PROCESS templates will also be applied
-to these error templates.
-
-Note that exception types are hierarchical and a 'foo' handler will
-catch all 'foo.*' errors (e.g. foo.bar, foo.bar.baz) if a more
-specific handler isn't defined. Be sure to quote any exception types
-that contain periods to prevent Perl concatenating them into a single
-string (i.e. C<user.passwd> is parsed as 'user'.'passwd').
-
- my $service = Template::Service->new({
- ERROR => {
- 'user.login' => 'user/login.html',
- 'user.passwd' => 'user/badpasswd.html',
- 'user' => 'user/index.html',
- 'default' => 'error/default',
- },
- });
-
-In this example, any template processed by the $service object, or
-other templates or code called from within, can raise a 'user.login'
-exception and have the service redirect to the 'user/login.html'
-template. Similarly, a 'user.passwd' exception has a specific
-handling template, 'user/badpasswd.html', while all other 'user' or
-'user.*' exceptions cause a redirection to the 'user/index.html' page.
-All other exception types are handled by 'error/default'.
-
-
-Exceptions can be raised in a template using the THROW directive,
-
- [% THROW user.login 'no user id: please login' %]
-
-or by calling the throw() method on the current Template::Context object,
-
- $context->throw('user.passwd', 'Incorrect Password');
- $context->throw('Incorrect Password'); # type 'undef'
-
-or from Perl code by calling die() with a Template::Exception object,
-
- die (Template::Exception->new('user.denied', 'Invalid User ID'));
-
-or by simply calling die() with an error string. This is
-automagically caught and converted to an exception of 'undef'
-type which can then be handled in the usual way.
-
- die "I'm sorry Dave, I can't do that";
-
-
-
-
-
-
-
-=item AUTO_RESET
-
-The AUTO_RESET option is set by default and causes the local BLOCKS
-cache for the Template::Context object to be reset on each call to the
-Template process() method. This ensures that any BLOCKs defined
-within a template will only persist until that template is finished
-processing. This prevents BLOCKs defined in one processing request
-from interfering with other independent requests subsequently
-processed by the same context object.
-
-The BLOCKS item may be used to specify a default set of block definitions
-for the Template::Context object. Subsequent BLOCK definitions in templates
-will over-ride these but they will be reinstated on each reset if AUTO_RESET
-is enabled (default), or if the Template::Context reset() method is called.
-
-
-
-
-
-
-
-=item DEBUG
-
-The DEBUG option can be used to enable debugging messages from the
-Template::Service module by setting it to include the DEBUG_SERVICE
-value.
-
- use Template::Constants qw( :debug );
-
- my $template = Template->new({
- DEBUG => DEBUG_SERVICE,
- });
-
-
-
-
-=back
-
-=head2 process($input, \%replace)
-
-The process() method is called to process a template specified as the first
-parameter, $input. This may be a file name, file handle (e.g. GLOB or IO::Handle)
-or a reference to a text string containing the template text. An additional
-hash reference may be passed containing template variable definitions.
-
-The method processes the template, adding any PRE_PROCESS or POST_PROCESS
-templates defined, and returns the output text. An uncaught exception thrown
-by the template will be handled by a relevant ERROR handler if defined.
-Errors that occur in the PRE_PROCESS or POST_PROCESS templates, or those that
-occur in the main input template and aren't handled, cause the method to
-return undef to indicate failure. The appropriate error message can be
-retrieved via the error() method.
-
- $service->process('myfile.html', { title => 'My Test File' })
- || die $service->error();
-
-
-=head2 context()
-
-Returns a reference to the internal context object which is, by default, an
-instance of the Template::Context class.
-
-=head2 error()
-
-Returns the most recent error message.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.79, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template|Template>, L<Template::Context|Template::Context>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Stash.pm b/lib/Template/Stash.pm
deleted file mode 100644
index 64553fe..0000000
--- a/lib/Template/Stash.pm
+++ /dev/null
@@ -1,1040 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Stash
-#
-# DESCRIPTION
-# Definition of an object class which stores and manages access to
-# variables for the Template Toolkit.
-#
-# AUTHOR
-# Andy Wardley <abw@wardley.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2003 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Stash.pm,v 2.85 2004/01/30 17:51:01 abw Exp $
-#
-#============================================================================
-
-package Template::Stash;
-
-require 5.004;
-
-use strict;
-use vars qw( $VERSION $DEBUG $ROOT_OPS $SCALAR_OPS $HASH_OPS $LIST_OPS );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.85 $ =~ /(\d+)\.(\d+)/);
-
-
-#========================================================================
-# -- PACKAGE VARIABLES AND SUBS --
-#========================================================================
-
-#------------------------------------------------------------------------
-# Definitions of various pseudo-methods. ROOT_OPS are merged into all
-# new Template::Stash objects, and are thus default global functions.
-# SCALAR_OPS are methods that can be called on a scalar, and ditto
-# respectively for LIST_OPS and HASH_OPS
-#------------------------------------------------------------------------
-
-$ROOT_OPS = {
- 'inc' => sub { local $^W = 0; my $item = shift; ++$item },
- 'dec' => sub { local $^W = 0; my $item = shift; --$item },
-# import => \&hash_import,
- defined $ROOT_OPS ? %$ROOT_OPS : (),
-};
-
-$SCALAR_OPS = {
- 'item' => sub { $_[0] },
- 'list' => sub { [ $_[0] ] },
- 'hash' => sub { { value => $_[0] } },
- 'length' => sub { length $_[0] },
- 'size' => sub { return 1 },
- 'defined' => sub { return 1 },
- 'repeat' => sub {
- my ($str, $count) = @_;
- $str = '' unless defined $str;
- return '' unless $count;
- $count ||= 1;
- return $str x $count;
- },
- 'search' => sub {
- my ($str, $pattern) = @_;
- return $str unless defined $str and defined $pattern;
- return $str =~ /$pattern/;
- },
- 'replace' => sub {
- my ($str, $search, $replace) = @_;
- $replace = '' unless defined $replace;
- return $str unless defined $str and defined $search;
- $str =~ s/$search/$replace/g;
-# print STDERR "s [ $search ] [ $replace ] g\n";
-# eval "\$str =~ s$search$replaceg";
- return $str;
- },
- 'match' => sub {
- my ($str, $search) = @_;
- return $str unless defined $str and defined $search;
- my @matches = ($str =~ /$search/);
- return @matches ? \@matches : '';
- },
- 'split' => sub {
- my ($str, $split, @args) = @_;
- $str = '' unless defined $str;
- return [ defined $split ? split($split, $str, @args)
- : split(' ', $str, @args) ];
- },
- 'chunk' => sub {
- my ($string, $size) = @_;
- my @list;
- $size ||= 1;
- if ($size < 0) {
- # sexeger! It's faster to reverse the string, search
- # it from the front and then reverse the output than to
- # search it from the end, believe it nor not!
- $string = reverse $string;
- $size = -$size;
- unshift(@list, scalar reverse $1)
- while ($string =~ /((.{$size})|(.+))/g);
- }
- else {
- push(@list, $1) while ($string =~ /((.{$size})|(.+))/g);
- }
- return \@list;
- },
-
-
- defined $SCALAR_OPS ? %$SCALAR_OPS : (),
-};
-
-$HASH_OPS = {
- 'item' => sub {
- my ($hash, $item) = @_;
- $item = '' unless defined $item;
- return if $item =~ /^[_.]/;
- $hash->{ $item };
- },
- 'hash' => sub { $_[0] },
- 'size' => sub { scalar keys %{$_[0]} },
- 'keys' => sub { [ keys %{ $_[0] } ] },
- 'values' => sub { [ values %{ $_[0] } ] },
- 'each' => sub { [ %{ $_[0] } ] },
- 'list' => sub {
- my ($hash, $what) = @_; $what ||= '';
- return ($what eq 'keys') ? [ keys %$hash ]
- : ($what eq 'values') ? [ values %$hash ]
- : ($what eq 'each') ? [ %$hash ]
- : [ map { { key => $_ , value => $hash->{ $_ } } }
- keys %$hash ];
- },
- 'exists' => sub { exists $_[0]->{ $_[1] } },
- 'defined' => sub { defined $_[0]->{ $_[1] } },
- 'import' => \&hash_import,
- 'sort' => sub {
- my ($hash) = @_;
- [ sort { lc $hash->{$a} cmp lc $hash->{$b} } (keys %$hash) ];
- },
- 'nsort' => sub {
- my ($hash) = @_;
- [ sort { $hash->{$a} <=> $hash->{$b} } (keys %$hash) ];
- },
- defined $HASH_OPS ? %$HASH_OPS : (),
-};
-
-$LIST_OPS = {
- 'item' => sub { $_[0]->[ $_[1] || 0 ] },
- 'list' => sub { $_[0] },
- 'hash' => sub { my $list = shift; my $n = 0;
- return { map { ($n++, $_) } @$list }; },
- 'push' => sub { my $list = shift; push(@$list, shift); return '' },
- 'pop' => sub { my $list = shift; pop(@$list) },
- 'unshift' => sub { my $list = shift; unshift(@$list, shift); return '' },
- 'shift' => sub { my $list = shift; shift(@$list) },
- 'max' => sub { local $^W = 0; my $list = shift; $#$list; },
- 'size' => sub { local $^W = 0; my $list = shift; $#$list + 1; },
- 'first' => sub {
- my $list = shift;
- return $list->[0] unless @_;
- return [ @$list[0..$_[0]-1] ];
- },
- 'last' => sub {
- my $list = shift;
- return $list->[-1] unless @_;
- return [ @$list[-$_[0]..-1] ];
- },
- 'reverse' => sub { my $list = shift; [ reverse @$list ] },
- 'grep' => sub {
- my ($list, $pattern) = @_;
- $pattern ||= '';
- return [ grep /$pattern/, @$list ];
- },
- 'join' => sub {
- my ($list, $joint) = @_;
- join(defined $joint ? $joint : ' ',
- map { defined $_ ? $_ : '' } @$list)
- },
- 'sort' => sub {
- $^W = 0;
- my ($list, $field) = @_;
- return $list unless @$list > 1; # no need to sort 1 item lists
- return $field # Schwartzian Transform
- ? map { $_->[0] } # for case insensitivity
- sort { $a->[1] cmp $b->[1] }
- map { [ $_, lc(ref($_) eq 'HASH'
- ? $_->{ $field } :
- UNIVERSAL::can($_, $field)
- ? $_->$field() : $_) ] }
- @$list
- : map { $_->[0] }
- sort { $a->[1] cmp $b->[1] }
- map { [ $_, lc $_ ] }
- @$list
- },
- 'nsort' => sub {
- my ($list, $field) = @_;
- return $list unless $#$list; # no need to sort 1 item lists
- return $field # Schwartzian Transform
- ? map { $_->[0] } # for case insensitivity
- sort { $a->[1] <=> $b->[1] }
- map { [ $_, lc(ref($_) eq 'HASH'
- ? $_->{ $field } :
- UNIVERSAL::can($_, $field)
- ? $_->$field() : $_) ] }
- @$list
- : map { $_->[0] }
- sort { $a->[1] <=> $b->[1] }
- map { [ $_, lc $_ ] }
- @$list
- },
- 'unique' => sub { my %u; [ grep { ++$u{$_} == 1 } @{$_[0]} ] },
- 'merge' => sub {
- my $list = shift;
- return [ @$list, grep defined, map ref eq 'ARRAY' ? @$_ : undef, @_ ];
- },
- 'slice' => sub {
- my ($list, $from, $to) = @_;
- $from ||= 0;
- $to = $#$list unless defined $to;
- return [ @$list[$from..$to] ];
- },
- 'splice' => sub {
- my ($list, $offset, $length, @replace) = @_;
- if (@replace) {
- # @replace can contain a list of multiple replace items, or
- # be a single reference to a list
- @replace = @{ $replace[0] }
- if @replace == 1 && ref $replace[0] eq 'ARRAY';
- return [ splice @$list, $offset, $length, @replace ];
- }
- elsif (defined $length) {
- return [ splice @$list, $offset, $length ];
- }
- elsif (defined $offset) {
- return [ splice @$list, $offset ];
- }
- else {
- return [ splice(@$list) ];
- }
- },
-
- defined $LIST_OPS ? %$LIST_OPS : (),
-};
-
-sub hash_import {
- my ($hash, $imp) = @_;
- $imp = {} unless ref $imp eq 'HASH';
- @$hash{ keys %$imp } = values %$imp;
- return '';
-}
-
-
-#------------------------------------------------------------------------
-# define_vmethod($type, $name, \&sub)
-#
-# Defines a virtual method of type $type (SCALAR, HASH, or LIST), with
-# name $name, that invokes &sub when called. It is expected that &sub
-# be able to handle the type that it will be called upon.
-#------------------------------------------------------------------------
-
-sub define_vmethod {
- my ($class, $type, $name, $sub) = @_;
- my $op;
- $type = lc $type;
-
- if ($type =~ /^scalar|item$/) {
- $op = $SCALAR_OPS;
- }
- elsif ($type eq 'hash') {
- $op = $HASH_OPS;
- }
- elsif ($type =~ /^list|array$/) {
- $op = $LIST_OPS;
- }
- else {
- die "invalid vmethod type: $type\n";
- }
-
- $op->{ $name } = $sub;
-
- return 1;
-}
-
-
-#========================================================================
-# ----- CLASS METHODS -----
-#========================================================================
-
-#------------------------------------------------------------------------
-# new(\%params)
-#
-# Constructor method which creates a new Template::Stash object.
-# An optional hash reference may be passed containing variable
-# definitions that will be used to initialise the stash.
-#
-# Returns a reference to a newly created Template::Stash.
-#------------------------------------------------------------------------
-
-sub new {
- my $class = shift;
- my $params = ref $_[0] eq 'HASH' ? shift(@_) : { @_ };
-
- my $self = {
- global => { },
- %$params,
- %$ROOT_OPS,
- '_PARENT' => undef,
- };
-
- bless $self, $class;
-}
-
-
-#========================================================================
-# ----- PUBLIC OBJECT METHODS -----
-#========================================================================
-
-#------------------------------------------------------------------------
-# clone(\%params)
-#
-# Creates a copy of the current stash object to effect localisation
-# of variables. The new stash is blessed into the same class as the
-# parent (which may be a derived class) and has a '_PARENT' member added
-# which contains a reference to the parent stash that created it
-# ($self). This member is used in a successive declone() method call to
-# return the reference to the parent.
-#
-# A parameter may be provided which should reference a hash of
-# variable/values which should be defined in the new stash. The
-# update() method is called to define these new variables in the cloned
-# stash.
-#
-# Returns a reference to a cloned Template::Stash.
-#------------------------------------------------------------------------
-
-sub clone {
- my ($self, $params) = @_;
- $params ||= { };
-
- # look out for magical 'import' argument which imports another hash
- my $import = $params->{ import };
- if (defined $import && UNIVERSAL::isa($import, 'HASH')) {
- delete $params->{ import };
- }
- else {
- undef $import;
- }
-
- my $clone = bless {
- %$self, # copy all parent members
- %$params, # copy all new data
- '_PARENT' => $self, # link to parent
- }, ref $self;
-
- # perform hash import if defined
- &{ $HASH_OPS->{ import }}($clone, $import)
- if defined $import;
-
- return $clone;
-}
-
-
-#------------------------------------------------------------------------
-# declone($export)
-#
-# Returns a reference to the PARENT stash. When called in the following
-# manner:
-# $stash = $stash->declone();
-# the reference count on the current stash will drop to 0 and be "freed"
-# and the caller will be left with a reference to the parent. This
-# contains the state of the stash before it was cloned.
-#------------------------------------------------------------------------
-
-sub declone {
- my $self = shift;
- $self->{ _PARENT } || $self;
-}
-
-
-#------------------------------------------------------------------------
-# get($ident)
-#
-# Returns the value for an variable stored in the stash. The variable
-# may be specified as a simple string, e.g. 'foo', or as an array
-# reference representing compound variables. In the latter case, each
-# pair of successive elements in the list represent a node in the
-# compound variable. The first is the variable name, the second a
-# list reference of arguments or 0 if undefined. So, the compound
-# variable [% foo.bar('foo').baz %] would be represented as the list
-# [ 'foo', 0, 'bar', ['foo'], 'baz', 0 ]. Returns the value of the
-# identifier or an empty string if undefined. Errors are thrown via
-# die().
-#------------------------------------------------------------------------
-
-sub get {
- my ($self, $ident, $args) = @_;
- my ($root, $result);
- $root = $self;
-
- if (ref $ident eq 'ARRAY'
- || ($ident =~ /\./)
- && ($ident = [ map { s/\(.*$//; ($_, 0) } split(/\./, $ident) ])) {
- my $size = $#$ident;
-
- # if $ident is a list reference, then we evaluate each item in the
- # identifier against the previous result, using the root stash
- # ($self) as the first implicit 'result'...
-
- foreach (my $i = 0; $i <= $size; $i += 2) {
- $result = $self->_dotop($root, @$ident[$i, $i+1]);
- last unless defined $result;
- $root = $result;
- }
- }
- else {
- $result = $self->_dotop($root, $ident, $args);
- }
-
- return defined $result ? $result : $self->undefined($ident, $args);
-}
-
-
-#------------------------------------------------------------------------
-# set($ident, $value, $default)
-#
-# Updates the value for a variable in the stash. The first parameter
-# should be the variable name or array, as per get(). The second
-# parameter should be the intended value for the variable. The third,
-# optional parameter is a flag which may be set to indicate 'default'
-# mode. When set true, the variable will only be updated if it is
-# currently undefined or has a false value. The magical 'IMPORT'
-# variable identifier may be used to indicate that $value is a hash
-# reference whose values should be imported. Returns the value set,
-# or an empty string if not set (e.g. default mode). In the case of
-# IMPORT, returns the number of items imported from the hash.
-#------------------------------------------------------------------------
-
-sub set {
- my ($self, $ident, $value, $default) = @_;
- my ($root, $result, $error);
-
- $root = $self;
-
- ELEMENT: {
- if (ref $ident eq 'ARRAY'
- || ($ident =~ /\./)
- && ($ident = [ map { s/\(.*$//; ($_, 0) }
- split(/\./, $ident) ])) {
-
- # a compound identifier may contain multiple elements (e.g.
- # foo.bar.baz) and we must first resolve all but the last,
- # using _dotop() with the $lvalue flag set which will create
- # intermediate hashes if necessary...
- my $size = $#$ident;
- foreach (my $i = 0; $i < $size - 2; $i += 2) {
- $result = $self->_dotop($root, @$ident[$i, $i+1], 1);
- last ELEMENT unless defined $result;
- $root = $result;
- }
-
- # then we call _assign() to assign the value to the last element
- $result = $self->_assign($root, @$ident[$size-1, $size],
- $value, $default);
- }
- else {
- $result = $self->_assign($root, $ident, 0, $value, $default);
- }
- }
-
- return defined $result ? $result : '';
-}
-
-
-#------------------------------------------------------------------------
-# getref($ident)
-#
-# Returns a "reference" to a particular item. This is represented as a
-# closure which will return the actual stash item when called.
-# WARNING: still experimental!
-#------------------------------------------------------------------------
-
-sub getref {
- my ($self, $ident, $args) = @_;
- my ($root, $item, $result);
- $root = $self;
-
- if (ref $ident eq 'ARRAY') {
- my $size = $#$ident;
-
- foreach (my $i = 0; $i <= $size; $i += 2) {
- ($item, $args) = @$ident[$i, $i + 1];
- last if $i >= $size - 2; # don't evaluate last node
- last unless defined
- ($root = $self->_dotop($root, $item, $args));
- }
- }
- else {
- $item = $ident;
- }
-
- if (defined $root) {
- return sub { my @args = (@{$args||[]}, @_);
- $self->_dotop($root, $item, \@args);
- }
- }
- else {
- return sub { '' };
- }
-}
-
-
-
-
-#------------------------------------------------------------------------
-# update(\%params)
-#
-# Update multiple variables en masse. No magic is performed. Simple
-# variable names only.
-#------------------------------------------------------------------------
-
-sub update {
- my ($self, $params) = @_;
-
- # look out for magical 'import' argument to import another hash
- my $import = $params->{ import };
- if (defined $import && UNIVERSAL::isa($import, 'HASH')) {
- @$self{ keys %$import } = values %$import;
- delete $params->{ import };
- }
-
- @$self{ keys %$params } = values %$params;
-}
-
-
-#------------------------------------------------------------------------
-# undefined($ident, $args)
-#
-# Method called when a get() returns an undefined value. Can be redefined
-# in a subclass to implement alternate handling.
-#------------------------------------------------------------------------
-
-sub undefined {
- my ($self, $ident, $args);
- return '';
-}
-
-
-#========================================================================
-# ----- PRIVATE OBJECT METHODS -----
-#========================================================================
-
-#------------------------------------------------------------------------
-# _dotop($root, $item, \@args, $lvalue)
-#
-# This is the core 'dot' operation method which evaluates elements of
-# variables against their root. All variables have an implicit root
-# which is the stash object itself (a hash). Thus, a non-compound
-# variable 'foo' is actually '(stash.)foo', the compound 'foo.bar' is
-# '(stash.)foo.bar'. The first parameter is a reference to the current
-# root, initially the stash itself. The second parameter contains the
-# name of the variable element, e.g. 'foo'. The third optional
-# parameter is a reference to a list of any parenthesised arguments
-# specified for the variable, which are passed to sub-routines, object
-# methods, etc. The final parameter is an optional flag to indicate
-# if this variable is being evaluated on the left side of an assignment
-# (e.g. foo.bar.baz = 10). When set true, intermediated hashes will
-# be created (e.g. bar) if necessary.
-#
-# Returns the result of evaluating the item against the root, having
-# performed any variable "magic". The value returned can then be used
-# as the root of the next _dotop() in a compound sequence. Returns
-# undef if the variable is undefined.
-#------------------------------------------------------------------------
-
-sub _dotop {
- my ($self, $root, $item, $args, $lvalue) = @_;
- my $rootref = ref $root;
- my $atroot = ($root eq $self);
- my ($value, @result);
-
- $args ||= [ ];
- $lvalue ||= 0;
-
-# print STDERR "_dotop(root=$root, item=$item, args=[@$args])\n"
-# if $DEBUG;
-
- # return undef without an error if either side of the dot is unviable
- # or if an attempt is made to access a private member, starting _ or .
- return undef
- unless defined($root) and defined($item) and $item !~ /^[\._]/;
-
- if ($atroot || $rootref eq 'HASH') {
- # if $root is a regular HASH or a Template::Stash kinda HASH (the
- # *real* root of everything). We first lookup the named key
- # in the hash, or create an empty hash in its place if undefined
- # and the $lvalue flag is set. Otherwise, we check the HASH_OPS
- # pseudo-methods table, calling the code if found, or return undef.
-
- if (defined($value = $root->{ $item })) {
- return $value unless ref $value eq 'CODE'; ## RETURN
- @result = &$value(@$args); ## @result
- }
- elsif ($lvalue) {
- # we create an intermediate hash if this is an lvalue
- return $root->{ $item } = { }; ## RETURN
- }
- # ugly hack: only allow import vmeth to be called on root stash
- elsif (($value = $HASH_OPS->{ $item })
- && ! $atroot || $item eq 'import') {
- @result = &$value($root, @$args); ## @result
- }
- elsif ( ref $item eq 'ARRAY' ) {
- # hash slice
- return [@$root{@$item}]; ## RETURN
- }
- }
- elsif ($rootref eq 'ARRAY') {
- # if root is an ARRAY then we check for a LIST_OPS pseudo-method
- # (except for l-values for which it doesn't make any sense)
- # or return the numerical index into the array, or undef
-
- if (($value = $LIST_OPS->{ $item }) && ! $lvalue) {
- @result = &$value($root, @$args); ## @result
- }
- elsif ($item =~ /^-?\d+$/) {
- $value = $root->[$item];
- return $value unless ref $value eq 'CODE'; ## RETURN
- @result = &$value(@$args); ## @result
- }
- elsif ( ref $item eq 'ARRAY' ) {
- # array slice
- return [@$root[@$item]]; ## RETURN
- }
- }
-
- # NOTE: we do the can-can because UNIVSERAL::isa($something, 'UNIVERSAL')
- # doesn't appear to work with CGI, returning true for the first call
- # and false for all subsequent calls.
-
- elsif (ref($root) && UNIVERSAL::can($root, 'can')) {
-
- # if $root is a blessed reference (i.e. inherits from the
- # UNIVERSAL object base class) then we call the item as a method.
- # If that fails then we try to fallback on HASH behaviour if
- # possible.
- eval { @result = $root->$item(@$args); };
-
- if ($@) {
- # temporary hack - required to propogate errors thrown
- # by views; if $@ is a ref (e.g. Template::Exception
- # object then we assume it's a real error that needs
- # real throwing
-
- die $@ if ref($@) || ($@ !~ /Can't locate object method/);
-
- # failed to call object method, so try some fallbacks
-# patch from Stephen Howard
-# -- remove from here... --
- if (UNIVERSAL::isa($root, 'HASH')
- && defined($value = $root->{ $item })) {
- return $value unless ref $value eq 'CODE'; ## RETURN
- @result = &$value(@$args);
- }
-# -- and replace with this... --
-# if (UNIVERSAL::isa($root, 'HASH') ) {
-# if( defined($value = $root->{ $item })) {
-# return $value unless ref $value eq 'CODE'; ## RETURN
-# @result = &$value(@$args);
-# }
-# elsif ($value = $HASH_OPS->{ $item }) {
-# @result = &$value($root, @$args);
-# }
-# }
-# -- remove from here... --
- elsif (UNIVERSAL::isa($root, 'ARRAY')
- && ($value = $LIST_OPS->{ $item })) {
- @result = &$value($root, @$args);
- }
-# -- and replace with this... --
-# elsif (UNIVERSAL::isa($root, 'ARRAY') ) {
-# if( $value = $LIST_OPS->{ $item }) {
-# @result = &$value($root, @$args);
-# }
-# elsif( $item =~ /^-?\d+$/ ) {
-# $value = $root->[$item];
-# return $value unless ref $value eq 'CODE'; ## RETURN
-# @result = &$value(@$args); ## @result
-# }
-# elsif ( ref $item eq 'ARRAY' ) {
-# # array slice
-# return [@$root[@$item]]; ## RETURN
-# }
-# }
-# -- end --
- elsif ($value = $SCALAR_OPS->{ $item }) {
- @result = &$value($root, @$args);
- }
- elsif ($value = $LIST_OPS->{ $item }) {
- @result = &$value([$root], @$args);
- }
- elsif ($self->{ _DEBUG }) {
- @result = (undef, $@);
- }
- }
- }
- elsif (($value = $SCALAR_OPS->{ $item }) && ! $lvalue) {
- # at this point, it doesn't look like we've got a reference to
- # anything we know about, so we try the SCALAR_OPS pseudo-methods
- # table (but not for l-values)
- @result = &$value($root, @$args); ## @result
- }
- elsif (($value = $LIST_OPS->{ $item }) && ! $lvalue) {
- # last-ditch: can we promote a scalar to a one-element
- # list and apply a LIST_OPS virtual method?
- @result = &$value([$root], @$args);
- }
- elsif ($self->{ _DEBUG }) {
- die "don't know how to access [ $root ].$item\n"; ## DIE
- }
- else {
- @result = ();
- }
-
- # fold multiple return items into a list unless first item is undef
- if (defined $result[0]) {
- return ## RETURN
- scalar @result > 1 ? [ @result ] : $result[0];
- }
- elsif (defined $result[1]) {
- die $result[1]; ## DIE
- }
- elsif ($self->{ _DEBUG }) {
- die "$item is undefined\n"; ## DIE
- }
-
- return undef;
-}
-
-
-#------------------------------------------------------------------------
-# _assign($root, $item, \@args, $value, $default)
-#
-# Similar to _dotop() above, but assigns a value to the given variable
-# instead of simply returning it. The first three parameters are the
-# root item, the item and arguments, as per _dotop(), followed by the
-# value to which the variable should be set and an optional $default
-# flag. If set true, the variable will only be set if currently false
-# (undefined/zero)
-#------------------------------------------------------------------------
-
-sub _assign {
- my ($self, $root, $item, $args, $value, $default) = @_;
- my $rootref = ref $root;
- my $atroot = ($root eq $self);
- my $result;
- $args ||= [ ];
- $default ||= 0;
-
-# print(STDERR "_assign(root=$root, item=$item, args=[@$args], \n",
-# "value=$value, default=$default)\n")
-# if $DEBUG;
-
- # return undef without an error if either side of the dot is unviable
- # or if an attempt is made to update a private member, starting _ or .
- return undef ## RETURN
- unless $root and defined $item and $item !~ /^[\._]/;
-
- if ($rootref eq 'HASH' || $atroot) {
-# if ($item eq 'IMPORT' && UNIVERSAL::isa($value, 'HASH')) {
-# # import hash entries into root hash
-# @$root{ keys %$value } = values %$value;
-# return ''; ## RETURN
-# }
- # if the root is a hash we set the named key
- return ($root->{ $item } = $value) ## RETURN
- unless $default && $root->{ $item };
- }
- elsif ($rootref eq 'ARRAY' && $item =~ /^-?\d+$/) {
- # or set a list item by index number
- return ($root->[$item] = $value) ## RETURN
- unless $default && $root->{ $item };
- }
- elsif (UNIVERSAL::isa($root, 'UNIVERSAL')) {
- # try to call the item as a method of an object
-
- return $root->$item(@$args, $value) ## RETURN
- unless $default && $root->$item();
-
-# 2 issues:
-# - method call should be wrapped in eval { }
-# - fallback on hash methods if object method not found
-#
-# eval { $result = $root->$item(@$args, $value); };
-#
-# if ($@) {
-# die $@ if ref($@) || ($@ !~ /Can't locate object method/);
-#
-# # failed to call object method, so try some fallbacks
-# if (UNIVERSAL::isa($root, 'HASH') && exists $root->{ $item }) {
-# $result = ($root->{ $item } = $value)
-# unless $default && $root->{ $item };
-# }
-# }
-# return $result; ## RETURN
-
- }
- else {
- die "don't know how to assign to [$root].[$item]\n"; ## DIE
- }
-
- return undef;
-}
-
-
-#------------------------------------------------------------------------
-# _dump()
-#
-# Debug method which returns a string representing the internal state
-# of the object. The method calls itself recursively to dump sub-hashes.
-#------------------------------------------------------------------------
-
-sub _dump {
- my $self = shift;
- return "[Template::Stash] " . $self->_dump_frame(2);
-}
-
-sub _dump_frame {
- my ($self, $indent) = @_;
- $indent ||= 1;
- my $buffer = ' ';
- my $pad = $buffer x $indent;
- my $text = "{\n";
- local $" = ', ';
-
- my ($key, $value);
-
- return $text . "...excessive recursion, terminating\n"
- if $indent > 32;
-
- foreach $key (keys %$self) {
- $value = $self->{ $key };
- $value = '<undef>' unless defined $value;
- next if $key =~ /^\./;
- if (ref($value) eq 'ARRAY') {
- $value = '[ ' . join(', ', map { defined $_ ? $_ : '<undef>' }
- @$value) . ' ]';
- }
- elsif (ref $value eq 'HASH') {
- $value = _dump_frame($value, $indent + 1);
- }
-
- $text .= sprintf("$pad%-16s => $value\n", $key);
- }
- $text .= $buffer x ($indent - 1) . '}';
- return $text;
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Stash - Magical storage for template variables
-
-=head1 SYNOPSIS
-
- use Template::Stash;
-
- my $stash = Template::Stash->new(\%vars);
-
- # get variable values
- $value = $stash->get($variable);
- $value = $stash->get(\@compound);
-
- # set variable value
- $stash->set($variable, $value);
- $stash->set(\@compound, $value);
-
- # default variable value
- $stash->set($variable, $value, 1);
- $stash->set(\@compound, $value, 1);
-
- # set variable values en masse
- $stash->update(\%new_vars)
-
- # methods for (de-)localising variables
- $stash = $stash->clone(\%new_vars);
- $stash = $stash->declone();
-
-=head1 DESCRIPTION
-
-The Template::Stash module defines an object class which is used to store
-variable values for the runtime use of the template processor. Variable
-values are stored internally in a hash reference (which itself is blessed
-to create the object) and are accessible via the get() and set() methods.
-
-Variables may reference hash arrays, lists, subroutines and objects
-as well as simple values. The stash automatically performs the right
-magic when dealing with variables, calling code or object methods,
-indexing into lists, hashes, etc.
-
-The stash has clone() and declone() methods which are used by the
-template processor to make temporary copies of the stash for
-localising changes made to variables.
-
-=head1 PUBLIC METHODS
-
-=head2 new(\%params)
-
-The new() constructor method creates and returns a reference to a new
-Template::Stash object.
-
- my $stash = Template::Stash->new();
-
-A hash reference may be passed to provide variables and values which
-should be used to initialise the stash.
-
- my $stash = Template::Stash->new({ var1 => 'value1',
- var2 => 'value2' });
-
-=head2 get($variable)
-
-The get() method retrieves the variable named by the first parameter.
-
- $value = $stash->get('var1');
-
-Dotted compound variables can be retrieved by specifying the variable
-elements by reference to a list. Each node in the variable occupies
-two entries in the list. The first gives the name of the variable
-element, the second is a reference to a list of arguments for that
-element, or 0 if none.
-
- [% foo.bar(10).baz(20) %]
-
- $stash->get([ 'foo', 0, 'bar', [ 10 ], 'baz', [ 20 ] ]);
-
-=head2 set($variable, $value, $default)
-
-The set() method sets the variable name in the first parameter to the
-value specified in the second.
-
- $stash->set('var1', 'value1');
-
-If the third parameter evaluates to a true value, the variable is
-set only if it did not have a true value before.
-
- $stash->set('var2', 'default_value', 1);
-
-Dotted compound variables may be specified as per get() above.
-
- [% foo.bar = 30 %]
-
- $stash->set([ 'foo', 0, 'bar', 0 ], 30);
-
-The magical variable 'IMPORT' can be specified whose corresponding
-value should be a hash reference. The contents of the hash array are
-copied (i.e. imported) into the current namespace.
-
- # foo.bar = baz, foo.wiz = waz
- $stash->set('foo', { 'bar' => 'baz', 'wiz' => 'waz' });
-
- # import 'foo' into main namespace: foo = baz, wiz = waz
- $stash->set('IMPORT', $stash->get('foo'));
-
-=head2 clone(\%params)
-
-The clone() method creates and returns a new Template::Stash object which
-represents a localised copy of the parent stash. Variables can be
-freely updated in the cloned stash and when declone() is called, the
-original stash is returned with all its members intact and in the
-same state as they were before clone() was called.
-
-For convenience, a hash of parameters may be passed into clone() which
-is used to update any simple variable (i.e. those that don't contain any
-namespace elements like 'foo' and 'bar' but not 'foo.bar') variables while
-cloning the stash. For adding and updating complex variables, the set()
-method should be used after calling clone(). This will correctly resolve
-and/or create any necessary namespace hashes.
-
-A cloned stash maintains a reference to the stash that it was copied
-from in its '_PARENT' member.
-
-=head2 declone()
-
-The declone() method returns the '_PARENT' reference and can be used to
-restore the state of a stash as described above.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.85, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template|Template>, L<Template::Context|Template::Context>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Stash/Context.pm b/lib/Template/Stash/Context.pm
deleted file mode 100644
index 975dc79..0000000
--- a/lib/Template/Stash/Context.pm
+++ /dev/null
@@ -1,791 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Stash::Context
-#
-# DESCRIPTION
-# This is an alternate stash object which includes a patch from
-# Craig Barratt to implement various new virtual methods to allow
-# dotted template variable to denote if object methods and subroutines
-# should be called in scalar or list context. It adds a little overhead
-# to each stash call and I'm a little wary of doing that. So for now,
-# it's implemented as a separate stash module which will allow us to
-# test it out, benchmark it and switch it in or out as we require.
-#
-# This is what Craig has to say about it:
-#
-# Here's a better set of features for the core. Attached is a new version
-# of Stash.pm (based on TT2.02) that:
-#
-# - supports the special op "scalar" that forces scalar context on
-# function calls, eg:
-#
-# cgi.param("foo").scalar
-#
-# calls cgi.param("foo") in scalar context (unlike my wimpy
-# scalar op from last night). Array context is the default.
-#
-# With non-function operands, scalar behaves like the perl
-# version (eg: no-op for scalar, size for arrays, etc).
-#
-# - supports the special op "ref" that behaves like the perl ref.
-# If applied to a function the function is not called. Eg:
-#
-# cgi.param("foo").ref
-#
-# does *not* call cgi.param and evaluates to "CODE". Similarly,
-# HASH.ref, ARRAY.ref return what you expect.
-#
-# - adds a new scalar and list op called "array" that is a no-op for
-# arrays and promotes scalars to one-element arrays.
-#
-# - allows scalar ops to be applied to arrays and hashes in place,
-# eg: ARRAY.repeat(3) repeats each element in place.
-#
-# - allows list ops to be applied to scalars by promoting the scalars
-# to one-element arrays (like an implicit "array"). So you can
-# do things like SCALAR.size, SCALAR.join and get a useful result.
-#
-# This also means you can now use x.0 to safely get the first element
-# whether x is an array or scalar.
-#
-# The new Stash.pm passes the TT2.02 test suite. But I haven't tested the
-# new features very much. One nagging implementation problem is that the
-# "scalar" and "ref" ops have higher precedence than user variable names.
-#
-# AUTHORS
-# Andy Wardley <abw@kfs.org>
-# Craig Barratt <craig@arraycomm.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Context.pm,v 1.58 2004/01/13 16:21:52 abw Exp $
-#
-#============================================================================
-
-package Template::Stash::Context;
-
-require 5.004;
-
-use strict;
-use Template::Stash;
-use vars qw( $VERSION $DEBUG $ROOT_OPS $SCALAR_OPS $HASH_OPS $LIST_OPS );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 1.58 $ =~ /(\d+)\.(\d+)/);
-
-
-#========================================================================
-# -- PACKAGE VARIABLES AND SUBS --
-#========================================================================
-
-#------------------------------------------------------------------------
-# copy virtual methods from those in the regular Template::Stash
-#------------------------------------------------------------------------
-
-$ROOT_OPS = {
- %$Template::Stash::ROOT_OPS,
- defined $ROOT_OPS ? %$ROOT_OPS : (),
-};
-
-$SCALAR_OPS = {
- %$Template::Stash::SCALAR_OPS,
- 'array' => sub { return [$_[0]] },
- defined $SCALAR_OPS ? %$SCALAR_OPS : (),
-};
-
-$LIST_OPS = {
- %$Template::Stash::LIST_OPS,
- 'array' => sub { return $_[0] },
- defined $LIST_OPS ? %$LIST_OPS : (),
-};
-
-$HASH_OPS = {
- %$Template::Stash::HASH_OPS,
- defined $HASH_OPS ? %$HASH_OPS : (),
-};
-
-
-
-#========================================================================
-# ----- CLASS METHODS -----
-#========================================================================
-
-#------------------------------------------------------------------------
-# new(\%params)
-#
-# Constructor method which creates a new Template::Stash object.
-# An optional hash reference may be passed containing variable
-# definitions that will be used to initialise the stash.
-#
-# Returns a reference to a newly created Template::Stash.
-#------------------------------------------------------------------------
-
-sub new {
- my $class = shift;
- my $params = ref $_[0] eq 'HASH' ? shift(@_) : { @_ };
-
- my $self = {
- global => { },
- %$params,
- %$ROOT_OPS,
- '_PARENT' => undef,
- };
-
- bless $self, $class;
-}
-
-
-#========================================================================
-# ----- PUBLIC OBJECT METHODS -----
-#========================================================================
-
-#------------------------------------------------------------------------
-# clone(\%params)
-#
-# Creates a copy of the current stash object to effect localisation
-# of variables. The new stash is blessed into the same class as the
-# parent (which may be a derived class) and has a '_PARENT' member added
-# which contains a reference to the parent stash that created it
-# ($self). This member is used in a successive declone() method call to
-# return the reference to the parent.
-#
-# A parameter may be provided which should reference a hash of
-# variable/values which should be defined in the new stash. The
-# update() method is called to define these new variables in the cloned
-# stash.
-#
-# Returns a reference to a cloned Template::Stash.
-#------------------------------------------------------------------------
-
-sub clone {
- my ($self, $params) = @_;
- $params ||= { };
-
- # look out for magical 'import' argument which imports another hash
- my $import = $params->{ import };
- if (defined $import && UNIVERSAL::isa($import, 'HASH')) {
- delete $params->{ import };
- }
- else {
- undef $import;
- }
-
- my $clone = bless {
- %$self, # copy all parent members
- %$params, # copy all new data
- '_PARENT' => $self, # link to parent
- }, ref $self;
-
- # perform hash import if defined
- &{ $HASH_OPS->{ import }}($clone, $import)
- if defined $import;
-
- return $clone;
-}
-
-
-#------------------------------------------------------------------------
-# declone($export)
-#
-# Returns a reference to the PARENT stash. When called in the following
-# manner:
-# $stash = $stash->declone();
-# the reference count on the current stash will drop to 0 and be "freed"
-# and the caller will be left with a reference to the parent. This
-# contains the state of the stash before it was cloned.
-#------------------------------------------------------------------------
-
-sub declone {
- my $self = shift;
- $self->{ _PARENT } || $self;
-}
-
-
-#------------------------------------------------------------------------
-# get($ident)
-#
-# Returns the value for an variable stored in the stash. The variable
-# may be specified as a simple string, e.g. 'foo', or as an array
-# reference representing compound variables. In the latter case, each
-# pair of successive elements in the list represent a node in the
-# compound variable. The first is the variable name, the second a
-# list reference of arguments or 0 if undefined. So, the compound
-# variable [% foo.bar('foo').baz %] would be represented as the list
-# [ 'foo', 0, 'bar', ['foo'], 'baz', 0 ]. Returns the value of the
-# identifier or an empty string if undefined. Errors are thrown via
-# die().
-#------------------------------------------------------------------------
-
-sub get {
- my ($self, $ident, $args) = @_;
- my ($root, $result);
- $root = $self;
-
- if (ref $ident eq 'ARRAY'
- || ($ident =~ /\./)
- && ($ident = [ map { s/\(.*$//; ($_, 0) } split(/\./, $ident) ])) {
- my $size = $#$ident;
-
- # if $ident is a list reference, then we evaluate each item in the
- # identifier against the previous result, using the root stash
- # ($self) as the first implicit 'result'...
-
- foreach (my $i = 0; $i <= $size; $i += 2) {
- if ( $i + 2 <= $size && ($ident->[$i+2] eq "scalar"
- || $ident->[$i+2] eq "ref") ) {
- $result = $self->_dotop($root, @$ident[$i, $i+1], 0,
- $ident->[$i+2]);
- $i += 2;
- } else {
- $result = $self->_dotop($root, @$ident[$i, $i+1]);
- }
- last unless defined $result;
- $root = $result;
- }
- }
- else {
- $result = $self->_dotop($root, $ident, $args);
- }
-
- return defined $result ? $result : '';
-}
-
-
-#------------------------------------------------------------------------
-# set($ident, $value, $default)
-#
-# Updates the value for a variable in the stash. The first parameter
-# should be the variable name or array, as per get(). The second
-# parameter should be the intended value for the variable. The third,
-# optional parameter is a flag which may be set to indicate 'default'
-# mode. When set true, the variable will only be updated if it is
-# currently undefined or has a false value. The magical 'IMPORT'
-# variable identifier may be used to indicate that $value is a hash
-# reference whose values should be imported. Returns the value set,
-# or an empty string if not set (e.g. default mode). In the case of
-# IMPORT, returns the number of items imported from the hash.
-#------------------------------------------------------------------------
-
-sub set {
- my ($self, $ident, $value, $default) = @_;
- my ($root, $result, $error);
-
- $root = $self;
-
- ELEMENT: {
- if (ref $ident eq 'ARRAY'
- || ($ident =~ /\./)
- && ($ident = [ map { s/\(.*$//; ($_, 0) }
- split(/\./, $ident) ])) {
-
- # a compound identifier may contain multiple elements (e.g.
- # foo.bar.baz) and we must first resolve all but the last,
- # using _dotop() with the $lvalue flag set which will create
- # intermediate hashes if necessary...
- my $size = $#$ident;
- foreach (my $i = 0; $i < $size - 2; $i += 2) {
- $result = $self->_dotop($root, @$ident[$i, $i+1], 1);
- last ELEMENT unless defined $result;
- $root = $result;
- }
-
- # then we call _assign() to assign the value to the last element
- $result = $self->_assign($root, @$ident[$size-1, $size],
- $value, $default);
- }
- else {
- $result = $self->_assign($root, $ident, 0, $value, $default);
- }
- }
-
- return defined $result ? $result : '';
-}
-
-
-#------------------------------------------------------------------------
-# getref($ident)
-#
-# Returns a "reference" to a particular item. This is represented as a
-# closure which will return the actual stash item when called.
-# WARNING: still experimental!
-#------------------------------------------------------------------------
-
-sub getref {
- my ($self, $ident, $args) = @_;
- my ($root, $item, $result);
- $root = $self;
-
- if (ref $ident eq 'ARRAY') {
- my $size = $#$ident;
-
- foreach (my $i = 0; $i <= $size; $i += 2) {
- ($item, $args) = @$ident[$i, $i + 1];
- last if $i >= $size - 2; # don't evaluate last node
- last unless defined
- ($root = $self->_dotop($root, $item, $args));
- }
- }
- else {
- $item = $ident;
- }
-
- if (defined $root) {
- return sub { my @args = (@{$args||[]}, @_);
- $self->_dotop($root, $item, \@args);
- }
- }
- else {
- return sub { '' };
- }
-}
-
-
-
-
-#------------------------------------------------------------------------
-# update(\%params)
-#
-# Update multiple variables en masse. No magic is performed. Simple
-# variable names only.
-#------------------------------------------------------------------------
-
-sub update {
- my ($self, $params) = @_;
-
- # look out for magical 'import' argument to import another hash
- my $import = $params->{ import };
- if (defined $import && UNIVERSAL::isa($import, 'HASH')) {
- @$self{ keys %$import } = values %$import;
- delete $params->{ import };
- }
-
- @$self{ keys %$params } = values %$params;
-}
-
-
-#========================================================================
-# ----- PRIVATE OBJECT METHODS -----
-#========================================================================
-
-#------------------------------------------------------------------------
-# _dotop($root, $item, \@args, $lvalue, $nextItem)
-#
-# This is the core 'dot' operation method which evaluates elements of
-# variables against their root. All variables have an implicit root
-# which is the stash object itself (a hash). Thus, a non-compound
-# variable 'foo' is actually '(stash.)foo', the compound 'foo.bar' is
-# '(stash.)foo.bar'. The first parameter is a reference to the current
-# root, initially the stash itself. The second parameter contains the
-# name of the variable element, e.g. 'foo'. The third optional
-# parameter is a reference to a list of any parenthesised arguments
-# specified for the variable, which are passed to sub-routines, object
-# methods, etc. The final parameter is an optional flag to indicate
-# if this variable is being evaluated on the left side of an assignment
-# (e.g. foo.bar.baz = 10). When set true, intermediated hashes will
-# be created (e.g. bar) if necessary.
-#
-# Returns the result of evaluating the item against the root, having
-# performed any variable "magic". The value returned can then be used
-# as the root of the next _dotop() in a compound sequence. Returns
-# undef if the variable is undefined.
-#------------------------------------------------------------------------
-
-sub _dotop {
- my ($self, $root, $item, $args, $lvalue, $nextItem) = @_;
- my $rootref = ref $root;
- my ($value, @result, $ret, $retVal);
- $nextItem ||= "";
- my $scalarContext = 1 if ( $nextItem eq "scalar" );
- my $returnRef = 1 if ( $nextItem eq "ref" );
-
- $args ||= [ ];
- $lvalue ||= 0;
-
-# print STDERR "_dotop(root=$root, item=$item, args=[@$args])\n"
-# if $DEBUG;
-
- # return undef without an error if either side of the dot is unviable
- # or if an attempt is made to access a private member, starting _ or .
- return undef
- unless defined($root) and defined($item) and $item !~ /^[\._]/;
-
- if (ref(\$root) eq "SCALAR" && !$lvalue &&
- (($value = $LIST_OPS->{ $item }) || $item =~ /^-?\d+$/) ) {
- #
- # Promote scalar to one element list, to be processed below.
- #
- $rootref = 'ARRAY';
- $root = [$root];
- }
- if ($rootref eq __PACKAGE__ || $rootref eq 'HASH') {
-
- # if $root is a regular HASH or a Template::Stash kinda HASH (the
- # *real* root of everything). We first lookup the named key
- # in the hash, or create an empty hash in its place if undefined
- # and the $lvalue flag is set. Otherwise, we check the HASH_OPS
- # pseudo-methods table, calling the code if found, or return undef.
-
- if (defined($value = $root->{ $item })) {
- ($ret, $retVal, @result) = _dotop_return($value, $args, $returnRef,
- $scalarContext);
- return $retVal if ( $ret ); ## RETURN
- }
- elsif ($lvalue) {
- # we create an intermediate hash if this is an lvalue
- return $root->{ $item } = { }; ## RETURN
- }
- elsif ($value = $HASH_OPS->{ $item }) {
- @result = &$value($root, @$args); ## @result
- }
- elsif (ref $item eq 'ARRAY') {
- # hash slice
- return [@$root{@$item}]; ## RETURN
- }
- elsif ($value = $SCALAR_OPS->{ $item }) {
- #
- # Apply scalar ops to every hash element, in place.
- #
- foreach my $key ( keys %$root ) {
- $root->{$key} = &$value($root->{$key}, @$args);
- }
- }
- }
- elsif ($rootref eq 'ARRAY') {
-
- # if root is an ARRAY then we check for a LIST_OPS pseudo-method
- # (except for l-values for which it doesn't make any sense)
- # or return the numerical index into the array, or undef
-
- if (($value = $LIST_OPS->{ $item }) && ! $lvalue) {
- @result = &$value($root, @$args); ## @result
- }
- elsif (($value = $SCALAR_OPS->{ $item }) && ! $lvalue) {
- #
- # Apply scalar ops to every array element, in place.
- #
- for ( my $i = 0 ; $i < @$root ; $i++ ) {
- $root->[$i] = &$value($root->[$i], @$args); ## @result
- }
- }
- elsif ($item =~ /^-?\d+$/) {
- $value = $root->[$item];
- ($ret, $retVal, @result) = _dotop_return($value, $args, $returnRef,
- $scalarContext);
- return $retVal if ( $ret ); ## RETURN
- }
- elsif (ref $item eq 'ARRAY' ) {
- # array slice
- return [@$root[@$item]]; ## RETURN
- }
- }
-
- # NOTE: we do the can-can because UNIVSERAL::isa($something, 'UNIVERSAL')
- # doesn't appear to work with CGI, returning true for the first call
- # and false for all subsequent calls.
-
- elsif (ref($root) && UNIVERSAL::can($root, 'can')) {
-
- # if $root is a blessed reference (i.e. inherits from the
- # UNIVERSAL object base class) then we call the item as a method.
- # If that fails then we try to fallback on HASH behaviour if
- # possible.
- return ref $root->can($item) if ( $returnRef ); ## RETURN
- eval {
- @result = $scalarContext ? scalar $root->$item(@$args)
- : $root->$item(@$args); ## @result
- };
-
- if ($@) {
- # failed to call object method, so try some fallbacks
- if (UNIVERSAL::isa($root, 'HASH')
- && defined($value = $root->{ $item })) {
- ($ret, $retVal, @result) = _dotop_return($value, $args,
- $returnRef, $scalarContext);
- return $retVal if ( $ret ); ## RETURN
- }
- elsif (UNIVERSAL::isa($root, 'ARRAY')
- && ($value = $LIST_OPS->{ $item })) {
- @result = &$value($root, @$args);
- }
- else {
- @result = (undef, $@);
- }
- }
- }
- elsif (($value = $SCALAR_OPS->{ $item }) && ! $lvalue) {
-
- # at this point, it doesn't look like we've got a reference to
- # anything we know about, so we try the SCALAR_OPS pseudo-methods
- # table (but not for l-values)
-
- @result = &$value($root, @$args); ## @result
- }
- elsif ($self->{ _DEBUG }) {
- die "don't know how to access [ $root ].$item\n"; ## DIE
- }
- else {
- @result = ();
- }
-
- # fold multiple return items into a list unless first item is undef
- if (defined $result[0]) {
- return ref(@result > 1 ? [ @result ] : $result[0])
- if ( $returnRef ); ## RETURN
- if ( $scalarContext ) {
- return scalar @result if ( @result > 1 ); ## RETURN
- return scalar(@{$result[0]}) if ( ref $result[0] eq "ARRAY" );
- return scalar(%{$result[0]}) if ( ref $result[0] eq "HASH" );
- return $result[0]; ## RETURN
- } else {
- return @result > 1 ? [ @result ] : $result[0]; ## RETURN
- }
- }
- elsif (defined $result[1]) {
- die $result[1]; ## DIE
- }
- elsif ($self->{ _DEBUG }) {
- die "$item is undefined\n"; ## DIE
- }
-
- return undef;
-}
-
-#------------------------------------------------------------------------
-# ($ret, $retVal, @result) = _dotop_return($value, $args, $returnRef,
-# $scalarContext);
-#
-# Handle the various return processing for _dotop
-#------------------------------------------------------------------------
-sub _dotop_return
-{
- my($value, $args, $returnRef, $scalarContext) = @_;
- my(@result);
-
- return (1, ref $value) if ( $returnRef ); ## RETURN
- if ( $scalarContext ) {
- return (1, scalar(@$value)) if ref $value eq 'ARRAY'; ## RETURN
- return (1, scalar(%$value)) if ref $value eq 'HASH'; ## RETURN
- return (1, scalar($value)) unless ref $value eq 'CODE'; ## RETURN;
- @result = scalar &$value(@$args) ## @result;
- } else {
- return (1, $value) unless ref $value eq 'CODE'; ## RETURN
- @result = &$value(@$args); ## @result
- }
- return (0, undef, @result);
-}
-
-
-#------------------------------------------------------------------------
-# _assign($root, $item, \@args, $value, $default)
-#
-# Similar to _dotop() above, but assigns a value to the given variable
-# instead of simply returning it. The first three parameters are the
-# root item, the item and arguments, as per _dotop(), followed by the
-# value to which the variable should be set and an optional $default
-# flag. If set true, the variable will only be set if currently false
-# (undefined/zero)
-#------------------------------------------------------------------------
-
-sub _assign {
- my ($self, $root, $item, $args, $value, $default) = @_;
- my $rootref = ref $root;
- my $result;
- $args ||= [ ];
- $default ||= 0;
-
-# print(STDERR "_assign(root=$root, item=$item, args=[@$args], \n",
-# "value=$value, default=$default)\n")
-# if $DEBUG;
-
- # return undef without an error if either side of the dot is unviable
- # or if an attempt is made to update a private member, starting _ or .
- return undef ## RETURN
- unless $root and defined $item and $item !~ /^[\._]/;
-
- if ($rootref eq 'HASH' || $rootref eq __PACKAGE__) {
-# if ($item eq 'IMPORT' && UNIVERSAL::isa($value, 'HASH')) {
-# # import hash entries into root hash
-# @$root{ keys %$value } = values %$value;
-# return ''; ## RETURN
-# }
- # if the root is a hash we set the named key
- return ($root->{ $item } = $value) ## RETURN
- unless $default && $root->{ $item };
- }
- elsif ($rootref eq 'ARRAY' && $item =~ /^-?\d+$/) {
- # or set a list item by index number
- return ($root->[$item] = $value) ## RETURN
- unless $default && $root->{ $item };
- }
- elsif (UNIVERSAL::isa($root, 'UNIVERSAL')) {
- # try to call the item as a method of an object
- return $root->$item(@$args, $value); ## RETURN
- }
- else {
- die "don't know how to assign to [$root].[$item]\n"; ## DIE
- }
-
- return undef;
-}
-
-
-#------------------------------------------------------------------------
-# _dump()
-#
-# Debug method which returns a string representing the internal state
-# of the object. The method calls itself recursively to dump sub-hashes.
-#------------------------------------------------------------------------
-
-sub _dump {
- my $self = shift;
- my $indent = shift || 1;
- my $buffer = ' ';
- my $pad = $buffer x $indent;
- my $text = '';
- local $" = ', ';
-
- my ($key, $value);
-
-
- return $text . "...excessive recursion, terminating\n"
- if $indent > 32;
-
- foreach $key (keys %$self) {
-
- $value = $self->{ $key };
- $value = '<undef>' unless defined $value;
-
- if (ref($value) eq 'ARRAY') {
- $value = "$value [@$value]";
- }
- $text .= sprintf("$pad%-8s => $value\n", $key);
- next if $key =~ /^\./;
- if (UNIVERSAL::isa($value, 'HASH')) {
- $text .= _dump($value, $indent + 1);
- }
- }
- $text;
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Stash::Context - Experimetal stash allowing list/scalar context definition
-
-=head1 SYNOPSIS
-
- use Template;
- use Template::Stash::Context;
-
- my $stash = Template::Stash::Context->new(\%vars);
- my $tt2 = Template->new({ STASH => $stash });
-
-=head1 DESCRIPTION
-
-This is an alternate stash object which includes a patch from
-Craig Barratt to implement various new virtual methods to allow
-dotted template variable to denote if object methods and subroutines
-should be called in scalar or list context. It adds a little overhead
-to each stash call and I'm a little wary of applying that to the core
-default stash without investigating the effects first. So for now,
-it's implemented as a separate stash module which will allow us to
-test it out, benchmark it and switch it in or out as we require.
-
-This is what Craig has to say about it:
-
-Here's a better set of features for the core. Attached is a new version
-of Stash.pm (based on TT2.02) that:
-
-* supports the special op "scalar" that forces scalar context on
-function calls, eg:
-
- cgi.param("foo").scalar
-
-calls cgi.param("foo") in scalar context (unlike my wimpy
-scalar op from last night). Array context is the default.
-
-With non-function operands, scalar behaves like the perl
-version (eg: no-op for scalar, size for arrays, etc).
-
-* supports the special op "ref" that behaves like the perl ref.
-If applied to a function the function is not called. Eg:
-
- cgi.param("foo").ref
-
-does *not* call cgi.param and evaluates to "CODE". Similarly,
-HASH.ref, ARRAY.ref return what you expect.
-
-* adds a new scalar and list op called "array" that is a no-op for
-arrays and promotes scalars to one-element arrays.
-
-* allows scalar ops to be applied to arrays and hashes in place,
-eg: ARRAY.repeat(3) repeats each element in place.
-
-* allows list ops to be applied to scalars by promoting the scalars
-to one-element arrays (like an implicit "array"). So you can
-do things like SCALAR.size, SCALAR.join and get a useful result.
-
-This also means you can now use x.0 to safely get the first element
-whether x is an array or scalar.
-
-The new Stash.pm passes the TT2.02 test suite. But I haven't tested the
-new features very much. One nagging implementation problem is that the
-"scalar" and "ref" ops have higher precedence than user variable names.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-1.58, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template::Stash|Template::Stash>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Stash/XS.pm b/lib/Template/Stash/XS.pm
deleted file mode 100644
index 2cfb543..0000000
--- a/lib/Template/Stash/XS.pm
+++ /dev/null
@@ -1,176 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Stash::XS
-#
-# DESCRIPTION
-#
-# Perl bootstrap for XS module. Inherits methods from
-# Template::Stash when not implemented in the XS module.
-#
-#========================================================================
-
-package Template::Stash::XS;
-
-use Template;
-use Template::Stash;
-
-BEGIN {
- require DynaLoader;
- @Template::Stash::XS::ISA = qw( DynaLoader Template::Stash );
-
- eval {
- bootstrap Template::Stash::XS $Template::VERSION;
- };
- if ($@) {
- die "Couldn't load Template::Stash::XS $Template::VERSION:\n\n$@\n";
- }
-}
-
-
-sub DESTROY {
- # no op
- 1;
-}
-
-
-# catch missing method calls here so perl doesn't barf
-# trying to load *.al files
-sub AUTOLOAD {
- my ($self, @args) = @_;
- my @c = caller(0);
- my $auto = $AUTOLOAD;
-
- $auto =~ s/.*:://;
- $self =~ s/=.*//;
-
- die "Can't locate object method \"$auto\"" .
- " via package \"$self\" at $c[1] line $c[2]\n";
-}
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Stash::XS - Experimetal high-speed stash written in XS
-
-=head1 SYNOPSIS
-
- use Template;
- use Template::Stash::XS;
-
- my $stash = Template::Stash::XS->new(\%vars);
- my $tt2 = Template->new({ STASH => $stash });
-
-=head1 DESCRIPTION
-
-This module loads the XS version of Template::Stash::XS. It should
-behave very much like the old one, but run about twice as fast.
-See the synopsis above for usage information.
-
-Only a few methods (such as get and set) have been implemented in XS.
-The others are inherited from Template::Stash.
-
-=head1 NOTE
-
-To always use the XS version of Stash, modify the Template/Config.pm
-module near line 45:
-
- $STASH = 'Template::Stash::XS';
-
-If you make this change, then there is no need to explicitly create
-an instance of Template::Stash::XS as seen in the SYNOPSIS above. Just
-use Template as normal.
-
-Alternatively, in your code add this line before creating a Template
-object:
-
- $Template::Config::STASH = 'Template::Stash::XS';
-
-To use the original, pure-perl version restore this line in
-Template/Config.pm:
-
- $STASH = 'Template::Stash';
-
-Or in your code:
-
- $Template::Config::STASH = 'Template::Stash';
-
-You can elect to have this performed once for you at installation
-time by answering 'y' or 'n' to the question that asks if you want
-to make the XS Stash the default.
-
-=head1 BUGS
-
-Please report bugs to the Template Toolkit mailing list
-templates@template-toolkit.org
-
-As of version 2.05 of the Template Toolkit, use of the XS Stash is
-known to have 2 potentially troublesome side effects. The first
-problem is that accesses to tied hashes (e.g. Apache::Session) may not
-work as expected. This should be fixed in an imminent release. If
-you are using tied hashes then it is suggested that you use the
-regular Stash by default, or write a thin wrapper around your tied
-hashes to enable the XS Stash to access items via regular method
-calls.
-
-The second potential problem is that enabling the XS Stash causes all
-the Template Toolkit modules to be installed in an architecture
-dependant library, e.g. in
-
- /usr/lib/perl5/site_perl/5.6.0/i386-linux/Template
-
-instead of
-
- /usr/lib/perl5/site_perl/5.6.0/Template
-
-At the time of writing, we're not sure why this is happening but it's
-likely that this is either a bug or intentional feature in the Perl
-ExtUtils::MakeMaker module. As far as I know, Perl always checks the
-architecture dependant directories before the architecture independant
-ones. Therefore, a newer version of the Template Toolkit installed
-with the XS Stash enabled should be used by Perl in preference to any
-existing version using the regular stash. However, if you install a
-future version of the Template Toolkit with the XS Stash disabled, you
-may find that Perl continues to use the older version with XS Stash
-enabled in preference.
-
-=head1 AUTHORS
-
-Andy Wardley E<lt>abw@tt2.orgE<gt>
-
-Doug Steinwand E<lt>dsteinwand@citysearch.comE<gt>
-
-=head1 VERSION
-
-Template Toolkit version 2.13, released on 30 January 2004.
-
-
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-
-
-=head1 SEE ALSO
-
-L<Template::Stash|Template::Stash>
-
diff --git a/lib/Template/Test.pm b/lib/Template/Test.pm
deleted file mode 100644
index 9413d68..0000000
--- a/lib/Template/Test.pm
+++ /dev/null
@@ -1,711 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::Test
-#
-# DESCRIPTION
-# Module defining a test harness which processes template input and
-# then compares the output against pre-define expected output.
-# Generates test output compatible with Test::Harness. This was
-# originally the t/texpect.pl script.
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2000 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.
-#
-#----------------------------------------------------------------------------
-#
-# $Id: Test.pm,v 2.69 2004/01/13 16:19:16 abw Exp $
-#
-#============================================================================
-
-package Template::Test;
-
-require 5.004;
-
-use strict;
-use vars qw( @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS
- $VERSION $DEBUG $EXTRA $PRESERVE $REASON $NO_FLUSH
- $loaded %callsign);
-use Template qw( :template );
-use Exporter;
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.69 $ =~ /(\d+)\.(\d+)/);
-$DEBUG = 0;
-@ISA = qw( Exporter );
-@EXPORT = qw( ntests ok is match flush skip_all test_expect callsign banner );
-@EXPORT_OK = ( 'assert' );
-%EXPORT_TAGS = ( all => [ @EXPORT_OK, @EXPORT ] );
-$| = 1;
-
-$REASON = 'not applicable on this platform';
-$NO_FLUSH = 0;
-$EXTRA = 0; # any extra tests to come after test_expect()
-$PRESERVE = 0 # don't mangle newlines in output/expect
- unless defined $PRESERVE;
-
-# always set binmode on Win32 machines so that any output generated
-# is true to what we expect
-$Template::BINMODE = ($^O eq 'MSWin32') ? 1 : 0;
-
-my @results = ();
-my ($ntests, $ok_count);
-*is = \&match;
-
-END {
- # ensure flush() is called to print any cached results
- flush();
-}
-
-
-#------------------------------------------------------------------------
-# ntests($n)
-#
-# Declare how many (more) tests are expected to come. If ok() is called
-# before ntests() then the results are cached instead of being printed
-# to STDOUT. When ntests() is called, the total number of tests
-# (including any cached) is known and the "1..$ntests" line can be
-# printed along with the cached results. After that, calls to ok()
-# generated printed output immediately.
-#------------------------------------------------------------------------
-
-sub ntests {
- $ntests = shift;
- # add any pre-declared extra tests, or pre-stored test @results, to
- # the grand total of tests
- $ntests += $EXTRA + scalar @results;
- $ok_count = 1;
- print $ntests ? "1..$ntests\n" : "1..$ntests # skipped: $REASON\n";
- # flush cached results
- foreach my $pre_test (@results) {
- ok(@$pre_test);
- }
-}
-
-
-#------------------------------------------------------------------------
-# ok($truth, $msg)
-#
-# Tests the value passed for truth and generates an "ok $n" or "not ok $n"
-# line accordingly. If ntests() hasn't been called then we cached
-# results for later, instead.
-#------------------------------------------------------------------------
-
-sub ok {
- my ($ok, $msg) = @_;
-
- # cache results if ntests() not yet called
- unless ($ok_count) {
- push(@results, [ $ok, $msg ]);
- return $ok;
- }
-
- $msg = defined $msg ? " - $msg" : '';
- if ($ok) {
- print "ok ", $ok_count++, "$msg\n";
- }
- else {
- print STDERR "FAILED $ok_count: $msg\n" if defined $msg;
- print "not ok ", $ok_count++, "$msg\n";
- }
-}
-
-
-
-#------------------------------------------------------------------------
-# assert($truth, $error)
-#
-# Test value for truth, die if false.
-#------------------------------------------------------------------------
-
-sub assert {
- my ($ok, $err) = @_;
- return ok(1) if $ok;
-
- # failed
- my ($pkg, $file, $line) = caller();
- $err ||= "assert failed";
- $err .= " at $file line $line\n";
- ok(0);
- die $err;
-}
-
-#------------------------------------------------------------------------
-# match( $result, $expect )
-#------------------------------------------------------------------------
-
-sub match {
- my ($result, $expect, $msg) = @_;
- my $count = $ok_count ? $ok_count : scalar @results + 1;
-
- # force stringification of $result to avoid 'no eq method' overload errors
- $result = "$result" if ref $result;
-
- if ($result eq $expect) {
- return ok(1, $msg);
- }
- else {
- print STDERR "FAILED $count:\n expect: [$expect]\n result: [$result]\n";
- return ok(0, $msg);
- }
-}
-
-
-#------------------------------------------------------------------------
-# flush()
-#
-# Flush any tests results.
-#------------------------------------------------------------------------
-
-sub flush {
- ntests(0)
- unless $ok_count || $NO_FLUSH;
-}
-
-
-#------------------------------------------------------------------------
-# skip_all($reason)
-#
-# Skip all tests, setting $REASON to contain any message passed. Calls
-# exit(0) which triggers flush() which generates a "1..0 # $REASON"
-# string to keep to test harness happy.
-#------------------------------------------------------------------------
-
-sub skip_all {
- $REASON = join('', @_);
- exit(0);
-}
-
-
-#------------------------------------------------------------------------
-# test_expect($input, $template, \%replace)
-#
-# This is the main testing sub-routine. The $input parameter should be a
-# text string or a filehandle reference (e.g. GLOB or IO::Handle) from
-# which the input text can be read. The input should contain a number
-# of tests which are split up and processed individually, comparing the
-# generated output against the expected output. Tests should be defined
-# as follows:
-#
-# -- test --
-# test input
-# -- expect --
-# expected output
-#
-# -- test --
-# etc...
-#
-# The number of tests is determined and ntests() is called to generate
-# the "0..$n" line compatible with Test::Harness. Each test input is
-# then processed by the Template object passed as the second parameter,
-# $template. This may also be a hash reference containing configuration
-# which are used to instantiate a Template object, or may be left
-# undefined in which case a default Template object will be instantiated.
-# The third parameter, also optional, may be a reference to a hash array
-# defining template variables. This is passed to the template process()
-# method.
-#------------------------------------------------------------------------
-
-sub test_expect {
- my ($src, $tproc, $params) = @_;
- my ($input, @tests);
- my ($output, $expect, $match);
- my $count = 0;
- my $ttprocs;
-
- # read input text
- eval {
- local $/ = undef;
- $input = ref $src ? <$src> : $src;
- };
- if ($@) {
- ntests(1); ok(0);
- warn "Cannot read input text from $src\n";
- return undef;
- }
-
- # remove any comment lines
- $input =~ s/^#.*?\n//gm;
-
- # remove anything before '-- start --' and/or after '-- stop --'
- $input = $' if $input =~ /\s*--\s*start\s*--\s*/;
- $input = $` if $input =~ /\s*--\s*stop\s*--\s*/;
-
- @tests = split(/^\s*--\s*test\s*--\s*\n/im, $input);
-
- # if the first line of the file was '--test--' (optional) then the
- # first test will be empty and can be discarded
- shift(@tests) if $tests[0] =~ /^\s*$/;
-
- ntests(3 + scalar(@tests) * 2);
-
- # first test is that Template loaded OK, which it did
- ok(1, 'running test_expect()');
-
- # optional second param may contain a Template reference or a HASH ref
- # of constructor options, or may be undefined
- if (ref($tproc) eq 'HASH') {
- # create Template object using hash of config items
- $tproc = Template->new($tproc)
- || die Template->error(), "\n";
- }
- elsif (ref($tproc) eq 'ARRAY') {
- # list of [ name => $tproc, name => $tproc ], use first $tproc
- $ttprocs = { @$tproc };
- $tproc = $tproc->[1];
- }
- elsif (! ref $tproc) {
- $tproc = Template->new()
- || die Template->error(), "\n";
- }
- # otherwise, we assume it's a Template reference
-
- # test: template processor created OK
- ok($tproc, 'template processor is engaged');
-
- # third test is that the input read ok, which it did
- ok(1, 'input read and split into ' . scalar @tests . ' tests');
-
- # the remaining tests are defined in @tests...
- foreach $input (@tests) {
- $count++;
- my $name = '';
-
- if ($input =~ s/^\s*-- name:? (.*?) --\s*\n//im) {
- $name = $1;
- }
- else {
- $name = "template text $count";
- }
-
- # split input by a line like "-- expect --"
- ($input, $expect) =
- split(/^\s*--\s*expect\s*--\s*\n/im, $input);
- $expect = ''
- unless defined $expect;
-
- $output = '';
-
- # input text may be prefixed with "-- use name --" to indicate a
- # Template object in the $ttproc hash which we should use
- if ($input =~ s/^\s*--\s*use\s+(\S+)\s*--\s*\n//im) {
- my $ttname = $1;
- my $ttlookup;
- if ($ttlookup = $ttprocs->{ $ttname }) {
- $tproc = $ttlookup;
- }
- else {
- warn "no such template object to use: $ttname\n";
- }
- }
-
- # process input text
- $tproc->process(\$input, $params, \$output) || do {
- warn "Template process failed: ", $tproc->error(), "\n";
- # report failure and automatically fail the expect match
- ok(0, "$name process FAILED: " . subtext($input));
- ok(0, '(obviously did not match expected)');
- next;
- };
-
- # processed OK
- ok(1, "$name processed OK: " . subtext($input));
-
- # another hack: if the '-- expect --' section starts with
- # '-- process --' then we process the expected output
- # before comparing it with the generated output. This is
- # slightly twisted but it makes it possible to run tests
- # where the expected output isn't static. See t/date.t for
- # an example.
-
- if ($expect =~ s/^\s*--+\s*process\s*--+\s*\n//im) {
- my $out;
- $tproc->process(\$expect, $params, \$out) || do {
- warn("Template process failed (expect): ",
- $tproc->error(), "\n");
- # report failure and automatically fail the expect match
- ok(0, "failed to process expected output ["
- . subtext($expect) . ']');
- next;
- };
- $expect = $out;
- };
-
- # strip any trailing blank lines from expected and real output
- foreach ($expect, $output) {
- s/\n*\Z//mg;
- }
-
- $match = ($expect eq $output) ? 1 : 0;
- if (! $match || $DEBUG) {
- print "MATCH FAILED\n"
- unless $match;
-
- my ($copyi, $copye, $copyo) = ($input, $expect, $output);
- unless ($PRESERVE) {
- foreach ($copyi, $copye, $copyo) {
- s/\n/\\n/g;
- }
- }
- printf(" input: [%s]\nexpect: [%s]\noutput: [%s]\n",
- $copyi, $copye, $copyo);
- }
-
- ok($match, $match ? "$name matched expected" : "$name did not match expected");
- };
-}
-
-#------------------------------------------------------------------------
-# callsign()
-#
-# Returns a hash array mapping lower a..z to their phonetic alphabet
-# equivalent.
-#------------------------------------------------------------------------
-
-sub callsign {
- my %callsign;
- @callsign{ 'a'..'z' } = qw(
- alpha bravo charlie delta echo foxtrot golf hotel india
- juliet kilo lima mike november oscar papa quebec romeo
- sierra tango umbrella victor whisky x-ray yankee zulu );
- return \%callsign;
-}
-
-
-#------------------------------------------------------------------------
-# banner($text)
-#
-# Prints a banner with the specified text if $DEBUG is set.
-#------------------------------------------------------------------------
-
-sub banner {
- return unless $DEBUG;
- my $text = join('', @_);
- my $count = $ok_count ? $ok_count - 1 : scalar @results;
- print "-" x 72, "\n$text ($count tests completed)\n", "-" x 72, "\n";
-}
-
-
-sub subtext {
- my $text = shift;
- $text =~ s/\s*$//sg;
- $text = substr($text, 0, 32) . '...' if length $text > 32;
- $text =~ s/\n/\\n/g;
- return $text;
-}
-
-
-1;
-
-__END__
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Test - Module for automating TT2 test scripts
-
-=head1 SYNOPSIS
-
- use Template::Test;
-
- $Template::Test::DEBUG = 0; # set this true to see each test running
- $Template::Test::EXTRA = 2; # 2 extra tests follow test_expect()...
-
- # ok() can be called any number of times before test_expect
- ok( $true_or_false )
-
- # test_expect() splits $input into individual tests, processes each
- # and compares generated output against expected output
- test_expect($input, $template, \%replace );
-
- # $input is text or filehandle (e.g. DATA section after __END__)
- test_expect( $text );
- test_expect( \*DATA );
-
- # $template is a Template object or configuration hash
- my $template_cfg = { ... };
- test_expect( $input, $template_cfg );
- my $template_obj = Template->new($template_cfg);
- test_expect( $input, $template_obj );
-
- # $replace is a hash reference of template variables
- my $replace = {
- a => 'alpha',
- b => 'bravo'
- };
- test_expect( $input, $template, $replace );
-
- # ok() called after test_expect should be declared in $EXTRA (2)
- ok( $true_or_false )
- ok( $true_or_false )
-
-=head1 DESCRIPTION
-
-The Template::Test module defines the test_expect() and other related
-subroutines which can be used to automate test scripts for the
-Template Toolkit. See the numerous tests in the 't' sub-directory of
-the distribution for examples of use.
-
-The test_expect() subroutine splits an input document into a number
-of separate tests, processes each one using the Template Toolkit and
-then compares the generated output against an expected output, also
-specified in the input document. It generates the familiar "ok/not
-ok" output compatible with Test::Harness.
-
-The test input should be specified as a text string or a reference to
-a filehandle (e.g. GLOB or IO::Handle) from which it can be read. In
-particular, this allows the test input to be placed after the __END__
-marker and read via the DATA filehandle.
-
- use Template::Test;
-
- test_expect(\*DATA);
-
- __END__
- # this is the first test (this is a comment)
- -- test --
- blah blah blah [% foo %]
- -- expect --
- blah blah blah value_of_foo
-
- # here's the second test (no surprise, so is this)
- -- test --
- more blah blah [% bar %]
- -- expect --
- more blah blah value_of_bar
-
-Blank lines between test sections are generally ignored. Any line starting
-with '#' is treated as a comment and is ignored.
-
-The second and third parameters to test_expect() are optional. The second
-may be either a reference to a Template object which should be used to
-process the template fragments, or a reference to a hash array containing
-configuration values which should be used to instantiate a new Template
-object.
-
- # pass reference to config hash
- my $config = {
- INCLUDE_PATH => '/here/there:/every/where',
- POST_CHOMP => 1,
- };
- test_expect(\*DATA, $config);
-
- # or create Template object explicitly
- my $template = Template->new($config);
- test_expect(\*DATA, $template);
-
-
-The third parameter may be used to reference a hash array of template
-variable which should be defined when processing the tests. This is
-passed to the Template process() method.
-
- my $replace = {
- a => 'alpha',
- b => 'bravo',
- };
-
- test_expect(\*DATA, $config, $replace);
-
-The second parameter may be left undefined to specify a default Template
-configuration.
-
- test_expect(\*DATA, undef, $replace);
-
-For testing the output of different Template configurations, a
-reference to a list of named Template objects also may be passed as
-the second parameter.
-
- my $tt1 = Template->new({ ... });
- my $tt2 = Template->new({ ... });
- my @tts = [ one => $tt1, two => $tt1 ];
-
-The first object in the list is used by default. Other objects may be
-switched in with the '-- use $name --' marker. This should immediately
-follow a '-- test --' line. That object will then be used for the rest
-of the test, or until a different object is selected.
-
- -- test --
- -- use one --
- [% blah %]
- -- expect --
- blah, blah
-
- -- test --
- still using one...
- -- expect --
- ...
-
- -- test --
- -- use two --
- [% blah %]
- -- expect --
- blah, blah, more blah
-
-The test_expect() sub counts the number of tests, and then calls ntests()
-to generate the familiar "1..$ntests\n" test harness line. Each
-test defined generates two test numbers. The first indicates
-that the input was processed without error, and the second that the
-output matches that expected.
-
-Additional test may be run before test_expect() by calling ok().
-These test results are cached until ntests() is called and the final
-number of tests can be calculated. Then, the "1..$ntests" line is
-output, along with "ok $n" / "not ok $n" lines for each of the cached
-test result. Subsequent calls to ok() then generate an output line
-immediately.
-
- my $something = SomeObject->new();
- ok( $something );
-
- my $other = AnotherThing->new();
- ok( $other );
-
- test_expect(\*DATA);
-
-If any tests are to follow after test_expect() is called then these
-should be pre-declared by setting the $EXTRA package variable. This
-value (default: 0) is added to the grand total calculated by ntests().
-The results of the additional tests are also registered by calling ok().
-
- $Template::Test::EXTRA = 2;
-
- # can call ok() any number of times before test_expect()
- ok( $did_that_work );
- ok( $make_sure );
- ok( $dead_certain );
-
- # <some> number of tests...
- test_expect(\*DATA, $config, $replace);
-
- # here's those $EXTRA tests
- ok( defined $some_result && ref $some_result eq 'ARRAY' );
- ok( $some_result->[0] eq 'some expected value' );
-
-If you don't want to call test_expect() at all then you can call
-ntests($n) to declare the number of tests and generate the test
-header line. After that, simply call ok() for each test passing
-a true or false values to indicate that the test passed or failed.
-
- ntests(2);
- ok(1);
- ok(0);
-
-If you're really lazy, you can just call ok() and not bother declaring
-the number of tests at all. All tests results will be cached until the
-end of the script and then printed in one go before the program exits.
-
- ok( $x );
- ok( $y );
-
-You can identify only a specific part of the input file for testing
-using the '-- start --' and '-- stop --' markers. Anything before the
-first '-- start --' is ignored, along with anything after the next
-'-- stop --' marker.
-
- -- test --
- this is test 1 (not performed)
- -- expect --
- this is test 1 (not performed)
-
- -- start --
-
- -- test --
- this is test 2
- -- expect --
- this is test 2
-
- -- stop --
-
- ...
-
-For historical reasons and general utility, the module also defines a
-'callsign' subroutine which returns a hash mapping a..z to their phonetic
-alphabet equivalent (e.g. radio callsigns). This is used by many
-of the test scripts as a "known source" of variable values.
-
- test_expect(\*DATA, $config, callsign());
-
-A banner() subroutine is also provided which prints a simple banner
-including any text passed as parameters, if $DEBUG is set.
-
- banner('Testing something-or-other');
-
-example output:
-
- #------------------------------------------------------------
- # Testing something-or-other (27 tests completed)
- #------------------------------------------------------------
-
-The $DEBUG package variable can be set to enable debugging mode.
-
-The $PRESERVE package variable can be set to stop the test_expect()
-from converting newlines in the output and expected output into
-the literal strings '\n'.
-
-=head1 HISTORY
-
-This module started its butt-ugly life as the t/texpect.pl script. It
-was cleaned up to became the Template::Test module some time around
-version 0.29. It underwent further cosmetic surgery for version 2.00
-but still retains some rear-end resemblances.
-
-=head1 BUGS / KNOWN "FEATURES"
-
-Imports all methods by default. This is generally a Bad Thing, but
-this module is only used in test scripts (i.e. at build time) so a) we
-don't really care and b) it saves typing.
-
-The line splitter may be a bit dumb, especially if it sees lines like
--- this -- that aren't supposed to be special markers. So don't do that.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.69, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<Template|Template>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Tools/tpage.pod b/lib/Template/Tools/tpage.pod
deleted file mode 100644
index e2b20fa..0000000
--- a/lib/Template/Tools/tpage.pod
+++ /dev/null
@@ -1,76 +0,0 @@
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Tools::tpage - Process templates from command line
-
-=head1 USAGE
-
- tpage [ --define var=value ] file(s)
-
-=head1 DESCRIPTION
-
-The B<tpage> script is a simple wrapper around the Template Toolkit processor.
-Files specified by name on the command line are processed in turn by the
-template processor and the resulting output is sent to STDOUT and can be
-redirected accordingly. e.g.
-
- tpage myfile > myfile.out
- tpage header myfile footer > myfile.html
-
-If no file names are specified on the command line then B<tpage> will read
-STDIN for input.
-
-The C<--define> option can be used to set the values of template variables.
-e.g.
-
- tpage --define author="Andy Wardley" skeleton.pm > MyModule.pm
-
-See L<Template> for general information about the Perl Template
-Toolkit and the template language and features.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-2.69, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<ttree|Template::Tools::ttree>
-
-=cut
-
-# Local Variables:
-# mode: perl
-# perl-indent-level: 4
-# indent-tabs-mode: nil
-# End:
-#
-# vim: expandtab shiftwidth=4:
diff --git a/lib/Template/Tools/ttree.pod b/lib/Template/Tools/ttree.pod
deleted file mode 100644
index 8984c51..0000000
--- a/lib/Template/Tools/ttree.pod
+++ /dev/null
@@ -1,332 +0,0 @@
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Tools::ttree - Process entire directory trees of templates
-
-=head1 SYNOPSIS
-
- ttree [options] [files]
-
-=head1 DESCRIPTION
-
-The F<ttree> script is used to process entire directory trees containing
-template files. The resulting output from processing each file is then
-written to a corresponding file in a destination directory. The script
-compares the modification times of source and destination files (where
-they already exist) and processes only those files that have been modified.
-In other words, it is the equivalent of 'make' for the Template Toolkit.
-
-It supports a number of options which can be used to configure
-behaviour, define locations and set Template Toolkit options. The
-script first reads the F<.ttreerc> configuration file in the HOME
-directory, or an alternative file specified in the TTREERC environment
-variable. Then, it processes any command line arguments, including
-any additional configuration files specified via the C<-f> (file)
-option.
-
-=head2 The F<.ttreerc> Configuration File
-
-When you run F<ttree> for the first time it will ask you if you want
-it to create a F<.ttreerc> file for you. This will be created in your
-home directory.
-
- $ ttree
- Do you want me to create a sample '.ttreerc' file for you?
- (file: /home/abw/.ttreerc) [y/n]: y
- /home/abw/.ttreerc created. Please edit accordingly and re-run ttree
-
-The purpose of this file is to set any I<global> configuration options
-that you want applied I<every> time F<ttree> is run. For example, you
-can use the C<ignore> and C<copy> option to provide regular expressions
-that specify which files should be ignored and which should be copied
-rather than being processed as templates. You may also want to set
-flags like C<verbose> and C<recurse> according to your preference.
-
-A minimal F<.ttreerc>:
-
- # ignore these files
- ignore = \b(CVS|RCS)\b
- ignore = ^#
- ignore = ~$
-
- # copy these files
- copy = \.(gif|png|jpg|pdf)$
-
- # recurse into directories
- recurse
-
- # provide info about what's going on
- verbose
-
-In most cases, you'll want to create a different F<ttree> configuration
-file for each project you're working on. The C<cfg> option allows you
-to specify a directory where F<ttree> can find further configuration
-files.
-
- cfg = /home/abw/.ttree
-
-The C<-f> command line option can be used to specify which configuration
-file should be used. You can specify a filename using an absolute or
-relative path:
-
- $ ttree -f /home/abw/web/example/etc/ttree.cfg
- $ ttree -f ./etc/ttree.cfg
- $ ttree -f ../etc/ttree.cfg
-
-If the configuration file does not begin with C</> or C<.> or something
-that looks like a MS-DOS absolute path (e.g. C<C:\\etc\\ttree.cfg>) then
-F<ttree> will look for it in the directory specified by the C<cfg> option.
-
- $ ttree -f test1 # /home/abw/.ttree/test1
-
-The C<cfg> option can only be used in the F<.ttreerc> file. All the
-other options can be used in the F<.ttreerc> or any other F<ttree>
-configuration file. They can all also be specified as command line
-options.
-
-Remember that F<.ttreerc> is always processed I<before> any
-configuration file specified with the C<-f> option. Certain options
-like C<lib> can be used any number of times and accumulate their values.
-
-For example, consider the following configuration files:
-
-F</home/abw/.ttreerc>:
-
- cfg = /home/abw/.ttree
- lib = /usr/local/tt2/templates
-
-F</home/abw/.ttree/myconfig>:
-
- lib = /home/abw/web/example/templates/lib
-
-When F<ttree> is invoked as follows:
-
- $ ttree -f myconfig
-
-the C<lib> option will be set to the following directories:
-
- /usr/local/tt2/templates
- /home/abw/web/example/templates/lib
-
-Any templates located under F</usr/local/tt2/templates> will be used
-in preference to those located under
-F</home/abw/web/example/templates/lib>. This may be what you want,
-but then again, it might not. For this reason, it is good practice to
-keep the F<.ttreerc> as simple as possible and use different
-configuration files for each F<ttree> project.
-
-=head2 Directory Options
-
-The C<src> option is used to define the directory containing the
-source templates to be processed. It can be provided as a command
-line option or in a configuration file as shown here:
-
- src = /home/abw/web/example/templates/src
-
-Each template in this directory typically corresponds to a single
-web page or other document.
-
-The C<dest> option is used to specify the destination directory for the
-generated output.
-
- dest = /home/abw/web/example/html
-
-The C<lib> option is used to define one or more directories containing
-additional library templates. These templates are not documents in
-their own right and typically comprise of smaller, modular components
-like headers, footers and menus that are incorporated into pages templates.
-
- lib = /home/abw/web/example/templates/lib
- lib = /usr/local/tt2/templates
-
-The C<lib> option can be used repeatedly to add further directories to
-the search path.
-
-A list of templates can be passed to F<ttree> as command line arguments.
-
- $ ttree foo.html bar.html
-
-It looks for these templates in the C<src> directory and processes them
-through the Template Toolkit, using any additional template components
-from the C<lib> directories. The generated output is then written to
-the corresponding file in the C<dest> directory.
-
-If F<ttree> is invoked without explicitly specifying any templates
-to be processed then it will process every file in the C<src> directory.
-If the C<-r> (recurse) option is set then it will additionally iterate
-down through sub-directories and process and other template files it finds
-therein.
-
- $ ttree -r
-
-If a template has been processed previously, F<ttree> will compare the
-modification times of the source and destination files. If the source
-template (or one it is dependant on) has not been modified more
-recently than the generated output file then F<ttree> will not process
-it. The F<-a> (all) option can be used to force F<ttree> to process
-all files regardless of modification time.
-
- $ tree -a
-
-Any templates explicitly named as command line argument are always
-processed and the modification time checking is bypassed.
-
-=head2 File Options
-
-The C<ignore>, C<copy> and C<accept> options are used to specify Perl
-regexen to filter file names. Files that match any of the C<ignore>
-options will not be processed. Remaining files that match any of the
-C<copy> regexen will be copied to the destination directory. Remaining
-files that then match any of the C<accept> criteria are then processed
-via the Template Toolkit. If no C<accept> parameter is specified then
-all files will be accepted for processing if not already copied or
-ignored.
-
- # ignore these files
- ignore = \b(CVS|RCS)\b
- ignore = ^#
- ignore = ~$
-
- # copy these files
- copy = \.(gif|png|jpg|pdf)$
-
- # accept only .tt2 templates
- accept = \.tt2$
-
-The C<suffix> option is used to define mappings between the file
-extensions for source templates and the generated output files. The
-following example specifies that source templates with a C<.tt2>
-suffix should be output as C<.html> files:
-
- suffix tt2=html
-
-Or on the command line,
-
- --suffix tt2=html
-
-You can provide any number of different suffix mappings by repeating
-this option.
-
-=head2 Template Dependencies
-
-The C<depend> and C<depend_file> options allow you to specify
-how any given template file depends on another file or group of files.
-The C<depend> option is used to express a single dependency.
-
- $ ttree --depend foo=bar,baz
-
-This command line example shows the C<--depend> option being used to
-specify that the F<foo> file is dependant on the F<bar> and F<baz>
-templates. This option can be used many time on the command line:
-
- $ ttree --depend foo=bar,baz --depend crash=bang,wallop
-
-or in a configuration file:
-
- depend foo=bar,baz
- depend crash=bang,wallop
-
-The file appearing on the left of the C<=> is specified relative to
-the C<src> or C<lib> directories. The file(s) appearing on the right
-can be specified relative to any of these directories or as absolute
-file paths.
-
-For example:
-
- $ ttree --depend foo=bar,/tmp/baz
-
-To define a dependency that applies to all files, use C<*> on the
-left of the C<=>.
-
- $ ttree --depend *=header,footer
-
-or in a configuration file:
-
- depend *=header,footer
-
-Any templates that are defined in the C<pre_process>, C<post_process>,
-C<process> or C<wrapper> options will automatically be added to the
-list of global dependencies that apply to all templates.
-
-The C<depend_file> option can be used to specify a file that contains
-dependency information.
-
- $ ttree --depend_file=/home/abw/web/example/etc/ttree.dep
-
-Here is an example of a dependency file:
-
- # This is a comment. It is ignored.
-
- index.html: header footer menubar
-
- header: titlebar hotlinks
-
- menubar: menuitem
-
- # spanning multiple lines with the backslash
- another.html: header footer menubar \
- sidebar searchform
-
-Lines beginning with the C<#> character are comments and are ignored.
-Blank lines are also ignored. All other lines should provide a
-filename followed by a colon and then a list of dependant files
-separated by whitespace, commas or both. Whitespace around the colon
-is also optional. Lines ending in the C<\> character are continued
-onto the following line.
-
-Files that contain spaces can be quoted. That is only necessary
-for files after the colon (':'). The file before the colon may be
-quoted if it contains a colon.
-
-As with the command line options, the C<*> character can be used
-as a wildcard to specify a dependency for all templates.
-
- * : config,header
-
-=head2 Template Toolkit Options
-
-F<ttree> also provides access to the usual range of Template Toolkit
-options. For example, the C<--pre_chomp> and C<--post_chomp> F<ttree>
-options correspond to the C<PRE_CHOMP> and C<POST_CHOMP> options.
-
-Run C<ttree -h> for a summary of the options available.
-
-=head1 AUTHORS
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-With contributions from Dylan William Hardison (support for
-dependencies), Bryce Harrington (C<absolute> and C<relative> options),
-Mark Anderson (C<suffix> and C<debug> options), Harald Joerg and Leon
-Brocard who gets everywhere, it seems.
-
-=head1 VERSION
-
-2.69, distributed as part of the
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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.
-
-=head1 SEE ALSO
-
-L<tpage|Template::Tools::tpage>
-
diff --git a/lib/Template/Tutorial.pod b/lib/Template/Tutorial.pod
deleted file mode 100644
index b6c894f..0000000
--- a/lib/Template/Tutorial.pod
+++ /dev/null
@@ -1,109 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Tutorial
-#
-# DESCRIPTION
-# This section includes tutorials on using the Template Toolkit.
-# Subjects currently include an general overview of the Template
-# Toolkit, showing users how to get quickly up to speed building web
-# content, and a tutorial on generating and using data files, with
-# particular reference to XML.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-#
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Tutorial - Template Toolkit Tutorials
-
-=head1 DESCRIPTION
-
-This section includes tutorials on using the Template Toolkit. Subjects
-currently include an general overview of the Template Toolkit, showing
-users how to get quickly up to speed building web content, and a
-tutorial on generating and using data files, with particular reference
-to XML.
-
-=over 4
-
-=item L<Template::Tutorial::Web|Template::Tutorial::Web>
-
-Generating Web Content Using the Template Toolkit
-
-This tutorial provides an introduction to the Template Toolkit and a
-"quick start" guide to getting up to speed. Its primarily focus is on
-using the Template Toolkit to build web content and it covers 4 basic
-areas: using tpage and ttree; using the Template.pm module in CGI
-scripts; writing Apache/mod_perl handlers; and extending the toolkit by
-writing plugins.
-
-=item L<Template::Tutorial::Datafile|Template::Tutorial::Datafile>
-
-Creating Data Output Files Using the Template Toolkit
-
-This tutorial gives an overview of the Template Toolkit, showing in
-particular how to use it to read and write data files in various
-different formats and styles. It was written by Dave Cross and first
-appeared as a lead article at http://www.perl.com/ earlier in the year
-(2001).
-
-
-
-=back
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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:
diff --git a/lib/Template/Tutorial/Datafile.pod b/lib/Template/Tutorial/Datafile.pod
deleted file mode 100644
index 652f79d..0000000
--- a/lib/Template/Tutorial/Datafile.pod
+++ /dev/null
@@ -1,461 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Tutorial::Datafile
-#
-# DESCRIPTION
-# This tutorial gives an overview of the Template Toolkit, showing in
-# particular how to use it to read and write data files in various
-# different formats and styles. It was written by Dave Cross and
-# first appeared as a lead article at http://www.perl.com/ earlier in
-# the year (2001).
-#
-# AUTHOR
-# Dave Cross <dave@dave.org.uk>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-#
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Tutorial::Datafile - Creating Data Output Files Using the Template Toolkit
-
-=head1 DESCRIPTION
-
-This tutorial gives an overview of the Template Toolkit, showing in
-particular how to use it to read and write data files in various
-different formats and styles. It was written by Dave Cross and first
-appeared as a lead article at http://www.perl.com/ earlier in the year
-(2001).
-
-=head1 Introducing the Template Toolkit
-
-There are a number of Perl modules that are universally
-recognised as The Right Thing To Use for certain tasks. If you
-accessed a database without using DBI, pulled data from the WWW
-without using one of the LWP modules or parsed XML without using
-XML::Parser or one of its subclasses then you'd run the risk of
-being shunned by polite Perl society.
-
-I believe that the year 2000 saw the emergence of another 'must
-have' Perl module - the Template Toolkit. I don't think I'm
-alone in this belief as the Template Toolkit won the 'Best New
-Module' award at the Perl Conference last summer. Version 2.0 of
-the Template Toolkit (known as TT2 to its friends) was recently
-released to the CPAN.
-
-TT2 was designed and written by Andy Wardley E<lt>abw@wardley.orgE<gt>.
-It was born out of Andy's previous templating module,
-Text::Metatext, in best Fred Brooks 'plan to throw one away'
-manner; and aims to be the most useful (or, at least, the most
-I<used>) Perl templating system.
-
-TT2 provides a way to take a file of fixed boilerplate text
-(the template) and embed variable data within it. One obvious
-use of this is in the creation of dynamic web pages and this is
-where a lot of the attention that TT2 has received has been
-focussed. In this article, I hope to demonstrate that TT2 is
-just as useful in non-web applications.
-
-=head1 Using the Template Toolkit
-
-Let's look at how we'd use TT2 to process a simple data file.
-TT2 is an object oriented Perl module. Having downloaded it from
-CPAN and installed it in the usual manner, using it in your
-program is as easy as putting the lines
-
- use Template;
- my $tt = Template->new;
-
-in your code. The constructor function, C<new>, takes
-a number of optional parameters which are documented in the
-copious manual pages that come with the module, but for the
-purposes of this article we'll keep things as simple as
-possible.
-
-To process the template, you would call the C<process> method
-like this
-
- $tt->process('my_template', \%data)
- || die $tt->error;
-
-We pass two parameters to C<process>, the first is the name of
-the file containing the template to process (in this case,
-my_template) and the second is a reference to a hash which
-contains the data items that you want to use in the template. If
-processing the template gives any kind of error, the program
-will die with a (hopefully) useful error message.
-
-So what kinds of things can go in C<%data>? The answer is just
-about anything. Here's an example showing data about English
-Premier League football teams.
-
- my @teams = ({ name => 'Man Utd',
- played => 16,
- won => 12,
- drawn => 3,
- lost => 1 },
- { name => 'Bradford',
- played => 16,
- won => 2,
- drawn => 5,
- lost => 9 });
-
- my %data = ( name => 'English Premier League',
- season => '2000/01',
- teams => \@teams );
-
-This creates three data items which can be accessed within the
-template, called C<name>, C<season> and C<teams>. Notice that
-C<teams> is a complex data structure.
-
-Here is a template that we might use to process this data.
-
- League Standings
-
- League Name: [% name %]
- Season : [% season %]
-
- Teams:
- [% FOREACH team = teams -%]
- [% team.name %] [% team.played -%]
- [% team.won %] [% team.drawn %] [% team.lost %]
- [% END %]
-
-Running this template with this data gives us the following
-output
-
- League Standings
-
- League Name: English Premier League
- Season : 2000/01
-
- Teams:
- Man Utd 16 12 3 1
- Bradford 16 2 5 9
-
-Hopefully the syntax of the template is simple enough to
-follow. There are a few points to note.
-
-=over 4
-
-=item *
-
-Template processing directives are written using a simple
-language which is not Perl.
-
-=item *
-
-The keys of the C<%data> have become the names of the data
-variables within the template.
-
-=item *
-
-Template processing directives are surrounded by C<[%> and
-C<%]> sequences.
-
-=item *
-
-If these tags are replaced with C<[%-> C<-%]> then the preceding
-or following linefeed is suppressed.
-
-=item *
-
-In the C<FOREACH> loop, each element of the C<teams> list was
-assigned, in turn, to the temporary variable C<team>.
-
-=item *
-
-Each item assigned to the C<team> variable is a Perl hash.
-Individual values within the hash are accessed using a dot notation.
-
-=back
-
-It's probably the first and last of these points which are the
-most important. The first point emphasises the separation of the
-data acquisition logic from the presentation logic. The person
-creating the presentation template doesn't need to know Perl,
-they only need to know the data items which will be passed into
-the template.
-
-The last point demonstrates the way that TT2 protects the
-template designer from the implementation of the data structures.
-The data objects passed to the template processor can be scalars,
-arrays, hashes, objects or even subroutines. The template
-processor will just interpret your data correctly and Do The
-Right Thing to return the correct value to you. In this example
-each team was a hash, but in a larger system each team might be
-an object, in which case C<name>, C<played>, etc. would be accessor
-methods to the underlying object attributes. No changes would be
-required to the template as the template processor would realise
-that it needed to call methods rather than access hash values.
-
-=head2 A more complex example
-
-Stats about the English Football League are usually presented in
-a slightly more complex format than the one we used above. A
-full set of stats will show the number of games that a team has
-won, lost or drawn, the number of goals scored for and against
-the team and the number of points that the team therefore has.
-Teams gain three points for a win and one point for a draw. When
-teams have the same number of points they are separated by the
-goal difference, that is the number of goals the team has scored
-minus the number of team scored against them. To complicate
-things even further, the games won, drawn and lost and the goals
-for and against are often split between home and away games.
-
-Therefore if you have a data source which lists the team name
-togther with the games won, drawn and lost and the goals for and
-against split into home and away (a total of eleven data items)
-you can calculate all of the other items (goal difference,
-points awarded and even position in the league). Let's take such
-a file, but we'll only look at the top three teams. It will look
-something like this:
-
- Man Utd,7,1,0,26,4,5,2,1,15,6
- Arsenal,7,1,0,17,4,2,3,3,7,9
- Leicester,4,3,1,10,8,4,2,2,7,4
-
-A simple script to read this data into an array of hashes will
-look something like this (I've simplified the names of the data
-columns - w, d, and l are games won, drawn and lost and f and a
-are goals scored for and against; h and a at the front of a data
-item name indicates whether it's a home or away statistic):
-
- my @cols = qw(name hw hd hl hf ha aw ad al af aa);
-
- my @teams;
- while (<>) {
- chomp;
-
- my %team;
-
- @team{@cols} = split /,/;
-
- push @teams, \%team;
- }
-
-We can then go thru the teams again and calculate all of the
-derived data items:
-
- foreach (@teams) {
- $_->{w} = $_->{hw} + $_->{aw};
- $_->{d} = $_->{hd} + $_->{ad};
- $_->{l} = $_->{hl} + $_->{al};
-
- $_->{pl} = $_->{w} + $_->{d} + $_->{l};
-
- $_->{f} = $_->{hf} + $_->{af};
- $_->{a} = $_->{ha} + $_->{aa};
-
- $_->{gd} = $_->{f} - $_->{a};
- $_->{pt} = (3 * $_->{w}) + $_->{d};
- }
-
-And then produce a list sorted in descending order:
-
- @teams = sort {
- $b->{pt} <=> $b->{pt} || $b->{gd} <=> $a->{gd}
- } @teams;
-
-And finally add the league position data item:
-
- $teams[$_]->{pos} = $_ + 1
- foreach 0 .. $#teams;
-
-Having pulled all of our data into an internal data structure
-we can start to produce output using out templates. A template
-to create a CSV file containing the data split between home and
-away stats would look like this:
-
- [% FOREACH team = teams -%]
- [% team.pos %],[% team.name %],[% team.pl %],[% team.hw %],
- [%- team.hd %],[% team.hl %],[% team.hf %],[% team.ha %],
- [%- team.aw %],[% team.ad %],[% team.al %],[% team.af %],
- [%- team.aa %],[% team.gd %],[% team.pt %]
- [%- END %]
-
-And processing it like this:
-
- $tt->process('split.tt', { teams => \@teams }, 'split.csv')
- || die $tt->error;
-
-produces the following output:
-
- 1,Man Utd,16,7,1,0,26,4,5,2,1,15,6,31,39
- 2,Arsenal,16,7,1,0,17,4,2,3,3,7,9,11,31
- 3,Leicester,16,4,3,1,10,8,4,2,2,7,4,5,29
-
-Notice that we've introduced the third parameter to C<process>.
-If this parameter is missing then the TT2 sends its output to
-C<STDOUT>. If this parameter is a scalar then it is taken as the
-name of a file to write the output to. This parameter can also be
-(amongst other things) a filehandle or a reference to an object w
-hich is assumed to implement a C<print> method.
-
-If we weren't interested in the split between home and away games,
-then we could use a simpler template like this:
-
- [% FOREACH team = teams -%]
- [% team.pos %],[% team.name %],[% team.pl %],[% team.w %],
- [%- team.d %],[% team.l %],[% team.f %],[% team.a %],
- [%- team.aa %],[% team.gd %],[% team.pt %]
- [% END -%]
-
-Which would produce output like this:
-
- 1,Man Utd,16,12,3,1,41,10,6,31,39
- 2,Arsenal,16,9,4,3,24,13,9,11,31
- 3,Leicester,16,8,5,3,17,12,4,5,29
-
-=head1 Producing XML
-
-This is starting to show some of the power and flexibility of
-TT2, but you may be thinking that you could just as easily produce
-this output with a C<foreach> loop and a couple of C<print>
-statements in your code. This is, of course, true; but that's
-because I've chosen a deliberately simple example to explain the
-concepts. What if we wanted to produce an XML file containing the
-data? And what if (as I mentioned earlier) the league data was held
-in an object? The code would then look even easier as most of the code
-we've written earlier would be hidden away in C<FootballLeague.pm>.
-
- use FootballLeague;
- use Template;
-
- my $league = FootballLeague->new(name => 'English Premier');
-
- my $tt = Template->new;
-
- $tt->process('league_xml.tt', { league => $league })
- || die $tt->error;
-
-And the template in C<league_xml.tt> would look something like this:
-
- <?xml version="1.0"?>
- <!DOCTYPE LEAGUE SYSTEM "league.dtd">
-
- <league name="[% league.name %]" season="[% league.season %]">
- [% FOREACH team = league.teams -%]
- <team name="[% team.name %]"
- pos="[% team.pos %]"
- played="[% team.pl %]"
- goal_diff="[% team.gd %]"
- points="[% team.pt %]">
- <stats type="home">
- win="[% team.hw %]"
- draw="[%- team.hd %]"
- lose="[% team.hl %]"
- for="[% team.hf %]"
- against="[% team.ha %]" />
- <stats type="away">
- win="[% team.aw %]"
- draw="[%- team.ad %]"
- lose="[% team.al %]"
- for="[% team.af %]"
- against="[% team.aa %]" />
- </team>
- [% END -%]
- &/league>
-
-Notice that as we've passed the whole object into C<process> then
-we need to put an extra level of indirection on our template
-variables - everything is now a component of the C<league> variable.
-Other than that, everything in the template is very similar to what
-we've used before. Presumably now C<team.name> calls an accessor
-function rather than carrying out a hash lookup, but all of this
-is transparent to our template designer.
-
-=head1 Multiple Formats
-
-As a final example, let's suppose that we need to create output
-football league tables in a number of formats. Perhaps we are
-passing this data on to other people and they can't all use the
-same format. Some of our users need CSV files and others need
-XML. Some require data split between home and away matches and
-other just want the totals. In total, then, we'll need four
-different templates, but the good news is that they can use the
-same data object. All the script needs to do is to establish
-which template is required and process it.
-
- use FootballLeague;
- use Template;
-
- my ($name, $type, $stats) = @_;
-
- my $league = FootballLeague->new(name => $name);
-
- my $tt = Template->new;
-
- $tt->process("league_${type}_$stats.tt",
- { league => $league }
- "league_$stats.$type")
- || die $tt->error;
-
-For example, you can call this script as
-
- league.pl 'English Premier' xml split
-
-This will process a template called C<league_xml_split.tt>
-and put the results in a file called C<league_split.xml>.
-
-This starts to show the true strength of the Template Toolkit.
-If we later wanted to add another file format - perhaps we
-wanted to create a league table HTML page or even a LaTeX
-document - then we would just need to create the appropriate
-template and name it according to our existing naming
-convention. We would need to make no changes to the code.
-
-I hope you can now see why the Template Toolkit is fast becoming
-an essential part of many people's Perl installation.
-
-=head1 AUTHOR
-
-Dave Cross E<lt>dave@dave.org.ukE<gt>
-
-
-
-
-=head1 VERSION
-
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
-
-Copyright (C) 2001 Dave Cross E<lt>dave@dave.org.ukE<gt>
-
-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:
diff --git a/lib/Template/Tutorial/Web.pod b/lib/Template/Tutorial/Web.pod
deleted file mode 100644
index a5ed9bb..0000000
--- a/lib/Template/Tutorial/Web.pod
+++ /dev/null
@@ -1,801 +0,0 @@
-#============================================================= -*-perl-*-
-#
-# Template::Tutorial::Web
-#
-# DESCRIPTION
-# This tutorial provides an introduction to the Template Toolkit and
-# a "quick start" guide to getting up to speed. Its primarily focus
-# is on using the Template Toolkit to build web content and it covers
-# 4 basic areas: using tpage and ttree; using the Template.pm module
-# in CGI scripts; writing Apache/mod_perl handlers; and extending the
-# toolkit by writing plugins.
-#
-# AUTHOR
-# Andy Wardley <abw@andywardley.com>
-#
-# COPYRIGHT
-# Copyright (C) 1996-2001 Andy Wardley. All Rights Reserved.
-# Copyright (C) 1998-2001 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.
-#
-# REVISION
-#
-#
-#========================================================================
-
-
-#------------------------------------------------------------------------
-# IMPORTANT NOTE
-# This documentation is generated automatically from source
-# templates. Any changes you make here may be lost.
-#
-# The 'docsrc' documentation source bundle is available for download
-# from http://www.template-toolkit.org/docs.html and contains all
-# the source templates, XML files, scripts, etc., from which the
-# documentation for the Template Toolkit is built.
-#------------------------------------------------------------------------
-
-=head1 NAME
-
-Template::Tutorial::Web - Generating Web Content Using the Template Toolkit
-
-=head1 DESCRIPTION
-
-This tutorial document provides a introduction to the Template Toolkit
-and demonstrates some of the typical ways it may be used for
-generating web content. It covers the generation of static pages from
-templates using the L<tpage|Template::Tools::tpage> and
-L<ttree|Template::Tools::ttree> scripts and then goes on to
-show dynamic content generation using CGI scripts and Apache/mod_perl
-handlers.
-
-Various features of the Template Toolkit are introduced and described
-briefly and explained by use of example. For further information,
-see L<Template>, L<Template::Manual> and the various sections within
-it. e.g.
-
- perldoc Template # Template.pm module usage
- perldoc Template::Manual # index to manual
- perldoc Template::Manual::Config # e.g. configuration options
-
-The documentation is now also distributed in HTML format (or rather,
-in the form of HTML templates). See the 'docs' sub-directory of the
-distribution for further information on building the HTML documentation.
-
-If you're already reading this as part of the HTML documentation, then
-you don't need to worry about all that. You can have a seat, sit back.
- back and enjoy the rest of the tutorial...
-
-=head1 INTRODUCTION
-
-The Template Toolkit is a set of Perl modules which collectively
-implement a template processing system. In this context, a template
-is a text document containing special markup tags called 'directives'.
-A directive is an instruction for the template processor to perform
-some action and substitute the result into the document in place of
-the original directive. Directives include those to define or insert
-a variable value, iterate through a list of values (FOREACH), declare
-a conditional block (IF/UNLESS/ELSE), include and process another template
-file (INCLUDE) and so on.
-
-In all other respects, the document is a plain text file and may
-contain any other content (e.g. HTML, XML, RTF, LaTeX, etc). Directives
-are inserted in the document within the special markup tags which are
-'[%' and '%]' by default, but can be changed via the module
-configuration options. Here's an example of an HTML document with
-additional Template Toolkit directives.
-
- [% INCLUDE header
- title = 'This is an HTML example'
- %]
-
- <h1>Some Interesting Links</h1>
-
- [% webpages = [
- { url => 'http://foo.org', title => 'The Foo Organisation' }
- { url => 'http://bar.org', title => 'The Bar Organisation' }
- ]
- %]
-
- Links:
- <ul>
- [% FOREACH link = webpages %]
- <li><a href="[% link.url %]">[% link.title %]</a>
- [% END %]
- </ul>
-
- [% INCLUDE footer %]
-
-This example shows how the INCLUDE directive is used to load and process
-separate 'header' and 'footer' template files, including the output in
-the current document. These files might look like this:
-
-header:
-
- <html>
- <head>
- <title>[% title %]</title>
- </head>
-
- <body bgcolor="#ffffff">
-
-footer:
-
- <hr>
-
- <center>
- &copy; Copyright 2000 Me, Myself, I
- </center>
-
- </body>
- </html>
-
-The example also uses the FOREACH directive to iterate through the
-'webpages' list to build a table of links. In this example, we have
-defined this list within the template to contain a number of hash references,
-each containing a 'url' and 'title' member. The FOREACH directive
-iterates through the list, aliasing 'link' to each item (hash ref).
-The B<[% link.url %]> and B<[% link.title %]> directives then access
-the individual values in the hash and insert them into the document.
-
-The following sections show other ways in which data can be defined for
-use in a template.
-
-=head1 GENERATING STATIC PAGES
-
-Having created a template file we can now process it to generate some
-real output. The quickest and easiest way to do this is to use the
-F<tpage> script. This is provided as part of the Template Toolkit and
-should be installed in your usual Perl bin directory.
-
-Assuming you saved your template file as 'mypage.html', you would run
-the command:
-
- tpage mypage.html
-
-This will process the template file, sending the output to STDOUT
-(i.e. whizzing past you on the screen). You may want to redirect the
-output to a file but be careful not to specify the same name as the
-template file, or you'll overwrite it. You may want to use one prefix
-for your templates such as '.atml' (for 'Another Template Markup
-Language', perhaps?) and the regular '.html' for the output files
-(assuming you're creating HTML, that is). Alternatively, you might
-redirect the output to another directory. e.g.
-
- tpage mypage.atml > mypage.html
- tpage templates/mypage.html > html/mypage.html
-
-The B<tpage> script is very basic and only really intended to give you
-an easy way to process a template without having to write any Perl code.
-A much more flexible tool is B<ttree>, described below, but for now let's
-look at the output generated by processing the above example (some
-whitespace removed for brevity):
-
- <html>
- <head>
- <title>This is an HTML example</title>
- </head>
-
- <body bgcolor="#ffffff">
-
- <h1>Some Interesting Links</h1>
-
- Links:
- <ul>
- <li><a href="http://foo.org">The Foo Organsiation</a>
- <li><a href="http://bar.org">The Bar Organsiation</a>
- </ul>
-
- <hr>
-
- <center>
- &copy; Copyright 2000 Me, Myself, I
- </center>
-
- </body>
- </html>
-
-The F<header> and F<footer> template files have been included (assuming
-you created them and they're in the current directory) and the link data
-has been built into an HTML list.
-
-The F<ttree> script, also distributed as part of the Template Toolkit,
-provides a more flexible way to process template documents. The first
-time you run the script, it will ask you if it should create a
-configuration file, usually called '.ttreerc' in your home directory.
-Answer 'y' to have it create the file.
-
-The F<ttree> documentation describes how you can change the location
-of this file and also explains the syntax and meaning of the various
-options in the file. Comments are written to the sample configuration
-file which should also help.
-
- perldoc ttree
- ttree -h
-
-In brief, the configuration file describes the directories in which
-template files are to be found (src), where the corresponding output
-should be written to (dest), and any other directories (lib) that may
-contain template files that you plan to INCLUDE into your source
-documents. You can also specify processing options (such as 'verbose'
-and 'recurse') and provide regular expression to match files that you
-don't want to process (ignore, accept) or should be copied instead of
-processed (copy).
-
-An example F<.ttreerc> file is shown here:
-
-$HOME/.ttreerc:
- verbose
- recurse
-
- # this is where I keep other ttree config files
- cfg = ~/.ttree
-
- src = ~/websrc/src
- lib = ~/websrc/lib
- dest = ~/public_html/test
-
- ignore = \b(CVS|RCS)\b
- ignore = ^#
-
-You can create many different configuration files and store them
-in the directory specified in the 'cfg' option, shown above. You then
-add the C<-f filename> option to F<ttree> to have it read that file.
-
-When you run the script, it compares all the files in the 'src' directory
-(including those in sub-directories if the 'recurse' option is set), with
-those in the 'dest' directory. If the destination file doesn't exist or
-has an earlier modification time than the corresponding source file, then
-the source will be processed with the output written to the destination
-file. The C<-a> option forces all files to be processed, regardless of
-modification times.
-
-The script I<doesn't> process any of the files in the 'lib' directory,
-but it does add it to the INCLUDE_PATH for the template processor so
-that it can locate these files via an INCLUDE or PROCESS directive.
-Thus, the 'lib' directory is an excellent place to keep template elements
-such as header, footers, etc., that aren't complete documents in their
-own right.
-
-You can also specify various Template Toolkit options from the configuration
-file. Consult the B<ttree> documentation and help summary (C<ttree -h>)
-for full details. e.g.
-
-$HOME/.ttreerc:
- pre_process = config
- interpolate
- post_chomp
-
-The 'pre_process' option allows you to specify a template file which
-should be processed before each file. Unsurprisingly, there's also a
-'post_process' option to add a template after each file. In the
-fragment above, we have specified that the 'config' template should be
-used as a prefix template. We can create this file in the 'lib'
-directory and use it to define some common variables, including those
-web page links we defined earlier and might want to re-use in other
-templates. We could also include an HTML header, title, or menu bar
-in this file which would then be prepended to each and every template
-file, but for now we'll keep all that in a separate 'header' file.
-
-$lib/config:
-
- [% root = '~/abw'
- home = "$root/index.html"
- images = "$root/images"
- email = 'abw@wardley.org'
- graphics = 1
- webpages = [
- { url => 'http://foo.org', title => 'The Foo Organsiation' }
- { url => 'http://bar.org', title => 'The Bar Organsiation' }
- ]
- %]
-
-Assuming you've created or copied the 'header' and 'footer' files from the
-earlier example into your 'lib' directory, you can now start to create
-web pages like the following in your 'src' directory and process them
-with F<ttree>.
-
-$src/newpage.html:
-
- [% INCLUDE header
- title = 'Another Template Toolkit Test Page'
- %]
-
- <a href="[% home %]">Home</a>
- <a href="mailto:[% email %]">Email</a>
-
- [% IF graphics %]
- <img src="[% images %]/logo.gif" align=right width=60 height=40>
- [% END %]
-
- [% INCLUDE footer %]
-
-Here we've shown how pre-defined variables can be used as flags to
-enable certain feature (e.g. 'graphics') and to specify common items
-such as an email address and URL's for the home page, images directory
-and so on. This approach allows you to define these values once so
-that they're consistent across all pages and can easily be changed to
-new values.
-
-When you run B<ttree>, you should see output similar to the following
-(assuming you have the verbose flag set).
-
- ttree 1.14 (Template Toolkit version 1.02a)
-
- Source: /home/abw/websrc/src
- Destination: /home/abw/public_html/test
- Include Path: [ /home/abw/websrc/lib ]
- Ignore: [ \b(CVS|RCS)\b, ^# ]
- Copy: [ ]
- Accept: [ * ]
-
- + newpage.html
-
-The '+' before 'newpage.html' shows that the file was processed, with
-the output being written to the destination directory. If you run the
-same command again, you'll see the following line displayed instead
-showing a '-' and giving a reason why the file wasn't processed.
-
- - newpage.html (not modified)
-
-It has detected a 'newpage.html' in the destination directory which is
-more recent than that in the source directory and so hasn't bothered
-to waste time re-processing it. To force all files to be processed,
-use the C<-a> option. You can also specify one or more filenames as
-command line arguments to F<ttree>:
-
- tpage newpage.html
-
-This is what the destination page looks like.
-
-$dest/newpage.html:
-
- <html>
- <head>
- <title>Another Template Toolkit Test Page</title>
- </head>
-
- <body bgcolor="#ffffff">
-
- <a href="~/abw/index.html">Home</a>
- <a href="mailto:abw@wardley.org">Email me</a>
-
- <img src="~/abw/images/logo.gif" align=right width=60 height=40>
-
- <hr>
-
- <center>
- &copy; Copyright 2000 Me, Myself, I
- </center>
-
- </body>
- </html>
-
-You can add as many documents as you like to the 'src' directory and
-F<ttree> will apply the same process to them all. In this way, it is
-possible to build an entire tree of static content for a web site with
-a single command. The added benefit is that you can be assured of
-consistency in links, header style, or whatever else you choose to
-implement in terms of common templates elements or variables.
-
-=head1 DYNAMIC CONTENT GENERATION VIA CGI SCRIPT
-
-The L<Template|Template> module provides a simple front-end to the Template
-Toolkit for use in CGI scripts and Apache/mod_perl handlers. Simply
-'use' the Template module, create an object instance with the new()
-method and then call the process() method on the object, passing the
-name of the template file as a parameter. The second parameter passed
-is a reference to a hash array of variables that we want made available
-to the template:
-
- #!/usr/bin/perl -w
-
- use strict;
- use Template;
-
- my $file = 'src/greeting.html';
- my $vars = {
- message => "Hello World\n"
- };
-
- my $template = Template->new();
-
- $template->process($file, $vars)
- || die "Template process failed: ", $template->error(), "\n";
-
-So that our scripts will work with the same template files as our earlier
-examples, we'll can add some configuration options to the constructor to
-tell it about our environment:
-
- my $template->new({
- # where to find template files
- INCLUDE_PATH => '/home/abw/websrc/src:/home/abw/websrc/lib',
- # pre-process lib/config to define any extra values
- PRE_PROCESS => 'config',
- });
-
-Note that here we specify the 'config' file as a PRE_PROCESS option.
-This means that the templates we process can use the same global
-variables defined earlier for our static pages. We don't have to
-replicate their definitions in this script. However, we can supply
-additional data and functionality specific to this script via the hash
-of variables that we pass to the process() method.
-
-These entries in this hash may contain simple text or other values,
-references to lists, others hashes, sub-routines or objects. The Template
-Toolkit will automatically apply the correct procedure to access these
-different types when you use the variables in a template.
-
-Here's a more detailed example to look over. Amongst the different
-template variables we define in C<$vars>, we create a reference to a
-CGI object and a 'get_user_projects' sub-routine.
-
- #!/usr/bin/perl -w
-
- use strict;
- use Template;
- use CGI;
-
- $| = 1;
- print "Content-type: text/html\n\n";
-
- my $file = 'userinfo.html';
- my $vars = {
- 'version' => 3.14,
- 'days' => [ qw( mon tue wed thu fri sat sun ) ],
- 'worklist' => \&get_user_projects,
- 'cgi' => CGI->new(),
- 'me' => {
- 'id' => 'abw',
- 'name' => 'Andy Wardley',
- },
- };
-
- sub get_user_projects {
- my $user = shift;
- my @projects = ... # do something to retrieve data
- return \@projects;
- }
-
- my $template = Template->new({
- INCLUDE_PATH => '/home/abw/websrc/src:/home/abw/websrc/lib',
- PRE_PROCESS => 'config',
- });
-
- $template->process($file, $vars)
- || die $template->error();
-
-Here's a sample template file that we might create to build the output
-for this script.
-
-$src/userinfo.html:
-
- [% INCLUDE header
- title = 'Template Toolkit CGI Test'
- %]
-
- <a href="mailto:[% email %]">Email [% me.name %]</a>
-
- <p>This is version [% version %]</p>
-
- <h3>Projects</h3>
- <ul>
- [% FOREACH project = worklist(me.id) %]
- <li> <a href="[% project.url %]">[% project.name %]</a>
- [% END %]
- </ul>
-
- [% INCLUDE footer %]
-
-This example shows how we've separated the Perl implementation (code) from
-the presentation (HTML) which not only makes them easier to maintain in
-isolation, but also allows the re-use of existing template elements
-such as headers and footers, etc. By using template to create the
-output of your CGI scripts, you can give them the same consistency
-as your static pages built via L<ttree|Template::Tools::ttree> or
-other means.
-
-Furthermore, we can modify our script so that it processes any one of a
-number of different templates based on some condition. A CGI script to
-maintain a user database, for example, might process one template to
-provide an empty form for new users, the same form with some default
-values set for updating an existing user record, a third template for
-listing all users in the system, and so on. You can use any Perl
-functionality you care to write to implement the logic of your
-application and then choose one or other template to generate the
-desired output for the application state.
-
-=head1 DYNAMIC CONTENT GENERATION VIA APACHE/MOD_PERL HANDLER
-
-B<NOTE:> the Apache::Template module is now available from CPAN
-and provides a simple and easy to use Apache/mod_perl interface to the
-Template Toolkit. It's only in it's first release (0.01) at the time
-of writing and it currently only offers a fairly basic facility, but
-it implements most, if not all of what is described below, and it
-avoids the need to write your own handler. However, in many cases,
-you'll want to write your own handler to customise processing for your
-own need, and this section will show you how to get started.
-
-The Template module can be used in a similar way from an Apache/mod_perl
-handler. Here's an example of a typical Apache F<httpd.conf> file:
-
- PerlModule CGI;
- PerlModule Template
- PerlModule MyOrg::Apache::User
-
- PerlSetVar websrc_root /home/abw/websrc
-
- <Location /user/bin>
- SetHandler perl-script
- PerlHandler MyOrg::Apache::User
- </Location>
-
-This defines a location called '/user/bin' to which all requests will
-be forwarded to the handler() method of the MyOrg::Apache::User
-module. That module might look something like this:
-
- package MyOrg::Apache::User;
-
- use strict;
- use vars qw( $VERSION );
- use Apache::Constants qw( :common );
- use Template qw( :template );
- use CGI;
-
- $VERSION = 1.59;
-
- sub handler {
- my $r = shift;
-
- my $websrc = $r->dir_config('websrc_root')
- or return fail($r, SERVER_ERROR,
- "'websrc_root' not specified");
-
- my $template = Template->new({
- INCLUDE_PATH => "$websrc/src/user:$websrc/lib",
- PRE_PROCESS => 'config',
- OUTPUT => $r, # direct output to Apache request
- });
-
- my $params = {
- uri => $r->uri,
- cgi => CGI->new,
- };
-
- # use the path_info to determine which template file to process
- my $file = $r->path_info;
- $file =~ s[^/][];
-
- $r->content_type('text/html');
- $r->send_http_header;
-
- $template->process($file, $params)
- || return fail($r, SERVER_ERROR, $template->error());
-
- return OK;
- }
-
- sub fail {
- my ($r, $status, $message) = @_;
- $r->log_reason($message, $r->filename);
- return $status;
- }
-
-The handler accepts the request and uses it to determine the 'websrc_root'
-value from the config file. This is then used to define an INCLUDE_PATH
-for a new Template object. The URI is extracted from the request and a
-CGI object is created. These are both defined as template variables.
-
-The name of the template file itself is taken from the PATH_INFO element
-of the request. In this case, it would comprise the part of the URL
-coming after '/user/bin', e.g for '/user/bin/edit', the template file
-would be 'edit' located in "$websrc/src/user". The headers are sent
-and the template file is processed. All output is sent directly to the
-print() method of the Apache request object.
-
-=head1 USING PLUGINS TO EXTEND FUNCTIONALITY
-
-As we've already shown, it is possible to bind Perl data and functions
-to template variables when creating dynamic content via a CGI script
-or Apache/mod_perl process. The Template Toolkit also supports a
-plugin interface which allows you define such additional data and/or
-functionality in a separate module and then load and use it as
-required with the USE directive.
-
-The main benefit to this approach is that you can load the extension into
-any template document, even those that are processed "statically" by
-F<tpage> or F<ttree>. You I<don't> need to write a Perl wrapper to
-explicitly load the module and make it available via the stash.
-
-Let's demonstrate this principle using the DBI plugin written by Simon
-Matthews E<lt>sam@knowledgepool.comE<gt>. You can create this
-template in your 'src' directory and process it using F<ttree> to see
-the results. Of course, this example relies on the existence of the
-appropriate SQL database but you should be able to adapt it to your
-own resources, or at least use it as a demonstrative example of what's
-possible.
-
- [% INCLUDE header
- title = 'User Info'
- %]
-
- [% USE DBI('dbi:mSQL:mydbname') %]
-
- <table border=0 width="100%">
- <tr>
- <th>User ID</th>
- <th>Name</th>
- <th>Email</th>
- </tr>
-
- [% FOREACH user = DBI.query('SELECT * FROM user ORDER BY id') %]
- <tr>
- <td>[% user.id %]</td>
- <td>[% user.name %]</td>
- <td>[% user.email %]</td>
- </tr>
- [% END %]
-
- </table>
-
- [% INCLUDE footer %]
-
-A plugin is simply a Perl module in a known location and conforming to
-a known standard such that the Template Toolkit can find and load it
-automatically. You can create your own plugin by inheriting from the
-F<Template::Plugin> module.
-
-Here's an example which defines some data items ('foo' and 'people')
-and also an object method ('bar'). We'll call the plugin 'FooBar' for
-want of a better name and create it in the 'MyOrg::Template::Plugin::FooBar'
-package. We've added a 'MyOrg' to the regular 'Template::Plugin::*' package
-to avoid any conflict with existing plugins.
-
-You can create a module stub using the Perl utlity F<h2xs>:
-
- h2xs -A -X -n MyOrg::Template::Plugin::FooBar
-
-This will create a directory structure representing the package name
-along with a set of files comprising your new module. You can then
-edit FooBar.pm to look something like this:
-
- package MyOrg::Template::Plugin::FooBar;
-
- use Template::Plugin;
- use vars qw( $VERSION );
- use base qw( Template::Plugin );
-
- $VERSION = 1.23;
-
- sub new {
- my ($class, $context, @params) = @_;
-
- bless {
- _CONTEXT => $context,
- foo => 25,
- people => [ 'tom', 'dick', 'harry' ],
- }, $class;
- }
-
- sub bar {
- my ($self, @params) = @_;
- # ...do something...
- return $some_value;
- }
-
-The plugin constructor new() receives the class name as the first
-parameter, as is usual in Perl, followed by a reference to something
-called a Template::Context object. You don't need to worry too much
-about this at the moment, other than to know that it's the main
-processing object for the Template Toolkit. It provides access to the
-functionality of the processor and some plugins may need to
-communicate with it. We don't at this stage, but we'll save the
-reference anyway in the '_CONTEXT' member. The leading underscore is
-a convention which indicates that this item is private and the
-Template Toolkit won't attempt to access this member. The other
-members defined, 'foo' and 'people' are regular data items which will be
-made available to templates using this plugin. Following the context
-reference are passed any additional parameters specified with the
-USE directive, such as the data source parameter, 'dbi:mSQL:mydbname',
-that we used in the earlier DBI example.
-
-If you used F<h2xs> to create the module stub then you'll already
-have a Makefile.PL and you can incite the familiar incantation to
-build and install it. Don't forget to add some tests to test.pl!
-
- perl Makefile.PL
- make
- make test
- make install
-
-If you don't or can't install it to the regular place for your Perl
-modules (perhaps because you don't have the required privileges) then
-you can set the PERL5LIB environment variable to specify another location.
-If you're using F<ttree> then you can add the following line to your
-configuration file instead. This has the effect of add '/path/to/modules'
-to the @INC array to a similar end.
-
-$HOME/.ttreerc:
-
- perl5lib = /path/to/modules
-
-One further configuration item must be added to inform the toolkit of
-the new package name we have adopted for our plugins:
-
-$HOME/.ttreerc:
-
- plugin_base = 'MyOrg::Template::Plugin'
-
-If you're writing Perl code to control the Template modules directly,
-then this value can be passed as a configuration parameter when you
-create the module.
-
- use Template;
-
- my $template = Template->new({
- PLUGIN_BASE => 'MyOrg::Template::Plugin'
- });
-
-Now we can create a template which uses this plugin:
-
- [% INCLUDE header
- title = 'FooBar Plugin Test'
- %]
-
- [% USE FooBar %]
-
- Some values available from this plugin:
- [% FooBar.foo %] [% FooBar.bar %]
-
- The users defined in the 'people' list:
- [% FOREACH uid = FooBar.people %]
- * [% uid %]
- [% END %]
-
- [% INCLUDE footer %]
-
-The 'foo', 'bar' and 'people' items of the FooBar plugin are
-automatically resolved to the appropriate data items or method calls
-on the underlying object.
-
-Using this approach, it is possible to create application
-functionality in a single module which can then be loaded and used on
-demand in any template. The simple interface between template
-directives and plugin objects allows complex, dynamic content to be
-built from a few simple template documents without knowing anything
-about the underlying implementation.
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@andywardley.comE<gt>
-
-L<http://www.andywardley.com/|http://www.andywardley.com/>
-
-
-
-
-=head1 VERSION
-
-Template Toolkit version 2.13, released on 30 January 2004.
-
-=head1 COPYRIGHT
-
- Copyright (C) 1996-2004 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:
diff --git a/lib/Template/View.pm b/lib/Template/View.pm
deleted file mode 100644
index 6de8d42..0000000
--- a/lib/Template/View.pm
+++ /dev/null
@@ -1,752 +0,0 @@
-#============================================================= -*-Perl-*-
-#
-# Template::View
-#
-# DESCRIPTION
-# A custom view of a template processing context. Can be used to
-# implement custom "skins".
-#
-# AUTHOR
-# Andy Wardley <abw@kfs.org>
-#
-# COPYRIGHT
-# Copyright (C) 2000 Andy Wardley. All Rights Reserved.
-#
-# This module is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-#
-# TODO
-# * allowing print to have a hash ref as final args will cause problems
-# if you do this: [% view.print(hash1, hash2, hash3) %]. Current
-# work-around is to do [% view.print(hash1); view.print(hash2);
-# view.print(hash3) %] or [% view.print(hash1, hash2, hash3, { }) %]
-#
-# REVISION
-# $Id: View.pm,v 2.9 2004/01/30 18:36:11 abw Exp $
-#
-#============================================================================
-
-package Template::View;
-
-require 5.004;
-
-use strict;
-use vars qw( $VERSION $DEBUG $AUTOLOAD @BASEARGS $MAP );
-use base qw( Template::Base );
-
-$VERSION = sprintf("%d.%02d", q$Revision: 2.9 $ =~ /(\d+)\.(\d+)/);
-$DEBUG = 0 unless defined $DEBUG;
-@BASEARGS = qw( context );
-$MAP = {
- HASH => 'hash',
- ARRAY => 'list',
- TEXT => 'text',
- default => '',
-};
-
-$DEBUG = 0;
-
-#------------------------------------------------------------------------
-# _init(\%config)
-#
-# Initialisation method called by the Template::Base class new()
-# constructor. $self->{ context } has already been set, by virtue of
-# being named in @BASEARGS. Remaining config arguments are presented
-# as a hash reference.
-#------------------------------------------------------------------------
-
-sub _init {
- my ($self, $config) = @_;
-
- # move 'context' somewhere more private
- $self->{ _CONTEXT } = $self->{ context };
- delete $self->{ context };
-
- # generate table mapping object types to templates
- my $map = $config->{ map } || { };
- $map->{ default } = $config->{ default } unless defined $map->{ default };
- $self->{ map } = {
- %$MAP,
- %$map,
- };
-
- # local BLOCKs definition table
- $self->{ _BLOCKS } = $config->{ blocks } || { };
-
- # name of presentation method which printed objects might provide
- $self->{ method } = defined $config->{ method }
- ? $config->{ method } : 'present';
-
- # view is sealed by default preventing variable update after
- # definition, however we don't actually seal a view until the
- # END of the view definition
- my $sealed = $config->{ sealed };
- $sealed = 1 unless defined $sealed;
- $self->{ sealed } = $sealed ? 1 : 0;
-
- # copy remaining config items from $config or set defaults
- foreach my $arg (qw( base prefix suffix notfound silent )) {
- $self->{ $arg } = $config->{ $arg } || '';
- }
-
- # name of data item used by view()
- $self->{ item } = $config->{ item } || 'item';
-
- # map methods of form ${include_prefix}_foobar() to include('foobar')?
- $self->{ include_prefix } = $config->{ include_prefix } || 'include_';
- # what about mapping foobar() to include('foobar')?
- $self->{ include_naked } = defined $config->{ include_naked }
- ? $config->{ include_naked } : 1;
-
- # map methods of form ${view_prefix}_foobar() to include('foobar')?
- $self->{ view_prefix } = $config->{ view_prefix } || 'view_';
- # what about mapping foobar() to view('foobar')?
- $self->{ view_naked } = $config->{ view_naked } || 0;
-
- # the view is initially unsealed, allowing directives in the initial
- # view template to create data items via the AUTOLOAD; once sealed via
- # call to seal(), the AUTOLOAD will not update any internal items.
- delete @$config{ qw( base method map default prefix suffix notfound item
- include_prefix include_naked silent sealed
- view_prefix view_naked blocks ) };
- $config = { %{ $self->{ base }->{ data } }, %$config }
- if $self->{ base };
- $self->{ data } = $config;
- $self->{ SEALED } = 0;
-
- return $self;
-}
-
-
-#------------------------------------------------------------------------
-# seal()
-# unseal()
-#
-# Seal or unseal the view to allow/prevent new datat items from being
-# automatically created by the AUTOLOAD method.
-#------------------------------------------------------------------------
-
-sub seal {
- my $self = shift;
- $self->{ SEALED } = $self->{ sealed };
-}
-
-sub unseal {
- my $self = shift;
- $self->{ SEALED } = 0;
-}
-
-
-#------------------------------------------------------------------------
-# clone(\%config)
-#
-# Cloning method which takes a copy of $self and then applies to it any
-# modifications specified in the $config hash passed as an argument.
-# Configuration items may also be specified as a list of "name => $value"
-# arguments. Returns a reference to the cloned Template::View object.
-#
-# NOTE: may need to copy BLOCKS???
-#------------------------------------------------------------------------
-
-sub clone {
- my $self = shift;
- my $clone = bless { %$self }, ref $self;
- my $config = ref $_[0] eq 'HASH' ? shift : { @_ };
-
- # merge maps
- $clone->{ map } = {
- %{ $self->{ map } },
- %{ $config->{ map } || { } },
- };
-
- # "map => { default=>'xxx' }" can be specified as "default => 'xxx'"
- $clone->{ map }->{ default } = $config->{ default }
- if defined $config->{ default };
-
- # update any remaining config items
- my @args = qw( base prefix suffix notfound item method include_prefix
- include_naked view_prefix view_naked );
- foreach my $arg (@args) {
- $clone->{ $arg } = $config->{ $arg } if defined $config->{ $arg };
- }
- push(@args, qw( default map ));
- delete @$config{ @args };
-
- # anything left is data
- my $data = $clone->{ data } = { %{ $self->{ data } } };
- @$data{ keys %$config } = values %$config;
-
- return $clone;
-}
-
-
-#------------------------------------------------------------------------
-# print(@items, ..., \%config)
-#
-# Prints @items in turn by mapping each to an approriate template using
-# the internal 'map' hash. If an entry isn't found and the item is an
-# object that implements the method named in the internal 'method' item,
-# (default: 'present'), then the method will be called passing a reference
-# to $self, against which the presenter method may make callbacks (e.g.
-# to view_item()). If the presenter method isn't implemented, then the
-# 'default' map entry is consulted and used if defined. The final argument
-# may be a reference to a hash array providing local overrides to the internal
-# defaults for various items (prefix, suffix, etc). In the presence
-# of this parameter, a clone of the current object is first made, applying
-# any configuration updates, and control is then delegated to it.
-#------------------------------------------------------------------------
-
-sub print {
- my $self = shift;
-
- # if final config hash is specified then create a clone and delegate to it
- # NOTE: potential problem when called print(\%data_hash1, \%data_hash2);
- if ((scalar @_ > 1) && (ref $_[-1] eq 'HASH')) {
- my $cfg = pop @_;
- my $clone = $self->clone($cfg)
- || return;
- return $clone->print(@_)
- || $self->error($clone->error());
- }
- my ($item, $type, $template, $present);
- my $method = $self->{ method };
- my $map = $self->{ map };
- my $output = '';
-
- # print each argument
- foreach $item (@_) {
- my $newtype;
-
- if (! ($type = ref $item)) {
- # non-references are TEXT
- $type = 'TEXT';
- $template = $map->{ $type };
- }
- elsif (! defined ($template = $map->{ $type })) {
- # no specific map entry for object, maybe it implements a
- # 'present' (or other) method?
- if ( $method && UNIVERSAL::can($item, $method) ) {
- $present = $item->$method($self); ## call item method
- # undef returned indicates error, note that we expect
- # $item to have called error() on the view
- return unless defined $present;
- $output .= $present;
- next; ## NEXT
- }
- elsif ( UNIVERSAL::isa($item, 'HASH' )
- && defined($newtype = $item->{$method})
- && defined($template = $map->{"$method=>$newtype"})) {
- }
- elsif ( defined($newtype)
- && defined($template = $map->{"$method=>*"}) ) {
- $template =~ s/\*/$newtype/;
- }
- elsif (! ($template = $map->{ default }) ) {
- # default not defined, so construct template name from type
- ($template = $type) =~ s/\W+/_/g;
- }
- }
-# else {
-# $self->DEBUG("defined map type for $type: $template\n");
-# }
- $self->DEBUG("printing view '", $template || '', "', $item\n") if $DEBUG;
- $output .= $self->view($template, $item)
- if $template;
- }
- return $output;
-}
-
-
-#------------------------------------------------------------------------
-# view($template, $item, \%vars)
-#
-# Wrapper around include() which expects a template name, $template,
-# followed by a data item, $item, and optionally, a further hash array
-# of template variables. The $item is added as an entry to the $vars
-# hash (which is created empty if not passed as an argument) under the
-# name specified by the internal 'item' member, which is appropriately
-# 'item' by default. Thus an external object present() method can
-# callback against this object method, simply passing a data item to
-# be displayed. The external object doesn't have to know what the
-# view expects the item to be called in the $vars hash.
-#------------------------------------------------------------------------
-
-sub view {
- my ($self, $template, $item) = splice(@_, 0, 3);
- my $vars = ref $_[0] eq 'HASH' ? shift : { @_ };
- $vars->{ $self->{ item } } = $item if defined $item;
- $self->include($template, $vars);
-}
-
-
-#------------------------------------------------------------------------
-# include($template, \%vars)
-#
-# INCLUDE a template, $template, mapped according to the current prefix,
-# suffix, default, etc., where $vars is an optional hash reference
-# containing template variable definitions. If the template isn't found
-# then the method will default to any 'notfound' template, if defined
-# as an internal item.
-#------------------------------------------------------------------------
-
-sub include {
- my ($self, $template, $vars) = @_;
- my $context = $self->{ _CONTEXT };
-
- $template = $self->template($template);
-
- $vars = { } unless ref $vars eq 'HASH';
- $vars->{ view } ||= $self;
-
- $context->include( $template, $vars );
-
-# DEBUGGING
-# my $out = $context->include( $template, $vars );
-# print STDERR "VIEW return [$out]\n";
-# return $out;
-}
-
-
-#------------------------------------------------------------------------
-# template($template)
-#
-# Returns a compiled template for the specified template name, according
-# to the current configuration parameters.
-#------------------------------------------------------------------------
-
-sub template {
- my ($self, $name) = @_;
- my $context = $self->{ _CONTEXT };
- return $context->throw(Template::Constants::ERROR_VIEW,
- "no view template specified")
- unless $name;
-
- my $notfound = $self->{ notfound };
- my $base = $self->{ base };
- my ($template, $block, $error);
-
- return $block
- if ($block = $self->{ _BLOCKS }->{ $name });
-
- # try the named template
- $template = $self->template_name($name);
- $self->DEBUG("looking for $template\n") if $DEBUG;
- eval { $template = $context->template($template) };
-
- # try asking the base view if not found
- if (($error = $@) && $base) {
- $self->DEBUG("asking base for $name\n") if $DEBUG;
- eval { $template = $base->template($name) };
- }
-
- # try the 'notfound' template (if defined) if that failed
- if (($error = $@) && $notfound) {
- unless ($template = $self->{ _BLOCKS }->{ $notfound }) {
- $notfound = $self->template_name($notfound);
- $self->DEBUG("not found, looking for $notfound\n") if $DEBUG;
- eval { $template = $context->template($notfound) };
-
- return $context->throw(Template::Constants::ERROR_VIEW, $error)
- if $@; # return first error
- }
- }
- elsif ($error) {
- $self->DEBUG("no 'notfound'\n")
- if $DEBUG;
- return $context->throw(Template::Constants::ERROR_VIEW, $error);
- }
- return $template;
-}
-
-
-#------------------------------------------------------------------------
-# template_name($template)
-#
-# Returns the name of the specified template with any appropriate prefix
-# and/or suffix added.
-#------------------------------------------------------------------------
-
-sub template_name {
- my ($self, $template) = @_;
- $template = $self->{ prefix } . $template . $self->{ suffix }
- if $template;
-
- $self->DEBUG("template name: $template\n") if $DEBUG;
- return $template;
-}
-
-
-#------------------------------------------------------------------------
-# default($val)
-#
-# Special case accessor to retrieve/update 'default' as an alias for
-# '$map->{ default }'.
-#------------------------------------------------------------------------
-
-sub default {
- my $self = shift;
- return @_ ? ($self->{ map }->{ default } = shift)
- : $self->{ map }->{ default };
-}
-
-
-#------------------------------------------------------------------------
-# AUTOLOAD
-#
-
-# Returns/updates public internal data items (i.e. not prefixed '_' or
-# '.') or presents a view if the method matches the view_prefix item,
-# e.g. view_foo(...) => view('foo', ...). Similarly, the
-# include_prefix is used, if defined, to map include_foo(...) to
-# include('foo', ...). If that fails then the entire method name will
-# be used as the name of a template to include iff the include_named
-# parameter is set (default: 1). Last attempt is to match the entire
-# method name to a view() call, iff view_naked is set. Otherwise, a
-# 'view' exception is raised reporting the error "no such view member:
-# $method".
-#------------------------------------------------------------------------
-
-sub AUTOLOAD {
- my $self = shift;
- my $item = $AUTOLOAD;
- $item =~ s/.*:://;
- return if $item eq 'DESTROY';
-
- if ($item =~ /^[\._]/) {
- return $self->{ _CONTEXT }->throw(Template::Constants::ERROR_VIEW,
- "attempt to view private member: $item");
- }
- elsif (exists $self->{ $item }) {
- # update existing config item (e.g. 'prefix') if unsealed
- return $self->{ _CONTEXT }->throw(Template::Constants::ERROR_VIEW,
- "cannot update config item in sealed view: $item")
- if @_ && $self->{ SEALED };
- $self->DEBUG("accessing item: $item\n") if $DEBUG;
- return @_ ? ($self->{ $item } = shift) : $self->{ $item };
- }
- elsif (exists $self->{ data }->{ $item }) {
- # get/update existing data item (must be unsealed to update)
- if (@_ && $self->{ SEALED }) {
- return $self->{ _CONTEXT }->throw(Template::Constants::ERROR_VIEW,
- "cannot update item in sealed view: $item")
- unless $self->{ silent };
- # ignore args if silent
- @_ = ();
- }
- $self->DEBUG(@_ ? "updating data item: $item <= $_[0]\n"
- : "returning data item: $item\n") if $DEBUG;
- return @_ ? ($self->{ data }->{ $item } = shift)
- : $self->{ data }->{ $item };
- }
- elsif (@_ && ! $self->{ SEALED }) {
- # set data item if unsealed
- $self->DEBUG("setting unsealed data: $item => @_\n") if $DEBUG;
- $self->{ data }->{ $item } = shift;
- }
- elsif ($item =~ s/^$self->{ view_prefix }//) {
- $self->DEBUG("returning view($item)\n") if $DEBUG;
- return $self->view($item, @_);
- }
- elsif ($item =~ s/^$self->{ include_prefix }//) {
- $self->DEBUG("returning include($item)\n") if $DEBUG;
- return $self->include($item, @_);
- }
- elsif ($self->{ include_naked }) {
- $self->DEBUG("returning naked include($item)\n") if $DEBUG;
- return $self->include($item, @_);
- }
- elsif ($self->{ view_naked }) {
- $self->DEBUG("returning naked view($item)\n") if $DEBUG;
- return $self->view($item, @_);
- }
- else {
- return $self->{ _CONTEXT }->throw(Template::Constants::ERROR_VIEW,
- "no such view member: $item");
- }
-}
-
-
-1;
-
-
-__END__
-
-=head1 NAME
-
-Template::View - customised view of a template processing context
-
-=head1 SYNOPSIS
-
- # define a view
- [% VIEW view
- # some standard args
- prefix => 'my_',
- suffix => '.tt2',
- notfound => 'no_such_file'
- ...
-
- # any other data
- title => 'My View title'
- other_item => 'Joe Random Data'
- ...
- %]
- # add new data definitions, via 'my' self reference
- [% my.author = "$abw.name <$abw.email>" %]
- [% my.copy = "&copy; Copyright 2000 $my.author" %]
-
- # define a local block
- [% BLOCK header %]
- This is the header block, title: [% title or my.title %]
- [% END %]
-
- [% END %]
-
- # access data items for view
- [% view.title %]
- [% view.other_item %]
-
- # access blocks directly ('include_naked' option, set by default)
- [% view.header %]
- [% view.header(title => 'New Title') %]
-
- # non-local templates have prefix/suffix attached
- [% view.footer %] # => [% INCLUDE my_footer.tt2 %]
-
- # more verbose form of block access
- [% view.include( 'header', title => 'The Header Title' ) %]
- [% view.include_header( title => 'The Header Title' ) %]
-
- # very short form of above ('include_naked' option, set by default)
- [% view.header( title => 'The Header Title' ) %]
-
- # non-local templates have prefix/suffix attached
- [% view.footer %] # => [% INCLUDE my_footer.tt2 %]
-
- # fallback on the 'notfound' template ('my_no_such_file.tt2')
- # if template not found
- [% view.include('missing') %]
- [% view.include_missing %]
- [% view.missing %]
-
- # print() includes a template relevant to argument type
- [% view.print("some text") %] # type=TEXT, template='text'
-
- [% BLOCK my_text.tt2 %] # 'text' with prefix/suffix
- Text: [% item %]
- [% END %]
-
- # now print() a hash ref, mapped to 'hash' template
- [% view.print(some_hash_ref) %] # type=HASH, template='hash'
-
- [% BLOCK my_hash.tt2 %] # 'hash' with prefix/suffix
- hash keys: [% item.keys.sort.join(', ')
- [% END %]
-
- # now print() a list ref, mapped to 'list' template
- [% view.print(my_list_ref) %] # type=ARRAY, template='list'
-
- [% BLOCK my_list.tt2 %] # 'list' with prefix/suffix
- list: [% item.join(', ') %]
- [% END %]
-
- # print() maps 'My::Object' to 'My_Object'
- [% view.print(myobj) %]
-
- [% BLOCK my_My_Object.tt2 %]
- [% item.this %], [% item.that %]
- [% END %]
-
- # update mapping table
- [% view.map.ARRAY = 'my_list_template' %]
- [% view.map.TEXT = 'my_text_block' %]
-
-
- # change prefix, suffix, item name, etc.
- [% view.prefix = 'your_' %]
- [% view.default = 'anyobj' %]
- ...
-
-=head1 DESCRIPTION
-
-TODO
-
-=head1 METHODS
-
-=head2 new($context, \%config)
-
-Creates a new Template::View presenting a custom view of the specified
-$context object.
-
-A reference to a hash array of configuration options may be passed as the
-second argument.
-
-=over 4
-
-=item prefix
-
-Prefix added to all template names.
-
- [% USE view(prefix => 'my_') %]
- [% view.view('foo', a => 20) %] # => my_foo
-
-=item suffix
-
-Suffix added to all template names.
-
- [% USE view(suffix => '.tt2') %]
- [% view.view('foo', a => 20) %] # => foo.tt2
-
-=item map
-
-Hash array mapping reference types to template names. The print()
-method uses this to determine which template to use to present any
-particular item. The TEXT, HASH and ARRAY items default to 'test',
-'hash' and 'list' appropriately.
-
- [% USE view(map => { ARRAY => 'my_list',
- HASH => 'your_hash',
- My::Foo => 'my_foo', } ) %]
-
- [% view.print(some_text) %] # => text
- [% view.print(a_list) %] # => my_list
- [% view.print(a_hash) %] # => your_hash
- [% view.print(a_foo) %] # => my_foo
-
- [% BLOCK text %]
- Text: [% item %]
- [% END %]
-
- [% BLOCK my_list %]
- list: [% item.join(', ') %]
- [% END %]
-
- [% BLOCK your_hash %]
- hash keys: [% item.keys.sort.join(', ')
- [% END %]
-
- [% BLOCK my_foo %]
- Foo: [% item.this %], [% item.that %]
- [% END %]
-
-=item method
-
-Name of a method which objects passed to print() may provide for presenting
-themselves to the view. If a specific map entry can't be found for an
-object reference and it supports the method (default: 'present') then
-the method will be called, passing the view as an argument. The object
-can then make callbacks against the view to present itself.
-
- package Foo;
-
- sub present {
- my ($self, $view) = @_;
- return "a regular view of a Foo\n";
- }
-
- sub debug {
- my ($self, $view) = @_;
- return "a debug view of a Foo\n";
- }
-
-In a template:
-
- [% USE view %]
- [% view.print(my_foo_object) %] # a regular view of a Foo
-
- [% USE view(method => 'debug') %]
- [% view.print(my_foo_object) %] # a debug view of a Foo
-
-=item default
-
-Default template to use if no specific map entry is found for an item.
-
- [% USE view(default => 'my_object') %]
-
- [% view.print(objref) %] # => my_object
-
-If no map entry or default is provided then the view will attempt to
-construct a template name from the object class, substituting any
-sequence of non-word characters to single underscores, e.g.
-
- # 'fubar' is an object of class Foo::Bar
- [% view.print(fubar) %] # => Foo_Bar
-
-Any current prefix and suffix will be added to both the default template
-name and any name constructed from the object class.
-
-=item notfound
-
-Fallback template to use if any other isn't found.
-
-=item item
-
-Name of the template variable to which the print() method assigns the current
-item. Defaults to 'item'.
-
- [% USE view %]
- [% BLOCK list %]
- [% item.join(', ') %]
- [% END %]
- [% view.print(a_list) %]
-
- [% USE view(item => 'thing') %]
- [% BLOCK list %]
- [% thing.join(', ') %]
- [% END %]
- [% view.print(a_list) %]
-
-=item view_prefix
-
-Prefix of methods which should be mapped to view() by AUTOLOAD. Defaults
-to 'view_'.
-
- [% USE view %]
- [% view.view_header() %] # => view('header')
-
- [% USE view(view_prefix => 'show_me_the_' %]
- [% view.show_me_the_header() %] # => view('header')
-
-=item view_naked
-
-Flag to indcate if any attempt should be made to map method names to
-template names where they don't match the view_prefix. Defaults to 0.
-
- [% USE view(view_naked => 1) %]
-
- [% view.header() %] # => view('header')
-
-=back
-
-=head2 print( $obj1, $obj2, ... \%config)
-
-TODO
-
-=head2 view( $template, \%vars, \%config );
-
-TODO
-
-=head1 AUTHOR
-
-Andy Wardley E<lt>abw@kfs.orgE<gt>
-
-=head1 REVISION
-
-$Revision: 2.9 $
-
-=head1 COPYRIGHT
-
-Copyright (C) 2000 Andy Wardley. All Rights Reserved.
-
-This module is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 SEE ALSO
-
-L<Template::Plugin|Template::Plugin>,
-
-=cut
-
-
-
-
-
diff --git a/lib/Text/Wrap.pm b/lib/Text/Wrap.pm
deleted file mode 100644
index 72574f6..0000000
--- a/lib/Text/Wrap.pm
+++ /dev/null
@@ -1,106 +0,0 @@
-package Text::Wrap;
-
-require Exporter;
-
-@ISA = qw(Exporter);
-@EXPORT = qw(wrap fill);
-@EXPORT_OK = qw($columns $break $huge);
-
-$VERSION = 2001.09291;
-
-use vars qw($VERSION $columns $debug $break $huge $unexpand $tabstop
- $separator);
-use strict;
-
-BEGIN {
- $columns = 76; # <= screen width
- $debug = 0;
- $break = '\s';
- $huge = 'wrap'; # alternatively: 'die' or 'overflow'
- $unexpand = 1;
- $tabstop = 8;
- $separator = "\n";
-}
-
-use Text::Tabs qw(expand unexpand);
-
-sub wrap
-{
- my ($ip, $xp, @t) = @_;
-
- local($Text::Tabs::tabstop) = $tabstop;
- my $r = "";
- my $tail = pop(@t);
- my $t = expand(join("", (map { /\s+\z/ ? ( $_ ) : ($_, ' ') } @t), $tail));
- my $lead = $ip;
- my $ll = $columns - length(expand($ip)) - 1;
- $ll = 0 if $ll < 0;
- my $nll = $columns - length(expand($xp)) - 1;
- my $nl = "";
- my $remainder = "";
-
- use re 'taint';
-
- pos($t) = 0;
- while ($t !~ /\G\s*\Z/gc) {
- if ($t =~ /\G([^\n]{0,$ll})($break|\z)/xmgc) {
- $r .= $unexpand
- ? unexpand($nl . $lead . $1)
- : $nl . $lead . $1;
- $remainder = $2;
- } elsif ($huge eq 'wrap' && $t =~ /\G([^\n]{$ll})/gc) {
- $r .= $unexpand
- ? unexpand($nl . $lead . $1)
- : $nl . $lead . $1;
- $remainder = $separator;
- } elsif ($huge eq 'overflow' && $t =~ /\G([^\n]*?)($break|\z)/xmgc) {
- $r .= $unexpand
- ? unexpand($nl . $lead . $1)
- : $nl . $lead . $1;
- $remainder = $2;
- } elsif ($huge eq 'die') {
- die "couldn't wrap '$t'";
- } else {
- die "This shouldn't happen";
- }
-
- $lead = $xp;
- $ll = $nll;
- $nl = $separator;
- }
- $r .= $remainder;
-
- print "-----------$r---------\n" if $debug;
-
- print "Finish up with '$lead'\n" if $debug;
-
- $r .= $lead . substr($t, pos($t), length($t)-pos($t))
- if pos($t) ne length($t);
-
- print "-----------$r---------\n" if $debug;;
-
- return $r;
-}
-
-sub fill
-{
- my ($ip, $xp, @raw) = @_;
- my @para;
- my $pp;
-
- for $pp (split(/\n\s+/, join("\n",@raw))) {
- $pp =~ s/\s+/ /g;
- my $x = wrap($ip, $xp, $pp);
- push(@para, $x);
- }
-
- # if paragraph_indent is the same as line_indent,
- # separate paragraphs with blank lines
-
- my $ps = ($ip eq $xp) ? "\n\n" : "\n";
- return join ($ps, @para);
-}
-
-1;
-__END__
-
diff --git a/lib/URI.pm b/lib/URI.pm
deleted file mode 100644
index 5114ae4..0000000
--- a/lib/URI.pm
+++ /dev/null
@@ -1,1019 +0,0 @@
-package URI;
-
-use strict;
-use vars qw($VERSION);
-$VERSION = "1.35"; # $Date: 2004/11/05 14:17:33 $
-
-use vars qw($ABS_REMOTE_LEADING_DOTS $ABS_ALLOW_RELATIVE_SCHEME);
-
-my %implements; # mapping from scheme to implementor class
-
-# Some "official" character classes
-
-use vars qw($reserved $mark $unreserved $uric $scheme_re);
-$reserved = q(;/?:@&=+$,[]);
-$mark = q(-_.!~*'()); #'; emacs
-$unreserved = "A-Za-z0-9\Q$mark\E";
-$uric = quotemeta($reserved) . $unreserved . "%";
-
-$scheme_re = '[a-zA-Z][a-zA-Z0-9.+\-]*';
-
-use Carp ();
-use URI::Escape ();
-
-use overload ('""' => sub { ${$_[0]} },
- '==' => sub { overload::StrVal($_[0]) eq
- overload::StrVal($_[1])
- },
- fallback => 1,
- );
-
-sub new
-{
- my($class, $uri, $scheme) = @_;
-
- $uri = defined ($uri) ? "$uri" : ""; # stringify
- # Get rid of potential wrapping
- $uri =~ s/^<(?:URL:)?(.*)>$/$1/; #
- $uri =~ s/^"(.*)"$/$1/;
- $uri =~ s/^\s+//;
- $uri =~ s/\s+$//;
-
- my $impclass;
- if ($uri =~ m/^($scheme_re):/so) {
- $scheme = $1;
- }
- else {
- if (($impclass = ref($scheme))) {
- $scheme = $scheme->scheme;
- }
- elsif ($scheme && $scheme =~ m/^($scheme_re)(?::|$)/o) {
- $scheme = $1;
- }
- }
- $impclass ||= implementor($scheme) ||
- do {
- require URI::_foreign;
- $impclass = 'URI::_foreign';
- };
-
- return $impclass->_init($uri, $scheme);
-}
-
-
-sub new_abs
-{
- my($class, $uri, $base) = @_;
- $uri = $class->new($uri, $base);
- $uri->abs($base);
-}
-
-
-sub _init
-{
- my $class = shift;
- my($str, $scheme) = @_;
- $str =~ s/([^$uric\#])/$URI::Escape::escapes{$1}/go;
- $str = "$scheme:$str" unless $str =~ /^$scheme_re:/o ||
- $class->_no_scheme_ok;
- my $self = bless \$str, $class;
- $self;
-}
-
-
-sub implementor
-{
- my($scheme, $impclass) = @_;
- if (!$scheme || $scheme !~ /\A$scheme_re\z/o) {
- require URI::_generic;
- return "URI::_generic";
- }
-
- $scheme = lc($scheme);
-
- if ($impclass) {
- # Set the implementor class for a given scheme
- my $old = $implements{$scheme};
- $impclass->_init_implementor($scheme);
- $implements{$scheme} = $impclass;
- return $old;
- }
-
- my $ic = $implements{$scheme};
- return $ic if $ic;
-
- # scheme not yet known, look for internal or
- # preloaded (with 'use') implementation
- $ic = "URI::$scheme"; # default location
-
- # turn scheme into a valid perl identifier by a simple tranformation...
- $ic =~ s/\+/_P/g;
- $ic =~ s/\./_O/g;
- $ic =~ s/\-/_/g;
-
- no strict 'refs';
- # check we actually have one for the scheme:
- unless (@{"${ic}::ISA"}) {
- # Try to load it
- eval "require $ic";
- die $@ if $@ && $@ !~ /Can\'t locate.*in \@INC/;
- return unless @{"${ic}::ISA"};
- }
-
- $ic->_init_implementor($scheme);
- $implements{$scheme} = $ic;
- $ic;
-}
-
-
-sub _init_implementor
-{
- my($class, $scheme) = @_;
- # Remember that one implementor class may actually
- # serve to implement several URI schemes.
-}
-
-
-sub clone
-{
- my $self = shift;
- my $other = $$self;
- bless \$other, ref $self;
-}
-
-
-sub _no_scheme_ok { 0 }
-
-sub _scheme
-{
- my $self = shift;
-
- unless (@_) {
- return unless $$self =~ /^($scheme_re):/o;
- return $1;
- }
-
- my $old;
- my $new = shift;
- if (defined($new) && length($new)) {
- Carp::croak("Bad scheme '$new'") unless $new =~ /^$scheme_re$/o;
- $old = $1 if $$self =~ s/^($scheme_re)://o;
- my $newself = URI->new("$new:$$self");
- $$self = $$newself;
- bless $self, ref($newself);
- }
- else {
- if ($self->_no_scheme_ok) {
- $old = $1 if $$self =~ s/^($scheme_re)://o;
- Carp::carp("Oops, opaque part now look like scheme")
- if $^W && $$self =~ m/^$scheme_re:/o
- }
- else {
- $old = $1 if $$self =~ m/^($scheme_re):/o;
- }
- }
-
- return $old;
-}
-
-sub scheme
-{
- my $scheme = shift->_scheme(@_);
- return unless defined $scheme;
- lc($scheme);
-}
-
-
-sub opaque
-{
- my $self = shift;
-
- unless (@_) {
- $$self =~ /^(?:$scheme_re:)?([^\#]*)/o or die;
- return $1;
- }
-
- $$self =~ /^($scheme_re:)? # optional scheme
- ([^\#]*) # opaque
- (\#.*)? # optional fragment
- $/sx or die;
-
- my $old_scheme = $1;
- my $old_opaque = $2;
- my $old_frag = $3;
-
- my $new_opaque = shift;
- $new_opaque = "" unless defined $new_opaque;
- $new_opaque =~ s/([^$uric])/$URI::Escape::escapes{$1}/go;
-
- $$self = defined($old_scheme) ? $old_scheme : "";
- $$self .= $new_opaque;
- $$self .= $old_frag if defined $old_frag;
-
- $old_opaque;
-}
-
-*path = \&opaque; # alias
-
-
-sub fragment
-{
- my $self = shift;
- unless (@_) {
- return unless $$self =~ /\#(.*)/s;
- return $1;
- }
-
- my $old;
- $old = $1 if $$self =~ s/\#(.*)//s;
-
- my $new_frag = shift;
- if (defined $new_frag) {
- $new_frag =~ s/([^$uric])/$URI::Escape::escapes{$1}/go;
- $$self .= "#$new_frag";
- }
- $old;
-}
-
-
-sub as_string
-{
- my $self = shift;
- $$self;
-}
-
-
-sub canonical
-{
- # Make sure scheme is lowercased, that we don't escape unreserved chars,
- # and that we use upcase escape sequences.
-
- my $self = shift;
- my $scheme = $self->_scheme || "";
- my $uc_scheme = $scheme =~ /[A-Z]/;
- my $esc = $$self =~ /%[a-fA-F0-9]{2}/;
- return $self unless $uc_scheme || $esc;
-
- my $other = $self->clone;
- if ($uc_scheme) {
- $other->_scheme(lc $scheme);
- }
- if ($esc) {
- $$other =~ s{%([0-9a-fA-F]{2})}
- { my $a = chr(hex($1));
- $a =~ /^[$unreserved]\z/o ? $a : "%\U$1"
- }ge;
- }
- return $other;
-}
-
-# Compare two URIs, subclasses will provide a more correct implementation
-sub eq {
- my($self, $other) = @_;
- $self = URI->new($self, $other) unless ref $self;
- $other = URI->new($other, $self) unless ref $other;
- ref($self) eq ref($other) && # same class
- $self->canonical->as_string eq $other->canonical->as_string;
-}
-
-# generic-URI transformation methods
-sub abs { $_[0]; }
-sub rel { $_[0]; }
-
-# help out Storable
-sub STORABLE_freeze {
- my($self, $cloning) = @_;
- return $$self;
-}
-
-sub STORABLE_thaw {
- my($self, $cloning, $str) = @_;
- $$self = $str;
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-URI - Uniform Resource Identifiers (absolute and relative)
-
-=head1 SYNOPSIS
-
- $u1 = URI->new("http://www.perl.com");
- $u2 = URI->new("foo", "http");
- $u3 = $u2->abs($u1);
- $u4 = $u3->clone;
- $u5 = URI->new("HTTP://WWW.perl.com:80")->canonical;
-
- $str = $u->as_string;
- $str = "$u";
-
- $scheme = $u->scheme;
- $opaque = $u->opaque;
- $path = $u->path;
- $frag = $u->fragment;
-
- $u->scheme("ftp");
- $u->host("ftp.perl.com");
- $u->path("cpan/");
-
-=head1 DESCRIPTION
-
-This module implements the C<URI> class. Objects of this class
-represent "Uniform Resource Identifier references" as specified in RFC
-2396 (and updated by RFC 2732).
-
-A Uniform Resource Identifier is a compact string of characters that
-identifies an abstract or physical resource. A Uniform Resource
-Identifier can be further classified as either a Uniform Resource Locator
-(URL) or a Uniform Resource Name (URN). The distinction between URL
-and URN does not matter to the C<URI> class interface. A
-"URI-reference" is a URI that may have additional information attached
-in the form of a fragment identifier.
-
-An absolute URI reference consists of three parts: a I<scheme>, a
-I<scheme-specific part> and a I<fragment> identifier. A subset of URI
-references share a common syntax for hierarchical namespaces. For
-these, the scheme-specific part is further broken down into
-I<authority>, I<path> and I<query> components. These URIs can also
-take the form of relative URI references, where the scheme (and
-usually also the authority) component is missing, but implied by the
-context of the URI reference. The three forms of URI reference
-syntax are summarized as follows:
-
- <scheme>:<scheme-specific-part>#<fragment>
- <scheme>://<authority><path>?<query>#<fragment>
- <path>?<query>#<fragment>
-
-The components into which a URI reference can be divided depend on the
-I<scheme>. The C<URI> class provides methods to get and set the
-individual components. The methods available for a specific
-C<URI> object depend on the scheme.
-
-=head1 CONSTRUCTORS
-
-The following methods construct new C<URI> objects:
-
-=over 4
-
-=item $uri = URI->new( $str )
-
-=item $uri = URI->new( $str, $scheme )
-
-Constructs a new URI object. The string
-representation of a URI is given as argument, together with an optional
-scheme specification. Common URI wrappers like "" and <>, as well as
-leading and trailing white space, are automatically removed from
-the $str argument before it is processed further.
-
-The constructor determines the scheme, maps this to an appropriate
-URI subclass, constructs a new object of that class and returns it.
-
-The $scheme argument is only used when $str is a
-relative URI. It can be either a simple string that
-denotes the scheme, a string containing an absolute URI reference, or
-an absolute C<URI> object. If no $scheme is specified for a relative
-URI $str, then $str is simply treated as a generic URI (no scheme-specific
-methods available).
-
-The set of characters available for building URI references is
-restricted (see L<URI::Escape>). Characters outside this set are
-automatically escaped by the URI constructor.
-
-=item $uri = URI->new_abs( $str, $base_uri )
-
-Constructs a new absolute URI object. The $str argument can
-denote a relative or absolute URI. If relative, then it is
-absolutized using $base_uri as base. The $base_uri must be an absolute
-URI.
-
-=item $uri = URI::file->new( $filename )
-
-=item $uri = URI::file->new( $filename, $os )
-
-Constructs a new I<file> URI from a file name. See L<URI::file>.
-
-=item $uri = URI::file->new_abs( $filename )
-
-=item $uri = URI::file->new_abs( $filename, $os )
-
-Constructs a new absolute I<file> URI from a file name. See
-L<URI::file>.
-
-=item $uri = URI::file->cwd
-
-Returns the current working directory as a I<file> URI. See
-L<URI::file>.
-
-=item $uri->clone
-
-Returns a copy of the $uri.
-
-=back
-
-=head1 COMMON METHODS
-
-The methods described in this section are available for all C<URI>
-objects.
-
-Methods that give access to components of a URI always return the
-old value of the component. The value returned is C<undef> if the
-component was not present. There is generally a difference between a
-component that is empty (represented as C<"">) and a component that is
-missing (represented as C<undef>). If an accessor method is given an
-argument, it updates the corresponding component in addition to
-returning the old value of the component. Passing an undefined
-argument removes the component (if possible). The description of
-each accessor method indicates whether the component is passed as
-an escaped or an unescaped string. A component that can be further
-divided into sub-parts are usually passed escaped, as unescaping might
-change its semantics.
-
-The common methods available for all URI are:
-
-=over 4
-
-=item $uri->scheme
-
-=item $uri->scheme( $new_scheme )
-
-Sets and returns the scheme part of the $uri. If the $uri is
-relative, then $uri->scheme returns C<undef>. If called with an
-argument, it updates the scheme of $uri, possibly changing the
-class of $uri, and returns the old scheme value. The method croaks
-if the new scheme name is illegal; a scheme name must begin with a
-letter and must consist of only US-ASCII letters, numbers, and a few
-special marks: ".", "+", "-". This restriction effectively means
-that the scheme must be passed unescaped. Passing an undefined
-argument to the scheme method makes the URI relative (if possible).
-
-Letter case does not matter for scheme names. The string
-returned by $uri->scheme is always lowercase. If you want the scheme
-just as it was written in the URI in its original case,
-you can use the $uri->_scheme method instead.
-
-=item $uri->opaque
-
-=item $uri->opaque( $new_opaque )
-
-Sets and returns the scheme-specific part of the $uri
-(everything between the scheme and the fragment)
-as an escaped string.
-
-=item $uri->path
-
-=item $uri->path( $new_path )
-
-Sets and returns the same value as $uri->opaque unless the URI
-supports the generic syntax for hierarchical namespaces.
-In that case the generic method is overridden to set and return
-the part of the URI between the I<host name> and the I<fragment>.
-
-=item $uri->fragment
-
-=item $uri->fragment( $new_frag )
-
-Returns the fragment identifier of a URI reference
-as an escaped string.
-
-=item $uri->as_string
-
-Returns a URI object to a plain string. URI objects are
-also converted to plain strings automatically by overloading. This
-means that $uri objects can be used as plain strings in most Perl
-constructs.
-
-=item $uri->canonical
-
-Returns a normalized version of the URI. The rules
-for normalization are scheme-dependent. They usually involve
-lowercasing the scheme and Internet host name components,
-removing the explicit port specification if it matches the default port,
-uppercasing all escape sequences, and unescaping octets that can be
-better represented as plain characters.
-
-For efficiency reasons, if the $uri is already in normalized form,
-then a reference to it is returned instead of a copy.
-
-=item $uri->eq( $other_uri )
-
-=item URI::eq( $first_uri, $other_uri )
-
-Tests whether two URI references are equal. URI references
-that normalize to the same string are considered equal. The method
-can also be used as a plain function which can also test two string
-arguments.
-
-If you need to test whether two C<URI> object references denote the
-same object, use the '==' operator.
-
-=item $uri->abs( $base_uri )
-
-Returns an absolute URI reference. If $uri is already
-absolute, then a reference to it is simply returned. If the $uri
-is relative, then a new absolute URI is constructed by combining the
-$uri and the $base_uri, and returned.
-
-=item $uri->rel( $base_uri )
-
-Returns a relative URI reference if it is possible to
-make one that denotes the same resource relative to $base_uri.
-If not, then $uri is simply returned.
-
-=back
-
-=head1 GENERIC METHODS
-
-The following methods are available to schemes that use the
-common/generic syntax for hierarchical namespaces. The descriptions of
-schemes below indicate which these are. Unknown schemes are
-assumed to support the generic syntax, and therefore the following
-methods:
-
-=over 4
-
-=item $uri->authority
-
-=item $uri->authority( $new_authority )
-
-Sets and returns the escaped authority component
-of the $uri.
-
-=item $uri->path
-
-=item $uri->path( $new_path )
-
-Sets and returns the escaped path component of
-the $uri (the part between the host name and the query or fragment).
-The path can never be undefined, but it can be the empty string.
-
-=item $uri->path_query
-
-=item $uri->path_query( $new_path_query )
-
-Sets and returns the escaped path and query
-components as a single entity. The path and the query are
-separated by a "?" character, but the query can itself contain "?".
-
-=item $uri->path_segments
-
-=item $uri->path_segments( $segment, ... )
-
-Sets and returns the path. In a scalar context, it returns
-the same value as $uri->path. In a list context, it returns the
-unescaped path segments that make up the path. Path segments that
-have parameters are returned as an anonymous array. The first element
-is the unescaped path segment proper; subsequent elements are escaped
-parameter strings. Such an anonymous array uses overloading so it can
-be treated as a string too, but this string does not include the
-parameters.
-
-Note that absolute paths have the empty string as their first
-I<path_segment>, i.e. the I<path> C</foo/bar> have 3
-I<path_segments>; "", "foo" and "bar".
-
-=item $uri->query
-
-=item $uri->query( $new_query )
-
-Sets and returns the escaped query component of
-the $uri.
-
-=item $uri->query_form
-
-=item $uri->query_form( $key1 => $val1, $key2 => $val2, ... )
-
-=item $uri->query_form( \@key_value_pairs )
-
-=item $uri->query_form( \%hash )
-
-Sets and returns query components that use the
-I<application/x-www-form-urlencoded> format. Key/value pairs are
-separated by "&", and the key is separated from the value by a "="
-character.
-
-The form can be set either by passing separate key/value pairs, or via
-an array or hash reference. Passing an empty array or an empty hash
-removes the query component, whereas passing no arguments at all leaves
-the component unchanged. The order of keys is undefined if a hash
-reference is passed. The old value is always returned as a list of
-separate key/value pairs. Assigning this list to a hash is unwise as
-the keys returned might repeat.
-
-The values passed when setting the form can be plain strings or
-references to arrays of strings. Passing an array of values has the
-same effect as passing the key repeatedly with one value at a time.
-All the following statements have the same effect:
-
- $uri->query_form(foo => 1, foo => 2);
- $uri->query_form(foo => [1, 2]);
- $uri->query_form([ foo => 1, foo => 2 ]);
- $uri->query_form([ foo => [1, 2] ]);
- $uri->query_form({ foo => [1, 2] });
-
-The C<URI::QueryParam> module can be loaded to add further methods to
-manipulate the form of a URI. See L<URI::QueryParam> for details.
-
-=item $uri->query_keywords
-
-=item $uri->query_keywords( $keywords, ... )
-
-=item $uri->query_keywords( \@keywords )
-
-Sets and returns query components that use the
-keywords separated by "+" format.
-
-The keywords can be set either by passing separate keywords directly
-or by passing a reference to an array of keywords. Passing an empty
-array removes the query component, whereas passing no arguments at
-all leaves the component unchanged. The old value is always returned
-as a list of separate words.
-
-=back
-
-=head1 SERVER METHODS
-
-For schemes where the I<authority> component denotes an Internet host,
-the following methods are available in addition to the generic
-methods.
-
-=over 4
-
-=item $uri->userinfo
-
-=item $uri->userinfo( $new_userinfo )
-
-Sets and returns the escaped userinfo part of the
-authority component.
-
-For some schemes this is a user name and a password separated by
-a colon. This practice is not recommended. Embedding passwords in
-clear text (such as URI) has proven to be a security risk in almost
-every case where it has been used.
-
-=item $uri->host
-
-=item $uri->host( $new_host )
-
-Sets and returns the unescaped hostname.
-
-If the $new_host string ends with a colon and a number, then this
-number also sets the port.
-
-=item $uri->port
-
-=item $uri->port( $new_port )
-
-Sets and returns the port. The port is a simple integer
-that should be greater than 0.
-
-If a port is not specified explicitly in the URI, then the URI scheme's default port
-is returned. If you don't want the default port
-substituted, then you can use the $uri->_port method instead.
-
-=item $uri->host_port
-
-=item $uri->host_port( $new_host_port )
-
-Sets and returns the host and port as a single
-unit. The returned value includes a port, even if it matches the
-default port. The host part and the port part are separated by a
-colon: ":".
-
-=item $uri->default_port
-
-Returns the default port of the URI scheme to which $uri
-belongs. For I<http> this is the number 80, for I<ftp> this
-is the number 21, etc. The default port for a scheme can not be
-changed.
-
-=back
-
-=head1 SCHEME-SPECIFIC SUPPORT
-
-Scheme-specific support is provided for the following URI schemes. For C<URI>
-objects that do not belong to one of these, you can only use the common and
-generic methods.
-
-=over 4
-
-=item B<data>:
-
-The I<data> URI scheme is specified in RFC 2397. It allows inclusion
-of small data items as "immediate" data, as if it had been included
-externally.
-
-C<URI> objects belonging to the data scheme support the common methods
-and two new methods to access their scheme-specific components:
-$uri->media_type and $uri->data. See L<URI::data> for details.
-
-=item B<file>:
-
-An old specification of the I<file> URI scheme is found in RFC 1738.
-A new RFC 2396 based specification in not available yet, but file URI
-references are in common use.
-
-C<URI> objects belonging to the file scheme support the common and
-generic methods. In addition, they provide two methods for mapping file URIs
-back to local file names; $uri->file and $uri->dir. See L<URI::file>
-for details.
-
-=item B<ftp>:
-
-An old specification of the I<ftp> URI scheme is found in RFC 1738. A
-new RFC 2396 based specification in not available yet, but ftp URI
-references are in common use.
-
-C<URI> objects belonging to the ftp scheme support the common,
-generic and server methods. In addition, they provide two methods for
-accessing the userinfo sub-components: $uri->user and $uri->password.
-
-=item B<gopher>:
-
-The I<gopher> URI scheme is specified in
-<draft-murali-url-gopher-1996-12-04> and will hopefully be available
-as a RFC 2396 based specification.
-
-C<URI> objects belonging to the gopher scheme support the common,
-generic and server methods. In addition, they support some methods for
-accessing gopher-specific path components: $uri->gopher_type,
-$uri->selector, $uri->search, $uri->string.
-
-=item B<http>:
-
-The I<http> URI scheme is specified in RFC 2616.
-The scheme is used to reference resources hosted by HTTP servers.
-
-C<URI> objects belonging to the http scheme support the common,
-generic and server methods.
-
-=item B<https>:
-
-The I<https> URI scheme is a Netscape invention which is commonly
-implemented. The scheme is used to reference HTTP servers through SSL
-connections. Its syntax is the same as http, but the default
-port is different.
-
-=item B<ldap>:
-
-The I<ldap> URI scheme is specified in RFC 2255. LDAP is the
-Lightweight Directory Access Protocol. An ldap URI describes an LDAP
-search operation to perform to retrieve information from an LDAP
-directory.
-
-C<URI> objects belonging to the ldap scheme support the common,
-generic and server methods as well as ldap-specific methods: $uri->dn,
-$uri->attributes, $uri->scope, $uri->filter, $uri->extensions. See
-L<URI::ldap> for details.
-
-=item B<ldapi>:
-
-Like the I<ldap> URI scheme, but uses a UNIX domain socket. The
-server methods are not supported, and the local socket path is
-available as $uri->un_path. The I<ldapi> scheme is used by the
-OpenLDAP package. There is no real specification for it, but it is
-mentioned in various OpenLDAP manual pages.
-
-=item B<ldaps>:
-
-Like the I<ldap> URI scheme, but uses an SSL connection. This
-scheme is deprecated, as the preferred way is to use the I<start_tls>
-mechanism.
-
-=item B<mailto>:
-
-The I<mailto> URI scheme is specified in RFC 2368. The scheme was
-originally used to designate the Internet mailing address of an
-individual or service. It has (in RFC 2368) been extended to allow
-setting of other mail header fields and the message body.
-
-C<URI> objects belonging to the mailto scheme support the common
-methods and the generic query methods. In addition, they support the
-following mailto-specific methods: $uri->to, $uri->headers.
-
-=item B<mms>:
-
-The I<mms> URL specification can be found at L<http://sdp.ppona.com/>
-C<URI> objects belonging to the mms scheme support the common,
-generic, and server methods, with the exception of userinfo and
-query-related sub-components.
-
-=item B<news>:
-
-The I<news>, I<nntp> and I<snews> URI schemes are specified in
-<draft-gilman-news-url-01> and will hopefully be available as an RFC
-2396 based specification soon.
-
-C<URI> objects belonging to the news scheme support the common,
-generic and server methods. In addition, they provide some methods to
-access the path: $uri->group and $uri->message.
-
-=item B<nntp>:
-
-See I<news> scheme.
-
-=item B<pop>:
-
-The I<pop> URI scheme is specified in RFC 2384. The scheme is used to
-reference a POP3 mailbox.
-
-C<URI> objects belonging to the pop scheme support the common, generic
-and server methods. In addition, they provide two methods to access the
-userinfo components: $uri->user and $uri->auth
-
-=item B<rlogin>:
-
-An old specification of the I<rlogin> URI scheme is found in RFC
-1738. C<URI> objects belonging to the rlogin scheme support the
-common, generic and server methods.
-
-=item B<rtsp>:
-
-The I<rtsp> URL specification can be found in section 3.2 of RFC 2326.
-C<URI> objects belonging to the rtsp scheme support the common,
-generic, and server methods, with the exception of userinfo and
-query-related sub-components.
-
-=item B<rtspu>:
-
-The I<rtspu> URI scheme is used to talk to RTSP servers over UDP
-instead of TCP. The syntax is the same as rtsp.
-
-=item B<rsync>:
-
-Information about rsync is available from http://rsync.samba.org.
-C<URI> objects belonging to the rsync scheme support the common,
-generic and server methods. In addition, they provide methods to
-access the userinfo sub-components: $uri->user and $uri->password.
-
-=item B<sip>:
-
-The I<sip> URI specification is described in sections 19.1 and 25
-of RFC 3261. C<URI> objects belonging to the sip scheme support the
-common, generic, and server methods with the exception of path related
-sub-components. In addition, they provide two methods to get and set
-I<sip> parameters: $uri->params_form and $uri->params.
-
-=item B<sips>:
-
-See I<sip> scheme. Its syntax is the same as sip, but the default
-port is different.
-
-=item B<snews>:
-
-See I<news> scheme. Its syntax is the same as news, but the default
-port is different.
-
-=item B<telnet>:
-
-An old specification of the I<telnet> URI scheme is found in RFC
-1738. C<URI> objects belonging to the telnet scheme support the
-common, generic and server methods.
-
-=item B<tn3270>:
-
-These URIs are used like I<telnet> URIs but for connections to IBM
-mainframes. C<URI> objects belonging to the tn3270 scheme support the
-common, generic and server methods.
-
-=item B<ssh>:
-
-Information about ssh is available at http://www.openssh.com/.
-C<URI> objects belonging to the ssh scheme support the common,
-generic and server methods. In addition, they provide methods to
-access the userinfo sub-components: $uri->user and $uri->password.
-
-=item B<urn>:
-
-The syntax of Uniform Resource Names is specified in RFC 2141. C<URI>
-objects belonging to the urn scheme provide the common methods, and also the
-methods $uri->nid and $uri->nss, which return the Namespace Identifier
-and the Namespace-Specific String respectively.
-
-The Namespace Identifier basically works like the Scheme identifier of
-URIs, and further divides the URN namespace. Namespace Identifier
-assignments are maintained at
-<http://www.iana.org/assignments/urn-namespaces>.
-
-Letter case is not significant for the Namespace Identifier. It is
-always returned in lower case by the $uri->nid method. The $uri->_nid
-method can be used if you want it in its original case.
-
-=item B<urn>:B<isbn>:
-
-The C<urn:isbn:> namespace contains International Standard Book
-Numbers (ISBNs) and is described in RFC 3187. A C<URI> object belonging
-to this namespace has the following extra methods (if the
-Business::ISBN module is available): $uri->isbn,
-$uri->isbn_publisher_code, $uri->isbn_country_code, $uri->isbn_as_ean.
-
-=item B<urn>:B<oid>:
-
-The C<urn:oid:> namespace contains Object Identifiers (OIDs) and is
-described in RFC 3061. An object identifier consists of sequences of digits
-separated by dots. A C<URI> object belonging to this namespace has an
-additional method called $uri->oid that can be used to get/set the oid
-value. In a list context, oid numbers are returned as separate elements.
-
-=back
-
-=head1 CONFIGURATION VARIABLES
-
-The following configuration variables influence how the class and its
-methods behave:
-
-=over 4
-
-=item $URI::ABS_ALLOW_RELATIVE_SCHEME
-
-Some older parsers used to allow the scheme name to be present in the
-relative URL if it was the same as the base URL scheme. RFC 2396 says
-that this should be avoided, but you can enable this old behaviour by
-setting the $URI::ABS_ALLOW_RELATIVE_SCHEME variable to a TRUE value.
-The difference is demonstrated by the following examples:
-
- URI->new("http:foo")->abs("http://host/a/b")
- ==> "http:foo"
-
- local $URI::ABS_ALLOW_RELATIVE_SCHEME = 1;
- URI->new("http:foo")->abs("http://host/a/b")
- ==> "http:/host/a/foo"
-
-
-=item $URI::ABS_REMOTE_LEADING_DOTS
-
-You can also have the abs() method ignore excess ".."
-segments in the relative URI by setting $URI::ABS_REMOTE_LEADING_DOTS
-to a TRUE value. The difference is demonstrated by the following
-examples:
-
- URI->new("../../../foo")->abs("http://host/a/b")
- ==> "http://host/../../foo"
-
- local $URI::ABS_REMOTE_LEADING_DOTS = 1;
- URI->new("../../../foo")->abs("http://host/a/b")
- ==> "http://host/foo"
-
-=back
-
-=head1 BUGS
-
-Using regexp variables like $1 directly as arguments to the URI methods
-does not work too well with current perl implementations. I would argue
-that this is actually a bug in perl. The workaround is to quote
-them. Example:
-
- /(...)/ || die;
- $u->query("$1");
-
-=head1 PARSING URIs WITH REGEXP
-
-As an alternative to this module, the following (official) regular
-expression can be used to decode a URI:
-
- my($scheme, $authority, $path, $query, $fragment) =
- $uri =~ m|(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?|;
-
-The C<URI::Split> module provides the function uri_split() as a
-readable alternative.
-
-=head1 SEE ALSO
-
-L<URI::file>, L<URI::WithBase>, L<URI::QueryParam>, L<URI::Escape>,
-L<URI::Split>, L<URI::Heuristic>
-
-RFC 2396: "Uniform Resource Identifiers (URI): Generic Syntax",
-Berners-Lee, Fielding, Masinter, August 1998.
-
-http://www.iana.org/assignments/uri-schemes
-
-http://www.iana.org/assignments/urn-namespaces
-
-http://www.w3.org/Addressing/
-
-=head1 COPYRIGHT
-
-Copyright 1995-2003 Gisle Aas.
-
-Copyright 1995 Martijn Koster.
-
-This program is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=head1 AUTHORS / ACKNOWLEDGMENTS
-
-This module is based on the C<URI::URL> module, which in turn was
-(distantly) based on the C<wwwurl.pl> code in the libwww-perl for
-perl4 developed by Roy Fielding, as part of the Arcadia project at the
-University of California, Irvine, with contributions from Brooks
-Cutter.
-
-C<URI::URL> was developed by Gisle Aas, Tim Bunce, Roy Fielding and
-Martijn Koster with input from other people on the libwww-perl mailing
-list.
-
-C<URI> and related subclasses was developed by Gisle Aas.
-
-=cut
diff --git a/lib/URI/Escape.pm b/lib/URI/Escape.pm
deleted file mode 100644
index 5f0de55..0000000
--- a/lib/URI/Escape.pm
+++ /dev/null
@@ -1,218 +0,0 @@
-#
-# $Id: Escape.pm,v 3.28 2004/11/05 13:58:31 gisle Exp $
-#
-
-package URI::Escape;
-use strict;
-
-=head1 NAME
-
-URI::Escape - Escape and unescape unsafe characters
-
-=head1 SYNOPSIS
-
- use URI::Escape;
- $safe = uri_escape("10% is enough\n");
- $verysafe = uri_escape("foo", "\0-\377");
- $str = uri_unescape($safe);
-
-=head1 DESCRIPTION
-
-This module provides functions to escape and unescape URI strings as
-defined by RFC 2396 (and updated by RFC 2732).
-A URI consists of a restricted set of characters,
-denoted as C<uric> in RFC 2396. The restricted set of characters
-consists of digits, letters, and a few graphic symbols chosen from
-those common to most of the character encodings and input facilities
-available to Internet users:
-
- "A" .. "Z", "a" .. "z", "0" .. "9",
- ";", "/", "?", ":", "@", "&", "=", "+", "$", ",", "[", "]", # reserved
- "-", "_", ".", "!", "~", "*", "'", "(", ")"
-
-In addition, any byte (octet) can be represented in a URI by an escape
-sequence: a triplet consisting of the character "%" followed by two
-hexadecimal digits. A byte can also be represented directly by a
-character, using the US-ASCII character for that octet (iff the
-character is part of C<uric>).
-
-Some of the C<uric> characters are I<reserved> for use as delimiters
-or as part of certain URI components. These must be escaped if they are
-to be treated as ordinary data. Read RFC 2396 for further details.
-
-The functions provided (and exported by default) from this module are:
-
-=over 4
-
-=item uri_escape( $string )
-
-=item uri_escape( $string, $unsafe )
-
-Replaces each unsafe character in the $string with the corresponding
-escape sequence and returns the result. The $string argument should
-be a string of bytes. The uri_escape() function will croak if given a
-characters with code above 255. Use uri_escape_utf8() if you know you
-have such chars or/and want chars in the 128 .. 255 range treated as
-UTF-8.
-
-The uri_escape() function takes an optional second argument that
-overrides the set of characters that are to be escaped. The set is
-specified as a string that can be used in a regular expression
-character class (between [ ]). E.g.:
-
- "\x00-\x1f\x7f-\xff" # all control and hi-bit characters
- "a-z" # all lower case characters
- "^A-Za-z" # everything not a letter
-
-The default set of characters to be escaped is all those which are
-I<not> part of the C<uric> character class shown above as well as the
-reserved characters. I.e. the default is:
-
- "^A-Za-z0-9\-_.!~*'()"
-
-=item uri_escape_utf8( $string )
-
-=item uri_escape_utf8( $string, $unsafe )
-
-Works like uri_escape(), but will encode chars as UTF-8 before
-escaping them. This makes this function able do deal with characters
-with code above 255 in $string. Note that chars in the 128 .. 255
-range will be escaped differently by this function compared to what
-uri_escape() would. For chars in the 0 .. 127 range there is no
-difference.
-
-The call:
-
- $uri = uri_escape_utf8($string);
-
-will be the same as:
-
- use Encode qw(encode);
- $uri = uri_escape(encode("UTF-8", $string));
-
-but will even work for perl-5.6 for chars in the 128 .. 255 range.
-
-Note: Javascript has a function called escape() that produce the
-sequence "%uXXXX" for chars in the 256 .. 65535 range. This function
-has really nothing to do with URI escaping but some folks got confused
-since it "does the right thing" in the 0 .. 255 range. Because of
-this you sometimes see "URIs" with these kind of escapes. The
-JavaScript encodeURI() function is similar to uri_escape_utf8().
-
-=item uri_unescape($string,...)
-
-Returns a string with each %XX sequence replaced with the actual byte
-(octet).
-
-This does the same as:
-
- $string =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
-
-but does not modify the string in-place as this RE would. Using the
-uri_unescape() function instead of the RE might make the code look
-cleaner and is a few characters less to type.
-
-In a simple benchmark test I did,
-calling the function (instead of the inline RE above) if a few chars
-were unescaped was something like 40% slower, and something like 700% slower if none were. If
-you are going to unescape a lot of times it might be a good idea to
-inline the RE.
-
-If the uri_unescape() function is passed multiple strings, then each
-one is returned unescaped.
-
-=back
-
-The module can also export the C<%escapes> hash, which contains the
-mapping from all 256 bytes to the corresponding escape codes. Lookup
-in this hash is faster than evaluating C<sprintf("%%%02X", ord($byte))>
-each time.
-
-=head1 SEE ALSO
-
-L<URI>
-
-
-=head1 COPYRIGHT
-
-Copyright 1995-2004 Gisle Aas.
-
-This program is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
-
-use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION);
-use vars qw(%escapes);
-
-require Exporter;
-@ISA = qw(Exporter);
-@EXPORT = qw(uri_escape uri_unescape);
-@EXPORT_OK = qw(%escapes uri_escape_utf8);
-$VERSION = sprintf("%d.%02d", q$Revision: 3.28 $ =~ /(\d+)\.(\d+)/);
-
-use Carp ();
-
-# Build a char->hex map
-for (0..255) {
- $escapes{chr($_)} = sprintf("%%%02X", $_);
-}
-
-my %subst; # compiled patternes
-
-sub uri_escape
-{
- my($text, $patn) = @_;
- return undef unless defined $text;
- if (defined $patn){
- unless (exists $subst{$patn}) {
- # Because we can't compile the regex we fake it with a cached sub
- (my $tmp = $patn) =~ s,/,\\/,g;
- eval "\$subst{\$patn} = sub {\$_[0] =~ s/([$tmp])/\$escapes{\$1} || _fail_hi(\$1)/ge; }";
- Carp::croak("uri_escape: $@") if $@;
- }
- &{$subst{$patn}}($text);
- } else {
- # Default unsafe characters. RFC 2732 ^(uric - reserved)
- $text =~ s/([^A-Za-z0-9\-_.!~*'()])/$escapes{$1} || _fail_hi($1)/ge;
- }
- $text;
-}
-
-sub _fail_hi {
- my $chr = shift;
- Carp::croak(sprintf "Can't escape \\x{%04X}, try uri_escape_utf8() instead", ord($chr));
-}
-
-sub uri_escape_utf8
-{
- my $text = shift;
- if ($] < 5.008) {
- $text =~ s/([^\0-\x7F])/do {my $o = ord($1); sprintf("%c%c", 0xc0 | ($o >> 6), 0x80 | ($o & 0x3f)) }/ge;
- }
- else {
- utf8::encode($text);
- }
-
- return uri_escape($text, @_);
-}
-
-sub uri_unescape
-{
- # Note from RFC1630: "Sequences which start with a percent sign
- # but are not followed by two hexadecimal characters are reserved
- # for future extension"
- my $str = shift;
- if (@_ && wantarray) {
- # not executed for the common case of a single argument
- my @str = ($str, @_); # need to copy
- foreach (@str) {
- s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
- }
- return @str;
- }
- $str =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg if defined $str;
- $str;
-}
-
-1;
diff --git a/lib/URI/Heuristic.pm b/lib/URI/Heuristic.pm
deleted file mode 100644
index e39c6c9..0000000
--- a/lib/URI/Heuristic.pm
+++ /dev/null
@@ -1,224 +0,0 @@
-package URI::Heuristic;
-
-# $Id: Heuristic.pm,v 4.17 2004/01/14 13:33:44 gisle Exp $
-
-=head1 NAME
-
-URI::Heuristic - Expand URI using heuristics
-
-=head1 SYNOPSIS
-
- use URI::Heuristic qw(uf_uristr);
- $u = uf_uristr("perl"); # http://www.perl.com
- $u = uf_uristr("www.sol.no/sol"); # http://www.sol.no/sol
- $u = uf_uristr("aas"); # http://www.aas.no
- $u = uf_uristr("ftp.funet.fi"); # ftp://ftp.funet.fi
- $u = uf_uristr("/etc/passwd"); # file:/etc/passwd
-
-=head1 DESCRIPTION
-
-This module provides functions that expand strings into real absolute
-URIs using some built-in heuristics. Strings that already represent
-absolute URIs (i.e. that start with a C<scheme:> part) are never modified
-and are returned unchanged. The main use of these functions is to
-allow abbreviated URIs similar to what many web browsers allow for URIs
-typed in by the user.
-
-The following functions are provided:
-
-=over 4
-
-=item uf_uristr($str)
-
-Tries to make the argument string
-into a proper absolute URI string. The "uf_" prefix stands for "User
-Friendly". Under MacOS, it assumes that any string with a common URL
-scheme (http, ftp, etc.) is a URL rather than a local path. So don't name
-your volumes after common URL schemes and expect uf_uristr() to construct
-valid file: URL's on those volumes for you, because it won't.
-
-=item uf_uri($str)
-
-Works the same way as uf_uristr() but
-returns a C<URI> object.
-
-=back
-
-=head1 ENVIRONMENT
-
-If the hostname portion of a URI does not contain any dots, then
-certain qualified guesses are made. These guesses are governed by
-the following two environment variables:
-
-=over 10
-
-=item COUNTRY
-
-The two-letter country code (ISO 3166) for your location. If
-the domain name of your host ends with two letters, then it is taken
-to be the default country. See also L<Locale::Country>.
-
-=item URL_GUESS_PATTERN
-
-Contains a space-separated list of URL patterns to try. The string
-"ACME" is for some reason used as a placeholder for the host name in
-the URL provided. Example:
-
- URL_GUESS_PATTERN="www.ACME.no www.ACME.se www.ACME.com"
- export URL_GUESS_PATTERN
-
-Specifying URL_GUESS_PATTERN disables any guessing rules based on
-country. An empty URL_GUESS_PATTERN disables any guessing that
-involves host name lookups.
-
-=back
-
-=head1 COPYRIGHT
-
-Copyright 1997-1998, Gisle Aas
-
-This library is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=cut
-
-use strict;
-
-use vars qw(@EXPORT_OK $VERSION $MY_COUNTRY %LOCAL_GUESSING $DEBUG);
-
-require Exporter;
-*import = \&Exporter::import;
-@EXPORT_OK = qw(uf_uri uf_uristr uf_url uf_urlstr);
-$VERSION = sprintf("%d.%02d", q$Revision: 4.17 $ =~ /(\d+)\.(\d+)/);
-
-sub MY_COUNTRY() {
- for ($MY_COUNTRY) {
- return $_ if defined;
-
- # First try the environment.
- $_ = $ENV{COUNTRY};
- return $_ if defined;
-
- # Could use LANG, LC_ALL, etc at this point, but probably too
- # much of a wild guess. (Catalan != Canada, etc.)
- #
-
- # Last bit of domain name. This may access the network.
- require Net::Domain;
- my $fqdn = Net::Domain::hostfqdn();
- $_ = lc($1) if $fqdn =~ /\.([a-zA-Z]{2})$/;
- return $_ if defined;
-
- # Give up. Defined but false.
- return ($_ = 0);
- }
-}
-
-%LOCAL_GUESSING =
-(
- 'us' => [qw(www.ACME.gov www.ACME.mil)],
- 'uk' => [qw(www.ACME.co.uk www.ACME.org.uk www.ACME.ac.uk)],
- 'au' => [qw(www.ACME.com.au www.ACME.org.au www.ACME.edu.au)],
- 'il' => [qw(www.ACME.co.il www.ACME.org.il www.ACME.net.il)],
- # send corrections and new entries to <gisle@aas.no>
-);
-
-
-sub uf_uristr ($)
-{
- local($_) = @_;
- print STDERR "uf_uristr: resolving $_\n" if $DEBUG;
- return unless defined;
-
- s/^\s+//;
- s/\s+$//;
-
- if (/^(www|web|home)\./) {
- $_ = "http://$_";
-
- } elsif (/^(ftp|gopher|news|wais|http|https)\./) {
- $_ = "$1://$_";
-
- } elsif ($^O ne "MacOS" &&
- (m,^/, || # absolute file name
- m,^\.\.?/, || # relative file name
- m,^[a-zA-Z]:[/\\],) # dosish file name
- )
- {
- $_ = "file:$_";
-
- } elsif ($^O eq "MacOS" && m/:/) {
- # potential MacOS file name
- unless (m/^(ftp|gopher|news|wais|http|https|mailto):/) {
- require URI::file;
- my $a = URI::file->new($_)->as_string;
- $_ = ($a =~ m/^file:/) ? $a : "file:$a";
- }
- } elsif (/^\w+([\.\-]\w+)*\@(\w+\.)+\w{2,3}$/) {
- $_ = "mailto:$_";
-
- } elsif (!/^[a-zA-Z][a-zA-Z0-9.+\-]*:/) { # no scheme specified
- if (s/^([-\w]+(?:\.[-\w]+)*)([\/:\?\#]|$)/$2/) {
- my $host = $1;
-
- if ($host !~ /\./ && $host ne "localhost") {
- my @guess;
- if (exists $ENV{URL_GUESS_PATTERN}) {
- @guess = map { s/\bACME\b/$host/; $_ }
- split(' ', $ENV{URL_GUESS_PATTERN});
- } else {
- if (MY_COUNTRY()) {
- my $special = $LOCAL_GUESSING{MY_COUNTRY()};
- if ($special) {
- my @special = @$special;
- push(@guess, map { s/\bACME\b/$host/; $_ }
- @special);
- } else {
- push(@guess, 'www.$host.' . MY_COUNTRY());
- }
- }
- push(@guess, map "www.$host.$_",
- "com", "org", "net", "edu", "int");
- }
-
-
- my $guess;
- for $guess (@guess) {
- print STDERR "uf_uristr: gethostbyname('$guess.')..."
- if $DEBUG;
- if (gethostbyname("$guess.")) {
- print STDERR "yes\n" if $DEBUG;
- $host = $guess;
- last;
- }
- print STDERR "no\n" if $DEBUG;
- }
- }
- $_ = "http://$host$_";
-
- } else {
- # pure junk, just return it unchanged...
-
- }
- }
- print STDERR "uf_uristr: ==> $_\n" if $DEBUG;
-
- $_;
-}
-
-sub uf_uri ($)
-{
- require URI;
- URI->new(uf_uristr($_[0]));
-}
-
-# legacy
-*uf_urlstr = \*uf_uristr;
-
-sub uf_url ($)
-{
- require URI::URL;
- URI::URL->new(uf_uristr($_[0]));
-}
-
-1;
diff --git a/lib/URI/QueryParam.pm b/lib/URI/QueryParam.pm
deleted file mode 100644
index 225ca6e..0000000
--- a/lib/URI/QueryParam.pm
+++ /dev/null
@@ -1,200 +0,0 @@
-package URI::QueryParam;
-
-use strict;
-
-sub URI::_query::query_param {
- my $self = shift;
- my @old = $self->query_form;
-
- if (@_ == 0) {
- # get keys
- my %seen;
- my @keys;
- for (my $i = 0; $i < @old; $i += 2) {
- push(@keys, $old[$i]) unless $seen{$old[$i]}++;
- }
- return @keys;
- }
-
- my $key = shift;
- my @i;
-
- for (my $i = 0; $i < @old; $i += 2) {
- push(@i, $i) if $old[$i] eq $key;
- }
-
- if (@_) {
- my @new = @old;
- my @new_i = @i;
- my @vals = map { ref($_) eq 'ARRAY' ? @$_ : $_ } @_;
- #print "VALS:@vals [@i]\n";
- while (@new_i > @vals) {
- #print "REMOVE $new_i[-1]\n";
- splice(@new, pop(@new_i), 2);
- }
- while (@vals > @new_i) {
- my $i = @new_i ? $new_i[-1] + 2 : @new;
- #print "SPLICE $i\n";
- splice(@new, $i, 0, $key => pop(@vals));
- }
- for (@vals) {
- #print "SET $new_i[0]\n";
- $new[shift(@new_i)+1] = $_;
- }
-
- $self->query_form(\@new);
- }
-
- return wantarray ? @old[map $_+1, @i] : @i ? $old[$i[0]+1] : undef;
-}
-
-sub URI::_query::query_param_append {
- my $self = shift;
- my $key = shift;
- $self->query_form($self->query_form, $key => \@_); # XXX
- return;
-}
-
-sub URI::_query::query_param_delete {
- my $self = shift;
- my $key = shift;
- my @old = $self->query_form;
- my @vals;
-
- for (my $i = @old - 2; $i >= 0; $i -= 2) {
- next if $old[$i] ne $key;
- push(@vals, (splice(@old, $i, 2))[1]);
- }
- $self->query_form(\@old) if @vals;
- return wantarray ? reverse @vals : $vals[-1];
-}
-
-sub URI::_query::query_form_hash {
- my $self = shift;
- my @old = $self->query_form;
- if (@_) {
- $self->query_form(@_ == 1 ? %{shift(@_)} : @_);
- }
- my %hash;
- while (my($k, $v) = splice(@old, 0, 2)) {
- if (exists $hash{$k}) {
- for ($hash{$k}) {
- $_ = [$_] unless ref($_) eq "ARRAY";
- push(@$_, $v);
- }
- }
- else {
- $hash{$k} = $v;
- }
- }
- return \%hash;
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-URI::QueryParam - Additional query methods for URIs
-
-=head1 SYNOPSIS
-
- use URI;
- use URI::QueryParam;
-
- $u = URI->new("", "http");
- $u->query_param(foo => 1, 2, 3);
- print $u->query; # prints foo=1&foo=2&foo=3
-
- for my $key ($u->query_param) {
- print "$key: ", join(", ", $u->query_param($key)), "\n";
- }
-
-=head1 DESCRIPTION
-
-Loading the C<URI::QueryParam> module adds some extra methods to
-URIs that support query methods. These methods provide an alternative
-interface to the $u->query_form data.
-
-The query_param_* methods have deliberately been made identical to the
-interface of the corresponding C<CGI.pm> methods.
-
-The following additional methods are made available:
-
-=over
-
-=item @keys = $u->query_param
-
-=item @values = $u->query_param( $key )
-
-=item $first_value = $u->query_param( $key )
-
-=item $u->query_param( $key, $value,... )
-
-If $u->query_param is called with no arguments, it returns all the
-distinct parameter keys of the URI. In a scalar context it returns the
-number of distinct keys.
-
-When a $key argument is given, the method returns the parameter values with the
-given key. In a scalar context, only the first parameter value is
-returned.
-
-If additional arguments are given, they are used to update successive
-parameters with the given key. If any of the values provided are
-array references, then the array is dereferenced to get the actual
-values.
-
-=item $u->query_param_append($key, $value,...)
-
-Adds new parameters with the given
-key without touching any old parameters with the same key. It
-can be explained as a more efficient version of:
-
- $u->query_param($key,
- $u->query_param($key),
- $value,...);
-
-One difference is that this expression would return the old values
-of $key, whereas the query_param_append() method does not.
-
-=item @values = $u->query_param_delete($key)
-
-=item $first_value = $u->query_param_delete($key)
-
-Deletes all key/value pairs with the given key.
-The old values are returned. In a scalar context, only the first value
-is returned.
-
-Using the query_param_delete() method is slightly more efficient than
-the equivalent:
-
- $u->query_param($key, []);
-
-=item $hashref = $u->query_form_hash
-
-=item $u->query_form_hash( \%new_form )
-
-Returns a reference to a hash that represents the
-query form's key/value pairs. If a key occurs multiple times, then the hash
-value becomes an array reference.
-
-Note that sequence information is lost. This means that:
-
- $u->query_form_hash($u->query_form_hash)
-
-is not necessarily a no-op, as it may reorder the key/value pairs.
-The values returned by the query_param() method should stay the same
-though.
-
-=back
-
-=head1 SEE ALSO
-
-L<URI>, L<CGI>
-
-=head1 COPYRIGHT
-
-Copyright 2002 Gisle Aas.
-
-=cut
diff --git a/lib/URI/Split.pm b/lib/URI/Split.pm
deleted file mode 100644
index 63bb62b..0000000
--- a/lib/URI/Split.pm
+++ /dev/null
@@ -1,96 +0,0 @@
-package URI::Split;
-
-use strict;
-
-use vars qw(@ISA @EXPORT_OK);
-require Exporter;
-@ISA = qw(Exporter);
-@EXPORT_OK = qw(uri_split uri_join);
-
-use URI::Escape ();
-
-sub uri_split {
- return $_[0] =~ m,(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?,;
-}
-
-sub uri_join {
- my($scheme, $auth, $path, $query, $frag) = @_;
- my $uri = defined($scheme) ? "$scheme:" : "";
- $path = "" unless defined $path;
- if (defined $auth) {
- $auth =~ s,([/?\#]),$URI::Escape::escapes{$1},g;
- $uri .= "//$auth";
- $path = "/$path" if length($path) && $path !~ m,^/,;
- }
- elsif ($path =~ m,^//,) {
- $uri .= "//"; # XXX force empty auth
- }
- unless (length $uri) {
- $path =~ s,(:),$URI::Escape::escapes{$1}, while $path =~ m,^[^:/?\#]+:,;
- }
- $path =~ s,([?\#]),$URI::Escape::escapes{$1},g;
- $uri .= $path;
- if (defined $query) {
- $query =~ s,(\#),$URI::Escape::escapes{$1},g;
- $uri .= "?$query";
- }
- $uri .= "#$frag" if defined $frag;
- $uri;
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-URI::Split - Parse and compose URI strings
-
-=head1 SYNOPSIS
-
- use URI::Split qw(uri_split uri_join);
- ($scheme, $auth, $path, $query, $frag) = uri_split($uri);
- $uri = uri_join($scheme, $auth, $path, $query, $frag);
-
-=head1 DESCRIPTION
-
-Provides functions to parse and compose URI
-strings. The following functions are provided:
-
-=over
-
-=item ($scheme, $auth, $path, $query, $frag) = uri_split($uri)
-
-Breaks up a URI string into its component
-parts. An C<undef> value is returned for those parts that are not
-present. The $path part is always present (but can be the empty
-string) and is thus never returned as C<undef>.
-
-No sensible value is returned if this function is called in a scalar
-context.
-
-=item $uri = uri_join($scheme, $auth, $path, $query, $frag)
-
-Puts together a URI string from its parts.
-Missing parts are signaled by passing C<undef> for the corresponding
-argument.
-
-Minimal escaping is applied to parts that contain reserved chars
-that would confuse a parser. For instance, any occurrence of '?' or '#'
-in $path is always escaped, as it would otherwise be parsed back
-as a query or fragment.
-
-=back
-
-=head1 SEE ALSO
-
-L<URI>, L<URI::Escape>
-
-=head1 COPYRIGHT
-
-Copyright 2003, Gisle Aas
-
-This library is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/URI/URL.pm b/lib/URI/URL.pm
deleted file mode 100644
index 7735448..0000000
--- a/lib/URI/URL.pm
+++ /dev/null
@@ -1,305 +0,0 @@
-package URI::URL;
-
-require URI::WithBase;
-@ISA=qw(URI::WithBase);
-
-use strict;
-use vars qw(@EXPORT $VERSION);
-
-$VERSION = "5.03";
-
-# Provide as much as possible of the old URI::URL interface for backwards
-# compatibility...
-
-require Exporter;
-*import = \&Exporter::import;
-@EXPORT = qw(url);
-
-# Easy to use constructor
-sub url ($;$) { URI::URL->new(@_); }
-
-use URI::Escape qw(uri_unescape);
-
-sub new
-{
- my $class = shift;
- my $self = $class->SUPER::new(@_);
- $self->[0] = $self->[0]->canonical;
- $self;
-}
-
-sub newlocal
-{
- my $class = shift;
- require URI::file;
- bless [URI::file->new_abs(shift)], $class;
-}
-
-{package URI::_foreign;
- sub _init # hope it is not defined
- {
- my $class = shift;
- die "Unknown URI::URL scheme $_[1]:" if $URI::URL::STRICT;
- $class->SUPER::_init(@_);
- }
-}
-
-sub strict
-{
- my $old = $URI::URL::STRICT;
- $URI::URL::STRICT = shift if @_;
- $old;
-}
-
-sub print_on
-{
- my $self = shift;
- require Data::Dumper;
- print STDERR Data::Dumper::Dumper($self);
-}
-
-sub _try
-{
- my $self = shift;
- my $method = shift;
- scalar(eval { $self->$method(@_) });
-}
-
-sub crack
-{
- # should be overridden by subclasses
- my $self = shift;
- (scalar($self->scheme),
- $self->_try("user"),
- $self->_try("password"),
- $self->_try("host"),
- $self->_try("port"),
- $self->_try("path"),
- $self->_try("params"),
- $self->_try("query"),
- scalar($self->fragment),
- )
-}
-
-sub full_path
-{
- my $self = shift;
- my $path = $self->path_query;
- $path = "/" unless length $path;
- $path;
-}
-
-sub netloc
-{
- shift->authority(@_);
-}
-
-sub epath
-{
- my $path = shift->SUPER::path(@_);
- $path =~ s/;.*//;
- $path;
-}
-
-sub eparams
-{
- my $self = shift;
- my @p = $self->path_segments;
- return unless ref($p[-1]);
- @p = @{$p[-1]};
- shift @p;
- join(";", @p);
-}
-
-sub params { shift->eparams(@_); }
-
-sub path {
- my $self = shift;
- my $old = $self->epath(@_);
- return unless defined wantarray;
- return '/' if !defined($old) || !length($old);
- Carp::croak("Path components contain '/' (you must call epath)")
- if $old =~ /%2[fF]/ and !@_;
- $old = "/$old" if $old !~ m|^/| && defined $self->netloc;
- return uri_unescape($old);
-}
-
-sub path_components {
- shift->path_segments(@_);
-}
-
-sub query {
- my $self = shift;
- my $old = $self->equery(@_);
- if (defined(wantarray) && defined($old)) {
- if ($old =~ /%(?:26|2[bB]|3[dD])/) { # contains escaped '=' '&' or '+'
- my $mess;
- for ($old) {
- $mess = "Query contains both '+' and '%2B'"
- if /\+/ && /%2[bB]/;
- $mess = "Form query contains escaped '=' or '&'"
- if /=/ && /%(?:3[dD]|26)/;
- }
- if ($mess) {
- Carp::croak("$mess (you must call equery)");
- }
- }
- # Now it should be safe to unescape the string without loosing
- # information
- return uri_unescape($old);
- }
- undef;
-
-}
-
-sub abs
-{
- my $self = shift;
- my $base = shift;
- my $allow_scheme = shift;
- $allow_scheme = $URI::URL::ABS_ALLOW_RELATIVE_SCHEME
- unless defined $allow_scheme;
- local $URI::ABS_ALLOW_RELATIVE_SCHEME = $allow_scheme;
- local $URI::ABS_REMOTE_LEADING_DOTS = $URI::URL::ABS_REMOTE_LEADING_DOTS;
- $self->SUPER::abs($base);
-}
-
-sub frag { shift->fragment(@_); }
-sub keywords { shift->query_keywords(@_); }
-
-# file:
-sub local_path { shift->file; }
-sub unix_path { shift->file("unix"); }
-sub dos_path { shift->file("dos"); }
-sub mac_path { shift->file("mac"); }
-sub vms_path { shift->file("vms"); }
-
-# mailto:
-sub address { shift->to(@_); }
-sub encoded822addr { shift->to(@_); }
-sub URI::mailto::authority { shift->to(@_); } # make 'netloc' method work
-
-# news:
-sub groupart { shift->_group(@_); }
-sub article { shift->message(@_); }
-
-1;
-
-__END__
-
-=head1 NAME
-
-URI::URL - Uniform Resource Locators
-
-=head1 SYNOPSIS
-
- $u1 = URI::URL->new($str, $base);
- $u2 = $u1->abs;
-
-=head1 DESCRIPTION
-
-This module is provided for backwards compatibility with modules that
-depend on the interface provided by the C<URI::URL> class that used to
-be distributed with the libwww-perl library.
-
-The following differences exist compared to the C<URI> class interface:
-
-=over 3
-
-=item *
-
-The URI::URL module exports the url() function as an alternate
-constructor interface.
-
-=item *
-
-The constructor takes an optional $base argument. The C<URI::URL>
-class is a subclass of C<URI::WithBase>.
-
-=item *
-
-The URI::URL->newlocal class method is the same as URI::file->new_abs.
-
-=item *
-
-URI::URL::strict(1)
-
-=item *
-
-$url->print_on method
-
-=item *
-
-$url->crack method
-
-=item *
-
-$url->full_path: same as ($uri->abs_path || "/")
-
-=item *
-
-$url->netloc: same as $uri->authority
-
-=item *
-
-$url->epath, $url->equery: same as $uri->path, $uri->query
-
-=item *
-
-$url->path and $url->query pass unescaped strings.
-
-=item *
-
-$url->path_components: same as $uri->path_segments (if you don't
-consider path segment parameters)
-
-=item *
-
-$url->params and $url->eparams methods
-
-=item *
-
-$url->base method. See L<URI::WithBase>.
-
-=item *
-
-$url->abs and $url->rel have an optional $base argument. See
-L<URI::WithBase>.
-
-=item *
-
-$url->frag: same as $uri->fragment
-
-=item *
-
-$url->keywords: same as $uri->query_keywords
-
-=item *
-
-$url->localpath and friends map to $uri->file.
-
-=item *
-
-$url->address and $url->encoded822addr: same as $uri->to for mailto URI
-
-=item *
-
-$url->groupart method for news URI
-
-=item *
-
-$url->article: same as $uri->message
-
-=back
-
-
-
-=head1 SEE ALSO
-
-L<URI>, L<URI::WithBase>
-
-=head1 COPYRIGHT
-
-Copyright 1998-2000 Gisle Aas.
-
-=cut
diff --git a/lib/URI/WithBase.pm b/lib/URI/WithBase.pm
deleted file mode 100644
index 0337c6b..0000000
--- a/lib/URI/WithBase.pm
+++ /dev/null
@@ -1,171 +0,0 @@
-package URI::WithBase;
-
-use strict;
-use vars qw($AUTOLOAD $VERSION);
-use URI;
-
-$VERSION = "2.19";
-
-use overload '""' => "as_string", fallback => 1;
-
-sub as_string; # help overload find it
-
-sub new
-{
- my($class, $uri, $base) = @_;
- my $ibase = $base;
- if ($base && ref($base) && UNIVERSAL::isa($base, __PACKAGE__)) {
- $base = $base->abs;
- $ibase = $base->[0];
- }
- bless [URI->new($uri, $ibase), $base], $class;
-}
-
-sub new_abs
-{
- my $class = shift;
- my $self = $class->new(@_);
- $self->abs;
-}
-
-sub _init
-{
- my $class = shift;
- my($str, $scheme) = @_;
- bless [URI->new($str, $scheme), undef], $class;
-}
-
-sub eq
-{
- my($self, $other) = @_;
- $other = $other->[0] if UNIVERSAL::isa($other, __PACKAGE__);
- $self->[0]->eq($other);
-}
-
-sub AUTOLOAD
-{
- my $self = shift;
- my $method = substr($AUTOLOAD, rindex($AUTOLOAD, '::')+2);
- return if $method eq "DESTROY";
- $self->[0]->$method(@_);
-}
-
-sub can { # override UNIVERSAL::can
- my $self = shift;
- $self->SUPER::can(@_) || (
- ref($self)
- ? $self->[0]->can(@_)
- : undef
- )
-}
-
-sub base {
- my $self = shift;
- my $base = $self->[1];
-
- if (@_) { # set
- my $new_base = shift;
- # ensure absoluteness
- $new_base = $new_base->abs if ref($new_base) && $new_base->isa(__PACKAGE__);
- $self->[1] = $new_base;
- }
- return unless defined wantarray;
-
- # The base attribute supports 'lazy' conversion from URL strings
- # to URL objects. Strings may be stored but when a string is
- # fetched it will automatically be converted to a URL object.
- # The main benefit is to make it much cheaper to say:
- # URI::WithBase->new($random_url_string, 'http:')
- if (defined($base) && !ref($base)) {
- $base = ref($self)->new($base);
- $self->[1] = $base unless @_;
- }
- $base;
-}
-
-sub clone
-{
- my $self = shift;
- my $base = $self->[1];
- $base = $base->clone if ref($base);
- bless [$self->[0]->clone, $base], ref($self);
-}
-
-sub abs
-{
- my $self = shift;
- my $base = shift || $self->base || return $self->clone;
- $base = $base->as_string if ref($base);
- bless [$self->[0]->abs($base, @_), $base], ref($self);
-}
-
-sub rel
-{
- my $self = shift;
- my $base = shift || $self->base || return $self->clone;
- $base = $base->as_string if ref($base);
- bless [$self->[0]->rel($base, @_), $base], ref($self);
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-URI::WithBase - URIs which remember their base
-
-=head1 SYNOPSIS
-
- $u1 = URI::WithBase->new($str, $base);
- $u2 = $u1->abs;
-
- $base = $u1->base;
- $u1->base( $new_base )
-
-=head1 DESCRIPTION
-
-This module provides the C<URI::WithBase> class. Objects of this class
-are like C<URI> objects, but can keep their base too. The base
-represents the context where this URI was found and can be used to
-absolutize or relativize the URI. All the methods described in L<URI>
-are supported for C<URI::WithBase> objects.
-
-The methods provided in addition to or modified from those of C<URI> are:
-
-=over 4
-
-=item $uri = URI::WithBase->new($str, [$base])
-
-The constructor takes an optional base URI as the second argument.
-If provided, this argument initializes the base attribute.
-
-=item $uri->base( [$new_base] )
-
-Can be used to get or set the value of the base attribute.
-The return value, which is the old value, is a URI object or C<undef>.
-
-=item $uri->abs( [$base_uri] )
-
-The $base_uri argument is now made optional as the object carries its
-base with it. A new object is returned even if $uri is already
-absolute (while plain URI objects simply return themselves in
-that case).
-
-=item $uri->rel( [$base_uri] )
-
-The $base_uri argument is now made optional as the object carries its
-base with it. A new object is always returned.
-
-=back
-
-
-=head1 SEE ALSO
-
-L<URI>
-
-=head1 COPYRIGHT
-
-Copyright 1998-2002 Gisle Aas.
-
-=cut
diff --git a/lib/URI/_foreign.pm b/lib/URI/_foreign.pm
deleted file mode 100644
index 075f0fd..0000000
--- a/lib/URI/_foreign.pm
+++ /dev/null
@@ -1,6 +0,0 @@
-package URI::_foreign;
-
-require URI::_generic;
-@ISA=qw(URI::_generic);
-
-1;
diff --git a/lib/URI/_generic.pm b/lib/URI/_generic.pm
deleted file mode 100644
index 5aa6ca9..0000000
--- a/lib/URI/_generic.pm
+++ /dev/null
@@ -1,249 +0,0 @@
-package URI::_generic;
-require URI;
-require URI::_query;
-@ISA=qw(URI URI::_query);
-
-use strict;
-use URI::Escape qw(uri_unescape);
-use Carp ();
-
-my $ACHAR = $URI::uric; $ACHAR =~ s,\\[/?],,g;
-my $PCHAR = $URI::uric; $PCHAR =~ s,\\[?],,g;
-
-sub _no_scheme_ok { 1 }
-
-sub authority
-{
- my $self = shift;
- $$self =~ m,^((?:$URI::scheme_re:)?)(?://([^/?\#]*))?(.*)$,os or die;
-
- if (@_) {
- my $auth = shift;
- $$self = $1;
- my $rest = $3;
- if (defined $auth) {
- $auth =~ s/([^$ACHAR])/$URI::Escape::escapes{$1}/go;
- $$self .= "//$auth";
- }
- _check_path($rest, $$self);
- $$self .= $rest;
- }
- $2;
-}
-
-sub path
-{
- my $self = shift;
- $$self =~ m,^((?:[^:/?\#]+:)?(?://[^/?\#]*)?)([^?\#]*)(.*)$,s or die;
-
- if (@_) {
- $$self = $1;
- my $rest = $3;
- my $new_path = shift;
- $new_path = "" unless defined $new_path;
- $new_path =~ s/([^$PCHAR])/$URI::Escape::escapes{$1}/go;
- _check_path($new_path, $$self);
- $$self .= $new_path . $rest;
- }
- $2;
-}
-
-sub path_query
-{
- my $self = shift;
- $$self =~ m,^((?:[^:/?\#]+:)?(?://[^/?\#]*)?)([^\#]*)(.*)$,s or die;
-
- if (@_) {
- $$self = $1;
- my $rest = $3;
- my $new_path = shift;
- $new_path = "" unless defined $new_path;
- $new_path =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
- _check_path($new_path, $$self);
- $$self .= $new_path . $rest;
- }
- $2;
-}
-
-sub _check_path
-{
- my($path, $pre) = @_;
- my $prefix;
- if ($pre =~ m,/,) { # authority present
- $prefix = "/" if length($path) && $path !~ m,^[/?\#],;
- }
- else {
- if ($path =~ m,^//,) {
- Carp::carp("Path starting with double slash is confusing")
- if $^W;
- }
- elsif (!length($pre) && $path =~ m,^[^:/?\#]+:,) {
- Carp::carp("Path might look like scheme, './' prepended")
- if $^W;
- $prefix = "./";
- }
- }
- substr($_[0], 0, 0) = $prefix if defined $prefix;
-}
-
-sub path_segments
-{
- my $self = shift;
- my $path = $self->path;
- if (@_) {
- my @arg = @_; # make a copy
- for (@arg) {
- if (ref($_)) {
- my @seg = @$_;
- $seg[0] =~ s/%/%25/g;
- for (@seg) { s/;/%3B/g; }
- $_ = join(";", @seg);
- }
- else {
- s/%/%25/g; s/;/%3B/g;
- }
- s,/,%2F,g;
- }
- $self->path(join("/", @arg));
- }
- return $path unless wantarray;
- map {/;/ ? $self->_split_segment($_)
- : uri_unescape($_) }
- split('/', $path, -1);
-}
-
-
-sub _split_segment
-{
- my $self = shift;
- require URI::_segment;
- URI::_segment->new(@_);
-}
-
-
-sub abs
-{
- my $self = shift;
- my $base = shift || Carp::croak("Missing base argument");
-
- if (my $scheme = $self->scheme) {
- return $self unless $URI::ABS_ALLOW_RELATIVE_SCHEME;
- $base = URI->new($base) unless ref $base;
- return $self unless $scheme eq $base->scheme;
- }
-
- $base = URI->new($base) unless ref $base;
- my $abs = $self->clone;
- $abs->scheme($base->scheme);
- return $abs if $$self =~ m,^(?:$URI::scheme_re:)?//,o;
- $abs->authority($base->authority);
-
- my $path = $self->path;
- return $abs if $path =~ m,^/,;
-
- if (!length($path)) {
- my $abs = $base->clone;
- my $query = $self->query;
- $abs->query($query) if defined $query;
- $abs->fragment($self->fragment);
- return $abs;
- }
-
- my $p = $base->path;
- $p =~ s,[^/]+$,,;
- $p .= $path;
- my @p = split('/', $p, -1);
- shift(@p) if @p && !length($p[0]);
- my $i = 1;
- while ($i < @p) {
- #print "$i ", join("/", @p), " ($p[$i])\n";
- if ($p[$i-1] eq ".") {
- splice(@p, $i-1, 1);
- $i-- if $i > 1;
- }
- elsif ($p[$i] eq ".." && $p[$i-1] ne "..") {
- splice(@p, $i-1, 2);
- if ($i > 1) {
- $i--;
- push(@p, "") if $i == @p;
- }
- }
- else {
- $i++;
- }
- }
- $p[-1] = "" if @p && $p[-1] eq "."; # trailing "/."
- if ($URI::ABS_REMOTE_LEADING_DOTS) {
- shift @p while @p && $p[0] =~ /^\.\.?$/;
- }
- $abs->path("/" . join("/", @p));
- $abs;
-}
-
-# The oposite of $url->abs. Return a URI which is as relative as possible
-sub rel {
- my $self = shift;
- my $base = shift || Carp::croak("Missing base argument");
- my $rel = $self->clone;
- $base = URI->new($base) unless ref $base;
-
- #my($scheme, $auth, $path) = @{$rel}{qw(scheme authority path)};
- my $scheme = $rel->scheme;
- my $auth = $rel->canonical->authority;
- my $path = $rel->path;
-
- if (!defined($scheme) && !defined($auth)) {
- # it is already relative
- return $rel;
- }
-
- #my($bscheme, $bauth, $bpath) = @{$base}{qw(scheme authority path)};
- my $bscheme = $base->scheme;
- my $bauth = $base->canonical->authority;
- my $bpath = $base->path;
-
- for ($bscheme, $bauth, $auth) {
- $_ = '' unless defined
- }
-
- unless ($scheme eq $bscheme && $auth eq $bauth) {
- # different location, can't make it relative
- return $rel;
- }
-
- for ($path, $bpath) { $_ = "/$_" unless m,^/,; }
-
- # Make it relative by eliminating scheme and authority
- $rel->scheme(undef);
- $rel->authority(undef);
-
- # This loop is based on code from Nicolai Langfeldt <janl@ifi.uio.no>.
- # First we calculate common initial path components length ($li).
- my $li = 1;
- while (1) {
- my $i = index($path, '/', $li);
- last if $i < 0 ||
- $i != index($bpath, '/', $li) ||
- substr($path,$li,$i-$li) ne substr($bpath,$li,$i-$li);
- $li=$i+1;
- }
- # then we nuke it from both paths
- substr($path, 0,$li) = '';
- substr($bpath,0,$li) = '';
-
- if ($path eq $bpath &&
- defined($rel->fragment) &&
- !defined($rel->query)) {
- $rel->path("");
- }
- else {
- # Add one "../" for each path component left in the base path
- $path = ('../' x $bpath =~ tr|/|/|) . $path;
- $path = "./" if $path eq "";
- $rel->path($path);
- }
-
- $rel;
-}
-
-1;
diff --git a/lib/URI/_ldap.pm b/lib/URI/_ldap.pm
deleted file mode 100644
index 608dbd3..0000000
--- a/lib/URI/_ldap.pm
+++ /dev/null
@@ -1,140 +0,0 @@
-# Copyright (c) 1998 Graham Barr <gbarr@pobox.com>. All rights reserved.
-# This program is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-
-package URI::_ldap;
-
-use strict;
-
-use vars qw($VERSION);
-$VERSION = "1.10";
-
-use URI::Escape qw(uri_unescape);
-
-sub _ldap_elem {
- my $self = shift;
- my $elem = shift;
- my $query = $self->query;
- my @bits = (split(/\?/,defined($query) ? $query : ""),("")x4);
- my $old = $bits[$elem];
-
- if (@_) {
- my $new = shift;
- $new =~ s/\?/%3F/g;
- $bits[$elem] = $new;
- $query = join("?",@bits);
- $query =~ s/\?+$//;
- $query = undef unless length($query);
- $self->query($query);
- }
-
- $old;
-}
-
-sub dn {
- my $old = shift->path(@_);
- $old =~ s:^/::;
- uri_unescape($old);
-}
-
-sub attributes {
- my $self = shift;
- my $old = _ldap_elem($self,0, @_ ? join(",", map { my $tmp = $_; $tmp =~ s/,/%2C/g; $tmp } @_) : ());
- return $old unless wantarray;
- map { uri_unescape($_) } split(/,/,$old);
-}
-
-sub _scope {
- my $self = shift;
- my $old = _ldap_elem($self,1, @_);
- return unless defined wantarray && defined $old;
- uri_unescape($old);
-}
-
-sub scope {
- my $old = &_scope;
- $old = "base" unless length $old;
- $old;
-}
-
-sub _filter {
- my $self = shift;
- my $old = _ldap_elem($self,2, @_);
- return unless defined wantarray && defined $old;
- uri_unescape($old); # || "(objectClass=*)";
-}
-
-sub filter {
- my $old = &_filter;
- $old = "(objectClass=*)" unless length $old;
- $old;
-}
-
-sub extensions {
- my $self = shift;
- my @ext;
- while (@_) {
- my $key = shift;
- my $value = shift;
- push(@ext, join("=", map { $_="" unless defined; s/,/%2C/g; $_ } $key, $value));
- }
- @ext = join(",", @ext) if @ext;
- my $old = _ldap_elem($self,3, @ext);
- return $old unless wantarray;
- map { uri_unescape($_) } map { /^([^=]+)=(.*)$/ } split(/,/,$old);
-}
-
-sub canonical
-{
- my $self = shift;
- my $other = $self->_nonldap_canonical;
-
- # The stuff below is not as efficient as one might hope...
-
- $other = $other->clone if $other == $self;
-
- $other->dn(_normalize_dn($other->dn));
-
- # Should really know about mixed case "postalAddress", etc...
- $other->attributes(map lc, $other->attributes);
-
- # Lowecase scope, remove default
- my $old_scope = $other->scope;
- my $new_scope = lc($old_scope);
- $new_scope = "" if $new_scope eq "base";
- $other->scope($new_scope) if $new_scope ne $old_scope;
-
- # Remove filter if default
- my $old_filter = $other->filter;
- $other->filter("") if lc($old_filter) eq "(objectclass=*)" ||
- lc($old_filter) eq "objectclass=*";
-
- # Lowercase extensions types and deal with known extension values
- my @ext = $other->extensions;
- for (my $i = 0; $i < @ext; $i += 2) {
- my $etype = $ext[$i] = lc($ext[$i]);
- if ($etype =~ /^!?bindname$/) {
- $ext[$i+1] = _normalize_dn($ext[$i+1]);
- }
- }
- $other->extensions(@ext) if @ext;
-
- $other;
-}
-
-sub _normalize_dn # RFC 2253
-{
- my $dn = shift;
-
- return $dn;
- # The code below will fail if the "+" or "," is embedding in a quoted
- # string or simply escaped...
-
- my @dn = split(/([+,])/, $dn);
- for (@dn) {
- s/^([a-zA-Z]+=)/lc($1)/e;
- }
- join("", @dn);
-}
-
-1;
diff --git a/lib/URI/_login.pm b/lib/URI/_login.pm
deleted file mode 100644
index 4583f20..0000000
--- a/lib/URI/_login.pm
+++ /dev/null
@@ -1,10 +0,0 @@
-package URI::_login;
-
-require URI::_server;
-require URI::_userpass;
-@ISA = qw(URI::_server URI::_userpass);
-
-# Generic terminal logins. This is used as a base class for 'telnet',
-# 'tn3270', and 'rlogin' URL schemes.
-
-1;
diff --git a/lib/URI/_query.pm b/lib/URI/_query.pm
deleted file mode 100644
index 9323893..0000000
--- a/lib/URI/_query.pm
+++ /dev/null
@@ -1,81 +0,0 @@
-package URI::_query;
-
-use strict;
-use URI ();
-use URI::Escape qw(uri_unescape);
-
-sub query
-{
- my $self = shift;
- $$self =~ m,^([^?\#]*)(?:\?([^\#]*))?(.*)$,s or die;
-
- if (@_) {
- my $q = shift;
- $$self = $1;
- if (defined $q) {
- $q =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
- $$self .= "?$q";
- }
- $$self .= $3;
- }
- $2;
-}
-
-# Handle ...?foo=bar&bar=foo type of query
-sub query_form {
- my $self = shift;
- my $old = $self->query;
- if (@_) {
- # Try to set query string
- my @new = @_;
- if (@new == 1) {
- my $n = $new[0];
- if (ref($n) eq "ARRAY") {
- @new = @$n;
- }
- elsif (ref($n) eq "HASH") {
- @new = %$n;
- }
- }
- my @query;
- while (my($key,$vals) = splice(@new, 0, 2)) {
- $key = '' unless defined $key;
- $key =~ s/([;\/?:@&=+,\$\[\]%])/$URI::Escape::escapes{$1}/g;
- $key =~ s/ /+/g;
- $vals = [ref($vals) eq "ARRAY" ? @$vals : $vals];
- for my $val (@$vals) {
- $val = '' unless defined $val;
- $val =~ s/([;\/?:@&=+,\$\[\]%])/$URI::Escape::escapes{$1}/g;
- $val =~ s/ /+/g;
- push(@query, "$key=$val");
- }
- }
- $self->query(@query ? join('&', @query) : undef);
- }
- return if !defined($old) || !length($old) || !defined(wantarray);
- return unless $old =~ /=/; # not a form
- map { s/\+/ /g; uri_unescape($_) }
- map { /=/ ? split(/=/, $_, 2) : ($_ => '')} split(/&/, $old);
-}
-
-# Handle ...?dog+bones type of query
-sub query_keywords
-{
- my $self = shift;
- my $old = $self->query;
- if (@_) {
- # Try to set query string
- my @copy = @_;
- @copy = @{$copy[0]} if @copy == 1 && ref($copy[0]) eq "ARRAY";
- for (@copy) { s/([;\/?:@&=+,\$\[\]%])/$URI::Escape::escapes{$1}/g; }
- $self->query(@copy ? join('+', @copy) : undef);
- }
- return if !defined($old) || !defined(wantarray);
- return if $old =~ /=/; # not keywords, but a form
- map { uri_unescape($_) } split(/\+/, $old, -1);
-}
-
-# Some URI::URL compatibility stuff
-*equery = \&query;
-
-1;
diff --git a/lib/URI/_segment.pm b/lib/URI/_segment.pm
deleted file mode 100644
index c91b696..0000000
--- a/lib/URI/_segment.pm
+++ /dev/null
@@ -1,20 +0,0 @@
-package URI::_segment;
-
-# Represents a generic path_segment so that it can be treated as
-# a string too.
-
-use strict;
-use URI::Escape qw(uri_unescape);
-
-use overload '""' => sub { $_[0]->[0] },
- fallback => 1;
-
-sub new
-{
- my $class = shift;
- my @segment = split(';', shift, -1);
- $segment[0] = uri_unescape($segment[0]);
- bless \@segment, $class;
-}
-
-1;
diff --git a/lib/URI/_server.pm b/lib/URI/_server.pm
deleted file mode 100644
index 10059f0..0000000
--- a/lib/URI/_server.pm
+++ /dev/null
@@ -1,106 +0,0 @@
-package URI::_server;
-require URI::_generic;
-@ISA=qw(URI::_generic);
-
-use strict;
-use URI::Escape qw(uri_unescape);
-
-sub userinfo
-{
- my $self = shift;
- my $old = $self->authority;
-
- if (@_) {
- my $new = $old;
- $new = "" unless defined $new;
- $new =~ s/.*@//; # remove old stuff
- my $ui = shift;
- if (defined $ui) {
- $ui =~ s/@/%40/g; # protect @
- $new = "$ui\@$new";
- }
- $self->authority($new);
- }
- return undef if !defined($old) || $old !~ /(.*)@/;
- return $1;
-}
-
-sub host
-{
- my $self = shift;
- my $old = $self->authority;
- if (@_) {
- my $tmp = $old;
- $tmp = "" unless defined $tmp;
- my $ui = ($tmp =~ /(.*@)/) ? $1 : "";
- my $port = ($tmp =~ /(:\d+)$/) ? $1 : "";
- my $new = shift;
- $new = "" unless defined $new;
- if (length $new) {
- $new =~ s/[@]/%40/g; # protect @
- $port = $1 if $new =~ s/(:\d+)$//;
- }
- $self->authority("$ui$new$port");
- }
- return undef unless defined $old;
- $old =~ s/.*@//;
- $old =~ s/:\d+$//;
- return uri_unescape($old);
-}
-
-sub _port
-{
- my $self = shift;
- my $old = $self->authority;
- if (@_) {
- my $new = $old;
- $new =~ s/:\d*$//;
- my $port = shift;
- $new .= ":$port" if defined $port;
- $self->authority($new);
- }
- return $1 if defined($old) && $old =~ /:(\d*)$/;
- return;
-}
-
-sub port
-{
- my $self = shift;
- my $port = $self->_port(@_);
- $port = $self->default_port if !defined($port) || $port eq "";
- $port;
-}
-
-sub host_port
-{
- my $self = shift;
- my $old = $self->authority;
- $self->host(shift) if @_;
- return undef unless defined $old;
- $old =~ s/.*@//; # zap userinfo
- $old =~ s/:$//; # empty port does not could
- $old .= ":" . $self->port unless $old =~ /:/;
- $old;
-}
-
-
-sub default_port { undef }
-
-sub canonical
-{
- my $self = shift;
- my $other = $self->SUPER::canonical;
- my $host = $other->host || "";
- my $port = $other->_port;
- my $uc_host = $host =~ /[A-Z]/;
- my $def_port = defined($port) && ($port eq "" ||
- $port == $self->default_port);
- if ($uc_host || $def_port) {
- $other = $other->clone if $other == $self;
- $other->host(lc $host) if $uc_host;
- $other->port(undef) if $def_port;
- }
- $other;
-}
-
-1;
diff --git a/lib/URI/_userpass.pm b/lib/URI/_userpass.pm
deleted file mode 100644
index a0361ae..0000000
--- a/lib/URI/_userpass.pm
+++ /dev/null
@@ -1,51 +0,0 @@
-package URI::_userpass;
-
-use strict;
-use URI::Escape qw(uri_unescape);
-
-sub user
-{
- my $self = shift;
- my $info = $self->userinfo;
- if (@_) {
- my $new = shift;
- my $pass = defined($info) ? $info : "";
- $pass =~ s/^[^:]*//;
-
- if (!defined($new) && !length($pass)) {
- $self->userinfo(undef);
- } else {
- $new = "" unless defined($new);
- $new =~ s/%/%25/g;
- $new =~ s/:/%3A/g;
- $self->userinfo("$new$pass");
- }
- }
- return unless defined $info;
- $info =~ s/:.*//;
- uri_unescape($info);
-}
-
-sub password
-{
- my $self = shift;
- my $info = $self->userinfo;
- if (@_) {
- my $new = shift;
- my $user = defined($info) ? $info : "";
- $user =~ s/:.*//;
-
- if (!defined($new) && !length($user)) {
- $self->userinfo(undef);
- } else {
- $new = "" unless defined($new);
- $new =~ s/%/%25/g;
- $self->userinfo("$user:$new");
- }
- }
- return unless defined $info;
- return unless $info =~ s/^[^:]*://;
- uri_unescape($info);
-}
-
-1;
diff --git a/lib/URI/data.pm b/lib/URI/data.pm
deleted file mode 100644
index 3c44df1..0000000
--- a/lib/URI/data.pm
+++ /dev/null
@@ -1,139 +0,0 @@
-package URI::data; # RFC 2397
-
-require URI;
-@ISA=qw(URI);
-
-use strict;
-
-use MIME::Base64 qw(encode_base64 decode_base64);
-use URI::Escape qw(uri_unescape);
-
-sub media_type
-{
- my $self = shift;
- my $opaque = $self->opaque;
- $opaque =~ /^([^,]*),?/ or die;
- my $old = $1;
- my $base64;
- $base64 = $1 if $old =~ s/(;base64)$//i;
- if (@_) {
- my $new = shift;
- $new = "" unless defined $new;
- $new =~ s/%/%25/g;
- $new =~ s/,/%2C/g;
- $base64 = "" unless defined $base64;
- $opaque =~ s/^[^,]*,?/$new$base64,/;
- $self->opaque($opaque);
- }
- return uri_unescape($old) if $old; # media_type can't really be "0"
- "text/plain;charset=US-ASCII"; # default type
-}
-
-sub data
-{
- my $self = shift;
- my($enc, $data) = split(",", $self->opaque, 2);
- unless (defined $data) {
- $data = "";
- $enc = "" unless defined $enc;
- }
- my $base64 = ($enc =~ /;base64$/i);
- if (@_) {
- $enc =~ s/;base64$//i if $base64;
- my $new = shift;
- $new = "" unless defined $new;
- my $uric_count = _uric_count($new);
- my $urienc_len = $uric_count + (length($new) - $uric_count) * 3;
- my $base64_len = int((length($new)+2) / 3) * 4;
- $base64_len += 7; # because of ";base64" marker
- if ($base64_len < $urienc_len || $_[0]) {
- $enc .= ";base64";
- $new = encode_base64($new, "");
- } else {
- $new =~ s/%/%25/g;
- }
- $self->opaque("$enc,$new");
- }
- return unless defined wantarray;
- return $base64 ? decode_base64($data) : uri_unescape($data);
-}
-
-# I could not find a better way to interpolate the tr/// chars from
-# a variable.
-my $ENC = $URI::uric;
-$ENC =~ s/%//;
-
-eval <<EOT; die $@ if $@;
-sub _uric_count
-{
- \$_[0] =~ tr/$ENC//;
-}
-EOT
-
-1;
-
-__END__
-
-=head1 NAME
-
-URI::data - URI that contains immediate data
-
-=head1 SYNOPSIS
-
- use URI;
-
- $u = URI->new("data:");
- $u->media_type("image/gif");
- $u->data(scalar(`cat camel.gif`));
- print "$u\n";
- open(XV, "|xv -") and print XV $u->data;
-
-=head1 DESCRIPTION
-
-The C<URI::data> class supports C<URI> objects belonging to the I<data>
-URI scheme. The I<data> URI scheme is specified in RFC 2397. It
-allows inclusion of small data items as "immediate" data, as if it had
-been included externally. Examples:
-
- data:,Perl%20is%20good
-
- data:image/gif;base64,R0lGODdhIAAgAIAAAAAAAPj8+CwAAAAAI
- AAgAAAClYyPqcu9AJyCjtIKc5w5xP14xgeO2tlY3nWcajmZZdeJcG
- Kxrmimms1KMTa1Wg8UROx4MNUq1HrycMjHT9b6xKxaFLM6VRKzI+p
- KS9XtXpcbdun6uWVxJXA8pNPkdkkxhxc21LZHFOgD2KMoQXa2KMWI
- JtnE2KizVUkYJVZZ1nczBxXlFopZBtoJ2diXGdNUymmJdFMAADs=
-
-
-
-C<URI> objects belonging to the data scheme support the common methods
-(described in L<URI>) and the following two scheme-specific methods:
-
-=over 4
-
-=item $uri->media_type( [$new_media_type] )
-
-Can be used to get or set the media type specified in the
-URI. If no media type is specified, then the default
-C<"text/plain;charset=US-ASCII"> is returned.
-
-=item $uri->data( [$new_data] )
-
-Can be used to get or set the data contained in the URI.
-The data is passed unescaped (in binary form). The decision about
-whether to base64 encode the data in the URI is taken automatically,
-based on the encoding that produces the shorter URI string.
-
-=back
-
-=head1 SEE ALSO
-
-L<URI>
-
-=head1 COPYRIGHT
-
-Copyright 1995-1998 Gisle Aas.
-
-This library is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/URI/file.pm b/lib/URI/file.pm
deleted file mode 100644
index 3f3f1f6..0000000
--- a/lib/URI/file.pm
+++ /dev/null
@@ -1,329 +0,0 @@
-package URI::file;
-
-use strict;
-use vars qw(@ISA $VERSION $DEFAULT_AUTHORITY %OS_CLASS);
-
-require URI::_generic;
-@ISA = qw(URI::_generic);
-$VERSION = sprintf("%d.%02d", q$Revision: 4.19 $ =~ /(\d+)\.(\d+)/);
-
-use URI::Escape qw(uri_unescape);
-
-$DEFAULT_AUTHORITY = "";
-
-# Map from $^O values to implementation classes. The Unix
-# class is the default.
-%OS_CLASS = (
- os2 => "OS2",
- mac => "Mac",
- MacOS => "Mac",
- MSWin32 => "Win32",
- win32 => "Win32",
- msdos => "FAT",
- dos => "FAT",
- qnx => "QNX",
-);
-
-sub os_class
-{
- my($OS) = shift || $^O;
-
- my $class = "URI::file::" . ($OS_CLASS{$OS} || "Unix");
- no strict 'refs';
- unless (%{"$class\::"}) {
- eval "require $class";
- die $@ if $@;
- }
- $class;
-}
-
-sub path { shift->path_query(@_) }
-sub host { uri_unescape(shift->authority(@_)) }
-
-sub new
-{
- my($class, $path, $os) = @_;
- os_class($os)->new($path);
-}
-
-sub new_abs
-{
- my $class = shift;
- my $file = $class->new(@_);
- return $file->abs($class->cwd) unless $$file =~ /^file:/;
- $file;
-}
-
-sub cwd
-{
- my $class = shift;
- require Cwd;
- my $cwd = Cwd::cwd();
- $cwd = VMS::Filespec::unixpath($cwd) if $^O eq 'VMS';
- $cwd = $class->new($cwd);
- $cwd .= "/" unless substr($cwd, -1, 1) eq "/";
- $cwd;
-}
-
-sub canonical {
- my $self = shift;
- my $other = $self->SUPER::canonical;
-
- my $scheme = $other->scheme;
- my $auth = $other->authority;
- return $other if !defined($scheme) && !defined($auth); # relative
-
- if (!defined($auth) ||
- $auth eq "" ||
- lc($auth) eq "localhost" ||
- (defined($DEFAULT_AUTHORITY) && lc($auth) eq lc($DEFAULT_AUTHORITY))
- )
- {
- # avoid cloning if $auth already match
- if ((defined($auth) || defined($DEFAULT_AUTHORITY)) &&
- (!defined($auth) || !defined($DEFAULT_AUTHORITY) || $auth ne $DEFAULT_AUTHORITY)
- )
- {
- $other = $other->clone if $self == $other;
- $other->authority($DEFAULT_AUTHORITY);
- }
- }
-
- $other;
-}
-
-sub file
-{
- my($self, $os) = @_;
- os_class($os)->file($self);
-}
-
-sub dir
-{
- my($self, $os) = @_;
- os_class($os)->dir($self);
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-URI::file - URI that maps to local file names
-
-=head1 SYNOPSIS
-
- use URI::file;
-
- $u1 = URI->new("file:/foo/bar");
- $u2 = URI->new("foo/bar", "file");
-
- $u3 = URI::file->new($path);
- $u4 = URI::file->new("c:\\windows\\", "win32");
-
- $u1->file;
- $u1->file("mac");
-
-=head1 DESCRIPTION
-
-The C<URI::file> class supports C<URI> objects belonging to the I<file>
-URI scheme. This scheme allows us to map the conventional file names
-found on various computer systems to the URI name space. An old
-specification of the I<file> URI scheme is found in RFC 1738. Some
-older background information is also in RFC 1630. There are no newer
-specifications as far as I know.
-
-If you simply want to construct I<file> URI objects from URI strings,
-use the normal C<URI> constructor. If you want to construct I<file>
-URI objects from the actual file names used by various systems, then
-use one of the following C<URI::file> constructors:
-
-=over 4
-
-=item $u = URI::file->new( $filename, [$os] )
-
-Maps a file name to the I<file:> URI name space, creates a URI object
-and returns it. The $filename is interpreted as belonging to the
-indicated operating system ($os), which defaults to the value of the
-$^O variable. The $filename can be either absolute or relative, and
-the corresponding type of URI object for $os is returned.
-
-=item $u = URI::file->new_abs( $filename, [$os] )
-
-Same as URI::file->new, but makes sure that the URI returned
-represents an absolute file name. If the $filename argument is
-relative, then the name is resolved relative to the current directory,
-i.e. this constructor is really the same as:
-
- URI::file->new($filename)->abs(URI::file->cwd);
-
-=item $u = URI::file->cwd
-
-Returns a I<file> URI that represents the current working directory.
-See L<Cwd>.
-
-=back
-
-The following methods are supported for I<file> URI (in addition to
-the common and generic methods described in L<URI>):
-
-=over 4
-
-=item $u->file( [$os] )
-
-Returns a file name. It maps from the URI name space
-to the file name space of the indicated operating system.
-
-It might return C<undef> if the name can not be represented in the
-indicated file system.
-
-=item $u->dir( [$os] )
-
-Some systems use a different form for names of directories than for plain
-files. Use this method if you know you want to use the name for
-a directory.
-
-=back
-
-The C<URI::file> module can be used to map generic file names to names
-suitable for the current system. As such, it can work as a nice
-replacement for the C<File::Spec> module. For instance, the following
-code translates the UNIX-style file name F<Foo/Bar.pm> to a name
-suitable for the local system:
-
- $file = URI::file->new("Foo/Bar.pm", "unix")->file;
- die "Can't map filename Foo/Bar.pm for $^O" unless defined $file;
- open(FILE, $file) || die "Can't open '$file': $!";
- # do something with FILE
-
-=head1 MAPPING NOTES
-
-Most computer systems today have hierarchically organized file systems.
-Mapping the names used in these systems to the generic URI syntax
-allows us to work with relative file URIs that behave as they should
-when resolved using the generic algorithm for URIs (specified in RFC
-2396). Mapping a file name to the generic URI syntax involves mapping
-the path separator character to "/" and encoding any reserved
-characters that appear in the path segments of the file name. If
-path segments consisting of the strings "." or ".." have a
-different meaning than what is specified for generic URIs, then these
-must be encoded as well.
-
-If the file system has device, volume or drive specifications as
-the root of the name space, then it makes sense to map them to the
-authority field of the generic URI syntax. This makes sure that
-relative URIs can not be resolved "above" them, i.e. generally how
-relative file names work in those systems.
-
-Another common use of the authority field is to encode the host on which
-this file name is valid. The host name "localhost" is special and
-generally has the same meaning as a missing or empty authority
-field. This use is in conflict with using it as a device
-specification, but can often be resolved for device specifications
-having characters not legal in plain host names.
-
-File name to URI mapping in normally not one-to-one. There are
-usually many URIs that map to any given file name. For instance, an
-authority of "localhost" maps the same as a URI with a missing or empty
-authority.
-
-Example 1: The Mac uses ":" as path separator, but not in the same way
-as a generic URI. ":foo" is a relative name. "foo:bar" is an absolute
-name. Also, path segments can contain the "/" character as well as the
-literal "." or "..". So the mapping looks like this:
-
- Mac URI
- ---------- -------------------
- :foo:bar <==> foo/bar
- : <==> ./
- ::foo:bar <==> ../foo/bar
- ::: <==> ../../
- foo:bar <==> file:/foo/bar
- foo:bar: <==> file:/foo/bar/
- .. <==> %2E%2E
- <undef> <== /
- foo/ <== file:/foo%2F
- ./foo.txt <== file:/.%2Ffoo.txt
-
-Note that if you want a relative URL, you *must* begin the path with a :. Any
-path that begins with [^:] is treated as absolute.
-
-Example 2: The UNIX file system is easy to map, as it uses the same path
-separator as URIs, has a single root, and segments of "." and ".."
-have the same meaning. URIs that have the character "\0" or "/" as
-part of any path segment can not be turned into valid UNIX file names.
-
- UNIX URI
- ---------- ------------------
- foo/bar <==> foo/bar
- /foo/bar <==> file:/foo/bar
- /foo/bar <== file://localhost/foo/bar
- file: ==> ./file:
- <undef> <== file:/fo%00/bar
- / <==> file:/
-
-=cut
-
-
-RFC 1630
-
- [...]
-
- There is clearly a danger of confusion that a link made to a local
- file should be followed by someone on a different system, with
- unexpected and possibly harmful results. Therefore, the convention
- is that even a "file" URL is provided with a host part. This allows
- a client on another system to know that it cannot access the file
- system, or perhaps to use some other local mechanism to access the
- file.
-
- The special value "localhost" is used in the host field to indicate
- that the filename should really be used on whatever host one is.
- This for example allows links to be made to files which are
- distribted on many machines, or to "your unix local password file"
- subject of course to consistency across the users of the data.
-
- A void host field is equivalent to "localhost".
-
-=head1 CONFIGURATION VARIABLES
-
-The following configuration variables influence how the class and its
-methods behave:
-
-=over
-
-=item %URI::file::OS_CLASS
-
-This hash maps OS identifiers to implementation classes. You might
-want to add or modify this if you want to plug in your own file
-handler class. Normally the keys should match the $^O values in use.
-
-If there is no mapping then the "Unix" implementation is used.
-
-=item $URI::file::DEFAULT_AUTHORITY
-
-This determine what "authority" string to include in absolute file
-URIs. It defaults to "". If you prefer verbose URIs you might set it
-to be "localhost".
-
-Setting this value to C<undef> force behaviour compatible to URI v1.31
-and earlier. In this mode host names in UNC paths and drive letters
-are mapped to the authority component on Windows, while we produce
-authority-less URIs on Unix.
-
-=back
-
-
-=head1 SEE ALSO
-
-L<URI>, L<File::Spec>, L<perlport>
-
-=head1 COPYRIGHT
-
-Copyright 1995-1998,2004 Gisle Aas.
-
-This library is free software; you can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=cut
diff --git a/lib/URI/file/Base.pm b/lib/URI/file/Base.pm
deleted file mode 100644
index 51030c2..0000000
--- a/lib/URI/file/Base.pm
+++ /dev/null
@@ -1,80 +0,0 @@
-package URI::file::Base;
-
-use strict;
-use URI::Escape qw();
-
-sub new
-{
- my $class = shift;
- my $path = shift;
- $path = "" unless defined $path;
-
- my($auth, $escaped_auth, $escaped_path);
-
- ($auth, $escaped_auth) = $class->_file_extract_authority($path);
- ($path, $escaped_path) = $class->_file_extract_path($path);
-
- if (defined $auth) {
- $auth =~ s,%,%25,g unless $escaped_auth;
- $auth =~ s,([/?\#]),$URI::Escape::escapes{$1},g;
- $auth = "//$auth";
- if (defined $path) {
- $path = "/$path" unless substr($path, 0, 1) eq "/";
- } else {
- $path = "";
- }
- } else {
- return undef unless defined $path;
- $auth = "";
- }
-
- $path =~ s,([%;?]),$URI::Escape::escapes{$1},g unless $escaped_path;
- $path =~ s/\#/%23/g;
-
- my $uri = $auth . $path;
- $uri = "file:$uri" if substr($uri, 0, 1) eq "/";
-
- URI->new($uri, "file");
-}
-
-sub _file_extract_authority
-{
- my($class, $path) = @_;
- return undef unless $class->_file_is_absolute($path);
- return $URI::file::DEFAULT_AUTHORITY;
-}
-
-sub _file_extract_path
-{
- return undef;
-}
-
-sub _file_is_absolute
-{
- return 0;
-}
-
-sub _file_is_localhost
-{
- shift; # class
- my $host = lc(shift);
- return 1 if $host eq "localhost";
- eval {
- require Net::Domain;
- lc(Net::Domain::hostfqdn()) eq $host ||
- lc(Net::Domain::hostname()) eq $host;
- };
-}
-
-sub file
-{
- undef;
-}
-
-sub dir
-{
- my $self = shift;
- $self->file(@_);
-}
-
-1;
diff --git a/lib/URI/file/FAT.pm b/lib/URI/file/FAT.pm
deleted file mode 100644
index 328169b..0000000
--- a/lib/URI/file/FAT.pm
+++ /dev/null
@@ -1,23 +0,0 @@
-package URI::file::FAT;
-
-require URI::file::Win32;
-@ISA=qw(URI::file::Win32);
-
-sub fix_path
-{
- shift; # class
- for (@_) {
- # turn it into 8.3 names
- my @p = map uc, split(/\./, $_, -1);
- return if @p > 2; # more than 1 dot is not allowed
- @p = ("") unless @p; # split bug? (returns nothing when splitting "")
- $_ = substr($p[0], 0, 8);
- if (@p > 1) {
- my $ext = substr($p[1], 0, 3);
- $_ .= ".$ext" if length $ext;
- }
- }
- 1; # ok
-}
-
-1;
diff --git a/lib/URI/file/Mac.pm b/lib/URI/file/Mac.pm
deleted file mode 100644
index 8eef34b..0000000
--- a/lib/URI/file/Mac.pm
+++ /dev/null
@@ -1,120 +0,0 @@
-package URI::file::Mac;
-
-require URI::file::Base;
-@ISA=qw(URI::file::Base);
-
-use strict;
-use URI::Escape qw(uri_unescape);
-
-
-
-sub _file_extract_path
-{
- my $class = shift;
- my $path = shift;
-
- my @pre;
- if ($path =~ s/^(:+)//) {
- if (length($1) == 1) {
- @pre = (".") unless length($path);
- } else {
- @pre = ("..") x (length($1) - 1);
- }
- } else { #absolute
- $pre[0] = "";
- }
-
- my $isdir = ($path =~ s/:$//);
- $path =~ s,([%/;]),$URI::Escape::escapes{$1},g;
-
- my @path = split(/:/, $path, -1);
- for (@path) {
- if ($_ eq "." || $_ eq "..") {
- $_ = "%2E" x length($_);
- }
- $_ = ".." unless length($_);
- }
- push (@path,"") if $isdir;
- (join("/", @pre, @path), 1);
-}
-
-
-sub file
-{
- my $class = shift;
- my $uri = shift;
- my @path;
-
- my $auth = $uri->authority;
- if (defined $auth) {
- if (lc($auth) ne "localhost" && $auth ne "") {
- my $u_auth = uri_unescape($auth);
- if (!$class->_file_is_localhost($u_auth)) {
- # some other host (use it as volume name)
- @path = ("", $auth);
- # XXX or just return to make it illegal;
- }
- }
- }
- my @ps = split("/", $uri->path, -1);
- shift @ps if @path;
- push(@path, @ps);
-
- my $pre = "";
- if (!@path) {
- return; # empty path; XXX return ":" instead?
- } elsif ($path[0] eq "") {
- # absolute
- shift(@path);
- if (@path == 1) {
- return if $path[0] eq ""; # not root directory
- push(@path, ""); # volume only, effectively append ":"
- }
- @ps = @path;
- @path = ();
- my $part;
- for (@ps) { #fix up "." and "..", including interior, in relatives
- next if $_ eq ".";
- $part = $_ eq ".." ? "" : $_;
- push(@path,$part);
- }
- if ($ps[-1] eq "..") { #if this happens, we need another :
- push(@path,"");
- }
-
- } else {
- $pre = ":";
- @ps = @path;
- @path = ();
- my $part;
- for (@ps) { #fix up "." and "..", including interior, in relatives
- next if $_ eq ".";
- $part = $_ eq ".." ? "" : $_;
- push(@path,$part);
- }
- if ($ps[-1] eq "..") { #if this happens, we need another :
- push(@path,"");
- }
-
- }
- return unless $pre || @path;
- for (@path) {
- s/;.*//; # get rid of parameters
- #return unless length; # XXX
- $_ = uri_unescape($_);
- return if /\0/;
- return if /:/; # Should we?
- }
- $pre . join(":", @path);
-}
-
-sub dir
-{
- my $class = shift;
- my $path = $class->file(@_);
- return unless defined $path;
- $path .= ":" unless $path =~ /:$/;
- $path;
-}
-
-1;
diff --git a/lib/URI/file/OS2.pm b/lib/URI/file/OS2.pm
deleted file mode 100644
index ad0a78e..0000000
--- a/lib/URI/file/OS2.pm
+++ /dev/null
@@ -1,28 +0,0 @@
-package URI::file::OS2;
-
-require URI::file::Win32;
-@ISA=qw(URI::file::Win32);
-
-# The Win32 version translates k:/foo to file://k:/foo (?!)
-# We add an empty host
-
-sub _file_extract_authority
-{
- my $class = shift;
- return $1 if $_[0] =~ s,^\\\\([^\\]+),,; # UNC
- return $1 if $_[0] =~ s,^//([^/]+),,; # UNC too?
-
- if ($_[0] =~ m#^[a-zA-Z]{1,2}:#) { # allow for ab: drives
- return "";
- }
- return;
-}
-
-sub file {
- my $p = &URI::file::Win32::file;
- return unless defined $p;
- $p =~ s,\\,/,g;
- $p;
-}
-
-1;
diff --git a/lib/URI/file/QNX.pm b/lib/URI/file/QNX.pm
deleted file mode 100644
index 93a4983..0000000
--- a/lib/URI/file/QNX.pm
+++ /dev/null
@@ -1,18 +0,0 @@
-package URI::file::QNX;
-
-require URI::file::Unix;
-@ISA=qw(URI::file::Unix);
-
-use strict;
-
-sub _file_extract_path
-{
- my($class, $path) = @_;
- # tidy path
- $path =~ s,(.)//+,$1/,g; # ^// is correct
- $path =~ s,(/\.)+/,/,g;
- $path = "./$path" if $path =~ m,^[^:/]+:,,; # look like "scheme:"
- $path;
-}
-
-1;
diff --git a/lib/URI/file/Unix.pm b/lib/URI/file/Unix.pm
deleted file mode 100644
index 5f8aaae..0000000
--- a/lib/URI/file/Unix.pm
+++ /dev/null
@@ -1,55 +0,0 @@
-package URI::file::Unix;
-
-require URI::file::Base;
-@ISA=qw(URI::file::Base);
-
-use strict;
-use URI::Escape qw(uri_unescape);
-
-sub _file_extract_path
-{
- my($class, $path) = @_;
-
- # tidy path
- $path =~ s,//+,/,g;
- $path =~ s,(/\.)+/,/,g;
- $path = "./$path" if $path =~ m,^[^:/]+:,,; # look like "scheme:"
-
- return $path;
-}
-
-sub _file_is_absolute {
- my($class, $path) = @_;
- return $path =~ m,^/,;
-}
-
-sub file
-{
- my $class = shift;
- my $uri = shift;
- my @path;
-
- my $auth = $uri->authority;
- if (defined($auth)) {
- if (lc($auth) ne "localhost" && $auth ne "") {
- $auth = uri_unescape($auth);
- unless ($class->_file_is_localhost($auth)) {
- push(@path, "", "", $auth);
- }
- }
- }
-
- my @ps = $uri->path_segments;
- shift @ps if @path;
- push(@path, @ps);
-
- for (@path) {
- # Unix file/directory names are not allowed to contain '\0' or '/'
- return undef if /\0/;
- return undef if /\//; # should we really?
- }
-
- return join("/", @path);
-}
-
-1;
diff --git a/lib/URI/file/Win32.pm b/lib/URI/file/Win32.pm
deleted file mode 100644
index 0459386..0000000
--- a/lib/URI/file/Win32.pm
+++ /dev/null
@@ -1,84 +0,0 @@
-package URI::file::Win32;
-
-require URI::file::Base;
-@ISA=qw(URI::file::Base);
-
-use strict;
-use URI::Escape qw(uri_unescape);
-
-sub _file_extract_authority
-{
- my $class = shift;
-
- return $class->SUPER::_file_extract_authority($_[0])
- if defined $URI::file::DEFAULT_AUTHORITY;
-
- return $1 if $_[0] =~ s,^\\\\([^\\]+),,; # UNC
- return $1 if $_[0] =~ s,^//([^/]+),,; # UNC too?
-
- if ($_[0] =~ s,^([a-zA-Z]:),,) {
- my $auth = $1;
- $auth .= "relative" if $_[0] !~ m,^[\\/],;
- return $auth;
- }
- return undef;
-}
-
-sub _file_extract_path
-{
- my($class, $path) = @_;
- $path =~ s,\\,/,g;
- #$path =~ s,//+,/,g;
- $path =~ s,(/\.)+/,/,g;
-
- if (defined $URI::file::DEFAULT_AUTHORITY) {
- $path =~ s,^([a-zA-Z]:),/$1,;
- }
-
- return $path;
-}
-
-sub _file_is_absolute {
- my($class, $path) = @_;
- return $path =~ m,^[a-zA-Z]:, || $path =~ m,^[/\\],;
-}
-
-sub file
-{
- my $class = shift;
- my $uri = shift;
- my $auth = $uri->authority;
- my $rel; # is filename relative to drive specified in authority
- if (defined $auth) {
- $auth = uri_unescape($auth);
- if ($auth =~ /^([a-zA-Z])[:|](relative)?/) {
- $auth = uc($1) . ":";
- $rel++ if $2;
- } elsif (lc($auth) eq "localhost") {
- $auth = "";
- } elsif (length $auth) {
- $auth = "\\\\" . $auth; # UNC
- }
- } else {
- $auth = "";
- }
-
- my @path = $uri->path_segments;
- for (@path) {
- return undef if /\0/;
- return undef if /\//;
- #return undef if /\\/; # URLs with "\" is not uncommon
- }
- return undef unless $class->fix_path(@path);
-
- my $path = join("\\", @path);
- $path =~ s/^\\// if $rel;
- $path = $auth . $path;
- $path =~ s,^\\([a-zA-Z])[:|],\u$1:,;
-
- return $path;
-}
-
-sub fix_path { 1; }
-
-1;
diff --git a/lib/URI/ftp.pm b/lib/URI/ftp.pm
deleted file mode 100644
index 89aeb07..0000000
--- a/lib/URI/ftp.pm
+++ /dev/null
@@ -1,45 +0,0 @@
-package URI::ftp;
-
-require URI::_server;
-require URI::_userpass;
-@ISA=qw(URI::_server URI::_userpass);
-
-use strict;
-
-sub default_port { 21 }
-
-sub path { shift->path_query(@_) } # XXX
-
-sub _user { shift->SUPER::user(@_); }
-sub _password { shift->SUPER::password(@_); }
-
-sub user
-{
- my $self = shift;
- my $user = $self->_user(@_);
- $user = "anonymous" unless defined $user;
- $user;
-}
-
-sub password
-{
- my $self = shift;
- my $pass = $self->_password(@_);
- unless (defined $pass) {
- my $user = $self->user;
- if ($user eq 'anonymous' || $user eq 'ftp') {
- # anonymous ftp login password
- # If there is no ftp anonymous password specified
- # then we'll just use 'anonymous@'
- # We don't try to send the read e-mail address because:
- # - We want to remain anonymous
- # - We want to stop SPAM
- # - We don't want to let ftp sites to discriminate by the user,
- # host, country or ftp client being used.
- $pass = 'anonymous@';
- }
- }
- $pass;
-}
-
-1;
diff --git a/lib/URI/gopher.pm b/lib/URI/gopher.pm
deleted file mode 100644
index ae66904..0000000
--- a/lib/URI/gopher.pm
+++ /dev/null
@@ -1,94 +0,0 @@
-package URI::gopher; # <draft-murali-url-gopher>, Dec 4, 1996
-
-require URI::_server;
-@ISA=qw(URI::_server);
-
-use strict;
-use URI::Escape qw(uri_unescape);
-
-# A Gopher URL follows the common internet scheme syntax as defined in
-# section 4.3 of [RFC-URL-SYNTAX]:
-#
-# gopher://<host>[:<port>]/<gopher-path>
-#
-# where
-#
-# <gopher-path> := <gopher-type><selector> |
-# <gopher-type><selector>%09<search> |
-# <gopher-type><selector>%09<search>%09<gopher+_string>
-#
-# <gopher-type> := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7'
-# '8' | '9' | '+' | 'I' | 'g' | 'T'
-#
-# <selector> := *pchar Refer to RFC 1808 [4]
-# <search> := *pchar
-# <gopher+_string> := *uchar Refer to RFC 1738 [3]
-#
-# If the optional port is omitted, the port defaults to 70.
-
-sub default_port { 70 }
-
-sub _gopher_type
-{
- my $self = shift;
- my $path = $self->path_query;
- $path =~ s,^/,,;
- my $gtype = $1 if $path =~ s/^(.)//s;
- if (@_) {
- my $new_type = shift;
- if (defined($new_type)) {
- Carp::croak("Bad gopher type '$new_type'")
- unless length($new_type) == 1;
- substr($path, 0, 0) = $new_type;
- $self->path_query($path);
- } else {
- Carp::croak("Can't delete gopher type when selector is present")
- if length($path);
- $self->path_query(undef);
- }
- }
- return $gtype;
-}
-
-sub gopher_type
-{
- my $self = shift;
- my $gtype = $self->_gopher_type(@_);
- $gtype = "1" unless defined $gtype;
- $gtype;
-}
-
-*gtype = \&gopher_type; # URI::URL compatibility
-
-sub selector { shift->_gfield(0, @_) }
-sub search { shift->_gfield(1, @_) }
-sub string { shift->_gfield(2, @_) }
-
-sub _gfield
-{
- my $self = shift;
- my $fno = shift;
- my $path = $self->path_query;
-
- # not according to spec., but many popular browsers accept
- # gopher URLs with a '?' before the search string.
- $path =~ s/\?/\t/;
- $path = uri_unescape($path);
- $path =~ s,^/,,;
- my $gtype = $1 if $path =~ s,^(.),,s;
- my @path = split(/\t/, $path, 3);
- if (@_) {
- # modify
- my $new = shift;
- $path[$fno] = $new;
- pop(@path) while @path && !defined($path[-1]);
- for (@path) { $_="" unless defined }
- $path = $gtype;
- $path = "1" unless defined $path;
- $path .= join("\t", @path);
- $self->path_query($path);
- }
- $path[$fno];
-}
-
-1;
diff --git a/lib/URI/http.pm b/lib/URI/http.pm
deleted file mode 100644
index cb69822..0000000
--- a/lib/URI/http.pm
+++ /dev/null
@@ -1,25 +0,0 @@
-package URI::http;
-
-require URI::_server;
-@ISA=qw(URI::_server);
-
-use strict;
-
-sub default_port { 80 }
-
-sub canonical
-{
- my $self = shift;
- my $other = $self->SUPER::canonical;
-
- my $slash_path = defined($other->authority) &&
- !length($other->path) && !defined($other->query);
-
- if ($slash_path) {
- $other = $other->clone if $other == $self;
- $other->path("/");
- }
- $other;
-}
-
-1;
diff --git a/lib/URI/https.pm b/lib/URI/https.pm
deleted file mode 100644
index c39c67b..0000000
--- a/lib/URI/https.pm
+++ /dev/null
@@ -1,7 +0,0 @@
-package URI::https;
-require URI::http;
-@ISA=qw(URI::http);
-
-sub default_port { 443 }
-
-1;
diff --git a/lib/URI/ldap.pm b/lib/URI/ldap.pm
deleted file mode 100644
index 8af504b..0000000
--- a/lib/URI/ldap.pm
+++ /dev/null
@@ -1,122 +0,0 @@
-# Copyright (c) 1998 Graham Barr <gbarr@pobox.com>. All rights reserved.
-# This program is free software; you can redistribute it and/or
-# modify it under the same terms as Perl itself.
-
-package URI::ldap;
-
-use strict;
-
-use vars qw(@ISA $VERSION);
-$VERSION = "1.11";
-
-require URI::_server;
-require URI::_ldap;
-@ISA=qw(URI::_ldap URI::_server);
-
-sub default_port { 389 }
-
-sub _nonldap_canonical {
- my $self = shift;
- $self->URI::_server::canonical(@_);
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-URI::ldap - LDAP Uniform Resource Locators
-
-=head1 SYNOPSIS
-
- use URI;
-
- $uri = URI->new("ldap:$uri_string");
- $dn = $uri->dn;
- $filter = $uri->filter;
- @attr = $uri->attributes;
- $scope = $uri->scope;
- %extn = $uri->extensions;
-
- $uri = URI->new("ldap:"); # start empty
- $uri->host("ldap.itd.umich.edu");
- $uri->dn("o=University of Michigan,c=US");
- $uri->attributes(qw(postalAddress));
- $uri->scope('sub');
- $uri->filter('(cn=Babs Jensen)');
- print $uri->as_string,"\n";
-
-=head1 DESCRIPTION
-
-C<URI::ldap> provides an interface to parse an LDAP URI into its
-constituent parts and also to build a URI as described in
-RFC 2255.
-
-=head1 METHODS
-
-C<URI::ldap> supports all the generic and server methods defined by
-L<URI>, plus the following.
-
-Each of the following methods can be used to set or get the value in
-the URI. The values are passed in unescaped form. None of these
-return undefined values, but elements without a default can be empty.
-If arguments are given, then a new value is set for the given part
-of the URI.
-
-=over 4
-
-=item $uri->dn( [$new_dn] )
-
-Sets or gets the I<Distinguished Name> part of the URI. The DN
-identifies the base object of the LDAP search.
-
-=item $uri->attributes( [@new_attrs] )
-
-Sets or gets the list of attribute names which are
-returned by the search.
-
-=item $uri->scope( [$new_scope] )
-
-Sets or gets the scope to be used by the search. The value can be one of
-C<"base">, C<"one"> or C<"sub">. If none is given in the URI then the
-return value defaults to C<"base">.
-
-=item $uri->_scope( [$new_scope] )
-
-Same as scope(), but does not default to anything.
-
-=item $uri->filter( [$new_filter] )
-
-Sets or gets the filter to be used by the search. If none is given in
-the URI then the return value defaults to C<"(objectClass=*)">.
-
-=item $uri->_filter( [$new_filter] )
-
-Same as filter(), but does not default to anything.
-
-=item $uri->extensions( [$etype => $evalue,...] )
-
-Sets or gets the extensions used for the search. The list passed should
-be in the form etype1 => evalue1, etype2 => evalue2,... This is also
-the form of list that is returned.
-
-=back
-
-=head1 SEE ALSO
-
-L<RFC-2255|http://www.cis.ohio-state.edu/htbin/rfc/rfc2255.html>
-
-=head1 AUTHOR
-
-Graham Barr E<lt>F<gbarr@pobox.com>E<gt>
-
-Slightly modified by Gisle Aas to fit into the URI distribution.
-
-=head1 COPYRIGHT
-
-Copyright (c) 1998 Graham Barr. All rights reserved. This program is
-free software; you can redistribute it and/or modify it under the same
-terms as Perl itself.
-
-=cut
diff --git a/lib/URI/ldapi.pm b/lib/URI/ldapi.pm
deleted file mode 100644
index d92b13f..0000000
--- a/lib/URI/ldapi.pm
+++ /dev/null
@@ -1,30 +0,0 @@
-package URI::ldapi;
-
-use strict;
-
-use vars qw(@ISA);
-
-require URI::_generic;
-require URI::_ldap;
-@ISA=qw(URI::_ldap URI::_generic);
-
-require URI::Escape;
-
-sub un_path {
- my $self = shift;
- my $old = URI::Escape::uri_unescape($self->authority);
- if (@_) {
- my $p = shift;
- $p =~ s/:/%3A/g;
- $p =~ s/\@/%40/g;
- $self->authority($p);
- }
- return $old;
-}
-
-sub _nonldap_canonical {
- my $self = shift;
- $self->URI::_generic::canonical(@_);
-}
-
-1;
diff --git a/lib/URI/ldaps.pm b/lib/URI/ldaps.pm
deleted file mode 100644
index 20180d5..0000000
--- a/lib/URI/ldaps.pm
+++ /dev/null
@@ -1,7 +0,0 @@
-package URI::ldaps;
-require URI::ldap;
-@ISA=qw(URI::ldap);
-
-sub default_port { 636 }
-
-1;
diff --git a/lib/URI/mailto.pm b/lib/URI/mailto.pm
deleted file mode 100644
index 1408fc6..0000000
--- a/lib/URI/mailto.pm
+++ /dev/null
@@ -1,72 +0,0 @@
-package URI::mailto; # RFC 2368
-
-require URI;
-require URI::_query;
-@ISA=qw(URI URI::_query);
-
-use strict;
-
-sub to
-{
- my $self = shift;
- my @old = $self->headers;
- if (@_) {
- my @new = @old;
- # get rid of any other to: fields
- for (my $i = 0; $i < @new; $i += 2) {
- if (lc($new[$i]) eq "to") {
- splice(@new, $i, 2);
- redo;
- }
- }
-
- my $to = shift;
- $to = "" unless defined $to;
- unshift(@new, "to" => $to);
- $self->headers(@new);
- }
- return unless defined wantarray;
-
- my @to;
- while (@old) {
- my $h = shift @old;
- my $v = shift @old;
- push(@to, $v) if lc($h) eq "to";
- }
- join(",", @to);
-}
-
-
-sub headers
-{
- my $self = shift;
-
- # The trick is to just treat everything as the query string...
- my $opaque = "to=" . $self->opaque;
- $opaque =~ s/\?/&/;
-
- if (@_) {
- my @new = @_;
-
- # strip out any "to" fields
- my @to;
- for (my $i=0; $i < @new; $i += 2) {
- if (lc($new[$i]) eq "to") {
- push(@to, (splice(@new, $i, 2))[1]); # remove header
- redo;
- }
- }
-
- my $new = join(",",@to);
- $new =~ s/%/%25/g;
- $new =~ s/\?/%3F/g;
- $self->opaque($new);
- $self->query_form(@new) if @new;
- }
- return unless defined wantarray;
-
- # I am lazy today...
- URI->new("mailto:?$opaque")->query_form;
-}
-
-1;
diff --git a/lib/URI/mms.pm b/lib/URI/mms.pm
deleted file mode 100644
index 2f1015b..0000000
--- a/lib/URI/mms.pm
+++ /dev/null
@@ -1,8 +0,0 @@
-package URI::mms;
-
-require URI::http;
-@ISA=qw(URI::http);
-
-sub default_port { 1755 }
-
-1;
diff --git a/lib/URI/news.pm b/lib/URI/news.pm
deleted file mode 100644
index 1ffb419..0000000
--- a/lib/URI/news.pm
+++ /dev/null
@@ -1,68 +0,0 @@
-package URI::news; # draft-gilman-news-url-01
-
-require URI::_server;
-@ISA=qw(URI::_server);
-
-use strict;
-use URI::Escape qw(uri_unescape);
-use Carp ();
-
-sub default_port { 119 }
-
-# newsURL = scheme ":" [ news-server ] [ refbygroup | message ]
-# scheme = "news" | "snews" | "nntp"
-# news-server = "//" server "/"
-# refbygroup = group [ "/" messageno [ "-" messageno ] ]
-# message = local-part "@" domain
-
-sub _group
-{
- my $self = shift;
- my $old = $self->path;
- if (@_) {
- my($group,$from,$to) = @_;
- if ($group =~ /\@/) {
- $group =~ s/^<(.*)>$/$1/; # "<" and ">" should not be part of it
- }
- $group =~ s,%,%25,g;
- $group =~ s,/,%2F,g;
- my $path = $group;
- if (defined $from) {
- $path .= "/$from";
- $path .= "-$to" if defined $to;
- }
- $self->path($path);
- }
-
- $old =~ s,^/,,;
- if ($old !~ /\@/ && $old =~ s,/(.*),, && wantarray) {
- my $extra = $1;
- return (uri_unescape($old), split(/-/, $extra));
- }
- uri_unescape($old);
-}
-
-
-sub group
-{
- my $self = shift;
- if (@_) {
- Carp::croak("Group name can't contain '\@'") if $_[0] =~ /\@/;
- }
- my @old = $self->_group(@_);
- return if $old[0] =~ /\@/;
- wantarray ? @old : $old[0];
-}
-
-sub message
-{
- my $self = shift;
- if (@_) {
- Carp::croak("Message must contain '\@'") unless $_[0] =~ /\@/;
- }
- my $old = $self->_group(@_);
- return unless $old =~ /\@/;
- return $old;
-}
-
-1;
diff --git a/lib/URI/nntp.pm b/lib/URI/nntp.pm
deleted file mode 100644
index af61e03..0000000
--- a/lib/URI/nntp.pm
+++ /dev/null
@@ -1,6 +0,0 @@
-package URI::nntp; # draft-gilman-news-url-01
-
-require URI::news;
-@ISA=qw(URI::news);
-
-1;
diff --git a/lib/URI/pop.pm b/lib/URI/pop.pm
deleted file mode 100644
index 50b8d6d..0000000
--- a/lib/URI/pop.pm
+++ /dev/null
@@ -1,68 +0,0 @@
-package URI::pop; # RFC 2384
-
-require URI::_server;
-@ISA=qw(URI::_server);
-
-use strict;
-use URI::Escape qw(uri_unescape);
-
-sub default_port { 110 }
-
-#pop://<user>;auth=<auth>@<host>:<port>
-
-sub user
-{
- my $self = shift;
- my $old = $self->userinfo;
-
- if (@_) {
- my $new_info = $old;
- $new_info = "" unless defined $new_info;
- $new_info =~ s/^[^;]*//;
-
- my $new = shift;
- if (!defined($new) && !length($new_info)) {
- $self->userinfo(undef);
- } else {
- $new = "" unless defined $new;
- $new =~ s/%/%25/g;
- $new =~ s/;/%3B/g;
- $self->userinfo("$new$new_info");
- }
- }
-
- return unless defined $old;
- $old =~ s/;.*//;
- return uri_unescape($old);
-}
-
-sub auth
-{
- my $self = shift;
- my $old = $self->userinfo;
-
- if (@_) {
- my $new = $old;
- $new = "" unless defined $new;
- $new =~ s/(^[^;]*)//;
- my $user = $1;
- $new =~ s/;auth=[^;]*//i;
-
-
- my $auth = shift;
- if (defined $auth) {
- $auth =~ s/%/%25/g;
- $auth =~ s/;/%3B/g;
- $new = ";AUTH=$auth$new";
- }
- $self->userinfo("$user$new");
-
- }
-
- return unless defined $old;
- $old =~ s/^[^;]*//;
- return uri_unescape($1) if $old =~ /;auth=(.*)/i;
- return;
-}
-
-1;
diff --git a/lib/URI/rlogin.pm b/lib/URI/rlogin.pm
deleted file mode 100644
index 18bb762..0000000
--- a/lib/URI/rlogin.pm
+++ /dev/null
@@ -1,7 +0,0 @@
-package URI::rlogin;
-require URI::_login;
-@ISA = qw(URI::_login);
-
-sub default_port { 513 }
-
-1;
diff --git a/lib/URI/rsync.pm b/lib/URI/rsync.pm
deleted file mode 100644
index 160d9d0..0000000
--- a/lib/URI/rsync.pm
+++ /dev/null
@@ -1,12 +0,0 @@
-package URI::rsync; # http://rsync.samba.org/
-
-# rsync://[USER@]HOST[:PORT]/SRC
-
-require URI::_server;
-require URI::_userpass;
-
-@ISA=qw(URI::_server URI::_userpass);
-
-sub default_port { 873 }
-
-1;
diff --git a/lib/URI/rtsp.pm b/lib/URI/rtsp.pm
deleted file mode 100644
index 982ca5e..0000000
--- a/lib/URI/rtsp.pm
+++ /dev/null
@@ -1,8 +0,0 @@
-package URI::rtsp;
-
-require URI::http;
-@ISA=qw(URI::http);
-
-sub default_port { 554 }
-
-1;
diff --git a/lib/URI/rtspu.pm b/lib/URI/rtspu.pm
deleted file mode 100644
index dbcf12b..0000000
--- a/lib/URI/rtspu.pm
+++ /dev/null
@@ -1,8 +0,0 @@
-package URI::rtspu;
-
-require URI::rtsp;
-@ISA=qw(URI::rtsp);
-
-sub default_port { 554 }
-
-1;
diff --git a/lib/URI/sip.pm b/lib/URI/sip.pm
deleted file mode 100644
index fae5d8e..0000000
--- a/lib/URI/sip.pm
+++ /dev/null
@@ -1,86 +0,0 @@
-#
-# Written by Ryan Kereliuk <ryker@ryker.org>. This file may be
-# distributed under the same terms as Perl itself.
-#
-# The RFC 3261 sip URI is <scheme>:<authority>;<params>?<query>.
-#
-
-package URI::sip;
-
-require URI::_server;
-require URI::_userpass;
-@ISA=qw(URI::_server URI::_userpass);
-
-use strict;
-use vars qw(@ISA $VERSION);
-use URI::Escape qw(uri_unescape);
-
-$VERSION = "0.10";
-
-sub default_port { 5060 }
-
-sub authority
-{
- my $self = shift;
- $$self =~ m,^($URI::scheme_re:)?([^;?]*)(.*)$,os or die;
- my $old = $2;
-
- if (@_) {
- my $auth = shift;
- $$self = defined($1) ? $1 : "";
- my $rest = $3;
- if (defined $auth) {
- $auth =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
- $$self .= "$auth";
- }
- $$self .= $rest;
- }
- $old;
-}
-
-sub params_form
-{
- my $self = shift;
- $$self =~ m,^((?:$URI::scheme_re:)?)(?:([^;?]*))?(;[^?]*)?(.*)$,os or die;
- my $paramstr = $3;
-
- if (@_) {
- my @args = @_;
- $$self = $1 . $2;
- my $rest = $4;
- my @new;
- for (my $i=0; $i < @args; $i += 2) {
- push(@new, "$args[$i]=$args[$i+1]");
- }
- $paramstr = join(";", @new);
- $$self .= ";" . $paramstr . $rest;
- }
- $paramstr =~ s/^;//o;
- return split(/[;=]/, $paramstr);
-}
-
-sub params
-{
- my $self = shift;
- $$self =~ m,^((?:$URI::scheme_re:)?)(?:([^;?]*))?(;[^?]*)?(.*)$,os or die;
- my $paramstr = $3;
-
- if (@_) {
- my $new = shift;
- $$self = $1 . $2;
- my $rest = $4;
- $$self .= $paramstr . $rest;
- }
- $paramstr =~ s/^;//o;
- return $paramstr;
-}
-
-# Inherited methods that make no sense for a SIP URI.
-sub path {}
-sub path_query {}
-sub path_segments {}
-sub abs { shift }
-sub rel { shift }
-sub query_keywords {}
-
-1;
diff --git a/lib/URI/sips.pm b/lib/URI/sips.pm
deleted file mode 100644
index b32e105..0000000
--- a/lib/URI/sips.pm
+++ /dev/null
@@ -1,7 +0,0 @@
-package URI::sips;
-require URI::sip;
-@ISA=qw(URI::sip);
-
-sub default_port { 5061 }
-
-1;
diff --git a/lib/URI/snews.pm b/lib/URI/snews.pm
deleted file mode 100644
index 7e5b037..0000000
--- a/lib/URI/snews.pm
+++ /dev/null
@@ -1,8 +0,0 @@
-package URI::snews; # draft-gilman-news-url-01
-
-require URI::news;
-@ISA=qw(URI::news);
-
-sub default_port { 563 }
-
-1;
diff --git a/lib/URI/ssh.pm b/lib/URI/ssh.pm
deleted file mode 100644
index 5cd30fc..0000000
--- a/lib/URI/ssh.pm
+++ /dev/null
@@ -1,9 +0,0 @@
-package URI::ssh;
-require URI::_login;
-@ISA=qw(URI::_login);
-
-# ssh://[USER@]HOST[:PORT]/SRC
-
-sub default_port { 22 }
-
-1;
diff --git a/lib/URI/telnet.pm b/lib/URI/telnet.pm
deleted file mode 100644
index 5f842d3..0000000
--- a/lib/URI/telnet.pm
+++ /dev/null
@@ -1,7 +0,0 @@
-package URI::telnet;
-require URI::_login;
-@ISA = qw(URI::_login);
-
-sub default_port { 23 }
-
-1;
diff --git a/lib/URI/tn3270.pm b/lib/URI/tn3270.pm
deleted file mode 100644
index dd1e648..0000000
--- a/lib/URI/tn3270.pm
+++ /dev/null
@@ -1,7 +0,0 @@
-package URI::tn3270;
-require URI::_login;
-@ISA = qw(URI::_login);
-
-sub default_port { 23 }
-
-1;
diff --git a/lib/URI/urn.pm b/lib/URI/urn.pm
deleted file mode 100644
index 12d40b2..0000000
--- a/lib/URI/urn.pm
+++ /dev/null
@@ -1,97 +0,0 @@
-package URI::urn; # RFC 2141
-
-require URI;
-@ISA=qw(URI);
-
-use strict;
-use Carp qw(carp);
-
-use vars qw(%implementor);
-
-sub _init {
- my $class = shift;
- my $self = $class->SUPER::_init(@_);
- my $nid = $self->nid;
-
- my $impclass = $implementor{$nid};
- return $impclass->_urn_init($self, $nid) if $impclass;
-
- $impclass = "URI::urn";
- if ($nid =~ /^[A-Za-z\d][A-Za-z\d\-]*\z/) {
- my $id = $nid;
- # make it a legal perl identifier
- $id =~ s/-/_/g;
- $id = "_$id" if $id =~ /^\d/;
-
- $impclass = "URI::urn::$id";
- no strict 'refs';
- unless (@{"${impclass}::ISA"}) {
- # Try to load it
- eval "require $impclass";
- die $@ if $@ && $@ !~ /Can\'t locate.*in \@INC/;
- $impclass = "URI::urn" unless @{"${impclass}::ISA"};
- }
- }
- else {
- carp("Illegal namespace identifier '$nid' for URN '$self'") if $^W;
- }
- $implementor{$nid} = $impclass;
-
- return $impclass->_urn_init($self, $nid);
-}
-
-sub _urn_init {
- my($class, $self, $nid) = @_;
- bless $self, $class;
-}
-
-sub _nid {
- my $self = shift;
- my $opaque = $self->opaque;
- if (@_) {
- my $v = $opaque;
- my $new = shift;
- $v =~ s/[^:]*/$new/;
- $self->opaque($v);
- # XXX possible rebless
- }
- $opaque =~ s/:.*//s;
- return $opaque;
-}
-
-sub nid { # namespace identifier
- my $self = shift;
- my $nid = $self->_nid(@_);
- $nid = lc($nid) if defined($nid);
- return $nid;
-}
-
-sub nss { # namespace specific string
- my $self = shift;
- my $opaque = $self->opaque;
- if (@_) {
- my $v = $opaque;
- my $new = shift;
- if (defined $new) {
- $v =~ s/(:|\z).*/:$new/;
- }
- else {
- $v =~ s/:.*//s;
- }
- $self->opaque($v);
- }
- return undef unless $opaque =~ s/^[^:]*://;
- return $opaque;
-}
-
-sub canonical {
- my $self = shift;
- my $nid = $self->_nid;
- my $new = $self->SUPER::canonical;
- return $new if $nid !~ /[A-Z]/ || $nid =~ /%/;
- $new = $new->clone if $new == $self;
- $new->nid(lc($nid));
- return $new;
-}
-
-1;
diff --git a/lib/URI/urn/isbn.pm b/lib/URI/urn/isbn.pm
deleted file mode 100644
index 622b56c..0000000
--- a/lib/URI/urn/isbn.pm
+++ /dev/null
@@ -1,58 +0,0 @@
-package URI::urn::isbn; # RFC 3187
-
-require URI::urn;
-@ISA=qw(URI::urn);
-
-use strict;
-use Business::ISBN ();
-
-
-sub _isbn {
- my $nss = shift;
- $nss = $nss->nss if ref($nss);
- my $isbn = Business::ISBN->new($nss);
- $isbn = undef if $isbn && !$isbn->is_valid;
- return $isbn;
-}
-
-sub _nss_isbn {
- my $self = shift;
- my $nss = $self->nss(@_);
- my $isbn = _isbn($nss);
- $isbn = $isbn->as_string if $isbn;
- return($nss, $isbn);
-}
-
-sub isbn {
- my $self = shift;
- my $isbn;
- (undef, $isbn) = $self->_nss_isbn(@_);
- return $isbn;
-}
-
-sub isbn_publisher_code {
- my $isbn = shift->_isbn || return undef;
- return $isbn->publisher_code;
-}
-
-sub isbn_country_code {
- my $isbn = shift->_isbn || return undef;
- return $isbn->country_code;
-}
-
-sub isbn_as_ean {
- my $isbn = shift->_isbn || return undef;
- return $isbn->as_ean;
-}
-
-sub canonical {
- my $self = shift;
- my($nss, $isbn) = $self->_nss_isbn;
- my $new = $self->SUPER::canonical;
- return $new unless $nss && $isbn && $nss ne $isbn;
- $new = $new->clone if $new == $self;
- $new->nss($isbn);
- return $new;
-}
-
-1;
diff --git a/lib/URI/urn/oid.pm b/lib/URI/urn/oid.pm
deleted file mode 100644
index 301b2bc..0000000
--- a/lib/URI/urn/oid.pm
+++ /dev/null
@@ -1,18 +0,0 @@
-package URI::urn::oid; # RFC 2061
-
-require URI::urn;
-@ISA=qw(URI::urn);
-
-use strict;
-
-sub oid {
- my $self = shift;
- my $old = $self->nss;
- if (@_) {
- $self->nss(join(".", @_));
- }
- return split(/\./, $old) if wantarray;
- return $old;
-}
-
-1;
diff --git a/lib/XML/Dumper.pm b/lib/XML/Dumper.pm
deleted file mode 100644
index 2d9f740..0000000
--- a/lib/XML/Dumper.pm
+++ /dev/null
@@ -1,897 +0,0 @@
-# ============================================================
-# XML::
-# ____
-# | _ \ _ _ _ __ ___ _ __ ___ _ __
-# | | | | | | | '_ ` _ \| '_ \ / _ \ '__|
-# | |_| | |_| | | | | | | |_) | __/ |
-# |____/ \__,_|_| |_| |_| .__/ \___|_|
-# |_|
-# Perl module for dumping Perl objects from/to XML
-# ============================================================
-
-=head1 NAME
-
-XML::Dumper - Perl module for dumping Perl objects from/to XML
-
-=head1 SYNOPSIS
-
- # ===== OO-way
- use XML::Dumper;
- $dump = new XML::Dumper;
-
- $xml = $dump->pl2xml( $perl );
- $perl = $dump->xml2pl( $xml );
- $dump->pl2xml( $perl, "my_perl_data.xml.gz" );
-
- # ===== Functional way
- use XML::Dumper;
-
- $xml = pl2xml( $perl );
- $perl = xml2pl( $xml );
-
-=head1 EXTENDED SYNOPSIS
-
- use XML::Dumper;
- my $dump = new XML::Dumper;
-
- my $perl = '';
- my $xml = '';
-
- # ===== Convert Perl code to XML
- $perl = [
- {
- fname => 'Fred',
- lname => 'Flintstone',
- residence => 'Bedrock'
- },
- {
- fname => 'Barney',
- lname => 'Rubble',
- residence => 'Bedrock'
- }
- ];
- $xml = $dump->pl2xml( $perl );
-
- # ===== Dump to a file
- my $file = "dump.xml";
- $dump->pl2xml( $perl, $file );
-
- # ===== Convert XML to Perl code
- $xml = q|
- <perldata>
- <arrayref>
- <item key="0">
- <hashref>
- <item key="fname">Fred</item>
- <item key="lname">Flintstone</item>
- <item key="residence">Bedrock</item>
- </hashref>
- </item>
- <item key="1">
- <hashref>
- <item key="fname">Barney</item>
- <item key="lname">Rubble</item>
- <item key="residence">Bedrock</item>
- </hashref>
- </item>
- </arrayref>
- </perldata>
- |;
-
- my $perl = $dump->xml2pl( $xml );
-
- # ===== Convert an XML file to Perl code
- my $perl = $dump->xml2pl( $file );
-
- # ===== And serialize Perl code to an XML file
- $dump->pl2xml( $perl, $file );
-
- # ===== USE COMPRESSION
- $dump->pl2xml( $perl, $file.".gz" );
-
- # ===== INCLUDE AN IN-DOCUMENT DTD
- $dump->dtd;
- my $xml_with_dtd = $dump->pl2xml( $perl );
-
- # ===== USE EXTERNAL DTD
- $dump->dtd( $file, $url );
- my $xml_with_link_to_dtd = $dump->pl2xml( $perl );
-
-=head1 DESCRIPTION
-
-XML::Dumper dumps Perl data to XML format. XML::Dumper can also read XML data
-that was previously dumped by the module and convert it back to Perl. You can
-use the module read the XML from a file and write the XML to a file. Perl
-objects are blessed back to their original packaging; if the modules are
-installed on the system where the perl objects are reconstituted from xml, they
-will behave as expected. Intuitively, if the perl objects are converted and
-reconstituted in the same environment, all should be well. And it is.
-
-Additionally, because XML benefits so nicely from compression, XML::Dumper
-understands gzipped XML files. It does so with an optional dependency on
-Compress::Zlib. So, if you dump a Perl variable with a file that has an
-extension of '.xml.gz', it will store and compress the file in gzipped format.
-Likewise, if you read a file with the extension '.xml.gz', it will uncompress
-the file in memory before parsing the XML back into a Perl variable.
-
-Another fine challenge that this module rises to meet is that it understands
-circular definitions and multiple references to a single object. This includes
-doubly-linked lists, circular references, and the so-called 'Flyweight' pattern of
-Object Oriented programming. So it can take the gnarliest of your perl data, and
-should do just fine.
-
-=head2 FUNCTIONS AND METHODS
-
-=over 4
-
-=cut
-
-package XML::Dumper;
-
-require 5.005_62;
-use strict;
-use warnings;
-
-require Exporter;
-use XML::Parser;
-use overload;
-
-our @ISA = qw( Exporter );
-our %EXPORT_TAGS = ( );
-our @EXPORT_OK = ( );
-our @EXPORT = qw( xml2pl pl2xml xml_compare xml_identity );
-our $VERSION = '0.79';
-
-our $COMPRESSION_AVAILABLE;
-
-BEGIN {
- eval { require Compress::Zlib; };
- if( $@ ) {
- $COMPRESSION_AVAILABLE = 0;
- } else {
- $COMPRESSION_AVAILABLE = 1;
- }
-}
-
-our $dump = new XML::Dumper;
-
-# ============================================================
-sub new {
-# ============================================================
-
-=item * new() - XML::Dumper constructor.
-
-Creates a lean, mean, XML dumping machine. It's also completely
-at your disposal.
-
-=cut
-
-# ------------------------------------------------------------
- my ($class) = map { ref || $_ } shift;
- my $self = bless {}, $class;
-
- $self->init;
-
- return $self;
-}
-
-# ============================================================
-sub init {
-# ============================================================
- my $self = shift;
- $self->{ perldata } = {};
- $self->{ xml } = {};
- 1;
-}
-
-# ============================================================
-sub dtd {
-# ============================================================
-
-=item * dtd -
-
-Generates a Document Type Dictionary for the 'perldata' data
-type. The default behaviour is to embed the DTD in the XML,
-thereby creating valid XML. Given a filename, the DTD will be
-written out to that file and the XML document for your Perl data
-will link to the file. Given a filename and an URL, the DTD will
-be written out the file and the XML document will link to the URL.
-XML::Dumper doesn't try really hard to determine where your DTD's
-ought to go or relative paths or anything, so be careful with
-what arguments you supply this method, or just go with the default
-with the embedded DTD. Between DTD's and Schemas, the potential
-for more free-form data to be imported and exported becomes
-feasible.
-
-Usage:
-
- dtd(); # Causes XML to include embedded DTD
- dtd( $file ); # DTD saved to $file; XML will link to $file
- dtd( $file, $url ); # DTD saved to $file; XML will link to $url
- dtd( 0 ); # Prevents XML from including embedded DTD
-
-=cut
-
-# ------------------------------------------------------------
- my $self = ( ref $_[0] && (ref $_[0]) =~ /XML::Dumper/ ) ? shift : $dump;
- my $file = shift;
- my $url = shift;
-
- my $dtd = qq{<!ELEMENT scalar (#PCDATA)>
-<!ELEMENT scalarref (#PCDATA)>
-<!ATTLIST scalarref
- blessed_package CDATA #IMPLIED
- memory_address CDATA #IMPLIED>
-<!ELEMENT arrayref (item*)>
-<!ATTLIST arrayref
- blessed_package CDATA #IMPLIED
- memory_address CDATA #IMPLIED>
-<!ELEMENT hashref (item*)>
-<!ATTLIST hashref
- blessed_package CDATA #IMPLIED
- memory_address CDATA #IMPLIED>
-<!ELEMENT item (#PCDATA|scalar|scalarref|arrayref|hashref)*>
-<!ATTLIST item
- key CDATA #REQUIRED
- defined CDATA #IMPLIED>
-<!ELEMENT perldata (scalar|scalarref|arrayref|hashref)*>
-};
-
- if( defined $file && $file ) {
- open DTD, ">$file" or die $!;
- print DTD $dtd;
- close DTD;
- $url = defined $url ? $url : $file;
- $self->{ dtd } = qq{
-<!DOCTYPE perldata SYSTEM "$url">
-};
- } elsif( not defined $file ) {
- $self->{ dtd } = join( "\n",
- "<?xml version=\"1.0\"?>",
- "<!DOCTYPE perldata [",
- ( map { /^\t/ ? $_ : " $_" } split /\n/, $dtd ),
- ']>',
- '');
- } else {
- delete $self->{ dtd };
- return;
- }
-
- $self->{ dtd };
-}
-
-# ============================================================
-sub dump {
-# ============================================================
- my $self = shift;
- my $ref = shift;
- my $indent = shift;
-
- my $string = '';
-
- # ===== HANDLE REFERENCE DUMPING
- if( ref $ref ) {
- no warnings;
- local $_ = ref( $ref );
- my $class = '';
- my $address = '';
- my $reused = '';
-
- # ===== HANDLE THE VARIETY OF THINGS A PERL REFERENCE CAN REFER TO
- REFERENCE: {
- # ----------------------------------------
- OBJECT: {
- # ----------------------------------------
- last OBJECT if /^(?:SCALAR|HASH|ARRAY)$/;
- $class = $_;
- $class = xml_escape( $class );
- ($_,$address) = overload::StrVal( $ref ) =~ /$class=([^(]+)\(([x0-9A-Fa-f]+)\)/;
- }
-
- # ----------------------------------------
- HAS_MEMORY_ADDRESS: {
- # ----------------------------------------
- # References which refer to the same memory space point to the
- # same thing
- last HAS_MEMORY_ADDRESS if( $class );
- ($_,$address) = overload::StrVal( $ref ) =~ /([^(]+)\(([x0-9A-Fa-f]+)\)/;
- }
-
- $reused = exists( $self->{ xml }{ $address } );
-
- # ----------------------------------------
- if( /^SCALAR$/ ) {
- # ----------------------------------------
- my $type =
- "<scalarref".
- ($class ? " blessed_package=\"$class\"" : '' ) .
- ($address ? " memory_address=\"$address\"" : '' ) .
- ( defined $$ref ? '' : " defined=\"false\"" ) .
- ">";
- $self->{ xml }{ $address }++ if( $address );
- $string = "\n" . " " x $indent . $type . ($reused ? '' : xml_escape($$ref)) . "</scalarref>";
- last REFERENCE;
- }
-
- # ----------------------------------------
- if( /^HASH$/ ) {
- # ----------------------------------------
- $self->{ xml }{ $address }++ if( $address );
- my $type =
- "<hashref".
- ($class ? " blessed_package=\"$class\"" : '' ).
- ($address && $self->{ xml }{ $address } ? " memory_address=\"$address\"" : '' ).
- ">";
- $string = "\n" . " " x $indent . $type;
- if( not $reused ) {
- $indent++;
- foreach my $key (sort keys(%$ref)) {
- my $type =
- "<item " .
- "key=\"" . xml_escape( $key ) . "\"" .
- ( defined $ref->{ $key } ? '' : " defined=\"false\"" ) .
- ">";
- $string .= "\n" . " " x $indent . $type;
- if (ref($ref->{$key})) {
- $string .= $self->dump( $ref->{$key}, $indent+1);
- $string .= "\n" . " " x $indent . "</item>";
- } else {
- $string .= xml_escape($ref->{$key}) . "</item>";
- }
- }
- $indent--;
- }
- $string .= "\n" . " " x $indent . "</hashref>";
- last REFERENCE;
- }
-
- # ----------------------------------------
- if( /^ARRAY$/ ) {
- # ----------------------------------------
- my $type =
- "<arrayref".
- ($class ? " blessed_package=\"$class\"" : '' ).
- ($address ? " memory_address=\"$address\"" : '' ).
- ">";
- $string .= "\n" . " " x $indent . $type;
- $self->{ xml }{ $address }++ if( $address );
- if( not $reused ) {
- $indent++;
- for (my $i=0; $i < @$ref; $i++) {
- my $defined;
- my $type =
- "<item " .
- "key=\"" . xml_escape( $i ) . "\"" .
- ( defined $ref->[ $i ] ? '' : " defined=\"false\"" ) .
- ">";
-
- $string .= "\n" . " " x $indent . $type;
- if (ref($ref->[$i])) {
- $string .= $self->dump($ref->[$i], $indent+1);
- $string .= "\n" . " " x $indent . "</item>";
- } else {
- $string .= xml_escape($ref->[$i]) . "</item>";
- }
- }
- $indent--;
- }
- $string .= "\n" . " " x $indent . "</arrayref>";
- last REFERENCE;
- }
-
- }
-
- # ===== HANDLE SCALAR DUMPING
- } else {
- my $type =
- "<scalar".
- ( defined $ref ? '' : " defined=\"false\"" ) .
- ">";
-
- $string .= "\n" . " " x $indent . $type . xml_escape( $ref ) . "</scalar>";
- }
-
- return( $string );
-}
-
-# ============================================================
-sub perl2xml {
-# ============================================================
- pl2xml( @_ );
-}
-
-# ============================================================
-sub pl2xml {
-# ============================================================
-
-=item * pl2xml( $xml, [ $file ] ) -
-
-(Also perl2xml(), for those who enjoy readability over brevity).
-
-Converts Perl data to XML. If a second argument is given, then the Perl data
-will be stored to disk as XML, using the second argument as a filename.
-
-Usage: See Synopsis
-
-=cut
-
-# ------------------------------------------------------------
- my $self = ( ref $_[0] && (ref $_[0]) =~ /XML::Dumper/ ) ? shift : $dump;
- my $ref = shift;
- my $file = shift;
-
- $self->init;
-
- my $xml =
- ( defined $self->{ dtd } ? $self->{ dtd } : '' ) .
- "<perldata>" . $self->dump( $ref, 1 ) . "\n</perldata>\n";
-
- if( defined $file ) {
- if( $file =~ /\.xml\.gz$/i ) {
- if( $COMPRESSION_AVAILABLE ) {
- my $compressed_xml = Compress::Zlib::memGzip( $xml ) or die "Failed to compress xml $!";
- open FILE, ">:utf8", $file or die "Can't open '$file' for writing $!";
- binmode FILE;
- print FILE $compressed_xml;
- close FILE;
-
- } else {
- my $uncompressed_file = $file;
- $uncompressed_file =~ s/\.gz$//i;
- warn "Compress::Zlib not installed. Saving '$file' as '$uncompressed_file'\n";
-
- open FILE, ">:utf8", $uncompressed_file or die "Can't open '$uncompressed_file' for writing $!";
- print FILE $xml;
- close FILE;
- }
- } else {
- no warnings; # to shut Perl up about Wide characters for UTF8 output
- open FILE, ">$file" or die "Can't open '$file' for writing $!";
- print FILE $xml;
- close FILE;
- }
- }
- return $xml;
-}
-
-# ============================================================
-sub undump {
-# ============================================================
-# undump
-# Takes the XML generated by pl2xml, and recursively undumps it to
-# create a data structure in memory. The top-level object is a scalar,
-# a reference to a scalar, a hash, or an array. Hashes and arrays may
-# themselves contain scalars, or references to scalars, or references to
-# hashes or arrays, with the exception that scalar values are never
-# "undef" because there's currently no way to represent undef in the
-# dumped data.
-#
-# The key to understanding undump is to understand XML::Parser's
-# Tree parsing format:
-#
-# <tag name>, [ { <attributes }, '0', <[text]>, <[children tag-array pair value(s)]...> ]
-# ------------------------------------------------------------
- my $self = shift;
- my $tree = shift;
- my $callback = shift;
-
- my $ref = undef;
- my $item;
-
- # make Perl stop whining about deep recursion and soft references
- no warnings;
-
- TREE: for (my $i = 1; $i < $#$tree; $i+=2) {
- local $_ = lc( $tree->[ $i ] );
- my $class = '';
- my $address = '';
-
- PERL_TYPES: {
- # ----------------------------------------
- if( /^scalar$/ ) {
- # ----------------------------------------
- $ref = defined $tree->[ $i+1 ][ 2 ] ? $tree->[ $i +1 ][ 2 ] : '';
- if( exists $tree->[ $i+1 ][ 0 ]{ 'defined' } ) {
- if( $tree->[ $i +1 ][ 0 ]{ 'defined' } =~ /false/i ) {
- $ref = undef;
- }
- }
- last TREE;
- }
-
- # ===== FIND PACKAGE
- if( $tree->[ $i+1 ] && ref( $tree->[ $i +1 ] ) eq 'ARRAY' ) {
- if( exists $tree->[ $i+1 ][0]{ blessed_package } ) {
- $class = $tree->[ $i+1 ][ 0 ]{ blessed_package };
- }
- }
-
- # ===== FIND MEMORY ADDRESS
- if( $tree->[ $i+1 ] && ref( $tree->[ $i +1 ] ) eq 'ARRAY' ) {
- if( exists $tree->[ $i+1 ][0]{ memory_address } ) {
- $address = $tree->[ $i+1 ][ 0 ]{ memory_address };
- }
- }
-
- ALREADY_EXISTS_IN_MEMORY: {
- if( exists $self->{ perldata }{ $address } ) {
- $ref = $self->{ perldata }{ $address };
- last TREE;
- }
- }
-
- # ----------------------------------------
- if( /^scalarref/ ) {
- # ----------------------------------------
- $ref = defined $tree->[ $i+1 ][ 2 ] ? \ $tree->[ $i +1 ][ 2 ] : \'';
- if( exists $tree->[ $i+1 ][ 0 ]{ 'defined' } ) {
- if( $tree->[ $i +1 ][ 0 ]{ 'defined' } =~ /false/i ) {
- $ref = \ undef;
- }
- }
-
- $self->{ perldata }{ $address } = $ref if( $address );
- if( $class ) {
- # Check class name for nasty stuff...
- $class =~ m/^[\w-]+(?:::[\w-]+)*$/
- or die "Refusing to load unsafe class name '$class'\n";
-
- unless( int( eval( "\%$class"."::")) ) {
- eval "require $class;";
- if( $@ ) {
- warn $@;
- }
- }
-
- bless $ref, $class;
- if( defined $callback && $ref->can( $callback ) ) {
- $ref->$callback();
- }
- }
- last TREE;
- }
-
- # ----------------------------------------
- if( /^hash(?:ref)?/ ) {
- # ----------------------------------------
- $ref = {};
- $self->{ perldata }{ $address } = $ref if( $address );
- for (my $j = 1; $j < $#{$tree->[$i+1]}; $j+=2) {
- next unless $tree->[$i+1][$j] eq 'item';
- my $item_tree = $tree->[$i+1][$j+1];
- if( exists $item_tree->[0]{ key } ) {
- my $key = $item_tree->[ 0 ]{ key };
- if( exists $item_tree->[ 0 ]{ 'defined' } ) {
- if( $item_tree->[ 0 ]{ 'defined' } =~ /false/ ) {
- $ref->{ $key } = undef;
- next;
- }
- }
- # ===== XML::PARSER IGNORES ZERO-LENGTH STRINGS
- # It indicates the presence of a zero-length string by
- # not having the array portion of the tag-name/array pair
- # values be of length 1. (Which is to say it captures only
- # the attributes of the tag and acknowledges that the tag
- # is an empty one.
- if( int( @{ $item_tree } ) == 1 ) {
- $ref->{ $key } = '';
- next;
- }
- $ref->{ $key } = $self->undump( $item_tree, $callback );
- }
- }
- if( $class ) {
- # Check class name for nasty stuff...
- $class =~ m/^[\w-]+(?:::[\w-]+)*$/
- or die "Refusing to load unsafe class name '$class'\n";
-
- unless( int( eval( "\%$class"."::")) ) {
- eval "require $class;";
- if( $@ ) {
- warn $@;
- }
- }
-
- bless $ref, $class;
- if( defined $callback && $ref->can( $callback ) ) {
- $ref->$callback();
- }
- }
- last TREE;
- }
-
- # ----------------------------------------
- if( /^arrayref/ ) {
- # ----------------------------------------
- $ref = [];
- $self->{ perldata }{ $address } = $ref if( $address );
- for (my $j = 1; $j < $#{$tree->[$i+1]}; $j+=2) {
- next unless $tree->[$i+1][$j] eq 'item';
- my $item_tree = $tree->[$i+1][$j+1];
- if( exists $item_tree->[0]{ key } ) {
- my $key = $item_tree->[0]{ key };
- if( exists $item_tree->[ 0 ]{ 'defined' } ) {
- if( $item_tree->[ 0 ]{ 'defined' } =~ /false/ ) {
- $ref->[ $key ] = undef;
- next;
- }
- }
- # ===== XML::PARSER IGNORES ZERO-LENGTH STRINGS
- # See note above.
- if( int( @{ $item_tree } ) == 1 ) {
- $ref->[ $key ] = '';
- next;
- }
- $ref->[ $key ] = $self->undump( $item_tree, $callback );
- }
- }
- if( $class ) {
- # Check class name for nasty stuff...
- $class =~ m/^[\w-]+(?:::[\w-]+)*$/
- or die "Refusing to load unsafe class name '$class'\n";
-
- unless( int( eval( "\%$class"."::")) ) {
- eval "require $class;";
- if( $@ ) {
- warn $@;
- }
- }
-
- bless $ref, $class;
- if( defined $callback && $ref->can( $callback ) ) {
- $ref->$callback();
- }
- }
- last TREE;
- }
-
- # ----------------------------------------
- if( /^0$/ ) { # SIMPLE SCALAR
- # ----------------------------------------
- $item = $tree->[$i + 1];
- }
- }
- }
-
- ## If $ref is not set at this point, it means we've just
- ## encountered a scalar value directly inside the item tag.
-
- $ref = $item unless defined( $ref );
-
- return ($ref);
-}
-
-# ============================================================
-sub xml_escape {
-# ============================================================
-# Transforms and filters input characters to acceptable XML characters
-# (or filters them out completely). There's probably a better
-# implementation of this in another module, by now.
-# ------------------------------------------------------------
- local $_ = shift;
- return $_ if not defined $_;
- s/&/&amp;/g;
- s/</&lt;/g;
- s/>/&gt;/g;
- s/[\0\ca\cb\cc\cd\ce\cf\cg\ch\ck\cl\cn\co\cp\cq\cr\cs\ct\cu\cv\cw\cx\cy\cz\c[\c\\c]\c^\c_]//g;
- s/'/&apos;/g;
- s/"/&quot;/g;
- return $_;
-}
-
-# ============================================================
-sub xml2perl {
-# ============================================================
- xml2pl( @_ );
-}
-
-# ============================================================
-sub xml2pl {
-# ============================================================
-
-=item * xml2pl( $xml_or_filename, [ $callback ] ) -
-
-(Also xml2perl(), for those who enjoy readability over brevity.)
-
-Converts XML to a Perl datatype. If this method is given a second argument,
-XML::Dumper will use the second argument as a callback (if possible). If
-the first argument isn't XML and exists as a file, that file will be read
-and its contents will be used as the input XML.
-
-Currently, the only supported invocation of callbacks is through soft
-references. That is to say, the callback argument ought to be a string
-that matches the name of a callable method for your classes. If you have
-a congruent interface, this should work like a peach. If your class
-interface doesn't have such a named method, it won't be called.
-
-=cut
-
-# ------------------------------------------------------------
- my $self = ( ref $_[0] && (ref $_[0]) =~ /XML::Dumper/) ? shift : $dump;
- my $xml = shift;
- my $callback = shift;
-
- $self->init;
-
- if( $xml !~ /\</ ) {
- my $file = $xml;
- if( -e $file ) {
- my $gzip_header_signature = pack "H4", "1f8b";
- my $first_two_bytes;
-
- open FILE, "<". $file or die "Can't open '$file' for reading $!";
- defined read FILE, $first_two_bytes, 2 or die "Can't read first two bytes of '$file' $!";
- close FILE;
-
- if( $first_two_bytes eq $gzip_header_signature ) {
- if( $COMPRESSION_AVAILABLE ) {
- my $gz = Compress::Zlib::gzopen( $file, "rb" );
- my @xml;
- my $buffer;
- while( $gz->gzread( $buffer ) > 0 ) {
- push @xml, $buffer;
- }
- $gz->gzclose();
- $xml = join "", @xml;
-
- } else {
- die "Compress::Zlib is not installed. Cannot read gzipped file '$file'";
- }
- } else {
-
- open FILE, $file or die "Can't open file '$file' for reading $!";
- my @xml = <FILE>;
- close FILE;
- $xml = join "", @xml;
- }
-
- } else {
- die "'$file' does not exist as a file and is not XML.\n";
- }
- }
-
- my $parser = new XML::Parser(Style => 'Tree');
- my $tree = $parser->parse($xml);
-
- # Skip enclosing "perldata" level
- my $topItem = $tree->[1];
- my $ref = $self->undump($topItem, $callback);
-
- return($ref);
-}
-
-# ============================================================
-sub xml_compare {
-# ============================================================
-
-=item * xml_compare( $xml1, $xml2 ) - Compares xml for content
-
-Compares two dumped Perl data structures (that is, compares the xml) for
-identity in content. Use this function rather than perl's built-in string
-comparison. This function will return true for any two perl data that are
-either deep clones of each other, or identical. This method is exported
-by default.
-
-=cut
-
-# ------------------------------------------------------------
- my $self = shift;
- my $xml1 = shift;
- my $xml2 = shift;
-
- my $class = ref $self;
- if( $class ne 'XML::Dumper' ) {
- $xml2 = $xml1;
- $xml1 = $self;
- }
-
- $xml1 =~ s/(<[^>]*)\smemory_address="\dx[A-Za-z0-9]+"([^<]*>)/$1$2/g;
- $xml2 =~ s/(<[^>]*)\smemory_address="\dx[A-Za-z0-9]+"([^<]*>)/$1$2/g;
- $xml1 =~ s/(<[^>]*)\sdefined=\"false\"([^<]>)/$1$2/g; # For backwards
- $xml2 =~ s/(<[^>]*)\sdefined=\"false\"([^<]>)/$1$2/g; # compatibility
- $xml1 =~ s/<\?xml .*>//; # Ignore XML declaration
- $xml2 =~ s/<\?xml .*>//;
- $xml1 =~ s/<\!DOCTYPE perldata \[.*\]>//s; # Remove DTD
- $xml2 =~ s/<\!DOCTYPE perldata \[.*\]>//s;
- $xml1 =~ s/^\s*</</; # Remove empty space
- $xml2 =~ s/^\s*</</;
- $xml1 =~ s/>\s*</></g;
- $xml2 =~ s/>\s*</></g;
- $xml1 =~ s/>\s*$/>/;
- $xml2 =~ s/>\s*$/>/;
-
- return $xml1 eq $xml2;
-}
-
-# ============================================================
-sub xml_identity {
-# ============================================================
-
-=item * xml_identity( $xml1, $xml2 ) - Compares xml for identity
-
-Compares two dumped Perl data structures (that is, compares the xml) for
-identity in instantiation. This function will return true for any two
-perl data that are identical, but not for deep clones of each other. This
-method is also exported by default.
-
-=cut
-
-# ------------------------------------------------------------
- my $self = shift;
- my $xml1 = shift;
- my $xml2 = shift;
-
- my $class = ref $self;
- if( $class ne 'XML::Dumper' ) {
- $xml2 = $xml1;
- $xml1 = $self;
- }
-
- return ( $xml1 eq $xml2 );
-}
-
-1;
-__END__
-
-=back
-
-=head1 EXPORTS
-
-By default, the following methods are exported:
-
- xml2pl, pl2xml, xml_compare, xml_identity
-
-=head1 BUGS AND DEPENDENCIES
-
-XML::Dumper has changed API since 0.4, as a response to a bug report
-from PerlMonks. I felt it was necessary, as the functions simply didn't
-work as advertised. That is, xml2pl really didnt accept xml as an
-argument; what it wanted was an XML Parse tree. To correct for the
-API change, simply don't parse the XML before feeding it to XML::Dumper.
-
-XML::Dumper also has no understanding of typeglobs (references or not),
-references to regular expressions, or references to Perl subroutines.
-Turns out that Data::Dumper doesn't do references to Perl subroutines,
-either, so at least I'm in somewhat good company.
-
-XML::Dumper requires one perl module, available from CPAN
-
- XML::Parser
-
-XML::Parser itself relies on Clark Cooper's Expat implementation in Perl,
-which in turn requires James Clark's expat package itself. See the
-documentation for XML::Parser for more information.
-
-=head1 REVISIONS AND CREDITS
-
-The list of credits got so long that I had to move it to the Changes
-file. Thanks to all those who've contributed with bug reports and
-suggested features! Keep 'em coming!
-
-I've had ownership of the module since June of 2002, and very much
-appreciate requests on how to make the module better. It has served me
-well, both as a learning tool on how I can repay my debt to the Perl
-Community, and as a practical module that is useful. I'm thrilled to
-be able to offer this bit of code. So, if you have suggestions, bug
-reports, or feature requests, please let me know and I'll do my best
-to make this a better module.
-
-=head1 CURRENT MAINTAINER
-
-Mike Wong E<lt>mike_w3@pacbell.netE<gt>
-
-XML::Dumper is free software. You can redistribute it and/or
-modify it under the same terms as Perl itself.
-
-=head1 ORIGINAL AUTHOR
-
-Jonathan Eisenzopf E<lt>eisen@pobox.comE<gt>
-
-=head1 SEE ALSO
-
-perl(1)
-Compress::Zlib(3)
-XML::Parser(3)
-Data::DumpXML(3)
-
-=cut
diff --git a/lib/XML/Simple.pm b/lib/XML/Simple.pm
deleted file mode 100644
index e2216be..0000000
--- a/lib/XML/Simple.pm
+++ /dev/null
@@ -1,3041 +0,0 @@
-# $Id: Simple.pm,v 1.23 2005/01/29 04:16:10 grantm Exp $
-
-package XML::Simple;
-
-=head1 NAME
-
-XML::Simple - Easy API to maintain XML (esp config files)
-
-=head1 SYNOPSIS
-
- use XML::Simple;
-
- my $ref = XMLin([<xml file or string>] [, <options>]);
-
- my $xml = XMLout($hashref [, <options>]);
-
-Or the object oriented way:
-
- require XML::Simple;
-
- my $xs = new XML::Simple(options);
-
- my $ref = $xs->XMLin([<xml file or string>] [, <options>]);
-
- my $xml = $xs->XMLout($hashref [, <options>]);
-
-(or see L<"SAX SUPPORT"> for 'the SAX way').
-
-To catch common errors:
-
- use XML::Simple qw(:strict);
-
-(see L<"STRICT MODE"> for more details).
-
-=cut
-
-# See after __END__ for more POD documentation
-
-
-# Load essentials here, other modules loaded on demand later
-
-use strict;
-use Carp;
-require Exporter;
-
-
-##############################################################################
-# Define some constants
-#
-
-use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $PREFERRED_PARSER);
-
-@ISA = qw(Exporter);
-@EXPORT = qw(XMLin XMLout);
-@EXPORT_OK = qw(xml_in xml_out);
-$VERSION = '2.14';
-$PREFERRED_PARSER = undef;
-
-my $StrictMode = 0;
-my %CacheScheme = (
- storable => [ \&StorableSave, \&StorableRestore ],
- memshare => [ \&MemShareSave, \&MemShareRestore ],
- memcopy => [ \&MemCopySave, \&MemCopyRestore ]
- );
-
-my @KnownOptIn = qw(keyattr keeproot forcecontent contentkey noattr
- searchpath forcearray cache suppressempty parseropts
- grouptags nsexpand datahandler varattr variables
- normalisespace normalizespace valueattr);
-
-my @KnownOptOut = qw(keyattr keeproot contentkey noattr
- rootname xmldecl outputfile noescape suppressempty
- grouptags nsexpand handler noindent attrindent nosort
- valueattr numericescape);
-
-my @DefKeyAttr = qw(name key id);
-my $DefRootName = qq(opt);
-my $DefContentKey = qq(content);
-my $DefXmlDecl = qq(<?xml version='1.0' standalone='yes'?>);
-
-my $xmlns_ns = 'http://www.w3.org/2000/xmlns/';
-my $bad_def_ns_jcn = '{' . $xmlns_ns . '}'; # LibXML::SAX workaround
-
-
-##############################################################################
-# Globals for use by caching routines
-#
-
-my %MemShareCache = ();
-my %MemCopyCache = ();
-
-
-##############################################################################
-# Wrapper for Exporter - handles ':strict'
-#
-
-sub import {
-
- # Handle the :strict tag
-
- $StrictMode = 1 if grep(/^:strict$/, @_);
-
- # Pass everything else to Exporter.pm
-
- __PACKAGE__->export_to_level(1, grep(!/^:strict$/, @_));
-}
-
-
-##############################################################################
-# Constructor for optional object interface.
-#
-
-sub new {
- my $class = shift;
-
- if(@_ % 2) {
- croak "Default options must be name=>value pairs (odd number supplied)";
- }
-
- my %known_opt;
- @known_opt{@KnownOptIn, @KnownOptOut} = (undef) x 100;
-
- my %raw_opt = @_;
- my %def_opt;
- while(my($key, $val) = each %raw_opt) {
- my $lkey = lc($key);
- $lkey =~ s/_//g;
- croak "Unrecognised option: $key" unless(exists($known_opt{$lkey}));
- $def_opt{$lkey} = $val;
- }
- my $self = { def_opt => \%def_opt };
-
- return(bless($self, $class));
-}
-
-
-##############################################################################
-# Sub/Method: XMLin()
-#
-# Exported routine for slurping XML into a hashref - see pod for info.
-#
-# May be called as object method or as a plain function.
-#
-# Expects one arg for the source XML, optionally followed by a number of
-# name => value option pairs.
-#
-
-sub XMLin {
-
- # If this is not a method call, create an object
-
- my $self;
- if($_[0] and UNIVERSAL::isa($_[0], 'XML::Simple')) {
- $self = shift;
- }
- else {
- $self = new XML::Simple();
- }
-
-
- my $string = shift;
-
- $self->handle_options('in', @_);
-
-
- # If no XML or filename supplied, look for scriptname.xml in script directory
-
- unless(defined($string)) {
-
- # Translate scriptname[.suffix] to scriptname.xml
-
- require File::Basename;
-
- my($ScriptName, $ScriptDir, $Extension) =
- File::Basename::fileparse($0, '\.[^\.]+');
-
- $string = $ScriptName . '.xml';
-
-
- # Add script directory to searchpath
-
- if($ScriptDir) {
- unshift(@{$self->{opt}->{searchpath}}, $ScriptDir);
- }
- }
-
-
- # Are we parsing from a file? If so, is there a valid cache available?
-
- my($filename, $scheme);
- unless($string =~ m{<.*?>}s or ref($string) or $string eq '-') {
-
- require File::Basename;
- require File::Spec;
-
- $filename = $self->find_xml_file($string, @{$self->{opt}->{searchpath}});
-
- if($self->{opt}->{cache}) {
- foreach $scheme (@{$self->{opt}->{cache}}) {
- croak "Unsupported caching scheme: $scheme"
- unless($CacheScheme{$scheme});
-
- my $opt = $CacheScheme{$scheme}->[1]->($filename);
- return($opt) if($opt);
- }
- }
- }
- else {
- delete($self->{opt}->{cache});
- if($string eq '-') {
- # Read from standard input
-
- local($/) = undef;
- $string = <STDIN>;
- }
- }
-
-
- # Parsing is required, so let's get on with it
-
- my $tree = $self->build_tree($filename, $string);
-
-
- # Now work some magic on the resulting parse tree
-
- my($ref);
- if($self->{opt}->{keeproot}) {
- $ref = $self->collapse({}, @$tree);
- }
- else {
- $ref = $self->collapse(@{$tree->[1]});
- }
-
- if($self->{opt}->{cache}) {
- $CacheScheme{$self->{opt}->{cache}->[0]}->[0]->($ref, $filename);
- }
-
- return($ref);
-}
-
-
-##############################################################################
-# Method: build_tree()
-#
-# This routine will be called if there is no suitable pre-parsed tree in a
-# cache. It parses the XML and returns an XML::Parser 'Tree' style data
-# structure (summarised in the comments for the collapse() routine below).
-#
-# XML::Simple requires the services of another module that knows how to
-# parse XML. If XML::SAX is installed, the default SAX parser will be used,
-# otherwise XML::Parser will be used.
-#
-# This routine expects to be passed a 'string' as argument 1 or a filename as
-# argument 2. The 'string' might be a string of XML or it might be a
-# reference to an IO::Handle. (This non-intuitive mess results in part from
-# the way XML::Parser works but that's really no excuse).
-#
-
-sub build_tree {
- my $self = shift;
- my $filename = shift;
- my $string = shift;
-
-
- my $preferred_parser = $PREFERRED_PARSER;
- unless(defined($preferred_parser)) {
- $preferred_parser = $ENV{XML_SIMPLE_PREFERRED_PARSER} || '';
- }
- if($preferred_parser eq 'XML::Parser') {
- return($self->build_tree_xml_parser($filename, $string));
- }
-
- eval { require XML::SAX; }; # We didn't need it until now
- if($@) { # No XML::SAX - fall back to XML::Parser
- if($preferred_parser) { # unless a SAX parser was expressly requested
- croak "XMLin() could not load XML::SAX";
- }
- return($self->build_tree_xml_parser($filename, $string));
- }
-
- $XML::SAX::ParserPackage = $preferred_parser if($preferred_parser);
-
- my $sp = XML::SAX::ParserFactory->parser(Handler => $self);
-
- $self->{nocollapse} = 1;
- my($tree);
- if($filename) {
- $tree = $sp->parse_uri($filename);
- }
- else {
- if(ref($string)) {
- $tree = $sp->parse_file($string);
- }
- else {
- $tree = $sp->parse_string($string);
- }
- }
-
- return($tree);
-}
-
-
-##############################################################################
-# Method: build_tree_xml_parser()
-#
-# This routine will be called if XML::SAX is not installed, or if XML::Parser
-# was specifically requested. It takes the same arguments as build_tree() and
-# returns the same data structure (XML::Parser 'Tree' style).
-#
-
-sub build_tree_xml_parser {
- my $self = shift;
- my $filename = shift;
- my $string = shift;
-
-
- eval {
- local($^W) = 0; # Suppress warning from Expat.pm re File::Spec::load()
- require XML::Parser; # We didn't need it until now
- };
- if($@) {
- croak "XMLin() requires either XML::SAX or XML::Parser";
- }
-
- if($self->{opt}->{nsexpand}) {
- carp "'nsexpand' option requires XML::SAX";
- }
-
- my $xp = new XML::Parser(Style => 'Tree', @{$self->{opt}->{parseropts}});
- my($tree);
- if($filename) {
- # $tree = $xp->parsefile($filename); # Changed due to prob w/mod_perl
- local(*XML_FILE);
- open(XML_FILE, '<', $filename) || croak qq($filename - $!);
- $tree = $xp->parse(*XML_FILE);
- close(XML_FILE);
- }
- else {
- $tree = $xp->parse($string);
- }
-
- return($tree);
-}
-
-
-##############################################################################
-# Sub: StorableSave()
-#
-# Wrapper routine for invoking Storable::nstore() to cache a parsed data
-# structure.
-#
-
-sub StorableSave {
- my($data, $filename) = @_;
-
- my $cachefile = $filename;
- $cachefile =~ s{(\.xml)?$}{.stor};
-
- require Storable; # We didn't need it until now
-
- if ('VMS' eq $^O) {
- Storable::nstore($data, $cachefile);
- }
- else {
- # If the following line fails for you, your Storable.pm is old - upgrade
- Storable::lock_nstore($data, $cachefile);
- }
-
-}
-
-
-##############################################################################
-# Sub: StorableRestore()
-#
-# Wrapper routine for invoking Storable::retrieve() to read a cached parsed
-# data structure. Only returns cached data if the cache file exists and is
-# newer than the source XML file.
-#
-
-sub StorableRestore {
- my($filename) = @_;
-
- my $cachefile = $filename;
- $cachefile =~ s{(\.xml)?$}{.stor};
-
- return unless(-r $cachefile);
- return unless((stat($cachefile))[9] > (stat($filename))[9]);
-
- require Storable; # We didn't need it until now
-
- if ('VMS' eq $^O) {
- return(Storable::retrieve($cachefile));
- }
- else {
- return(Storable::lock_retrieve($cachefile));
- }
-
-}
-
-
-##############################################################################
-# Sub: MemShareSave()
-#
-# Takes the supplied data structure reference and stores it away in a global
-# hash structure.
-#
-
-sub MemShareSave {
- my($data, $filename) = @_;
-
- $MemShareCache{$filename} = [time(), $data];
-}
-
-
-##############################################################################
-# Sub: MemShareRestore()
-#
-# Takes a filename and looks in a global hash for a cached parsed version.
-#
-
-sub MemShareRestore {
- my($filename) = @_;
-
- return unless($MemShareCache{$filename});
- return unless($MemShareCache{$filename}->[0] > (stat($filename))[9]);
-
- return($MemShareCache{$filename}->[1]);
-
-}
-
-
-##############################################################################
-# Sub: MemCopySave()
-#
-# Takes the supplied data structure and stores a copy of it in a global hash
-# structure.
-#
-
-sub MemCopySave {
- my($data, $filename) = @_;
-
- require Storable; # We didn't need it until now
-
- $MemCopyCache{$filename} = [time(), Storable::dclone($data)];
-}
-
-
-##############################################################################
-# Sub: MemCopyRestore()
-#
-# Takes a filename and looks in a global hash for a cached parsed version.
-# Returns a reference to a copy of that data structure.
-#
-
-sub MemCopyRestore {
- my($filename) = @_;
-
- return unless($MemCopyCache{$filename});
- return unless($MemCopyCache{$filename}->[0] > (stat($filename))[9]);
-
- return(Storable::dclone($MemCopyCache{$filename}->[1]));
-
-}
-
-
-##############################################################################
-# Sub/Method: XMLout()
-#
-# Exported routine for 'unslurping' a data structure out to XML.
-#
-# Expects a reference to a data structure and an optional list of option
-# name => value pairs.
-#
-
-sub XMLout {
-
- # If this is not a method call, create an object
-
- my $self;
- if($_[0] and UNIVERSAL::isa($_[0], 'XML::Simple')) {
- $self = shift;
- }
- else {
- $self = new XML::Simple();
- }
-
- croak "XMLout() requires at least one argument" unless(@_);
- my $ref = shift;
-
- $self->handle_options('out', @_);
-
-
- # If namespace expansion is set, XML::NamespaceSupport is required
-
- if($self->{opt}->{nsexpand}) {
- require XML::NamespaceSupport;
- $self->{nsup} = XML::NamespaceSupport->new();
- $self->{ns_prefix} = 'aaa';
- }
-
-
- # Wrap top level arrayref in a hash
-
- if(UNIVERSAL::isa($ref, 'ARRAY')) {
- $ref = { anon => $ref };
- }
-
-
- # Extract rootname from top level hash if keeproot enabled
-
- if($self->{opt}->{keeproot}) {
- my(@keys) = keys(%$ref);
- if(@keys == 1) {
- $ref = $ref->{$keys[0]};
- $self->{opt}->{rootname} = $keys[0];
- }
- }
-
- # Ensure there are no top level attributes if we're not adding root elements
-
- elsif($self->{opt}->{rootname} eq '') {
- if(UNIVERSAL::isa($ref, 'HASH')) {
- my $refsave = $ref;
- $ref = {};
- foreach (keys(%$refsave)) {
- if(ref($refsave->{$_})) {
- $ref->{$_} = $refsave->{$_};
- }
- else {
- $ref->{$_} = [ $refsave->{$_} ];
- }
- }
- }
- }
-
-
- # Encode the hashref and write to file if necessary
-
- $self->{_ancestors} = [];
- my $xml = $self->value_to_xml($ref, $self->{opt}->{rootname}, '');
- delete $self->{_ancestors};
-
- if($self->{opt}->{xmldecl}) {
- $xml = $self->{opt}->{xmldecl} . "\n" . $xml;
- }
-
- if($self->{opt}->{outputfile}) {
- if(ref($self->{opt}->{outputfile})) {
- return($self->{opt}->{outputfile}->print($xml));
- }
- else {
- local(*OUT);
- open(OUT, '>', "$self->{opt}->{outputfile}") ||
- croak "open($self->{opt}->{outputfile}): $!";
- binmode(OUT, ':utf8') if($] >= 5.008);
- print OUT $xml || croak "print: $!";
- close(OUT);
- }
- }
- elsif($self->{opt}->{handler}) {
- require XML::SAX;
- my $sp = XML::SAX::ParserFactory->parser(
- Handler => $self->{opt}->{handler}
- );
- return($sp->parse_string($xml));
- }
- else {
- return($xml);
- }
-}
-
-
-##############################################################################
-# Method: handle_options()
-#
-# Helper routine for both XMLin() and XMLout(). Both routines handle their
-# first argument and assume all other args are options handled by this routine.
-# Saves a hash of options in $self->{opt}.
-#
-# If default options were passed to the constructor, they will be retrieved
-# here and merged with options supplied to the method call.
-#
-# First argument should be the string 'in' or the string 'out'.
-#
-# Remaining arguments should be name=>value pairs. Sets up default values
-# for options not supplied. Unrecognised options are a fatal error.
-#
-
-sub handle_options {
- my $self = shift;
- my $dirn = shift;
-
-
- # Determine valid options based on context
-
- my %known_opt;
- if($dirn eq 'in') {
- @known_opt{@KnownOptIn} = @KnownOptIn;
- }
- else {
- @known_opt{@KnownOptOut} = @KnownOptOut;
- }
-
-
- # Store supplied options in hashref and weed out invalid ones
-
- if(@_ % 2) {
- croak "Options must be name=>value pairs (odd number supplied)";
- }
- my %raw_opt = @_;
- my $opt = {};
- $self->{opt} = $opt;
-
- while(my($key, $val) = each %raw_opt) {
- my $lkey = lc($key);
- $lkey =~ s/_//g;
- croak "Unrecognised option: $key" unless($known_opt{$lkey});
- $opt->{$lkey} = $val;
- }
-
-
- # Merge in options passed to constructor
-
- foreach (keys(%known_opt)) {
- unless(exists($opt->{$_})) {
- if(exists($self->{def_opt}->{$_})) {
- $opt->{$_} = $self->{def_opt}->{$_};
- }
- }
- }
-
-
- # Set sensible defaults if not supplied
-
- if(exists($opt->{rootname})) {
- unless(defined($opt->{rootname})) {
- $opt->{rootname} = '';
- }
- }
- else {
- $opt->{rootname} = $DefRootName;
- }
-
- if($opt->{xmldecl} and $opt->{xmldecl} eq '1') {
- $opt->{xmldecl} = $DefXmlDecl;
- }
-
- if(exists($opt->{contentkey})) {
- if($opt->{contentkey} =~ m{^-(.*)$}) {
- $opt->{contentkey} = $1;
- $opt->{collapseagain} = 1;
- }
- }
- else {
- $opt->{contentkey} = $DefContentKey;
- }
-
- unless(exists($opt->{normalisespace})) {
- $opt->{normalisespace} = $opt->{normalizespace};
- }
- $opt->{normalisespace} = 0 unless(defined($opt->{normalisespace}));
-
- # Cleanups for values assumed to be arrays later
-
- if($opt->{searchpath}) {
- unless(ref($opt->{searchpath})) {
- $opt->{searchpath} = [ $opt->{searchpath} ];
- }
- }
- else {
- $opt->{searchpath} = [ ];
- }
-
- if($opt->{cache} and !ref($opt->{cache})) {
- $opt->{cache} = [ $opt->{cache} ];
- }
- if($opt->{cache}) {
- $_ = lc($_) foreach (@{$opt->{cache}});
- }
-
- if(exists($opt->{parseropts})) {
- if($^W) {
- carp "Warning: " .
- "'ParserOpts' is deprecated, contact the author if you need it";
- }
- }
- else {
- $opt->{parseropts} = [ ];
- }
-
-
- # Special cleanup for {forcearray} which could be regex, arrayref or boolean
- # or left to default to 0
-
- if(exists($opt->{forcearray})) {
- if(ref($opt->{forcearray}) eq 'Regexp') {
- $opt->{forcearray} = [ $opt->{forcearray} ];
- }
-
- if(ref($opt->{forcearray}) eq 'ARRAY') {
- my @force_list = @{$opt->{forcearray}};
- if(@force_list) {
- $opt->{forcearray} = {};
- foreach my $tag (@force_list) {
- if(ref($tag) eq 'Regexp') {
- push @{$opt->{forcearray}->{_regex}}, $tag;
- }
- else {
- $opt->{forcearray}->{$tag} = 1;
- }
- }
- }
- else {
- $opt->{forcearray} = 0;
- }
- }
- else {
- $opt->{forcearray} = ( $opt->{forcearray} ? 1 : 0 );
- }
- }
- else {
- if($StrictMode and $dirn eq 'in') {
- croak "No value specified for 'ForceArray' option in call to XML$dirn()";
- }
- $opt->{forcearray} = 0;
- }
-
-
- # Special cleanup for {keyattr} which could be arrayref or hashref or left
- # to default to arrayref
-
- if(exists($opt->{keyattr})) {
- if(ref($opt->{keyattr})) {
- if(ref($opt->{keyattr}) eq 'HASH') {
-
- # Make a copy so we can mess with it
-
- $opt->{keyattr} = { %{$opt->{keyattr}} };
-
-
- # Convert keyattr => { elem => '+attr' }
- # to keyattr => { elem => [ 'attr', '+' ] }
-
- foreach my $el (keys(%{$opt->{keyattr}})) {
- if($opt->{keyattr}->{$el} =~ /^(\+|-)?(.*)$/) {
- $opt->{keyattr}->{$el} = [ $2, ($1 ? $1 : '') ];
- if($StrictMode and $dirn eq 'in') {
- next if($opt->{forcearray} == 1);
- next if(ref($opt->{forcearray}) eq 'HASH'
- and $opt->{forcearray}->{$el});
- croak "<$el> set in KeyAttr but not in ForceArray";
- }
- }
- else {
- delete($opt->{keyattr}->{$el}); # Never reached (famous last words?)
- }
- }
- }
- else {
- if(@{$opt->{keyattr}} == 0) {
- delete($opt->{keyattr});
- }
- }
- }
- else {
- $opt->{keyattr} = [ $opt->{keyattr} ];
- }
- }
- else {
- if($StrictMode) {
- croak "No value specified for 'KeyAttr' option in call to XML$dirn()";
- }
- $opt->{keyattr} = [ @DefKeyAttr ];
- }
-
-
- # Special cleanup for {valueattr} which could be arrayref or hashref
-
- if(exists($opt->{valueattr})) {
- if(ref($opt->{valueattr}) eq 'ARRAY') {
- $opt->{valueattrlist} = {};
- $opt->{valueattrlist}->{$_} = 1 foreach(@{ delete $opt->{valueattr} });
- }
- }
-
- # make sure there's nothing weird in {grouptags}
-
- if($opt->{grouptags} and !UNIVERSAL::isa($opt->{grouptags}, 'HASH')) {
- croak "Illegal value for 'GroupTags' option - expected a hashref";
- }
-
-
- # Check the {variables} option is valid and initialise variables hash
-
- if($opt->{variables} and !UNIVERSAL::isa($opt->{variables}, 'HASH')) {
- croak "Illegal value for 'Variables' option - expected a hashref";
- }
-
- if($opt->{variables}) {
- $self->{_var_values} = { %{$opt->{variables}} };
- }
- elsif($opt->{varattr}) {
- $self->{_var_values} = {};
- }
-
-}
-
-
-##############################################################################
-# Method: find_xml_file()
-#
-# Helper routine for XMLin().
-# Takes a filename, and a list of directories, attempts to locate the file in
-# the directories listed.
-# Returns a full pathname on success; croaks on failure.
-#
-
-sub find_xml_file {
- my $self = shift;
- my $file = shift;
- my @search_path = @_;
-
-
- my($filename, $filedir) =
- File::Basename::fileparse($file);
-
- if($filename ne $file) { # Ignore searchpath if dir component
- return($file) if(-e $file);
- }
- else {
- my($path);
- foreach $path (@search_path) {
- my $fullpath = File::Spec->catfile($path, $file);
- return($fullpath) if(-e $fullpath);
- }
- }
-
- # If user did not supply a search path, default to current directory
-
- if(!@search_path) {
- return($file) if(-e $file);
- croak "File does not exist: $file";
- }
-
- croak "Could not find $file in ", join(':', @search_path);
-}
-
-
-##############################################################################
-# Method: collapse()
-#
-# Helper routine for XMLin(). This routine really comprises the 'smarts' (or
-# value add) of this module.
-#
-# Takes the parse tree that XML::Parser produced from the supplied XML and
-# recurses through it 'collapsing' unnecessary levels of indirection (nested
-# arrays etc) to produce a data structure that is easier to work with.
-#
-# Elements in the original parser tree are represented as an element name
-# followed by an arrayref. The first element of the array is a hashref
-# containing the attributes. The rest of the array contains a list of any
-# nested elements as name+arrayref pairs:
-#
-# <element name>, [ { <attribute hashref> }, <element name>, [ ... ], ... ]
-#
-# The special element name '0' (zero) flags text content.
-#
-# This routine cuts down the noise by discarding any text content consisting of
-# only whitespace and then moves the nested elements into the attribute hash
-# using the name of the nested element as the hash key and the collapsed
-# version of the nested element as the value. Multiple nested elements with
-# the same name will initially be represented as an arrayref, but this may be
-# 'folded' into a hashref depending on the value of the keyattr option.
-#
-
-sub collapse {
- my $self = shift;
-
-
- # Start with the hash of attributes
-
- my $attr = shift;
- if($self->{opt}->{noattr}) { # Discard if 'noattr' set
- $attr = {};
- }
- elsif($self->{opt}->{normalisespace} == 2) {
- while(my($key, $value) = each %$attr) {
- $attr->{$key} = $self->normalise_space($value)
- }
- }
-
-
- # Do variable substitutions
-
- if(my $var = $self->{_var_values}) {
- while(my($key, $val) = each(%$attr)) {
- $val =~ s{\$\{(\w+)\}}{ $self->get_var($1) }ge;
- $attr->{$key} = $val;
- }
- }
-
-
- # Roll up 'value' attributes (but only if no nested elements)
-
- if(!@_ and keys %$attr == 1) {
- my($k) = keys %$attr;
- if($self->{opt}->{valueattrlist} and $self->{opt}->{valueattrlist}->{$k}) {
- return $attr->{$k};
- }
- }
-
-
- # Add any nested elements
-
- my($key, $val);
- while(@_) {
- $key = shift;
- $val = shift;
-
- if(ref($val)) {
- $val = $self->collapse(@$val);
- next if(!defined($val) and $self->{opt}->{suppressempty});
- }
- elsif($key eq '0') {
- next if($val =~ m{^\s*$}s); # Skip all whitespace content
-
- $val = $self->normalise_space($val)
- if($self->{opt}->{normalisespace} == 2);
-
- # do variable substitutions
-
- if(my $var = $self->{_var_values}) {
- $val =~ s{\$\{(\w+)\}}{ $self->get_var($1) }ge;
- }
-
-
- # look for variable definitions
-
- if(my $var = $self->{opt}->{varattr}) {
- if(exists $attr->{$var}) {
- $self->set_var($attr->{$var}, $val);
- }
- }
-
-
- # Collapse text content in element with no attributes to a string
-
- if(!%$attr and !@_) {
- return($self->{opt}->{forcecontent} ?
- { $self->{opt}->{contentkey} => $val } : $val
- );
- }
- $key = $self->{opt}->{contentkey};
- }
-
-
- # Combine duplicate attributes into arrayref if required
-
- if(exists($attr->{$key})) {
- if(UNIVERSAL::isa($attr->{$key}, 'ARRAY')) {
- push(@{$attr->{$key}}, $val);
- }
- else {
- $attr->{$key} = [ $attr->{$key}, $val ];
- }
- }
- elsif(defined($val) and UNIVERSAL::isa($val, 'ARRAY')) {
- $attr->{$key} = [ $val ];
- }
- else {
- if( $key ne $self->{opt}->{contentkey}
- and (
- ($self->{opt}->{forcearray} == 1)
- or (
- (ref($self->{opt}->{forcearray}) eq 'HASH')
- and (
- $self->{opt}->{forcearray}->{$key}
- or (grep $key =~ $_, @{$self->{opt}->{forcearray}->{_regex}})
- )
- )
- )
- ) {
- $attr->{$key} = [ $val ];
- }
- else {
- $attr->{$key} = $val;
- }
- }
-
- }
-
-
- # Turn arrayrefs into hashrefs if key fields present
-
- if($self->{opt}->{keyattr}) {
- while(($key,$val) = each %$attr) {
- if(defined($val) and UNIVERSAL::isa($val, 'ARRAY')) {
- $attr->{$key} = $self->array_to_hash($key, $val);
- }
- }
- }
-
-
- # disintermediate grouped tags
-
- if($self->{opt}->{grouptags}) {
- while(my($key, $val) = each(%$attr)) {
- next unless(UNIVERSAL::isa($val, 'HASH') and (keys %$val == 1));
- next unless(exists($self->{opt}->{grouptags}->{$key}));
-
- my($child_key, $child_val) = %$val;
-
- if($self->{opt}->{grouptags}->{$key} eq $child_key) {
- $attr->{$key}= $child_val;
- }
- }
- }
-
-
- # Fold hashes containing a single anonymous array up into just the array
-
- my $count = scalar keys %$attr;
- if($count == 1
- and exists $attr->{anon}
- and UNIVERSAL::isa($attr->{anon}, 'ARRAY')
- ) {
- return($attr->{anon});
- }
-
-
- # Do the right thing if hash is empty, otherwise just return it
-
- if(!%$attr and exists($self->{opt}->{suppressempty})) {
- if(defined($self->{opt}->{suppressempty}) and
- $self->{opt}->{suppressempty} eq '') {
- return('');
- }
- return(undef);
- }
-
-
- # Roll up named elements with named nested 'value' attributes
-
- if($self->{opt}->{valueattr}) {
- while(my($key, $val) = each(%$attr)) {
- next unless($self->{opt}->{valueattr}->{$key});
- next unless(UNIVERSAL::isa($val, 'HASH') and (keys %$val == 1));
- my($k) = keys %$val;
- next unless($k eq $self->{opt}->{valueattr}->{$key});
- $attr->{$key} = $val->{$k};
- }
- }
-
- return($attr)
-
-}
-
-
-##############################################################################
-# Method: set_var()
-#
-# Called when a variable definition is encountered in the XML. (A variable
-# definition looks like <element attrname="name">value</element> where attrname
-# matches the varattr setting).
-#
-
-sub set_var {
- my($self, $name, $value) = @_;
-
- $self->{_var_values}->{$name} = $value;
-}
-
-
-##############################################################################
-# Method: get_var()
-#
-# Called during variable substitution to get the value for the named variable.
-#
-
-sub get_var {
- my($self, $name) = @_;
-
- my $value = $self->{_var_values}->{$name};
- return $value if(defined($value));
-
- return '${' . $name . '}';
-}
-
-
-##############################################################################
-# Method: normalise_space()
-#
-# Strips leading and trailing whitespace and collapses sequences of whitespace
-# characters to a single space.
-#
-
-sub normalise_space {
- my($self, $text) = @_;
-
- $text =~ s/^\s+//s;
- $text =~ s/\s+$//s;
- $text =~ s/\s\s+/ /sg;
-
- return $text;
-}
-
-
-##############################################################################
-# Method: array_to_hash()
-#
-# Helper routine for collapse().
-# Attempts to 'fold' an array of hashes into an hash of hashes. Returns a
-# reference to the hash on success or the original array if folding is
-# not possible. Behaviour is controlled by 'keyattr' option.
-#
-
-sub array_to_hash {
- my $self = shift;
- my $name = shift;
- my $arrayref = shift;
-
- my $hashref = {};
-
- my($i, $key, $val, $flag);
-
-
- # Handle keyattr => { .... }
-
- if(ref($self->{opt}->{keyattr}) eq 'HASH') {
- return($arrayref) unless(exists($self->{opt}->{keyattr}->{$name}));
- ($key, $flag) = @{$self->{opt}->{keyattr}->{$name}};
- for($i = 0; $i < @$arrayref; $i++) {
- if(UNIVERSAL::isa($arrayref->[$i], 'HASH') and
- exists($arrayref->[$i]->{$key})
- ) {
- $val = $arrayref->[$i]->{$key};
- if(ref($val)) {
- if($StrictMode) {
- croak "<$name> element has non-scalar '$key' key attribute";
- }
- if($^W) {
- carp "Warning: <$name> element has non-scalar '$key' key attribute";
- }
- return($arrayref);
- }
- $val = $self->normalise_space($val)
- if($self->{opt}->{normalisespace} == 1);
- $hashref->{$val} = { %{$arrayref->[$i]} };
- $hashref->{$val}->{"-$key"} = $hashref->{$val}->{$key} if($flag eq '-');
- delete $hashref->{$val}->{$key} unless($flag eq '+');
- }
- else {
- croak "<$name> element has no '$key' key attribute" if($StrictMode);
- carp "Warning: <$name> element has no '$key' key attribute" if($^W);
- return($arrayref);
- }
- }
- }
-
-
- # Or assume keyattr => [ .... ]
-
- else {
- ELEMENT: for($i = 0; $i < @$arrayref; $i++) {
- return($arrayref) unless(UNIVERSAL::isa($arrayref->[$i], 'HASH'));
-
- foreach $key (@{$self->{opt}->{keyattr}}) {
- if(defined($arrayref->[$i]->{$key})) {
- $val = $arrayref->[$i]->{$key};
- return($arrayref) if(ref($val));
- $val = $self->normalise_space($val)
- if($self->{opt}->{normalisespace} == 1);
- $hashref->{$val} = { %{$arrayref->[$i]} };
- delete $hashref->{$val}->{$key};
- next ELEMENT;
- }
- }
-
- return($arrayref); # No keyfield matched
- }
- }
-
- # collapse any hashes which now only have a 'content' key
-
- if($self->{opt}->{collapseagain}) {
- $hashref = $self->collapse_content($hashref);
- }
-
- return($hashref);
-}
-
-
-##############################################################################
-# Method: collapse_content()
-#
-# Helper routine for array_to_hash
-#
-# Arguments expected are:
-# - an XML::Simple object
-# - a hasref
-# the hashref is a former array, turned into a hash by array_to_hash because
-# of the presence of key attributes
-# at this point collapse_content avoids over-complicated structures like
-# dir => { libexecdir => { content => '$exec_prefix/libexec' },
-# localstatedir => { content => '$prefix' },
-# }
-# into
-# dir => { libexecdir => '$exec_prefix/libexec',
-# localstatedir => '$prefix',
-# }
-
-sub collapse_content {
- my $self = shift;
- my $hashref = shift;
-
- my $contentkey = $self->{opt}->{contentkey};
-
- # first go through the values,checking that they are fit to collapse
- foreach my $val (values %$hashref) {
- return $hashref unless ( (ref($val) eq 'HASH')
- and (keys %$val == 1)
- and (exists $val->{$contentkey})
- );
- }
-
- # now collapse them
- foreach my $key (keys %$hashref) {
- $hashref->{$key}= $hashref->{$key}->{$contentkey};
- }
-
- return $hashref;
-}
-
-
-##############################################################################
-# Method: value_to_xml()
-#
-# Helper routine for XMLout() - recurses through a data structure building up
-# and returning an XML representation of that structure as a string.
-#
-# Arguments expected are:
-# - the data structure to be encoded (usually a reference)
-# - the XML tag name to use for this item
-# - a string of spaces for use as the current indent level
-#
-
-sub value_to_xml {
- my $self = shift;;
-
-
- # Grab the other arguments
-
- my($ref, $name, $indent) = @_;
-
- my $named = (defined($name) and $name ne '' ? 1 : 0);
-
- my $nl = "\n";
-
- my $is_root = $indent eq '' ? 1 : 0; # Warning, dirty hack!
- if($self->{opt}->{noindent}) {
- $indent = '';
- $nl = '';
- }
-
-
- # Convert to XML
-
- if(ref($ref)) {
- croak "circular data structures not supported"
- if(grep($_ == $ref, @{$self->{_ancestors}}));
- push @{$self->{_ancestors}}, $ref;
- }
- else {
- if($named) {
- return(join('',
- $indent, '<', $name, '>',
- ($self->{opt}->{noescape} ? $ref : $self->escape_value($ref)),
- '</', $name, ">", $nl
- ));
- }
- else {
- return("$ref$nl");
- }
- }
-
-
- # Unfold hash to array if possible
-
- if(UNIVERSAL::isa($ref, 'HASH') # It is a hash
- and keys %$ref # and it's not empty
- and $self->{opt}->{keyattr} # and folding is enabled
- and !$is_root # and its not the root element
- ) {
- $ref = $self->hash_to_array($name, $ref);
- }
-
-
- my @result = ();
- my($key, $value);
-
-
- # Handle hashrefs
-
- if(UNIVERSAL::isa($ref, 'HASH')) {
-
- # Reintermediate grouped values if applicable
-
- if($self->{opt}->{grouptags}) {
- $ref = $self->copy_hash($ref);
- while(my($key, $val) = each %$ref) {
- if($self->{opt}->{grouptags}->{$key}) {
- $ref->{$key} = { $self->{opt}->{grouptags}->{$key} => $val };
- }
- }
- }
-
-
- # Scan for namespace declaration attributes
-
- my $nsdecls = '';
- my $default_ns_uri;
- if($self->{nsup}) {
- $ref = $self->copy_hash($ref);
- $self->{nsup}->push_context();
-
- # Look for default namespace declaration first
-
- if(exists($ref->{xmlns})) {
- $self->{nsup}->declare_prefix('', $ref->{xmlns});
- $nsdecls .= qq( xmlns="$ref->{xmlns}");
- delete($ref->{xmlns});
- }
- $default_ns_uri = $self->{nsup}->get_uri('');
-
-
- # Then check all the other keys
-
- foreach my $qname (keys(%$ref)) {
- my($uri, $lname) = $self->{nsup}->parse_jclark_notation($qname);
- if($uri) {
- if($uri eq $xmlns_ns) {
- $self->{nsup}->declare_prefix($lname, $ref->{$qname});
- $nsdecls .= qq( xmlns:$lname="$ref->{$qname}");
- delete($ref->{$qname});
- }
- }
- }
-
- # Translate any remaining Clarkian names
-
- foreach my $qname (keys(%$ref)) {
- my($uri, $lname) = $self->{nsup}->parse_jclark_notation($qname);
- if($uri) {
- if($default_ns_uri and $uri eq $default_ns_uri) {
- $ref->{$lname} = $ref->{$qname};
- delete($ref->{$qname});
- }
- else {
- my $prefix = $self->{nsup}->get_prefix($uri);
- unless($prefix) {
- # $self->{nsup}->declare_prefix(undef, $uri);
- # $prefix = $self->{nsup}->get_prefix($uri);
- $prefix = $self->{ns_prefix}++;
- $self->{nsup}->declare_prefix($prefix, $uri);
- $nsdecls .= qq( xmlns:$prefix="$uri");
- }
- $ref->{"$prefix:$lname"} = $ref->{$qname};
- delete($ref->{$qname});
- }
- }
- }
- }
-
-
- my @nested = ();
- my $text_content = undef;
- if($named) {
- push @result, $indent, '<', $name, $nsdecls;
- }
-
- if(keys %$ref) {
- my $first_arg = 1;
- foreach my $key ($self->sorted_keys($name, $ref)) {
- my $value = $ref->{$key};
- next if(substr($key, 0, 1) eq '-');
- if(!defined($value)) {
- next if $self->{opt}->{suppressempty};
- unless(exists($self->{opt}->{suppressempty})
- and !defined($self->{opt}->{suppressempty})
- ) {
- carp 'Use of uninitialized value' if($^W);
- }
- if($key eq $self->{opt}->{contentkey}) {
- $text_content = '';
- }
- else {
- $value = exists($self->{opt}->{suppressempty}) ? {} : '';
- }
- }
-
- if(!ref($value)
- and $self->{opt}->{valueattr}
- and $self->{opt}->{valueattr}->{$key}
- ) {
- $value = { $self->{opt}->{valueattr}->{$key} => $value };
- }
-
- if(ref($value) or $self->{opt}->{noattr}) {
- push @nested,
- $self->value_to_xml($value, $key, "$indent ");
- }
- else {
- $value = $self->escape_value($value) unless($self->{opt}->{noescape});
- if($key eq $self->{opt}->{contentkey}) {
- $text_content = $value;
- }
- else {
- push @result, "\n$indent " . ' ' x length($name)
- if($self->{opt}->{attrindent} and !$first_arg);
- push @result, ' ', $key, '="', $value , '"';
- $first_arg = 0;
- }
- }
- }
- }
- else {
- $text_content = '';
- }
-
- if(@nested or defined($text_content)) {
- if($named) {
- push @result, ">";
- if(defined($text_content)) {
- push @result, $text_content;
- $nested[0] =~ s/^\s+// if(@nested);
- }
- else {
- push @result, $nl;
- }
- if(@nested) {
- push @result, @nested, $indent;
- }
- push @result, '</', $name, ">", $nl;
- }
- else {
- push @result, @nested; # Special case if no root elements
- }
- }
- else {
- push @result, " />", $nl;
- }
- $self->{nsup}->pop_context() if($self->{nsup});
- }
-
-
- # Handle arrayrefs
-
- elsif(UNIVERSAL::isa($ref, 'ARRAY')) {
- foreach $value (@$ref) {
- if(!ref($value)) {
- push @result,
- $indent, '<', $name, '>',
- ($self->{opt}->{noescape} ? $value : $self->escape_value($value)),
- '</', $name, ">$nl";
- }
- elsif(UNIVERSAL::isa($value, 'HASH')) {
- push @result, $self->value_to_xml($value, $name, $indent);
- }
- else {
- push @result,
- $indent, '<', $name, ">$nl",
- $self->value_to_xml($value, 'anon', "$indent "),
- $indent, '</', $name, ">$nl";
- }
- }
- }
-
- else {
- croak "Can't encode a value of type: " . ref($ref);
- }
-
-
- pop @{$self->{_ancestors}} if(ref($ref));
-
- return(join('', @result));
-}
-
-
-##############################################################################
-# Method: sorted_keys()
-#
-# Returns the keys of the referenced hash sorted into alphabetical order, but
-# with the 'key' key (as in KeyAttr) first, if there is one.
-#
-
-sub sorted_keys {
- my($self, $name, $ref) = @_;
-
- return keys %$ref if $self->{opt}->{nosort};
-
- my %hash = %$ref;
- my $keyattr = $self->{opt}->{keyattr};
-
- my @key;
-
- if(ref $keyattr eq 'HASH') {
- if(exists $keyattr->{$name} and exists $hash{$keyattr->{$name}->[0]}) {
- push @key, $keyattr->{$name}->[0];
- delete $hash{$keyattr->{$name}->[0]};
- }
- }
- elsif(ref $keyattr eq 'ARRAY') {
- foreach (@{$keyattr}) {
- if(exists $hash{$_}) {
- push @key, $_;
- delete $hash{$_};
- last;
- }
- }
- }
-
- return(@key, sort keys %hash);
-}
-
-##############################################################################
-# Method: escape_value()
-#
-# Helper routine for automatically escaping values for XMLout().
-# Expects a scalar data value. Returns escaped version.
-#
-
-sub escape_value {
- my($self, $data) = @_;
-
- return '' unless(defined($data));
-
- $data =~ s/&/&amp;/sg;
- $data =~ s/</&lt;/sg;
- $data =~ s/>/&gt;/sg;
- $data =~ s/"/&quot;/sg;
-
- my $level = $self->{opt}->{numericescape} or return $data;
-
- return $self->numeric_escape($data, $level);
-}
-
-sub numeric_escape {
- my($self, $data, $level) = @_;
-
- use utf8; # required for 5.6
-
- if($self->{opt}->{numericescape} eq '2') {
- $data =~ s/([^\x00-\x7F])/'&#' . ord($1) . ';'/gse;
- }
- else {
- $data =~ s/([^\x00-\xFF])/'&#' . ord($1) . ';'/gse;
- }
-
- return $data;
-}
-
-
-##############################################################################
-# Method: hash_to_array()
-#
-# Helper routine for value_to_xml().
-# Attempts to 'unfold' a hash of hashes into an array of hashes. Returns a
-# reference to the array on success or the original hash if unfolding is
-# not possible.
-#
-
-sub hash_to_array {
- my $self = shift;
- my $parent = shift;
- my $hashref = shift;
-
- my $arrayref = [];
-
- my($key, $value);
-
- my @keys = $self->{opt}->{nosort} ? keys %$hashref : sort keys %$hashref;
- foreach $key (@keys) {
- $value = $hashref->{$key};
- return($hashref) unless(UNIVERSAL::isa($value, 'HASH'));
-
- if(ref($self->{opt}->{keyattr}) eq 'HASH') {
- return($hashref) unless(defined($self->{opt}->{keyattr}->{$parent}));
- push @$arrayref, $self->copy_hash(
- $value, $self->{opt}->{keyattr}->{$parent}->[0] => $key
- );
- }
- else {
- push(@$arrayref, { $self->{opt}->{keyattr}->[0] => $key, %$value });
- }
- }
-
- return($arrayref);
-}
-
-
-##############################################################################
-# Method: copy_hash()
-#
-# Helper routine for hash_to_array(). When unfolding a hash of hashes into
-# an array of hashes, we need to copy the key from the outer hash into the
-# inner hash. This routine makes a copy of the original hash so we don't
-# destroy the original data structure. You might wish to override this
-# method if you're using tied hashes and don't want them to get untied.
-#
-
-sub copy_hash {
- my($self, $orig, @extra) = @_;
-
- return { @extra, %$orig };
-}
-
-##############################################################################
-# Methods required for building trees from SAX events
-##############################################################################
-
-sub start_document {
- my $self = shift;
-
- $self->handle_options('in') unless($self->{opt});
-
- $self->{lists} = [];
- $self->{curlist} = $self->{tree} = [];
-}
-
-
-sub start_element {
- my $self = shift;
- my $element = shift;
-
- my $name = $element->{Name};
- if($self->{opt}->{nsexpand}) {
- $name = $element->{LocalName} || '';
- if($element->{NamespaceURI}) {
- $name = '{' . $element->{NamespaceURI} . '}' . $name;
- }
- }
- my $attributes = {};
- if($element->{Attributes}) { # Might be undef
- foreach my $attr (values %{$element->{Attributes}}) {
- if($self->{opt}->{nsexpand}) {
- my $name = $attr->{LocalName} || '';
- if($attr->{NamespaceURI}) {
- $name = '{' . $attr->{NamespaceURI} . '}' . $name
- }
- $name = 'xmlns' if($name eq $bad_def_ns_jcn);
- $attributes->{$name} = $attr->{Value};
- }
- else {
- $attributes->{$attr->{Name}} = $attr->{Value};
- }
- }
- }
- my $newlist = [ $attributes ];
- push @{ $self->{lists} }, $self->{curlist};
- push @{ $self->{curlist} }, $name => $newlist;
- $self->{curlist} = $newlist;
-}
-
-
-sub characters {
- my $self = shift;
- my $chars = shift;
-
- my $text = $chars->{Data};
- my $clist = $self->{curlist};
- my $pos = $#$clist;
-
- if ($pos > 0 and $clist->[$pos - 1] eq '0') {
- $clist->[$pos] .= $text;
- }
- else {
- push @$clist, 0 => $text;
- }
-}
-
-
-sub end_element {
- my $self = shift;
-
- $self->{curlist} = pop @{ $self->{lists} };
-}
-
-
-sub end_document {
- my $self = shift;
-
- delete($self->{curlist});
- delete($self->{lists});
-
- my $tree = $self->{tree};
- delete($self->{tree});
-
-
- # Return tree as-is to XMLin()
-
- return($tree) if($self->{nocollapse});
-
-
- # Or collapse it before returning it to SAX parser class
-
- if($self->{opt}->{keeproot}) {
- $tree = $self->collapse({}, @$tree);
- }
- else {
- $tree = $self->collapse(@{$tree->[1]});
- }
-
- if($self->{opt}->{datahandler}) {
- return($self->{opt}->{datahandler}->($self, $tree));
- }
-
- return($tree);
-}
-
-*xml_in = \&XMLin;
-*xml_out = \&XMLout;
-
-1;
-
-__END__
-
-=head1 QUICK START
-
-Say you have a script called B<foo> and a file of configuration options
-called B<foo.xml> containing this:
-
- <config logdir="/var/log/foo/" debugfile="/tmp/foo.debug">
- <server name="sahara" osname="solaris" osversion="2.6">
- <address>10.0.0.101</address>
- <address>10.0.1.101</address>
- </server>
- <server name="gobi" osname="irix" osversion="6.5">
- <address>10.0.0.102</address>
- </server>
- <server name="kalahari" osname="linux" osversion="2.0.34">
- <address>10.0.0.103</address>
- <address>10.0.1.103</address>
- </server>
- </config>
-
-The following lines of code in B<foo>:
-
- use XML::Simple;
-
- my $config = XMLin();
-
-will 'slurp' the configuration options into the hashref $config (because no
-arguments are passed to C<XMLin()> the name and location of the XML file will
-be inferred from name and location of the script). You can dump out the
-contents of the hashref using Data::Dumper:
-
- use Data::Dumper;
-
- print Dumper($config);
-
-which will produce something like this (formatting has been adjusted for
-brevity):
-
- {
- 'logdir' => '/var/log/foo/',
- 'debugfile' => '/tmp/foo.debug',
- 'server' => {
- 'sahara' => {
- 'osversion' => '2.6',
- 'osname' => 'solaris',
- 'address' => [ '10.0.0.101', '10.0.1.101' ]
- },
- 'gobi' => {
- 'osversion' => '6.5',
- 'osname' => 'irix',
- 'address' => '10.0.0.102'
- },
- 'kalahari' => {
- 'osversion' => '2.0.34',
- 'osname' => 'linux',
- 'address' => [ '10.0.0.103', '10.0.1.103' ]
- }
- }
- }
-
-Your script could then access the name of the log directory like this:
-
- print $config->{logdir};
-
-similarly, the second address on the server 'kalahari' could be referenced as:
-
- print $config->{server}->{kalahari}->{address}->[1];
-
-What could be simpler? (Rhetorical).
-
-For simple requirements, that's really all there is to it. If you want to
-store your XML in a different directory or file, or pass it in as a string or
-even pass it in via some derivative of an IO::Handle, you'll need to check out
-L<"OPTIONS">. If you want to turn off or tweak the array folding feature (that
-neat little transformation that produced $config->{server}) you'll find options
-for that as well.
-
-If you want to generate XML (for example to write a modified version of
-$config back out as XML), check out C<XMLout()>.
-
-If your needs are not so simple, this may not be the module for you. In that
-case, you might want to read L<"WHERE TO FROM HERE?">.
-
-=head1 DESCRIPTION
-
-The XML::Simple module provides a simple API layer on top of an underlying XML
-parsing module (either XML::Parser or one of the SAX2 parser modules). Two
-functions are exported: C<XMLin()> and C<XMLout()>. Note: you can explicity
-request the lower case versions of the function names: C<xml_in()> and
-C<xml_out()>.
-
-The simplest approach is to call these two functions directly, but an
-optional object oriented interface (see L<"OPTIONAL OO INTERFACE"> below)
-allows them to be called as methods of an B<XML::Simple> object. The object
-interface can also be used at either end of a SAX pipeline.
-
-=head2 XMLin()
-
-Parses XML formatted data and returns a reference to a data structure which
-contains the same information in a more readily accessible form. (Skip
-down to L<"EXAMPLES"> below, for more sample code).
-
-C<XMLin()> accepts an optional XML specifier followed by zero or more 'name =>
-value' option pairs. The XML specifier can be one of the following:
-
-=over 4
-
-=item A filename
-
-If the filename contains no directory components C<XMLin()> will look for the
-file in each directory in the SearchPath (see L<"OPTIONS"> below) or in the
-current directory if the SearchPath option is not defined. eg:
-
- $ref = XMLin('/etc/params.xml');
-
-Note, the filename '-' can be used to parse from STDIN.
-
-=item undef
-
-If there is no XML specifier, C<XMLin()> will check the script directory and
-each of the SearchPath directories for a file with the same name as the script
-but with the extension '.xml'. Note: if you wish to specify options, you
-must specify the value 'undef'. eg:
-
- $ref = XMLin(undef, ForceArray => 1);
-
-=item A string of XML
-
-A string containing XML (recognised by the presence of '<' and '>' characters)
-will be parsed directly. eg:
-
- $ref = XMLin('<opt username="bob" password="flurp" />');
-
-=item An IO::Handle object
-
-An IO::Handle object will be read to EOF and its contents parsed. eg:
-
- $fh = new IO::File('/etc/params.xml');
- $ref = XMLin($fh);
-
-=back
-
-=head2 XMLout()
-
-Takes a data structure (generally a hashref) and returns an XML encoding of
-that structure. If the resulting XML is parsed using C<XMLin()>, it should
-return a data structure equivalent to the original (see caveats below).
-
-The C<XMLout()> function can also be used to output the XML as SAX events
-see the C<Handler> option and L<"SAX SUPPORT"> for more details).
-
-When translating hashes to XML, hash keys which have a leading '-' will be
-silently skipped. This is the approved method for marking elements of a
-data structure which should be ignored by C<XMLout>. (Note: If these items
-were not skipped the key names would be emitted as element or attribute names
-with a leading '-' which would not be valid XML).
-
-=head2 Caveats
-
-Some care is required in creating data structures which will be passed to
-C<XMLout()>. Hash keys from the data structure will be encoded as either XML
-element names or attribute names. Therefore, you should use hash key names
-which conform to the relatively strict XML naming rules:
-
-Names in XML must begin with a letter. The remaining characters may be
-letters, digits, hyphens (-), underscores (_) or full stops (.). It is also
-allowable to include one colon (:) in an element name but this should only be
-used when working with namespaces (B<XML::Simple> can only usefully work with
-namespaces when teamed with a SAX Parser).
-
-You can use other punctuation characters in hash values (just not in hash
-keys) however B<XML::Simple> does not support dumping binary data.
-
-If you break these rules, the current implementation of C<XMLout()> will
-simply emit non-compliant XML which will be rejected if you try to read it
-back in. (A later version of B<XML::Simple> might take a more proactive
-approach).
-
-Note also that although you can nest hashes and arrays to arbitrary levels,
-circular data structures are not supported and will cause C<XMLout()> to die.
-
-If you wish to 'round-trip' arbitrary data structures from Perl to XML and back
-to Perl, then you should probably disable array folding (using the KeyAttr
-option) both with C<XMLout()> and with C<XMLin()>. If you still don't get the
-expected results, you may prefer to use L<XML::Dumper> which is designed for
-exactly that purpose.
-
-Refer to L<"WHERE TO FROM HERE?"> if C<XMLout()> is too simple for your needs.
-
-
-=head1 OPTIONS
-
-B<XML::Simple> supports a number of options (in fact as each release of
-B<XML::Simple> adds more options, the module's claim to the name 'Simple'
-becomes increasingly tenuous). If you find yourself repeatedly having to
-specify the same options, you might like to investigate L<"OPTIONAL OO
-INTERFACE"> below.
-
-If you can't be bothered reading the documentation, refer to
-L<"STRICT MODE"> to automatically catch common mistakes.
-
-Because there are so many options, it's hard for new users to know which ones
-are important, so here are the two you really need to know about:
-
-=over 4
-
-=item *
-
-check out C<ForceArray> because you'll almost certainly want to turn it on
-
-=item *
-
-make sure you know what the C<KeyAttr> option does and what its default value is
-because it may surprise you otherwise (note in particular that 'KeyAttr'
-affects both C<XMLin> and C<XMLout>)
-
-=back
-
-The option name headings below have a trailing 'comment' - a hash followed by
-two pieces of metadata:
-
-=over 4
-
-=item *
-
-Options are marked with 'I<in>' if they are recognised by C<XMLin()> and
-'I<out>' if they are recognised by C<XMLout()>.
-
-=item *
-
-Each option is also flagged to indicate whether it is:
-
- 'important' - don't use the module until you understand this one
- 'handy' - you can skip this on the first time through
- 'advanced' - you can skip this on the second time through
- 'SAX only' - don't worry about this unless you're using SAX (or
- alternatively if you need this, you also need SAX)
- 'seldom used' - you'll probably never use this unless you were the
- person that requested the feature
-
-=back
-
-The options are listed alphabetically:
-
-Note: option names are no longer case sensitive so you can use the mixed case
-versions shown here; all lower case as required by versions 2.03 and earlier;
-or you can add underscores between the words (eg: key_attr).
-
-
-=head2 AttrIndent => 1 I<# out - handy>
-
-When you are using C<XMLout()>, enable this option to have attributes printed
-one-per-line with sensible indentation rather than all on one line.
-
-=head2 Cache => [ cache schemes ] I<# in - advanced>
-
-Because loading the B<XML::Parser> module and parsing an XML file can consume a
-significant number of CPU cycles, it is often desirable to cache the output of
-C<XMLin()> for later reuse.
-
-When parsing from a named file, B<XML::Simple> supports a number of caching
-schemes. The 'Cache' option may be used to specify one or more schemes (using
-an anonymous array). Each scheme will be tried in turn in the hope of finding
-a cached pre-parsed representation of the XML file. If no cached copy is
-found, the file will be parsed and the first cache scheme in the list will be
-used to save a copy of the results. The following cache schemes have been
-implemented:
-
-=over 4
-
-=item storable
-
-Utilises B<Storable.pm> to read/write a cache file with the same name as the
-XML file but with the extension .stor
-
-=item memshare
-
-When a file is first parsed, a copy of the resulting data structure is retained
-in memory in the B<XML::Simple> module's namespace. Subsequent calls to parse
-the same file will return a reference to this structure. This cached version
-will persist only for the life of the Perl interpreter (which in the case of
-mod_perl for example, may be some significant time).
-
-Because each caller receives a reference to the same data structure, a change
-made by one caller will be visible to all. For this reason, the reference
-returned should be treated as read-only.
-
-=item memcopy
-
-This scheme works identically to 'memshare' (above) except that each caller
-receives a reference to a new data structure which is a copy of the cached
-version. Copying the data structure will add a little processing overhead,
-therefore this scheme should only be used where the caller intends to modify
-the data structure (or wishes to protect itself from others who might). This
-scheme uses B<Storable.pm> to perform the copy.
-
-=back
-
-Warning! The memory-based caching schemes compare the timestamp on the file to
-the time when it was last parsed. If the file is stored on an NFS filesystem
-(or other network share) and the clock on the file server is not exactly
-synchronised with the clock where your script is run, updates to the source XML
-file may appear to be ignored.
-
-=head2 ContentKey => 'keyname' I<# in+out - seldom used>
-
-When text content is parsed to a hash value, this option let's you specify a
-name for the hash key to override the default 'content'. So for example:
-
- XMLin('<opt one="1">Text</opt>', ContentKey => 'text')
-
-will parse to:
-
- { 'one' => 1, 'text' => 'Text' }
-
-instead of:
-
- { 'one' => 1, 'content' => 'Text' }
-
-C<XMLout()> will also honour the value of this option when converting a hashref
-to XML.
-
-You can also prefix your selected key name with a '-' character to have
-C<XMLin()> try a little harder to eliminate unnecessary 'content' keys after
-array folding. For example:
-
- XMLin(
- '<opt><item name="one">First</item><item name="two">Second</item></opt>',
- KeyAttr => {item => 'name'},
- ForceArray => [ 'item' ],
- ContentKey => '-content'
- )
-
-will parse to:
-
- {
- 'item' => {
- 'one' => 'First'
- 'two' => 'Second'
- }
- }
-
-rather than this (without the '-'):
-
- {
- 'item' => {
- 'one' => { 'content' => 'First' }
- 'two' => { 'content' => 'Second' }
- }
- }
-
-=head2 DataHandler => code_ref I<# in - SAX only>
-
-When you use an B<XML::Simple> object as a SAX handler, it will return a
-'simple tree' data structure in the same format as C<XMLin()> would return. If
-this option is set (to a subroutine reference), then when the tree is built the
-subroutine will be called and passed two arguments: a reference to the
-B<XML::Simple> object and a reference to the data tree. The return value from
-the subroutine will be returned to the SAX driver. (See L<"SAX SUPPORT"> for
-more details).
-
-=head2 ForceArray => 1 I<# in - important>
-
-This option should be set to '1' to force nested elements to be represented
-as arrays even when there is only one. Eg, with ForceArray enabled, this
-XML:
-
- <opt>
- <name>value</name>
- </opt>
-
-would parse to this:
-
- {
- 'name' => [
- 'value'
- ]
- }
-
-instead of this (the default):
-
- {
- 'name' => 'value'
- }
-
-This option is especially useful if the data structure is likely to be written
-back out as XML and the default behaviour of rolling single nested elements up
-into attributes is not desirable.
-
-If you are using the array folding feature, you should almost certainly enable
-this option. If you do not, single nested elements will not be parsed to
-arrays and therefore will not be candidates for folding to a hash. (Given that
-the default value of 'KeyAttr' enables array folding, the default value of this
-option should probably also have been enabled too - sorry).
-
-=head2 ForceArray => [ names ] I<# in - important>
-
-This alternative (and preferred) form of the 'ForceArray' option allows you to
-specify a list of element names which should always be forced into an array
-representation, rather than the 'all or nothing' approach above.
-
-It is also possible (since version 2.05) to include compiled regular
-expressions in the list - any element names which match the pattern will be
-forced to arrays. If the list contains only a single regex, then it is not
-necessary to enclose it in an arrayref. Eg:
-
- ForceArray => qr/_list$/
-
-=head2 ForceContent => 1 I<# in - seldom used>
-
-When C<XMLin()> parses elements which have text content as well as attributes,
-the text content must be represented as a hash value rather than a simple
-scalar. This option allows you to force text content to always parse to
-a hash value even when there are no attributes. So for example:
-
- XMLin('<opt><x>text1</x><y a="2">text2</y></opt>', ForceContent => 1)
-
-will parse to:
-
- {
- 'x' => { 'content' => 'text1' },
- 'y' => { 'a' => 2, 'content' => 'text2' }
- }
-
-instead of:
-
- {
- 'x' => 'text1',
- 'y' => { 'a' => 2, 'content' => 'text2' }
- }
-
-=head2 GroupTags => { grouping tag => grouped tag } I<# in+out - handy>
-
-You can use this option to eliminate extra levels of indirection in your Perl
-data structure. For example this XML:
-
- <opt>
- <searchpath>
- <dir>/usr/bin</dir>
- <dir>/usr/local/bin</dir>
- <dir>/usr/X11/bin</dir>
- </searchpath>
- </opt>
-
-Would normally be read into a structure like this:
-
- {
- searchpath => {
- dir => [ '/usr/bin', '/usr/local/bin', '/usr/X11/bin' ]
- }
- }
-
-But when read in with the appropriate value for 'GroupTags':
-
- my $opt = XMLin($xml, GroupTags => { searchpath => 'dir' });
-
-It will return this simpler structure:
-
- {
- searchpath => [ '/usr/bin', '/usr/local/bin', '/usr/X11/bin' ]
- }
-
-The grouping element (C<< <searchpath> >> in the example) must not contain any
-attributes or elements other than the grouped element.
-
-You can specify multiple 'grouping element' to 'grouped element' mappings in
-the same hashref. If this option is combined with C<KeyAttr>, the array
-folding will occur first and then the grouped element names will be eliminated.
-
-C<XMLout> will also use the grouptag mappings to re-introduce the tags around
-the grouped elements. Beware though that this will occur in all places that
-the 'grouping tag' name occurs - you probably don't want to use the same name
-for elements as well as attributes.
-
-=head2 Handler => object_ref I<# out - SAX only>
-
-Use the 'Handler' option to have C<XMLout()> generate SAX events rather than
-returning a string of XML. For more details see L<"SAX SUPPORT"> below.
-
-Note: the current implementation of this option generates a string of XML
-and uses a SAX parser to translate it into SAX events. The normal encoding
-rules apply here - your data must be UTF8 encoded unless you specify an
-alternative encoding via the 'XMLDecl' option; and by the time the data reaches
-the handler object, it will be in UTF8 form regardless of the encoding you
-supply. A future implementation of this option may generate the events
-directly.
-
-=head2 KeepRoot => 1 I<# in+out - handy>
-
-In its attempt to return a data structure free of superfluous detail and
-unnecessary levels of indirection, C<XMLin()> normally discards the root
-element name. Setting the 'KeepRoot' option to '1' will cause the root element
-name to be retained. So after executing this code:
-
- $config = XMLin('<config tempdir="/tmp" />', KeepRoot => 1)
-
-You'll be able to reference the tempdir as
-C<$config-E<gt>{config}-E<gt>{tempdir}> instead of the default
-C<$config-E<gt>{tempdir}>.
-
-Similarly, setting the 'KeepRoot' option to '1' will tell C<XMLout()> that the
-data structure already contains a root element name and it is not necessary to
-add another.
-
-=head2 KeyAttr => [ list ] I<# in+out - important>
-
-This option controls the 'array folding' feature which translates nested
-elements from an array to a hash. It also controls the 'unfolding' of hashes
-to arrays.
-
-For example, this XML:
-
- <opt>
- <user login="grep" fullname="Gary R Epstein" />
- <user login="stty" fullname="Simon T Tyson" />
- </opt>
-
-would, by default, parse to this:
-
- {
- 'user' => [
- {
- 'login' => 'grep',
- 'fullname' => 'Gary R Epstein'
- },
- {
- 'login' => 'stty',
- 'fullname' => 'Simon T Tyson'
- }
- ]
- }
-
-If the option 'KeyAttr => "login"' were used to specify that the 'login'
-attribute is a key, the same XML would parse to:
-
- {
- 'user' => {
- 'stty' => {
- 'fullname' => 'Simon T Tyson'
- },
- 'grep' => {
- 'fullname' => 'Gary R Epstein'
- }
- }
- }
-
-The key attribute names should be supplied in an arrayref if there is more
-than one. C<XMLin()> will attempt to match attribute names in the order
-supplied. C<XMLout()> will use the first attribute name supplied when
-'unfolding' a hash into an array.
-
-Note 1: The default value for 'KeyAttr' is ['name', 'key', 'id']. If you do
-not want folding on input or unfolding on output you must setting this option
-to an empty list to disable the feature.
-
-Note 2: If you wish to use this option, you should also enable the
-C<ForceArray> option. Without 'ForceArray', a single nested element will be
-rolled up into a scalar rather than an array and therefore will not be folded
-(since only arrays get folded).
-
-=head2 KeyAttr => { list } I<# in+out - important>
-
-This alternative (and preferred) method of specifiying the key attributes
-allows more fine grained control over which elements are folded and on which
-attributes. For example the option 'KeyAttr => { package => 'id' } will cause
-any package elements to be folded on the 'id' attribute. No other elements
-which have an 'id' attribute will be folded at all.
-
-Note: C<XMLin()> will generate a warning (or a fatal error in L<"STRICT MODE">)
-if this syntax is used and an element which does not have the specified key
-attribute is encountered (eg: a 'package' element without an 'id' attribute, to
-use the example above). Warnings will only be generated if B<-w> is in force.
-
-Two further variations are made possible by prefixing a '+' or a '-' character
-to the attribute name:
-
-The option 'KeyAttr => { user => "+login" }' will cause this XML:
-
- <opt>
- <user login="grep" fullname="Gary R Epstein" />
- <user login="stty" fullname="Simon T Tyson" />
- </opt>
-
-to parse to this data structure:
-
- {
- 'user' => {
- 'stty' => {
- 'fullname' => 'Simon T Tyson',
- 'login' => 'stty'
- },
- 'grep' => {
- 'fullname' => 'Gary R Epstein',
- 'login' => 'grep'
- }
- }
- }
-
-The '+' indicates that the value of the key attribute should be copied rather
-than moved to the folded hash key.
-
-A '-' prefix would produce this result:
-
- {
- 'user' => {
- 'stty' => {
- 'fullname' => 'Simon T Tyson',
- '-login' => 'stty'
- },
- 'grep' => {
- 'fullname' => 'Gary R Epstein',
- '-login' => 'grep'
- }
- }
- }
-
-As described earlier, C<XMLout> will ignore hash keys starting with a '-'.
-
-=head2 NoAttr => 1 I<# in+out - handy>
-
-When used with C<XMLout()>, the generated XML will contain no attributes.
-All hash key/values will be represented as nested elements instead.
-
-When used with C<XMLin()>, any attributes in the XML will be ignored.
-
-=head2 NoEscape => 1 I<# out - seldom used>
-
-By default, C<XMLout()> will translate the characters 'E<lt>', 'E<gt>', '&' and
-'"' to '&lt;', '&gt;', '&amp;' and '&quot' respectively. Use this option to
-suppress escaping (presumably because you've already escaped the data in some
-more sophisticated manner).
-
-=head2 NoIndent => 1 I<# out - seldom used>
-
-Set this option to 1 to disable C<XMLout()>'s default 'pretty printing' mode.
-With this option enabled, the XML output will all be on one line (unless there
-are newlines in the data) - this may be easier for downstream processing.
-
-=head2 NoSort => 1 I<# out - seldom used>
-
-Newer versions of XML::Simple sort elements and attributes alphabetically (*),
-by default. Enable this option to suppress the sorting - possibly for
-backwards compatibility.
-
-* Actually, sorting is alphabetical but 'key' attribute or element names (as in
-'KeyAttr') sort first. Also, when a hash of hashes is 'unfolded', the elements
-are sorted alphabetically by the value of the key field.
-
-=head2 NormaliseSpace => 0 | 1 | 2 I<# in - handy>
-
-This option controls how whitespace in text content is handled. Recognised
-values for the option are:
-
-=over 4
-
-=item *
-
-0 = (default) whitespace is passed through unaltered (except of course for the
-normalisation of whitespace in attribute values which is mandated by the XML
-recommendation)
-
-=item *
-
-1 = whitespace is normalised in any value used as a hash key (normalising means
-removing leading and trailing whitespace and collapsing sequences of whitespace
-characters to a single space)
-
-=item *
-
-2 = whitespace is normalised in all text content
-
-=back
-
-Note: you can spell this option with a 'z' if that is more natural for you.
-
-=head2 NSExpand => 1 I<# in+out handy - SAX only>
-
-This option controls namespace expansion - the translation of element and
-attribute names of the form 'prefix:name' to '{uri}name'. For example the
-element name 'xsl:template' might be expanded to:
-'{http://www.w3.org/1999/XSL/Transform}template'.
-
-By default, C<XMLin()> will return element names and attribute names exactly as
-they appear in the XML. Setting this option to 1 will cause all element and
-attribute names to be expanded to include their namespace prefix.
-
-I<Note: You must be using a SAX parser for this option to work (ie: it does not
-work with XML::Parser)>.
-
-This option also controls whether C<XMLout()> performs the reverse translation
-from '{uri}name' back to 'prefix:name'. The default is no translation. If
-your data contains expanded names, you should set this option to 1 otherwise
-C<XMLout> will emit XML which is not well formed.
-
-I<Note: You must have the XML::NamespaceSupport module installed if you want
-C<XMLout()> to translate URIs back to prefixes>.
-
-=head2 NumericEscape => 0 | 1 | 2 I<# out - handy>
-
-Use this option to have 'high' (non-ASCII) characters in your Perl data
-structure converted to numeric entities (eg: &#8364;) in the XML output. Three
-levels are possible:
-
-0 - default: no numeric escaping (OK if you're writing out UTF8)
-
-1 - only characters above 0xFF are escaped (ie: characters in the 0x80-FF range are not escaped), possibly useful with ISO8859-1 output
-
-2 - all characters above 0x7F are escaped (good for plain ASCII output)
-
-=head2 OutputFile => <file specifier> I<# out - handy>
-
-The default behaviour of C<XMLout()> is to return the XML as a string. If you
-wish to write the XML to a file, simply supply the filename using the
-'OutputFile' option.
-
-This option also accepts an IO handle object - especially useful in Perl 5.8.0
-and later for output using an encoding other than UTF-8, eg:
-
- open my $fh, '>:encoding(iso-8859-1)', $path or die "open($path): $!";
- XMLout($ref, OutputFile => $fh);
-
-=head2 ParserOpts => [ XML::Parser Options ] I<# in - don't use this>
-
-I<Note: This option is now officially deprecated. If you find it useful, email
-the author with an example of what you use it for. Do not use this option to
-set the ProtocolEncoding, that's just plain wrong - fix the XML>.
-
-This option allows you to pass parameters to the constructor of the underlying
-XML::Parser object (which of course assumes you're not using SAX).
-
-=head2 RootName => 'string' I<# out - handy>
-
-By default, when C<XMLout()> generates XML, the root element will be named
-'opt'. This option allows you to specify an alternative name.
-
-Specifying either undef or the empty string for the RootName option will
-produce XML with no root elements. In most cases the resulting XML fragment
-will not be 'well formed' and therefore could not be read back in by C<XMLin()>.
-Nevertheless, the option has been found to be useful in certain circumstances.
-
-=head2 SearchPath => [ list ] I<# in - handy>
-
-If you pass C<XMLin()> a filename, but the filename include no directory
-component, you can use this option to specify which directories should be
-searched to locate the file. You might use this option to search first in the
-user's home directory, then in a global directory such as /etc.
-
-If a filename is provided to C<XMLin()> but SearchPath is not defined, the
-file is assumed to be in the current directory.
-
-If the first parameter to C<XMLin()> is undefined, the default SearchPath
-will contain only the directory in which the script itself is located.
-Otherwise the default SearchPath will be empty.
-
-=head2 SuppressEmpty => 1 | '' | undef I<# in+out - handy>
-
-This option controls what C<XMLin()> should do with empty elements (no
-attributes and no content). The default behaviour is to represent them as
-empty hashes. Setting this option to a true value (eg: 1) will cause empty
-elements to be skipped altogether. Setting the option to 'undef' or the empty
-string will cause empty elements to be represented as the undefined value or
-the empty string respectively. The latter two alternatives are a little
-easier to test for in your code than a hash with no keys.
-
-The option also controls what C<XMLout()> does with undefined values. Setting
-the option to undef causes undefined values to be output as empty elements
-(rather than empty attributes), it also suppresses the generation of warnings
-about undefined values. Setting the option to a true value (eg: 1) causes
-undefined values to be skipped altogether on output.
-
-=head2 ValueAttr => [ names ] I<# in - handy>
-
-Use this option to deal elements which always have a single attribute and no
-content. Eg:
-
- <opt>
- <colour value="red" />
- <size value="XXL" />
- </opt>
-
-Setting C<< ValueAttr => [ 'value' ] >> will cause the above XML to parse to:
-
- {
- colour => 'red',
- size => 'XXL'
- }
-
-instead of this (the default):
-
- {
- colour => { value => 'red' },
- size => { value => 'XXL' }
- }
-
-Note: This form of the ValueAttr option is not compatible with C<XMLout()> -
-since the attribute name is discarded at parse time, the original XML cannot be
-reconstructed.
-
-=head2 ValueAttr => { element => attribute, ... } I<# in+out - handy>
-
-This (preferred) form of the ValueAttr option requires you to specify both
-the element and the attribute names. This is not only safer, it also allows
-the original XML to be reconstructed by C<XMLout()>.
-
-Note: You probably don't want to use this option and the NoAttr option at the
-same time.
-
-=head2 Variables => { name => value } I<# in - handy>
-
-This option allows variables in the XML to be expanded when the file is read.
-(there is no facility for putting the variable names back if you regenerate
-XML using C<XMLout>).
-
-A 'variable' is any text of the form C<${name}> which occurs in an attribute
-value or in the text content of an element. If 'name' matches a key in the
-supplied hashref, C<${name}> will be replaced with the corresponding value from
-the hashref. If no matching key is found, the variable will not be replaced.
-
-=head2 VarAttr => 'attr_name' I<# in - handy>
-
-In addition to the variables defined using C<Variables>, this option allows
-variables to be defined in the XML. A variable definition consists of an
-element with an attribute called 'attr_name' (the value of the C<VarAttr>
-option). The value of the attribute will be used as the variable name and the
-text content of the element will be used as the value. A variable defined in
-this way will override a variable defined using the C<Variables> option. For
-example:
-
- XMLin( '<opt>
- <dir name="prefix">/usr/local/apache</dir>
- <dir name="exec_prefix">${prefix}</dir>
- <dir name="bindir">${exec_prefix}/bin</dir>
- </opt>',
- VarAttr => 'name', ContentKey => '-content'
- );
-
-produces the following data structure:
-
- {
- dir => {
- prefix => '/usr/local/apache',
- exec_prefix => '/usr/local/apache',
- bindir => '/usr/local/apache/bin',
- }
- }
-
-=head2 XMLDecl => 1 or XMLDecl => 'string' I<# out - handy>
-
-If you want the output from C<XMLout()> to start with the optional XML
-declaration, simply set the option to '1'. The default XML declaration is:
-
- <?xml version='1.0' standalone='yes'?>
-
-If you want some other string (for example to declare an encoding value), set
-the value of this option to the complete string you require.
-
-
-=head1 OPTIONAL OO INTERFACE
-
-The procedural interface is both simple and convenient however there are a
-couple of reasons why you might prefer to use the object oriented (OO)
-interface:
-
-=over 4
-
-=item *
-
-to define a set of default values which should be used on all subsequent calls
-to C<XMLin()> or C<XMLout()>
-
-=item *
-
-to override methods in B<XML::Simple> to provide customised behaviour
-
-=back
-
-The default values for the options described above are unlikely to suit
-everyone. The OO interface allows you to effectively override B<XML::Simple>'s
-defaults with your preferred values. It works like this:
-
-First create an XML::Simple parser object with your preferred defaults:
-
- my $xs = new XML::Simple(ForceArray => 1, KeepRoot => 1);
-
-then call C<XMLin()> or C<XMLout()> as a method of that object:
-
- my $ref = $xs->XMLin($xml);
- my $xml = $xs->XMLout($ref);
-
-You can also specify options when you make the method calls and these values
-will be merged with the values specified when the object was created. Values
-specified in a method call take precedence.
-
-Overriding methods is a more advanced topic but might be useful if for example
-you wished to provide an alternative routine for escaping character data (the
-escape_value method) or for building the initial parse tree (the build_tree
-method).
-
-Note: when called as methods, the C<XMLin()> and C<XMLout()> routines may be
-called as C<xml_in()> or C<xml_out()>. The method names are aliased so the
-only difference is the aesthetics.
-
-=head1 STRICT MODE
-
-If you import the B<XML::Simple> routines like this:
-
- use XML::Simple qw(:strict);
-
-the following common mistakes will be detected and treated as fatal errors
-
-=over 4
-
-=item *
-
-Failing to explicitly set the C<KeyAttr> option - if you can't be bothered
-reading about this option, turn it off with: KeyAttr => [ ]
-
-=item *
-
-Failing to explicitly set the C<ForceArray> option - if you can't be bothered
-reading about this option, set it to the safest mode with: ForceArray => 1
-
-=item *
-
-Setting ForceArray to an array, but failing to list all the elements from the
-KeyAttr hash.
-
-=item *
-
-Data error - KeyAttr is set to say { part => 'partnum' } but the XML contains
-one or more E<lt>partE<gt> elements without a 'partnum' attribute (or nested
-element). Note: if strict mode is not set but -w is, this condition triggers a
-warning.
-
-=item *
-
-Data error - as above, but value of key attribute (eg: partnum) is not a
-scalar string (due to nested elements etc). This will also trigger a warning
-if strict mode is not enabled.
-
-=back
-
-=head1 SAX SUPPORT
-
-From version 1.08_01, B<XML::Simple> includes support for SAX (the Simple API
-for XML) - specifically SAX2.
-
-In a typical SAX application, an XML parser (or SAX 'driver') module generates
-SAX events (start of element, character data, end of element, etc) as it parses
-an XML document and a 'handler' module processes the events to extract the
-required data. This simple model allows for some interesting and powerful
-possibilities:
-
-=over 4
-
-=item *
-
-Applications written to the SAX API can extract data from huge XML documents
-without the memory overheads of a DOM or tree API.
-
-=item *
-
-The SAX API allows for plug and play interchange of parser modules without
-having to change your code to fit a new module's API. A number of SAX parsers
-are available with capabilities ranging from extreme portability to blazing
-performance.
-
-=item *
-
-A SAX 'filter' module can implement both a handler interface for receiving
-data and a generator interface for passing modified data on to a downstream
-handler. Filters can be chained together in 'pipelines'.
-
-=item *
-
-One filter module might split a data stream to direct data to two or more
-downstream handlers.
-
-=item *
-
-Generating SAX events is not the exclusive preserve of XML parsing modules.
-For example, a module might extract data from a relational database using DBI
-and pass it on to a SAX pipeline for filtering and formatting.
-
-=back
-
-B<XML::Simple> can operate at either end of a SAX pipeline. For example,
-you can take a data structure in the form of a hashref and pass it into a
-SAX pipeline using the 'Handler' option on C<XMLout()>:
-
- use XML::Simple;
- use Some::SAX::Filter;
- use XML::SAX::Writer;
-
- my $ref = {
- .... # your data here
- };
-
- my $writer = XML::SAX::Writer->new();
- my $filter = Some::SAX::Filter->new(Handler => $writer);
- my $simple = XML::Simple->new(Handler => $filter);
- $simple->XMLout($ref);
-
-You can also put B<XML::Simple> at the opposite end of the pipeline to take
-advantage of the simple 'tree' data structure once the relevant data has been
-isolated through filtering:
-
- use XML::SAX;
- use Some::SAX::Filter;
- use XML::Simple;
-
- my $simple = XML::Simple->new(ForceArray => 1, KeyAttr => ['partnum']);
- my $filter = Some::SAX::Filter->new(Handler => $simple);
- my $parser = XML::SAX::ParserFactory->parser(Handler => $filter);
-
- my $ref = $parser->parse_uri('some_huge_file.xml');
-
- print $ref->{part}->{'555-1234'};
-
-You can build a filter by using an XML::Simple object as a handler and setting
-its DataHandler option to point to a routine which takes the resulting tree,
-modifies it and sends it off as SAX events to a downstream handler:
-
- my $writer = XML::SAX::Writer->new();
- my $filter = XML::Simple->new(
- DataHandler => sub {
- my $simple = shift;
- my $data = shift;
-
- # Modify $data here
-
- $simple->XMLout($data, Handler => $writer);
- }
- );
- my $parser = XML::SAX::ParserFactory->parser(Handler => $filter);
-
- $parser->parse_uri($filename);
-
-I<Note: In this last example, the 'Handler' option was specified in the call to
-C<XMLout()> but it could also have been specified in the constructor>.
-
-=head1 ENVIRONMENT
-
-If you don't care which parser module B<XML::Simple> uses then skip this
-section entirely (it looks more complicated than it really is).
-
-B<XML::Simple> will default to using a B<SAX> parser if one is available or
-B<XML::Parser> if SAX is not available.
-
-You can dictate which parser module is used by setting either the environment
-variable 'XML_SIMPLE_PREFERRED_PARSER' or the package variable
-$XML::Simple::PREFERRED_PARSER to contain the module name. The following rules
-are used:
-
-=over 4
-
-=item *
-
-The package variable takes precedence over the environment variable if both are defined. To force B<XML::Simple> to ignore the environment settings and use
-its default rules, you can set the package variable to an empty string.
-
-=item *
-
-If the 'preferred parser' is set to the string 'XML::Parser', then
-L<XML::Parser> will be used (or C<XMLin()> will die if L<XML::Parser> is not
-installed).
-
-=item *
-
-If the 'preferred parser' is set to some other value, then it is assumed to be
-the name of a SAX parser module and is passed to L<XML::SAX::ParserFactory.>
-If L<XML::SAX> is not installed, or the requested parser module is not
-installed, then C<XMLin()> will die.
-
-=item *
-
-If the 'preferred parser' is not defined at all (the normal default
-state), an attempt will be made to load L<XML::SAX>. If L<XML::SAX> is
-installed, then a parser module will be selected according to
-L<XML::SAX::ParserFactory>'s normal rules (which typically means the last SAX
-parser installed).
-
-=item *
-
-if the 'preferred parser' is not defined and B<XML::SAX> is not
-installed, then B<XML::Parser> will be used. C<XMLin()> will die if
-L<XML::Parser> is not installed.
-
-=back
-
-Note: The B<XML::SAX> distribution includes an XML parser written entirely in
-Perl. It is very portable but it is not very fast. You should consider
-installing L<XML::LibXML> or L<XML::SAX::Expat> if they are available for your
-platform.
-
-=head1 ERROR HANDLING
-
-The XML standard is very clear on the issue of non-compliant documents. An
-error in parsing any single element (for example a missing end tag) must cause
-the whole document to be rejected. B<XML::Simple> will die with an appropriate
-message if it encounters a parsing error.
-
-If dying is not appropriate for your application, you should arrange to call
-C<XMLin()> in an eval block and look for errors in $@. eg:
-
- my $config = eval { XMLin() };
- PopUpMessage($@) if($@);
-
-Note, there is a common misconception that use of B<eval> will significantly
-slow down a script. While that may be true when the code being eval'd is in a
-string, it is not true of code like the sample above.
-
-=head1 EXAMPLES
-
-When C<XMLin()> reads the following very simple piece of XML:
-
- <opt username="testuser" password="frodo"></opt>
-
-it returns the following data structure:
-
- {
- 'username' => 'testuser',
- 'password' => 'frodo'
- }
-
-The identical result could have been produced with this alternative XML:
-
- <opt username="testuser" password="frodo" />
-
-Or this (although see 'ForceArray' option for variations):
-
- <opt>
- <username>testuser</username>
- <password>frodo</password>
- </opt>
-
-Repeated nested elements are represented as anonymous arrays:
-
- <opt>
- <person firstname="Joe" lastname="Smith">
- <email>joe@smith.com</email>
- <email>jsmith@yahoo.com</email>
- </person>
- <person firstname="Bob" lastname="Smith">
- <email>bob@smith.com</email>
- </person>
- </opt>
-
- {
- 'person' => [
- {
- 'email' => [
- 'joe@smith.com',
- 'jsmith@yahoo.com'
- ],
- 'firstname' => 'Joe',
- 'lastname' => 'Smith'
- },
- {
- 'email' => 'bob@smith.com',
- 'firstname' => 'Bob',
- 'lastname' => 'Smith'
- }
- ]
- }
-
-Nested elements with a recognised key attribute are transformed (folded) from
-an array into a hash keyed on the value of that attribute (see the C<KeyAttr>
-option):
-
- <opt>
- <person key="jsmith" firstname="Joe" lastname="Smith" />
- <person key="tsmith" firstname="Tom" lastname="Smith" />
- <person key="jbloggs" firstname="Joe" lastname="Bloggs" />
- </opt>
-
- {
- 'person' => {
- 'jbloggs' => {
- 'firstname' => 'Joe',
- 'lastname' => 'Bloggs'
- },
- 'tsmith' => {
- 'firstname' => 'Tom',
- 'lastname' => 'Smith'
- },
- 'jsmith' => {
- 'firstname' => 'Joe',
- 'lastname' => 'Smith'
- }
- }
- }
-
-
-The <anon> tag can be used to form anonymous arrays:
-
- <opt>
- <head><anon>Col 1</anon><anon>Col 2</anon><anon>Col 3</anon></head>
- <data><anon>R1C1</anon><anon>R1C2</anon><anon>R1C3</anon></data>
- <data><anon>R2C1</anon><anon>R2C2</anon><anon>R2C3</anon></data>
- <data><anon>R3C1</anon><anon>R3C2</anon><anon>R3C3</anon></data>
- </opt>
-
- {
- 'head' => [
- [ 'Col 1', 'Col 2', 'Col 3' ]
- ],
- 'data' => [
- [ 'R1C1', 'R1C2', 'R1C3' ],
- [ 'R2C1', 'R2C2', 'R2C3' ],
- [ 'R3C1', 'R3C2', 'R3C3' ]
- ]
- }
-
-Anonymous arrays can be nested to arbirtrary levels and as a special case, if
-the surrounding tags for an XML document contain only an anonymous array the
-arrayref will be returned directly rather than the usual hashref:
-
- <opt>
- <anon><anon>Col 1</anon><anon>Col 2</anon></anon>
- <anon><anon>R1C1</anon><anon>R1C2</anon></anon>
- <anon><anon>R2C1</anon><anon>R2C2</anon></anon>
- </opt>
-
- [
- [ 'Col 1', 'Col 2' ],
- [ 'R1C1', 'R1C2' ],
- [ 'R2C1', 'R2C2' ]
- ]
-
-Elements which only contain text content will simply be represented as a
-scalar. Where an element has both attributes and text content, the element
-will be represented as a hashref with the text content in the 'content' key
-(see the C<ContentKey> option):
-
- <opt>
- <one>first</one>
- <two attr="value">second</two>
- </opt>
-
- {
- 'one' => 'first',
- 'two' => { 'attr' => 'value', 'content' => 'second' }
- }
-
-Mixed content (elements which contain both text content and nested elements)
-will be not be represented in a useful way - element order and significant
-whitespace will be lost. If you need to work with mixed content, then
-XML::Simple is not the right tool for your job - check out the next section.
-
-=head1 WHERE TO FROM HERE?
-
-B<XML::Simple> is able to present a simple API because it makes some
-assumptions on your behalf. These include:
-
-=over 4
-
-=item *
-
-You're not interested in text content consisting only of whitespace
-
-=item *
-
-You don't mind that when things get slurped into a hash the order is lost
-
-=item *
-
-You don't want fine-grained control of the formatting of generated XML
-
-=item *
-
-You would never use a hash key that was not a legal XML element name
-
-=item *
-
-You don't need help converting between different encodings
-
-=back
-
-In a serious XML project, you'll probably outgrow these assumptions fairly
-quickly. This section of the document used to offer some advice on chosing a
-more powerful option. That advice has now grown into the 'Perl-XML FAQ'
-document which you can find at: L<http://perl-xml.sourceforge.net/faq/>
-
-The advice in the FAQ boils down to a quick explanation of tree versus
-event based parsers and then recommends:
-
-For event based parsing, use SAX (do not set out to write any new code for
-XML::Parser's handler API - it is obselete).
-
-For tree-based parsing, you could choose between the 'Perlish' approach of
-L<XML::Twig> and more standards based DOM implementations - preferably one with
-XPath support.
-
-
-=head1 SEE ALSO
-
-B<XML::Simple> requires either L<XML::Parser> or L<XML::SAX>.
-
-To generate documents with namespaces, L<XML::NamespaceSupport> is required.
-
-The optional caching functions require L<Storable>.
-
-Answers to Frequently Asked Questions about XML::Simple are bundled with this
-distribution as: L<XML::Simple::FAQ>
-
-=head1 COPYRIGHT
-
-Copyright 1999-2004 Grant McLean E<lt>grantm@cpan.orgE<gt>
-
-This library is free software; you can redistribute it and/or modify it
-under the same terms as Perl itself.
-
-=cut
-
-
diff --git a/lib/XML/Stream.pm b/lib/XML/Stream.pm
deleted file mode 100644
index f95f784..0000000
--- a/lib/XML/Stream.pm
+++ /dev/null
@@ -1,3268 +0,0 @@
-##############################################################################
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Library General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Library General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-# Jabber
-# Copyright (C) 1998-2004 Jabber Software Foundation http://jabber.org/
-#
-##############################################################################
-
-package XML::Stream;
-
-=head1 NAME
-
-XML::Stream - Creates and XML Stream connection and parses return data
-
-=head1 SYNOPSIS
-
- XML::Stream is an attempt at solidifying the use of XML via streaming.
-
-=head1 DESCRIPTION
-
- This module provides the user with methods to connect to a remote
- server, send a stream of XML to the server, and receive/parse an XML
- stream from the server. It is primarily based work for the Etherx XML
- router developed by the Jabber Development Team. For more information
- about this project visit http://etherx.jabber.org/stream/.
-
- XML::Stream gives the user the ability to define a central callback
- that will be used to handle the tags received from the server. These
- tags are passed in the format defined at instantiation time.
- the closing tag of an object is seen, the tree is finished and passed
- to the call back function. What the user does with it from there is up
- to them.
-
- For a detailed description of how this module works, and about the data
- structure that it returns, please view the source of Stream.pm and
- look at the detailed description at the end of the file.
-
-
- NOTE: The parser that XML::Stream::Parser provides, as are most Perl
- parsers, is synchronous. If you are in the middle of parsing a
- packet and call a user defined callback, the Parser is blocked until
- your callback finishes. This means you cannot be operating on a
- packet, send out another packet and wait for a response to that packet.
- It will never get to you. Threading might solve this, but as we all
- know threading in Perl is not quite up to par yet. This issue will be
- revisted in the future.
-
-
-
-=head1 METHODS
-
- new(debug=>string, - creates the XML::Stream object. debug
- debugfh=>FileHandle, should be set to the path for the debug log
- debuglevel=>0|1|N, to be written. If set to "stdout" then the
- debugtime=>0|1, debug will go there. Also, you can specify
- style=>string) a filehandle that already exists byt using
- debugfh. debuglevel determines the amount
- of debug to generate. 0 is the least, 1 is
- a little more, N is the limit you want.
- debugtime determines wether a timestamp
- should be preappended to the entry. style
- defines the way the data structure is
- returned. The two available styles are:
-
- tree - XML::Parser Tree format
- node - XML::Stream::Node format
-
- For more information see the respective man
- pages.
-
- Connect(hostname=>string, - opens a tcp connection to the
- port=>integer, specified server and sends the proper
- to=>string, opening XML Stream tag. hostname,
- from=>string, port, and namespace are required.
- myhostname=>string, namespaces allows you to use
- namespace=>string, XML::Stream::Namespace objects.
- namespaces=>array, to is needed if you want the stream
- connectiontype=>string, to attribute to be something other
- ssl=>0|1, than the hostname you are connecting
- srv=>string) to. from is needed if you want the
- stream from attribute to be something
- other than the hostname you are
- connecting from. myhostname should
- not be needed but if the module
- cannot determine your hostname
- properly (check the debug log), set
- this to the correct value, or if you
- want the other side of the stream to
- think that you are someone else. The
- type determines the kind of
- connection that is made:
- "tcpip" - TCP/IP (default)
- "stdinout" - STDIN/STDOUT
- "http" - HTTP
- HTTP recognizes proxies if the ENV
- variables http_proxy or https_proxy
- are set. ssl specifies if an SLL
- socket should be used for encrypted
- communications. This function
- returns the same hash from GetRoot()
- below. Make sure you get the SID
- (Session ID) since you have to use it
- to call most other functions in here.
-
- If srv is specified AND Net::DNS is
- installed and can be loaded, then
- an SRV query is sent to srv.hostname
- and the results processed to replace
- the hostname and port. If the lookup
- fails, or Net::DNS cannot be loaded,
- then hostname and port are left alone
- as the defaults.
-
-
- OpenFile(string) - opens a filehandle to the argument specified, and
- pretends that it is a stream. It will ignore the
- outer tag, and not check if it was a
- <stream:stream/>. This is useful for writing a
- program that has to parse any XML file that is
- basically made up of small packets (like RDF).
-
- Disconnect(sid) - sends the proper closing XML tag and closes the
- specified socket down.
-
- Process(integer) - waits for data to be available on the socket. If
- a timeout is specified then the Process function
- waits that period of time before returning nothing.
- If a timeout period is not specified then the
- function blocks until data is received. The
- function returns a hash with session ids as the key,
- and status values or data as the hash values.
-
- SetCallBacks(node=>function, - sets the callback that should be
- update=>function) called in various situations. node
- is used to handle the data structures
- that are built for each top level tag.
- Update is used for when Process is
- blocking waiting for data, but you
- want your original code to be updated.
-
- GetRoot(sid) - returns the attributes that the stream:stream tag sent
- by the other end listed in a hash for the specified
- session.
-
- GetSock(sid) - returns a pointer to the IO::Socket object for the
- specified session.
-
- Send(sid, - sends the string over the specified connection as is.
- string) This does no checking if valid XML was sent or not.
- Best behavior when sending information.
-
- GetErrorCode(sid) - returns a string for the specified session that
- will hopefully contain some useful information
- about why Process or Connect returned an undef
- to you.
-
- XPath(node,path) - returns an array of results that match the xpath.
- node can be any of the three types (Tree, Node).
-
-=head1 VARIABLES
-
- $NONBLOCKING - tells the Parser to enter into a nonblocking state. This
- might cause some funky behavior since you can get nested
- callbacks while things are waiting. 1=on, 0=off(default).
-
-=head1 EXAMPLES
-
- ##########################
- # simple example
-
- use XML::Stream qw( Tree );
-
- $stream = new XML::Stream;
-
- my $status = $stream->Connect(hostname => "jabber.org",
- port => 5222,
- namespace => "jabber:client");
-
- if (!defined($status)) {
- print "ERROR: Could not connect to server\n";
- print " (",$stream->GetErrorCode(),")\n";
- exit(0);
- }
-
- while($node = $stream->Process()) {
- # do something with $node
- }
-
- $stream->Disconnect();
-
-
- ###########################
- # example using a handler
-
- use XML::Stream qw( Tree );
-
- $stream = new XML::Stream;
- $stream->SetCallBacks(node=>\&noder);
- $stream->Connect(hostname => "jabber.org",
- port => 5222,
- namespace => "jabber:client",
- timeout => undef) || die $!;
-
- # Blocks here forever, noder is called for incoming
- # packets when they arrive.
- while(defined($stream->Process())) { }
-
- print "ERROR: Stream died (",$stream->GetErrorCode(),")\n";
-
- sub noder
- {
- my $sid = shift;
- my $node = shift;
- # do something with $node
- }
-
-=head1 AUTHOR
-
-Tweaked, tuned, and brightness changes by Ryan Eatmon, reatmon@ti.com
-in May of 2000.
-Colorized, and Dolby Surround sound added by Thomas Charron,
-tcharron@jabber.org
-By Jeremie in October of 1999 for http://etherx.jabber.org/streams/
-
-=head1 COPYRIGHT
-
-This module is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
-
-use 5.006_001;
-use strict;
-use Sys::Hostname;
-use IO::Socket;
-use IO::Select;
-use FileHandle;
-use Carp;
-use POSIX;
-use Authen::SASL;
-use MIME::Base64;
-use utf8;
-use Encode;
-
-$SIG{PIPE} = "IGNORE";
-
-use vars qw($VERSION $PAC $SSL $NONBLOCKING %HANDLERS $NETDNS %XMLNS );
-
-##############################################################################
-# Define the namespaces in an easy/constant manner.
-#-----------------------------------------------------------------------------
-# 0.9
-#-----------------------------------------------------------------------------
-$XMLNS{'stream'} = "http://etherx.jabber.org/streams";
-
-#-----------------------------------------------------------------------------
-# 1.0
-#-----------------------------------------------------------------------------
-$XMLNS{'xmppstreams'} = "urn:ietf:params:xml:ns:xmpp-streams";
-$XMLNS{'xmpp-bind'} = "urn:ietf:params:xml:ns:xmpp-bind";
-$XMLNS{'xmpp-sasl'} = "urn:ietf:params:xml:ns:xmpp-sasl";
-$XMLNS{'xmpp-session'} = "urn:ietf:params:xml:ns:xmpp-session";
-$XMLNS{'xmpp-tls'} = "urn:ietf:params:xml:ns:xmpp-tls";
-##############################################################################
-
-
-if (eval "require Net::DNS;" )
-{
- require Net::DNS;
- import Net::DNS;
- $NETDNS = 1;
-}
-else
-{
- $NETDNS = 0;
-}
-
-
-$VERSION = "1.22";
-$NONBLOCKING = 0;
-
-use XML::Stream::Namespace;
-use XML::Stream::Parser;
-use XML::Stream::XPath;
-
-##############################################################################
-#
-# Setup the exportable objects
-#
-##############################################################################
-require Exporter;
-my @ISA = qw(Exporter);
-my @EXPORT_OK = qw(Tree Node);
-
-sub import
-{
- my $class = shift;
-
- foreach my $module (@_)
- {
- eval "use XML::Stream::$module;";
- die($@) if ($@);
-
- my $lc = lc($module);
-
- eval("\$HANDLERS{\$lc}->{startElement} = \\&XML::Stream::${module}::_handle_element;");
- eval("\$HANDLERS{\$lc}->{endElement} = \\&XML::Stream::${module}::_handle_close;");
- eval("\$HANDLERS{\$lc}->{characters} = \\&XML::Stream::${module}::_handle_cdata;");
- }
-}
-
-
-sub new
-{
- my $proto = shift;
- my $self = { };
-
- bless($self,$proto);
-
- my %args;
- while($#_ >= 0) { $args{ lc pop(@_) } = pop(@_); }
-
- $self->{DATASTYLE} = "tree";
- $self->{DATASTYLE} = delete($args{style}) if exists($args{style});
-
- if ((($self->{DATASTYLE} eq "tree") && !defined($XML::Stream::Tree::LOADED)) ||
- (($self->{DATASTYLE} eq "node") && !defined($XML::Stream::Node::LOADED))
- )
- {
- croak("The style that you have chosen was not defined when you \"use\"d the module.\n");
- }
-
- $self->{DEBUGARGS} = \%args;
-
- $self->{DEBUGTIME} = 0;
- $self->{DEBUGTIME} = $args{debugtime} if exists($args{debugtime});
-
- $self->{DEBUGLEVEL} = 0;
- $self->{DEBUGLEVEL} = $args{debuglevel} if exists($args{debuglevel});
-
- $self->{DEBUGFILE} = "";
-
- if (exists($args{debugfh}) && ($args{debugfh} ne ""))
- {
- $self->{DEBUGFILE} = $args{debugfh};
- $self->{DEBUG} = 1;
- }
- if ((exists($args{debugfh}) && ($args{debugfh} eq "")) ||
- (exists($args{debug}) && ($args{debug} ne "")))
- {
- $self->{DEBUG} = 1;
- if (lc($args{debug}) eq "stdout")
- {
- $self->{DEBUGFILE} = new FileHandle(">&STDERR");
- $self->{DEBUGFILE}->autoflush(1);
- }
- else
- {
- if (-e $args{debug})
- {
- if (-w $args{debug})
- {
- $self->{DEBUGFILE} = new FileHandle(">$args{debug}");
- $self->{DEBUGFILE}->autoflush(1);
- }
- else
- {
- print "WARNING: debug file ($args{debug}) is not writable by you\n";
- print " No debug information being saved.\n";
- $self->{DEBUG} = 0;
- }
- }
- else
- {
- $self->{DEBUGFILE} = new FileHandle(">$args{debug}");
- if (defined($self->{DEBUGFILE}))
- {
- $self->{DEBUGFILE}->autoflush(1);
- }
- else
- {
- print "WARNING: debug file ($args{debug}) does not exist \n";
- print " and is not writable by you.\n";
- print " No debug information being saved.\n";
- $self->{DEBUG} = 0;
- }
- }
- }
- }
-
- my $hostname = hostname();
- my $address = gethostbyname($hostname) || 'localhost';
- my $fullname = gethostbyaddr($address,AF_INET) || $hostname;
-
- $self->debug(1,"new: hostname = ($fullname)");
-
- #---------------------------------------------------------------------------
- # Setup the defaults that the module will work with.
- #---------------------------------------------------------------------------
- $self->{SIDS}->{default}->{hostname} = "";
- $self->{SIDS}->{default}->{port} = "";
- $self->{SIDS}->{default}->{sock} = 0;
- $self->{SIDS}->{default}->{ssl} = (exists($args{ssl}) ? $args{ssl} : 0);
- $self->{SIDS}->{default}->{namespace} = "";
- $self->{SIDS}->{default}->{myhostname} = $fullname;
- $self->{SIDS}->{default}->{derivedhostname} = $fullname;
- $self->{SIDS}->{default}->{id} = "";
-
- #---------------------------------------------------------------------------
- # We are only going to use one callback, let the user call other callbacks
- # on his own.
- #---------------------------------------------------------------------------
- $self->SetCallBacks(node=>sub { $self->_node(@_) });
-
- $self->{IDCOUNT} = 0;
-
- return $self;
-}
-
-
-
-
-##############################################################################
-#+----------------------------------------------------------------------------
-#|
-#| Incoming Connection Functions
-#|
-#+----------------------------------------------------------------------------
-##############################################################################
-
-##############################################################################
-#
-# Listen - starts the stream by listening on a port for someone to connect,
-# and send the opening stream tag, and then sending a response based
-# on if the received header was correct for this stream. Server
-# name, port, and namespace are required otherwise we don't know
-# where to listen and what namespace to accept.
-#
-##############################################################################
-sub Listen
-{
- my $self = shift;
- my %args;
- while($#_ >= 0) { $args{ lc pop(@_) } = pop(@_); }
-
- my $serverid = "server$args{port}";
-
- return if exists($self->{SIDS}->{$serverid});
-
- push(@{$self->{SIDS}->{server}},$serverid);
-
- foreach my $key (keys(%{$self->{SIDS}->{default}}))
- {
- $self->{SIDS}->{$serverid}->{$key} = $self->{SIDS}->{default}->{$key};
- }
-
- foreach my $key (keys(%args))
- {
- $self->{SIDS}->{$serverid}->{$key} = $args{$key};
- }
-
- $self->debug(1,"Listen: start");
-
- if ($self->{SIDS}->{$serverid}->{namespace} eq "")
- {
- $self->SetErrorCode($serverid,"Namespace not specified");
- return;
- }
-
- #---------------------------------------------------------------------------
- # Check some things that we have to know in order get the connection up
- # and running. Server hostname, port number, namespace, etc...
- #---------------------------------------------------------------------------
- if ($self->{SIDS}->{$serverid}->{hostname} eq "")
- {
- $self->SetErrorCode("$serverid","Server hostname not specified");
- return;
- }
- if ($self->{SIDS}->{$serverid}->{port} eq "")
- {
- $self->SetErrorCode("$serverid","Server port not specified");
- return;
- }
- if ($self->{SIDS}->{$serverid}->{myhostname} eq "")
- {
- $self->{SIDS}->{$serverid}->{myhostname} = $self->{SIDS}->{$serverid}->{derivedhostname};
- }
-
- #-------------------------------------------------------------------------
- # Open the connection to the listed server and port. If that fails then
- # abort ourselves and let the user check $! on his own.
- #-------------------------------------------------------------------------
-
- while($self->{SIDS}->{$serverid}->{sock} == 0)
- {
- $self->{SIDS}->{$serverid}->{sock} =
- new IO::Socket::INET(LocalHost=>$self->{SIDS}->{$serverid}->{hostname},
- LocalPort=>$self->{SIDS}->{$serverid}->{port},
- Reuse=>1,
- Listen=>10,
- Proto=>'tcp');
- select(undef,undef,undef,.1);
- }
- $self->{SIDS}->{$serverid}->{status} = 1;
- $self->nonblock($self->{SIDS}->{$serverid}->{sock});
- $self->{SIDS}->{$serverid}->{sock}->autoflush(1);
-
- $self->{SELECT} =
- new IO::Select($self->{SIDS}->{$serverid}->{sock});
- $self->{SIDS}->{$serverid}->{select} =
- new IO::Select($self->{SIDS}->{$serverid}->{sock});
-
- $self->{SOCKETS}->{$self->{SIDS}->{$serverid}->{sock}} = "$serverid";
-
- return $serverid;
-}
-
-
-##############################################################################
-#
-# ConnectionAccept - accept an incoming connection.
-#
-##############################################################################
-sub ConnectionAccept
-{
- my $self = shift;
- my $serverid = shift;
-
- my $sid = $self->NewSID();
-
- $self->debug(1,"ConnectionAccept: sid($sid)");
-
- $self->{SIDS}->{$sid}->{sock} = $self->{SIDS}->{$serverid}->{sock}->accept();
-
- $self->nonblock($self->{SIDS}->{$sid}->{sock});
- $self->{SIDS}->{$sid}->{sock}->autoflush(1);
-
- $self->debug(3,"ConnectionAccept: sid($sid) client($self->{SIDS}->{$sid}->{sock}) server($self->{SIDS}->{$serverid}->{sock})");
-
- $self->{SELECT}->add($self->{SIDS}->{$sid}->{sock});
-
- #-------------------------------------------------------------------------
- # Create the XML::Stream::Parser and register our callbacks
- #-------------------------------------------------------------------------
- $self->{SIDS}->{$sid}->{parser} =
- new XML::Stream::Parser(%{$self->{DEBUGARGS}},
- nonblocking=>$NONBLOCKING,
- sid=>$sid,
- style=>$self->{DATASTYLE},
- Handlers=>{
- startElement=>sub{ $self->_handle_root(@_) },
- endElement=>sub{ &{$HANDLERS{$self->{DATASTYLE}}->{endElement}}($self,@_) },
- characters=>sub{ &{$HANDLERS{$self->{DATASTYLE}}->{characters}}($self,@_) },
- }
- );
-
- $self->{SIDS}->{$sid}->{select} =
- new IO::Select($self->{SIDS}->{$sid}->{sock});
- $self->{SIDS}->{$sid}->{connectiontype} = "tcpip";
- $self->{SOCKETS}->{$self->{SIDS}->{$sid}->{sock}} = $sid;
-
- $self->InitConnection($sid,$serverid);
-
- #---------------------------------------------------------------------------
- # Grab the init time so that we can check if we get data in the timeout
- # period or not.
- #---------------------------------------------------------------------------
- $self->{SIDS}->{$sid}->{activitytimeout} = time;
-
- return $sid;
-}
-
-
-##############################################################################
-#
-# Respond - If this is a listening socket then we need to respond to the
-# opening <stream:stream/>.
-#
-##############################################################################
-sub Respond
-{
- my $self = shift;
- my $sid = shift;
- my $serverid = $self->{SIDS}->{$sid}->{serverid};
-
- my $root = $self->GetRoot($sid);
-
- if ($root->{xmlns} ne $self->{SIDS}->{$serverid}->{namespace})
- {
- my $error = $self->StreamError($sid,"invalid-namespace","Invalid namespace specified");
- $self->Send($sid,$error);
-
- $self->{SIDS}->{$sid}->{sock}->flush();
- select(undef,undef,undef,1);
- $self->Disconnect($sid);
- }
-
- #---------------------------------------------------------------------------
- # Next, we build the opening handshake.
- #---------------------------------------------------------------------------
- my %stream_args;
-
- $stream_args{from} =
- (exists($self->{SIDS}->{$serverid}->{from}) ?
- $self->{SIDS}->{$serverid}->{from} :
- $self->{SIDS}->{$serverid}->{hostname}
- );
-
- $stream_args{to} = $self->GetRoot($sid)->{from};
- $stream_args{id} = $sid;
- $stream_args{namespaces} = $self->{SIDS}->{$serverid}->{namespaces};
-
- my $stream =
- $self->StreamHeader(
- xmlns=>$self->{SIDS}->{$serverid}->{namespace},
- xmllang=>"en",
- %stream_args
- );
-
- #---------------------------------------------------------------------------
- # Then we send the opening handshake.
- #---------------------------------------------------------------------------
- $self->Send($sid,$stream);
- delete($self->{SIDS}->{$sid}->{activitytimeout});
-}
-
-
-
-
-##############################################################################
-#+----------------------------------------------------------------------------
-#|
-#| Outgoing Connection Functions
-#|
-#+----------------------------------------------------------------------------
-##############################################################################
-
-##############################################################################
-#
-# Connect - starts the stream by connecting to the server, sending the opening
-# stream tag, and then waiting for a response and verifying that it
-# is correct for this stream. Server name, port, and namespace are
-# required otherwise we don't know where to send the stream to...
-#
-##############################################################################
-sub Connect
-{
- my $self = shift;
-
- foreach my $key (keys(%{$self->{SIDS}->{default}}))
- {
- $self->{SIDS}->{newconnection}->{$key} = $self->{SIDS}->{default}->{$key};
- }
- while($#_ >= 0) { $self->{SIDS}->{newconnection}->{ lc pop(@_) } = pop(@_); }
-
- my $timeout = exists($self->{SIDS}->{newconnection}->{timeout}) ?
- delete($self->{SIDS}->{newconnection}->{timeout}) :
- "";
-
- $self->debug(4,"Connect: timeout($timeout)");
-
-
- if (exists($self->{SIDS}->{newconnection}->{srv}))
- {
- $self->debug(1,"Connect: srv requested");
- if ($NETDNS)
- {
- my $res = new Net::DNS::Resolver();
- my $query = $res->query($self->{SIDS}->{newconnection}->{srv}.".".$self->{SIDS}->{newconnection}->{hostname},"SRV");
-
- if ($query)
- {
- $self->{SIDS}->{newconnection}->{hostname} = ($query->answer)[0]->target();
- $self->{SIDS}->{newconnection}->{port} = ($query->answer)[0]->port();
- $self->debug(1,"Connect: srv host: $self->{SIDS}->{newconnection}->{hostname}");
- $self->debug(1,"Connect: srv post: $self->{SIDS}->{newconnection}->{port}");
- }
- else
- {
- $self->debug(1,"Connect: srv query failed");
- }
- }
- else
- {
- $self->debug(1,"Connect: srv query failed");
- }
- delete($self->{SIDS}->{newconnection}->{srv});
- }
-
- $self->{SIDS}->{newconnection}->{connectiontype} = "tcpip"
- unless exists($self->{SIDS}->{newconnection}->{connectiontype});
-
- $self->debug(1,"Connect: type($self->{SIDS}->{newconnection}->{connectiontype})");
-
- if ($self->{SIDS}->{newconnection}->{namespace} eq "")
- {
- $self->SetErrorCode("newconnection","Namespace not specified");
- return;
- }
-
- #---------------------------------------------------------------------------
- # TCP/IP
- #---------------------------------------------------------------------------
- if ($self->{SIDS}->{newconnection}->{connectiontype} eq "tcpip")
- {
- #-----------------------------------------------------------------------
- # Check some things that we have to know in order get the connection up
- # and running. Server hostname, port number, namespace, etc...
- #-----------------------------------------------------------------------
- if ($self->{SIDS}->{newconnection}->{hostname} eq "")
- {
- $self->SetErrorCode("newconnection","Server hostname not specified");
- return;
- }
- if ($self->{SIDS}->{newconnection}->{port} eq "")
- {
- $self->SetErrorCode("newconnection","Server port not specified");
- return;
- }
- if ($self->{SIDS}->{newconnection}->{myhostname} eq "")
- {
- $self->{SIDS}->{newconnection}->{myhostname} = $self->{SIDS}->{newconnection}->{derivedhostname};
- }
-
- #-----------------------------------------------------------------------
- # Open the connection to the listed server and port. If that fails then
- # abort ourselves and let the user check $! on his own.
- #-----------------------------------------------------------------------
- $self->{SIDS}->{newconnection}->{sock} =
- new IO::Socket::INET(PeerAddr=>$self->{SIDS}->{newconnection}->{hostname},
- PeerPort=>$self->{SIDS}->{newconnection}->{port},
- Proto=>"tcp",
- (($timeout ne "") ? ( Timeout=>$timeout ) : ()),
- );
- return unless $self->{SIDS}->{newconnection}->{sock};
-
- if ($self->{SIDS}->{newconnection}->{ssl} == 1)
- {
- $self->debug(1,"Connect: Convert normal socket to SSL");
- $self->debug(1,"Connect: sock($self->{SIDS}->{newconnection}->{sock})");
- $self->LoadSSL();
- $self->{SIDS}->{newconnection}->{sock} =
- IO::Socket::SSL::socketToSSL($self->{SIDS}->{newconnection}->{sock},
- {SSL_verify_mode=>0x00});
- $self->debug(1,"Connect: ssl_sock($self->{SIDS}->{newconnection}->{sock})");
- $self->debug(1,"Connect: SSL: We are secure") if ($self->{SIDS}->{newconnection}->{sock});
- }
- return unless $self->{SIDS}->{newconnection}->{sock};
- }
-
- #---------------------------------------------------------------------------
- # STDIN/OUT
- #---------------------------------------------------------------------------
- if ($self->{SIDS}->{newconnection}->{connectiontype} eq "stdinout")
- {
- $self->{SIDS}->{newconnection}->{sock} =
- new FileHandle(">&STDOUT");
- }
-
- #---------------------------------------------------------------------------
- # HTTP
- #---------------------------------------------------------------------------
- if ($self->{SIDS}->{newconnection}->{connectiontype} eq "http")
- {
- #-----------------------------------------------------------------------
- # Check some things that we have to know in order get the connection up
- # and running. Server hostname, port number, namespace, etc...
- #-----------------------------------------------------------------------
- if ($self->{SIDS}->{newconnection}->{hostname} eq "")
- {
- $self->SetErrorCode("newconnection","Server hostname not specified");
- return;
- }
- if ($self->{SIDS}->{newconnection}->{port} eq "")
- {
- $self->SetErrorCode("newconnection","Server port not specified");
- return;
- }
- if ($self->{SIDS}->{newconnection}->{myhostname} eq "")
- {
- $self->{SIDS}->{newconnection}->{myhostname} = $self->{SIDS}->{newconnection}->{derivedhostname};
- }
-
- if (!defined($PAC))
- {
- eval("use HTTP::ProxyAutoConfig;");
- if ($@)
- {
- $PAC = 0;
- }
- else
- {
- require HTTP::ProxyAutoConfig;
- $PAC = new HTTP::ProxyAutoConfig();
- }
- }
-
- if ($PAC eq "0") {
- if (exists($ENV{"http_proxy"}))
- {
- my($host,$port) = ($ENV{"http_proxy"} =~ /^(\S+)\:(\d+)$/);
- $self->{SIDS}->{newconnection}->{httpproxyhostname} = $host;
- $self->{SIDS}->{newconnection}->{httpproxyport} = $port;
- $self->{SIDS}->{newconnection}->{httpproxyhostname} =~ s/^http\:\/\///;
- }
- if (exists($ENV{"https_proxy"}))
- {
- my($host,$port) = ($ENV{"https_proxy"} =~ /^(\S+)\:(\d+)$/);
- $self->{SIDS}->{newconnection}->{httpsproxyhostname} = $host;
- $self->{SIDS}->{newconnection}->{httpsproxyport} = $port;
- $self->{SIDS}->{newconnection}->{httpsproxyhostname} =~ s/^https?\:\/\///;
- }
- }
- else
- {
- my $proxy = $PAC->FindProxy("http://".$self->{SIDS}->{newconnection}->{hostname});
- if ($proxy ne "DIRECT")
- {
- ($self->{SIDS}->{newconnection}->{httpproxyhostname},$self->{SIDS}->{newconnection}->{httpproxyport}) = ($proxy =~ /^PROXY ([^:]+):(\d+)$/);
- }
-
- $proxy = $PAC->FindProxy("https://".$self->{SIDS}->{newconnection}->{hostname});
-
- if ($proxy ne "DIRECT")
- {
- ($self->{SIDS}->{newconnection}->{httpsproxyhostname},$self->{SIDS}->{newconnection}->{httpsproxyport}) = ($proxy =~ /^PROXY ([^:]+):(\d+)$/);
- }
- }
-
- $self->debug(1,"Connect: http_proxy($self->{SIDS}->{newconnection}->{httpproxyhostname}:$self->{SIDS}->{newconnection}->{httpproxyport})")
- if (exists($self->{SIDS}->{newconnection}->{httpproxyhostname}) &&
- defined($self->{SIDS}->{newconnection}->{httpproxyhostname}) &&
- exists($self->{SIDS}->{newconnection}->{httpproxyport}) &&
- defined($self->{SIDS}->{newconnection}->{httpproxyport}));
- $self->debug(1,"Connect: https_proxy($self->{SIDS}->{newconnection}->{httpsproxyhostname}:$self->{SIDS}->{newconnection}->{httpsproxyport})")
- if (exists($self->{SIDS}->{newconnection}->{httpsproxyhostname}) &&
- defined($self->{SIDS}->{newconnection}->{httpsproxyhostname}) &&
- exists($self->{SIDS}->{newconnection}->{httpsproxyport}) &&
- defined($self->{SIDS}->{newconnection}->{httpsproxyport}));
-
- #-----------------------------------------------------------------------
- # Open the connection to the listed server and port. If that fails then
- # abort ourselves and let the user check $! on his own.
- #-----------------------------------------------------------------------
- my $connect = "CONNECT $self->{SIDS}->{newconnection}->{hostname}:$self->{SIDS}->{newconnection}->{port} HTTP/1.1\r\nHost: $self->{SIDS}->{newconnection}->{hostname}\r\n\r\n";
- my $put = "PUT http://$self->{SIDS}->{newconnection}->{hostname}:$self->{SIDS}->{newconnection}->{port} HTTP/1.1\r\nHost: $self->{SIDS}->{newconnection}->{hostname}\r\nProxy-Connection: Keep-Alive\r\n\r\n";
-
- my $connected = 0;
- #-----------------------------------------------------------------------
- # Combo #0 - The user didn't specify a proxy
- #-----------------------------------------------------------------------
- if (!exists($self->{SIDS}->{newconnection}->{httpproxyhostname}) &&
- !exists($self->{SIDS}->{newconnection}->{httpsproxyhostname}))
- {
-
- $self->debug(1,"Connect: Combo #0: User did not specify a proxy... connecting DIRECT");
-
- $self->debug(1,"Connect: Combo #0: Create normal socket");
- $self->{SIDS}->{newconnection}->{sock} =
- new IO::Socket::INET(PeerAddr=>$self->{SIDS}->{newconnection}->{hostname},
- PeerPort=>$self->{SIDS}->{newconnection}->{port},
- Proto=>"tcp",
- (($timeout ne "") ? ( Timeout=>$timeout ) : ()),
- );
- $connected = defined($self->{SIDS}->{newconnection}->{sock});
- $self->debug(1,"Connect: Combo #0: connected($connected)");
- # if ($connected)
- # {
- # $self->{SIDS}->{newconnection}->{sock}->syswrite($put,length($put),0);
- # my $buff;
- # $self->{SIDS}->{newconnection}->{sock}->sysread($buff,4*POSIX::BUFSIZ);
- # my ($code) = ($buff =~ /^\S+\s+(\S+)\s+/);
- # $self->debug(1,"Connect: Combo #1: buff($buff)");
- # $connected = 0 if ($code !~ /2\d\d/);
- # }
- # $self->debug(1,"Connect: Combo #0: connected($connected)");
- }
-
- #-----------------------------------------------------------------------
- # Combo #1 - PUT through http_proxy
- #-----------------------------------------------------------------------
- if (!$connected &&
- exists($self->{SIDS}->{newconnection}->{httpproxyhostname}) &&
- ($self->{SIDS}->{newconnection}->{ssl} == 0))
- {
-
- $self->debug(1,"Connect: Combo #1: PUT through http_proxy");
- $self->{SIDS}->{newconnection}->{sock} =
- new IO::Socket::INET(PeerAddr=>$self->{SIDS}->{newconnection}->{httpproxyhostname},
- PeerPort=>$self->{SIDS}->{newconnection}->{httpproxyport},
- Proto=>"tcp",
- (($timeout ne "") ? ( Timeout=>$timeout ) : ()),
- );
- $connected = defined($self->{SIDS}->{newconnection}->{sock});
- $self->debug(1,"Connect: Combo #1: connected($connected)");
- if ($connected)
- {
- $self->debug(1,"Connect: Combo #1: send($put)");
- $self->{SIDS}->{newconnection}->{sock}->syswrite($put,length($put),0);
- my $buff;
- $self->{SIDS}->{newconnection}->{sock}->sysread($buff,4*POSIX::BUFSIZ);
- my ($code) = ($buff =~ /^\S+\s+(\S+)\s+/);
- $self->debug(1,"Connect: Combo #1: buff($buff)");
- $connected = 0 if ($code !~ /2\d\d/);
- }
- $self->debug(1,"Connect: Combo #1: connected($connected)");
- }
- #-----------------------------------------------------------------------
- # Combo #2 - CONNECT through http_proxy
- #-----------------------------------------------------------------------
- if (!$connected &&
- exists($self->{SIDS}->{newconnection}->{httpproxyhostname}) &&
- ($self->{SIDS}->{newconnection}->{ssl} == 0))
- {
-
- $self->debug(1,"Connect: Combo #2: CONNECT through http_proxy");
- $self->{SIDS}->{newconnection}->{sock} =
- new IO::Socket::INET(PeerAddr=>$self->{SIDS}->{newconnection}->{httpproxyhostname},
- PeerPort=>$self->{SIDS}->{newconnection}->{httpproxyport},
- Proto=>"tcp",
- (($timeout ne "") ? ( Timeout=>$timeout ) : ()),
- );
- $connected = defined($self->{SIDS}->{newconnection}->{sock});
- $self->debug(1,"Connect: Combo #2: connected($connected)");
- if ($connected)
- {
- $self->{SIDS}->{newconnection}->{sock}->syswrite($connect,length($connect),0);
- my $buff;
- $self->{SIDS}->{newconnection}->{sock}->sysread($buff,4*POSIX::BUFSIZ);
- my ($code) = ($buff =~ /^\S+\s+(\S+)\s+/);
- $self->debug(1,"Connect: Combo #2: buff($buff)");
- $connected = 0 if ($code !~ /2\d\d/);
- }
- $self->debug(1,"Connect: Combo #2: connected($connected)");
- }
-
- #-----------------------------------------------------------------------
- # Combo #3 - CONNECT through https_proxy
- #-----------------------------------------------------------------------
- if (!$connected &&
- exists($self->{SIDS}->{newconnection}->{httpsproxyhostname}))
- {
- $self->debug(1,"Connect: Combo #3: CONNECT through https_proxy");
- $self->{SIDS}->{newconnection}->{sock} =
- new IO::Socket::INET(PeerAddr=>$self->{SIDS}->{newconnection}->{httpsproxyhostname},
- PeerPort=>$self->{SIDS}->{newconnection}->{httpsproxyport},
- Proto=>"tcp");
- $connected = defined($self->{SIDS}->{newconnection}->{sock});
- $self->debug(1,"Connect: Combo #3: connected($connected)");
- if ($connected)
- {
- $self->{SIDS}->{newconnection}->{sock}->syswrite($connect,length($connect),0);
- my $buff;
- $self->{SIDS}->{newconnection}->{sock}->sysread($buff,4*POSIX::BUFSIZ);
- my ($code) = ($buff =~ /^\S+\s+(\S+)\s+/);
- $self->debug(1,"Connect: Combo #3: buff($buff)");
- $connected = 0 if ($code !~ /2\d\d/);
- }
- $self->debug(1,"Connect: Combo #3: connected($connected)");
- }
-
- #-----------------------------------------------------------------------
- # We have failed
- #-----------------------------------------------------------------------
- if (!$connected)
- {
- $self->debug(1,"Connect: No connection... I have failed... I.. must... end it all...");
- $self->SetErrorCode("newconnection","Unable to open a connection to destination. Please check your http_proxy and/or https_proxy environment variables.");
- return;
- }
-
- return unless $self->{SIDS}->{newconnection}->{sock};
-
- $self->debug(1,"Connect: We are connected");
-
- if (($self->{SIDS}->{newconnection}->{ssl} == 1) &&
- (ref($self->{SIDS}->{newconnection}->{sock}) eq "IO::Socket::INET"))
- {
- $self->debug(1,"Connect: Convert normal socket to SSL");
- $self->debug(1,"Connect: sock($self->{SIDS}->{newconnection}->{sock})");
- $self->LoadSSL();
- $self->{SIDS}->{newconnection}->{sock} =
- IO::Socket::SSL::socketToSSL($self->{SIDS}->{newconnection}->{sock},
- {SSL_verify_mode=>0x00});
- $self->debug(1,"Connect: ssl_sock($self->{SIDS}->{newconnection}->{sock})");
- $self->debug(1,"Connect: SSL: We are secure") if ($self->{SIDS}->{newconnection}->{sock});
- }
- return unless $self->{SIDS}->{newconnection}->{sock};
- }
-
- $self->debug(1,"Connect: Got a connection");
-
- $self->{SIDS}->{newconnection}->{sock}->autoflush(1);
-
- return $self->OpenStream("newconnection",$timeout);
-}
-
-
-##############################################################################
-#
-# OpenStream - Send the opening stream and save the root element info.
-#
-##############################################################################
-sub OpenStream
-{
- my $self = shift;
- my $currsid = shift;
- my $timeout = shift;
- $timeout = "" unless defined($timeout);
-
- $self->InitConnection($currsid,$currsid);
-
- #---------------------------------------------------------------------------
- # Next, we build the opening handshake.
- #---------------------------------------------------------------------------
- my %stream_args;
-
- if (($self->{SIDS}->{$currsid}->{connectiontype} eq "tcpip") ||
- ($self->{SIDS}->{$currsid}->{connectiontype} eq "http"))
- {
- $stream_args{to}= $self->{SIDS}->{$currsid}->{hostname}
- unless exists($self->{SIDS}->{$currsid}->{to});
-
- $stream_args{to} = $self->{SIDS}->{$currsid}->{to}
- if exists($self->{SIDS}->{$currsid}->{to});
-
- $stream_args{from} = $self->{SIDS}->{$currsid}->{myhostname}
- if (!exists($self->{SIDS}->{$currsid}->{from}) &&
- ($self->{SIDS}->{$currsid}->{myhostname} ne "")
- );
-
- $stream_args{from} = $self->{SIDS}->{$currsid}->{from}
- if exists($self->{SIDS}->{$currsid}->{from});
-
- $stream_args{id} = $self->{SIDS}->{$currsid}->{id}
- if (exists($self->{SIDS}->{$currsid}->{id}) &&
- ($self->{SIDS}->{$currsid}->{id} ne "")
- );
-
- $stream_args{namespaces} = $self->{SIDS}->{$currsid}->{namespaces};
- }
-
- my $stream =
- $self->StreamHeader(
- xmlns=>$self->{SIDS}->{$currsid}->{namespace},
- xmllang=>"en",
- %stream_args
- );
-
- #---------------------------------------------------------------------------
- # Create the XML::Stream::Parser and register our callbacks
- #---------------------------------------------------------------------------
- $self->{SIDS}->{$currsid}->{parser} =
- new XML::Stream::Parser(%{$self->{DEBUGARGS}},
- nonblocking=>$NONBLOCKING,
- sid=>$currsid,
- style=>$self->{DATASTYLE},
- Handlers=>{
- startElement=>sub{ $self->_handle_root(@_) },
- endElement=>sub{ &{$HANDLERS{$self->{DATASTYLE}}->{endElement}}($self,@_) },
- characters=>sub{ &{$HANDLERS{$self->{DATASTYLE}}->{characters}}($self,@_) },
- }
- );
-
- $self->{SIDS}->{$currsid}->{select} =
- new IO::Select($self->{SIDS}->{$currsid}->{sock});
-
- if (($self->{SIDS}->{$currsid}->{connectiontype} eq "tcpip") ||
- ($self->{SIDS}->{$currsid}->{connectiontype} eq "http"))
- {
- $self->{SELECT} = new IO::Select($self->{SIDS}->{$currsid}->{sock});
- $self->{SOCKETS}->{$self->{SIDS}->{$currsid}->{sock}} = "newconnection";
- }
-
- if ($self->{SIDS}->{$currsid}->{connectiontype} eq "stdinout")
- {
- $self->{SELECT} = new IO::Select(*STDIN);
- $self->{SOCKETS}->{$self->{SIDS}->{$currsid}->{sock}} = $currsid;
- $self->{SOCKETS}->{*STDIN} = $currsid;
- $self->{SIDS}->{$currsid}->{select}->add(*STDIN);
- }
-
- $self->{SIDS}->{$currsid}->{status} = 0;
-
- #---------------------------------------------------------------------------
- # Then we send the opening handshake.
- #---------------------------------------------------------------------------
- $self->Send($currsid,$stream) || return;
-
- #---------------------------------------------------------------------------
- # Before going on let's make sure that the server responded with a valid
- # root tag and that the stream is open.
- #---------------------------------------------------------------------------
- my $buff = "";
- my $timeEnd = ($timeout eq "") ? "" : time + $timeout;
- while($self->{SIDS}->{$currsid}->{status} == 0)
- {
- my $now = time;
- my $wait = (($timeEnd eq "") || ($timeEnd - $now > 10)) ? 10 :
- $timeEnd - $now;
-
- $self->debug(5,"Connect: can_read(",join(",",$self->{SIDS}->{$currsid}->{select}->can_read(0)),")");
- if ($self->{SIDS}->{$currsid}->{select}->can_read($wait))
- {
- $self->{SIDS}->{$currsid}->{status} = -1
- unless defined($buff = $self->Read($currsid));
- return unless($self->{SIDS}->{$currsid}->{status} == 0);
- return unless($self->ParseStream($currsid,$buff) == 1);
- }
- else
- {
- if ($timeout ne "")
- {
- if (time >= $timeEnd)
- {
- $self->SetErrorCode($currsid,"Timeout limit reached");
- return;
- }
- }
- }
-
- return if($self->{SIDS}->{$currsid}->{select}->has_exception(0));
- }
- return if($self->{SIDS}->{$currsid}->{status} != 1);
-
- $self->debug(3,"Connect: status($self->{SIDS}->{$currsid}->{status})");
-
- my $sid = $self->GetRoot($currsid)->{id};
- $| = 1;
- foreach my $key (keys(%{$self->{SIDS}->{$currsid}}))
- {
- $self->{SIDS}->{$sid}->{$key} = $self->{SIDS}->{$currsid}->{$key};
- }
- $self->{SIDS}->{$sid}->{parser}->setSID($sid);
-
- if (($self->{SIDS}->{$sid}->{connectiontype} eq "tcpip") ||
- ($self->{SIDS}->{$sid}->{connectiontype} eq "http"))
- {
- $self->{SOCKETS}->{$self->{SIDS}->{$currsid}->{sock}} = $sid;
- }
-
- if ($self->{SIDS}->{$sid}->{connectiontype} eq "stdinout")
- {
- $self->{SOCKETS}->{$self->{SIDS}->{$currsid}->{sock}} = $sid;
- $self->{SOCKETS}->{*STDIN} = $sid;
- }
-
- delete($self->{SIDS}->{$currsid});
-
- if (exists($self->GetRoot($sid)->{version}) &&
- ($self->GetRoot($sid)->{version} ne ""))
- {
- while(!$self->ReceivedStreamFeatures($sid))
- {
- $self->Process(1);
- }
- }
-
- return $self->GetRoot($sid);
-}
-
-
-##############################################################################
-#
-# OpenFile - starts the stream by opening a file and setting it up so that
-# Process reads from the filehandle to get the incoming stream.
-#
-##############################################################################
-sub OpenFile
-{
- my $self = shift;
- my $file = shift;
-
- $self->debug(1,"OpenFile: file($file)");
-
- $self->{SIDS}->{newconnection}->{connectiontype} = "file";
-
- $self->{SIDS}->{newconnection}->{sock} = new FileHandle($file);
- $self->{SIDS}->{newconnection}->{sock}->autoflush(1);
-
- $self->RegisterPrefix("newconnection",&ConstXMLNS("stream"),"stream");
-
- #---------------------------------------------------------------------------
- # Create the XML::Stream::Parser and register our callbacks
- #---------------------------------------------------------------------------
- $self->{SIDS}->{newconnection}->{parser} =
- new XML::Stream::Parser(%{$self->{DEBUGARGS}},
- nonblocking=>$NONBLOCKING,
- sid=>"newconnection",
- style=>$self->{DATASTYLE},
- Handlers=>{
- startElement=>sub{ $self->_handle_root(@_) },
- endElement=>sub{ &{$HANDLERS{$self->{DATASTYLE}}->{endElement}}($self,@_) },
- characters=>sub{ &{$HANDLERS{$self->{DATASTYLE}}->{characters}}($self,@_) },
- }
- );
-
- $self->{SIDS}->{newconnection}->{select} =
- new IO::Select($self->{SIDS}->{newconnection}->{sock});
-
- $self->{SELECT} = new IO::Select($self->{SIDS}->{newconnection}->{sock});
-
- $self->{SIDS}->{newconnection}->{status} = 0;
-
- my $buff = "";
- while($self->{SIDS}->{newconnection}->{status} == 0)
- {
- $self->debug(5,"OpenFile: can_read(",join(",",$self->{SIDS}->{newconnection}->{select}->can_read(0)),")");
- if ($self->{SIDS}->{newconnection}->{select}->can_read(0))
- {
- $self->{SIDS}->{newconnection}->{status} = -1
- unless defined($buff = $self->Read("newconnection"));
- return unless($self->{SIDS}->{newconnection}->{status} == 0);
- return unless($self->ParseStream("newconnection",$buff) == 1);
- }
-
- return if($self->{SIDS}->{newconnection}->{select}->has_exception(0) &&
- $self->{SIDS}->{newconnection}->{sock}->error());
- }
- return if($self->{SIDS}->{newconnection}->{status} != 1);
-
-
- my $sid = $self->NewSID();
- foreach my $key (keys(%{$self->{SIDS}->{newconnection}}))
- {
- $self->{SIDS}->{$sid}->{$key} = $self->{SIDS}->{newconnection}->{$key};
- }
- $self->{SIDS}->{$sid}->{parser}->setSID($sid);
-
- $self->{SOCKETS}->{$self->{SIDS}->{newconnection}->{sock}} = $sid;
-
- delete($self->{SIDS}->{newconnection});
-
- return $sid;
-}
-
-
-
-
-##############################################################################
-#+----------------------------------------------------------------------------
-#|
-#| Common Functions
-#|
-#+----------------------------------------------------------------------------
-##############################################################################
-
-##############################################################################
-#
-# Disconnect - sends the closing XML tag and shuts down the socket.
-#
-##############################################################################
-sub Disconnect
-{
- my $self = shift;
- my $sid = shift;
-
- $self->Send($sid,"</stream:stream>");
- close($self->{SIDS}->{$sid}->{sock})
- if (($self->{SIDS}->{$sid}->{connectiontype} eq "tcpip") ||
- ($self->{SIDS}->{$sid}->{connectiontype} eq "http"));
- delete($self->{SOCKETS}->{$self->{SIDS}->{$sid}->{sock}});
- foreach my $key (keys(%{$self->{SIDS}->{$sid}}))
- {
- delete($self->{SIDS}->{$sid}->{$key});
- }
- delete($self->{SIDS}->{$sid});
-}
-
-
-##############################################################################
-#
-# InitConnection - Initialize the connection data structure
-#
-##############################################################################
-sub InitConnection
-{
- my $self = shift;
- my $sid = shift;
- my $serverid = shift;
-
- #---------------------------------------------------------------------------
- # Set the default STATUS so that we can keep track of it throughout the
- # session.
- # 1 = no errors
- # 0 = no data has been received yet
- # -1 = error from handlers
- # -2 = error but keep the connection alive so that we can send some info.
- #---------------------------------------------------------------------------
- $self->{SIDS}->{$sid}->{status} = 0;
-
- #---------------------------------------------------------------------------
- # A storage place for when we don't have a callback registered and we need
- # to stockpile the nodes we receive until Process is called and we return
- # them.
- #---------------------------------------------------------------------------
- $self->{SIDS}->{$sid}->{nodes} = ();
-
- #---------------------------------------------------------------------------
- # If there is an error on the stream, then we need a place to indicate that.
- #---------------------------------------------------------------------------
- $self->{SIDS}->{$sid}->{streamerror} = {};
-
- #---------------------------------------------------------------------------
- # Grab the init time so that we can keep the connection alive by sending " "
- #---------------------------------------------------------------------------
- $self->{SIDS}->{$sid}->{keepalive} = time;
-
- #---------------------------------------------------------------------------
- # Keep track of the "server" we are connected to so we can check stuff
- # later.
- #---------------------------------------------------------------------------
- $self->{SIDS}->{$sid}->{serverid} = $serverid;
-
- #---------------------------------------------------------------------------
- # Mark the stream:features as MIA.
- #---------------------------------------------------------------------------
- $self->{SIDS}->{$sid}->{streamfeatures}->{received} = 0;
-
- #---------------------------------------------------------------------------
- # First acitivty is the connection... duh. =)
- #---------------------------------------------------------------------------
- $self->MarkActivity($sid);
-}
-
-
-##############################################################################
-#
-# ParseStream - takes the incoming stream and makes sure that only full
-# XML tags gets passed to the parser. If a full tag has not
-# read yet, then the Stream saves the incomplete part and
-# sends the rest to the parser.
-#
-##############################################################################
-sub ParseStream
-{
- my $self = shift;
- my $sid = shift;
- my $stream = shift;
-
- $stream = "" unless defined($stream);
-
- $self->debug(3,"ParseStream: sid($sid) stream($stream)");
-
- $self->{SIDS}->{$sid}->{parser}->parse($stream);
-
- if (exists($self->{SIDS}->{$sid}->{streamerror}->{type}))
- {
- $self->debug(3,"ParseStream: ERROR($self->{SIDS}->{$sid}->{streamerror}->{type})");
- $self->SetErrorCode($sid,$self->{SIDS}->{$sid}->{streamerror});
- return 0;
- }
-
- return 1;
-}
-
-
-##############################################################################
-#
-# Process - checks for data on the socket and returns a status code depending
-# on if there was data or not. If a timeout is not defined in the
-# call then the timeout defined in Connect() is used. If a timeout
-# of 0 is used then the call blocks until it gets some data,
-# otherwise it returns after the timeout period.
-#
-##############################################################################
-sub Process
-{
- my $self = shift;
- my $timeout = shift;
- $timeout = "" unless defined($timeout);
-
- $self->debug(4,"Process: timeout($timeout)");
- #---------------------------------------------------------------------------
- # We need to keep track of what's going on in the function and tell the
- # outside world about it so let's return something useful. We track this
- # information based on sid:
- # -1 connection closed and error
- # 0 connection open but no data received.
- # 1 connection open and data received.
- # array connection open and the data that has been collected
- # over time (No CallBack specified)
- #---------------------------------------------------------------------------
- my %status;
- foreach my $sid (keys(%{$self->{SIDS}}))
- {
- next if ($sid eq "default");
- $self->debug(5,"Process: initialize sid($sid) status to 0");
- $status{$sid} = 0;
- }
-
- #---------------------------------------------------------------------------
- # Either block until there is data and we have parsed it all, or wait a
- # certain period of time and then return control to the user.
- #---------------------------------------------------------------------------
- my $block = 1;
- my $timeEnd = ($timeout eq "") ? "" : time + $timeout;
- while($block == 1)
- {
- $self->debug(4,"Process: let's wait for data");
-
- my $now = time;
- my $wait = (($timeEnd eq "") || ($timeEnd - $now > 10)) ? 10 :
- $timeEnd - $now;
-
- foreach my $connection ($self->{SELECT}->can_read($wait))
- {
- $self->debug(4,"Process: connection($connection)");
- $self->debug(4,"Process: sid($self->{SOCKETS}->{$connection})");
- $self->debug(4,"Process: connection_status($self->{SIDS}->{$self->{SOCKETS}->{$connection}}->{status})");
-
- next unless (($self->{SIDS}->{$self->{SOCKETS}->{$connection}}->{status} == 1) ||
- exists($self->{SIDS}->{$self->{SOCKETS}->{$connection}}->{activitytimeout}));
-
- my $processit = 1;
- if (exists($self->{SIDS}->{server}))
- {
- foreach my $serverid (@{$self->{SIDS}->{server}})
- {
- if (exists($self->{SIDS}->{$serverid}->{sock}) &&
- ($connection == $self->{SIDS}->{$serverid}->{sock}))
- {
- my $sid = $self->ConnectionAccept($serverid);
- $status{$sid} = 0;
- $processit = 0;
- last;
- }
- }
- }
- if ($processit == 1)
- {
- my $sid = $self->{SOCKETS}->{$connection};
- $self->debug(4,"Process: there's something to read");
- $self->debug(4,"Process: connection($connection) sid($sid)");
- my $buff;
- $self->debug(4,"Process: read");
- $status{$sid} = 1;
- $self->{SIDS}->{$sid}->{status} = -1
- if (!defined($buff = $self->Read($sid)));
- $buff = "" unless defined($buff);
- $self->debug(4,"Process: connection_status($self->{SIDS}->{$sid}->{status})");
- $status{$sid} = -1 unless($self->{SIDS}->{$sid}->{status} == 1);
- $self->debug(4,"Process: parse($buff)");
- $status{$sid} = -1 unless($self->ParseStream($sid,$buff) == 1);
- }
- $block = 0;
- }
-
- if ($timeout ne "")
- {
- if (time >= $timeEnd)
- {
- $self->debug(4,"Process: Everyone out of the pool! Time to stop blocking.");
- $block = 0;
- }
- }
-
- $self->debug(4,"Process: timeout($timeout)");
-
- if (exists($self->{CB}->{update}))
- {
- $self->debug(4,"Process: Calling user defined update function");
- &{$self->{CB}->{update}}();
- }
-
- $block = 1 if $self->{SELECT}->can_read(0);
-
- #---------------------------------------------------------------------
- # Check for connections that need to be kept alive
- #---------------------------------------------------------------------
- $self->debug(4,"Process: check for keepalives");
- foreach my $sid (keys(%{$self->{SIDS}}))
- {
- next if ($sid eq "default");
- next if ($sid =~ /^server/);
- next if ($status{$sid} == -1);
- if ((time - $self->{SIDS}->{$sid}->{keepalive}) > 10)
- {
- $self->IgnoreActivity($sid,1);
- $self->{SIDS}->{$sid}->{status} = -1
- if !defined($self->Send($sid," "));
- $status{$sid} = -1 unless($self->{SIDS}->{$sid}->{status} == 1);
- if ($status{$sid} == -1)
- {
- $self->debug(2,"Process: Keep-Alive failed. What the hell happened?!?!");
- $self->debug(2,"Process: connection_status($self->{SIDS}->{$sid}->{status})");
- }
- $self->IgnoreActivity($sid,0);
- }
- }
- #---------------------------------------------------------------------
- # Check for connections that have timed out.
- #---------------------------------------------------------------------
- $self->debug(4,"Process: check for timeouts");
- foreach my $sid (keys(%{$self->{SIDS}}))
- {
- next if ($sid eq "default");
- next if ($sid =~ /^server/);
-
- if (exists($self->{SIDS}->{$sid}->{activitytimeout}))
- {
- $self->debug(4,"Process: sid($sid) time(",time,") timeout($self->{SIDS}->{$sid}->{activitytimeout})");
- }
- else
- {
- $self->debug(4,"Process: sid($sid) time(",time,") timeout(undef)");
- }
-
- $self->Respond($sid)
- if (exists($self->{SIDS}->{$sid}->{activitytimeout}) &&
- defined($self->GetRoot($sid)));
- $self->Disconnect($sid)
- if (exists($self->{SIDS}->{$sid}->{activitytimeout}) &&
- ((time - $self->{SIDS}->{$sid}->{activitytimeout}) > 10) &&
- ($self->{SIDS}->{$sid}->{status} != 1));
- }
-
-
- #---------------------------------------------------------------------
- # If any of the connections have status == -1 then return so that the
- # user can handle it.
- #---------------------------------------------------------------------
- foreach my $sid (keys(%status))
- {
- if ($status{$sid} == -1)
- {
- $self->debug(4,"Process: sid($sid) is broken... let's tell someone and watch it hit the fan... =)");
- $block = 0;
- }
- }
-
- $self->debug(2,"Process: block($block)");
- }
-
- #---------------------------------------------------------------------------
- # If the Select has an error then shut this party down.
- #---------------------------------------------------------------------------
- foreach my $connection ($self->{SELECT}->has_exception(0))
- {
- $self->debug(4,"Process: has_exception sid($self->{SOCKETS}->{$connection})");
- $status{$self->{SOCKETS}->{$connection}} = -1;
- }
-
- #---------------------------------------------------------------------------
- # If there are data structures that have not been collected return
- # those, otherwise return the status which indicates if nodes were read or
- # not.
- #---------------------------------------------------------------------------
- foreach my $sid (keys(%status))
- {
- $status{$sid} = $self->{SIDS}->{$sid}->{nodes}
- if (($status{$sid} == 1) &&
- ($#{$self->{SIDS}->{$sid}->{nodes}} > -1));
- }
-
- return %status;
-}
-
-
-##############################################################################
-#
-# Read - Takes the data from the server and returns a string
-#
-##############################################################################
-sub Read
-{
- my $self = shift;
- my $sid = shift;
- my $buff;
- my $status = 1;
-
- $self->debug(3,"Read: sid($sid)");
- $self->debug(3,"Read: connectionType($self->{SIDS}->{$sid}->{connectiontype})");
- $self->debug(3,"Read: socket($self->{SIDS}->{$sid}->{sock})");
-
- return if ($self->{SIDS}->{$sid}->{status} == -1);
-
- if (!defined($self->{SIDS}->{$sid}->{sock}))
- {
- $self->{SIDS}->{$sid}->{status} = -1;
- $self->SetErrorCode($sid,"Socket does not defined.");
- return;
- }
-
- $self->{SIDS}->{$sid}->{sock}->flush();
-
- $status = $self->{SIDS}->{$sid}->{sock}->sysread($buff,4*POSIX::BUFSIZ)
- if (($self->{SIDS}->{$sid}->{connectiontype} eq "tcpip") ||
- ($self->{SIDS}->{$sid}->{connectiontype} eq "http") ||
- ($self->{SIDS}->{$sid}->{connectiontype} eq "file"));
- $status = sysread(STDIN,$buff,1024)
- if ($self->{SIDS}->{$sid}->{connectiontype} eq "stdinout");
-
- $buff =~ s/^HTTP[\S\s]+\n\n// if ($self->{SIDS}->{$sid}->{connectiontype} eq "http");
- $self->debug(1,"Read: buff($buff)");
- $self->debug(3,"Read: status($status)") if defined($status);
- $self->debug(3,"Read: status(undef)") unless defined($status);
- $self->{SIDS}->{$sid}->{keepalive} = time
- unless (($buff eq "") || !defined($status) || ($status == 0));
- if (defined($status) && ($status != 0))
- {
- $buff = Encode::decode_utf8($buff);
- return $buff;
- }
- #return $buff unless (!defined($status) || ($status == 0));
- $self->debug(1,"Read: ERROR");
- return;
-}
-
-
-##############################################################################
-#
-# Send - Takes the data string and sends it to the server
-#
-##############################################################################
-sub Send
-{
- my $self = shift;
- my $sid = shift;
- $self->debug(1,"Send: (@_)");
- $self->debug(3,"Send: sid($sid)");
- $self->debug(3,"Send: status($self->{SIDS}->{$sid}->{status})");
-
- $self->{SIDS}->{$sid}->{keepalive} = time;
-
- return if ($self->{SIDS}->{$sid}->{status} == -1);
-
- if (!defined($self->{SIDS}->{$sid}->{sock}))
- {
- $self->debug(3,"Send: socket not defined");
- $self->{SIDS}->{$sid}->{status} = -1;
- $self->SetErrorCode($sid,"Socket not defined.");
- return;
- }
- else
- {
- $self->debug(3,"Send: socket($self->{SIDS}->{$sid}->{sock})");
- }
-
- $self->{SIDS}->{$sid}->{sock}->flush();
-
- if ($self->{SIDS}->{$sid}->{select}->can_write(0))
- {
- $self->debug(3,"Send: can_write");
-
- $self->{SENDSTRING} = Encode::encode_utf8(join("",@_));
-
- $self->{SENDWRITTEN} = 0;
- $self->{SENDOFFSET} = 0;
- $self->{SENDLENGTH} = length($self->{SENDSTRING});
- while ($self->{SENDLENGTH})
- {
- $self->{SENDWRITTEN} = $self->{SIDS}->{$sid}->{sock}->syswrite($self->{SENDSTRING},$self->{SENDLENGTH},$self->{SENDOFFSET});
-
- if (!defined($self->{SENDWRITTEN}))
- {
- $self->debug(4,"Send: SENDWRITTEN(undef)");
- $self->debug(4,"Send: Ok... what happened? Did we lose the connection?");
- $self->{SIDS}->{$sid}->{status} = -1;
- $self->SetErrorCode($sid,"Socket died for an unknown reason.");
- return;
- }
-
- $self->debug(4,"Send: SENDWRITTEN($self->{SENDWRITTEN})");
-
- $self->{SENDLENGTH} -= $self->{SENDWRITTEN};
- $self->{SENDOFFSET} += $self->{SENDWRITTEN};
- }
- }
- else
- {
- $self->debug(3,"Send: can't write...");
- }
-
- return if($self->{SIDS}->{$sid}->{select}->has_exception(0));
-
- $self->debug(3,"Send: no exceptions");
-
- $self->{SIDS}->{$sid}->{keepalive} = time;
-
- $self->MarkActivity($sid);
-
- return 1;
-}
-
-
-
-
-##############################################################################
-#+----------------------------------------------------------------------------
-#|
-#| Feature Functions
-#|
-#+----------------------------------------------------------------------------
-##############################################################################
-
-##############################################################################
-#
-# ProcessStreamFeatures - process the <stream:featutres/> block.
-#
-##############################################################################
-sub ProcessStreamFeatures
-{
- my $self = shift;
- my $sid = shift;
- my $node = shift;
-
- $self->{SIDS}->{$sid}->{streamfeatures}->{received} = 1;
-
- #-------------------------------------------------------------------------
- # SASL - 1.0
- #-------------------------------------------------------------------------
- my @sasl = &XPath($node,'*[@xmlns="'.&ConstXMLNS('xmpp-sasl').'"]');
- if ($#sasl > -1)
- {
- if (&XPath($sasl[0],"name()") eq "mechanisms")
- {
- my @mechanisms = &XPath($sasl[0],"mechanism/text()");
- $self->{SIDS}->{$sid}->{streamfeatures}->{'xmpp-sasl'} = \@mechanisms;
- }
- }
-
- #-------------------------------------------------------------------------
- # XMPP-TLS - 1.0
- #-------------------------------------------------------------------------
- my @tls = &XPath($node,'*[@xmlns="'.&ConstXMLNS('xmpp-tls').'"]');
- if ($#tls > -1)
- {
- if (&XPath($tls[0],"name()") eq "starttls")
- {
- $self->{SIDS}->{$sid}->{streamfeatures}->{'xmpp-tls'} = 1;
- my @required = &XPath($tls[0],"required");
- if ($#required > -1)
- {
- $self->{SIDS}->{$sid}->{streamfeatures}->{'xmpp-tls'} = "required";
- }
- }
- }
-
- #-------------------------------------------------------------------------
- # XMPP-Bind - 1.0
- #-------------------------------------------------------------------------
- my @bind = &XPath($node,'*[@xmlns="'.&ConstXMLNS('xmpp-bind').'"]');
- if ($#bind > -1)
- {
- $self->{SIDS}->{$sid}->{streamfeatures}->{'xmpp-bind'} = 1;
- }
-
- #-------------------------------------------------------------------------
- # XMPP-Session - 1.0
- #-------------------------------------------------------------------------
- my @session = &XPath($node,'*[@xmlns="'.&ConstXMLNS('xmpp-session').'"]');
- if ($#session > -1)
- {
- $self->{SIDS}->{$sid}->{streamfeatures}->{'xmpp-session'} = 1;
- }
-
-}
-
-
-##############################################################################
-#
-# GetStreamFeature - Return the value of the stream feature (if any).
-#
-##############################################################################
-sub GetStreamFeature
-{
- my $self = shift;
- my $sid = shift;
- my $feature = shift;
-
- return unless exists($self->{SIDS}->{$sid}->{streamfeatures}->{$feature});
- return $self->{SIDS}->{$sid}->{streamfeatures}->{$feature};
-}
-
-
-##############################################################################
-#
-# ReceivedStreamFeatures - Have we received the stream:features yet?
-#
-##############################################################################
-sub ReceivedStreamFeatures
-{
- my $self = shift;
- my $sid = shift;
- my $feature = shift;
-
- return $self->{SIDS}->{$sid}->{streamfeatures}->{received};
-}
-
-
-
-
-##############################################################################
-#+----------------------------------------------------------------------------
-#|
-#| TLS Functions
-#|
-#+----------------------------------------------------------------------------
-##############################################################################
-
-##############################################################################
-#
-# ProcessTLSPacket - process a TLS based packet.
-#
-##############################################################################
-sub ProcessTLSPacket
-{
- my $self = shift;
- my $sid = shift;
- my $node = shift;
-
- my $tag = &XPath($node,"name()");
-
- if ($tag eq "failure")
- {
- $self->TLSClientFailure($sid,$node);
- }
-
- if ($tag eq "proceed")
- {
- $self->TLSClientProceed($sid,$node);
- }
-}
-
-
-##############################################################################
-#
-# StartTLS - client function to have the socket start TLS.
-#
-##############################################################################
-sub StartTLS
-{
- my $self = shift;
- my $sid = shift;
- my $timeout = shift;
- $timeout = 120 unless defined($timeout);
- $timeout = 120 if ($timeout eq "");
-
- $self->TLSStartTLS($sid);
-
- my $endTime = time + $timeout;
- while(!$self->TLSClientDone($sid) && ($endTime >= time))
- {
- $self->Process(1);
- }
-
- if (!$self->TLSClientSecure($sid))
- {
- return;
- }
-
- return $self->OpenStream($sid,$timeout);
-}
-
-
-##############################################################################
-#
-# TLSStartTLS - send a <starttls/> in the TLS namespace.
-#
-##############################################################################
-sub TLSStartTLS
-{
- my $self = shift;
- my $sid = shift;
-
- $self->Send($sid,"<starttls xmlns='".&ConstXMLNS('xmpp-tls')."'/>");
-}
-
-
-##############################################################################
-#
-# TLSClientProceed - handle a <proceed/> packet.
-#
-##############################################################################
-sub TLSClientProceed
-{
- my $self = shift;
- my $sid = shift;
- my $node = shift;
-
- $self->debug(1,"TLSClientProceed: Convert normal socket to SSL");
- $self->debug(1,"TLSClientProceed: sock($self->{SIDS}->{$sid}->{sock})");
- if (!$self->LoadSSL())
- {
- $self->{SIDS}->{$sid}->{tls}->{error} = "Could not load IO::Socket::SSL.";
- $self->{SIDS}->{$sid}->{tls}->{done} = 1;
- return;
- }
-
- IO::Socket::SSL->start_SSL($self->{SIDS}->{$sid}->{sock},{SSL_verify_mode=>0x00});
-
- $self->debug(1,"TLSClientProceed: ssl_sock($self->{SIDS}->{$sid}->{sock})");
- $self->debug(1,"TLSClientProceed: SSL: We are secure")
- if ($self->{SIDS}->{$sid}->{sock});
-
- $self->{SIDS}->{$sid}->{tls}->{done} = 1;
- $self->{SIDS}->{$sid}->{tls}->{secure} = 1;
-}
-
-
-##############################################################################
-#
-# TLSClientSecure - return 1 if the socket is secure, 0 otherwise.
-#
-##############################################################################
-sub TLSClientSecure
-{
- my $self = shift;
- my $sid = shift;
-
- return $self->{SIDS}->{$sid}->{tls}->{secure};
-}
-
-
-##############################################################################
-#
-# TLSClientDone - return 1 if the TLS process is done
-#
-##############################################################################
-sub TLSClientDone
-{
- my $self = shift;
- my $sid = shift;
-
- return $self->{SIDS}->{$sid}->{tls}->{done};
-}
-
-
-##############################################################################
-#
-# TLSClientError - return the TLS error if any
-#
-##############################################################################
-sub TLSClientError
-{
- my $self = shift;
- my $sid = shift;
-
- return $self->{SIDS}->{$sid}->{tls}->{error};
-}
-
-
-##############################################################################
-#
-# TLSClientFailure - handle a <failure/>
-#
-##############################################################################
-sub TLSClientFailure
-{
- my $self = shift;
- my $sid = shift;
- my $node = shift;
-
- my $type = &XPath($node,"*/name()");
-
- $self->{SIDS}->{$sid}->{tls}->{error} = $type;
- $self->{SIDS}->{$sid}->{tls}->{done} = 1;
-}
-
-
-##############################################################################
-#
-# TLSFailure - Send a <failure/> in the TLS namespace
-#
-##############################################################################
-sub TLSFailure
-{
- my $self = shift;
- my $sid = shift;
- my $type = shift;
-
- $self->Send($sid,"<failure xmlns='".&ConstXMLNS('xmpp-tls')."'><${type}/></failure>");
-}
-
-
-
-
-##############################################################################
-#+----------------------------------------------------------------------------
-#|
-#| SASL Functions
-#|
-#+----------------------------------------------------------------------------
-##############################################################################
-
-##############################################################################
-#
-# ProcessSASLPacket - process a SASL based packet.
-#
-##############################################################################
-sub ProcessSASLPacket
-{
- my $self = shift;
- my $sid = shift;
- my $node = shift;
-
- my $tag = &XPath($node,"name()");
-
- if ($tag eq "challenge")
- {
- $self->SASLAnswerChallenge($sid,$node);
- }
-
- if ($tag eq "failure")
- {
- $self->SASLClientFailure($sid,$node);
- }
-
- if ($tag eq "success")
- {
- $self->SASLClientSuccess($sid,$node);
- }
-}
-
-
-##############################################################################
-#
-# SASLAnswerChallenge - when we get a <challenge/> we need to do the grunt
-# work to return a <response/>.
-#
-##############################################################################
-sub SASLAnswerChallenge
-{
- my $self = shift;
- my $sid = shift;
- my $node = shift;
-
- my $challenge64 = &XPath($node,"text()");
- my $challenge = MIME::Base64::decode_base64($challenge64);
-
- #-------------------------------------------------------------------------
- # As far as I can tell, if the challenge contains rspauth, then we authed.
- # If you try to send that to Authen::SASL, it will spew warnings about
- # the missing qop, nonce, etc... However, in order for jabberd2 to think
- # that you answered, you have to send back an empty response. Not sure
- # which approach is right... So let's hack for now.
- #-------------------------------------------------------------------------
- my $response = "";
- if ($challenge !~ /rspauth\=/)
- {
- $response = $self->{SIDS}->{$sid}->{sasl}->{client}->client_step($challenge);
- }
-
- my $response64 = MIME::Base64::encode_base64($response,"");
- $self->SASLResponse($sid,$response64);
-}
-
-
-##############################################################################
-#
-# SASLAuth - send an <auth/> in the SASL namespace
-#
-##############################################################################
-sub SASLAuth
-{
- my $self = shift;
- my $sid = shift;
-
- my $first_step = $self->{SIDS}->{$sid}->{sasl}->{client}->client_start();
- my $first_step64 = MIME::Base64::encode_base64($first_step,"");
-
- $self->Send($sid,"<auth xmlns='".&ConstXMLNS('xmpp-sasl')."' mechanism='".$self->{SIDS}->{$sid}->{sasl}->{client}->mechanism()."'>".$first_step64."</auth>");
-}
-
-
-##############################################################################
-#
-# SASLChallenge - Send a <challenge/> in the SASL namespace
-#
-##############################################################################
-sub SASLChallenge
-{
- my $self = shift;
- my $sid = shift;
- my $challenge = shift;
-
- $self->Send($sid,"<challenge xmlns='".&ConstXMLNS('xmpp-sasl')."'>${challenge}</challenge>");
-}
-
-
-###############################################################################
-#
-# SASLClient - This is a helper function to perform all of the required steps
-# for doing SASL with the server.
-#
-###############################################################################
-sub SASLClient
-{
- my $self = shift;
- my $sid = shift;
- my $username = shift;
- my $password = shift;
-
- my $mechanisms = $self->GetStreamFeature($sid,"xmpp-sasl");
-
- return unless defined($mechanisms);
-
- my $sasl = new Authen::SASL(mechanism=>join(" ",@{$mechanisms}),
- callback=>{
- authname => $username."@".$self->{SIDS}->{$sid}->{hostname},
-
- user => $username,
- pass => $password
- }
- );
-
- $self->{SIDS}->{$sid}->{sasl}->{client} = $sasl->client_new();
- $self->{SIDS}->{$sid}->{sasl}->{username} = $username;
- $self->{SIDS}->{$sid}->{sasl}->{password} = $password;
- $self->{SIDS}->{$sid}->{sasl}->{authed} = 0;
- $self->{SIDS}->{$sid}->{sasl}->{done} = 0;
-
- $self->SASLAuth($sid);
-}
-
-
-##############################################################################
-#
-# SASLClientAuthed - return 1 if we authed via SASL, 0 otherwise
-#
-##############################################################################
-sub SASLClientAuthed
-{
- my $self = shift;
- my $sid = shift;
-
- return $self->{SIDS}->{$sid}->{sasl}->{authed};
-}
-
-
-##############################################################################
-#
-# SASLClientDone - return 1 if the SASL process is finished
-#
-##############################################################################
-sub SASLClientDone
-{
- my $self = shift;
- my $sid = shift;
-
- return $self->{SIDS}->{$sid}->{sasl}->{done};
-}
-
-
-##############################################################################
-#
-# SASLClientError - return the error if any
-#
-##############################################################################
-sub SASLClientError
-{
- my $self = shift;
- my $sid = shift;
-
- return $self->{SIDS}->{$sid}->{sasl}->{error};
-}
-
-
-##############################################################################
-#
-# SASLClientFailure - handle a received <failure/>
-#
-##############################################################################
-sub SASLClientFailure
-{
- my $self = shift;
- my $sid = shift;
- my $node = shift;
-
- my $type = &XPath($node,"*/name()");
-
- $self->{SIDS}->{$sid}->{sasl}->{error} = $type;
- $self->{SIDS}->{$sid}->{sasl}->{done} = 1;
-}
-
-
-##############################################################################
-#
-# SASLClientSuccess - handle a received <success/>
-#
-##############################################################################
-sub SASLClientSuccess
-{
- my $self = shift;
- my $sid = shift;
- my $node = shift;
-
- $self->{SIDS}->{$sid}->{sasl}->{authed} = 1;
- $self->{SIDS}->{$sid}->{sasl}->{done} = 1;
-}
-
-
-##############################################################################
-#
-# SASLFailure - Send a <failure/> tag in the SASL namespace
-#
-##############################################################################
-sub SASLFailure
-{
- my $self = shift;
- my $sid = shift;
- my $type = shift;
-
- $self->Send($sid,"<failure xmlns='".&ConstXMLNS('xmpp-sasl')."'><${type}/></failure>");
-}
-
-
-##############################################################################
-#
-# SASLResponse - Send a <response/> tag in the SASL namespace
-#
-##############################################################################
-sub SASLResponse
-{
- my $self = shift;
- my $sid = shift;
- my $response = shift;
-
- $self->Send($sid,"<response xmlns='".&ConstXMLNS('xmpp-sasl')."'>${response}</response>");
-}
-
-
-
-
-##############################################################################
-#+----------------------------------------------------------------------------
-#|
-#| Packet Handlers
-#|
-#+----------------------------------------------------------------------------
-##############################################################################
-
-
-##############################################################################
-#
-# ProcessStreamPacket - process the <stream:XXXX/> packet
-#
-##############################################################################
-sub ProcessStreamPacket
-{
- my $self = shift;
- my $sid = shift;
- my $node = shift;
-
- my $tag = &XPath($node,"name()");
- my $stream_prefix = $self->StreamPrefix($sid);
- my ($type) = ($tag =~ /^${stream_prefix}\:(.+)$/);
-
- $self->ProcessStreamError($sid,$node) if ($type eq "error");
- $self->ProcessStreamFeatures($sid,$node) if ($type eq "features");
-}
-
-
-##############################################################################
-#
-# _handle_root - handles a root tag and checks that it is a stream:stream tag
-# with the proper namespace. If not then it sets the STATUS
-# to -1 and let's the outer code know that an error occurred.
-# Then it changes the Start tag handlers to the methond listed
-# in $self->{DATASTYLE}
-#
-##############################################################################
-sub _handle_root
-{
- my $self = shift;
- my ($sax, $tag, %att) = @_;
- my $sid = $sax->getSID();
-
- $self->debug(2,"_handle_root: sid($sid) sax($sax) tag($tag) att(",%att,")");
-
- $self->{SIDS}->{$sid}->{rootTag} = $tag;
-
- if ($self->{SIDS}->{$sid}->{connectiontype} ne "file")
- {
- #---------------------------------------------------------------------
- # Make sure we are receiving a valid stream on the same namespace.
- #---------------------------------------------------------------------
-
- $self->debug(3,"_handle_root: ($self->{SIDS}->{$self->{SIDS}->{$sid}->{serverid}}->{namespace})");
- $self->{SIDS}->{$sid}->{status} =
- ((($tag eq "stream:stream") &&
- exists($att{'xmlns'}) &&
- ($att{'xmlns'} eq $self->{SIDS}->{$self->{SIDS}->{$sid}->{serverid}}->{namespace})
- ) ?
- 1 :
- -1
- );
- $self->debug(3,"_handle_root: status($self->{SIDS}->{$sid}->{status})");
- }
- else
- {
- $self->{SIDS}->{$sid}->{status} = 1;
- }
-
- #-------------------------------------------------------------------------
- # Get the root tag attributes and save them for later. You never know when
- # you'll need to check the namespace or the from attributes sent by the
- # server.
- #-------------------------------------------------------------------------
- $self->{SIDS}->{$sid}->{root} = \%att;
-
- #-------------------------------------------------------------------------
- # Run through the various xmlns:*** attributes and register the namespace
- # to prefix map.
- #-------------------------------------------------------------------------
- foreach my $key (keys(%att))
- {
- if ($key =~ /^xmlns\:(.+?)$/)
- {
- $self->debug(5,"_handle_root: RegisterPrefix: prefix($att{$key}) ns($1)");
- $self->RegisterPrefix($sid,$att{$key},$1);
- }
- }
-
- #-------------------------------------------------------------------------
- # Sometimes we will get an error, so let's parse the tag assuming that we
- # got a stream:error
- #-------------------------------------------------------------------------
- my $stream_prefix = $self->StreamPrefix($sid);
- $self->debug(5,"_handle_root: stream_prefix($stream_prefix)");
-
- if ($tag eq $stream_prefix.":error")
- {
- &XML::Stream::Tree::_handle_element($self,$sax,$tag,%att)
- if ($self->{DATASTYLE} eq "tree");
- &XML::Stream::Node::_handle_element($self,$sax,$tag,%att)
- if ($self->{DATASTYLE} eq "node");
- }
-
- #---------------------------------------------------------------------------
- # Now that we have gotten a root tag, let's look for the tags that make up
- # the stream. Change the handler for a Start tag to another function.
- #---------------------------------------------------------------------------
- $sax->setHandlers(startElement=>sub{ &{$HANDLERS{$self->{DATASTYLE}}->{startElement}}($self,@_) },
- endElement=>sub{ &{$HANDLERS{$self->{DATASTYLE}}->{endElement}}($self,@_) },
- characters=>sub{ &{$HANDLERS{$self->{DATASTYLE}}->{characters}}($self,@_) },
- );
-}
-
-
-##############################################################################
-#
-# _node - internal callback for nodes. All it does is place the nodes in a
-# list so that Process() can return them later.
-#
-##############################################################################
-sub _node
-{
- my $self = shift;
- my $sid = shift;
- my @node = shift;
-
- if (ref($node[0]) eq "XML::Stream::Node")
- {
- push(@{$self->{SIDS}->{$sid}->{nodes}},$node[0]);
- }
- else
- {
- push(@{$self->{SIDS}->{$sid}->{nodes}},\@node);
- }
-}
-
-
-
-
-##############################################################################
-#+----------------------------------------------------------------------------
-#|
-#| Error Functions
-#|
-#+----------------------------------------------------------------------------
-##############################################################################
-
-##############################################################################
-#
-# GetErrorCode - if you are returned an undef, you can call this function
-# and hopefully learn more information about the problem.
-#
-##############################################################################
-sub GetErrorCode
-{
- my $self = shift;
- my $sid = shift;
-
- $sid = "newconnection" unless defined($sid);
-
- $self->debug(3,"GetErrorCode: sid($sid)");
- return ((exists($self->{SIDS}->{$sid}->{errorcode}) &&
- (ref($self->{SIDS}->{$sid}->{errorcode}) eq "HASH")) ?
- $self->{SIDS}->{$sid}->{errorcode} :
- { type=>"system",
- text=>$!,
- }
- );
-}
-
-
-##############################################################################
-#
-# SetErrorCode - sets the error code so that the caller can find out more
-# information about the problem
-#
-##############################################################################
-sub SetErrorCode
-{
- my $self = shift;
- my $sid = shift;
- my $errorcode = shift;
-
- $self->{SIDS}->{$sid}->{errorcode} = $errorcode;
-}
-
-
-##############################################################################
-#
-# ProcessStreamError - Take the XML packet and extract out the error.
-#
-##############################################################################
-sub ProcessStreamError
-{
- my $self = shift;
- my $sid = shift;
- my $node = shift;
-
- $self->{SIDS}->{$sid}->{streamerror}->{type} = "unknown";
- $self->{SIDS}->{$sid}->{streamerror}->{node} = $node;
-
- #-------------------------------------------------------------------------
- # Check for older 0.9 streams and handle the errors for them.
- #-------------------------------------------------------------------------
- if (!exists($self->{SIDS}->{$sid}->{root}->{version}) ||
- ($self->{SIDS}->{$sid}->{root}->{version} eq "") ||
- ($self->{SIDS}->{$sid}->{root}->{version} < 1.0)
- )
- {
- $self->{SIDS}->{$sid}->{streamerror}->{text} =
- &XPath($node,"text()");
- return;
- }
-
- #-------------------------------------------------------------------------
- # Otherwise we are in XMPP land with real stream errors.
- #-------------------------------------------------------------------------
- my @errors = &XPath($node,'*[@xmlns="'.&ConstXMLNS("xmppstreams").'"]');
-
- my $type;
- my $text;
- foreach my $error (@errors)
- {
- if (&XPath($error,"name()") eq "text")
- {
- $self->{SIDS}->{$sid}->{streamerror}->{text} =
- &XPath($error,"text()");
- }
- else
- {
- $self->{SIDS}->{$sid}->{streamerror}->{type} =
- &XPath($error,"name()");
- }
- }
-}
-
-
-##############################################################################
-#
-# StreamError - Given a type and text, generate a <stream:error/> packet to
-# send back to the other side.
-#
-##############################################################################
-sub StreamError
-{
- my $self = shift;
- my $sid = shift;
- my $type = shift;
- my $text = shift;
-
- my $root = $self->GetRoot($sid);
- my $stream_base = $self->StreamPrefix($sid);
- my $error = "<${stream_base}:error>";
-
- if (exists($root->{version}) && ($root->{version} ne ""))
- {
- $error .= "<${type} xmlns='".&ConstXMLNS('xmppstreams')."'/>";
- if (defined($text))
- {
- $error .= "<text xmlns='".&ConstXMLNS('xmppstreams')."'>";
- $error .= $text;
- $error .= "</text>";
- }
- }
- else
- {
- $error .= $text;
- }
-
- $error .= "</${stream_base}:error>";
-
- return $error;
-}
-
-
-
-
-##############################################################################
-#+----------------------------------------------------------------------------
-#|
-#| Activity Monitoring Functions
-#|
-#+----------------------------------------------------------------------------
-##############################################################################
-
-##############################################################################
-#
-# IgnoreActivity - Set the flag that will ignore the activity monitor.
-#
-##############################################################################
-sub IgnoreActivity
-{
- my $self = shift;
- my $sid = shift;
- my $ignoreActivity = shift;
- $ignoreActivity = 1 unless defined($ignoreActivity);
-
- $self->debug(3,"IgnoreActivity: ignoreActivity($ignoreActivity)");
- $self->debug(4,"IgnoreActivity: sid($sid)");
-
- $self->{SIDS}->{$sid}->{ignoreActivity} = $ignoreActivity;
-}
-
-
-##############################################################################
-#
-# LastActivity - Return the time of the last activity.
-#
-##############################################################################
-sub LastActivity
-{
- my $self = shift;
- my $sid = shift;
-
- $self->debug(3,"LastActivity: sid($sid)");
- $self->debug(1,"LastActivity: lastActivity($self->{SIDS}->{$sid}->{lastActivity})");
-
- return $self->{SIDS}->{$sid}->{lastActivity};
-}
-
-
-##############################################################################
-#
-# MarkActivity - Record the current time for this sid.
-#
-##############################################################################
-sub MarkActivity
-{
- my $self = shift;
- my $sid = shift;
-
- return if (exists($self->{SIDS}->{$sid}->{ignoreActivity}) &&
- ($self->{SIDS}->{$sid}->{ignoreActivity} == 1));
-
- $self->debug(3,"MarkActivity: sid($sid)");
-
- $self->{SIDS}->{$sid}->{lastActivity} = time;
-}
-
-
-
-
-##############################################################################
-#+----------------------------------------------------------------------------
-#|
-#| XML Node Interface functions
-#|
-#| These are generic wrappers around the Tree and Node data types. The
-#| problem being that the Tree class cannot support methods.
-#|
-#+----------------------------------------------------------------------------
-##############################################################################
-
-##############################################################################
-#
-# SetXMLData - takes a host of arguments and sets a portion of the specified
-# data strucure with that data. The function works in two
-# modes "single" or "multiple". "single" denotes that the
-# function should locate the current tag that matches this
-# data and overwrite it's contents with data passed in.
-# "multiple" denotes that a new tag should be created even if
-# others exist.
-#
-# type - single or multiple
-# XMLTree - pointer to XML::Stream data object (tree or node)
-# tag - name of tag to create/modify (if blank assumes
-# working with top level tag)
-# data - CDATA to set for tag
-# attribs - attributes to ADD to tag
-#
-##############################################################################
-sub SetXMLData
-{
- return &XML::Stream::Node::SetXMLData(@_) if (ref($_[1]) eq "XML::Stream::Node");
- return &XML::Stream::Tree::SetXMLData(@_) if (ref($_[1]) eq "ARRAY");
-}
-
-
-##############################################################################
-#
-# GetXMLData - takes a host of arguments and returns various data structures
-# that match them.
-#
-# type - "existence" - returns 1 or 0 if the tag exists in the
-# top level.
-# "value" - returns either the CDATA of the tag, or the
-# value of the attribute depending on which is
-# sought. This ignores any mark ups to the data
-# and just returns the raw CDATA.
-# "value array" - returns an array of strings representing
-# all of the CDATA in the specified tag.
-# This ignores any mark ups to the data
-# and just returns the raw CDATA.
-# "tree" - returns a data structure that represents the
-# XML with the specified tag as the root tag.
-# Depends on the format that you are working with.
-# "tree array" - returns an array of data structures each
-# with the specified tag as the root tag.
-# "child array" - returns a list of all children nodes
-# not including CDATA nodes.
-# "attribs" - returns a hash with the attributes, and
-# their values, for the things that match
-# the parameters
-# "count" - returns the number of things that match
-# the arguments
-# "tag" - returns the root tag of this tree
-# XMLTree - pointer to XML::Stream data structure
-# tag - tag to pull data from. If blank then the top level
-# tag is accessed.
-# attrib - attribute value to retrieve. Ignored for types
-# "value array", "tree", "tree array". If paired
-# with value can be used to filter tags based on
-# attributes and values.
-# value - only valid if an attribute is supplied. Used to
-# filter for tags that only contain this attribute.
-# Useful to search through multiple tags that all
-# reference different name spaces.
-#
-##############################################################################
-sub GetXMLData
-{
- return &XML::Stream::Node::GetXMLData(@_) if (ref($_[1]) eq "XML::Stream::Node");
- return &XML::Stream::Tree::GetXMLData(@_) if (ref($_[1]) eq "ARRAY");
-}
-
-
-##############################################################################
-#
-# XPath - run an xpath query on a node and return back the result.
-#
-##############################################################################
-sub XPath
-{
- my $tree = shift;
- my $path = shift;
-
- my $query = new XML::Stream::XPath::Query($path);
- my $result = $query->execute($tree);
- if ($result->check())
- {
- my %attribs = $result->getAttribs();
- return %attribs if (scalar(keys(%attribs)) > 0);
-
- my @values = $result->getValues();
- @values = $result->getList() unless ($#values > -1);
- return @values if wantarray;
- return $values[0];
- }
- return;
-}
-
-
-##############################################################################
-#
-# XPathCheck - run an xpath query on a node and return 1 or 0 if the path is
-# valid.
-#
-##############################################################################
-sub XPathCheck
-{
- my $tree = shift;
- my $path = shift;
-
- my $query = new XML::Stream::XPath::Query($path);
- my $result = $query->execute($tree);
- return $result->check();
-}
-
-
-##############################################################################
-#
-# XML2Config - takes an XML data tree and turns it into a hash of hashes.
-# This only works for certain kinds of XML trees like this:
-#
-# <foo>
-# <bar>1</bar>
-# <x>
-# <y>foo</y>
-# </x>
-# <z>5</z>
-# <z>6</z>
-# </foo>
-#
-# The resulting hash would be:
-#
-# $hash{bar} = 1;
-# $hash{x}->{y} = "foo";
-# $hash{z}->[0] = 5;
-# $hash{z}->[1] = 6;
-#
-# Good for config files.
-#
-##############################################################################
-sub XML2Config
-{
- return &XML::Stream::Node::XML2Config(@_) if (ref($_[0]) eq "XML::Stream::Node");
- return &XML::Stream::Tree::XML2Config(@_) if (ref($_[0]) eq "ARRAY");
-}
-
-
-##############################################################################
-#
-# Config2XML - takes a hash and produces an XML string from it. If the hash
-# looks like this:
-#
-# $hash{bar} = 1;
-# $hash{x}->{y} = "foo";
-# $hash{z}->[0] = 5;
-# $hash{z}->[1] = 6;
-#
-# The resulting xml would be:
-#
-# <foo>
-# <bar>1</bar>
-# <x>
-# <y>foo</y>
-# </x>
-# <z>5</z>
-# <z>6</z>
-# </foo>
-#
-# Good for config files.
-#
-##############################################################################
-sub Config2XML
-{
- my ($tag,$hash,$indent) = @_;
- $indent = "" unless defined($indent);
-
- my $xml;
-
- if (ref($hash) eq "ARRAY")
- {
- foreach my $item (@{$hash})
- {
- $xml .= &XML::Stream::Config2XML($tag,$item,$indent);
- }
- }
- else
- {
- if ((ref($hash) eq "HASH") && ((scalar keys(%{$hash})) == 0))
- {
- $xml .= "$indent<$tag/>\n";
- }
- else
- {
- if (ref($hash) eq "")
- {
- if ($hash eq "")
- {
- return "$indent<$tag/>\n";
- }
- else
- {
- return "$indent<$tag>$hash</$tag>\n";
- }
- }
- else
- {
- $xml .= "$indent<$tag>\n";
- foreach my $item (sort {$a cmp $b} keys(%{$hash}))
- {
- $xml .= &XML::Stream::Config2XML($item,$hash->{$item}," $indent");
- }
- $xml .= "$indent</$tag>\n";
- }
- }
- }
- return $xml;
-}
-
-
-##############################################################################
-#
-# EscapeXML - Simple function to make sure that no bad characters make it into
-# in the XML string that might cause the string to be
-# misinterpreted.
-#
-##############################################################################
-sub EscapeXML
-{
- my $data = shift;
-
- if (defined($data))
- {
- $data =~ s/&/&amp;/g;
- $data =~ s/</&lt;/g;
- $data =~ s/>/&gt;/g;
- $data =~ s/\"/&quot;/g;
- $data =~ s/\'/&apos;/g;
- }
-
- return $data;
-}
-
-
-##############################################################################
-#
-# UnescapeXML - Simple function to take an escaped string and return it to
-# normal.
-#
-##############################################################################
-sub UnescapeXML
-{
- my $data = shift;
-
- if (defined($data))
- {
- $data =~ s/&amp;/&/g;
- $data =~ s/&lt;/</g;
- $data =~ s/&gt;/>/g;
- $data =~ s/&quot;/\"/g;
- $data =~ s/&apos;/\'/g;
- }
-
- return $data;
-}
-
-
-##############################################################################
-#
-# BuildXML - takes one of the data formats that XML::Stream supports and call
-# the proper BuildXML_xxx function on it.
-#
-##############################################################################
-sub BuildXML
-{
- return &XML::Stream::Node::BuildXML(@_) if (ref($_[0]) eq "XML::Stream::Node");
- return &XML::Stream::Tree::BuildXML(@_) if (ref($_[0]) eq "ARRAY");
- return &XML::Stream::Tree::BuildXML(@_) if (ref($_[1]) eq "ARRAY");
-}
-
-
-
-##############################################################################
-#+----------------------------------------------------------------------------
-#|
-#| Namespace/Prefix Functions
-#|
-#+----------------------------------------------------------------------------
-##############################################################################
-
-##############################################################################
-#
-# ConstXMLNS - Return the namespace from the constant string.
-#
-##############################################################################
-sub ConstXMLNS
-{
- my $const = shift;
-
- return $XMLNS{$const};
-}
-
-
-##############################################################################
-#
-# StreamPrefix - Return the prefix of the <stream:stream/>
-#
-##############################################################################
-sub StreamPrefix
-{
- my $self = shift;
- my $sid = shift;
-
- return $self->ns2prefix($sid,&ConstXMLNS("stream"));
-}
-
-
-##############################################################################
-#
-# RegisterPrefix - setup the map for namespace to prefix
-#
-##############################################################################
-sub RegisterPrefix
-{
- my $self = shift;
- my $sid = shift;
- my $ns = shift;
- my $prefix = shift;
-
- $self->{SIDS}->{$sid}->{ns2prefix}->{$ns} = $prefix;
-}
-
-
-##############################################################################
-#
-# ns2prefix - for a stream, return the prefix for the given namespace
-#
-##############################################################################
-sub ns2prefix
-{
- my $self = shift;
- my $sid = shift;
- my $ns = shift;
-
- return $self->{SIDS}->{$sid}->{ns2prefix}->{$ns};
-}
-
-
-
-
-##############################################################################
-#+----------------------------------------------------------------------------
-#|
-#| Helper Functions
-#|
-#+----------------------------------------------------------------------------
-##############################################################################
-
-##############################################################################
-#
-# GetRoot - returns the hash of attributes for the root <stream:stream/> tag
-# so that any attributes returned can be accessed. from and any
-# xmlns:foobar might be important.
-#
-##############################################################################
-sub GetRoot
-{
- my $self = shift;
- my $sid = shift;
- return unless exists($self->{SIDS}->{$sid}->{root});
- return $self->{SIDS}->{$sid}->{root};
-}
-
-
-##############################################################################
-#
-# GetSock - returns the Socket so that an outside function can access it if
-# desired.
-#
-##############################################################################
-sub GetSock
-{
- my $self = shift;
- my $sid = shift;
- return $self->{SIDS}->{$sid}->{sock};
-}
-
-
-##############################################################################
-#
-# LoadSSL - simple call to set everything up for SSL one time.
-#
-##############################################################################
-sub LoadSSL
-{
- my $self = shift;
-
- $self->debug(1,"LoadSSL: Load the IO::Socket::SSL module");
-
- if (defined($SSL) && ($SSL == 1))
- {
- $self->debug(1,"LoadSSL: Success");
- return 1;
- }
-
- if (defined($SSL) && ($SSL == 0))
- {
- $self->debug(1,"LoadSSL: Failure");
- return;
- }
-
- my $SSL_Version = "0.81";
- eval "use IO::Socket::SSL $SSL_Version";
- if ($@)
- {
- croak("You requested that XML::Stream turn the socket into an SSL socket, but you don't have the correct version of IO::Socket::SSL v$SSL_Version.");
- }
- IO::Socket::SSL::context_init({SSL_verify_mode=>0x00});
- $SSL = 1;
-
- $self->debug(1,"LoadSSL: Success");
- return 1;
-}
-
-
-##############################################################################
-#
-# Host2SID - For a server this allows you to lookup the SID of a stream server
-# based on the hostname that is is listening on.
-#
-##############################################################################
-sub Host2SID
-{
- my $self = shift;
- my $hostname = shift;
-
- foreach my $sid (keys(%{$self->{SIDS}}))
- {
- next if ($sid eq "default");
- next if ($sid =~ /^server/);
-
- return $sid if ($self->{SIDS}->{$sid}->{hostname} eq $hostname);
- }
- return;
-}
-
-
-##############################################################################
-#
-# NewSID - returns a session ID to send to an incoming stream in the return
-# header. By default it just increments a counter and returns that,
-# or you can define a function and set it using the SetCallBacks
-# function.
-#
-##############################################################################
-sub NewSID
-{
- my $self = shift;
- return &{$self->{CB}->{sid}}() if (exists($self->{CB}->{sid}) &&
- defined($self->{CB}->{sid}));
- return $$.time.$self->{IDCOUNT}++;
-}
-
-
-###########################################################################
-#
-# SetCallBacks - Takes a hash with top level tags to look for as the keys
-# and pointers to functions as the values.
-#
-###########################################################################
-sub SetCallBacks
-{
- my $self = shift;
- while($#_ >= 0) {
- my $func = pop(@_);
- my $tag = pop(@_);
- if (($tag eq "node") && !defined($func))
- {
- $self->SetCallBacks(node=>sub { $self->_node(@_) });
- }
- else
- {
- $self->debug(1,"SetCallBacks: tag($tag) func($func)");
- $self->{CB}->{$tag} = $func;
- }
- }
-}
-
-
-##############################################################################
-#
-# StreamHeader - Given the arguments, return the opening stream header.
-#
-##############################################################################
-sub StreamHeader
-{
- my $self = shift;
- my (%args) = @_;
-
- my $stream;
- $stream .= "<?xml version='1.0'?>";
- $stream .= "<stream:stream ";
- $stream .= "version='1.0' ";
- $stream .= "xmlns:stream='".&ConstXMLNS("stream")."' ";
- $stream .= "xmlns='$args{xmlns}' ";
- $stream .= "to='$args{to}' " if exists($args{to});
- $stream .= "from='$args{from}' " if exists($args{from});
- $stream .= "xml:lang='$args{xmllang}' " if exists($args{xmllang});
-
- foreach my $ns (@{$args{namespaces}})
- {
- $stream .= " ".$ns->GetStream();
- }
-
- $stream .= ">";
-
- return $stream;
-}
-
-
-###########################################################################
-#
-# debug - prints the arguments to the debug log if debug is turned on.
-#
-###########################################################################
-sub debug
-{
- return if ($_[1] > $_[0]->{DEBUGLEVEL});
- my $self = shift;
- my ($limit,@args) = @_;
- return if ($self->{DEBUGFILE} eq "");
- my $fh = $self->{DEBUGFILE};
- if ($self->{DEBUGTIME} == 1)
- {
- my ($sec,$min,$hour) = localtime(time);
- print $fh sprintf("[%02d:%02d:%02d] ",$hour,$min,$sec);
- }
- print $fh "XML::Stream: @args\n";
-}
-
-
-##############################################################################
-#
-# nonblock - set the socket to be non-blocking.
-#
-##############################################################################
-sub nonblock
-{
- my $self = shift;
- my $socket = shift;
-
- #--------------------------------------------------------------------------
- # Code copied from POE::Wheel::SocketFactory...
- # Win32 does things one way...
- #--------------------------------------------------------------------------
- if ($^O eq "MSWin32")
- {
- ioctl( $socket, 0x80000000 | (4 << 16) | (ord('f') << 8) | 126, 1) ||
- croak("Can't make socket nonblocking (win32): $!");
- return;
- }
-
- #--------------------------------------------------------------------------
- # And UNIX does them another
- #--------------------------------------------------------------------------
- my $flags = fcntl($socket, F_GETFL, 0)
- or die "Can't get flags for socket: $!\n";
- fcntl($socket, F_SETFL, $flags | O_NONBLOCK)
- or die "Can't make socket nonblocking: $!\n";
-}
-
-
-##############################################################################
-#
-# printData - debugging function to print out any data structure in an
-# organized manner. Very useful for debugging XML::Parser::Tree
-# objects. This is a private function that will only exist in
-# in the development version.
-#
-##############################################################################
-sub printData
-{
- print &sprintData(@_);
-}
-
-
-##############################################################################
-#
-# sprintData - debugging function to build a string out of any data structure
-# in an organized manner. Very useful for debugging
-# XML::Parser::Tree objects and perl hashes of hashes.
-#
-# This is a private function.
-#
-##############################################################################
-sub sprintData
-{
- my ($preString,$data) = @_;
-
- my $outString = "";
-
- if (ref($data) eq "HASH")
- {
- my $key;
- foreach $key (sort { $a cmp $b } keys(%{$data}))
- {
- if (ref($$data{$key}) eq "")
- {
- my $value = defined($$data{$key}) ? $$data{$key} : "";
- $outString .= $preString."{'$key'} = \"".$value."\";\n";
- }
- else
- {
- if (ref($$data{$key}) =~ /Net::Jabber/)
- {
- $outString .= $preString."{'$key'} = ".ref($$data{$key}).";\n";
- }
- else
- {
- $outString .= $preString."{'$key'};\n";
- $outString .= &sprintData($preString."{'$key'}->",$$data{$key});
- }
- }
- }
- }
- else
- {
- if (ref($data) eq "ARRAY")
- {
- my $index;
- foreach $index (0..$#{$data})
- {
- if (ref($$data[$index]) eq "")
- {
- $outString .= $preString."[$index] = \"$$data[$index]\";\n";
- }
- else
- {
- if (ref($$data[$index]) =~ /Net::Jabber/)
- {
- $outString .= $preString."[$index] = ".ref($$data[$index]).";\n";
- }
- else
- {
- $outString .= $preString."[$index];\n";
- $outString .= &sprintData($preString."[$index]->",$$data[$index]);
- }
- }
- }
- }
- else
- {
- if (ref($data) eq "REF")
- {
- $outString .= &sprintData($preString."->",$$data);
- }
- else
- {
- if (ref($data) eq "")
- {
- $outString .= $preString." = \"$data\";\n";
- }
- else
- {
- $outString .= $preString." = ".ref($data).";\n";
- }
- }
- }
- }
-
- return $outString;
-}
-
-
-1;
diff --git a/lib/XML/Stream/Namespace.pm b/lib/XML/Stream/Namespace.pm
deleted file mode 100644
index a9aee25..0000000
--- a/lib/XML/Stream/Namespace.pm
+++ /dev/null
@@ -1,190 +0,0 @@
-##############################################################################
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Library General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Library General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-# Jabber
-# Copyright (C) 1998-2004 Jabber Software Foundation http://jabber.org/
-#
-##############################################################################
-
-package XML::Stream::Namespace;
-
-=head1 NAME
-
-XML::Stream::Namespace - Object to make defining Namespaces easier in
- XML::Stream.
-
-=head1 SYNOPSIS
-
-XML::Stream::Namespace is a helper package to XML::Stream. It provides
-a clean way of defining Namespaces for XML::Stream to use when connecting.
-
-=head1 DESCRIPTION
-
- This module allows you to set and read elements from an XML::Stream
- Namespace.
-
-=head1 METHODS
-
- SetNamespace("mynamespace");
- SetXMLNS("http://www.mynamespace.com/xmlns");
- SetAttributes(attrib1=>"value1",
- attrib2=>"value2");
-
- GetNamespace() returns "mynamespace"
- GetXMLNS() returns "http://www.mynamespace.com/xmlns"
- GetAttributes() returns a hash ( attrib1=>"value1",attrib2=>"value2")
- GetStream() returns the following string:
- "xmlns:mynamespace='http://www.nynamespace.com/xmlns'
- mynamespace:attrib1='value1'
- mynamespace:attrib2='value2'"
-
-=head1 EXAMPLES
-
-
- $myNamespace = new XML::Stream::Namespace("mynamspace");
- $myNamespace->SetXMLNS("http://www.mynamespace.org/xmlns");
- $myNamespace->SetAttributes(foo=>"bar",
- bob=>"vila");
-
- $stream = new XML::Stream;
- $stream->Connect(name=>"foo.bar.org",
- port=>1234,
- namespace=>"foo:bar",
- namespaces=>[ $myNamespace ]);
-
- #
- # The above Connect will send the following as the opening string
- # of the stream to foo.bar.org:1234...
- #
- # <stream:stream
- # xmlns:stream="http://etherx.jabber.org/streams"
- # to="foo.bar.org"
- # xmlns="foo:bar"
- # xmlns:mynamespace="http://www.mynamespace.org/xmlns"
- # mynamespace:foo="bar"
- # mynamespace:bob="vila">
- #
-
-
-=head1 AUTHOR
-
-Written by Ryan Eatmon in February 2000
-Idea By Thomas Charron in January of 2000 for http://etherx.jabber.org/streams/
-
-=head1 COPYRIGHT
-
-This module is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
-
-use strict;
-use Carp;
-use vars qw( $VERSION );
-
-$VERSION = "1.22";
-
-sub new
-{
- my $proto = shift;
- my $self = { };
-
- ($self->{Namespace}) = @_ if ($#_ > -1);
-
- $self->{Attributes} = {};
-
- bless($self,$proto);
- return $self;
-}
-
-
-sub SetNamespace
-{
- my $self = shift;
- my ($namespace) = @_;
-
- $self->{Namespace} = $namespace;
-}
-
-
-sub SetXMLNS
-{
- my $self = shift;
- my ($xmlns) = @_;
-
- $self->{XMLNS} = $xmlns;
-}
-
-
-sub SetAttributes
-{
- my $self = shift;
- my %att = @_;
-
- my $key;
- foreach $key (keys(%att))
- {
- $self->{Attributes}->{$key} = $att{$key};
- }
-}
-
-
-sub GetNamespace
-{
- my $self = shift;
-
- return $self->{Namespace};
-}
-
-sub GetXMLNS
-{
- my $self = shift;
-
- return $self->{XMLNS};
-}
-
-sub GetAttributes
-{
- my $self = shift;
- my ($attrib) = @_;
-
- return $self->{Attributes} if ($attrib eq "");
- return $self->{Attributes}->{$attrib};
-}
-
-
-sub GetStream
-{
- my $self = shift;
-
- my $string = "";
-
- $string .= "xmlns:".$self->GetNamespace();
- $string .= "='".$self->GetXMLNS()."'";
- my $attrib;
- foreach $attrib (keys(%{$self->GetAttributes()}))
- {
- $string .= " ".$self->GetNamespace().":";
- $string .= $attrib;
- $string .= "='".$self->GetAttributes($attrib)."'";
- }
-
- return $string;
-}
-
-1;
-
diff --git a/lib/XML/Stream/Node.pm b/lib/XML/Stream/Node.pm
deleted file mode 100644
index 4dca834..0000000
--- a/lib/XML/Stream/Node.pm
+++ /dev/null
@@ -1,944 +0,0 @@
-##############################################################################
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Library General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Library General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-# Jabber
-# Copyright (C) 1998-2004 Jabber Software Foundation http://jabber.org/
-#
-##############################################################################
-
-package XML::Stream::Node;
-
-=head1 NAME
-
-XML::Stream::Node - Functions to make building and parsing the tree easier
-to work with.
-
-=head1 SYNOPSIS
-
- Just a collection of functions that do not need to be in memory if you
-choose one of the other methods of data storage.
-
- This creates a hierarchy of Perl objects and provides various methods
-to manipulate the structure of the tree. It is much like the C library
-libxml.
-
-=head1 FORMAT
-
-The result of parsing:
-
- <foo><head id="a">Hello <em>there</em></head><bar>Howdy<ref/></bar>do</foo>
-
-would be:
-
- [ tag: foo
- att: {}
- children: [ tag: head
- att: {id=>"a"}
- children: [ tag: "__xmlstream__:node:cdata"
- children: "Hello "
- ]
- [ tag: em
- children: [ tag: "__xmlstream__:node:cdata"
- children: "there"
- ]
- ]
- ]
- [ tag: bar
- children: [ tag: "__xmlstream__:node:cdata"
- children: "Howdy "
- ]
- [ tag: ref
- ]
- ]
- [ tag: "__xmlstream__:node:cdata"
- children: "do"
- ]
- ]
-
-=head1 METHODS
-
- new() - creates a new node. If you specify tag, then the root
- new(tag) tag is set. If you specify data, then cdata is added
- new(tag,cdata) to the node as well. Returns the created node.
-
- get_tag() - returns the root tag of the node.
-
- set_tag(tag) - set the root tag of the node to tag.
-
- add_child(node) - adds the specified node as a child to the current
- add_child(tag) node, or creates a new node with the specified tag
- add_child(tag,cdata) as the root node. Returns the node added.
-
- remove_child(node) - removes the child node from the current node.
-
- remove_cdata() - removes all of the cdata children from the current node.
-
- add_cdata(string) - adds the string as cdata onto the current nodes
- child list.
-
- get_cdata() - returns all of the cdata children concatenated together
- into one string.
-
- get_attrib(attrib) - returns the value of the attrib if it is valid,
- or returns undef is attrib is not a real
- attribute.
-
- put_attrib(hash) - for each key/value pair specified, create an
- attribute in the node.
-
- remove_attrib(attrib) - remove the specified attribute from the node.
-
- add_raw_xml(string,[string,...]) - directly add a string into the XML
- packet as the last child, with no
- translation.
-
- get_raw_xml() - return all of the XML in a single string, undef if there
- is no raw XML to include.
-
- remove_raw_xml() - remove all raw XML strings.
-
- children() - return all of the children of the node in a list.
-
- attrib() - returns a hash containing all of the attributes on this
- node.
-
- copy() - return a recursive copy of the node.
-
- XPath(path) - run XML::Stream::XPath on this node.
-
- XPathCheck(path) - run XML::Stream::XPath on this node and return 1 or 0
- to see if it matches or not.
-
- GetXML() - return the node in XML string form.
-
-=head1 AUTHOR
-
-By Ryan Eatmon in June 2002 for http://jabber.org/
-
-=head1 COPYRIGHT
-
-This module is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
-
-use vars qw( $VERSION $LOADED );
-
-$VERSION = "1.22";
-$LOADED = 1;
-
-sub new
-{
- my $proto = shift;
- my $class = ref($proto) || $proto;
-
- if (ref($_[0]) eq "XML::Stream::Node")
- {
- return $_[0];
- }
-
- my $self = {};
- bless($self, $proto);
-
- my ($tag,$data) = @_;
-
- $self->set_tag($tag) if defined($tag);
- $self->add_cdata($data) if defined($data);
- $self->remove_raw_xml();
-
- return $self;
-}
-
-
-sub debug
-{
- my $self = shift;
- my ($indent) = @_;
-
- $indent = "" unless defined($indent);
-
- if ($self->{TAG} eq "__xmlstream__:node:cdata")
- {
- print $indent,"cdata(",join("",@{$self->{CHILDREN}}),")\n";
- }
- else
- {
- print $indent,"packet($self):\n";
- print $indent,"tag: <$self->{TAG}\n";
- if (scalar(keys(%{$self->{ATTRIBS}})) > 0)
- {
- print $indent,"attribs:\n";
- foreach my $key (sort {$a cmp $b} keys(%{$self->{ATTRIBS}}))
- {
- print $indent," $key = '$self->{ATTRIBS}->{$key}'\n";
- }
- }
- if ($#{$self->{CHILDREN}} == -1)
- {
- print $indent," />\n";
- }
- else
- {
- print $indent," >\n";
- print $indent,"children:\n";
- foreach my $child (@{$self->{CHILDREN}})
- {
- $child->debug($indent." ");
- }
- }
- print $indent," </$self->{TAG}>\n";
- }
-}
-
-
-sub children
-{
- my $self = shift;
-
- return () unless exists($self->{CHILDREN});
- return @{$self->{CHILDREN}};
-}
-
-
-sub add_child
-{
- my $self = shift;
-
- my $child = new XML::Stream::Node(@_);
- push(@{$self->{CHILDREN}},$child);
- return $child;
-}
-
-
-sub remove_child
-{
- my $self = shift;
- my $child = shift;
-
- foreach my $index (0..$#{$self->{CHILDREN}})
- {
- if ($child == $self->{CHILDREN}->[$index])
- {
- splice(@{$self->{CHILDREN}},$index,1);
- last;
- }
- }
-}
-
-
-sub add_cdata
-{
- my $self = shift;
- my $child = new XML::Stream::Node("__xmlstream__:node:cdata");
- foreach my $cdata (@_)
- {
- push(@{$child->{CHILDREN}},$cdata);
- }
- push(@{$self->{CHILDREN}},$child);
- return $child;
-}
-
-
-sub get_cdata
-{
- my $self = shift;
-
- my $cdata = "";
- foreach my $child (@{$self->{CHILDREN}})
- {
- $cdata .= join("",$child->children())
- if ($child->get_tag() eq "__xmlstream__:node:cdata");
- }
-
- return $cdata;
-}
-
-
-sub remove_cdata
-{
- my $self = shift;
-
- my @remove = ();
- foreach my $index (0..$#{$self->{CHILDREN}})
- {
- if ($self->{CHILDREN}->[$index]->get_tag() eq "__xmlstream__:node:cdata")
- {
-
- unshift(@remove,$index);
- }
- }
- foreach my $index (@remove)
- {
- splice(@{$self->{CHILDREN}},$index,1);
- }
-}
-
-
-sub attrib
-{
- my $self = shift;
- return () unless exists($self->{ATTRIBS});
- return %{$self->{ATTRIBS}};
-}
-
-
-sub get_attrib
-{
- my $self = shift;
- my ($key) = @_;
-
- return unless exists($self->{ATTRIBS}->{$key});
- return $self->{ATTRIBS}->{$key};
-}
-
-
-sub put_attrib
-{
- my $self = shift;
- my (%att) = @_;
-
- foreach my $key (keys(%att))
- {
- $self->{ATTRIBS}->{$key} = $att{$key};
- }
-}
-
-
-sub remove_attrib
-{
- my $self = shift;
- my ($key) = @_;
-
- return unless exists($self->{ATTRIBS}->{$key});
- delete($self->{ATTRIBS}->{$key});
-}
-
-
-sub add_raw_xml
-{
- my $self = shift;
- my (@raw) = @_;
-
- push(@{$self->{RAWXML}},@raw);
-}
-
-sub get_raw_xml
-{
- my $self = shift;
-
- return if ($#{$self->{RAWXML}} == -1);
- return join("",@{$self->{RAWXML}});
-}
-
-
-sub remove_raw_xml
-{
- my $self = shift;
- $self->{RAWXML} = [];
-}
-
-
-sub get_tag
-{
- my $self = shift;
-
- return $self->{TAG};
-}
-
-
-sub set_tag
-{
- my $self = shift;
- my ($tag) = @_;
-
- $self->{TAG} = $tag;
-}
-
-
-sub XPath
-{
- my $self = shift;
- my @results = &XML::Stream::XPath($self,@_);
- return unless ($#results > -1);
- return $results[0] unless wantarray;
- return @results;
-}
-
-
-sub XPathCheck
-{
- my $self = shift;
- return &XML::Stream::XPathCheck($self,@_);
-}
-
-
-sub GetXML
-{
- my $self = shift;
-
- return &BuildXML($self,@_);
-}
-
-
-sub copy
-{
- my $self = shift;
-
- my $new_node = new XML::Stream::Node();
- $new_node->set_tag($self->get_tag());
- $new_node->put_attrib($self->attrib());
-
- foreach my $child ($self->children())
- {
- if ($child->get_tag() eq "__xmlstream__:node:cdata")
- {
- $new_node->add_cdata($self->get_cdata());
- }
- else
- {
- $new_node->add_child($child->copy());
- }
- }
-
- return $new_node;
-}
-
-
-
-
-
-##############################################################################
-#
-# _handle_element - handles the main tag elements sent from the server.
-# On an open tag it creates a new XML::Parser::Node so
-# that _handle_cdata and _handle_element can add data
-# and tags to it later.
-#
-##############################################################################
-sub _handle_element
-{
- my $self;
- $self = $_[0] if (ref($_[0]) eq "XML::Stream::Parser");
- $self = shift unless (ref($_[0]) eq "XML::Stream::Parser");
- my ($sax, $tag, %att) = @_;
- my $sid = $sax->getSID();
-
- $self->debug(2,"Node: _handle_element: sid($sid) sax($sax) tag($tag) att(",%att,")");
-
- my $node = new XML::Stream::Node($tag);
- $node->put_attrib(%att);
-
- $self->debug(2,"Node: _handle_element: check(",$#{$self->{SIDS}->{$sid}->{node}},")");
-
- if ($#{$self->{SIDS}->{$sid}->{node}} >= 0)
- {
- $self->{SIDS}->{$sid}->{node}->[$#{$self->{SIDS}->{$sid}->{node}}]->
- add_child($node);
- }
-
- push(@{$self->{SIDS}->{$sid}->{node}},$node);
-}
-
-
-##############################################################################
-#
-# _handle_cdata - handles the CDATA that is encountered. Also, in the
-# spirit of XML::Parser::Node it combines any sequential
-# CDATA into one tag.
-#
-##############################################################################
-sub _handle_cdata
-{
- my $self;
- $self = $_[0] if (ref($_[0]) eq "XML::Stream::Parser");
- $self = shift unless (ref($_[0]) eq "XML::Stream::Parser");
- my ($sax, $cdata) = @_;
- my $sid = $sax->getSID();
-
- $self->debug(2,"Node: _handle_cdata: sid($sid) sax($sax) cdata($cdata)");
-
- return if ($#{$self->{SIDS}->{$sid}->{node}} == -1);
-
- $self->debug(2,"Node: _handle_cdata: sax($sax) cdata($cdata)");
-
- $self->{SIDS}->{$sid}->{node}->[$#{$self->{SIDS}->{$sid}->{node}}]->
- add_cdata($cdata);
-}
-
-
-##############################################################################
-#
-# _handle_close - when we see a close tag we need to pop the last element
-# from the list and push it onto the end of the previous
-# element. This is how we build our hierarchy.
-#
-##############################################################################
-sub _handle_close
-{
- my $self;
- $self = $_[0] if (ref($_[0]) eq "XML::Stream::Parser");
- $self = shift unless (ref($_[0]) eq "XML::Stream::Parser");
- my ($sax, $tag) = @_;
- my $sid = $sax->getSID();
-
- $self->debug(2,"Node: _handle_close: sid($sid) sax($sax) tag($tag)");
-
- $self->debug(2,"Node: _handle_close: check(",$#{$self->{SIDS}->{$sid}->{node}},")");
-
- if ($#{$self->{SIDS}->{$sid}->{node}} == -1)
- {
- $self->debug(2,"Node: _handle_close: rootTag($self->{SIDS}->{$sid}->{rootTag}) tag($tag)");
- if ($self->{SIDS}->{$sid}->{rootTag} ne $tag)
- {
- $self->{SIDS}->{$sid}->{streamerror} = "Root tag mis-match: <$self->{SIDS}->{$sid}->{rootTag}> ... </$tag>\n";
- }
- return;
- }
-
- my $CLOSED = pop @{$self->{SIDS}->{$sid}->{node}};
-
- $self->debug(2,"Node: _handle_close: check2(",$#{$self->{SIDS}->{$sid}->{node}},")");
-
- if($#{$self->{SIDS}->{$sid}->{node}} == -1)
- {
- push @{$self->{SIDS}->{$sid}->{node}}, $CLOSED;
-
- if (ref($self) ne "XML::Stream::Parser")
- {
- my $stream_prefix = $self->StreamPrefix($sid);
-
- if(defined($self->{SIDS}->{$sid}->{node}->[0]) &&
- ($self->{SIDS}->{$sid}->{node}->[0]->get_tag() =~ /^${stream_prefix}\:/))
- {
- my $node = $self->{SIDS}->{$sid}->{node}->[0];
- $self->{SIDS}->{$sid}->{node} = [];
- $self->ProcessStreamPacket($sid,$node);
- }
- else
- {
- my $node = $self->{SIDS}->{$sid}->{node}->[0];
- $self->{SIDS}->{$sid}->{node} = [];
-
- my @special =
- &XML::Stream::XPath(
- $node,
- '[@xmlns="'.&XML::Stream::ConstXMLNS("xmpp-sasl").'" or @xmlns="'.&XML::Stream::ConstXMLNS("xmpp-tls").'"]'
- );
- if ($#special > -1)
- {
- my $xmlns = $node->get_attrib("xmlns");
-
- $self->ProcessSASLPacket($sid,$node)
- if ($xmlns eq &XML::Stream::ConstXMLNS("xmpp-sasl"));
- $self->ProcessTLSPacket($sid,$node)
- if ($xmlns eq &XML::Stream::ConstXMLNS("xmpp-tls"));
- }
- else
- {
- &{$self->{CB}->{node}}($sid,$node);
- }
- }
- }
- }
-}
-
-
-##############################################################################
-#
-# SetXMLData - takes a host of arguments and sets a portion of the specified
-# XML::Parser::Node object with that data. The function works
-# in two modes "single" or "multiple". "single" denotes that
-# the function should locate the current tag that matches this
-# data and overwrite it's contents with data passed in.
-# "multiple" denotes that a new tag should be created even if
-# others exist.
-#
-# type - single or multiple
-# XMLTree - pointer to XML::Stream Node object
-# tag - name of tag to create/modify (if blank assumes
-# working with top level tag)
-# data - CDATA to set for tag
-# attribs - attributes to ADD to tag
-#
-##############################################################################
-sub SetXMLData
-{
- my ($type,$XMLTree,$tag,$data,$attribs) = @_;
-
- if ($tag ne "")
- {
- if ($type eq "single")
- {
- foreach my $child ($XMLTree->children())
- {
- if ($$XMLTree[1]->[$child] eq $tag)
- {
- $XMLTree->remove_child($child);
-
- my $newChild = $XMLTree->add_child($tag);
- $newChild->put_attrib(%{$attribs});
- $newChild->add_cdata($data) if ($data ne "");
- return;
- }
- }
- }
- my $newChild = $XMLTree->add_child($tag);
- $newChild->put_attrib(%{$attribs});
- $newChild->add_cdata($data) if ($data ne "");
- }
- else
- {
- $XMLTree->put_attrib(%{$attribs});
- $XMLTree->add_cdata($data) if ($data ne "");
- }
-}
-
-
-##############################################################################
-#
-# GetXMLData - takes a host of arguments and returns various data structures
-# that match them.
-#
-# type - "existence" - returns 1 or 0 if the tag exists in the
-# top level.
-# "value" - returns either the CDATA of the tag, or the
-# value of the attribute depending on which is
-# sought. This ignores any mark ups to the data
-# and just returns the raw CDATA.
-# "value array" - returns an array of strings representing
-# all of the CDATA in the specified tag.
-# This ignores any mark ups to the data
-# and just returns the raw CDATA.
-# "tree" - returns an XML::Parser::Node object with the
-# specified tag as the root tag.
-# "tree array" - returns an array of XML::Parser::Node
-# objects each with the specified tag as
-# the root tag.
-# "child array" - returns a list of all children nodes
-# not including CDATA nodes.
-# "attribs" - returns a hash with the attributes, and
-# their values, for the things that match
-# the parameters
-# "count" - returns the number of things that match
-# the arguments
-# "tag" - returns the root tag of this tree
-# XMLTree - pointer to XML::Parser::Node object
-# tag - tag to pull data from. If blank then the top level
-# tag is accessed.
-# attrib - attribute value to retrieve. Ignored for types
-# "value array", "tree", "tree array". If paired
-# with value can be used to filter tags based on
-# attributes and values.
-# value - only valid if an attribute is supplied. Used to
-# filter for tags that only contain this attribute.
-# Useful to search through multiple tags that all
-# reference different name spaces.
-#
-##############################################################################
-sub GetXMLData
-{
- my ($type,$XMLTree,$tag,$attrib,$value) = @_;
-
- $tag = "" if !defined($tag);
- $attrib = "" if !defined($attrib);
- $value = "" if !defined($value);
-
- my $skipthis = 0;
-
- #-------------------------------------------------------------------------
- # Check if a child tag in the root tag is being requested.
- #-------------------------------------------------------------------------
- if ($tag ne "")
- {
- my $count = 0;
- my @array;
- foreach my $child ($XMLTree->children())
- {
- if (($child->get_tag() eq $tag) || ($tag eq "*"))
- {
- #-------------------------------------------------------------
- # Filter out tags that do not contain the attribute and value.
- #-------------------------------------------------------------
- next if (($value ne "") && ($attrib ne "") && $child->get_attrib($attrib) && ($XMLTree->get_attrib($attrib) ne $value));
- next if (($attrib ne "") && !$child->get_attrib($attrib));
-
- #-------------------------------------------------------------
- # Check for existence
- #-------------------------------------------------------------
- if ($type eq "existence")
- {
- return 1;
- }
- #-------------------------------------------------------------
- # Return the raw CDATA value without mark ups, or the value of
- # the requested attribute.
- #-------------------------------------------------------------
- if ($type eq "value")
- {
- if ($attrib eq "")
- {
- my $str = $child->get_cdata();
- return $str;
- }
- return $XMLTree->get_attrib($attrib)
- if defined($XMLTree->get_attrib($attrib));
- }
- #-------------------------------------------------------------
- # Return an array of values that represent the raw CDATA without
- # mark up tags for the requested tags.
- #-------------------------------------------------------------
- if ($type eq "value array")
- {
- if ($attrib eq "")
- {
- my $str = $child->get_cdata();
- push(@array,$str);
- }
- else
- {
- push(@array, $XMLTree->get_attrib($attrib))
- if defined($XMLTree->get_attrib($attrib));
- }
- }
- #-------------------------------------------------------------
- # Return a pointer to a new XML::Parser::Tree object that has
- # the requested tag as the root tag.
- #-------------------------------------------------------------
- if ($type eq "tree")
- {
- return $child;
- }
- #-------------------------------------------------------------
- # Return an array of pointers to XML::Parser::Tree objects
- # that have the requested tag as the root tags.
- #-------------------------------------------------------------
- if ($type eq "tree array")
- {
- push(@array,$child);
- }
- #-------------------------------------------------------------
- # Return an array of pointers to XML::Parser::Tree objects
- # that have the requested tag as the root tags.
- #-------------------------------------------------------------
- if ($type eq "child array")
- {
- push(@array,$child) if ($child->get_tag() ne "__xmlstream__:node:cdata");
- }
- #-------------------------------------------------------------
- # Return a count of the number of tags that match
- #-------------------------------------------------------------
- if ($type eq "count")
- {
- $count++;
- }
- #-------------------------------------------------------------
- # Return the attribute hash that matches this tag
- #-------------------------------------------------------------
- if ($type eq "attribs")
- {
- return $XMLTree->attrib();
- }
- }
- }
- #---------------------------------------------------------------------
- # If we are returning arrays then return array.
- #---------------------------------------------------------------------
- if (($type eq "tree array") || ($type eq "value array") ||
- ($type eq "child array"))
- {
- return @array;
- }
-
- #---------------------------------------------------------------------
- # If we are returning then count, then do so
- #---------------------------------------------------------------------
- if ($type eq "count")
- {
- return $count;
- }
- }
- else
- {
- #---------------------------------------------------------------------
- # This is the root tag, so handle things a level up.
- #---------------------------------------------------------------------
-
- #---------------------------------------------------------------------
- # Return the raw CDATA value without mark ups, or the value of the
- # requested attribute.
- #---------------------------------------------------------------------
- if ($type eq "value")
- {
- if ($attrib eq "")
- {
- my $str = $XMLTree->get_cdata();
- return $str;
- }
- return $XMLTree->get_attrib($attrib)
- if $XMLTree->get_attrib($attrib);
- }
- #---------------------------------------------------------------------
- # Return a pointer to a new XML::Parser::Tree object that has the
- # requested tag as the root tag.
- #---------------------------------------------------------------------
- if ($type eq "tree")
- {
- return $XMLTree;
- }
-
- #---------------------------------------------------------------------
- # Return the 1 if the specified attribute exists in the root tag.
- #---------------------------------------------------------------------
- if ($type eq "existence")
- {
- if ($attrib ne "")
- {
- return ($XMLTree->get_attrib($attrib) eq $value) if ($value ne "");
- return defined($XMLTree->get_attrib($attrib));
- }
- return 0;
- }
-
- #---------------------------------------------------------------------
- # Return the attribute hash that matches this tag
- #---------------------------------------------------------------------
- if ($type eq "attribs")
- {
- return $XMLTree->attrib();
- }
- #---------------------------------------------------------------------
- # Return the tag of this node
- #---------------------------------------------------------------------
- if ($type eq "tag")
- {
- return $XMLTree->get_tag();
- }
- }
- #-------------------------------------------------------------------------
- # Return 0 if this was a request for existence, or "" if a request for
- # a "value", or [] for "tree", "value array", and "tree array".
- #-------------------------------------------------------------------------
- return 0 if ($type eq "existence");
- return "" if ($type eq "value");
- return [];
-}
-
-
-##############################################################################
-#
-# BuildXML - takes an XML::Parser::Tree object and builds the XML string
-# that it represents.
-#
-##############################################################################
-sub BuildXML
-{
- my ($node,$rawXML) = @_;
-
- my $str = "<".$node->get_tag();
-
- my %attrib = $node->attrib();
-
- foreach my $att (sort {$a cmp $b} keys(%attrib))
- {
- $str .= " ".$att."='".&XML::Stream::EscapeXML($attrib{$att})."'";
- }
-
- my @children = $node->children();
- if (($#children > -1) ||
- (defined($rawXML) && ($rawXML ne "")) ||
- (defined($node->get_raw_xml()) && ($node->get_raw_xml() ne ""))
- )
- {
- $str .= ">";
- foreach my $child (@children)
- {
- if ($child->get_tag() eq "__xmlstream__:node:cdata")
- {
- $str .= &XML::Stream::EscapeXML(join("",$child->children()));
- }
- else
- {
- $str .= &XML::Stream::Node::BuildXML($child);
- }
- }
- $str .= $node->get_raw_xml()
- if (defined($node->get_raw_xml()) &&
- ($node->get_raw_xml() ne "")
- );
- $str .= $rawXML if (defined($rawXML) && ($rawXML ne ""));
- $str .= "</".$node->get_tag().">";
- }
- else
- {
- $str .= "/>";
- }
-
- return $str;
-}
-
-
-##############################################################################
-#
-# XML2Config - takes an XML data tree and turns it into a hash of hashes.
-# This only works for certain kinds of XML trees like this:
-#
-# <foo>
-# <bar>1</bar>
-# <x>
-# <y>foo</y>
-# </x>
-# <z>5</z>
-# </foo>
-#
-# The resulting hash would be:
-#
-# $hash{bar} = 1;
-# $hash{x}->{y} = "foo";
-# $hash{z} = 5;
-#
-# Good for config files.
-#
-##############################################################################
-sub XML2Config
-{
- my ($XMLTree) = @_;
-
- my %hash;
- foreach my $tree (&XML::Stream::GetXMLData("tree array",$XMLTree,"*"))
- {
- if ($tree->get_tag() eq "__xmlstream__:node:cdata")
- {
- my $str = join("",$tree->children());
- return $str unless ($str =~ /^\s*$/);
- }
- else
- {
- if (&XML::Stream::GetXMLData("count",$XMLTree,$tree->get_tag()) > 1)
- {
- push(@{$hash{$tree->get_tag()}},&XML::Stream::XML2Config($tree));
- }
- else
- {
- $hash{$tree->get_tag()} = &XML::Stream::XML2Config($tree);
- }
- }
- }
- return \%hash;
-}
-
-
-1;
diff --git a/lib/XML/Stream/Parser.pm b/lib/XML/Stream/Parser.pm
deleted file mode 100644
index 9ca7832..0000000
--- a/lib/XML/Stream/Parser.pm
+++ /dev/null
@@ -1,567 +0,0 @@
-##############################################################################
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Library General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Library General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-# Jabber
-# Copyright (C) 1998-2004 Jabber Software Foundation http://jabber.org/
-#
-##############################################################################
-
-package XML::Stream::Parser;
-
-=head1 NAME
-
- XML::Stream::Parser - SAX XML Parser for XML Streams
-
-=head1 SYNOPSIS
-
- Light weight XML parser that builds XML::Parser::Tree objects from the
- incoming stream and passes them to a function to tell whoever is using
- it that there are new packets.
-
-=head1 DESCRIPTION
-
- This module provides a very light weight parser
-
-=head1 METHODS
-
-=head1 EXAMPLES
-
-=head1 AUTHOR
-
-By Ryan Eatmon in January of 2001 for http://jabber.org/
-
-=head1 COPYRIGHT
-
-This module is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
-
-use strict;
-use vars qw( $VERSION );
-
-$VERSION = "1.22";
-
-sub new
-{
- my $self = { };
-
- bless($self);
-
- my %args;
- while($#_ >= 0) { $args{ lc pop(@_) } = pop(@_); }
-
- $self->{PARSING} = 0;
- $self->{DOC} = 0;
- $self->{XML} = "";
- $self->{CNAME} = ();
- $self->{CURR} = 0;
-
- $args{nonblocking} = 0 unless exists($args{nonblocking});
-
- $self->{NONBLOCKING} = delete($args{nonblocking});
-
- $self->{DEBUGTIME} = 0;
- $self->{DEBUGTIME} = $args{debugtime} if exists($args{debugtime});
-
- $self->{DEBUGLEVEL} = 0;
- $self->{DEBUGLEVEL} = $args{debuglevel} if exists($args{debuglevel});
-
- $self->{DEBUGFILE} = "";
-
- if (exists($args{debugfh}) && ($args{debugfh} ne ""))
- {
- $self->{DEBUGFILE} = $args{debugfh};
- $self->{DEBUG} = 1;
- }
-
- if ((exists($args{debugfh}) && ($args{debugfh} eq "")) ||
- (exists($args{debug}) && ($args{debug} ne "")))
- {
- $self->{DEBUG} = 1;
- if (lc($args{debug}) eq "stdout")
- {
- $self->{DEBUGFILE} = new FileHandle(">&STDERR");
- $self->{DEBUGFILE}->autoflush(1);
- }
- else
- {
- if (-e $args{debug})
- {
- if (-w $args{debug})
- {
- $self->{DEBUGFILE} = new FileHandle(">$args{debug}");
- $self->{DEBUGFILE}->autoflush(1);
- }
- else
- {
- print "WARNING: debug file ($args{debug}) is not writable by you\n";
- print " No debug information being saved.\n";
- $self->{DEBUG} = 0;
- }
- }
- else
- {
- $self->{DEBUGFILE} = new FileHandle(">$args{debug}");
- if (defined($self->{DEBUGFILE}))
- {
- $self->{DEBUGFILE}->autoflush(1);
- }
- else
- {
- print "WARNING: debug file ($args{debug}) does not exist \n";
- print " and is not writable by you.\n";
- print " No debug information being saved.\n";
- $self->{DEBUG} = 0;
- }
- }
- }
- }
-
- $self->{SID} = exists($args{sid}) ? $args{sid} : "__xmlstream__:sid";
-
- $self->{STYLE} = (exists($args{style}) ? lc($args{style}) : "tree");
- $self->{DTD} = (exists($args{dtd}) ? lc($args{dtd}) : 0);
-
- if ($self->{STYLE} eq "tree")
- {
- $self->{HANDLER}->{startDocument} = sub{ $self->startDocument(@_); };
- $self->{HANDLER}->{endDocument} = sub{ $self->endDocument(@_); };
- $self->{HANDLER}->{startElement} = sub{ &XML::Stream::Tree::_handle_element(@_); };
- $self->{HANDLER}->{endElement} = sub{ &XML::Stream::Tree::_handle_close(@_); };
- $self->{HANDLER}->{characters} = sub{ &XML::Stream::Tree::_handle_cdata(@_); };
- }
- elsif ($self->{STYLE} eq "node")
- {
- $self->{HANDLER}->{startDocument} = sub{ $self->startDocument(@_); };
- $self->{HANDLER}->{endDocument} = sub{ $self->endDocument(@_); };
- $self->{HANDLER}->{startElement} = sub{ &XML::Stream::Node::_handle_element(@_); };
- $self->{HANDLER}->{endElement} = sub{ &XML::Stream::Node::_handle_close(@_); };
- $self->{HANDLER}->{characters} = sub{ &XML::Stream::Node::_handle_cdata(@_); };
- }
- $self->setHandlers(%{$args{handlers}});
-
- $self->{XMLONHOLD} = "";
-
- return $self;
-}
-
-
-###########################################################################
-#
-# debug - prints the arguments to the debug log if debug is turned on.
-#
-###########################################################################
-sub debug
-{
- return if ($_[1] > $_[0]->{DEBUGLEVEL});
- my $self = shift;
- my ($limit,@args) = @_;
- return if ($self->{DEBUGFILE} eq "");
- my $fh = $self->{DEBUGFILE};
- if ($self->{DEBUGTIME} == 1)
- {
- my ($sec,$min,$hour) = localtime(time);
- print $fh sprintf("[%02d:%02d:%02d] ",$hour,$min,$sec);
- }
- print $fh "XML::Stream::Parser: $self->{STYLE}: @args\n";
-}
-
-
-sub setSID
-{
- my $self = shift;
- my $sid = shift;
- $self->{SID} = $sid;
-}
-
-
-sub getSID
-{
- my $self = shift;
- return $self->{SID};
-}
-
-
-sub setHandlers
-{
- my $self = shift;
- my (%handlers) = @_;
-
- foreach my $handler (keys(%handlers))
- {
- $self->{HANDLER}->{$handler} = $handlers{$handler};
- }
-}
-
-
-sub parse
-{
- my $self = shift;
- my $xml = shift;
-
- return unless defined($xml);
- return if ($xml eq "");
-
- if ($self->{XMLONHOLD} ne "")
- {
- $self->{XML} = $self->{XMLONHOLD};
- $self->{XMLONHOLD} = "";
- }
-
- # XXX change this to not use regex?
- while($xml =~ s/<\!--.*?-->//gs) {}
-
- $self->{XML} .= $xml;
-
- return if ($self->{PARSING} == 1);
-
- $self->{PARSING} = 1;
-
- if(!$self->{DOC} == 1)
- {
- my $start = index($self->{XML},"<");
-
- if ((substr($self->{XML},$start,3) eq "<?x") ||
- (substr($self->{XML},$start,3) eq "<?X"))
- {
- my $close = index($self->{XML},"?>");
- if ($close == -1)
- {
- $self->{PARSING} = 0;
- return;
- }
- $self->{XML} = substr($self->{XML},$close+2,length($self->{XML})-$close-2);
- }
-
- &{$self->{HANDLER}->{startDocument}}($self);
- $self->{DOC} = 1;
- }
-
- while(1)
- {
- if (length($self->{XML}) == 0)
- {
- $self->{PARSING} = 0;
- return $self->returnData(0);
- }
- my $eclose = -1;
- $eclose = index($self->{XML},"</".$self->{CNAME}->[$self->{CURR}].">")
- if ($#{$self->{CNAME}} > -1);
-
- if ($eclose == 0)
- {
- $self->{XML} = substr($self->{XML},length($self->{CNAME}->[$self->{CURR}])+3,length($self->{XML})-length($self->{CNAME}->[$self->{CURR}])-3);
-
- $self->{PARSING} = 0 if ($self->{NONBLOCKING} == 1);
- &{$self->{HANDLER}->{endElement}}($self,$self->{CNAME}->[$self->{CURR}]);
- $self->{PARSING} = 1 if ($self->{NONBLOCKING} == 1);
-
- $self->{CURR}--;
- if ($self->{CURR} == 0)
- {
- $self->{DOC} = 0;
- $self->{PARSING} = 0;
- &{$self->{HANDLER}->{endDocument}}($self);
- return $self->returnData(0);
- }
- next;
- }
-
- my $estart = index($self->{XML},"<");
- my $cdatastart = index($self->{XML},"<![CDATA[");
- if (($estart == 0) && ($cdatastart != 0))
- {
- my $close = index($self->{XML},">");
- if ($close == -1)
- {
- $self->{PARSING} = 0;
- return $self->returnData(0);
- }
- my $empty = (substr($self->{XML},$close-1,1) eq "/");
- my $starttag = substr($self->{XML},1,$close-($empty ? 2 : 1));
- my $nextspace = index($starttag," ");
- my $attribs;
- my $name;
- if ($nextspace != -1)
- {
- $name = substr($starttag,0,$nextspace);
- $attribs = substr($starttag,$nextspace+1,length($starttag)-$nextspace-1);
- }
- else
- {
- $name = $starttag;
- }
-
- my %attribs = $self->attribution($attribs);
- if (($self->{DTD} == 1) && (exists($attribs{xmlns})))
- {
- }
-
- &{$self->{HANDLER}->{startElement}}($self,$name,%attribs);
-
- if($empty == 1)
- {
- &{$self->{HANDLER}->{endElement}}($self,$name);
- }
- else
- {
- $self->{CURR}++;
- $self->{CNAME}->[$self->{CURR}] = $name;
- }
-
- $self->{XML} = substr($self->{XML},$close+1,length($self->{XML})-$close-1);
- next;
- }
-
- if ($cdatastart == 0)
- {
- my $cdataclose = index($self->{XML},"]]>");
- if ($cdataclose == -1)
- {
- $self->{PARSING} = 0;
- return $self->returnData(0);
- }
-
- &{$self->{HANDLER}->{characters}}($self,substr($self->{XML},9,$cdataclose-9));
-
- $self->{XML} = substr($self->{XML},$cdataclose+3,length($self->{XML})-$cdataclose-3);
- next;
- }
-
- if ($estart == -1)
- {
- $self->{XMLONHOLD} = $self->{XML};
- $self->{XML} = "";
- }
- elsif (($cdatastart == -1) || ($cdatastart > $estart))
- {
- &{$self->{HANDLER}->{characters}}($self,$self->entityCheck(substr($self->{XML},0,$estart)));
- $self->{XML} = substr($self->{XML},$estart,length($self->{XML})-$estart);
- }
- }
-}
-
-
-sub attribution
-{
- my $self = shift;
- my $str = shift;
-
- $str = "" unless defined($str);
-
- my %attribs;
-
- while(1)
- {
- my $eq = index($str,"=");
- if((length($str) == 0) || ($eq == -1))
- {
- return %attribs;
- }
-
- my $ids;
- my $id;
- my $id1 = index($str,"\'");
- my $id2 = index($str,"\"");
- if((($id1 < $id2) && ($id1 != -1)) || ($id2 == -1))
- {
- $ids = $id1;
- $id = "\'";
- }
- if((($id2 < $id1) && ($id1 == -1)) || ($id2 != -1))
- {
- $ids = $id2;
- $id = "\"";
- }
-
- my $nextid = index($str,$id,$ids+1);
- my $val = substr($str,$ids+1,$nextid-$ids-1);
- my $key = substr($str,0,$eq);
-
- while($key =~ s/\s//) {}
-
- $attribs{$key} = $self->entityCheck($val);
- $str = substr($str,$nextid+1,length($str)-$nextid-1);
- }
-
- return %attribs;
-}
-
-
-sub entityCheck
-{
- my $self = shift;
- my $str = shift;
-
- while($str =~ s/\&lt\;/\</) {}
- while($str =~ s/\&gt\;/\>/) {}
- while($str =~ s/\&quot\;/\"/) {}
- while($str =~ s/\&apos\;/\'/) {}
- while($str =~ s/\&amp\;/\&/) {}
-
- return $str;
-}
-
-
-sub parsefile
-{
- my $self = shift;
- my $fileName = shift;
-
- open(FILE,"<",$fileName);
- my $file;
- while(<FILE>) { $file .= $_; }
- $self->parse($file);
- close(FILE);
-
- return $self->returnData();
-}
-
-
-sub returnData
-{
- my $self = shift;
- my $clearData = shift;
- $clearData = 1 unless defined($clearData);
-
- my $sid = $self->{SID};
-
- if ($self->{STYLE} eq "tree")
- {
- return unless exists($self->{SIDS}->{$sid}->{tree});
- my @tree = @{$self->{SIDS}->{$sid}->{tree}};
- delete($self->{SIDS}->{$sid}->{tree}) if ($clearData == 1);
- return ( \@tree );
- }
- if ($self->{STYLE} eq "node")
- {
- return unless exists($self->{SIDS}->{$sid}->{node});
- my $node = $self->{SIDS}->{$sid}->{node}->[0];
- delete($self->{SIDS}->{$sid}->{node}) if ($clearData == 1);
- return $node;
- }
-}
-
-
-sub startDocument
-{
- my $self = shift;
-}
-
-
-sub endDocument
-{
- my $self = shift;
-}
-
-
-sub startElement
-{
- my $self = shift;
- my ($sax, $tag, %att) = @_;
-
- return unless ($self->{DOC} == 1);
-
- if ($self->{STYLE} eq "debug")
- {
- print "$self->{DEBUGHEADER} \\\\ (",join(" ",%att),")\n";
- $self->{DEBUGHEADER} .= $tag." ";
- }
- else
- {
- my @NEW;
- if($#{$self->{TREE}} < 0)
- {
- push @{$self->{TREE}}, $tag;
- }
- else
- {
- push @{ $self->{TREE}[ $#{$self->{TREE}}]}, $tag;
- }
- push @NEW, \%att;
- push @{$self->{TREE}}, \@NEW;
- }
-}
-
-
-sub characters
-{
- my $self = shift;
- my ($sax, $cdata) = @_;
-
- return unless ($self->{DOC} == 1);
-
- if ($self->{STYLE} eq "debug")
- {
- my $str = $cdata;
- $str =~ s/\n/\#10\;/g;
- print "$self->{DEBUGHEADER} || $str\n";
- }
- else
- {
- return if ($#{$self->{TREE}} == -1);
-
- my $pos = $#{$self->{TREE}};
-
- if ($pos > 0 && $self->{TREE}[$pos - 1] eq "0")
- {
- $self->{TREE}[$pos - 1] .= $cdata;
- }
- else
- {
- push @{$self->{TREE}[$#{$self->{TREE}}]}, 0;
- push @{$self->{TREE}[$#{$self->{TREE}}]}, $cdata;
- }
- }
-}
-
-
-sub endElement
-{
- my $self = shift;
- my ($sax, $tag) = @_;
-
- return unless ($self->{DOC} == 1);
-
- if ($self->{STYLE} eq "debug")
- {
- $self->{DEBUGHEADER} =~ s/\S+\ $//;
- print "$self->{DEBUGHEADER} //\n";
- }
- else
- {
- my $CLOSED = pop @{$self->{TREE}};
-
- if($#{$self->{TREE}} < 1)
- {
- push @{$self->{TREE}}, $CLOSED;
-
- if($self->{TREE}->[0] eq "stream:error")
- {
- $self->{STREAMERROR} = $self->{TREE}[1]->[2];
- }
- }
- else
- {
- push @{$self->{TREE}[$#{$self->{TREE}}]}, $CLOSED;
- }
- }
-}
-
-
-1;
diff --git a/lib/XML/Stream/Parser/DTD.pm b/lib/XML/Stream/Parser/DTD.pm
deleted file mode 100644
index 25dc888..0000000
--- a/lib/XML/Stream/Parser/DTD.pm
+++ /dev/null
@@ -1,769 +0,0 @@
-##############################################################################
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Library General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Library General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-# Jabber
-# Copyright (C) 1998-2004 Jabber Software Foundation http://jabber.org/
-#
-##############################################################################
-
-package XML::Stream::Parser::DTD;
-
-=head1 NAME
-
- XML::Stream::Parser::DTD - XML DTD Parser and Verifier
-
-=head1 SYNOPSIS
-
- This is a work in progress. I had need for a DTD parser and verifier
- and so am working on it here. If you are reading this then you are
- snooping. =)
-
-=head1 DESCRIPTION
-
- This module provides the initial code for a DTD parser and verifier.
-
-=head1 METHODS
-
-=head1 EXAMPLES
-
-=head1 AUTHOR
-
-By Ryan Eatmon in February of 2001 for http://jabber.org/
-
-=head1 COPYRIGHT
-
-This module is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
-
-use strict;
-use vars qw( $VERSION );
-
-$VERSION = "1.22";
-
-sub new
-{
- my $self = { };
-
- bless($self);
-
- my %args;
- while($#_ >= 0) { $args{ lc pop(@_) } = pop(@_); }
-
- $self->{URI} = $args{uri};
-
- $self->{PARSING} = 0;
- $self->{DOC} = 0;
- $self->{XML} = "";
- $self->{CNAME} = ();
- $self->{CURR} = 0;
-
- $self->{ENTITY}->{"&lt;"} = "<";
- $self->{ENTITY}->{"&gt;"} = ">";
- $self->{ENTITY}->{"&quot;"} = "\"";
- $self->{ENTITY}->{"&apos;"} = "'";
- $self->{ENTITY}->{"&amp;"} = "&";
-
- $self->{HANDLER}->{startDocument} = sub{ $self->startDocument(@_); };
- $self->{HANDLER}->{endDocument} = sub{ $self->endDocument(@_); };
- $self->{HANDLER}->{startElement} = sub{ $self->startElement(@_); };
- $self->{HANDLER}->{endElement} = sub{ $self->endElement(@_); };
-
- $self->{STYLE} = "debug";
-
- open(DTD,$args{uri});
- my $dtd = join("",<DTD>);
- close(DTD);
-
- $self->parse($dtd);
-
- return $self;
-}
-
-
-sub parse
-{
- my $self = shift;
- my $xml = shift;
-
- while($xml =~ s/<\!--.*?-->//gs) {}
- while($xml =~ s/\n//g) {}
-
- $self->{XML} .= $xml;
-
- return if ($self->{PARSING} == 1);
-
- $self->{PARSING} = 1;
-
- if(!$self->{DOC} == 1)
- {
- my $start = index($self->{XML},"<");
-
- if (substr($self->{XML},$start,3) =~ /^<\?x$/i)
- {
- my $close = index($self->{XML},"?>");
- if ($close == -1)
- {
- $self->{PARSING} = 0;
- return;
- }
- $self->{XML} = substr($self->{XML},$close+2,length($self->{XML})-$close-2);
- }
-
- &{$self->{HANDLER}->{startDocument}}($self);
- $self->{DOC} = 1;
- }
-
- while(1)
- {
-
- if (length($self->{XML}) == 0)
- {
- $self->{PARSING} = 0;
- return;
- }
-
- my $estart = index($self->{XML},"<");
- if ($estart == -1)
- {
- $self->{PARSING} = 0;
- return;
- }
-
- my $close = index($self->{XML},">");
- my $dtddata = substr($self->{XML},$estart+1,$close-1);
- my $nextspace = index($dtddata," ");
- my $attribs;
-
- my $type = substr($dtddata,0,$nextspace);
- $dtddata = substr($dtddata,$nextspace+1,length($dtddata)-$nextspace-1);
- $nextspace = index($dtddata," ");
-
- if ($type eq "!ENTITY")
- {
- $self->entity($type,$dtddata);
- }
- else
- {
- my $tag = substr($dtddata,0,$nextspace);
- $dtddata = substr($dtddata,$nextspace+1,length($dtddata)-$nextspace-1);
- $nextspace = index($dtddata," ");
-
- $self->element($type,$tag,$dtddata) if ($type eq "!ELEMENT");
- $self->attlist($type,$tag,$dtddata) if ($type eq "!ATTLIST");
- }
-
- $self->{XML} = substr($self->{XML},$close+1,length($self->{XML})-$close-1);
- next;
- }
-}
-
-
-sub startDocument
-{
- my $self = shift;
-}
-
-
-sub endDocument
-{
- my $self = shift;
-}
-
-
-sub entity
-{
- my $self = shift;
- my ($type, $data) = @_;
-
- foreach my $entity (keys(%{$self->{ENTITY}}))
- {
- $data =~ s/$entity/$self->{ENTITY}->{$entity}/g;
- }
-
- my ($symbol,$tag,undef,$string) = ($data =~ /^\s*(\S+)\s+(\S+)\s+(\"|\')([^\3]*)\3\s*$/);
- $self->{ENTITY}->{"${symbol}${tag}\;"} = $string;
-}
-
-sub element
-{
- my $self = shift;
- my ($type, $tag, $data) = @_;
-
- foreach my $entity (keys(%{$self->{ENTITY}}))
- {
- $data =~ s/$entity/$self->{ENTITY}->{$entity}/g;
- }
-
- $self->{COUNTER}->{$tag} = 0 unless exists($self->{COUNTER}->{$tag});
-
- $self->parsegrouping($tag,\$self->{ELEMENT}->{$tag},$data);
- $self->flattendata(\$self->{ELEMENT}->{$tag});
-
-}
-
-
-sub flattendata
-{
- my $self = shift;
- my $dstr = shift;
-
- if ($$dstr->{type} eq "list")
- {
- foreach my $index (0..$#{$$dstr->{list}})
- {
- $self->flattendata(\$$dstr->{list}->[$index]);
- }
-
- if (!exists($$dstr->{repeat}) && ($#{$$dstr->{list}} == 0))
- {
- $$dstr = $$dstr->{list}->[0];
- }
- }
-}
-
-sub parsegrouping
-{
- my $self = shift;
- my ($tag,$dstr,$data) = @_;
-
- $data =~ s/^\s*//;
- $data =~ s/\s*$//;
-
- if ($data =~ /[\*\+\?]$/)
- {
- ($$dstr->{repeat}) = ($data =~ /(.)$/);
- $data =~ s/.$//;
- }
-
- if ($data =~ /^\(.*\)$/)
- {
- my ($seperator) = ($data =~ /^\(\s*\S+\s*(\,|\|)/);
- $$dstr->{ordered} = "yes" if ($seperator eq ",");
- $$dstr->{ordered} = "no" if ($seperator eq "|");
-
- my $count = 0;
- $$dstr->{type} = "list";
- foreach my $grouping ($self->groupinglist($data,$seperator))
- {
- $self->parsegrouping($tag,\$$dstr->{list}->[$count],$grouping);
- $count++;
- }
- }
- else
- {
- $$dstr->{type} = "element";
- $$dstr->{element} = $data;
- $self->{COUNTER}->{$data} = 0 unless exists($self->{COUNTER}->{$data});
- $self->{COUNTER}->{$data}++;
- $self->{CHILDREN}->{$tag}->{$data} = 1;
- }
-}
-
-
-sub attlist
-{
- my $self = shift;
- my ($type, $tag, $data) = @_;
-
- foreach my $entity (keys(%{$self->{ENTITY}}))
- {
- $data =~ s/$entity/$self->{ENTITY}->{$entity}/g;
- }
-
- while($data ne "")
- {
- my ($att) = ($data =~ /^\s*(\S+)/);
- $data =~ s/^\s*\S+\s*//;
-
- my $value;
- if ($data =~ /^\(/)
- {
- $value = $self->getgrouping($data);
- $data = substr($data,length($value)+1,length($data));
- $data =~ s/^\s*//;
- $self->{ATTLIST}->{$tag}->{$att}->{type} = "list";
- foreach my $val (split(/\s*\|\s*/,substr($value,1,length($value)-2))) {
-$self->{ATTLIST}->{$tag}->{$att}->{value}->{$val} = 1;
- }
- }
- else
- {
- ($value) = ($data =~ /^(\S+)/);
- $data =~ s/^\S+\s*//;
- $self->{ATTLIST}->{$tag}->{$att}->{type} = $value;
- }
-
- my $default;
- if ($data =~ /^\"|^\'/)
- {
- my($sq,$val) = ($data =~ /^(\"|\')([^\"\']*)\1/);
- $default = $val;
- $data =~ s/^$sq$val$sq\s*//;
- }
- else
- {
- ($default) = ($data =~ /^(\S+)/);
- $data =~ s/^\S+\s*//;
- }
-
- $self->{ATTLIST}->{$tag}->{$att}->{default} = $default;
- }
-}
-
-
-
-sub getgrouping
-{
- my $self = shift;
- my ($data) = @_;
-
- my $count = 0;
- my $parens = 0;
- foreach my $char (split("",$data))
- {
- $parens++ if ($char eq "(");
- $parens-- if ($char eq ")");
- $count++;
- last if ($parens == 0);
- }
- return substr($data,0,$count);
-}
-
-
-sub groupinglist
-{
- my $self = shift;
- my ($grouping,$seperator) = @_;
-
- my @list;
- my $item = "";
- my $parens = 0;
- my $word = "";
- $grouping = substr($grouping,1,length($grouping)-2) if ($grouping =~ /^\(/);
- foreach my $char (split("",$grouping))
- {
- $parens++ if ($char eq "(");
- $parens-- if ($char eq ")");
- if (($parens == 0) && ($char eq $seperator))
- {
- push(@list,$word);
- $word = "";
- }
- else
- {
- $word .= $char;
- }
- }
- push(@list,$word) unless ($word eq "");
- return @list;
-}
-
-
-sub root
-{
- my $self = shift;
- my $tag = shift;
- my @root;
- foreach my $tag (keys(%{$self->{COUNTER}}))
- {
- push(@root,$tag) if ($self->{COUNTER}->{$tag} == 0);
- }
-
- print "ERROR: Too many root tags... Check the DTD...\n"
- if ($#root > 0);
- return $root[0];
-}
-
-
-sub children
-{
- my $self = shift;
- my ($tag,$tree) = @_;
-
- return unless exists ($self->{CHILDREN}->{$tag});
- return if (exists($self->{CHILDREN}->{$tag}->{EMPTY}));
- if (defined($tree))
- {
- my @current;
- foreach my $current (&XML::Stream::GetXMLData("tree array",$tree,"*","",""))
- {
- push(@current,$$current[0]);
- }
- return $self->allowedchildren($self->{ELEMENT}->{$tag},\@current);
- }
- return $self->allowedchildren($self->{ELEMENT}->{$tag});
-}
-
-
-sub allowedchildren
-{
- my $self = shift;
- my ($dstr,$current) = @_;
-
- my @allowed;
-
- if ($dstr->{type} eq "element")
- {
- my $test = (defined($current) && $#{@{$current}} > -1) ? $$current[0] : "";
- shift(@{$current}) if ($dstr->{element} eq $test);
- if ($self->repeatcheck($dstr,$test) == 1)
- {
- return $dstr->{element};
- }
- }
- else
- {
- foreach my $index (0..$#{$dstr->{list}})
- {
- push(@allowed,$self->allowedchildren($dstr->{list}->[$index],$current));
- }
- }
-
- return @allowed;
-}
-
-
-sub repeatcheck
-{
- my $self = shift;
- my ($dstr,$tag) = @_;
-
- $dstr = $self->{ELEMENT}->{$dstr} if exists($self->{ELEMENT}->{$dstr});
-
-# print "repeatcheck: tag($tag)\n";
-# print "repeatcheck: repeat($dstr->{repeat})\n"
-# if exists($dstr->{repeat});
-
- my $return = 0;
- $return = ((!defined($tag) ||
- ($tag eq $dstr->{element})) ?
- 0 :
- 1)
- if (!exists($dstr->{repeat}) ||
- ($dstr->{repeat} eq "?"));
- $return = ((defined($tag) ||
- (exists($dstr->{ordered}) &&
- ($dstr->{ordered} eq "yes"))) ?
- 1 :
- 0)
- if (exists($dstr->{repeat}) &&
- (($dstr->{repeat} eq "+") ||
- ($dstr->{repeat} eq "*")));
-
-# print "repeatcheck: return($return)\n";
- return $return;
-}
-
-
-sub required
-{
- my $self = shift;
- my ($dstr,$tag,$count) = @_;
-
- $dstr = $self->{ELEMENT}->{$dstr} if exists($self->{ELEMENT}->{$dstr});
-
- if ($dstr->{type} eq "element")
- {
- return 0 if ($dstr->{element} ne $tag);
- return 1 if !exists($dstr->{repeat});
- return 1 if (($dstr->{repeat} eq "+") && ($count == 1)) ;
- }
- else
- {
- return 0 if (($dstr->{repeat} eq "*") || ($dstr->{repeat} eq "?"));
- my $test = 0;
- foreach my $index (0..$#{$dstr->{list}})
- {
- $test = $test | $self->required($dstr->{list}->[$index],$tag,$count);
- }
- return $test;
- }
- return 0;
-}
-
-
-sub addchild
-{
- my $self = shift;
- my ($tag,$child,$tree) = @_;
-
-# print "addchild: tag($tag) child($child)\n";
-
- my @current;
- if (defined($tree))
- {
-# &Net::Jabber::printData("\$tree",$tree);
-
- @current = &XML::Stream::GetXMLData("index array",$tree,"*","","");
-
-# &Net::Jabber::printData("\$current",\@current);
- }
-
- my @newBranch = $self->addchildrecurse($self->{ELEMENT}->{$tag},$child,\@current);
-
- return $tree unless ("@newBranch" ne "");
-
-# &Net::Jabber::printData("\$newBranch",\@newBranch);
-
- my $location = shift(@newBranch);
-
- if ($location eq "end")
- {
- splice(@{$$tree[1]},@{$$tree[1]},0,@newBranch);
- }
- else
- {
- splice(@{$$tree[1]},$location,0,@newBranch);
- }
- return $tree;
-}
-
-
-sub addcdata
-{
- my $self = shift;
- my ($tag,$child,$tree) = @_;
-
-# print "addchild: tag($tag) child($child)\n";
-
- my @current;
- if (defined($tree))
- {
-# &Net::Jabber::printData("\$tree",$tree);
-
- @current = &XML::Stream::GetXMLData("index array",$tree,"*","","");
-
-# &Net::Jabber::printData("\$current",\@current);
- }
-
- my @newBranch = $self->addchildrecurse($self->{ELEMENT}->{$tag},$child,\@current);
-
- return $tree unless ("@newBranch" ne "");
-
-# &Net::Jabber::printData("\$newBranch",\@newBranch);
-
- my $location = shift(@newBranch);
-
- if ($location eq "end")
- {
- splice(@{$$tree[1]},@{$$tree[1]},0,@newBranch);
- }
- else
- {
- splice(@{$$tree[1]},$location,0,@newBranch);
- }
- return $tree;
-}
-
-
-sub addchildrecurse
-{
- my $self = shift;
- my ($dstr,$child,$current) = @_;
-
-# print "addchildrecurse: child($child) type($dstr->{type})\n";
-
- if ($dstr->{type} eq "element")
- {
-# print "addchildrecurse: tag($dstr->{element})\n";
- my $count = 0;
- while(($#{@{$current}} > -1) && ($dstr->{element} eq $$current[0]))
- {
- shift(@{$current});
- shift(@{$current});
- $count++;
- }
- if (($dstr->{element} eq $child) &&
- ($self->repeatcheck($dstr,(($count > 0) ? $child : "")) == 1))
- {
- my @return = ( "end" , $self->newbranch($child));
- @return = ($$current[1], $self->newbranch($child))
- if ($#{@{$current}} > -1);
-# print "addchildrecurse: Found the spot! (",join(",",@return),")\n";
-
- return @return;
- }
- }
- else
- {
- foreach my $index (0..$#{$dstr->{list}})
- {
- my @newBranch = $self->addchildrecurse($dstr->{list}->[$index],$child,$current);
- return @newBranch if ("@newBranch" ne "");
- }
- }
-# print "Let's blow....\n";
- return;
-}
-
-
-sub deletechild
-{
- my $self = shift;
- my ($tag,$parent,$parenttree,$tree) = @_;
-
- return $tree unless exists($self->{ELEMENT}->{$tag});
- return $tree if $self->required($parent,$tag,&XML::Stream::GetXMLData("count",$parenttree,$tag));
-
- return [];
-}
-
-
-
-sub newbranch
-{
- my $self = shift;
- my $tag = shift;
-
- $tag = $self->root() unless defined($tag);
-
- my @tree = ();
-
- return ("0","") if ($tag eq "#PCDATA");
-
- push(@tree,$tag);
- push(@tree,[ {} ]);
-
- foreach my $att ($self->attribs($tag))
- {
- $tree[1]->[0]->{$att} = ""
- if (($self->{ATTLIST}->{$tag}->{$att}->{default} eq "#REQUIRED") &&
- ($self->{ATTLIST}->{$tag}->{$att}->{type} eq "CDATA"));
- }
-
- push(@{$tree[1]},$self->recursebranch($self->{ELEMENT}->{$tag}));
- return @tree;
-}
-
-
-sub recursebranch
-{
- my $self = shift;
- my $dstr = shift;
-
- my @tree;
- if (($dstr->{type} eq "element") &&
- ($dstr->{element} ne "EMPTY"))
- {
- @tree = $self->newbranch($dstr->{element})
- if (!exists($dstr->{repeat}) ||
- ($dstr->{repeat} eq "+"));
- }
- else
- {
- foreach my $index (0..$#{$dstr->{list}})
- {
- push(@tree,$self->recursebranch($dstr->{list}->[$index]))
-if (!exists($dstr->{repeat}) ||
- ($dstr->{repeat} eq "+"));
- }
- }
- return @tree;
-}
-
-
-sub attribs
-{
- my $self = shift;
- my ($tag,$tree) = @_;
-
- return unless exists ($self->{ATTLIST}->{$tag});
-
- if (defined($tree))
- {
- my %current = &XML::Stream::GetXMLData("attribs",$tree,"","","");
- return $self->allowedattribs($tag,\%current);
- }
- return $self->allowedattribs($tag);
-}
-
-
-sub allowedattribs
-{
- my $self = shift;
- my ($tag,$current) = @_;
-
- my %allowed;
- foreach my $att (keys(%{$self->{ATTLIST}->{$tag}}))
- {
- $allowed{$att} = 1 unless (defined($current) &&
- exists($current->{$att}));
- }
- return sort {$a cmp $b} keys(%allowed);
-}
-
-
-sub attribvalue
-{
- my $self = shift;
- my $tag = shift;
- my $att = shift;
-
- return $self->{ATTLIST}->{$tag}->{$att}->{type}
- if ($self->{ATTLIST}->{$tag}->{$att}->{type} ne "list");
- return sort {$a cmp $b} keys(%{$self->{ATTLIST}->{$tag}->{$att}->{value}});
-}
-
-
-sub addattrib
-{
- my $self = shift;
- my ($tag,$att,$tree) = @_;
-
- return $tree unless exists($self->{ATTLIST}->{$tag});
- return $tree unless exists($self->{ATTLIST}->{$tag}->{$att});
-
- my $default = $self->{ATTLIST}->{$tag}->{$att}->{default};
- $default = "" if ($default eq "#REQUIRED");
- $default = "" if ($default eq "#IMPLIED");
-
- $$tree[1]->[0]->{$att} = $default;
-
- return $tree;
-}
-
-
-sub attribrequired
-{
- my $self = shift;
- my ($tag,$att) = @_;
-
- return 0 unless exists($self->{ATTLIST}->{$tag});
- return 0 unless exists($self->{ATTLIST}->{$tag}->{$att});
-
- return 1 if ($self->{ATTLIST}->{$tag}->{$att}->{default} eq "#REQUIRED");
- return 0;
-}
-
-
-sub deleteattrib
-{
- my $self = shift;
- my ($tag,$att,$tree) = @_;
-
- return $tree unless exists($self->{ATTLIST}->{$tag});
- return $tree unless exists($self->{ATTLIST}->{$tag}->{$att});
-
- return if $self->attribrequired($tag,$att);
-
- delete($$tree[1]->[0]->{$att});
-
- return $tree;
-}
-
diff --git a/lib/XML/Stream/Tree.pm b/lib/XML/Stream/Tree.pm
deleted file mode 100644
index b52269c..0000000
--- a/lib/XML/Stream/Tree.pm
+++ /dev/null
@@ -1,682 +0,0 @@
-##############################################################################
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Library General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Library General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-# Jabber
-# Copyright (C) 1998-2004 Jabber Software Foundation http://jabber.org/
-#
-##############################################################################
-
-package XML::Stream::Tree;
-
-=head1 NAME
-
-XML::Stream::Tree - Functions to make building and parsing the tree easier
-to work with.
-
-=head1 SYNOPSIS
-
- Just a collection of functions that do not need to be in memory if you
-choose one of the other methods of data storage.
-
-=head1 FORMAT
-
-The result of parsing:
-
- <foo><head id="a">Hello <em>there</em></head><bar>Howdy<ref/></bar>do</foo>
-
-would be:
- Tag Content
- ==================================================================
- [foo, [{},
- head, [{id => "a"},
- 0, "Hello ",
- em, [{},
- 0, "there"
- ]
- ],
- bar, [{},
- 0, "Howdy",
- ref, [{}]
- ],
- 0, "do"
- ]
- ]
-
-The above was copied from the XML::Parser man page. Many thanks to
-Larry and Clark.
-
-=head1 AUTHOR
-
-By Ryan Eatmon in March 2001 for http://jabber.org/
-
-=head1 COPYRIGHT
-
-This module is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
-
-use vars qw( $VERSION $LOADED );
-
-$VERSION = "1.22";
-$LOADED = 1;
-
-##############################################################################
-#
-# _handle_element - handles the main tag elements sent from the server.
-# On an open tag it creates a new XML::Parser::Tree so
-# that _handle_cdata and _handle_element can add data
-# and tags to it later.
-#
-##############################################################################
-sub _handle_element
-{
- my $self;
- $self = $_[0] if (ref($_[0]) eq "XML::Stream::Parser");
- $self = shift unless (ref($_[0]) eq "XML::Stream::Parser");
- my ($sax, $tag, %att) = @_;
- my $sid = $sax->getSID();
-
- $self->debug(2,"_handle_element: sid($sid) sax($sax) tag($tag) att(",%att,")");
-
- my @NEW;
- if($#{$self->{SIDS}->{$sid}->{tree}} < 0)
- {
- push @{$self->{SIDS}->{$sid}->{tree}}, $tag;
- }
- else
- {
- push @{ $self->{SIDS}->{$sid}->{tree}[ $#{$self->{SIDS}->{$sid}->{tree}}]}, $tag;
- }
- push @NEW, \%att;
- push @{$self->{SIDS}->{$sid}->{tree}}, \@NEW;
-}
-
-
-##############################################################################
-#
-# _handle_cdata - handles the CDATA that is encountered. Also, in the
-# spirit of XML::Parser::Tree it combines any sequential
-# CDATA into one tag.
-#
-##############################################################################
-sub _handle_cdata
-{
- my $self;
- $self = $_[0] if (ref($_[0]) eq "XML::Stream::Parser");
- $self = shift unless (ref($_[0]) eq "XML::Stream::Parser");
- my ($sax, $cdata) = @_;
- my $sid = $sax->getSID();
-
- $self->debug(2,"_handle_cdata: sid($sid) sax($sax) cdata($cdata)");
-
- return if ($#{$self->{SIDS}->{$sid}->{tree}} == -1);
-
- $self->debug(2,"_handle_cdata: sax($sax) cdata($cdata)");
-
- my $pos = $#{$self->{SIDS}->{$sid}->{tree}};
- $self->debug(2,"_handle_cdata: pos($pos)");
-
- if ($pos > 0 && $self->{SIDS}->{$sid}->{tree}[$pos - 1] eq "0")
- {
- $self->debug(2,"_handle_cdata: append cdata");
- $self->{SIDS}->{$sid}->{tree}[$pos - 1] .= $cdata;
- }
- else
- {
- $self->debug(2,"_handle_cdata: new cdata");
- push @{$self->{SIDS}->{$sid}->{tree}[$#{$self->{SIDS}->{$sid}->{tree}}]}, 0;
- push @{$self->{SIDS}->{$sid}->{tree}[$#{$self->{SIDS}->{$sid}->{tree}}]}, $cdata;
- }
-}
-
-
-##############################################################################
-#
-# _handle_close - when we see a close tag we need to pop the last element
-# from the list and push it onto the end of the previous
-# element. This is how we build our hierarchy.
-#
-##############################################################################
-sub _handle_close
-{
- my $self;
- $self = $_[0] if (ref($_[0]) eq "XML::Stream::Parser");
- $self = shift unless (ref($_[0]) eq "XML::Stream::Parser");
- my ($sax, $tag) = @_;
- my $sid = $sax->getSID();
-
- $self->debug(2,"_handle_close: sid($sid) sax($sax) tag($tag)");
-
- my $CLOSED = pop @{$self->{SIDS}->{$sid}->{tree}};
-
- $self->debug(2,"_handle_close: check(",$#{$self->{SIDS}->{$sid}->{tree}},")");
-
- if ($#{$self->{SIDS}->{$sid}->{tree}} == -1)
- {
- if ($self->{SIDS}->{$sid}->{rootTag} ne $tag)
- {
- $self->{SIDS}->{$sid}->{streamerror} = "Root tag mis-match: <$self->{SIDS}->{$sid}->{rootTag}> ... </$tag>\n";
- }
- return;
- }
-
- if($#{$self->{SIDS}->{$sid}->{tree}} < 1)
- {
-
- push @{$self->{SIDS}->{$sid}->{tree}}, $CLOSED;
-
- if (ref($self) ne "XML::Stream::Parser")
- {
- my $stream_prefix = $self->StreamPrefix($sid);
-
- if(defined($self->{SIDS}->{$sid}->{tree}->[0]) &&
- ($self->{SIDS}->{$sid}->{tree}->[0] =~ /^${stream_prefix}\:/))
- {
- my @tree = @{$self->{SIDS}->{$sid}->{tree}};
- $self->{SIDS}->{$sid}->{tree} = [];
- $self->ProcessStreamPacket($sid,\@tree);
- }
- else
- {
- my @tree = @{$self->{SIDS}->{$sid}->{tree}};
- $self->{SIDS}->{$sid}->{tree} = [];
-
- my @special =
- &XML::Stream::XPath(
- \@tree,
- '[@xmlns="'.&XML::Stream::ConstXMLNS("xmpp-sasl").'" or @xmlns="'.&XML::Stream::ConstXMLNS("xmpp-tls").'"]'
- );
- if ($#special > -1)
- {
- my $xmlns = &GetXMLData("value",\@tree,"","xmlns");
-
- $self->ProcessSASLPacket($sid,\@tree)
- if ($xmlns eq &XML::Stream::ConstXMLNS("xmpp-sasl"));
- $self->ProcessTLSPacket($sid,\@tree)
- if ($xmlns eq &XML::Stream::ConstXMLNS("xmpp-tls"));
- }
- else
- {
- &{$self->{CB}->{node}}($sid,\@tree);
- }
- }
- }
- }
- else
- {
- push @{$self->{SIDS}->{$sid}->{tree}[$#{$self->{SIDS}->{$sid}->{tree}}]}, $CLOSED;
- }
-}
-
-
-##############################################################################
-#
-# SetXMLData - takes a host of arguments and sets a portion of the specified
-# XML::Parser::Tree object with that data. The function works
-# in two modes "single" or "multiple". "single" denotes that
-# the function should locate the current tag that matches this
-# data and overwrite it's contents with data passed in.
-# "multiple" denotes that a new tag should be created even if
-# others exist.
-#
-# type - single or multiple
-# XMLTree - pointer to XML::Stream Tree object
-# tag - name of tag to create/modify (if blank assumes
-# working with top level tag)
-# data - CDATA to set for tag
-# attribs - attributes to ADD to tag
-#
-##############################################################################
-sub SetXMLData
-{
- my ($type,$XMLTree,$tag,$data,$attribs) = @_;
- my ($key);
-
- if ($tag ne "")
- {
- if ($type eq "single")
- {
- my ($child);
- foreach $child (1..$#{$$XMLTree[1]})
- {
- if ($$XMLTree[1]->[$child] eq $tag)
- {
- if ($data ne "")
- {
- #todo: add code to handle writing the cdata again and appending it.
- $$XMLTree[1]->[$child+1]->[1] = 0;
- $$XMLTree[1]->[$child+1]->[2] = $data;
- }
- foreach $key (keys(%{$attribs}))
- {
- $$XMLTree[1]->[$child+1]->[0]->{$key} = $$attribs{$key};
- }
- return;
- }
- }
- }
- $$XMLTree[1]->[($#{$$XMLTree[1]}+1)] = $tag;
- $$XMLTree[1]->[($#{$$XMLTree[1]}+1)]->[0] = {};
- foreach $key (keys(%{$attribs}))
- {
- $$XMLTree[1]->[$#{$$XMLTree[1]}]->[0]->{$key} = $$attribs{$key};
- }
- if ($data ne "")
- {
- $$XMLTree[1]->[$#{$$XMLTree[1]}]->[1] = 0;
- $$XMLTree[1]->[$#{$$XMLTree[1]}]->[2] = $data;
- }
- }
- else
- {
- foreach $key (keys(%{$attribs}))
- {
- $$XMLTree[1]->[0]->{$key} = $$attribs{$key};
- }
- if ($data ne "")
- {
- if (($#{$$XMLTree[1]} > 0) &&
- ($$XMLTree[1]->[($#{$$XMLTree[1]}-1)] eq "0"))
- {
- $$XMLTree[1]->[$#{$$XMLTree[1]}] .= $data;
- }
- else
- {
- $$XMLTree[1]->[($#{$$XMLTree[1]}+1)] = 0;
- $$XMLTree[1]->[($#{$$XMLTree[1]}+1)] = $data;
- }
- }
- }
-}
-
-
-##############################################################################
-#
-# GetXMLData - takes a host of arguments and returns various data structures
-# that match them.
-#
-# type - "existence" - returns 1 or 0 if the tag exists in the
-# top level.
-# "value" - returns either the CDATA of the tag, or the
-# value of the attribute depending on which is
-# sought. This ignores any mark ups to the data
-# and just returns the raw CDATA.
-# "value array" - returns an array of strings representing
-# all of the CDATA in the specified tag.
-# This ignores any mark ups to the data
-# and just returns the raw CDATA.
-# "tree" - returns an XML::Parser::Tree object with the
-# specified tag as the root tag.
-# "tree array" - returns an array of XML::Parser::Tree
-# objects each with the specified tag as
-# the root tag.
-# "child array" - returns a list of all children nodes
-# not including CDATA nodes.
-# "attribs" - returns a hash with the attributes, and
-# their values, for the things that match
-# the parameters
-# "count" - returns the number of things that match
-# the arguments
-# "tag" - returns the root tag of this tree
-# XMLTree - pointer to XML::Parser::Tree object
-# tag - tag to pull data from. If blank then the top level
-# tag is accessed.
-# attrib - attribute value to retrieve. Ignored for types
-# "value array", "tree", "tree array". If paired
-# with value can be used to filter tags based on
-# attributes and values.
-# value - only valid if an attribute is supplied. Used to
-# filter for tags that only contain this attribute.
-# Useful to search through multiple tags that all
-# reference different name spaces.
-#
-##############################################################################
-sub GetXMLData
-{
- my ($type,$XMLTree,$tag,$attrib,$value) = @_;
-
- $tag = "" if !defined($tag);
- $attrib = "" if !defined($attrib);
- $value = "" if !defined($value);
-
- my $skipthis = 0;
-
- #---------------------------------------------------------------------------
- # Check if a child tag in the root tag is being requested.
- #---------------------------------------------------------------------------
- if ($tag ne "")
- {
- my $count = 0;
- my @array;
- foreach my $child (1..$#{$$XMLTree[1]})
- {
- next if (($child/2) !~ /\./);
- if (($$XMLTree[1]->[$child] eq $tag) || ($tag eq "*"))
- {
- next if (ref($$XMLTree[1]->[$child]) eq "ARRAY");
-
- #---------------------------------------------------------------------
- # Filter out tags that do not contain the attribute and value.
- #---------------------------------------------------------------------
- next if (($value ne "") && ($attrib ne "") && exists($$XMLTree[1]->[$child+1]->[0]->{$attrib}) && ($$XMLTree[1]->[$child+1]->[0]->{$attrib} ne $value));
- next if (($attrib ne "") && ((ref($$XMLTree[1]->[$child+1]) ne "ARRAY") || !exists($$XMLTree[1]->[$child+1]->[0]->{$attrib})));
-
- #---------------------------------------------------------------------
- # Check for existence
- #---------------------------------------------------------------------
- if ($type eq "existence")
- {
- return 1;
- }
-
- #---------------------------------------------------------------------
- # Return the raw CDATA value without mark ups, or the value of the
- # requested attribute.
- #---------------------------------------------------------------------
- if ($type eq "value")
- {
- if ($attrib eq "")
- {
- my $str = "";
- my $next = 0;
- my $index;
- foreach $index (1..$#{$$XMLTree[1]->[$child+1]}) {
- if ($next == 1) { $next = 0; next; }
- if ($$XMLTree[1]->[$child+1]->[$index] eq "0") {
- $str .= $$XMLTree[1]->[$child+1]->[$index+1];
- $next = 1;
- }
- }
- return $str;
- }
- return $$XMLTree[1]->[$child+1]->[0]->{$attrib}
- if (exists $$XMLTree[1]->[$child+1]->[0]->{$attrib});
- }
- #---------------------------------------------------------------------
- # Return an array of values that represent the raw CDATA without
- # mark up tags for the requested tags.
- #---------------------------------------------------------------------
- if ($type eq "value array")
- {
- if ($attrib eq "")
- {
- my $str = "";
- my $next = 0;
- my $index;
- foreach $index (1..$#{$$XMLTree[1]->[$child+1]})
- {
- if ($next == 1) { $next = 0; next; }
- if ($$XMLTree[1]->[$child+1]->[$index] eq "0")
- {
- $str .= $$XMLTree[1]->[$child+1]->[$index+1];
- $next = 1;
- }
- }
- push(@array,$str);
- }
- else
- {
- push(@array,$$XMLTree[1]->[$child+1]->[0]->{$attrib})
- if (exists $$XMLTree[1]->[$child+1]->[0]->{$attrib});
- }
- }
- #---------------------------------------------------------------------
- # Return a pointer to a new XML::Parser::Tree object that has the
- # requested tag as the root tag.
- #---------------------------------------------------------------------
- if ($type eq "tree")
- {
- my @tree = ( $$XMLTree[1]->[$child] , $$XMLTree[1]->[$child+1] );
- return @tree;
- }
- #---------------------------------------------------------------------
- # Return an array of pointers to XML::Parser::Tree objects that have
- # the requested tag as the root tags.
- #---------------------------------------------------------------------
- if ($type eq "tree array")
- {
- my @tree = ( $$XMLTree[1]->[$child] , $$XMLTree[1]->[$child+1] );
- push(@array,\@tree);
- }
- #---------------------------------------------------------------------
- # Return a count of the number of tags that match
- #---------------------------------------------------------------------
- if ($type eq "count")
- {
- if ($$XMLTree[1]->[$child] eq "0")
- {
- $skipthis = 1;
- next;
- }
- if ($skipthis == 1)
- {
- $skipthis = 0;
- next;
- }
- $count++;
- }
- #---------------------------------------------------------------------
- # Return a count of the number of tags that match
- #---------------------------------------------------------------------
- if ($type eq "child array")
- {
- my @tree = ( $$XMLTree[1]->[$child] , $$XMLTree[1]->[$child+1] );
- push(@array,\@tree) if ($tree[0] ne "0");
- }
- #---------------------------------------------------------------------
- # Return the attribute hash that matches this tag
- #---------------------------------------------------------------------
- if ($type eq "attribs")
- {
- return (%{$$XMLTree[1]->[$child+1]->[0]});
- }
- }
- }
- #-------------------------------------------------------------------------
- # If we are returning arrays then return array.
- #-------------------------------------------------------------------------
- if (($type eq "tree array") || ($type eq "value array") ||
- ($type eq "child array"))
- {
- return @array;
- }
-
- #-------------------------------------------------------------------------
- # If we are returning then count, then do so
- #-------------------------------------------------------------------------
- if ($type eq "count")
- {
- return $count;
- }
- }
- else
- {
- #-------------------------------------------------------------------------
- # This is the root tag, so handle things a level up.
- #-------------------------------------------------------------------------
-
- #-------------------------------------------------------------------------
- # Return the raw CDATA value without mark ups, or the value of the
- # requested attribute.
- #-------------------------------------------------------------------------
- if ($type eq "value")
- {
- if ($attrib eq "")
- {
- my $str = "";
- my $next = 0;
- my $index;
- foreach $index (1..$#{$$XMLTree[1]})
- {
- if ($next == 1) { $next = 0; next; }
- if ($$XMLTree[1]->[$index] eq "0")
- {
- $str .= $$XMLTree[1]->[$index+1];
- $next = 1;
- }
- }
- return $str;
- }
- return $$XMLTree[1]->[0]->{$attrib}
- if (exists $$XMLTree[1]->[0]->{$attrib});
- }
- #-------------------------------------------------------------------------
- # Return a pointer to a new XML::Parser::Tree object that has the
- # requested tag as the root tag.
- #-------------------------------------------------------------------------
- if ($type eq "tree")
- {
- my @tree = @{$$XMLTree};
- return @tree;
- }
-
- #-------------------------------------------------------------------------
- # Return the 1 if the specified attribute exists in the root tag.
- #-------------------------------------------------------------------------
- if ($type eq "existence")
- {
- return 1 if (($attrib ne "") && (exists($$XMLTree[1]->[0]->{$attrib})));
- }
-
- #-------------------------------------------------------------------------
- # Return the attribute hash that matches this tag
- #-------------------------------------------------------------------------
- if ($type eq "attribs")
- {
- return %{$$XMLTree[1]->[0]};
- }
- #-------------------------------------------------------------------------
- # Return the tag of this node
- #-------------------------------------------------------------------------
- if ($type eq "tag")
- {
- return $$XMLTree[0];
- }
- }
- #---------------------------------------------------------------------------
- # Return 0 if this was a request for existence, or "" if a request for
- # a "value", or [] for "tree", "value array", and "tree array".
- #---------------------------------------------------------------------------
- return 0 if ($type eq "existence");
- return "" if ($type eq "value");
- return [];
-}
-
-
-##############################################################################
-#
-# BuildXML - takes an XML::Parser::Tree object and builds the XML string
-# that it represents.
-#
-##############################################################################
-sub BuildXML
-{
- my ($parseTree,$rawXML) = @_;
-
- return "" if $#{$parseTree} == -1;
-
- my $str = "";
- if (ref($parseTree->[0]) eq "")
- {
- if ($parseTree->[0] eq "0")
- {
- return &XML::Stream::EscapeXML($parseTree->[1]);
- }
-
- $str = "<".$parseTree->[0];
- foreach my $att (sort {$a cmp $b} keys(%{$parseTree->[1]->[0]}))
- {
- $str .= " ".$att."='".&XML::Stream::EscapeXML($parseTree->[1]->[0]->{$att})."'";
- }
-
- if (($#{$parseTree->[1]} > 0) || (defined($rawXML) && ($rawXML ne "")))
- {
- $str .= ">";
-
- my $index = 1;
- while($index <= $#{$parseTree->[1]})
- {
- my @newTree = ( $parseTree->[1]->[$index], $parseTree->[1]->[$index+1] );
- $str .= &XML::Stream::Tree::BuildXML(\@newTree);
- $index += 2;
- }
-
- $str .= $rawXML if defined($rawXML);
- $str .= "</".$parseTree->[0].">";
- }
- else
- {
- $str .= "/>";
- }
-
- }
-
- return $str;
-}
-
-
-##############################################################################
-#
-# XML2Config - takes an XML data tree and turns it into a hash of hashes.
-# This only works for certain kinds of XML trees like this:
-#
-# <foo>
-# <bar>1</bar>
-# <x>
-# <y>foo</y>
-# </x>
-# <z>5</z>
-# </foo>
-#
-# The resulting hash would be:
-#
-# $hash{bar} = 1;
-# $hash{x}->{y} = "foo";
-# $hash{z} = 5;
-#
-# Good for config files.
-#
-##############################################################################
-sub XML2Config
-{
- my ($XMLTree) = @_;
-
- my %hash;
- foreach my $tree (&XML::Stream::GetXMLData("tree array",$XMLTree,"*"))
- {
- if ($tree->[0] eq "0")
- {
- return $tree->[1] unless ($tree->[1] =~ /^\s*$/);
- }
- else
- {
- if (&XML::Stream::GetXMLData("count",$XMLTree,$tree->[0]) > 1)
- {
- push(@{$hash{$tree->[0]}},&XML::Stream::XML2Config($tree));
- }
- else
- {
- $hash{$tree->[0]} = &XML::Stream::XML2Config($tree);
- }
- }
- }
- return \%hash;
-}
-
-
-1;
diff --git a/lib/XML/Stream/XPath.pm b/lib/XML/Stream/XPath.pm
deleted file mode 100644
index 164a7a7..0000000
--- a/lib/XML/Stream/XPath.pm
+++ /dev/null
@@ -1,50 +0,0 @@
-##############################################################################
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Library General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Library General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-# Jabber
-# Copyright (C) 1998-2004 Jabber Software Foundation http://jabber.org/
-#
-##############################################################################
-
-package XML::Stream::XPath;
-
-use 5.006_001;
-use strict;
-use vars qw( $VERSION %FUNCTIONS );
-
-$VERSION = "1.22";
-
-use XML::Stream::XPath::Value;
-use XML::Stream::XPath::Op;
-use XML::Stream::XPath::Query;
-
-sub AddFunction
-{
- my $function = shift;
- my $code = shift;
- if (!defined($code))
- {
- delete($FUNCTIONS{$code});
- return;
- }
-
- $FUNCTIONS{$function} = $code;
-}
-
-
-1;
-
diff --git a/lib/XML/Stream/XPath/Op.pm b/lib/XML/Stream/XPath/Op.pm
deleted file mode 100644
index 4209a5c..0000000
--- a/lib/XML/Stream/XPath/Op.pm
+++ /dev/null
@@ -1,919 +0,0 @@
-##############################################################################
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Library General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Library General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-# Jabber
-# Copyright (C) 1998-2004 Jabber Software Foundation http://jabber.org/
-#
-##############################################################################
-
-
-##############################################################################
-#
-# Op - Base Op class
-#
-##############################################################################
-package XML::Stream::XPath::Op;
-
-use 5.006_001;
-use strict;
-use vars qw( $VERSION );
-
-$VERSION = "1.22";
-
-sub new
-{
- my $proto = shift;
- return &allocate($proto,@_);
-}
-
-sub allocate
-{
- my $proto = shift;
- my $self = { };
-
- bless($self,$proto);
-
- $self->{TYPE} = shift;
- $self->{VALUE} = shift;
-
- return $self;
-}
-
-sub getValue
-{
- my $self = shift;
- return $self->{VALUE};
-}
-
-sub calcStr
-{
- my $self = shift;
- return $self->{VALUE};
-}
-
-sub getType
-{
- my $self = shift;
- return $self->{TYPE};
-}
-
-
-sub isValid
-{
- my $self = shift;
- my $ctxt = shift;
- return 1;
-}
-
-sub display
-{
- my $self = shift;
- my $space = shift;
- $space = "" unless defined($space);
-
- print $space,"OP: type($self->{TYPE}) value($self->{VALUE})\n";
-}
-
-
-
-##############################################################################
-#
-# PositionOp - class to handle [0] ops
-#
-##############################################################################
-package XML::Stream::XPath::PositionOp;
-
-use vars qw (@ISA);
-@ISA = ( "XML::Stream::XPath::Op" );
-
-sub new
-{
- my $proto = shift;
- my $self = $proto->allocate("POSITION","");
- $self->{POS} = shift;
-
- return $self;
-}
-
-
-sub isValid
-{
- my $self = shift;
- my $ctxt = shift;
-
- my @elems = $$ctxt->getList();
- my @valid_elems;
- if ($#elems+1 < $self->{POS})
- {
- return;
- }
-
- push(@valid_elems, $elems[$self->{POS}-1]);
-
- $$ctxt->setList(@valid_elems);
-
- return 1;
-}
-
-
-
-##############################################################################
-#
-# ContextOp - class to handle [...] ops
-#
-##############################################################################
-package XML::Stream::XPath::ContextOp;
-
-use vars qw (@ISA);
-@ISA = ( "XML::Stream::XPath::Op" );
-
-sub new
-{
- my $proto = shift;
- my $self = $proto->allocate("CONTEXT","");
- $self->{OP} = shift;
- return $self;
-}
-
-
-sub isValid
-{
- my $self = shift;
- my $ctxt = shift;
-
- my @elems = $$ctxt->getList();
- my @valid_elems;
- foreach my $elem (@elems)
- {
- my $tmp_ctxt = new XML::Stream::XPath::Value($elem);
- $tmp_ctxt->in_context(1);
- if ($self->{OP}->isValid(\$tmp_ctxt))
- {
- push(@valid_elems,$elem);
- }
- }
-
- $$ctxt->setList(@valid_elems);
-
- if ($#valid_elems == -1)
- {
- return;
- }
-
- return 1;
-}
-
-
-sub display
-{
- my $self = shift;
- my $space = shift;
- $space = "" unless defined($space);
-
- print "${space}OP: type(CONTEXT) op: \n";
- $self->{OP}->display("$space ");
-}
-
-
-
-
-##############################################################################
-#
-# AllOp - class to handle // ops
-#
-##############################################################################
-package XML::Stream::XPath::AllOp;
-
-use vars qw (@ISA);
-@ISA = ( "XML::Stream::XPath::Op" );
-
-sub new
-{
- my $proto = shift;
- my $name = shift;
- my $self = $proto->allocate("ALL",$name);
- return $self;
-}
-
-
-sub isValid
-{
- my $self = shift;
- my $ctxt = shift;
-
- my @elems = $$ctxt->getList();
-
- if ($#elems == -1)
- {
- return;
- }
-
- my @valid_elems;
-
- foreach my $elem (@elems)
- {
- push(@valid_elems,$self->descend($elem));
- }
-
- $$ctxt->setList(@valid_elems);
-
- if ($#valid_elems == -1)
- {
- return;
- }
-
- return 1;
-}
-
-
-sub descend
-{
- my $self = shift;
- my $elem = shift;
-
- my @valid_elems;
-
- if (($self->{VALUE} eq "*") || (&XML::Stream::GetXMLData("tag",$elem) eq $self->{VALUE}))
- {
- push(@valid_elems,$elem);
- }
-
- foreach my $child (&XML::Stream::GetXMLData("child array",$elem,"*"))
- {
- push(@valid_elems,$self->descend($child));
- }
-
- return @valid_elems;
-}
-
-
-
-##############################################################################
-#
-# NodeOp - class to handle ops based on node names
-#
-##############################################################################
-package XML::Stream::XPath::NodeOp;
-
-use vars qw (@ISA);
-@ISA = ( "XML::Stream::XPath::Op" );
-
-sub new
-{
- my $proto = shift;
- my $name = shift;
- my $is_root = shift;
- $is_root = 0 unless defined($is_root);
- my $self = $proto->allocate("NODE",$name);
- $self->{ISROOT} = $is_root;
- return $self;
-}
-
-
-sub isValid
-{
- my $self = shift;
- my $ctxt = shift;
-
- if ($self->{ISROOT})
- {
- my $elem = $$ctxt->getFirstElem();
- if (&XML::Stream::GetXMLData("tag",$elem) ne $self->{VALUE})
- {
- return;
- }
- return 1;
- }
-
- my @valid_elems;
-
- foreach my $elem ($$ctxt->getList())
- {
- my $valid = 0;
-
- foreach my $child (&XML::Stream::GetXMLData("child array",$elem,"*"))
- {
- if (($self->{VALUE} eq "*") ||
- (&XML::Stream::GetXMLData("tag",$child) eq $self->{VALUE}))
- {
- if ($$ctxt->in_context())
- {
- $valid = 1;
- }
- else
- {
- push(@valid_elems,$child);
- }
- }
- }
- if ($valid)
- {
- push(@valid_elems,$elem);
- }
- }
-
- $$ctxt->setList(@valid_elems);
-
- if ($#valid_elems == -1)
- {
- return;
- }
-
- return 1;
-}
-
-
-sub calcStr
-{
- my $self = shift;
- my $elem = shift;
- return &XML::Stream::GetXMLData("value",$elem);
-}
-
-
-##############################################################################
-#
-# EqualOp - class to handle [ x = y ] ops
-#
-##############################################################################
-package XML::Stream::XPath::EqualOp;
-
-use vars qw (@ISA);
-@ISA = ( "XML::Stream::XPath::Op" );
-
-sub new
-{
- my $proto = shift;
- my $self = $proto->allocate("EQUAL","");
- $self->{OP_L} = shift;
- $self->{OP_R} = shift;
- return $self;
-}
-
-
-sub isValid
-{
- my $self = shift;
- my $ctxt = shift;
-
- my $tmp_ctxt = new XML::Stream::XPath::Value();
- $tmp_ctxt->setList($$ctxt->getList());
- $tmp_ctxt->in_context(0);
-
- if (!$self->{OP_L}->isValid(\$tmp_ctxt) || !$self->{OP_R}->isValid(\$tmp_ctxt))
- {
- return;
- }
-
- my @valid_elems;
- foreach my $elem ($tmp_ctxt->getList)
- {
- if ($self->{OP_L}->calcStr($elem) eq $self->{OP_R}->calcStr($elem))
- {
- push(@valid_elems,$elem);
- }
- }
-
- if ( $#valid_elems > -1)
- {
- @valid_elems = $$ctxt->getList();
- }
-
- $$ctxt->setList(@valid_elems);
-
- if ($#valid_elems == -1)
- {
- return;
- }
-
- return 1;
-}
-
-
-sub display
-{
- my $self = shift;
- my $space = shift;
- $space = "" unless defined($space);
-
- print $space,"OP: type(EQUAL)\n";
- print $space," op_l: ";
- $self->{OP_L}->display($space." ");
-
- print $space," op_r: ";
- $self->{OP_R}->display($space." ");
-}
-
-
-
-##############################################################################
-#
-# NotEqualOp - class to handle [ x != y ] ops
-#
-##############################################################################
-package XML::Stream::XPath::NotEqualOp;
-
-use vars qw (@ISA);
-@ISA = ( "XML::Stream::XPath::Op" );
-
-sub new
-{
- my $proto = shift;
- my $self = $proto->allocate("NOTEQUAL","");
- $self->{OP_L} = shift;
- $self->{OP_R} = shift;
- return $self;
-}
-
-
-sub isValid
-{
- my $self = shift;
- my $ctxt = shift;
-
- my $tmp_ctxt = new XML::Stream::XPath::Value();
- $tmp_ctxt->setList($$ctxt->getList());
- $tmp_ctxt->in_context(0);
-
- if (!$self->{OP_L}->isValid(\$tmp_ctxt) || !$self->{OP_R}->isValid(\$tmp_ctxt))
- {
- return;
- }
-
- my @valid_elems;
- foreach my $elem ($tmp_ctxt->getList)
- {
- if ($self->{OP_L}->calcStr($elem) ne $self->{OP_R}->calcStr($elem))
- {
- push(@valid_elems,$elem);
- }
- }
-
- if ( $#valid_elems > -1)
- {
- @valid_elems = $$ctxt->getList();
- }
-
- $$ctxt->setList(@valid_elems);
-
- if ($#valid_elems == -1)
- {
- return;
- }
-
- return 1;
-}
-
-
-sub display
-{
- my $self = shift;
- my $space = shift;
- $space = "" unless defined($space);
-
- print $space,"OP: type(NOTEQUAL)\n";
- print $space," op_l: ";
- $self->{OP_L}->display($space." ");
-
- print $space," op_r: ";
- $self->{OP_R}->display($space." ");
-}
-
-
-
-##############################################################################
-#
-# AttributeOp - class to handle @foo ops.
-#
-##############################################################################
-package XML::Stream::XPath::AttributeOp;
-
-use vars qw (@ISA);
-@ISA = ( "XML::Stream::XPath::Op" );
-
-sub new
-{
- my $proto = shift;
- my $name = shift;
- my $self = $proto->allocate("ATTRIBUTE",$name);
- return $self;
-}
-
-
-sub isValid
-{
- my $self = shift;
- my $ctxt = shift;
-
- my @elems = $$ctxt->getList();
- my @valid_elems;
- my @values;
- my %attribs;
-
- foreach my $elem (@elems)
- {
- if ($self->{VALUE} ne "*")
- {
- if (&XML::Stream::GetXMLData("value",$elem,"",$self->{VALUE}))
- {
- $self->{VAL} = $self->calcStr($elem);
- push(@valid_elems,$elem);
- push(@values,$self->{VAL});
- }
- }
- else
- {
- my %attrib = &XML::Stream::GetXMLData("attribs",$elem);
- if (scalar(keys(%attrib)) > 0)
- {
- push(@valid_elems,$elem);
- foreach my $key (keys(%attrib))
- {
- $attribs{$key} = $attrib{$key};
- }
- }
- }
- }
-
- $$ctxt->setList(@valid_elems);
- $$ctxt->setValues(@values);
- $$ctxt->setAttribs(%attribs);
-
- if ($#valid_elems == -1)
- {
- return;
- }
-
- return 1;
-}
-
-
-sub getValue
-{
- my $self = shift;
- return $self->{VAL};
-}
-
-
-sub calcStr
-{
- my $self = shift;
- my $elem = shift;
- return &XML::Stream::GetXMLData("value",$elem,"",$self->{VALUE});
-}
-
-
-
-
-##############################################################################
-#
-# AndOp - class to handle [ .... and .... ] ops
-#
-##############################################################################
-package XML::Stream::XPath::AndOp;
-
-use vars qw (@ISA);
-@ISA = ( "XML::Stream::XPath::Op" );
-
-sub new
-{
- my $proto = shift;
- my $self = $proto->allocate("AND","and");
- $self->{OP_L} = shift;
- $self->{OP_R} = shift;
- return $self;
-}
-
-
-sub isValid
-{
- my $self = shift;
- my $ctxt = shift;
-
- my $opl = $self->{OP_L}->isValid($ctxt);
- my $opr = $self->{OP_R}->isValid($ctxt);
-
- if ($opl && $opr)
- {
- return 1;
- }
- else
- {
- return;
- }
-}
-
-
-sub display
-{
- my $self = shift;
- my $space = shift;
- $space = "" unless defined($space);
-
- print $space,"OP: type(AND)\n";
- print $space," op_l: \n";
- $self->{OP_L}->display($space." ");
-
- print $space," op_r: \n";
- $self->{OP_R}->display($space." ");
-}
-
-
-
-##############################################################################
-#
-# OrOp - class to handle [ .... or .... ] ops
-#
-##############################################################################
-package XML::Stream::XPath::OrOp;
-
-use vars qw (@ISA);
-@ISA = ( "XML::Stream::XPath::Op" );
-
-sub new
-{
- my $proto = shift;
- my $self = $proto->allocate("OR","or");
- $self->{OP_L} = shift;
- $self->{OP_R} = shift;
- return $self;
-}
-
-
-sub isValid
-{
- my $self = shift;
- my $ctxt = shift;
-
- my @elems = $$ctxt->getList();
- my @valid_elems;
-
- foreach my $elem (@elems)
- {
- my $tmp_ctxt_l = new XML::Stream::XPath::Value($elem);
- $tmp_ctxt_l->in_context(1);
- my $tmp_ctxt_r = new XML::Stream::XPath::Value($elem);
- $tmp_ctxt_r->in_context(1);
-
- my $opl = $self->{OP_L}->isValid(\$tmp_ctxt_l);
- my $opr = $self->{OP_R}->isValid(\$tmp_ctxt_r);
-
- if ($opl || $opr)
- {
- push(@valid_elems,$elem);
- }
- }
-
- $$ctxt->setList(@valid_elems);
-
- if ($#valid_elems == -1)
- {
- return;
- }
-
- return 1;
-}
-
-
-sub display
-{
- my $self = shift;
- my $space = shift;
- $space = "" unless defined($space);
-
- print "${space}OP: type(OR)\n";
- print "$space op_l: ";
- $self->{OP_L}->display("$space ");
-
- print "$space op_r: ";
- $self->{OP_R}->display("$space ");
-}
-
-
-
-##############################################################################
-#
-# FunctionOp - class to handle xxxx(...) ops
-#
-##############################################################################
-package XML::Stream::XPath::FunctionOp;
-
-use vars qw (@ISA);
-@ISA = ( "XML::Stream::XPath::Op" );
-
-sub new
-{
- my $proto = shift;
- my $function = shift;
- my $self = $proto->allocate("FUNCTION",$function);
- $self->{CLOSED} = 0;
- return $self;
-}
-
-
-sub addArg
-{
- my $self = shift;
- my $arg = shift;
-
- push(@{$self->{ARGOPS}},$arg);
-}
-
-
-sub isValid
-{
- my $self = shift;
- my $ctxt = shift;
-
- my $result;
- eval("\$result = &{\$XML::Stream::XPath::FUNCTIONS{\$self->{VALUE}}}(\$ctxt,\@{\$self->{ARGOPS}});");
- return $result;
-}
-
-
-sub calcStr
-{
- my $self = shift;
- my $elem = shift;
-
- my $result;
- eval("\$result = &{\$XML::Stream::XPath::VALUES{\$self->{VALUE}}}(\$elem);");
- return $result;
-
-}
-
-
-sub display
-{
- my $self = shift;
- my $space = shift;
- $space = "" unless defined($space);
-
- print $space,"OP: type(FUNCTION)\n";
- print $space," $self->{VALUE}(\n";
- foreach my $arg (@{$self->{ARGOPS}})
- {
- print $arg,"\n";
- $arg->display($space." ");
- }
- print "$space )\n";
-}
-
-
-sub function_name
-{
- my $ctxt = shift;
- my (@args) = @_;
-
- my @elems = $$ctxt->getList();
- my @valid_elems;
- my @valid_values;
- foreach my $elem (@elems)
- {
- my $text = &value_name($elem);
- if (defined($text))
- {
- push(@valid_elems,$elem);
- push(@valid_values,$text);
- }
- }
-
- $$ctxt->setList(@valid_elems);
- $$ctxt->setValues(@valid_values);
-
- if ($#valid_elems == -1)
- {
- return;
- }
-
- return 1;
-}
-
-
-sub function_not
-{
- my $ctxt = shift;
- my (@args) = @_;
-
- my @elems = $$ctxt->getList();
- my @valid_elems;
- foreach my $elem (@elems)
- {
- my $tmp_ctxt = new XML::Stream::XPath::Value($elem);
- $tmp_ctxt->in_context(1);
- if (!($args[0]->isValid(\$tmp_ctxt)))
- {
- push(@valid_elems,$elem);
- }
- }
-
- $$ctxt->setList(@valid_elems);
-
- if ($#valid_elems == -1)
- {
- return;
- }
-
- return 1;
-}
-
-
-sub function_text
-{
- my $ctxt = shift;
- my (@args) = @_;
-
- my @elems = $$ctxt->getList();
- my @valid_elems;
- my @valid_values;
- foreach my $elem (@elems)
- {
- my $text = &value_text($elem);
- if (defined($text))
- {
- push(@valid_elems,$elem);
- push(@valid_values,$text);
- }
- }
-
- $$ctxt->setList(@valid_elems);
- $$ctxt->setValues(@valid_values);
-
- if ($#valid_elems == -1)
- {
- return;
- }
-
- return 1;
-}
-
-
-sub function_startswith
-{
- my $ctxt = shift;
- my (@args) = @_;
-
- my @elems = $$ctxt->getList();
- my @valid_elems;
- foreach my $elem (@elems)
- {
- my $val1 = $args[0]->calcStr($elem);
- my $val2 = $args[1]->calcStr($elem);
-
- if (substr($val1,0,length($val2)) eq $val2)
- {
- push(@valid_elems,$elem);
- }
- }
-
- $$ctxt->setList(@valid_elems);
-
- if ($#valid_elems == -1)
- {
- return;
- }
-
- return 1;
-}
-
-
-sub value_name
-{
- my $elem = shift;
- return &XML::Stream::GetXMLData("tag",$elem);
-}
-
-
-sub value_text
-{
- my $elem = shift;
- return &XML::Stream::GetXMLData("value",$elem);
-}
-
-
-
-$XML::Stream::XPath::FUNCTIONS{'name'} = \&function_name;
-$XML::Stream::XPath::FUNCTIONS{'not'} = \&function_not;
-$XML::Stream::XPath::FUNCTIONS{'text'} = \&function_text;
-$XML::Stream::XPath::FUNCTIONS{'starts-with'} = \&function_startswith;
-
-$XML::Stream::XPath::VALUES{'name'} = \&value_name;
-$XML::Stream::XPath::VALUES{'text'} = \&value_text;
-
-1;
-
-
diff --git a/lib/XML/Stream/XPath/Query.pm b/lib/XML/Stream/XPath/Query.pm
deleted file mode 100644
index c4831fe..0000000
--- a/lib/XML/Stream/XPath/Query.pm
+++ /dev/null
@@ -1,374 +0,0 @@
-##############################################################################
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Library General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Library General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-# Jabber
-# Copyright (C) 1998-2004 Jabber Software Foundation http://jabber.org/
-#
-##############################################################################
-
-package XML::Stream::XPath::Query;
-
-use 5.006_001;
-use strict;
-use Carp;
-use vars qw( $VERSION );
-
-$VERSION = "1.22";
-
-sub new
-{
- my $proto = shift;
- my $self = { };
-
- bless($self,$proto);
-
- $self->{TOKENS} = [ '/','[',']','@','"',"'",'=','!','(',')',':',' ',','];
- $self->{QUERY} = shift;
-
- if (!defined($self->{QUERY}) || ($self->{QUERY} eq ""))
- {
- confess("No query string specified");
- }
-
- $self->parseQuery();
-
- return $self;
-}
-
-
-sub getNextToken
-{
- my $self = shift;
- my $pos = shift;
-
- my @toks = grep{ $_ eq substr($self->{QUERY},$$pos,1)} @{$self->{TOKENS}};
- while( $#toks == -1 )
- {
- $$pos++;
- if ($$pos > length($self->{QUERY}))
- {
- $$pos = length($self->{QUERY});
- return 0;
- }
- @toks = grep{ $_ eq substr($self->{QUERY},$$pos,1)} @{$self->{TOKENS}};
- }
-
- return $toks[0];
-}
-
-
-sub getNextIdentifier
-{
- my $self = shift;
- my $pos = shift;
- my $sp = $$pos;
- $self->getNextToken($pos);
- return substr($self->{QUERY},$sp,$$pos-$sp);
-}
-
-
-sub getOp
-{
- my $self = shift;
- my $pos = shift;
- my $in_context = shift;
- $in_context = 0 unless defined($in_context);
-
- my $ret_op;
-
- my $loop = 1;
- while( $loop )
- {
- my $pos_start = $$pos;
-
- my $token = $self->getNextToken($pos);
- if (($token eq "0") && $in_context)
- {
- return;
- }
-
- my $token_start = ++$$pos;
- my $ident;
-
- if (defined($token))
- {
-
- if ($pos_start != ($token_start-1))
- {
- $$pos = $pos_start;
- my $temp_ident = $self->getNextIdentifier($pos);
- $ret_op = new XML::Stream::XPath::NodeOp($temp_ident,"0");
- }
- elsif ($token eq "/")
- {
- if (substr($self->{QUERY},$token_start,1) eq "/")
- {
- $$pos++;
- my $temp_ident = $self->getNextIdentifier($pos);
- $ret_op = new XML::Stream::XPath::AllOp($temp_ident);
- }
- else
- {
- my $temp_ident = $self->getNextIdentifier($pos);
- if ($temp_ident ne "")
- {
- $ret_op = new XML::Stream::XPath::NodeOp($temp_ident,($pos_start == 0 ? "1" : "0"));
- }
- }
- }
- elsif ($token eq "\@")
- {
- $ret_op = new XML::Stream::XPath::AttributeOp($self->getNextIdentifier($pos));
- }
- elsif ($token eq "]")
- {
- if ($in_context eq "[")
- {
- $ret_op = pop(@{$self->{OPS}});
- $in_context = 0;
- }
- else
- {
- confess("Found ']' but not in context");
- return;
- }
- }
- elsif (($token eq "\"") || ($token eq "\'"))
- {
- $$pos = index($self->{QUERY},$token,$token_start);
- $ret_op = new XML::Stream::XPath::Op("LITERAL",substr($self->{QUERY},$token_start,$$pos-$token_start));
- $$pos++;
- }
- elsif ($token eq " ")
- {
- $ident = $self->getNextIdentifier($pos);
- if ($ident eq "and")
- {
- $$pos++;
- my $tmp_op = $self->getOp($pos,$in_context);
- if (!defined($tmp_op))
- {
- confess("Invalid 'and' operation");
- return;
- }
- $ret_op = new XML::Stream::XPath::AndOp($self->{OPS}->[$#{$self->{OPS}}],$tmp_op);
- $in_context = 0;
- pop(@{$self->{OPS}});
- }
- elsif ($ident eq "or")
- {
- $$pos++;
- my $tmp_op = $self->getOp($pos,$in_context);
- if (!defined($tmp_op))
- {
- confess("Invalid 'or' operation");
- return;
- }
- $ret_op = new XML::Stream::XPath::OrOp($self->{OPS}->[$#{$self->{OPS}}],$tmp_op);
- $in_context = 0;
- pop(@{$self->{OPS}});
- }
- }
- elsif ($token eq "[")
- {
- if ($self->getNextToken($pos) eq "]")
- {
- if ($$pos == $token_start)
- {
- confess("Nothing in the []");
- return;
- }
-
- $$pos = $token_start;
- my $val = $self->getNextIdentifier($pos);
- if ($val =~ /^\d+$/)
- {
- $ret_op = new XML::Stream::XPath::PositionOp($val);
- $$pos++;
- }
- else
- {
- $$pos = $pos_start + 1;
- $ret_op = new XML::Stream::XPath::ContextOp($self->getOp($pos,$token));
- }
- }
- else
- {
- $$pos = $pos_start + 1;
- $ret_op = new XML::Stream::XPath::ContextOp($self->getOp($pos,$token));
- }
- }
- elsif ($token eq "(")
- {
- #-------------------------------------------------------------
- # The function name would have been mistaken for a NodeOp.
- # Pop it off the back and get the function name.
- #-------------------------------------------------------------
- my $op = pop(@{$self->{OPS}});
- if ($op->getType() ne "NODE")
- {
- confess("No function name specified.");
- }
- my $function = $op->getValue();
- if (!exists($XML::Stream::XPath::FUNCTIONS{$function}))
- {
- confess("Undefined function \"$function\"");
- }
- $ret_op = new XML::Stream::XPath::FunctionOp($function);
-
- my $op_pos = $#{$self->{OPS}} + 1;
-
- $self->getOp($pos,$token);
-
- foreach my $arg ($op_pos..$#{$self->{OPS}})
- {
- $ret_op->addArg($self->{OPS}->[$arg]);
- }
-
- splice(@{$self->{OPS}},$op_pos);
-
- }
- elsif ($token eq ")")
- {
- if ($in_context eq "(")
- {
- $ret_op = undef;
- $in_context = 0;
- }
- else
- {
- confess("Found ')' but not in context");
- }
- }
- elsif ($token eq ",")
- {
- if ($in_context ne "(")
- {
- confess("Found ',' but not in a function");
- }
-
- }
- elsif ($token eq "=")
- {
- my $tmp_op;
- while(!defined($tmp_op))
- {
- $tmp_op = $self->getOp($pos);
- }
- $ret_op = new XML::Stream::XPath::EqualOp($self->{OPS}->[$#{$self->{OPS}}],$tmp_op);
- pop(@{$self->{OPS}});
- }
- elsif ($token eq "!")
- {
- if (substr($self->{QUERY},$token_start,1) ne "=")
- {
- confess("Badly formed !=");
- }
- $$pos++;
-
- my $tmp_op;
- while(!defined($tmp_op))
- {
- $tmp_op = $self->getOp($pos);
- }
- $ret_op = new XML::Stream::XPath::NotEqualOp($self->{OPS}->[$#{$self->{OPS}}],$tmp_op);
- pop(@{$self->{OPS}});
- }
- else
- {
- confess("Unhandled \"$token\"");
- }
-
- if ($in_context)
- {
- if (defined($ret_op))
- {
- push(@{$self->{OPS}},$ret_op);
- }
- $ret_op = undef;
- }
- }
- else
- {
- confess("Token undefined");
- }
-
- $loop = 0 unless $in_context;
- }
-
- return $ret_op;
-}
-
-
-sub parseQuery
-{
- my $self = shift;
- my $query = shift;
-
- my $op;
- my $pos = 0;
- while($pos < length($self->{QUERY}))
- {
- $op = $self->getOp(\$pos);
- if (defined($op))
- {
- push(@{$self->{OPS}},$op);
- }
- }
-
- #foreach my $op (@{$self->{OPS}})
- #{
- # $op->display();
- #}
-
- return 1;
-}
-
-
-sub execute
-{
- my $self = shift;
- my $root = shift;
-
- my $ctxt = new XML::Stream::XPath::Value($root);
-
- foreach my $op (@{$self->{OPS}})
- {
- if (!$op->isValid(\$ctxt))
- {
- $ctxt->setValid(0);
- return $ctxt;
- }
- }
-
- $ctxt->setValid(1);
- return $ctxt;
-}
-
-
-sub check
-{
- my $self = shift;
- my $root = shift;
-
- my $ctxt = $self->execute($root);
- return $ctxt->check();
-}
-
-
-1;
-
diff --git a/lib/XML/Stream/XPath/Value.pm b/lib/XML/Stream/XPath/Value.pm
deleted file mode 100644
index 425e183..0000000
--- a/lib/XML/Stream/XPath/Value.pm
+++ /dev/null
@@ -1,153 +0,0 @@
-##############################################################################
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Library General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Library General Public License for more details.
-#
-# You should have received a copy of the GNU Library General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-# Jabber
-# Copyright (C) 1998-2004 Jabber Software Foundation http://jabber.org/
-#
-##############################################################################
-
-package XML::Stream::XPath::Value;
-
-use 5.006_001;
-use strict;
-use vars qw( $VERSION );
-
-$VERSION = "1.22";
-
-sub new
-{
- my $proto = shift;
- my $self = { };
-
- bless($self,$proto);
-
- $self->setList(@_);
- $self->setValues();
- $self->setAttribs();
- $self->setValid(0);
- $self->in_context(0);
-
- return $self;
-}
-
-
-sub setList
-{
- my $self = shift;
- my (@values) = @_;
- $self->{LIST} = \@values;
-}
-
-
-sub getList
-{
- my $self = shift;
- return unless ($#{$self->{LIST}} > -1);
- return @{$self->{LIST}};
-}
-
-
-sub getFirstElem
-{
- my $self = shift;
- return unless ($#{$self->{LIST}} > -1);
- return $self->{LIST}->[0];
-}
-
-
-sub setValues
-{
- my $self = shift;
- my (@values) = @_;
- $self->{VALUES} = \@values;
-}
-
-
-sub getValues
-{
- my $self = shift;
- return unless ($#{$self->{VALUES}} > -1);
- return $self->{VALUES}->[0] if !wantarray;
- return @{$self->{VALUES}};
-}
-
-
-sub setAttribs
-{
- my $self = shift;
- my (%attribs) = @_;
- $self->{ATTRIBS} = \%attribs;
-}
-
-
-sub getAttribs
-{
- my $self = shift;
- return unless (scalar(keys(%{$self->{ATTRIBS}})) > 0);
- return %{$self->{ATTRIBS}};
-}
-
-
-sub setValid
-{
- my $self = shift;
- my $valid = shift;
- $self->{VALID} = $valid;
-}
-
-
-sub check
-{
- my $self = shift;
- return $self->{VALID};
-}
-
-
-sub in_context
-{
- my $self = shift;
- my $in_context = shift;
-
- if (defined($in_context))
- {
- $self->{INCONTEXT} = $in_context;
- }
- return $self->{INCONTEXT};
-}
-
-
-sub display
-{
- my $self = shift;
- if (0)
- {
- print "VALUE: list(",join(",",@{$self->{LIST}}),")\n";
- }
- else
- {
- print "VALUE: list(\n";
- foreach my $elem (@{$self->{LIST}})
- {
- print "VALUE: ",$elem->GetXML(),"\n";
- }
- print "VALUE: )\n";
- }
- print "VALUE: values(",join(",",@{$self->{VALUES}}),")\n";
-}
-
-1;
-
diff --git a/lib/XXV/MODULES/CONFIG.pm b/lib/XXV/MODULES/CONFIG.pm
index c2289dc..213cd6d 100644
--- a/lib/XXV/MODULES/CONFIG.pm
+++ b/lib/XXV/MODULES/CONFIG.pm
@@ -13,7 +13,7 @@ sub module {
my $args = {
Name => 'CONFIG',
Prereq => {
- # 'Perl::Module' => 'Description',
+ 'Module::Reload' => 'Reload %INC files when updated on disk ',
},
Description => gettext('This module edits, writes and saves the configuration.'),
Version => (split(/ /, '$Revision$'))[1],
diff --git a/lib/XXV/MODULES/TELNET.pm b/lib/XXV/MODULES/TELNET.pm
index 90fcfe1..7e8572c 100644
--- a/lib/XXV/MODULES/TELNET.pm
+++ b/lib/XXV/MODULES/TELNET.pm
@@ -15,7 +15,6 @@ sub module {
Name => 'TELNET',
Prereq => {
'IO::Socket::INET' => 'Object interface for AF_INET domain sockets ',
- 'Module::Reload' => 'Reload %INC files when updated on disk ',
},
Description => gettext('This module is a multisession telnet server.'),
Version => (split(/ /, '$Revision$'))[1],
@@ -196,7 +195,7 @@ sub init {
);
# welcome
- $client->print(sprintf(gettext("Welcome to xxv system version: %s.\r\nThis is session %s.\r\n"),$obj->{MOD}->{Version},$channel));
+ $client->print(sprintf(gettext("Welcome to xxv system version: %s.\r\nThis is session %s.\r\n"),main::getVersion(),$channel));
my $userMod = main::getModule('USER');
unless(exists $console->{USER} or $userMod->{active} ne 'y') {
diff --git a/lib/XXV/OUTPUT/Console.pm b/lib/XXV/OUTPUT/Console.pm
index a450227..dca6ee5 100644
--- a/lib/XXV/OUTPUT/Console.pm
+++ b/lib/XXV/OUTPUT/Console.pm
@@ -4,13 +4,11 @@ BEGIN{
$ENV{PERL_RL} = 'Perl'
};
-use Locale::gettext;
-use Term::ReadLine;
-
use strict;
+use Locale::gettext;
+use Term::ReadLine;
use Tools;
-use Pod::Text;
use vars qw($AUTOLOAD);
# This module method must exist for XXV
@@ -21,8 +19,9 @@ sub module {
my $args = {
Name => 'Telnet',
Prereq => {
- 'XML::Simple' => 'Easy API to maintain XML (esp config files)',
+ 'Pod::Text' => 'Convert POD data to formatted ASCII text ',
'Text::ASCIITable' => 'Create a nice formatted table using ASCII characters.',
+# 'Term::ReadLine' => 'Perl interface to various readline packages.',
'Term::ReadLine::Perl' => 'a quick implementation of the minimal interface to Readline',
},
Description => gettext('This receives and sends ASCII messages'),
diff --git a/lib/XXV/OUTPUT/Html.pm b/lib/XXV/OUTPUT/Html.pm
index fc7cdba..32b946c 100644
--- a/lib/XXV/OUTPUT/Html.pm
+++ b/lib/XXV/OUTPUT/Html.pm
@@ -2,16 +2,13 @@ package XXV::OUTPUT::Html;
use strict;
-#use Template;
use vars qw($AUTOLOAD);
use Locale::gettext;
use Tools;
use XXV::OUTPUT::HTML::WAIT;
use File::Path;
use File::Basename;
-use Pod::Html;
use Fcntl;
-#use Thread;
$SIG{CHLD} = 'IGNORE';
@@ -23,6 +20,9 @@ sub module {
my $args = {
Name => 'Html',
Prereq => {
+ 'Pod::Html' => 'Module to convert pod files to HTML ',
+# 'Template' => 'Front-end module to the Template Toolkit',
+# 'Compress::Zlib' => 'Interface to zlib compression library',
'HTML::TextToHTML' => 'convert plain text file to HTML. ',
},
Description => gettext('This receives and sends HTML messages.'),
diff --git a/lib/XXV/OUTPUT/Wml.pm b/lib/XXV/OUTPUT/Wml.pm
index 2e6e417..7349ab5 100644
--- a/lib/XXV/OUTPUT/Wml.pm
+++ b/lib/XXV/OUTPUT/Wml.pm
@@ -16,7 +16,7 @@ sub module {
my $args = {
Name => 'Wml',
Prereq => {
- 'Template' => 'Front-end module to the Template Toolkit ',
+ 'Template' => 'Front-end module to the Template Toolkit',
},
Description => gettext('This receives and sends WAP messages.'),
Version => (split(/ /, '$Revision$'))[1],