Adding debug info to CLI.

Adding debug info to the CLI and the general option
of the main Qt app. Also took time to:
* use `EXIT_SUCCESS`/`EXIT_FAILURE` constants
for main.cpp (this is what is used in `src/cli`);
* fixed `m_initalized` typo;
* added info on debugging mode being disabled
or not;
* regrouped Qt related stuff in the debug output.
This commit is contained in:
louib 2019-02-18 20:17:28 -05:00 committed by Jonathan White
parent 76913a5dd1
commit a58e3d5ee0
11 changed files with 126 additions and 82 deletions

View File

@ -56,6 +56,9 @@ Shows the title, username, password, URL and notes of a database entry. Can also
.SS "General options" .SS "General options"
.IP "--debug-info"
Displays debugging information.
.IP "-k, --key-file <path>" .IP "-k, --key-file <path>"
Specifies a path to a key file for unlocking the database. In a merge operation this option is used to specify the key file path for the first database. Specifies a path to a key file for unlocking the database. In a merge operation this option is used to specify the key file path for the first database.
@ -66,7 +69,7 @@ Silence password prompt and other secondary outputs.
Displays help information. Displays help information.
.IP "-v, --version" .IP "-v, --version"
Shows the program version. Displays the program version.
.SS "Merge options" .SS "Merge options"

View File

@ -26,6 +26,7 @@
#include "config-keepassx.h" #include "config-keepassx.h"
#include "core/Bootstrap.h" #include "core/Bootstrap.h"
#include "core/Tools.h"
#include "crypto/Crypto.h" #include "crypto/Crypto.h"
#if defined(WITH_ASAN) && defined(WITH_LSAN) #if defined(WITH_ASAN) && defined(WITH_LSAN)
@ -60,6 +61,9 @@ int main(int argc, char** argv)
parser.addPositionalArgument("command", QObject::tr("Name of the command to execute.")); parser.addPositionalArgument("command", QObject::tr("Name of the command to execute."));
QCommandLineOption debugInfoOption(QStringList() << "debug-info",
QObject::tr("Displays debugging information."));
parser.addOption(debugInfoOption);
parser.addHelpOption(); parser.addHelpOption();
parser.addVersionOption(); parser.addVersionOption();
// TODO : use the setOptionsAfterPositionalArgumentsMode (Qt 5.6) function // TODO : use the setOptionsAfterPositionalArgumentsMode (Qt 5.6) function
@ -72,6 +76,10 @@ int main(int argc, char** argv)
// Switch to parser.showVersion() when available (QT 5.4). // Switch to parser.showVersion() when available (QT 5.4).
out << KEEPASSXC_VERSION << endl; out << KEEPASSXC_VERSION << endl;
return EXIT_SUCCESS; return EXIT_SUCCESS;
} else if (parser.isSet(debugInfoOption)) {
QString debugInfo = Tools::debugInfo().append("\n").append(Crypto::debugInfo());
out << debugInfo << endl;
return EXIT_SUCCESS;
} }
parser.showHelp(); parser.showHelp();
} }

View File

@ -18,6 +18,8 @@
*/ */
#include "Tools.h" #include "Tools.h"
#include "config-keepassx.h"
#include "core/Config.h" #include "core/Config.h"
#include "core/Translator.h" #include "core/Translator.h"
@ -28,8 +30,10 @@
#include <QLocale> #include <QLocale>
#include <QRegularExpression> #include <QRegularExpression>
#include <QStringList> #include <QStringList>
#include <QSysInfo>
#include <QUuid> #include <QUuid>
#include <cctype> #include <cctype>
#include "git-info.h"
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include <windows.h> // for Sleep() #include <windows.h> // for Sleep()
@ -41,6 +45,78 @@
namespace Tools namespace Tools
{ {
QString debugInfo()
{
QString debugInfo = "KeePassXC - ";
debugInfo.append(QObject::tr("Version %1").arg(KEEPASSXC_VERSION).append("\n"));
#ifndef KEEPASSXC_BUILD_TYPE_RELEASE
debugInfo.append(QObject::tr("Build Type: %1").arg(KEEPASSXC_BUILD_TYPE).append("\n"));
#endif
QString commitHash;
if (!QString(GIT_HEAD).isEmpty()) {
commitHash = GIT_HEAD;
}
if (!commitHash.isEmpty()) {
debugInfo.append(QObject::tr("Revision: %1").arg(commitHash.left(7)).append("\n"));
}
#ifdef KEEPASSXC_DIST
debugInfo.append(QObject::tr("Distribution: %1").arg(KEEPASSXC_DIST_TYPE).append("\n"));
#endif
// Qt related debugging information.
debugInfo.append("\n");
debugInfo.append("Qt ").append(QString::fromLocal8Bit(qVersion())).append("\n");
#ifdef QT_NO_DEBUG
debugInfo.append(QObject::tr("Debugging mode is disabled.").append("\n"));
#else
debugInfo.append(QObject::tr("Debugging mode is enabled.").append("\n"));
#endif
debugInfo.append("\n");
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
debugInfo.append(QObject::tr("Operating system: %1\nCPU architecture: %2\nKernel: %3 %4")
.arg(QSysInfo::prettyProductName(),
QSysInfo::currentCpuArchitecture(),
QSysInfo::kernelType(),
QSysInfo::kernelVersion()));
debugInfo.append("\n\n");
#endif
QString extensions;
#ifdef WITH_XC_AUTOTYPE
extensions += "\n- " + QObject::tr("Auto-Type");
#endif
#ifdef WITH_XC_BROWSER
extensions += "\n- " + QObject::tr("Browser Integration");
#endif
#ifdef WITH_XC_SSHAGENT
extensions += "\n- " + QObject::tr("SSH Agent");
#endif
#if defined(WITH_XC_KEESHARE_SECURE) && defined(WITH_XC_KEESHARE_INSECURE)
extensions += "\n- " + QObject::tr("KeeShare (signed and unsigned sharing)");
#elif defined(WITH_XC_KEESHARE_SECURE)
extensions += "\n- " + QObject::tr("KeeShare (only signed sharing)");
#elif defined(WITH_XC_KEESHARE_INSECURE)
extensions += "\n- " + QObject::tr("KeeShare (only unsigned sharing)");
#endif
#ifdef WITH_XC_YUBIKEY
extensions += "\n- " + QObject::tr("YubiKey");
#endif
#ifdef WITH_XC_TOUCHID
extensions += "\n- " + QObject::tr("TouchID");
#endif
if (extensions.isEmpty())
extensions = " " + QObject::tr("None");
debugInfo.append(QObject::tr("Enabled extensions:").append(extensions).append("\n"));
return debugInfo;
}
QString humanReadableFileSize(qint64 bytes, quint32 precision) QString humanReadableFileSize(qint64 bytes, quint32 precision)
{ {
constexpr auto kibibyte = 1024; constexpr auto kibibyte = 1024;

View File

@ -32,6 +32,7 @@ class QRegularExpression;
namespace Tools namespace Tools
{ {
QString debugInfo();
QString humanReadableFileSize(qint64 bytes, quint32 precision = 2); QString humanReadableFileSize(qint64 bytes, quint32 precision = 2);
bool readFromDevice(QIODevice* device, QByteArray& data, int size = 16384); bool readFromDevice(QIODevice* device, QByteArray& data, int size = 16384);
bool readAllFromDevice(QIODevice* device, QByteArray& data); bool readAllFromDevice(QIODevice* device, QByteArray& data);

View File

@ -25,7 +25,7 @@
#include "crypto/CryptoHash.h" #include "crypto/CryptoHash.h"
#include "crypto/SymmetricCipher.h" #include "crypto/SymmetricCipher.h"
bool Crypto::m_initalized(false); bool Crypto::m_initialized(false);
QString Crypto::m_errorStr; QString Crypto::m_errorStr;
QString Crypto::m_backendVersion; QString Crypto::m_backendVersion;
@ -35,8 +35,8 @@ Crypto::Crypto()
bool Crypto::init() bool Crypto::init()
{ {
if (m_initalized) { if (m_initialized) {
qWarning("Crypto::init: already initalized"); qWarning("Crypto::init: already initialized");
return true; return true;
} }
@ -48,19 +48,19 @@ bool Crypto::init()
} }
// has to be set before testing Crypto classes // has to be set before testing Crypto classes
m_initalized = true; m_initialized = true;
if (!backendSelfTest() || !selfTest()) { if (!backendSelfTest() || !selfTest()) {
m_initalized = false; m_initialized = false;
return false; return false;
} }
return true; return true;
} }
bool Crypto::initalized() bool Crypto::initialized()
{ {
return m_initalized; return m_initialized;
} }
QString Crypto::errorString() QString Crypto::errorString()
@ -68,9 +68,13 @@ QString Crypto::errorString()
return m_errorStr; return m_errorStr;
} }
QString Crypto::backendVersion() QString Crypto::debugInfo()
{ {
return QString("libgcrypt ").append(m_backendVersion); Q_ASSERT(Crypto::initialized());
QString debugInfo = QObject::tr("Cryptographic libraries:").append("\n");
debugInfo.append(" libgcrypt ").append(m_backendVersion).append("\n");
return debugInfo;
} }
bool Crypto::backendSelfTest() bool Crypto::backendSelfTest()

View File

@ -24,10 +24,10 @@ class Crypto
{ {
public: public:
static bool init(); static bool init();
static bool initalized(); static bool initialized();
static bool backendSelfTest(); static bool backendSelfTest();
static QString errorString(); static QString errorString();
static QString backendVersion(); static QString debugInfo();
private: private:
Crypto(); Crypto();
@ -42,7 +42,7 @@ private:
static bool testSalsa20(); static bool testSalsa20();
static bool testChaCha20(); static bool testChaCha20();
static bool m_initalized; static bool m_initialized;
static QString m_errorStr; static QString m_errorStr;
static QString m_backendVersion; static QString m_backendVersion;
}; };

View File

@ -33,7 +33,7 @@ CryptoHash::CryptoHash(Algorithm algo, bool hmac)
{ {
Q_D(CryptoHash); Q_D(CryptoHash);
Q_ASSERT(Crypto::initalized()); Q_ASSERT(Crypto::initialized());
int algoGcrypt = -1; int algoGcrypt = -1;
unsigned int flagsGcrypt = GCRY_MD_FLAG_SECURE; unsigned int flagsGcrypt = GCRY_MD_FLAG_SECURE;

View File

@ -93,7 +93,7 @@ Random::Random(RandomBackend* backend)
void RandomBackendGcrypt::randomize(void* data, int len) void RandomBackendGcrypt::randomize(void* data, int len)
{ {
Q_ASSERT(Crypto::initalized()); Q_ASSERT(Crypto::initialized());
gcry_randomize(data, len, GCRY_STRONG_RANDOM); gcry_randomize(data, len, GCRY_STRONG_RANDOM);
} }

View File

@ -90,7 +90,7 @@ void SymmetricCipherGcrypt::setError(const gcry_error_t& err)
bool SymmetricCipherGcrypt::init() bool SymmetricCipherGcrypt::init()
{ {
Q_ASSERT(Crypto::initalized()); Q_ASSERT(Crypto::initialized());
gcry_error_t error; gcry_error_t error;

View File

@ -21,11 +21,11 @@
#include "config-keepassx.h" #include "config-keepassx.h"
#include "core/FilePath.h" #include "core/FilePath.h"
#include "core/Tools.h"
#include "crypto/Crypto.h" #include "crypto/Crypto.h"
#include "git-info.h"
#include <QClipboard> #include <QClipboard>
#include <QSysInfo>
static const QString aboutMaintainers = R"( static const QString aboutMaintainers = R"(
<p><ul> <p><ul>
@ -175,67 +175,7 @@ AboutDialog::AboutDialog(QWidget* parent)
m_ui->iconLabel->setPixmap(filePath()->applicationIcon().pixmap(48)); m_ui->iconLabel->setPixmap(filePath()->applicationIcon().pixmap(48));
QString commitHash; QString debugInfo = Tools::debugInfo().append("\n").append(Crypto::debugInfo());
if (!QString(GIT_HEAD).isEmpty()) {
commitHash = GIT_HEAD;
}
QString debugInfo = "KeePassXC - ";
debugInfo.append(tr("Version %1").arg(KEEPASSXC_VERSION).append("\n"));
#ifndef KEEPASSXC_BUILD_TYPE_RELEASE
debugInfo.append(tr("Build Type: %1").arg(KEEPASSXC_BUILD_TYPE).append("\n"));
#endif
if (!commitHash.isEmpty()) {
debugInfo.append(tr("Revision: %1").arg(commitHash.left(7)).append("\n"));
}
#ifdef KEEPASSXC_DIST
debugInfo.append(tr("Distribution: %1").arg(KEEPASSXC_DIST_TYPE).append("\n"));
#endif
debugInfo.append("\n").append(
QString("%1\n- Qt %2\n- %3\n\n")
.arg(tr("Libraries:"), QString::fromLocal8Bit(qVersion()), Crypto::backendVersion()));
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
debugInfo.append(tr("Operating system: %1\nCPU architecture: %2\nKernel: %3 %4")
.arg(QSysInfo::prettyProductName(),
QSysInfo::currentCpuArchitecture(),
QSysInfo::kernelType(),
QSysInfo::kernelVersion()));
debugInfo.append("\n\n");
#endif
QString extensions;
#ifdef WITH_XC_AUTOTYPE
extensions += "\n- " + tr("Auto-Type");
#endif
#ifdef WITH_XC_BROWSER
extensions += "\n- " + tr("Browser Integration");
#endif
#ifdef WITH_XC_SSHAGENT
extensions += "\n- " + tr("SSH Agent");
#endif
#if defined(WITH_XC_KEESHARE_SECURE) && defined(WITH_XC_KEESHARE_INSECURE)
extensions += "\n- " + tr("KeeShare (signed and unsigned sharing)");
#elif defined(WITH_XC_KEESHARE_SECURE)
extensions += "\n- " + tr("KeeShare (only signed sharing)");
#elif defined(WITH_XC_KEESHARE_INSECURE)
extensions += "\n- " + tr("KeeShare (only unsigned sharing)");
#endif
#ifdef WITH_XC_YUBIKEY
extensions += "\n- " + tr("YubiKey");
#endif
#ifdef WITH_XC_TOUCHID
extensions += "\n- " + tr("TouchID");
#endif
if (extensions.isEmpty())
extensions = " " + tr("None");
debugInfo.append(tr("Enabled extensions:").append(extensions));
m_ui->debugInfo->setPlainText(debugInfo); m_ui->debugInfo->setPlainText(debugInfo);
m_ui->maintainers->setText(aboutMaintainers); m_ui->maintainers->setText(aboutMaintainers);

View File

@ -82,16 +82,19 @@ int main(int argc, char** argv)
QCommandLineOption helpOption = parser.addHelpOption(); QCommandLineOption helpOption = parser.addHelpOption();
QCommandLineOption versionOption = parser.addVersionOption(); QCommandLineOption versionOption = parser.addVersionOption();
QCommandLineOption debugInfoOption(QStringList() << "debug-info",
QObject::tr("Displays debugging information."));
parser.addOption(configOption); parser.addOption(configOption);
parser.addOption(keyfileOption); parser.addOption(keyfileOption);
parser.addOption(pwstdinOption); parser.addOption(pwstdinOption);
parser.addOption(parentWindowOption); parser.addOption(parentWindowOption);
parser.addOption(debugInfoOption);
parser.process(app); parser.process(app);
// Don't try and do anything with the application if we're only showing the help / version // Don't try and do anything with the application if we're only showing the help / version
if (parser.isSet(versionOption) || parser.isSet(helpOption)) { if (parser.isSet(versionOption) || parser.isSet(helpOption)) {
return 0; return EXIT_SUCCESS;
} }
const QStringList fileNames = parser.positionalArguments(); const QStringList fileNames = parser.positionalArguments();
@ -101,7 +104,7 @@ int main(int argc, char** argv)
app.sendFileNamesToRunningInstance(fileNames); app.sendFileNamesToRunningInstance(fileNames);
} }
qWarning() << QObject::tr("Another instance of KeePassXC is already running.").toUtf8().constData(); qWarning() << QObject::tr("Another instance of KeePassXC is already running.").toUtf8().constData();
return 0; return EXIT_SUCCESS;
} }
QApplication::setQuitOnLastWindowClosed(false); QApplication::setQuitOnLastWindowClosed(false);
@ -111,7 +114,16 @@ int main(int argc, char** argv)
error.append("\n"); error.append("\n");
error.append(Crypto::errorString()); error.append(Crypto::errorString());
MessageBox::critical(nullptr, QObject::tr("KeePassXC - Error"), error); MessageBox::critical(nullptr, QObject::tr("KeePassXC - Error"), error);
return 1; return EXIT_FAILURE;
}
// Displaying the debugging informations must be done after Crypto::init,
// to make sure we know which libgcrypt version is used.
if (parser.isSet(debugInfoOption)) {
QTextStream out(stdout, QIODevice::WriteOnly);
QString debugInfo = Tools::debugInfo().append("\n").append(Crypto::debugInfo());
out << debugInfo << endl;
return EXIT_SUCCESS;
} }
if (parser.isSet(configOption)) { if (parser.isSet(configOption)) {