28QProcessEnvironment Util::_env;
29bool Util::_envInitialised =
false;
41void Util::initialiseEnvironment() {
42 if (!_envInitialised) {
43 _env = QProcessEnvironment::systemEnvironment();
45 QString path = _env.value(
"PATH");
46 if (!path.contains(
"/usr/local/MacGPG2/bin") &&
47 QDir(
"/usr/local/MacGPG2/bin").exists())
48 path +=
":/usr/local/MacGPG2/bin";
49 if (!path.contains(
"/usr/local/bin"))
50 path +=
":/usr/local/bin";
51 _env.insert(
"PATH", path);
54 QString path = _env.value(
"PATH");
55 if (!path.contains(
"C:\\Program Files\\WinGPG\\x86") &&
56 QDir(
"C:\\Program Files\\WinGPG\\x86").exists())
57 path +=
";C:\\Program Files\\WinGPG\\x86";
58 if (!path.contains(
"C:\\Program Files\\GnuPG\\bin") &&
59 QDir(
"C:\\Program Files\\GnuPG\\bin").exists())
60 path +=
";C:\\Program Files\\GnuPG\\bin";
61 _env.insert(
"PATH", path);
64 dbg() << _env.value(
"PATH");
66 _envInitialised =
true;
79 initialiseEnvironment();
80 if (_env.contains(
"PASSWORD_STORE_DIR")) {
81 path = _env.value(
"PASSWORD_STORE_DIR");
84 path = QDir::homePath() + QDir::separator() +
"password-store" +
87 path = QDir::homePath() + QDir::separator() +
".password-store" +
95 QString normalizedPath = path;
96 if (!normalizedPath.endsWith(
"/") &&
97 !normalizedPath.endsWith(QDir::separator())) {
98 normalizedPath += QDir::separator();
100 return QDir::toNativeSeparators(normalizedPath);
121 if (binary.isEmpty())
124 initialiseEnvironment();
128 const QString binaryWithSep = QDir::separator() + binary;
130 if (_env.contains(
"PATH")) {
131 QString path = _env.value(
"PATH");
132 const QChar delimiter = QDir::separator() ==
'\\' ?
';' :
':';
133 QStringList entries = path.split(delimiter);
135 for (
const QString &entryConst : entries) {
136 QString fullPath = entryConst + binaryWithSep;
137 QFileInfo qfi(fullPath);
140 QString fullPathExe = fullPath +
".exe";
141 qfi = QFileInfo(fullPathExe);
147 if (!qfi.isExecutable()) {
151 ret = qfi.absoluteFilePath();
157 static const QRegularExpression whitespaceRegex(QStringLiteral(
"\\s"));
158 const bool hasWhitespace = binary.contains(whitespaceRegex);
159 if (!binary.isEmpty() && !hasWhitespace) {
160 QString wslCommand = QStringLiteral(
"wsl ") + binary;
162 dbg() <<
"Util::findBinaryInPath(): falling back to WSL for binary"
168 !out.isEmpty() && err.isEmpty()) {
170 dbg() <<
"Util::findBinaryInPath(): using WSL binary" << wslCommand;
192 const QString configFilePath =
194 if (!QFile(configFilePath).exists()) {
202 if (executable.startsWith(QStringLiteral(
"wsl "))) {
206 {QStringLiteral(
"--version")}, &out,
208 !out.isEmpty() && err.isEmpty()) {
212 return QFile(executable).exists();
235 const QFileSystemModel &model,
const StoreModel &storeModel)
239 if (!index.isValid()) {
240 return forPass ?
"" : abspath;
242 QFileInfo info = model.fileInfo(storeModel.mapToSource(index));
244 (info.isFile() ? info.absolutePath() : info.absoluteFilePath());
246 filePath = QDir(abspath).relativeFilePath(filePath);
248 filePath += QDir::separator();
253 static const QRegularExpression expr{
"\\.gpg$"};
270 static const QRegularExpression regex{
271 "((?:https?|ftp|ssh|sftp|ftps|webdav|webdavs)://[^\" <>\\)\\]\\[]+)"};
276 static const QRegularExpression regex{
"[\r\n]"};
281 static const QRegularExpression hexPrefixRegex{
"^0[xX]"};
282 static const QRegularExpression specialPrefixRegex{
"^[@/#&]"};
283 static const QRegularExpression hexKeyIdRegex{
"^[0-9A-Fa-f]{8,40}$"};
285 if (keyId.isEmpty()) {
289 QString normalized = keyId;
290 if (normalized.startsWith(
'<') && normalized.endsWith(
'>')) {
291 normalized = normalized.mid(1, normalized.length() - 2);
293 normalized.remove(hexPrefixRegex);
295 if (specialPrefixRegex.match(normalized).hasMatch() ||
296 normalized.contains(
'@')) {
300 return hexKeyIdRegex.match(normalized).hasMatch();
static auto executeBlocking(const 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.
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 getGpgExecutable(const QString &defaultValue=QVariant().toString()) -> QString
Get GPG executable path.
static auto getPassExecutable(const QString &defaultValue=QVariant().toString()) -> QString
Get pass executable path.
QSortFilterProxyModel for filtering and displaying password store.
static auto protocolRegex() -> const QRegularExpression &
Returns a regex to match URL protocols.
static auto endsWithGpg() -> const QRegularExpression &
Returns a regex to match .gpg file extensions.
static auto findPasswordStore() -> QString
Locate the password store directory.
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.
static auto isValidKeyId(const QString &keyId) -> bool
Check if a string looks like a valid GPG key ID. Accepts:
static auto newLinesRegex() -> const QRegularExpression &
Returns a regex to match newline characters.
static auto normalizeFolderPath(const QString &path) -> QString
Ensure a folder path always ends with the native directory separator.
static auto findBinaryInPath(const QString &binary) -> QString
Locate an executable by searching the process PATH and (on Windows) falling back to WSL.
static auto configIsValid() -> bool
Verify that the required configuration is complete.
Debug utilities for QtPass.
#define dbg()
Simple debug macro that includes file and line number.