eoin has asked for the wisdom of the Perl Monks concerning the following question:

Hey monks i've recently been working with Tk and Crypt in a GUI for an ecryption application. I've got a few problems as I'm not very familiar with Tk. I've done my best with this first draft of the code but I can't really get my head around how I'm going to get the encryptyion key people insert into the textbox in the popup window. Also I don't think that the "DialogBox" method is the best way to obain a popup window and if it is I'm doing it wrong.

So far I've proofed the encryption code and the main window code but its the in between that I'm having problems with.

  • The taking of text from the top textbox sending it to the encrypting sub and sending it back.
  • Creating the popup window with a textbox inside.
  • Taking a value from the textbox.

I'd really apprieciate any help you can give. The code is inside.

use strict; use warnings; use Tk; use Crypt::CBC; use Crypt::DES; my($key); my $mw = new MainWindow; $mw->geometry('800x600'); my $menu = $mw->Menu(-menuitems => &menubar_menuitems() ); $mw->configure(-menu => $menu); my $tpfrme = $mw->Frame; my $mdfrme = $mw->Frame(-height => '60'); my $bmfrme = $mw->Frame; my($text1) = $tpfrme->Scrolled('TextUndo', -height => '1', -width => '1', -scrollbars => 'osoe', ); my $encrypt_button = $mdfrme->Button(-text=>"Encrypt", -height=>'1', -command=>[\&OnEncrypt] ); my $get_key_button = $mdfrme->Button(-text=>"Set Encryption Key", -height=>'1', -command=>[\&get_key] ); my $decrypt_button = $mdfrme->Button(-text=>"Decrypt", -height=>'1', -command=>[\&OnDecrypt] ); my($text2) = $bmfrme->Scrolled('TextUndo', -height => '1', -width => '1', -scrollbars => 'osoe', ); $mw->bind('Tk::TextUndo', '<Control-Key-o>', sub { OnFileLoad(); } ); $mw->bind('Tk::TextUndo', '<Control-Key-s>', sub { OnFileSave(); } ); $mw->bind('<Control-Key-q>', sub { OnExit(); } ); $mw->bind('Tk::TextUndo', '<Control-Key-s>', sub { OnEncrypt(); } ); $mw->bind('Tk::TextUndo', '<Control-Key-s>', sub { OnDecrypt(); } ); $mw->bind('<Control-Key-a>', sub { OnAbout(); } ); $tpfrme ->pack(qw/-side top -fill both -expand 1 + /); $mdfrme ->pack(qw/-side top -fill both -expand 0 + /); $bmfrme ->pack(qw/-side bottom -fill both -expand 1 + /); $text1 ->pack(qw/-side top -fill both -expand 1 + /); $encrypt_button->pack(qw/-side left + /); $get_key_button->pack(qw/ -anchor cen +ter/); $decrypt_button->pack(qw/-side right + /); $text2 ->pack(qw/-side top -fill both -expand 1 + /); MainLoop; sub menubar_menuitems{ return [ map ['cascade', $_->[0], -tearoff=> 0, -menuitems => $_->[1]], ['~File', &file_menuitems() ], ['~Actions', &actions_menuitems()], ['~Help', &help_menuitems() ], ]; } sub file_menuitems { return [ [qw/command ~Open -accelerator Ctrl-o/, -command=>[\&OnFileLoad]], [qw/command ~Save -accelerator Ctrl-s/, -command=>[\&OnFileSave]], '', [qw/command ~Exit -accelerator Ctrl-q/, -command=>[\&OnExit]] ]; } sub actions_menuitems { return [ [qw/command ~Encrypt -accelerator Ctrl-e/, -command=>[\&OnEncrypt]], [qw/command ~Decrypt -accelerator Ctrl-d/, -command=>[\&OnDecrypt]], ]; } sub help_menuitems { return [ [qw/command ~About -accelerator Ctrl-a/, -command=>[\&OnAbout] ] ]; } sub OnFileLoad { $text1->FileLoadPopup(); } sub OnFileSave { $text2->FileSaveAsPopup(); } sub OnExit { exit 0; } sub OnEncrypt { my $text = $text1->get(0.1, 'end') ; my $encrypted_data = encrypt_string($text) ; my $widget = $text2->Subwidget("text") ; tie *STDOUT, ref $widget, $widget; print $encrypted_data; } sub OnDecrypt { my $text = $text1->get(0.1, 'end') ; my $decrypted_data = decrypt_string($text) ; my $widget = $text2->Subwidget("text") ; tie *STDOUT, ref $widget, $widget; print $decrypted_data; } sub encrypt_string { my $cipher = new_cipher() ; my $string = shift ; my $encryp_data = $cipher->encrypt($string); $cipher = "" ; return $encryp_data ; } sub decrypt_string { my $cipher = new_cipher() ; my $string = shift ; my $decryp_data = $cipher->decrypt($string); $cipher = "" ; return $decryp_data ; } sub new_cipher { my $key = get_key(); my $cipher = Crypt::CBC->new( {'key' => "$key", 'cipher' => 'DES', 'iv' => '$KJh#(}q', 'regenerate_key' => 0, # default true 'padding' => 'space', 'prepend_iv' => 0 }); return $cipher; } sub get_key { my $getkeybox = $mw->DialogBox(-title=>"Set Encryption Key", -buttons=>["OK"] ); $getkeybox->add('Label', -anchor => 'w', -justify => 'left', -text => qq(Please enter your Encryption Key))->pa +ck(qw/-side top -anchor w/); my $keybox = $getkeybox->add('Scrolled', 'TextUndo', -height => '10' )->pack(qw/-side top -fill both -expand +1 -anchor w/); my $result = $getkeybox->show(); $key = $keybox->get(0.1, 'end') unless(undef $result); }


I'm very thankful of any and all help.

All the Best, Eoin...

If everything seems to be going well, you obviously don't know what the hell is going on.

Replies are listed 'Best First'.
Re: popup values in Tk
by pg (Canon) on Oct 19, 2003 at 16:40 UTC

    There is no problem with DialogBox, an it allows you to make up really complex dialogs.

    I attached a piece of code here, and it is a big chunk, but it is some real code I am using. It is highly OO'd. I believe that it shows you most of the things you want and how to deliver them in Tk.

    package OpenRemoteFile; use VisitedHosts; use Net::FTP; use Tk::DialogBox; use File::Temp qw/:POSIX/; use IO::Socket::INET; use Hash::Util (lock_keys); use strict; use warnings; sub new { my $self = {}; shift; $self->{PARENT_WIDGET} = shift; $self->{HOST} = undef; $self->{USER} = undef; $self->{PASSWD} = undef; $self->{VISITED_HOSTS} = new VisitedHosts; $self->{DIRECTORY} = undef; $self->{FILE} = undef; $self->{CURRENT_FTP_SESSION} = undef; $self->{DATA} = []; $self->{DEBUG} = 1; bless($self); return $self; } sub Show { my $self = shift; $self->{HOST} = undef; $self->{FILE} = undef; $self->clean(); $self->{CURRENT_FTP_SESSION} = undef; my $continueinue = 1; $continueinue = $self->host_dialog(); if ($continueinue) { $continueinue = $self->login_dialog(); } if ($continueinue) { $continueinue = $self->file_dialog(); } return $continueinue; } sub host_dialog { my $self = shift; my $continueinue = 1; my $host_first_try = 1; while (1) { my $host_dialog = $self->{PARENT_WIDGET}->DialogBox(-buttons = +> ["OK", "Cancel"], -title => +"Open Remote File"); my $instruction; if ($host_first_try) { $instruction = "Please specify host name: "; $host_first_try = 0; } else { $instruction = "Failed to connect, please try again: " } $host_dialog->add("Label", anchor => "w", text => $instruction) ->pack(fill => "x"); my $host_text = $host_dialog->add("Entry", width => 30) ->pack(); my $host_list = $host_dialog->add("Listbox", height => 5) ->pack(fill => "x"); $host_list->bind("<Double-Button-1>", sub { my $sel_index = $host_list->curselection +(); if (defined($sel_index)) { $host_text->delete("1.0", "end"); $host_text->insert("end", $host_list +->get($sel_index)); } }); my @visited_hosts = sort $self->{VISITED_HOSTS}->all_visited() +; foreach (@visited_hosts) { $host_list->insert("end", $_); } $host_text->focus(); if ($host_dialog->Show() eq "OK") { $self->{HOST} = $host_text->get(); last if ($self->{CURRENT_FTP_SESSION} = new Net::FTP($self +->{HOST})); } else { $continueinue = 0; last; } } return $continueinue; } sub login_dialog { my $self = shift; my $continueinue = 1; my $login_first_try = 1; my $visited; my $id; my $passwd; if ($visited = $self->{VISITED_HOSTS}->visited($self->{HOST})) { $id = $visited->userid(); $passwd = $visited->passwd(); $self->{CURRENT_FTP_SESSION}->login($id, $passwd); } else { while (1) { my $dialog = $main::self->{MAIN_WINDOW} ->DialogBox(-buttons => ["OK", "Ca +ncel"], -title => "Login"); my $instruction; if ($login_first_try) { $instruction = "Please provide id/passwd: "; $login_first_try = 0; } else { $instruction = "Failed to login, please try again: " } $dialog->add("Label", anchor => "w", text => $instruction) ->pack(fill => "x"); my $id_text = $dialog->add("Entry", width => 30) ->pack(); my $passwd_text = $dialog->add("Entry", show => "*", width => 30) ->pack(); $id_text->focus(); if ($dialog->Show() eq "OK") { $id = $id_text->get(); $passwd = $passwd_text->get(); if ($self->{CURRENT_FTP_SESSION}->login($id, $passwd)) + { $self->{DIRECTORY} = $self->{CURRENT_FTP_SESSION}- +>pwd(); if (!$visited) { $self->{VISITED_HOSTS}->add($self->{HOST}, $id +, $passwd); $self->{USER} = $id; $self->{PASSWD} = $passwd; } last; } } else { $continueinue = 0; last; } } } return $continueinue; } sub file_dialog { my $self = shift; my $dialog = $self->{PARENT_WIDGET} ->DialogBox(-buttons => ["OK", "Cancel"], -title => "Open File"); $dialog->add("Label", anchor => "w", text => "Host: $self->{HOST}") ->pack(fill => "x"); my $label = $dialog->add("Label", anchor => "w", textvariable => \$self->{DIRECTORY}) ->pack(fill => "x"); my $file_list = $dialog->add("Scrolled", "Listbox", -scrollbars => "e", height => 10, width => 40) ->pack(fill => "x"); $file_list->bind("<Double-Button-1>", sub { $self->display_file_list($file_list, $label) +; }); $label->configure("text", $self->{CURRENT_FTP_SESSION}->pwd()); $self->update_file_list($file_list); my $sel_file; if ($dialog->Show() eq "OK") { my $sel_index = $file_list->curselection(); print "\nsel_index = $sel_index\n"; if (defined($sel_index)) { $self->{FILE} = $file_list->get($sel_index); print $self->{FILE}; } if (defined($self->{FILE})) { $self->open_remote(); } } $self->{CURRENT_FTP_SESSION}->quit(); } sub update_file_list { my ($self, $file_list) = @_; my @files = sort($self->{CURRENT_FTP_SESSION}->ls()); $file_list->delete(0, "end"); $file_list->insert("end", ".."); for my $name (@files) { $file_list->insert("end", $name); } } sub display_file_list { my ($self, $file_list, $label) = @_; my $sel_index = $file_list->curselection(); if (defined($sel_index)) { my $sel = $file_list->get($sel_index); if ($self->{CURRENT_FTP_SESSION}->cwd($sel)) { $self->update_file_list($file_list); $self->{DIRECTORY} = $self->{CURRENT_FTP_SESSION}->pwd(); } else { $self->{FILE} = $sel; $self->{CURRENT_FTP_SESSION}->get($self->{FILE}); } } } sub host { my $self = shift; return $self->{HOST}; } sub directory { my $self = shift; return $self->{DIRECTORY}; } sub tmp_file { my $self = shift; return $self->{FILE}; } sub clean { my $self = shift; if (defined($self->{TMP_FILE})) { unlink($self->{TMP_FILE}); $self->{TMP_FILE} = undef; } } sub data { my $self = shift; return $self->{DATA}; } sub open_remote { my $self = shift; my $ftp = new Net::FTP($self->{HOST}, Debug => 1); $ftp->login("peip", "930612jg"); $ftp->cwd($self->{DIRECTORY}); my $data; open(LOCALFILE, ">", "abc") || die "failed"; print LOCALFILE "abcd1234"; print "==$self->{FILE}==\n"; $ftp->get($self->{FILE}, \*LOCALFILE); $ftp->quit(); close(LOCALFILE); print $data; @{$self->{DATA}} = split(/\n/, $data); =document my $continue = 1; my $ftp = new IO::Socket::INET(Proto => "tcp", PeerAddr => $self->{HOST}, PeerPort => 21, Timeout => 60, Reuse => 1); if (!$ftp) { $continue = 0; print "Failed to new control socket\n" if ($self->{DEBUG}); } if ($continue) { my $response = <$ftp>; print $response if ($self->{DEBUG}); $continue = 0 if ($response !~ /^220/); } if ($continue) { print $ftp "USER $self->{USER}\r\n"; my $response = <$ftp>; print $response if ($self->{DEBUG}); $continue = 0 if ($response !~ /^331/); } if ($continue) { print $ftp "PASS $self->{PASSWD}\r\n"; my $response = <$ftp>; print $response if ($self->{DEBUG}); $continue = 0 if ($response !~ /^230/); } if ($continue) { print $ftp "CWD $self->{DIRECTORY}\r\n"; my $response = <$ftp>; print $response if ($self->{DEBUG}); $continue = 0 if ($response !~ /^250/); } my $data_l; my $data; if ($continue) { $data_l = new IO::Socket::INET(Proto => "tcp", LocalPort => $ftp->sockport(), Listen => 1, Timeout => 60, Reuse => 1); if (!$data_l) { $continue = 0; print "Failed to new data socket\n" if ($self->{DEBUG}); } } if ($continue) { print $ftp "RETR $self->{FILE}\r\n"; $data = $data_l->accept(); close($data_l); if (!$data) { print "failed to accept data connection\n" if ($self->{DEB +UG}); $continue = 0; } else { my $response = <$ftp>; print $response if ($self->{DEBUG}); @{$self->{DATA}} = <$data>; close($data); $response = <$ftp>; print $response if ($self->{DEBUG}); } } if ($ftp) { print $ftp "QUIT\r\n"; my $response = <$ftp>; print $response if ($self->{DEBUG}); close($ftp); } =cut } 1;

      Thanks pg thats just what I needed to see. I think I got those problems sorted
      but I'm after uncovering new problems. I'm trying to

      • Set the encryption key using get_key() whether its envoked by new_cipher() or just the Set Encryption Key button in the main window. And store this key so new_cipher() doesn't ask for a new key, the only way to change it would be to click on the Set Encryption Key button in the main window.

      This doesn't seem to want to work new_cipher() doesn't envoke get_key() at all. And when new_cipher is run it returns an error of invalid key.(From the DES module) although the key has been created correctly(as far as I can see.) The $key is created at the start of the script and is accessible to all functions.(i.e. its public) in each of the functions I use $newkey  #(a new private var) for creating and setting the key.

      See the functions new_cipher() and get_key() below.

      sub new_cipher { my $newkey = get_key() if ($key eq ""); my $cipher = Crypt::CBC->new( {'key' => "$newkey", 'cipher' => 'DES', 'iv' => '$KJh#(}q', 'regenerate_key' => 0, # default tr +ue 'padding' => 'space', 'prepend_iv' => 0 }); return $cipher; } sub get_key { my $getkeybox = $mw->DialogBox(-title=>"Set Encryption Key", -buttons=>["Ok", "Cancel"] ); $getkeybox->add('Label', -anchor => 'w', -justify => 'left', -text => qq(Please enter your Encryption Key))->pa +ck(qw/-side top -anchor w/); my $keybox = $getkeybox->add('Entry', -takefocus => '1', -textvariable => "$key", )->pack(qw/-side top -fill both -expand 1 + -anchor w/); my $button = $getkeybox->Show(); my $newkey = pack("H16", $keybox->get) unless $button eq "Cancel"; $key = $newkey; return $newkey; }


      The error I get is:
      Tk::Error: Can't locate object method "TIEHANDLE" via package "" at cbc.pl line
      162.
      

      I get this error by clicking straight on the Encryption button which calls new_cipher() before get_key()!!
      I'm pretty puzzled. And would apprieciate any help you could give.


      All the Best, Eoin...

      If everything seems to be going well, you obviously don't know what the hell is going on.

        ##################UPDATE################

        The problems above have been fixed here
        use strict; use warnings; use Tk 800.000; use Tk::Frame; use Tk::TextUndo; use Tk::Menu; use Tk::Menubutton; use Tk::DialogBox; use Crypt::CBC; use Crypt::DES; my $key; my $mw = new MainWindow; $mw->geometry('800x600'); my $menu = $mw->Menu(-menuitems => &menubar_menuitems() ); $mw->configure(-menu => $menu); my $tpfrme = $mw->Frame; my $mdfrme = $mw->Frame(-height => '50'); my $bmfrme = $mw->Frame; my($text1) = $tpfrme->Scrolled('TextUndo', -height => '1', -width => '1', -scrollbars => 'osoe', ); my $encrypt_button = $mdfrme->Button(-text=>"Encrypt", -height=>'1', -command=>[\&OnEncrypt] ); my $get_key_button = $mdfrme->Button(-text=>"Set Encryption Key", -height=>'1', -command=>[\&get_key] ); my $decrypt_button = $mdfrme->Button(-text=>"Decrypt", -height=>'1', -command=>[\&OnDecrypt] ); my($text2) = $bmfrme->Scrolled('TextUndo', -height => '1', -width => '1', -scrollbars => 'osoe', ); $mw->bind('Tk::TextUndo', '<Control-Key-o>', sub { OnFileLoad(); } ); $mw->bind('Tk::TextUndo', '<Control-Key-s>', sub { OnFileSave(); } ); $mw->bind('<Control-Key-q>', sub { OnExit(); } ); $mw->bind('Tk::TextUndo', '<Control-Key-e>', sub { OnEncrypt(); } ); $mw->bind('Tk::TextUndo', '<Control-Key-d>', sub { OnDecrypt(); } ); $mw->bind('<Control-Key-a>', sub { OnAbout(); } ); $tpfrme ->pack(qw/-side top -fill both -expand 1 + /); $mdfrme ->pack(qw/-side top -fill both -expand 0 + /); $bmfrme ->pack(qw/-side bottom -fill both -expand 1 + /); $text1 ->pack(qw/-side top -fill both -expand 1 + /); $encrypt_button->pack(qw/-side left + /); $decrypt_button->pack(qw/-side right + /); $get_key_button->pack(qw/ + /); $text2 ->pack(qw/-side top -fill both -expand 1 + /); MainLoop; sub menubar_menuitems{ return [ map ['cascade', $_->[0], -tearoff=> 0, -menuitems => $_->[1]], ['~File', &file_menuitems() ], ['~Actions', &actions_menuitems()], ['~Help', &help_menuitems() ], ]; } sub file_menuitems { return [ [qw/command ~Open -accelerator Ctrl-o/, -command=>[\&OnFileLoad]], [qw/command ~Save -accelerator Ctrl-s/, -command=>[\&OnFileSave]], '', [qw/command ~Exit -accelerator Ctrl-q/, -command=>[\&OnExit]] ]; } sub actions_menuitems { return [ [qw/command ~Encrypt -accelerator Ctrl-e/, -command=>[\&OnEncrypt]], [qw/command ~Decrypt -accelerator Ctrl-d/, -command=>[\&OnDecrypt]], ]; } sub help_menuitems { return [ [qw/command ~About -accelerator Ctrl-a/, -command=>[\&OnAbout] ] ]; } sub OnFileLoad { $text1->FileLoadPopup(); } sub OnFileSave { $text2->FileSaveAsPopup(); } sub OnExit { exit 0; } sub OnEncrypt { my $text = $text1->get(0.1, 'end') ; my $encrypted_data = encrypt_string($text) ; my $widget = $text2->Subwidget("text") ; tie *STDOUT, ref $widget, $widget; print $encrypted_data; } sub OnDecrypt { my $text = $text1->get(0.1, 'end') ; my $decrypted_data = decrypt_string($text) ; my $widget = $text2->Subwidget("text") ; tie *STDOUT, ref $widget, $widget; print $decrypted_data; } sub encrypt_string { my $cipher = new_cipher() ; my $string = shift ; my $encryp_data = $cipher->encrypt($string); $cipher = "" ; return $encryp_data ; } sub decrypt_string { my $cipher = new_cipher() ; my $string = shift ; my $decryp_data = $cipher->decrypt($string); $cipher = "" ; return $decryp_data ; } sub new_cipher { my $usedkey; if(defined $key) { $usedkey = $key; } elsif(undef $key) { $key = get_key(); $usedkey = $key; } else { return $key } my $cipher = Crypt::CBC->new( {'key' => "$usedkey", 'cipher' => 'DES', 'iv' => '$KJh#(}q', 'regenerate_key' => 0, # default tr +ue 'padding' => 'space', 'prepend_iv' => 0 }); return $cipher; } sub get_key { my $getkeybox = $mw->DialogBox(-title=>"Set Encryption Key", -buttons=>["Ok", "Cancel"] ); $getkeybox->add('Label', -anchor => 'w', -justify => 'left', -text => qq(Please enter your Encryption Key))->pa +ck(qw/-side top -anchor w/); my $keybox = $getkeybox->add('Entry', -takefocus => '1', -textvariable => "$key", )->pack(qw/-side top -fill both -expand 1 + -anchor w/); my $button = $getkeybox->Show(); $key = pack("H16", $keybox->get) unless $button eq "Cancel"; print $key; if($button eq "Cancel"){ if(defined $key) { return $key } elsif(undef $key) { return $key } } return $key; }
        Thanks for the help pg.

        Eoin.
Re: popup values in Tk
by ptkdb (Monk) on Oct 19, 2003 at 18:59 UTC
  • This code needs alot more comments.
  • Your problems are only described in the most general of terms. Example: "taking of text from the top textbox". what exactly is the problem? Are you not not getting the text? Is is some how garbled; getting the wrong text; error messages?? What?
  • I don't recognize the methods 'FileLoadPopup', or 'FileSaveAsPopup' that are being called on your Tk::Text objects, and they don't appear to be in the man pages, but I may be behind revision of Tk.
  • When you do any one of your bound actions are you getting a stack trace of any kind?
Re: popup values in Tk
by PodMaster (Abbot) on Oct 19, 2003 at 16:23 UTC
    I see you're dealing with a Tk::TextUndo. Taking a quick peek at the docs, I see it says "see also" Tk::Text (if you look inside TextUndo you'll see use base qw(Tk::Text);). A Tk::Text widget has many methods available to it, and they're mostly documented (if they're not, look at the source or try perltk.org). Also, the Tk widget demo contains lots of examples.

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.