package HTML::Include;

use strict; use warnings;

use base 'Markup::Processor';

use Markup;
use Alias;

use vars qw(@elements $i $e $type $tag $name @context $dir $root);

use L;  # for In, slurp

sub load {
	my ($class, $markup, $dir, $root) = @_;
	# $dir and $root must be absolute paths
	for ($dir, $root) { s,/$,, }
	# NOTE: $root will be "" if it was "/"
	my $p = $class->new($markup);
	$p->{dir} = $dir;
	$p->{root} = $root;
	$p->main_loop;
}

sub main_loop {
	my $p = attr shift;
	while(1) {
		$p->read or last;
		if ($type eq "open" && $e->attr_exists("src") &&
#			In($tag, [qw(include p div span td)])
			!In($tag, [qw(img input embed frame iframe)])
			) {
			my $to_insert;
			if (defined $dir) {
				my $src = $e->attr_get("src");
				my $type = $e->attr_get("type") || 'text/html';
				if ($src =~ m|^[a-z]+:|) {
					die "bad src: $src - only local files can be included";
				}
				my $path_to_file = $src =~ m|^/| ?
					"$root/$src" :
					"$dir/$src";
				while ($path_to_file =~ s|[^/]*/\.\./||) {}
				if (substr($path_to_file, 0, length($root)) ne $root || $path_to_file =~ m,/\.\.(/|$),) {
					# apparently they attempted to go above $root
					# so we make it $root ALL the way up :)
					$src =~ s|.*/||;
					$path_to_file = "$root/$src";
				}
				unless (-f $path_to_file && -r $path_to_file) {
					die "bad src: $src - cannot read";
				}
				if ($type eq "text/html") {
					my $new_markup = Markup->parse_file($src);
					$to_insert = $new_markup->elements;
				} elsif ($type eq "text/plain") {
					my $content = slurp($src);
					$to_insert = [Markup::Text->new($content)];
				} else {
					die "unknown mime type for include: $type";
				}
			} else { # !defined $dir
				# we clear it
				$to_insert = [];
			}
			$p->replace_container_content(@$to_insert);
		}
	}
}

sub clear {
	my ($class, $markup) = @_;
	$class->load($markup);
	# no $dir means we clear all the includes
}

1
