# See bottom of file for license and copyright information

=begin TML

---+ package Foswiki::IncludeHandlers::local

This package is designed to be lazy-loaded when Foswiki sees
an INCLUDE macro with the local: protocol. It implements a single
method INCLUDE.

=cut

package Foswiki::IncludeHandlers::local;

use strict;

use Foswiki;

# Fetch content from a URL for inclusion by an INCLUDE
sub INCLUDE {
    my ( $ignore, $session,  $control, $options ) = @_;

    my $text = '';
    my $url = $control->{_DEFAULT};

    # SMELL: should use the URI module from CPAN to parse the URL
    # SMELL: but additional CPAN adds to code bloat
    unless ( $url =~ m!^local:! ) {
        $text = $session->_includeWarning(
            $control->{warn}, 'bad_protocol', $url );
        return $text;
    }

    (my $newurl=$url)=~s!^local:/*!!;
    if ( $newurl =~ m!(%|\.\.|:|//|&#)! ) {
	return $session->_includeWarning( $control->{warn}, 'urls_not_allowed' )
    }
    $newurl=Foswiki::Func::getUrlHost() . "//" . $newurl;
    my $response = $session->net->getExternalResource($newurl);
    if ( !$response->is_error() ) {
        my $contentType = $response->header('content-type');
        $text = $response->content();
        if ( $contentType =~ /^text\/html/ ) {
            if ( !$control->{raw} ) {
                $newurl =~ m!^([a-z]+:/*[^/]*)(/[^#?]*)!;
                $text = _cleanupIncludedHTML( $text, $1, $2, $options );
            }
        }
        elsif ( $contentType =~ /^text\/(plain|css)/ ) {

            # do nothing
        }
        else {
            $text =
              $session->_includeWarning(
                  $control->{warn}, 'bad_content', $contentType );
        }
        $text = Foswiki::applyPatternToIncludedText(
            $text, $control->{pattern} ) if ($control->{pattern});
        $text = "<literal>\n" . $text . "\n</literal>"
          if ( $options->{literal} );
    }
    else {
        $text =
          $session->_includeWarning( $control->{warn}, 'geturl_failed',
            $url . ' ' . $response->message() );
    }

    return $text;
}

# Clean-up HTML text so that it can be shown embedded in a topic
sub _cleanupIncludedHTML {
    my ( $text, $host, $path, $options ) = @_;

    # FIXME: Make aware of <base> tag

    $text =~ s/^.*?<\/head>//is
      unless ( $options->{disableremoveheaders} );    # remove all HEAD
    $text =~ s/<script.*?<\/script>//gis
      unless ( $options->{disableremovescript} );     # remove all SCRIPTs
    $text =~ s/^.*?<body[^>]*>//is
      unless ( $options->{disableremovebody} );       # remove all to <BODY>
    $text =~ s/(?:\n)<\/body>.*//is
      unless ( $options->{disableremovebody} );       # remove </BODY>
    $text =~ s/(?:\n)<\/html>.*//is
      unless ( $options->{disableremoveheaders} );    # remove </HTML>
    $text =~ s/(<[^>]*>)/_removeNewlines($1)/ges
      unless ( $options->{disablecompresstags} )
      ;    # replace newlines in html tags with space
    $text =~ s/(\s(?:href|src|action)=(["']))(.*?)\2/$1 .
      _rewriteURLInInclude( $host, $path, $3 ).$2/geis
        unless ( $options->{disablerewriteurls} );

    return $text;
}

sub _removeNewlines {
    my ($theTag) = @_;
    $theTag =~ s/[\r\n]+/ /gs;
    return $theTag;
}

# Convert relative URLs to absolute URIs
sub _rewriteURLInInclude {
    my ( $theHost, $theAbsPath, $url ) = @_;

    # leave out an eventual final non-directory component from the absolute path
    $theAbsPath =~ s/(.*?)[^\/]*$/$1/;

    if ( $url =~ /^\// ) {

        # fix absolute URL
        $url = $theHost . $url;
    }
    elsif ( $url =~ /^\./ ) {

        # fix relative URL
        $url = $theHost . $theAbsPath . '/' . $url;
    }
    elsif ( $url =~ /^$Foswiki::regex{linkProtocolPattern}:/o ) {

        # full qualified URL, do nothing
    }
    elsif ( $url =~ /^#/ ) {

        # anchor. This needs to be left relative to the including topic
        # so do nothing
    }
    elsif ($url) {

        # FIXME: is this test enough to detect relative URLs?
        $url = $theHost . $theAbsPath . '/' . $url;
    }

    return $url;
}

1;
__END__
# Foswiki - The Free and Open Source Wiki, http://foswiki.org/
#
# Copyright (C) 2008-2009 Foswiki Contributors. Foswiki Contributors
# are listed in the AUTHORS file in the root of this distribution.
# NOTE: Please extend that file, not this notice.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version. For
# more details read LICENSE in the root of this distribution.
#
# This program 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.
#
# As per the GPL, removal of this notice is prohibited.
