/[pcsclite]/trunk/pcsc-tools/trunk/gscriptor
ViewVC logotype

Contents of /trunk/pcsc-tools/trunk/gscriptor

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3659 - (hide annotations) (download)
Sat Nov 8 17:07:02 2003 UTC (9 years, 6 months ago) by rousseau
File size: 24633 byte(s)
simplify status word printing
1 rousseau 3510 #!/usr/bin/perl -w
2 lvictor 3504
3 rousseau 3510 # gscriptor: GTK interface to send APDU commands to a smart card
4 rousseau 3520 # Copyright (C) 2001 Lionel Victor, Ludovic Rousseau
5 rousseau 3626 # 2002-2003 Ludovic Rousseau
6 rousseau 3510 #
7     # This program is free software; you can redistribute it and/or modify
8     # it under the terms of the GNU General Public License as published by
9     # the Free Software Foundation; either version 2 of the License, or
10     # (at your option) any later version.
11     #
12     # This program is distributed in the hope that it will be useful,
13     # but WITHOUT ANY WARRANTY; without even the implied warranty of
14     # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     # GNU General Public License for more details.
16     #
17     # You should have received a copy of the GNU General Public License
18     # along with this program; if not, write to the Free Software
19     # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20    
21 lvictor 3504 # gscriptor uses libgtk-perl, please make sure it is correctly installed
22     # on your system
23    
24 rousseau 3659 # $Id: gscriptor,v 1.23 2003-11-08 17:07:02 rousseau Exp $
25 rousseau 3626
26 lvictor 3505 use strict;
27    
28 lvictor 3504 use Gtk;
29     use File::Basename;
30     use Carp;
31 rousseau 3626 use Chipcard::PCSC;
32     use Chipcard::PCSC::Card;
33 lvictor 3504
34     init Gtk;
35     set_locale Gtk;
36    
37     my $strAppName = "gscriptor";
38     my $strConfigFileName = "$ENV{HOME}/.$strAppName";
39     my @ResultStruct;
40     my %hConfig;
41    
42     # PCSC related variables
43 rousseau 3626 my $hContext = new Chipcard::PCSC ();
44     die ("Can't create the Chipcard::PCSC object: $Chipcard::PCSC::errno\n") unless (defined $hContext);
45     my $hCard = new Chipcard::PCSC::Card ($hContext);
46     die ("Can't create the Chipcard::PCSC::Card object: $Chipcard::PCSC::errno\n") unless (defined $hContext);
47 lvictor 3504
48     ############################### create widgets ###############################
49     my $wndMain = new Gtk::Window ("toplevel");
50     my $txtScript = new Gtk::Text ();
51     my $txtResult = new Gtk::Text ();
52     my $rdbASCII = new Gtk::RadioButton("ASCII");
53     my $rdbHex = new Gtk::RadioButton("Hex", $rdbASCII);
54     my $chkWrap = new Gtk::CheckButton ("Wrap lines");
55     my $btnRun = new Gtk::Button ("Run");
56     my $txtStatus = new Gtk::Entry();
57    
58    
59     ############################## arrange widgets ###############################
60     # arrange_widgets () is used to arrange widgets in the windows.
61     # It allows to conveniently allocate temporary variables for the various
62     # containers and the scrollbars, as well as the menu.
63     # This function also sets some basic properties of the different
64     # widgets used... configuration is therefore grouped in a single place.
65     sub arrange_widgets () {
66     $wndMain->set_title ("$strAppName");
67    
68     $txtScript->set_editable(1);
69     $txtScript->set_word_wrap(1);
70    
71     $txtResult->set_word_wrap(1);
72    
73     $txtStatus->set_sensitive(0);
74     $txtStatus->set_editable(0);
75    
76     $chkWrap->set_active(1);
77     $rdbHex->set_active(1);
78    
79     # create and bind toolbars
80     my $vscScript = new Gtk::VScrollbar ($txtScript->vadj);
81     my $vscResult = new Gtk::VScrollbar ($txtResult->vadj);
82    
83     # create and set tooltips
84     my $tipScript = new Gtk::Tooltips();
85     my $tipResult = new Gtk::Tooltips();
86     my $tipASCII = new Gtk::Tooltips();
87     my $tipHex = new Gtk::Tooltips();
88     my $tipRun = new Gtk::Tooltips();
89     my $tipWrap = new Gtk::Tooltips();
90     $tipScript->set_tip ($txtScript, "list of APDUs to exchange");
91     $tipResult->set_tip ($txtResult, "result window");
92     $tipASCII->set_tip ($rdbASCII, "show ASCII data");
93     $tipHex->set_tip ($rdbHex, "show hexadecimal data");
94     $tipRun->set_tip ($btnRun, "run the current script");
95 rousseau 3519 $tipWrap->set_tip ($chkWrap, "wrap long lines");
96 lvictor 3504
97     # create and set the menu with the accel_table
98     my @menu_items = ({ path => '/_File',
99     type => '<Branch>' },
100     { path => '/File/_New',
101     accelerator => '<control>N',
102     callback => \&NewScriptFile },
103     { path => '/File/_Open',
104     accelerator => '<control>O',
105     callback => \&LoadScriptFile },
106     { path => '/File/_Save',
107     accelerator => '<control>S',
108     callback => \&SaveScriptFile },
109     { path => '/File/Save _As',
110     callback => \&SaveAsScriptFile },
111     { path => '/File/sep',
112     type => '<Separator>' },
113 rousseau 3517 { path => '/File/_Quit',
114     accelerator => '<control>Q',
115 lvictor 3504 callback => \&CloseAppWindow },
116    
117 lvictor 3505 { path => '/R_eader',
118 lvictor 3504 type => '<Branch>' },
119     { path => '/Reader/_Connect',
120     accelerator => '<control>C',
121     callback => \&ConnectDefaultReader },
122     { path => '/Reader/Reco_nnect',
123 lvictor 3509 accelerator => '<control>R',
124 lvictor 3504 callback => \&ReconnectDefaultReader },
125     { path => '/Reader/_Disconnect',
126     accelerator => '<control>D',
127     callback => \&DisconnectDefaultReader },
128     { path => '/Reader/sep',
129     type => '<Separator>' },
130 lvictor 3505 { path => '/Reader/_Status...',
131     callback => \&DefaultReaderStatus },
132    
133 lvictor 3509 { path => '/Ru_n',
134 lvictor 3505 type => '<Branch>' },
135     { path => '/Run/_Run Script',
136 lvictor 3509 accelerator => '<control>n',
137 lvictor 3504 callback => \&RunScript },
138 lvictor 3505 { path => '/Run/C_lear Result Area',
139 lvictor 3504 accelerator => '<control>L',
140     callback => \&ClearResult },
141    
142     { path => '/_Settings',
143     type => '<Branch>' },
144     { path => '/Settings/Reader',
145     callback => \&ReaderConfig },
146    
147     { path => '/_Help',
148     type => '<LastBranch>' },
149     { path => '/_Help/About',
150     callback => \&Help });
151    
152     my $accel_group = new Gtk::AccelGroup();
153     my $item_factory = new Gtk::ItemFactory( 'Gtk::MenuBar', '<main>', $accel_group);
154     $item_factory->create_items( @menu_items );
155     $wndMain->add_accel_group( $accel_group );
156    
157     # create and arrange box containers
158     my $vbxMainBox = new Gtk::VBox(0,3);
159 rousseau 3658 my $hbxScriptBox = new Gtk::HBox(0,3);
160     my $vbxScriptBox = new Gtk::VBox(0,10);
161     my $hbxResultBox = new Gtk::HBox(0,3);
162     my $vbxResultBox = new Gtk::VBox(0,3);
163 lvictor 3504
164     $hbxScriptBox->add($txtScript);
165     $hbxScriptBox->pack_end($vscScript, 0, 0, 0);
166     $vbxScriptBox->add($hbxScriptBox);
167     $vbxScriptBox->pack_end($btnRun, 0, 0, 0);
168     $vbxScriptBox->pack_end($chkWrap, 0, 0, 0);
169     $vbxScriptBox->set_border_width(5);
170     $hbxResultBox->add($txtResult);
171     $hbxResultBox->pack_end($vscResult, 0, 0, 0);
172     $vbxResultBox->add($hbxResultBox);
173     $vbxResultBox->pack_start($rdbASCII, 0, 0, 0);
174     $vbxResultBox->pack_start($rdbHex, 0, 0, 0);
175     $vbxResultBox->set_border_width(5);
176    
177    
178     # create and fill frame containers
179     my $frmScript = new Gtk::Frame ("Script");
180     my $frmResult = new Gtk::Frame ("Result");
181     $frmScript->set_border_width(5);
182     $frmScript->add ($vbxScriptBox);
183     $frmResult->set_border_width(5);
184     $frmResult->add ($vbxResultBox);
185    
186 rousseau 3658 my $hpaned = new Gtk::HPaned;
187     $hpaned->border_width(5);
188 lvictor 3504
189     my $hbxBox = new Gtk::HBox (0,10);
190 rousseau 3658 $hpaned->add1($frmScript);
191     $hpaned->add2($frmResult);
192     $hbxBox->add($hpaned);
193 lvictor 3504 $vbxMainBox->pack_start ($item_factory->get_widget( '<main>' ), 0, 0, 0);
194     $vbxMainBox->add ($hbxBox);
195     $vbxMainBox->pack_end ($txtStatus, 0, 0, 0);
196     $vbxMainBox->show_all();
197     $wndMain->add($vbxMainBox);
198     }
199    
200 rousseau 3658 # Connect widgets together
201 lvictor 3504 $chkWrap->signal_connect('toggled', sub { $txtScript->set_line_wrap($chkWrap->active); } );
202     $wndMain->signal_connect ("delete_event", \&CloseAppWindow);
203     $btnRun->signal_connect ("clicked", \&RunScript);
204     $rdbASCII->signal_connect('toggled', \&RefreshResult);
205     $rdbHex->signal_connect('toggled', \&RefreshResult);
206    
207     ReadConfigFile();
208     arrange_widgets();
209    
210     ############################### create widgets ###############################
211    
212     $txtStatus->set_text ("welcome to the $strAppName application !!! - not connected");
213    
214     # Show up everything as we should be ready by now
215     $wndMain->show_all();
216    
217     if (exists $hConfig{'script'}) {
218     unless (ReadScriptFile ($hConfig{'script'})) {
219 lvictor 3507 MessageBox ("Can not open $hConfig{'script'}: $!", ['OK']);
220 lvictor 3504 delete $hConfig{'script'};
221     }
222     }
223    
224    
225     main Gtk;
226     die ("The Gtk event loop failed to start resulting in abnormal program termination...\n");
227    
228     ######################### application engine follows #########################
229    
230     sub MessageBox {
231     my $strMessage = shift;
232 lvictor 3512 my $strTitle = shift unless ref ($_[0]);
233 lvictor 3504 my @ButtonDescr = @_;
234    
235     my $refCurButtonDescr;
236 rousseau 3514 my $last_button;
237 lvictor 3504
238     # Choose a nice title to our message box
239     $strTitle = $strAppName unless $strTitle;
240 rousseau 3515 @ButtonDescr = ["OK"] unless @ButtonDescr;
241 lvictor 3504
242     my $dlgDialog = new Gtk::Dialog ();
243     my $hbxButtonBox = new Gtk::HBox (0,3);
244     my $hbxTextBox = new Gtk::HBox (0,3);
245    
246     # build up all the buttons and associate callbacks
247     foreach $refCurButtonDescr (reverse @ButtonDescr) {
248     croak ("invalid button name") unless scalar ($$refCurButtonDescr[0]);
249     $$refCurButtonDescr[1] = sub { $dlgDialog->destroy(); } if $#$refCurButtonDescr == 0;
250 lvictor 3507 warn ("button named '$$refCurButtonDescr[0]' has an invalid callback: '$$refCurButtonDescr[1]'")
251 lvictor 3504 unless ref ($$refCurButtonDescr[1]);
252    
253 lvictor 3512 # Each button is constructed from its label
254 lvictor 3504 my $btnTmpButton = new Gtk::Button($$refCurButtonDescr[0]);
255 lvictor 3523 $btnTmpButton->can_default(1);
256 lvictor 3512
257     # A mouse click on the button triggers a call to its embedded
258     # callback then destroys the dialog box
259 lvictor 3504 $btnTmpButton->signal_connect ("clicked", sub { &{$$refCurButtonDescr[1]}; $dlgDialog->destroy(); });
260     $hbxButtonBox->pack_end($btnTmpButton, 0, 0, 10);
261 rousseau 3514
262     $last_button = $btnTmpButton;
263 lvictor 3504 }
264    
265     $dlgDialog->action_area->pack_start($hbxButtonBox, 1, 1, 0 );
266     my $label = new Gtk::Label($strMessage);
267     $hbxTextBox->pack_start($label, 0, 0, 30);
268     $dlgDialog->vbox->add ($hbxTextBox);
269    
270 rousseau 3514 # the last button is the default one
271     $last_button->grab_default();
272    
273 lvictor 3504 # Finally show up everything
274     $dlgDialog->set_policy (0, 0, 1);
275     $dlgDialog->set_default_size (0,0);
276     $dlgDialog->set_title ($strTitle);
277     $dlgDialog->set_modal(1);
278     $dlgDialog->show_all();
279     }
280    
281     sub ReaderConfig {
282     my $dlgReaderConfig = new Gtk::Dialog ();
283     my $txtReader = new Gtk::Label ("Reader");
284     my $cboReaders = new Gtk::Combo();
285     my $rdbT0 = new Gtk::RadioButton("T=0");
286     my $rdbT1 = new Gtk::RadioButton("T=1", $rdbT0);
287     my $rdbRAW = new Gtk::RadioButton("T=RAW", $rdbT0);
288 lvictor 3513 my $txtProtocol = new Gtk::Label ("Protocol");
289 lvictor 3504
290     # This sub adjusts the content of $hConfig with the selected protocol
291     my $subProtocol = sub {
292 rousseau 3626 $hConfig{'protocol'} = $Chipcard::PCSC::SCARD_PROTOCOL_RAW if ($rdbRAW->active);
293     $hConfig{'protocol'} = $Chipcard::PCSC::SCARD_PROTOCOL_T0 if ($rdbT0->active);
294     $hConfig{'protocol'} = $Chipcard::PCSC::SCARD_PROTOCOL_T1 if ($rdbT1->active);
295 lvictor 3504 };
296     $rdbT0->signal_connect ('toggled', $subProtocol);
297     $rdbT1->signal_connect ('toggled', $subProtocol);
298     $rdbRAW->signal_connect('toggled', $subProtocol);
299    
300     my $btnOK = new Gtk::Button ("OK");
301     $btnOK->signal_connect( "clicked", sub {
302     $hConfig{'reader'} = $cboReaders->entry->get_text();
303 rousseau 3626 $hCard->Disconnect($Chipcard::PCSC::SCARD_UNPOWER_CARD);
304 lvictor 3504 $dlgReaderConfig->destroy();
305     });
306 lvictor 3523 $btnOK->can_default(1);
307 lvictor 3504
308     my $btnCancel = new Gtk::Button ("Cancel");
309     $btnCancel->signal_connect( "clicked", sub {
310     $dlgReaderConfig->destroy();
311     });
312 lvictor 3523 $btnCancel->can_default(1);
313 lvictor 3504
314     my $hbxReaderBox = new Gtk::HBox (0,10);
315     my $hbxButtonBox = new Gtk::HBox (0,3);
316 rousseau 3516 my $hbxStatusBox = new Gtk::Table (3,2,1);
317 lvictor 3504
318     $hbxReaderBox->pack_start ($txtReader, 0, 0, 10);
319     $hbxReaderBox->pack_start ($cboReaders, 1, 1, 10);
320    
321     $hbxButtonBox->pack_end($btnCancel, 0, 0, 10);
322     $hbxButtonBox->pack_end($btnOK, 0, 0, 10);
323    
324 lvictor 3512 # Select the last prefered protocol if any
325     if (defined $hConfig {'protocol'}) {
326 rousseau 3626 $rdbT0->set_active(1) if ($hConfig {'protocol'} == $Chipcard::PCSC::SCARD_PROTOCOL_T0);
327     $rdbT1->set_active(1) if ($hConfig {'protocol'} == $Chipcard::PCSC::SCARD_PROTOCOL_T1);
328     $rdbRAW->set_active(1) if ($hConfig {'protocol'} == $Chipcard::PCSC::SCARD_PROTOCOL_RAW);
329 lvictor 3512 }
330 lvictor 3504
331 lvictor 3513 $hbxStatusBox->attach_defaults ($txtProtocol, 0, 1, 0, 1);
332     $hbxStatusBox->attach_defaults ($rdbT0, 1, 2, 0, 1);
333     $hbxStatusBox->attach_defaults ($rdbT1, 1, 2, 1, 2);
334     $hbxStatusBox->attach_defaults ($rdbRAW, 1, 2, 2, 3);
335 lvictor 3504
336     $cboReaders->set_popdown_strings ($hContext->ListReaders ());
337     $cboReaders->set_case_sensitive(1);
338     $cboReaders->set_value_in_list(1, 0);
339     # We select the last reader if available
340     if (exists $hConfig{'reader'}) {
341     $cboReaders->entry->set_text($hConfig{'reader'});
342     }
343    
344     $dlgReaderConfig->action_area->pack_start($hbxButtonBox, 1, 1, 0 );
345     $dlgReaderConfig->vbox->add ($hbxReaderBox);
346     $dlgReaderConfig->vbox->add (new Gtk::HSeparator());
347     $dlgReaderConfig->vbox->add ($hbxStatusBox);
348    
349 rousseau 3514 # the OK button is the default one
350     $btnOK->grab_default();
351    
352 lvictor 3504 $dlgReaderConfig->set_policy (0, 0, 1);
353     $dlgReaderConfig->set_default_size (0,0);
354     $dlgReaderConfig->set_modal(1);
355     $dlgReaderConfig->show_all();
356     }
357    
358     sub ReadConfigFile {
359     if (-f $strConfigFileName) {
360 lvictor 3507 die ("Can't open $strConfigFileName for reading: $!\n") unless (open (FILE, "<$strConfigFileName"));
361 lvictor 3504 while (<FILE>) {
362     chomp;
363     next if /^#/;
364     next if /^\s*$/;
365 lvictor 3505 if (/^\s*(\S+)\s*=\s*\'(.*)\'$/) {
366 lvictor 3504 $hConfig{$1} = $2;
367     } else {
368     print STDERR "Error while parsing $strConfigFileName\n\t'$_'\n";
369     }
370     }
371     close (FILE);
372     } else {
373     print STDERR "Couldn't read from $strConfigFileName. Using default configuration\n";
374     }
375     }
376    
377     sub WriteConfigFile {
378     my $strTmpKey;
379    
380 lvictor 3507 die ("Can't open $strConfigFileName for writing: $!\n") unless (open (FILE, ">$strConfigFileName"));
381 lvictor 3504 print FILE "# This file is automatically generated\n# Do not edit unless you know what you are doing\n\n";
382     foreach $strTmpKey (keys %hConfig) {
383 lvictor 3505 print FILE "$strTmpKey = \'$hConfig{$strTmpKey}\'\n";
384 lvictor 3504 }
385     close (FILE);
386     }
387    
388     sub ReadScriptFile {
389     my $strScriptFileName = shift;
390     my $strBaseFileName = basename ($strScriptFileName);
391    
392     return 0 unless open (FILE, "<$strScriptFileName");
393     $txtScript->freeze();
394     $txtScript->delete_text (0,-1);
395 rousseau 3517 while (<FILE>)
396     {
397 rousseau 3518 $txtScript->insert_text ($_, $txtScript->get_length);
398 rousseau 3517 }
399 lvictor 3504 $txtScript->thaw();
400     close (FILE);
401     # Upon succesfull completion, we also set the window title as well
402     # as the current ScriptfileName in the configuration hash
403     $hConfig{'script'} = $strScriptFileName;
404     $wndMain->set_title ("$strAppName - <$strBaseFileName>");
405     return 1;
406     }
407    
408     sub WriteScriptFile {
409     my $strScriptFileName = shift;
410     my $strBaseFileName = basename ($strScriptFileName);
411    
412     return 0 unless open (FILE, ">$strScriptFileName");
413     print FILE $txtScript->get_chars (0,-1);
414     close (FILE);
415     # Upon successfull completion, we also set the window title as well
416     # as the current ScriptfileName in the configuration hash
417     $hConfig{'script'} = $strScriptFileName;
418     $wndMain->set_title ("$strAppName - <$strBaseFileName>");
419     return 1;
420     }
421    
422     sub NewScriptFile {
423     if ($txtScript->get_length()) {
424     # That call to MessageBox will connect the OK button with a callback
425     # that actually erase the script
426     MessageBox(
427     "The current work will be lost !\nAre you sure you want to continue ?",
428     ["OK", sub { EraseCurrentScript(); } ],
429     ["CANCEL"]
430     );
431     }
432     }
433    
434     sub EraseCurrentScript {
435     $txtScript->delete_text (0,-1);
436     $wndMain->set_title ("$strAppName");
437     delete $hConfig{'script'};
438     }
439    
440     sub SaveScriptFile {
441     my ($widget) = @_;
442     if (exists $hConfig{'script'}) {
443     WriteScriptFile ($hConfig{'script'});
444     } else {
445     SaveAsScriptFile ($widget);
446     }
447     }
448    
449     sub SaveAsScriptFile {
450     my ($widget) = @_;
451    
452     my $file_dialog = new Gtk::FileSelection( "Save File" );
453     $file_dialog->ok_button->signal_connect( "clicked", sub {
454     my $file = $file_dialog->get_filename();
455    
456     if (-d $file) {
457 lvictor 3507 MessageBox ("Can't open $file: file is a directory", ['OK']);
458 lvictor 3504 } else {
459 lvictor 3507 MessageBox ("Can't open $file: $!", ['OK']) unless WriteScriptFile ($file);
460 lvictor 3504 }
461     $file_dialog->destroy();
462     });
463     $file_dialog->cancel_button->signal_connect( "clicked", sub { $file_dialog->destroy(); });
464     if (exists $hConfig{'script'}) {
465     $file_dialog->set_filename(dirname($hConfig{'script'}))
466     }
467    
468     $file_dialog->show();
469     }
470    
471     sub LoadScriptFile {
472     if ($txtScript->get_length()) {
473     MessageBox(
474     "The current work will be lost !\nAre you sure you want to continue ?",
475     ["OK", \&LoadScript],
476     ["CANCEL"]
477     );
478     } else {
479     LoadScript();
480     }
481     }
482    
483     sub LoadScript {
484     my $file_dialog = new Gtk::FileSelection( "Load File" );
485     $file_dialog->ok_button->signal_connect( "clicked", sub {
486     my $file = $file_dialog->get_filename();
487    
488     if (-d $file) {
489 lvictor 3507 MessageBox ("Can't open $file: file is a directory", ['OK']);
490 lvictor 3504 } else {
491 lvictor 3507 MessageBox ("Can't open $file: $!", ['OK']) unless ReadScriptFile ($file);
492 lvictor 3504 }
493     $file_dialog->destroy();
494     });
495     $file_dialog->cancel_button->signal_connect( "clicked", sub { $file_dialog->destroy(); });
496     if (exists $hConfig{'script'}) {
497 lvictor 3505 $file_dialog->set_filename(dirname($hConfig{'script'})."/");
498 lvictor 3504 }
499    
500     $file_dialog->show();
501     }
502    
503     sub ClearResult {
504     $txtResult->delete_text (0, -1);
505     @ResultStruct = ();
506     }
507    
508     sub RefreshResult {
509     my $tmpLine;
510     my $tmp_value;
511    
512     $txtResult->freeze();
513     $txtResult->delete_text (0, -1);
514     foreach $tmpLine (@ResultStruct) {
515     if (ref $tmpLine) {
516     foreach $tmp_value (@$tmpLine) {
517     if ($rdbHex->active) {
518 rousseau 3518 $txtResult->insert_text (sprintf ("%02X ", $tmp_value), $txtResult->get_length);
519 lvictor 3504 } else {
520 lvictor 3505 # TODO: enhance filtering of non-printable chars
521 lvictor 3509 # TODO: how can we use array_to_ascii here ??? maybe
522     # enhence the function so it can directly receive
523     # ranges of chars to ignore optionally ?
524 lvictor 3505 if (($tmp_value > 0x20) && ($tmp_value < 0x80)) {
525 rousseau 3518 $txtResult->insert_text (chr ($tmp_value), $txtResult->get_length);
526 lvictor 3505 } else {
527 rousseau 3518 $txtResult->insert_text ('.', $txtResult->get_length);
528 lvictor 3505 }
529 lvictor 3504 }
530     }
531 rousseau 3518 $txtResult->insert_text ("\n", $txtResult->get_length);
532 lvictor 3504 } else {
533 rousseau 3518 $txtResult->insert_text ($tmpLine, $txtResult->get_length);
534 lvictor 3504 }
535     }
536     $txtResult->thaw();
537     }
538    
539     sub ConnectDefaultReader {
540 lvictor 3505 if (exists $hConfig{'reader'} && !($hConfig{'reader'} eq '')) {
541 lvictor 3504 if (defined $hCard->{hCard}) {
542     MessageBox (
543     "The card is already connected...\nDo you want to reconnect ?",
544     ['OK', \&ReconnectDefaultReader],
545     ['CANCEL']
546     );
547     } else {
548 rousseau 3626 $hCard->Connect ($hConfig{'reader'}, $Chipcard::PCSC::SCARD_SHARE_EXCLUSIVE, $hConfig{'protocol'});
549 lvictor 3504 if (defined $hCard->{hCard}) {
550     $txtStatus->set_text ("Connected to '$hConfig{'reader'}'");
551     } else {
552 rousseau 3626 MessageBox ("Can not connect to the reader named '$hConfig{'reader'}':\n$Chipcard::PCSC::errno", ['OK'])
553 lvictor 3504 };
554     }
555     } else {
556     MessageBox ("No default reader has been configured\nPlease make sure you have configured a reader first", ['OK']);
557     }
558     }
559    
560     sub ReconnectDefaultReader {
561     if (defined $hCard->{hCard}) {
562 rousseau 3626 $hCard->Reconnect ($Chipcard::PCSC::SCARD_SHARE_EXCLUSIVE, $hConfig{'protocol'}, $Chipcard::PCSC::SCARD_RESET_CARD);
563 lvictor 3504 if (defined $hCard->{hCard}) {
564     $txtStatus->set_text ("Connected to '$hConfig{'reader'}'");
565     } else {
566 rousseau 3626 MessageBox ("Can not reconnect to the reader named '$hConfig{'reader'}':\n$Chipcard::PCSC::errno", ['OK'])
567 lvictor 3504 };
568     } else {
569 lvictor 3505 # we just propose to connect but do not call Reconnect()
570     # afterwards that would be quite useless
571 rousseau 3626 MessageBox ("The Chipcard::PCSC:Card object is not connected...\n Do you want to connect ?",
572 lvictor 3505 ['OK', sub {ConnectDefaultReader();}],
573     ['CANCEL']);
574 lvictor 3504 }
575     }
576    
577     sub DisconnectDefaultReader {
578     if (defined $hCard->{hCard}) {
579 rousseau 3626 $hCard->Disconnect($Chipcard::PCSC::SCARD_UNPOWER_CARD);
580 lvictor 3504 if (defined $hCard->{hCard}) {
581 rousseau 3626 MessageBox ("Can not disconnect from the reader named '$hConfig{'reader'}':\n$Chipcard::PCSC::errno", ['OK']);
582 lvictor 3504 } else {
583     $txtStatus->set_text ("not connected");
584     };
585     } else {
586 rousseau 3626 MessageBox ("The Chipcard::PCSC::Card object is not connected !", ['OK']);
587 lvictor 3504 }
588     }
589    
590     sub DefaultReaderStatus {
591 lvictor 3505 if (defined $hCard->{hCard}) {
592     my @StatusResult = $hCard->Status();
593     if (defined $StatusResult[0]) {
594 lvictor 3506 #TODO This stinks can't I rewrite it so it looks better&shorter
595     my $tmpVal = 0;
596 lvictor 3505
597 lvictor 3506 my $MessageString = "You are connected to reader $StatusResult[0].\n";
598     $MessageString .= "Card status (". sprintf ("0x%04X",$StatusResult[1]) ."): ";
599    
600     # Verbosely describes the Card Status (powered, inserted, etc...
601 rousseau 3626 if ($StatusResult[1] & $Chipcard::PCSC::SCARD_UNKNOWN) {
602 lvictor 3506 if ($tmpVal) { $MessageString .= ", "; } ++$tmpVal;
603     $MessageString .= "'Unknown state'";
604     }
605 rousseau 3626 if ($StatusResult[1] & $Chipcard::PCSC::SCARD_ABSENT) {
606 lvictor 3506 if ($tmpVal) { $MessageString .= ", "; } ++$tmpVal;
607     $MessageString .= "Absent";
608     }
609 rousseau 3626 if ($StatusResult[1] & $Chipcard::PCSC::SCARD_PRESENT) {
610 lvictor 3506 if ($tmpVal) { $MessageString .= ", "; } ++$tmpVal;
611     $MessageString .= "Present";
612     }
613 rousseau 3626 if ($StatusResult[1] & $Chipcard::PCSC::SCARD_SWALLOWED) {
614 lvictor 3506 if ($tmpVal) { $MessageString .= ", "; } ++$tmpVal;
615     $MessageString .= "Swallowed";
616     }
617 rousseau 3626 if ($StatusResult[1] & $Chipcard::PCSC::SCARD_POWERED) {
618 lvictor 3506 if ($tmpVal) { $MessageString .= ", "; } ++$tmpVal;
619     $MessageString .= "Powered";
620     }
621 rousseau 3626 if ($StatusResult[1] & $Chipcard::PCSC::SCARD_NEGOTIABLE) {
622 lvictor 3506 if ($tmpVal) { $MessageString .= ", "; } ++$tmpVal;
623     $MessageString .= "'PTS is negotiable'";
624     }
625 rousseau 3626 if ($StatusResult[1] & $Chipcard::PCSC::SCARD_SPECIFIC) {
626 lvictor 3506 if ($tmpVal) { $MessageString .= ", "; } ++$tmpVal;
627     $MessageString .= "'PTS has been set'";
628     }
629    
630     # Verbosely describes the currently active protocol
631     $MessageString .= ".\nThe active protocol (".sprintf ("0x%04X", $StatusResult[2]).") is ";
632 rousseau 3626 if (($StatusResult[2] & $Chipcard::PCSC::SCARD_PROTOCOL_T0)) {
633 lvictor 3506 $MessageString .= "T=0 ";
634 rousseau 3626 } elsif (($StatusResult[2] & $Chipcard::PCSC::SCARD_PROTOCOL_T1)) {
635 lvictor 3506 $MessageString .= "T=1 ";
636 rousseau 3626 } elsif (($StatusResult[2] & $Chipcard::PCSC::SCARD_PROTOCOL_RAW)) {
637 lvictor 3506 $MessageString .= "RAW ";
638     } else {
639     $MessageString .= "unknown";
640     }
641    
642     # Displays the ATR (if available)
643     $MessageString .= ".\nThe ATR is ";
644     if (defined $StatusResult[3]) {
645     foreach $tmpVal (@{$StatusResult[3]}) { $MessageString .= sprintf ("%02X ", $tmpVal); }
646     } else {
647     $MessageString .= "not available";
648     }
649 lvictor 3505 MessageBox ($MessageString, ['OK']);
650     } else {
651 rousseau 3626 MessageBox ("Can not retrieve reader status:\n$Chipcard::PCSC::errno", ['OK'])
652 lvictor 3505 }
653     } else {
654     MessageBox ("The reader is not connected...\n Do you want to connect ?",
655     ['OK', sub {ConnectDefaultReader(); if (defined $hCard->{hCard}) {DefaultReaderStatus();}}],
656     ['CANCEL']);
657     }
658 lvictor 3504 }
659    
660     sub RunScript {
661 lvictor 3505 if (defined $hCard->{hCard}) {
662 lvictor 3504 my @tmpCommandArray = split /\n/, $txtScript->get_chars (0,-1);
663     my $raCurrentResult;
664     my $nIndex;
665    
666     push @ResultStruct, "Beginning script execution...\n\n";
667     foreach $_ (@tmpCommandArray) {
668     # this variable has to be inside the loop as we store a
669     # reference to it in the result struct... it has to be
670     # unique for each command line
671 lvictor 3509 my $raCurrentCommand;
672 lvictor 3504
673     # Skip blank lines and comments
674     next if /^\s*$/;
675     next if /^#/;
676    
677 rousseau 3559 if (/reset/i) {
678 lvictor 3509 push @ResultStruct, "[Reset]\n\n";
679     ReconnectDefaultReader();
680     next;
681     }
682    
683 lvictor 3504 # Extract bytes from the ascii string
684 rousseau 3626 $raCurrentCommand = Chipcard::PCSC::ascii_to_array($_);
685 lvictor 3504
686 lvictor 3509 # push them in the Display structure
687 lvictor 3507 push @ResultStruct, "Sending: ";
688 lvictor 3509 push @ResultStruct, $raCurrentCommand;
689 lvictor 3504
690 lvictor 3509 # Transmit them to the card
691     $raCurrentResult = $hCard->Transmit ($raCurrentCommand);
692 lvictor 3504 if (ref $raCurrentResult) {
693 lvictor 3507 push @ResultStruct, "Received: ";
694 lvictor 3504 push @ResultStruct, $raCurrentResult;
695 rousseau 3659 push @ResultStruct, Chipcard::PCSC::Card::ISO7816Error(Chipcard::PCSC::array_to_ascii($raCurrentResult)), "\n\n";
696 lvictor 3504 } else {
697 rousseau 3626 MessageBox ("Transmit failed: $Chipcard::PCSC::errno\nStopping script execution", ['OK']);
698     push @ResultStruct, "\nErrors During Script Execution: $Chipcard::PCSC::errno\n";
699 lvictor 3504 last;
700     }
701     }
702     push @ResultStruct, "Script was executed without error...\n";
703     } else {
704 rousseau 3626 MessageBox ("The Chipcard::PCSC::Card object is not connected !\nDo you want to connect ?",
705 lvictor 3505 ['OK', sub {ConnectDefaultReader(); if (defined $hCard->{hCard}) {RunScript();}}],
706     ['CANCEL']);
707 lvictor 3504 }
708     RefreshResult();
709     }
710    
711     sub CloseAppWindow {
712     undef $hCard;
713     undef $hContext;
714     WriteConfigFile();
715     Gtk->exit(0);
716     }
717    
718     sub Help {
719     MessageBox ("
720 rousseau 3520 $strAppName is coded by Lionel VICTOR, (C) 2001.
721 rousseau 3628 and debugged by Ludovic ROUSSEAU, (C) 2001-2003.
722 lvictor 3504
723 rousseau 3520 $strAppName is a small application written in Perl.
724 lvictor 3504 It basically demonstrates how easy it is to develop a
725 rousseau 3520 quick working prototype that uses smartcards in Perl.
726 lvictor 3504 ",
727     ['OK']
728     );
729     }
730    
731     # End of File #
732 rousseau 3510

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.5