summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortezeb <tezeb+github@outoftheblue.pl>2016-12-04 22:43:17 +0100
committertezeb <tezeb+github@outoftheblue.pl>2016-12-04 22:43:17 +0100
commitb11e71d331310c27fde3e53a098ba108bc8f0f61 (patch)
tree41b32b214ec97a11b131aab221bf687c59125e64
parentaa0eb00e50d732a7fc00fd56b2c10d41a2053a7c (diff)
Use new executor in Pass
-rw-r--r--imitatepass.cpp168
-rw-r--r--imitatepass.h13
-rw-r--r--mainwindow.cpp246
-rw-r--r--mainwindow.h12
-rw-r--r--pass.cpp176
-rw-r--r--pass.h55
-rw-r--r--qtpass.pro8
-rw-r--r--realpass.cpp90
-rw-r--r--realpass.h9
9 files changed, 393 insertions, 384 deletions
diff --git a/imitatepass.cpp b/imitatepass.cpp
index ace52ff7..65f1aceb 100644
--- a/imitatepass.cpp
+++ b/imitatepass.cpp
@@ -1,47 +1,80 @@
#include "imitatepass.h"
+#include "debughelper.h"
#include "mainwindow.h"
#include "qtpasssettings.h"
ImitatePass::ImitatePass() {}
+void ImitatePass::executeWrapper(int id, const QString &app,
+ const QStringList &args, bool readStdout,
+ bool readStderr) {
+ executeWrapper(id, app, args, QString(), readStdout, readStderr);
+}
+
+void ImitatePass::executeWrapper(int id, const QString &app,
+ const QStringList &args, QString input,
+ bool readStdout, bool readStderr) {
+ QString d;
+ for (auto &i : args)
+ d += " " + i;
+ dbg() << app << d;
+ exec.execute(id, QtPassSettings::getPassStore(), app, args, input, readStdout,
+ readStderr);
+}
+
/**
* @brief ImitatePass::GitInit git init wrapper
*/
void ImitatePass::GitInit() {
- executeWrapper(QtPassSettings::getGitExecutable(),
- "init \"" + QtPassSettings::getPassStore() + '"');
+ executeWrapper(GIT_INIT, QtPassSettings::getGitExecutable(),
+ {"init", QtPassSettings::getPassStore()});
}
/**
* @brief ImitatePass::GitPull git init wrapper
*/
void ImitatePass::GitPull() {
- executeWrapper(QtPassSettings::getGitExecutable(), "pull");
+ executeWrapper(GIT_PULL, QtPassSettings::getGitExecutable(), {"pull"});
+}
+
+/**
+ * @brief ImitatePass::GitPull_b git pull wrapper
+ */
+void ImitatePass::GitPull_b() {
+ exec.executeBlocking(QtPassSettings::getGitExecutable(), {"pull"});
}
/**
* @brief ImitatePass::GitPush git init wrapper
*/
void ImitatePass::GitPush() {
- executeWrapper(QtPassSettings::getGitExecutable(), "push");
+ executeWrapper(GIT_PUSH, QtPassSettings::getGitExecutable(), {"push"});
}
/**
- * @brief ImitatePass::Show git init wrapper
+ * @brief ImitatePass::Show shows content of file
*/
-QProcess::ExitStatus ImitatePass::Show(QString file, bool block) {
+void ImitatePass::Show(QString file) {
// TODO(bezet): apparently not yet needed
// file += ".gpg";
- executeWrapper(QtPassSettings::getGpgExecutable(),
- "-d --quiet --yes --no-encrypt-to --batch --use-agent \"" +
- file + '"');
- if (block)
- return waitForProcess();
- return QProcess::NormalExit;
+ QStringList args = {"-d", "--quiet", "--yes", "--no-encrypt-to",
+ "--batch", "--use-agent", file};
+ executeWrapper(PASS_SHOW, QtPassSettings::getGpgExecutable(), args);
}
/**
- * @brief ImitatePass::Insert git init wrapper
+ * @brief ImitatePass::Show_b show content of file, blocking version
+ *
+ * @returns process exitCode
+ */
+int ImitatePass::Show_b(QString file) {
+ QStringList args = {"-d", "--quiet", "--yes", "--no-encrypt-to",
+ "--batch", "--use-agent", file};
+ return exec.executeBlocking(QtPassSettings::getGpgExecutable(), args);
+}
+
+/**
+ * @brief ImitatePass::Insert create new file with encrypted content
*
* @param file file to be created
* @param value value to be stored in file
@@ -50,7 +83,7 @@ QProcess::ExitStatus ImitatePass::Show(QString file, bool block) {
void ImitatePass::Insert(QString file, QString newValue, bool overwrite) {
file += ".gpg";
// TODO(bezet): getRecipientString is in MainWindow for now - fix this ;)
- QString recipients = Pass::getRecipientString(file, " -r ");
+ QStringList recipients = Pass::getRecipientList(file);
if (recipients.isEmpty()) {
// TODO(bezet): probably throw here
emit critical(tr("Can not edit"),
@@ -58,36 +91,43 @@ void ImitatePass::Insert(QString file, QString newValue, bool overwrite) {
"file missing or invalid."));
return;
}
- QString force(overwrite ? " --yes " : " ");
- executeWrapper(QtPassSettings::getGpgExecutable(),
- force + "--batch -eq --output \"" + file + "\" " + recipients +
- " -",
+ QStringList args = {"--batch", "-eq", "--output", file};
+ for (auto &r : recipients) {
+ args.append("-r");
+ args.append(r);
+ };
+ if (overwrite)
+ args.append("--yes");
+ args.append("-");
+ executeWrapper(PASS_INSERT, QtPassSettings::getGpgExecutable(), args,
newValue);
if (!QtPassSettings::isUseWebDav() && QtPassSettings::isUseGit()) {
if (!overwrite)
- executeWrapper(QtPassSettings::getGitExecutable(), "add \"" + file + '"');
+ executeWrapper(GIT_ADD, QtPassSettings::getGitExecutable(),
+ {"add", file});
QString path = QDir(QtPassSettings::getPassStore()).relativeFilePath(file);
path.replace(QRegExp("\\.gpg$"), "");
- executeWrapper(QtPassSettings::getGitExecutable(),
- "commit \"" + file + "\" -m \"" +
- (overwrite ? "Edit" : "Add") + " for " + path +
- " using QtPass.\"");
+ QString msg = QString(overwrite ? "Edit" : "\"Add") + " for " + path +
+ " using QtPass.";
+ GitCommit(file, msg);
}
}
+void ImitatePass::GitCommit(const QString &file, const QString &msg) {
+ executeWrapper(GIT_COMMIT, QtPassSettings::getGitExecutable(),
+ {"commit", "-m", msg, "--", file});
+}
+
/**
* @brief ImitatePass::Remove git init wrapper
*/
void ImitatePass::Remove(QString file, bool isDir) {
if (QtPassSettings::isUseGit()) {
- executeWrapper(QtPassSettings::getGitExecutable(),
- QString("rm ") + (isDir ? "-rf " : "-f ") + '"' + file +
- '"');
+ executeWrapper(GIT_RM, QtPassSettings::getGitExecutable(),
+ {"rm", (isDir ? "-rf" : "-f"), file});
// TODO(bezet): commit message used to have pass-like file name inside(ie.
// getFile(file, true)
- executeWrapper(QtPassSettings::getGitExecutable(),
- "commit \"" + file + "\" -m \"Remove for " + file +
- " using QtPass.\"");
+ GitCommit(file, "Remove for " + file + " using QtPass.");
} else {
if (isDir) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
@@ -105,7 +145,8 @@ void ImitatePass::Remove(QString file, bool isDir) {
* @brief ImitatePass::Init initialize pass repository
*
* @param path path in which new password-store will be created
- * @param users list of users who shall be able to decrypt passwords in path
+ * @param users list of users who shall be able to decrypt passwords in
+ * path
*/
void ImitatePass::Init(QString path, const QList<UserInfo> &users) {
QString gpgIdFile = path + ".gpg-id";
@@ -140,13 +181,11 @@ void ImitatePass::Init(QString path, const QList<UserInfo> &users) {
if (!QtPassSettings::isUseWebDav() && QtPassSettings::isUseGit() &&
!QtPassSettings::getGitExecutable().isEmpty()) {
if (addFile)
- executeWrapper(QtPassSettings::getGitExecutable(),
- "add \"" + gpgIdFile + '"');
+ executeWrapper(GIT_ADD, QtPassSettings::getGitExecutable(),
+ {"add", gpgIdFile});
QString path = gpgIdFile;
path.replace(QRegExp("\\.gpg$"), "");
- executeWrapper(QtPassSettings::getGitExecutable(),
- "commit \"" + gpgIdFile + "\" -m \"Added " + path +
- " using QtPass.\"");
+ GitCommit(gpgIdFile, "Added " + path + " using QtPass.");
}
reencryptPath(path);
}
@@ -191,10 +230,8 @@ void ImitatePass::reencryptPath(QString dir) {
if (QtPassSettings::isAutoPull()) {
// TODO(bezet): move statuses inside actions?
emit statusMsg(tr("Updating password-store"), 2000);
- GitPull();
+ GitPull_b();
}
- waitFor(50);
- process.waitForFinished();
QDir currentDir;
QDirIterator gpgFiles(dir, QStringList() << "*.gpg", QDir::Files,
QDirIterator::Subdirectories);
@@ -205,16 +242,14 @@ void ImitatePass::reencryptPath(QString dir) {
gpgId = getRecipientList(fileName);
gpgId.sort();
}
- process.waitForFinished();
- executeWrapper(QtPassSettings::getGpgExecutable(),
- "-v --no-secmem-warning "
- "--no-permission-warning --list-only "
- "--keyid-format long " +
- fileName);
- process.waitForFinished(3000);
+ // TODO(bezet): enable --with-colons for better future-proofness?
+ QStringList args = {
+ "-v", "--no-secmem-warning", "--no-permission-warning",
+ "--list-only", "--keyid-format=long", fileName};
+ QString keys, err;
+ exec.executeBlocking(QtPassSettings::getGpgExecutable(), args, &keys, &err);
QStringList actualKeys;
- QString keys =
- process.readAllStandardOutput() + process.readAllStandardError();
+ keys += err;
QStringList key = keys.split("\n");
QListIterator<QString> itr(key);
while (itr.hasNext()) {
@@ -230,14 +265,13 @@ void ImitatePass::reencryptPath(QString dir) {
actualKeys.sort();
if (actualKeys != gpgId) {
// dbg()<< actualKeys << gpgId << getRecipientList(fileName);
- dbg()<< "reencrypt " << fileName << " for " << gpgId;
+ dbg() << "reencrypt " << fileName << " for " << gpgId;
QString local_lastDecrypt = "Could not decrypt";
emit lastDecrypt(local_lastDecrypt);
- executeWrapper(QtPassSettings::getGpgExecutable(),
- "-d --quiet --yes --no-encrypt-to --batch --use-agent \"" +
- fileName + '"');
- process.waitForFinished(30000); // long wait (passphrase stuff)
- local_lastDecrypt = process.readAllStandardOutput();
+ args = QStringList{"-d", "--quiet", "--yes", "--no-encrypt-to",
+ "--batch", "--use-agent", fileName};
+ exec.executeBlocking(QtPassSettings::getGpgExecutable(), args,
+ &local_lastDecrypt);
emit lastDecrypt(local_lastDecrypt);
if (!local_lastDecrypt.isEmpty() &&
@@ -246,33 +280,35 @@ void ImitatePass::reencryptPath(QString dir) {
local_lastDecrypt += "\n";
emit lastDecrypt(local_lastDecrypt);
- QString recipients = getRecipientString(fileName, " -r ");
+ QStringList recipients = Pass::getRecipientList(fileName);
if (recipients.isEmpty()) {
emit critical(tr("Can not edit"),
tr("Could not read encryption key to use, .gpg-id "
"file missing or invalid."));
return;
}
- executeWrapper(QtPassSettings::getGpgExecutable(),
- "--yes --batch -eq --output \"" + fileName + "\" " +
- recipients + " -",
- local_lastDecrypt);
- process.waitForFinished(3000);
+ args = QStringList{"--yes", "--batch", "-eq", "--output", fileName};
+ for (auto &i : recipients) {
+ args.append("-r");
+ args.append(i);
+ }
+ args.append("-");
+ exec.executeBlocking(QtPassSettings::getGpgExecutable(), args,
+ local_lastDecrypt);
if (!QtPassSettings::isUseWebDav() && QtPassSettings::isUseGit()) {
- executeWrapper(QtPassSettings::getGitExecutable(),
- "add \"" + fileName + '"');
+ exec.executeBlocking(QtPassSettings::getGitExecutable(),
+ {"add", fileName});
QString path =
QDir(QtPassSettings::getPassStore()).relativeFilePath(fileName);
path.replace(QRegExp("\\.gpg$"), "");
- executeWrapper(QtPassSettings::getGitExecutable(),
- "commit \"" + fileName + "\" -m \"" + "Edit for " +
- path + " using QtPass.\"");
- process.waitForFinished(3000);
+ exec.executeBlocking(QtPassSettings::getGitExecutable(),
+ {"commit", fileName, "-m",
+ "Edit for " + path + " using QtPass."});
}
} else {
- dbg()<< "Decrypt error on re-encrypt";
+ dbg() << "Decrypt error on re-encrypt";
}
}
}
diff --git a/imitatepass.h b/imitatepass.h
index cc56cb62..8d2fd253 100644
--- a/imitatepass.h
+++ b/imitatepass.h
@@ -8,13 +8,24 @@ class ImitatePass : public Pass {
bool removeDir(const QString &dirName);
+ void executeWrapper(int id, const QString &app, const QStringList &args,
+ bool readStdout = true, bool readStderr = true);
+
+ void executeWrapper(int id, const QString &app, const QStringList &args,
+ QString input, bool readStdout = true,
+ bool readStderr = true);
+
+ void GitCommit(const QString &file, const QString &msg);
+
public:
ImitatePass();
virtual ~ImitatePass() {}
virtual void GitInit() override;
virtual void GitPull() override;
+ virtual void GitPull_b() override;
virtual void GitPush() override;
- virtual QProcess::ExitStatus Show(QString file, bool block = false) override;
+ virtual void Show(QString file) override;
+ virtual int Show_b(QString file) override;
virtual void Insert(QString file, QString value,
bool overwrite = false) override;
virtual void Remove(QString file, bool isDir = false) override;
diff --git a/mainwindow.cpp b/mainwindow.cpp
index 92deb47c..c63a27f1 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -35,14 +35,11 @@
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow), fusedav(this), keygen(NULL),
tray(NULL), pass(nullptr) {
- // connect(process.data(), SIGNAL(readyReadStandardOutput()), this,
- // SLOT(readyRead()));
-
// TODO(bezet): this should be reconnected dynamically when pass changes
connect(&rpass, SIGNAL(error(QProcess::ProcessError)), this,
SLOT(processError(QProcess::ProcessError)));
- connect(&rpass, SIGNAL(finished(int, QProcess::ExitStatus)), this,
- SLOT(processFinished(int, QProcess::ExitStatus)));
+ connect(&rpass, SIGNAL(finished(int, const QString &, const QString &)), this,
+ SLOT(processFinished(int, const QString &, const QString &)));
connect(&rpass, SIGNAL(startingExecuteWrapper()), this,
SLOT(executeWrapperStarted()));
connect(&rpass, SIGNAL(statusMsg(QString, int)), this,
@@ -52,8 +49,8 @@ MainWindow::MainWindow(QWidget *parent)
connect(&ipass, SIGNAL(error(QProcess::ProcessError)), this,
SLOT(processError(QProcess::ProcessError)));
- connect(&ipass, SIGNAL(finished(int, QProcess::ExitStatus)), this,
- SLOT(processFinished(int, QProcess::ExitStatus)));
+ connect(&ipass, SIGNAL(finished(int, const QString &, const QString &)), this,
+ SLOT(processFinished(int, const QString &, const QString &)));
connect(&ipass, SIGNAL(startingExecuteWrapper()), this,
SLOT(executeWrapperStarted()));
connect(&ipass, SIGNAL(statusMsg(QString, int)), this,
@@ -69,7 +66,6 @@ MainWindow::MainWindow(QWidget *parent)
ui->setupUi(this);
enableUiElements(true);
- execQueue = new QQueue<execQueueItem>;
ui->statusBar->showMessage(tr("Welcome to QtPass %1").arg(VERSION), 2000);
freshStart = true;
startupPhase = true;
@@ -525,11 +521,12 @@ void MainWindow::config() {
/**
* @brief MainWindow::on_updateButton_clicked do a git pull
*/
-// TODO(bezet): add bool block and wait for process to finish
-void MainWindow::on_updateButton_clicked() {
+void MainWindow::on_updateButton_clicked(bool block) {
ui->statusBar->showMessage(tr("Updating password-store"), 2000);
- currentAction = GIT;
- pass->GitPull();
+ if (block)
+ pass->GitPull_b();
+ else
+ pass->GitPull();
}
/**
@@ -659,114 +656,139 @@ void MainWindow::executeWrapperStarted() {
/**
* @brief MainWindow::readyRead we have data
*/
-void MainWindow::readyRead(bool finished = false) {
- if (currentAction == PWGEN)
+void MainWindow::readyRead(const QString &p_output, const QString &p_errout) {
+ QString output = p_output;
+ QString error = p_errout;
+ if (currentAction == PWGEN) {
return;
- QString output = "";
- QString error = "";
- if (currentAction != GPG_INTERNAL) {
- error = pass->readAllStandardError();
- QByteArray processOutBytes = pass->readAllStandardOutput();
- QTextCodec *codec = QTextCodec::codecForLocale();
- output = codec->toUnicode(processOutBytes);
- if (finished && currentAction == GPG) {
- lastDecrypt = output;
- QStringList tokens = output.split("\n");
- QString password = tokens.at(0);
-
- if (QtPassSettings::getClipBoardType() != Enums::CLIPBOARD_NEVER &&
- !output.isEmpty()) {
- clippedText = tokens[0];
- if (QtPassSettings::getClipBoardType() == Enums::CLIPBOARD_ALWAYS)
- copyTextToClipboard(tokens[0]);
- if (QtPassSettings::isUseAutoclearPanel()) {
- clearPanelTimer.start();
- }
- if (QtPassSettings::isHidePassword() &&
- !QtPassSettings::isUseTemplate()) {
- tokens[0] = "***" + tr("Password hidden") + "***";
- output = tokens.join("\n");
- }
- if (QtPassSettings::isHideContent())
- output = "***" + tr("Content hidden") + "***";
- }
-
- if (QtPassSettings::isUseTemplate() && !QtPassSettings::isHideContent()) {
- while (ui->gridLayout->count() > 0) {
- QLayoutItem *item = ui->gridLayout->takeAt(0);
- delete item->widget();
- delete item;
- }
- QStringList remainingTokens;
- for (int j = 1; j < tokens.length(); ++j) {
- QString token = tokens.at(j);
- if (token.contains(':')) {
- int colon = token.indexOf(':');
- QString field = token.left(colon);
- if (QtPassSettings::isTemplateAllFields() ||
- QtPassSettings::getPassTemplate().contains(field)) {
- QString value = token.right(token.length() - colon - 1);
- if (!QtPassSettings::getPassTemplate().contains(field) &&
- value.startsWith("//")) {
- remainingTokens.append(token);
- continue; // colon is probably from a url
- }
- addToGridLayout(j, field, value);
- }
- } else {
- remainingTokens.append(token);
- }
- }
- if (ui->gridLayout->count() == 0)
- ui->verticalLayoutPassword->setSpacing(0);
- else
- ui->verticalLayoutPassword->setSpacing(6);
- output = remainingTokens.join("\n");
- } else {
- clearTemplateWidgets();
- }
- if (!QtPassSettings::isHideContent() && !password.isEmpty()) {
- // now set the password. If we set it earlier, the layout will be
- // cleared
- addToGridLayout(0, tr("Password"), password);
- }
- if (QtPassSettings::isUseAutoclearPanel()) {
- clearPanelTimer.start();
- }
- }
- output.replace(QRegExp("<"), "&lt;");
- output.replace(QRegExp(">"), "&gt;");
- output.replace(QRegExp(" "), "&nbsp;");
- } else {
+ } else if (currentAction == GPG) {
+ passShowHandler(p_output);
+ } else if (currentAction == GPG_INTERNAL) {
// qDebug() << process->readAllStandardOutput();
// qDebug() << process->readAllStandardError();
- if (finished && 0 != keygen) {
+ if (0 != keygen) {
qDebug() << "Keygen Done";
keygen->close();
keygen = 0;
// TODO(annejan) some sanity checking ?
}
+ } else {
+ DisplayInTextBrowser(p_output);
}
- if (!error.isEmpty()) {
- if (currentAction == GIT) {
- // https://github.com/IJHack/qtpass/issues/111
- output = "<span style=\"color: darkgray;\">" + error + "</span><br />" +
- output;
+ processErrorExit(p_errout);
+}
+
+void MainWindow::passShowHandler(const QString &p_output) {
+ QString output = p_output;
+ lastDecrypt = p_output;
+ {
+ QStringList tokens = p_output.split("\n");
+ QString password = tokens.at(0);
+
+ if (QtPassSettings::getClipBoardType() != Enums::CLIPBOARD_NEVER &&
+ !p_output.isEmpty()) {
+ clippedText = tokens[0];
+ if (QtPassSettings::getClipBoardType() == Enums::CLIPBOARD_ALWAYS)
+ copyTextToClipboard(tokens[0]);
+ if (QtPassSettings::isUseAutoclearPanel()) {
+ clearPanelTimer.start();
+ }
+ if (QtPassSettings::isHidePassword() &&
+ !QtPassSettings::isUseTemplate()) {
+ tokens[0] = "***" + tr("Password hidden") + "***";
+ output = tokens.join("\n");
+ }
+ if (QtPassSettings::isHideContent())
+ output = "***" + tr("Content hidden") + "***";
+ }
+
+ if (QtPassSettings::isUseTemplate() && !QtPassSettings::isHideContent()) {
+ while (ui->gridLayout->count() > 0) {
+ QLayoutItem *item = ui->gridLayout->takeAt(0);
+ delete item->widget();
+ delete item;
+ }
+ QStringList remainingTokens;
+ for (int j = 1; j < tokens.length(); ++j) {
+ QString token = tokens.at(j);
+ if (token.contains(':')) {
+ int colon = token.indexOf(':');
+ QString field = token.left(colon);
+ if (QtPassSettings::isTemplateAllFields() ||
+ QtPassSettings::getPassTemplate().contains(field)) {
+ QString value = token.right(token.length() - colon - 1);
+ if (!QtPassSettings::getPassTemplate().contains(field) &&
+ value.startsWith("//")) {
+ remainingTokens.append(token);
+ continue; // colon is probably from a url
+ }
+ addToGridLayout(j, field, value);
+ }
+ } else {
+ remainingTokens.append(token);
+ }
+ }
+ if (ui->gridLayout->count() == 0)
+ ui->verticalLayoutPassword->setSpacing(0);
+ else
+ ui->verticalLayoutPassword->setSpacing(6);
+ output = remainingTokens.join("\n");
} else {
- output =
- "<span style=\"color: red;\">" + error + "</span><br />" + output;
+ clearTemplateWidgets();
+ }
+ if (!QtPassSettings::isHideContent() && !password.isEmpty()) {
+ // now set the password. If we set it earlier, the layout will be
+ // cleared
+ addToGridLayout(0, tr("Password"), password);
+ }
+ if (QtPassSettings::isUseAutoclearPanel()) {
+ clearPanelTimer.start();
}
}
+ DisplayInTextBrowser(output);
+}
+
+void MainWindow::DisplayInTextBrowser(QString output, QString prefix,
+ QString postfix) {
+
+ output.replace(QRegExp("<"), "&lt;");
+ output.replace(QRegExp(">"), "&gt;");
+ output.replace(QRegExp(" "), "&nbsp;");
+
output.replace(QRegExp("((?:https?|ftp|ssh)://\\S+)"),
"<a href=\"\\1\">\\1</a>");
output.replace(QRegExp("\n"), "<br />");
+ output = prefix + output + postfix;
if (!ui->textBrowser->toPlainText().isEmpty())
output = ui->textBrowser->toHtml() + output;
ui->textBrowser->setHtml(output);
}
+void MainWindow::processErrorExit(const QString &p_error) {
+ if (!p_error.isEmpty()) {
+ QString output;
+ QString error = p_error;
+ error.replace(QRegExp("<"), "&lt;");
+ error.replace(QRegExp(">"), "&gt;");
+ error.replace(QRegExp(" "), "&nbsp;");
+ if (currentAction == GIT) {
+ // https://github.com/IJHack/qtpass/issues/111
+ output = "<span style=\"color: darkgray;\">" + error + "</span><br />";
+ } else {
+ output = "<span style=\"color: red;\">" + error + "</span><br />";
+ }
+
+ output.replace(QRegExp("((?:https?|ftp|ssh)://\\S+)"),
+ "<a href=\"\\1\">\\1</a>");
+ output.replace(QRegExp("\n"), "<br />");
+ if (!ui->textBrowser->toPlainText().isEmpty())
+ output = ui->textBrowser->toHtml() + output;
+ ui->textBrowser->setHtml(output);
+ }
+}
+
/**
* @brief MainWindow::clearClipboard remove clipboard contents.
*/
@@ -799,23 +821,23 @@ void MainWindow::clearPanel(bool notify = true) {
}
/**
- * @brief MainWindow::clearPanel because slots needs the same amout of params as
- * signals
+ * @brief MainWindow::clearPanel because slots needs the same amout of params
+ * as signals
*/
void MainWindow::clearPanel() { clearPanel(true); }
/**
- * @brief MainWindow::processFinished process is finished, if there is another
- * one queued up to run, start it.
+ * @brief MainWindow::processFinished background process has finished
* @param exitCode
* @param exitStatus
+ * @param output stdout from a process
+ * @param errout stderr from a process
*/
-void MainWindow::processFinished(int exitCode,
- QProcess::ExitStatus exitStatus) {
- bool error = exitStatus != QProcess::NormalExit || exitCode > 0;
- readyRead(true);
+void MainWindow::processFinished(int exitCode, const QString &output,
+ const QString &errout) {
+ readyRead(output, errout);
enableUiElements(true);
- if (!error && currentAction == EDIT)
+ if (exitCode == 0 && currentAction == EDIT)
on_treeView_clicked(ui->treeView->currentIndex());
}
@@ -869,8 +891,8 @@ void MainWindow::processError(QProcess::ProcessError error) {
ui->textBrowser->setText(errorString);
// TODO(bezet): this probably shall be done in finished handler(I guess it
// finishes even on error)
- if (pass->state() == QProcess::NotRunning)
- enableUiElements(true);
+ // if (pass->state() == QProcess::NotRunning)
+ enableUiElements(true);
}
/**
@@ -1421,9 +1443,7 @@ void MainWindow::addFolder() {
*/
void MainWindow::editPassword() {
if (QtPassSettings::isUseGit() && QtPassSettings::isAutoPull())
- on_updateButton_clicked();
- pass->waitFor(30);
- pass->waitForProcess();
+ on_updateButton_clicked(true);
// TODO(annejan) move to editbutton stuff possibly?
currentDir = getDir(ui->treeView->currentIndex(), false);
lastDecrypt = "Could not decrypt";
@@ -1431,7 +1451,7 @@ void MainWindow::editPassword() {
getFile(ui->treeView->currentIndex(), QtPassSettings::isUsePass());
if (!file.isEmpty()) {
currentAction = GPG;
- if (pass->Show(file, true) == QProcess::NormalExit)
+ if (pass->Show_b(file) == 0)
on_editButton_clicked();
}
}
diff --git a/mainwindow.h b/mainwindow.h
index 64abe785..f09d4e98 100644
--- a/mainwindow.h
+++ b/mainwindow.h
@@ -65,13 +65,13 @@ public slots:
void deselect();
private slots:
- void on_updateButton_clicked();
+ void on_updateButton_clicked(bool block = false);
void on_pushButton_clicked();
void on_treeView_clicked(const QModelIndex &index);
void on_treeView_doubleClicked(const QModelIndex &index);
void on_configButton_clicked();
- void readyRead(bool finished);
- void processFinished(int, QProcess::ExitStatus);
+ void readyRead(const QString &, const QString &);
+ void processFinished(int, const QString &, const QString &);
void processError(QProcess::ProcessError);
void clearClipboard();
void clearPanel(bool notify);
@@ -97,6 +97,9 @@ private slots:
void endReencryptPath();
void critical(QString, QString);
void setLastDecrypt(QString);
+ void passShowHandler(const QString &);
+
+ void processErrorExit(const QString &);
private:
QAction *actionAddPassword;
@@ -114,7 +117,6 @@ private:
QTimer clearClipboardTimer;
actionType currentAction;
QString lastDecrypt;
- QQueue<execQueueItem> *execQueue;
bool freshStart;
QDialog *keygen;
QString currentDir;
@@ -141,6 +143,8 @@ private:
void reencryptPath(QString dir);
void addToGridLayout(int position, const QString &field,
const QString &value);
+ void DisplayInTextBrowser(QString toShow, QString prefix = QString(),
+ QString postfix = QString());
};
#endif // MAINWINDOW_H_
diff --git a/pass.cpp b/pass.cpp
index abbed7d4..b13b0da9 100644
--- a/pass.cpp
+++ b/pass.cpp
@@ -4,15 +4,14 @@
#include "util.h"
#include <QTextCodec>
-Pass::Pass() : wrapperRunning(false) {
- connect(&process, SIGNAL(finished(int, QProcess::ExitStatus)), this,
- SIGNAL(finished(int, QProcess::ExitStatus)));
- connect(&process, SIGNAL(error(QProcess::ProcessError)), this,
- SIGNAL(error(QProcess::ProcessError)));
- connect(&process, SIGNAL(finished(int, QProcess::ExitStatus)), this,
- SLOT(processFinished(int, QProcess::ExitStatus)));
+Pass::Pass() : wrapperRunning(false), env(QProcess::systemEnvironment()) {
+ connect(&exec, SIGNAL(finished(int, const QString &, const QString &)), this,
+ SIGNAL(finished(int, const QString &, const QString &)));
+ // TODO(bezet): stop using process
+ // connect(&process, SIGNAL(error(QProcess::ProcessError)), this,
+ // SIGNAL(error(QProcess::ProcessError)));
- env = QProcess::systemEnvironment();
+ connect(&exec, &Executor::starting, this, &Pass::startingExecuteWrapper);
#ifdef __APPLE__
// If it exists, add the gpgtools to PATH
@@ -30,11 +29,6 @@ Pass::Pass() : wrapperRunning(false) {
}
}
-QProcess::ExitStatus Pass::waitForProcess() {
- process.waitForFinished(30000);
- return process.exitStatus();
-}
-
/**
* @brief Pass::Generate use either pwgen or internal password
* generator
@@ -46,22 +40,29 @@ QProcess::ExitStatus Pass::waitForProcess() {
QString Pass::Generate(int length, const QString &charset) {
QString passwd;
if (QtPassSettings::isUsePwgen()) {
- waitFor(2);
// --secure goes first as it overrides --no-* otherwise
- QString args =
- QString("-1 ") + (QtPassSettings::isLessRandom() ? "" : "--secure ") +
- (QtPassSettings::isAvoidCapitals() ? "--no-capitalize "
- : "--capitalize ") +
- (QtPassSettings::isAvoidNumbers() ? "--no-numerals " : "--numerals ") +
- (QtPassSettings::isUseSymbols() ? "--symbols " : "") +
- QString::number(length);
- executeWrapper(QtPassSettings::getPwgenExecutable(), args);
- process.waitForFinished(1000);
- if (process.exitStatus() == QProcess::NormalExit)
- passwd =
- QString(process.readAllStandardOutput()).remove(QRegExp("[\\n\\r]"));
- else
- qDebug() << "pwgen fail";
+ QStringList args;
+ args.append("-1");
+ if (QtPassSettings::isLessRandom())
+ args.append("--secure ");
+ args.append(QtPassSettings::isAvoidCapitals() ? "--no-capitalize "
+ : "--capitalize ");
+ args.append(QtPassSettings::isAvoidNumbers() ? "--no-numerals "
+ : "--numerals ");
+ if (QtPassSettings::isUseSymbols())
+ args.append("--symbols ");
+ args.append(QString::number(length));
+ QString p_out;
+ // TODO(bezet): try-catch here(2 statuses to merge o_O)
+ if (exec.executeBlocking(QtPassSettings::getPwgenExecutable(), args,
+ &passwd) == 0)
+ passwd.remove(QRegExp("[\\n\\r]"));
+ else {
+ passwd.clear();
+ qDebug() << __FILE__ << ":" << __LINE__ << "\t"
+ << "pwgen fail";
+ // TODO(bezet): emit critical ?
+ }
} else {
if (charset.length() > 0) {
for (int i = 0; i < length; ++i) {
@@ -81,12 +82,12 @@ QString Pass::Generate(int length, const QString &charset) {
/**
* @brief Pass::GenerateGPGKeys internal gpg keypair generator . .
- * @param batch
+ * @param batch GnuPG style configuration string
* @param keygenWindow
*/
void Pass::GenerateGPGKeys(QString batch) {
- executeWrapper(QtPassSettings::getGpgExecutable(),
- "--gen-key --no-tty --batch", batch);
+ exec.execute(PASSWD_GENERATE, QtPassSettings::getGpgExecutable(),
+ {"--gen-key", "--no-tty", "--batch"}, batch);
// TODO check status / error messages
// https://github.com/IJHack/QtPass/issues/202#issuecomment-251081688
}
@@ -98,19 +99,16 @@ void Pass::GenerateGPGKeys(QString batch) {
* @return QList<UserInfo> users
*/
QList<UserInfo> Pass::listKeys(QString keystring, bool secret) {
- waitFor(5);
QList<UserInfo> users;
- QString listopt = secret ? "--list-secret-keys " : "--list-keys ";
- executeWrapper(QtPassSettings::getGpgExecutable(),
- "--no-tty --with-colons " + listopt + keystring);
- process.waitForFinished(2000);
- if (process.exitStatus() != QProcess::NormalExit)
+ QStringList args = {"--no-tty", "--with-colons"};
+ args.append(secret ? "--list-secret-keys" : "--list-keys");
+ if (!keystring.isEmpty())
+ args.append(keystring);
+ QString p_out;
+ if (exec.executeBlocking(QtPassSettings::getGpgExecutable(), args, &p_out) !=
+ 0)
return users;
- QByteArray processOutBytes = process.readAllStandardOutput();
- QTextCodec *codec = QTextCodec::codecForLocale();
- QString processOutString = codec->toUnicode(processOutBytes);
- QStringList keys = QString(processOutString)
- .split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
+ QStringList keys = p_out.split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
UserInfo current_user;
foreach (QString key, keys) {
QStringList props = key.split(':');
@@ -135,97 +133,6 @@ QList<UserInfo> Pass::listKeys(QString keystring, bool secret) {
}
/**
- * @brief Pass::waitFor wait until process.atEnd and execQueue.isEmpty
- * or timeout after x-seconds
- *
- * @param seconds
- */
-void Pass::waitFor(uint seconds) {
- QDateTime current = QDateTime::currentDateTime();
- uint stop = current.toTime_t() + seconds;
- while (!process.atEnd() || !execQueue.isEmpty()) {
- current = QDateTime::currentDateTime();
- if (stop < current.toTime_t()) {
- emit critical(tr("Timed out"),
- tr("Can't start process, previous one is still running!"));
- }
- Util::qSleep(100);
- }
-}
-
-/**
- * @brief Pass::processFinished process is finished, if there is another
- * one queued up to run, start it.
- * @param exitCode
- * @param exitStatus
- */
-void Pass::processFinished(int, QProcess::ExitStatus) {
- wrapperRunning = false;
- if (!execQueue.isEmpty()) {
- execQueueItem item = execQueue.dequeue();
- executeWrapper(item.app, item.args, item.input);
- }
-}
-
-/**
- * Temporary wrapper to ease refactoring, don't get used to it ;)
- */