App-Parcimonie-0.8/0000700000175200017520000000000012253322520014725 5ustar intrigeriintrigeriApp-Parcimonie-0.8/share/0000700000175200017520000000000012253322520016027 5ustar intrigeriintrigeriApp-Parcimonie-0.8/share/applications/0000700000175200017520000000000012253322520020515 5ustar intrigeriintrigeriApp-Parcimonie-0.8/share/applications/parcimonie-applet.desktop0000600000175200017520000000104412253322520025522 0ustar intrigeriintrigeri[Desktop Entry] Version=1.0 Type=Application Categories= Name=Parcimonie applet # short description, usually shown in parentheses after Name GenericName=Privacy-friendly helper to refresh a GnuPG keyring (applet) # tooltip, also shown in the Applications at startup preferences Comment=Privacy-friendly helper to refresh a GnuPG keyring (applet) # If it's a name only, it looks for "name.[png|xpm]" file in # $XDG_DATA_DIRS/icons and /usr/share/pixmaps. # An absolute file path is also supported. Icon=parcimonie-applet Exec=parcimonie-applet App-Parcimonie-0.8/share/applications/parcimonie.desktop0000600000175200017520000000077512253322520024251 0ustar intrigeriintrigeri[Desktop Entry] Version=1.0 Type=Application Categories= Name=Parcimonie # short description, usually shown in parentheses after Name GenericName=Privacy-friendly helper to refresh a GnuPG keyring # tooltip, also shown in the Applications at startup preferences Comment=Privacy-friendly helper to refresh a GnuPG keyring # If it's a name only, it looks for "name.[png|xpm]" file in # $XDG_DATA_DIRS/icons and /usr/share/pixmaps. # An absolute file path is also supported. Icon=parcimonie Exec=parcimonie App-Parcimonie-0.8/parcimonie-torified-gpg.1.markdown0000600000175200017520000000060412253322520023336 0ustar intrigeriintrigeri% PARCIMONIE-TORIFIED-GPG(1) parcimonie-torified-gpg user manual % parcimonie and this manual page were written by intrigeri % July 21, 2011 NAME ==== parcimonie-torified-gpg - torified gpg wrapper for parcimonie SYNOPSIS ======== parcimonie-torified-gpg GPG_ARGS Calls the `torsocks gpg` command, passing it the arguments received on the initial command line. App-Parcimonie-0.8/lib/0000700000175200017520000000000012253322520015473 5ustar intrigeriintrigeriApp-Parcimonie-0.8/lib/App/0000700000175200017520000000000012253322520016213 5ustar intrigeriintrigeriApp-Parcimonie-0.8/lib/App/Parcimonie/0000700000175200017520000000000012253322520020301 5ustar intrigeriintrigeriApp-Parcimonie-0.8/lib/App/Parcimonie/Role/0000700000175200017520000000000012253322520021202 5ustar intrigeriintrigeriApp-Parcimonie-0.8/lib/App/Parcimonie/Role/HasEncoding.pm0000600000175200017520000000131412253322520023723 0ustar intrigeriintrigeri=head1 NAME App::Parcimonie::Role::HasEncoding - role to provide an Encode::Encoding objet for the codeset being used =head1 SYNOPSIS use Moo; with 'App::Parcimonie::Role::HasEncoding'; sub foo { $self->encoding->decode("bla") } See App::Parcimonie::Daemon for a real-life usage example. =cut package App::Parcimonie::Role::HasEncoding; use Encode qw{find_encoding}; use Moo::Role; use MooX::late; with 'App::Parcimonie::Role::HasCodeset'; has 'encoding' => ( isa => 'Encode::Encoding', is => 'ro', lazy_build => 1, ); sub _build_encoding { my $self = shift; find_encoding($self->codeset); } no Moo::Role; 1; # End of App::Parcimonie::Role::HasEncoding App-Parcimonie-0.8/lib/App/Parcimonie/Role/HasCodeset.pm0000600000175200017520000000140612253322520023565 0ustar intrigeriintrigeri=head1 NAME App::Parcimonie::Role::HasCodeset - role to get the codeset being used =head1 SYNOPSIS See App::Parcimonie::Role::HasEncoding source code. =cut package App::Parcimonie::Role::HasCodeset; use Try::Tiny; use Moo::Role; # Moo::Role exports all methods declared after it's "use"'d use MooX::late; has 'codeset' => ( isa => 'Str', is => 'ro', lazy_build => 1, ); sub _build_codeset { my $codeset; try { require I18N::Langinfo; I18N::Langinfo->import(qw(langinfo CODESET)); $codeset = langinfo(CODESET()); } catch { die "No default character code set configured.\nPlease fix your locale settings."; }; $codeset; } no Moo::Role; 1; # End of App::Parcimonie::Role::HasCodeset App-Parcimonie-0.8/lib/App/Parcimonie/GnuPG/0000700000175200017520000000000012253322520021261 5ustar intrigeriintrigeriApp-Parcimonie-0.8/lib/App/Parcimonie/GnuPG/Interface.pm0000600000175200017520000000415512253322520023526 0ustar intrigeriintrigeri=head1 NAME App::Parcimonie::GnuPG::Interface - parcimonie's GnuPG::Interface subclass =head1 SYNOPSIS Have a look to App::Parcimonie::Daemon for a full-blown real life usage example. =cut package App::Parcimonie::GnuPG::Interface; use Moo; use MooX::late; extends 'GnuPG::Interface'; use namespace::autoclean; use Carp; use File::Which qw{which}; has 'already_torified' => ( isa => 'Bool', is => 'rw', required => 0, default => sub { 0; }, ); after 'BUILD' => sub { my $self = shift; unless ($self->already_torified) { foreach my $prog (qw{torsocks parcimonie-torified-gpg}) { defined which($prog) or croak "$prog not found in \$PATH"; } $self->call('parcimonie-torified-gpg'); } }; sub get_public_keys_hex { my $self = shift; my @saved_extra_args = @{$self->options->extra_args()}; $self->options->push_extra_args( '--with-colons', '--fixed-list-mode', '--with-fingerprint', '--with-fingerprint', '--with-key-data', ); my $stdin = IO::Handle->new(); my $stdout = IO::Handle->new(); my $handles = GnuPG::Handles->new( stdin => $stdin, stdout => $stdout, ); my $pid = $self->wrap_call( handles => $handles, commands => ['--list-public-keys'], command_args => [], ); my @returned_keys; my $current_primary_key; my $current_signed_item; my $current_key; my $current_pubkey = 0; while (<$stdout>) { my $line = $_; chomp $line; my @fields = split ':', $line; my $record_type = $fields[0]; if ( $record_type eq 'pub' ) { $current_pubkey = 1; } elsif ( $record_type eq 'fpr' && $current_pubkey ) { next unless @fields > 9; push @returned_keys, $fields[9]; $current_pubkey = 0; } else { $current_pubkey = 0; } } waitpid $pid, 0; $self->options->extra_args(\@saved_extra_args); return @returned_keys; } no Moo; 1; # End of App::Parcimonie::GnuPG::Interface App-Parcimonie-0.8/lib/App/Parcimonie/DBus/0000700000175200017520000000000012253322520021136 5ustar intrigeriintrigeriApp-Parcimonie-0.8/lib/App/Parcimonie/DBus/Object.pm0000600000175200017520000000123412253322520022704 0ustar intrigeriintrigeri=head1 NAME App::Parcimonie::DBus::Object - provide parcimonie's D-Bus service and interface =cut package App::Parcimonie::DBus::Object; use strict; use warnings; # We're going to be a DBus object use base qw{Net::DBus::Object}; # Specify the main interface provided by our object use Net::DBus::Exporter qw{org.parcimonie.daemon}; sub new { my $class = shift; my $service = shift; my $self = $class->SUPER::new($service, "/org/parcimonie/daemon/object"); bless $self, $class; return $self; } # args: keyid dbus_signal("FetchBegin", ["string"]); # args: keyid, success, error message dbus_signal("FetchEnd", ["string", "bool", "string"]); App-Parcimonie-0.8/lib/App/Parcimonie/Applet.pm0000600000175200017520000002017512253322520022073 0ustar intrigeriintrigeri=head1 NAME App::Parcimonie::Applet - systray applet object monitoring parcimonie's activities =for Pod::Coverage TRUE FALSE =cut package App::Parcimonie::Applet; use Moo; use MooX::late; with 'App::Parcimonie::Role::HasEncoding'; use 5.10.0; use Encode; use Glib qw{TRUE FALSE}; use Gtk3 qw{-init}; use Net::DBus; use Net::DBus::GLib; use Locale::gettext; use POSIX; setlocale(LC_MESSAGES, ""); textdomain("parcimonie-applet"); use Try::Tiny; =head1 ATTRIBUTES =cut has 'verbose' => ( documentation => q{Use this option to get more output.}, isa => 'Bool', is => 'ro', default => sub { exists $ENV{DEBUG} && defined $ENV{DEBUG} && $ENV{DEBUG} }, ); has 'icon_display_time' => ( documentation => q{How many seconds the trayicon is displayed after key fetch.}, isa => 'Int', is => 'ro', default => 10, ); has 'dbus_object' => ( isa => 'Net::DBus::RemoteObject', is => 'rw', predicate => 'has_dbus_object', ); has 'statusicon' => ( isa => 'Gtk3::StatusIcon', is => 'rw', lazy_build => 1, ); has 'monitorwin' => ( isa => 'Gtk3::Window', is => 'rw', lazy_build => 1, ); has 'logbuffer' => ( isa => 'Gtk3::TextBuffer', is => 'rw', lazy_build => 1, ); =head1 CONSTRUCTORS AND BUILDERS =cut sub BUILD { my $self = shift; $self->build_ui; }; sub _build_monitorwin { my $self = shift; my $win = Gtk3::Window->new('toplevel'); $win->set_title($self->encoding->decode(gettext('parcimonie log viewer'))); $win->set_keep_above(1); $win->set_position('center'); $win->signal_connect('delete_event' => sub { $win->hide; 1; }); my $textview = Gtk3::TextView->new_with_buffer($self->logbuffer); $textview->set_editable(FALSE); $textview->set_cursor_visible(FALSE); $textview->set_wrap_mode('word'); my $text_desc = Pango::FontDescription->new; $text_desc->set_family('Monospace'); $textview->modify_font($text_desc); my $scrolled_win = Gtk3::ScrolledWindow->new; $scrolled_win->set_policy('automatic', 'automatic'); $scrolled_win->add($textview); $win->add($scrolled_win); $win->set_default_size(800, 400); $win->set_size_request(100, 100); $win->signal_connect('key-press-event' => sub { my $twin = shift; my $event = shift; $win->hide if $event->key->{keyval} == Gtk3::Gdk::keyval_from_name('Escape'); }); return $win; } sub _build_logbuffer { my $self = shift; Gtk3::TextBuffer->new; } sub _build_statusicon { my $self = shift; my $icon = Gtk3::StatusIcon->new; $icon->set_visible(FALSE); $icon->set_from_stock('gtk-media-pause'); my $menu = Gtk3::Menu->new; my $mlog = Gtk3::MenuItem->new_with_mnemonic($self->encoding->decode(gettext('View log'))); $mlog->signal_connect('activate' => sub { $self->monitorwin->show_all }); my $mexit = Gtk3::MenuItem->new_with_mnemonic($self->encoding->decode(gettext('Exit'))); $mexit->signal_connect('activate' => sub { Gtk3->main_quit; }); my $mabout = Gtk3::MenuItem->new_with_mnemonic($self->encoding->decode(gettext('About'))); $mabout->signal_connect('activate' => sub { Gtk3->show_about_dialog( $self->monitorwin, 'program-name' => 'Parcimonie applet', 'license' => q{This program is free software; you can redistribute it and/or modify it under the terms of either: a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" which comes with Perl. }, 'wrap-license' => 1, 'website' => 'https://gaffer.ptitcanardnoir.org/intrigeri/code/parcimonie/', )}); $menu->append($mlog); $menu->append(Gtk3::SeparatorMenuItem->new); $menu->append($mexit); $menu->append(Gtk3::SeparatorMenuItem->new); $menu->append($mabout); $icon->signal_connect('popup-menu', sub { my ($ticon, $button, $time) = @_; my ($x, $y, $push) = Gtk3::StatusIcon::position_menu($menu, $ticon); $menu->show_all; $menu->popup(undef, undef, sub {($x, $y,$push)}, undef, $button, $time); }); $icon->signal_connect('button-press-event' => sub { my $ticon = shift; my $event = shift; return unless $event->button == 1; if ($self->monitorwin->get_visible) { $self->monitorwin->hide; } else { $self->monitorwin->show_all; } }); return $icon; } =head1 METHODS =cut sub debug { my $self = shift; my $mesg = shift; say STDERR $self->encoding->encode($mesg) if $self->verbose; } sub fatal { my $self = shift; my $mesg = shift; my $exit_code = shift; say STDERR $self->encoding->encode($mesg); exit($exit_code); } sub run { my $self = shift; for (1..30) { last if $self->dbus_connect; my $sleep = $_ * $_; warn("Cannot reach the daemon's D-Bus service. ", "Let' wait $sleep seconds before retrying."); sleep($sleep); } $self->fatal("Could not reach the parcimonie daemon's D-Bus service.", 16) unless $self->has_dbus_object; $self->debug("Connected to the daemon's D-Bus service."); $self->init_dbus_watcher; $self->debug("Entering main Gtk3 loop."); Gtk3->main; } sub build_ui { my $self = shift; $self->statusicon->set_visible(TRUE); } sub dbus_connect { my $self = shift; try { my $bus = Net::DBus::GLib->session; my $service = $bus->get_service("org.parcimonie.daemon"); my $object = $service->get_object( "/org/parcimonie/daemon/object", "org.parcimonie.daemon" ); $self->dbus_object($object); return 1; } catch { $self->debug("Could not connect to parcimonie daemon's D-Bus service."); return 0; }; } sub init_dbus_watcher { my $self = shift; $self->dbus_object->connect_to_signal("FetchBegin", sub { $self->signal_fetch_begin_cb(@_); }); $self->dbus_object->connect_to_signal("FetchEnd", sub { $self->signal_fetch_end_cb(@_); }); } sub append_mesg { my $self = shift; my $mesg = shift; my $buffer = $self->logbuffer; $buffer->insert($buffer->get_end_iter, $mesg . "\n", -1); } sub signal_fetch_begin_cb { my $self = shift; my $keyid = shift; # TRANSLATORS: OpenPGP key id my $mesg = $self->encoding->decode( sprintf(gettext('Fetching key %s...'), $keyid) ); $self->debug($mesg); $self->statusicon->set_from_stock('gtk-refresh'); $self->statusicon->set_tooltip_text($mesg); $self->append_mesg($mesg); $self->statusicon->set_visible(TRUE); } sub signal_fetch_end_cb { my $self = shift; my $keyid = shift; my $success = shift; my $gpgmesg = shift; $gpgmesg = $self->encoding->decode($gpgmesg); my $mesg = $success ? sprintf( $self->encoding->decode( # TRANSLATORS: OpenPGP key id gettext('Successfully fetched key %s.') ), $keyid) : sprintf( $self->encoding->decode( # TRANSLATORS: OpenPGP key id, error message gettext('Failed to fetch key %s: %s.') ), $keyid, $gpgmesg ); my $new_pixmap = $success ? 'gtk-yes' : 'gtk-no'; $self->debug($mesg); $self->statusicon->set_from_stock($new_pixmap); $self->statusicon->set_tooltip_text($mesg); $self->append_mesg($mesg); $self->statusicon->set_visible(TRUE); Glib::Timeout->add( $self->icon_display_time * 1000, sub { $self->now_resting; } ); } sub now_resting { my $self = shift; $self->statusicon->set_from_stock('gtk-media-pause'); $self->statusicon->set_tooltip_text($self->encoding->decode( gettext('Having a rest.') )); $self->statusicon->set_visible(TRUE); # return false so that the Glib::Timeout stops looping return; } 1; App-Parcimonie-0.8/lib/App/Parcimonie/Daemon.pm0000600000175200017520000002010712253322520022044 0ustar intrigeriintrigeri=head1 NAME App::Parcimonie::Daemon - parcimonie daemon class =head1 SYNOPSIS Have a look to bin/parcimonie for a full-blown real life usage example. =cut package App::Parcimonie::Daemon; use Moo; use MooX::late; with 'App::Parcimonie::Role::HasEncoding'; use MooX::Options; use 5.10.1; use namespace::autoclean; use App::Parcimonie; use App::Parcimonie::DBus::Object; use Encode; use English qw{-no_match_vars}; use File::Spec; use List::MoreUtils qw{any}; use Net::DBus; use Net::DBus::Reactor; use Net::DBus::Service; use Net::DBus::Test::MockObject; use Tie::Cache; use Time::Duration::Parse qw(parse_duration); use Try::Tiny; use Type::Utils qw{declare as where coerce from}; use Types::Path::Tiny qw{Dir}; use Types::Standard qw{Str Num}; =head1 TYPES =cut my $DurationInSeconds = declare as Num, where { $_ > 0 }; coerce $DurationInSeconds, from Str, sub { parse_duration($_) }; =head1 ATTRIBUTES =cut option 'verbose' => ( documentation => q{Use this option to get more output.}, isa => 'Bool', is => 'ro', default => 0 ); option 'gnupg_homedir' => ( documentation => q{GnuPG homedir.}, isa => Dir, is => 'ro', format => 's', coerce => Dir->coercion, ); option 'gnupg_extra_args' => ( documentation => q{Extra argument passed to GnuPG. Use this option once per needed argument.}, cmd_flag => 'gnupg-extra-arg', isa => 'ArrayRef[Str]', is => 'ro', default => sub { [] }, format => 's@', ); has 'gnupg_options' => ( isa => 'HashRef', is => 'ro', lazy_build => 1, ); option 'average_lapse_time' => ( documentation => q{Average lapse time between two key fetches. Can be expressed in any way understood by Time::Duration::Parse.}, isa => $DurationInSeconds, is => 'ro', predicate => 'has_average_lapse_time', format => 's', coerce => $DurationInSeconds->coercion, ); option 'minimum_lapse_time' => ( documentation => q{Minimum lapse time between two key fetches. Can be expressed in any way understood by Time::Duration::Parse. Defaults to 600 seconds.}, isa => $DurationInSeconds, is => 'ro', default => sub { 600 }, predicate => 'has_minimum_lapse_time', format => 's', coerce => $DurationInSeconds->coercion, ); has 'last_try' => ( documentation => q{In-memory LRU buffer storing the result of last key fetch attempts}, isa => 'HashRef', is => 'rw', default => sub { my %last_try; tie %last_try, 'Tie::Cache', { MaxCount => 1000 }; return \%last_try; }, ); has 'iterate_id' => ( isa => 'Int', is => 'rw', ); has 'dbus_object' => ( isa => 'Object', is => 'rw', default => sub { my ($bus, $service); if ($ENV{HARNESS_ACTIVE}) { $bus = Net::DBus->test; $service = $bus->export_service("org.parcimonie.daemon"); Net::DBus::Test::MockObject->new($service, "/org/parcimonie/daemon/object"); } else { $bus = Net::DBus->session; $service = $bus->export_service("org.parcimonie.daemon"); App::Parcimonie::DBus::Object->new($service); } }, ); option 'gnupg_already_torified' => ( documentation => q{gpg is already torified somehow (e.g. gpg.conf or firewall)}, isa => 'Bool', is => 'ro', required => 0, default => sub { 0; }, ); =head1 METHODS =cut =head2 BUILD Post-constructor. =cut sub BUILD { my $self = shift; $self->keyserver_defined_on_command_line or checkGpgHasDefinedKeyserver($self->gnupg_options); } =head2 run Run the daemon infinite loop. =cut sub run { my $self = shift; my $opt = shift; my $args = shift; my $reactor = Net::DBus::Reactor->main(); my $initial_sleep_time = 1 * 1000; $self->iterate_id( $reactor->add_timeout( $initial_sleep_time, Net::DBus::Callback->new(method => sub { my $next_sleep_time = $self->iterate; # at definition time, the ->add_timeout return value is not known yet; # it's stored in the iterate_id attribute # => use it only once it's been computed. if (defined $self->iterate_id) { $self->debug(sprintf( "Will now sleep %i seconds.", $next_sleep_time )); $reactor->toggle_timeout( $self->iterate_id, 1, $next_sleep_time * 1000 ); } }) ) ); $reactor->run(); }; sub debug { my $self = shift; my $msg = shift; say STDERR $self->encoding->encode($msg) if $self->verbose; } sub fatal { my $self = shift; my $msg = shift; my $exit_code = shift; say STDERR $self->encoding->encode($msg); exit($exit_code); } sub _build_gnupg_options { my $self = shift; my %opts; $opts{homedir} = $self->gnupg_homedir if defined $self->gnupg_homedir; $opts{extra_args} = $self->gnupg_extra_args if defined $self->gnupg_extra_args; return \%opts; } =head2 keyserver_defined_on_command_line Return true iff a keyserver was passed on the command-line via --gnupg-extra-arg. =cut sub keyserver_defined_on_command_line { my $self = shift; any { $_ =~ m{ \A # starts with [-] [-] keyserver # literal --keyserver, followed by [ =] # a space or an equal sign [^\n]+ # followed by anything but a newline }xms } @{$self->gnupg_extra_args}; } sub tryRecvKey { my $self = shift; my $keyid = shift; my $gpg_output; my $gpg_error; $self->debug(sprintf("tryRecvKey: trying to fetch %s", $keyid)); $self->dbus_object->emit_signal("FetchBegin", $keyid); try { $gpg_output = gpgRecvKeys( [ $keyid ], $self->gnupg_options, already_torified => $self->gnupg_already_torified, ); } catch { $gpg_error = $_; }; $gpg_output ||= ''; my $success = 0; if (defined $gpg_error) { warn $self->encoding->encode($gpg_error); } else { $self->debug($gpg_output); $success = 1; $gpg_error = ''; } $self->set_last_try( $keyid => { success => $success, msg => $gpg_error } ); $self->dbus_object->emit_signal("FetchEnd", $keyid, $success, $gpg_error); } sub next_sleep_time { my $self = shift; my $num_public_keys = shift; my $average_lapse_time = $self->has_average_lapse_time ? $self->average_lapse_time : averageLapseTime($num_public_keys); $self->debug(sprintf('Using %s seconds as average sleep time.', $average_lapse_time )); my $next_sleep_time = rand(2 * $average_lapse_time); if ($next_sleep_time < $self->minimum_lapse_time) { $next_sleep_time = $self->minimum_lapse_time; } return $next_sleep_time; } =head2 iterate Arg: long PGP key id (Str). Returns next sleep time (seconds). =cut sub iterate { my $self = shift; my $default_sleep_time = 600; my @public_keys = gpgPublicKeys( $self->gnupg_options, already_torified => $self->gnupg_already_torified, ); unless (@public_keys) { warn "No public key was found."; return $default_sleep_time ; } my $next_sleep_time = $self->next_sleep_time(scalar(@public_keys)); my ( $keyid ) = pickRandomItems(1, @public_keys); # allow the GC to free some memory undef(@public_keys); $self->tryRecvKey($keyid); return $next_sleep_time; } sub set_last_try { my $self = shift; my $keyid = shift; my $result = shift; $self->last_try->{$keyid} = $result; } no Moo; 1; # End of App::Parcimonie::Daemon App-Parcimonie-0.8/lib/App/Parcimonie.pm0000600000175200017520000001107112253322520020641 0ustar intrigeriintrigeripackage App::Parcimonie; use warnings; use strict; use App::Parcimonie::GnuPG::Interface; use Carp; use Clone qw{clone}; use Config::General qw/ParseConfig/; use Encode; use English qw/-no_match_vars/; use File::HomeDir; use List::MoreUtils qw/uniq/; use List::Util qw/shuffle/; use Path::Class; use Try::Tiny; use Exporter; our @ISA = qw(Exporter); =head1 NAME App::Parcimonie - tools for the parcimonie program =head1 SYNOPSIS See bin/parcimonie :) =head1 EXPORT =cut our @EXPORT = qw/pickRandomItems gpgPublicKeys gpgRecvKeys checkGpgHasDefinedKeyserver averageLapseTime/; my $codeset; try { require I18N::Langinfo; I18N::Langinfo->import(qw(langinfo CODESET)); $codeset = langinfo(CODESET()); } catch { croak "No default character code set configured.\nPlease fix your locale settings."; }; =head1 SUBROUTINES =head2 pickRandomItems(N, @list) Returns a list of N unique items picked at random from the input list. =cut sub pickRandomItems { my $n = shift; my @randomized_pool = shuffle(uniq(@_)); defined $n or croak "pickRandomItems must be passed at least one argument"; $n =~ m/[0-9]+/ or croak "pickRandomItems must be passed an integer"; $n <= @randomized_pool or croak "pickRandomItems can't return more unique items than you feed it"; return @randomized_pool[0..$n - 1]; } =head2 gpgPublicKeys() Returns the list of key fingerprints found in the public keyring. Args: - $gnupg_options: reference to a hash passed to ->hash_init =cut sub gpgPublicKeys { my $gnupg_options = shift; my %gi_args = @_; my $gnupg = App::Parcimonie::GnuPG::Interface->new(%gi_args); $gnupg->options->hash_init(%{ clone($gnupg_options) }); $gnupg->get_public_keys_hex(); } =head2 gpgRecvKeys( @keyids ) Imports the keys with the given key IDs from a keyserver. Args: - $keyids: reference to an array of key IDs - $gnupg_options: reference to a hash passed to ->hash_init =cut sub gpgRecvKeys { my $keyids = shift; my $gnupg_options = shift; my %gi_args = @_; my $gnupg = App::Parcimonie::GnuPG::Interface->new(%gi_args); $gnupg->options->hash_init(%{ clone($gnupg_options) }); my $err_h = IO::Handle->new(); my $handles = GnuPG::Handles->new(stderr => $err_h); my $pid = $gnupg->recv_keys( handles => $handles, command_args => $keyids ); my @raw_stderr = <$err_h>; # reading the output close $err_h; waitpid $pid, 0; # clean up the finished GnuPG process my $std_err = decode($codeset, join('', @raw_stderr)); # Filter out lines such as: # 11:21:19 libtorsocks(27234): The symbol res_query() was not found... $std_err =~ s{ ^ # anchor at a line beginning [[:digit:]]{2} [:] [[:digit:]]{2} # time such as 11:21:19 [:] [[:digit:]]{2} [[:space:]]+ libtorsocks [(] [[:digit:]]+ # PID surrounded by parenthesis [)] [:] [[:space:]]+ [^\n]* # anything but a line break $ [\n]? }{}xmsg; no warnings; unless ($CHILD_ERROR == 0) { use warnings; croak $std_err; } use warnings; return $std_err; } =head2 checkGpgHasDefinedKeyserver Throws an exception if no keyserver is defined in GnuPG configuration. =cut sub checkGpgHasDefinedKeyserver { my $arg_ref = shift; my $gnupg_homedir = $arg_ref->{homedir}; my $gpgconf; if (defined $gnupg_homedir) { $gpgconf = file($gnupg_homedir, 'gpg.conf'); } else { $gpgconf = file(File::HomeDir->my_home, '.gnupg', 'gpg.conf'); } -f $gpgconf or croak "No GnuPG configuration file was found in '$gpgconf'"; -r $gpgconf or croak "The GnuPG configuration file ($gpgconf) is not readable"; my %gpgconf = ParseConfig($gpgconf); defined $gpgconf{keyserver} && length $gpgconf{keyserver} or croak "No keyserver is defined in GnuPG configuration ($gpgconf).\n" . "See 'man parcimonie' to learn how to correct that."; return; } =head2 averageLapseTime Argument: number of public keys in the keyring. Returns the desirable average lapse time (in seconds) between two key fetches. =cut sub averageLapseTime { 604800 / shift; # 1 week = 604800 seconds } 1; # End of App::Parcimonie App-Parcimonie-0.8/inc/0000700000175200017520000000000012253322520015476 5ustar intrigeriintrigeriApp-Parcimonie-0.8/inc/My/0000700000175200017520000000000012253322520016063 5ustar intrigeriintrigeriApp-Parcimonie-0.8/inc/My/Builder.pm0000600000175200017520000000246712253322520020022 0ustar intrigeriintrigeripackage My::Builder; use strict; use warnings; use 5.10.0; use base qw{Module::Build}; use autodie; use Cwd; use Path::Class qw{dir}; =head1 Methods and method modifiers =head2 run_in_po_dir Run the command+args passed in @_, using Module::Build's do_system method, in the directory that contains our gettext infrastructure and .po / .pot files. Return what do_system has returned, i.e. true on success, false on failure. =cut sub run_in_po_dir { my $self = shift; my $orig_dir = getcwd; chdir('po'); my $res = $self->do_system(@_); chdir($orig_dir); return $res; } =head2 ACTION_build Copy .mo files to blib/share/locale. =cut sub ACTION_build { my $self = shift; my @args = @_; $self->SUPER::ACTION_build(@args); my $blibdir = dir()->parent->subdir('blib'); say "blibdir: $blibdir"; $self->run_in_po_dir(qw{make install}, "DESTDIR=$blibdir"); }; =head2 ACTION_test Set strict permissions on GnuPG test home directories. =cut sub ACTION_test { my $self = shift; my @args = @_; my $datadir = dir()->subdir('t')->subdir('data'); my @gnupg_homedirs = map { $datadir->subdir("gnupg_homedir$_")->stringify } ('', '_without_defined_keyserver', '_without_gpgconf'); chmod 0700, @gnupg_homedirs; $self->SUPER::ACTION_test(@args); }; 1; App-Parcimonie-0.8/t/0000700000175200017520000000000012253322520015170 5ustar intrigeriintrigeriApp-Parcimonie-0.8/t/32-keyserver_defined_on_command_line.t0000600000175200017520000000231312253322520024476 0ustar intrigeriintrigeri#!perl use Test::Most tests => 4; use App::Parcimonie::Daemon; use Net::DBus::Reactor; use Path::Class; my $gnupg_homedir = dir('t', 'data', 'gnupg_homedir'); my @tests = ( { should_succeed => 0, gnupg_extra_args => [], explanation => 'no keyserver is set on the command line', }, { should_succeed => 0, gnupg_extra_args => ['--keyserver'], explanation => '--keyserver lacks its argument', }, { should_succeed => 1, gnupg_extra_args => [ '--keyserver=hkp://example.com' ], explanation => '--keyserver followed by equal sign and something', }, { should_succeed => 1, gnupg_extra_args => [ '--keyserver hkp://example.com' ], explanation => '--keyserver followed by space and something', }, ); sub run { my $test = shift; my $daemon = App::Parcimonie::Daemon->new_with_options( gnupg_extra_args => $test->{gnupg_extra_args}, gnupg_homedir => $gnupg_homedir, ); my $res = $daemon->keyserver_defined_on_command_line; $test->{should_succeed} ? $res : !$res; } foreach my $test (@tests) { ok(run($test), $test->{explanation}); } App-Parcimonie-0.8/t/33-checkGpgHasDefinedKeyserver.t0000600000175200017520000000120112253322520023122 0ustar intrigeriintrigeri#!perl -T use Test::Most tests => 2; use App::Parcimonie; use Path::Class; my $gnupg_options; # without any gpg.conf $gnupg_options = { homedir => dir('t', 'data', 'gnupg_homedir_without_gpgconf') }; dies_ok { checkGpgHasDefinedKeyserver($gnupg_options) } "checkGpgHasDefinedKeyserver throws an exception if no gpg.conf can be found"; # without any defined keyserver in gpg.conf $gnupg_options = { homedir => dir('t', 'data', 'gnupg_homedir_without_defined_keyserver') }; dies_ok { checkGpgHasDefinedKeyserver($gnupg_options) } "checkGpgHasDefinedKeyserver throws an exception if no keyserver is defined in gpg.conf"; App-Parcimonie-0.8/t/90-tryRecvKey.t.disabled0000600000175200017520000000163212253322520021464 0ustar intrigeriintrigeri#!perl BEGIN { unless ($ENV{RELEASE_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for release candidate testing'); } } use LWP::Online ':skip_all'; use Test::Most tests => 2; use Test::Trap; use Path::Class; use Env qw{@PATH}; use FindBin; unshift @PATH, "$FindBin::Bin/../bin"; my $nonexistent_keyid = 'A'x40; my $existent_keyid = '6F818B215E159EF3FA26B0BE624DC565135EA668'; my $gnupg_homedir = dir('t', 'data', 'gnupg_homedir'); $ENV{LC_ALL} = 'C'; use App::Parcimonie::Daemon; my $daemon = App::Parcimonie::Daemon->new_with_options(gnupg_homedir => $gnupg_homedir); trap { $daemon->tryRecvKey( $nonexistent_keyid ) }; like ( $trap->stderr, qr/^gpgkeys:/xms, 'Warns /^gpgkeys:/ when trying to receive a non-existing key.' ); trap { $daemon->tryRecvKey( $existent_keyid ) }; is ( $trap->stderr, '', 'No STDERR when trying to receive an existing key.' ); App-Parcimonie-0.8/t/release-pod-coverage.t0000644000175200017520000000076512253322520021370 0ustar intrigeriintrigeri#!perl BEGIN { unless ($ENV{RELEASE_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for release candidate testing'); } } use Test::More; eval "use Test::Pod::Coverage 1.08"; plan skip_all => "Test::Pod::Coverage 1.08 required for testing POD coverage" if $@; eval "use Pod::Coverage::TrustPod"; plan skip_all => "Pod::Coverage::TrustPod required for testing POD coverage" if $@; all_pod_coverage_ok({ coverage_class => 'Pod::Coverage::TrustPod' }); App-Parcimonie-0.8/t/release-pod-syntax.t0000644000175200017520000000045012253322520021112 0ustar intrigeriintrigeri#!perl BEGIN { unless ($ENV{RELEASE_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for release candidate testing'); } } use Test::More; eval "use Test::Pod 1.41"; plan skip_all => "Test::Pod 1.41 required for testing POD" if $@; all_pod_files_ok(); App-Parcimonie-0.8/t/data/0000700000175200017520000000000012253322520016101 5ustar intrigeriintrigeriApp-Parcimonie-0.8/t/data/gnupg_homedir_without_defined_keyserver/0000700000175200017520000000000012253322520026270 5ustar intrigeriintrigeriApp-Parcimonie-0.8/t/data/gnupg_homedir_without_defined_keyserver/gpg.conf0000600000175200017520000000003012253322520027707 0ustar intrigeriintrigericert-digest-algo SHA256 App-Parcimonie-0.8/t/data/gnupg_homedir_without_gpgconf/0000700000175200017520000000000012253322520024216 5ustar intrigeriintrigeriApp-Parcimonie-0.8/t/data/gnupg_homedir_without_gpgconf/placeholder0000600000175200017520000000000012253322520026413 0ustar intrigeriintrigeriApp-Parcimonie-0.8/t/data/gnupg_homedir/0000700000175200017520000000000012253322520020730 5ustar intrigeriintrigeriApp-Parcimonie-0.8/t/data/gnupg_homedir/gpg.conf0000600000175200017520000000005212253322520022353 0ustar intrigeriintrigerikeyserver x-hkp://pool.sks-keyservers.net App-Parcimonie-0.8/t/data/pubkeys/0000700000175200017520000000000012253322520017563 5ustar intrigeriintrigeriApp-Parcimonie-0.8/t/data/pubkeys/intrigeri.asc0000600000175200017520000003270012253322520022253 0ustar intrigeriintrigeri-----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.4.10 (GNU/Linux) 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 =+eYc -----END PGP PUBLIC KEY BLOCK----- App-Parcimonie-0.8/t/data/pubkeys/rms.asc0000600000175200017520000004150612253322520021064 0ustar intrigeriintrigeri-----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.4.10 (GNU/Linux) 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 om8o2DEPC8M= =UNxl -----END PGP PUBLIC KEY BLOCK----- App-Parcimonie-0.8/t/30-pickRandomItems.t0000600000175200017520000000260412253322520020672 0ustar intrigeriintrigeri#!perl -T use Test::Most tests => 12; my @set = (0, 1, 2, 3); my @list = (0, 1, 1, 3); use App::Parcimonie; use List::MoreUtils qw{uniq}; my @res; ### pickRandomItems dies_ok { App::Parcimonie::pickRandomItems() } "pickRandomItems sends an exception if N is not defined"; dies_ok { App::Parcimonie::pickRandomItems("abc") } "pickRandomItems sends an exception if N is not an integer"; dies_ok { App::Parcimonie::pickRandomItems(42, @set) } "pickRandomItems sends an exception if N is too big"; dies_ok { App::Parcimonie::pickRandomItems(42, @list) } "pickRandomItems sends an exception if N is too big"; dies_ok { App::Parcimonie::pickRandomItems(42, ()) } "pickRandomItems sends an exception if N>0 and empty input list"; @res = App::Parcimonie::pickRandomItems(2, @set); is(scalar(@res), 2, "returns a list with N items"); is(uniq(@res), @res, "returns a list of unique items"); @res = App::Parcimonie::pickRandomItems(2, @list); is(scalar(@res), 2, "returns a list with N items"); is(uniq(@res), @res, "returns a list of unique items"); @res = App::Parcimonie::pickRandomItems(0, @set); is(scalar(@res), 0, "returns the empty list when N=0"); @res = App::Parcimonie::pickRandomItems(0, @list); is(scalar(@res), 0, "returns the empty list when N=0"); @res = App::Parcimonie::pickRandomItems(0, ()); is(scalar(@res), 0, "returns the empty list when N=0 and empty input list"); App-Parcimonie-0.8/t/31-gpgPublicKeys.t0000600000175200017520000000060712253322520020353 0ustar intrigeriintrigeri#!perl use Test::Most tests => 1; use Path::Class; my $expected_pubkeys = 2; my $gnupg_options = { homedir => dir('t', 'data', 'gnupg_homedir') }; $ENV{LC_ALL} = 'C'; use Env qw{@PATH}; use FindBin; unshift @PATH, "$FindBin::Bin/../bin"; use App::Parcimonie; is(scalar gpgPublicKeys($gnupg_options), $expected_pubkeys, "There are $expected_pubkeys public keys in the keyring." ); App-Parcimonie-0.8/t/release-no-tabs.t0000644000175200017520000000132012253322520020344 0ustar intrigeriintrigeri BEGIN { unless ($ENV{RELEASE_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for release candidate testing'); } } use strict; use warnings; # this test was generated with Dist::Zilla::Plugin::NoTabsTests 0.05 use Test::More 0.88; use Test::NoTabs; my @files = ( 'bin/parcimonie', 'bin/parcimonie-applet', 'bin/parcimonie-torified-gpg', 'lib/App/Parcimonie.pm', 'lib/App/Parcimonie/Applet.pm', 'lib/App/Parcimonie/DBus/Object.pm', 'lib/App/Parcimonie/Daemon.pm', 'lib/App/Parcimonie/GnuPG/Interface.pm', 'lib/App/Parcimonie/Role/HasCodeset.pm', 'lib/App/Parcimonie/Role/HasEncoding.pm' ); notabs_ok($_) foreach @files; done_testing; App-Parcimonie-0.8/t/05-init-keyring.t0000600000175200017520000000307112253322520020213 0ustar intrigeriintrigeri#!perl use Test::Most tests => 3; use English qw{-no_match_vars}; use GnuPG::Interface; use IO::Handle; use Path::Class; my $gnupg_homedir = dir('t', 'data', 'gnupg_homedir'); my $gnupg_pubkeys_dir = dir('t', 'data', 'pubkeys'); sub importKeyFile ($) { my $file = shift; my $gnupg = GnuPG::Interface->new(); $gnupg->options->hash_init( homedir => $gnupg_homedir ); my ( $input, $output, $error ) = (IO::Handle->new(), IO::Handle->new(), IO::Handle->new(), ); my $handles = GnuPG::Handles->new(stdin => $input, stdout => $output, stderr => $error, ); my $pid = $gnupg->import_keys( handles => $handles ); my $key_str; unless ($key_str = $file->slurp) { warn "Could not slurp file '$file'."; return undef; } print $input $key_str; close $input; my @std_output = <$output>; # reading the output my @error_output = <$error>; # reading the error close $output; close $error; waitpid $pid, 0; # clean up the finished GnuPG process no warnings; return 1 if ($CHILD_ERROR == 0); use warnings; warn @error_output; return undef; } ok(importKeyFile(file($gnupg_pubkeys_dir, 'intrigeri.asc'))); ok(importKeyFile(file($gnupg_pubkeys_dir, 'rms.asc'))); is(system('gpg', '--homedir', $gnupg_homedir, '--update-trustdb'), 0, "updated GnuPG trustdb"); App-Parcimonie-0.8/t/91-gpgRecvKeys.t0000600000175200017520000000162612253322520020044 0ustar intrigeriintrigeri#!perl BEGIN { unless ($ENV{RELEASE_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for release candidate testing'); } } use LWP::Online ':skip_all'; use Test::Most tests => 2; use Path::Class; use App::Parcimonie; my $nonexistent_keyid = 'A'x40; my $existent_keyid = '6F818B215E159EF3FA26B0BE624DC565135EA668'; my $gnupg_options = { homedir => dir('t', 'data', 'gnupg_homedir') }; $ENV{LC_ALL} = 'C'; use Env qw{@PATH}; use FindBin; unshift @PATH, "$FindBin::Bin/../bin"; dies_ok { gpgRecvKeys([ $nonexistent_keyid ], $gnupg_options) } "gpgRecvKeys throws an exception when trying to receive a non-existing key."; like( gpgRecvKeys([ $existent_keyid ], $gnupg_options), '/gpg: \s+ Total\snumber\sprocessed: \s+ 1\n gpg: \s+ (?:unchanged|new\s+signatures) : \s+ /xms', "gpgRecvKeys returns an expected string when receiving an existing key." ); App-Parcimonie-0.8/t/author-critic.t0000644000175200017520000000066612253322520020154 0ustar intrigeriintrigeri#!perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for testing by the author'); } } use strict; use warnings; use Test::More; use English qw(-no_match_vars); eval "use Test::Perl::Critic"; plan skip_all => 'Test::Perl::Critic required to criticise code' if $@; Test::Perl::Critic->import( -profile => "perlcritic.rc" ) if -e "perlcritic.rc"; all_critic_ok(); App-Parcimonie-0.8/t/release-eol.t0000644000175200017520000000047612253322520017573 0ustar intrigeriintrigeri BEGIN { unless ($ENV{RELEASE_TESTING}) { require Test::More; Test::More::plan(skip_all => 'these tests are for release candidate testing'); } } use strict; use warnings; use Test::More; eval 'use Test::EOL'; plan skip_all => 'Test::EOL required' if $@; all_perl_files_ok({ trailing_whitespace => 1 }); App-Parcimonie-0.8/t/00-load_all.t0000600000175200017520000000120212253322520017336 0ustar intrigeriintrigeriuse Test::Most; use Path::Class; use Module::Pluggable::Object; eval { require Win32; }; # progs # my @progs=file("bin", "parcimonie"); # foreach my $file (@progs) { # ok(system("perl -c $file") eq 0, $file); # } # libs my @needsX = qw{App::Parcimonie::Applet}; my $finder = Module::Pluggable::Object->new( search_path => [ 'App::Parcimonie' ], ); foreach my $class (grep !/\.ToDo/, sort do { local @INC = ('lib'); $finder->plugins }) { if (grep { $_ eq $class } @needsX) { next unless defined($ENV{DISPLAY}) && length($ENV{DISPLAY}); } use_ok($class); } done_testing(); App-Parcimonie-0.8/bin/0000700000175200017520000000000012253322520015475 5ustar intrigeriintrigeriApp-Parcimonie-0.8/bin/parcimonie-torified-gpg0000700000175200017520000000004012253322520022121 0ustar intrigeriintrigeri#!/bin/sh exec torsocks gpg $@ App-Parcimonie-0.8/bin/parcimonie-applet0000700000175200017520000000220612253322520021034 0ustar intrigeriintrigeri#!/usr/bin/perl =head1 NAME parcimonie-applet - GNOME monitoring applet for parcimonie =cut use strict; use warnings; use 5.10.0; use FindBin; use lib "$FindBin::Bin/../lib"; use Carp; use Try::Tiny; my $mu; sub record_memory_usage { 1 } sub report_memory_usage { 1 } BEGIN { if (exists $ENV{REPORT_MEMORY_USAGE} && defined $ENV{REPORT_MEMORY_USAGE} && $ENV{REPORT_MEMORY_USAGE}) { try { require Memory::Usage; } catch { croak "Memory::Usage is needed when REPORT_MEMORY_USAGE is set." }; $mu = Memory::Usage->new(); no warnings 'redefine'; *record_memory_usage = sub { $mu->record(shift) }; *report_memory_usage = sub { $mu->dump() }; } } BEGIN { record_memory_usage('before loading App::Parcimonie::Applet'); require App::Parcimonie::Applet; App::Parcimonie::Applet->import(); record_memory_usage('after loading App::Parcimonie::Applet'); } $SIG{'INT'} = $SIG{'TERM'} = sub { report_memory_usage(); exit(0); }; $SIG{'USR1'} = sub { report_memory_usage(); }; App::Parcimonie::Applet->new->run; report_memory_usage(); App-Parcimonie-0.8/bin/parcimonie0000700000175200017520000001143712253322520017557 0ustar intrigeriintrigeri#!/usr/bin/perl =head1 NAME parcimonie - privacy-friendly helper to refresh a GnuPG keyring =head1 VERSION Version 0.8 =head1 SYNOPSIS B [options] =head1 DESCRIPTION parcimonie is a daemon that slowly refreshes a GnuPG public keyring from a keyserver. Its refreshes one key at a time; between every key update, parcimonie sleeps a random amount of time, long enough for the previously used Tor circuit to expire. This process is meant to make it hard for an attacker to correlate the multiple performed key update operations. See the design.mdwn document to learn more about the threat and risk models parcimonie attempts to help coping with. =head1 USAGE 1. Configure GnuPG to be able to use a keyserver. You can skip this section if you already have configured a keyserver in ~/.gnupg/gpg.conf. Else, add to your gpg.conf something along these lines: keyserver hkp://pool.sks-keyservers.net You obviously can choose your preferred keyserver here; if using hkps:// (which would be our second choice behind hkpms://), your GnuPG installation should support HKPS; on Debian systems, enabling such support is done by installing the gnupg-curl package; see those web pages for help with GnuPG hkps:// configuration: http://sks-keyservers.net/overview-of-pools.php#pool_hkps http://keys.indymedia.org/ You may want parcimonie to use a different keyserver than the one your usual GnuPG invocations do. This can be achieved by passing to parcimonie a command-line option such as: --gnupg-extra-arg "--keyserver=hkps://hkps.pool.sks-keyservers.net" 2. Run "parcimonie --verbose". 3. Check the output for misconfiguration or bugs. 4. Once happy, start the daemon without the --verbose option. Note: the Debian package automatically starts the daemon with your X session. For example, GNOME users can configure its startup from the "System -> Preferences -> Startup Applications" menu. =head1 OPTIONS The following command lists available options: parcimonie --help =head2 Tor configuration vs. --minimum-lapse-time In case you set the Tor MaxCircuitDirtiness setting yourself, you probably want to pass parcimonie a matching --minimum-lapse-time option so that subsequent key fetches use different Tor circuits. Just make sure this remains true: minimum-lapse-time >= Tor MaxCircuitDirtiness =head2 hkpms:// We recommend using hkpms; see http://web.monkeysphere.info/ for details. When a hkpms:// keyserver is being used, one needs to do two additional steps since gpgkeys_hkpms does not work in the torsocks wrapped environment parcimonie uses by default to run gpg. =head3 Torify gpgkeys_hkpms Just add the following line to gpg.conf: keyserver-options http-proxy=socks://127.0.0.1:9050 =head3 Hey, parcimonie, gpg is already torified Pass the --gnupg-already-torified switch to the parcimonie daemon command-line. parcimonie will then rely on the keyserver-options previously added to gpg.conf, and won't attempt to torify gpg connections itself. =head1 AUTHOR intrigeri =head1 LICENSE AND COPYRIGHT Copyright (C) 2010-2013 intrigeri Licensed under the same terms as Perl itself. =head1 BUGS Please report any bugs or feature requests to C. =head1 SUPPORT You can find documentation for parcimonie with the man command. man parcimonie You can also look for information at: =over 4 =item * parcimonie's homepage L =back =cut use strict; use warnings; our $VERSION = '0.8'; use FindBin; use lib "$FindBin::Bin/../lib"; use Env qw{@PATH}; unshift @PATH, "$FindBin::Bin"; use 5.10.0; use Carp; use Try::Tiny; my $mu; sub record_memory_usage { 1 } sub report_memory_usage { 1 } BEGIN { if (exists $ENV{REPORT_MEMORY_USAGE} && defined $ENV{REPORT_MEMORY_USAGE} && $ENV{REPORT_MEMORY_USAGE}) { try { require Memory::Usage; } catch { croak "Memory::Usage is needed when REPORT_MEMORY_USAGE is set." }; $mu = Memory::Usage->new(); no warnings 'redefine'; *record_memory_usage = sub { $mu->record(shift) }; *report_memory_usage = sub { $mu->dump() }; } } $SIG{'INT'} = $SIG{'TERM'} = sub { report_memory_usage(); exit(0); }; $SIG{'USR1'} = sub { report_memory_usage(); }; record_memory_usage('starting work'); record_memory_usage('before loading App::Parcimonie'); require App::Parcimonie; App::Parcimonie->import(); record_memory_usage('after loading App::Parcimonie'); record_memory_usage('before loading App::Parcimonie::Daemon'); require App::Parcimonie::Daemon; App::Parcimonie::Daemon->import(); record_memory_usage('after loading App::Parcimonie::Daemon'); App::Parcimonie::Daemon->new_with_options()->run; report_memory_usage(); App-Parcimonie-0.8/MANIFEST.SKIP0000600000175200017520000000006212253322520016623 0ustar intrigeriintrigeri^cover_db ~$ ^debian \.bak$ \.gpg$ \.gpg~$ \.old$ App-Parcimonie-0.8/perlcritic.rc0000600000175200017520000000011312253322520017410 0ustar intrigeriintrigeri[TestingAndDebugging::RequireUseStrict] equivalent_modules = Moo Moo::Role App-Parcimonie-0.8/Changes.OLD0000600000175200017520000000756412253322520016653 0ustar intrigeriintrigeriRevision history for App-Parcimonie 0.7.1 20121020 Fix critical applet bugs: - Use correct method name to set tooltip on status icon. Thanks to Vagrant Cascadian for reporting it as Debian bug #690577. - Pass the -1 placeholder for text length when inserting into a TextBuffer. 0.7 20120623 Migrate from Gtk2 to Gtk3: - Remove obsolete library import. - Use new Gtk3/GDK API for event buttons. - Use new Gtk3/GDK3 event API to access pressed key value. - Use Gtk3::Gdk::keyval_from_name instead of obsolete (undefined) ::Keysyms. - Use new Gtk3 API for window visibility toggling. - Use Gtk3::MenuItem->new_with_mnemonic, as ->new('label' is not supported in Gtk3. - Require Gtk3 0.007, which will be the first one supporting Gtk3::show_about_dialog. Update README. Testsuite: use pool.sks-keyservers.net instead of keys.indymedia.org. Fix option name in test suite. Skip online tests unless in release testing mode. 0.6 20111004 Don't send NEWNYM nor talk to Tor control port/socket anymore: sleeping long enough for the previously used Tor circuit to expire (MaxCircuitDirtiness) is enough. Drastic memory savings: - 75% (RSS) for the parcimonie daemon (58MB -> 15MB) - 50% (RSS) for the parcimonie applet (54MB -> 28MB) Add an About dialog to the applet. 0.5.2 20110820 Look up keys using the full fingerprint, instead of long key ID. Documentation: - make it clear the torrc settings depend on the Tor version - update keyserver configuration instructions Set strict permissions on GnuPG test home directories. Fix dependency: Gtk2 1.222 is enough. 0.5.1 20110729 Use new Debian default location for ControlSocket and CookieAuthFile. Document how Tor shall be configured. 0.5 20110725 Really fix the ever-growing gpg command-line bug. Add a --gnupg-already-torified daemon option. Document how hkpms:// can be used with parcimonie. Filter out libtorsocks error messages. 0.4 20110724 Bugfix: gpg command-line was infinitely growing. Run "torsocks gpg" using exec. Fix HasEncoding role on older Perl. Support password and null Tor authentication methods. Support connecting to Tor over the shiny new ControlSocket. Applet: add a log viewer window. 0.3.3 20110722 Subclass Module::Build using "base" rather than MooseX::NonMoose. Add parcimonie-torified-gpg manpage source. 0.3.2 20110718 Convert to Dist::Zilla. Add gettext translation infrastructure. Support tor_ctl_host to be supplied as a hostname. Croak if needed programs cannot be found in $PATH. Torify gpg ourselves using torsocks. Allow the user to specify arbitrary arguments that are passed to GnuPG. Add opt-in recording and reporting of memory usage. Decode/encode from/to current locale on IO boundaries. Build the public keys list in an optimized way. 0.3.1 20110624 Add .desktop files forgotten in 0.3. Fix MANIFEST and thus released tarball. Add missing dependency. Don't run tests that need X unless $DISPLAY is set. 0.3 20110624 Daemon: use D-Bus main loop to handle the key fetch timing, send D-Bus signals before and after fetching a key. Add a desktop systray applet. Keep a in-memory buffer of max 1000 key fetch attempts result. Validate more user-provided options. Many cleanups and small improvements. 0.2 20110212 Make the average lapse time configurable. 0.01 20101226 First version, released on an unsuspecting world. App-Parcimonie-0.8/design.mdwn0000600000175200017520000000547212253322520017077 0ustar intrigeriintrigeriAssumptions =========== Let us consider an individual's public keyring as an unordered set of public OpenPGP keys. We assume there probably exists at least one subset of public keys in this keyring that identifies it, i.e. no other individual's keyring contain the same subset of public keys. This unproven assumption is the basis for any subsequent design thought about parcimonie. It is generally considered good practice to refresh such public keys from public keyservers on a regular basis, notably since public OpenPGP keys can be compromised and thus revoked. The usual way to refresh a public keyring is to run the `gpg --refresh-keys` command that queries the configured keyserver for updates of every public key stored in the to-be-refreshed keyring. Combined with the identifying subset assumption, this "query all keys at a time" way of refreshing a keyring might disclose private information to an adversary. The adversary ============= Network-wise we assume the same type of threat that Tor does: an non-global adversary who has full control over the network traffic of some fractions of the Internet. OpenPGP keyservers administrators are in a privileged position to observe public keys requests. To put it short, the rest of this document will call "the adversary" anyone able to monitor a given individual's connections to her configured OpenPGP keyserver(s) on a regular basis. The adversary is able to establish the identifying subset <-> individual. XXX: explain why/how the adversary may be able to do so. Threats ======= Using Tor --------- (application-level leakage) The adversary gains knowledge of the rest of the keyring. Not using Tor ------------- (IP-level + application-level leakage) The adversary gains knowledge of the rest of the keyring + user location. Possible workarounds ==================== Greatly increase the cost of correlating every key update. parcimonie refreshes one key at a time, over Tor; between every key update it sleeps a random amount of time, long enough for the previously used Tor circuit to expire. Refresh rate ============ parcimonie sleeps a random amount of time between every key fetch; - the longest the delay is, the longest it takes for a published key update (e.g. revocation certificate) to become locally available - the shortest the delay is, the cheaper a correlation attack is this lapse time is computed in function of the number of public keys in the keyring: max(MaxCircuitDirtiness, rand(2 * ( seconds in a week / number of pubkeys ))) Examples: - 50 public keys -> average lapse time =~ 200 min. - 500 public keys -> average lapse time =~ 20 min. Feedback to the user ==================== The parcimonie daemon sends a D-Bus signal before and after every key fetch attempt. The applet registers to this signal and displays status information accordingly. App-Parcimonie-0.8/META.json0000644000175200017520000000532612253322520016366 0ustar intrigeriintrigeri{ "abstract" : "privacy-friendly helper to refresh a GnuPG keyring", "author" : [ "intrigeri " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 5.006, CPAN::Meta::Converter version 2.132830", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "App-Parcimonie", "prereqs" : { "build" : { "requires" : { "Cwd" : "3.30", "Module::Build" : "0.3601", "Path::Class" : "0.19", "autodie" : "2.06_01" } }, "configure" : { "requires" : { "Module::Build" : "0.3601" } }, "develop" : { "requires" : { "Pod::Coverage::TrustPod" : "0", "Test::More" : "0", "Test::NoTabs" : "0", "Test::Pod" : "1.41", "Test::Pod::Coverage" : "1.08" } }, "runtime" : { "requires" : { "Carp" : "1.11", "Clone" : "0.31", "Config::General" : "2.48", "Encode" : "0", "English" : "1.04", "File::HomeDir" : "0.86", "File::ShareDir" : "1.00", "File::Spec" : "3.3100", "File::Which" : "1.08", "Glib" : "1.223", "GnuPG::Interface" : "0.42", "Gtk3" : "0.011", "I18N::Langinfo" : "0", "List::MoreUtils" : "0.25", "Moo" : "1.003", "MooX::Options" : "3.83", "MooX::late" : "0.014", "Net::DBus" : "v0.33.6", "Net::DBus::GLib" : "v0.33.0", "Pango" : "1.221", "Path::Class" : "0.19", "Tie::Cache" : "0.17", "Time::Duration::Parse" : "0.06", "Try::Tiny" : "0.04", "Type::Tiny" : "0.022", "Types::Path::Tiny" : "0.005", "namespace::autoclean" : "0.09" } }, "test" : { "requires" : { "File::Which" : "1.08", "GnuPG::Interface" : "0.42", "IO::Handle" : "1.28", "LWP::Online" : "1.07", "List::MoreUtils" : "0.25", "List::Util" : "1.21", "Module::Pluggable::Object" : "3.9", "Path::Class" : "0.19", "Test::Most" : "0.22", "Test::Trap" : "v0.2.1" } } }, "release_status" : "stable", "resources" : { "homepage" : "https://gaffer.ptitcanardnoir.org/intrigeri/code/parcimonie/", "repository" : { "type" : "git", "url" : "git://gaffer.ptitcanardnoir.org/App-Parcimonie.git" } }, "version" : "0.8" } App-Parcimonie-0.8/Build.PL0000644000175200017520000000503112253322520016232 0ustar intrigeriintrigeri use strict; use warnings; use Module::Build 0.3601; use lib qw{inc}; use My::Builder; my %module_build_args = ( "build_requires" => { "Cwd" => "3.30", "Module::Build" => "0.3601", "Path::Class" => "0.19", "autodie" => "2.06_01" }, "configure_requires" => { "Module::Build" => "0.3601" }, "dist_abstract" => "privacy-friendly helper to refresh a GnuPG keyring", "dist_author" => [ "intrigeri " ], "dist_name" => "App-Parcimonie", "dist_version" => "0.8", "license" => "perl", "module_name" => "App::Parcimonie", "recommends" => {}, "recursive_test_files" => 1, "requires" => { "Carp" => "1.11", "Clone" => "0.31", "Config::General" => "2.48", "Encode" => 0, "English" => "1.04", "File::HomeDir" => "0.86", "File::ShareDir" => "1.00", "File::Spec" => "3.3100", "File::Which" => "1.08", "Glib" => "1.223", "GnuPG::Interface" => "0.42", "Gtk3" => "0.011", "I18N::Langinfo" => 0, "List::MoreUtils" => "0.25", "Moo" => "1.003", "MooX::Options" => "3.83", "MooX::late" => "0.014", "Net::DBus" => "v0.33.6", "Net::DBus::GLib" => "v0.33.0", "Pango" => "1.221", "Path::Class" => "0.19", "Tie::Cache" => "0.17", "Time::Duration::Parse" => "0.06", "Try::Tiny" => "0.04", "Type::Tiny" => "0.022", "Types::Path::Tiny" => "0.005", "namespace::autoclean" => "0.09" }, "script_files" => [ "bin/parcimonie", "bin/parcimonie-applet", "bin/parcimonie-torified-gpg" ], "share_dir" => { "dist" => "share" }, "test_requires" => { "File::Which" => "1.08", "GnuPG::Interface" => "0.42", "IO::Handle" => "1.28", "LWP::Online" => "1.07", "List::MoreUtils" => "0.25", "List::Util" => "1.21", "Module::Pluggable::Object" => "3.9", "Path::Class" => "0.19", "Test::Most" => "0.22", "Test::Trap" => "v0.2.1" } ); my %fallback_build_requires = ( "Cwd" => "3.30", "File::Which" => "1.08", "GnuPG::Interface" => "0.42", "IO::Handle" => "1.28", "LWP::Online" => "1.07", "List::MoreUtils" => "0.25", "List::Util" => "1.21", "Module::Build" => "0.3601", "Module::Pluggable::Object" => "3.9", "Path::Class" => "0.19", "Test::Most" => "0.22", "Test::Trap" => "v0.2.1", "autodie" => "2.06_01" ); unless ( eval { Module::Build->VERSION(0.4004) } ) { delete $module_build_args{test_requires}; $module_build_args{build_requires} = \%fallback_build_requires; } my $build = My::Builder->new(%module_build_args); $build->create_build_script; App-Parcimonie-0.8/MANIFEST0000644000175200017520000000220212253322520016064 0ustar intrigeriintrigeriBuild.PL Changes Changes.OLD INSTALL LICENSE MANIFEST MANIFEST.SKIP META.json META.yml README TODO bin/parcimonie bin/parcimonie-applet bin/parcimonie-torified-gpg design.mdwn dist.ini inc/My/Builder.pm lib/App/Parcimonie.pm lib/App/Parcimonie/Applet.pm lib/App/Parcimonie/DBus/Object.pm lib/App/Parcimonie/Daemon.pm lib/App/Parcimonie/GnuPG/Interface.pm lib/App/Parcimonie/Role/HasCodeset.pm lib/App/Parcimonie/Role/HasEncoding.pm parcimonie-torified-gpg.1.markdown perlcritic.rc po/Makefile po/PACKAGE po/POTFILES.in po/de.mo po/de.po po/fr.mo po/fr.po po/parcimonie-applet.pot share/applications/parcimonie-applet.desktop share/applications/parcimonie.desktop t/00-load_all.t t/05-init-keyring.t t/30-pickRandomItems.t t/31-gpgPublicKeys.t t/32-keyserver_defined_on_command_line.t t/33-checkGpgHasDefinedKeyserver.t t/90-tryRecvKey.t.disabled t/91-gpgRecvKeys.t t/author-critic.t t/data/gnupg_homedir/gpg.conf t/data/gnupg_homedir_without_defined_keyserver/gpg.conf t/data/gnupg_homedir_without_gpgconf/placeholder t/data/pubkeys/intrigeri.asc t/data/pubkeys/rms.asc t/release-eol.t t/release-no-tabs.t t/release-pod-coverage.t t/release-pod-syntax.t App-Parcimonie-0.8/META.yml0000644000175200017520000000255212253322520016214 0ustar intrigeriintrigeri--- abstract: 'privacy-friendly helper to refresh a GnuPG keyring' author: - 'intrigeri ' build_requires: Cwd: 3.30 File::Which: 1.08 GnuPG::Interface: 0.42 IO::Handle: 1.28 LWP::Online: 1.07 List::MoreUtils: 0.25 List::Util: 1.21 Module::Build: 0.3601 Module::Pluggable::Object: 3.9 Path::Class: 0.19 Test::Most: 0.22 Test::Trap: v0.2.1 autodie: 2.06_01 configure_requires: Module::Build: 0.3601 dynamic_config: 0 generated_by: 'Dist::Zilla version 5.006, CPAN::Meta::Converter version 2.132830' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: App-Parcimonie requires: Carp: 1.11 Clone: 0.31 Config::General: 2.48 Encode: 0 English: 1.04 File::HomeDir: 0.86 File::ShareDir: 1.00 File::Spec: 3.3100 File::Which: 1.08 Glib: 1.223 GnuPG::Interface: 0.42 Gtk3: 0.011 I18N::Langinfo: 0 List::MoreUtils: 0.25 Moo: 1.003 MooX::Options: 3.83 MooX::late: 0.014 Net::DBus: v0.33.6 Net::DBus::GLib: v0.33.0 Pango: 1.221 Path::Class: 0.19 Tie::Cache: 0.17 Time::Duration::Parse: 0.06 Try::Tiny: 0.04 Type::Tiny: 0.022 Types::Path::Tiny: 0.005 namespace::autoclean: 0.09 resources: homepage: https://gaffer.ptitcanardnoir.org/intrigeri/code/parcimonie/ repository: git://gaffer.ptitcanardnoir.org/App-Parcimonie.git version: 0.8 App-Parcimonie-0.8/po/0000700000175200017520000000000012253322520015343 5ustar intrigeriintrigeriApp-Parcimonie-0.8/po/parcimonie-applet.pot0000600000175200017520000000243512253322520021506 0ustar intrigeriintrigeri# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR intrigeri # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: intrigeri \n" "POT-Creation-Date: 2011-10-05 13:19+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: ../lib/App/Parcimonie/Applet.pm:91 msgid "parcimonie log viewer" msgstr "" #: ../lib/App/Parcimonie/Applet.pm:135 msgid "View log" msgstr "" #: ../lib/App/Parcimonie/Applet.pm:137 msgid "Exit" msgstr "" #: ../lib/App/Parcimonie/Applet.pm:139 msgid "About" msgstr "" #: ../lib/App/Parcimonie/Applet.pm:261 #, perl-format msgid "Fetching key %s..." msgstr "" #. TRANSLATORS: OpenPGP key id #: ../lib/App/Parcimonie/Applet.pm:280 #, perl-format msgid "Successfully fetched key %s." msgstr "" #. TRANSLATORS: OpenPGP key id, error message #: ../lib/App/Parcimonie/Applet.pm:286 #, perl-format msgid "Failed to fetch key %s: %s." msgstr "" #: ../lib/App/Parcimonie/Applet.pm:309 msgid "Having a rest." msgstr "" App-Parcimonie-0.8/po/POTFILES.in0000600000175200017520000000007112253322520017120 0ustar intrigeriintrigeri../bin/parcimonie-applet ../lib/App/Parcimonie/Applet.pm App-Parcimonie-0.8/po/Makefile0000600000175200017520000000500412253322520017004 0ustar intrigeriintrigeri# Makefile for various po files. srcdir = . destdir = $(DESTDIR)$(PREFIX) #CATALOGS = $(addsuffix .po, LINGUAS) CATALOGS = $(LINGUAS) MO_FILES = $(addsuffix .mo, $(LINGUAS)) MSGMERGE = msgmerge MSGFMT = msgfmt XGETTEXT = xgettext CATOBJEXT = .po include PACKAGE TD = $(strip $(TEXTDOMAIN)) default: help all: $(TD).pot update-po update-mo help: @echo "Available targets:" @echo " pot - remake master catalog" @echo " update-po - merge po files" @echo " update-mo - regenerate mo files" @echo " install - install mo files" @echo " all - all of the above" POTFILES = $(srcdir)/POTFILES.in \ $(shell cat $(srcdir)/POTFILES.in) pot: $(TD).pot clean: rm -f *~ *.bak *.mo # FIXME: The parameter --from-code is only needed if your sources contain # any 8 bit data (even in comments). UTF-8 is only a guess here, but it # will at least accept any 8 bit data. # # The parameter "--language=perl" is not strictly needed because the # source language of all our files will be auto-detected by xgettext # by their filename extension. You should even avoid this parameter # if you want to extract strings from multiple source languages. $(TD).pot: $(POTFILES) $(XGETTEXT) --output=$(srcdir)/$(TD).pox --from-code=utf-8 \ --add-comments=TRANSLATORS: --files-from=$(srcdir)/POTFILES.in \ --copyright-holder="$(COPYRIGHT_HOLDER)" \ --msgid-bugs-address="$(MSGID_BUGS_ADDRESS)" \ --language=perl && \ rm -f $@ && mv $(TD).pox $@ install: $(MO_FILES) cd $(srcdir); \ targetdir='$(destdir)/share/locale'; \ languages='$(LINGUAS)'; \ for lang in $$languages; do \ mkdir -p "$$targetdir/$$lang/LC_MESSAGES" || exit 1; \ dest="$$targetdir/$$lang/LC_MESSAGES/$(TD).mo"; \ cat="$$lang.mo"; \ echo "installing $$cat as $$dest"; \ cp -f $$cat $$dest && chmod 644 $$dest || exit 1; \ done update-mo: $(MO_FILES) update-po: $(MAKE) $(TD).pot cd $(srcdir); \ catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ mv $$lang.po $$lang.old.po; \ echo "$$lang:"; \ if $(MSGMERGE) $$lang.old.po $(TD).pot -o $$lang.po; then \ rm -f $$lang.old.po; \ else \ echo "msgmerge for $$cat failed!"; \ rm -f $$lang.po; \ mv $$lang.old.po $$lang.po; \ fi; \ done .SUFFIXES: .SUFFIXES: .po .mo .po.mo: $(MSGFMT) --check --statistics --verbose -o $@ $< App-Parcimonie-0.8/po/PACKAGE0000600000175200017520000000065212253322520016326 0ustar intrigeriintrigeri# Makefile snippet that holds all package-dependent information. # Add more languages here! Beware that this is a makefile snippet and # you have to adhere to make syntax. LINGUAS = de \ fr \ # Textdomain for our package. TEXTDOMAIN = parcimonie-applet # Initial copyright holder added to pot and po files. COPYRIGHT_HOLDER = intrigeri # Where to send msgid bugs? MSGID_BUGS_ADDRESS = intrigeri App-Parcimonie-0.8/po/fr.mo0000600000175200017520000000152712253322520016316 0ustar intrigeriintrigeri•Þ d¬­³¸Ôçö^2 ‘›5£Ù ÷!##3AboutExitFailed to fetch key %s: %s.Fetching key %s...Having a rest.Successfully fetched key %s.View logparcimonie log viewerProject-Id-Version: PACKAGE VERSION Report-Msgid-Bugs-To: intrigeri POT-Creation-Date: 2011-10-05 13:19+0200 PO-Revision-Date: 2011-10-05 13:21+0200 Last-Translator: FULL NAME Language-Team: LANGUAGE Language: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit À proposQuitterÉchec lors du rafraîchissement de la clé %s : %s.Mise à jour de la clé %s...En pause.Clé %s rafraîchie avec succès.Voir le journalVisionneur du journal de parcimonieApp-Parcimonie-0.8/po/de.po0000600000175200017520000000243312253322520016277 0ustar intrigeriintrigeri# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR intrigeri # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: intrigeri \n" "POT-Creation-Date: 2011-10-05 13:19+0200\n" "PO-Revision-Date: 2011-06-25 00:47+0200\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../lib/App/Parcimonie/Applet.pm:91 msgid "parcimonie log viewer" msgstr "" #: ../lib/App/Parcimonie/Applet.pm:135 msgid "View log" msgstr "" #: ../lib/App/Parcimonie/Applet.pm:137 msgid "Exit" msgstr "" #: ../lib/App/Parcimonie/Applet.pm:139 msgid "About" msgstr "" #: ../lib/App/Parcimonie/Applet.pm:261 #, perl-format msgid "Fetching key %s..." msgstr "" #. TRANSLATORS: OpenPGP key id #: ../lib/App/Parcimonie/Applet.pm:280 #, perl-format msgid "Successfully fetched key %s." msgstr "" #. TRANSLATORS: OpenPGP key id, error message #: ../lib/App/Parcimonie/Applet.pm:286 #, perl-format msgid "Failed to fetch key %s: %s." msgstr "" #: ../lib/App/Parcimonie/Applet.pm:309 msgid "Having a rest." msgstr "" App-Parcimonie-0.8/po/fr.po0000600000175200017520000000273112253322520016317 0ustar intrigeriintrigeri# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR intrigeri # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: intrigeri \n" "POT-Creation-Date: 2011-10-05 13:19+0200\n" "PO-Revision-Date: 2011-10-05 13:21+0200\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../lib/App/Parcimonie/Applet.pm:91 msgid "parcimonie log viewer" msgstr "Visionneur du journal de parcimonie" #: ../lib/App/Parcimonie/Applet.pm:135 msgid "View log" msgstr "Voir le journal" #: ../lib/App/Parcimonie/Applet.pm:137 msgid "Exit" msgstr "Quitter" #: ../lib/App/Parcimonie/Applet.pm:139 msgid "About" msgstr "À propos" #: ../lib/App/Parcimonie/Applet.pm:261 #, perl-format msgid "Fetching key %s..." msgstr "Mise à jour de la clé %s..." #. TRANSLATORS: OpenPGP key id #: ../lib/App/Parcimonie/Applet.pm:280 #, perl-format msgid "Successfully fetched key %s." msgstr "Clé %s rafraîchie avec succès." #. TRANSLATORS: OpenPGP key id, error message #: ../lib/App/Parcimonie/Applet.pm:286 #, perl-format msgid "Failed to fetch key %s: %s." msgstr "Échec lors du rafraîchissement de la clé %s : %s." #: ../lib/App/Parcimonie/Applet.pm:309 msgid "Having a rest." msgstr "En pause." App-Parcimonie-0.8/po/de.mo0000600000175200017520000000061412253322520016273 0ustar intrigeriintrigeri•Þ$,^-Project-Id-Version: PACKAGE VERSION Report-Msgid-Bugs-To: intrigeri POT-Creation-Date: 2011-10-05 13:19+0200 PO-Revision-Date: 2011-06-25 00:47+0200 Last-Translator: FULL NAME Language-Team: LANGUAGE Language: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit App-Parcimonie-0.8/dist.ini0000600000175200017520000000316512253322520016400 0ustar intrigeriintrigeriname = App-Parcimonie main_module = bin/parcimonie author = intrigeri license = Perl_5 copyright_holder = intrigeri copyright_year = 2013 [VersionFromModule] [MetaResources] homepage = https://gaffer.ptitcanardnoir.org/intrigeri/code/parcimonie/ repository.url = git://gaffer.ptitcanardnoir.org/App-Parcimonie.git repository.type = git [@Filter] -bundle = @Basic -remove = MakeMaker -remove = Readme [ModuleBuild] mb_class = My::Builder [InstallGuide] ; must come after ModuleBuild [MetaJSON] [Test::Perl::Critic] [PodCoverageTests] [PodSyntaxTests] [NoTabsTests] [EOLTests] [Prereqs] namespace::autoclean = 0.09 Carp = 1.11 Clone = 0.31 Config::General = 2.48 Encode = 0 English = 1.04 File::HomeDir = 0.86 File::ShareDir = 1.00 File::Spec = 3.3100 File::Which = 1.08 Glib = 1.223 GnuPG::Interface = 0.42 Gtk3 = 0.011 I18N::Langinfo = 0 List::MoreUtils = 0.25 Moo = 1.003 MooX::late = 0.014 MooX::Options = 3.83 Net::DBus = 0.33.6 Net::DBus::GLib = 0.33.0 Pango = 1.221 Path::Class = 0.19 Tie::Cache = 0.17 Time::Duration::Parse = 0.06 Try::Tiny = 0.04 Type::Tiny = 0.022 Types::Path::Tiny = 0.005 [Prereqs / BuildRequires] autodie = 2.06_01 Cwd = 3.30 Path::Class = 0.19 [Prereqs / TestRequires] File::Which = 1.08 GnuPG::Interface = 0.42 IO::Handle = 1.28 List::MoreUtils = 0.25 List::Util = 1.21 LWP::Online = 1.07 Module::Pluggable::Object = 3.9 Path::Class = 0.19 Test::Most = 0.22 Test::Trap = 0.2.1 ; Compile .po files to .mo files [LocaleMsgfmt] locale = po [Git::Check] [ChangelogFromGit] max_age = 99999 tag_regexp = ^parcimonie_(?:\d+[.]?)+$ file_name = Changes App-Parcimonie-0.8/INSTALL0000644000175200017520000000172112253322520015771 0ustar intrigeriintrigeri This is the Perl distribution App-Parcimonie. Installing App-Parcimonie is straightforward. ## Installation with cpanm If you have cpanm, you only need one line: % cpanm App::Parcimonie If you are installing into a system-wide directory, you may need to pass the "-S" flag to cpanm, which uses sudo to install the module: % cpanm -S App::Parcimonie ## Installing with the CPAN shell Alternatively, if your CPAN shell is set up, you should just be able to do: % cpan App::Parcimonie ## Manual installation As a last resort, you can manually install it. Download the tarball, untar it, then build it: % perl Build.PL % ./Build && ./Build test Then install it: % ./Build install If you are installing into a system-wide directory, you may need to run: % sudo ./Build install ## Documentation App-Parcimonie documentation is available as POD. You can run perldoc from a shell to read the documentation: % perldoc App::Parcimonie App-Parcimonie-0.8/Changes0000644000175200017520000012010212253322520016226 0ustar intrigeriintrigeri============================== 9999-99-99 99:99:99 +0000 HEAD ============================== commit 44cb291d369f16befa36810dcf2981937b8fd34c Author: intrigeri Date: Sun Dec 15 12:47:42 2013 +0000 Release parcimonie 0.8. commit a52a30f3518c84c9ff1ab242c0c33367b0de43b2 Author: intrigeri Date: Sun Dec 15 12:48:47 2013 +0000 Don't use Dist::Zilla's CheckChangeLog, it is now generated from Git. commit 2048123a8104568c8bdd6a7e43f3c8be191435aa Author: intrigeri Date: Sun Dec 15 12:45:58 2013 +0000 Bump copyright years, don't add copyright info to libraries. commit 80d598dbdb3a056a7c65536ea6e0bdbf52b5dc55 Author: intrigeri Date: Sun Dec 15 12:43:09 2013 +0000 Stop using OurPkgVersion, drop VERSION placeholders. commit f752cd65b89a5680f716836d7ee2fbdd9e839455 Author: intrigeri Date: Fri Dec 6 09:25:04 2013 +0000 Use Moo::Role before loading other libraries: exports all methods declared after it's used. commit 55910a4c1174921e8f1d4d0143f8272ff4ac91f8 Author: intrigeri Date: Sat Nov 2 09:10:11 2013 +0000 Use D::Z::P::ChangelogFromGit, rename old Changes. commit 006e944c8a1b605954f49ab1b0d09005112aa999 Author: intrigeri Date: Sat Nov 2 08:53:24 2013 +0000 Move from the deprecated CriticTests to Test::Perl::Critic. commit 0d5f193e1a85af2757396e5f4063eff13059d388 Author: intrigeri Date: Thu Sep 5 15:13:04 2013 +0000 Fully migrate to Moo, Type::Tiny and MooX::Options, thanks to MooX::late. commit 1883d95a7af95e77b39dbf35cf796645bbd14c1c Author: intrigeri Date: Thu Sep 5 15:13:56 2013 +0000 Adapt syntax to newer Gtk3 bindings, and depend on it. In practice, this reverts 7073b57fe0a62cd9b43f873a0f98a455708b2d40 that we sadly had to make when initially migrating to Gtk3. commit 437a7993357a42c78ed77d6ed4ecdc3b72d4f4d5 Author: kwadronaut Date: Thu Dec 27 14:54:24 2012 +0100 changing help urls about HKPS commit d30a0265416c68456d24c4ad344b31a0b4a675a3 Author: kwadronaut Date: Thu Dec 27 14:53:15 2012 +0100 changing specific keyservers to pools commit c24f6571a3a577a9a02ed855fc5009f1d3b2c472 Author: kwadronaut Date: Thu Dec 27 14:51:28 2012 +0100 typo ========================================== 2012-10-20 12:52:14 +0200 parcimonie_0.7.1 ========================================== commit cdaf096a831e351f3ce82582224af50094f79d31 Author: intrigeri Date: Fri Oct 19 16:32:21 2012 +0200 Releasing parcimonie 0.7.1. commit 8c2a8b17edeb21586f16e3097494db5942834af2 Author: intrigeri Date: Fri Oct 19 19:24:10 2012 +0200 Pass the -1 placeholder for text length when inserting into a TextBuffer. Fixes yet another GTK+3 -related critical parcimonie-applet bug. commit e2d282d1280eae97958f53ec242379f178e67a9a Author: intrigeri Date: Fri Oct 19 16:28:15 2012 +0200 Use correct method name to set tooltip on status icon (fixes critical applet bug). ======================================== 2012-06-23 23:22:56 +0200 parcimonie_0.7 ======================================== commit c54b257c25dc5e5cb6ffcc58816926fb66433e27 Author: intrigeri Date: Sat Jun 23 23:22:56 2012 +0200 Releasing parcimonie 0.7. commit a082860af537b9e078621de5309e1d18810b2404 Author: intrigeri Date: Sat Jun 23 23:19:14 2012 +0200 Require Gtk3 0.007, which will be the first one supporting Gtk3::show_about_dialog. commit dd32e7f697808fe08e21fa0dda5aaac5cb23d934 Author: intrigeri Date: Sun May 20 14:34:49 2012 +0200 Use Gtk3::MenuItem->new_with_mnemonic (->new('label') is not supported in Gtk3). commit f316dd899880237af9c2bbcefd58d4105b1db5c3 Author: intrigeri Date: Sun Apr 15 17:20:09 2012 +0200 Use new Gtk3 API for window visibility toggling. commit d146070988343c6a4d8dae9f8ba4d37b4330641f Author: intrigeri Date: Sun Apr 15 17:27:56 2012 +0200 Use Gtk3::Gdk::keyval_from_name instead of obsolete (undefined) ::Keysyms. commit 7134160b1696610f63adb9e496b1ff418cc210a4 Author: intrigeri Date: Sun Apr 15 17:24:52 2012 +0200 Use new Gtk3/GDK3 event API to access pressed key value. commit 7073b57fe0a62cd9b43f873a0f98a455708b2d40 Author: intrigeri Date: Sun Apr 15 17:18:06 2012 +0200 Use new Gtk3/GDK API for event buttons. commit 431318ca75d07bc3adce552c2d6b2b7bd5093f2c Author: intrigeri Date: Sun Apr 15 17:17:57 2012 +0200 Remove obsolete library import. commit d36b49c5a23592a74f418e3b623dfffdd3ba5846 Author: intrigeri Date: Sun Apr 15 17:10:22 2012 +0200 s/Gtk2/Gtk3/ commit 9fe3c6c18d985816a0ceeb11d7f6c0f0dcb496a8 Author: intrigeri Date: Sun Apr 8 12:02:25 2012 +0200 Untabify. commit 5dc2e3ed9b43f9160b53c774d5fb90442062e593 Author: intrigeri Date: Sun Apr 8 11:51:01 2012 +0200 Skip online tests unless in release testing mode. Debian FTBFS such as #665249 indicates network tests are not robust enough to run on automated buildds. commit 6103a9db74c067ba83438697fc8dcad6f298312d Author: intrigeri Date: Sat Apr 7 20:49:06 2012 +0200 Fix option name in test suite. commit af2b80a2eb5353cf854ee7ba621157631dad2681 Author: intrigeri Date: Mon Mar 5 17:55:33 2012 +0100 Testsuite: use pool.sks-keyservers.net instead of keys.indymedia.org. commit 9561c323bfec201a6b4c982dbbe0746d6cfea86d Author: intrigeri Date: Wed Oct 5 13:28:24 2011 +0200 Update README: parcimonie was uploaded to Debian. ======================================== 2011-10-05 13:24:01 +0200 parcimonie_0.6 ======================================== commit bcde1624df6b0b48996578867e5be99e0c3fc475 Author: intrigeri Date: Tue Oct 4 19:47:09 2011 +0200 Releasing parcimonie 0.6. commit 01e9db72035de04cee06e6e5607668160e97dc77 Author: intrigeri Date: Wed Oct 5 13:21:15 2011 +0200 Update po/pot files. commit a663f5d9fc2f3f04f0744ee12911cc0860631819 Author: intrigeri Date: Wed Oct 5 11:34:15 2011 +0200 Fix testsuite. commit 689d8c4a5c5b73e092e51723766fe3e9130a6814 Author: intrigeri Date: Wed Oct 5 12:18:04 2011 +0200 Pass gnupg_options to checkGpgHasDefinedKeyserver. commit df8b2b9250f51e05fbf56444bd6a5c167f7168e7 Author: intrigeri Date: Sun Sep 25 10:44:55 2011 +0200 Remove dependency on Mo[ou]seX::StrictConstructor. commit ed792ee3496d2816b2607361805ce87c1de44813 Author: intrigeri Date: Sun Sep 25 10:43:39 2011 +0200 Remove dependency on MouseX::NativeTraits. commit afab6ad464747040c81a52ac5e3674b7fc732a42 Author: intrigeri Date: Sat Sep 24 23:12:52 2011 +0200 TODO update. commit d5261847abeea7df44309a49241c3813e90fbed4 Author: intrigeri Date: Sat Sep 24 23:12:42 2011 +0200 Start filling Changes. commit 544817e6b1c922883f101438b8dc954f98068377 Author: intrigeri Date: Sat Sep 24 21:49:10 2011 +0200 Move some design documentation where it belongs. commit a3f593ca2aa41db888ce649339a4d8e9037956ee Author: intrigeri Date: Sat Sep 24 21:48:54 2011 +0200 Add an About dialog to the applet. commit 0008c5fdea97613f8af6130047ebb3bedc019ea7 Author: intrigeri Date: Sat Sep 24 21:25:00 2011 +0200 Move memory savings notes from TODO to Changes. commit 33671f33c322466d9a5c5325b73b3a8817fa4f2e Author: intrigeri Date: Sat Sep 24 09:47:34 2011 +0200 TODO update. commit 9de52bab4fae531a813513198a92470b0d3909fc Author: intrigeri Date: Sat Sep 24 09:44:22 2011 +0200 Cleanup. commit 5c7c862a04b38c9f687dfa95cc9b15745acdc871 Author: intrigeri Date: Sat Sep 24 09:43:20 2011 +0200 Use namespace::autoclean in all classes and roles. commit 7d43eac8c230e05fc0ef91d16e76c522a9988c5a Author: intrigeri Date: Sat Sep 24 09:36:11 2011 +0200 Convert gnupg_options to a lazy attribute. commit 0fdd2803be0283724f7a4785b166e6ac9991cb4f Author: intrigeri Date: Sat Sep 24 09:24:35 2011 +0200 Document the case when a custom --minimum-lapse-time should be used. commit 29ece0b6c6f0240549687379d5e27e4c64ee18e6 Author: intrigeri Date: Sat Sep 24 09:19:13 2011 +0200 Update TODO. commit 444ca95ceca04fa59ac87af726cc4d8911c2423c Author: intrigeri Date: Sat Sep 24 09:17:00 2011 +0200 Migrate dependencies from Moose* to Mouse*. commit d7450955812daa480c9dea0d3156b121066d8525 Author: intrigeri Date: Sat Sep 24 09:04:01 2011 +0200 Tell perlcritic Any::Moose enables strictures. commit fc69dc3e35439a291cc8d1a0385f08f2d2f00be9 Author: intrigeri Date: Fri Sep 23 16:25:48 2011 +0200 Convert daemon to plain MX::Getopt without App::Cmd. commit 39f1484aa3d89446e1c9ef4cec605d849a9c4752 Author: intrigeri Date: Fri Sep 23 01:26:35 2011 +0200 TODO update. commit ecdca6edbce7ec0362e4df3e7343291b1db7c2e2 Author: intrigeri Date: Fri Sep 23 01:27:56 2011 +0200 Make it clear we don't depend on MooseX::Types directly anymore. commit 2de76fbd58c02ffc7dd8121809e897947ceafc92 Author: intrigeri Date: Fri Sep 23 01:24:31 2011 +0200 Convert ::Applet to Any::Moose. ... and save 26MB vsz / 10MB rss runtime memory. commit fcd0ecf6865765d4792ee701f42e93b0f4fe5e84 Author: intrigeri Date: Fri Sep 23 01:17:24 2011 +0200 TODO update wrt. memory savings. commit 445480be8d43bffb39cf739eb1be74a2a3897333 Author: intrigeri Date: Fri Sep 23 01:17:05 2011 +0200 Remove obsolete perlcritic configuration. commit a6320860b1229c4978feb70d2d17da32624e106c Author: intrigeri Date: Fri Sep 23 01:13:16 2011 +0200 Convert to Any::Moose. ... and save 23MB vsz / 11MB rss runtime memory. commit 894e244aba57b98d6eda70f72136a8e50688230f Author: intrigeri Date: Thu Sep 22 23:04:55 2011 +0200 TODO update. commit 2715e8e839283a823c5311fa1fd0265e526db19f Author: intrigeri Date: Thu Sep 22 23:02:13 2011 +0200 Convert A::P::Daemon from MooseX::Daemonize to MooseX::App::Cmd. ... and save 32MB vsz / 15MB rss memory at runtime. commit fa89f70abc6f66c75a4ae4cd65351ba0402aab64 Author: intrigeri Date: Thu Sep 22 18:10:08 2011 +0200 Update TODO wrt. memory usage. commit 10695a5b6bc9c8864138c85356183be698019da1 Author: intrigeri Date: Thu Sep 22 18:03:44 2011 +0200 Remove obsolete dependency on MooseX::Declare. commit ce34c1ac214880c966b81aede2741f32ed9dfde2 Author: intrigeri Date: Thu Sep 22 18:03:24 2011 +0200 Convert A::P::Applet from MooseX::Declare to plain Moose. This saves 25MB (vsz) / 16MB (rss) memory at runtime. commit 3577afda0d32419ef8db1ae8047b24dfd58bcce9 Author: intrigeri Date: Thu Sep 22 17:21:48 2011 +0200 Migrate A::P::Daemon from MooseX::Declare to plain Moose. ... and save 15MB rss / 20MB vsz runtime memory. commit d98acabb65aef2487894983e9d78e203a388a9f0 Author: intrigeri Date: Thu Sep 22 17:16:16 2011 +0200 Move initialization code outside of useless BEGIN block. commit 210d1450cf013349e87a9160c1e9e3eaa3b49919 Author: intrigeri Date: Thu Sep 22 17:00:16 2011 +0200 Fix name of role in POD. commit 6e9642c721922019337b38301f5fca6642c4272b Author: intrigeri Date: Thu Sep 22 16:58:08 2011 +0200 Convert tiny roles to plain Moose. ... and save some more memory usage. commit f8dd13294f04d675cc9a95fbe042e7f265508fc6 Author: intrigeri Date: Thu Sep 22 16:26:28 2011 +0200 Convert App::Parcimonie::GnuPG::Interface to Any::Moose. ... and save a dozen MB rss/vsz memory at runtime. commit a965a916c0be58f9e5e3cce078de18a81886a3df Author: intrigeri Date: Thu Sep 22 15:57:07 2011 +0200 Remove support for controlling Tor. Don't send NEWNYM anymore. We now sleep long enough for the Tor circuit previously used expires. Therefore, we can greatly simplify parcimonie code, configuration, and system interaction, by avoiding talking to the Tor control port/socket at all. commit 71ec552e1c5294d373599b8c993d743921706b96 Author: intrigeri Date: Thu Sep 22 15:52:21 2011 +0200 New setting: minimum_lapse_time, defaulting to Tor default MaxCircuitDirtiness. That is: 600 seconds. commit 7a1831758f8de3ee208b67471329b3a5e4e21c38 Author: intrigeri Date: Wed Sep 7 11:29:19 2011 +0200 Tiny design document update. ========================================== 2011-08-20 16:08:08 +0200 parcimonie_0.5.2 ========================================== commit eb6072c02866ec96a5f1146e528e468698c82a2e Author: intrigeri Date: Sat Aug 20 16:08:08 2011 +0200 Releasing parcimonie 0.5.2 commit 514460b032004aaa074d994014b9ce2f861f764c Author: intrigeri Date: Sat Aug 20 15:59:37 2011 +0200 Update keyserver configuration instructions. hkps://keys.indymedia.org/ stopped using a SSL certificate signed by CaCert => document hkp://keys.indymedia.org for the simple, out-of-the-box configuration, and point to Indymedia and Mayfirst keyserver help pages on the web for hkps:// instructions. commit f647bd4428dde367a1e877542f3047cf5925201e Author: intrigeri Date: Mon Aug 15 20:02:47 2011 +0200 Fix dependency: Gtk2 1.222 is enough. Since 1.223 is not in Debian Squeeze, this made backporting slightly painful. commit 684b3840bd2d53089fc5b9cd056f73752d4c94b2 Author: intrigeri Date: Sun Aug 14 19:46:52 2011 +0200 Look up keys using the full fingerprint, instead of long key ID. This reduces the likelihood of extraneous keys being downloaded and added to a user's keyring. Thanks to Paul Wise for reporting it as Debian bug #637018. commit 5c7209571646b8d6631a5100b49d2b368828a977 Author: intrigeri Date: Sun Aug 14 19:17:33 2011 +0200 Documentation: make it clear the torrc settings depend on the Tor version. commit b7ba9f0f36c07820a23591481126add3c15c2879 Author: intrigeri Date: Sat Jul 30 17:02:01 2011 +0200 Set strict permissions on GnuPG test home directories. Else the test suite fails unless the build/test user's umask is strict enough. ========================================== 2011-07-29 15:14:06 +0200 parcimonie_0.5.1 ========================================== commit 3b63337b952d6442ec504b8bc9215c9ef4354632 Author: intrigeri Date: Fri Jul 29 15:14:06 2011 +0200 Releasing parcimonie 0.5.1 commit 9472807c0dcb94e59dc9c3f539c0ffc65184ad2d Author: intrigeri Date: Fri Jul 29 15:12:07 2011 +0200 Update TODO. commit 43b03aabf8c278ca83c6455ac8ec9cc07a4d6ff4 Author: intrigeri Date: Tue Jul 26 16:28:43 2011 +0200 Update doc wrt. new location of control socket and authentication cookie. commit 10d2620f96c8621aa32250e174c78d0fe2e87a23 Author: intrigeri Date: Tue Jul 26 16:28:22 2011 +0200 Use new Debian default location for ControlSocket and CookieAuthFile. commit 418ec216ff5a5a5eff0908a91fc763c577683707 Author: intrigeri Date: Tue Jul 26 16:20:21 2011 +0200 Document how Tor must be configured. ======================================== 2011-07-25 18:01:49 +0200 parcimonie_0.5 ======================================== commit 19a3978679081e8fc2d7af4a7abe655d109db7c9 Author: intrigeri Date: Mon Jul 25 18:01:49 2011 +0200 Releasing parcimonie 0.5 commit f38d9daacd7c24508935b60ef081c662d3d95421 Author: intrigeri Date: Mon Jul 25 17:44:16 2011 +0200 TODO update. commit 0438acc2b623fb49d206fee161bcb571b69412b5 Author: intrigeri Date: Mon Jul 25 17:43:37 2011 +0200 Document how hkpms:// can be used with parcimonie. commit 6bcc14a1654e5955234ecfa6b2f6279bc2a4eab3 Author: intrigeri Date: Mon Jul 25 17:36:01 2011 +0200 Add a --gnupg-already-torified daemon option. commit 725a48724a35fc4dc5972055c4e46b3aaea60bd6 Author: intrigeri Date: Mon Jul 25 17:35:21 2011 +0200 G::I: add an already_torified attribute. When passed, the torifying wrapper is not used. commit 1bef6df0254c76350df1cf31751818379b168232 Author: intrigeri Date: Mon Jul 25 12:38:48 2011 +0200 Really fix the ever-growing gpg command-line bug, again. commit bde425515c782bad19efa34572fe96da2737430d Author: intrigeri Date: Mon Jul 25 11:36:41 2011 +0200 Filter out libtorsocks error messages. commit 801cdac08907e3925b3a465a5890db0bb7ba2a1e Author: intrigeri Date: Mon Jul 25 11:35:18 2011 +0200 Only capture gpg's stderr. This workarounds the "gpg's stdout or stderr is blocked because the other's pipe buffer is full but we read both in a single time at the end". commit fbce2d4a1e56693becabeaaebd92437f5635e4ed Author: intrigeri Date: Sun Jul 24 17:03:51 2011 +0200 Fix spelling. ======================================== 2011-07-24 16:58:50 +0200 parcimonie_0.4 ======================================== commit 359865824bf324c8fd2a600cbae8ec9e517b89b1 Author: intrigeri Date: Sun Jul 24 16:39:54 2011 +0200 Releasing parcimonie 0.4 commit 10b2cbd1d9ac15d091d874d77e3afb131fd52b03 Author: intrigeri Date: Sun Jul 24 12:54:19 2011 +0200 TODO update. commit a29150a6adf85d2039906212a1841b14ef87ca28 Author: intrigeri Date: Sun Jul 24 16:57:17 2011 +0200 init_control_tor_with: short-circuit if running in test harness. commit be8f180879391f0cf7f9850751480eba7f342a64 Author: intrigeri Date: Sun Jul 24 16:37:37 2011 +0200 Update mock object accordingly to current implementation. commit a7e50344b42569a78eee4c0c086f24c45526b60e Author: intrigeri Date: Sun Jul 24 16:28:49 2011 +0200 Fix test. commit 46986c703d7dbbf5103456ddeaeb09e51befcfe5 Author: intrigeri Date: Sun Jul 24 15:56:04 2011 +0200 Bugfix: gpg command-line was infinitely growing. commit db15e5b04735754b5f68070e1fbc86609cdb68c0 Author: intrigeri Date: Sun Jul 24 15:42:03 2011 +0200 Run "torsocks gpg" using exec. commit ca84dc89ba5e86b71e83b25a5b3ccf88be42a387 Author: intrigeri Date: Sun Jul 24 15:27:51 2011 +0200 Fix HasEncoding role on older Perl. find_encoding returns an Encoding::XS object rather than a Encode::Encoding one on Debian Squeeze. commit 6782467459b9b539f6fec8e47b637101917342b8 Author: intrigeri Date: Sun Jul 24 12:53:08 2011 +0200 Support password and null Tor authentication methods. commit 0be2738a5ab5a7bfe90bf4a7a50ef0208c9ad9ce Author: intrigeri Date: Sun Jul 24 00:44:56 2011 +0200 Support connecting to Tor over the shiny new ControlSocket. commit d39b7fea4519448dcaf73d8663005f99847dcf37 Author: intrigeri Date: Sat Jul 23 22:48:50 2011 +0200 Applet: add a log viewer window. ========================================== 2011-07-22 13:27:40 +0200 parcimonie_0.3.3 ========================================== commit 8f60b5a5a799d230521f6e5c3519af3ca5e0d8ac Author: intrigeri Date: Fri Jul 22 13:27:40 2011 +0200 Releasing parcimonie 0.3.3 commit 58a269ff06f67019872b9998fe87a8106c2d4c35 Author: intrigeri Date: Fri Jul 22 00:01:53 2011 +0200 Add simple manpage source for parcimonie-torified-gpg. No support was added for it in the build system. This manpage is intended to be compiled using Pandoc. TBH, it's merely present to help the Debian packaging satisfy the Debian "every binary in /usr/bin must be shipped with a manpage" rule. commit ad9d35837c0799e62efd49a1eaec26318a69b98c Author: intrigeri Date: Mon Jul 18 19:18:50 2011 +0200 inc::My::Builder: subclass using "base" rather than MooseX::NonMoose. The latter is a bit overkill, not part of Debian Squeeze, and depends on Moose 1.15 which is not in Squeeze either => a pain to backport. ========================================== 2011-07-18 18:08:33 +0200 parcimonie_0.3.2 ========================================== commit ac0e3c53ed9a179cf5f21db7c995804a8872dc99 Author: intrigeri Date: Mon Jul 18 16:57:04 2011 +0200 Release parcimonie 0.3.2 commit 7baa40767166eca4693952cd9f3e08b87958386f Author: intrigeri Date: Mon Jul 18 18:01:50 2011 +0200 Add missing prereq on File::ShareDir. commit 0184c99f8797e862a4588a2b4a8c94d027cbc24b Author: intrigeri Date: Mon Jul 18 17:59:37 2011 +0200 Remove all CPAN URLs since parcimonie has not been published there yet. commit ba211afd40b64fa80e321ae31e20f2cff599d560 Author: intrigeri Date: Wed Jul 6 20:14:50 2011 +0200 Update TODO. commit 151ae05db3b1f03731025b26bd37814a5f991f03 Author: intrigeri Date: Thu Jul 7 11:22:48 2011 +0200 Build the public keys list in an optimized way. GnuPG::Interface's get_keys function builds a great nice list of objects and sub-objects full of features we don't need. It took 11 seconds on my devel system for 700 keys. This new implementation, with very much less features, only takes 1 second. commit 87eee40f79aa8fb92d4eeb6271c66a9322dbff77 Author: intrigeri Date: Thu Jul 7 10:56:43 2011 +0200 Reindent. commit f4251999b5026fb569ef22da2976882314620227 Author: intrigeri Date: Thu Jul 7 10:31:48 2011 +0200 Make the Encode::Encoding object persistent. Every use of Encode's decode and encode functions builds a new Encode::Encoding object; best practices recommend to build this object once and use it every time it's needed. commit af08ee0052b79fa5e9575dd712c4f6674b59e067 Author: intrigeri Date: Thu Jul 7 10:14:46 2011 +0200 Add missing MooseX::StrictConstructor. commit 9bf0f11a7c91bbf9ed817fd97b35bae28e000db5 Author: intrigeri Date: Thu Jul 7 10:01:27 2011 +0200 Move Moose role to the A::P::Role namespace. commit 330571f176ee13c50a3164448507d1030eb2769a Author: intrigeri Date: Thu Jul 7 02:48:35 2011 +0200 Update README: we now ship a Build.PL. commit 834cf1bada2d45016f5218c962e048c52018e3f2 Author: intrigeri Date: Thu Jul 7 02:45:58 2011 +0200 Disable the PodVersion Dist::Zilla plugin. commit f45bac23db99916cc5a05ef001e2a2a325dc814e Author: intrigeri Date: Mon Jul 18 16:58:08 2011 +0200 Enable the OurPkgVersion Dist::Zilla module. commit 3f8ff5fa7314df7a09405309d8d0ef1b2730060b Author: intrigeri Date: Wed Jul 6 20:16:59 2011 +0200 Fit in 80-chars width. commit 4a8cbbb24704fe0609e08dad757aeb80651eb5a6 Author: intrigeri Date: Wed Jul 6 20:15:07 2011 +0200 Reformat, document D-Bus signal args. commit d3293e8fab9e7cb987e4f7692a5dffb6c5a3b124 Author: intrigeri Date: Wed Jul 6 19:53:32 2011 +0200 Use the codeset defined by the current locale settings instead of utf-8. commit e10a43d12d4a8e94f4282f43af7b2970c7d6a372 Author: intrigeri Date: Wed Jul 6 19:09:48 2011 +0200 Display the trayicon for 10 seconds after key fetch end. commit c6cbb425ed67f9d41d993f25b51a6b8dc6fecc7d Author: intrigeri Date: Wed Jul 6 18:59:37 2011 +0200 Decode/encode from/to UTF-8 on IO boundaries. This is wrong, because we should not assume input/output are both UTF-8, but still better than what we did before. At least the applet trayicon tooltip is not double-UTF-8-encoded anymore when using a UTF-8 locale. commit 67d00d6cedef0efe34a4e4d53af7ecb4c04f22d6 Author: intrigeri Date: Wed Jul 6 18:56:31 2011 +0200 Remove obsoleted line. commit c21ef8bd751c9d34fa9987484fdaca757b1f23fe Author: intrigeri Date: Mon Jul 4 01:39:32 2011 +0200 Update TODO. commit c5769e575b4db9c79f76073aa63817590a00acb5 Author: intrigeri Date: Wed Jul 6 15:18:09 2011 +0200 Update usage documentation. commit 8576297ea2568fd4255f7e9de247f41203430bb9 Author: intrigeri Date: Mon Jul 4 13:13:31 2011 +0200 Add opt-in recording and reporting of memory usage to the applet. This is enabled iff the REPORT_MEMORY_USAGE environment variable is set to a true value. commit a2b968b3875a6e73832bfc945375876d9dc4dce6 Author: intrigeri Date: Mon Jul 4 13:02:23 2011 +0200 Add opt-in recording and reporting of memory usage to the daemon. This is enabled iff the REPORT_MEMORY_USAGE environment variable is set to a true value. commit aa280a9eef76ed531dfb302551080058fee64b75 Author: intrigeri Date: Mon Jul 4 02:00:55 2011 +0200 Deal with torNewNym failures: skip fetching a key. commit 8af17e7d18f815130081cba2324e4c8f252ec677 Author: intrigeri Date: Mon Jul 4 01:46:41 2011 +0200 Clearer error message. commit c44d0724c886b71d0f224d62408843653e634bdc Author: intrigeri Date: Mon Jul 4 01:38:41 2011 +0200 Stricter type constraint. commit 873d006fe7f9bbdaa635eb5178aaef525a4612c4 Author: intrigeri Date: Mon Jul 4 01:38:06 2011 +0200 Allow no keyserver set in gpg.conf if --gnupg-extra-arg "--keyserver=.." is used. commit 80b2d9559ee7f53447b86f2223a31561f79a6652 Author: intrigeri Date: Mon Jul 4 01:36:27 2011 +0200 Use Net::DBus mock object and connection when running in test harness. commit 599fa2aef08c8b1c882fa599cea3626cb73aa74b Author: intrigeri Date: Mon Jul 4 00:59:56 2011 +0200 Move tests that need Internet access to the end. commit 68a085a6111b01be9766c62705577a864ab0c833 Author: intrigeri Date: Mon Jul 4 00:57:29 2011 +0200 tor_ctl_host can indeed be supplied as a hostname. NetAddr::IP uses gethostbyname to get its IP. commit 8a9f58ac34abf9411b9c78a1a775099a0a6e9f16 Author: intrigeri Date: Mon Jul 4 00:44:45 2011 +0200 Consistency. commit cf30261e18a7b4de3880c183edc1c27380ba0e0a Author: intrigeri Date: Mon Jul 4 00:30:43 2011 +0200 Update error message. commit 09e56ae1295feb5a4dcfb57ad8276870ffc5a415 Author: intrigeri Date: Mon Jul 4 00:09:08 2011 +0200 Croak if needed programs cannot be found in $PATH. commit ca37f03e8610c8bf45fdd91b69c9759873594d4f Author: intrigeri Date: Sun Jul 3 14:47:31 2011 +0200 Run "torsocks gpg" instead of gpg. Implemented by sub-classing GnuPG::Interface so that its "call" attribute points to a custom wrapper called parcimonie-torified-gpg. This required adding our bin/ directory to the $PATH using FindBin, both to support running parcimonie from a Git checkout and to keep the testsuite functional. commit 65daf96b132231993ea303fe87941ddee2d112fb Author: intrigeri Date: Sun Jul 3 13:57:37 2011 +0200 TODO test now passes. commit dbe3d01e84cf37b86de4692a3f723a350a7de631 Author: intrigeri Date: Sun Jul 3 13:57:23 2011 +0200 Enhance POD. commit c39f7f07272c86f4d27a9c36f6620ed233bef788 Author: intrigeri Date: Sun Jul 3 13:57:08 2011 +0200 Add /.build to .gitignore. commit 93b8fe35b5c493319d57cba0b8c95b5b641aa9ef Author: intrigeri Date: Sun Jul 3 13:46:55 2011 +0200 Allow the user to specify arbitrary arguments that are passed to GnuPG. commit 986313f162b794460b93c94d25c60900f862449a Author: intrigeri Date: Sun Jul 3 04:31:30 2011 +0200 Update the .po files at release time, copy the .mo files to blib/ at build time. commit 6fe93a876f2466db1de86fcc9d8b7016621389cf Author: intrigeri Date: Sun Jul 3 03:26:13 2011 +0200 Dist::Zilla: move from MakeMaker to ModuleBuild. This allows more fine-grained customization by subclassing M::B. commit 22a6d159f478e46f80429aced393aff6e6a1dce7 Author: intrigeri Date: Sun Jul 3 00:55:43 2011 +0200 TODO update. commit 2f51ff43e03cfa94a6a6a405c2f539eaf2b30b5a Author: intrigeri Date: Sun Jul 3 00:57:14 2011 +0200 Cleanup obsolete strings in PO file. commit 96b6434b7f46670b83023bf5fb7089fa8cc94657 Author: intrigeri Date: Sat Jun 25 21:33:08 2011 +0200 Disable Dist::Zilla PkgVersion plugin. It conflicts with CriticTests by adding code before strictures are enabled. commit 9db74d1ab6e93ffc4bee6922d5aa897a684fc323 Author: intrigeri Date: Sat Jun 25 21:24:29 2011 +0200 Remove obsolete comment. commit dd780bed2d7225800a1637d988086d4ee4f2461a Author: intrigeri Date: Sat Jun 25 21:24:03 2011 +0200 Reindent. commit 9febd4e481fc9da328a658c0ce67aa0b61751caf Author: intrigeri Date: Sat Jun 25 21:18:18 2011 +0200 Move back gettext directory to ./po/. I did not manage to get Dist::Zilla build a Build.PL or Makefile.PL that would install the compiled .mo files to the right place. Better leave these alone, shipped as part of the dist but unfortunately not installed by "make install". And anyway, putting them into share/ had them automagically installed into the module's ShareDir, which was wrong. commit d0b3b14c24e76ff672a797d7f24852e8941be4ff Author: intrigeri Date: Sat Jun 25 21:17:05 2011 +0200 po: remove "install" target from the "all" one. commit eff455e550d1739ed8c2f38296904ca5494469f7 Author: intrigeri Date: Sat Jun 25 21:16:44 2011 +0200 po: use DESTDIR and PREFIX to build the destination install directory. commit f2d434b871e546b3a703186c12a5b61fb7a30e48 Author: intrigeri Date: Sat Jun 25 21:11:09 2011 +0200 Disable Dist::Zilla's ModuleBuild plugin. Else both Build.PL and Makefile.PL are generated, both M::B and M::I are added to the prereqs, and the testsuite is run twice. commit 1cf3b1c64836e9388ef8841029e3f476738d199d Author: intrigeri Date: Sat Jun 25 20:23:16 2011 +0200 Only the systray applet is now translatable. This will ease very much the packaging. Set the textdomain to parcimonie-applet. commit 0d35763945fe36eef7b9f263a4fa31babcb7de0f Author: intrigeri Date: Sat Jun 25 18:49:05 2011 +0200 Update gettext infrastructure to match files move. commit ac062b37a64178e98fe7c3bff07799e70797e779 Author: intrigeri Date: Sat Jun 25 18:41:44 2011 +0200 Get back our README. Dist::Zilla's one is much worse. commit 31b18471aaef494ee63c00bb8e2146d58818dde0 Author: intrigeri Date: Sat Jun 25 18:35:38 2011 +0200 Update TODO. commit b6c237e3564738e61d13085cc6fa38eaed5b0f9b Author: intrigeri Date: Sat Jun 25 18:24:54 2011 +0200 Enable the Git::Check Dist::Zilla plugin. commit 11927bdd474f41a10340f68b1b9c0b610b15d1d5 Author: intrigeri Date: Sat Jun 25 18:15:23 2011 +0200 Dist::Zilla: enable PkgVersion plugin. commit 7e4d83490e09afbd2c0a498d07288b1cbecb89ca Author: intrigeri Date: Sat Jun 25 18:08:44 2011 +0200 Cleanup from MANIFEST.SKIP stuff already done by ::PruneCruft. commit 8e90890e933c81f4de5064cc79160aebc642096e Author: intrigeri Date: Sat Jun 25 18:08:13 2011 +0200 Move .placeholder to placeholder to that it's ignored by ::PruneCruft. commit 8a7ab28ad76c7f478acd9bc65f0d671737982013 Author: intrigeri Date: Sat Jun 25 18:00:03 2011 +0200 Workaround Pod::Coverage being dumb. commit 1b097fe11d6f723cb009e6a09e1dbc4692bd2bcd Author: intrigeri Date: Sat Jun 25 17:54:03 2011 +0200 Remove duplicate version declaration. commit 14e779f1c1d59857359b4b5ae0a972ec4217662c Author: intrigeri Date: Sat Jun 25 17:46:26 2011 +0200 More complete Dist::Zilla config. commit 5ed6dbaf1e26e69f251f759b2437c6ac08a3427d Author: intrigeri Date: Sat Jun 25 17:45:38 2011 +0200 Add missing POD. commit a6500ada7a7251f85ebe5e5d97bf901fce96dff1 Author: intrigeri Date: Sat Jun 25 17:45:14 2011 +0200 Remove more cruft that will be auto-generated by Dist::Zilla. commit d502f578bc3e9db7e9dbce5ac031a83d1e791e37 Author: intrigeri Date: Sat Jun 25 17:44:48 2011 +0200 Change license to Perl 5 one. commit aa97c44e92116307f9c6d49ebc1606355e8b647c Author: intrigeri Date: Sat Jun 25 17:44:18 2011 +0200 Remove files that will be generated by dzil. commit ed2f694fb6d71b04d1e16e596ee4e852c4be7af1 Author: intrigeri Date: Fri Dec 24 12:23:04 2010 +0100 Start migrating to Dist::Zilla. Left to do: - the license is wrong (what's the way to tell GPL-3+ in Dist::Zilla jargon?) - have MANIFEST* autogenerated and stop shipping these - move dependencies and other meta-data from Makefile.PL to dist.ini, then stop shipping Makefile.PL - generate Changes from Git log - get version information automatically inserted into the main script: use the Classic plugin bundle (or the PkgVersion and PodVersion plugins) - Debian packaging should be based on a branch where dists prepared by Dist::Zilla are imported commit 940a3ed0cd3f5eec70f4b9b7f3fcb45f5baad433 Author: intrigeri Date: Sat Jun 25 15:11:50 2011 +0200 Update copyright years. commit 6c335772a152eebd59aca92b924d4acf8b08c15d Author: intrigeri Date: Sat Jun 25 14:54:12 2011 +0200 TODO update. commit 8bc0b6143f0df56389b93ae073e43df7a82dae20 Author: intrigeri Date: Sat Jun 25 14:27:16 2011 +0200 Files in share/ must not be installed into the distribution 'auto' path. => Stop using Module::Install::Share. Something better must be found. commit 2e5115e741acef60881528a8bddcf57a399ccf2d Author: intrigeri Date: Sat Jun 25 02:29:56 2011 +0200 Move data files to share/{applications,locale}. commit a39391682f7e40ba7cae7fde8a220d72accb0db9 Author: intrigeri Date: Sat Jun 25 01:32:50 2011 +0200 Update PO files. commit fcde33bd25b93c62b4b5b80a037344d7131ee3fa Author: intrigeri Date: Sat Jun 25 01:15:36 2011 +0200 Update TODO. commit 9be6791fd5a0197bcb083320a4d7e54d4344bed7 Author: intrigeri Date: Sat Jun 25 01:13:19 2011 +0200 Update French translation. commit 77bee4ee0a1a96a86cb52f4b1230be38dc7c18ec Author: intrigeri Date: Sat Jun 25 01:09:55 2011 +0200 Git, please ignore .mo files. commit af831c2f9933714ef1d8b8bf8fa682735d813f0c Author: intrigeri Date: Sat Jun 25 01:09:47 2011 +0200 Update PO files. commit aa16e2676d02b9c7d3a8242b076b77563c14b568 Author: intrigeri Date: Sat Jun 25 01:08:23 2011 +0200 Gettext-ize every ->debug call. commit b2961c16ff7b3a331499cb63f7a535cff3284863 Author: intrigeri Date: Sat Jun 25 00:58:05 2011 +0200 Migrated to the "parcimonie" text domain. commit 1b27255e9edd6bdaf725e3344b374d2d583a0af5 Author: intrigeri Date: Sat Jun 25 00:52:56 2011 +0200 Updated PO files. commit 3224ee07f4f8e90cc3588fca11d91a5845956457 Author: intrigeri Date: Sat Jun 25 00:52:46 2011 +0200 Add TRANSLATORS: help messages. commit e3271c6e0fcaf745a18d33b9739d07376e1bb79b Author: intrigeri Date: Sat Jun 25 00:47:40 2011 +0200 Generate .pot and .po files. commit 1fceeb26f715f7b7880d987d86921e3b6ef0f40b Author: intrigeri Date: Sat Jun 25 00:42:43 2011 +0200 Bootstrap gettext po directory. The infrastructure was cargo-culted from libintl-perl's simplecal example. commit 4b8918a21e74291a05ecba5eb979444bb683688b Author: intrigeri Date: Fri Jun 24 22:05:34 2011 +0200 Fix background daemon mode. For some unknown reason, entering the D-Bus mainloop kills the daemon when run in the background. Workaround'ed by setting MooseX::Daemonize's attribute dont_close_all_files to true. ========================================== 2011-06-24 14:10:28 +0200 parcimonie_0.3.1 ========================================== commit e2af492206b17445448e0d5cea9fbf4161ea4977 Author: intrigeri Date: Fri Jun 24 00:41:01 2011 +0200 Releasing parcimonie 0.3.1 commit da13cf064ab9152d69360cfef63f86fabfd52a1b Author: intrigeri Date: Fri Jun 24 14:09:10 2011 +0200 Don't run tests that need X unless $DISPLAY is set. commit 0924450987fea64bf5eeb9528536109600a20535 Author: intrigeri Date: Fri Jun 24 13:57:39 2011 +0200 Add missing dependency. commit 362e281b88993f6240133eedd82c3ac89fb5a55e Author: intrigeri Date: Fri Jun 24 13:45:31 2011 +0200 Add Makefile.PL and META.yml to the MANIFEST. Else they are not shipped in released dist tarballs. commit e8a5a8f4df6b14a5595d48433ada95bfd7695a02 Author: intrigeri Date: Fri Jun 24 13:08:46 2011 +0200 Update TODO. commit 29437708d636839e630c3fdffe738eedd66a921d Author: intrigeri Date: Fri Jun 24 00:40:00 2011 +0200 Import .desktop files from the Debian packaging. Those can be useful to non-Debian users as well. Install them into the share directory. ===================================== End of changes in the last 99999 days ===================================== App-Parcimonie-0.8/LICENSE0000644000175200017520000004364212253322520015755 0ustar intrigeriintrigeriThis software is copyright (c) 2013 by intrigeri. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. Terms of the Perl programming language system itself a) the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version, or b) the "Artistic License" --- The GNU General Public License, Version 1, February 1989 --- This software is Copyright (c) 2013 by intrigeri. This is free software, licensed under: The GNU General Public License, Version 1, February 1989 GNU GENERAL PUBLIC LICENSE Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. 51 Franklin St, Suite 500, Boston, MA 02110-1335 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of a such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as "you". 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 2. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this General Public License. d) You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 3. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: a) accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 4. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 5. By copying, distributing or modifying the Program (or any work based on the Program) you indicate your acceptance of this license to do so, and all its terms and conditions. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. 7. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of the license which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the license, you may choose any version ever published by the Free Software Foundation. 8. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to humanity, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy 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 1, 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19xx name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice That's all there is to it! --- The Artistic License 1.0 --- This software is Copyright (c) 2013 by intrigeri. This is free software, licensed under: The Artistic License 1.0 The Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: - "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. - "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. - "Copyright Holder" is whoever is named in the copyright or copyrights for the package. - "You" is you, if you're thinking about copying or distributing this Package. - "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) - "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) accompany any non-standard executables with their corresponding Standard Version executables, giving the non-standard executables non-standard names, and clearly documenting the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. C or perl subroutines supplied by you and linked into this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End App-Parcimonie-0.8/README0000600000175200017520000000134312253322520015610 0ustar intrigeriintrigeriApp-Parcimonie INSTALLATION ============ Debian and derivative distributions ----------------------------------- parcimonie is part of Debian testing/unstable. Standalone ---------- To manually install parcimonie, run the following commands: perl Build.PL ./Build ./Build test ./Build install SUPPORT AND DOCUMENTATION ========================= After installing, you can find documentation for parcimonie with the man command: man parcimonie You can also look for information at: parcimonie's homepage https://gaffer.ptitcanardnoir.org/intrigeri/code/parcimonie/ LICENSE AND COPYRIGHT ===================== Copyright (C) 2010-2013 intrigeri This program is released under the same terms as Perl itself. App-Parcimonie-0.8/TODO0000600000175200017520000000463512253322520015427 0ustar intrigeriintrigeri* Robustness++ - The applet does not get the daemon signals anymore after the latter was restarted. It should periodically check if it's still connected to the daemon's D-Bus signals, and try to reconnect if needed. - Don't wait indefinitely for spawned gpg processes. Somehow timeout. * User feedback - custom applet icons Inspiration: /usr/share/icons/hicolor/48x48/status/aptdaemon-add.png /usr/share/icons/hicolor/48x48/status/aptdaemon-cleanup.png /usr/share/icons/hicolor/48x48/status/aptdaemon-delete.png /usr/share/icons/hicolor/48x48/status/aptdaemon-download.png /usr/share/icons/hicolor/48x48/status/aptdaemon-resolve.png /usr/share/icons/hicolor/48x48/status/aptdaemon-update-cache.png /usr/share/icons/hicolor/48x48/status/aptdaemon-upgrade.png /usr/share/icons/hicolor/48x48/status/aptdaemon-wait.png /usr/share/icons/hicolor/48x48/status/aptdaemon-working.png and background: /usr/share/icons/hicolor/48x48/apps/seahorse.png - log/tooltip message: tell "parcimonie is resting until $TIME" rather than just "Resting" - avoid passing "at .../../xxx.pm" in the signal message - non-desktop log viewer: Either log to syslog instead of sending D-Bus signals, or fork a tiny D-Bus signal receiver + dispatcher early in the main daemon startup process. - painful torsocks "error" output filtering does not work * l10n/i18n: - documentation for translators * Add functional tests, probably using Test::Trap. * Write design documentation: threat and risk models, hypothesis, etc. * Debian packaging - Split into two binary packages: parcimonie and parcimonie-applet * Make sure an update is attempted for every key on a regular basis. Remember last time a given key update has been attempted, and randomly pick the key to update among the oldest-updated keys. Beware: key update attempt time shall be recorded instead of successful key update time, else there is a risk to loop trying to update keys that are not available on the keyserver. * Improve tests coverage - App::Parcimonie::Role::HasEncoding and App::Parcimonie::Role::HasCodeset could be quite easily tested * Bug: starting parcimonie outside of X fails org.freedesktop.DBus.Error.Spawn.ExecFailed: /usr/bin/dbus-launch terminated abnormally with the following error: Autolaunch error: X11 initialization failed. * Test suite: configure, use and run Tor