#!/usr/bin/perl -w # # A screen grabber with an embedded Web Server # Angelos Karageorgiou # angelos@unix.gr # package Rautor; # look for it under sourceforge use common::sense; use HTTP::Daemon; use HTTP::Response; use HTTP::Status; use HTTP::Request; use Getopt::Long; use IO::Socket::INET; use IO::Select; use File::Temp qw|tempdir|; use Fcntl qw |:flock|; use Carp; my $PORT=42000; my $VERBOSE=''; my $format="png"; my $imgFname="screen.$format"; my $SLEEP=5; #my $CMDLINE="/usr/bin/import -silent -window root"; my $CMDLINE="/usr/bin/xwd -root -silent | /usr/bin/xwdtopnm -quiet | /usr/bin/pnmtopng"; $ENV{"DISPLAY"}=":0.0"; # just in case GetOptions ( 'verbose' => \$VERBOSE, ); print "Port is $PORT\n" if ( $VERBOSE); my $RepeatHeader="\r\n \r\n "; my $sessdir = tempdir ( "sessXXXXXX", TMPDIR => 1 , CLEANUP => 1); open(my $LOCKFILE ,">/tmp/sesslock") || carp("cannot create lock file"); $HTTP::Daemon::PROTO = "HTTP/1.0"; my $daemon = HTTP::Daemon->new(Listen=>3,LocalPort=>$PORT, ReuseAddr=>1) || die "cannot spawn http server"; my $sel= IO::Select->new(); $sel->add($daemon); while(my @ready = $sel->can_read()) { # 1 sec timeout foreach my $fh (@ready) { if($fh == $daemon) { # Create a new socket my $new = $daemon->accept; $sel->add($new); # add it to the select list } else { my @ip = unpack("C4",$fh->peeraddr); my $ip=join(".",@ip); print "Connection from $ip\n" if ( $VERBOSE); process_one_req($fh,$ip); $sel->remove($fh); $fh->close; } } } 1; ######################################################################################## sub process_one_req { my $connection = shift; #my $SESSIONID=shift; my $IP=shift; my $RepeatHTML=$RepeatHeader; my $receiver = $connection->get_request; if ( ! $receiver ) { return; } if (! ($receiver->method eq 'GET') ){ # Method GET $connection->send_error(RC_FORBIDDEN); return; } $receiver->url->path =~ m/^\/(.*)$/mi; my $path=$1; if ( ($path eq "monitor" ) || ($path eq "" ) ) { domonitor($connection,$RepeatHTML,$IP); return; } if ($path =~ /^screen([1-9]*)\.$format$/ ) { # Screen[1-9].$format my $scrnum=1; if ( $1 ) { $scrnum=$1; } my $res=screendumper_UNIX($scrnum); my $fname="screen".$scrnum.".$format"; if ( $fname eq "screen.$format" ) { $fname="screen1.$format"; } if ( ! -f "$sessdir/$fname" ) { $connection->send_error(404,"Could not grab the screen num $scrnum"); $connection->close; undef($connection); return; } my $response = HTTP::Response->new(200); $response->push_header('Content-Type','image/$format'); $connection->send_response($response); $connection->send_file("$sessdir/$fname"); unlink $fname; return; } # no matches $connection->send_error(RC_FORBIDDEN); } ###################################################################### sub domonitor{ my ($connection,$RepeatHTML,$SESSIONID,$IP)=@_; my $span=2; my $NumScreens=1; my $KEYLOG=""; for (my $i=1;$i<=$NumScreens;$i++){ my $fname="screen".$i.".$format"; $RepeatHTML .= "\r\n"; if ( ( $i % 2 ) == 0 ) { $RepeatHTML .= "\r\n"; } } $RepeatHTML .= ""; $RepeatHTML .= "
"; $RepeatHTML .= "
"; my $response = HTTP::Response->new(length($RepeatHTML)); $response->content($RepeatHTML); $connection->send_response($response); $KEYLOG=""; # reset untill next call } ############################################################ sub screendumper_UNIX{ my $scrnum=shift; lock($LOCKFILE); print "Calling system\n" if ( $VERBOSE ); # system("/usr/bin/import -silent -window root $sessdir/screen".$scrnum.".$format"); system($CMDLINE . ">" . $sessdir . "/screen" . $scrnum . ".". $format); print "Import done\n" if ( $VERBOSE ); unlock($LOCKFILE); return 1; } ############################################################ sub lock { my ($fh) = @_; flock($fh, LOCK_EX) or die "Cannot lock session - $!\n"; } ############################################################ sub unlock { my ($fh) = @_; flock($fh, LOCK_UN) or die "Cannot unlock session - $!\n"; }