perl/keyring/kdewallet / lib / Passwd / Keyring /

Full commit
package Passwd::Keyring::KDEWallet;

use warnings;
use strict;
#use parent 'Keyring';
use Net::DBus;
use Carp;

=head1 NAME

Passwd::Keyring::KDEWallet - Password storage implementation based on KDE Wallet.

=head1 VERSION

Version 0.21


our $VERSION = '0.21';

our $APP_NAME = "Passwd::Keyring";
our $FOLDER_NAME = "Perl-Passwd-Keyring";


KDE Wallet based implementation of L<Passwd::Keyring>.

    use Passwd::Keyring::KDEWallet;

    my $keyring = Passwd::Keyring::KDEWallet->new(app=>"My beautiful app", group=>"My app web passwords");

    $keyring->set_password("John", "verysecret", "my-pseudodomain");
    # And later, on next run maybe
    my $password = $keyring->get_password("John", "my-pseudodomain");
    # plus
    $keyring->clear_password("John", "my-pseudodomain");


=head2 new

Initializes the processing. Croaks if kwallet does not 
seem to be available.


sub new {
    my ($cls, %args) = @_;

    my $self = {};
    $self->{app} = $args{app} || 'Passwd::Keyring::KDEWallet';
    $self->{group} = $args{group} || 'Passwd::Keyring::default';
    bless $self;

    #$self->{bus} = Net::DBus->find()
    $self->{bus} = Net::DBus->session()
      or croak("KWallet not available (can't access DBus)");
    my $kwallet_svc = $self->{bus}->get_service('org.kde.kwalletd')
      or croak("KWallet not available (can't access KWallet, likely kwalletd not running)");
    $self->{kwallet} = $kwallet_svc->get_object('/modules/kwalletd', 'org.kde.KWallet')
      or croak("Kwallet not available (can't find wallet)");

    unless($self->{kwallet}->hasFolder($self->{handle}, $self->{group}, $self->{app})) {
        $self->{kwallet}->createFolder($self->{handle}, $self->{group}, $self->{app})
          or croak("Failed to create $self->{group} folder (app $self->{app})");

    return $self;

sub _open_if_not_open {
    my $self = shift;

    if($self->{handle}) {
        if($self->{kwallet}->isOpen($self->{handle})) {
    my $net_wallet = $self->{kwallet}->networkWallet()
      or croak("Kwallet not available (can't access network wallet");
    $self->{handle} = $self->{kwallet}->open($net_wallet, 0, $self->{app})
      or croak("Failed to open the KDE wallet");

=head2 set_password(username, password, domain)

Sets (stores) password identified by given domain for given user 


sub set_password {
    my ($self, $user_name, $user_password, $domain) = @_;
    my $status = $self->{kwallet}->writePassword(
        $self->{handle}, $self->{group}, "$domain || $user_name", $user_password, $self->{app});
    if($status) { # non-zero means failure
        croak("Failed to save the password (status $status, user name $user_name, domain $domain, handle $self->{handle}, group $self->{group})");

=head2 get_password($user_name, $domain)

Reads previously stored password for given user in given app.
If such password can not be found, returns undef.


sub get_password {
    my ($self, $user_name, $domain) = @_;
    my $reply = $self->{kwallet}->readPassword(
        $self->{handle}, $self->{group}, "$domain || $user_name", $self->{app});
    return $reply;

=head2 clear_password($user_name, $domain)

Removes given password (if present)


sub clear_password {
    my ($self, $user_name, $domain) = @_;
    my $status = $self->{kwallet}->removeEntry(
        $self->{handle}, $self->{group}, "$domain || $user_name", $self->{app});
    if($status >= 0) {
        return 1;
    } else {
        # TODO: classify failures
        return 0;

=head2 is_persistent

Returns info, whether this keyring actually saves passwords persistently.

(true in this case)


sub is_persistent {
    my ($self) = @_;
    return 1;

=head1 AUTHOR

Marcin Kasperski, C<< <Marcin.Kasperski at> >>

Code heavily inspired by L<>
and partially by python keyring.

=head1 BUGS

Please report any bugs or feature requests to 
issue tracker at L<>.

=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Passwd::Keyring::KDEWallet

You can also look for information at:



Copyright 2010-2012 Marcin Kasperski.

This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.

See for more information.


1; # End of Passwd::Keyring::KDEWallet