File Coverage

blib/lib/SlideShow.pm
Criterion Covered Total %
statement 18 240 7.5
branch 0 98 0.0
condition 0 9 0.0
subroutine 6 14 42.8
pod 4 7 57.1
total 28 368 7.6


line stmt bran cond sub pod time code
1             package SlideShow;
2              
3 1     1   865 use strict;
  1         2  
  1         47  
4 1     1   5 use vars qw($VERSION @ISA);
  1         2  
  1         94  
5              
6             $VERSION = '2.0';
7              
8             @SlideShow::ISA = qw(HTML::Parser);
9              
10 1     1   2330 use CGI qw/:standard/;
  1         17472  
  1         6  
11 1     1   4937 use LWP::UserAgent;
  1         59499  
  1         27  
12 1     1   896 use HTML::Parser;
  1         13045  
  1         45  
13 1     1   10 use URI::Escape;
  1         3  
  1         3389  
14              
15             sub new {
16 0     0 1   my $class = shift;
17              
18 0           my $self = HTML::Parser->new();
19 0           bless $self, $class;
20              
21 0           while (my $X = shift) {
22 0           my $Y = shift;
23 0           $self->{$X} = $Y;
24             }
25              
26 0 0         die "SlideShow::Master missing required parameter 'master_cgi'"
27             unless exists $self->{master_cgi};
28              
29 0 0         $self->{start_title} = "SlideShow Startup"
30             unless exists $self->{start_title};
31 0 0         $self->{tmp_dir} = "/tmp"
32             unless exists $self->{tmp_dir};
33 0 0         $self->{view_file} = "$self->{tmp_dir}/viewfile.html"
34             unless exists $self->{view_file};
35 0 0         $self->{log_file} = "$self->{tmp_dir}/surflog.last"
36             unless exists $self->{tmp_log};
37 0 0         $self->{tmp_log} = "$self->{tmp_dir}/surf.tmp"
38             unless exists $self->{tmp_log};
39              
40 0 0         $self->{url_list} = [ "http://www.perl.com/CPAN/" ]
41             unless exists $self->{url_list};
42              
43 0 0         $self->{commentary} = "Presented using SlideShow, a Perl module"
44             . " for remote browser control available at"
45             ." www.perl.com/CPAN/"
46             unless exists $self->{commentary};
47              
48 0           $self->{redirect} = "$self->{master_cgi}?URL=";
49 0           $self->{inside} = 0;
50              
51 0           $self->{ua} = new LWP::UserAgent;
52 0           $self->{ua}->agent("SlideShow/2.0");
53 0           $SlideShow::last_marker = '';
54              
55 0           $self;
56             }
57              
58             sub run {
59 0     0 0   my $self = shift;
60              
61 0 0         if (not param()) {
62             # no URL given
63 0           print
64             header,
65             start_html(-title => $self->{start_title},
66             -BGCOLOR => "#FFFFFF"),
67             h1($self->{start_title}),
68             start_form,
69             submit('Show URL'),
70             textfield('URL'),
71             end_form;
72              
73 0 0         if ($self->{url_list}) {
74 0           print hr;
75 0           print h2('presets');
76 0           print "
    \n";
77 0           for my $url (@{$self->{url_list}}) {
  0            
78 0           print "
  • {master_cgi}?URL=$url\">$url\n";
  • 79             }
    80 0           print "\n";
    81             }
    82            
    83 0 0         if ($self->{commentary}) {
    84 0           print hr;
    85 0           print $self->{commentary};
    86             }
    87              
    88 0           print end_html;
    89              
    90             } else {
    91 0           my $current_http_dir = param('URL');
    92 0           $current_http_dir =~ s/\s+$//;
    93              
    94 0 0         if (substr($current_http_dir, -1, 1) ne '/') {
    95 0           $current_http_dir =~ s!^(http://.*/).*!$1!;
    96             }
    97              
    98 0           $self->{current_dir} = $current_http_dir;
    99              
    100 0           print header;
    101              
    102 0           my $item = param('URL');
    103              
    104 0           unlink($self->{view_file});
    105              
    106 0 0         if (not open VIEWFILE, ">$self->{view_file}") {
    107 0           print "

    can't create $self->{view_file}: $!

    \n";
    108             } else {
    109 0           print VIEWFILE $$."\n";
    110              
    111 0 0         if ($item =~ /^\s*last\s*$/) {
    112 0           print VIEWFILE $SlideShow::last_marker."\n"; # send the termination
    113 0           close VIEWFILE;
    114              
    115 0 0         if (-e $self->{tmp_log}) {
    116 0           unlink ($self->{log_file});
    117 0           rename ($self->{tmp_log}, $self->{log_file});
    118             }
    119              
    120             print
    121 0           start_html(-title => "Session finished",
    122             -BGCOLOR => "#FFFFFF"),
    123             h1("Session finished");
    124              
    125 0           print "{master_cgi}\">New Session",p;
    126              
    127 0 0         if ($self->{log_file}) {
    128 0           print "
    \n";
    129 0           print "The pages were visited in this order:

    \n";

    130            
    131 0           open(LOG, $self->{log_file});
    132            
    133 0           while() {
    134 0           print "
  • ".$_;
  • 135             }
    136 0           close(LOG);
    137 0           print "
    \n";
    138 0           print "Save this document locally if you'd like to"
    139             . " keep a record.\n";
    140             }
    141              
    142 0           sleep(4); # sleep longer than the update time for clients
    143 0           unlink ($self->{view_file});
    144 0           exit 0;
    145             }
    146              
    147 0           my $req = new HTTP::Request 'GET' => $item;
    148 0           my $res = $self->{ua}->request($req);
    149              
    150 0 0         if (not $res->is_success) {
    151 0           print "Error: " . $res->status_line . "\n";
    152             } else {
    153 0           my $item = $res->as_string;
    154 0           print $self->rewrite($item, "master");
    155 0           print VIEWFILE $self->rewrite($item, "viewer");
    156 0 0         if ($self->{log_file}) {
    157 0 0         open LOG, ">>$self->{tmp_log}"
    158             or die "can't open $self->{tmp_log}: $!";
    159 0           print LOG param('URL')."\n";
    160 0           close LOG;
    161             }
    162             }
    163 0           close VIEWFILE;
    164              
    165             }
    166 0           print end_html;
    167             }
    168             }
    169              
    170             sub start {
    171 0     0 1   my $self = shift ;
    172 0           my ($tag, $attr, $attrseq, $origtext) = @_;
    173              
    174 0           $self->{result} .= '<' . $tag;
    175              
    176 0 0         if (lc($tag) eq 'html') {
    177 0           $self->{inside} = 1;
    178             }
    179              
    180 0 0         return unless $self->{inside};
    181 0           my $dirpref = $self->{current_dir};
    182              
    183 0           my $hostpref = $dirpref;
    184 0           $hostpref =~ s!^((?:ht|f)tp://[^\/]+).*!$1/!;
    185              
    186 0 0         if (defined $dirpref) {
    187 0 0         $dirpref .= '/' unless
    188             substr($dirpref, -1, 1) eq '/';
    189             }
    190              
    191 0 0         if (defined $attr->{'src'}) {
    192             # fully qualify any relative IMG paths
    193             # perhaps this should get the images locally and
    194             # serve them up, too, but for now it still points
    195             # to the original sites.
    196 0 0         if ($attr->{'src'} !~ m!^(?:ht|f)tp://!i) {
    197 0 0         if (substr($attr->{'src'}, 0, 1) eq '/') {
    198 0           $attr->{'src'} = $hostpref . $attr->{'src'};
    199             } else {
    200 0           print STDERR "$attr->{'src'} -> ";
    201 0           $attr->{'src'} = $dirpref . $attr->{'src'};
    202 0           print STDERR "$attr->{'src'}\n";
    203             }
    204             }
    205 0           $attr->{'src'} =~ s|/+$|/|;
    206             }
    207              
    208 0 0         if (defined $attr->{'href'}) {
    209 0 0         if ($attr->{'href'} !~ m!^(ht|f)tp://!i) {
    210 0 0         if (substr($attr->{'href'}, 0, 1) eq '/') {
    211 0           $attr->{'href'} = $hostpref . $attr->{'href'};
    212             } else {
    213 0           $attr->{'href'} = $dirpref . $attr->{'href'};
    214             }
    215             }
    216 0           $attr->{'href'} =~ s!/+$!/!;
    217             }
    218              
    219 0 0         if ($tag eq 'a') {
    220 0 0         if ($attr->{'href'}) {
    221              
    222 0 0         if ($self->{'which'} eq 'master') {
    223             # redirect HREFs on the master back into the CGI
    224 0           my $h = $self->{redirect} . $attr->{'href'};
    225 0           $attr->{'href'} = $h;
    226             } else {
    227             # convert the viewer's HREFs to some style
    228             # change so that aren't as easily tempted
    229             # to click off the path
    230 0           delete $attr->{'href'};
    231              
    232 0           $attr->{'color'} = 'red';
    233              
    234 0 0         push @$attrseq, 'color'
    235             unless grep $_ eq 'color', @$attrseq;
    236             }
    237             }
    238             }
    239              
    240 0           for my $m (@$attrseq) {
    241 0           $self->{result} .= " $m=\"$attr->{$m}\"";
    242             }
    243              
    244 0           $self->{result} .= '>';
    245 0 0 0       if ($tag eq 'body' and $self->{which} eq 'master') {
    246 0           $self->{result} .= "

    \n";

    247 0           $self->{result} .= "\nSlideShow: ";
    248 0           $self->{result} .= "{master_cgi}\">Top | ";
    249 0           $self->{result} .= "{master_cgi}?URL=last\">Quit ";
    250 0           $self->{result} .= "

    \n";
    251             }
    252            
    253 0           $self->{result};
    254             }
    255              
    256             sub text {
    257 0     0 1   my $self = shift ;
    258 0           my $text = shift;
    259              
    260 0 0         return unless $self->{inside};
    261              
    262 0           $self->{result} .= $text;
    263             }
    264              
    265             sub comment {
    266 0     0     my $self = shift ;
    267 0           my $comment = shift;
    268 0 0         return unless $self->{inside};
    269 0           $self->{result} .= "";
    270             }
    271              
    272             sub end {
    273 0     0 1   my $self = shift ;
    274 0 0         return unless $self->{inside};
    275              
    276 0           my ($tag, $origtext) = @_;
    277 0 0         if (lc($tag) eq 'html') {
    278 0           $self->{inside} = 0;
    279             }
    280 0 0 0       if (lc($tag) eq 'body' and $self->{which} eq 'master') {
    281 0           $self->{result} .= "\n";
    282              
    283 0           $self->{result} .= start_form
    284             . submit('Next Slide:')
    285             . textfield(-name => 'URL', -size=>40, -default=>param('URL'))
    286             . end_form;
    287             }
    288 0           $self->{result} .= $origtext;
    289             }
    290              
    291             sub rewrite {
    292 0     0 0   my $self = shift;
    293 0           my $html = shift;
    294 0           my $which = shift;
    295              
    296 0           $html =~ s/^.*?(
    297              
    298 0 0         if (lc($which) eq 'viewer') {
    299 0           $self->{which} = 'viewer';
    300             } else {
    301 0           $self->{which} = 'master';
    302             }
    303              
    304 0           $self->{result} = '';
    305              
    306 0           $self->parse($html);
    307              
    308 0           return $self->{result};
    309             }
    310              
    311             sub client {
    312 0     0 0   my %p;
    313 0           while (shift) {
    314 0           $p{$_} = shift;
    315             }
    316              
    317 0 0         $p{view_file} = "/tmp/viewfile.html"
    318             unless $p{view_file};
    319              
    320 0 0         $p{log_file} = "/tmp/surflog.last"
    321             unless $p{log_file};
    322             # $DEBUG = 1;
    323              
    324             # Unbuffer STDOUT
    325 0           $|=1;
    326              
    327 0           print "HTTP/1.0 200 OK\n";
    328 0           print "Content-type: multipart/x-mixed-replace;boundary=ThisRandomString\n";
    329 0           print "\n";
    330 0           print "--ThisRandomString\n";
    331              
    332 0           my $prev_surf_id = "-1";
    333 0           my $done = 0;
    334 0           my $count = 0;
    335 0           my $TIMEOUT = 60 * 4; # (browser timeout is typically 5 minutes)
    336              
    337             #
    338             # wait for the file to show up
    339             # present the startup message until it does
    340             #
    341 0           while (!-r $p{view_file}) {
    342 0           print "Content-type: text/html\n\n";
    343              
    344 0           print "\n";
    345 0           print "Waiting for session\n";
    346 0           print "\n";
    347 0           print "

    Presentation view

    \n";
    348              
    349 0           print "time: ".`date`."

    \n";

    350 0           print "Waiting for session to begin...
    \n\n";
    351              
    352 0           print "\n";
    353 0           print "\n";
    354              
    355 0           print "--ThisRandomString\n";
    356 0           sleep(5);
    357             }
    358              
    359             #
    360             # Once we've seen the file, we're in a presentation.
    361             #
    362 0           my ($line, $surf_id);
    363 0   0       while(($count < $TIMEOUT) && !$done) {
    364 0           $count++;
    365 0           $line = 0;
    366 0 0         if (open(ITEM, $p{view_file})) {
    367 0           while (my $item = ) {
    368 0           $line++;
    369 0 0         if ($line == 1) {
    370 0           chop $item;
    371 0           $surf_id = $item;
    372              
    373 0 0         if ($prev_surf_id eq $surf_id) {
    374 0           last;
    375             } else {
    376 0           $prev_surf_id = $surf_id;
    377 0           print "Content-type: text/html\n\n";
    378              
    379             ## Reset the presentation counter
    380 0           $count = 0;
    381              
    382 0           next;
    383             }
    384             }
    385              
    386 0 0         if ($item =~ /^$SlideShow::last_marker$/) {
    387 0           print "\n";
    388 0           print "Session finished\n";
    389 0           print "\n";
    390              
    391 0           print '
    392            

    Thank you

    393              
    394             The session has finished.
    395             ';
    396 0 0         if ($p{log_file}) {
    397 0           print "
    \n";
    398 0           print "The pages were visited in this order:

    \n";

    399            
    400 0           open(LOG, $p{log_file});
    401            
    402 0           while() {
    403 0           print "
  • ".$_;
  • 404             }
    405 0           close(LOG);
    406 0           print "
    \n";
    407 0           print "Save this document locally if you'd like to"
    408             . " keep a record.\n";
    409             }
    410 0           $done = 1;
    411 0           next;
    412             }
    413              
    414 0           print $item;
    415             }
    416 0           close(ITEM);
    417 0 0         print "\n--ThisRandomString\n" if ($line > 1);
    418             }
    419 0           sleep(1);
    420             }
    421              
    422 0 0         if ($count >= $TIMEOUT) {
    423 0           print "--ThisRandomString\n";
    424              
    425 0           print "Content-type: text/html\n\n";
    426 0           print "\n";
    427 0           print '',"\n";
    428 0           print "

    Timed out.

    \n";
    429 0           print "
    \n";
    430 0           print "This session has been active without update for too long.
    \n";
    431 0           print "Hit Reload if you think the session is still in progress.\n";
    432 0           print "\n";
    433             }
    434              
    435 0           print "--ThisRandomString--\n";
    436             }
    437              
    438              
    439             1;
    440             __END__