Apache2-SSI

 view release on metacpan or  search on metacpan

lib/Apache2/SSI.pm  view on Meta::CPAN


sub lookup_file
{
    my $self = shift( @_ );
    my $file = shift( @_ ) || return( $self->error( "No file provided to look up." ) );
    my $r = $self->apache_request;
    my $f = Apache2::SSI::File->new(
        $file,
        ( $r ? ( apache_request => $r ) : () ),
        base_file => $self->uri->filename,
        debug => $self->debug
    ) || return( $self->error( "Unable to instantiate an Apache2::SSI::File object: ", Apache2::SSI::File->error ) );
    if( $f->code == 404 )
    {
        # Mimic the Apache error when the file does not exist
        $self->error( "unable to lookup information about \"$file\" in parsed file \"", $self->uri, "\"." );
    }
    return( $f );
}

sub lookup_uri
{
    my $self = shift( @_ );
    my $uri  = shift( @_ );
    my $r = $self->apache_request;
    my $u = Apache2::SSI::URI->new(
        ( $r ? ( apache_request => $r ) : () ),
        base_uri => $self->uri,
        document_uri => $uri,
        document_root => ( $r ? $r->document_root : $self->document_root ),
        debug => $self->debug
    ) || return( $self->error( "Unable to instantiate an Apache2::SSI::URI object: ", Apache2::SSI::URI->error ) );
    if( $u->code == 404 )
    {
        # Mimic the Apache error when the file does not exist
        $self->error( "unable to get information about uri \"$uri\" in parsed file ", $self->uri );
    }
    return( $u );
}

sub mod_perl { return( shift->_set_get_boolean( 'mod_perl', @_ ) ); }

sub new_uri
{
    my $self = shift( @_ );
    my $uri  = shift( @_ );
    return( $self->error( "No uri provided to create an Apache2::SSI::URI object." ) ) if( !defined( $uri ) || !length( $uri ) );
    my $p =
    {
        document_uri => $uri,
        document_root => $self->document_root,
        base_uri => $self->uri,
        debug => $self->debug,
    };
    $p->{apache_request} = $self->apache_request if( $self->apache_request );
    my $o = Apache2::SSI::URI->new( $p ) ||
        return( $self->error( "Unable to create an Apache2::SSI::URI: ", Apache2::SSI::URI->error ) );
    return( $o );
}

# This makes use of Apache2::SSI::Notes which guarantees that notes are shared in and out of Apache framework
# Notes are cleaned up at server shutdown with an handler set in startup.pl
# See scripts/startup.pl and conf/extra.conf.in as an example
sub notes
{
    my $self = shift( @_ );
    my $notes = $self->{notes};
    my $r = $self->apache_request;
    unless( scalar( @_ ) )
    {
        if( $r )
        {
            return( $r->pnotes );
        }
        elsif( $notes )
        {
            return( $notes->get );
        }
        # We just return an empty hash to avoid error
        else
        {
            return( {} );
        }
    }
    my $var  = shift( @_ );
    my $new;
    my $new_value_set = 0;
    if( @_ )
    {
        $new = shift( @_ );
        $new_value_set++;
        if( $notes )
        {
            $notes->set( $var => $new );
        }
    }
    
    if( $r )
    {
        local $@;
        # try-catch
        my $rv = eval
        {
            $r->pnotes( $var => $new ) if( $new_value_set );
            my $val = $r->pnotes( $var );
            $val //= $notes->get( $var ) if( $notes );
            return( $val );
        };
        if( $@ )
        {
            return( $self->error( "An error occurred trying to ", (defined( $new ) ? 'set/' : ''), " get the note value for variable \"${var}\"", (defined( $new ) ? " with value '${new}" : ''), ": $@" ) );
        }
        return( $rv );
    }
    return( $notes->get( $var ) ) if( $notes );
    return( '' );
}

sub parse
{
    my $self = shift( @_ );

lib/Apache2/SSI.pm  view on Meta::CPAN

        $ssi->throw;
    };
    print( $result );

Inside Apache, in the VirtualHost configuration, for example:

    PerlModule Apache2::SSI
    PerlOptions +GlobalRequest
    PerlSetupEnv On
    <Directory "/home/joe/www">
        Options All +Includes +ExecCGI -Indexes -MultiViews
        AllowOverride All
        SetHandler modperl
        # You can choose to set this as a response handler or a output filter, whichever works.
        # PerlResponseHandler Apache2::SSI
        PerlOutputFilterHandler Apache2::SSI
        # If you do not set this to On, path info will not work, example:
        # /path/to/file.html/path/info
        # See: <https://httpd.apache.org/docs/current/en/mod/core.html#acceptpathinfo>
        AcceptPathInfo On
        # To enable no-caching (see no_cache() in Apache2::RequestUtil:
        PerlSetVar Apache2_SSI_NO_CACHE On
        # This is required for exec cgi to work:
        # <https://httpd.apache.org/docs/current/en/mod/mod_include.html#element.exec>
        <Files ~ "\.pl$">
            SetHandler perl-script
            AcceptPathInfo On
            PerlResponseHandler ModPerl::PerlRun
            # Even better for stable cgi scripts:
            # PerlResponseHandler ModPerl::Registry
            # Change this in mod_perl1 PerlSendHeader On to the following:
            # <https://perl.apache.org/docs/2.0/user/porting/compat.html#C_PerlSendHeader_>
            PerlOptions +ParseHeaders
        </Files>
        <Files ~ "\.cgi$">
            SetHandler cgi-script
            AcceptPathInfo On
        </Files>
        # To enable debugging output in the Apache error log
        # PerlSetVar Apache2_SSI_DEBUG 3
        # To set the default echo message
        # PerlSetVar Apache2_SSI_Echomsg 
        # To Set the default error message
        # PerlSetVar Apache2_SSI_Errmsg "Oops, something went wrong"
        # To Set the default size format: bytes or abbrev
        # PerlSetVar Apache2_SSI_Sizefmt "bytes"
        # To Set the default date time format
        # PerlSetVar Apache2_SSI_Timefmt ""
        # To enable legacy mode:
        # PerlSetVar Apache2_SSI_Expression "legacy"
        # To enable trunk mode:
        # PerlSetVar Apache2_SSI_Expression "trunk"
    </Directory>

=head1 VERSION

    v0.2.0

=head1 DESCRIPTION

L<Apache2::SSI> implements L<Apache Server Side Include|https://httpd.apache.org/docs/current/en/howto/ssi.html>, a.k.a. SSI, within and outside of Apache2/mod_perl2 framework.

L<Apache2::SSI> is inspired from the original work of L<Apache::SSI> with the main difference that L<Apache2::SSI> works well when called from within Apache mod_perl2 as well as when called outside of Apache if you want to simulate L<SSI|https://http...

L<Apache2::SSI> also implements all of Apache SSI features, including functions, encoding and decoding and old style variables such as C<${QUERY_STRING}> as well as modern style such as C<v('QUERY_STRING')> and variants such as C<%{REQUEST_URI}>.

See below details in this documentation and in the section on L</"SSI Directives">

Under Apache mod_perl, you would implement it like this in your C<apache2.conf> or C<httpd.conf>

    <Files *.phtml>
        SetHandler modperl
        PerlOutputFilterHandler Apache2::SSI
    </Files>

This would enable L<Apache2::SSI> for files whose extension is C<.phtml>. You can also limit this by location, such as:

    <Location /some/web/path>
        <Files *.html>
            SetHandler modperl
            PerlOutputFilterHandler Apache2::SSI
        </Files>
    </Location>

In the example above, we enable it in files with extensions C<.phtml>, but you can, of course, enable it for all html by setting extension C<.html> or whatever extension you use for your html files.

As pointed out by Ken Williams, the original author of L<Apache::SSI>, the benefit for using L<Apache2::SSI> is:

=over 4

=item 1. You want to subclass L<Apache2::SSI> and have granular control on how to render ssi

=item 2. You want to "parse the output of other mod_perl handlers, or send the SSI output through another handler"

=item 3. You want to imitate SSI without activating them or without using Apache (such as in command line) or within your perl/cgi script

=back

=head2 INSTALLATION

    perl Makefile.PL
    make
    make test
    sudo make install

This will detect if you have Apache installed and run the Apache mod_perl2 tests by starting a separate instance of Apache on a non-standard port like 8123 under your username just for the purpose of testing. This is all handled automatically by L<Ap...

If you do not have Apache or mod_perl installed, it will still install, but obviously not start an instance of Apache/mod_perl, nor perform any of the Apache mod_perl tests.

It tries hard to find the Apache configuration file. You can help it by providing command line modifiers, such as:

    perl Makefile.PL -apxs /usr/bin/apxs

or, even specify the Apache configuration file:

    perl Makefile.PL -apxs /usr/bin/apxs -httpd_conf /home/john/etc/apache2/apache2.conf

To run only some tests, for example:

    make test TEST_FILES="./t/31.file.t"

lib/Apache2/SSI.pm  view on Meta::CPAN

Lookup operating system environment variable

    <!--#if expr="env('LANG') =~ /en(_(GB|US))/" -->
    Showing English language
    <!--#endif -->

=head2 parse_func_replace

replace(string, "from", "to") replaces all occurrences of "from" in the string with "to".

Example:

    <!--#if expr="replace( 'John is in Tokyo', 'John', 'Jack' ) == 'Jack is in Tokyo'" -->
    This worked!
    <!--#else -->
    Nope, it failed.
    <!--#endif -->

=head2 parse_func_req

See L</parse_func_http>

=head2 parse_func_reqenv

Lookup request environment variable (as a shortcut, v can also be used to access variables).

This is only different from L</parse_func_env> under Apache.

See L</parse_func_env>

Example:

    <!--#if expr="reqenv('ProcessId') == '$$'" -->
    This worked!
    <!--#else -->
    Nope, it failed.
    <!--#endif -->

Or using the Apache SSI C<v> shortcut:

    <!--#if expr="v('ProcessId') == '$$'" -->

=head2 parse_func_req_novary

Same as L</parse_func_req>, but header names will not be added to the Vary header.

=head2 parse_func_resp

Get HTTP response header.

Example:

    <!--#if expr="resp('X-ProcessId') == '$$'" -->
    This worked!
    <!--#else -->
    Nope, it failed.
    <!--#endif -->

An important note here:

First, there is obviously no response header available for perl scripts running outside of Apache2/mod_perl2 framework.

If the script runs under mod_perl, not all response header will be available depending on whether you are using L<Apache2::SSI> in your Apache configuration as an output filter handler (C<PerlOutputFilterHandler>) or a response handler (C<PerlRespons...

If it is running as an output filter handler, then some headers, such as C<Content-Type> will not be available, unless they have been set by a script in a previous phase. Only basic headers will be available. For more information, check the Apache/mo...

=head2 parse_func_sha1

Hash the string using SHA1, then encode the hash with hexadecimal encoding.

Example:

    <!--#if expr="sha1('Tous les êtres humains naissent libres et égaux en dignité et en droits.') == '8c244078c64a51e8924ecf646df968094a818d59'" -->
    This worked!
    <!--#else -->
    Nope, it failed.
    <!--#endif -->

=head2 parse_func_tolower

Convert string to lower case.

Example:

    <!--#if expr="tolower('Tous les êtres humains naissent libres et égaux en dignité et en droits.') == 'tous les êtres humains naissent libres et égaux en dignité et en droits.'" -->
    This worked!
    <!--#else -->
    Nope, it failed.
    <!--#endif -->

=head2 parse_func_toupper

Convert string to upper case.

Example:

    <!--#if expr="toupper('Tous les êtres humains naissent libres et égaux en dignité et en droits.') == 'TOUS LES ÊTRES HUMAINS NAISSENT LIBRES ET ÉGAUX EN DIGNITÉ ET EN DROITS.'" -->
    This worked!
    <!--#else -->
    Nope, it failed.
    <!--#endif -->

=head2 parse_func_unbase64

Decode base64 encoded string, return truncated string if 0x00 is found.

Example:

    <!--#if expr="unbase64('VG91cyBsZXMgw6p0cmVzIGh1bWFpbnMgbmFpc3NlbnQgbGlicmVzIGV0IMOpZ2F1eCBlbiBkaWduaXTDqSBldCBlbiBkcm9pdHMu') == 'Tous les êtres humains naissent libres et égaux en dignité et en droits.'" -->
    This worked!
    <!--#else -->
    Nope, it failed.
    <!--#endif -->

=head2 parse_func_unescape

Unescape %hex encoded string, leaving encoded slashes alone; return empty string if %00 is found.

Example:

    <!--#if expr="unescape('https%3A%2F%2Fwww.example.com%2F') == 'https://www.example.com/'" -->



( run in 1.706 second using v1.01-cache-2.11-cpan-e1769b4cff6 )