File Coverage

blib/lib/Pod/Webserver/Source.pm
Criterion Covered Total %
statement 9 64 14.0
branch 0 24 0.0
condition 0 8 0.0
subroutine 3 6 50.0
pod n/a
total 12 102 11.7


line stmt bran cond sub pod time code
1             package Pod::Webserver::Source;
2             # $Id: Source.pm,v 1.1 2005/01/05 12:26:39 cwest Exp $
3 1     1   1065 use strict;
  1         2  
  1         38  
4 1     1   4 use vars qw[$LINK_PATH $PERLTIDY_ARGV $VERSION];
  1         1  
  1         2447  
5             $PERLTIDY_ARGV = [qw[-html -npod -nnn]];
6             $VERSION = sprintf "%d.%02d", split m/\./, (qw$Revision: 1.1 $)[1];
7              
8             sub _serve_thing {
9 0     0     my ($self, $conn, $req) = @_;
10 0 0         return $conn->send_error(405) unless $req->method eq 'GET'; # sanity
11              
12 0           my $path = $req->url;
13 0   0       $path .= substr( ($ENV{PATH} ||''), 0, 0); # to force-taint it.
14            
15 0           my $fs = $self->{'__daemon_fs'};
16 0           my $pods = $self->{'__modname2path'};
17 0           my $resp = HTTP::Response->new(200);
18 0   0       $resp->content_type( $fs->{"\e$path"} || 'text/html' );
19              
20 0           my $path = $req->url;
21 0   0       $path .= substr( ($ENV{PATH} ||''), 0, 0); # to force-taint it.
22 0           $path =~ s{:+}{/}g;
23 0           my $modname = $path;
24 0           $modname =~ s{/+}{::}g; $modname =~ s{^:+}{};
  0            
25 0           $modname =~ s{:+$}{}; $modname =~ s{:+$}{::}g;
  0            
26              
27 0           $Pod::Webserver::Source::LINK_PATH = $req->url;
28 0 0         return shift->_real_serve_thing(@_) unless $modname =~ /\.source$/;
29              
30 0           $modname =~ s/\.source$//;
31 0 0         if ( $modname =~ m{^([a-zA-Z0-9_]+(?:::[a-zA-Z0-9_]+)*)$}s ) {
32 0           $modname = $1; # thus untainting
33             } else {
34 0           $modname = '';
35             }
36 0 0         Pod::Webserver::DEBUG() > 1 and print "Modname $modname source ($path)\n";
37              
38 0 0         if ( $pods->{$modname} ) { # Is it known pod?
39 0           $self->muse("I know $modname source as ", $pods->{$modname});
40 0           __PACKAGE__->_serve_source($pods->{$modname}, $resp);
41             } else {
42             # If it's not known, look for it.
43             # This is necessary for indexless mode, and also useful just incase
44             # the user has just installed a new module (after the index was generated)
45 0           my $fspath = $Pod::Simple::HTMLBatch::SEARCH_CLASS->new->find($modname);
46            
47 0 0         if( defined($fspath) ) {
48 0           $self->muse("Found $modname source as $fspath");
49 0           __PACKAGE__->_serve_source($fspath, $resp);
50             } else {
51 0           $resp = '';
52 0           $self->muse("Can't find $modname in \@INC");
53 0 0         unless( $self->{'httpd_has_noted_inc_already'} ++ ) {
54 0           $self->muse(" \@INC = [ @INC ]");
55             }
56             }
57             }
58            
59 0 0         $resp ? $conn->send_response( $resp ) : $conn->send_error(404);
60 0           return;
61             }
62              
63             sub _serve_source {
64 0     0     my ($self, $fspath, $resp) = @_;
65            
66 0           my $output = '';
67 0 0         if ( eval { require Perl::Tidy } ) {
  0            
68 0           Perl::Tidy::perltidy(
69             source => $fspath,
70             destination => \$output,
71             argv => $Pod::Webserver::Source::PERLTIDY_ARGV,
72             );
73             } else {
74 0           $resp->header('Content-Type' => 'text/plain');
75 0           local *PODFH;
76 0           my $line = 1;
77 0 0         if ( open PODFH, "< $fspath" ) {
78 0           $output .= sprintf "%5d %s",
79             $line++,
80             $_ while <PODFH>;
81 0           close PODFH;
82             } else {
83 0           $output = "Can't locate sources ($!)!\n";
84             }
85             }
86 0           $resp->content($output);
87            
88 0           return;
89             }
90              
91             sub _add_header_backlink {
92 0     0     my $self = shift;
93 0 0         return if $self->no_contents_links;
94 0           my($page, $module, $infile, $outfile, $depth) = @_;
95 0 0 0       $page->html_header_after_title( join '',
96             $page->html_header_after_title || '',
97             qq[<p class="backlinktop"><b><a name="___top" href="],
98             $self->url_up_to_contents($depth),
99             qq[" accesskey="1" title="All Documents">&lt;&lt;</a>],
100             qq[ <a href="$Pod::Webserver::Source::LINK_PATH.source">Source</a>],
101             qq[</b></p>\n],
102             ) if $self->contents_file;
103 0           return;
104             }
105              
106             package Pod::Webserver;
107 1     1   22 no strict;
  1         2  
  1         80  
108              
109             *_real_serve_thing = \&_serve_thing;
110             *_serve_thing = \&Pod::Webserver::Source::_serve_thing;
111             *add_header_backlink = \&Pod::Webserver::Source::_add_header_backlink;
112              
113             1;
114              
115             __END__
116              
117             =head1 NAME
118              
119             Pod::Webserver::Source - Plugin to Pod::Webserver for Viewing Source Code
120              
121             =head1 SYNOPSIS
122              
123             use Pod::Webserver;
124             use Pod::Webserver::Source; # Add this line to 'podwebserver' CLI.
125             Pod::Webserver::httpd();
126              
127             =head1 DESCRIPTION
128              
129             This software adds source code viewing support to C<Pod::Webserver>.
130             Optional C<Perl::Tidy> support is included. If C<Perl::Tidy> has been
131             installed, the source code will be formatted using the following
132             C<Perl::Tidy> arguments: C<-html -npod -nnn>. You may override these
133             arguments by resetting the package variable
134             C<$Pod::Webserver::Source::PERLTIDY_ARGV> to a list reference or string
135             containing your personal preferences. Your F<~/.perltidyrc> file will be
136             honored in the same way C<Perl::Tidy> would honor it. If C<Perl::Tidy>
137             is not installed source code will be formatted in plain text and
138             prefixed with line numbers.
139              
140             Viewing the source of a module is simple, just click on the link in the
141             header next to the back link called B<Source>.
142              
143             Due to the nature of this code it is imperitive that
144             C<Pod::Webserver::Source> be loaded I<after> C<Pod::Webserver> as
145             demonstrated in the SYNOPSIS.
146              
147             =head1 MODIFY F<podwebserver>
148              
149             Here's a Perl-ish way to modify podwebserver as I know it, distributed
150             with version C<3.02> of C<Pod::Webserver>.
151              
152             perl -pi -e'eof and
153             $_ .= "use Pod::Webserver::Source;\n"' `which podwebserver`
154              
155             =head1 SEE ALSO
156              
157             L<Pod::Webserver>,
158             C<Perl::Tidy>,
159             L<perl>.
160              
161             =head1 THANKS
162              
163             Much of this code was ripped from various pieces written by Sean Burke
164             who did all the hard work. I merely mutilated his code to produce this
165             functionality.
166              
167             =head1 AUTHOR
168              
169             Casey West, <F<casey@geeknest.com>>.
170              
171             =head1 COPYRIGHT
172              
173             Copyright (c) 2005 Casey West. All rights reserved.
174             This module is free software; you can redistribute it and/or modify it
175             under the same terms as Perl itself.
176              
177             =cut