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

IJHack / QtPass / 23837649068

01 Apr 2026 07:41AM UTC coverage: 20.098% (+0.03%) from 20.071%
23837649068

push

github

web-flow
Merge pull request #883 from IJHack/ai-findings-autofix/src-util.cpp

Potential fixes for 2 code quality findings

2 of 2 new or added lines in 1 file covered. (100.0%)

1 existing line in 1 file now uncovered.

1025 of 5100 relevant lines covered (20.1%)

7.93 hits per line

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

86.44
/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(QString path) -> QString {
13✔
78
  if (!path.endsWith("/") && !path.endsWith(QDir::separator())) {
26✔
79
    path += QDir::separator();
7✔
80
  }
81
  return QDir::toNativeSeparators(path);
13✔
82
}
83

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

87
  QString ret;
12✔
88

89
  binary.prepend(QDir::separator());
12✔
90

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

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

112
      ret = qfi.absoluteFilePath();
10✔
113
      break;
114
    }
178✔
115
  }
116
#ifdef Q_OS_WIN
117
  if (ret.isEmpty()) {
118
    // Remove leading path separator added earlier when searching PATH entries.
119
    if (!binary.isEmpty() &&
120
        (binary.at(0) == QDir::separator() || binary.at(0) == '/')) {
121
      binary.remove(0, 1);
122
    }
123

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

147
  return ret;
12✔
148
}
149

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

157
  const QString executable = QtPassSettings::isUsePass()
×
158
                                 ? QtPassSettings::getPassExecutable()
×
159
                                 : QtPassSettings::getGpgExecutable();
×
160

161
  if (executable.startsWith("wsl ")) {
×
162
    return true;
163
  }
164
  return QFile(executable).exists();
×
165
}
166

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

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

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

196
auto Util::newLinesRegex() -> const QRegularExpression & {
2✔
197
  static const QRegularExpression regex{"[\r\n]"};
2✔
198
  return regex;
2✔
199
}
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