• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IJHack / QtPass / 23845714675

01 Apr 2026 11:11AM UTC coverage: 20.09% (-0.008%) from 20.098%
23845714675

push

github

web-flow
Merge pull request #886 from IJHack/fix/ai-findings-util-cpp

fix: address 3 AI findings in util.cpp

7 of 14 new or added lines in 1 file covered. (50.0%)

7 existing lines in 1 file now uncovered.

1026 of 5107 relevant lines covered (20.09%)

7.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.79
/src/util.cpp
1
// SPDX-FileCopyrightText: 2016 Anne Jan Brouwer
2
// SPDX-License-Identifier: GPL-3.0-or-later
3

4
/**
5
 * @class Util
6
 * @brief Static utility functions implementation.
7
 *
8
 * Implementation of utility functions for path handling, binary discovery,
9
 * and configuration validation.
10
 *
11
 * @see util.h
12
 */
13

14
#include "util.h"
15
#include <QDir>
16
#include <QFileInfo>
17
#ifdef Q_OS_WIN
18
#include <windows.h>
19
#else
20
#include <sys/time.h>
21
#endif
22
#include "qtpasssettings.h"
23

24
#ifdef QT_DEBUG
25
#include "debughelper.h"
26
#endif
27

28
QProcessEnvironment Util::_env;
29
bool Util::_envInitialised = false;
30

31
void Util::initialiseEnvironment() {
14✔
32
  if (!_envInitialised) {
14✔
33
    _env = QProcessEnvironment::systemEnvironment();
1✔
34
#ifdef __APPLE__
35
    QString path = _env.value("PATH");
36
    if (!path.contains("/usr/local/MacGPG2/bin") &&
37
        QDir("/usr/local/MacGPG2/bin").exists())
38
      path += ":/usr/local/MacGPG2/bin";
39
    if (!path.contains("/usr/local/bin"))
40
      path += ":/usr/local/bin";
41
    _env.insert("PATH", path);
42
#endif
43
#ifdef Q_OS_WIN
44
    QString path = _env.value("PATH");
45
    if (!path.contains("C:\\Program Files\\WinGPG\\x86") &&
46
        QDir("C:\\Program Files\\WinGPG\\x86").exists())
47
      path += ";C:\\Program Files\\WinGPG\\x86";
48
    if (!path.contains("C:\\Program Files\\GnuPG\\bin") &&
49
        QDir("C:\\Program Files\\GnuPG\\bin").exists())
50
      path += ";C:\\Program Files\\GnuPG\\bin";
51
    _env.insert("PATH", path);
52
#endif
53
#ifdef QT_DEBUG
54
    dbg() << _env.value("PATH");
55
#endif
56
    _envInitialised = true;
1✔
57
  }
58
}
14✔
59

60
auto Util::findPasswordStore() -> QString {
2✔
61
  QString path;
2✔
62
  initialiseEnvironment();
2✔
63
  if (_env.contains("PASSWORD_STORE_DIR")) {
4✔
64
    path = _env.value("PASSWORD_STORE_DIR");
×
65
  } else {
66
#ifdef Q_OS_WIN
67
    path = QDir::homePath() + QDir::separator() + "password-store" +
68
           QDir::separator();
69
#else
70
    path = QDir::homePath() + QDir::separator() + ".password-store" +
4✔
71
           QDir::separator();
72
#endif
73
  }
74
  return Util::normalizeFolderPath(path);
4✔
75
}
76

77
auto Util::normalizeFolderPath(const QString &path) -> QString {
13✔
78
  QString normalizedPath = path;
79
  if (!normalizedPath.endsWith("/") &&
33✔
80
      !normalizedPath.endsWith(QDir::separator())) {
7✔
81
    normalizedPath += QDir::separator();
7✔
82
  }
83
  return QDir::toNativeSeparators(normalizedPath);
26✔
84
}
85

86
auto Util::findBinaryInPath(QString binary) -> QString {
12✔
87
  initialiseEnvironment();
12✔
88

89
  QString ret;
12✔
90

91
  const QString binaryWithSep = QDir::separator() + binary;
12✔
92

93
  if (_env.contains("PATH")) {
24✔
94
    QString path = _env.value("PATH");
24✔
95
    const QChar delimiter = QDir::separator() == '\\' ? ';' : ':';
96
    QStringList entries = path.split(delimiter);
12✔
97

98
    for (const QString &entryConst : entries) {
192✔
99
      QString fullPath = entryConst + binaryWithSep;
178✔
100
      QFileInfo qfi(fullPath);
178✔
101
#ifdef Q_OS_WIN
102
      if (!qfi.exists()) {
103
        QString fullPathExe = fullPath + ".exe";
104
        qfi = QFileInfo(fullPathExe);
105
      }
106
#endif
107
      if (!qfi.exists()) {
178✔
108
        continue;
168✔
109
      }
110
      if (!qfi.isExecutable()) {
10✔
111
        continue;
×
112
      }
113

114
      ret = qfi.absoluteFilePath();
10✔
115
      break;
116
    }
178✔
117
  }
118
#ifdef Q_OS_WIN
119
  if (ret.isEmpty()) {
120
    // Validate binary name before attempting WSL fallback: require a non-empty,
121
    // whitespace-free program name to avoid confusing WSL invocations.
122
    const bool hasWhitespace =
123
        binary.contains(QRegularExpression(QStringLiteral("\\s")));
124
    if (!binary.isEmpty() && !hasWhitespace) {
125
      QString wslCommand = QStringLiteral("wsl ") + binary;
126
#ifdef QT_DEBUG
127
      dbg() << "Util::findBinaryInPath(): falling back to WSL for binary"
128
            << binary;
129
#endif
130
      QString out, err;
131
      if (Executor::executeBlocking(wslCommand, {"--version"}, &out, &err) ==
132
              0 &&
133
          !out.isEmpty() && err.isEmpty()) {
134
#ifdef QT_DEBUG
135
        dbg() << "Util::findBinaryInPath(): using WSL binary" << wslCommand;
136
#endif
137
        ret = wslCommand;
138
      }
139
    }
140
  }
141
#endif
142

143
  return ret;
12✔
144
}
145

146
auto Util::configIsValid() -> bool {
1✔
147
  const QString configFilePath =
148
      QDir(QtPassSettings::getPassStore()).filePath(".gpg-id");
3✔
149
  if (!QFile(configFilePath).exists()) {
1✔
150
    return false;
151
  }
152

153
  const QString executable = QtPassSettings::isUsePass()
×
154
                                 ? QtPassSettings::getPassExecutable()
×
155
                                 : QtPassSettings::getGpgExecutable();
×
156

NEW
157
  if (executable.startsWith(QStringLiteral("wsl "))) {
×
NEW
158
    QString out;
×
NEW
159
    QString err;
×
NEW
160
    if (Executor::executeBlocking(QStringLiteral("wsl"),
×
NEW
161
                                  {QStringLiteral("--version")}, &out,
×
NEW
162
                                  &err) == 0 &&
×
NEW
163
        !out.isEmpty() && err.isEmpty()) {
×
164
      return true;
165
    }
166
  }
167
  return QFile(executable).exists();
×
168
}
169

170
auto Util::getDir(const QModelIndex &index, bool forPass,
3✔
171
                  const QFileSystemModel &model, const StoreModel &storeModel)
172
    -> QString {
173
  QString abspath =
174
      QDir(QtPassSettings::getPassStore()).absolutePath() + QDir::separator();
9✔
175
  if (!index.isValid()) {
176
    return forPass ? "" : abspath;
2✔
177
  }
178
  QFileInfo info = model.fileInfo(storeModel.mapToSource(index));
1✔
179
  QString filePath =
180
      (info.isFile() ? info.absolutePath() : info.absoluteFilePath());
1✔
181
  if (forPass) {
1✔
182
    filePath = QDir(abspath).relativeFilePath(filePath);
×
183
  }
184
  filePath += QDir::separator();
1✔
185
  return filePath;
186
}
1✔
187

188
auto Util::endsWithGpg() -> const QRegularExpression & {
22✔
189
  static const QRegularExpression expr{"\\.gpg$"};
22✔
190
  return expr;
22✔
191
}
192

193
auto Util::protocolRegex() -> const QRegularExpression & {
3✔
194
  static const QRegularExpression regex{
195
      "((?:https?|ftp|ssh|sftp|ftps|webdav|webdavs)://[^\" <>\\)\\]\\[]+)"};
3✔
196
  return regex;
3✔
197
}
198

199
auto Util::newLinesRegex() -> const QRegularExpression & {
2✔
200
  static const QRegularExpression regex{"[\r\n]"};
2✔
201
  return regex;
2✔
202
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc