#!/usr/bin/perl # URLToys GUI Version use strict; use Tk qw( :DEFAULT DoOneEvent MainLoop DONT_WAIT ALL_EVENTS exit); use WWW::URLToys qw/:DEFAULT ut_command_loop loadconfig $VERSION :configvars/; use LWP::TkIO; use Tk::ROText; use Tk::DialogBox; use Tk::ProgressBar; # ************************************************************ # The theme. my %theme = ( title => "URLToys / .flux ${URLToys::VERSION}", outputfont => 'courier 8', outputbg => '#000000', windowsize => '500x190', windowsizeo => '500x400', colornorm => '#aaaaaa', colorhelp => '#ff0000', coloruser => '#FFFFFF', colorfg => '#FFFFFF', colorbg => '#000055', ); # ************************************************************ load_theme(); # **** Init Variables **************************************** my @utlist; my %utvars = (); $utvars{'url'} = ''; $utvars{'dldir'} = ''; $utvars{'dlcount'} = 0; $utvars{'dltotal'} = 0; $utvars{'dlk'} = 0; $utvars{'dllen'} = 0; my $resumedir = ''; # Set all of URLToys' callbacks to talk to our $ut_callback{'print'} = \&box_output; $ut_callback{'help'} = \&box_output; $ut_callback{'output'} = \&box_output; $ut_callback{'variable'} = \&set_variable; $ut_callback{'action'} = \&action_callback; $ut_callback{'endaction'} = \&endaction_callback; $ut_callback{'begin'} = \&dl_begin; $ut_callback{'complete'} = \&dl_complete; $ut_callback{'dlupdate'} = \&ignored; $ut_callback{'makeupdate'} = \&ignored; $ut_callback{'warnuser'} = \&warnuser; # **** Tk creation and program begins here *************** sub ignored {}; my %actiontext = ( 'idle' => 'Idle', 'flux' => 'Fluxing...', 'filter' => 'Filtering Links...', 'add' => 'Adding URLs...', 'replace' => 'Replacing text in URLs...', 'save' => 'Saving...', 'load' => 'Loading...', 'size' => 'Filtering URLs by file size...', 'sort' => 'Sorting URLs...', 'make' => 'Searching...', 'download' => 'Downloading...', ); my $downloading = 0; my $output_visible = 0; my $action = 'idle'; my $mw; my $outputwindow; my $tkprog_total = 0; my $tkprog_current = 0; my $tktext_total = ''; my $tktext_current = ''; my $tktext_dldir = ''; my $tk_action = ''; # Create the main outer window ... $mw = MainWindow->new; $mw->geometry($theme{windowsize}); $mw->packPropagate(0); $mw->title($theme{title}); # This forces the script to quit if someone clicks the "close" button in the corner $mw->protocol( WM_DELETE_WINDOW => \&close_ut ); # Some basic frames my $frame = $mw->Frame(-background=>$theme{colorbg})->pack(-fill => 'both'); my $toptext = $frame->Frame(-background=>$theme{colorbg})->pack(-fill => 'x'); $toptext->Label( -font =>'14', -anchor=>'w', -justify=>'left', -textvariable=>\$tk_action, -background=>$theme{colorbg}, -foreground=>$theme{colorfg}, )->pack( -side=>'left', -fill=>'x', -padx=>6 ); $toptext->Label( -font =>'14', -anchor=>'e', -justify=>'right', -textvariable=>\$tktext_dldir, -background=>$theme{colorbg}, -foreground=>$theme{colorfg}, )->pack( -side=>'right', -fill=>'x', -padx=>6 ); $frame->Label( -anchor=>'w', -justify=>'left', -textvariable=>\$tktext_current, -background=>$theme{colorbg}, -foreground=>$theme{colorfg}, )->pack( -fill=>'x', -padx=>20 ); $frame->ProgressBar( -length=>400, -anchor=>'w', -from=>0, -to=>100, -value=>50, -blocks=>50, -width=>30, -colors=>[0,'#00FF00'], -variable=>\$tkprog_current, -background=>$theme{colorbg}, )->pack( -pady=>5, -padx=>20, -fill=>'x', ); $frame->Label( -anchor=>'w', -justify=>'left', -textvariable=>\$tktext_total, -background=>$theme{colorbg}, -foreground=>$theme{colorfg}, )->pack( -fill=>'x', -padx=>20 ); $frame->ProgressBar( -length=>400, -anchor=>'w', -from=>0, -to=>100, -value=>50, -blocks=>50, -width=>30, -colors=>[0,'#00FF00'], -variable=>\$tkprog_total )->pack( -pady=>5, -padx=>20, -fill=>'x' ); my $buttonframe = $frame->Frame(-background=>$theme{colorbg})->pack(-fill => 'x',-padx=>20); my $b_hide = $buttonframe->Button( -text=>'Show Messages', -command=>\&toggle_output, )->pack( -side=>'left', ); my $b_get = $buttonframe->Button( -text=>'Start Download / "Get"', -command=>\&start_download, -state=>'disabled', )->pack( -side=>'left', -fill=>'x', ); my $b_quit = $buttonframe->Button( -text=>'Close', -command=>\&exit, )->pack( -side=>'right', ); my $outputframe = $frame->Frame(-background=>$theme{colorbg})->pack(-fill => 'x',-pady=>10); $outputwindow = $outputframe->Scrolled('ROText', -background=>$theme{outputbg}, -scrollbars=>'e', -font => $theme{outputfont}, -relief => 'flat', -width=>80, -height=>20, ); $tk_action = "Idle"; # Sets the colors for the output window $outputwindow->tagConfigure( 'printcolor' , -foreground => $theme{coloruser} ); $outputwindow->tagConfigure( 'regularcolor', -foreground => $theme{colornorm} ); $outputwindow->tagConfigure( 'helpcolor' , -foreground => $theme{colorhelp} ); loadconfig($config_file); chdir $config_downloaddir if ($config_downloaddir); # Process pending events like window creation before fighting the initial command update_window(); # Allow one URL passed via command line if(@ARGV > 0) { my $initial_command = join ' ',@ARGV; ut_exec_command($initial_command,\@utlist); }; # After the initial command (usually a flux), enable that button if its not already $b_get->configure(-state=>'normal'); MainLoop; # **** Main Program ends here *************************** # **** Event Handlers *********************************** # Shows / hides the output window sub toggle_output { $output_visible = !$output_visible; if($output_visible) { $mw->geometry($theme{windowsizeo}); $outputframe->pack($outputwindow,-fill=>'both'); } else { $outputwindow->packForget(); $mw->geometry($theme{windowsize}); } } sub close_ut { # perform any other cleanup here exit; } sub dl_begin { my ($type,$dldir,$ignored) = @_; $utvars{'dlcount'} = 0; $utvars{'dltotal'} = 0; $utvars{'dlk'} = 0; $utvars{'dllen'} = 0; $resumedir = $dldir; box_output('output',"Starting download...",0); $b_get->configure(-text=>'Pause Download',-command=>\&stop_download); } sub dl_complete { my ($type,$dldir,$ignored) = @_; box_output('output',"Download complete.",0); $b_get->configure(-text=>'Start Download Again',-command=>\&start_download); } sub start_download { # hide output window on download $output_visible = 1; toggle_output(); ut_exec_command('get',\@utlist); } sub resume_download { ut_exec_command("resume $resumedir",\@utlist); } sub stop_download { box_output('output',"Stopping download...",0); $b_get->configure(-text=>'Resume Download',-command=>\&resume_download); ut_stop_download; } sub action_callback { my ($type,$newstate,$ignored) = @_; $action = $newstate; update_window(); } sub endaction_callback { my ($type,$endingstate,$ignored) = @_; # Do something with $endingstate if need be } sub set_variable { my ($type,$varname,$varvalue) = @_; $utvars{$varname} = $varvalue; $tktext_dldir = "to $varvalue" if($varname eq 'dldir'); update_window(); } sub update_window { $tk_action = $actiontext{$action}; # This button should always be enabled once a download starts $b_get->configure(-state=>'normal') if($action eq 'download'); if($action eq 'idle') { $tktext_current = "Idling..."; $tktext_total = "Idling..."; $tkprog_current = 0; $tkprog_total = 0; $tktext_dldir = scalar(@utlist) . " files"; } else { $tktext_current = $utvars{'ct'}; $tkprog_current = $utvars{'cp'}; $tkprog_total = $utvars{'tp'}; $tktext_total = $utvars{'tt'}; }; # handle all of those posted updates 1 while(DoOneEvent(ALL_EVENTS|DONT_WAIT)); } sub box_output { my ($type,$text,$ignored) = @_; chomp($text); $text =~ s/\r+$//; $text =~ s/^\r+//; $text .= "\n"; if($type eq 'print') { toggle_output() if(!$output_visible); $outputwindow->insert('end',$text,[qw/printcolor/]); } elsif($type eq 'help') { $outputwindow->insert('end',$text,[qw/helpcolor/]); } else { $outputwindow->insert('end',$text,[qw/regularcolor/]); } $outputwindow->see('end'); update_window; } sub load_theme { my $themefile = $urltoys_dir . "/theme"; open(THEME,"< $themefile") or return; # Do nothing gracefully while() { if(m/^([^=]+)=(.*)$/) { my ($which, $what) = ($1,$2); $theme{lc $which} = $what; } } close(THEME); } sub warnuser { my ($type,$warnlist,$ignored) = @_; my $runanyway = 'NO'; my $yo = $mw->DialogBox(-width => 400,-buttons => ['Close This Window (will not execute flux without checkbox)']); $yo->add('Label',-text=>"WARNING !!!")->pack; $yo->add('Label',-text=>"These are potentially dangerous commands in this script:")->pack; chomp for(@$warnlist); my $lb = $yo->add('Listbox')->pack(-fill => 'both'); $lb->insert('end',@$warnlist); $yo->add('Label',-text=>"If you understand what these lines do, and trust the")->pack; $yo->add('Label',-text=>"source of the .flux file, check the box and say yes.")->pack; $yo->add('Label',-text=>"Otherwise say no, and contact the creator of this file for an explanation.")->pack; $yo->add('Label',-text=>"IF YOU SAY YES AND YOUR MACHINE IS COMPROMISED -- BLAME YOURSELF",-fg=>'#FF0000')->pack; $yo->add('Checkbutton',-text=>'I understand exactly what this does. Run despite the warning.',-offvalue=>'NO',-onvalue=>'YES',-variable=>\$runanyway)->pack(-pady=>20); $yo->Show(); return 1 if($runanyway eq 'YES'); exit; return 0; }