QtPass 1.6.0
Multi-platform GUI for pass, the standard unix password manager.
Loading...
Searching...
No Matches
/home/annejan/Projects/QtPass/src/util.cpp

Initializes the process environment and augments PATH with platform-specific GPG locations.

Util::initialiseEnvironment();.

Initializes the process environment and augments PATH with platform-specific GPG locations.

Util::initialiseEnvironment();

Note
On macOS, appends common MacGPG2 and /usr/local/bin paths if available.
On Windows, appends common WinGPG and GnuPG installation paths if available.
// SPDX-FileCopyrightText: 2014 Anne Jan Brouwer
// SPDX-License-Identifier: GPL-3.0-or-later
#include "util.h"
#include <QDir>
#include <QFileInfo>
#ifdef Q_OS_WIN
#include <windows.h>
#else
#include <sys/time.h>
#endif
#include "qtpasssettings.h"
#ifdef QT_DEBUG
#include "debughelper.h"
#endif
QProcessEnvironment Util::_env;
bool Util::_envInitialised = false;
void Util::initialiseEnvironment() {
if (!_envInitialised) {
_env = QProcessEnvironment::systemEnvironment();
#ifdef __APPLE__
QString path = _env.value("PATH");
if (!path.contains("/usr/local/MacGPG2/bin") &&
QDir("/usr/local/MacGPG2/bin").exists())
path += ":/usr/local/MacGPG2/bin";
if (!path.contains("/usr/local/bin"))
path += ":/usr/local/bin";
_env.insert("PATH", path);
#endif
#ifdef Q_OS_WIN
QString path = _env.value("PATH");
if (!path.contains("C:\\Program Files\\WinGPG\\x86") &&
QDir("C:\\Program Files\\WinGPG\\x86").exists())
path += ";C:\\Program Files\\WinGPG\\x86";
if (!path.contains("C:\\Program Files\\GnuPG\\bin") &&
QDir("C:\\Program Files\\GnuPG\\bin").exists())
path += ";C:\\Program Files\\GnuPG\\bin";
_env.insert("PATH", path);
#endif
#ifdef QT_DEBUG
dbg() << _env.value("PATH");
#endif
_envInitialised = true;
}
}
auto Util::findPasswordStore() -> QString {
QString path;
initialiseEnvironment();
if (_env.contains("PASSWORD_STORE_DIR")) {
path = _env.value("PASSWORD_STORE_DIR");
} else {
#ifdef Q_OS_WIN
path = QDir::homePath() + QDir::separator() + "password-store" +
QDir::separator();
#else
path = QDir::homePath() + QDir::separator() + ".password-store" +
QDir::separator();
#endif
}
}
auto Util::normalizeFolderPath(const QString &path) -> QString {
QString normalizedPath = path;
if (!normalizedPath.endsWith("/") &&
!normalizedPath.endsWith(QDir::separator())) {
normalizedPath += QDir::separator();
}
return QDir::toNativeSeparators(normalizedPath);
}
auto Util::findBinaryInPath(QString binary) -> QString {
initialiseEnvironment();
QString ret;
const QString binaryWithSep = QDir::separator() + binary;
if (_env.contains("PATH")) {
QString path = _env.value("PATH");
const QChar delimiter = QDir::separator() == '\\' ? ';' : ':';
QStringList entries = path.split(delimiter);
for (const QString &entryConst : entries) {
QString fullPath = entryConst + binaryWithSep;
QFileInfo qfi(fullPath);
#ifdef Q_OS_WIN
if (!qfi.exists()) {
QString fullPathExe = fullPath + ".exe";
qfi = QFileInfo(fullPathExe);
}
#endif
if (!qfi.exists()) {
continue;
}
if (!qfi.isExecutable()) {
continue;
}
ret = qfi.absoluteFilePath();
break;
}
}
#ifdef Q_OS_WIN
if (ret.isEmpty()) {
static const QRegularExpression whitespaceRegex(QStringLiteral("\\s"));
const bool hasWhitespace = binary.contains(whitespaceRegex);
if (!binary.isEmpty() && !hasWhitespace) {
QString wslCommand = QStringLiteral("wsl ") + binary;
#ifdef QT_DEBUG
dbg() << "Util::findBinaryInPath(): falling back to WSL for binary"
<< binary;
#endif
QString out, err;
if (Executor::executeBlocking(wslCommand, {"--version"}, &out, &err) ==
0 &&
!out.isEmpty() && err.isEmpty()) {
#ifdef QT_DEBUG
dbg() << "Util::findBinaryInPath(): using WSL binary" << wslCommand;
#endif
ret = wslCommand;
}
}
}
#endif
return ret;
}
auto Util::configIsValid() -> bool {
const QString configFilePath =
QDir(QtPassSettings::getPassStore()).filePath(".gpg-id");
if (!QFile(configFilePath).exists()) {
return false;
}
const QString executable = QtPassSettings::isUsePass()
: QtPassSettings::getGpgExecutable();
if (executable.startsWith(QStringLiteral("wsl "))) {
QString out;
QString err;
if (Executor::executeBlocking(QStringLiteral("wsl"),
{QStringLiteral("--version")}, &out,
&err) == 0 &&
!out.isEmpty() && err.isEmpty()) {
return true;
}
}
return QFile(executable).exists();
}
auto Util::getDir(const QModelIndex &index, bool forPass,
const QFileSystemModel &model, const StoreModel &storeModel)
-> QString {
QString abspath =
QDir(QtPassSettings::getPassStore()).absolutePath() + QDir::separator();
if (!index.isValid()) {
return forPass ? "" : abspath;
}
QFileInfo info = model.fileInfo(storeModel.mapToSource(index));
QString filePath =
(info.isFile() ? info.absolutePath() : info.absoluteFilePath());
if (forPass) {
filePath = QDir(abspath).relativeFilePath(filePath);
}
filePath += QDir::separator();
return filePath;
}
auto Util::endsWithGpg() -> const QRegularExpression & {
static const QRegularExpression expr{"\\.gpg$"};
return expr;
}
auto Util::protocolRegex() -> const QRegularExpression & {
static const QRegularExpression regex{
"((?:https?|ftp|ssh|sftp|ftps|webdav|webdavs)://[^\" <>\\)\\]\\[]+)"};
return regex;
}
auto Util::newLinesRegex() -> const QRegularExpression & {
static const QRegularExpression regex{"[\r\n]"};
return regex;
}
auto Util::isValidKeyId(const QString &keyId) -> bool {
static const QRegularExpression hexPrefixRegex{"^0[xX]"};
static const QRegularExpression specialPrefixRegex{"^[@/#&]"};
static const QRegularExpression hexKeyIdRegex{"^[0-9A-Fa-f]{8,40}$"};
if (keyId.isEmpty()) {
return false;
}
QString normalized = keyId;
if (normalized.startsWith('<') && normalized.endsWith('>')) {
normalized = normalized.mid(1, normalized.length() - 2);
}
normalized.remove(hexPrefixRegex);
if (specialPrefixRegex.match(normalized).hasMatch() ||
normalized.contains('@')) {
return true;
}
return hexKeyIdRegex.match(normalized).hasMatch();
}
static auto executeBlocking(QString app, const QStringList &args, const QString &input=QString(), QString *process_out=nullptr, QString *process_err=nullptr) -> int
Executor::executeBlocking blocking version of the executor, takes input and presents it as stdin.
Definition executor.cpp:223
Singleton settings manager implementation.
static auto isUsePass(const bool &defaultValue=QVariant().toBool()) -> bool
Get whether to use pass (true) or GPG (false).
static auto getPassStore(const QString &defaultValue=QVariant().toString()) -> QString
Get password store directory path.
static auto getPassExecutable(const QString &defaultValue=QVariant().toString()) -> QString
Get pass executable path.
QSortFilterProxyModel for filtering and displaying password store.
Definition storemodel.h:31
static auto protocolRegex() -> const QRegularExpression &
Returns a regex to match URL protocols.
Definition util.cpp:266
static auto endsWithGpg() -> const QRegularExpression &
Returns a regex to match .gpg file extensions.
Definition util.cpp:249
static auto findPasswordStore() -> QString
Locate the password store directory.
Definition util.cpp:77
static auto getDir(const QModelIndex &index, bool forPass, const QFileSystemModel &model, const StoreModel &storeModel) -> QString
Get the selected folder path, either relative to the configured pass store or absolute.
Definition util.cpp:231
static auto isValidKeyId(const QString &keyId) -> bool
Check if a string looks like a valid GPG key ID. Validates a GPG key ID after normalization:
Definition util.cpp:277
static auto newLinesRegex() -> const QRegularExpression &
Returns a regex to match newline characters.
Definition util.cpp:272
static auto normalizeFolderPath(const QString &path) -> QString
Ensure a folder path always ends with the native directory separator.
Definition util.cpp:94
static auto findBinaryInPath(QString binary) -> QString
Locate an executable by searching the process PATH and (on Windows) falling back to WSL.
Definition util.cpp:120
static auto configIsValid() -> bool
Verify that the required configuration is complete.
Definition util.cpp:188
Debug utilities for QtPass.
#define dbg()
Simple debug macro that includes file and line number.
Definition debughelper.h:21