#!/usr/bin/perl #################################################################Modules use strict; use warnings; use threads; use threads::shared; use Cwd; use Fcntl; use Net::NNTP; use Date::Parse; use Date::Format; use String::CRC32; use Convert::BulkDecoder; use MLDBM qw (DB_File Storable); use Tk::ResizeButton; use Tk::ProgressBar; use Tk::ItemStyle; use Tk::CornerBox; use Tk::ROText; use Tk::HList; use Tk::Tree; use Tk::Pod; use Tk; ############################################################Declarations our $VERSION = 3.10; my $DEBUG = 0; #1 turns on debugging, > 1 turns on verbose debugging my ($mw, %shash, %threads,); ########################################################Optional Modules if ($^O eq 'MSWin32') { eval { require Win32::Console; Win32::Console::Free() }; if ($@) { warn 'Win32::Console is not installed' . "\n"; } } ####################################################################Main local $| = 1; init(); #Start GUI, logging, and threads splash(); #Display the splash screen news_gui(); #Build GUI, destroy splash screen Tk::MainLoop(); #Process interactions ####################################################################Exit foreach my $k (sort {$a <=> $b} (keys %threads)) { warn 'Destroying Thread [' . $k . "]\n"; $shash{$k}{'die'} = 1; sleep (1); } warn "Exiting..\n"; close STDERR || warn "Unable to close STDERR\n$!"; exit; #############################################################Subroutines sub init #-------------------------------------------------------------- { #start gui { my $cbox; $mw = MainWindow->new( -title => 'NewsSurfer', -relief => 'groove', -colormap => 'new', -bd => 2, ); $mw->gridPropagate(0); $mw->withdraw; $cbox = $mw->CornerBox(); $cbox->place( '-anchor' => 'se', '-width' => 20, '-height' => 20, '-relx' => 1, '-rely' => 1, '-x' => -3, '-y' => -3, ); } #start logging { my $log = 'NewsSurfer.log'; #start logging if (my $fBytes = -s $log) { #rename log to backup log if (! rename ($log, $log . '.old')) { writeLog('e', "Can't rename: " . $log . "]\n[$!]"); } } if (! open (STDERR, '>>', $log)) { writeLog('f', "Can't create: " . $log . "]\n[$!]"); } } #create a blank killfile.txt if one doesn't exist if (! -e 'killfile.txt') { open ('FH', '>', 'killfile.txt') || writeLog('f', "Unable to create killfile.txt\n$!"); close FH || writeLog('e', "Unable to close killfile.txt\n$!"); } #launch threads writeLog('i', 'Launching thread'); foreach my $l qw ( rss xover article decode post list die return progress optionCSV ) { share ($shash{1}{$l}); $shash{1}{$l} = 0; } #share (%sHoA); #<-for implementing threaded xover in scan() #$sxover{HoA}{0} = [0,0]; $threads{1} = threads->new(\&worker, 1); writeLog('i', 'Thread 1 is active'); #initialize settings { my %OPT; dbmopen (%OPT, 'settings', 0640) || writeLog('f', "Can't create settings\n$!"); if (! $OPT{Mail}) { $OPT{Mail} = 'NewsSurfer@domain.invalid'; } if (! $OPT{DDir}) { $OPT{DDir} = '.'; } if (! (-e $OPT{DDir}) && ! (-d $OPT{DDir})) { $OPT{DDir} = '.'; } dbmclose %OPT || writeLog('f', "Can't close settings\n$!"); } return (1); } sub splash #------------------------------------------------------------ { my ($image, $splash, $canvas, $windowx, $windowy,); $windowx = $mw->screenwidth; $windowy = $mw->screenheight; my $x = ($windowx - 500) / 2; my $y = ($windowy - 288) / 2; my $geometry = '500x288+' . $x . '+' . $y; { my $imagedata = load_image(1); $image = $mw->Photo( -format => 'gif', -data => $imagedata ); } $splash = $mw->Toplevel(-takefocus => 1,); $splash->overrideredirect(1); $splash->geometry($geometry); $splash->resizable(0, 0); $canvas = $splash->Canvas()->pack( -fill => 'both', -expand => 1, ); $canvas->createImage(0,0, -image => $image, -anchor => 'nw', ); $splash->update; $mw->after(9000, sub { $splash->destroy; $mw->GeometryRequest($windowx,$windowy); $mw->Post(-5,-5); $mw->update; }); return (1); } sub writeLog #---------------------------------------------------------- { my $msgType = lc ($_[0]) || return (0); my $msgIn = $_[1] || return (0); my ($msgOut, $time,); #Prepare time { #(sec, min, hour, mday, mon, year, wday, yday, isdst) my @ary = localtime (time); $ary[4]++; foreach my $i (0..3) { if ($ary[$i] < 10) { $ary[$i] = '0' . $ary[$i]; } } $time = $ary[4] . '/' . $ary[3] . ' ' . $ary[2] . ':' . $ary[1] . ':' . $ary[0]; } #Verbose mode if ($DEBUG > 1) { my ($c1, $c2, $c3,); $c1 = (caller (1))[3] || 'main'; $c2 = (caller (2))[3] || 'main'; $c3 = (caller (0))[2]; warn $time . " VRBS [$c1 line $c3 (called by $c2)]:\n"; } #Prepare output chomp $msgIn; if ($msgType eq 'i') { $msgOut = 'INFO ' . $msgIn; } elsif ($msgType eq 'w') { $msgOut = 'WARN ' . $msgIn; } elsif ($msgType eq 'e') { $msgOut = 'ERRO ' . $msgIn; } elsif ($msgType eq 'f') { $msgOut = 'FATL ' . $msgIn; } elsif ($msgType eq 'd') { if ($DEBUG > 0) { $msgOut = 'DBUG ' . $msgIn; } else { return (1); } } else { $msgOut = 'Invalid msgType: [' . $msgType . "] in writeLog\n"; return (0); } #Output to log, close log warn $time . ' ' . $msgOut . "\n"; if ($msgType eq 'f') { $mw->destroy(); } return (1); } sub news_gui #---------------------------------------------------------- { #Widget Initialization our $sort_cnt = 3; our $msglimitOption; my $windowx = $mw->screenwidth; my $windowy = $mw->screenheight; my $sys_bg = $mw->cget(-background); my $sys_fg = $mw->cget(-foreground); $mw->gridRowconfigure(2, -weight => 1,); $mw->gridRowconfigure(4, -minsize => 8,); $mw->gridColumnconfigure(1, -weight => 1,); $mw->setPalette( background => '#a1a1a1', activebackground => '#a1a1a1', activeforeground => '#000fff', ); #Set resolution based defaults our ($sFont, $lFont, $tFont,); { my ($sfVal, $mfVal, $lfVal,); my $baseFont = '{Ariel}'; if ($windowx >= 1600) { $sfVal = 8; $mfVal = 10; $lfVal = 12; } if ($windowx >= 1400) { $sfVal = 8; $mfVal = 10; $lfVal = 12; } elsif ($windowx >= 801) { $sfVal = 8; $mfVal = 10; $lfVal = 10; } else { $sfVal = 8; $mfVal = 8; $lfVal = 10; } $sFont = $baseFont . ' ' . $sfVal; $lFont = $baseFont . ' ' . $mfVal; $tFont = $baseFont . ' ' . $lfVal; } #Create frames and panedwindow my ($pw1, $f1_main, $f2_main, $f3_main,); { $f1_main = $mw->Frame( -relief => 'flat', -bd => 2, )->grid( -in => $mw, -column => 1, -padx => 8, -sticky => 'news', -row => 1, -pady => 0, ); $f1_main->gridColumnconfigure(2, -minsize => 8,); $f1_main->gridColumnconfigure(7, -minsize => 8,); $f1_main->gridColumnconfigure(11, -minsize => 8,); $f1_main->gridColumnconfigure(14, -weight => 1,); $f2_main = $mw->Frame( -relief => 'groove', -bd => 4, )->grid( -in => $mw, -column => 1, -padx => 8, -sticky => 'news', -row => 2, -pady => 0, ); $f2_main->gridRowconfigure(1, -weight => 1,); $f2_main->gridColumnconfigure(1, -weight => 1,); $f3_main = $mw->Frame( -relief => 'groove', -bd => 2, )->grid( -in => $mw, -column => 1, -padx => 8, -sticky => 'news', -row => 3, -pady => 0, ); $f3_main->gridRowconfigure(1, -weight => 1,); $f3_main->gridColumnconfigure(1, -weight => 1,); $pw1 = $f2_main->Panedwindow( -orient => 'vertical', -relief => 'groove', -bd => 2, )->grid( -in => $f2_main, -row => 1, -sticky => 'news', -column => 1, ); } #frame 1 (toolbar frame) my $logo; our @buttons; { my $font; if ($tFont =~ m/^\{Ariel\}\s+(\d+).*$/) { $font = '{Courier New} ' . ($1 + 8); } if (! $font) { $font = '{Courier New} 16'; } $logo = $mw->Label( -text => 'NewsSurfer', -font => $font, )->grid( -in => $f1_main, -column => 14, -sticky => 'news', -row => 1, ); my $c = 1; foreach my $l qw( scan grab read_message post browse group opt show_log help quit ) { my $sub = \&{ $l; }; my $w = $f1_main->Button( -activebackground => '#a1a1a1', -bd => 0, -highlightthickness => 0, -command => sub { &$sub(); }, )->grid( -in => $f1_main, -column => $c, -sticky => 'news', -row => 1, ); push (@buttons, $w); if ($c =~ m/^(?:1|6|10)$/) { $c++; } $c++; } } #frame 2 (main display frame) #upper HList our ($lb1_grp, $lb1_k1, $lb1_k2,); { my $c = 0; my $height = 4; if ($windowx >= 1600) { $height = 9; } $lb1_grp = $pw1->Scrolled( 'HList', -highlightthickness => 1, -columns => 3, -header => 1, -height => $height, -indicator => 1, #for spacing -indicatorcmd => sub {}, -highlightcolor => '#000000', -background => '#ffffff', -foreground => '#000000', -selectbackground => '#000000', -selectforeground => '#fff000', -selectmode => 'single', -scrollbars => 'ose', ); #upper HList header columns foreach my $label ('Group', 'Last Scanned', '',) { my $w = $lb1_grp->ResizeButton( -widget => \$lb1_grp, -column => $c, -text => $label, -font => $sFont, -activebackground => '#a1a1a1', -activeforeground => '#000000', -relief => 'flat', -anchor => 'w', -borderwidth => 0, -takefocus => 0, -command => sub {}, ); $lb1_grp->columnWidth($c, -char => 1); $lb1_grp->header( 'create', $c, -itemtype => 'window', -headerbackground => '#a1a1a1', -widget => $w, -borderwidth => 1, ); $c++; } #upper HList item styles $lb1_k1 = $lb1_grp->ItemStyle('text', -anchor => 'w', -selectforeground => '#fff000', -background => '#ffffff', -foreground => '#000000', -font => $lFont, ); $lb1_k2 = $lb1_grp->ItemStyle('text', -anchor => 'e', -selectforeground => '#fff000', -background => '#ffffff', -foreground => '#000000', -font => $sFont, ); #resize upper HList according to screen resolution { my ($cntr, @colWidth,); if ($windowx >= 1600) { @colWidth = (237, 25, ''); } elsif ($windowx >= 1400) { @colWidth = (180, 25, ''); } elsif ($windowx >= 1200) { @colWidth = (160, 25, ''); } elsif ($windowx >= 801) { @colWidth = (127, 25, ''); } else { @colWidth = (95, 25, ''); } $cntr = 0; foreach my $width (@colWidth) { $lb1_grp->columnWidth ($cntr, -char => $width); $cntr++; } } } #lower HList our ($lb2_msg, $lb2_k1, $lb2_k2, $lb2_b1, $lb2_b2,); { $lb2_msg = $pw1->Scrolled( 'Tree', -highlightthickness => 1, -columns => 6, -header => 1, -separator => '.', #<-important setting (entry paths) -scrollbars => 'ose', -highlightcolor => '#000000', -background => '#ffffff', -foreground => '#000000', -selectbackground => '#000000', -selectforeground => '#fff000', -selectmode => 'extended', ); $lb2_msg->autosetmode(); #lower HList column headers my $c = 0; foreach my $label ( 'Headers', 'From', 'Parts', 'Bytes', 'Date', ' ', ) { my $w = $lb2_msg->ResizeButton( -widget => \$lb2_msg, -column => $c, -text => $label, -font => $sFont, -activebackground => '#a1a1a1', -activeforeground => '#000fff', -relief => 'flat', -anchor => 'w', -borderwidth => 0, -takefocus => 0, -command => sub { lb2_msg_sort($label) },); $lb2_msg->columnWidth($c, -char => '1'); $lb2_msg->header( 'create', $c, -itemtype => 'window', -headerbackground => '#a1a1a1', -widget => $w, -borderwidth => 1, ); $c++; } #lower HList item styles $lb2_b1 = $lb2_msg->ItemStyle('text', -anchor => 'e', -selectforeground => '#fff000', -background => '#ffffff', -foreground => '#0000ff', -font => $sFont, ); $lb2_b2 = $lb2_msg->ItemStyle('text', -anchor => 'w', -selectforeground => '#fff000', -background => '#ffffff', -foreground => '#0000ff', -font => $lFont, ); $lb2_k1 = $lb2_msg->ItemStyle('text', -anchor => 'e', -selectforeground => '#fff000', -background => '#ffffff', -foreground => '#000000', -font => $sFont, ); $lb2_k2 = $lb2_msg->ItemStyle('text', -anchor => 'w', -selectforeground => '#fff000', -background => '#ffffff', -foreground => '#000000', -font => $lFont, ); #resize lower HList according to screen resolution if ($windowx >= 1600) {$lb2_msg->columnWidth (0, -char => 210);} elsif ($windowx >= 1400) {$lb2_msg->columnWidth (0, -char => 152);} elsif ($windowx >= 1200) {$lb2_msg->columnWidth (0, -char => 132);} elsif ($windowx >= 801) {$lb2_msg->columnWidth (0, -char => 100);} else {$lb2_msg->columnWidth (0, -char => 68); } $lb2_msg->columnWidth (1, -char => 10); $lb2_msg->columnWidth (2, -char => 7); $lb2_msg->columnWidth (3, -char => 10); $lb2_msg->columnWidth (4, -char => 25); $lb2_msg->columnWidth (5, -char => ''); } #frame 3 ('Statusbar frame') our ($sb_lab,); our $sblabel = ' '; our $pb = 0; { my $font; if ($lFont =~ m/^\{Ariel\}\s+(\d+).*$/) { $font = '{Courier New} ' . $1; } if (! $font) { $font = '{Courier New} 10'; } $sb_lab = $mw->Label( -text => ' ' . $sblabel, -font => $font, -relief => 'sunken', -anchor => 'w', -bd => 2, )->grid( -in => $f3_main, -column => 1, -sticky => 'ew', -row => 1, ); $mw->ProgressBar( -variable => \$pb, -bd => 2, -length => 270, -from => 0, -to => 100, -blocks => 50, -colors => [0, '#00ff00',], #-showvalue => '1', #-valuecolor => 'black', #-relief => 'sunken', #-font => '9x15', #-valueformat => '<%.2f %%>', )->grid( -in => $f3_main, -column => 2, -sticky => 'news', -row => 1, ); } #log window our ($tl1, $txt_log,); { $tl1 = $mw->Toplevel( -title => 'View Log', -relief => 'groove', -bd => 2, ); $tl1->gridRowconfigure(1, -weight => 1,); $tl1->gridColumnconfigure(4, -weight => 1,); $tl1->transient($mw); $tl1->withdraw; my $f = $tl1->Frame( -relief => 'sunken', -bd => 2, )->grid( -in => $tl1, -columnspan => 4, -column => 1, -rowspan => 1, -row => 1, -sticky => 'news' ); $f->gridRowconfigure(1, -weight => 1,); $f->gridColumnconfigure(1, -weight => 1,); $txt_log = $f->Scrolled( 'ROText', -scrollbars => 'se', -foreground => '#ffffff', -background => '#000000', -selectforeground => '#fff000', -selectbackground => '#000000', -wrap => 'none', -relief => 'flat', -bd => 0, -width => 80, -height => 30, )->grid( -in => $f, -columnspan => 1, -column => 1, -rowspan => 1, -row => 1, -sticky => 'news' ); foreach my $csv ( 'Red,#ff0000', 'Blue,#80c0ff', 'Green,#00ff00', 'White,#ffffff', 'Yellow,#fff000' ) { my ($color,$value) = split (/,/, $csv); $txt_log->tagConfigure($color, -foreground => $value); } $txt_log->tagConfigure('Debug', -background => '#fff000', -foreground => '#000000', ); $txt_log->tagConfigure('Verbose', -background => '#ffffaa', -foreground => '#000000', ); { my $menu = $txt_log->menu; $menu->configure( -bg => $sys_bg, -fg => $sys_fg, -activeforeground => '#000fff', -activebackground => '#a1a1a1', ); $menu->delete('File'); $menu->delete('Search'); $menu->delete('View'); } my $c = 1; foreach my $label ('C l o s e', 'R e f r e s h', 'S a v e') { my ($w, $s, $sublabel, $sub,); $s = 'w'; $sublabel = $label; $sublabel =~ s/\s//g; $sub = \&{ 'log_' . lc ($sublabel); }; if ($c > 1) { $s = 'e'; } if ($c == 3) { $c++; } $w = $tl1->Button( -text => $label, -activeforeground => '#000fff', -activebackground => '#a1a1a1', -relief => 'flat', -command => sub { &$sub(); }, )->grid( -in => $tl1, -column => $c, -sticky => $s, -row => 4, ); FlashButton($w, '#181830', $sys_fg); $c++; } } #post message window our ($tl2, $txt_post, @post_entries,); { $tl2 = $mw->Toplevel( -relief => 'groove', -bd => 2, ); $tl2->title('Post Message'); #$tl2->resizable(0, 0); $tl2->transient($mw); $tl2->withdraw; $tl2->gridColumnconfigure(4, -weight => 1,); $tl2->gridRowconfigure(3, -weight => 1,); my $c = 1; foreach my $label ('From: ', 'Subject: ',) { $tl2->Label( -text => $label, )->grid( -in => $tl2, -column => 1, -sticky => 'e', -row => $c, ); my $w = $tl2->Entry( -width => 60, -background => '#ffffff', -foreground => '#000000', )->grid( -in => $tl2, -columnspan => 2, -column => 2, -rowspan => 1, -row => $c, -sticky => 'w' ); $c++; push (@post_entries, $w); } my $f = $tl2->Frame( -relief => 'sunken', -bd => 2, )->grid( -in => $tl2, -columnspan => 4, -column => 1, -rowspan => 1, -row => 3, -sticky => 'news' ); $f->gridRowconfigure(1, -weight => 1,); $f->gridColumnconfigure(1, -weight => 1,); $txt_post = $f->Scrolled( 'Text', -scrollbars => 'se', -font => $tFont, -background => '#ffffff', -foreground => '#000000', -selectforeground => '#fff000', -selectbackground => '#000000', -relief => 'flat', -wrap => 'none', -height => 30, -width => 80, )->grid( -in => $f, -column => 1, -sticky => 'news', -row => 1, ); { my $post_menu = $txt_post->menu; $post_menu->delete('File'); $post_menu->delete('Search'); $post_menu->delete('View'); } $c = 1; foreach my $label ( 'C a n c e l ', 'P o s t ', 'A t t a c h a n d P o s t', ) { my $sublabel = $label; $sublabel =~ s/\s//g; my $sub = \&{ 'post_' . lc ($sublabel); }; my $w = $tl2->Button( -text => $label, -activeforeground => '#000fff', -activebackground => '#a1a1a1', -relief => 'flat', -command => sub { &$sub(); }, )->grid( -in => $tl2, -column => $c, -sticky => 'w', -row => 4, ); FlashButton($w, '#181830', $sys_fg); $c++; } } #groups subscription window our ($tl3, $lb_grp, $grpSubSearch,); { $tl3 = $mw->Toplevel( -relief => 'groove', -bd => 2, ); $tl3->title('Groups'); $tl3->geometry("+90+35"); $tl3->resizable(0, 0); $tl3->transient($mw); $tl3->withdraw; $tl3->gridColumnconfigure(5, -weight => 1,); my $f = $tl3->Frame( -relief => 'sunken', -bd => 2, )->grid( -in => $tl3, -columnspan => 5, -column => 1, -rowspan => 1, -row => 2, -sticky => 'news' ); $lb_grp = $f->Scrolled( 'HList', -scrollbars => 'ose', -background => '#000000', -foreground => '#ffffff', -selectbackground => '#fff000', -selectforeground => '#000000', -selectmode => 'extended', -relief => 'flat', -highlightthickness => 0, -takefocus => 0, -header => 1, -columns => 2, -indicator => 1, -height => 30, -width => 96, -indicatorcmd => sub {}, #do nothing )->grid( -in => $f, -column => 1, -sticky => 'news', -row => 1, ); $lb_grp ->columnWidth (0, -char => 70); $lb_grp ->columnWidth (1, -char => 20); $lb_grp ->headerCreate(0, -text => 'Newsgroups',); $lb_grp ->headerCreate(1, -text => 'Message Count',); $f = $tl3->Frame( -relief => 'flat', )->grid( -in => $tl3, -column => 1, -columnspan => 5, -sticky => 'ew', -row => 1, -rowspan => 1, ); $f->gridColumnconfigure(3, -weight => 1,); my $e = $tl3->Entry( -background => '#ffffff', -foreground => '#000000', -textvariable => \$grpSubSearch, -width => 40, )->grid( -in => $f, -column => 1, -sticky => 'ew', -row => 1, ); $e->bind('' => sub { search($lb_grp, 'GROUP', 0); }); my $c = 2; foreach my $label ( 'S e a r c h', 'S h o w A l l N e w s g r o u p s' ) { my ($w, $showAll,); if ($c > 2) { $showAll = 1; } else { $showAll = 0; } $w = $f->Button( -text => $label, -activeforeground => '#000fff', -activebackground => '#a1a1a1', -relief => 'flat', -command => sub { search($lb_grp, 'GROUP', $showAll); } )->grid( -in => $f, -column => $c, -sticky => 'ew', -row => 1, ); FlashButton($w, '#181830', $sys_fg); $c += 2; } $c = 1; foreach my $label ( 'C l o s e ', 'U p d a t e ', 'S u b s c r i b e ', 'U n S u b s c r i b e', ) { my $sublabel = $label; $sublabel =~ s/\s//g; my $sub = \&{ 'grp_' . lc ($sublabel); }; my $w = $tl3->Button( -text => $label, -activeforeground => '#000fff', -activebackground => '#a1a1a1', -relief => 'flat', -command => sub { &$sub(); }, )->grid( -in => $tl3, -column => $c, -sticky => 'n', -row => 3, ); FlashButton($w, '#181830', $sys_fg); $c++; } } #read message window our ($tl4, $txt_read,); { $tl4 = $mw->Toplevel( -relief => 'groove', -bd => 2, ); $tl4->gridRowconfigure(1, -weight => 1,); $tl4->gridColumnconfigure(1, -weight => 1,); $tl4->title('Read Message'); $tl4->transient($mw); $tl4->withdraw; my $f = $tl4->Frame( -relief => 'sunken', -bd => 2, )->grid( -in => $tl4, -columnspan => 2, -column => 1, -rowspan => 1, -row => 1, -sticky => 'news' ); $f->gridRowconfigure(1, -weight => 1,); $f->gridColumnconfigure(1, -weight => 1,); $txt_read = $f->Scrolled( 'ROText', -scrollbars => 'se', -font => $tFont, -background => '#ffffff', -foreground => '#000000', -selectforeground => '#fff000', -selectbackground => '#000000', -wrap => 'none', -relief => 'flat', -width => 80, -height => 30, )->grid( -in => $f, -columnspan => 1, -column => 1, -rowspan => 1, -row => 1, -sticky => 'news' ); { my $read_menu = $txt_read->menu; $read_menu->configure( -bg => $sys_bg, -fg => $sys_fg, -activeforeground => '#000fff', -activebackground => '#a1a1a1', ); $read_menu->delete('File'); $read_menu->delete('Search'); $read_menu->delete('View'); } my $c = 1; foreach my $label ('C l o s e', 'R e p l y',) { my $s = 'w'; if ($c > 1) { $s = 'e' }; my $sublabel = $label; $sublabel =~ s/\s+//g; my $sub = \&{ 'read_' . lc ($sublabel); }; my $w = $tl4->Button( -text => $label, -activeforeground => '#000fff', -activebackground => '#a1a1a1', -relief => 'flat', -command => sub { &$sub(); }, )->grid( -in => $tl4, -column => $c, -sticky => $s, -row => 2, ); FlashButton($w, '#181830', $sys_fg); $c++; } } #options window our ($tl5, $quoteSig, $killFile, @OPT_widgets,); { $tl5 = $mw->Toplevel( -relief => 'groove', -bd => 2, -takefocus => 1, ); $tl5->title('Options'); $tl5->geometry("+105+70"); $tl5->resizable(0, 0); $tl5->transient($mw); $tl5->withdraw; my $f = $tl5->Frame( -bd => 3, -relief => 'sunken', -bg => '#000000', )->grid( -in => $tl5, -column => 1, -sticky => 'e', -row => 1, ); $f->gridRowconfigure(5, -minsize => 8,); $f->gridRowconfigure(10, -minsize => 96, -weight => 1,); $f->gridColumnconfigure(3, -minsize => 96,); #options window / labels { my $c = 1; foreach my $label ( 'NNTP Server: ', 'Username: ', 'Password: ', 'Email: ', ) { $f->Label( -text => $label, -background => '#000000', -foreground => '#ffffff', -anchor => 'e', -width => 15, )->grid( -in => $f, -column => 1, -sticky => 'e', -row => $c, ); $c++; } $c = 6; foreach my $label ('Download Dir: ', 'Signature File: ',) { if ($label =~ m/\b(\w+)\b/) { my $sub = \&{ 'opt_' . lc ($1); }; my $w = $f->Button( -text => $label, -anchor => 'e', -relief => 'flat', -bg => '#000000', -fg => '#ffffff', -activeforeground => '#fff000', -activebackground => '#000000', -width => 15, -command => sub { &$sub(); }, )->grid( -in => $f, -column => 1, -sticky => 'e', -row => $c, ); FlashButton($w, '#181830', '#ffffff'); $c++; } } } #options window / entry boxes { foreach my $row (1, 2, 3, 4, 6, 7,) { my $w = $f->Entry( -width => 32, -background => '#ffffff', -foreground => '#000000', )->grid( -in => $f, -column => 2, -sticky => 'w', -row => $row, ); if ($row >= 3) { if ($row == 3) { $w->configure(-show => '*',); } elsif ($row >= 6) { $w->configure(-width => 64,); } } push (@OPT_widgets, $w); } } #options window / checkbuttons { my $w = $f->Checkbutton( -foreground => '#ffffff', -background => '#000000', -activeforeground => '#ffffff', -activebackground => '#000000', -selectcolor => '#000000', -variable => \$killFile, )->grid( -in => $f, -column => 1, -sticky => 'e', -row => 8, ); push (@OPT_widgets, $w); $w = $f->Label( -text => 'Enable kill file post filtering.', -background => '#000000', -foreground => '#ffffff', )->grid( -in => $f, -column => 2, -sticky => 'w', -row => 8, ); $w = $f->Checkbutton( -foreground => '#ffffff', -background => '#000000', -activeforeground => '#ffffff', -activebackground => '#000000', -selectcolor => '#000000', -variable => \$quoteSig, )->grid( -in => $f, -column => 1, -sticky => 'e', -row => 9, ); push (@OPT_widgets, $w); $w = $f->Label( -text => 'Quote signatures in reply message.', -background => '#000000', -foreground => '#ffffff', )->grid( -in => $f, -column => 2, -sticky => 'w', -row => 9, ); } #options window / main buttons { my $w = $tl5->Button( -text => 'C l o s e & S a v e', -relief => 'flat', -activeforeground => '#000fff', -activebackground => '#a1a1a1', -command => sub { opt_close(); } )->grid( -in => $tl5, -column => 1, -sticky => 'w', -row => 2, ); FlashButton($w, '#181830', $sys_fg); } } #group right click menu our ($tl7,); { $tl7 = $mw->Toplevel( -title => 'group_rc_menu', -relief => 'raised', -borderwidth => 2.5, ); $tl7->overrideredirect(1); $tl7->resizable(0, 0); $tl7->transient($mw); $tl7->withdraw; my $f = $tl7->Frame( -relief => 'sunken', -bd => 1.5, -takefocus => 1, )->grid( -in => $tl7, -column => 1, -sticky => 'news', -row => 1, ); $f->gridRowconfigure(3, -minsize => 2,); $f->gridRowconfigure(5, -minsize => 2,); $f->bind('' => sub { $tl7->withdraw; }); $f->Frame( -relief => 'groove', -bd => 8, )->grid( -in => $f, -column => 1, -sticky => 'news', -row => 3, ); $f->Frame( -relief => 'groove', -bd => 2, )->grid( -in => $f, -column => 1, -sticky => 'news', -row => 5, ); $f->Button( -text => 'Scan', -activeforeground => '#000fff', -activebackground => '#a1a1a1', -relief => 'flat', -anchor => 'w', -width => 10, -command => sub { scan(); })->grid( -in => $f, -column => 1, -sticky => 'n', -row => 1, ); $f->Button( -text => 'Load', -activeforeground => '#000fff', -activebackground => '#a1a1a1', -relief => 'flat', -anchor => 'w', -width => 10, -command => sub { message_load(); })->grid( -in => $f, -column => 1, -sticky => 'n', -row => 2, ); $f->Button( -text => 'Search', -activeforeground => '#000fff', -activebackground => '#a1a1a1', -relief => 'flat', -anchor => 'w', -width => 10, -command => sub { search_popup(); })->grid( -in => $f, -column => 1, -sticky => 'n', -row => 4, ); $f->Button( -text => 'Clear', -activeforeground => '#000fff', -activebackground => '#a1a1a1', -relief => 'flat', -anchor => 'w', -width => 10, -command => sub { message_clear(); })->grid( -in => $f, -column => 1, -sticky => 'n', -row => 6, ); $f->Button( -text => 'Reset', -activeforeground => '#000fff', -activebackground => '#a1a1a1', -relief => 'flat', -anchor => 'w', -width => 10, -command => sub { $lb1_grp->focus; rset_cmd(); })->grid( -in => $f, -column => 1, -sticky => 'n', -row => 7, ); $f->Button( -activeforeground => '#000fff', -activebackground => '#a1a1a1', -relief => 'flat', -text => 'Remove', -anchor => 'w', -width => 10, -command => sub { $lb1_grp->focus; grp_unsubscribe('X'); })->grid( -in => $f, -column => 1, -sticky => 'n', -row => 8, ); } #message right click menu our ($tl8,); { $tl8 = $mw->Toplevel( -title => 'message_rc_menu', -relief => 'raised', -borderwidth => 2.5, ); $tl8->overrideredirect(1); $tl8->resizable(0, 0); $tl8->transient($mw); $tl8->withdraw; my $f = $tl8->Frame( -relief => 'sunken', -bd => 1.5, -takefocus => 1, )->grid( -in => $tl8, -column => 1, -sticky => 'news', -row => 1, ); $f->bind('' => sub { $tl8->withdraw; }); $f->Button( -text => 'Read', -activeforeground => '#000fff', -activebackground => '#a1a1a1', -relief => 'flat', -anchor => 'w', -width => 10, -command => sub { read_message(); })->grid( -in => $f, -column => 1, -sticky => 'n', -row => 1, ); $f->Button( -text => 'Grab', -activeforeground => '#000fff', -activebackground => '#a1a1a1', -relief => 'flat', -anchor => 'w', -width => 10, -command => sub { grab(); })->grid( -in => $f, -column => 1, -sticky => 'n', -row => 2, ); $f->Button( -text => 'Grab&Open', -activeforeground => '#000fff', -activebackground => '#a1a1a1', -relief => 'flat', -anchor => 'w', -width => 10, -command => sub { grab(1); })->grid( -in => $f, -column => 1, -sticky => 'n', -row => 3, ); $f->Button( -text => 'SelectAll', -activeforeground => '#000fff', -activebackground => '#a1a1a1', -relief => 'flat', -anchor => 'w', -width => 10, -command => sub { lb2_msg_select_all(); })->grid( -in => $f, -column => 1, -sticky => 'n', -row => 4, ); $f->Button( -text => 'Delete', -activeforeground => '#000fff', -activebackground => '#a1a1a1', -relief => 'flat', -anchor => 'w', -width => 10, -command => sub { $lb2_msg->focus; message_delete(); })->grid( -in => $f, -column => 1, -sticky => 'n', -row => 5, ); } #message download window our ($tl9, $l1_msgs, $e1_msgs, $dlnew,); { $tl9 = $mw->Toplevel( -relief => 'groove', -bd => 2, ); $tl9->title('Download Messages'); $tl9->geometry("+220+160"); $tl9->resizable(0, 0); $tl9->transient($mw); $tl9->withdraw; $tl9->gridColumnconfigure(4, -weight => 1,); my $f = $tl9->Frame( -bg => '#000000', -relief => 'sunken', -bd => 3, )->grid( -in => $tl9, -columnspan => 4, -column => 1, -rowspan => 1, -row => 1, -sticky => 'news', ); $f->gridRowconfigure(4, -minsize => 100,); $f->gridColumnconfigure(4, -weight => 1,); $l1_msgs = $f->Label( -text => '', -bg => '#000000', -fg => '#ffffff', )->grid( -in => $f, -columnspan => 3, -column => 1, -rowspan => 1, -row => 1, -sticky => 'w', ); $f->Label( -text => 'Enter the number of messages to be downloaded: ', -bg => '#000000', -fg => '#ffffff', )->grid( -in => $f, -padx => 0, -columnspan => 2, -column => 1, -pady => 8, -row => 2, -sticky => 'w', ); $f->Label( -text => 'Newest messages only (mark the rest read).', -bg => '#000000', -fg => '#ffffff', )->grid( -in => $f, -padx => 0, -column => 2, -pady => 0, -row => 4, -sticky => 'nw', ); $e1_msgs = $f->Entry( -bg => '#ffffff', -fg => '#000000', -selectbackground => '#000000', -selectforeground => '#fff000', -width => 6, )->grid( -in => $f, -padx => 0, -column => 3, -pady => 8, -row => 2, -sticky => 'w', ); $f->Checkbutton( -variable => \$dlnew, -activeforeground => '#000000', -activebackground => '#000000', -foreground => '#000000', -background => '#000000', -selectcolor => '#ffffff', )->grid( -in => $f, -padx => 0, -column => 1, -padx => 0, -row => 4, -sticky => 'ne', ); my $c = 1; foreach my $label ('O k', 'C a n c e l',) { my $sublabel = $label; $sublabel =~ s/\s//g; my $w = $tl9->Button( -text => $label, -activeforeground => '#000fff', -activebackground => '#a1a1a1', -relief => 'flat', -command => sub { $msglimitOption = uc ($sublabel); }, )->grid( -in => $tl9, -column => $c, -sticky => 'e', -row => 2, ); FlashButton($w, '#181830', $sys_fg); $c += 3; } } #Search group popup our ($tla,); { $tla = $mw->Toplevel(); $tla->title('Search Group'); $tla->geometry("+250+200"); $tla->resizable(0, 0); $tla->transient($mw); $tla->withdraw; $tla->gridColumnconfigure(1, -weight => 1,); my $f = $tla->Frame( -bd => 3, -relief => 'sunken', -bg => '#000000', )->grid( -in => $tla, -column => 1, -columnspan => 2, -sticky => 'news', -row => 1, -rowspan => 1, ); $tla->Label( -text => 'To clear previous search results, ' . 'perform an empty search.' . "\n\n\n\n", -bg => '#000000', -fg => '#ffffff', )->grid( -in => $f, -column => 1, -sticky => 'news', -row => 1, ); my $e = $tla->Entry( #$grpSubSearch is shared with the groups window -textvariable => \$grpSubSearch, -bg => '#ffffff', -fg => '#000000', -relief => 'sunken', -bd => 2, )->grid( -in => $tla, -column => 1, -sticky => 'news', -row => 2, ); $e->bind('' => sub { search($lb2_msg); }); my $w = $tla->Button( -text => 'S e a r c h', -activeforeground => '#000fff', -activebackground => '#a1a1a1', -relief => 'flat', -command => sub { search($lb2_msg); } )->grid( -in => $tla, -column => 2, -sticky => '', -row => 2, ); FlashButton($w, '#181830', $sys_fg); } $pw1->add($lb1_grp, $lb2_msg,); #Bindings $tl2->protocol(WM_DELETE_WINDOW => \&post_cancel); $tl3->protocol(WM_DELETE_WINDOW => \&grp_close); $tl4->protocol(WM_DELETE_WINDOW => \&read_close); $tl9->protocol(WM_DELETE_WINDOW => \&dlmsgs_cancel); $tl1->protocol(WM_DELETE_WINDOW => sub {$tl1->withdraw;}); $tl5->protocol(WM_DELETE_WINDOW => sub {$tl5->withdraw;}); $tla->protocol(WM_DELETE_WINDOW => sub {$tla->withdraw;}); $logo->bind('' => sub { $logo->configure(-text=>'');$mw->update;$mw->after(200); $logo->configure(-text=>'N');$mw->update;$mw->after(180); $logo->configure(-text=>'Ne');$mw->update;$mw->after(130); $logo->configure(-text=>'New');$mw->update;$mw->after(120); $logo->configure(-text=>'News');$mw->update;$mw->after(160); $logo->configure(-text=>'NewsS');$mw->update;$mw->after(130); $logo->configure(-text=>'NewsSu');$mw->update;$mw->after(100); $logo->configure(-text=>'NewsSur');$mw->update;$mw->after(120); $logo->configure(-text=>'NewsSurf');$mw->update;$mw->after(130); $logo->configure(-text=>'NewsSurfe');$mw->update;$mw->after(110); $logo->configure(-text=>'NewsSurfer');$mw->update;$mw->after(100); }); $lb1_grp ->bind('' => sub { raise_rc_menu($tl7); }); $lb1_grp->bind(''=> sub { b4_grp_unsubscribe('X'); }); $lb2_msg ->bind('' => sub { my @sel = $lb2_msg->selectionGet; if ($sel[1]) { raise_rc_menu($tl8); } else { $lb2_msg->Tk::HList::ButtonRelease_1; raise_rc_menu($tl8, $lb2_msg); } }); $lb2_msg ->bind('' => sub { b2_grab_cmd(1); }); $lb2_msg->bind('' => \&read_message); $lb1_grp->bind('' => \&message_load); $lb1_grp->bind('' => \&scan); $lb1_grp->bind('' => \&message_clear); $lb1_grp->bind('' => \&message_clear); $lb1_grp->bind('' => \&rset_cmd); $lb1_grp->bind('' => \&rset_cmd); $lb2_msg->bind('' => \&message_delete); $lb2_msg->bind('' => \&read_message); $lb2_msg->bind('' => \&lb2_msg_select_all); $lb2_msg->bind('' => \&lb2_msg_select_all); $lb2_msg->bind('' => \&lb2_msg_select_end); $lb2_msg->bind('' => \&lb2_msg_select_hom); $lb2_msg->bind('' => \&message_delete); $lb2_msg->bind('' => \&message_delete); { #bind images onto buttons my $c = 10; foreach my $b (@buttons) { MainButtons($b, $c); $c++ } } #Defaults warn 'Started at: (' . localtime(time) . ")\n"; foreach my $p (glob 'part*.pt') { #todo - recovery if (! unlink $p) { writeLog('e', "Can't delete part: [" . $p . "]\n$!"); } } $sblabel = 'Ready'; $msglimitOption = 0; display_groups(); $lb1_grp->focus(); ready(); #Callbacks sub nntpconnect #----------------------------------------------------- { #Called whenever a connection to the server needs to be established #This sub is also used by the worker thread my ($nntp, $serv, $user, $pass,); eval { my %OPT; dbmopen (%OPT, 'settings', 0640) || writeLog('f', "Can't create settings\n$!"); $serv = $OPT{Serv}; $user = $OPT{User}; $pass = $OPT{Pass}; dbmclose %OPT || writeLog('e', "Can't close settings\n$!"); }; if (! $@) { #db access ok, try to connect, will retry once if needed foreach my $c (1..2) { writeLog('i', 'Connection attempt: [' . $c . ' of 2]'); eval { $nntp->quit }; $nntp = Net::NNTP->new( $serv, Debug => 1, Timeout => 5, Reader => 1, ); if (! $nntp) { if ($c > 1) { #could not connect writeLog('e', "Can't connect to server: [" . $serv . "]"); return (0); } else { #wait 1 second and then try one more time my $a = $c + 1; writeLog('w', "Couldn't connect to server: [" . $serv . "]"); update_status('Retrying connection...'); next; } } else { #connected last; } } } else { #error accessing db, not connected writeLog('e', "Can't connect to server, DB error: [$@]"); return (0); } #Connection ok, authenticate user if credentials are defined if (defined $user) { my $ok; if (! defined $pass) { writeLog('w', "Null password supplied"); $pass = "\n"; } eval { $ok = $nntp->authinfo($user, $pass) }; if (! $ok || $@) { #possible errors - timeout or access denied #authinfo will only return true or false so no easy way to tell #the reason a false return value was produced writeLog('w', 'Problem connecting, retrying authinfo'); update_status('Retrying connection...'); #retry connecting with authentication once more $nntp->quit; $nntp = Net::NNTP->new( $serv, Debug => 1, Timeout => 5, Reader => 1, ); if ($nntp) { $ok = $nntp->authinfo($user, $pass); if (! $ok || $@) { writeLog('e', 'Unable to authenticate with server'); writeLog('d', 'Serv: ' . $serv . 'User: ' . $user . 'Pass: ' . $pass ); return (0); } } } } else { writeLog('w', 'Logon ID not supplied, bypassing authentication'); } #return a reference to the nntp object if (! $nntp) { writeLog('e', 'Unable to connect to server'); return (0); } return (\$nntp); } sub scan #------------------------------------------------------------ { #called from a button pressed in the main window or rc menu my (@sel,); #clear old newsgroup's display $lb2_msg->focus; $lb2_msg->delete('all'); $mw->update; #determine which newsgroup to scan @sel = $lb1_grp->selectionGet; if (defined $sel[0]) { $mw->Busy(-recurse => 1); my ($group, $nntpRef,); $group = $lb1_grp->itemCget($sel[0], 0, -text); #connect to nntp server update_status('Connecting to NNTP server...'); update_status('4', 'PROGRESSBAR'); $nntpRef = nntpconnect(); if($nntpRef) { #determine article number range available on the server my ($dlmsg, $totmsgs, $rng, @nfo,); update_status('Scanning newsgroup...'); update_status('4', 'PROGRESSBAR'); @nfo = $$nntpRef->group($group); #<-blocks if ($nfo[1]) { shift @nfo; pop @nfo; $totmsgs = $nfo[1] - $nfo[0]; $totmsgs++; $dlmsg = $nfo[1] - $nfo[0]; $dlmsg++; #load group db and determine which headers to download next. if (-e $group . '.grp') { update_status('Removing expired articles...'); update_status('4', 'PROGRESSBAR'); tie my %file, 'MLDBM', $group . '.grp', O_CREAT|O_RDWR, 0640 || writeLog('f', 'Cant open MLDBM'); #remove expired articles my $tmp = $file{HEADERDB}; while (my $k = each %$tmp) { #k is a message number of a previously downloaded message #remove messages that are no longer on the server if ($k < $nfo[0]) { delete $tmp->{$k}; } } #determine the new article range my (@keys, $lastArticle,); update_status('4', 'PROGRESSBAR'); @keys = sort {$b <=> $a} (keys %$tmp); $lastArticle = $keys[0] || 0; writeLog( 'd', 'Last msgID downloaded: [' . $lastArticle . "]" ); writeLog( 'd', 'First new msgID: [' . $nfo[1] . "]" ); $lastArticle++; #save to db $file{HEADERDB} = $tmp; undef $tmp; untie %file; #check for new messages if ($lastArticle <= $nfo[1]) { #there are new messages in the newsgroup undef $rng; if ($lastArticle != 1) { shift @nfo; unshift (@nfo, $lastArticle); } $totmsgs = $nfo[1] - $nfo[0]; $totmsgs++; $dlmsg = $nfo[1] - $nfo[0]; $dlmsg++; writeLog('i', '[' . $totmsgs . " new message(s)"); #enforce maximum message download limit if ($totmsgs > 4999) { my $r = msglimit($totmsgs); if ($r == 0) { $$nntpRef->quit(); $dlmsg = 0; } elsif ($dlnew == 1) { $nfo[0] = $nfo[1] - $r; $dlmsg = $nfo[1] - $nfo[0]; } else { $nfo[1] = $nfo[0] + $r; $dlmsg = $nfo[1] - $nfo[0]; } } } else { #there are no new messages on the newsgroup writeLog('i', "No new messages..\n"); update_status('No new messages..'); undef $dlmsg; #load old messages displayheaders('OLD'); } } else { #Newly subscribed or reset group; create a new db. writeLog('i', 'Creating a new db for ' . $group); update_status('Initializing newsgroup...'); update_status('4', 'PROGRESSBAR'); if ($totmsgs >= 5000) { #popup d/l messages my $mLim = msglimit($totmsgs); writeLog('i', "Message download limit: [" . $mLim . "]"); if ($mLim == 0) { $dlmsg = 0; } elsif ($dlnew == 1) { $nfo[0] = $nfo[1] - $mLim; } else { $nfo[1] = $nfo[0] + $mLim; } $dlmsg = $nfo[1] - $nfo[0]; } } if ($dlmsg) { my ($href, %xover); $rng = \@nfo; #download this groups' xover information, then disconnect update_status( 'Downloading ' . $dlmsg . ' of ' . $totmsgs . ' new headers' ); update_status('16', 'PROGRESSBAR'); #Due to a limitation of threads::shared #It is difficult but possible to not block here #Error: Invalid value for shared scalar $href = $$nntpRef->xover($rng); #<-blocks if ($href) { %xover = %$href; writeLog('i', "Header download completed"); #(%xover is a HoA) $_ is msgnum #$xover{$_}[0] #subject #$xover{$_}[4] #references #$xover{$_}[1] #from #$xover{$_}[5] #bytes #$xover{$_}[2] #date #$xover{$_}[6] #lines *parts* #$xover{$_}[3] #msg-id #$xover{$_}[7] #xref:full *read* undef $href; } if (keys %xover) { #xover ok update_status('Preparing messages...'); my (%file, $tmp,); my $subj_sav = ' '; my $cnt = 0; tie %file, 'MLDBM', $group . '.grp', O_CREAT|O_RDWR, 0640 || writeLog('f', "Can't open MLDBM"); $tmp = $file{MULTIPARTDB}; while (my $k = each %xover) { #handle multipart messages if ($pb >= 100) { $pb = 0; } if ($cnt > 500) { for (1..1) { $pb++; $cnt = 0; $mw->update; } } else { $cnt++; } if ($xover{$k}[0] =~ m/ (\p{Any}+) #the main subject $1 [\(\[\{]+? #followed by a ( or [ or { (\d+) #followed by a digit $2 [\/\-]+? #followed by a foward slash or dash (\d+) #followed by a digit $3 [\)\]\}]+? #followed by a ) or ] or } (\p{Any}*) #additional subject text $4 /gx ) { #it is a multipart message #$1 = sub, $2 = pt, $3 = tot, $4 = more sub my $newsubj; $newsubj = $1 . $4; #record multipart message ids $tmp->{$newsubj}{$2} = $xover{$k}[3]; #combine parts for display, update subject if ($1 ne $subj_sav) { $subj_sav = $1; #it is a new subject $xover{$k}[6] = $3; #parts total $xover{$k}[0] = $newsubj; #edited subject } else { #seen this subject already delete $xover{$k}; } } else { #not a multipart message $xover{$k}[6] = 1; } } $file{MULTIPARTDB} = $tmp; undef $tmp; #remove multipart duplicates and log new message id's update_status('Combining parts...'); update_status('16', 'PROGRESSBAR'); my %seen; while (my $k = each %xover) { if ($xover{$k}) { if ($xover{$k}[6] != 1) { my $l; $l = $xover{$k}[0] . $xover{$k}[1] . $xover{$k}[6]; # subject from parts if (defined $seen{$l}) { delete $xover{$k}; } $seen{$l} = 1; } } } undef %seen; #count headers, format the time/date, remove old headers update_status('Formatting Time/Date...'); update_status('16', 'PROGRESSBAR'); my @mNums = sort {$a <=> $b} (keys (%xover)); my $keyTot = $#mNums; foreach my $mNum (@mNums) { my $now = time; my $epoch = str2time ($xover{$mNum}[2]); my $age = $now - $epoch; if ($age < 2592000 || $mNum == $nfo [1]) { chomp ($xover{$mNum}[2] = ctime ($epoch)); } else { if ($keyTot > 1) { #<-bug when all msgs > 30 days delete $xover{$mNum}; $keyTot--; } } } #save new headers to group header db my $newheadercount = 0; update_status('Saving Group...'); update_status('16', 'PROGRESSBAR'); $tmp = $file{HEADERDB}; while (my $messagenumber = each %xover) { for my $c (0..7) { $tmp->{$messagenumber}[$c] = $xover{$messagenumber}[$c]; } $newheadercount++; } $file{HEADERDB} = $tmp; undef $tmp; untie %file; #display messages writeLog('i', "Displaying [$newheadercount] new messages\n"); update_status('Displaying messages...'); update_status('4', 'PROGRESSBAR'); displayheaders('NEW', $newheadercount); #update last scanned time { dbmopen (my %SBSCRIBE, 'sbscribe', 0640) || writeLog('f', "Can't create sbscribe\n$!"); my $stime; chomp ($stime = ctime(time)); $SBSCRIBE{$group} = $stime; dbmclose %SBSCRIBE; } } else { #xover error writeLog('e', "Trouble reading xover header information"); } } } else { #unable to get group information from server writeLog('e', "Unable to get group information from server"); } $$nntpRef->quit(); } else { #could not connect to server writeLog('e', "Couldn't connect to the server"); update_status('Could not connect to the server'); $mw->after(1000); } } else { #no group selected to scan return (0); } #cleanup gui display_groups(); $lb2_msg->focus; if ($sel[0]) { $lb1_grp->selectionSet($sel[0]) }; ready(); return (1); } sub msglimit #-------------------------------------------------------- { #called from sub scan my $totmsgs = $_[0] || 'NULL'; $dlnew = 0; my $ret; $ret = dlmsgs('PROMPT', $totmsgs); $ret = dlmsgs($ret, $totmsgs); #return number of messages to be downloaded to the scan subroutine return ($ret); } sub dlmsgs #---------------------------------------------------------- { #called from sub msglimit my $opt = uc ($_[0]) || 'NULL'; my $totmsgs = $_[1] || 'NULL'; my $maxdl = $e1_msgs->get || '5000'; $e1_msgs->delete(0, 'end'); $e1_msgs->insert(0, $maxdl); if ($opt eq 'PROMPT') { $l1_msgs->configure( -text => "There are more than " . $totmsgs . ' ' . 'unread messages in this group.' ); $tl9->Popup; $e1_msgs->focus; $mw->update; $mw->Unbusy; $mw->waitVariable(\$msglimitOption); #wait for user click $mw->Busy(-recurse => 1); return ($msglimitOption); } elsif ($opt eq 'OK') { if ($maxdl =~ m/^\D/) { $maxdl = 0; } elsif ($maxdl > $totmsgs) { $maxdl = $totmsgs; } } elsif ($opt eq 'ALL') { $maxdl = $totmsgs; } elsif ($opt eq 'CANCEL') { $maxdl = 0; } else { writeLog('e', 'Invalid dlmsgs option: [' . $opt . "]"); $maxdl = 0; } $tl9->withdraw; return ($maxdl); } sub displayheaders #-------------------------------------------------- { #called from: scan, lower hlist header buttons, and message_load #when opt1 is set to 'NEW' then opt2 should specify # of new msgs #if sort is requested, column to sort and the sort type are needed my $opt1 = uc ($_[0]) || 'OLD'; my $opt2 = $_[1] || 0; my $sort = $_[2] || 0; my (%file, $group, $msgHeaderDB, %tmpMsgDB, @msgNums,); my (@parentsWithNewReplies,); my $c = 0; writeLog('i', "Preparing headers"); #Determine which newsgroup is selected { my @sel = $lb1_grp->selectionGet; if (defined $sel[0]) { $group = $lb1_grp->itemCget($sel[0], 0, -text); } else { writeLog('w', "No valid group selected for header display"); return (0); } } #Load group db for (1..10) { $pb++; $mw->update; } if (! tie %file, 'MLDBM', $group . '.grp', O_CREAT|O_RDWR, 0640) { writeLog('f', "Can't open group DB"); } $msgHeaderDB = $file{HEADERDB}; #Re-format DB to alot for discussion thread grouping #<-Test #Leave message db intact, create tmpMsgDB #$mldbm{HEADERDB}{MESSAGENUMBER}[0,1,3,4] #subj,from,msgId,refs #$mldbm{HEADERDB}{MESSAGENUMBER}[msgitem1, etc..] #tmpMsg{firstRef}{parentMsgNum}{refMsgNums}[msgitem1, etc..] update_status ('Processing group DB...'); dbmopen (my %OPT, 'settings', 0640) || writeLog('f', "Can't read settings\n$!"); foreach my $msgNum (sort { $b <=> $a } (keys (%$msgHeaderDB))) { my ($firstRef, $parentMsgNum,); writeLog('d', 'MsgNum: [' . $msgNum . "]"); #Refresh display { if ($pb >= 100) { $pb = 0; } if ($c > 100) { for (1..10) { $pb++; $mw->update; $c = 0; } } else { $c++; } } #Killfile filtering { if ($OPT{Kfile}) { #determine if this message should be filtered my $name = $msgHeaderDB->{$msgNum}->[1]; if (killfile($group, $name) == 1) { #do not load this header writeLog('w', 'Poster: ' . $name . " was filtered by killfile" ); next; } } } #Check if this message has references to other messages { my $refs = $msgHeaderDB->{$msgNum}->[4]; if ($refs && $refs =~ m/^(<[^>]+>).*$/) { #message references other messages #categorize this message under the first message reference $firstRef = $1; #check group db, determine parent message message number my $found; foreach my $pMsgNum (sort {$b <=> $a} (keys %$msgHeaderDB)) { my ($mId,); $mId = $msgHeaderDB->{$pMsgNum}->[3] || $pMsgNum; $mId = quotemeta $mId; if ($firstRef =~ m/$mId/) { #found a msgID that matches the firstRef $parentMsgNum = $pMsgNum; $found++; last; } } if (! $found) { #did not find a msgID that matches firstRef #use this msgNum for parentMsgNum writeLog('d', "Unable to determine the parent MsgNum"); $parentMsgNum = $msgNum; } } else { #<-test #no refs found, use msgNum for firstRef and parentMsgNum $parentMsgNum = $msgNum; $firstRef = $msgNum; } } #Save to tmpDB writeLog('d', 'Saving msgNum: [' . $msgNum . "] to tmpDB\n" . ' firstRef: [' . $firstRef . "]\n" . ' parentMsgNum: [' . $parentMsgNum . "]" ); push ( @{$tmpMsgDB{$parentMsgNum}{$msgNum}}, $msgHeaderDB->{$msgNum} ); #Process next message number } dbmclose %OPT || writeLog('e', "Can't close OPT db\n$!"); #Sort if ($sort) { #<-test #Sort requested my ($col,$opt) = split (/,/, $sort); writeLog('d', 'Sorting options: [' . $sort . "]"); if ($sort_cnt % 2) { if ($opt == 1) { @msgNums = sort { lc ($tmpMsgDB{$b}{$b}[$col]) cmp lc ($tmpMsgDB{$a}{$a}[$col]) } keys %tmpMsgDB; } elsif ($opt == 2) { @msgNums = sort { $tmpMsgDB{$b}{$b}[$col] <=> $tmpMsgDB{$b}{$b}[$col] } keys %tmpMsgDB; } else { @msgNums = sort { str2time ($tmpMsgDB{$b}{$b}[$col]) <=> str2time ($tmpMsgDB{$b}{$b}[$col]) } keys %tmpMsgDB; } } else { if ($opt == 1) { @msgNums = sort { lc ($tmpMsgDB{$b}{$b}[$col]) cmp lc ($tmpMsgDB{$b}{$b}[$col]) } keys %tmpMsgDB; } elsif ($opt == 2) { @msgNums = sort { $tmpMsgDB{$b}{$b}[$col] <=> $tmpMsgDB{$b}{$b}[$col] } keys %tmpMsgDB; } else { @msgNums = sort { str2time ($tmpMsgDB{$b}{$b}[$col]) <=> str2time ($tmpMsgDB{$b}{$b}[$col]) } keys %tmpMsgDB; } } } else { @msgNums = sort {$b <=> $a} (keys %tmpMsgDB); } #Insert and display the headers in the lower HList $mw->update; my $counter = 0; update_status ('Displaying headers...'); writeLog('i', "Displaying headers"); foreach my $pMsgNum (@msgNums) { my @cMsgNums = keys (%{$tmpMsgDB{$pMsgNum}}); my $refCount = keys (%{$tmpMsgDB{$pMsgNum}}); my $cMsgNum = $cMsgNums[0]; writeLog('d', 'Message has refCount: [' . $refCount . "]"); if ($refCount && $refCount > 1) { #message has other messages referencing it #create parent Hlist entry { my $msgAref = \@{$tmpMsgDB{$pMsgNum}{$pMsgNum}}; if ($opt1 eq 'NEW' && $counter <= $opt2) { loadHlist('BLUE', 'PARENT', $pMsgNum, $pMsgNum, $msgAref); } else { loadHlist('BLACK', 'PARENT', $pMsgNum, $pMsgNum, $msgAref); $msgHeaderDB->{$pMsgNum}[8] = 1; } $counter++; } #add child Hlist entries to this parent entry foreach my $cMsgNum( sort {$b <=> $a} (keys %{$tmpMsgDB{$pMsgNum}}) ) { if ($cMsgNum eq $pMsgNum) { next; #dont load the original post twice } $counter++; my $msgAref = \@{$tmpMsgDB{$pMsgNum}{$cMsgNum}}; if ($opt1 eq 'NEW' && $counter <= $opt2) { loadHlist('BLUE', 'CHILD', $pMsgNum, $cMsgNum, $msgAref); #added a new reply to the parent entry #save the pMsgNum so later we can indicate the new reply push (@parentsWithNewReplies, $pMsgNum); } else { loadHlist('BLACK', 'CHILD', $pMsgNum, $cMsgNum, $msgAref); $msgHeaderDB->{$pMsgNum}[8] = 1; } #remove added message from tmpMsgDB delete $tmpMsgDB{$pMsgNum}{$cMsgNum}; } } else { #create only a parent Hlist entry my $msgAref = \@{$tmpMsgDB{$pMsgNum}{$cMsgNum}}; $counter++; if ($opt1 eq 'NEW' && $counter <= $opt2) { loadHlist('BLUE', 'PARENT', $pMsgNum, $pMsgNum, $msgAref); } else { loadHlist('BLACK', 'PARENT', $pMsgNum, $pMsgNum, $msgAref); $msgHeaderDB->{$pMsgNum}[8] = 1; } } #next parent message } undef %tmpMsgDB; #Apply additional formatting { update_status ('Formatting headers...'); my $style1 = $lb2_msg->ItemStyle('text', -anchor => 'w', -selectforeground => '#fff000', -background => '#ffffff', -foreground => '#2040A0', -font => '{Arial} 10 italic', ); my $style2 = $lb2_msg->ItemStyle('text', -anchor => 'w', -selectforeground => '#fff000', -background => '#ffffff', -foreground => '#2040ff', -font => '{Arial} 10 bold italic', ); foreach my $pPath ($lb2_msg->infoChildren()) { #format parent messages marked as 'read' if ($msgHeaderDB->{$pPath}->[7] eq 'read') { $lb2_msg->itemConfigure($pPath, 0, -style => $style1,); } #format child messages marked as 'read' foreach my $cPath ($lb2_msg->infoChildren($pPath)) { if ($cPath =~ m/^.+\.([^\.\s]+)$/) { my $cPathClean = $1; if (! exists $msgHeaderDB->{$cPathClean}) { writeLog('e', 'Path: [' . $cPathClean . "] not defined"); next; } if ($msgHeaderDB->{$cPathClean}->[7] eq 'read') { $lb2_msg->itemConfigure($cPath, 0, -style => $style1,); } } } #format message thread indicator if ($lb2_msg->infoChildren($pPath)) { eval { $lb2_msg->indicator('create', $pPath, -itemtype => 'image', -image => $mw->Getimage('plus'), ) }; eval { $lb2_msg->open($pPath) }; eval { $lb2_msg->close($pPath) }; } } #indicate if parent message has a new reply foreach my $pmn (@parentsWithNewReplies) { eval { $lb2_msg->itemConfigure($pmn, 0, -style => $style2,) }; } $mw->update; } #Save db update_status ('Saving group DB...'); $file{HEADERDB} = $msgHeaderDB; undef $msgHeaderDB; untie %file; $mw->update; return (1); } sub loadHlist #------------------------------------------------------- { #requires the following startup parameters: #color, parent or child, parent id, id, message aref, read my $color = uc $_[0] || return (0); my $mode = uc $_[1] || return (0); my $pid = $_[2] || return (0); my $cid = $_[3] || return (0); my $aref = $_[4] || return (0); my $entryPath; my @paths; my $c = 0; writeLog('d', 'loadHlist aref: [' . $aref . '] ' . 'mode: [' . $mode . "]") ; writeLog('d', 'loadHlist pid: [' . $pid . '] ' . 'cid: [' . $cid . "]" ); #Determine mode if ($mode eq 'PARENT') { $entryPath = $pid; } elsif ($mode eq 'CHILD') { $entryPath = $pid . '.' . $cid; } else { writeLog('e', 'Invalid mode in loadHlist: [' . $mode . "]"); return (0); } #Create entry path { my $path; writeLog('d', 'Attempting to create path: [' . $entryPath . "]"); eval { $path = $lb2_msg->add($entryPath) }; if (! $@) { writeLog('d', 'Created path: [' . $path . "]"); } else { writeLog('e', 'Unable to create path: [' . $entryPath . "]"); return (0); } } #Create entry foreach my $headerCol (0, 1, 6, 5, 2,) { #(0, 1, 6, 5, 2) = (subject, from, parts, bytes, date) my $style; my $text = $aref->[0]->[$headerCol]; if (! defined $text) { writeLog('e', "Header column: [$headerCol] is undefined"); writeLog('w', "Not displaying invalid message"); return (0); } if ($c < 2) { $style = 2; } else { $style = 1; } #check color and style if ($color eq 'BLUE') { if ($style == 1) { $lb2_msg->itemCreate($entryPath, $c, -itemtype => 'text', -style => $lb2_b1, -text => $text, ); } elsif ($style == 2) { $lb2_msg->itemCreate($entryPath, $c, -itemtype => 'text', -style => $lb2_b2, -text => $text, ); } } elsif ($color eq 'BLACK') { if ($style == 1) { $lb2_msg->itemCreate($entryPath, $c, -itemtype => 'text', -style => $lb2_k1, -text => $text, ); } elsif ($style == 2) { $lb2_msg->itemCreate($entryPath, $c, -itemtype => 'text', -style => $lb2_k2, -text => $text, ); } } $c++; } return (1); } sub killfile #-------------------------------------------------------- { #requires from, returns -1 on error, 1 if filtered, 0 if not my $group = quotemeta (uc ($_[0])) || 'ALL'; my $from = quotemeta (uc ($_[1])) || return (-1); #$from =~ s/\/\s+/ /; #load up killfile rules if (open ('KF', '<', 'killfile.txt')) { my $lNum; while (my $line = ()) { $lNum++; chomp $line; if ($line =~ m/^$/) { next; } my ($grp,$rul) = split (/,/, $line); #warn "In killfile rule: $rul group: $grp from: $from\n"; if (defined $grp && defined $rul) { if ($grp eq 'ALL' || $grp =~ m/$group/i) { my $rClean = quotemeta (uc $rul); # warn "in killfile ruleclean: $rClean\n"; if ($from =~ m/^$rClean\s*.*$/) { #killfile entry found somewhere in from field return (1); } } } else { #error parsing killfile writeLog('w', "Unexpected data in killfile, line: [$lNum]"); } } close KF || writeLog('e', "Unable to close killfile.txt\n$!"); } else { writeLog('e', "Unable to open killfile.txt\n$!"); return (-1); } #entry ok return (0); } sub message_load #---------------------------------------------------- { #called from the main window, rc menu, or message_clear() my ($group, $return,); update_status('Loading newsgroup...'); $mw->Busy(-recurse => 1); $lb2_msg->focus; $mw->update; #load messages $lb2_msg->delete('all'); for (1..10) { $pb++; $mw->update; } my $ret = displayheaders('OLD'); if ($ret) { $return = 1; } else { $return = 0; } ready(); $lb2_msg->focus; $mw->update; return ($return); } sub message_clear #--------------------------------------------------- { #called from the rc menu my ($group, @sel, @paths, %file,); update_status('Clearing previously scanned messages from group...'); $mw->Busy(-recurse => 1); $mw->update; #get a list of paths for the message hlist lb2_msg_select_all(); @paths = $lb2_msg->infoSelection; if (! $paths[0]) { my $ret = displayheaders('OLD'); if ($ret) { lb2_msg_select_all(); @paths = $lb2_msg->infoSelection; } else { writeLog('e', 'Unable to clear group'); ready(); $mw->Unbusy; return (0); } } #determine group @sel = $lb1_grp->selectionGet; eval { $group = $lb1_grp->itemCget($sel[0], 0, -text) }; if ($@) { writeLog('e', "No valid group selected to clear"); ready(); return (0); } #open the selected groups' DB file if (-e $group . '.grp') { tie %file, 'MLDBM', $group . '.grp', O_CREAT|O_RDWR, 0640 || writeLog('f', "Can't open group DB"); #select this groups HEADERDB table my $tmp = $file{HEADERDB}; #clear the selected group, and update it's HEADERDB my $c = 1; foreach my $path (@paths) { if ($path != $paths[0]) { #my @subPaths; #<-todo, remove re's too #eval { $lb2_msg->infoChildren($path) }; #if ($subPaths[0]) { # eval { $lb2_msg->delete('siblings', $path) }; # foreach my $cPath (@subPaths) { # delete $tmp->{$cPath}; # } # redo; #} eval { $lb2_msg->delete('entry', $path) }; delete $tmp->{$path}; if ($c == 100) { $mw->update; undef $c; } $c++; } } $file{HEADERDB} = $tmp; #delete this groups' MULTIPARTDB delete $file{MULTIPARTDB}; } else { writeLog('e', 'Unable to locate group file: ' . $group . '.grp'); } #close the DB file and finish up untie %file; writeLog('w', 'Cleared group: ' . $group); ready(); return (1); } sub lb2_msg_sort #---------------------------------------------------- { #called from a button pressed in the main window my $caller = uc ($_[0]) || ' '; my ($col, $opt,); if ($caller eq ' ') { return (1); } elsif ($caller eq 'HEADERS') { $col = 0; $opt = 1; } elsif ($caller eq 'FROM') { $col = 1; $opt = 1; } elsif ($caller eq 'PARTS') { $col = 6; $opt = 2; } elsif ($caller eq 'BYTES') { $col = 5; $opt = 2; } elsif ($caller eq 'DATE') { $col = 2; $opt = 3; } else { writeLog('e', 'Invalid sort option: [' . $caller . "]"); return (0); } $sort_cnt++; $mw->Busy(-recurse => 1,); $lb2_msg->delete('all'); update_status ('Sorting...'); displayheaders('OLD', 0, $col . ',' . $opt); ready(); return (1); } sub grab #------------------------------------------------------------ { #called from a button in the main window or the rc menu my $open = $_[0] || 0; my (%file, @sel, @grabs, $group,); $pb = 0; #grab what? @sel = $lb1_grp->selectionGet; eval { $group = $lb1_grp->itemCget($sel[0], 0, -text) }; if ($@) { writeLog('w', 'No valid group selected for grab'); ready(); return (0); } $mw->update; $lb2_msg->focus; $mw->Busy(-recurse => 1); @grabs = $lb2_msg->selectionGet; if (! $group || ! @grabs) { writeLog('e', 'Selection error'); $mw->Unbusy; ready(); return (0); } #load group multipart db (%multi is a HoHoA) subj->part = msg id tie %file, 'MLDBM', $group . '.grp', O_CREAT|O_RDWR, 0640 || writeLog('f', "Can't open group DB",); #following commented code used for testing purposes #foreach my $subj (keys %{$file{MULTIPARTDB}}) { # warn "\nsubj is: $subj\n"; # foreach my $partnum (keys %{$file{MULTIPARTDB}{$subj}}) { # warn "partnum is: $partnum\n"; # warn "msgid is: $file{MULTIPARTDB}{$subj}{$partnum}\n"; # } #} #get selection(s) foreach my $path (@grabs) { my ($subje, $parts, @art, $aref, $treturn, $mNumber,); $mw->after(500); #check if this is a child entry if ($path =~ m/^.+\.([^\.\s]+)$/) { $mNumber = $1; } else { $mNumber = $path; } #read subject $subje = $lb2_msg->itemCget($path, 0, -text); $parts = $lb2_msg->itemCget($path, 2, -text); writeLog('d', "$subje, $parts, $mNumber, $path\n"); #lookup subject if (defined $subje && defined $parts && $parts > 1) { #Multipart message my ($msgIDs, $ptNum, $ptTot,); #prepare options to provide to the thread { my $tmp = $file{MULTIPARTDB}{$subje}; if ($tmp) { foreach my $ptNum (sort {$a <=> $b} (keys %$tmp)) { $msgIDs .= $tmp->{$ptNum} . ','; writeLog('d', 'Appending msgID: [' . $tmp->{$ptNum} . ']'); } chop $msgIDs; #account for part 0 nfo files in messages $ptTot = keys %$tmp; if ($ptTot == $parts + 1) { $ptNum = 0; $ptTot--; } else { $ptNum = 1; } } else { writeLog('e', "Message data not found in group DB"); next; } } #launch thread, download parts $shash{1}{optionCSV} = $group . ',' . $ptNum . ',' . $msgIDs; $shash{1}{progress} = 1; $shash{1}{article} = 1; $mw->after(500); while ($shash{1}{article} == 1) { #wait for the thread, update gui $pb += .001; if ($pb >= 100) { $pb = 0; } elsif ($pb % 2) { update_status( 'Downloading... (' . $shash{1}{progress} . ' of ' . $ptTot . ')' ); } } $treturn = $shash{1}{return}; } else { #singlepart message my @a = ($path); update_status('Downloading message...'); #Launch thread $shash{1}{optionCSV} = $group . ',1,' . $mNumber; $shash{1}{article} = 1; while ($shash{1}{article} == 1) { $pb += .001; if ($pb >= 100) { $pb = 0; } else { if ($pb % 2) { $mw->update; } } } $treturn = $shash{1}{return}; } #Decode attachment if ($treturn) { my ($ret,); $pb++; #launch thread update_status('Decoding attachment...'); $shash{1}{decode} = 1; $mw->after(500); while ($shash{1}{decode} == 1) { $pb += .001; if ($pb >= 100) { $pb = 0; } else { if ($pb % 2) { $mw->update; } } } $ret = $shash{1}{return}; if ($ret) { #load and update group header db my $tmp = $file{HEADERDB}; $tmp->{$mNumber}[7] = 'read'; $file{HEADERDB} = $tmp; #update display my $style = $lb2_msg->ItemStyle('text', -anchor => 'w', -selectforeground => '#fff000', -background => '#ffffff', -foreground => '#2040A0', -font => '{Arial} 10 italic', ); $lb2_msg->itemConfigure($path, 0, -style => $style,); $lb2_msg->selectionClear($path); $mw->update; #open it? if ($open == 1) { my $cwd = cwd; my ($dir, $file) = split (/\*/, $ret); if ($^O eq 'MSWin32') { chdir ($dir); system ('start', '/B', $file); chdir ($cwd); } else { chdir ($dir); system ($file); chdir ($cwd); } } } else { #Could not decode attachment, try the next message my $m1 = "Couldn't decode attachment"; writeLog('e', $m1 . "\n[$!]"); update_status($m1 . '.'); $mw->after(3000); } } else { #Missing some or all parts, try the next message my $m1 = "Couldn't download attachment"; my $m2 = 'Article: [' . $mNumber . '] is incomplete'; writeLog('e', $m1); writeLog('w', $m2); update_status($m1 . '. ' . $m2 . '.'); $mw->after(3000); } } untie %file; ready(); return (1); } sub cleanFileNames #-------------------------------------------------- { my $fName = $_[0] || return (0); chomp $fName; #Remove leading and trailing spaces $fName =~ s/^\s+//; $fName =~ s/\s+$//; #Change spaces to _'s on non MSWin32 OS's if ($^O ne 'MSWin32') { $fName =~ s/\s+/_/g; } #Replace single and multiple \'s or /'s with a single / $fName =~ s/[\\\/]+/\//g; #Remove leading .'s and replace multiple .'s with a single . $fName =~ s/^\.+//; $fName =~ s/\.\.+/./g; #Substitute an opening drive letter sequence with: / $fName =~ s/^(?:[a-z]:[^\/]*\/*\s*)*(.*)$/\/$1/i; #Change unprintables to _'s $fName =~ s/[\000-\040'`"\177-\240]/_/g; return ($fName); } sub message_delete #-------------------------------------------------- { #called from the rc menu my ($group, @sel, %file,); $mw->Busy(-recurse => 1,); update_status('Deleting selected messages...'); #determine group @sel = $lb1_grp->selectionGet; eval { $group = $lb1_grp->itemCget($sel[0], 0, -text) }; if ($@) { writeLog('e', "No valid group selected for message delete"); ready(); $mw->Unbusy; return (0); } #get a list of messages to delete $lb2_msg->focus; @sel = $lb2_msg->selectionGet; if (! $sel[0]) { ready(); $mw->Unbusy; return (0); } #load group header db if (-e $group . '.grp') { tie %file, 'MLDBM', $group . '.grp', O_CREAT|O_RDWR, 0640 || writeLog('f', "Can't open group DB"); } else { ready(); $mw->Unbusy; return (0); } #delete selected messages from screen and group header db my $tmp = $file{HEADERDB}; foreach my $path (@sel) { $lb2_msg->hide('entry', $path); my $msgNum; if ($path =~ m/^.+\.([^\.\s]+)$/) { $msgNum = $1; } #<-test else { $msgNum = $path; } delete $tmp->{$msgNum}; } $file{HEADERDB} = $tmp; $lb2_msg->selectionClear; $mw->update; untie %file; ready(); return (1); } sub read_message #---------------------------------------------------- { #Called from a button pressed in the main window or the rc menu my (@sel, $group, $msgNumber,); $mw->Busy(-recurse => 1,); update_status('Connecting to server...'); #Determine which group @sel = $lb1_grp->selectionGet; eval { $group = $lb1_grp->itemCget($sel[0], 0, -text) }; if ($@) { writeLog('e', "No valid group selected for message read"); ready(); return (0); } #Determine which article @sel = $lb2_msg->selectionGet; $lb2_msg->focus; if (! $group || ! $sel[0]) { ready(); return (0); } else { #cleanup selection path, determine real msg number { writeLog('d', 'Selected path is: [' . $sel[0] . "]"); if ($sel[0] =~ m/^.+\.([^\.\s]+)$/) { $msgNumber = $1; } else { $msgNumber = $sel[0]; } writeLog('d', 'Real msgNumber is: [' . $msgNumber . "]"); } #connect to server my ($nntpRef,); $nntpRef = nntpconnect(); if (! $nntpRef) { writeLog('w', "Retrying connection.."); $nntpRef = nntpconnect(); if (! $nntpRef) { writeLog('e', 'Unable to connect to server, try again'); ready(); return (0); } } #launch thread, download article { update_status('Downloading message...'); $shash{1}{optionCSV} = $group . ',1,' . $msgNumber; $shash{1}{article} = 1; update_status('Downloading message'); while ($shash{1}{article} == 1) { #wait for the thread, update gui if ($pb >= 100) { $pb = 0; } else { $pb += .01; } $mw->update; } } #check return, read, format, and display downloaded message my $treturn = $shash{1}{return}; if ($treturn) { #read message header and determine encoding (max 128 lines) my ($headerLineCount, $blankLineAt, $encoding, $qp,); if (! open ('FH', '<', 'part1.pt')) { writeLog('e', "Can't open part1.pt\n$!"); return (0); } while (my $l = ()) { #determine if we are still in the header $headerLineCount++; if ($l =~ m/^$/) { #this line is blank $blankLineAt = $headerLineCount; if ($blankLineAt = $headerLineCount - 1) { #the last line was blank also (indicates end of header) last; } } #determine encoding used for this message if ($l =~ m/Content-Transfer-Encoding:\s+(.+)/) { #record specified encoding $encoding = $1; if ($encoding eq 'quoted-printable') { $qp = 1; } last; } if ($headerLineCount > 128) { #extra long header? (sanity check) writeLog('e', 'Extra long header detected (> 128 lines)'); writeLog('w', 'Processing rest of message as body'); last; } } if (! close FH) { writeLog('e', "Can't close part1.pt\n$!"); } if (! defined $encoding) { $encoding = 'UNKNOWN'; } writeLog('i', '[' . $encoding . '] encoding detected'); #format message for display if (! open ('FH', '<', 'part1.pt')) { writeLog('e', "Can't open part1.pt\n$!"); return (0); } while (my $l = ()) { #check if quoted printable encoding was detected if ($qp) { #decode quoted printable #The following is borrowed from the module #MIME::QuotedPrint::Perl created by: Gisle Aas $l =~ s/\r\n/\n/g; # normalize newlines $l =~ s/[ \t]+\n/\n/g; # rule #3 (trailing space deleted) $l =~ s/=\n//g; # rule #5 (soft line breaks) if (ord('A') == 193) { # EBCDIC style machine if (ord('[') == 173) { $l =~ s/=([\da-fA-F]{2})/Encode::encode('cp1047', Encode::decode('iso-8859-1',pack("C", hex($1))))/gex; } elsif (ord('[') == 187) { $l =~ s/=([\da-fA-F]{2})/Encode::encode('posix-bc', Encode::decode('iso-8859-1',pack("C", hex($1))))/gex; } elsif (ord('[') == 186) { $l =~ s/=([\da-fA-F]{2})/Encode::encode('cp37', Encode::decode('iso-8859-1',pack("C", hex($1))))/gex; } } else { # ASCII style machine $l =~ s/=([\da-fA-F]{2})/pack("C", hex($1))/ge; } #End MIME::QuotedPrint::Perl code } #check for formatting tags if ($l =~ s/[A-F]\<(.*)\>/$1/) { #handle (remove for now) 'tin-like' formatting tags <-todo - use these for formatting } #display message $txt_read->insert('end', $l); $mw->update; } if (! close FH) { writeLog('e', "Unable to close part1.pt"); } if (! unlink 'part1.pt') { writeLog('w', "Couldn't remove part1.pt"); } } else { #error downloading message update_status('Could not download article from server'); writeLog('e', "Couldn't download the article"); $mw->update; $mw->after(1000); ready(); return (0); } } writeLog('i', "The message was displayed for reading"); #Mark message as read in group header db { my ($tmp, %file,); tie %file, 'MLDBM', $group . '.grp', O_CREAT|O_RDWR, 0640 || writeLog('f', "Can't group DB"); $tmp = $file{HEADERDB}; $tmp->{$msgNumber}[7] = 'read'; $file{HEADERDB} = $tmp; untie %file; } #Update gui { my $style = $lb2_msg->ItemStyle('text', -anchor => 'w', -selectforeground => '#fff000', -background => '#ffffff', -foreground => '#2040A0', -font => '{Arial} 10 italic', ); $lb2_msg->itemConfigure($sel[0], 0, -style => $style,); $txt_read->focus; $tl4->update; $tl4->deiconify(); $tl4->raise(); } ready(); return (1); } sub read_close #------------------------------------------------------ { #called from a button pressed in the read window $txt_read->delete('1.0', 'end'); $tl4->withdraw; $tl4->configure(-title => 'Read Message'); $mw->update; return (1); } sub read_reply #------------------------------------------------------ { #called from a button pressed in the read window my ($c, $txt, @tmp, $refs, $mid, $subj); $mw->Busy(-recurse => 1); #read message $txt = $txt_read->get('1.0', 'end'); @tmp = split(/\n/, $txt); undef $txt; $txt_read->delete('1.0', 'end'); $tl4->withdraw; dbmopen (my %OPT, 'settings', 0640) || writeLog('f', "Can't create settings\n$!"); my $QSig = $OPT{QSig}; dbmclose %OPT; #process header, and quote message $c = 0; foreach my $line (@tmp) { #look for blank lines (delimits header) if (! $line =~ m/(.+)/) { $c++; } if ($c >= 1) { #found blank lines, start quoting everything from here if ($line =~ m/^-- $/) { #found signature if ($QSig) { $txt .= '> '.$line."\n"; } else { last; } } else { #quote message line $txt .= '> '.$line."\n"; } } else { #process header if ($line =~ m/^References:\s+(.+)/) { $refs = $1; } elsif ($line =~ m/^Message-ID:\s+(.+)/) { $mid = $1; } elsif ($line =~ m/^Subject:\s+(.+)/) { my $a = $1; if ($a =~ m/[Rr][Ee]:.*/) { $subj = $a; } else { $subj = 'Re: ' . $a; } } } } if ($mid) { $refs .= $mid; } #save references, so the send function can craft the header dbmopen (%OPT, 'settings', 0640) || writeLog('f', "Can't create settings\n$!"); $OPT{Refs} = $refs; $post_entries[0]->delete('0', 'end'); $post_entries[1]->delete('0', 'end'); $post_entries[0]->insert('end', $OPT{Mail}); $post_entries[1]->insert('end', $subj); dbmclose %OPT; #populate then display the reply window my $typed; my @sel = $lb2_msg->selectionGet; $typed = $lb2_msg->itemCget($sel[0], 1, -text); $typed .= " wrote in message-id: " . $mid . "\n"; $txt_post->insert('end', $typed . "\n"); $txt_post->insert('end', $txt); $mw->Unbusy; post(); return (1); } sub post #------------------------------------------------------------ { #called from a main button, rc menu, or read_reply my ($from,); my @sel = $lb1_grp->selectionGet; my $group; eval { $group = $lb1_grp->itemCget($sel[0], 0, -text) }; if ($@) { writeLog('e', "No valid group selected for message post"); return (0); } { dbmopen (my %OPT, 'settings', 0640) || writeLog('f', "Can't read settings\n$!"); $from = $OPT{Mail}; dbmclose %OPT } $post_entries[0]->delete('0', 'end'); $post_entries[0]->insert('end', $from); $tl2->deiconify(); $tl2->raise(); $txt_post->focus; $mw->update; return (1); } sub post_post #------------------------------------------------------- { #called from a button pressed in the post window or sub post_attach my $atch = $_[0] || 0; my $curr = $_[1] || 1; my $totl = $_[2] || 1; my $file = $_[3] || ' '; my (@sel, $msg, $hdr, $bdy, $subj, $from, $refs, $sign, $group,); #determine group @sel = $lb1_grp->selectionGet; eval { $group = $lb1_grp->itemCget($sel[0], 0, -text) }; if ($@) { writeLog('e', 'No valid group selected for posting to'); return (0); } $mw->update; $mw->Busy(-recurse => 1,); update_status('Formatting message...'); for (1..4) { $pb++; $mw->update; } #gather message information, update subject header #subject should not contain (#/#), it should look like below #[Comment1] "filename" yEnc (partnum/numparts) [size] [Comment2] $subj = $post_entries[1]->get(); $from = $post_entries[0]->get(); $subj =~ s/\(\d+\/\d+\)//g; { dbmopen (my %OPT, 'settings', 0640) || writeLog('f', "Can't read settings\n$!"); if (! $sign) { $sign = 0; } if (! $subj) { $subj = 'No Subject'; } if (! $OPT{Refs}) { $OPT{Refs} = 0; } if ($atch) { $subj .= ' "' . $file . '" yEnc (' . $curr . '/' . $totl . ')'; } $refs = $OPT{Refs}; $sign = $OPT{Sig}; $OPT{Refs} = 0; #<-test dbmclose %OPT || writeLog('w', "Can't close settings\n$!"); } #create header if ($refs) { $hdr = 'From: ' . $from . "\n" . 'Newsgroups: ' . $group . "\n" . 'References: ' . $refs . "\n" . 'X-NNTPclient: ' . "NewsSurfer v3.10\n". 'X-CreatedBy: ' . "Just another Perl hacker, \n". 'Subject: ' . $subj . "\n\n"; } else { $hdr = 'From: ' . $from . "\n". 'Newsgroups: ' . $group . "\n" . 'X-NNTPclient: ' . "NewsSurfer v3.10\n" . 'X-CreatedBy: ' . "Just another Perl hacker, \n" . 'Subject: ' . $subj . "\n\n"; } $msg = $hdr . "\n"; #attach body and signature to first article only if ($curr == 1) { $bdy = $txt_post->get('1.0', 'end'); if ($sign) { #attach signature to body if (open ('FH', '<', $sign)) { #'four lines after the double dash space' my $c = 1; $bdy .= "\n-- \n"; while (my $line = ()) { chomp $line; $bdy .= $line . "\n"; if ($c == 4) { last; } $c++; } if (! close FH) { writeLog('w', "Can't close signature file\n$!\n"); } } else { writeLog('e', "Can't open signature file\n$!\n"); } } $msg .= $bdy . "\n"; } if ($atch) { #attach file part to article $msg .= $atch . "\n"; } #connect, post message, and disconnect update_status('Posting message...'); for (1..4) { $pb += 4; $mw->update; } my $nntpRef = nntpconnect(); if($nntpRef) { my $bool = $$nntpRef->post([$msg]); #<-blocks if (! $bool) { writeLog('e', 'Unable to post message, could not post'); } } else { writeLog('e', 'Unable to post message, could not connect'); } $$nntpRef->quit; #finish up ready(); if ($curr == $totl) { post_cancel(); } return (1); } sub post_attachandpost #---------------------------------------------- { #called from a button pressed in the post window my $file = $mw->getOpenFile(); $mw->Busy(-recurse => 1); if (defined $file) { #Open the file, or return early if (! open ('ATCH', '< :raw', $file)) { writeLog('e', "Couldn't open attachment for input"); return (0); } #deterimine filename and remove leading and trailing whitespace update_status('Creating attachment...'); for (1..4) { $pb += 4; $mw->update; } my $file_name = $file; $file_name =~ s/ .*\/ #0 or more of anything until foward slash (.+) #capture 1 or more of anything /$1 #replace those with capture variable 1 /x; #remove leading and trailing space $file_name =~ s/(?:^\s+|\s+$)//g; #truncate filenames longer than 254 characters if (length $file_name >= 255) { $file_name = substr ($file_name, 0, 254); } #how large is the file in bytes my ($file_bytes,); $file_bytes = -s $file; #send attachment, split large files ( > 400KB) if ($file_bytes > 409600) { #<-Research #create a multipart attachment my ($totalparts, $currentpart,); #how many 400k parts will this be? $totalparts = 1 + (int ($file_bytes / 409600)); $currentpart = 1; #read 400k chunks of the file into a string while (my $size = read (ATCH, my $buf, 409600)) { #yEncode data #<-Test my $begin = 1 + (($currentpart * 409600) - 409600); my @data = map { ord $_ } split (//, $buf); my $ydata = post_yenc(\@data); my $psize = length $ydata; my $pcrc = crc32($ydata); my $end; if ($size == 409600) { $end = $currentpart * $size; } else { $end = (($currentpart - 1) * 409600) + $size; } #Encapsulate data in yENC headers #<-Test my $crlf = "\015\012"; my $yhead = '=ybegin' . ' ' . 'part=' . $currentpart . ' ' . #enable multipart 'total=' . $totalparts . ' ' . #number of parts 'line=' . '128' . ' ' . #~ line length 'size=' . $file_bytes . ' ' . #unencoded size 'name=' . $file_name; #file name my $ypart = '=ypart' . ' ' . 'begin=' . $begin . ' ' . #start byte 'end=' . $end; #end byte my $ytail = '=yend' . ' ' . 'size=' . $size . ' ' . #part bytes 'part=' . $currentpart . ' ' . #part number 'pcrc32=' . $pcrc; #part crc32 my $atch = $crlf . $yhead . $crlf . $ypart . $crlf . $ydata . $crlf . $ytail . $crlf; #Send the message my $ret = post_post( $atch, $currentpart, $totalparts, $file_name ); if (! $ret) { writeLog('e', 'Unable to attach: [' . $file_name . ']'); last; } $currentpart++; $mw->update; } close ATCH || warn "Can't close attachment file\n$!\n"; } else { #<-Test #Create single part message attachement my $line; while () { $line .= $_; } close ATCH || warn "Can't close attachment file\n$!\n"; #yEncode data my @data = map { ord $_ } split (//, $line); my $ydata = post_yenc(\@data); #Encapsulate data in yENC headers my $crlf = "\015\012"; my $yhead = '=ybegin' . ' ' . 'line=' . '128' . ' ' . 'size=' . $file_bytes . ' ' . 'name=' . $file_name; my $ytail = '=yend' . ' ' . 'size=' . $file_bytes; my $atch = $crlf . $yhead . $crlf . $ydata . $crlf . $ytail . $crlf; #send the message my $ret = post_post($atch, 1, 1, $file_name); if (! $ret) { writeLog('e', 'Unable to attach file: [' . $file_name . ']'); } } } else { writeLog('w', 'No file selected for attachment'); } $mw->Unbusy; return (1); } sub post_yenc #------------------------------------------------------- { #<-Test, research my $aref = $_[0] || return (0); my (@in, @out, $linesize,); update_status('Encoding attachment...'); for (1..4) { $pb++; $mw->update; } @in = @$aref; undef $aref; $linesize = 0; while (defined (my $byte = shift @in)) { my $yenc = ($byte + 42) % 256; if ($linesize >= 128) { #enforce line size, insert a CRLF pair push @out, 0x0D; push @out, 0x0A; $linesize = 0; } if ($linesize == 0 || $linesize == 127) { #<-test, line may go over 128 #escape a tab or space in the first or last column of a line if ($yenc == 0x09 || $yenc == 0x20) { $yenc = ( $byte + 64 ) % 256; push @out, 0x3D; push @out, $yenc; $linesize += 2; next; } } if ($yenc==0x00 || $yenc==0x0A || $yenc==0x0D || $yenc==0x3D ){ #found a critical character, escape it with 0x3D (=) push @out, 0x3D; $yenc = ( $byte + 64 ) % 256; $linesize++; } push @out, $yenc; $linesize++; } my $ydata = join '', map { chr $_ } @out; return ($ydata); } sub post_cancel #----------------------------------------------------- { #called from a button pressed in the post window $txt_post->delete('1.0', 'end'); $tl2->Unbusy; $tl2->withdraw(); $mw->update; return (1); } sub browse #---------------------------------------------------------- { #called from a button pressed in the main window $mw->Busy(-recurse => 1); dbmopen (my %OPT, 'settings', 0640) || writeLog('f', "Can't read settings\n$!"); if ($^O eq 'MSWin32') { my ($dir,); $dir = $OPT{DDir}; $dir =~ s/\//\\/g; system ('explorer.exe', $dir); } else { system ('ls', $OPT{DDir}); } dbmclose %OPT; $mw->Unbusy; $mw->update; return (1); } sub rset_cmd #-------------------------------------------------------- { #called from the rc menu my ($sel, $rem,); $mw->Busy(-recurse => 1); $sel = $lb1_grp->selectionGet; $rem = $lb1_grp->itemCget($sel, 0, -text); if (! $sel && ! $rem) { writeLog('w', 'No valid groups selected for reset'); return (0); } $lb2_msg->delete('all'); if (-e $rem . '.grp') { if (! unlink $rem . '.grp') { writeLog('e', "Couldn't delete the group DB"); return (0); } } dbmopen (my %SBSCRIBE, 'sbscribe', 0640) || writeLog('f', "Can't create sbscribe\n$!"); $SBSCRIBE{$rem} = 'Never'; dbmclose %SBSCRIBE; $mw->after(500); display_groups(); $mw->Unbusy; return (1); } sub group #----------------------------------------------------------- { #called from a button pressed in the main window my ($lb_grp_s1, $imagedata, $chek,); $mw->Busy(-recurse => 1); $tl3->Popup; $lb_grp->focus; foreach my $b (@buttons) { $b->configure(-state => 'disabled'); } $mw->Unbusy; $mw->update; return (1); } sub grp_search #------------------------------------------------------ { search($lb_grp, 'GROUP'); return (1); } sub grp_shownewsgroups #---------------------------------------------- { my $opt1 = uc ($_[0]) || 'ALL'; my ($chek, $lb_grp_s1,); $mw->Busy(-recurse => 1,); update_status('Loading groups...'); { my $imagedata = load_image(3); $chek = $mw->Photo(-format => 'bmp', -data => $imagedata); for (1..4) { $pb++; $mw->update; } undef $imagedata; } $lb_grp_s1 = $lb_grp->ItemStyle( 'text', -selectforeground => '#000000', -selectbackground => '#fff000', -bg => '#000000', -fg => '#ffffff', -font => '{Arial} 8', -anchor => 'w', ); $lb_grp->delete('all'); $mw->update; if (-e 'groups') { my (%groups, $counter, $c,); tie %groups, 'MLDBM', 'groups', O_CREAT|O_RDWR, 0640 || writeLog('f', $!); dbmopen (my %SBSCRIBE, 'sbscribe', 0640) || writeLog('f', "Can't create sbscribe\n$!"); $counter = $c = 0; foreach my $k (sort {$a cmp $b} (keys (%groups))) { my $found; if ($opt1 eq 'SEARCH') { #search action specified if ($k =~ m/$grpSubSearch/) { $found++; } } if ($opt1 eq 'SEARCH' && !defined $found) { #item does not match search next; } else { #display the item my $v = $groups{$k}; $lb_grp->add($counter); $lb_grp->itemCreate($counter, 0, -text => $k, -style => $lb_grp_s1 ); $lb_grp->itemCreate($counter, 1, -text => $v, -style => $lb_grp_s1 ); if ($SBSCRIBE{$k}) { $lb_grp->indicator('create', $counter, -itemtype => 'image', -image => $chek ); } } if ($pb >= 100) { $pb = 0; $mw->update; } if ($c > 1000) { for (1..5) { $pb++; $mw->update; } $c = 0; } else { $c++; } $counter++; } untie %groups; dbmclose %SBSCRIBE; } else { $lb_grp->add(0); $lb_grp->itemCreate(0,0, -text => 'Press the Update button to retrieve groups '. 'from server.' ); } ready(); return (1); } sub grp_update #------------------------------------------------------ { #called from a button pressed in the group window $tl3->Busy(-recurse => 1,); update_status('Downloading groups...'); $lb_grp->delete('all'); $pb++; $mw->update; #remove old groups database if (! unlink 'groups') { writeLog('e', "Can't delete groups db\n$!"); if (! rename ('groups', 'groups.old')) { writeLog('e', "Can't rename groups db\n$!"); writeLog('w', "Merging new groups into old db\n$!"); } } #create groups database $shash{1}{list} = 1; while ($shash{1}{list} == 1) { if ($pb >= 100) { $pb = 0; } else { $pb++; } $mw->after(100); $mw->update; } #show newsgroup list $tl3->Unbusy; grp_close(); group(); grp_shownewsgroups(); ready(); return (1); } sub grp_subscribe #--------------------------------------------------- { #called from a button pressed in the group window my ($imagedata, $chek, @sel,); $imagedata = load_image(3); $chek = $mw->Photo( -format => 'bmp', -data => $imagedata ); undef $imagedata; dbmopen (my %SBSCRIBE, 'sbscribe', 0640) || writeLog('f'. "Can't create sbscribe\n$!"); @sel = $lb_grp->selectionGet; foreach my $i (@sel) { my $a = $lb_grp->itemCget($i, 0, -text); $lb_grp->indicator('create', $i, -itemtype => 'image', -image => $chek ); $SBSCRIBE{$a} = 'Never'; } dbmclose %SBSCRIBE; display_groups(); return (1); } sub grp_unsubscribe #------------------------------------------------- { #called from a button pressed in the group or main window my $opt = $_[0]; dbmopen (my %SBSCRIBE, 'sbscribe', 0640) || writeLog('f', "Can't create sbscribe\n$!"); if ($opt) { #unsubscribe from main screen my ($sel, $gName,); $sel = $lb1_grp->selectionGet; if (! $sel) { writeLog('w', 'No valid group selected to remove'); return (0); } $gName = $lb1_grp->itemCget($sel, 0, -text); writeLog('w', "Removing newsgroup: [$gName.grp]"); delete $SBSCRIBE{$gName}; if (-e $gName . '.grp') { unlink $gName . '.grp' || writeLog('e', "Couldn't delete the group file\n[$!]"); } $lb2_msg->delete('all'); } else { #unsubscribe from groups screen my (@sel,); @sel = $lb_grp->selectionGet; if (! @sel) { writeLog('w', 'No valid group selected to remove'); return (0); } foreach my $i (@sel) { my $gName = $lb_grp->itemCget($i, 0, -text); $lb_grp->indicator('delete', $i,); writeLog('w', 'Removing newsgroup: [' . $gName . ".grp]"); delete $SBSCRIBE{$gName}; if (-e $gName . '.grp') { unlink $gName . '.grp' || writeLog('e', "Couldn't delete the group file\n[$!]"); } } } dbmclose %SBSCRIBE; display_groups(); return (1); } sub grp_close #------------------------------------------------------- { #called from a button pressed in the group window $mw->Busy(-recurse => 1); $mw->update; $lb_grp->delete('all'); $tl3->withdraw; foreach my $b (@buttons) { $b->configure(-state => 'normal',); } $mw->update; $mw->Unbusy; return (1); } sub display_groups #-------------------------------------------------- { #called from subs: group_subscribe, group_unsubscribe $lb1_grp->delete('all'); my $counter = 1; my %SBSCRIBE; if (! dbmopen (%SBSCRIBE, 'sbscribe', 0640)) { writeLog('f', "Can't read sbscribe\n$!"); } foreach my $k (sort {$a cmp $b} keys %SBSCRIBE) { $lb1_grp->add($counter); $lb1_grp->itemCreate($counter, 0, -text => $k, -style => $lb1_k1, ); $lb1_grp->itemCreate($counter, 1, -text => $SBSCRIBE{$k}, -style => $lb1_k2, ); $counter++; } dbmclose %SBSCRIBE || writeLog('e', "Can't close SBSCRIBE DB"); $mw->update; return (1); } sub search_popup #---------------------------------------------------- { #called from rc menu my ($group, @sel,); #make sure the group clicked has been loaded or scanned. @sel = $lb1_grp->selectionGet; eval { $group = $lb1_grp->itemCget($sel[0], 0, -text) }; if ($@) { writeLog('w', 'No valid group selected to search'); } #raise popup $tla->Popup; $tla->focus; my @kids = $tla->children; foreach my $widget (@kids) { if ($widget->class eq 'Entry') { $widget->focus; last; } } $mw->update; return (1); } sub search #---------------------------------------------------------- { #works for HLists only #called from button pressed in group window or search_popup window #Todo - add search within results option #<--Todo my $w = $_[0] || return (0); my $opt1 = uc ($_[1]) || 0; my $opt2 = $_[2] || 0; my (@paths, $c,); #show all requested if ($opt1 eq 'GROUP' && $opt2 == 1) { #show all available newsgroups grp_shownewsgroups('ALL'); return (1); } #start searching $w->focus; $mw->Busy(-recurse => 1,); update_status('Searching groups...'); $mw->update; if (defined $grpSubSearch) { #escape any regex metachars found within search string $grpSubSearch = quotemeta $grpSubSearch; } else { #Default search regex (all but newline regex metachar) $grpSubSearch = '.'; } foreach my $i (1,3,4,2) { $pb += $i; $mw->update; } $tla->withdraw; $c = 0; @paths = $w->infoChildren; if ($paths[0]) { #Widget is populated, show only entries which match search term #my $regex = qr/$grpSubSearch/; foreach my $path (@paths) { my $item = $w->itemCget($path, 0, -text); if ($item =~ m/$grpSubSearch/i) { $w->show('entry', $path); } else { $w->hide('entry', $path); } if ($c >= 1000) { if ($pb >= 100) { $pb = 0; } else { $pb++; } $c = 0; $mw->update; next; } $c++; } } else { #searching an empty widget, see if it is the groups window if ($opt1 eq 'GROUP') { #call a more specific search subroutine grp_shownewsgroups('SEARCH'); } } ready(); return (1); } sub opt #------------------------------------------------------------- { #called from button pressed in the main window dbmopen (my %OPT, 'settings', 0640) || writeLog('f', "Can't create settings\n$!"); { my $c = 0; foreach my $k qw(Serv User Pass Mail DDir Sig) { $OPT_widgets[$c]->delete(0, 'end'); $OPT_widgets[$c]->insert('end', $OPT{$k}); $mw->update; $c++ } foreach my $k qw(Kilf QSig) { if ($OPT{$k}) { $OPT_widgets[$c]->select; } $c++; } } dbmclose %OPT; $tl5->Popup; $tl5->focus; $mw->update; return (1); } sub opt_close #------------------------------------------------------- { #called from button pressed in the option window my ($serv, $user, $pass, $email, $ddir, $sig,); dbmopen (my %OPT, 'settings', 0640) || writeLog('f', "Can't create settings\n$!"); $serv = $OPT_widgets[0]->get(); $user = $OPT_widgets[1]->get(); $pass = $OPT_widgets[2]->get(); $email = $OPT_widgets[3]->get(); $ddir = $OPT_widgets[4]->get(); $sig = $OPT_widgets[5]->get(); $OPT{Serv} = $serv; $OPT{User} = $user; $OPT{Pass} = $pass; $OPT{Mail} = $email; $OPT{DDir} = $ddir; $OPT{Sig} = $sig; $OPT{QSig} = $quoteSig; $OPT{Kfile} = $killFile; dbmclose %OPT; $tl5->withdraw; $mw->update; return (1); } sub opt_download #---------------------------------------------------- { #called from button pressed in the option window my ($dir,); $OPT_widgets[4]->delete(0, 'end'); eval { $dir = $tl5->chooseDirectory( -title => 'Choose a download directory', -initialdir => '.', -mustexist => 1, ) }; if ($@) { #error writeLog('e', 'Unable to choose a download directory'); } else { if ($dir) { #user defined directory $OPT_widgets[4]->insert('end', $dir); } else { #default directory $OPT_widgets[4]->insert('end', '.'); } } $mw->update; return (1); } sub opt_signature #--------------------------------------------------- { #called from button pressed in the option window my ($sig, $ofile,); $OPT_widgets[5]->delete(0, 'end'); $ofile = $tl5->getOpenFile( -title => 'Choose Signature File', -initialdir => '.', ); if ($ofile) { $OPT_widgets[5]->insert('end', $ofile); $mw->update; return (1); } return (0); } sub show_log #-------------------------------------------------------- { #called from button pressed in the main window my (@log,); $mw->Busy(-recurse => 1); warn "Displaying log\n"; close STDERR || warn "Can't close STDERR\n$!\n"; $mw->after(500); $tl1->deiconify(); $tl1->raise(); $txt_log->focus; $txt_log->delete('1.0', 'end'); $mw->update; if (open ('FH', '<', 'NewsSurfer.log')) { my $c = 1; while (my $line = ()) { chomp $line; if (! defined $line) { $line = '#'; } $line =~ s/^Net.*\)(<|>.*)/$1/; if ($line =~ m/^(?:Net::NNTP)*>>>.*$/) { $txt_log->insert('end', $line . "\n", 'Blue'); } elsif ($line =~ m/^<<<.*$/) { $txt_log->insert('end', $line . "\n", 'Green'); } elsif ($line =~ m/\bINFO.+$/) { $txt_log->insert('end', $line . "\n", 'White'); } elsif ($line =~ m/\bERRO.+$/) { $txt_log->insert('end', $line . "\n", 'Red'); } elsif ($line =~ m/\bWARN.+$/) { $txt_log->insert('end', $line . "\n", 'Yellow'); } elsif ($line =~ m/\bDBUG.+$/) { if ($DEBUG > 0) { $txt_log->insert('end', $line . "\n", 'Debug'); } } elsif ($line =~ m/\bVRBS.+$/) { if ($DEBUG > 1) { $txt_log->insert('end', $line . "\n", 'Verbose'); } } elsif ($line =~ m/^\s+.+$/) { if ($DEBUG > 1) { $txt_log->insert('end', $line . "\n", 'Verbose'); } } else { $txt_log->insert('end', $line . "\n"); } if ($c == 512) { $c = 0; $txt_log->see('end'); $mw->update; } $c++; } close FH || warn "Can't close log\n$!\n"; } else { warn "Can't open log\n$!\n"; } open (STDERR, '>>', 'NewsSurfer.log') || warn "Can't open log\n$!\n"; $txt_log->see('end'); $mw->Unbusy; $mw->update; return (1); } sub log_refresh #----------------------------------------------------- { show_log(); return (1); } sub log_close #------------------------------------------------------- { #called from button pressed in the log window $tl1->withdraw; $mw->update; return (1); } sub log_save #-------------------------------------------------------- { #called from button pressed in the log window my (@log, $sf,); writeLog('i', 'Saving log'); $sf = $tl1->getSaveFile(-title => 'Save Log',); if ($sf) { writeLog('w', 'The logfile has been saved'); $mw->Busy(-recurse => 1); if (open ('FH', '<', 'NewsSurfer.log')) { if (open ('LOG', '>', $sf)) { while (my $line = ()) { chomp $line; print LOG $line . "\n"; } close LOG || writeLog('e', "Can't close log\n$!"); } else { writeLog('e', "Can't save log\n$!"); } close FH || writeLog('e', "Can't close log\n$!"); } else { writeLog('e', "Can't open log\n$!"); } $mw->Unbusy; return (1); } } sub help #------------------------------------------------------------ { #called from button pressed in the main window my $pod = $mw->Pod( -tree => 0, -file => $0, -title => 'NewsSurfer documentation', ); #$pod->configure(-file => $0); return (1); } sub quit #------------------------------------------------------------ { #called from button pressed in the main window $mw->Busy(-recurse => 1,); $mw->update; warn 'NewsSurfer has closed. (' . localtime(time) . ")\n"; $mw->destroy; return (1); } sub raise_rc_menu #--------------------------------------------------- { #called from right-clicking in the main window my $toplevelwidget = $_[0] || 'NULL'; #required my $listbox = $_[1]; #optional my ($x, $y) = $mw->pointerxy; my $height; $mw->Busy(-recurse => 1,); if ($listbox && Exists($listbox) && Exists($toplevelwidget)) { #a listbox was supplied my ($selected,); #verify widget is a listbox eval { $selected = $listbox->nearest($y - $listbox->rooty) }; if (! $@) { #it's a listbox, make selection at xy if there is a entry if ($selected) { $listbox->selectionClear(); $listbox->selectionSet($selected); } } $height = $toplevelwidget->height; $y -= $height; } if (Exists($toplevelwidget)) { $toplevelwidget->geometry('+' . $x . '+' . $y); $toplevelwidget->deiconify(); $toplevelwidget->raise(); $toplevelwidget->focus(); $mw->update; } $mw->Unbusy; return (1); } sub lb2_msg_select_all #---------------------------------------------- { #called from the rc menu or key binding my (@paths, $count, $home, $end,); $mw->Busy(-recurse => 1); @paths = $lb2_msg->infoChildren; if (@paths) { $count = $#paths; $home = $paths[0]; $end = $paths[$count]; $lb2_msg->focus; $lb2_msg->selectionSet($home, $end); } $mw->update; $mw->Unbusy; return (1); } sub lb2_msg_select_end #---------------------------------------------- { #called from the rc menu or key binding my ($sel, @paths, $count, $end,); $sel = $lb2_msg->selectionGet; @paths = $lb2_msg->infoChildren; $count = $#paths; $end = $paths[$count]; $lb2_msg->selectionSet($sel, $end); $mw->update; return (1); } sub lb2_msg_select_hom #---------------------------------------------- { #called from the rc menu or key binding my ($sel, @paths, $home,); $sel = $lb2_msg->selectionGet; @paths = $lb2_msg->infoChildren; $home = $paths[0]; $lb2_msg->selectionSet($sel, $home); $mw->update; return (1); } sub FlashButton #----------------------------------------------------- { #called during widget creation my $w = $_[0]; my $c1 = $_[1]; my $c2 = $_[2]; if (! $w || ! $c1 || ! $c2) { return (0); } $w->bind('' => sub { $w->configure(-relief => 'flat',); $w->configure(-fg => $c1); $w->flash; $w->flash; $w->configure(-fg => $c2); }); return (1); } sub MainButtons #----------------------------------------------------- { #called during widget creation my $w = $_[0] || return (0); my $o1 = $_[1] || return (0); my $width = $mw->screenwidth; my ($id1, $id2, $i1, $i2, $i3,); $id1 = load_image($o1); $id2 = load_image($o1 . '1'); #warn 'id1: ' . $id1 . "\n"; #warn 'id2: ' . $id2 . "\n"; #if ($width > 799) { #<-todo, resize buttons # my ($scaled1, $scaled2, $imager1, $imager2,); # $imager1 = Imager->new; # $imager2 = Imager->new; # $imager1->read(data => $id1); # $imager2->read (data => $id2,); # $scaled1 = $imager1->scale(scalefactor => 1.25); # $scaled2 = $imager2->scale(scalefactor => 1.25); # $scaled1->write(data => \$id1,); # $scaled2->write(data => \$id2,); #} $i1 = $mw->Photo( -data => $id1, -format => 'bmp', -palette => '256', ); $i2 = $mw->Photo( -data => $id1, -format => 'bmp', -palette => '64/64/64', ); $i3 = $mw->Photo( -data => $id2, -format => 'bmp', ); $w->configure(-relief => 'flat', -image => $i1); $w->bind('' => sub { $w->configure(-image => $i1); }); $w->bind('' => sub { $w->configure(-image => $i2); }); $w->bind('' => sub { $w->configure(-relief => 'flat', -image => $i3); }); $w->bind('' => sub { $w->configure(-relief => 'flat', -image => $i1); }); $mw->update; return (1); } sub ready #----------------------------------------------------------- { if (! defined $pb) { $pb = 0; } while ($pb < 100) { $pb++; if ($pb % 2) { $mw->update }; } $pb = 0; update_status('Ready'); $mw->Unbusy; $mw->update; return (1); } sub update_status #---------------------------------------------------<-redo interface { #called from various subroutines #called with either a status message in $txt #or a number followed by PROGRESSBAR (triggers progressbar update) #or a word followed by PROGRESSBAR (triggers progress complete) my $txt = $_[0] || 'NULL'; my $opt = $_[1] || 'NULL'; if ($opt eq 'PROGRESSBAR') { if ($txt =~ m/(^\d+)/) { #update status of progressbar for (1..$1) { $pb++; $mw->update; $mw->after(64); } } else { #complete and reset the progress bar while ($pb < 100) { $pb++; $mw->update; } $pb = 0; } } elsif ($txt ne 'NULL' && $opt ne 'PROGRESSBAR') { $sb_lab->configure(-text => ' ' . $txt); $mw->update; } else { writeLog('e', 'Sub - update_status: ' . 'txt [' . $txt . "]\n" . 'opt [' . $opt . "]\n$!" ); $mw->destroy; } return (1); } return (1); } #***********************************************************************END news_gui sub worker #------------------------------------------------------------ { #called from main my $TID = $_[0] || 0; local $| = 1; while(1) { if ($shash{$TID}{die} == 1) { #DIE last; } elsif ($shash{$TID}{rss} == 1) { #RSS my $xml; my @URLs = split (/,/, $shash{$TID}{optionCSV}); foreach my $url (@URLs) { #Download XML from RSS feed print '='x79 . "\nFetching URL: [$url]\n" . '='x79 . "\n"; eval { $xml = XML::FeedPP->new($url) }; if (! $@) { #Parse RSS XML if (! parseRSS(\$xml)) { writeLog('e', "Problem processing URL: [$url]\n$!"); } } else { writeLog('e', "Problem downloading URL: [$url]\n$!"); } } } elsif ($shash{$TID}{post} == 1) { #POST #collect stringRef from sub post_post my $message = $shash{$TID}{optionCSV} || 'NULL'; undef $shash{$TID}{optionCSV}; #connect, post message, and disconnect my $nntpRef = nntpconnect(); if ($nntpRef) { writeLog('i', "Posting message"); my $ret = $$nntpRef->post([$message]); $$nntpRef->quit; #check return if ($ret) { writeLog('i', "Message posted"); } else { writeLog('e', "Unable to post message, couldn't send"); } } else { writeLog('e', "Unable to post message, couldn't connect"); } #go back to sleep $shash{$TID}{optionCSV} = 0; $shash{$TID}{post} = 0; } elsif ($shash{$TID}{decode} == 1) { #DECODE #gather files into an array ref for the decoder #look for any part 0 nfo files my (@art, @pt_files, $cvt, $nfochk, $result, $ddir,); dbmopen (my %OPT, 'settings', 0640) || writeLog('f', "Can't create settings\n$!"); $ddir = $OPT{DDir} || './'; dbmclose %OPT; @pt_files = glob "part*.pt"; if (! $pt_files[0]) { writeLog('e', "Error while gathering part file list\n$!"); $shash{$TID}{return} = 0; $shash{$TID}{optionCSV} = 0; $shash{$TID}{decode} = 0; } else { #load part file contents into an array for the decoder foreach my $partfile (@pt_files) { open ('PTFH', '< :raw', $partfile) || writeLog('f', "Decoder: [$!]"); if (! defined $nfochk && $partfile eq 'part0.pt') { #part 0 nfo fix $nfochk = 1; } else { while (my $line = ()) { push (@art, $line); } } } #initialize decoder #neat will call the sub with the name of the file writeLog('i', "Decoding attachment(s)"); $cvt = Convert::BulkDecoder->new( destdir => $ddir, tmpdir => '.', force => 1, #todo - add option verbose => 1, debug => 1, crc => 0, neat => \&cleanFileNames, #<-Test ); #decode partfiles eval { $result = $cvt->decode(\@art) }; if (! defined $result) { $result = 'DECODER ERROR'; } if ($@ || $result eq 'FAIL') { #decode failed writeLog('e', "Couldn't decode the file, [" . $result . ']'); $shash{$TID}{return} = 0; } else { #decode succeded my ($dirname, $filename,) = 0; my $size = $cvt->{size} || 0; my $file = $cvt->{file} || 'NULL'; writeLog('i', "Extracted [$size] bytes to file: [$file]"); if ($size && $file ne 'NULL') { #determine filename and path if ($file =~ m/(\b.+)\/(.+\..{3,4})/ || $file =~ m/(.+)\/(.+\..{3,4})/ ) { $dirname = $1; $filename = $2; #copy any part0 nfo files found if (defined $nfochk && $nfochk == 1) { #found part 0 nfo file if ($^O eq 'MSWin32') { $file =~ s#\/#\\#g; system ("copy part0.pt $file.nfo"); writeLog('d', "copy part0.pt $file.nfo"); } else { system ("cp part0.pt $file.nfo"); writeLog('d', "cp part0.pt $file.nfo"); } } $shash{$TID}{return} = $dirname . '*' . $filename; } else { writeLog('e', 'Error while parsing filename and path'); $shash{$TID}{return} = 0; } } else { $shash{$TID}{return} = 0; } } } #remove temporary part files foreach my $f (@pt_files) { unlink $f || writeLog('e', "Can't delete part\n$!"); } #go back to sleep $shash{$TID}{decode} = 0; } elsif ($shash{$TID}{article} == 1) { #ARTICLE #gather and verify startup parameters #expects: group name, 0 or 1 (1st pt num), message id(s)* # * when multiple message ids are found, multipart is on writeLog('d', "optionCSV: [$shash{1}{optionCSV}"); my (@options, $groupName, $firstPart, $nntpRef,); @options = split (/,/, $shash{$TID}{optionCSV}); $groupName = shift (@options); $firstPart = shift (@options); #connect to NNTP server eval { $nntpRef = nntpconnect() }; if (! $nntpRef || ! defined $groupName || ! defined $firstPart) { if (! $nntpRef) { writeLog('e', "Couldn't connect to server"); } else { writeLog('e', 'Invalid option in ARTICLE worker thread'); } $shash{$TID}{return} = 0; } else { #connected, download article my $ok; if (! $options[1]) { #for singlepart messages eval { $$nntpRef->group($groupName) }; if (defined $options[0]) { #create a temporary file and download the part my $partNumber = $firstPart; open ('FH', '> :raw', 'part' . $partNumber . '.pt') || writeLog('f', $!); eval { $ok = $$nntpRef->article($options[0], *FH) }; if (! $ok) { writeLog('i', "Retrying article download"); #<-test eval { $ok = $$nntpRef->article($options[0], *FH) }; if (! $ok) { writeLog('w', "Download failed, reconnecting"); #download failed, re-connect and retry eval { $$nntpRef->quit }; eval { $nntpRef = nntpconnect() }; if ($nntpRef) { #re-connected, retry download writeLog('i', "Retrying article download"); eval { $ok = $$nntpRef->article($options[0], *FH) }; } else { #could not connect writeLog('e', "Couldn't connect to server"); $shash{$TID}{return} = 0; #cant download part, delete temporary part files close FH || writeLog('e', "Can't close part file\n$!"); foreach my $p (glob "part*.pt") { unlink $p || writeLog('e', "Can't delete part\n$!"); } writeLog('e', "Unable to download article"); last; } } } close FH || writeLog('e', "Unable to close part file\n$!"); } else { writeLog('e', "Article number not supplied"); } } else { #for multipart messages my $partNumber = $firstPart; eval { $$nntpRef->group($groupName) }; foreach my $i (@options) { #create a temporary file and download the part open ('FH', '> :raw', 'part' . $partNumber . '.pt') || writeLog('f', $!); #download each part of the multipart message eval { $ok = $$nntpRef->article($i, *FH) }; if (! $ok) { #download failed, re-connect and retry eval { $$nntpRef->quit }; eval { $nntpRef = nntpconnect() }; if ($nntpRef) { #re-connected eval { $ok = $$nntpRef->article($i, *FH) }; } else { #could not connect writeLog('e', "Couldn't connect to server"); $shash{$TID}{return} = 0; #cant download part, delete temporary part files foreach my $p (glob "part*.pt") { unlink $p || writeLog('e', "Can't delete part\n$!"); } writeLog('e', "Unable to download article"); last; } } $partNumber++; if ($ok) { #part downloaded, try next part $shash{$TID}{progress} = $partNumber; } close FH || writeLog('e', "Unable to close part file\n$!"); } } #close nntp connection and set return eval { $$nntpRef->quit }; if ($ok) { $shash{$TID}{return} = 1; } else { $shash{$TID}{return} = 0; } } #go back to sleep $shash{$TID}{optionCSV} = 0; $shash{$TID}{article} = 0; } #elsif ($shash{$TID}{xover} == 1) { #XOVER # my ($fMsg,$lMsg,$grp) = split (/,/, $shash{$TID}{optionCSV}); # my ($href, $return,); # # if ($fMsg && $lMsg) { # my @range = ($fMsg, $lMsg); # my $nntpRef; # eval { $nntpRef = nntpconnect() }; # if (! $nntpRef) { # writeLog('e', "Couldn't connect to server"); # } # else { # #connected, get xover information # $$nntpRef->group($grp); # $href = $$nntpRef->xover(\@range); # } # eval { $$nntpRef->quit }; # } # else { # writeLog('e', 'Invalid range in xover worker'); # } # # #go back to sleep # if ($href) { %sHoA = %$href; $return = 1; } # else { $return = 0; } # $shash{$TID}{return} = $return; # $shash{$TID}{xover} = 0; #} elsif ($shash{$TID}{list} == 1) { #LIST my ($nntpRef, $connected,); #connect eval { $nntpRef = nntpconnect() }; if (! $nntpRef) { #retry once eval { $nntpRef = nntpconnect() }; if (! $nntpRef) { $connected = 0; } else { $connected = 1; } } else { $connected = 1; } if ($connected) { my (%HoA, $HoA_ref,); #get list of newsgroups eval { $HoA_ref = $$nntpRef->list() }; if ($HoA_ref) { #(HoA_ref) groupname = last, first, moderated #pl.misc.telefonia.gsm: 0000339959 0000307277 y #mvis.lists.apache.talk: 0000003574 0000003322 m %HoA = %$HoA_ref; undef $HoA_ref; } eval { $$nntpRef->quit() }; #create groups database { my (%groups,); tie %groups, 'MLDBM', 'groups', O_CREAT|O_RDWR, 0640 || writeLog('f', $!); for my $groupname (keys %HoA) { my $articleTot = $HoA{$groupname}[0] - $HoA{$groupname}[1]; $groups{$groupname} = $articleTot; } untie %groups; } } else { writeLog('e', "Unable to connect to server, try again"); } $shash{$TID}{list} = 0; } sleep (1); } writeLog('w', 'Thread: [' . $TID . '] is closing'); return (0); } sub load_image #-------------------------------------------------------- { #called from various subroutines, returns imagedata my $opt = int $_[0] || return (0); my $imagedata; if ($opt == 2) { $imagedata = 'Qk1YAgAAAAAAADYAAAAoAAAACgAAABEAAAABABgAAAAAAAAAAAASCwAAEgsAAA'. 'AAAAAAAAAA////////////////////////////////////////AAD4+Pj/////'. '//////////////////////////////8AAP////////////////////////////'. '39/f39/fj4+AAA////////////////////////////////////////AAD/////'. '///+/v7+/v79/f39/f3+/v7///////////8AAGZHumlKvUYvi4p0xotyzVhEkm'. 'BFp1w8sP38/v///wAAdlfK////////9fL79fP8+vj//fz/i3LN+vn9////AABm'. 'R7r49//4+/9JTFsXGCGvr7b///9sU7X////9/f8AAGZHuvHu/sPG1RYZKBobKx'. 'AQFGFedGFHrPz8/f79/wAAa0+6/Pv/Xl5mAAAIq6yyJygrAAASZE6i+/v9/v7/'. 'AAByWLv49f/R0NfLy9Dw8PStrrUHBhBRP4P///////8AAHNVv/v6/fXy+vj3/P'. 'Lv+vHv+RcSJgUDCO/v7////wAAgGTGeV3AlX3RhGjLi3LNi3LNdlrAIiElDQsT'. '7+/vAAD///3///7+/f/////////////9/fz39/clJyPQ0NAAAP////////////'. '///////////////////////////wAA/v7+////////////////////////+/v7'. '////+Pj5AAD////////+/v7+/v7+/v7////////////////7/PsAAAAA'; } elsif ($opt == 3) { $imagedata = 'Qk1YAgAAAAAAADYAAAAoAAAACgAAABEAAAABABgAAAAAAAAAAAASCwAAEgsAAA'. 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHBwcAAAAA'. 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. 'ICAgICAgcHBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. 'AAARDSABAQEBAQEAAAAAAAANCRgAAAAAAAAAAGZHunZXymtQtmZHumlYmHNfqm'. 'tRsWxSsAgHDQAAAAAAdlfKAAAAAAAACg0ECgwDBQcAAgMAZke6HBYuAAAAAABm'. 'R7oHCAAHBAC2s6To595QUEkAAABtWKgZES0BAQAAAGZHug4RATw5Kunm1+Xk1O'. '/v656hi3JepREMHQAAAAAAa0+6AwQAoaGZ///3VFNN2NfU///taUy1GRIsAQEA'. 'AAByWLsHCgAjIx4qKiYODgpSUUr4+e9sUrQYESwAAAAAAHNVvwoJDg0KFRwUMB'. 'wYKBQTEdDO0/r89xAQEAAAAAAAbU69Zke6ZkytZ0uzaVSgZke6Zke63d7a8vTs'. 'EBAQAAAAAAIAAAEBAgAAAAAAAAAAAAACAgMICAja2NwvLy8AAAAAAAAAAAAAAA'. 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAAAAAAAAAAAAAAAAAAAAAAAABAQE'. 'AAAABwcGAAAAAAAAAAABAQEBAQEBAQEAAAAAAAAAAAAAAAAEAwQAAAAA'; } elsif ($opt == 10) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAoaGh oaGhoKCgoKCgoKCgnJyckJCQiIiIh4eHh4eHhYWFhYWFhISEhISEhISEg4ODg4ODg4ODg4ODgoKC goKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg4ODg4ODg4ODhISEhISEhISEhYWFhYWFhoaGhoaG hoaGh4eHh4eHh4eHh4eHh4eHiIiIiIiIiIiIjIyMlJSUnp6eoaGhoaGhoaGhoaGhoaGhoaGhoaGh oKCgoKCgkpKSj4+Purq61NTU29vb2dnZ2tra2dnZ2NjY1tbW1tbW1dXV1dXV1dXV1NTU1NTU1NTU 09PT09PT09PT09PT09PT09PT09PT1NTU1dXV1dXV1dXV1tbW1tbW2NjY2dnZ2tra29vb3Nzc3Nzc 3Nzc3d3d3d3d3t7e3t7e39/f39/f39/f0dHRsrKyioqKlJSUoaGhoaGhoaGhoaGhoaGhoaGhoKCg jo6OoqKi6enp/Pz8+/v7+vr6+fn5+Pj49vb29fX19PT08/Pz8vLy8fHx8fHx8PDw7+/v7+/v7+/v 7+/v7+/v7u7u7+/v7+/v7+/v8PDw8PDw8fHx8vLy8/Pz9PT09fX19/f3+Pj4+fn5+vr6+/v7/Pz8 /f39/f39/v7+/v7+////////////////////5ubmoaGhjo6OoaGhoaGhoaGhoaGhoKCgkZGRoKCg +fn5/Pz8+/v7+vr6+fn5+Pj49vb29fX18/Pz8vLy8fHx8PDw7+/v7u7u7u7u7e3t7Ozs7Ozs7Ozs 7Ozs7Ozs7Ozs7Ozs7Ozs7u7u7u7u7+/v8PDw8fHx8vLy8/Pz9fX19/f3+Pj4+fn5+vr6+/v7/Pz8 /f39/v7+/v7+/v7+/////////////////////Pz8qqqqj4+PoaGhoaGhoaGhmZmZi4uL5+fn9vb2 9fX19PT08/Pz8vLy8fHx7+/v7e3t6+vr6urq6enp6Ojo5ubm5ubm5eXl5OTk5OTk5OTk5OTk5OTk 5OTk5OTk5OTk5OTk5eXl5ubm5ubm6Ojo6enp6urq7Ozs7u7u7+/v8fHx8/Pz9PT09fX19vb29/f3 9/f3+Pj4+Pj4+fn5+fn5+fn5+fn5+fn5+fn58/PznJyck5OToaGhoaGhjIyMxcXF7+/v7u7u7e3t 7Ozs6+vr6enp6Ojo5ubm5eXl4+Pj4eHh39/f3t7e3d3d3Nzc3Nzc29vb29vb2tra2tra2tra2tra 2tra2tra29vb3Nzc3d3d3d3d39/f4eHh4uLi4+Pj5eXl5+fn6Ojo6urq6+vr7e3t7u7u7u7u7+/v 8PDw8PDw8fHx8fHx8fHx8fHx8fHx8fHx8fHx4ODgh4eHn5+fnJycjo6O4uLi5eXl5OTk4+Pj4uLi 4eHh39/f3d3d29vb2dnZ2NjY1tbW1NTU09PT0tLS0dHR0NDQ0NDQz8/Pz8/Pz8/Pz8/Pz8/Pz8/P z8/P0NDQ0dHR0tLS09PT1NTU1dXV19fX2dnZ2tra3Nzc3t7e4ODg4uLi4uLi4+Pj5OTk5eXl5ubm 5ubm5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fnp6enlZWVlJSUpKSk29vb2tra2dnZ2NjY19fX1dXV 09PT0tLS0NDQzs7OzMzMy8vLycnJyMjIx8fHxsbGxsbGxcXFxMTExMTExMTEw8PDw8PDxMTExMTE xcXFxsbGxsbGx8fHycnJysrKzMzMzc3Nz8/P0dHR09PT1dXV1tbW2NjY2dnZ2dnZ2tra29vb29vb 3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3NzcxMTEiYmJjIyMsrKyzs7Ozs7Ozc3NzMzMy8vLycnJyMjI xsbGxcXFw8PDwcHBv7+/vr6+vLy8vLy8u7u7urq6ubm5ubm5uLi4uLi4uLi4uLi4uLi4ubm5ubm5 u7u7vLy8vLy8vb29v7+/wMDAwsLCxMTExcXFx8fHycnJysrKzMzMzc3Nzs7Ozs7Oz8/Pz8/P0NDQ 0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQy8vLgoKChoaGt7e3wsLCwsLCwcHBwMDAv7+/v7+/vr6+vb29 vLy8u7u7uLi4t7e3tbW1vaem32Vf8kI48kI46lBH0Xp1sbGxsbGx1nNt7kk/8kI45VdOsrKy419W 8kI45lhP8kI4419XuLi48kI45GBYvb295WFZ8kI4wcHBwsLCw8PDxMTExMTExcXFxcXFxsbGxcXF xcXFxMTExMTExMTExMTExMTEwMDAgoKCg4ODs7OzuLi4t7e3tra2tra2urq6u7u7u7u7urq6ubm5 t7e3tbW1tLS0s7OzwpqX6FxTyY2JwZiW1Hp08FBGyIyI0IF78FBG1Hp0wJiW1Hp0wZiW8FBG3W9o xpSQ8FBG4WpitbW18FBG4mtjurq642tk8FBGvb29vr6+v7+/wMDAwcHBwcHBwcHBwsLCwsLCwMDA vLy8ubm5ubm5ubm5ubm5tra2goKCgoKCq6urrq6urq6urKyssrKyurq6u7u7urq6ubm5t7e3t7e3 tra2tLS0tLS0t66us7Ozs7Ozwp2b3Xhy8F5V0IiE4HNt8F5VsbGxsrKysrKyt62t7GRb6Glh0omF 8F5V4XRttra28F5V4nRuubm54nVv8F5VvLy8vb29vb29vr6+v7+/v7+/v7+/v7+/v7+/v7+/u7u7 srKyr6+vr6+vr6+vrKysgoKCg4ODoqKipqampqamp6entbW1vr6+vr6+vb29vLy8u7u7urq6urq6 ubm5uLi4t7e305SQ7XRt8HBo8HBo7XRtva2s3oaB8HBovq6tt7e3vq6ut7e3u7OyyqKf1JSR8HBo 4oJ8urq68HBo44N9vLy85IN+8HBov7+/v7+/wMDAwcHBwcHBwcHBwcHBwcHBwcHBwcHBwMDAs7Oz qKiop6enp6enpaWlgoKCh4eHmZmZoKCgoKCgp6envb29xMTExMTEw8PDw8PDwcHBwcHBwcHBwMDA wMDAybSy8oN974eB252a0qimwbu6vr6+yLSy74eB74eB5ZKN8oN9vr6+4paS5ZKN6I+J8oN93J6b wcHB8oN974eB5pOO8oN97IuGxMTExMTExcXFxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGurq6paWl oaGhoaGhn5+fgoKCjY2Nk5OToKCgoKCgrq6uysrKz8/Pzs7Ozs7Ozs7Ozc3NzMzMzMzMzMzMy8vL 08LB9JmT56ily8vLzcfH2ri20sHAysrK0MTD3bWy37Kv2Lu5y8vL08LB4LKw4LKw27m2zMzMzMzM 18C+1cPC18C/4bSx08jHz8/Pz8/Pz8/P0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQx8fHq6uroaGh oaGhn5+fgoKClZWVi4uLoKCgoKCgtLS01NTU2dnZ2dnZ2NjY2NjY19fX19fX19fX19fX1tbW1tbW 6MC99q6p9q6p9q6p9q6p3M7N1tbW1tbW1tbW1tbW1tbW1tbW1tbW19fX19fX19fX19fX19fX19fX 2NjY2NjY2NjY2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2tra2tra2tra2tra2tra0dHRr6+voaGhoaGh l5eXioqKnp6eg4ODnp6eoKCgsLCw2NjY4uLi4uLi4uLi4uLi4uLi4eHh4eHh4eHh4eHh4eHh4eHh 4t/f59nY59nY4eHh4ODg4ODg4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4uLi 4uLi4uLi4uLi4uLi4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj0tLSq6uroaGhoaGhioqK l5eXoaGhkJCQkJCQoKCgqamp1tbW6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6urq6urq 6urq6urq6urq6urq6urq6urq6urq6urq6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr 6+vr6+vr6+vr7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs6+vry8vLpaWloaGhmZmZgYGBoKCg oaGhnZ2dgYGBmZmZoqKixsbG7u7u8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz9PT09PT09PT09PT09PT05+fnubm5oaGhnZ2dhYWFlZWVoaGhoaGh oaGhlJSUhYWFnZ2dsbGx4eHh+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr68/Pzzs7Op6ennp6eiIiIkZGRoaGhoaGhoaGhoaGh oaGhkJCQhISEmpqavLy84ODg8vLy9/f39/f3+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn58/Pz5eXly8vLrKyslpaWhYWFkJCQoaGhoaGhoaGhoaGhoaGhoaGh oaGhlpaWgYGBjIyMoaGhsrKyurq6vb29wMDAwcHBwcHBwMDAwMDAwMDAwMDAwMDAwMDAwMDAwcHB wcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHB wcHBwcHBwcHBwcHBwMDAtra2pqamlpaWioqKgICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 101) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAoaGh oaGhoKCgoKCgoKCgnJyckJCQiIiIh4eHh4eHhYWFhYWFhISEhISEhISEg4ODg4ODg4ODg4ODgoKC goKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg4ODg4ODg4ODhISEhISEhISEhYWFhYWFhoaGhoaG hoaGh4eHh4eHh4eHh4eHh4eHiIiIiIiIiIiIjIyMlJSUnp6eoaGhoaGhoaGhoaGhoaGhoaGhoaGh oKCgoKCgkpKShoaGmpqapaWlqampqKioqKiop6enp6enpaWlpaWlpaWlpKSkpKSko6Ojo6Ojo6Oj o6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6OjpKSkpKSkpaWlpaWlpaWlp6enp6enqKioqampqampqqqq qqqqq6urq6urq6urq6urrKysrKysrKyspqaml5eXhYWFlJSUoaGhoaGhoaGhoaGhoaGhoaGhoKCg jo6Oj4+PsLCwubm5uLi4t7e3t7e3tra2tLS0tLS0s7OzsrKysbGxsbGxsbGxsLCwr6+vr6+vr6+v r6+vr6+vr6+vr6+vr6+vr6+vsLCwsLCwsbGxsbGxsrKys7OztLS0tbW1tra2t7e3t7e3uLi4ubm5 urq6urq6urq6urq6u7u7u7u7u7u7u7u7u7u7r6+vkJCQjo6OoaGhoaGhoaGhoaGhoKCgkZGRj4+P uLi4ubm5uLi4t7e3t7e3tra2tLS0tLS0srKysbGxsbGxsLCwr6+vr6+vr6+vrq6ura2tra2tra2t ra2tra2tra2tra2tra2tr6+vr6+vr6+vsLCwsbGxsbGxsrKytLS0tbW1tra2t7e3t7e3uLi4ubm5 urq6urq6urq6urq6u7u7u7u7u7u7u7u7u7u7urq6lJSUj4+PoaGhoaGhoaGhmZmZhISEsLCwtra2 tbW1tLS0tLS0s7OzsrKysbGxr6+vrq6ura2trKysrKysqqqqqqqqqqqqqampqampqampqKioqKio qKioqKioqampqampqqqqqqqqqqqqrKysrKysra2tr6+vsLCwsbGxsrKytLS0tLS0tbW1tra2t7e3 t7e3t7e3t7e3uLi4uLi4uLi4uLi4uLi4uLi4tbW1jY2Nk5OToaGhoaGhjIyMnp6esrKysbGxsLCw r6+vr6+vra2trKysq6urqqqqqKiop6enpqampaWlpKSkpKSkpKSko6Ojo6OjoqKioqKioqKioqKi oqKioqKio6OjpKSkpKSkpKSkpqamp6enqKioqKioqqqqq6urra2trq6ur6+vsLCwsbGxsbGxsrKy srKysrKys7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozq6urg4ODn5+fnJychYWFqqqqrKysq6urqqqqqamp qKiop6enpqampKSko6OjoaGhoKCgn5+fnp6enZ2dnZ2dnJycnJycm5ubm5ubm5ubm5ubm5ubm5ub m5ubnJycnZ2dnZ2dnp6en5+fn5+foaGhoqKipKSkpaWlpqamqKioqampqqqqqqqqq6urrKysrKys rKysra2tra2tra2tra2tra2tra2tra2tra2tkZGRlZWVlJSUj4+PpqampqampKSkpKSko6OjoqKi oKCgn5+fnp6enZ2dm5ubmpqamZmZmJiYl5eXl5eXlpaWlZWVlZWVlZWVlZWVlJSUlJSUlZWVlZWV lZWVlpaWl5eXl5eXmZmZmZmZm5ubnJycnZ2dnp6eoKCgoqKioqKipKSkpKSkpaWlpqampqampqam p6enp6enp6enp6enp6enp6enp6enp6ennZ2diYmJjIyMk5OTn5+fn5+fnZ2dnZ2dnJycm5ubmpqa mJiYl5eXlpaWlJSUk5OTkpKSkZGRkJCQkJCQj4+Pjo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6O kJCQkJCQkZGRkpKSk5OTk5OTlZWVl5eXmJiYmZmZmpqanJycnZ2dnZ2dnp6en5+fn5+fn5+foKCg oKCgoKCgoKCgoKCgoKCgoKCgoKCgnp6egoKChoaGk5OTmJiYl5eXl5eXlpaWlpaWlpaWl5eXlpaW lpaWlJSUk5OTkZGRkJCQm4WEzFNM6Dku6Dku3UM6umJejY2NjY2Nv15X4z406Dku10lAjo6O0U1G 6Dku2ElA6Dku0k5Hk5OT6Dku009IlpaW1FBI6DkumZmZmpqam5ubm5ubnJycnJycnJycnJycm5ub mpqamZmZmZmZmZmZmZmZmZmZmJiYgoKCg4ODkJCQkpKSkZGRkZGRkpKSl5eXm5ubm5ubmpqamZmZ mJiYlpaWlpaWlZWVqYF+3lJIs3hzqIF+wmlj6Eg+s3ZyvW1o6Eg+wmljqIB9wmljqIF+6Eg+zmBZ r3156Eg+01xUlpaW6Eg+1FxVmpqa1V1V6Eg+nZ2dnZ2dnp6enp6en5+fn5+fn5+foKCgn5+fnZ2d mJiYk5OTk5OTk5OTk5OTkpKSgoKCgoKCi4uLjIyMjIyMi4uLk5OTn5+foaGhn5+fn5+fnp6enp6e nJycm5ubm5ubn5eWmpqampqarYiH0G1m6lhPwXh01mlh6lhPmZmZmZmZmZmZn5aV5VxU4GFZwnl1 6lhP1mlinZ2d6lhP1mljn5+f12pj6lhPoqKioqKio6Ojo6Ojo6Ojo6Ojo6OjpKSkpKSkpKSknp6e kpKSjY2NjY2NjY2NjIyMgoKCg4ODhoaGh4eHh4eHiYmJm5ubqampqampqKiop6enp6enpqampaWl pKSkpKSkpKSkx4eD525n62tj62tj525nq5ub1Hx362tjrJybo6OjrJybo6OjqKCgupKPyIiE62tj 2np0pqam62tj2np0qKio2np162tjqampqqqqqqqqq6urq6urq6urq6urq6urq6urq6urqampmJiY iYmJiIiIiIiIiIiIgoKCh4eHg4ODhISEhISEjY2Nq6urtLS0s7Ozs7OzsrKysrKysbGxsLCwsLCw sLCwu6al7X946oJ80pSQxp2as6yrr6+vu6ak6YJ86YJ83ouG7X94r6+v2o6K3ouG4oiD7X9405WR sbGx7X946oJ83oyH7X945oaAtLS0tLS0tLS0tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1pqamioqK hYWFhYWFhYWFgoKCjY2NgoKChISEhISEl5eXu7u7wcHBwcHBwMDAwMDAwMDAv7+/v7+/vr6+vr6+ yLe18ZWQ4aKevr6+wLu60a6sx7a1vb29xLi41Kyp16qnzrGvvr6+yLe116qn16qn0q+tv7+/v7+/ zLWzybi3zLW02auox7u7wcHBwcHBwcHBwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCt7e3kpKShYWF hYWFhYWFgoKClZWVgYGBhISEhYWFnp6eyMjIzs7Ozc3Nzc3Nzc3Nzc3Nzc3NzMzMzMzMzMzMzMzM 4rm39Kun9Kun9Kun9Kun08bEzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzc3N zc3Nzc3Nzc3Nzc3Nzs7Ozs7Ozs7Ozs7Ozs7Ozs7Oz8/Pz8/Pz8/Pz8/Pz8/PxMTEl5eXhYWFhYWF g4ODioqKnp6egYGBhISEhISEmZmZzc3N2tra2tra2tra2tra2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ 2tfX4NLR4NLR2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ 2tra2tra2tra2tra2tra2tra2tra2tra2tra29vb29vb29vb29vb29vbxcXFkpKShYWFhYWFgoKC l5eXoaGhkJCQgoKChISEkJCQysrK5ubm5ubm5ubm5ubm5ubm5eXl5eXl5eXl5eXl5eXl5eXl5eXl 5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5ubm5ubm5ubm 5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5OTku7u7ioqKhYWFhISEgICAoKCg oaGhnZ2df39/g4ODhoaGtra26urq8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw 8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw 8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw39/fpKSkhYWFhISEgYGBlZWVoaGhoaGh oaGhlJSUgICAhISEmpqa2NjY+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn57+/vwMDAjY2NhYWFgYGBkZGRoaGhoaGhoaGhoaGh oaGhkJCQgICAhoaGqKio19fX7u7u9PT09fX19/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3 9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3 9/f39/f39/f39/f39/f39/f37+/v3t7evLy8lJSUg4ODgYGBkJCQoaGhoaGhoaGhoaGhoaGhoaGh oaGhlpaWf39/gYGBkJCQpKSkra2tr6+vs7OztLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0 tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tbW1tbW1 tbW1tbW1tbW1tbW1s7Ozp6enlJSUhYWFgYGBgICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 11) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAoaGh oaGhoKCgoKCgoKCgnJyckJCQiIiIh4eHh4eHhYWFhYWFhYWFhISEhISEhISEg4ODg4ODg4ODg4OD goKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg4ODg4ODg4ODhISEhISEhISEhYWFhYWFhoaG hoaGh4eHh4eHh4eHh4eHh4eHiIiIiIiIiIiIjIyMlJSUnp6eoaGhoaGhoaGhoaGhoaGhoaGhoaGh oKCgoKCgkpKSj4+Purq61NTU29vb2dnZ2tra2dnZ2NjY19fX1tbW1dXV1dXV1dXV1dXV1NTU1NTU 1NTU1NTU09PT09PT09PT09PT09PT1NTU1NTU1NTU1dXV1dXV1tbW1tbW2NjY2dnZ2tra29vb3Nzc 3Nzc3d3d3d3d3t7e3t7e39/f39/f39/f0dHRsrKyioqKlJSUoaGhoaGhoaGhoaGhoaGhoaGhoKCg jo6OoqKi6enp/Pz8+/v7+vr6+fn5+Pj49/f39fX19PT08/Pz8vLy8vLy8fHx8fHx8PDw8PDw7+/v 7+/v7+/v7+/v7+/v7+/v7+/v7+/v8PDw8PDw8fHx8vLy8/Pz9PT09fX19/f3+Pj4+fn5+vr6+/v7 /Pz8/f39/v7+/v7+/v7+////////////////5ubmoaGhjo6OoaGhoaGhoaGhoaGhoKCgkZGRoKCg +fn5/Pz8+/v7+vr6+fn5+Pj49/f39fX19PT08vLy8fHx8PDw7+/v7+/v7+/v7u7u7e3t7e3t7Ozs 7Ozs7Ozs7Ozs7Ozs7Ozs7e3t7u7u7u7u7+/v8PDw8fHx8vLy9PT09fX19/f3+Pj4+vr6+/v7/Pz8 /f39/f39/v7+/v7+/////////////////////Pz8qqqqj4+PoaGhoaGhoaGhmZmZi4uL5+fn9/f3 9vb29fX18/Pz8vLy8fHx7+/v7e3t7Ozs6+vr6urq6Ojo5+fn5ubm5ubm5eXl5eXl5OTk5OTk5OTk 5OTk5OTk5OTk5OTk5OTk5eXl5eXl5ubm6Ojo6enp6urq7Ozs7u7u8PDw8vLy8/Pz9PT09fX19vb2 9/f3+Pj4+Pj4+fn5+fn5+fn5+fn5+fn5+fn58/PznJyck5OToaGhoaGhjIyMxcXF7+/v7u7u7e3t 7Ozs6+vr6enp6Ojo5+fn5eXl4+Pj4uLi4eHh39/f3t7e3d3d3d3d3Nzc29vb29vb29vb2tra2tra 2tra2tra2tra29vb3Nzc3Nzc3d3d3t7e4ODg4uLi5OTk5ubm5+fn6enp6urq7Ozs7e3t7u7u7+/v 8PDw8PDw8fHx8fHx8fHx8fHx8fHx8fHx8fHx4ODgh4eHn5+fnJycjo6O4uLi5eXl5OTk4+Pj4uLi 4eHh39/f3d3d3Nzc2tra2dnZ19fX1dXV1NTU09PT0tLS0tLS0dHR0NDQ0NDQz8/Pz8/Pz8/Pz8/P z8/Pz8/P0NDQ0NDQ0dHR0tLS09PT1dXV19fX2dnZ2tra3Nzc3t7e4eHh4uLi4uLi5OTk5eXl5ubm 5ubm5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fnp6enlZWVlJSUpKSk29vb2tra2dnZ2NjY19fX1tbW 09PT09PT0dHRz8/Pzc3NzMzMysrKycnJx8fHx8fHxsbGxsbGxcXFxcXFxMTExMTEw8PDw8PDxMTE xMTExcXFxsbGxsbGxsbGyMjIysrKzMzMzc3Nz8/P0tLS09PT1dXV19fX2NjY2dnZ2tra29vb29vb 3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3NzcxMTEiYmJjIyMsrKyzs7Ozs7Ozs7OzMzMy8vLycnJyMjI xsbGxcXFw8PDwcHBwMDAvr6+vb29vLy8vLy8u7u7urq6ubm5ubm5uLi4uLi4uLi4uLi4uLi4uLi4 ubm5urq6u7u7vLy8vb29vr6+wMDAwsLCxMTExcXFx8fHycnJy8vLzMzMzc3Nzs7Ozs7Oz8/P0NDQ 0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQy8vLgoKChoaGt7e3wsLCwsLCwcHBwMDAv7+/v7+/vr6+vb29 vLy8u7u7ubm5uLi4tra2tbW1ua2t221m7kk/8kI46lBH2mxlsbGx0Xp18kI4wZaTsbGxsbGx4l5W 8kI45ldO8kI4419Xtra2419Y8kI47kpA8kI43HlzwMDAwcHBwsLCw8PDxMTExMTExcXFxsbGxcXF xcXFxMTExMTExMTExMTExMTEwMDAgoKCg4ODs7OzuLi4uLi4t7e3tra2urq6u7u7u7u7urq6ubm5 t7e3tra2tLS0tLS0s7Oz4Glh8FBG2HVuwZiW5GNa8FBGsLCw0IF78FBGwJiWsLCwwJiW8FBG3G9n xZOP8FBG4GlhtLS04Wpi8FBGxp2b33Jq8FBGyaGevr6+vr6+v7+/wcHBwcHBwcHBwsLCwsLCwMDA vLy8ubm5ubm5ubm5ubm5tra2goKCgoKCq6urrq6urq6ura2tsrKyurq6u7u7u7u7ubm5uLi4t7e3 tra2tbW1tLS0u6mo8F5V4XRts7Ozwp2b5G5n8F5VsbGx0IiE8F5VwZyasbGxtaur7GRb6Glh0YiE 8F5V4XRttLS04nRt8F5Vt7e3xqKg8F5V1o2IvLy8vb29vr6+v7+/v7+/v7+/v7+/v7+/v7+/u7u7 srKyr6+vr6+vr6+vrKysgoKCg4ODoqKipqampqamp6entbW1vr6+vr6+vr6+vLy8vLy8u7u7urq6 urq6ubm5xqak8HBo05SQt7e38HBo8HBo8HBotra205OP8HBoyKCdtra2tra2urKyyaGf05SQ8HBo 4oJ8ubm544N88HBou7u7zKSi8HBo15eTv7+/v7+/wMDAwcHBwcHBwcHBwcHBwcHBwcHBwMDAs7Oz qKiop6enp6enpaWlgoKCh4eHmZmZoKCgoKCgp6envb29xMTExMTEw8PDw8PDwsLCwcHBwcHBwMDA wMDAybSz8oN93pqVvr6+vr6+vr6+vr6+vr6+2KGe8oN96I6J8oN9vr6+4ZaR5ZKN6I6J8oN93J6a wMDA5pON8oN96Y+K74eB8oN9yry7xMTExMTExcXFxsbGxsbGxsbGxsbGxsbGxsbGxsbGurq6paWl oaGhoaGhn5+fgoKCjY2Nk5OToKCgoKCgrq6uysrKz8/Pzs7Ozs7Ozs7Ozc3Nzc3NzMzMzMzMzMzM y8vL7KKe9JmT1b69y8vL0MTD6qWhysrK0MTD1b68zcfH1b68ysrK08HA37Kv37Kv27i2zMzMzMzM 6qai9JmT1cPC4bOx2MG/z8/Pz8/Pz8/P0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQx8fHq6uroaGh oaGhn5+fgoKClZWVi4uLoKCgoKCgtLS01NTU2dnZ2dnZ2NjY2NjY2NjY19fX19fX19fX19fX1tbW 3M/O8LWy9q6p9q6p9q6p8rOv1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW19fX19fX7ri1 9q6p2NjY2NjY2NjY2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2tra2tra2tra2tra2tra0dHRr6+voaGhoaGh l5eXioqKnp6eg4ODnp6eoKCgsLCw2NjY4uLi4uLi4uLi4uLi4uLi4eHh4eHh4eHh4eHh4eHh4eHh 4eHh5dva59nY5dva4ODg4ODg4ODg4ODg4ODg4ODg4ODg4eHh4eHh4eHh4eHh4eHh4eHh5tvb59nZ 4uLi4uLi4uLi4uLi4uLi4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj0tLSq6uroaGhoaGhioqK l5eXoaGhkJCQkJCQoKCgqamp1tbW6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6urq 6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6+vr6+vr6+vr6+vr6+vr6+vr6+vr 6+vr6+vr6+vr6+vr7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs6+vry8vLpaWloaGhmZmZgYGBoKCg oaGhnZ2dgYGBmZmZoqKixsbG7u7u8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz9PT09PT09PT09PT09PT05+fnubm5oaGhnZ2dhYWFlZWVoaGhoaGh oaGhlJSUhYWFnZ2dsbGx4eHh+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr68/Pzzs7Op6ennp6eiIiIkZGRoaGhoaGhoaGhoaGh oaGhkZGRhISEmpqavLy84ODg8vLy9/f39/f3+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn58/Pz5eXly8vLrKyslpaWhYWFkJCQoaGhoaGhoaGhoaGhoaGhoaGh oaGhl5eXgYGBjIyMoaGhsrKyurq6vb29wMDAwcHBwcHBwcHBwMDAwMDAwMDAwMDAwMDAwMDAwMDA wMDAwMDAwMDAwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHB wcHBwcHBwcHBwcHBwMDAtra2pqamlpaWioqKgICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 111) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAoaGh oaGhoKCgoKCgoKCgnJyckJCQiIiIh4eHh4eHhYWFhYWFhYWFhISEhISEhISEg4ODg4ODg4ODg4OD goKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg4ODg4ODg4ODhISEhISEhISEhYWFhYWFhoaG hoaGh4eHh4eHh4eHh4eHh4eHiIiIiIiIiIiIjIyMlJSUnp6eoaGhoaGhoaGhoaGhoaGhoaGhoaGh oKCgoKCgkpKSioqKp6enurq6vb29vLy8vLy8vLy8u7u7urq6ubm5ubm5ubm5uLi4uLi4t7e3t7e3 t7e3t7e3tra2tra2tra2tra2tra2t7e3t7e3t7e3uLi4ubm5ubm5ubm5u7u7vLy8vLy8vb29vr6+ v7+/v7+/v7+/wMDAwMDAwcHBwcHBwcHBuLi4oqKih4eHlJSUoaGhoaGhoaGhoaGhoaGhoaGhoKCg jo6Ol5eXyMjI1NTU1NTU09PT0tLS0dHR0NDQz8/Pzs7Ozc3NzMzMzMzMy8vLy8vLysrKysrKysrK ysrKysrKysrKysrKysrKysrKysrKysrKysrKy8vLzMzMzc3Nzs7Oz8/P0NDQ0dHR0tLS09PT1NTU 1NTU1dXV1tbW1tbW1tbW19fX19fX19fX19fXxsbGl5eXjo6OoaGhoaGhoaGhoaGhoKCgkZGRlpaW 0tLS1NTU1NTU09PT0tLS0dHR0NDQz8/Pzs7OzMzMy8vLysrKysrKysrKysrKycnJyMjIyMjIx8fH x8fHx8fHx8fHx8fHx8fHyMjIycnJycnJysrKysrKy8vLzMzMzs7Oz8/P0NDQ0dHR09PT1NTU1NTU 1dXV1dXV1tbW1tbW19fX19fX19fX19fX19fX1dXVnZ2dj4+PoaGhoaGhoaGhmZmZh4eHxcXFz8/P z8/Pzs7OzMzMy8vLysrKycnJx8fHxsbGxsbGxcXFw8PDwsLCwcHBwcHBwcHBwcHBwMDAwMDAwMDA v7+/v7+/v7+/wMDAwMDAwcHBwcHBwcHBw8PDxMTExcXFxsbGyMjIysrKy8vLzMzMzc3Nzs7Oz8/P z8/P0NDQ0NDQ0dHR0dHR0dHR0dHR0dHR0dHRzc3Nk5OTk5OToaGhoaGhjIyMrKysx8fHx8fHxsbG xcXFxMTEw8PDwcHBwMDAv7+/vb29vLy8vLy8urq6ubm5uLi4uLi4uLi4t7e3t7e3t7e3tra2tra2 tra2tra2tra2t7e3uLi4uLi4uLi4ubm5u7u7vLy8vr6+wMDAwMDAw8PDw8PDxcXFxsbGx8fHx8fH yMjIyMjIycnJycnJycnJycnJycnJycnJycnJvr6+hISEn5+fnJyciIiIvLy8vr6+vb29vLy8u7u7 urq6uLi4t7e3tra2tbW1s7OzsrKysLCwr6+vr6+vrq6urq6ura2trKysrKysrKysrKysq6urq6ur rKysrKysrKysrKysra2trq6ur6+vsLCwsrKys7OztbW1tra2uLi4urq6u7u7u7u7vb29vr6+vr6+ vr6+v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/mJiYlZWVlJSUlJSUs7Ozs7OzsrKysLCwsLCwr6+v ra2trKysq6urqampqKiop6enpaWlpKSko6Ojo6OjoqKioqKioaGhoaGhoKCgoKCgoKCgoKCgoKCg oKCgoaGhoqKioqKioqKipKSkpaWlp6enqKioqamprKysra2trq6usLCwsLCwsbGxs7Ozs7Ozs7Oz tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0pqamiYmJjIyMmZmZp6enp6enpqampaWlpKSko6OjoaGh oKCgn5+fnZ2dnJycm5ubmpqamZmZmJiYmJiYl5eXlpaWlpaWlpaWlZWVlZWVlZWVlZWVlZWVlZWV lpaWlpaWl5eXmJiYmZmZmpqam5ubnZ2dnp6en5+foaGho6OjpKSkpaWlpaWlpqamp6enp6enqKio qKioqKioqKioqKioqKioqKioqKiopqamgoKChoaGlpaWm5ubm5ubmpqamZmZmZmZmZmZmZmZmZmZ mJiYl5eXlpaWlZWVlJSUk5OTmIyLx1tT4z806Dou3UQ6xlpSkJCQu2Rf6DoupXp3j4+Pj4+P0k9H 6Dou2EpA6Dou009HlJSU01BI6Dou4z816DouxWNdm5ubnJycnZ2dnp6enp6en5+fn5+fn5+fnp6e nZ2dnJycnJycnJycnJycnJycmpqagoKCg4ODjo6OkJCQkJCQj4+PkJCQlpaWmZmZmZmZmJiYl5eX lpaWlpaWlZWVlJSUk5OT0lpT6Ec+yGRdp39811VO6Ec+kJCQvGxn6Ec+pn57kJCQpn576Ec+zV5Y rXp46Ec+01tTlJSU01tU6Ec+q4KBz2Fa6Ec+rYWDnJycnJycnZ2dnZ2dnZ2dnZ2dnp6enZ2dm5ub lpaWkZGRkZGRkZGRkZGRkJCQgoKCgoKChoaGhoaGhoaGhYWFjY2NmpqanJycm5ubm5ubmpqamZmZ mJiYmJiYl5eXoY+N6FdN02dglZWVqoWD2GNb6FdNlJSUvnZx6FdNqYWDlJSUmpCQ4ltS3l9Wv3Zx 6FdN02dgl5eX1Gdg6FdNmpqaroqI6FdNwnp1nZ2dnZ2dnp6en5+fn5+fn5+fn5+fn5+fn5+fmZmZ jIyMh4eHh4eHh4eHh4eHgoKCg4ODf39/f39/fn5+gYGBlZWVo6Ojo6OjoqKioqKioaGhoKCgoKCg oKCgn5+fsZGP6Wlhw4N/nZ2d6Wlh6Wlh6WlhnZ2dw4N/6WlhtY2KnZ2dnZ2dopqatY2Kw4N/6Wlh 1ndxn5+f13dx6WlhoaGhuJCN6WlhxoaCpKSkpKSkpKSkpKSkpaWlpaWlpaWlpaWlpaWlo6OjkJCQ gICAf39/f39/f39/goKCh4eHenp6eXl5eHh4g4ODo6Ojra2trKysrKysq6urq6urqqqqqqqqqamp qamptaCf7H130o2JqampqampqKioqKioqKioypOP7H1334WA7H13qKio14qG24iD34aA7H13z5CN qamp24mD7H134IaA54B67H13tKamra2tra2tra2tra2trq6urq6urq6urq6urq6urq6unZ2df39/ eXl5eXl5eXl5goKCjY2NfHx8eXl5eHh4jo6OtLS0u7u7u7u7u7u7urq6urq6urq6ubm5ubm5ubm5 uLi45ZuW75SOxq+uuLi4v7Oz4Z2ZuLi4v7Ozxq+tu7W1xq+tuLi4wrGw1Kaj1Kajzauoubm5ubm5 4p2Z75SOxLOy1aekyLGwu7u7u7u7vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8sLCwh4eHeXl5 eXl5eXl5goKClZWVfX19eXl5eXl5lZWVxMTEycnJycnJycnJycnJyMjIyMjIyMjIyMjIyMjIx8fH z8LB6q+s8qql8qql8qql7a2qx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHyMjIyMjI6LGu 8qqlyMjIycnJycnJycnJycnJysrKysrKysrKysrKysrKysrKysrKysrKysrKvr6+jY2NeXl5eXl5 e3t7ioqKnp6ef39/eXl5eXl5j4+PycnJ19fX1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1dXV1dXV 1dXV29HR3dDP29HR1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1tbW1tbW3NHR3tDP 1tbW1tbW1tbW1tbW19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXv7+/h4eHeXl5eXl5fn5+ l5eXoaGhkJCQfHx8eXl5hYWFxMTE4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj 4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj 4+Pj4+Pj4+Pj4+Pj4+Pj5OTk5OTk5OTk5OTk5OTk5OTk5OTk4uLitbW1fn5+eXl5e3t7gICAoKCg oaGhnZ2df39/enp6e3t7r6+v6Ojo7+/v7+/v7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u 7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u 7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v3Nzcm5ubeXl5enp6f39/lZWVoaGhoaGh oaGhlJSUf39/enp6kZGR1NTU+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4 +Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4 +Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj47u7uubm5goKCenp6fn5+kZGRoaGhoaGhoaGhoaGh oaGhkZGRf39/f39/oKCg1NTU7Ozs8/Pz9PT09vb29/f39/f39vb29vb29vb29vb29vb29vb29vb2 9vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29/f39/f39/f39/f39/f39/f39/f39/f3 9/f39/f39/f39/f39/f39vb27u7u2tratbW1iYmJe3t7f39/kJCQoaGhoaGhoaGhoaGhoaGhoaGh oaGhl5eXf39/fn5+ioqKnp6eqKioqamprq6ur6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+v r6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+v r6+vr6+vr6+vr6+vra2toKCgjIyMf39/fn5+gICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 12) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAoaGh oaGhoKCgoKCgoKCgnJyckJCQiIiIh4eHh4eHhYWFhYWFhISEhISEhISEg4ODg4ODgoKCgoKCgoKC goKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg4ODg4ODg4ODhISEhISEhYWFhYWF hoaGhoaGhoaGh4eHh4eHh4eHh4eHiIiIiIiIjIyMlJSUnp6eoaGhoaGhoaGhoaGhoaGhoaGhoaGh oKCgoKCgkpKSj4+Purq61NTU2tra2NjY2dnZ2NjY19fX1tbW1dXV1dXV1dXV1NTU1NTU09PT09PT 0tLS0tLS0tLS0tLS0tLS0tLS0tLS09PT09PT09PT1NTU1NTU1dXV1dXV1tbW19fX2dnZ2tra29vb 3Nzc3Nzc3Nzc3d3d3d3d3t7e3t7e39/f0dHRsrKyioqKlJSUoaGhoaGhoaGhoaGhoaGhoKCgoKCg jo6OoqKi6enp+/v7+vr6+fn5+Pj49/f39fX19PT08/Pz8vLy8fHx8PDw8PDw7+/v7+/v7u7u7u7u 7u7u7u7u7u7u7u7u7u7u7u7u7u7u7+/v7+/v8PDw8PDw8fHx8vLy8/Pz9PT09vb2+Pj4+fn5+vr6 +/v7/Pz8/Pz8/f39/v7+/v7+////////////5ubmoaGhjo6OoaGhoaGhoaGhoaGhoKCgkZGRoKCg +Pj4/Pz8+/v7+vr6+fn59/f39fX19PT08vLy8fHx8PDw7+/v7u7u7e3t7Ozs7Ozs6+vr6+vr6+vr 6urq6urq6+vr6+vr6+vr6+vr7Ozs7Ozs7e3t7u7u7+/v8PDw8fHx8/Pz9PT09vb2+Pj4+fn5+vr6 +/v7/Pz8/f39/v7+/v7+/////////////////Pz8qqqqj4+PoaGhoaGhoaGhmZmZi4uL5+fn9vb2 9fX19PT08/Pz8vLy8PDw7u7u7Ozs6urq6enp6Ojo5ubm5eXl5eXl5OTk5OTk5OTk4+Pj4+Pj4+Pj 4+Pj4+Pj4+Pj4+Pj5OTk5OTk5OTk5eXl5ubm5+fn6Ojo6urq6+vr7e3t7+/v8fHx8vLy9PT09fX1 9vb29/f39/f3+Pj4+Pj4+fn5+fn5+fn5+fn58/PznJyck5OToaGhoaGhjIyMxcXF7+/v7u7u7e3t 6+vr6urq6enp6Ojo5ubm5OTk4uLi4ODg3t7e3d3d3Nzc29vb29vb2tra2dnZ2dnZ2dnZ2NjY2NjY 2NjY2dnZ2dnZ2dnZ2tra29vb29vb3Nzc3t7e39/f4eHh4+Pj5eXl5+fn6Ojo6enp6+vr7Ozs7e3t 7u7u7+/v8PDw8PDw8fHx8fHx8fHx8fHx8fHx4ODgh4eHn5+fnJycjo6O4eHh5eXl4+Pj4uLi4uLi 4ODg3t7e3Nzc2tra2dnZ19fX1dXV09PT0tLS0dHR0NDQz8/Pz8/Pzs7Ozs7Ozc3Nzc3Nzc3Nzc3N zs7Ozs7Ozs7Oz8/Pz8/P0NDQ0dHR09PT1NTU1tbW2NjY2dnZ29vb3d3d4ODg4eHh4uLi4+Pj5OTk 5eXl5ubm5ubm5+fn5+fn5+fn5+fn5+fn5+fnp6enlZWVlJSUpKSk2tra2dnZ2dnZ2NjY1tbW1dXV 09PT0tLSz8/Pzc3Ny8vLycnJyMjIxsbGxsbGxcXFxMTEw8PDwsLCwsLCwsLCwsLCwsLCwsLCwsLC wsLCw8PDw8PDxMTExsbGxsbGx8fHycnJysrKzMzMzs7O0dHR09PT1NTU1tbW19fX2dnZ2dnZ2tra 29vb29vb3Nzc3Nzc3Nzc3Nzc3Nzc3NzcxMTEiYmJjIyMsrKyzs7Ozs7Ozc3Ny8vLysrKycnJx8fH xcXFxMTEwcHBv7+/vr6+vLy8vLy8urq6ubm5uLi4uLi4uLi4t7e3t7e3t7e3t7e3t7e3t7e3uLi4 uLi4uLi4ubm5urq6u7u7vLy8vb29v7+/wcHBw8PDxcXFxsbGyMjIysrKy8vLzMzMzs7Ozs7Oz8/P z8/P0NDQ0NDQ0NDQ0NDQ0NDQ0NDQy8vLgoKChoaGt7e3wsLCwsLCwcHBv7+/v7+/vr6+vr6+vb29 u7u7ubm5t7e3tbW1tbW1s7Oz8kI44l5WsbGxuaOh7kk/7kk/vJuYs6mo3WRd8kI48kI45VdOuaOh 0Xp18kI47kk/6lBH8kI4tbW1vqmn6lBI8kI45GBZ8kI42IF8wcHBwcHBwsLCxMTExMTExcXFxMTE xcXFxMTExMTExMTExMTExMTEwMDAgoKCg4ODs7OzuLi4t7e3tra2tra2ubm5urq6urq6urq6uLi4 t7e3tLS0s7Ozs7OzsrKy8FBG4GhgsLCw5GJa8FBGx4uHrq6u32hg8FBGy4WBwJeV0IB6u52b8FBG 6FxTwZiW6FxT8FBGs7Oz2XZv8FBG0IqF1YWA8FBG1oaBvb29vr6+vr6+wMDAwcHBwcHBwcHBwMDA vLy8ubm5ubm5ubm5ubm5tra2goKCgoKCq6urrq6ura2trKyssrKyubm5u7u7ubm5ubm5t7e3tra2 tLS0tLS0s7Ozs7Oz8F5V6Glh3Hhy8F5V1IJ9sLCwsLCw8F5V6Glh0IiD0IiD0IiDuaem4HNt7GRb 1YR+6Glh8F5VtLS04XRt8F5Vt7e3xqKf8F5V1YyIu7u7vLy8vb29vr6+v7+/v7+/v7+/v7+/u7u7 srKyr6+vr6+vr6+vrKysgoKCg4ODoqKipqampaWlpqamtbW1vr6+vr6+vLy8vLy8u7u7urq6ubm5 uLi4t7e3t7e38HBo7XRt4oF87XRt5X13urKxtra27XRt6Xly05OP4oF88HBoxaSit7e3xaWj05SQ 6Xly8HBoubm534eB8HBowrKwyamn8HBo15eTvr6+v7+/v7+/wMDAwcHBwcHBwcHBwcHBwMDAs7Oz qKiop6enp6enpaWlgoKCh4eHmZmZoKCgoKCgp6envb29xMTExMTEw8PDwsLCwcHBwcHBwMDAwMDA v7+/vr6+8oN95ZKNvr6+zqyp8oN91KShvb290ael8oN95JKN74eB64qFvr6+2KGe5ZKN5ZKN8oN9 6I+JwMDAzbGv8oN97IuF6Y+K8oN926SgxMTExMTExMTExcXFxsbGxsbGxsbGxsbGxsbGurq6paWl oaGhoaGhn5+fgoKCjY2Nk5OToKCgoKCgrq6uysrKz8/Pzs7Ozs7Ozc3Nzc3NzMzMzMzMy8vLy8vL y8vL9JmT7KKe1b685Kuo9JmT3LSyysrKysrK1L2837Gv3bWyzcfHysrK0MTD3bWy37Kv3bWyzsjI zMzMzMzM1r++4LOw4bOw9JmT4bSxz8/Pz8/Pz8/P0NDQ0NDQ0NDQ0NDQ0NDQ0NDQx8fHq6uroaGh oaGhn5+fgoKClZWVi4uLoKCgoKCgs7Oz1NTU2dnZ2dnZ2NjY2NjY19fX19fX19fX1tbW1tbW1tbW 9q6p9q6p9q6p9q6p7Lq319PT1dXV1dXV1dXV1dXV1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW19fX 19fX19fX19fX383M9q6p58PB2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2tra2tra2tra0dHRr6+voaGhoaGh l5eXioqKnp6egoKCnp6eoKCgsLCw2NjY4uLi4uLi4uLi4uLi4eHh4eHh4eHh4eHh4eHh4eHh4ODg 4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4eHh4eHh4eHh4eHh4eHh4eHh4eHh 4eHh4eHh4+Dg59rZ5d7e4uLi4uLi4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj0tLSq6uroaGhoaGhioqK l5eXoaGhkJCQkJCQoKCgqamp1dXV6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6urq6urq6urq 6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6+vr6+vr6+vr6+vr6+vr6+vr 6+vr6+vr6+vr6+vr6+vr6+vr7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs6+vry8vLpaWloaGhmZmZgYGBoKCg oaGhnZ2dgYGBmZmZoqKixsbG7u7u8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz9PT09PT05+fnubm5oaGhnZ2dhYWFlZWVoaGhoaGh oaGhlJSUhYWFnZ2dsbGx4eHh+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr68/Pzzs7Op6ennp6eiIiIkZGRoaGhoaGhoaGhoaGh oaGhkJCQhISEmpqavLy84ODg8vLy9/f39/f3+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn58/Pz5eXly8vLrKyslpaWhYWFkJCQoaGhoaGhoaGhoaGhoaGhoaGh oaGhlpaWgYGBjIyMoaGhsrKyurq6vb29wMDAwcHBwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA wcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHB wcHBwcHBwcHBwcHBwMDAtra2pqamlpaWioqKgICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 121) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAoaGh oaGhoKCgoKCgoKCgnJyckJCQiIiIh4eHh4eHhYWFhYWFhISEhISEhISEg4ODg4ODgoKCgoKCgoKC goKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg4ODg4ODg4ODhISEhISEhYWFhYWF hoaGhoaGhoaGh4eHh4eHh4eHh4eHiIiIiIiIjIyMlJSUnp6eoaGhoaGhoaGhoaGhoaGhoaGhoaGh oKCgoKCgkpKShoaGmpqapaWlqampp6enp6enp6enpqampaWlpaWlpKSkpKSko6Ojo6Ojo6Ojo6Oj oqKioqKioqKioqKioqKioqKioqKio6Ojo6Ojo6Ojo6Ojo6OjpKSkpaWlpaWlpqamp6enqKioqamp qampqqqqqqqqq6urq6urq6urq6urrKyspqaml5eXhYWFlJSUoaGhoaGhoaGhoaGhoaGhoKCgoKCg jo6Oj4+PsLCwuLi4t7e3t7e3tra2tbW1tLS0s7OzsrKysbGxsbGxsLCwsLCwr6+vr6+vr6+vr6+v r6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vsLCwsLCwsbGxsbGxsrKys7OztLS0tra2t7e3t7e3 uLi4ubm5ubm5urq6urq6urq6u7u7u7u7u7u7r6+vkJCQjo6OoaGhoaGhoaGhoaGhoKCgkZGRj4+P t7e3ubm5uLi4t7e3t7e3tbW1tLS0s7OzsbGxsbGxsLCwr6+vr6+vrq6ura2tra2trKysrKysrKys rKysrKysrKysrKysrKysrKysra2tra2trq6ur6+vr6+vsLCwsbGxsrKys7OztLS0tra2t7e3t7e3 uLi4ubm5urq6urq6urq6u7u7u7u7u7u7u7u7urq6lJSUj4+PoaGhoaGhoaGhmZmZhISEsLCwtra2 tbW1tLS0tLS0s7OzsrKysLCwr6+vra2trKysrKysqqqqqqqqqqqqqampqKioqKiop6enp6enp6en p6enp6enp6enp6enqKioqKioqampqqqqqqqqq6urrKysra2trq6ur6+vsbGxsrKys7OztLS0tbW1 tra2t7e3t7e3t7e3t7e3uLi4uLi4uLi4uLi4tbW1jY2Nk5OToaGhoaGhjIyMnp6esrKysbGxsLCw r6+vrq6ura2trKysq6urqampqKiopqampaWlpKSkpKSko6Ojo6OjoqKioaGhoaGhoaGhoaGhoaGh oaGhoaGhoaGhoaGhoqKio6Ojo6OjpKSkpaWlpqamp6enqKioqqqqq6urrKysra2tr6+vr6+vsLCw sbGxsrKysrKysrKys7Ozs7Ozs7Ozs7Ozs7Ozq6urg4ODn5+fnJychYWFqqqqrKysqqqqqqqqqamp qKiopqampaWlpKSkoqKioaGhn5+fnp6enZ2dnZ2dnJycm5ubm5ubmpqampqamZmZmZmZmZmZmZmZ mpqampqampqam5ubm5ubnJycnZ2dnp6en5+foKCgoaGho6OjpKSkpqamqKioqKioqqqqqqqqq6ur rKysrKysrKysra2tra2tra2tra2tra2tra2tkZGRlZWVlJSUj4+PpqampaWlpKSkpKSkoqKioqKi oKCgn5+fnZ2dnJycmpqamZmZmJiYl5eXlpaWlZWVlZWVlJSUk5OTk5OTk5OTk5OTk5OTk5OTk5OT k5OTlJSUlJSUlZWVlpaWl5eXl5eXmZmZmZmZm5ubnZ2dnp6eoKCgoaGhoqKio6OjpKSkpaWlpqam pqampqamp6enp6enp6enp6enp6enp6ennZ2diYmJjIyMk5OTn5+fnp6enZ2dnJycnJycmpqamZmZ mJiYl5eXlZWVk5OTkpKSkZGRkJCQj4+Pjo6Ojo6OjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2N jY2Njo6Ojo6Oj4+PkJCQkZGRkpKSk5OTlJSUlpaWl5eXmJiYmpqanJycnJycnZ2dnp6en5+fn5+f n5+foKCgoKCgoKCgoKCgoKCgoKCgnp6egoKChoaGk5OTmJiYl5eXl5eXlZWVlpaWlpaWlpaWlZWV lZWVk5OTkZGRkJCQkJCQjo6O6Dku0U1GjY2NmIKB4z004z00nHx6kYaFy1JL6Dku6Dku10g/mIKB umJe6Dku4z403UM66DkukJCQm4WF3kQ66Dku009I6Dkuv2himZmZmZmZmpqam5ubnJycm5ubmpqa mpqamZmZmZmZmZmZmZmZmZmZmJiYgoKCg4ODkJCQkpKSkZGRkZGRkpKSl5eXm5ubm5ubmpqamJiY l5eXlpaWlZWVlJSUlJSU6Eg+0ltTkpKS11ZO6Eg+snZykZGR0ltT6Eg+t3Jsp398vG1oooOB6Eg+ 3lJIqIF+3lJI6Eg+lZWVyWVf6Eg+u3VxwXJs6Eg+wnJtnZ2dnZ2dnZ2dnp6en5+fn5+fnp6enZ2d mJiYk5OTk5OTk5OTk5OTkpKSgoKCgoKCi4uLjIyMi4uLi4uLk5OTnp6eoaGhn5+fn5+fnp6enZ2d m5ubm5ubmpqampqa6lhP32BZ0G1m6lhPxnRvmJiYmJiY6lhP32BZwXh0wXh0wXh0o5GQ1mlh5VxU xnRw32BZ6lhPm5ub1mli6lhPnp6eso2L6lhPxXx4oaGhoqKio6Ojo6Ojo6Ojo6Ojo6OjpKSknp6e kpKSjY2NjY2NjY2NjIyMgoKCg4ODhoaGh4eHhoaGiYmJm5ubqampqampqKiop6enp6enpaWlpKSk pKSkpKSko6Oj62tj5m5n2Xlz5m5n3XVvp5+eoqKi5m5n4nJrx4eD2Xlz62tjtZSSo6OjtZWTx4eD 4nJs62tjpKSk1n1462tjr5+euJiW62tjyoqGqampqampqqqqqqqqq6urq6urq6urq6urqampmJiY iYmJiIiIiIiIiIiIgoKCh4eHg4ODhISEhISEjY2Nq6urtLS0s7Ozs7OzsrKysrKysbGxsLCwsLCw r6+vr6+v7X943ouGr6+vw6Ce7X94ypqXrq6uxp2a7X943ouG6YJ85oV/r6+vzpeU3ouG3ouG7X94 4oiDsLCwwKSj7X945oaA4omD7X940JmWtLS0tLS0tLS0tLS0tbW1tbW1tbW1tbW1tbW1pqamioqK hYWFhYWFhYWFgoKCjY2NgoKChISEhISEl5eXu7u7wcHBwcHBwMDAwMDAv7+/v7+/v7+/vr6+vr6+ vr6+8ZWQ552YyrOy3aSh8ZWQ1Kypvb29vb29yrOy16mn1KypwLu6vb29xLi41Kyq16qn1Kyqwby7 vr6+v7+/zLWz2Kqo2Kuo8ZWQ2auowcHBwcHBwcHBwsLCwsLCwsLCwsLCwsLCwsLCt7e3kpKShYWF hYWFhYWFgoKClZWVgYGBhISEhYWFnZ2dyMjIzs7Ozc3Nzc3Nzc3Nzc3NzMzMzMzMzMzMzMzMzMzM 9Kun9Kun9Kun9Kun57WyzcnJy8vLy8vLy8vLy8vLzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM zMzMzMzMzc3N18TE9Kun4by6zs7Ozs7Ozs7Ozs7Ozs7Ozs7Oz8/Pz8/Pz8/PxMTEl5eXhYWFhYWF g4ODioqKnp6egICAhISEhISEmZmZzc3N2tra2tra2tra2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ 2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ 2dnZ2dnZ29jY4dPS3dbW2tra2tra2tra2tra2tra2tra29vb29vb29vbxcXFkpKShYWFhYWFgoKC l5eXoaGhkJCQgoKChISEkJCQysrK5ubm5ubm5ubm5ubm5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl 5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl 5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5OTku7u7ioqKhYWFhISEgICAoKCg oaGhnZ2df39/g4ODhoaGtra26urq8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw 8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw 8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw39/fpKSkhYWFhISEgYGBlZWVoaGhoaGh oaGhlJSUgICAhISEmpqa2NjY+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn57+/vwMDAjY2NhYWFgYGBkZGRoaGhoaGhoaGhoaGh oaGhkJCQgICAhoaGqKio19fX7u7u9PT09fX19/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3 9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3 9/f39/f39/f39/f39/f39/f37+/v3t7evLy8lJSUg4ODgYGBkJCQoaGhoaGhoaGhoaGhoaGhoaGh oaGhlpaWf39/gYGBkJCQpKSkra2tr6+vs7OztLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0 tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0 tLS0tLS0tLS0tbW1s7Ozp6enlJSUhYWFgYGBgICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 13) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAoaGh oaGhoKCgoKCgoKCgnJyckJCQiIiIh4eHh4eHhoaGhYWFhYWFhISEhISEhISEhISEg4ODg4ODg4OD goKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg4ODg4ODg4ODhISEhISEhYWFhYWFhYWFhoaGhoaGh4eH h4eHh4eHh4eHh4eHiIiIiIiIiIiIiIiIiIiIjIyMlJSUnp6eoaGhoaGhoaGhoaGhoaGhoaGhoaGh oKCgoKCgkpKSj4+Purq61NTU29vb2dnZ2tra2dnZ2NjY2NjY19fX1tbW1dXV1dXV1dXV1NTU1NTU 1NTU09PT09PT09PT1NTU1NTU1NTU1dXV1dXV1dXV1tbW19fX2NjY2dnZ2tra29vb3Nzc3Nzc3d3d 3d3d3t7e3t7e39/f39/f39/f39/f39/f0dHRsrKyioqKlJSUoaGhoaGhoaGhoaGhoaGhoKCgoKCg jo6OoqKi6enp/Pz8+/v7+vr6+fn5+Pj49/f39fX19PT09PT08/Pz8vLy8vLy8fHx8PDw8PDw7+/v 7+/v7+/v7+/v7+/v8PDw8PDw8PDw8fHx8vLy8/Pz9PT09fX19/f3+Pj4+fn5+vr6+/v7/Pz8/f39 /v7+/v7+/v7+////////////////////////5ubmoaGhjo6OoaGhoaGhoaGhoaGhoKCgkZGRoKCg +fn5/Pz8+/v7+vr6+fn5+Pj49/f39fX19PT08/Pz8vLy8fHx8PDw7+/v7+/v7u7u7e3t7Ozs7Ozs 7Ozs7Ozs7Ozs7e3t7u7u7u7u7+/v8PDw8fHx8vLy9PT09fX19/f3+fn5+vr6+/v7/Pz8/f39/f39 /v7+/v7+/////////////////////////////Pz8qqqqj4+PoaGhoaGhoaGhmZmZi4uL5+fn9vb2 9vb29fX19PT08/Pz8fHx7+/v7u7u7Ozs6+vr6urq6enp6Ojo5+fn5ubm5eXl5OTk5OTk5OTk5OTk 5OTk5OTk5OTk5eXl5ubm5+fn6Ojo6enp6+vr7Ozs7u7u8PDw8vLy8/Pz9PT09fX19vb29/f3+Pj4 +Pj4+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn58/PznJyck5OToaGhoaGhjIyMxcXF7+/v7u7u7e3t 7Ozs6+vr6urq6Ojo5+fn5eXl5OTk4uLi4eHh4ODg3t7e3t7e3d3d3Nzc29vb2tra2tra2tra2tra 29vb29vb3Nzc3Nzc3t7e39/f4ODg4uLi5OTk5ubm6Ojo6enp6urq7Ozs7e3t7u7u7+/v8PDw8PDw 8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx4ODgh4eHn5+fnJycjo6O4eHh5eXl5OTk4+Pj4uLi 4eHh4ODg3t7e3Nzc2tra2dnZ2NjY1tbW1dXV09PT0tLS0dHR0NDQ0NDQz8/Pz8/Pz8/Pz8/Pz8/P 0NDQ0NDQ0dHR09PT1NTU1dXV2NjY2dnZ29vb3d3d3t7e4ODg4uLi4uLi5OTk5eXl5eXl5ubm5+fn 5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fnp6enlZWVlJSUpKSk2tra2dnZ2dnZ2NjY19fX1tbW 1NTU09PT0dHRz8/Pzc3NzMzMysrKycnJyMjIx8fHxsbGxsbGxMTExMTEw8PDw8PDxMTExMTExcXF xsbGxsbGx8fHyMjIysrKzMzMzs7O0NDQ0tLS09PT1dXV19fX2NjY2dnZ2dnZ2tra29vb3Nzc3Nzc 3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3NzcxMTEiYmJjIyMsrKyzs7Ozs7Ozc3NzMzMy8vLycnJyMjI xsbGxcXFw8PDwcHBwMDAvr6+vb29vLy8vLy8u7u7ubm5uLi4uLi4uLi4uLi4uLi4uLi4ubm5urq6 u7u7vLy8vb29vr6+wMDAwsLCxMTExsbGyMjIycnJysrKzMzMzc3Nzs7Ozs7Oz8/P0NDQ0NDQ0NDQ 0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQy8vLgoKChoaGt7e3wsLCwsLCwcHBwMDAv7+/v7+/vr6+vb29 vLy8u7u7uLi4t7e3tra2tbW18kI4419WsrKysbGxsbGxsLCwsLCw0Xp07kk/8kI42mxltquqvp6c 5lhP8kI48kI43G5nvbKxwauq61FJ8kI442liwcHBwsLCw8PDxMTExMTExcXFxsbGxsbGxsbGxcXF xcXFxMTExMTExMTExMTExMTEwMDAgoKCg4ODs7OzuLi4t7e3tra2tra2urq6u7u7u7u7urq6ubm5 t7e3tbW1tLS0s7Ozs7Oz8FBG4GlhsbGxsLCwsLCwr6+vwJeV8FBG2HRuzIaB8FBG0IF7vZ+d0YF8 wpqX0oJ98FBG0IqF1IWA8FBG1oaByaGevr6+vr6+v7+/wMDAwcHBwcHBwsLCwsLCwsLCwsLCwMDA vLy8ubm5ubm5ubm5ubm5tra2goKCgoKCq6urrq6ura2trKyssrKyurq6u7u7urq6ubm5uLi4t7e3 tra2tLS0tLS0s7Oz8F5V7GRb4HNt4HNtxZeUsLCw0IiD8F5VwZyasbGx8F5V4XRts7Oz1oR/7GRb 8F5V8F5VyZuY1IyH8F5Vx6Ogu7u7vLy8vb29vr6+v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/u7u7 srKyr6+vr6+vr6+vrKysgoKCg4ODoqKipqampqamp6entbW1vr6+vr6+vb29vLy8u7u7urq6urq6 ubm5uLi4t7e38HBo6Xly05SP4oF88HBozJuZz5eU8HBoyKCdurKx8HBo34aBxaWk8HBo5n130ZmV xKyrvra21paS8HBoyqmovr6+vr6+v7+/wMDAwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwMDAs7Oz qKiop6enp6enpaWlgoKCh4eHmZmZoKCgoKCgp6envb29xMTExMTEw8PDw8PDwsLCwcHBwcHBwMDA wMDAv7+/8oN95ZKNvr6+vr6+8oN95JKNwbq674eB74eB64qF8oN9y6+uwru774eB74eB5ZKN74eB 2qOf8oN98oN98oN95pSPxMTExMTExcXFxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGurq6paWl oaGhoaGhn5+fgoKCjY2Nk5OToKCgoKCgrq6uysrKz8/Pzs7Ozs7Ozs7Ozc3NzMzMzMzMzMzMzMzM y8vL9JmT7KKe1b693bWy9JmT5KuoysrKzMfG3bWy37Kv0MTEy8vLy8vLzsjI3rWz4LKw27m30sbG 5q2p9JmT37e01cTDz8/Pz8/Pz8/P0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQx8fHq6uroaGh oaGhn5+fgoKClZWVi4uLoKCgoKCgtLS01NTU2dnZ2dnZ2NjY2NjY19fX19fX19fX19fX1tbW1tbW 9q6p9q6p9q6p9q6p7Lq319PT1dXV1dXV1tbW1tbW1tbW1tbW1tbW1tbW19fX19fX19fX19fX48jG 77i13tDP2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2tra2tra2tra2tra2tra2tra0dHRr6+voaGhoaGh l5eXioqKnp6egoKCnp6eoKCgsLCw2NjY4uLi4uLi4uLi4uLi4uLi4eHh4eHh4eHh4eHh4eHh4eHh 4eHh4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4uLi4uLi 4uLi4uLi4uLi4uLi4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj0tLSq6uroaGhoaGhioqK l5eXoaGhkJCQkJCQoKCgqamp1tbW6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6urq6urq 6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr 6+vr6+vr7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs6+vry8vLpaWloaGhmZmZgYGBoKCg oaGhnZ2dgYGBmZmZoqKixsbG7u7u8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 8/Pz8/Pz8/Pz8/Pz8/Pz9PT09PT09PT09PT09PT09PT05+fnubm5oaGhnZ2dhYWFlZWVoaGhoaGh oaGhlJSUhYWFnZ2dsbGx4eHh+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr68/Pzzs7Op6ennp6eiIiIkZGRoaGhoaGhoaGhoaGh oaGhkJCQhISEmpqavLy84ODg8vLy9/f39/f3+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn58/Pz5eXly8vLrKyslpaWhYWFkJCQoaGhoaGhoaGhoaGhoaGhoaGh oaGhlpaWgYGBjIyMoaGhsrKyurq6vb29wMDAwcHBwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA wMDAwMDAwMDAwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHB wcHBwcHBwcHBwcHBwMDAtra2pqamlpaWioqKgICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 131) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAoaGh oaGhoKCgoKCgoKCgnJyckJCQiIiIh4eHh4eHhoaGhYWFhYWFhISEhISEhISEhISEg4ODg4ODg4OD goKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg4ODg4ODg4ODhISEhISEhYWFhYWFhYWFhoaGhoaGh4eH h4eHh4eHh4eHh4eHiIiIiIiIiIiIiIiIiIiIjIyMlJSUnp6eoaGhoaGhoaGhoaGhoaGhoaGhoaGh oKCgoKCgkpKShoaGmpqapqamqampqKioqKiop6enp6enp6enpqampaWlpaWlpaWlpKSko6Ojo6Oj o6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6OjpKSkpKSkpaWlpaWlpqamp6enp6enqKioqampqampqqqqq6ur q6urq6urq6urrKysrKysrKysrKysrKyspqaml5eXhYWFlJSUoaGhoaGhoaGhoaGhoaGhoKCgoKCg jo6Oj4+PsLCwubm5uLi4t7e3t7e3tra2tbW1tLS0s7Ozs7OzsrKysbGxsbGxsbGxsLCwsLCwr6+v r6+vr6+vr6+vr6+vsLCwsLCwsLCwsbGxsbGxsrKys7OztLS0tbW1tra2t7e3t7e3uLi4ubm5urq6 urq6urq6urq6u7u7u7u7u7u7u7u7u7u7u7u7r6+vkJCQjo6OoaGhoaGhoaGhoaGhoKCgkZGRj4+P uLi4ubm5uLi4t7e3t7e3tra2tbW1tLS0s7OzsrKysbGxsbGxsLCwr6+vr6+vr6+vrq6ura2tra2t ra2tra2tra2trq6ur6+vr6+vr6+vsLCwsbGxsbGxs7OztLS0tbW1t7e3t7e3uLi4ubm5urq6urq6 urq6urq6u7u7u7u7u7u7u7u7u7u7u7u7u7u7urq6lJSUj4+PoaGhoaGhoaGhmZmZhISEsLCwtra2 tra2tbW1tLS0tLS0srKysbGxsLCwr6+vrq6ura2trKysrKysq6urqqqqqqqqqampqampqKioqamp qampqampqampqqqqqqqqq6urrKysrKysrq6ur6+vsLCwsrKys7OztLS0tLS0tbW1tra2t7e3t7e3 t7e3uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4tbW1jY2Nk5OToaGhoaGhjIyMnp6esrKysbGxsLCw r6+vr6+vrq6ura2tq6urqqqqqampqKiop6enpqampaWlpaWlpKSkpKSko6OjoqKioqKioqKioqKi o6Ojo6OjpKSkpKSkpaWlpqampqamqKioqampq6urrKysra2trq6ur6+vsLCwsbGxsrKysrKysrKy s7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozq6urg4ODn5+fnJychYWFqqqqrKysq6urqqqqqqqq qKioqKiopqampaWlpKSkoqKioaGhoKCgn5+fnp6enZ2dnZ2dnJycnJycm5ubm5ubm5ubm5ubm5ub nJycnJycnZ2dnp6en5+fn5+foaGho6OjpKSkpqampqamqKioqampqqqqq6urrKysrKysrKysra2t ra2tra2tra2tra2tra2tra2tra2tra2tra2tkZGRlZWVlJSUj4+PpqampaWlpKSkpKSko6OjoqKi oaGhoKCgnp6enZ2dnJycm5ubmZmZmZmZmJiYl5eXl5eXlpaWlZWVlZWVlJSUlJSUlZWVlZWVlZWV lpaWl5eXl5eXmJiYmZmZm5ubnZ2dnp6en5+foKCgoqKio6OjpKSkpKSkpaWlpqampqamp6enp6en p6enp6enp6enp6enp6enp6enp6enp6ennZ2diYmJjIyMk5OTn5+fnp6enZ2dnZ2dnJycm5ubmpqa mJiYl5eXlpaWlJSUk5OTkpKSkpKSkZGRkJCQkJCQjo6Ojo6Ojo6OjY2NjY2Njo6Ojo6Ojo6Oj4+P kJCQkZGRkpKSkpKSk5OTlZWVl5eXmJiYmpqam5ubnJycnZ2dnZ2dnp6en5+fn5+foKCgoKCgoKCg oKCgoKCgoKCgoKCgoKCgoKCgoKCgnp6egoKChoaGk5OTmJiYl5eXl5eXlpaWlpaWlpaWl5eXlpaW lpaWlJSUk5OTkZGRkZGRkJCQ6Dku0U1Gjo6OjY2NjY2NjIyMjIyMumJd4z406DkuxVhRlIiIn358 2ElA6Dku6Dkux1pTmY6Nn4mI3kQ76Dkuz1ZPmZmZmpqam5ubm5ubnJycnJycnZ2dnZ2dnJycm5ub mpqamZmZmZmZmZmZmZmZmZmZmJiYgoKCg4ODkJCQkpKSkZGRkZGRkpKSl5eXm5ubm5ubmpqamZmZ mJiYlpaWlpaWlZWVlZWV6Eg+01xUk5OTkpKSkpKSkZGRp3986Eg+yGRduHJt6Eg+vW5ppIaEvm5p qoF/v29q6Eg+u3VxwXFr6Eg+wnJsr4eEnZ2dnZ2dnp6enp6en5+fn5+foKCgoKCgoKCgn5+fnZ2d mJiYk5OTk5OTk5OTk5OTkpKSgoKCgoKCi4uLjIyMi4uLi4uLk5OTn5+foaGhn5+fn5+fn5+fnZ2d nJycm5ubm5ubm5ub6lhP5VxU1mlh1mlhs4SCmJiYwXh06lhPrYiHmZmZ6lhP1mlimpqax3Vx5VxU 6lhP6lhPtYiExHx36lhPso2MoaGhoqKioqKio6Ojo6Ojo6Ojo6OjpKSkpKSkpKSkpKSkpKSknp6e kpKSjY2NjY2NjY2NjIyMgoKCg4ODhoaGh4eHh4eHiYmJm5ubqampqampqKiop6enp6enpqampaWl pKSkpKSkpKSk62tj4nJrx4eD2Xlz62tjvo2Kw4qG62tjupGPp5+e62tj1Xx4tZWT62tj3nVvw4uI spqZq6OiyYmG62tjuZmWqampqampqqqqqqqqq6urq6urq6urq6urq6urq6urq6urq6urqampmJiY iYmJiIiIiIiIiIiIgoKCh4eHg4ODhISEhISEjY2Nq6urtLS0tLS0s7OzsrKysrKysbGxsLCwsLCw sLCwr6+v7X943ouGr6+vr6+v7X943ouGs6yr6YJ86YJ85oV/7X94v6Ohs6ys6oJ86oJ83oyG6oJ8 z5iV7X947X947X9434yHtLS0tLS0tLS0tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1pqamioqK hYWFhYWFhYWFgoKCjY2NgoKChISEhISEl5eXu7u7wcHBwcHBwMDAwMDAwMDAv7+/v7+/vr6+vr6+ vr6+8ZWQ552Yy7Sy1Kyp8ZWQ3aShvb29wLu61Kyp16mnxLm4vr6+vr6+wby71Kyq2Kqn0q+txbq5 3qWi8ZWQ1q2ryrm4wcHBwcHBwcHBwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCt7e3kpKShYWF hYWFhYWFgoKClZWVgYGBhISEhYWFnp6eyMjIzs7Ozc3Nzc3Nzc3Nzc3Nzc3NzMzMzMzMzMzMzMzM 9Kun9Kun9Kun9Kun57WyzcnJy8vLy8vLzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzc3N3MC+ 6rSw1cfGzc3Nzs7Ozs7Ozs7Ozs7Ozs7Ozs7Oz8/Pz8/Pz8/Pz8/Pz8/Pz8/PxMTEl5eXhYWFhYWF g4ODioqKnp6egICAhISEhISEmZmZzc3N2tra2tra2tra2tra2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ 2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2tra 2tra2tra2tra2tra2tra2tra2tra29vb29vb29vb29vb29vb29vb29vbxcXFkpKShYWFhYWFgoKC l5eXoaGhkJCQgoKChISEkJCQysrK5ubm5ubm5ubm5ubm5ubm5eXl5eXl5eXl5eXl5eXl5eXl5eXl 5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5ubm5ubm5ubm 5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5OTku7u7ioqKhYWFhISEgICAoKCg oaGhnZ2df39/g4ODhoaGtra26urq8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw 8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw 8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw39/fpKSkhYWFhISEgYGBlZWVoaGhoaGh oaGhlJSUgICAhISEmpqa2NjY+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn57+/vwMDAjY2NhYWFgYGBkZGRoaGhoaGhoaGhoaGh oaGhkJCQgICAhoaGqKio19fX7u7u9PT09fX19/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3 9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3 9/f39/f39/f39/f39/f39/f37+/v3t7evLy8lJSUg4ODgYGBkJCQoaGhoaGhoaGhoaGhoaGhoaGh oaGhlpaWf39/gYGBkJCQpKSkra2tr6+vs7OztLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0 tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tbW1 tbW1tbW1tbW1tbW1s7Ozp6enlJSUhYWFgYGBgICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 14) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAn5+f np6enp6enp6enZ2dmZmZjIyMhoaGhISEhISEg4ODg4ODgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKC goKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg4ODg4OD hISEhISEhISEhYWFhYWFhoaGhoaGhoaGh4eHi4uLk5OTnZ2doKCgoaGhoaGhoaGhoaGhnp6enp6e nZ2dnZ2djo6Oi4uLtbW1zs7O1NTU09PT1dXV1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NTU 1NTU1NTU1NTU1NTU1NTU09PT09PT09PT09PT09PT09PT09PT09PT09PT1NTU1NTU1dXV1dXV1dXV 1tbW2NjY2dnZ2tra29vb3Nzc3Nzc3Nzcz8/PsbGxiYmJk5OToaGhoaGhoaGhoaGhnp6enZ2dnZ2d i4uLnZ2d4uLi8/Pz8vLy8fHx8fHx8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw 8PDw8PDw7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v8PDw8PDw8fHx8vLy8vLy8/Pz 9fX19vb2+Pj4+fn5+vr6+/v7/Pz8/f39/f395eXloKCgjo6OoaGhoaGhoaGhnZ2dnZ2djY2Nm5ub 8PDw8vLy8fHx8PDw7+/v7u7u7u7u7u7u7u7u7e3t7e3t7e3t7e3t7e3t7u7u7u7u7u7u7u7u7u7u 7e3t7e3t7e3t7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7e3t7u7u7+/v8PDw8fHx8vLy8/Pz 9fX19vb2+Pj4+fn5+vr6+/v7/Pz8/f39/v7++/v7qqqqj4+PoaGhoaGhnZ2dlZWVh4eH39/f7Ozs 6urq6enp6Ojo5ubm5ubm5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl 5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5eXl5eXl5ubm6Ojo6enp6urq7Ozs7e3t 7+/v8fHx8vLy9PT09fX19vb29/f39/f3+Pj48vLynJyck5OToaGhnZ2diIiIvb295eXl4+Pj4uLi 39/f3t7e3d3d3Nzc3Nzc3Nzc29vb29vb29vb29vb29vb29vb3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc29vb 29vb29vb29vb2tra2tra2tra2tra2tra2tra29vb29vb3Nzc3d3d3t7e4ODg4uLi4+Pj5eXl5+fn 6Ojo6urq6+vr7Ozs7e3t7u7u7+/v8PDw8PDw4ODgh4eHn5+fl5eXiYmJ2NjY2tra2dnZ1tbW1dXV 09PT0tLS0dHR0dHR0dHR0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0dHR0dHR0dHR0dHR0NDQ0NDQ0NDQ 0NDQz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/P0NDQ0dHR0tLS09PT1dXV1tbW2dnZ2tra3Nzc3t7e 4ODg4eHh4uLi4+Pj5OTk5eXl5ubm5ubm5+fnp6enlZWVj4+Pnp6e0dHRz8/Pzc3Ny8vLycnJyMjI x8fHxsbGxsbGxsbGxsbGxcXFxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxcXFxcXFxcXF xMTExMTExMTExMTExMTExMTExMTExMTExsbGxsbGx8fHyMjIysrKy8vLzc3Nz8/P0dHR09PT1NTU 1tbW2NjY2dnZ2dnZ2tra29vb29vb3NzcxMTEiYmJh4eHq6urxcXFw8PDwcHBv7+/vr6+vLy8vLy8 u7u7u7u7urq6ubm5ubm5ubm5ubm5ubm5ubm5urq6urq6u7u7u7u7u7u7urq6ubm5ubm5ubm5uLi4 uLi4uLi4uLi4uLi4uLi4uLi4ubm5urq6u7u7vLy8vb29vr6+wMDAwcHBxMTExcXFx8fHycnJysrK y8vLzc3Nzs7Ozs7Oz8/Pz8/P0NDQy8vLgoKCgYGBr6+vubm5uLi4tra2tLS0s7OztLS0tLS08kE3 8kI38kI48kI43mRetaqqsbGx8kI44l5WsrKys7Ozt6yr22xm8kI47kk/0Xp1sbGxsbGxuaOi8kI4 8kI4sbGxxY+L8kI42mxlsbGxvZ2b5ldO8kI48kI43G5nvLCwvbGx4Whg8kI48kI46FpRx7GwwMDA wsLCwsLCwsLCw8PDw8PDxMTEwMDAgoKCfn5+rKyssLCwrq6urKysq6urr6+vsrKysrKy8FBG5GNa wZiWzIaB8FBG2HRusLCw8FBG4GlhsbGxsbGx0IF88FBGzYeC2HRu8FBGwZiWsbGxyIyI8FBG7FZN wJiW2HRu7FZN6FxTsbGxvZ6d0IF8wpqX0YJ98FBGz4iE4mpi8FBG0YuHyKCd1oeBx6mmvr6+vb29 urq6uLi4uLi4uLi4ubm5tra2goKCfX19paWlpqampaWlo6OjqKiosrKys7Ozs7Oz8F5V4HNtsrKy uqem8F5V3XhysrKy8F5V4HNts7Ozs7Oz4XRt8F5Vs7Ozwp2b8F5V0YiEs7Oz3Xhy8F5V2X540YiE 7GRb0YiE8F5VvqOhs7Oz1YR+7GRb8F5V8F5VyJqY8F5V6Wlh1IyI1YyI1o2IwrCvvb29vb29urq6 sbGxrq6urq6ur6+vrKysgoKCf39/nZ2dn5+fnp6en5+frq6uuLi4t7e3t7e38HBo8HBo8HBo8HBo 5n13wamot7e38HBo5n13t7e3t7e334aB8HBou7OyyaGf8HBo0ZiUt7e38HBo4oJ8zJyZ8HBo8HBo urKy8HBo05SQxaWk8HBo5n130ZmVxKuqvrW17XVt6npz1paS5IN98HBoy6upv7+/wMDAv7+/srKy p6enpqamp6enpaWlgoKCg4ODlZWVmpqamZmZoKCguLi4wMDAv7+/vr6+8oN96I6Jy6+u4ZaR74eB wbu6vr6+8oN964qF74eB2KGezLCu8oN964qF74eB74eBwbu6z6yq8oN92KGexbe28oN94ZaRvr6+ 5ZKN6I6Jwru774eB74eB5ZKN74eBzbGw1Kqn8oN95pOO74eB7IuGxMTExMTExcXFxsbGurq6pKSk oaGhoaGhn5+fgoKCioqKj4+Pm5ubmpqaqampx8fHy8vLy8vLy8vL9JmT7KKe1b6956il9JmT1b69 y8vL1b6908HA0MTE0MTEy8vL0MXE4LKv3bWyzcjHy8vL0MTE1b69zcjHy8vL1b690MTEy8vL0MTE 1b69y8vLzsjI3rWz4LKw27m2z8nJzc3N18C/4bOx37e00cvLz8/Pz8/Pz8/P0NDQx8fHqqqqoaGh oaGhn5+fgoKCkZGRiIiInJycm5ubr6+v0tLS1tbW1tbW1tbW9q6p9q6p9q6p9q6p6r261tbW1tbW 1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW 1tbW1tbW19fX19fX19fX19fX19fX2NjY2NjY2NjY2dnZ2dnZ2dnZ2dnZ2dnZ0NDQrq6uoaGhoaGh l5eXioqKm5ubgICAm5ubnJycrKys1tbW4eHh4eHh4eHh4eHh4eHh4eHh4ODg4eHh4eHh4eHh4eHh 4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh 4eHh4eHh4eHh4eHh4eHh4eHh4uLi4uLi4uLi4uLi4uLi4uLi4+Pj4+Pj0tLSqqqqoaGhoaGhioqK l5eXnp6ejY2Njo6OnZ2dpqam1NTU6+vr6+vr6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq 6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr 6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr7Ozs7Ozs6+vrysrKpaWloaGhmZmZgYGBoKCg n5+fm5ubf39/l5eXn5+fxcXF7u7u8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz5ubmuLi4oaGhnZ2dhYWFlZWVoaGhoKCg n5+fkpKShISEnJycsLCw4ODg+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr68/Pzzs7Op6ennp6eiIiIkZGRoaGhoaGhoKCgoKCg oKCgj4+Pg4ODmZmZu7u74ODg8fHx9/f39/f3+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn58/Pz5eXlysrKrKyslpaWhYWFkJCQoaGhoaGhoaGhoKCgoKCgoKCg oKCglpaWgYGBi4uLoKCgsrKyurq6vLy8v7+/wMDAwMDAwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHB wcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHB wcHBwcHBwcHBwcHBv7+/tra2pqamlpaWioqKgICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 141) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAn5+f np6enp6enp6enZ2dmZmZjIyMhoaGhISEhISEg4ODg4ODgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKC goKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg4ODg4OD hISEhISEhISEhYWFhYWFhoaGhoaGhoaGh4eHi4uLk5OTnZ2doKCgoaGhoaGhoaGhoaGhnp6enp6e nZ2dnZ2djo6OgoKClpaWoaGhpKSko6OjpKSko6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Oj o6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6OjpKSkpKSkpaWl paWlp6enp6enqKioqampqampqampqqqqpaWllpaWhISEk5OToaGhoaGhoaGhoaGhnp6enZ2dnZ2d i4uLioqKqqqqsrKysbGxsbGxsbGxsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCw sLCwsLCwr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vsLCwsLCwsbGxsbGxsbGxsrKy tLS0tLS0tra2t7e3t7e3uLi4ubm5urq6urq6rq6uj4+Pjo6OoaGhoaGhoaGhnZ2dnZ2djY2NioqK sbGxsbGxsbGxsLCwr6+vr6+vr6+vr6+vr6+vrq6urq6urq6urq6urq6ur6+vr6+vr6+vr6+vr6+v rq6urq6urq6ura2tra2tra2tra2tra2tra2tra2tra2tra2trq6ur6+vr6+vsLCwsbGxsbGxsrKy tLS0tLS0tra2t7e3t7e3uLi4ubm5urq6urq6ubm5lJSUj4+PoaGhoaGhnZ2dlZWVgICAqampr6+v ra2trKysrKysqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq qampqampqampqampqampqKioqampqampqampqampqampqqqqqqqqqqqqrKysrKysra2tr6+vr6+v sbGxsrKys7OztLS0tbW1tra2t7e3t7e3t7e3tLS0jY2Nk5OToaGhnZ2diIiImJiYqqqqqKioqKio pqampaWlpKSkpKSkpKSkpKSko6Ojo6Ojo6Ojo6Ojo6Ojo6OjpKSkpKSkpKSkpKSkpKSkpKSko6Oj o6Ojo6Ojo6OjoqKioqKioqKioqKioqKioqKio6Ojo6OjpKSkpKSkpaWlpqamqKioqKioqqqqq6ur rKysrq6ur6+vr6+vsLCwsbGxsrKysrKysrKyq6urg4ODn5+fl5eXgYGBo6OjpKSkoqKioKCgn5+f np6enZ2dnZ2dnZ2dnZ2dnJycnJycnJycnJycnJycnJycnJycnZ2dnZ2dnZ2dnZ2dnJycnJycnJyc nJycm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubnJycnZ2dnZ2dnp6en5+foKCgoqKipKSkpaWlpqam qKioqKioqqqqqqqqq6urrKysrKysrKysra2tkZGRlZWVj4+PioqKnp6enZ2dnJycmpqamZmZmJiY l5eXl5eXlpaWlpaWlpaWlZWVlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlZWVlZWVlZWV lZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlpaWl5eXl5eXmJiYmZmZmpqanJycnZ2dnp6eoKCgoaGh oqKipKSkpKSkpaWlpqampqampqamp6ennZ2diYmJh4eHjo6OmJiYlpaWlZWVk5OTkpKSkZGRkJCQ kJCQkJCQj4+Pjo6Ojo6Ojo6Ojo6Ojo6Ojo6Oj4+Pj4+PkJCQkJCQkJCQj4+Pjo6Ojo6Ojo6Ojo6O jo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Oj4+PkJCQkJCQkpKSkpKSk5OTlZWVl5eXmJiYmZmZmpqanJyc nJycnZ2dnp6en5+fn5+fn5+foKCgnp6egoKCgYGBjY2NkZGRj4+Pjo6OjIyMjIyMjo6Ojo6O6Dgt 6Dgt6Dku6Dkuy1NMk4eHjY2N6Dku0U1Gjo6Ojo6OlIiIxllS6Dku4z40umJejY2NjY2NmIOC6Dku 6DkujY2NqnJv6DkuxVhRjY2Nn35810lA6Dku6Dkux1pTmIyLmI2MzlVO6Dku6Dku2UtCooyLl5eX mJiYl5eXmJiYmJiYmJiYmZmZmJiYgoKCfn5+i4uLjIyMioqKiYmJiYmJj4+Pk5OTlJSU6Eg+2FZO qIF+uHJt6Eg+yGRdkpKS6Eg+01tTk5OTk5OTvm5p6Eg+uXJuyGRe6Eg+qIF+k5OTs3Zy6Eg+401D qIB9yGRd401D3lJIk5OTo4WDvm5pqYF+vm9q6Eg+unRw1FxV6Eg+vHZyroaDwnJtq42LnJycm5ub lpaWkpKSkpKSkpKSk5OTkpKSgoKCfX19hoaGhoaGhYWFhISEi4uLmJiYmpqampqa6lhP1mlhmZmZ o5GQ6lhP0G1mmZmZ6lhP1mlhmpqampqa1mli6lhPmpqaromH6lhPwnl0mpqa0G1m6lhPy3FrwXh0 5VxUwXh06lhPqY2MmpqaxnRw5VxU6lhP6lhPtYiE6lhP4GFZxHx3xHx4xXx4q5iYoqKio6OjnZ2d kZGRjIyMjIyMjY2NjIyMgoKCf39/goKCgoKCgYGBgoKClpaWpKSkpKSko6Oj62tj62tj62tj62tj 3nVvsJmXo6Oj62tj3nVvo6Ojo6Oj1Xx462tjqKCgupKP62tjw4qHo6Oj62tj2Xlzvo6L62tj62tj p6Cf62tjx4eDtZWT62tj3nVvw4uIspqZqaKh525n43NsyYmG2np162tjupqYqqqqqqqqqKiol5eX iIiIh4eHiIiIiIiIgoKCg4ODf39/f39/fn5+iIiIpqamsLCwr6+vr6+v7X944YiDvqOh2o6J6YJ8 s6yrr6+v7X945oV/6oJ8zpeUv6Oh7X945oV/6oJ86oJ8s6ysw6Ce7X94zpeUt6mp7X942o6Kr6+v 3ouG4oiDs6ys6oJ86oJ83oyG6oJ8wKSjyJ6c7X943oyH6oJ85oaAtLS0tLS0tLS0tbW1pqamiYmJ hYWFhYWFhYWFgoKCioqKf39/gICAf39/k5OTubm5vr6+vr6+vr6+8ZWQ552Yy7Sy4aKe8ZWQy7Sy vr6+y7Syx7a1xLm4xLm4vr6+xbm416qn1Kyqwbu7vr6+xLm4y7Sywbu7vr6+y7SyxLm4vr6+xLm4 y7Syvr6+wby71Kyq16qn0q+twr28v7+/zLW02Kuo1q2rxL6+wcHBwcHBwcHBwsLCt7e3kZGRhYWF hYWFhYWFgoKCkZGRfn5+gYGBgYGBmpqaxsbGzMzMzMzMzMzM9Kun9Kun9Kun9Kun5Le1zMzMzMzM zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM zMzMzMzMzMzMzMzMzMzMzMzMzc3Nzc3Nzc3Nzc3Nzc3Nzs7Ozs7Ozs7Ozs7Ow8PDlpaWhYWFhYWF g4ODioqKm5ubfn5+gYGBgYGBlpaWzMzM2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ 2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ 2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2tra2tra2tra2tra2tra2tra2traxMTEkZGRhYWFhYWFgoKC l5eXnp6ejY2NgICAgYGBjY2NyMjI5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl 5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl 5eXl5eXl5eXl5eXl5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5OTku7u7ioqKhYWFhISEgICAoKCg n5+fm5ubfX19gYGBhISEtLS06enp8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw 8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw 8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw39/fo6OjhYWFhISEgYGBlZWVoaGhoKCg n5+fkpKSf39/g4ODmZmZ2NjY+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn57+/vv7+/jY2NhYWFgYGBkZGRoaGhoaGhoKCgoKCg oKCgj4+Pf39/hYWFp6en19fX7e3t9PT09fX19/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3 9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3 9/f39/f39/f39/f39/f39/f37+/v3d3du7u7lJSUg4ODgYGBkJCQoaGhoaGhoaGhoKCgoKCgoKCg oKCglpaWf39/gICAj4+Po6Ojra2tr6+vs7OztLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0 tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0 tLS0tLS0tLS0tLS0srKyp6enlJSUhYWFgYGBgICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 15) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAn5+f n5+fnp6enp6enZ2dmZmZjY2NhoaGhYWFhISEg4ODg4ODg4ODg4ODg4ODgoKCgoKCgoKCgoKCgoKC goKCgoKCgoKCgoKCgoKCgoKCgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgoKCgoKCgoKCg4ODg4OD hISEhISEhYWFhYWFhoaGhoaGhoaGh4eHh4eHi4uLk5OTnp6eoaGhoaGhoaGhoaGhoaGhn5+fnp6e np6enZ2dj4+Pi4uLtbW1z8/P1NTU09PT1dXV1dXV1dXV1NTU1NTU1NTU1NTU1NTU1NTU1NTU09PT 09PT09PT09PT0tLS0tLS0tLS0dHR0dHR0dHR0dHR0dHR0tLS0tLS09PT09PT1NTU1dXV1dXV1tbW 2NjY2dnZ2tra29vb3Nzc3Nzc3d3d3d3d0NDQsbGxioqKlJSUoaGhoaGhoaGhoaGhnp6enp6enZ2d i4uLnp6e4+Pj9PT08/Pz8vLy8vLy8fHx8fHx8fHx8PDw8PDw8PDw8PDw8PDw8PDw7+/v7+/v7+/v 7+/v7u7u7u7u7u7u7e3t7e3t7Ozs7Ozs7Ozs7Ozs7e3t7u7u7u7u7+/v8PDw8fHx8vLy8/Pz9fX1 9/f3+Pj4+fn5+vr6+/v7/Pz8/f39/f39/v7+5eXloaGhjo6OoaGhoaGhoaGhnp6enZ2djo6OnJyc 8fHx8/Pz8vLy8fHx8PDw8PDw7+/v7+/v7u7u7u7u7u7u7u7u7u7u7u7u7e3t7e3t7Ozs7Ozs7Ozs 7Ozs6+vr6+vr6+vr6urq6urq6urq6enp6urq6urq6+vr6+vr7Ozs7u7u7+/v8PDw8vLy8/Pz9fX1 9/f3+Pj4+vr6+/v7/Pz8/f39/f39/v7+/v7+/Pz8qqqqj4+PoaGhoaGhnZ2dlpaWiIiI4ODg7e3t 7Ozs6+vr6enp6Ojo6Ojo5ubm5ubm5ubm5eXl5eXl5eXl5eXl5eXl5eXl5OTk5OTk5OTk5OTk5OTk 5OTk5OTk4+Pj4+Pj4uLi4uLi4uLi4uLi4+Pj4+Pj5OTk5OTk5eXl5+fn6Ojo6urq7Ozs7u7u7+/v 8vLy8/Pz9PT09fX19vb29/f3+Pj4+Pj4+fn58/PznJyck5OToaGhnZ2diYmJvr6+5+fn5eXl4+Pj 4uLi4eHh39/f3t7e3d3d3d3d3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc29vb29vb29vb29vb29vb2tra2tra 2dnZ2dnZ2NjY2NjY2NjY2NjY2NjY2NjY2dnZ2tra29vb3Nzc3t7e39/f4eHh4+Pj5eXl5+fn6enp 6urq7Ozs7e3t7u7u7+/v8PDw8PDw8fHx8fHx4ODgh4eHn5+fmJiYioqK2dnZ3Nzc2tra2dnZ19fX 1dXV1NTU09PT0tLS0tLS0dHR0dHR0dHR0dHR0NDQ0NDQ0NDQ0NDQ0NDQ0NDQz8/Pz8/Pz8/Pz8/P zs7Ozs7Ozc3Nzc3Nzc3Nzc3Nzs7Oz8/Pz8/P0NDQ0tLS09PT1dXV1tbW2dnZ2tra3Nzc3t7e4eHh 4uLi4uLi5OTk5OTk5eXl5ubm5+fn5+fn5+fnp6enlZWVkJCQn5+f09PT0dHRz8/Pzc3Ny8vLysrK ycnJx8fHx8fHxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxcXFxcXFxcXFxMTExMTEw8PDw8PD wsLCwsLCwsLCwsLCwsLCw8PDw8PD90A162JZxsbGyMjIysrKzMzMzc3N0NDQ0tLS09PT1dXV19fX 2NjY2dnZ2dnZ2tra29vb3Nzc3Nzc3NzcxMTEiYmJiIiIrKysxsbGxcXFw8PDwcHBwMDAvr6+vb29 vLy8vLy8vLy8u7u7u7u7urq6urq6urq6urq6urq6urq6ubm5ubm5ubm5ubm5uLi4uLi4uLi4uLi4 uLi4uLi4t7e3uLi4uLi4uLi49D0y5l1UvLy8vb29vr6+wMDAwsLCxMTExsbGyMjIycnJy8vLzMzM zc3Nzs7Ozs7Oz8/P0NDQ0NDQ0NDQy8vLgoKCgoKCsbGxu7u7ubm5uLi4tra2tra2tbW1tbW1ua2t 221m7kk/8kI46lBH2mxlsrKy0nt18kI4wpeUsrKysrKyxo+M6lBH8kI44l5WvZyasbGxxI6K7kk/ 6U9H4l5W8kI4wZaTsbGx8kI47kk/7kk/7ko/zYuHuLi4419Y8kI48kI45WFZyqmnwcHBwsLCwsLC w8PDwsLCw8PDxMTExMTExMTEwMDAgoKCf39/ra2tsLCwr6+vra2tra2tsLCws7Ozs7Oz4Glh8FBG 2HVuwpmW5GNa8FBGsbGx0IF78FBGwZiWsbGxtauq7FZN5GNaxZKP7FZN4GhgsLCw4Ghg8FBGw5GO 3G5n8FBGwJiWsLCw8FBG5WNawpqX6FxU7VZNua+u23dxx56cypiW8FBG33Jrvr6+vr6+v7+/vr6+ u7u7uLi4ubm5ubm5ubm5tra2goKCfn5+pqamp6enpqampaWlqqqqs7OztLS0u6mn8F5V4XRts7Oz wp2b5W5n8F5Vs7Oz0YiE8F5Vwp2bs7Ozwp2b8F5V0YiEs7Oz4HNt8F5VsrKy4HNt8F5VsbGx0IiE 8F5Vwp2bsrKy8F5V4XRts7Oz0omF8F5VxJ+ezZaT6Wli8F5V8F5V2YeCvLy8vb29vr6+v7+/u7u7 sbGxr6+vr6+vr6+vrKysgoKCf39/np6eoKCgn5+foKCgr6+vurq6ubm5xqak8HBo05SQt7e38HBo 8HBo8HBot7e305SQ8HBoyaGft7e3wqqp8HBo14+Lt7e35n137XRtt7e34oF88HBot7e305OP8HBo xaWjt7e38HBo4oJ8uLi42JCM8HBoyKem8HBo7XVt1paSyqqowbq5v7+/v7+/wMDAwcHBwMDAsrKy qKiop6enp6enpaWlgoKChISElZWVm5ubmpqaoaGhubm5wMDAwMDAybSz8oN93pqVvr6+vr6+vr6+ vr6+vr6+2KGe8oN96I6J8oN9v7+/5ZKN8oN96I6J8oN92KGevr6+5ZKN8oN9vr6+2KGe8oN9y6+u vr6+8oN974eB5ZKN8oN97IuFwcHB5pOO8oN95pSO7IuG26SgxMTExcXFxcXFxsbGxsbGurq6paWl oaGhoaGhn5+fgoKCioqKkJCQnJycm5ubqqqqx8fHzMzMzMzMy8vL7KKe9JmT1b69y8vL0MTE6qWh y8vL0MTE1b69zcjH1b69y8vLy8vL2ri237Kv1b69y8vLy8vL08HA1b69y8vL0MTE1b69zcjHy8vL 1b6908LB1r++4LKw0cbFzMzMzc3N3Lm34bSx37e008jHz8/Pz8/P0NDQ0NDQ0NDQx8fHq6uroaGh oaGhn5+fgoKCkpKSiYmJnZ2dnJycsLCw0tLS19fX19fX1tbW3M/O8LWy9q6p9q6p9q6p8rOv1tbW 1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW 1tbW19fX19fX19fX19fX19fX2NjY2NjY2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ0NDQr6+voaGhoaGh l5eXioqKnJycgICAm5ubnZ2dra2t19fX4eHh4eHh4eHh4eHh4eHh5dva59nY5dva4eHh4eHh4eHh 4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh 4eHh4eHh4eHh4eHh4uLi4uLi4uLi4uLi4uLi4uLi4+Pj4+Pj4+Pj4+Pj0tLSq6uroaGhoaGhioqK l5eXn5+fjo6Ojo6OnZ2dpqam1NTU6+vr6+vr6+vr6+vr6urq6urq6urq6urq6urq6urq6+vr6+vr 6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr 6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr7Ozs7Ozs7Ozs7Ozs6+vry8vLpaWloaGhmZmZgYGBoKCg n5+fm5ubgICAl5eXoKCgxcXF7u7u8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz5+fnubm5oaGhnZ2dhYWFlZWVoaGhoKCg n5+fkpKShISEnJycsLCw4ODg+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr68/Pzzs7Op6ennp6eiIiIkZGRoaGhoaGhoKCgoKCg oKCgkJCQg4ODmZmZu7u74ODg8fHx9/f39/f3+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn58/Pz5eXly8vLrKyslpaWhYWFkJCQoaGhoaGhoaGhoKCgoKCgoKCg oKCglpaWgYGBjIyMoaGhsrKyurq6vLy8v7+/wcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHB wcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHB wcHBwcHBwcHBwcHBwMDAtra2pqamlpaWioqKgICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 151) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAn5+f n5+fnp6enp6enZ2dmZmZjY2NhoaGhYWFhISEg4ODg4ODg4ODg4ODg4ODgoKCgoKCgoKCgoKCgoKC goKCgoKCgoKCgoKCgoKCgoKCgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgoKCgoKCgoKCg4ODg4OD hISEhISEhYWFhYWFhoaGhoaGhoaGh4eHh4eHi4uLk5OTnp6eoaGhoaGhoaGhoaGhoaGhn5+fnp6e np6enZ2dj4+Pg4ODlpaWoaGhpaWlpKSkpKSkpKSkpKSko6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Oj o6Ojo6Ojo6OjoqKioqKioqKioaGhoaGhoaGhoaGhoaGhoqKioqKio6Ojo6Ojo6OjpKSkpaWlpaWl p6enp6enqKioqampqampqqqqq6urq6urpaWllpaWhYWFlJSUoaGhoaGhoaGhoaGhnp6enp6enZ2d i4uLi4uLq6urs7OzsrKysbGxsbGxsbGxsbGxsbGxsLCwsLCwsLCwsLCwsLCwsLCwr6+vr6+vr6+v r6+vr6+vr6+vr6+vrq6urq6ura2tra2tra2tra2trq6ur6+vr6+vr6+vsLCwsbGxsbGxsrKytLS0 tbW1tra2t7e3t7e3uLi4ubm5urq6urq6urq6rq6ukJCQjo6OoaGhoaGhoaGhnp6enZ2djo6Oi4uL srKysrKysbGxsbGxsLCwsLCwr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vrq6urq6ura2tra2tra2t ra2trKysrKysrKysrKysrKysrKysq6urrKysrKysrKysrKysra2tr6+vr6+vsLCwsbGxsrKytLS0 tbW1tra2t7e3uLi4ubm5urq6urq6urq6urq6urq6lJSUj4+PoaGhoaGhnZ2dlpaWgYGBqqqqr6+v r6+vrq6urKysrKysrKysqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqampqampqampqampqKio qKioqKiop6enp6enp6enp6enp6enp6enp6enp6enqKioqampqqqqq6urrKysra2tr6+vsLCwsbGx s7OztLS0tLS0tbW1tra2t7e3t7e3t7e3uLi4tbW1jY2Nk5OToaGhnZ2diYmJmZmZq6urqqqqqKio qKiop6enpqampaWlpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSko6Ojo6Ojo6Ojo6Ojo6OjoqKioqKi oaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoqKio6OjpKSkpaWlpqamp6enqKioqqqqq6urra2t rq6ur6+vsLCwsbGxsrKysrKysrKys7Ozs7Ozq6urg4ODn5+fmJiYgYGBpKSkpaWlpKSkoqKioaGh n5+fn5+fnp6enZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnJycnJycnJycnJycnJycnJycm5ubm5ubm5ubm5ub mpqampqamZmZmZmZmZmZmZmZmpqam5ubm5ubnJycnZ2dnp6en5+foKCgoqKipKSkpaWlpqamqKio qampqqqqq6urq6urrKysrKysra2tra2tra2tkZGRlZWVkJCQioqKoKCgnp6enZ2dnJycmpqamZmZ mZmZl5eXl5eXl5eXl5eXlpaWlpaWlpaWlpaWlpaWlpaWlpaWlZWVlZWVlZWVlZWVlZWVlJSUlJSU k5OTk5OTk5OTk5OTk5OTlJSUlJSU6jMo1UxEl5eXmJiYmZmZm5ubnJycnp6en5+foKCgoqKio6Oj pKSkpKSkpaWlpqampqamp6enp6enp6ennZ2diYmJiIiIjo6OmJiYl5eXlpaWlZWVk5OTkpKSkpKS kZGRkJCQkJCQkJCQkJCQj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pjo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6OjY2N jY2NjY2NjY2NjY2NjY2Njo6O6DIm0kpBkJCQkpKSkpKSk5OTlZWVl5eXmJiYmpqam5ubnJycnZ2d nZ2dnp6en5+fn5+foKCgoKCgoKCgnp6egoKCgoKCjo6OkpKSkZGRj4+Pjo6Ojo6Oj4+Pj4+PlYmJ xllS4z406Dku3UM6xllSjo6Ou2Ne6DkupXl2jo6Ojo6OqnNw3UM66Dku0U1Gnn17jY2NqXJu4z00 3UM60U1G6DkupHh1jY2N6Dku4z404z404z40sW9rk5OT009I6Dku6Dku1FBJqIaFmZmZmZmZmZmZ mJiYmJiYmJiYmZmZmZmZmZmZmJiYgoKCf39/i4uLjIyMi4uLioqKi4uLkJCQlZWVlZWV01xU6Eg+ yWReqYF+2FZO6Eg+k5OTvW5p6Eg+qIF+k5OTmI+O401D2FZOrXt5401D0ltTkpKS0ltT6Eg+rHp3 zV9Y6Eg+qIB9kpKS6Eg+2FZOqYF+3lJI405DnJGRymZgrYWCs4F96Eg+0GNcnZ2dnZ2dnZ2dm5ub l5eXkpKSk5OTk5OTk5OTkpKSgoKCfn5+h4eHh4eHhoaGhYWFjY2NmJiYm5ubpJKR6lhP1mlimpqa romH2mVd6lhPmpqawnl06lhPromHmpqaromH6lhPwnl0mpqa1mlh6lhPmZmZ1mlh6lhPmZmZwXh0 6lhPrYiHmZmZ6lhP1mlim5ubwnl16lhPsIyJu4SA4GFZ6lhP6lhPynhzoqKio6Ojo6Ojo6OjnZ2d kZGRjY2NjY2NjY2NjIyMgoKCf39/g4ODgoKCgoKChISEl5eXpaWlpKSktpaU62tjx4eDo6Oj62tj 62tj62tjo6Ojx4eD62tjupGPo6OjsJmX62tjzIN/o6Oj3nVv525no6Oj2Xlz62tjo6Ojx4eD62tj tZWTo6Oj62tj2XlzpKSkzISA62tjt5eV62tj525nyoqGupmXrqWlqampqqqqqqqqq6urqampl5eX iYmJiIiIiIiIiIiIgoKChISEgICAgICAf39/iIiIp6ensLCwsLCwu6em7X941pGNr6+vr6+vr6+v r6+vr6+vzpeU7X944oiD7X94r6+v3ouG7X944oiD7X94zpeUr6+v3ouG7X94r6+vzpeU7X94v6Oh r6+v7X946oJ83ouG7X945oWAsbGx3oyH7X9434yH5oaA0JqWtLS0tLS0tLS0tbW1tbW1pqamioqK hYWFhYWFhYWFgoKCioqKf39/gYGBgICAlJSUubm5v7+/vr6+vr6+552Y8ZWQy7Syvr6+xLm45J+b vr6+xLm4y7Sywbu7y7Syvr6+vr6+0a+s16qny7Syvr6+vr6+x7a1y7Syvr6+xLm4y7Sywbu7vr6+ y7SyyLe1y7Sz2Kqnxbq5v7+/v7+/0rCu2Kuo1q6rx7u7wcHBwcHBwsLCwsLCwsLCt7e3kpKShYWF hYWFhYWFgoKCkpKSf39/gYGBgoKCm5ubxsbGzMzMzMzMzMzM08bF7LGu9Kun9Kun9Kun7q+rzMzM zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM zMzMzMzMzMzMzMzMzc3Nzc3Nzc3Nzc3Nzc3Nzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ow8PDl5eXhYWFhYWF g4ODioqKnJycfn5+goKCgYGBlpaWzMzM2dnZ2dnZ2dnZ2dnZ2dnZ3tTT4NLR3tTT2dnZ2dnZ2dnZ 2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ 2dnZ2dnZ2dnZ2dnZ2dnZ2tra2tra2tra2tra2tra2tra2tra2tra2traxcXFkpKShYWFhYWFgoKC l5eXn5+fjo6OgICAgoKCjY2NyMjI5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl 5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl 5eXl5eXl5eXl5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5OTku7u7ioqKhYWFhISEgICAoKCg n5+fm5ubfn5+gYGBhISEtbW16enp8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw 8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw 8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw39/fpKSkhYWFhISEgYGBlZWVoaGhoKCg n5+fkpKSf39/g4ODmpqa2NjY+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn57+/vwMDAjY2NhYWFgYGBkZGRoaGhoaGhoKCgoKCg oKCgkJCQf39/hYWFp6en19fX7e3t9PT09fX19/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3 9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3 9/f39/f39/f39/f39/f39/f37+/v3t7evLy8lJSUg4ODgYGBkJCQoaGhoaGhoaGhoKCgoKCgoKCg oKCglpaWf39/gYGBkJCQo6Ojra2tr6+vs7OztLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0 tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0 tLS0tLS0tLS0tLS0s7Ozp6enlJSUhYWFgYGBgICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 16) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAn5+f n5+fnp6enp6enZ2dmZmZjIyMhYWFhISEg4ODgoKCgoKCgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGB gYGBgYGBgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg4ODg4OD g4ODhISEhISEhISEhYWFhYWFhYWFhoaGhoaGioqKk5OTnZ2doKCgoKCgoaGhoaGhoaGhn5+fnp6e np6enZ2dj4+Pi4uLtbW1zs7O1NTU0tLS09PT09PT0tLS0dHR0dHR0dHR0dHR0dHR0dHR0dHR0tLS 0tLS0tLS0tLS0tLS09PT09PT09PT09PT09PT09PT09PT09PT09PT1NTU1NTU1NTU1dXV1dXV1dXV 1dXV1tbW19fX2NjY2dnZ2tra29vb3Nzcz8/PsLCwiYmJk5OToKCgoKCgoaGhoaGhnp6enp6enZ2d i4uLnZ2d4uLi8/Pz8vLy8fHx8PDw7+/v7u7u7e3t7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7e3t 7e3t7u7u7u7u7u7u7u7u7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v8PDw8PDw8PDw8fHx8vLy8vLy 8/Pz9PT09fX19/f3+Pj4+fn5+vr6+/v7/Pz85OTkoKCgjY2NoKCgoaGhoaGhnp6enZ2djo6Om5ub 8PDw8/Pz8fHx8PDw7u7u7e3t7Ozs6+vr6urq6enp6enp6enp6enp6enp6enp6enp6urq6urq6urq 6+vr6+vr6+vr6+vr7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7e3t7u7u7u7u7+/v8PDw8fHx8vLy 8/Pz9PT09fX19/f3+Pj4+vr6+/v7/Pz8/Pz8+vr6qampjo6OoaGhoaGhnp6elpaWiIiI4ODg7e3t 6+vr6enp6Ojo5ubm5OTk5OTk4+Pj4uLi4uLi4eHh4eHh4eHh4eHh4uLi4uLi4uLi4uLi4+Pj4+Pj 4+Pj5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5eXl5eXl5ubm5+fn6Ojo6enp6urq6+vr 7e3t7u7u8PDw8vLy8/Pz9PT09fX19vb29/f38vLym5ubk5OToaGhnZ2diYmJvr6+5ubm5OTk4uLi 4ODg3t7e3d3d29vb2tra2dnZ2NjY19fX19fX19fX19fX19fX19fX19fX19fX2NjY2NjY2NjY2dnZ 2dnZ2dnZ2tra2tra2tra2tra2tra29vb29vb29vb29vb3Nzc3d3d3t7e39/f4ODg4eHh4+Pj5OTk 5ubm6Ojo6enp6urq6+vr7e3t7u7u7+/v7+/v39/fh4eHn5+fmJiYi4uL2dnZ29vb2dnZ2NjY1dXV 1NTU0tLS0NDQz8/Pzs7Ozc3NzMzMzMzMzMzMy8vLzMzMzMzMzMzMzMzMzc3Nzc3Nzc3Nzs7Ozs7O zs7Oz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/P0NDQ0NDQ0dHR0tLS09PT1NTU1dXV1tbW2NjY2dnZ29vb 3d3d3t7e4eHh4uLi4uLi4+Pj5OTk5eXl5ubmpqamlZWVkJCQn5+f09PT0dHRzs7OzMzMysrKyMjI x8fHxsbGxMTEw8PDwsLCwcHBwMDAwMDAzqCd90A124B7wMDAwcHBwcHBwsLCwsLCwsLCwsLCw8PD w8PDw8PDxMTExMTExMTExMTExMTExcXFxsbGxsbGxsbGx8fHyMjIysrKy8vLzMzMzs7O0NDQ0tLS 09PT1dXV19fX2NjY2dnZ2dnZ2tra29vbw8PDiYmJiIiIrKysxsbGxcXFw8PDwcHBv7+/vb29vLy8 urq6uLi4uLi4t7e3tra2tra2tbW1xZeU9D0y1Xp0tra2tra2tra2t7e3t7e3t7e3uLi4uLi4uLi4 uLi4uLi4uLi4uLi4ubm5ubm5ubm5urq6u7u7vLy8vLy8vb29vr6+wMDAwcHBw8PDxcXFxsbGyMjI ycnJysrKzMzMzc3Nzs7Ozs7Oz8/PysrKgoKCgoKCsbGxu7u7ubm5uLi4tbW1tbW1tLS0tLS0tquq 2mxl8kI48kI44V1Vu5qYrq6uv5SR8kI46U9H8kI46U9Hu5qYr6+vxI2K7kk/8kI4zYB80Xp08kI4 wZaTtaqq2mxl8kI47kk/0Xp1srKys7Oz8kI4419XtbW1419X8kI4uLi42ndx7kpA8kI461BIz5eU wMDAwMDAwcHBwsLCwsLCw8PDv7+/goKCf39/ra2tsLCwr6+vra2trKyssLCwsrKysrKy4Glh8FBG zIaBw5CO7FZM7FZMsqenvpaT8FBG13NswpCN8FBG32hgrq6u32hg8FBGw5COu52b0IB68FBGwJiW 0IF78FBGzIaB2HRu8FBGwZiWsrKy8FBG4Glhs7Oz4Wpi8FBGt7e304R/ypiVyJ+d6V1V7VZMvLy8 uLi4tra2t7e3uLi4uLi4tbW1goKCfn5+pqamp6enpqampaWlqqqqsrKys7Ozu6in8F5V2H14sLCw sLCwx5GN8F5Vx5CNv5uY8F5Vz4eCr6+v33Js8F5Vr6+v4HNt8F5VsLCwsLCw0IiD8F5VwZya4HNt 8F5VsrKywp2b8F5V0YiEs7Oz8F5V4XRttLS04XRt8F5Vt7e3wqel5m9o8F5V8F5V5nBpvLy8ubm5 sLCwra2trq6urq6urKysgoKCf39/np6eoKCgn5+foKCgr6+vubm5uLi4xaWk8HBo05OPtra2tbW1 w6Oi8HBo0pKPw6Oi8HBo0pKPtbW15Xx38HBotbW14oF88HBotra2tra205OP8HBoxaSi3oaB8HBo urKyyaCe8HBo0ZiUt7e38HBo4oJ8ubm54oJ88HBourq644N98HBo2ZGNzqWjxbW0v7+/vr6+sbGx p6enpqampqampaWlgoKChISElpaWm5ubmpqaoaGhubm5wMDAwMDAyLSy8oN9252Zvr6+vb29zaup 8oN91KShyq6s8oN964qE6I6J8oN93pmV16Cd8oN98oN98oN92KGd2KGd8oN9y6+uy6+u8oN964qF 74eB74eBwbu6v7+/8oN974eB5ZKN8oN97IuFwcHB2qOf8oN96Y+K6Y+K5pSPxMTExMTEubm5pKSk oKCgoKCgn5+fgoKCioqKkJCQnJycm5ubqampx8fHzMzMy8vLy8vL75+a8pyX0sG/zMfG7KKe9JmT z8PCzMbG1L28z8TD2re13LSyzMfGz8TD7KKe9JmT1L28z8TD0MTD1b68zcfHysrK0MTE37Kv3bWy zcjHy8vLy8vL1r+908LB1r++4LKw0cbFzMzMzc3N18C/4bSx4bSx1sXEz8/Pz8/Px8fHqqqqoKCg oKCgn5+fgoKCkpKSiYmJnZ2dnJycsLCw0tLS19fX1tbW1tbW3M7N8rOv9q6p9q6p9LCs4sbF1dXV 1dXV1dXV1dXV1dXV1dXV1dXV1dXV6L+97ri11dXV1dXV5sLA9q6p3szL1tbW1tbW1tbW1tbW1tbW 1tbW1tbW1tbW19fX19fX19fX19fX19fX19fX2NjY2NjY2dnZ2dnZ2dnZ2dnZ0NDQrq6uoKCgoKCg l5eXioqKnJycgICAm5ubnZ2dra2t19fX4eHh4eHh4eHh4eHh4ODg5tnY5tnY4t/e4ODg4ODg4ODg 4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg49zc5tnY4t/e4eHh4eHh4eHh4eHh4eHh4eHh 4eHh4eHh4eHh4eHh4eHh4eHh4eHh4uLi4uLi4uLi4uLi4uLi4uLi4+Pj0tLSqqqqoKCgoKCgioqK l5eXn5+fjo6Ojo6OnZ2dpqam1NTU6+vr6+vr6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq 6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6+vr6+vr6+vr 6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr7Ozs6+vrysrKpKSkoKCgmZmZgYGBoKCg n5+fm5ubgICAl5eXoKCgxcXF7u7u8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz5ubmuLi4oKCgnJychYWFlZWVoaGhoKCg n5+fkpKShISEnJycsLCw4ODg+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr68/Pzzs7OpqamnZ2diIiIkZGRoaGhoaGhoKCgoKCg oKCgj4+Pg4ODmZmZu7u74ODg8fHx9/f39/f3+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn58/Pz5eXlysrKrKyslpaWhYWFkJCQoaGhoaGhoaGhoKCgoKCgoKCg oKCglpaWgYGBjIyMoKCgsrKyurq6vLy8v7+/wMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA wMDAwMDAwMDAwMDAwMDAwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHB wcHBwcHBwcHBwcHBv7+/tbW1paWllpaWioqKgICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 161) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAn5+f n5+fnp6enp6enZ2dmZmZjIyMhYWFhISEg4ODgoKCgoKCgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGB gYGBgYGBgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg4ODg4OD g4ODhISEhISEhISEhYWFhYWFhYWFhoaGhoaGioqKk5OTnZ2doKCgoKCgoaGhoaGhoaGhn5+fnp6e np6enZ2dj4+PgoKClpaWoaGhpKSkoqKio6Ojo6OjoqKioaGhoaGhoaGhoaGhoaGhoaGhoaGhoqKi oqKioqKioqKioqKio6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6OjpKSkpKSkpaWl paWlpaWlpqamp6enp6enqKioqampqamppKSklZWVhISEk5OToKCgoKCgoaGhoaGhnp6enp6enZ2d i4uLi4uLqqqqsrKysbGxsbGxsLCwr6+vr6+vrq6ura2tra2tra2tra2tra2tra2tra2tra2trq6u rq6ur6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vsLCwsLCwsLCwsbGxsbGxsbGx srKys7OztLS0tbW1tra2t7e3t7e3uLi4ubm5rq6uj4+PjY2NoKCgoaGhoaGhnp6enZ2djo6Oi4uL sbGxsrKysbGxsLCwr6+vrq6ura2trKysrKysq6urq6urq6urq6urq6urq6urq6urrKysrKysrKys rKysrKysrKysrKysra2tra2tra2tra2tra2tra2tra2tra2trq6ur6+vr6+vr6+vsLCwsbGxsbGx srKys7OztLS0tbW1tra2t7e3uLi4ubm5ubm5ubm5k5OTjo6OoaGhoaGhnp6elpaWgYGBqqqqr6+v rq6urKysrKysqqqqqampqKiop6enp6enp6enpqampqampqampqamp6enp6enp6enp6enp6enp6en p6enqKioqKioqKioqKioqKioqampqampqampqampqampqqqqqqqqqqqqq6urrKysrKysra2trq6u r6+vsLCwsrKys7OztLS0tLS0tbW1tra2t7e3tLS0jIyMk5OToaGhnZ2diYmJmZmZq6urqampqKio pqampaWlpKSko6OjoqKioaGhoaGhoKCgn5+fn5+fn5+fn5+fn5+fn5+foKCgoaGhoaGhoaGhoaGh oaGhoaGhoqKioqKioqKioqKioqKio6Ojo6Ojo6Ojo6OjpKSkpKSkpaWlpqampqamp6enqKioqamp q6urrKysra2trq6ur6+vsLCwsbGxsrKysrKyqqqqg4ODn5+fmJiYgoKCpKSkpKSko6OjoaGhn5+f n5+fnZ2dnJycm5ubmpqamZmZmZmZmZmZmZmZmJiYmZmZmZmZmZmZmZmZmZmZmZmZmZmZmpqampqa mpqam5ubm5ubm5ubm5ubm5ubm5ubm5ubnJycnJycnZ2dnZ2dnp6en5+fn5+foKCgoaGho6OjpKSk pqampqamqKioqampqqqqqqqqq6urrKysrKyskJCQlZWVkJCQi4uLoKCgnp6enZ2dm5ubmZmZmJiY l5eXlpaWlZWVlJSUk5OTk5OTkpKSkpKSqHp36jMovmNdkpKSk5OTk5OTk5OTk5OTk5OTk5OTlJSU lJSUlJSUlZWVlZWVlZWVlZWVlZWVlZWVlpaWlpaWl5eXl5eXmJiYmZmZmpqam5ubnZ2dnp6en5+f oKCgoqKio6OjpKSkpKSkpaWlpqampqamnJyciYmJiIiIjo6OmJiYl5eXlpaWlJSUk5OTkpKSkJCQ j4+Pjo6OjY2NjY2NjIyMjIyMi4uLonVy6DImul9ZjIyMjIyMjIyMjY2NjY2NjY2NjY2NjY2NjY2N jo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Oj4+PkJCQkJCQkZGRkpKSkpKSk5OTlJSUlpaWl5eXmJiYmpqa m5ubnJycnZ2dnZ2dnp6en5+fn5+fnZ2dgoKCgoKCjo6OkpKSkZGRj4+Pjo6OjY2Njo6Ojo6Ok4eH xVhR6Dku6Dku0U1FnHx6ioqKonZz6Dku3UM66Dku3UM6nHx6i4uLqHFu4z006DkutGdiumJd6Dku pHh1k4eHxVhR6Dku4z40umJejo6Ojo6O6Dku0k5HkJCQ0k5H6Dkuk5OTwmBb4z416Dku3UM6sHh0 lpaWlpaWl5eXl5eXmJiYmJiYl5eXgoKCf39/i4uLjIyMi4uLioqKioqKkJCQlJSUlJSU01tT6Eg+ t3JsrHp3401D401DloyLpn576Eg+x2RcrHl36Eg+0ltTkZGR0ltT6Eg+rHp3ooOBvG1o6Eg+qIB9 vW1o6Eg+uHJtyGRd6Eg+qIF+lJSU6Eg+01xUlZWV01xU6Eg+l5eXwHFrsoB8rYaD3lNJ5E1Dmpqa lZWVkZGRkZGRkpKSkpKSkZGRgoKCfn5+h4eHh4eHhoaGhYWFjIyMmJiYm5ubpJKQ6lhPy3FrmJiY mJiYt4B86lhPtn98q4eE6lhPwHhzl5eX1Whh6lhPmJiY1Whh6lhPmJiYmJiYwXh06lhPrYiH1mlh 6lhPmZmZrYiH6lhPwnl0mpqa6lhP1mlim5ub1mli6lhPnZ2drJCP22Ve6lhP6lhP3GVeoqKinZ2d kJCQi4uLjIyMjIyMjIyMgoKCf39/g4ODgoKCgoKChISEl5eXpKSkpKSktZWT62tjx4eDoqKioqKi tJSS62tjxoaCtJSR62tjxoaDoqKi3XVv62tjoqKi2Xlz62tjoqKioqKix4eD62tjtZSS1Xx462tj p6CfupGP62tjw4qHpKSk62tj2npzpKSk2np062tjpqam2np062tjzoaBvpWTsqKgqampqKiolpaW iIiIh4eHh4eHiIiIgoKChISEgICAgICAf39/iIiIpqamsLCwsLCwu6al7X940pSQr6+vrq6uwZ+d 7X94ypmWvqKg7X945oV/4YeD7X941ZCMzZeU7X947X947X94zpeUzpeU7X94vqOhvqOh7X945oV/ 6oJ86oJ8s6ysr6+v7X946oJ83oyG7X945oWAsbGxz5iV7X9444mD44mD34yHtLS0tLS0paWliYmJ hISEhISEhYWFgoKCioqKf39/gYGBgICAlJSUubm5vr6+vr6+vr6+6pqV7piTx7a1wLq6552Y8ZWQ w7i3wLq6yrOxw7i30K6s1KupwLq6w7i3552Y8ZWQyrOyxLi4xLi4yrOywLu6vb29xLm416qn1Kyq wbu7vr6+vr6+y7SzyLe1y7Sz2Kqnxbq5v7+/wMDAzLW02Kuo2auoyrm4wcHBwcHBt7e3kZGRhISE hISEhYWFgoKCkpKSf39/gYGBgoKCm5ubxsbGzMzMzMzMzMzM08bE7q+r9Kun9Kun8a2p2r+9y8vL y8vLy8vLy8vLy8vLy8vLy8vLy8vL4rm36bOwy8vLy8vL37u59Kun1cPCzMzMzMzMzMzMzMzMzMzM zMzMzMzMzMzMzMzMzMzMzMzMzMzMzc3Nzc3Nzc3Nzc3Nzc3Nzs7Ozs7Ozs7Ow8PDlpaWhISEhISE g4ODioqKnJycfn5+goKCgYGBlpaWzMzM2dnZ2dnZ2dnZ2dnZ2dnZ4NLR4NLR2tfW2NjY2NjY2NjY 2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2dnZ2dnZ3NbV4NLR2tfX2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ 2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2tra2tra2tra2tra2tra2traxMTEkZGRhISEhISEgoKC l5eXn5+fjo6OgICAgoKCjY2NyMjI5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl 5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl 5eXl5eXl5eXl5eXl5eXl5eXl5ubm5ubm5ubm5ubm5ubm5ubm5OTku7u7iYmJhISEhISEgICAoKCg n5+fm5ubfn5+gYGBhISEtbW16enp8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw 8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw 8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw39/fo6OjhISEg4ODgYGBlZWVoaGhoKCg n5+fkpKSf39/g4ODmZmZ2NjY+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn57+/vv7+/jIyMhISEgYGBkZGRoaGhoaGhoKCgoKCg oKCgj4+Pf39/hYWFp6en19fX7e3t9PT09fX19/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3 9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3 9/f39/f39/f39/f39/f39/f37+/v3d3du7u7k5OTg4ODgYGBkJCQoaGhoaGhoaGhoKCgoKCgoKCg oKCglpaWf39/gYGBj4+Po6Ojra2tr6+vs7OztLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0 tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0 tLS0tLS0tLS0tLS0srKypqamk5OThYWFgYGBgICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 17) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAoaGh oaGhoKCgoKCgoKCgnJyckJCQiIiIh4eHh4eHhYWFhYWFhYWFhISEhISEhISEg4ODg4ODgoKCgoKC goKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg4ODg4ODhISEhISEhYWFhYWFhoaGhoaGh4eHh4eHh4eH h4eHiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIjIyMlJSUnp6eoaGhoaGhoaGhoaGhoaGhoaGhoaGh oKCgoKCgkpKSj4+Purq61NTU29vb2dnZ2tra2tra2NjY2NjY1tbW1dXV1dXV1dXV1NTU09PT09PT 0tLS0tLS0tLS0tLS09PT09PT1NTU1dXV1dXV1tbW2NjY2dnZ29vb3Nzc3Nzc3Nzc3d3d3t7e3t7e 39/f39/f39/f39/f39/f39/f39/f39/f0dHRsrKyioqKlJSUoaGhoaGhoaGhoaGhoaGhoKCgoKCg jo6OoqKi6urq/Pz8+/v7+vr6+fn5+Pj49/f39vb29fX19PT08/Pz8vLy8fHx8PDw7+/v7u7u7u7u 7u7u7u7u7u7u7+/v7+/v8PDw8fHx8/Pz9PT09vb29/f3+fn5+vr6+/v7/Pz8/f39/v7+/v7+//// ////////////////////////////////////5ubmoaGhjo6OoaGhoaGhoaGhoaGhoKCgkZGRoKCg +fn5/Pz8/Pz8+/v7+vr6+fn59/f39vb29PT08/Pz8vLy8fHx8PDw7+/v7u7u7Ozs7Ozs6+vr6+vr 6+vr6+vr7Ozs7e3t7u7u7+/v8fHx8/Pz9PT09vb2+Pj4+fn5+vr6+/v7/f39/f39/v7+//////// /////////////////////////////////////Pz8qqqqj4+PoaGhoaGhoaGhmZmZi4uL5+fn9/f3 9vb29fX19PT08/Pz8vLy8PDw7+/v7e3t7Ozs6+vr6enp6Ojo5ubm5eXl5OTk5OTk5OTk5OTk5OTk 5OTk5OTk5eXl5ubm5+fn6enp6+vr7e3t7+/v8fHx8/Pz9PT09fX19vb29/f3+Pj4+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn58/PznJyck5OToaGhoaGhjIyMxcXF7+/v7u7u7u7u 7e3t7Ozs6urq6enp6Ojo5ubm5eXl4+Pj4uLi4eHh39/f3d3d3Nzc29vb2tra2tra2tra2tra2tra 29vb3Nzc3d3d3t7e4eHh4+Pj5eXl5+fn6Ojo6urq6+vr7e3t7u7u7+/v8PDw8fHx8fHx8fHx8fHx 8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx4ODgh4eHn5+fnJycjo6O4eHh5eXl5OTk4+Pj4uLi 4uLi4eHh39/f3d3d29vb2dnZ2dnZ2NjY1tbW1NTU09PT0dHR0NDQz8/Pz8/Pz8/Pz8/P0NDQ0NDQ 0tLS09PT1NTU19fX2dnZ29vb3d3d3t7e4eHh4uLi4+Pj5OTk5eXl5ubm5+fn5+fn5+fn5+fn5+fn 5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fnp6enlZWVlJSUpKSk2tra2tra2dnZ2dnZ2NjY19fX 1dXV09PT0tLS0dHRz8/Pzc3NzMzMy8vLycnJyMjIxsbGxsbGxcXFxcXFxcXFxcXFxsbGxsbGx8fH yMjI25aS90A190A18lJI4JuX09PT1tbW19fX2NjY2dnZ2tra29vb3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc 3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3NzcxMTEiYmJjIyMsrKyzs7Ozs7Ozs7Ozc3NzMzMy8vLycnJ yMjIxsbGxcXFw8PDwsLCwcHBwMDAvr6+vLy8vLy8u7u7urq6ubm5ubm5urq6u7u7vLy8vLy8vb29 zJ6c0ZiUz6Gf61dO9D0yzre1ysrKy8vLzMzMzs7Ozs7Oz8/P0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ 0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQy8vLgoKChoaGt7e3wsLCwsLCwsLCwcHBwMDAwMDAwMDAvr6+ vb29vb29u7u7urq6uLi4uLi48kI48kI48kI48kI48kI4srKyxo+M6lBH8kI4419XwJ+dtra2yZOP 7ko/7kpA6FlQ8kI4zKCdwcHBwcHBw8PDxMTExMTExcXFxsbGxsbGxsbGxsbGxsbGxsbGxsbGxcXF xcXFxMTExMTExMTExMTExMTEwMDAgoKCg4ODs7OzuLi4uLi4t7e3t7e3urq6vb29vb29u7u7urq6 urq6uLi4t7e3tra2tbW18FBG5WNbwpqXwpmWwpmWtauq7VZN5WNaxpSQ7VZN4GlhtLS06FxU7VZN yZeU33Jq8FBGyaCdvb29vr6+v7+/wMDAwcHBwcHBwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwMDA vLy8ubm5ubm5ubm5ubm5tra2goKCgoKCq6urrq6urq6ura2tsrKyu7u7vLy8u7u7u7u7ubm5ubm5 t7e3t7e3t7e3tra28F5V4XRts7Ozs7Ozs7Ozwp2b8F5V0YiEs7Oz4XRt8F5VtLS08F5V4nRut7e3 1IyI8F5VyaSivLy8vb29vb29vr6+v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/u7u7 srKyr6+vr6+vr6+vrKysgoKCg4ODoqKipqampqamp6entra2v7+/v7+/vr6+vr6+vLy8vLy8u7u7 u7u7urq6urq68HBo4oJ8uLi4t7e3t7e3wqqp8HBo14+LuLi45n137XVturq67XVt6XlzvLy81paS 8HBoyqqovr6+v7+/wMDAwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwMDAs7Oz qKiop6enp6enpaWlgoKCh4eHmZmZoKCgoKCgqKiovr6+xMTExMTExMTExMTEw8PDw8PDwcHBwcHB wcHBwcHB8oN95ZKNwMDAv7+/v7+/v7+/5ZKN8oN96I+J8oN92aKewcHB3J6b8oN96Y+K7IuG8oN9 z7SyxMTExMTExcXFxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGurq6paWl oaGhoaGhn5+fgoKCjY2Nk5OToKCgoKCgr6+vysrKz8/Pz8/Pz8/Pzs7Ozs7Ozs7Ozc3Nzc3NzMzM zMzM9JmT6qahzMzMy8vLy8vLy8vLy8vL27i24LKw1r++zMzMzMzMzMzM3Lm34bOw18C/2MG/0cvL z8/Pz8/Pz8/P0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQx8fHq6uroaGh oaGhn5+fgoKClZWVi4uLoKCgoKCgtLS01dXV2dnZ2dnZ2dnZ2dnZ2NjY2NjY2NjY19fX19fX19fX 9q6p7ri119fX1tbW1tbW1tbW1tbW19fX19fX19fX19fX19fX19fX19fX2NjY2NjY2dnZ2dnZ2dnZ 2dnZ2dnZ2dnZ2dnZ2dnZ2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra0dHRr6+voaGhoaGh l5eXioqKnp6egoKCnp6eoKCgsLCw2dnZ4uLi4uLi4uLi4uLi4uLi4uLi4uLi4eHh4eHh4eHh4eHh 4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4uLi4uLi4uLi4uLi4uLi4uLi4+Pj 4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj0tLSq6uroaGhoaGhioqK l5eXoaGhkJCQkJCQoKCgqamp1tbW7Ozs6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr 6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr7Ozs7Ozs7Ozs 7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs6+vry8vLpaWloaGhmZmZgYGBoKCg oaGhnZ2dgYGBmZmZoqKixsbG7u7u8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT05+fnubm5oaGhnZ2dhYWFlZWVoaGhoaGh oaGhlJSUhYWFnZ2dsbGx4eHh+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr68/Pzzs7Op6ennp6eiIiIkZGRoaGhoaGhoaGhoaGh oaGhkZGRhISEmpqavLy84ODg8vLy9/f39/f3+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn58/Pz5eXly8vLrKyslpaWhYWFkJCQoaGhoaGhoaGhoaGhoaGhoaGh oaGhl5eXgoKCjIyMoaGhsrKyurq6vb29wMDAwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHB wcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHB wcHBwcHBwcHBwcHBwMDAtra2pqamlpaWioqKgICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 171) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAoaGh oaGhoKCgoKCgoKCgnJyckJCQiIiIh4eHh4eHhYWFhYWFhYWFhISEhISEhISEg4ODg4ODgoKCgoKC goKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg4ODg4ODhISEhISEhYWFhYWFhoaGhoaGh4eHh4eHh4eH h4eHiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIjIyMlJSUnp6eoaGhoaGhoaGhoaGhoaGhoaGhoaGh oKCgoKCgkpKShoaGmpqapqamqampqKioqKioqKiop6enp6enpaWlpaWlpaWlpKSko6Ojo6Ojo6Oj oqKioqKioqKioqKio6Ojo6Ojo6OjpKSkpaWlpaWlp6enp6enqampqampqampqqqqq6urq6urq6ur rKysrKysrKysrKysrKysrKysrKysrKyspqaml5eXhYWFlJSUoaGhoaGhoaGhoaGhoaGhoKCgoKCg jo6Oj4+PsbGxubm5uLi4t7e3t7e3tra2tbW1tLS0tLS0s7OzsrKysbGxsbGxsLCwr6+vr6+vr6+v r6+vr6+vr6+vr6+vr6+vsLCwsbGxsrKys7OztLS0tbW1t7e3t7e3uLi4ubm5urq6urq6urq6u7u7 u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7r6+vkJCQjo6OoaGhoaGhoaGhoaGhoKCgkZGRj4+P uLi4ubm5ubm5uLi4t7e3t7e3tbW1tLS0s7OzsrKysbGxsbGxsLCwr6+vr6+vra2tra2trKysrKys rKysrKysra2trq6ur6+vr6+vsbGxsrKys7OztLS0tra2t7e3t7e3uLi4urq6urq6urq6u7u7u7u7 u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7urq6lJSUj4+PoaGhoaGhoaGhmZmZhISEsLCwt7e3 tra2tbW1tLS0tLS0s7OzsrKysbGxr6+vr6+vrq6urKysrKysqqqqqqqqqampqKioqKioqKioqKio qKioqampqqqqqqqqq6urrKysrq6ur6+vsbGxsrKytLS0tLS0tbW1tra2t7e3t7e3uLi4uLi4uLi4 uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4tbW1jY2Nk5OToaGhoaGhjIyMnp6esrKysbGxsbGx sLCwr6+vrq6ura2trKysq6urqqqqqKioqKiop6enpqampKSkpKSko6OjoqKioqKioqKioqKioqKi o6OjpKSkpKSkpaWlp6enqKioqqqqq6urra2trq6ur6+vsLCwsbGxsrKysrKys7Ozs7Ozs7Ozs7Oz s7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozq6urg4ODn5+fnJychYWFqqqqrKysq6urqqqqqqqq qampqKiop6enpqampKSko6OjoqKioaGhoKCgn5+fnp6enZ2dnJycm5ubm5ubm5ubm5ubnJycnJyc nZ2dnp6en5+foaGhoqKipKSkpqampqamqKioqampqqqqq6urrKysrKysra2tra2tra2tra2tra2t ra2tra2tra2tra2tra2tra2tra2tra2tra2tkZGRlZWVlJSUj4+PpqampqampaWlpKSkpKSko6Oj oqKioKCgn5+fnp6enZ2dnJycm5ubmpqamZmZmJiYl5eXlpaWlZWVlZWVlZWVlZWVlpaWl5eXl5eX mJiYt3Nu6jMo6jMo4EA3u3ZyoKCgoqKio6OjpKSkpaWlpqampqamp6enp6enp6enp6enp6enp6en p6enp6enp6enp6enp6enp6enp6enp6ennZ2diYmJjIyMk5OTn5+fn5+fnp6enZ2dnZ2dnJycm5ub mpqamJiYl5eXlpaWlZWVlJSUk5OTkpKSkZGRkJCQkJCQj4+Pjo6Ojo6Oj4+PkJCQkJCQkZGRkpKS qHt4rnVxq3162UU76DImpI2LnJycnJycnZ2dnp6en5+fn5+foKCgoKCgoKCgoKCgoKCgoKCgoKCg oKCgoKCgoKCgoKCgoKCgoKCgoKCgnp6egoKChoaGk5OTmJiYmJiYl5eXl5eXl5eXl5eXl5eXl5eX l5eXlpaWlZWVlJSUk5OTkpKS6Dku6Dku6Dku6Dku6Dkujo6OqnNw3UM66Dku0k5GoIB+kZGRrHVy 4z414z412UpB6DkurIF+mZmZmZmZm5ubm5ubnJycnJycnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnJycm5ub mpqamZmZmZmZmZmZmZmZmZmZmJiYgoKCg4ODkJCQkpKSkpKSkZGRk5OTl5eXnJycnZ2dm5ubm5ub mpqamJiYmJiYl5eXlpaW6Eg+2FZOqYF+qYF+qYF+mI+O401D2FZOrnx5401D01xUlpaW3lJJ405D sn980GJb6Eg+r4eEnZ2dnZ2dnp6enp6en5+fn5+foKCgoKCgoKCgoKCgoKCgoKCgoKCgn5+fnZ2d mJiYk5OTk5OTk5OTk5OTkpKSgoKCgoKCi4uLjIyMjIyMi4uLlJSUn5+foqKioaGhoKCgn5+fn5+f np6enp6enZ2dnJyc6lhP1mlim5ubmpqampqaromH6lhPwnl0mpqa1mli6lhPm5ub6lhP1mljnp6e xHx36lhPs4+MoqKioqKio6Ojo6Ojo6Ojo6OjpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSknp6e kpKSjY2NjY2NjY2NjIyMgoKCg4ODhoaGh4eHh4eHiYmJnJycqqqqqampqampqampqKiop6enp6en p6enpqampaWl62tj2npzpKSkpKSkpKSksZmY62tjzIR/pKSk3nVv525npaWl525n43Nsp6enyYmG 62tjupmXqampqqqqqqqqq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urqampmJiY iYmJiIiIiIiIiIiIgoKCh4eHg4ODhISEhISEjo6Oq6urtLS0tLS0tLS0s7Ozs7OzsrKysrKysbGx sbGxsbGx7X943oyGsLCwr6+vr6+vr6+v3ouG7X944oiD7X94z5iVsLCw05WR7X944omD5oaA7X94 wqaktLS0tLS0tLS0tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1pqamioqK hYWFhYWFhYWFgoKCjY2NgoKChISEhISEmJiYu7u7wcHBwcHBwcHBwcHBwMDAwMDAwMDAv7+/v7+/ v7+/8ZWQ5KCcvr6+vr6+vr6+vr6+vr6+0a+t16qny7Szv7+/v7+/v7+/0q+t2KuozLW0zba0xL6+ wcHBwcHBwcHBwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCt7e3kpKShYWF hYWFhYWFgoKClZWVgYGBhISEhYWFnp6eyMjIzs7Ozs7Ozs7Ozc3Nzc3Nzc3Nzc3Nzc3Nzc3NzMzM 9Kun6rOwzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzc3Nzc3Nzc3Nzc3Nzc3Nzs7Ozs7O zs7Ozs7Ozs7Ozs7Ozs7Oz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/PxMTEl5eXhYWFhYWF g4ODioqKnp6egICAhISEhISEmZmZzc3N2tra2tra2tra2tra2tra2tra2dnZ2dnZ2dnZ2dnZ2dnZ 2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2tra2tra2tra2tra2tra2tra 2tra2tra2tra29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vbxcXFkpKShYWFhYWFgoKC l5eXoaGhkJCQgoKChISEkJCQysrK5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5eXl5eXl5eXl5eXl 5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm 5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5OTku7u7ioqKhYWFhISEgICAoKCg oaGhnZ2df39/g4ODhoaGtra26urq8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw 8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw 8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw39/fpKSkhYWFhISEgYGBlZWVoaGhoaGh oaGhlJSUgICAhISEmpqa2NjY+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn57+/vwMDAjY2NhYWFgYGBkZGRoaGhoaGhoaGhoaGh oaGhkZGRgICAhoaGqKio19fX7u7u9PT09fX19/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3 9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3 9/f39/f39/f39/f39/f39/f37+/v3t7evLy8lJSUg4ODgYGBkJCQoaGhoaGhoaGhoaGhoaGhoaGh oaGhl5eXgICAgYGBkJCQpKSkra2tr6+vs7OztLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0 tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tbW1tbW1tbW1tbW1tbW1tbW1tbW1 tbW1tbW1tbW1tbW1s7Ozp6enlJSUhYWFgYGBgICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 18) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAoaGh oaGhoKCgoKCgoKCgnJyckJCQiIiIh4eHh4eHhYWFhYWFhISEhISEhISEhISEg4ODg4ODgoKCgoKC goKCgoKCgYGBgYGBgYGBgYGBgYGBgoKCgoKCgoKCgoKCgoKCg4ODhISEhISEhYWFhYWFhoaGhoaG hoaGh4eHh4eHh4eHh4eHiIiIiIiIiIiIiIiIjIyMlJSUnp6eoaGhoaGhoaGhoaGhoaGhoaGhoaGh oKCgoKCgkpKSj4+Purq61NTU29vb2dnZ2tra2dnZ2NjY19fX1tbW1dXV1dXV1NTU1NTU09PT09PT 0tLS0tLS0dHR0dHR0tLS0tLS0tLS0tLS09PT09PT1NTU1dXV1tbW19fX2dnZ2tra29vb3Nzc3Nzc 3Nzc3d3d3t7e3t7e39/f39/f39/f39/f0dHRsrKyioqKlJSUoaGhoaGhoaGhoaGhoaGhoKCgoKCg jo6OoqKi6urq/Pz8+/v7+vr6+fn5+Pj49/f39fX19PT08/Pz8vLy8fHx8PDw7+/v7+/v7u7u7e3t 7Ozs7Ozs7Ozs7Ozs7e3t7e3t7u7u7u7u7+/v8PDw8vLy8/Pz9PT09vb2+Pj4+fn5+vr6+/v7/Pz8 /f39/v7+/v7+////////////////////////5ubmoaGhjo6OoaGhoaGhoaGhoaGhoKCgkZGRoKCg +fn5/Pz8+/v7+vr6+fn5+Pj49/f39fX18/Pz8vLy8fHx8PDw7+/v7u7u7e3t7Ozs6+vr6urq6urq 6urq6urq6urq6urq6urq6+vr7Ozs7e3t7u7u8PDw8fHx8/Pz9fX19/f3+Pj4+fn5+/v7/Pz8/f39 /f39/v7+/v7+/////////////////////////Pz8qqqqj4+PoaGhoaGhoaGhmZmZi4uL5+fn9/f3 9vb29fX19PT08vLy8fHx7+/v7e3t7Ozs6urq6enp6Ojo5ubm5eXl5OTk5OTk4+Pj4+Pj4uLi4uLi 4uLi4uLi4uLi4+Pj5OTk5OTk5OTk5ubm6Ojo6urq7Ozs7e3t7+/v8fHx8/Pz9PT09fX19vb29/f3 +Pj4+Pj4+fn5+fn5+fn5+fn5+fn5+fn5+fn58/PznJyck5OToaGhoaGhjIyMxcXF7+/v7u7u7e3t 7Ozs6+vr6urq6Ojo5+fn5eXl4+Pj4uLi4ODg3t7e3d3d3Nzc29vb2tra2dnZ2NjY19fX19fX19fX 2NjY2NjY2NjY2dnZ2tra29vb3d3d39/f4eHh4+Pj5eXl5+fn6Ojo6urq7Ozs7e3t7u7u7+/v8PDw 8PDw8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx4ODgh4eHn5+fnJycjo6O4uLi5eXl5OTk4+Pj4uLi 4eHh4ODg3t7e3Nzc2tra2NjY1tbW1dXV09PT0tLS0dHRz8/Pz8/Pzs7Ozc3NzMzMzMzMzMzMzc3N zc3Nzs7Oz8/Pz8/P0dHR0tLS1NTU1tbW2dnZ2tra3Nzc3t7e4eHh4uLi4+Pj5OTk5eXl5ubm5ubm 5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fnp6enlZWVlJSUpKSk2tra2tra2dnZ2dnZ19fX1tbW 1NTU09PT0dHRz8/PzMzMy8vLycnJyMjIxsbGxsbGxMTEw8PDwsLCwcHBwcHBwcHBwcHBwcHBwsLC wsLCw8PDxMTExsbGx8fHycnJ90A17GNb0NDQ0tLS09PT1dXV19fX2NjY2dnZ2tra29vb29vb3Nzc 3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3NzcxMTEiYmJjIyMsrKyzs7Ozs7Ozs7OzMzMy8vLycnJyMjI xsbGxcXFw8PDwcHBv7+/vr6+vLy8u7u7ubm5uLi4uLi4t7e3tra2tra2tra2tra2t7e3t7e3uLi4 uLi4ubm5u7u7vLy8vr6+9D0y515WxcXFxsbGyMjIycnJy8vLzMzMzs7Ozs7Oz8/Pz8/P0NDQ0NDQ 0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQy8vLgoKChoaGt7e3wsLCwsLCwsLCwMDAv7+/v7+/vr6+vb29 vLy8u7u7uLi4t7e3tbW1tbW18kI44l5WsbGxsLCw0Hl08kI4v5SRrq6ux4WC6U9H8kI47kk/0Xp1 wZaT8kI403x3tra28kI47kpA7kpA70pA0pCMwMDAwcHBwsLCxMTExMTExcXFxcXFxsbGxsbGxcXF xcXFxMTExMTExMTExMTExMTEwMDAgoKCg4ODs7OzuLi4uLi4t7e3tra2urq6u7u7u7u7urq6ubm5 t7e3tbW1tLS0s7Ozs7Oz8FBG4GhgsLCwr6+vz4B68FBGv5aUv5aU8FBG5GJZv5aUw5GO0IF7wZiW 8FBG0YF8tLS08FBG5mRbx56c6V1V7VdNwba1vr6+v7+/wMDAwcHBwcHBwcHBwsLCwsLCwsLCwMDA vLy8ubm5ubm5ubm5ubm5tra2goKCgoKCq6urrq6urq6ura2tsrKyurq6u7u7u7u7ubm5uLi4t7e3 tra2tLS0tLS0s7Oz8F5V4HNtsbGxsLCw0IiD8F5Vv5uYz4eC8F5V2Hx40IiD0IiDyZKPwp2b8F5V 0omEtLS08F5V4nRuuLi41IyI8F5VyaSivb29vb29vr6+v7+/v7+/v7+/v7+/v7+/v7+/v7+/u7u7 srKyr6+vr6+vr6+vrKysgoKCg4ODoqKipqampqamp6entbW1v7+/vr6+vr6+vLy8vLy8u7u7urq6 ubm5uLi4t7e38HBo7XRt4oF84oF86Xhy8HBow6Oiz5aT8HBo2oqF05OP8HBo4oF8xaWk8HBo1JSQ ubm58HBo44N9vLy82ZGN8HBoy6upv7+/v7+/wMDAwcHBwcHBwcHBwcHBwcHBwcHBwcHBwMDAs7Oz qKiop6enp6enpaWlgoKCh4eHmZmZoKCgoKCgp6envb29xMTExMTExMTEw8PDwsLCwcHBwcHBwMDA wMDAv7+/8oN964qF2KGd16Cd5JKN8oN9yq+twLq56I6J64qE6I6J8oN90qimy6+u8oN92KGewMDA 8oN974eB5pOO8oN97IuGxMTExMTExcXFxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGurq6paWl oaGhoaGhn5+fgoKCjY2Nk5OToKCgoKCgr6+vysrKz8/Pz8/Pzs7Ozs7Ozc3Nzc3NzMzMzMzMzMzM y8vL9JmT6qWhysrKysrK37Gv9JmT1L28ysrKzMfG3LSy37Gv1L28ysrK1b699JmT4LKwzMzM1r++ 1MPC18C/4bSx08jHz8/Pz8/Pz8/P0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQx8fHq6uroaGh oaGhn5+fgoKClZWVi4uLoKCgoKCgtLS01NTU2dnZ2dnZ2NjY2NjY2NjY19fX19fX19fX19fX1tbW 9q6p7ri11dXV1dXV5sLA9q6p3cvK1dXV1dXV1dXV1dXV1tbW1tbW3szL9q6p5sLA19fX19fX19fX 2NjY2NjY2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2tra2tra2tra2tra2tra2tra0dHRr6+voaGhoaGh l5eXioqKnp6egoKCnp6eoKCgsLCw2NjY4uLi4uLi4uLi4uLi4uLi4eHh4eHh4eHh4eHh4eHh4eHh 4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4eHh4t/f59nY5N3d4eHh4eHh4uLi4uLi 4uLi4uLi4uLi4uLi4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj0tLSq6uroaGhoaGhioqK l5eXoaGhkJCQkJCQoKCgqamp1tbW6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6urq6urq 6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr 6+vr6+vr7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs6+vry8vLpaWloaGhmZmZgYGBoKCg oaGhnZ2dgYGBmZmZoqKixsbG7u7u8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 8/Pz8/Pz8/Pz8/Pz8/Pz9PT09PT09PT09PT09PT09PT05+fnubm5oaGhnZ2dhYWFlZWVoaGhoaGh oaGhlJSUhYWFnZ2dsbGx4eHh+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr68/Pzzs7Op6ennp6eiIiIkZGRoaGhoaGhoaGhoaGh oaGhkZGRhISEmpqavLy84ODg8vLy9/f39/f3+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn58/Pz5eXly8vLrKyslpaWhYWFkJCQoaGhoaGhoaGhoaGhoaGhoaGh oaGhl5eXgYGBjIyMoaGhsrKyurq6vb29wMDAwcHBwcHBwcHBwMDAwMDAwMDAwMDAwMDAwMDAwMDA wMDAwMDAwMDAwMDAwMDAwMDAwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHB wcHBwcHBwcHBwcHBwMDAtra2pqamlpaWioqKgICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 181) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAoaGh oaGhoKCgoKCgoKCgnJyckJCQiIiIh4eHh4eHhYWFhYWFhISEhISEhISEhISEg4ODg4ODgoKCgoKC goKCgoKCgYGBgYGBgYGBgYGBgYGBgoKCgoKCgoKCgoKCgoKCg4ODhISEhISEhYWFhYWFhoaGhoaG hoaGh4eHh4eHh4eHh4eHiIiIiIiIiIiIiIiIjIyMlJSUnp6eoaGhoaGhoaGhoaGhoaGhoaGhoaGh oKCgoKCgkpKShoaGmpqapqamqampqKioqKiop6enp6enpqampaWlpaWlpKSko6Ojo6Ojo6Ojo6Oj oqKioqKioaGhoaGhoqKioqKioqKioqKio6Ojo6Ojo6OjpKSkpaWlpqamp6enqKioqampqampqqqq qqqqq6urq6urq6urrKysrKysrKysrKyspqaml5eXhYWFlJSUoaGhoaGhoaGhoaGhoaGhoKCgoKCg jo6Oj4+PsbGxubm5uLi4t7e3t7e3tra2tbW1tLS0s7OzsrKysbGxsbGxsLCwr6+vr6+vr6+vrq6u ra2tra2tra2tra2trq6urq6ur6+vr6+vr6+vsLCwsbGxsrKys7OztLS0tra2t7e3t7e3uLi4ubm5 urq6urq6urq6u7u7u7u7u7u7u7u7u7u7u7u7r6+vkJCQjo6OoaGhoaGhoaGhoaGhoKCgkZGRj4+P uLi4ubm5uLi4t7e3t7e3tra2tbW1tLS0srKysbGxsbGxsLCwr6+vr6+vrq6ura2trKysrKysrKys rKysrKysrKysrKysrKysrKysra2trq6ur6+vsLCwsbGxsrKytLS0tbW1tra2t7e3uLi4ubm5urq6 urq6urq6urq6u7u7u7u7u7u7u7u7u7u7u7u7urq6lJSUj4+PoaGhoaGhoaGhmZmZhISEsLCwt7e3 tra2tbW1tLS0s7OzsrKysbGxr6+vr6+vra2trKysrKysqqqqqqqqqampqKiop6enp6enp6enp6en p6enp6enp6enp6enqKioqKioqampqqqqrKysra2tr6+vr6+vsbGxsrKytLS0tLS0tbW1tra2t7e3 t7e3t7e3uLi4uLi4uLi4uLi4uLi4uLi4uLi4tbW1jY2Nk5OToaGhoaGhjIyMnp6esrKysbGxsLCw r6+vr6+vrq6ura2tq6urqqqqqKioqKiopqampaWlpKSkpKSko6OjoqKioaGhoaGhoKCgoKCgoKCg oaGhoaGhoaGhoaGhoqKio6OjpKSkpqamp6enqKioqqqqq6urra2trq6ur6+vsLCwsbGxsrKysrKy srKys7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozq6urg4ODn5+fnJychYWFqqqqrKysq6urqqqqqqqq qKioqKiopqampaWlpKSkoaGhoKCgn5+fnp6enZ2dnZ2dm5ubm5ubmpqamZmZmZmZmZmZmZmZmZmZ mZmZmpqam5ubm5ubnZ2dnZ2dn5+foKCgoqKipKSkpaWlpqamqKioqampqqqqq6urrKysrKysrKys ra2tra2tra2tra2tra2tra2tra2tra2tra2tkZGRlZWVlJSUj4+PpqampqampaWlpKSko6OjoqKi oaGhoKCgnp6enZ2dm5ubmpqamZmZmJiYl5eXlpaWlZWVlJSUk5OTk5OTk5OTk5OTk5OTk5OTk5OT k5OTlJSUlZWVlpaWl5eXmZmZ6jMo1k1Fnp6en5+foKCgoqKio6OjpKSkpaWlpqampqampqamp6en p6enp6enp6enp6enp6enp6enp6enp6ennZ2diYmJjIyMk5OTn5+fn5+fnp6enZ2dnJycm5ubmpqa mJiYl5eXlpaWlJSUk5OTkpKSkZGRkJCQjo6Ojo6OjY2NjY2NjIyMjIyMjIyMjIyMjY2NjY2NjY2N jo6Ojo6OkJCQkZGRkpKS6DIm00tCl5eXmJiYmpqam5ubnJycnZ2dnp6en5+fn5+fn5+foKCgoKCg oKCgoKCgoKCgoKCgoKCgoKCgoKCgnp6egoKChoaGk5OTmJiYmJiYl5eXlpaWlpaWlpaWl5eXlpaW lpaWlJSUk5OTkZGRkJCQkJCQ6Dku0U1GjY2NjIyMuWFd6DkuonZ0i4uLrmxn3UM66Dku4z00umJe pHh16DkuvGRfkZGR6Dku4z414z414z41tnRwmJiYmZmZmpqam5ubnJycnJycnJycnZ2dnJycm5ub mpqamZmZmZmZmZmZmZmZmZmZmJiYgoKCg4ODkJCQkpKSkpKSkZGRkpKSl5eXm5ubm5ubmpqamZmZ mJiYlpaWlpaWlZWVlJSU6Eg+0ltTkpKSkZGRvG1o6Eg+pn57pn576Eg+11ZOp398rHp3vW1oqIF+ 6Eg+vm9qlpaW6Eg+2VdOrYWC3lNJ405EoZeWnZ2dnp6enp6en5+fn5+fn5+foKCgoKCgn5+fnZ2d mJiYk5OTk5OTk5OTk5OTkpKSgoKCgoKCi4uLjIyMjIyMi4uLk5OTn5+foaGhoKCgn5+fn5+fnp6e nJycm5ubm5ubmpqa6lhP1mlhmZmZmJiYwXh06lhPq4eEwHhz6lhPynBqwXh0wXh0t4B9rYiH6lhP wnl1m5ub6lhP1mljn5+fxHx46lhPs4+MoqKio6Ojo6Ojo6Ojo6Ojo6OjpKSkpKSkpKSkpKSknp6e kpKSjY2NjY2NjY2NjIyMgoKCg4ODhoaGh4eHh4eHiYmJnJycqampqampqampqKiop6enp6enpaWl pKSkpKSkpKSk62tj5m5n2Xlz2Xlz4nJr62tjtJSSwoqG62tjz397x4eD62tj2XlztZWT62tjyIiD pKSk62tj2np0p6enzoaB62tjupqYqampqqqqqqqqq6urq6urq6urq6urq6urq6urq6urqampmJiY iYmJiIiIiIiIiIiIgoKCh4eHg4ODhISEhISEjY2Nq6urtLS0tLS0s7OzsrKysrKysbGxsLCwsLCw sLCwr6+v7X945oV/zpeUzZeU3ouG7X94vqKgsqqq4YeD5oV/4YiD7X94xp2av6Oh7X94z5iUsLCw 7X946oJ83oyH7X945oaAtLS0tLS0tLS0tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1pqamioqK hYWFhYWFhYWFgoKCjY2NgoKChISEhISEmJiYu7u7wcHBwcHBwMDAwMDAwMDAv7+/v7+/v7+/vr6+ vr6+8ZWQ5J+bvb29vb2916mm8ZWQyrOxvb29wLq61Kup16mnyrOyvb29y7Sy8ZWQ16qnv7+/zLWz ybe2zLW02Kuox7u7wcHBwcHBwcHBwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCt7e3kpKShYWF hYWFhYWFgoKClZWVgYGBhISEhYWFnp6eyMjIzs7Ozc3Nzc3Nzc3Nzc3Nzc3NzMzMzMzMzMzMzMzM 9Kun6rOwy8vLy8vL37u59Kun1cPCy8vLy8vLy8vLy8vLzMzMzMzM1cPC9Kun4Ly5zMzMzMzMzc3N zc3Nzc3Nzc3Nzs7Ozs7Ozs7Ozs7Ozs7Ozs7Oz8/Pz8/Pz8/Pz8/Pz8/Pz8/PxMTEl5eXhYWFhYWF g4ODioqKnp6egICAhISEhISEmZmZzc3N2tra2tra2tra2tra2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ 2dnZ2dnZ2NjY2NjY2NjY2NjY2NjY2NjY2NjY2dnZ2dnZ2dnZ2tfX4NPS3NbV2dnZ2dnZ2dnZ2tra 2tra2tra2tra2tra2tra2tra2tra2tra29vb29vb29vb29vb29vb29vbxcXFkpKShYWFhYWFgoKC l5eXoaGhkJCQgoKChISEkJCQysrK5ubm5ubm5ubm5ubm5ubm5eXl5eXl5eXl5eXl5eXl5eXl5eXl 5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5ubm5ubm5ubm 5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5OTku7u7ioqKhYWFhISEgICAoKCg oaGhnZ2df39/g4ODhoaGtra26urq8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw 8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw 8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw39/fpKSkhYWFhISEgYGBlZWVoaGhoaGh oaGhlJSUgICAhISEmpqa2NjY+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn57+/vwMDAjY2NhYWFgYGBkZGRoaGhoaGhoaGhoaGh oaGhkZGRgICAhoaGqKio19fX7u7u9PT09fX19/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3 9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3 9/f39/f39/f39/f39/f39/f37+/v3t7evLy8lJSUg4ODgYGBkJCQoaGhoaGhoaGhoaGhoaGhoaGh oaGhl5eXf39/gYGBkJCQpKSkra2tr6+vs7OztLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0 tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tbW1tbW1 tbW1tbW1tbW1tbW1s7Ozp6enlJSUhYWFgYGBgICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 19) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAoaGh oaGhoKCgoKCgoKCgnJyckJCQiIiIh4eHh4eHhYWFhYWFhISEhISEhISEg4ODg4ODg4ODg4ODgoKC goKCgoKCgoKCgoKCg4ODg4ODg4ODhISEhISEhISEhYWFhYWFhoaGhoaGhoaGh4eHh4eHh4eHh4eH h4eHiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIjIyMlJSUnp6eoaGhoaGhoaGhoaGhoaGhoaGhoaGh oKCgoKCgkpKSj4+Purq61NTU29vb2dnZ2tra2dnZ2NjY1tbW1dXV1dXV1dXV1dXV1NTU1NTU1NTU 1NTU1NTU1NTU1NTU1dXV1dXV1dXV1tbW19fX2NjY2dnZ2tra29vb3Nzc3Nzc3d3d3d3d3t7e3t7e 39/f39/f39/f39/f39/f39/f39/f39/f0dHRsrKyioqKlJSUoaGhoaGhoaGhoaGhoaGhoKCgoKCg jo6OoqKi6enp+/v7+/v7+vr6+fn59/f39vb29PT08/Pz8/Pz8vLy8fHx8fHx8PDw7+/v7+/v7+/v 7+/v8PDw8PDw8fHx8vLy8vLy8/Pz9PT09fX19/f3+Pj4+fn5+vr6+/v7/Pz8/f39/v7+/v7+/v7+ ////////////////////////////////////5ubmoaGhjo6OoaGhoaGhoaGhoaGhoKCgkZGRoKCg +Pj4/Pz8+/v7+vr6+fn5+Pj49vb29PT08/Pz8vLy8fHx8PDw7+/v7u7u7u7u7e3t7Ozs7Ozs7Ozs 7e3t7u7u7+/v8PDw8PDw8fHx8/Pz9PT09fX19/f3+fn5+vr6+/v7/Pz8/f39/f39/v7+/v7+//// /////////////////////////////////////Pz8qqqqj4+PoaGhoaGhoaGhmZmZi4uL5+fn9vb2 9fX19PT08/Pz8vLy8PDw7u7u7e3t6+vr6urq6enp6Ojo5ubm5ubm5eXl5OTk5OTk5OTk5OTk5eXl 5eXl5ubm6Ojo6Ojo6urq6+vr7e3t7u7u8PDw8vLy8/Pz9PT09fX19vb29/f3+Pj4+Pj4+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn58/PznJyck5OToaGhoaGhjIyMxcXF7+/v7u7u7e3t 7Ozs6urq6enp6Ojo5ubm5OTk4+Pj4eHh39/f3t7e3d3d3Nzc29vb29vb2tra2tra29vb29vb3Nzc 3d3d3t7e39/f4eHh4uLi5OTk5ubm6Ojo6enp6urq7Ozs7e3t7u7u7+/v8PDw8PDw8fHx8fHx8fHx 8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx4ODgh4eHn5+fnJycjo6O4eHh5OTk4+Pj4uLi4uLi 4eHh39/f3d3d29vb2dnZ2NjY1tbW1NTU09PT0tLS0dHR0NDQz8/Pz8/Pz8/Pz8/P0NDQ0dHR0tLS 09PT1NTU1dXV2NjY2dnZ29vb3d3d3t7e4eHh4uLi4uLi4+Pj5eXl5eXl5ubm5+fn5+fn5+fn5+fn 5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fnp6enlZWVlJSUpKSk2tra2dnZ2dnZ2NjY19fX1dXV 09PT0tLS0NDQzs7OzMzMy8vLycnJyMjIx8fHxsbGxsbGxMTExMTExMTExMTExsbGxsbGxsbGyMjI ycnJysrKzMzMzs7O0NDQ0tLS09PT1dXV19fX2NjY2dnZ2dnZ2tra29vb3Nzc3Nzc3Nzc3Nzc3Nzc 3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3Nzc3NzcxMTEiYmJjIyMsrKyzs7Ozs7Ozc3NzMzMysrKycnJyMjI xsbGxcXFw8PDwcHBv7+/vr6+vLy8vLy8u7u7urq6ubm5uLi4uLi4ubm5ubm5u7u7vLy8vLy8vb29 v7+/wcHBwsLCxMTExsbGyMjIycnJysrKzMzMzc3Nzs7Ozs7Oz8/P0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ 0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQy8vLgoKChoaGt7e3wsLCwsLCwcHBwMDAv7+/v7+/vr6+vb29 vLy8urq6uLi4t7e3tbW1tbW18kI48kI48kI48kI48kI4vZya7kk/5VdOsrKy1nRu8kI4zIqG1H13 8kI4yJyZwauq61FJ8kI442liwcHBwsLCw8PDxMTExMTExcXFxsbGxsbGxsbGxsbGxsbGxsbGxcXF xcXFxMTExMTExMTExMTExMTEwMDAgoKCg4ODs7OzuLi4t7e3tra2tra2ubm5u7u7u7u7urq6ubm5 t7e3tbW1tLS0s7Ozs7Oz8FBG5GNawJiWwJiWwJiWsLCwxJKP8FBG4Glh8FBG1Xt1s7Oz0oJ98FBG xZ2b1IWA8FBG1oaByaGevb29vr6+v7+/wMDAwcHBwcHBwsLCwsLCwsLCwsLCwsLCwsLCwsLCwMDA vLy8ubm5ubm5ubm5ubm5tra2goKCgoKCq6urrq6ura2trKyssrKyurq6u7u7urq6ubm5t7e3t7e3 tra2tLS0tLS0s7Oz8F5V4XRtsrKysbGxsbGxsbGxsbGx1YN+8F5V5W5ns7OztLS00omF8F5VxaCe 04uH8F5Vx6Ogu7u7vLy8vb29vb29vr6+v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/u7u7 srKyr6+vr6+vr6+vrKysgoKCg4ODoqKipqampaWlpqamtbW1vr6+vr6+vb29vLy8u7u7urq6urq6 ubm5uLi4t7e38HBo7XRt4oF84oF814+Ktra2wamn7XRt7XRt8HBozJ2ZuLi41JSR8HBoyKem1paR 8HBoyqmovr6+vr6+v7+/wMDAwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwMDAs7Oz qKiop6enp6enpaWlgoKCh4eHmZmZoKCgoKCgp6envb29xMTExMTEw8PDw8PDwcHBwcHBwcHBwMDA wMDAv7+/8oN964qF2KGe2KGd0aelwbq66I6J74eBwbu65ZKN74eBybSz2aKe8oN92qOf8oN98oN9 8oN95pSPxMTExMTExcXFxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGurq6paWl oaGhoaGhn5+fgoKCjY2Nk5OToKCgoKCgrq6uysrKz8/Pzs7Ozs7Ozs7Ozc3NzMzMzMzMzMzMy8vL y8vL9JmT7KKe1b681b681L28z8TD1b680MTDy8vLzcjH1r+908LB0cXF1r++0cbF5q2p9JmT37e0 1cTDz8/Pz8/Pz8/P0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQx8fHq6uroaGh oaGhn5+fgoKClZWVi4uLoKCgoKCgs7Oz1NTU2dnZ2dnZ2NjY2NjY19fX19fX19fX19fX1tbW1tbW 9q6p9q6p9q6p9q6p9q6p1dXV1tbW1tbW1tbW1tbW1tbW1tbW5sLA9q6p383M48jG77i13tDP2dnZ 2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2tra2tra2tra2tra2tra2tra2tra2tra2tra0dHRr6+voaGhoaGh l5eXioqKnp6egoKCnp6eoKCgsLCw2NjY4uLi4uLi4uLi4uLi4uLi4eHh4eHh4eHh4eHh4eHh4eHh 4eHh4ODg4ODg4ODg4ODg4ODg4ODg4eHh4eHh4eHh4eHh5N3d59nZ49/f4uLi4uLi4uLi4uLi4uLi 4uLi4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj0tLSq6uroaGhoaGhioqK l5eXoaGhkJCQkJCQoKCgqamp1tbW6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6urq6urq 6urq6urq6urq6urq6urq6urq6urq6urq6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr7Ozs 7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs6+vry8vLpaWloaGhmZmZgYGBoKCg oaGhnZ2dgYGBmZmZoqKixsbG7u7u8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz 8/Pz8/Pz9PT09PT09PT09PT09PT09PT09PT09PT09PT05+fnubm5oaGhnZ2dhYWFlZWVoaGhoaGh oaGhk5OThYWFnZ2dsbGx4eHh+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6 +vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr6+vr68/Pzzs7Op6ennp6eiIiIkZGRoaGhoaGhoaGhoaGh oaGhkJCQhISEmpqavLy84ODg8vLy9/f39/f3+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn58/Pz5eXly8vLrKyslpaWhYWFkJCQoaGhoaGhoaGhoaGhoaGhoaGh oaGhlpaWgYGBjIyMoaGhsrKyurq6vb29wMDAwcHBwcHBwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA wMDAwMDAwMDAwMDAwMDAwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHB wcHBwcHBwcHBwcHBwMDAtra2pqamlpaWioqKgICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 191) { $imagedata = 'Qk2mDgAAAAAAADYAAAAoAAAAOAAAABYAAAABABgAAAAAAHAOAAAmDgAAJg4AAAAAAAAAAAAAoaGh oaGhoKCgoKCgoKCgnJyckJCQiIiIh4eHh4eHhYWFhYWFhISEhISEhISEg4ODg4ODg4ODg4ODgoKC goKCgoKCgoKCgoKCg4ODg4ODg4ODhISEhISEhISEhYWFhYWFhoaGhoaGhoaGh4eHh4eHh4eHh4eH h4eHiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIjIyMlJSUnp6eoaGhoaGhoaGhoaGhoaGhoaGhoaGh oKCgoKCgkpKShoaGmpqapaWlqampqKioqKiop6enp6enpaWlpaWlpaWlpKSkpKSko6Ojo6Ojo6Oj o6Ojo6Ojo6Ojo6OjpKSkpaWlpaWlpaWlpqamp6enp6enqKioqampqampqqqqq6urq6urq6urq6ur rKysrKysrKysrKysrKysrKysrKysrKyspqaml5eXhYWFlJSUoaGhoaGhoaGhoaGhoaGhoKCgoKCg jo6Oj4+PsLCwuLi4uLi4t7e3t7e3tbW1tLS0s7OzsrKysrKysbGxsbGxsbGxsLCwr6+vr6+vr6+v r6+vsLCwsLCwsbGxsbGxsbGxsrKys7OztLS0tbW1tra2t7e3t7e3uLi4ubm5urq6urq6urq6urq6 u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7r6+vkJCQjo6OoaGhoaGhoaGhoaGhoKCgkZGRj4+P t7e3ubm5uLi4t7e3t7e3tra2tLS0s7OzsrKysbGxsbGxsLCwr6+vr6+vr6+vrq6ura2tra2tra2t rq6ur6+vr6+vsLCwsLCwsbGxsrKys7OztLS0tbW1t7e3t7e3uLi4ubm5urq6urq6urq6urq6u7u7 u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7urq6lJSUj4+PoaGhoaGhoaGhmZmZhISEsLCwtra2 tbW1tLS0tLS0s7OzsrKysLCwr6+vrq6ura2trKysrKysqqqqqqqqqqqqqampqampqampqampqqqq qqqqqqqqrKysrKysra2trq6ur6+vsLCwsrKys7OztLS0tLS0tbW1tra2t7e3t7e3t7e3uLi4uLi4 uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4tbW1jY2Nk5OToaGhoaGhjIyMnp6esrKysbGxsLCw r6+vrq6ura2trKysq6urqampqKiop6enpqampaWlpKSkpKSko6Ojo6OjoqKioqKio6Ojo6OjpKSk pKSkpaWlpqamp6enqKioqampq6urrKysra2trq6ur6+vsLCwsbGxsrKysrKysrKys7Ozs7Ozs7Oz s7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozq6urg4ODn5+fnJychYWFqqqqq6urqqqqqqqqqamp qKiop6enpqampKSko6OjoaGhoKCgn5+fnp6enZ2dnZ2dnJycm5ubm5ubm5ubm5ubnJycnZ2dnZ2d np6en5+fn5+foaGho6OjpKSkpqampqamqKioqampqqqqqqqqrKysrKysrKysra2tra2tra2tra2t ra2tra2tra2tra2tra2tra2tra2tra2tra2tkZGRlZWVlJSUj4+PpqampaWlpKSkpKSko6OjoqKi oKCgn5+fnp6enZ2dm5ubmpqamZmZmJiYl5eXl5eXlpaWlZWVlZWVlZWVlZWVlpaWlpaWl5eXmJiY mZmZmZmZm5ubnZ2dnp6en5+foKCgoqKio6OjpKSkpKSkpaWlpqampqamp6enp6enp6enp6enp6en p6enp6enp6enp6enp6enp6enp6enp6ennZ2diYmJjIyMk5OTn5+fnp6enZ2dnZ2dnJycm5ubmpqa mJiYl5eXlpaWlJSUk5OTkpKSkZGRkJCQkJCQj4+Pjo6Ojo6Ojo6Ojo6Ojo6OkJCQkJCQkZGRkpKS k5OTlJSUlZWVl5eXmJiYmpqam5ubnJycnZ2dnZ2dnp6en5+fn5+foKCgoKCgoKCgoKCgoKCgoKCg oKCgoKCgoKCgoKCgoKCgoKCgoKCgnp6egoKChoaGk5OTmJiYl5eXl5eXlpaWlpaWlpaWl5eXlpaW lpaWlJSUk5OTkZGRkJCQkJCQ6Dku6Dku6Dku6Dku6Dkunn174z4010lAjo6OwF5Y6DkusW9rvGRf 6DkuqX16n4mI3kQ76Dkuz1ZPmZmZmpqam5ubm5ubnJycnJycnZ2dnZ2dnZ2dnZ2dnZ2dnJycm5ub mpqamZmZmZmZmZmZmZmZmZmZmJiYgoKCg4ODkJCQkpKSkZGRkZGRkpKSl5eXm5ubm5ubmpqamZmZ mJiYlpaWlpaWlZWVlZWV6Eg+2FZOqIB9qIB9qIB9kpKSrXt46Eg+01tT6Eg+w2pklZWVv29q6Eg+ rIOBwXFr6Eg+wnJsr4eEnZ2dnZ2dnp6enp6en5+fn5+foKCgoKCgoKCgoKCgoKCgoKCgn5+fnZ2d mJiYk5OTk5OTk5OTk5OTkpKSgoKCgoKCi4uLjIyMi4uLi4uLk5OTn5+foaGhn5+fn5+fnp6enZ2d nJycm5ubm5ubm5ub6lhP1mlimZmZmZmZmZmZmZmZmZmZxnRw6lhP2mVdm5ubm5ubwnp16lhPsIyJ w3t36lhPso2MoaGhoqKioqKio6Ojo6Ojo6Ojo6OjpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSknp6e kpKSjY2NjY2NjY2NjIyMgoKCg4ODhoaGh4eHhoaGiYmJm5ubqampqampqKiop6enp6enpqampaWl pKSkpKSkpKSk62tj525n2Xlz2Xlzy4N/oqKisJiW5m5n525n62tjvo+LpKSkyIiE62tjt5eVyYmF 62tjuZmWqampqampqampqqqqq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urqampmJiY iYmJiIiIiIiIiIiIgoKCh4eHg4ODhISEhISEjY2Nq6urtLS0s7Ozs7OzsrKysrKysbGxsLCwsLCw sLCwr6+v7X945oV/zpeUzpeUxp2as6yr4YiD6YJ8s6yr3ouG6oJ8u6emz5iV7X94z5iV7X947X94 7X9434yHtLS0tLS0tLS0tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1pqamioqK hYWFhYWFhYWFgoKCjY2NgoKChISEhISEl5eXu7u7wcHBwcHBwMDAwMDAwMDAv7+/v7+/vr6+vr6+ vr6+8ZWQ552YyrOyyrOyyrOyxLi4yrOyxLi4vr6+wbu7y7SzyLe1xbq5y7Szxbq53qWi8ZWQ1q2r yrm4wcHBwcHBwcHBwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCt7e3kpKShYWF hYWFhYWFgoKClZWVgYGBhISEhYWFnZ2dyMjIzs7Ozc3Nzc3Nzc3Nzc3Nzc3NzMzMzMzMzMzMzMzM 9Kun9Kun9Kun9Kun9Kuny8vLzMzMzMzMzMzMzMzMzMzMzMzM4Ly59Kun18TD3MC+6rSw1cfGzc3N zs7Ozs7Ozs7Ozs7Ozs7Ozs7Oz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/PxMTEl5eXhYWFhYWF g4ODioqKnp6egICAhISEhISEmZmZzc3N2tra2tra2tra2tra2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ 2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ3NbV4dPS29jY2dnZ2tra2tra2tra2tra 2tra2tra2tra2tra29vb29vb29vb29vb29vb29vb29vb29vb29vb29vbxcXFkpKShYWFhYWFgoKC l5eXoaGhkJCQgoKChISEkJCQysrK5ubm5ubm5ubm5ubm5ubm5eXl5eXl5eXl5eXl5eXl5eXl5eXl 5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5ubm5ubm5ubm5ubm5ubm5ubm 5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5OTku7u7ioqKhYWFhISEgICAoKCg oaGhnZ2df39/g4ODhoaGtra26urq8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw 8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw 8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw39/fpKSkhYWFhISEgYGBlZWVoaGhoaGh oaGhk5OTgICAhISEmpqa2NjY+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5 +fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn57+/vwMDAjY2NhYWFgYGBkZGRoaGhoaGhoaGhoaGh oaGhkJCQgICAhoaGqKio19fX7u7u9PT09fX19/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3 9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3 9/f39/f39/f39/f39/f39/f37+/v3t7evLy8lJSUg4ODgYGBkJCQoaGhoaGhoaGhoaGhoaGhoaGh oaGhlpaWf39/gYGBkJCQpKSkra2tr6+vs7OztLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0 tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tbW1tbW1tbW1tbW1 tbW1tbW1tbW1tbW1s7Ozp6enlJSUhYWFgYGBgICAmZmZoaGhoaGhoaGhoaGh'; } elsif ($opt == 1) { $imagedata = 'R0lGODlh9AEgAcQAABISEpeRiFdNRNPa2Gppbi0qKbKzsXJqXP///4F9dhsXIKOhoEA4O8TFxFdW V+Xp5QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA 9AEgAUAF/+AijqRBLqaJrkbapuwrz3Tz2m1j7wbv90CdUNgbGo9I3UC4VDaWUGf0qYxCB9dnFku1 ar1WbvhLvmLP6DT6qza33+IzW8uGi+luc/cub3q7Un9ggH5MhkOFVEmLSUWOOkVDjzw0OZaXlZkv MS4iMCwnoaEwKp0uMyiamZQ4j0GvREeRjLSItYeFfHhuhGW+a2p1dnN9eXZ6w8fJxsV1u2/EXMJx 02C6yHzWe3iAhlODt+E7sZDlrpCTM62qqDKpK/AqI/LznjGpLe/s6zeXPv+TxombUiuXlG3bxsTZ ogwYtTbVGko882DigIoVL2LJaHEjxY52OIK0uKuMQojFrP9dq/KtG8FuTmzFFBdkXM1zsNhlwrfJ lD5PpUCd0lmpFcBySJM0EXdw6aCTvfpwWwgt5Ug1Ij2iySqy60eNHjli/Dh2rFawGsWGTWMWbVm2 X9HGjWs269VlDKlG3IOsJCFw3mTOZJoUpzkcrIjy1PfJlCp+iGWYg/Uv3FLBBhFqy9bQ5NWMduGe fQta7luwD0qn1Zp6Lem0r0unrgvb9emyGGevXh177UWxssmK3g0n9F1sDvs+1WxQ6pHLhGfFemWY uuKePNVZSvxDElOnimw1j3rtWMSQFtuq552bde3greP/5s2+/ezc8vHDxo37d3/+/r13n3/x8Vdg fvOhxl7/bfSBZp+CdAl3XBrnLURMQlEpAh14z90ySyTVRUZUUUBIRtl0hB2i4VO8PFTNM8q05VaE u8G3kW4DtnZjgPkdWCCBOM5335BEFkkkj0AeuR+ORjbppI/4IThkkkwKmaN+Vs74HoQ2jibhVhLt tcZUW2iIRCKCIQEiiomV6KaJ/iBmU1JKnSnTZhZSaFVDXv1HI4T1Scljj08WaqQOCCSq6KKMNuro o5BGKumklFZqKaUPNGDopqRVueCPOp4WoVojeQZMTFIR9FJ4RkBnxDndWXfUiQOZKUhLVIHUp5a+ 2QfqoFByKuywv2l66bHIJqvsssw2agCVw0b7pJAK9kbc/7Vh5pmQNII0FZ6rTIV4mEAFtUretpyh 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 2FmbflKMvkPcuei/iktk7eCizHvoml/efORbN1879E2Lnrvd2MtONMaIWXzW2K87enZHq4evduyz M95X6d6bwiRa73sv/1kVu18/+/Z7P8r8Zo2y//78C6D9ANi/SXAufggJoPwcISzzeK8slDhPAxu4 JJ9lClOaUpIFEXM686VuBq3jjgg9SLJIbc92mpOY+whQOhWewn0NsZjE6CdA+83whgrM4QIr5j8m EdCH/OthEPs3PwD20H9CLMv/MCUsJh6xgkiEYossKMEllQZ8JJxOobTDqCyS/+wBsZue8AREP4cg UIb3wyH/ZnhGG5oxf2ssYhnZV4khGtCIFttfWYjYxO5ZTIl8BCID81hAJu6RikT83yhGlEH/WYgA a/Hio+aiKElmsQEw809DKJSgF6KRhmcEZRrvR8cYvs99e6yfxBqEoAOwkI6hrNgeKUHLOvrxh7ZM jC4j+EA/EhFdsrSTE205CXQpRomDXBIGLcgzmBgAi5askeqi6UEwQq5xYWPhg2IIQ8zlEIatPKAr x2nGF5KxjpQI5x95iEB08WyTqGTSK3nWpGDOD4L80+YfFVPHY06wlhA0ETox1M9i8nJnmKKlSxAU gGVRk2Pje+jrHjCABjSgZv8zq5xG4zMp6G3vcR49yWTGOc5WNkhzAOKPQ7TJQs+00j+uZCVJ1XlS mMrElhJqUi0HusdX1rOlj6mjNqfHwk2axafptFgrIQMZhyQVQyYthc0GAE2JSrOSVs3iALbK1QZw date9SpFNULWslJ0q2OlakUNYFGLspVmF60ZRr8l18ENbnIczSjRZGZXuMb1onS1a1sH69a4vhWu iB2cYf3aVrZedLGMbataqQoytIkMhGZdVFY3lqPNevazoA2taFlR1dGa9rSoTe0kVcva1rr2tbCN rWxnS9va2va2uM2tbnfL29769rfADa5wh0vc4hr3uMhNrnKXy9zmOve50I1JrnSnS93qWve62M2u drfL3e5697vgDa94x0ve8pr3vOhNr3rXy972uve98I2vfOdL3/ra9774za9+98vf/vr3vwAOsIAH vN8QAAA7'; } return ($imagedata); } ###########################################################DOCUMENTATION =head1 Name NewsSurfer =head1 Description Read/Download/Post - To/From - NNTP Newsgroups =head1 Readme NewsSurfer v3.10 A Threaded Perl Tk GUI based NNTP client Now includes discussion grouping! =head1 Prerequisites Net-NNTP Date-Parse Date-Format Convert-BulkDecoder Tk =head1 Corequisites Win32::Console (Optional) =head1 OSnames MSWin32 m/^((?:linu|uni)x)$/i based OS's may work ok also! =head1 Script Categories News =head1 Copyright NewsSurfer - Read/Download/Post - To/From - NNTP Newsgroups Copyright (C) 2004-2010 Jason David McManus This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA =head1 New features Discussion based message grouping: Messages are now grouped using references The 'marked read' indicator is now italic dark blue When a parent msg receives a new reply the entry is bolded blue Killfile support: Now you can filter posts based on the 'from' field. Rules you define in killfile.txt will be checked against all posts. If the 'from' field of any post matches a killfile rule entry, the post will be filtered and will not be displayed. Edit the file 'killfile.txt' in this programs' main directory. You may add one rule per line. The rules are not case sensitive. =head1 History v1_00 *Initial release. (Jan. 2004) v1_10 *Improved Ctrl-A shortcut *Added Shift-End and Shift-Home shortcuts to the message display v1_20 *Will no longer attempt to authenticate unless the user & pass fields have been completed in options *Cosmetic improvements to Post & Read functions *Added preformance improving option (limits message age) v1_30 *Added option to open files after download (Win32 only?) *Message reply and post functions are faster now *Improved error display v1_40 *Improvements to memory management *Added search function to groups screen *Added right-click menus to main window *Fixed a bug in the scanning multipart function v1_50 *Minor GUI fixes/enhancements *Fixed a bug with opening file when the Dl Dir is not configured *Added a button to browse or ls the download directory v1_60 *Optimized for Tk 804.25 beta 15 *Some window decoration improvements *Added chooseDirectory function to the options page *Fixed a bug in grab&open when opening files with 4 char ext's *Improved delete function and overall responsiveness *Speed up sorting function slightly v1_70 *Added 'wrote:' line *Fixed grab function: when article doesnt exist on server v1_80 *Disabled as many widgets as possible while groups window is open *Improved search function for the groups screen *Implemented 'quoted-printable' message parsing *Added ability to attach signatures v1_90 *Fixed a major bug with the duplicates function *Fixed a bug with selecting text in the read/post screens v2_00 *Removed popup progressbar, added statusbar v2_10 *Added new option (limit to 5k messages per scan) *Added error routine for invalid logins *Improvements to statusbar *Improved speed v2_20 *Fixed a subject line bug *Fixed a bug when all messages are older than 30 days *Changed error message for configure download directory *Added a screen to select the number of new message to download *Added a new function - message_load v2_30 *Fixed a display bug in group unsubscribe from main screen *Improved groups update function (uses less memory) *Added a much needed new function 'Clear newsgroup' *Added option to beep on errors *Added logging option v2_40 *Reworked the sort function *Added a time-out for the non-fatal error dialogs *Changed message display update from time based to count based *Replaced some backtick operations with 'system' ones *Created a subroutine for loading program images *Added splashscreen *Improved Grid v2_50 *Added new functions to d/l messages dialog (all, newest) *Added header line for the references field *Improved Log and Error system *Improved groups/search v2_60 *Added some extra error handling for some connect sequences *Wrapped the decode attachment process in an 'Eval' *Added a function to search subject headers in group *Configured some error messages to appear in the statusbar *Changed timeout from 30 to 5 *Removed some timed mw updates *Improved group/search v2_80 *Rolled back changes to the connection timeout values. *Changed right-click bindings for message hlist *Fixed a bug where program would freeze if there was a problem connecting during a post operation *Messages are no longer marked read if the attachment is not *decoded properly v2_90 *Added new images for buttons (thanks!) *Implemented paned window for main screen v2_91 *Improved error handling *Retries once on a bad article download *More efficient v3_00 *Code has been re-structured *Some functions now use threads *Newsgroup storage now uses MLDBM instead of a flat file format *Now only using two images for each main button *Various other bug fixes, performance, and memory improvements *Disabled posting of attachments untill yEnc bugs are fixed v3_01 *Fixed reply quoting (changed '>' to '> ') v3_02 *Improved functionality of the groups subscribe window search, it is now possilble to search before displaying all newsgroups *Fixed regex character escaping in the groups subscribe window *Cleaned code, removed most goto's, added ready subroutine *Move nearly all blocking functions to a threaded model *Handles timeout and other network errors better v3_03 *New help system *Added killfile support *Fixed handling of part 0 files in decode section *Fixed a bad memory leak caused by the progress bar widget *Implemented bug-fixes reported on comp.lang.perl.tk (thanks!) v3_10 *Added a CornerBox *New logfile system *Added discussion grouping features =head1 Notes xover %xover is a HoA $k is the message number on the server $xover{$k}[0] #subject $xover{$k}[4] #references $xover{$k}[1] #from $xover{$k}[5] #bytes $xover{$k}[2] #date $xover{$k}[6] #lines *parts* $xover{$k}[3] #msg-id $xover{$k}[7] #xref:full *read* Main data structure (1 for each subscribed group): DB Name Structure ----------- --------- MULTIPARTDB HoHoH HEADERDB HoHoA RSSDB HoHoS $mldbm{MULTIPARTDB}{SUBJECT}{PART} #Message ID $mldbm{HEADERDB}{MESSAGENUMBER}[0] #subject $mldbm{HEADERDB}{MESSAGENUMBER}[1] #from $mldbm{HEADERDB}{MESSAGENUMBER}[2] #date $mldbm{HEADERDB}{MESSAGENUMBER}[3] #message-id $mldbm{HEADERDB}{MESSAGENUMBER}[4] #references $mldbm{HEADERDB}{MESSAGENUMBER}[5] #bytes $mldbm{HEADERDB}{MESSAGENUMBER}[6] #lines *parts* $mldbm{HEADERDB}{MESSAGENUMBER}[7] #xref:full *read* $mldbm{HEADERDB}{MESSAGENUMBER}[8] #old message? $mldbm{RSSDB}{URL} #XML as string *Each subscribed newsgroup gets a database file (groupname.grp) Posting subroutines: [raise the post message window] | | [wait for user input] {press a button (Attach&Send | Send)} | --------<-------|---------->----------- | Attach&Send Send | | | [post_attach] | ^ {more attachment data? (yes | no)} | | | | | ------<------|----->--------- | | | yes no | | | | | | [post_yEnc] [post_send] | | | | | --------------------<---------- | | [lower the post message window] *allows for 1 attachment of >= 1 part(s) per post =head1 Todo list =over =item * Expand options to include killfile editing and font/color configuration =item * Test the new references based discussion grouping routines =item * Finish integrating RSS and Email functions =item * Reimplement image loading interface =item * Fix and improve posting =item * Linux and Unix testing =item * Internationalization =back =head1 Caveats =over =item * Install to a new directory if upgrading from version 3.0 or earlier =item * This is still beta software =back =head1 Contact Contact: QoSnoSpam@cpan.org Just remove the noSpam ;) Thank you =cut