Apache-PSP

 view release on metacpan or  search on metacpan

lib/Template/PSP.pm  view on Meta::CPAN

package Template::PSP;

require 5.005;

use strict;

use Carp;

use HTML::Parser;
use IO::Scalar;
use DBI; 
use vars qw($VERSION);

$VERSION = 1.00;

# %tags        - list of special HTML tags defined in Template.pm
# %global_tags - list of HTML tags, accessible by all pages
#
# $page       - scalar reference to script being created from template
# $frags      - html fragments
# $outputflag - process '$' variables
# $perlflag   - perl code
# $package    - template is being placed in $package
# %tagdata    - data associated with tag being created
# %Cache      - file time stamps for loaded psp pages
# %Handler    - pointers to subroutines for psp pages
# %type       - subroutines for handling output types

use vars qw (%tags %global_tags $page $parsefile $frags $outputflag $perlflag
	     $handlerflag $package %tagdata %Cache %Handler %type $lineno
	     $top_package $escapeflag $space
	    );

use vars qw(%QUERY %CGI %FILENAMES %AUTH %COOKIE);

%tags = map {$_ => 1} 
	( "tag", "loop", "if", "else", "elseif", "perl", "fetch", "output", 
	"handler", "return", "include", "pspescape" );

sub cleanup
{
  no strict 'refs';
  push(@{$top_package . "::cleanup_handler"}, shift);
}

sub cleanup_handler
{
  my $handlers = shift(@_);
  
  for (my $i=0;$handlers->[$i];$i++)
  {
    &{$handlers->[$i]}();
  }
}

sub setpvar
{
  my $item = shift;
  my $value = shift;
  if ($item)
  {
    no strict 'refs';
    ${$top_package . "::" . $item} = $value;
  }
}

sub getpvar
{
  my $item = shift;
  no strict 'refs';
  return ${$top_package . "::" . $item};
}

# derive the absolute path based on a
# relative filename and the current file
# 
# thanks to Scott Kiehn
#
sub abs_path
{
  my $file = shift(@_);
  
  my $prefix = substr($file, 0, 1);
  
  # if this is not an absolute path, 
  # create an absolute path from it
  if ($prefix ne '/')          
  {
    # check for document root abbreviation
    if ($prefix eq '~')     
    {
      $file = substr($file, 1);
      $file = $ENV{DOCUMENT_ROOT} . $file;
    }
    # otherwise use relative path based on the current file
    else                        
    {
      $file = substr( $parsefile, 0, rindex($parsefile, '/') ) . "/" . $file;

lib/Template/PSP.pm  view on Meta::CPAN

  # fill %QUERY with query values
  my $cgi = CGI::Minimal->new();
#  %QUERY = map { my $x = [$cgi->param($_)]; $_ => scalar(@{$x}) > 1 ? \@{$x} : $$x[0] } ($cgi->param);
  # canonically-correct (and possibly temporary) expansion
  %QUERY = ();
  my @params = $cgi->param();
  foreach my $p (@params)
  {
    my @items = $cgi->param($p);
    if (scalar(@items) > 1)
    {
      $QUERY{$p} = \@items;
    }
    else
    {
      $QUERY{$p} = $items[0];
    }
  }

  
  # process cookies for this request
  my $cgi = CGI::Minimal->new();
  %COOKIE = ();
  my @cookies = split(/; ?/,$ENV{HTTP_COOKIE});
  foreach my $item (@cookies) 
  {
    my ($name, $value) = split('=', $item);
    $COOKIE{$name} = $cgi->url_decode($value);
  }
  
  # leave authorization for another time
#  if ($ENV->{HTTP_AUTHORIZATION}) 
#  {
#    my @list = split(/ /, $ENV{HTTP_AUTHORIZATION});
#    if (lc($list[0]) eq "basic") 
#    {
#      my $encoded = pop(@list);
#      my $decoded = decode_base64($encoded);
#  
#      ($AUTH->{username}, $AUTH->{password}) = split(/:/, $decoded);
#    }
#  }
  
  return 1;
}

#########################################
# Template::PSP::Parser
# used to process psp pages using HTML::Parser

sub start
{
  my $tagname = lc(shift);
  my $attr = shift;
  my $text = shift;

  no strict 'refs';

  default($text);

  if ($escapeflag || $tagname eq $tagdata{name} || $perlflag)
  {
    text($space . $text);
    $space = "";
    return;
  }

  # start tag
  if ($tags{$tagname})
  {
    no strict 'refs';
    &{$tagname}($attr);
    return;
  }

  my $fn = ${$package . "::custom_tags"}{$tagname} || $global_tags{$tagname};

  if ($fn)
  {
    append_page('&' . $fn . '({');
    
    foreach my $item (keys %{$attr})
    {
      my $s;
      my $s2;
      my $arg = ${$attr}{$item};
      $s2 = substr($arg,0,1);
      $s = substr($arg,1,1);
      
      if (($s2 eq '$') ||
          (($s2 eq "\\") &&
           ($s eq '@') ||
           ($s eq '%') ||
           ($s eq '&')
          )
         )
      {
        # don't quote because arg is a reference
        append_page("'$item'", '=>', $arg . ',');
      }
      else
      {
        if ($arg !~ /^@/)
        {
          $arg =~ s/@/\\@/gs;
        }
        $arg =~ s/{/\\{/g;
        $arg =~ s/}/\\}/g;
        append_page("'$item'", '=>', 'qq{' . $arg . '},');
      }
    }
    
    append_page('});'  . "\n");
    return;
  }
  
  text($space . $text);
  $space = "";
  return;
}

sub end
{
  my $tagname = lc(shift);
  my $text = shift;

  default($text);

  if (($escapeflag && $tagname ne "pspescape") ||
      ($tagname eq $tagdata{name}) ||
      ($handlerflag && $tagname ne "handler") ||
      (!$handlerflag && $perlflag && $tagname ne "perl"))
  {
    text($space . $text);
    $space = "";
    return;
  }

  if ($tags{$tagname})
  {
    no strict 'refs';
    &{$tagname . "_"}();
    return;
  }

  no strict 'refs';

  my $fn = $global_tags{$tagname . "_"} ||
           ${$package . "::custom_tags"}{$tagname . "_"};

  if ($fn)
  {
    no strict 'refs';
    append_page('&' . $fn .'();' . "\n");
    return;
  }
  
  text($space . $text);
  $space = "";
  return;
}

# for comments,
# display the comment as provided
sub comment
{
  my ($text) = @_;
  default($text);

  text($space . $text);
  $space = "";
  return;
  
  return;
}

sub default
{
  my ($text) = @_;
  $lineno += count_lines($text);
}

# handles all text that is read by the parser
sub text
{
  my ($text) = @_;

  if (!$escapeflag && $text =~ /^\s*$/s)
  {
    $space = $text;
    return;
  }
  if ($perlflag)
  {
    append_page($text);
  }
  elsif ($outputflag)
  {
    $text =~ s/\@/\\\@/g;
    append_page('print qq{' . $text . '};' . "\n");
  }
  else
  {
    no strict 'refs';
    $frags++;
    ${$package . '::__html_' . $frags} = $text;
    append_page("print \$" . $package . '::__html_' . $frags . ";\n");;
  }
}


#########################################
# BEGIN TAG DEFINITIONS
#
# The tag TAG allows building of non-looping tags.
# three parameters can be passed:
# name - name of tag to create
# body - if set to nonzero, the tag being defined contains
#     a body
# output - if set to nonzero, the tag being defined will
#     evaluate variables that begin with '$' 


sub tag
{
  my ($attr) = @_;
  my (@attrs) = split(/,/, $attr->{accepts});

  # Try to hide global variables for building tag in
  # %Template::PSP::tagdata

  $tagdata{body} = $attr->{body};
  if ($tagdata{body})
  {
    push(@attrs, "body");
  }
  $tagdata{global} = $attr->{global};
  $tagdata{name} = lc($attr->{name});
  $tagdata{oldpage} = $page;
  $page = \$tagdata{page};

  # For each new tag, create a Perl function 
  # which will be called when the start tag is 
  # encountered

  append_page('package', $package . ";\n");
  append_page("no strict 'refs';\n");
  append_page('sub', $tagdata{name}, "{\n");

lib/Template/PSP.pm  view on Meta::CPAN

  $perlflag--;
}

# The <fetch> tag searches the %type hash for a handler.
# If no handler is found, we assume that the user
# is outputting global scalars.  New output types can
# be easily added by adding handlers to the %type hash.

sub fetch {
    my ($attr) = @_;
    my ($handler) = $type{$attr->{type}};
    my @fetch = split(/,/, $attr->{fetch});

    if (defined($handler)) {
	my $attrs;
	$attrs .= "[";
	foreach my $item (@fetch) {
	    $attrs .= "\"$item\",";
	}
	$attrs .= "]";
	    
	my $startrow = $attr->{startrow} || 0;
	my $endrow = $attr->{endrow};

	append_page("#line $lineno $parsefile\n"); 
	append_page('for (my $i=' . $startrow . '; (my $results = &{$Template::PSP::type{'
		    . lc($attr->{type})
		    . '}}($' . $attr->{query} . ' || getpvar("'
		    . $attr->{query}
		    . '"), $i, '
		    . $attrs
		    . '))' );
	if ($endrow) {
	    append_page('&& $i <' . $endrow);
	}
	append_page('; $i++) {' . "\n");
    } else {
	append_page("{\n");
	append_page('my $results = $'.$attr->{query}.' || getpvar("'.$attr->{query}."\");\n");
    }
    foreach my $item (@fetch) {
        append_page("my \$$item =", '$results->{' . $item. '};' . "\n");
    }
}

sub fetch_ {
    append_page("}\n");
}

sub output 
{
    $outputflag++;
}

sub output_ 
{
  $outputflag--;
  $outputflag = 0 if $outputflag < 0;  
}

sub pspescape 
{
  $escapeflag++;
}

sub pspescape_ 
{
  $escapeflag--;
  $escapeflag = 0 if $escapeflag < 0;  
}

sub include 
{
  my ($attr) = @_;
 
  my $file     = eval qq{"$attr->{file}"};
  $file = abs_path($file);

  if (! -f $file) 
  {
    croak "Cannot include file '", $attr->{file}, 
          "' while processing $parsefile\n";
  }
  
  pspload($file);
  
  append_page('&{&Template::PSP::pspload(' . "'$file'" . ')}();' . "\n");
}

sub include_ {}

# load the rest of the tags
foreach my $filename qw(Tags.psp autoform.psp)
{
  my $tags_file;
  
  foreach my $path (@INC)
  {
    my $test = $path . "/Template/PSP/$filename";
    
    if (-e $test)
    {
      $tags_file = $test;
      last;
    }
  }
  
  if ($tags_file)
  {
    eval { pspload($tags_file, "Template::PSP"); };
    if ($@)
    {
      warn "WARNING: Can't load optional tags from $tags_file. " .
           "Some global tags may not be available.\n";
    }
  }
}

#########################################
# MISC FUNCTIONS

# checks if file has changed on disk
sub newfile {
    my $file = shift;
    my $mtime = -M "$file";

    if (!defined($Cache{$file}) || $Cache{$file} != $mtime) {
	$Cache{$file} = $mtime;
	return 1;



( run in 1.034 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )