#!/usr/bin/perl use strict; use warnings; #print @INC; my $module_cache = '/tmp/readpod.cache'; my $script_pid = '/tmp/readpod.pid'; my $cache_updates_now = 0; $cache_updates_now = 1 if -f $script_pid and kill (0, file_contents($script_pid)) == 1; # now we must check for availability of cache file or # pid of script, who wrote now this file my $cache_mtime = (stat $module_cache) [9]; my $cache_outdated = 0; my @INC_sorted = sort { length ( $b ) cmp length ( $a ) } @INC; foreach (@INC) { my $mtime = (stat) [9]; $cache_outdated = 1 if $mtime > $cache_mtime; } my $inc_dirs_re = "(" . join ( '|', @INC_sorted ) . ")"; my $inc_dirs_pod = join ':', @INC_sorted; # preparation complete, now logic begins #list_all_modules (@INC); # QUERY ANALYZE my $query = $ENV{QUERY_STRING}; $query = '' unless defined $query; if ($query eq 'css') { print "Content-Type: text/css\n\n"; while () { print $_; } exit; } print "Content-Type: text/html\nCache-Control: no-store\n\n"; my $referrer; if ( defined $ENV{HTTP_REFERER} ) { ( $referrer = $ENV{HTTP_REFERER} ) =~ s#http://[\w\-/]*/([\w\.]+)(?:\?.*|$)#$1# ; } my $script = ( $ENV{SCRIPT_NAME} =~ /.*\/(.*)/ )[0]; #print "referrer: '$referrer'\nscript: '$script'"; #exit; if (($referrer eq '' or $referrer !~ /$script(?:$|\?)/) and not $query) { print < pod reader <h1>sorry!</h1> <h3>this page must be viewed by a browser that is capable of viewing frames.</h3> FRAMESET exit; } #print ''; #print $filename, $referrer; my $pod2html_params = { cachedir => '/tmp', css => "$script?css", header => undef, }; sub make_pod_cmd { my $query = shift; my @params = (); foreach (sort keys %$pod2html_params) { my $value = $pod2html_params->{$_}; if (defined $value) { push @params, "--$_=$value"; } else { push @params, "--$_"; } } my $command = "cd /tmp && perldoc -u $query 2>&1 | pod2html " . join (' ', @params) . " 2>&1"; } if ($query) { if ($query =~ /^\//) { if (-d $query) { &html_template ( "

module list

\n
\n\n\n

\n", list_modules ($script, $query)); } if ( -f $query) { #print `cd /tmp && perldoc -u $query | pod2html 2>&1 `; my $cmd = make_pod_cmd ($query); print `$cmd`; #print `cd /tmp && perldoc -u $query 2>&1 | pod2html --cachedir=/tmp -css=/css/cpan.css --header 2>&1`; } } elsif ($query =~ /^query/i) { my ($document) = ($query =~ /query=(.*)/i); if ($document) { $document = decode ($document); my $cmd = make_pod_cmd ($document); print `$cmd`; } else { &html_template ( "

module list

\n
\n\n\n

\n"); } } else { my $cmd = make_pod_cmd ($query); print `$cmd`; } } elsif ( $query eq '' or not defined $query) { my $cache_contents = ''; if ($cache_updates_now) { $cache_contents = "

please reload page within 30 seconds, module list cache updating

\n"; } elsif ($cache_outdated or -f $script_pid) { file_contents ($script_pid, $$); $cache_contents = generate_cache ($script, @INC); file_contents ($module_cache, $cache_contents); unlink $script_pid; } else { $cache_contents = file_contents ($module_cache); } &html_template ( "

file list

\n
\n\n\n

\n", $cache_contents); } sub file_contents { my $file_name = shift; my $file_contents = shift; my $mode = '<'; $mode = '>' if defined $file_contents and $file_contents ne ''; if (open (FILE, $mode, $file_name)) { if (defined $file_contents and $file_contents ne '') { print FILE $file_contents; return ''; } else { local $/; return ; } close FILE; } return ''; } sub generate_cache { my $script = shift; my @dirs = @_; my $dirs = {}; # print "sorted \@INC:
", join "\n", @INC_sorted;
#  print "

"; foreach my $dir (@dirs) { my @out = split /\n/, `grep -lsrE "=(pod|head)" $dir `; # $,="\n"; # print "found ", scalar @out, "
\n"; foreach ( @out ) { my $module_path = $_; my $module_name = $module_path; $module_name =~ s!$inc_dirs_re/!!; # print $module_path, " ($_)
"; $module_name =~ s/^(.+)\.w+?$/$1/; my @parts = split /\//, $module_name; # my $orig_=$_; my $hash = $dirs; while( 1 ) { my $part = shift @parts; if( not scalar @parts ) { $hash ->{ $part } = "$module_path?$module_name"; last; } else { if ( not exists $hash ->{ $part } ) { $hash = $hash->{$part} = {}; } else { $hash = $hash->{$part}; } } } } } # use Data::Dumper; # print "
\n" , Dumper( $dirs ) , "
\n\n"; my $html = dir_to_html ($script, $dirs, 'mktree'); return $html; } sub list_modules { my $script = shift; my $dir = shift; # print $dir, '
'; my @out = split /\n/, `grep -lsE "=(pod|head)" $dir/* `; my @dirs; $,="\n
"; if (opendir (DIR_HANDLE, $dir)) { $dir .= '/' unless ( $dir =~ /\/$/ ); @dirs = grep { !/^\./ && -d ($dir.$_) } readdir (DIR_HANDLE); closedir DIR_HANDLE; } my $html = ''; foreach ( @dirs ) { $html .= "$_
\n"; } foreach ( @out ) { my ($file_name) = (/.*\/(.*)/); $html .= "$file_name
\n"; } @dirs = split /\//, $dir; my $current_path = ''; my $file_path = ''; # print scalar @dirs, "
"; unshift @dirs, '' if not @dirs; my $counter = scalar @dirs; foreach ( @dirs ) { $counter--; $current_path.= $_.'/'; $_ = '(root)' unless $_; if ( $counter ) { $file_path .= "$_/"; } else { $file_path .= $_; } } #my $html = dir_to_html ( $dir ); #print "
$file_path
"; return $html; } sub html_template { my @body = @_; print < @body HTML } sub dir_to_html { my $script = shift; my $dir = shift; my $class = shift || ''; my $html = $class eq '' ? "
    \n" : "
      \n"; foreach my $key (sort keys %$dir) { if ( ref ( $dir -> {$key} ) eq 'HASH' ) { $html .= q{
    • } .$key.''.dir_to_html ($script, $dir -> {$key})."
    • \n"; #my $dir_contents = ; #$html .= $dir_contents; } else { my ($module_path, $id) = split /\?/, $dir -> {$key}; $html .= qq{
    • $key
    • \n}; } } $html .= "
    \n"; return $html; } sub decode { my $value = shift; $value=~s/\+/ /g; $value=~s/%(\w\w)/chr(hex($1))/eg; return $value; } __DATA__ body, .logo { background: white; } body { color: black; font-family: arial,sans-serif; margin: 0; padding: 1em; } table { border-collapse: collapse; border-spacing: 0; border-width: 0; color: inherit; } ul {margin-left: 5px; padding-left: 5px;} img { border: 0; } form { margin: 0; } input { margin: 2px; } .logo { float: left; width: 264px; height: 77px; } .front .logo { float: none; display:block; } .front .searchbox { margin: 2ex auto; text-align: center; } .front .menubar { text-align: center; } .menubar { background: #006699; margin: 1ex 0; padding: 1px; } .menubar a { padding: 0.8ex; font: bold 10pt Arial,Helvetica,sans-serif; } .menubar a:link, .menubar a:visited { color: white; text-decoration: none; } .menubar a:hover { color: #ff6600; text-decoration: underline; } a:link, a:visited { background: transparent; color: #006699; } a[href="#POD_ERRORS"] { background: transparent; color: #FF0000; } td { margin: 0; padding: 0; } div { border-width: 0; } dt { margin-top: 1em; } .credits td { padding: 0.5ex 2ex; } .huge { font-size: 32pt; } .s { background: #dddddd; color: inherit; } .s td, .r td { padding: 0.2ex 1ex; vertical-align: baseline; } th { background: #bbbbbb; color: inherit; padding: 0.4ex 1ex; text-align: left; } th a:link, th a:visited { background: transparent; color: black; } .box { border: 1px solid #006699; margin: 1ex 0; padding: 0; } .distfiles td { padding: 0 2ex 0 0; vertical-align: baseline; } .manifest td { padding: 0 1ex; vertical-align: top; } .l1 { font-weight: bold; } .l2 { font-weight: normal; } .t1, .t2, .t3, .t4 { background: #006699; color: white; } .t4 { padding: 0.2ex 0.4ex; } .t1, .t2, .t3 { padding: 0.5ex 1ex; } /* IE does not support .box>.t1 Grrr */ .box .t1, .box .t2, .box .t3 { margin: 0; } .t1 { font-size: 1.4em; font-weight: bold; text-align: center; } .t2 { font-size: 1.0em; font-weight: bold; text-align: left; } .t3 { font-size: 1.0em; font-weight: normal; text-align: left; } /* width: 100%; border: 0.1px solid #FFFFFF; */ /* NN4 hack */ .datecell { text-align: center; width: 17em; } .cell { padding: 0.2ex 1ex; text-align: left; } .label { background: #aaaaaa; color: black; font-weight: bold; padding: 0.2ex 1ex; text-align: right; white-space: nowrap; vertical-align: baseline; } .categories { border-bottom: 3px double #006699; margin-bottom: 1ex; padding-bottom: 1ex; } .categories table { margin: auto; } .categories td { padding: 0.5ex 1ex; vertical-align: baseline; } .path a { background: transparent; color: #006699; font-weight: bold; } .pages { background: #dddddd; color: #006699; padding: 0.2ex 0.4ex; } .path { background: #dddddd; border-bottom: 1px solid #006699; color: #006699; /* font-size: 1.4em;*/ margin: 1ex 0; padding: 0.5ex 1ex; } .menubar td { background: #006699; color: white; } .menubar { background: #006699; color: white; margin: 1ex 0; padding: 1px; } .menubar .links { background: transparent; color: white; padding: 0.2ex; text-align: left; } .menubar .searchbar { background: black; color: black; margin: 0px; padding: 2px; text-align: right; } a.m:link, a.m:visited { background: #006699; color: white; font: bold 10pt Arial,Helvetica,sans-serif; text-decoration: none; } a.o:link, a.o:visited { background: #006699; color: #ccffcc; font: bold 10pt Arial,Helvetica,sans-serif; text-decoration: none; } a.o:hover { background: transparent; color: #ff6600; text-decoration: underline; } a.m:hover { background: transparent; color: #ff6600; text-decoration: underline; } table.dlsip { background: #dddddd; border: 0.4ex solid #dddddd; } pre { background: #eeeeee; border: 1px solid #888888; color: black; padding: 1em; white-space: pre; } h1 { background: transparent; color: #006699; font-size: large; } h2 { background: transparent; color: #006699; font-size: medium; } img { vertical-align: top; } .toc a { text-decoration: none; } .toc li { line-height: 1.2em; list-style-type: none; } .faq dt { font-size: 1.4em; font-weight: bold; } .chmenu { background: black; color: red; font: bold 1.1em Arial,Helvetica,sans-serif; margin: 1ex auto; padding: 0.5ex; } .chmenu td { padding: 0.2ex 1ex; } .chmenu a:link, .chmenu a:visited { background: transparent; color: white; text-decoration: none; } .chmenu a:hover { background: transparent; color: #ff6600; text-decoration: underline; } .column { padding: 0.5ex 1ex; vertical-align: top; } .datebar { margin: auto; width: 14em; } .date { background: transparent; color: #008000; } /* mktree section */ ul.mktree {margin: 0; padding: 0} acronym {cursor: help;} ul.mktree li {list-style: none;} ul.mktree li span.b {padding-left: 15px; margin-left: 0px;} /* IE? fuck off! */ ul.mktree li.clo>span.b {cursor: pointer; background: url(data:image/gif;base64,R0lGODlhEgASAMQAAAAAAP////z8/Pf39/T09Obm5tnZ2dHR0cXFxa6urp6enpeXl5KSkouLi4ODg4CAgHd3d3Nzc////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABIALAAAAAASABIAAAU2oCSOZGmeaKqu68GWzFK8YhQ5CfHa9oMIKx6vYRikhDyI4ogkGlFCH1Blw+lYsRnNRet6v6MQADs=) center left no-repeat;} ul.mktree li.op>span.b {cursor: pointer; background: url(data:image/gif;base64,R0lGODlhEgASAMQAAAAAAP////z8/Pf39/T09Obm5tnZ2dHR0cXFxa6urp6enpeXl5KSkouLi4ODg4CAgHd3d3Nzc////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABIALAAAAAASABIAAAU5oCSOZGmeaKqubDseTCTPEXOgCz0vaeHojoIqoUusCI/Zg8BCzBAtQSPSELgMEINLMlAMtuCwuBUCADs=) center left no-repeat;} ul.mktree li.bull>span.b {cursor: default; background: none;} ul.mktree li.op>ul {display: block;} ul.mktree li.clo>ul {display: none;}