sailfish-safe

Sailfish frontend for safe(1)
git clone git://git.z3bra.org/sailfish-safe.git
Log | Files | Refs | README | LICENSE

passwordprovider.cpp (4002B)


      1 /*
      2  *   Copyright (C) 2018  Daniel Vrátil <dvratil@kde.org>
      3  *                 2021  Willy Goiffon <contact@z3bra.org>
      4  *
      5  *   This program is free software; you can redistribute it and/or modify
      6  *   it under the terms of the GNU Library General Public License as
      7  *   published by the Free Software Foundation; either version 2, or
      8  *   (at your option) any later version.
      9  *
     10  *   This program is distributed in the hope that it will be useful,
     11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  *   GNU General Public License for more details
     14  *
     15  *   You should have received a copy of the GNU Library General Public
     16  *   License along with this program; if not, write to the
     17  *   Free Software Foundation, Inc.,
     18  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
     19  */
     20 
     21 #include "passwordprovider.h"
     22 #include "settings.h"
     23 #include "safe.h"
     24 
     25 #include <QClipboard>
     26 #include <QGuiApplication>
     27 #include <QDir>
     28 #include <QDebug>
     29 
     30 namespace {
     31 
     32 static const auto PasswordTimeoutUpdateInterval = 100;
     33 
     34 
     35 #define SAFE_DIR "SAFE_DIR"
     36 #define SAFE_SOCK "SAFE_SOCK"
     37 
     38 }
     39 
     40 PasswordProvider::PasswordProvider(const QString &path, QObject *parent)
     41     : QObject(parent)
     42     , mPath(path)
     43 {}
     44 
     45 
     46 PasswordProvider::~PasswordProvider()
     47 {}
     48 
     49 bool PasswordProvider::isValid() const
     50 {
     51     return !mPassword.isNull();
     52 }
     53 
     54 QString PasswordProvider::password() const
     55 {
     56     return mPassword;
     57 }
     58 
     59 void PasswordProvider::setPassword(const QString &password)
     60 {
     61     qGuiApp->clipboard()->setText(password, QClipboard::Clipboard);
     62 
     63     if (qGuiApp->clipboard()->supportsSelection()) {
     64         qGuiApp->clipboard()->setText(password, QClipboard::Selection);
     65     }
     66 
     67     mPassword = password;
     68     Q_EMIT validChanged();
     69     Q_EMIT passwordChanged();
     70 
     71     mTimeout = defaultTimeout();
     72     Q_EMIT timeoutChanged();
     73     mTimer.start();
     74 }
     75 
     76 void PasswordProvider::expirePassword()
     77 {
     78     removePasswordFromClipboard(mPassword);
     79 
     80     mPassword.clear();
     81     mTimer.stop();
     82     Q_EMIT validChanged();
     83     Q_EMIT passwordChanged();
     84 
     85     // Delete the provider, it's no longer needed
     86     deleteLater();
     87 }
     88 
     89 void PasswordProvider::requestPassword()
     90 {
     91     setError({});
     92     mPassword.clear();
     93     mTimer.stop();
     94     Q_EMIT validChanged();
     95     Q_EMIT passwordChanged();
     96 
     97     auto *job = Safe::decrypt(mPath);
     98     connect(job, &Safe::DecryptTask::finished,
     99         this, [this, job]() {
    100             if (job->error()) {
    101                 qWarning() << "Failed to unlock safe: " << job->errorString();
    102                 setError(job->errorString());
    103                 return;
    104             }
    105         // .split() always return one argument, so it's used here to remove
    106         // trailing \n if any, or keep the whole content otherwise
    107         const QStringList lines = job->content().split(QLatin1Char('\n'));
    108         setPassword(lines[0]);
    109         qDebug() << "requestPassword() got: " << lines[0];
    110     });
    111 
    112     mTimer.setInterval(PasswordTimeoutUpdateInterval);
    113     connect(&mTimer, &QTimer::timeout,
    114             this, [this]() {
    115                 mTimeout -= mTimer.interval();
    116                 Q_EMIT timeoutChanged();
    117                 if (mTimeout == 0) {
    118                     expirePassword();
    119                 }
    120             });
    121 }
    122 
    123 int PasswordProvider::timeout() const
    124 {
    125     return mTimeout;
    126 }
    127 
    128 int PasswordProvider::defaultTimeout() const
    129 {
    130     return Settings::self()->expirationTimeout() * 1000;
    131 }
    132 
    133 QString PasswordProvider::error() const
    134 {
    135     return mError;
    136 }
    137 
    138 bool PasswordProvider::hasError() const
    139 {
    140     return !mError.isNull();
    141 }
    142 
    143 void PasswordProvider::setError(const QString &error)
    144 {
    145     mError = error;
    146     Q_EMIT errorChanged();
    147 }
    148 
    149 void PasswordProvider::cancel()
    150 {
    151     setError(tr("Cancelled by user."));
    152 }
    153 
    154 void PasswordProvider::removePasswordFromClipboard(const QString &password)
    155 {
    156     // Clear the WS clipboard itself
    157     const auto clipboard = qGuiApp->clipboard();
    158     if (clipboard->text() == password) {
    159         clipboard->clear();
    160     }
    161 }