Apache2-PodBrowser

 view release on metacpan or  search on metacpan

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

        my $prefix='';
        my $firstchar=substr($name, 0, 1);
        unless( $firstchar eq $current ) {
            push @index, $firstchar;
            $prefix="<h2><a name=\"$firstchar\">$firstchar</a></h2>\n";
            $current=$firstchar;
        }

        my $display;
        if( length $name>35 ) {
            $display='...'.substr($name, -32);
        } else {
            $display=$name;
        }
        my $title=$name;
        $name=~s{([^A-Za-z0-9\-_.!~*'()/:\$@&=+,;?\\\]\[^`|<>{}])}
                {sprintf("%%%02X",ord($1))}eg;
        for my $x ($title, $display) {
            $x=~s/(["<>&])/$html{$1}/ge;
        }
        $prefix."<a href=\"./$linkprefix$name\" title=\"$title\">$display</a>";
    }

    sub _gen_index {
        "<div class=\"indexgroup\"><div>\n    ".join("\n    ", map {
            "<a href=\"#$_\">$_</a>";
        } @index)."\n</div></div>\n";
    }
}

sub _stylesheet {
    my ($r)=@_;

    my $stylesheet=$r->dir_config('STYLESHEET') || '';
    if ($stylesheet=~/^auto$/i) {
        $stylesheet='./auto.css';
    } elsif ($stylesheet=~/^fancy$/i) {
        $stylesheet='./fancy.css';
    }

    return $stylesheet;
}

sub _findpod {
    my ($r, $name, $ignore_NOINC)=@_;
    $name=~s!^/!!;
    $name=Pod::Find::pod_where
        ( {
           -inc=>$ignore_NOINC || !$r->dir_config->get('NOINC'),
           -dirs=>[$r->dir_config->get('PODDIR')],
          },
          $name );
    die \Apache2::Const::NOT_FOUND unless( length $name );

    return $name;
}

sub update_finfo {
    my ($r, $name)=@_;

    $r->finfo(APR::Finfo::stat($name, APR::Const::FINFO_NORM,
                               $r->pool)) if defined $name;

    $r->set_last_modified($r->finfo->mtime);
    $r->set_etag;
    my $rc=$r->meets_conditions;
    die \$rc unless $rc==Apache2::Const::OK;
}

sub _findex {
    my ($r)=@_;

    my @links=do {
        local $_;
        my %unique;

        open my $f, '<', _findpod($r, 'perlfunc', 1) or
            die \Apache2::Const::NOT_FOUND;

        while ( <$f> ) {
            /^=head2 Alphabetical Listing of Perl Functions/ and last;
        }

        my $level=0;
        while ( <$f> ) {
            if( ($level==0 && /^=over/)..($level==1 && /^=back/) ) {
                /^=over/ and $level++;
                /^=back/ and $level--;
                $level==1 && /^=item ([-\w]+)/ and undef $unique{$1};
            }
        }

        open my $f, '<', _findpod($r, 'perlvar', 1) or
            die \Apache2::Const::NOT_FOUND;

        my $level=0;
        while ( <$f> ) {
            if( ($level==0 && /^=over 8/)..($level==1 && /^=back/) ) {
                /^=over/ and $level++;
                /^=back/ and $level--;
                $level==1 && /^=item (?!IO::|HANDLE|\$\w+\{expr\})(.+)/
                    and do {
                        my $name=$1;
                        $name='$1..$N' if $name=~/digit/i;
                        undef $unique{$name};
                    };
            }
        }

        _reset_link_generator;
        map {_link($_, '?')} sort keys %unique;
    };

    return (_header(INDEX_FUNCINDEX, _stylesheet($r)).
            _gen_index.
            join("\n", @links)."\n".
            _footer);
}

sub __pod_idx {
    my ($r)=@_;

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

                }
            } else {
                my $fn=_findpod($r, $pi);
                update_finfo $r, $fn;
                $body=_compress(_body($r, $fn, undef, 1), $r);
            }
        } else {                    # simple handler
            # here we expect $r->filename to point to a file containing POD
            # and path_info to be empty.
            die \Apache2::Const::NOT_FOUND
                if (length $r->path_info or
                    ($r->finfo->filetype!=APR::Const::FILETYPE_REG));

            update_finfo $r;

            $body=_compress(_body($r, $r->filename, undef, 0), $r);
        }
    };
    # In case of an error we expect $@ to be a reference
    # the points to a scalar containing the HTTP error code
    # If that is not the case the next line will lead to an internal
    # server error which is ok then.
    return Apache2::Const::NOT_FOUND
        if ref $@ eq 'APR::Error' and $@==APR::Const::ENOENT;

    return ${$@} if ref $@ eq 'SCALAR';

    if( $@ ) {
        chomp $@;
        $r->log_reason($@);
        return Apache2::Const::NOT_FOUND;
    }

    $r->set_content_length(length($body));
    $r->print( $body );

    return Apache2::Const::OK;
}

sub Fixup {                     # use a fixup instead of a transhandler here
    my $r = shift;              # so it can be used in a <Location>

    return Apache2::Const::DECLINED unless ($r->uri =~ m!/(\w+).css$!);

    my $name=$1;
    my $css=$INC{"Apache2/PodBrowser.pm"};
    $css=~s!\.pm$!/$name.css!;

    if ($r->dir_config('GZIP')) {
        $r->headers_out->add(Vary=>'accept-encoding');
        if ($r->headers_in->{'Accept-Encoding'}=~/\bgzip\b/ and
            $r->subprocess_env->{'no-gzip'} ne '1' and # behave as mod_deflate
            $r->subprocess_env->{'gzip-only-text/html'} ne '1' and
            -f $css.'.gz') {
            $r->headers_out->{'Content-Encoding'} = 'gzip';
            $r->content_encoding('gzip');
            $r->filename($css.'.gz');
            $r->path_info('');
            $r->handler('default');
            $r->content_type('text/css');
            $r->finfo(APR::Finfo::stat($r->filename, APR::Const::FINFO_NORM,
                                       $r->pool));
            return Apache2::Const::OK;
        }
    }

    if (-f $css) {
        $r->filename($css);
        $r->path_info('');
        $r->handler('default');
        $r->content_type('text/css');
        $r->finfo(APR::Finfo::stat($r->filename, APR::Const::FINFO_NORM,
                                   $r->pool));

        return Apache2::Const::OK;
    }

    return Apache2::Const::DECLINED;
}

{
    package Apache2::PodBrowser::Formatter;

    use strict;
    use base qw/Pod::Simple::HTML/;

    our $VERSION=Apache2::PodBrowser->VERSION;

    @INC{'Apache2/PodBrowser/Formatter.pm'}=1;

    sub new {
        local $Pod::Simple::HTML::Doctype_decl=
            (qq{<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"}.
             qq{ "http://www.w3.org/TR/html4/loose.dtd">\n});

        return shift->SUPER::new(@_);
    }

    sub resolve_pod_page_link {
        my ($I, $to, $sec)=@_;

        $to=~s/::$//s;
        $to=~s/([^A-Za-z0-9\-_.!~*'():])/sprintf("%%%02X", ord $1)/ge;

        return './'.$to.$I->perldoc_url_postfix
            unless length($I->perldoc_url_prefix);

        return $I->perldoc_url_prefix.$to.$I->perldoc_url_postfix;
    }
}

{
    package Apache2::PodBrowser::DirectMode;

    use strict;
    use base qw/Apache2::PodBrowser::Formatter/;

    our $VERSION=Apache2::PodBrowser->VERSION;

    @INC{'Apache2/PodBrowser/DirectMode.pm'}=1;

    sub r {
        my ($I)=@_;

        if( @_>=2 ) {
            $I->{__PACKAGE__.'::r'}=$_[1];
        }
        $I->{__PACKAGE__.'::r'};
    }

    sub resolve_pod_page_link {
        my ($I, $to, $sec)=@_;



( run in 3.567 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )