xml-axkit-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jw...@apache.org
Subject cvs commit: xml-axkit/lib/Apache/AxKit/Language/XSP SimpleTaglib.pm
Date Fri, 15 Mar 2002 00:02:55 GMT
jwalt       02/03/14 16:02:55

  Modified:    demo     axkit.conf
               demo/xsp .htaccess index.xml session.xsp showsource.xsp
  Added:       demo/AxKit/XSP/Demo Simple.pm
               demo/xsp auth.xsp globals.xsp simpletaglib-simple.xsp
               lib/Apache/AxKit/Language/XSP SimpleTaglib.pm
  Log:
   - SimpleTaglib added (initial commit, code stable)
   - Demos added: SimpleTaglib, Session, Globals, Auth (all untested)
   - possible information leaking in showsource.xsp tagged
  
  Revision  Changes    Path
  1.3       +7 -0      xml-axkit/demo/axkit.conf
  
  Index: axkit.conf
  ===================================================================
  RCS file: /home/cvs/xml-axkit/demo/axkit.conf,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- axkit.conf	8 Mar 2002 17:44:58 -0000	1.2
  +++ axkit.conf	15 Mar 2002 00:02:55 -0000	1.3
  @@ -14,6 +14,13 @@
   ## CHANGE THIS to the location of your demo files
   Alias /axkit/ /opt/axkit/demo/
   
  +<Perl>
  +## CHANGE THIS as well
  +use lib /opt/axkit/demo/
  +</Perl>
  +
  +## and another one, CHANGE THIS
   <Directory /opt/axkit/demo>
   AllowOverride All
   </Directory>
  +
  
  
  
  1.1                  xml-axkit/demo/AxKit/XSP/Demo/Simple.pm
  
  Index: Simple.pm
  ===================================================================
  # $Id: Simple.pm,v 1.1 2002/03/15 00:02:55 jwalt Exp $
  # Derived from Axkit::XSP::Simple - application global variable management, part of the
  # session plugin package
  package AxKit::XSP::Demo::Simple;
  
  # Always use strict. Do it. I mean it. And turn on warnings as well.
  use strict;
  
  # this single line makes the taglib a Simpletaglib powered one
  use Apache::AxKit::Language::XSP::SimpleTaglib;
  
  # providing a version is good style, but not strictly neccessary
  $AxKit::XSP::Demo::Simple::VERSION = 0.90;
  
  # The namespace associated with this taglib. If it doesn't work, double check
  # that you are using the exact same NS uri here and in the XSP.
  $AxKit::XSP::Demo::Simple::NS = 'http://www.creITve.de/2002/XSP/Demo/Simple';
  
  # something to go at the top of the XSP script - this is NOT executed on every
  # request, but only once for each httpd process
  
  sub start_document {
      return "use Time::Piece;\n".
             # note the naming convention: all xsp internal variable names start with
             # _xsp_, followed by the package name minus AxKit::XSP::, replacing '::'
             # with '_'.
             "my \$_xsp_demo_simple_first_time = localtime();\n".
             "my \$_xsp_demo_simple_last_time = localtime(0);\n";
  }
  
  # a utility function.
  
  sub do_long_and_complex_calculation {
      return int(rand(42));
  }
  
  ################################################################
  # package for the handler subs - here the taglib really begins #
  ################################################################
  package AxKit::XSP::Simple::Handlers;
  
  # a very simple tag: <demo:set-time/>
  sub set_time
  {
      return '$_xsp_demo_simple_last_time = localtime();';
  }
  
  # a more complex tag: <demo:first-time [as="node|string"]/>
  # input is an attribute, output is a node or a scalar
  sub first_time : attrib(as) exprOrNode(first-run-time)
  {
      my ($e, $tag, %attribs) = @_;
  	if ($attribs{'as'} eq 'string') {
  		return '$_xsp_demo_simple_first_time->strftime("%a %b %d %H:%M:%S %Z %Y");';
  	} else {
  		return '$_xsp_demo_simple_first_time';
  	}
  }
  
  # another one: <demo:last-time [as="node|string"]/>
  sub last_time : attrib(as) exprOrNode(last-run-time)
  {
      my ($e, $tag, %attribs) = @_;
  	if ($attribs{'as'} eq 'string') {
  		return '$_xsp_demo_simple_last_time->strftime("%a %b %d %H:%M:%S %Z %Y");';
  	} else {
  		return '$_xsp_demo_simple_last_time';
  	}
  }
  
  # returning a list or a list of nodes
  sub times : exprOrNodelist(run-time)
  {
  	return '($_xsp_demo_simple_first_time,$_xsp_demo_simple_last_time)';
  }
  
  # returning a scalar, array, or text node, depending on context.
  sub calculate_something : expr
  {
      return 'AxKit::XSP::Demo::Simple::do_long_and_complex_calculation();';
  }
  
  # input is an attribute or a node
  sub set_custom_time : attribOrChild(time)
  {
  	return '$_xsp_demo_simple_last_time = localtime($attr_time);';
  }
  
  # input is the text content of the tag
  sub set_custom_time_content : captureContent
  {
  	return '$_xsp_demo_simple_last_time = localtime(int($_));';
  }
  
  # this demo does not cover the childStruct and struct input/output specs.
  # stay tuned for the advanced demo.
  
  1;
  
  __END__
  
  =head1 NAME
  
  AxKit::XSP::Demo::Simple - basic SimpleTaglib demo
  
  =head1 SYNOPSIS
  
  Add the demo: namespace to your XSP C<<xsp:page>> tag:
  
      <xsp:page
           language="Perl"
           xmlns:xsp="http://apache.org/xsp/core/v1"
           xmlns:simple="http://www.creITve.de/2002/XSP/Demo/Simple"
      >
  
  Add this taglib to AxKit (via httpd.conf or .htaccess):
  
      AxAddXSPTaglib AxKit::XSP::Demo::Simple
  
  =head1 DESCRIPTION
  
  This is a demo of the basic SimpleTaglib features. See the SimpleTaglib docs
  for details.
  
  =head1 AUTHOR
  
  Jörg Walter <jwalt@cpan.org>
  
  =head1 COPYRIGHT
  
  Copyright (c) 2002 Jörg Walter.
  All rights reserved. This program is free software; you can redistribute it and/or
  modify it under the same terms as AxKit itself.
  
  =head1 SEE ALSO
  
  AxKit, Apache::AxKit::Language::XSP, Apache::AxKit::Language::XSP::SimpleTaglib
  
  =cut
  
  
  
  1.4       +37 -0     xml-axkit/demo/xsp/.htaccess
  
  Index: .htaccess
  ===================================================================
  RCS file: /home/cvs/xml-axkit/demo/xsp/.htaccess,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- .htaccess	14 Mar 2002 22:29:58 -0000	1.3
  +++ .htaccess	15 Mar 2002 00:02:55 -0000	1.4
  @@ -11,3 +11,40 @@
   <Files esql.xsp>
   AxAddXSPTaglib AxKit::XSP::ESQL
   </Files>
  +
  +<Files simpletaglib-simple.xsp>
  +AxAddXSPTaglib AxKit::XSP::Demo::Simple
  +</Files>
  +
  +<Files session.xsp>
  +	AxAddPlugin Apache::AxKit::Plugin::Session
  +	AxAddXSPTaglib AxKit::XSP::Session
  +</Files>
  +
  +<Files globals.xsp>
  +	AxAddPlugin Apache::AxKit::Plugin::Session
  +	AxAddXSPTaglib AxKit::XSP::Session
  +	AxAddXSPTaglib AxKit::XSP::Global
  +</Files>
  +
  +<Files auth.xsp>
  +	AxAddPlugin Apache::AxKit::Plugin::Session
  +	AxAddXSPTaglib AxKit::XSP::Session
  +	AxAddXSPTaglib AxKit::XSP::Auth
  +
  +	AuthType Apache::AxKit::Plugin::Session
  +	AuthName AxKitSession
  +	require valid-user
  +</Files>
  +
  +<Files auth.xsp#view>
  +	AxAddPlugin Apache::AxKit::Plugin::Session
  +	AxAddXSPTaglib AxKit::XSP::Session
  +	AxAddXSPTaglib AxKit::XSP::Auth
  +
  +	AuthType Apache::AxKit::Plugin::Session
  +	AuthName AxKitSession
  +	require group admin
  +</Files>
  +
  +<Files auth
  
  
  
  1.3       +219 -182  xml-axkit/demo/xsp/index.xml
  
  Index: index.xml
  ===================================================================
  RCS file: /home/cvs/xml-axkit/demo/xsp/index.xml,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- index.xml	14 Mar 2002 22:29:58 -0000	1.2
  +++ index.xml	15 Mar 2002 00:02:55 -0000	1.3
  @@ -1,182 +1,219 @@
  -<xsp:page xmlns:xsp="http://www.apache.org/1999/XSP/Core">
  -
  -<xsp:logic>
  -my @errors;
  -</xsp:logic>
  -
  -<html>
  -    <head>
  -        <title>XSP Examples</title>
  -        <link rel="stylesheet" href="/axkit/stylesheets/style.css"/>
  -    </head>
  -    <body>
  -        <h1>XSP Examples</h1>
  -        <p>
  -        This page contains some XSP examples. This page is an example in itself,
  -        and lists the example pages that will work on your installation.
  -        </p>
  -        <p>
  -        Please note that all of these examples purely use only XSP, whereas normally
  -        you would use XSP in conjunction with some stylesheet language such as XSLT,
  -        in order to maintain a separation of content from presentation. Therefore
  -        these examples should be used as a technology demonstration, not a guideline.
  -        </p>
  -        <p>
  -            <ul>
  -                
  -            <xsp:logic>
  -            @errors = ();
  -            
  -            eval {
  -                require AxKit::XSP::ESQL;
  -                require DBD::SQLite;
  -            };
  -            if (!$@) {
  -                <li><a href="esql.xsp">ESQL Example</a></li>
  -            }
  -            else {
  -                AxKit::Debug(1, "ESQL failed to load: $@");
  -                push @errors, $@;
  -                <li>ESQL Example unavailable (see below for details)</li>
  -            }
  -            
  -            eval {
  -                require AxKit::XSP::Cookie;
  -            };
  -            if (!$@) {
  -                <li><a href="cookie.xsp">Cookie Example</a></li>
  -            }
  -            else {
  -                AxKit::Debug(1, "Cookie Taglib failed to load: $@");
  -                push @errors, $@;
  -                <li>Cookie Example unavailable (see below for details)</li>
  -            }
  -            
  -            eval {
  -                require AxKit::XSP::Exception;
  -            };
  -            if (!$@) {
  -                <li><a href="exception.xsp">Exceptions Example</a></li>
  -            }
  -            else {
  -                AxKit::Debug(1, "Exceptions Taglib failed to load: $@");
  -                push @errors, $@;
  -                <li>Exceptions Example unavailable (see below for details)</li>
  -            }
  -            
  -            eval {
  -                require AxKit::XSP::IfParam;
  -            };
  -            if (!$@) {
  -                <li><a href="ifparam.xsp">IfParam Taglib Example</a></li>
  -            }
  -            else {
  -                AxKit::Debug(1, "IfParam Taglib failed to load: $@");
  -                push @errors, $@;
  -                <li>IfParam Taglib Example unavailable (see below for details)</li>
  -            }
  -            
  -            eval {
  -                require AxKit::XSP::Param;
  -            };
  -            if (!$@) {
  -                <li><a href="param.xsp">Param Example</a></li>
  -            }
  -            else {
  -                AxKit::Debug(1, "Param Taglib failed to load: $@");
  -                push @errors, $@;
  -                <li>Param Example unavailable (see below for details)</li>
  -            }
  -            
  -            eval {
  -                require AxKit::XSP::PerForm;
  -                require XML::LibXSLT;
  -            };
  -            if (!$@) {
  -                <li><a href="perform.xsp">PerForm Example</a></li>
  -            }
  -            else {
  -                AxKit::Debug(1, "PerForm Taglib failed to load: $@");
  -                push @errors, $@;
  -                <li>PerForm Example unavailable (see below for details)</li>
  -            }
  -            
  -            eval {
  -                require AxKit::XSP::Sendmail;
  -            };
  -            if (!$@) {
  -                <li><a href="sendmail.xsp">Sending Email Example</a></li>
  -            }
  -            else {
  -                AxKit::Debug(1, "Sendmail Taglib failed to load: $@");
  -                push @errors, $@;
  -                <li>Sending Email Example unavailable (see below for details)</li>
  -            }
  -            
  -            eval {
  -                require AxKit::XSP::Util;
  -            };
  -            if (!$@) {
  -                <li><a href="util.xsp">Util Taglib Example</a></li>
  -            }
  -            else {
  -                AxKit::Debug(1, "Util Taglib failed to load: $@");
  -                push @errors, $@;
  -                <li>Util Taglib Example unavailable (see below for details)</li>
  -            }
  -            
  -            eval {
  -                require AxKit::XSP::WebUtils;
  -            };
  -            if (!$@) {
  -                <li><a href="webutils.xsp">WebUtils Taglib Example</a></li>
  -            }
  -            else {
  -                AxKit::Debug(1, "WebUtils Taglib failed to load: $@");
  -                push @errors, $@;
  -                <li>WebUtils Taglib Example unavailable (see below for details)</li>
  -            }
  -            
  -            eval {
  -                require AxKit::XSP::Session;
  -            };
  -            if (!$@) {
  -                <li><a href="session.xsp">Session Taglib Example</a></li>
  -            }
  -            else {
  -                AxKit::Debug(1, "Session Taglib failed to load: $@");
  -                push @errors, $@;
  -                <li>Session Taglib Example unavailable (see below for details)</li>
  -            }
  -            
  -            </xsp:logic>
  -            </ul>
  -        </p>
  -        <p>
  -        If no examples appear other than the core XSP example, then you may
  -        need to install some of the XSP taglibs from CPAN. To find those, either
  -        load up the CPAN shell and type: <tt>i /XSP/</tt> to see all the taglibs
  -        available, or go to 
  -        <a href="http://theoryx5.uwinnipeg.ca/mod_perl/cpan-search?search=AxKit%3A%3AXSP"
  -        >this link</a>
  -        to find all the XSP taglibs on CPAN.
  -        </p>
  -        <p>
  -        Please also note that this file itself is an example of XSP without using
  -        any tag libraries. You can see it by clicking on <a href="showsource.xsp?index.xml">View Source</a>
  -        </p>
  -        <!--
  -        <p>
  -        The errors that occured checking if the above demos would work are, in order:
  -        <ul>
  -        <xsp:logic>
  -            foreach my $err (@errors) {
  -                <li><tt><xsp:expr>$err</xsp:expr></tt></li>
  -            }
  -        </xsp:logic>
  -        </ul>
  -        </p>
  -        -->
  -    </body>
  -</html>
  -</xsp:page>
  \ No newline at end of file
  +<?xml version="1.0"?>
  +<xsp:page xmlns:xsp="http://www.apache.org/1999/XSP/Core">
  +
  +<xsp:logic>
  +my @errors;
  +</xsp:logic>
  +
  +<html>
  +    <head>
  +        <title>XSP Examples</title>
  +        <link rel="stylesheet" href="/axkit/stylesheets/style.css"/>
  +    </head>
  +    <body>
  +        <h1>XSP Examples</h1>
  +        <p>
  +        This page contains some XSP examples. This page is an example in itself,
  +        and lists the example pages that will work on your installation.
  +        </p>
  +        <p>
  +        Please note that all of these examples purely use only XSP, whereas normally
  +        you would use XSP in conjunction with some stylesheet language such as XSLT,
  +        in order to maintain a separation of content from presentation. Therefore
  +        these examples should be used as a technology demonstration, not a guideline.
  +        </p>
  +        <p>
  +            <ul>
  +                
  +            <xsp:logic>
  +            @errors = ();
  +            
  +            eval {
  +                require AxKit::XSP::ESQL;
  +                require DBD::SQLite;
  +            };
  +            if (!$@) {
  +                <li><a href="esql.xsp">ESQL Example</a></li>
  +            }
  +            else {
  +                AxKit::Debug(1, "ESQL failed to load: $@");
  +                push @errors, $@;
  +                <li>ESQL Example unavailable (see below for details)</li>
  +            }
  +
  +            eval {
  +                require AxKit::XSP::Cookie;
  +            };
  +            if (!$@) {
  +                <li><a href="cookie.xsp">Cookie Example</a></li>
  +            }
  +            else {
  +                AxKit::Debug(1, "Cookie Taglib failed to load: $@");
  +                push @errors, $@;
  +                <li>Cookie Example unavailable (see below for details)</li>
  +            }
  +
  +            eval {
  +                require AxKit::XSP::Exception;
  +            };
  +            if (!$@) {
  +                <li><a href="exception.xsp">Exceptions Example</a></li>
  +            }
  +            else {
  +                AxKit::Debug(1, "Exceptions Taglib failed to load: $@");
  +                push @errors, $@;
  +                <li>Exceptions Example unavailable (see below for details)</li>
  +            }
  +
  +            eval {
  +                require AxKit::XSP::IfParam;
  +            };
  +            if (!$@) {
  +                <li><a href="ifparam.xsp">IfParam Taglib Example</a></li>
  +            }
  +            else {
  +                AxKit::Debug(1, "IfParam Taglib failed to load: $@");
  +                push @errors, $@;
  +                <li>IfParam Taglib Example unavailable (see below for details)</li>
  +            }
  +
  +            eval {
  +                require AxKit::XSP::Param;
  +            };
  +            if (!$@) {
  +                <li><a href="param.xsp">Param Example</a></li>
  +            }
  +            else {
  +                AxKit::Debug(1, "Param Taglib failed to load: $@");
  +                push @errors, $@;
  +                <li>Param Example unavailable (see below for details)</li>
  +            }
  +
  +            eval {
  +                require AxKit::XSP::PerForm;
  +                require XML::LibXSLT;
  +            };
  +            if (!$@) {
  +                <li><a href="perform.xsp">PerForm Example</a></li>
  +            }
  +            else {
  +                AxKit::Debug(1, "PerForm Taglib failed to load: $@");
  +                push @errors, $@;
  +                <li>PerForm Example unavailable (see below for details)</li>
  +            }
  +
  +            eval {
  +                require AxKit::XSP::Sendmail;
  +            };
  +            if (!$@) {
  +                <li><a href="sendmail.xsp">Sending Email Example</a></li>
  +            }
  +            else {
  +                AxKit::Debug(1, "Sendmail Taglib failed to load: $@");
  +                push @errors, $@;
  +                <li>Sending Email Example unavailable (see below for details)</li>
  +            }
  +
  +            eval {
  +                require AxKit::XSP::Util;
  +            };
  +            if (!$@) {
  +                <li><a href="util.xsp">Util Taglib Example</a></li>
  +            }
  +            else {
  +                AxKit::Debug(1, "Util Taglib failed to load: $@");
  +                push @errors, $@;
  +                <li>Util Taglib Example unavailable (see below for details)</li>
  +            }
  +
  +            eval {
  +                require AxKit::XSP::WebUtils;
  +            };
  +            if (!$@) {
  +                <li><a href="webutils.xsp">WebUtils Taglib Example</a></li>
  +            }
  +            else {
  +                AxKit::Debug(1, "WebUtils Taglib failed to load: $@");
  +                push @errors, $@;
  +                <li>WebUtils Taglib Example unavailable (see below for details)</li>
  +            }
  +
  +            eval {
  +                require AxKit::XSP::Session;
  +            };
  +            if (!$@) {
  +                <li><a href="session.xsp">Session Taglib Example</a></li>
  +            }
  +            else {
  +                AxKit::Debug(1, "Session Taglib failed to load: $@");
  +                push @errors, $@;
  +                <li>Session Taglib Example unavailable (see below for details)</li>
  +            }
  +
  +            eval {
  +                require AxKit::XSP::Global;
  +            };
  +            if (!$@) {
  +                <li><a href="global.xsp">Globals Taglib Example</a></li>
  +            }
  +            else {
  +                AxKit::Debug(1, "Globals Taglib failed to load: $@");
  +                push @errors, $@;
  +                <li>Globals Taglib Example unavailable (see below for details)</li>
  +            }
  +
  +            eval {
  +                require AxKit::XSP::Auth;
  +            };
  +            if (!$@) {
  +                <li><a href="auth.xsp">Authorization Taglib Example</a></li>
  +            }
  +            else {
  +                AxKit::Debug(1, "Authorization Taglib failed to load: $@");
  +                push @errors, $@;
  +                <li>Authorization Taglib Example unavailable (see below for details)</li>
  +            }
  +
  +            eval {
  +                require Apache::AxKit::Language::XSP::SimpleTaglib;
  +            }
  +            if (!$@) {
  +                <li><a href="simpletaglib-simple.xsp">SimpleTaglib Taglib Example</a></li>
  +            }
  +            else {
  +                AxKit::Debug(1, "SimpleTaglib failed to load: $@");
  +                push @errors, $@;
  +                <li>SimpleTaglib Taglib Example unavailable (see below for details)</li>
  +            }
  +
  +            </xsp:logic>
  +            </ul>
  +        </p>
  +        <p>
  +        If no examples appear other than the core XSP example, then you may
  +        need to install some of the XSP taglibs from CPAN. To find those, either
  +        load up the CPAN shell and type: <tt>i /XSP/</tt> to see all the taglibs
  +        available, or go to
  +        <a href="http://theoryx5.uwinnipeg.ca/mod_perl/cpan-search?search=AxKit%3A%3AXSP"
  +        >this link</a>
  +        to find all the XSP taglibs on CPAN.
  +        </p>
  +        <p>
  +        Please also note that this file itself is an example of XSP without using
  +        any tag libraries. You can see it by clicking on <a href="showsource.xsp?index.xml">View Source</a>
  +        </p>
  +        <!--
  +        <p>
  +        The errors that occured checking if the above demos would work are, in order:
  +        <ul>
  +        <xsp:logic>
  +            foreach my $err (@errors) {
  +                <li><tt><xsp:expr>$err</xsp:expr></tt></li>
  +            }
  +        </xsp:logic>
  +        </ul>
  +        </p>
  +        -->
  +    </body>
  +</html>
  +</xsp:page>
  
  
  
  1.2       +32 -0     xml-axkit/demo/xsp/session.xsp
  
  Index: session.xsp
  ===================================================================
  RCS file: /home/cvs/xml-axkit/demo/xsp/session.xsp,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- session.xsp	14 Mar 2002 22:29:58 -0000	1.1
  +++ session.xsp	15 Mar 2002 00:02:55 -0000	1.2
  @@ -0,0 +1,32 @@
  +<?xml version="1.0"?>
  +<?xml-stylesheet href="." type="application/x-xsp"?>
  +<?xml-stylesheet href="Taglib-Demo.xsl" type="text/xsl"?>
  +<xsp:page xmlns:foo="file:///dev/null" language="Perl"
  +	xmlns:xsp="http://www.apache.org/1999/XSP/Core"
  +	xmlns:session="http://www.apache.org/1999/XSP/Session"
  + 	xmlns="http://www.w3.org/1999/xhtml">
  +<html>
  +<body>
  +<h1>Session Taglib demo</h1>
  +<session:set-attribute><session:name>Test</session:name>In fact, there are more attributes, but they
  +are internal and not accessible through this taglib.</session:set-attribute>
  +<dl>
  +<dt><b>Session ID:</b></dt><dd><session:get-id as="node"/></dd>
  +<dt><b>Names:</b></dt><dd><xsp:expr>join(",",<session:get-attribute-names/>)</xsp:expr><br/><session:get-attribute-names as="node"/></dd>
  +<dt><b>Values:</b></dt><dd><ul><xsp:logic>
  +foreach my $name (<session:get-attribute-names/>) {
  +</xsp:logic>
  +<li><b><em><xsp:expr>$name</xsp:expr></em></b>:
  +<tt><session:get-attribute as="node"><session:name><xsp:expr>$name</xsp:expr></session:name></session:get-attribute></tt></li>
  +<xsp:logic>
  +}
  +</xsp:logic>
  +</ul></dd>
  +<dt><b>Creation Time:</b></dt><dd><session:get-creation-time as="string"/></dd>
  +<dt><b>Access Time:</b></dt><dd><session:get-last-accessed-time/></dd>
  +<dt><b>Inactive Interval:</b></dt><dd><session:get-max-inactive-interval/></dd>
  +<dt><b>Is new?</b></dt><dd><xsp:expr><session:is-new/>?"Yes":"No"</xsp:expr></dd>
  +</dl>
  +</body>
  +</html>
  +</xsp:page>
  
  
  
  1.2       +29 -28    xml-axkit/demo/xsp/showsource.xsp
  
  Index: showsource.xsp
  ===================================================================
  RCS file: /home/cvs/xml-axkit/demo/xsp/showsource.xsp,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- showsource.xsp	14 Mar 2002 22:29:58 -0000	1.1
  +++ showsource.xsp	15 Mar 2002 00:02:55 -0000	1.2
  @@ -1,28 +1,29 @@
  -<xsp:page xmlns:xsp="http://www.apache.org/1999/XSP/Core">
  -
  -<xsp:import>Apache::File</xsp:import>
  -
  -<html>
  -    <head>
  -        <title>Source for <xsp:expr>$r->args</xsp:expr></title>
  -        <link rel="stylesheet" url="/axkit/stylesheets/style.css"/>
  -    </head>
  -    
  -    <body>
  -    <h1>Source for <xsp:expr>$r->args</xsp:expr></h1>
  -    <xsp:logic>
  -    my $filename = $r->lookup_uri($r->args)->filename;
  -    my $file = Apache::File->new($filename);
  -    <pre>
  -    <xsp:expr><![CDATA[
  -        join('', <$file>);
  -    ]]></xsp:expr>
  -    </pre>
  -    </xsp:logic>
  -    <p>
  -    <a href="showsource.xsp?showsource.xsp">View Source</a>
  -    </p>
  -    </body>
  -</html>
  -
  -</xsp:page>
  \ No newline at end of file
  +<xsp:page xmlns:xsp="http://www.apache.org/1999/XSP/Core">
  +
  +<xsp:import>Apache::File</xsp:import>
  +
  +<html>
  +    <head>
  +        <title>Source for <xsp:expr>$r->args</xsp:expr></title>
  +        <link rel="stylesheet" url="/axkit/stylesheets/style.css"/>
  +    </head>
  +    
  +    <body>
  +    <h1>Source for <xsp:expr>$r->args</xsp:expr></h1>
  +    <xsp:logic>
  +    # this oculd leak information. should check for 'demo files only'
  +    my $filename = $r->lookup_uri($r->args)->filename;
  +    my $file = Apache::File->new($filename);
  +    <pre>
  +    <xsp:expr><![CDATA[
  +        join('', <$file>);
  +    ]]></xsp:expr>
  +    </pre>
  +    </xsp:logic>
  +    <p>
  +    <a href="showsource.xsp?showsource.xsp">View Source</a>
  +    </p>
  +    </body>
  +</html>
  +
  +</xsp:page>
  
  
  
  1.1                  xml-axkit/demo/xsp/auth.xsp
  
  Index: auth.xsp
  ===================================================================
  <?xml version="1.0"?>
  <?xml-stylesheet href="." type="application/x-xsp"?>
  <?xml-stylesheet href="Taglib-Demo.xsl" type="text/xsl"?>
  <xsp:page xmlns:foo="file:///dev/null" language="Perl"
  	xmlns:xsp="http://www.apache.org/1999/XSP/Core"
  	xmlns:session="http://www.apache.org/1999/XSP/Session"
  	xmlns:auth="http://www.creITve.de/2002/XSP/Auth"
   	xmlns="http://www.w3.org/1999/xhtml">
  <html>
  <body>
  <h1>Auth Taglib demo</h1>
  <auth:add-access><auth:access type="group">blas</auth:access></auth:add-access>
  <auth:set-access><auth:access type="user">fubar</auth:access></auth:set-access>
  <auth:add-access><auth:access type="group">foos</auth:access></auth:add-access>
  <auth:add-access><auth:access type="group">bars</auth:access></auth:add-access>
  <auth:rem-access><auth:access type="group">bars</auth:access></auth:rem-access>
  <dl>
  <dt><b>Access:</b></dt><dd><auth:get-access/></dd>
  <dt><b>Permissions of this page:</b></dt><dd><auth:get-permission target=""/></dd>
  <dt><b>Permissions of subresource 'view':</b></dt><dd><auth:get-permission target="view"/></dd>
  <dt><b>Encrypt password:</b></dt><dd><auth:encrypt-password>ficken</auth:encrypt-password></dd>
  <dt><b>Password matches?</b></dt><dd><auth:password-matches encrypted="$1$jsdxRBEt$IzCeNthea4KqzkzNB7sT4/" clear="ficken"/></dd>
  </dl>
  </body>
  </html>
  </xsp:page>
  
  
  
  1.1                  xml-axkit/demo/xsp/globals.xsp
  
  Index: globals.xsp
  ===================================================================
  <?xml version="1.0"?>
  <?xml-stylesheet href="." type="application/x-xsp"?>
  <?xml-stylesheet href="Taglib-Demo.xsl" type="text/xsl"?>
  <xsp:page xmlns:foo="file:///dev/null" language="Perl"
  	xmlns:xsp="http://www.apache.org/1999/XSP/Core"
  	xmlns:session="http://www.apache.org/1999/XSP/Session"
  	xmlns:global="http://www.creITve.de/2002/XSP/Global"
   	xmlns="http://www.w3.org/1999/xhtml">
  <html>
  <body>
  <h1>Globals Taglib demo</h1>
  <global:set-attribute><global:name>Accesses</global:name><xsp:expr>
  <global:get-attribute name="Accesses"/>+1</xsp:expr></global:set-attribute>
  <dl>
  <dt><b>Names:</b></dt><dd><xsp:expr>join(",",<global:get-attribute-names/>)</xsp:expr><br/><global:get-attribute-names as="node"/></dd>
  <dt><b>Values:</b></dt><dd><ul><xsp:logic>
  foreach my $name (<global:get-attribute-names/>) {
  </xsp:logic>
  <li><b><em><xsp:expr>$name</xsp:expr></em></b>:
  <tt><global:get-attribute as="node"><global:name><xsp:expr>$name</xsp:expr></global:name></global:get-attribute></tt></li>
  <xsp:logic>
  }
  </xsp:logic>
  </ul></dd>
  <dt><b>Creation Time:</b></dt><dd><global:get-creation-time as="string"/></dd>
  </dl>
  </body>
  </html>
  </xsp:page>
  
  
  
  1.1                  xml-axkit/demo/xsp/simpletaglib-simple.xsp
  
  Index: simpletaglib-simple.xsp
  ===================================================================
  <?xml version="1.0"?>
  <xsp:page
      language="Perl"
      xmlns:xsp="http://apache.org/xsp/core/v1"
      xmlns:simple="http://www.creITve.de/2002/XSP/Demo/Simple"
  >
  <html>
  <head>
  <title>Simple SimpleTaglib Demo</title>
  </head>
  <body>
  <h1>Simple SimpleTaglib Demo</h1>
  <h2>Output modes</h2>
  <ul>
  <li>expr in xml context: <demo:calculate-something/></li>
  <li>expr in perl context: <xsp:expr>'perl '.<demo:calculate-something/></xsp:expr></li>
  <li>exprOrNode in xml context: <demo:first-time/></li>
  <li>exprOrNode in xml context as node: <demo:first-time as="node"/></li>
  <li>exprOrNode in perl context as string: <xsp:expr>'time: '.<demo:first-time as="node"/></xsp:expr></li>
  <li>node list in xml context: <demo:times/></li>
  <li>node list in perl array context: <xsp:expr>join(", ",<demo:times/>)</xsp:expr></li>
  <li>node list in perl scalar context: <xsp:expr>scalar(<demo:times/>)</xsp:expr></li>
  <h2>Input modes</h2>
  <ul>
  <li>last access time of this page in this process: <demo:last-time as="string"/></li>
  <li>no input, no output: <demo:set-time/></li>
  <li>last access time of this page in this process: <demo:last-time as="string"/></li>
  <li>input as attribute, no output: <demo:set-custom-time time="1234567890"/></li>
  <li>last access time of this page in this process: <demo:last-time as="string"/></li>
  <li>input as child element, no output: <demo:set-custom-time><time>1000000000</time></demo:set-custom-time></li>
  <li>last access time of this page in this process: <demo:last-time as="string"/></li>
  <li>input as content: <demo:set-custom-time-content>9876543210</demo:set-custom-time></li>
  <li>last access time of this page in this process: <demo:last-time as="string"/></li>
  </ul>
  </body>
  </html>
  </xsp:page>
  
  
  
  1.1                  xml-axkit/lib/Apache/AxKit/Language/XSP/SimpleTaglib.pm
  
  Index: SimpleTaglib.pm
  ===================================================================
  # $Id: SimpleTaglib.pm,v 1.1 2002/03/15 00:02:55 jwalt Exp $
  # Apache::AxKit::XSP::Language::SimpleTaglib - alternate taglib helper code
  package Apache::AxKit::Language::XSP::SimpleTaglib;
  require 5.006;
  use strict;
  use Apache::AxKit::Language::XSP;
  use CGI::Carp;
  use attributes;
  $Apache::AxKit::Language::XSP::SimpleTaglib::VERSION = 0.1;
  @Apache::AxKit::Language::XSP::SimpleTaglib::ISA = ('Apache::AxKit::Language::XSP');
  
  # utility functions
  
  sub makeSingleQuoted($) { $_ = shift; s/([\\%])/\\$1/g; 'q%'.$_.'%'; }
  sub _makeAttributeQuoted(@) { $_ = join(',',@_); s/([\\()])/\\\1/g; '('.$_.')'; }
  sub makeVariableName($) { $_ = shift; s/[^a-zA-Z0-9]/_/g; $_; }
  
  # perl attribute handlers
  
  my %handlerAttributes;
  
  use constant PLAIN => 0;
  use constant EXPR => 1;
  use constant EXPRORNODE => 2;
  use constant NODE => 3;
  use constant EXPRORNODELIST => 4;
  use constant NODELIST => 5;
  use constant STRUCT => 6;
  
  # memory leak ahead! the '&' construct may create circular references, which perl
  # can't clean up. But this has only an effect if a taglib is reloaded, which shouldn't
  # happen on production machines. Moreover, '&' is rather unusual.
  sub parseChildStructSpec {
      my ($specs, $refs) = @_;
      for my $spec ($_[0]) {
          my $result = {};
          while (length($spec)) {
              (my ($type, $token, $next) = ($spec =~ m/^([\&\@\*\$]?)([^ {}]+)(.|$)/))
                   || die("childStruct specification invalid. Parse error at: '$spec'");
              substr($spec,0,length($token)+1+($type?1:0)) = '';
              #warn("type: $type, token: $token, next: $next");
              my ($realtoken, $params);
              if ((($realtoken,$params) = ($token =~ m/^([^\(]+)((?:\([^ \)]+\))+)$/))) {
                  my $i = 0;
                  $token = $realtoken;
                  $$result{$token}{'param'} = { map { $_ => $i++ } ($params =~ m/\(([^ )]+)\)/g) };
              }
              if ($type eq '&') {
                  ($$result{$token} = $$refs{$token})
                      || die("childStruct specification invalid. '&' reference not found.");
                  die("childStruct specification invalid. '&' cannot be used on '*' nodes.")
                      if ($$result{$token}{'type'} eq '*');
                  die("childStruct specification invalid. '&' may only take a reference.")
                      if $$result{'param'};
                  return $result if (!$next || $next eq '}');
                  next;
              }
              $$result{$token}{'type'} = $type || '$';
              die("childStruct specification invalid. '*' cannot be used with '{'.")
                  if ($next eq '{' and $type eq '*');
              $$result{''}{'name'} = $token if ($type eq '*');
              $$result{$token}{'name'} = $token;
              return $result if (!$next || $next eq '}');
              ($$result{$token}{'sub'} = parseChildStructSpec($spec, { %$refs, $token => $$result{$token} })) || return undef if $next eq '{';
          }
          return $result;
      }
  }
  
  sub serializeChildStructSpec {
      my ($struct, $refs) = @_;
      my $result = '';
      my $first = 1;
      foreach my $token (keys %$struct) {
          next unless length($token);
          $result .= ' ' unless $first;
          undef $first;
          if (exists $$refs{$$struct{$token}}) {
              $result .= '&'.$token;
              next;
          }
          $result .= $$struct{$token}{'type'};
          $result .= $token;
          if (exists $$struct{$token}{'param'}) {
              my %keys = reverse %{$$struct{$token}{'param'}};
              $result .= '('.join(')(',@keys{0..(scalar(%keys)-1)}).')'
          }
          $result .= '{'.serializeChildStructSpec($$struct{$token}{'sub'},{ %$refs, $$struct{$token} => undef }).'}'
              if exists $$struct{$token}{'sub'};
      }
      return $result;
  }
  
  sub MODIFY_CODE_ATTRIBUTES {
      my ($pkg,$sub,@attr) = @_;
      my @rest;
      $handlerAttributes{$sub} ||= {};
      my $handlerAttributes = $handlerAttributes{$sub};
      foreach my $a (@attr) {
          #warn("attr: $a");
          my ($attr,$param) = ($a =~ m/([^(]*)(?:\((.*)\))?$/);
          $param = eval "q($param)";
          my @param = split(/,/,$param);
  
          if ($attr eq 'expr') {
              $$handlerAttributes{'result'} = EXPR;
          } elsif ($attr eq 'node') {
              $$handlerAttributes{'result'} = NODE;
              $$handlerAttributes{'nodename'} = $param[0] || 'value';
          } elsif ($attr eq 'exprOrNode') {
              $$handlerAttributes{'result'} = EXPRORNODE;
              $$handlerAttributes{'nodename'} = $param[0] || 'value';
              $$handlerAttributes{'resultparam'} = $param[1] || 'as';
              $$handlerAttributes{'resultnode'} = $param[2] || 'node';
          } elsif ($attr eq 'nodelist') {
              $$handlerAttributes{'result'} = NODELIST;
              $$handlerAttributes{'nodename'} = $param[0] || 'value';
          } elsif ($attr eq 'exprOrNodelist') {
              $$handlerAttributes{'result'} = EXPRORNODELIST;
              $$handlerAttributes{'nodename'} = $param[0] || 'value';
              $$handlerAttributes{'resultparam'} = $param[1] || 'as';
              $$handlerAttributes{'resultnode'} = $param[2] || 'node';
          } elsif ($attr eq 'struct') {
              $$handlerAttributes{'result'} = STRUCT;
          } elsif ($attr eq 'nodeAttr') {
              while (@param > 1) {
                  $$handlerAttributes{'resultattr'}{$param[0]} = $param[1];
                  shift @param; shift @param;
              }
          } elsif ($attr eq 'attrib') {
              foreach my $param (@param) {
                  $$handlerAttributes{'attribs'}{$param} = undef;
              }
          } elsif ($attr eq 'child') {
              foreach my $param (@param) {
                  $$handlerAttributes{'children'}{$param} = undef;
              }
          } elsif ($attr eq 'attribOrChild') {
              foreach my $param (@param) {
                  $$handlerAttributes{'attribs'}{$param} = undef;
                  $$handlerAttributes{'children'}{$param} = undef;
              }
          } elsif ($attr eq 'childStruct') {
              my $spec = $param[0];
              #warn("parsing $spec");
              $spec =~ s/\s+/ /g;
              $spec =~ s/ ?([{}]) ?/$1/g;
              $$handlerAttributes{'struct'} = parseChildStructSpec($spec,{});
              #warn("parsed $param[0], got ".serializeChildStructSpec($$handlerAttributes{'struct'}));
              die("childStruct parse error") unless $$handlerAttributes{'struct'};
          } elsif ($attr eq 'keepWhitespace') {
              $$handlerAttributes{'keepWS'} = 1;
          } elsif ($attr eq 'captureContent') {
              $$handlerAttributes{'capture'} = 1;
          } else {
              push @rest, $a;
          }
      }
      return @rest;
  }
  
  sub FETCH_CODE_ATTRIBUTES {
      my ($pkg,$sub) = @_;
      my @attr;
      my $handlerAttributes = $handlerAttributes{$sub};
      if (exists $$handlerAttributes{'result'}) {
          if ($$handlerAttributes{'result'} == NODELIST) {
              push @attr, 'nodelist'._makeAttributeQuoted($$handlerAttributes{'nodename'});
          } elsif ($$handlerAttributes{'result'} == EXPRORNODELIST) {
              push @attr, 'exprOrNodelist'._makeAttributeQuoted($$handlerAttributes{'nodename'},$$handlerAttributes{'resultparam'},$$handlerAttributes{'resultnode'});
          } elsif ($$handlerAttributes{'result'} == NODE) {
              push @attr, 'node'._makeAttributeQuoted($$handlerAttributes{'nodename'});
          } elsif ($$handlerAttributes{'result'} == EXPRORNODE) {
              push @attr, 'exprOrNode'._makeAttributeQuoted($$handlerAttributes{'nodename'},$$handlerAttributes{'resultparam'},$$handlerAttributes{'resultnode'});
          } elsif ($$handlerAttributes{'result'} == EXPR) {
              push @attr, 'expr';
          } elsif ($$handlerAttributes{'result'} == STRUCT) {
              push @attr, 'struct';
          }
      }
      push @attr, 'nodeAttr'._makeAttributeQuoted(%{$$handlerAttributes{'resultattr'}}) if $$handlerAttributes{'resultattr'};
      push @attr, 'keepWhitespace' if $$handlerAttributes{'keepWS'};
      push @attr, 'captureContent' if $$handlerAttributes{'capture'};
  
      push @attr, 'childStruct'._makeAttributeQuoted(serializeChildStructSpec($$handlerAttributes{'struct'},{}))
          if ($$handlerAttributes{'struct'});
  
      my (@attribs, @children, @both);
      foreach my $param (keys %{$$handlerAttributes{'attribs'}}) {
          if (exists $$handlerAttributes{'children'}{$param}) {
              push @both, $param;
          } else {
              push @attribs, $param;
          }
      }
      foreach my $param (keys %{$$handlerAttributes{'children'}}) {
          if (!exists $$handlerAttributes{'attribs'}{$param}) {
              push @children, $param;
          }
      }
      push @attr, 'attrib'._makeAttributeQuoted(@attribs) if @attribs;
      push @attr, 'child'._makeAttributeQuoted(@children) if @children;
      push @attr, 'attribOrChild'._makeAttributeQuoted(@both) if @both;
      return @attr;
  }
  
  sub import {
      my $pkg = caller;
      #warn("making $pkg a SimpleTaglib");
      {
          no strict 'refs';
          *{$pkg.'::Handlers::MODIFY_CODE_ATTRIBUTES'} = \&MODIFY_CODE_ATTRIBUTES;
          *{$pkg.'::Handlers::FETCH_CODE_ATTRIBUTES'} = \&FETCH_CODE_ATTRIBUTES;
          push @{$pkg.'::ISA'}, 'Apache::AxKit::Language::XSP::SimpleTaglib';
  
      }
      return undef;
  }
  
  # companions to start_expr
  
  sub start_elem {
      my ($e, $name, $attribs, $prefix, $ns) = @_;
      $name = $prefix.':'.$name if $prefix;
      $e->append_to_script('{ my $elem = $document->createElementNS('.makeSingleQuoted($ns).','.makeSingleQuoted($name).');' .
                      '$parent->appendChild($elem); $parent = $elem; }' . "\n");
      if ($attribs) {
          while (my ($key, $value) = each %$attribs) {
              start_attr($e, $key); $e->append_to_script('.'.$value); end_attr($e);
          }
      }
      $e->manage_text(0);
  }
  
  sub end_elem {
      my ($e) = @_;
      $e->append_to_script('$parent = $parent->getParentNode;'."\n");
  }
  
  sub start_attr {
      my ($e, $name, $prefix) = @_;
      $name = $prefix.':'.$name if $prefix;
      $e->append_to_script('$parent->setAttribute('.makeSingleQuoted($name).', ""');
      $e->manage_text(0);
  }
  
  sub end_attr {
      my ($e) = @_;
      $e->append_to_script(');'."\n");
  }
  
  # global variables
  # FIXME - put into $e (are we allowed to?)
  
  my %structStack = ();
  my %frame = ();
  my @globalframe = ();
  my $structStack;
  
  # generic tag handler subs
  
  sub set_attribOrChild_value__open {
      my ($e, $tag) = @_;
      $globalframe[0]{'capture'} = 1;
      return '$attr_'.makeVariableName($tag).' = ""';
  }
  
  sub set_attribOrChild_value : keepWhitespace {
      return '; ';
  }
  
  sub set_childStruct_value__open {
      my ($e, $tag, %attribs) = @_;
      my $var = '$_{'.makeSingleQuoted($tag).'}';
      if ($$structStack[0][0]{'param'} && exists $$structStack[0][0]{'param'}{$tag}) {
          $e->append_to_script('.do { $param_'.$$structStack[0][0]{'param'}{$tag}.' = ""');
          $globalframe[0]{'capture'} = 1;
          return '';
      }
      my $desc = $$structStack[0][0]{'sub'}{$tag};
      unshift @{$$structStack[0]},$desc;
      if ($$desc{'param'}) {
          $e->append_to_script("{ \n");
          foreach my $key (keys %{$$desc{'param'}}) {
              $_ = $$desc{'param'}{$key};
              $e->append_to_script("my \$param_$_; ");
              $e->append_to_script("\$param_$_ = ".makeSingleQuoted($attribs{$key}).'; ')
                  if exists $attribs{$key};
          }
          $e->append_to_script('local ($_) = ""; ');
          $var = '$_';
      }
      if ($$desc{'type'} eq '@') {
          $e->append_to_script("$var ||= []; push \@{$var}, ");
      } else {
          $e->append_to_script("$var = ");
      }
      if ($$desc{'sub'}) {
          $e->append_to_script('do {');
          $e->append_to_script('local (%_) = (); ');
          foreach my $attrib (keys %attribs) {
              next if $$desc{'sub'}{$attrib}{'type'} eq '%';
              $e->append_to_script('$_{'.makeSingleQuoted($attrib).'} = ');
              $e->append_to_script('[ ') if $$desc{'sub'}{$attrib}{'type'} eq '@';
              $e->append_to_script(makeSingleQuoted($attribs{$attrib}));
              $e->append_to_script(' ]') if $$desc{'sub'}{$attrib}{'type'} eq '@';
              $e->append_to_script('; ');
          }
          my $textname = $$desc{'sub'}{''}{'name'};
          if ($textname) {
              $e->append_to_script(' $_{'.makeSingleQuoted($textname).'} = ""');
              $globalframe[0]{'capture'} = 1;
          }
      } else {
          $e->append_to_script('""');
          $globalframe[0]{'capture'} = 1;
      }
      return '';
  }
  
  sub set_childStruct_value {
      my ($e, $tag) = @_;
      if ($$structStack[0][0]{'param'} && exists $$structStack[0][0]{'param'}{$tag}) {
          $e->append_to_script('; }');
          return '';
      }
      my $desc = $$structStack[0][0];
      shift @{$$structStack[0]};
      if ($$desc{'sub'}) {
          $e->append_to_script(' \%_; }; ');
      }
      if ($$desc{'param'}) {
          my $var = '$_{'.makeSingleQuoted($tag).'}';
          for (0..(scalar(%{$$desc{'param'}})-1)) {
              $var .= "{\$param_$_}";
          }
          if ($$desc{'type'} eq '@') {
              $e->append_to_script("$var ||= []; push \@{$var}, \@{\$_};");
          } else {
              $e->append_to_script("$var = \$_;");
          }
          $e->append_to_script(" }\n");
      }
      return '';
  }
  
  # code called from compiled XSP scripts
  
  sub xmlize {
      my ($document, $parent, $prefix, $ns, @data) = @_;
      foreach my $data (@data) {
          die 'data is not a hash ref!' unless ref($data) eq 'HASH';
          while (my ($key, $val) = each %$data) {
              if (substr($key,0,1) eq '@') {
                  $key = substr($key,1);
                  die 'attribute value is not a simple scalar!' if ref($val);
                  #$key = $prefix.':'.$key if $prefix;
                  $parent->setAttribute($key,$val);
                  next;
              }
  
              $key = $prefix.':'.$key if $prefix && length($key);
              my @data = ref($val) eq 'ARRAY'? @$val:$val;
              foreach my $data (@data) {
                  my $elem;
                  if (length($key)) {
                      $elem = $document->createElementNS($ns,$key);
                  } else {
                      $elem = $parent;
                  }
                  #$elem->setAttribute("xmlns:$prefix", $ns) if ($ns);
                  $parent->appendChild($elem);
                  if (ref($data)) {
                      xmlize($document, $elem, $prefix, $ns, $data);
                  } else {
                      my $tn = $document->createTextNode($data);
                      $elem->appendChild($tn);
                  }
              }
          }
      }
  }
  
  # event handlers
  
  sub characters {
      my ($e, $node) = @_;
      my $text = $node->{'Data'};
      if ($globalframe[0]{'ignoreWS'}) {
          $text =~ s/^\s*//;
          $text =~ s/\s*$//;
      }
      return '' if $text eq '';
      return '.'.makeSingleQuoted($text);
  }
  
  sub start_element
  {
      my ($e, $element) = @_;
      my %attribs = map { $_->{'Name'} => $_->{'Value'} } @{$element->{'Attributes'}};
      my $tag = $element->{'Name'};
      #warn("Element: ".join(",",map { "$_ => ".$$element{$_} } keys %$element));
      my $ns = $element->{'NamespaceURI'};
      my $frame = ($frame{$ns} ||= []);
      $structStack = ($structStack{$ns} ||= []);
      my $pkg = $Apache::AxKit::Language::XSP::tag_lib{$ns}."::Handlers";
      my ($sub, $subOpen);
      my $attribs = {};
      #warn("full struct: ".serializeChildStructSpec($$structStack[0][$#{$$structStack[0]}]{'sub'})) if $$structStack[0];
      #warn("current node: ".$$structStack[0][0]{'name'}) if $$structStack[0];
      #warn("rest struct: ".serializeChildStructSpec($$structStack[0][0]{'sub'})) if $$structStack[0];
      if ($$structStack[0][0]{'param'} && exists $$structStack[0][0]{'param'}{$tag}) {
          $sub = \&set_childStruct_value;
          $subOpen = \&set_childStruct_value__open;
      } elsif ($$structStack[0][0]{'sub'} && exists $$structStack[0][0]{'sub'}{$tag}) {
          if ($$structStack[0][0]{'sub'}{$tag}{'sub'}) {
              foreach my $key (keys %{$$structStack[0][0]{'sub'}{$tag}{'sub'}}) {
                  $$attribs{$key} = $attribs{$key} if exists $attribs{$key};
              }
          }
          if ($$structStack[0][0]{'sub'}{$tag}{'param'}) {
              foreach my $key (keys %{$$structStack[0][0]{'sub'}{$tag}{'param'}}) {
                  $$attribs{$key} = $attribs{$key} if exists $attribs{$key};
              }
          }
          $sub = \&set_childStruct_value;
          $subOpen = \&set_childStruct_value__open;
      } else {
          for my $i (0..$#{$frame}) {
              if (exists $$frame[$i]{'vars'}{$tag}) {
                  #warn("variable: $tag");
                  $sub = \&set_attribOrChild_value;
                  $subOpen = \&set_attribOrChild_value__open;
                  last;
              }
          }
          if (!$sub) {
              my @backframes = (reverse(map{ ${$_}{'name'} } @{$frame}),$tag);
              #warn("frames: ".@$frame.", backframes: ".join(",",@backframes));
              while (@backframes) {
                  my $longtag = join('___', @backframes);
                  shift @backframes;
                  #warn("checking for $longtag");
                  if ($sub = $pkg->can(makeVariableName($longtag))) {
                      $subOpen = $pkg->can(makeVariableName($longtag)."__open");
                      last;
                  }
              }
          }
      }
      die "invalid tag: $tag (namespace: $ns, package $pkg, parents ".join(", ",map{ ${$_}{'name'} } @{$frame}).")" unless $sub;
  
      my $handlerAttributes = $handlerAttributes{$sub};
  
      if ($$handlerAttributes{'result'} == STRUCT || !$$handlerAttributes{'result'} ||
          $$handlerAttributes{'result'} == NODELIST ||
          ($$handlerAttributes{'result'} == EXPRORNODELIST &&
           $attribs{$$handlerAttributes{'resultparam'}} eq
           $$handlerAttributes{'resultnode'})) {
  
          # FIXME: this can give problems with non-SimpleTaglib-taglib interaction
          # it must autodetect whether to use '.do' or not like xsp:expr, but as
  		# that one doesn't work reliably neither, it probably doesn't make any
          # difference
          $e->append_to_script('.') if ($globalframe[0]{'capture'});
          $e->append_to_script('do { ');
  
      } elsif ($$handlerAttributes{'result'} == NODE ||
          ($$handlerAttributes{'result'} == EXPRORNODE
          && $attribs{$$handlerAttributes{'resultparam'}} eq
          $$handlerAttributes{'resultnode'})) {
  
          $e->append_to_script('.') if ($globalframe[0]{'capture'});
          $e->append_to_script('do { ');
          start_elem($e,$$handlerAttributes{'nodename'},{ 'xmlns:'.$element->{'Prefix'} => makeSingleQuoted($ns) },$element->{'Prefix'},$ns);
          $e->start_expr($tag);
      } else {
          $e->append_to_script('.') if ($globalframe[0]{'capture'});
          $e->start_expr($tag);
      }
  
      foreach my $attrib (keys %{$$handlerAttributes{'attribs'}}) {
          $$attribs{$attrib} = $attribs{$attrib}
              unless exists $$handlerAttributes{'children'}{$attrib};
      }
      $$attribs{$$handlerAttributes{'resultparam'}} = $attribs{$$handlerAttributes{'resultparam'}}
          if $$handlerAttributes{'resultparam'};
  
      unshift @{$frame}, {};
      unshift @globalframe,{};
      $$frame[0]{'attribs'} = $attribs;
      $globalframe[0]{'ignoreWS'} = !$$handlerAttributes{'keepWS'};
      $globalframe[0]{'capture'} = $$handlerAttributes{'capture'};
      $globalframe[0]{'pkg'} = $pkg;
      $globalframe[0]{'ns'} = $pkg;
      $$frame[0]{'name'} = $tag;
      $$frame[0]{'sub'} = $sub;
      if ($$handlerAttributes{'struct'}) {
          unshift @{$structStack}, [{ 'sub' => $$handlerAttributes{'struct'}, 'name' => $tag }];
          $$frame[0]{'struct'} = 1;
          $e->append_to_script('local(%_) = (); ');
      }
  
      $e->append_to_script('my ($attr_'.join(', $attr_',map { makeVariableName($_) } keys %{$$handlerAttributes{'children'}}).'); ')
          if $$handlerAttributes{'children'} && %{$$handlerAttributes{'children'}};
      foreach my $var (keys %{$$handlerAttributes{'children'}}) {
          next unless exists $attribs{$var};
          $e->append_to_script('$attr_'.makeVariableName($var).' = '.makeSingleQuoted($attribs{$var}).'; ');
      }
      $$frame[0]{'vars'} = $$handlerAttributes{'children'};
  
      $e->append_to_script($subOpen->($e,$tag,%$attribs)) if $subOpen;
  
      if ($$handlerAttributes{'capture'}) {
          $e->append_to_script('local($_) = ""');
          $e->{'Current_Element'}->{'SimpleTaglib_SavedNS'} = $e->{'Current_Element'}->{'NamespaceURI'};
          $e->{'Current_Element'}->{'NamespaceURI'} = $ns;
      }
  
      return '';
  }
  
  sub end_element {
      my ($e, $element) = @_;
  
      my $tag = $element->{'Name'};
      my $ns = $element->{'NamespaceURI'};
      my $frame = $frame{$ns};
      $structStack = $structStack{$ns};
      my $pkg = $Apache::AxKit::Language::XSP::tag_lib{$ns}."::Handlers";
      my $longtag;
      my $sub = $$frame[0]{'sub'};
      die "invalid closing tag: $tag (namespace: $ns, package $pkg, sub ".makeVariableName($tag).")" unless $sub;
      my $handlerAttributes = $handlerAttributes{$sub};
  
      if ($globalframe[0]{'capture'}) {
          $e->append_to_script('; ');
      }
  
      if ($$handlerAttributes{'result'}) {
          $e->append_to_script(' my @_res = do {');
      }
  
      my $attribs = $$frame[0]{'attribs'};
      shift @{$structStack} if $$frame[0]{'struct'};
      shift @{$frame};
      shift @globalframe;
      $e->append_to_script($sub->($e, $tag, %{$attribs}));
  
      if (defined $e->{'Current_Element'}->{'SimpleTaglib_SavedNS'}) {
          $e->{'Current_Element'}->{'NamespaceURI'} = $e->{'Current_Element'}->{'SimpleTaglib_SavedNS'};
          delete $e->{'Current_Element'}->{'SimpleTaglib_SavedNS'};
      }
  
      if ($$handlerAttributes{'result'} == NODELIST ||
          ($$handlerAttributes{'result'} == EXPRORNODELIST
           && $$attribs{$$handlerAttributes{'resultparam'}} eq
           $$handlerAttributes{'resultnode'})) {
  
          $e->append_to_script('}; foreach my $_res (@_res) {');
          start_elem($e,$$handlerAttributes{'nodename'},{ %{$$handlerAttributes{'resultattr'}||{}}, 'xmlns:'.$element->{'Prefix'} => makeSingleQuoted($ns) }, $element->{'Prefix'},$ns);
          $e->start_expr($$handlerAttributes{'nodename'});
          $e->append_to_script('$_res');
          $e->end_expr();
          end_elem($e);
          $e->append_to_script("} ");
          $e->append_to_script('""; ') if ($globalframe[0]{'capture'});
          $e->append_to_script("};\n");
      } elsif ($$handlerAttributes{'result'} == NODE ||
          ($$handlerAttributes{'result'} == EXPRORNODE
           && $$attribs{$$handlerAttributes{'resultparam'}} eq
           $$handlerAttributes{'resultnode'})) {
  
          $e->append_to_script('}; ');
          while (my ($key, $value) = each %{$$handlerAttributes{'resultattr'}}) {
              start_attr($e, $key); $e->append_to_script('.'.$value); end_attr($e);
          }
          $e->append_to_script('join("",@_res);');
          $e->end_expr($tag);
          end_elem($e);
          if ($globalframe[0]{'capture'}) {
              $e->append_to_script("\"\"; }\n");
          } else {
              $e->append_to_script(" };\n");
          }
      } elsif ($$handlerAttributes{'result'} == STRUCT) {
          $e->append_to_script('}; ');
          if (Apache::AxKit::Language::XSP::is_xsp_namespace($element->{'Parent'}->{'NamespaceURI'})) {
              if (!$e->manage_text() || $element->{'Parent'}->{'Name'} =~ /^(.*:)?content$/) {
                  $e->append_to_script('Apache::AxKit::Language::XSP::SimpleTaglib::xmlize($document,$parent,'.makeSingleQuoted($element->{'Prefix'}).','.makeSingleQuoted($ns).',@_res); ');
              } else {
                  $e->append_to_script('eval{if (wantarray) { @_res; } else { join("",@_res); }}');
              }
          } else {
              $e->append_to_script('Apache::AxKit::Language::XSP::SimpleTaglib::xmlize($document,$parent,'.makeSingleQuoted($element->{'Prefix'}).','.makeSingleQuoted($ns).',@_res); ');
          }
          if ($globalframe[0]{'capture'}) {
              $e->append_to_script("\"\"; }\n");
          } else {
              $e->append_to_script(" };\n");
          }
      } elsif ($$handlerAttributes{'result'}) {
          $e->append_to_script('}; eval{if (wantarray) { @_res; } else { join("",@_res); }} ');
          $e->end_expr();
      } else {
          if ($globalframe[0]{'capture'}) {
              $e->append_to_script("\"\"; }\n");
          } else {
              $e->append_to_script(" };\n");
          }
      }
      #warn('script len: '.length($e->{XSP_Script}).', end tag: '.$tag);
      return '';
  }
  
  1;
  
  __END__
  
  =head1 NAME
  
  Apache::AxKit::XSP::Language::SimpleTaglib - alternate XSP taglib helper
  
  =head1 SYNOPSIS
  
      package Your::XSP::Package;
      use Apache::AxKit::Language::XSP::SimpleTaglib;
  
      ... more initialization stuff, start_document handler, utility functions, whatever
  	you like, but no parse_start/end handler needed - if in doubt, just leave empty ...
  
      package Your::XSP::Package::Handlers;
  
      sub some_tag : attrib(id) attribOrChild(some-param) node(result) keepWhitespace {
          my ($e, $tag, %attr) = @_;
          return 'do_something($attr_some_param,'.$attr{'id'}.');';
      }
  
  
  =head1 DESCRIPTION
  
  This taglib helper allows you to easily write tag handlers with most of the common
  behaviours needed. It manages all 'Design Patterns' from the XSP man page plus
  several other useful tag styles.
  
  =head2 Simple handler subs
  
  A tag "<yourNS:foo>" will trigger a call to sub "foo" during the closing tag event.
  What happens in between can be configured in many ways
  using function attributes. In the rare cases where some action has to happen during
  the opening tag event, you may provide a sub "foo__open" (double underscore)
  which will be called at the appropriate time. Usually you would only do that for 'if'-
  style tags which enclose some block of code.
  
  =head2 Context sensitive handler subs
  
  A sub named "foo___bar" (triple underscore) gets called on the following XML input:
  "<yourNS:foo><yourNS:bar/></yourNS:foo>". Handler subs may have any nesting depth.
  The rule for opening tag handlers applies here as well. The sub name must represent the
  exact tag hierarchy (within your namespace).
  
  =head2 Names, parameters, return values
  
  Names for subs and variables get created by replacing any non-alphanumeric character in the
  original tag or attribute to underscores. For example, 'get-id' becomes 'get_id'.
  
  The called subs get passed 3 parameters: The parser object, the tag name, and an attribute
  hash. This hash only contains XML attributes declared using the 'attrib()' function
  attribute. (Try not to confuse these two meanings of 'attribute' - unfortunately XML and
  Perl both call them that way.) All other declared parameters get converted into local
  variables with prefix 'attr_'.
  
  If a sub has any result attribute ('node', 'expr', etc.), it gets called in list context. If
  neccessary, returned lists get converted to scalars by joining them without separation. Plain
  subs (without result attribute) inherit their context and have their return value left unmodified.
  
  =head2 Precedence
  
  If more than one handler matches a tag, the following rules determine which one is chosen.
  Remember, though, that only tags in your namespace are considered.
  
  =over 4
  
  =item 1. If the innermost tag has a 'childStruct' spec which matches, the internal childStruct
  handler takes precedence.
  
  =item 2. Otherwise, if any surrounding tag has a matching 'child' or 'attribOrChild'
  attribute, the internal handler for the innermost matching tag gets chosen.
  
  =item 3. Otherwise, the handler sub with the deepest tag hierarchy gets called.
  
  =back
  
  =head2 Utility functions
  
  Apache::AxKit::Language::XSP contains a few handy utility subs:
  
  =over 4
  
  =item * start_elem, end_elem, start_attr, end_attr - these create elements and attributes
  in the output document. Call them just like you call start_expr and end_expr.
  
  =item * makeSingleQuoted - given a scalar as input, it returns a scalar which yields
  the exact input value when evaluated; handy when using unknown text as-is in return values.
  
  =item * makeVariableName - creates a valid, readable perl identifier from arbitrary input text.
  The return values might overlap.
  
  =back
  
  =head1 Available attributes
  
  Parameters to attributes get handled as if 'q()' enclosed them. Commas separate arguments, so
  values cannot contain commas.
  
  =head2 Result attributes
  
  Choose none or one of these to select output behaviour.
  
  =head3 C<expr>
  
  Makes this tag behave like an '<xsp:expr>' tag, creating text nodes or inline text as appropriate.
  Choose this if you create plain text which may be used everywhere, including inside code. This
  attribute has no parameters.
  
  =head3 C<node(name)>
  
  Makes this tag create an XML node named C<name>. The tag encloses all content as well as the
  results of the handler sub.
  Choose this if you want to create one XML node with all your output.
  
  =head3 C<nodelist(name)>
  
  Makes this tag create a list of XML nodes named C<name>. The tag(s) do not enclose content nodes,
  which become preceding siblings of the generated nodes. The return value gets converted to a
  node list by enclosing each element with an XML node named C<name>.
  Choose this if you want to create a list of uniform XML nodes with all your output.
  
  =head3 C<exprOrNode(name,attrname,attrvalue)>
  
  Makes this tag behave described under either 'node()' or 'expr', depending on the value of
  XML attribute C<attrname>. If that value matches C<attrvalue>, it will work like 'node()',
  otherwise it will work like 'expr'. C<attrname> defaults to 'as', C<attrvalue> defaults to
  'node', thus leaving out both parameters means that 'as="node"' will select 'node()' behaviour.
  Choose this if you want to let the XSP author decide what to generate.
  
  =head3 C<exprOrNodelist(name,attrname,attrvalue)>
  
  Like exprOrNode, selecting between 'expr' and 'nodelist()' behaviour.
  
  =head3 C<struct>
  
  Makes this tag create a more complex XML fragment. You may return a single hashref or an array
  of hashrefs, which get converted into an XML structure. Each hash element may contain a scalar,
  which gets converted into an XML tag with the key as name and the value as content. Alternatively,
  an element may contain an arrayref, which means that an XML tag encloses each single array element.
  Finally, you may use hashrefs in place of scalars to create substructures. To create attributes on
  tags, use a hashref that contain the attribute names prefixed by '@'. A '' (empty
  string) as key denotes the text contents of that node.
  
  In an expression context, passes on the unmodified return value.
  
  =head2 Other output attributes
  
  These may appear more than once and modify output behaviour.
  
  =head3 C<nodeAttr(name,expr,...)>
  
  Adds an XML attribute named C<name> to all generated nodes. C<expr> gets evaluated at run time.
  Evaluation happens once for each generated node. Of course, this tag only makes sense with
  'node()' type handlers.
  
  =head2 Input attributes
  
  These tags specify how input gets handled. Most may appear more than once, if that makes sense.
  
  =head3 C<attrib(name,...)>
  
  Declares C<name> as a (non-mandatory) XML attribute. All attributes declared this way get
  passed to the handler subs in the attribute hash.
  
  =head3 C<child(name,...)>
  
  Declares a child tag C<name>. It always lies within the same namespace as the taglib itself. The
  contents of the tag, if any, get saved in a local variable named $attr_C<name>. If the child tag
  appears more than once, the last value overrides any previous value.
  
  =head3 C<attribOrChild(name,...)>
  
  Declares an attribute or child tag named C<name>. A variable is created just like for 'child()',
  containing the attribute or child tag contents. If both appear, the contents of the child tag take
  precedence.
  
  =head3 C<keepWhitespace>
  
  Makes this tag preserve contained whitespace.
  
  =head3 C<captureContent>
  
  Makes this tag store the enclosed content in '$_' for later retrieval in the handler sub, instead
  of adding it to the enclosing element. Non-text nodes will not work as expected.
  
  =head3 C<childStruct(spec)>
  
  Marks this tag to take a complex xml fragment as input. The resulting data structure is available
  as %_ in the sub. Whitespace is always preserved.
  
  C<spec> has the following syntax:
  
  =over 4
  
  =item 1. A C<spec> consists of a list of tag names, separated by whitespace.
  
  =item 2. Tags may appear in any order.
  
  =item 3. A tag name prefixed by '@' may appear more than once in the xml document. A tag
  name prefixed by '$' or without any prefix may only appear once.
  
  =item 4. If a '{' follows a tag name, that tag has child tags. A valid C<spec> and a
  closing '}' must follow.
  
  =item 5. A tag name prefixed by '*' does not indicate an input tag but specifies the name
  for the text contents of the surrounding tag in the resulting data structure. Such a tag name may
  not bear a '{...}' block.
  
  =item 6. Any tag without child tags may also appear as attribute of the parent tag.
  
  =item 7. A tag name folloewd by one or more parameter specs in parentheses means a hash
  gets created with the value of the corresponding attribute (or child tag) as key. This usage does
  not forbid appending a '{...}' block, which would result in a nested hash.
  
  =item 8. A tag name prefixed by '&' denotes a recursive structure. The tag name must appear
  as the name of one of the surrounding '{...}'-blocks. The innermost matching block gets chosen.
  
  =back
  
  Example:
  
  sub:
  
      set_permission : childStruct(add{@permission{$type *name} $target $comment(lang)(day)} remove{@permission{$type *name} $target})
  
  XML:
  
      <set-permission>
          <add>
              <permission type="user">
                  foo
              </permission>
              <permission>
                  <type>group</type>
                  bar
              </permission>
              <target>/test.html</target>
              <comment lang="en" day="Sun">Test entry</comment>
              <comment lang="en" day="Wed">Test entry 2</comment>
              <comment><lang>de</lang>Testeintrag</comment>
          </add>
          <remove target="/test2.html">
              <permission type="user">
                  baz
              </permission>
          </remove>
      </set-permission>
  
  Result: a call to set_permission with %_ set like this:
  
      %_ = (
          add => {
              permission => [
                  { type => "user", name => 'foo' },
                  { type => "group", name => 'bar' },
              ],
              target => '/test.html',
              comment => {
                  'en' => { 'Sun' => 'Test entry', 'Wed' => 'Test entry 2' },
                  'de' => { '' => 'Testeintrag' },
              }
          },
          remove => {
              permission => [
                  { type => "user", name => 'baz' },
              ],
              target => '/test2.html',
          },
      );
  
  
  =head1 EXAMPLE
  
  See AxKit::XSP::Sessions and AxKit::XSP::Auth source code for full-featured examples.
  
  =head1 BUGS
  
  Because of the use of perl attributes, SimpleTaglib will only work with Perl 5.6.0 or later.
  This software is already tested quite well and works for a number of simple and complex
  taglibs. Still, you may have to experiment with the attribute declarations, as the differences
  can be quite subtle but decide between 'it works' and 'it doesn't'. XSP can be quite fragile if
  you start using heavy trickery.
  
  If some tags don't work as expected, try surrounding the offending tag with
  <xsp:content>, this is a common gotcha (but correct and intended). If you find yourself needing
  <xsp:expr> around a tag, please contact the author, as that is probably a bug.
  
  =head1 AUTHOR
  
  Jörg Walter <jwalt@cpan.org>
  
  =head1 COPYRIGHT
  
  Copyright (c) 2002 Jörg Walter. Documentation
  All rights reserved. This program is free software; you can redistribute it and/or
  modify it under the same terms as AxKit itself.
  
  =head1 SEE ALSO
  
  AxKit, Apache::AxKit::Language::XSP, Apache::AxKit::Language::XSP::TaglibHelper
  
  =cut
  
  
  

Mime
View raw message