Apache-Clickable

 view release on metacpan or  search on metacpan

lib/Apache/Clickable.pm  view on Meta::CPAN

package Apache::Clickable;

use strict;
use vars qw($VERSION);
$VERSION = 0.02;

use Apache::Constants qw(:common);
use Apache::File;
use Carp ();

sub handler {
    my $r = shift;

    my $filtered = uc($r->dir_config('Filter')) eq 'ON';
    $r = $r->filter_register if $filtered;

    # only for text/html
    return DECLINED unless ($r->content_type eq 'text/html' && $r->is_main);

    my($fh, $status);
    if ($filtered) {
	($fh, $status) = $r->filter_input;
	undef $fh unless $status == OK;
    } else {
	$fh = Apache::File->new($r->filename);
    }

    return DECLINED unless $fh;

    $r->send_http_header;

    local $/;			# slurp
    my $input = <$fh>;
    my $output = make_it_clickable($r, $input);
    $r->print($output);
    return OK;
}

sub make_it_clickable {
    my($r, $input) = @_;
    my $parser = Apache::Clickable::Parser->new(apr => $r);
    $parser->parse($input);
    return $parser->{output};
}

package Apache::Clickable::Parser;

require HTML::Parser;
@Apache::Clickable::Parser::ISA = qw(HTML::Parser);

use Email::Find 0.04;
use URI::Find;

sub new {
    my($class, %args) = @_;

    my $self = $class->SUPER::new;
    $self->{apr} = $args{apr};
    $self->{currently_in_a} = 0;
    return $self;
}

sub comment {
    my($self, $comment) = @_;
    $self->{output} .= "<!--$comment-->";
}

sub declaration {
    my($self, $declaration) = @_;
    $self->{output} .= "<!$declaration>";
}

sub start {
    my($self, $tag, $attr, $attrseq, $origtext) = @_;
    if ($tag eq 'a') {
	$self->{currently_in_a}++;
    }
    $self->{output} .= $origtext;
}

sub end {
    my($self, $tag, $origtext) = @_;
    if ($tag eq 'a') {
	$self->{currently_in_a}--;
    }
    $self->{output} .= $origtext;
}

sub text {
    my($self, $origtext) = @_;
    if ($self->{currently_in_a}) {
	$self->{output} .= $origtext;
	return;
    }

    $self->{output} .= $self->replace_sub->($origtext);
}

my $sub;			# closure
sub replace_sub {
    my $self = shift;
    unless ($sub) {
	$sub = sub {
	    my $input = shift;
	    # replace URLs
	    my $target = $self->{apr}->dir_config('ClickableTarget') || undef;
	    find_uris($input, sub {
			  my($uri, $orig_uri) = @_;
			  return sprintf(qq(<a href="%s"%s>%s</a>),
					 $orig_uri,
					 ($target ? qq( target="$target") : ''),
					 $orig_uri);
		      });

	    # replace Emails
	    unless (uc($self->{apr}->dir_config('ClickableEmail')) eq 'OFF') {
		find_emails($input, sub {



( run in 1.767 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )