App-USBKeyCopyCon
view release on metacpan or search on metacpan
lib/App/USBKeyCopyCon.pm view on Meta::CPAN
return if $> == 0;
my $path = $self->find_command('gksudo') || $self->find_command('sudo');
if($path) {
$self->sudo_path($path);
return;
}
die "You must either run this program as root or install sudo\n";
}
sub disable_automount {
my $self = shift;
my $state = `gconftool-2 --get $gconf_automount_path 2>/dev/null`;
return if !defined($state) or $? != 0;
chomp($state);
$self->automount_state($state);
system("gconftool-2 --type bool --set $gconf_automount_path false 2>/dev/null");
}
sub restore_automount {
my $self = shift;
my $state = $self->automount_state or return;
system("gconftool-2 --type bool --set $gconf_automount_path $state 2>/dev/null");
}
sub build_ui {
my $self = shift;
my $window = Gtk2::Window->new;
$self->app_win($window);
$window->signal_connect(destroy => sub { Gtk2->main_quit; });
$window->set_title('USB Key Copying Console');
$window->set_default_size(850, 250);
my $vbox = Gtk2::VBox->new(FALSE);
$vbox->pack_start($self->build_menu, FALSE, FALSE, 0);
$vbox->pack_start($self->build_filters, FALSE, FALSE, 0);
$vbox->pack_start(Gtk2::HSeparator->new, FALSE, TRUE, 0);
$vbox->pack_start($self->build_key_rack, FALSE, FALSE, 0);
$vbox->pack_start($self->build_console, TRUE, TRUE, 0);
$window->add($vbox);
$window->show_all;
}
sub init_dbus_watcher {
my $self = shift;
my $bus = Net::DBus::GLib->system;
my $hal = $bus->get_service("org.freedesktop.Hal");
my $manager = $hal->get_object(
"/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager"
);
$self->hal($manager);
$manager->connect_to_signal('DeviceAdded', sub {
$self->hal_device_added(@_);
});
$manager->connect_to_signal('DeviceRemoved', sub {
$self->hal_device_removed(@_);
});
}
sub require_master_key {
my $self = shift;
if(not $self->reader_script) {
return $self->ready_to_write;
}
$self->current_state('MASTER-WAIT');
$self->disable_filter_inputs;
$self->say("Waiting for USB master key ...\n");
}
sub hal_device_added {
my($self, $target_udi) = @_;
return unless $target_udi =~ /storage/;
my $prop = $self->hal_device_properties($target_udi) or return;
if($self->current_state eq 'MASTER-WAIT') {
$self->start_master_read($prop);
return;
}
elsif($self->current_state eq 'COPYING') {
if($self->match_device_filter($prop)) {
$self->say("Device added: $prop->{block_device}\n");
}
else {
$self->say(" - device ignored\n");
$prop->{ignored} = 1;
}
#$self->say(Dumper($prop));
$self->add_key_to_rack($prop);
}
}
sub hal_device_removed {
my($self, $target_udi) = @_;
return unless $target_udi =~ /storage/;
my $state = $self->current_state;
if($state eq 'MASTER-COPIED') {
if($self->master_info->{udi} eq $target_udi) {
$self->ready_to_write;
}
}
lib/App/USBKeyCopyCon.pm view on Meta::CPAN
sub { $self->on_copier_pipe_read(@_); },
$key_info->{udi}
);
$key_info->{pid} = $pid;
$key_info->{fh} = $rd;
$key_info->{output} = '';
$key_info->{status} = 0;
}
sub on_copier_pipe_read {
my($self, $fd, $cond, $udi) = @_;
my $key_info = $self->current_keys->{$udi} or return FALSE;
my $fh = $key_info->{fh};
my $buffer;
if(sysread($fh, $buffer, 100000)) {
$key_info->{output} .= $buffer;
if($key_info->{output} =~ m/\A.*^\{(\d+)\/(\d+)\}/sm) {
$self->update_key_progress($udi, int(9 * $1 / $2));
}
return TRUE;
}
close($fh);
delete $key_info->{fh};
return FALSE;
}
sub remove_key_from_rack {
my($self, $udi) = @_;
my $key_info = delete $self->current_keys->{$udi} or return;
$self->key_rack->remove($key_info->{widget});
return;
}
sub update_key_progress {
my($self, $udi, $status) = @_;
$status = -1 if !defined $status or $status < -1 or $status > 10;
my $key_info = $self->current_keys->{$udi} or return;
$key_info->{status} = $status;
$key_info->{icon_widget}->set_from_pixbuf(
App::USBKeyCopyCon::Chrome::usb_icon($status)
);
}
sub on_menu_file_new {
my $self = shift;
$self->require_master_key;
}
sub on_menu_file_quit {
my $self = shift;
# TODO: check for work in progress
# TODO: check if desktop automount should be re-enabled
Gtk2->main_quit;
}
sub on_menu_edit_preferences {
my $self = shift;
$self->say("Edit>Preferences - not implemented\n");
}
sub on_menu_help_about {
my $self = shift;
my $dialog = Gtk2::Dialog->new(
'About: usb-key-copy-con',
$self->app_win,
[qw/modal destroy-with-parent/],
'gtk-close' => 'ok',
);
$dialog->set_default_size (90, 80);
my $panel = Gtk2::VBox->new(FALSE, 12);
my $title = Gtk2::Label->new;
$title->set_markup("<span font_desc='sans 20'> USB Key Copy Console </span>");
$title->set_selectable(TRUE);
$panel->pack_start($title, FALSE, FALSE, 10);
my $version = Gtk2::Label->new;
$version->set_markup("<span font_desc='sans 16'>Version: $VERSION</span>");
$version->set_selectable(TRUE);
$panel->pack_start($version, FALSE, FALSE, 0);
my $author = Gtk2::Label->new;
my $detail = '(c) 2009 Grant McLean <grantm@cpan.org>';
$author->set_markup(" <span font_desc='sans 10'>$detail</span> ");
$author->set_selectable(TRUE);
$panel->pack_start($author, FALSE, FALSE, 10);
$dialog->vbox->pack_start($panel, FALSE, FALSE, 4);
$dialog->show_all;
$dialog->run;
$dialog->destroy;
}
sub build_menu {
my $self = shift;
foreach my $item (@menu_entries) {
if(exists $item->[5]) {
my $action = 'on_menu_' . $item->[5];
$item->[5] = sub { $self->$action(@_) };
}
}
my $actions = Gtk2::ActionGroup->new("Actions");
$actions->add_actions(\@menu_entries, undef);
lib/App/USBKeyCopyCon.pm view on Meta::CPAN
$self->restore_automount;
$self->clean_temp_dir;
}
1;
__END__
=head1 ATTRIBUTES
The application object has the following attributes (with correspondingly named
accessor methods):
=over 4
=item app_win
The main Gtk2::Window object.
=item automount_state
Stores the enabled state ('true' or 'false') of the GNOME/Nautilus media
automount option. The function will be disabled on startup and this value will
be restored on exit.
=item capacity_combo
The Gtk2::ComboBox object for the device filter 'Capacity' drop-down menu.
=item capacity_entry
The Gtk2::Entry object for the device filter 'Capacity' text entry box.
=item console
The Gtk2::TextView object used for writing output messages.
=item current_keys
A hash for tracking which (non-master) keys are currently inserted and what
stage each copy process is at. The hash key is the device 'UDI' and the value
is a hash of device dtails .
=item current_state
Used to control which mode the application is in:
MASTER-WAIT waiting for the user to insert the master key
MASTER-COPYING waiting for the master key 'reader' script to complete
MASTER-COPIED waiting for the user to remove the master key
COPYING waiting for the user to insert blank keys
=item exit_status
Used by a SIGCHLD handler to track the exit status of the copy scripts. The
key is a process ID and the value is the exist status returned by C<wait>.
=item hal
The DBus object ('org.freedesktop.Hal.Manager') from which device add/remove
events are received.
=item key_rack
The Gtk2::HBox object containing the widgets representing currently inserted
keys.
=item master_info
A hash of device details for the 'master' USB key.
=item master_root
The path to the temp directory containing the copy of the master key.
=item mount_dir
The path to the temp directory containing temporary mount points.
The volume label read from the master key and to be applied to the copies.
=item options
A hash of option name/value pairs passed in from comman-line arguments by the
wrapper script.
=item profiles
A hash of details of known profiles. Used to populate the profile drop-down
menu on the confirm master key dialog.
=item selected_profile
The name of the copying profile which will be used to select reader/writer
scripts.
=item selected_sound
Pathname of the currently selected sound file, to be played when copying is
complete.
=item sudo_path
If the script was run by a non-root user and sudo is available, this string
will be populated with the pathname of either C<gksudo> or C<sudo>. When
running the read/writer scripts the string will be prepended onto the commands.
=item temp_root
The temp directory selected by the user. The application will create a
subdirectory for the copy of the master key and for temporary mount points.
=item vendor_combo
The Gtk2::ComboBox object for the device filter 'Vendor' drop-down menu.
=item vendor_entry
The Gtk2::Entry object for the device filter 'Vendor' text entry box.
( run in 1.835 second using v1.01-cache-2.11-cpan-13bb782fe5a )