Merge branch 'release/2.4.0' into develop
This commit is contained in:
@@ -368,7 +368,7 @@ if(MINGW)
|
||||
"${CMAKE_SOURCE_DIR}/LICENSE.GPL-2"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/INSTALLER_LICENSE.txt")
|
||||
|
||||
string(REGEX REPLACE "-snapshot$" "" KEEPASSXC_VERSION_CLEAN ${KEEPASSXC_VERSION})
|
||||
string(REGEX REPLACE "-.*$" "" KEEPASSXC_VERSION_CLEAN ${KEEPASSXC_VERSION})
|
||||
|
||||
set(CPACK_GENERATOR "ZIP;WIX")
|
||||
set(CPACK_STRIP_FILES OFF)
|
||||
@@ -428,4 +428,10 @@ if(MINGW)
|
||||
|
||||
# install CA cert chains
|
||||
install(FILES ${Qt5_PREFIX}/ssl/certs/ca-bundle.crt DESTINATION "ssl/certs")
|
||||
# install OpenSSL library
|
||||
if(WITH_XC_NETWORKING)
|
||||
find_library(OPENSSL_DLL NAMES libssl-1_1.dll libssl-1_1-x64.dll PATH_SUFFIXES bin)
|
||||
find_library(CRYPTO_DLL NAMES libcrypto-1_1.dll libcrypto-1_1-x64.dll PATH_SUFFIXES bin)
|
||||
install(FILES ${OPENSSL_DLL} ${CRYPTO_DLL} DESTINATION ".")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -54,8 +54,7 @@ BrowserService::BrowserService(DatabaseTabWidget* parent)
|
||||
: m_dbTabWidget(parent)
|
||||
, m_dialogActive(false)
|
||||
, m_bringToFrontRequested(false)
|
||||
, m_wasMinimized(false)
|
||||
, m_wasHidden(false)
|
||||
, m_prevWindowState(WindowState::Normal)
|
||||
, m_keepassBrowserUUID(Tools::hexToUuid("de887cc3036343b8974b5911b8816224"))
|
||||
{
|
||||
// Don't connect the signals when used from DatabaseSettingsWidgetBrowser (parent is nullptr)
|
||||
@@ -1009,29 +1008,42 @@ bool BrowserService::checkLegacySettings()
|
||||
|
||||
void BrowserService::hideWindow() const
|
||||
{
|
||||
if (m_wasMinimized) {
|
||||
if (m_prevWindowState == WindowState::Minimized) {
|
||||
getMainWindow()->showMinimized();
|
||||
} else {
|
||||
#ifdef Q_OS_MACOS
|
||||
if (m_wasHidden) {
|
||||
if (m_prevWindowState == WindowState::Hidden) {
|
||||
macUtils()->hideOwnWindow();
|
||||
} else {
|
||||
macUtils()->raiseLastActiveWindow();
|
||||
}
|
||||
#else
|
||||
getMainWindow()->lower();
|
||||
if (m_prevWindowState == WindowState::Hidden) {
|
||||
getMainWindow()->hideWindow();
|
||||
} else {
|
||||
getMainWindow()->lower();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserService::raiseWindow(const bool force)
|
||||
{
|
||||
m_wasMinimized = getMainWindow()->isMinimized();
|
||||
m_prevWindowState = WindowState::Normal;
|
||||
if (getMainWindow()->isMinimized()) {
|
||||
m_prevWindowState = WindowState::Minimized;
|
||||
}
|
||||
#ifdef Q_OS_MACOS
|
||||
m_wasHidden = macUtils()->isHidden();
|
||||
if (macUtils()->isHidden()) {
|
||||
m_prevWindowState = WindowState::Hidden;
|
||||
}
|
||||
macUtils()->raiseOwnWindow();
|
||||
Tools::wait(500);
|
||||
#else
|
||||
if (getMainWindow()->isHidden()) {
|
||||
m_prevWindowState = WindowState::Hidden;
|
||||
}
|
||||
|
||||
if (force) {
|
||||
getMainWindow()->bringToFront();
|
||||
}
|
||||
|
||||
@@ -97,6 +97,13 @@ private:
|
||||
Allowed
|
||||
};
|
||||
|
||||
enum WindowState
|
||||
{
|
||||
Normal,
|
||||
Minimized,
|
||||
Hidden
|
||||
};
|
||||
|
||||
private:
|
||||
QList<Entry*> sortEntries(QList<Entry*>& pwEntries, const QString& host, const QString& submitUrl);
|
||||
bool confirmEntries(QList<Entry*>& pwEntriesToConfirm,
|
||||
@@ -125,8 +132,7 @@ private:
|
||||
DatabaseTabWidget* const m_dbTabWidget;
|
||||
bool m_dialogActive;
|
||||
bool m_bringToFrontRequested;
|
||||
bool m_wasMinimized;
|
||||
bool m_wasHidden;
|
||||
WindowState m_prevWindowState;
|
||||
QUuid m_keepassBrowserUUID;
|
||||
};
|
||||
|
||||
|
||||
@@ -78,7 +78,10 @@ int Merge::execute(const QStringList& arguments)
|
||||
|
||||
QSharedPointer<Database> db2;
|
||||
if (!parser.isSet("same-credentials")) {
|
||||
db2 = Utils::unlockDatabase(args.at(1), parser.value(keyFileFromOption), Utils::STDOUT, Utils::STDERR);
|
||||
db2 = Utils::unlockDatabase(args.at(1),
|
||||
parser.value(keyFileFromOption),
|
||||
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
|
||||
Utils::STDERR);
|
||||
if (!db2) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -47,11 +47,11 @@ int Remove::execute(const QStringList& arguments)
|
||||
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription(QCoreApplication::tr("main", "Remove an entry from the database."));
|
||||
parser.addPositionalArgument("database", QCoreApplication::tr("main", "Path of the database."));
|
||||
parser.setApplicationDescription(QObject::tr("Remove an entry from the database."));
|
||||
parser.addPositionalArgument("database", QObject::tr("Path of the database."));
|
||||
parser.addOption(Command::QuietOption);
|
||||
parser.addOption(Command::KeyFileOption);
|
||||
parser.addPositionalArgument("entry", QCoreApplication::tr("main", "Path of the entry to remove."));
|
||||
parser.addPositionalArgument("entry", QObject::tr("Path of the entry to remove."));
|
||||
parser.addHelpOption();
|
||||
parser.process(arguments);
|
||||
|
||||
|
||||
@@ -427,14 +427,21 @@ QString Entry::totp() const
|
||||
void Entry::setTotp(QSharedPointer<Totp::Settings> settings)
|
||||
{
|
||||
beginUpdate();
|
||||
m_data.totpSettings = std::move(settings);
|
||||
|
||||
auto text = Totp::writeSettings(m_data.totpSettings, title(), username());
|
||||
if (m_attributes->hasKey(Totp::ATTRIBUTE_OTP)) {
|
||||
m_attributes->set(Totp::ATTRIBUTE_OTP, text, true);
|
||||
if (settings->key.isEmpty()) {
|
||||
m_data.totpSettings.reset();
|
||||
m_attributes->remove(Totp::ATTRIBUTE_OTP);
|
||||
m_attributes->remove(Totp::ATTRIBUTE_SEED);
|
||||
m_attributes->remove(Totp::ATTRIBUTE_SETTINGS);
|
||||
} else {
|
||||
m_attributes->set(Totp::ATTRIBUTE_SEED, m_data.totpSettings->key, true);
|
||||
m_attributes->set(Totp::ATTRIBUTE_SETTINGS, text);
|
||||
m_data.totpSettings = std::move(settings);
|
||||
|
||||
auto text = Totp::writeSettings(m_data.totpSettings, title(), username());
|
||||
if (m_attributes->hasKey(Totp::ATTRIBUTE_OTP)) {
|
||||
m_attributes->set(Totp::ATTRIBUTE_OTP, text, true);
|
||||
} else {
|
||||
m_attributes->set(Totp::ATTRIBUTE_SEED, m_data.totpSettings->key, true);
|
||||
m_attributes->set(Totp::ATTRIBUTE_SETTINGS, text);
|
||||
}
|
||||
}
|
||||
endUpdate();
|
||||
}
|
||||
|
||||
@@ -137,7 +137,6 @@ void EntryAttributes::remove(const QString& key)
|
||||
Q_ASSERT(!isDefaultAttribute(key));
|
||||
|
||||
if (!m_attributes.contains(key)) {
|
||||
Q_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -865,7 +865,9 @@ Group* Group::clone(Entry::CloneFlags entryFlags, Group::CloneFlags groupFlags)
|
||||
|
||||
void Group::copyDataFrom(const Group* other)
|
||||
{
|
||||
m_data = other->m_data;
|
||||
if (set(m_data, other->m_data)) {
|
||||
emit groupDataChanged(this);
|
||||
}
|
||||
m_customData->copyDataFrom(other->m_customData);
|
||||
m_lastTopVisibleEntry = other->m_lastTopVisibleEntry;
|
||||
}
|
||||
@@ -1079,7 +1081,7 @@ bool Group::GroupData::equals(const Group::GroupData& other, CompareItemOptions
|
||||
if (::compare(customIcon, other.customIcon) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (timeInfo.equals(other.timeInfo, options) != 0) {
|
||||
if (!timeInfo.equals(other.timeInfo, options)) {
|
||||
return false;
|
||||
}
|
||||
// TODO HNH: Some properties are configurable - should they be ignored?
|
||||
|
||||
@@ -367,6 +367,10 @@ void KdbxXmlReader::parseIcon()
|
||||
}
|
||||
|
||||
if (uuidSet && iconSet) {
|
||||
// Check for duplicate UUID (corruption)
|
||||
if (m_meta->containsCustomIcon(uuid)) {
|
||||
uuid = QUuid::createUuid();
|
||||
}
|
||||
m_meta->addCustomIcon(uuid, icon);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -20,13 +20,144 @@
|
||||
#include "ui_AboutDialog.h"
|
||||
|
||||
#include "config-keepassx.h"
|
||||
#include "git-info.h"
|
||||
#include "core/FilePath.h"
|
||||
#include "crypto/Crypto.h"
|
||||
#include "git-info.h"
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QSysInfo>
|
||||
|
||||
static const QString aboutMaintainers = R"(
|
||||
<p><ul>
|
||||
<li>Jonathan White (<a href="https://github.com/droidmonkey">droidmonkey</a>)</li>
|
||||
<li>Janek Bevendorff (<a href="https://github.com/phoerious">phoerious</a>)</li>
|
||||
<li><a href="https://github.com/TheZ3ro">TheZ3ro</a></li>
|
||||
<li>Louis-Bertrand (<a href="https://github.com/louib">louib</a>)</li>
|
||||
<li>Weslly Honorato (<a href="https://github.com/weslly">weslly</a>)</li>
|
||||
<li>Toni Spets (<a href="https://github.com/hifi">hifi</a>)</li>
|
||||
<li>Sami Vänttinen (<a href="https://github.com/varjolintu">varjolintu</a>)</li>
|
||||
</ul></p>
|
||||
)";
|
||||
|
||||
static const QString aboutContributors = R"(
|
||||
<h3>VIP Patreon Supporters:</h3>
|
||||
<ul>
|
||||
<li>John Cook</li>
|
||||
<li>Max Anderson</li>
|
||||
<li>l0b0</li>
|
||||
<li>NarwhalOfAges</li>
|
||||
<li>Caleb Currie</li>
|
||||
<li>Igor Zinovik</li>
|
||||
<li>Morgan Courbet</li>
|
||||
<li>Sergiu Coroi</li>
|
||||
</ul>
|
||||
<h3>Notable Code Contributions:</h3>
|
||||
<ul>
|
||||
<li>droidmonkey</li>
|
||||
<li>phoerious</li>
|
||||
<li>TheZ3ro</li>
|
||||
<li>louib</li>
|
||||
<li>weslly</li>
|
||||
<li>varjolintu (KeePassXC-Browser)</li>
|
||||
<li>hifi (SSH Agent)</li>
|
||||
<li>ckieschnick (KeeShare)</li>
|
||||
<li>seatedscribe (CSV Import)</li>
|
||||
<li>brainplot (many improvements)</li>
|
||||
<li>kneitinger (many improvements)</li>
|
||||
<li>frostasm (many improvements)</li>
|
||||
<li>fonic (Entry Table View)</li>
|
||||
<li>kylemanna (YubiKey)</li>
|
||||
<li>keithbennett (KeePassHTTP)</li>
|
||||
<li>Typz (KeePassHTTP)</li>
|
||||
<li>denk-mal (KeePassHTTP)</li>
|
||||
<li>angelsl (KDBX 4)</li>
|
||||
<li>debfx (KeePassX)</li>
|
||||
<li>BlueIce (KeePassX)</li>
|
||||
</ul>
|
||||
<h3>Patreon Supporters:</h3>
|
||||
<ul>
|
||||
<li>Ashura</li>
|
||||
<li>Alexanderjb</li>
|
||||
<li>Andreas Kollmann</li>
|
||||
<li>Richard Ames</li>
|
||||
<li>Christian Rasmussen</li>
|
||||
<li>Gregory Werbin</li>
|
||||
<li>Nuutti Toivola</li>
|
||||
<li>SLmanDR</li>
|
||||
<li>Tyler Gass</li>
|
||||
<li>Lionel Laské</li>
|
||||
<li>Dmitrii Galinskii</li>
|
||||
<li>Sergei Maximov</li>
|
||||
<li>John-Ivar</li>
|
||||
<li>Clayton Casciato</li>
|
||||
</ul>
|
||||
<h3>Translations:</h3>
|
||||
<ul>
|
||||
<li><strong>Arabic</strong>: AboShanab, Night1, kmutahar, muha_abdulaziz, omar.nsy</li>
|
||||
<li><strong>Basque</strong>: azken_tximinoa, Hey_neken</li>
|
||||
<li><strong>Bengali</strong>: codesmite</li>
|
||||
<li><strong>Burmese</strong>: Phyu</li>
|
||||
<li><strong>Catalan</strong>: capitantrueno, dsoms, mcus, raulua, ZJaume</li>
|
||||
<li><strong>Chinese (China)</strong>: Biggulu, Brandon_c, Dy64, Felix2yu, Small_Ku, Z4HD,
|
||||
carp0129, ef6, holic, kikyous, kofzhanganguo, ligyxy, remonli, slgray, umi_neko, vc5</li>
|
||||
<li><strong>Chinese (Taiwan)</strong>: BestSteve, MiauLightouch, Small_Ku, flachesis, gojpdchx,
|
||||
raymondtau, th3lusive, yan12125, ymhuang0808</li>
|
||||
<li><strong>Czech</strong>: DanielMilde, JosefVitu, awesomevojta, pavelb, tpavelek</li>
|
||||
<li><strong>Danish</strong>: nlkl, KalleDK, MannVera, alfabetacain, ebbe, thniels</li>
|
||||
<li><strong>Dutch</strong>: Bubbel, Dr.Default, apie, bartlibert, evanoosten, fvw, KnooL,
|
||||
srgvg, Vistaus, wanderingidea, Stephan_P, Zombaya1, e2jk, ovisicnarf, pietermj, rigrig,
|
||||
theniels17</li>
|
||||
<li><strong>English (UK)</strong>: YCMHARHZ, rookwood01, throne3d</li>
|
||||
<li><strong>Esperanto</strong>: batisteo</li>
|
||||
<li><strong>Estonian</strong>: Hermanio</li>
|
||||
<li><strong>Finnish</strong>: artnay, Jarppi, MawKKe, petri, tomisalmi, hifi, varjolintu</li>
|
||||
<li><strong>French</strong>: yahoe.001, A1RO, Albynton, Cabirto, Fumble, Gui13, MartialBis,
|
||||
MrHeadwar, Nesousx, Raphi111, Scrat15, aghilas.messara, alexisju, b_mortgat, benoitbalon,
|
||||
bisaloo, e2jk, ebrious, frgnca, ggtr1138, gilbsgilbs, gtalbot, houdini, houdini69,
|
||||
iannick, jlutran, kyodev, lacnic, laetilodie, logut, mlpo, narzb, nekopep, pBouillon,
|
||||
plunkets, theodex, tl_pierre, wilfriedroset</li>
|
||||
<li><strong>German</strong>: origin_de, mithrial, andreas.maier, NotAName, Atalanttore,
|
||||
Hativ, muellerma, mircsicz, derhagen, Wyrrrd, mbetz, kflesch, nursoda, BasicBaer,
|
||||
mfernau77, for1real, joe776, waster, eth0, marcbone, mcliquid, transi_222, MarcEdinger,
|
||||
DavidHamburg, jensrutschmann, codejunky, vlenzer, montilo, antsas, rgloor, Calyrx,
|
||||
omnisome4, pcrcoding</li>
|
||||
<li><strong>Greek</strong>: magkopian, nplatis, tassos.b, xinomilo</li>
|
||||
<li><strong>Hungarian</strong>: bubu, meskobalazs, urbalazs, andras_tim</li>
|
||||
<li><strong>Indonesian</strong>: zk, bora_ach</li>
|
||||
<li><strong>Italian</strong>: the.sailor, VosaxAlo, tosky, seatedscribe, bovirus, Peo,
|
||||
NITAL, FranzMari, Gringoarg, amaxis, salvatorecordiano, duncanmid, lucaim</li>
|
||||
<li><strong>Japanese</strong>: masoo, metalic_cat, p2635, Shinichirou_Yamada,
|
||||
vargas.peniel, vmemjp, yukinakato, gojpdchx, saita</li>
|
||||
<li><strong>Korean</strong>: cancantun, peremen</li>
|
||||
<li><strong>Lithuanian</strong>: Moo, pauliusbaulius, rookwood101</li>
|
||||
<li><strong>Norweigian Bokmål</strong>: sattor, ysteinalver, jumpingmushroom,
|
||||
JardarBolin, eothred, torgeirf, haarek</li>
|
||||
<li><strong>Polish</strong>: keypress, konradmb, mrerexx, psobczak, SebJez, hoek</li>
|
||||
<li><strong>Portuguese</strong>: weslly, xendez</li>
|
||||
<li><strong>Portuguese (Brazil)</strong>: danielbibit, guilherme__sr, Havokdan, fabiom,
|
||||
flaviobn, weslly, newmanisaac, rafaelnp, RockyTV, xendez, lucasjsoliveira, vitor895,
|
||||
mauri.andres, andersoniop</li>
|
||||
<li><strong>Portuguese (Portugal)</strong>: American_Jesus, xendez, hds, arainho, a.santos,
|
||||
pfialho, smarquespt, mihai.ile, smiguel, lmagomes, xnenjm</li>
|
||||
<li><strong>Russian</strong>: Mogost, alexminza, KekcuHa, NcNZllQnHVU, ruslan.denisenko,
|
||||
agag11507, anm, cl0ne, JayDi85, RKuchma, Rakleed, vsvyatski, NetWormKido, DG,
|
||||
Mr.GreyWolf, VictorR2007, _nomoretears_, netforhack, denoos, wkill95, Shevchuk,
|
||||
talvind, artemkonenko, ShareDVI</li>
|
||||
<li><strong>Slovak</strong>: l.martinicky, Slavko, crazko, pecer</li>
|
||||
<li><strong>Spanish</strong>: gonrial, iglpdc, vsvyatski, Xlate1984, erinm, AndreachongB,
|
||||
piegope, lupa18, e2jk, capitantrueno, LeoBeltran, antifaz, Zranz, AdrianClv,
|
||||
EdwardNavarro, rodolfo.guagnini, NicolasCGN, caralu74, puchrojo, DarkHolme,
|
||||
pdinoto, masanchez5000, adolfogc, systurbed, mauri.andres, Bendhet, vargas.peniel,
|
||||
eliluminado, jojobrambs, pquin</li>
|
||||
<li><strong>Swedish</strong>: theschitz, Anders_Bergqvist, LIINdd, krklns, henziger,
|
||||
jpyllman, peron, Thelin, baxtex, zeroxfourc</li>
|
||||
<li><strong>Thai</strong>: arthit, rayg</li>
|
||||
<li><strong>Turkish</strong>: TeknoMobil, etc, SeLeNLeR, ethem578, cagries, N3pp</li>
|
||||
<li><strong>Ukrainian</strong>: brisk022, exlevan, chulivska, cl0ne, zoresvit,
|
||||
netforhack, ShareDVI</li>
|
||||
</ul>
|
||||
)";
|
||||
|
||||
AboutDialog::AboutDialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, m_ui(new Ui::AboutDialog())
|
||||
@@ -107,6 +238,9 @@ AboutDialog::AboutDialog(QWidget* parent)
|
||||
|
||||
m_ui->debugInfo->setPlainText(debugInfo);
|
||||
|
||||
m_ui->maintainers->setText(aboutMaintainers);
|
||||
m_ui->contributors->setText(aboutContributors);
|
||||
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(close()));
|
||||
connect(m_ui->copyToClipboard, SIGNAL(clicked()), SLOT(copyToClipboard()));
|
||||
|
||||
@@ -163,7 +163,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<widget class="QLabel" name="maintainers">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -171,15 +171,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"><ul>
|
||||
<li>Jonathan White (<a href="https://github.com/droidmonkey">droidmonkey</a>)</li>
|
||||
<li>Janek Bevendorff (<a href="https://github.com/phoerious">phoerious</a>)</li>
|
||||
<li><a href="https://github.com/TheZ3ro">TheZ3ro</a></li>
|
||||
<li>Louis-Bertrand (<a href="https://github.com/louib">louib</a>)</li>
|
||||
<li>Weslly Honorato (<a href="https://github.com/weslly">weslly</a>)</li>
|
||||
<li>Toni Spets (<a href="https://github.com/hifi">hifi</a>)</li>
|
||||
<li>Sami V&auml;nttinen (<a href="https://github.com/varjolintu">varjolintu</a>)</li>
|
||||
</ul></string>
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
@@ -238,8 +230,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>449</width>
|
||||
<height>845</height>
|
||||
<width>466</width>
|
||||
<height>246</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
@@ -255,61 +247,7 @@
|
||||
<cursorShape>IBeamCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"><h3>VIP Patreon Supporters:</h3>
|
||||
<ul>
|
||||
<li>John Cook</li>
|
||||
<li>Max Anderson</li>
|
||||
</ul>
|
||||
<h3>Notable Code Contributions:</h3>
|
||||
<ul>
|
||||
<li>droidmonkey</li>
|
||||
<li>phoerious</li>
|
||||
<li>TheZ3ro</li>
|
||||
<li>louib</li>
|
||||
<li>weslly</li>
|
||||
<li>varjolintu (KeePassXC-Browser)</li>
|
||||
<li>hifi (SSH Agent)</li>
|
||||
<li>frostasm</li>
|
||||
<li>fonic (Entry Table View)</li>
|
||||
<li>kylemanna (YubiKey)</li>
|
||||
<li>keithbennett (KeePassHTTP)</li>
|
||||
<li>Typz (KeePassHTTP)</li>
|
||||
<li>denk-mal (KeePassHTTP)</li>
|
||||
<li>angelsl (KDBX 4)</li>
|
||||
<li>seatedscribe (CSV Import)</li>
|
||||
<li>debfx (KeePassX)</li>
|
||||
<li>BlueIce (KeePassX)</li>
|
||||
</ul>
|
||||
<h3>Patreon Supporters:</h3>
|
||||
<ul>
|
||||
<li>Ashura</li>
|
||||
<li>Alexanderjb</li>
|
||||
<li>Andreas Kollmann</li>
|
||||
<li>Richard Ames</li>
|
||||
</ul>
|
||||
<h3>Translations:</h3>
|
||||
<ul>
|
||||
<li><strong>Basque</strong>: azken_tximinoa, Hey_neken</li>
|
||||
<li><strong>Catalan</strong>: capitantrueno, dsoms, mcus, raulua, ZJaume</li>
|
||||
<li><strong>Chinese (China)</strong>: Biggulu, Brandon_c, hoilc, ligyxy, vc5, Small_Ku</li>
|
||||
<li><strong>Chinese (Taiwan)</strong>: BestSteve, MiauLightouch, Small_Ku, yan12125, ymhuang0808</li>
|
||||
<li><strong>Czech</strong>: DanielMilde, JosefVitu, pavelb, tpavelek</li>
|
||||
<li><strong>Danish</strong>: nlkl</li>
|
||||
<li><strong>Dutch</strong>: apie, bartlibert, evanoosten, fvw, KnooL, srgvg, Vistaus, wanderingidea</li>
|
||||
<li><strong>Finnish</strong>: artnay, Jarppi, MawKKe</li>
|
||||
<li><strong>French</strong>: A1RO, aghilas.messara, bisaloo, frgnca, ggtr1138, gilbsgilbs, gtalbot, Gui13, iannick, jlutran, kyodev, logut, MartialBis, narzb, pBouillon, plunkets, Raphi111, Scrat15, tl_pierre, wilfriedroset</li>
|
||||
<li><strong>German</strong>: antsas, BasicBaer, Calyrx, codejunky, DavidHamburg, eth0, for1real, jensrutschmann, joe776, kflesch, MarcEdinger, marcbone, mcliquid, mfernau77, montilo, nursoda, omnisome4, origin_de, pcrcoding, phoerious, rgloor, transi_222, vlenzer, waster</li>
|
||||
<li><strong>Greek</strong>: magkopian, nplatis, tassos.b, xinomilo</li>
|
||||
<li><strong>Hungarian</strong>: bubu, meskobalazs, urbalazs</li>
|
||||
<li><strong>Indonesian</strong>: zk</li>
|
||||
<li><strong>Italian</strong>: amaxis, bovirus, duncanmid, FranzMari, lucaim, Mte90, Peo, TheZ3ro, tosky, VosaxAlo</li>
|
||||
<li><strong>Japanese</strong>: masoo, metalic_cat, p2635, Shinichirou_Yamada, vargas.peniel, vmemjp, yukinakato</li>
|
||||
<li><strong>Korean</strong>: cancantun, peremen</li>
|
||||
<li><strong>Lithuanian</strong>: Moo</li>
|
||||
<li><strong>Polish</strong>: keypress, konradmb, mrerexx, psobczak</li>
|
||||
<li><strong>Portuguese (Brazil)</strong>: danielbibit, fabiom, flaviobn, vitor895, weslly</li>
|
||||
</ul>
|
||||
</string>
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::AutoText</enum>
|
||||
|
||||
@@ -111,8 +111,7 @@ Application::Application(int& argc, char** argv)
|
||||
|
||||
if (!m_alreadyRunning) {
|
||||
// If we get here then the original instance is likely dead
|
||||
qWarning() << QCoreApplication::translate(
|
||||
"Main", "Existing single-instance lock file is invalid. Launching new instance.")
|
||||
qWarning() << QObject::tr("Existing single-instance lock file is invalid. Launching new instance.")
|
||||
.toUtf8()
|
||||
.constData();
|
||||
|
||||
@@ -126,8 +125,7 @@ Application::Application(int& argc, char** argv)
|
||||
break;
|
||||
}
|
||||
default:
|
||||
qWarning() << QCoreApplication::translate("Main",
|
||||
"The lock file could not be created. Single-instance mode disabled.")
|
||||
qWarning() << QObject::tr("The lock file could not be created. Single-instance mode disabled.")
|
||||
.toUtf8()
|
||||
.constData();
|
||||
}
|
||||
|
||||
@@ -1162,7 +1162,7 @@ void MainWindow::hideYubiKeyPopup()
|
||||
void MainWindow::bringToFront()
|
||||
{
|
||||
ensurePolished();
|
||||
setWindowState(windowState() & ~Qt::WindowMinimized);
|
||||
setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
|
||||
show();
|
||||
raise();
|
||||
activateWindow();
|
||||
|
||||
@@ -45,16 +45,21 @@ void TotpSetupDialog::saveSettings()
|
||||
{
|
||||
QString encShortName;
|
||||
uint digits = Totp::DEFAULT_DIGITS;
|
||||
if (m_ui->radio8Digits->isChecked()) {
|
||||
digits = 8;
|
||||
} else if (m_ui->radio7Digits->isChecked()) {
|
||||
digits = 7;
|
||||
} else if (m_ui->radioSteam->isChecked()) {
|
||||
uint step = Totp::DEFAULT_STEP;
|
||||
|
||||
if (m_ui->radioSteam->isChecked()) {
|
||||
digits = Totp::STEAM_DIGITS;
|
||||
encShortName = Totp::STEAM_SHORTNAME;
|
||||
} else if (m_ui->radioCustom->isChecked()) {
|
||||
step = m_ui->stepSpinBox->value();
|
||||
if (m_ui->radio8Digits->isChecked()) {
|
||||
digits = 8;
|
||||
} else if (m_ui->radio7Digits->isChecked()) {
|
||||
digits = 7;
|
||||
}
|
||||
}
|
||||
|
||||
auto settings = Totp::createSettings(m_ui->seedEdit->text(), digits, m_ui->stepSpinBox->value(), encShortName);
|
||||
auto settings = Totp::createSettings(m_ui->seedEdit->text(), digits, step, encShortName, m_entry->totpSettings());
|
||||
m_entry->setTotp(settings);
|
||||
emit totpUpdated();
|
||||
close();
|
||||
|
||||
@@ -127,7 +127,7 @@ void DatabaseSettingsWidgetEncryption::setupAlgorithmComboBox()
|
||||
{
|
||||
m_ui->algorithmComboBox->clear();
|
||||
for (auto& cipher : asConst(KeePass2::CIPHERS)) {
|
||||
m_ui->algorithmComboBox->addItem(QCoreApplication::translate("KeePass2", cipher.second.toUtf8()),
|
||||
m_ui->algorithmComboBox->addItem(cipher.second.toUtf8(),
|
||||
cipher.first.toByteArray());
|
||||
}
|
||||
int cipherIndex = m_ui->algorithmComboBox->findData(m_db->cipher().toByteArray());
|
||||
@@ -142,7 +142,7 @@ void DatabaseSettingsWidgetEncryption::setupKdfComboBox()
|
||||
bool block = m_ui->kdfComboBox->blockSignals(true);
|
||||
m_ui->kdfComboBox->clear();
|
||||
for (auto& kdf : asConst(KeePass2::KDFS)) {
|
||||
m_ui->kdfComboBox->addItem(QCoreApplication::translate("KeePass2", kdf.second.toUtf8()),
|
||||
m_ui->kdfComboBox->addItem(kdf.second.toUtf8(),
|
||||
kdf.first.toByteArray());
|
||||
}
|
||||
m_ui->kdfComboBox->blockSignals(block);
|
||||
|
||||
@@ -312,7 +312,7 @@ bool EntryAttachmentsWidget::insertAttachments(const QStringList& filenames, QSt
|
||||
}
|
||||
|
||||
if (!errors.isEmpty()) {
|
||||
errorMessage = tr("Unable to open files:\n%1").arg(errors.join('\n'));
|
||||
errorMessage = tr("Unable to open file(s):\n%1", "", errors.size()).arg(errors.join('\n'));
|
||||
}
|
||||
|
||||
return errors.isEmpty();
|
||||
|
||||
@@ -79,9 +79,9 @@ QWidget* YubiKeyEditWidget::componentEditWidget()
|
||||
|
||||
// clang-format off
|
||||
connect(YubiKey::instance(), SIGNAL(detected(int,bool)), SLOT(yubikeyDetected(int,bool)), Qt::QueuedConnection);
|
||||
// clang-format on
|
||||
|
||||
connect(YubiKey::instance(), SIGNAL(detectComplete()), SLOT(yubikeyDetectComplete()), Qt::QueuedConnection);
|
||||
connect(YubiKey::instance(), SIGNAL(notFound()), SLOT(noYubikeyFound()), Qt::QueuedConnection);
|
||||
// clang-format on
|
||||
|
||||
pollYubikey();
|
||||
#endif
|
||||
@@ -102,9 +102,11 @@ void YubiKeyEditWidget::pollYubikey()
|
||||
if (!m_compEditWidget) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_isDetected = false;
|
||||
m_compUi->comboChallengeResponse->clear();
|
||||
m_compUi->buttonRedetectYubikey->setEnabled(false);
|
||||
m_compUi->comboChallengeResponse->setEnabled(false);
|
||||
m_compUi->comboChallengeResponse->clear();
|
||||
m_compUi->yubikeyProgress->setVisible(true);
|
||||
|
||||
// YubiKey init is slow, detect asynchronously to not block the UI
|
||||
@@ -119,12 +121,8 @@ void YubiKeyEditWidget::yubikeyDetected(int slot, bool blocking)
|
||||
return;
|
||||
}
|
||||
YkChallengeResponseKey yk(slot, blocking);
|
||||
m_compUi->comboChallengeResponse->clear();
|
||||
// add detected YubiKey to combo box and encode blocking mode in LSB, slot number in second LSB
|
||||
m_compUi->comboChallengeResponse->addItem(yk.getName(), QVariant((slot << 1u) | blocking));
|
||||
m_compUi->comboChallengeResponse->setEnabled(true);
|
||||
m_compUi->buttonRedetectYubikey->setEnabled(true);
|
||||
m_compUi->yubikeyProgress->setVisible(false);
|
||||
m_isDetected = true;
|
||||
#else
|
||||
Q_UNUSED(slot);
|
||||
@@ -132,6 +130,13 @@ void YubiKeyEditWidget::yubikeyDetected(int slot, bool blocking)
|
||||
#endif
|
||||
}
|
||||
|
||||
void YubiKeyEditWidget::yubikeyDetectComplete()
|
||||
{
|
||||
m_compUi->comboChallengeResponse->setEnabled(true);
|
||||
m_compUi->buttonRedetectYubikey->setEnabled(true);
|
||||
m_compUi->yubikeyProgress->setVisible(false);
|
||||
}
|
||||
|
||||
void YubiKeyEditWidget::noYubikeyFound()
|
||||
{
|
||||
#ifdef WITH_XC_YUBIKEY
|
||||
|
||||
@@ -46,6 +46,7 @@ protected:
|
||||
|
||||
private slots:
|
||||
void yubikeyDetected(int slot, bool blocking);
|
||||
void yubikeyDetectComplete();
|
||||
void noYubikeyFound();
|
||||
void pollYubikey();
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace
|
||||
} else {
|
||||
warning.setIcon(QMessageBox::Question);
|
||||
warning.setWindowTitle(ShareObserver::tr("Import from container with certificate"));
|
||||
warning.setText(ShareObserver::tr("Do you want to trust %1 with the fingerprint of %2 from %3")
|
||||
warning.setText(ShareObserver::tr("Do you want to trust %1 with the fingerprint of %2 from %3?")
|
||||
.arg(certificate.signer, certificate.fingerprint(), reference.path));
|
||||
}
|
||||
auto untrustedOnce = warning.addButton(ShareObserver::tr("Not this time"), QMessageBox::ButtonRole::NoRole);
|
||||
|
||||
20
src/main.cpp
20
src/main.cpp
@@ -68,22 +68,22 @@ int main(int argc, char** argv)
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription(
|
||||
QCoreApplication::translate("main", "KeePassXC - cross-platform password manager"));
|
||||
QObject::tr("KeePassXC - cross-platform password manager"));
|
||||
parser.addPositionalArgument(
|
||||
"filename",
|
||||
QCoreApplication::translate("main", "filenames of the password databases to open (*.kdbx)"),
|
||||
QObject::tr("filenames of the password databases to open (*.kdbx)"),
|
||||
"[filename(s)]");
|
||||
|
||||
QCommandLineOption configOption(
|
||||
"config", QCoreApplication::translate("main", "path to a custom config file"), "config");
|
||||
"config", QObject::tr("path to a custom config file"), "config");
|
||||
QCommandLineOption keyfileOption(
|
||||
"keyfile", QCoreApplication::translate("main", "key file of the database"), "keyfile");
|
||||
"keyfile", QObject::tr("key file of the database"), "keyfile");
|
||||
QCommandLineOption pwstdinOption("pw-stdin",
|
||||
QCoreApplication::translate("main", "read password of the database from stdin"));
|
||||
QObject::tr("read password of the database from stdin"));
|
||||
// This is needed under Windows where clients send --parent-window parameter with Native Messaging connect method
|
||||
QCommandLineOption parentWindowOption(QStringList() << "pw"
|
||||
<< "parent-window",
|
||||
QCoreApplication::translate("main", "Parent window handle"),
|
||||
QObject::tr("Parent window handle"),
|
||||
"handle");
|
||||
|
||||
QCommandLineOption helpOption = parser.addHelpOption();
|
||||
@@ -106,7 +106,7 @@ int main(int argc, char** argv)
|
||||
if (!fileNames.isEmpty()) {
|
||||
app.sendFileNamesToRunningInstance(fileNames);
|
||||
}
|
||||
qWarning() << QCoreApplication::translate("Main", "Another instance of KeePassXC is already running.")
|
||||
qWarning() << QObject::tr("Another instance of KeePassXC is already running.")
|
||||
.toUtf8()
|
||||
.constData();
|
||||
return 0;
|
||||
@@ -115,10 +115,10 @@ int main(int argc, char** argv)
|
||||
QApplication::setQuitOnLastWindowClosed(false);
|
||||
|
||||
if (!Crypto::init()) {
|
||||
QString error = QCoreApplication::translate("Main", "Fatal error while testing the cryptographic functions.");
|
||||
QString error = QObject::tr("Fatal error while testing the cryptographic functions.");
|
||||
error.append("\n");
|
||||
error.append(Crypto::errorString());
|
||||
MessageBox::critical(nullptr, QCoreApplication::translate("Main", "KeePassXC - Error"), error);
|
||||
MessageBox::critical(nullptr, QObject::tr("KeePassXC - Error"), error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ int main(int argc, char** argv)
|
||||
// buffer for native messaging, even if the specified file does not exist
|
||||
static QTextStream in(stdin, QIODevice::ReadOnly);
|
||||
static QTextStream out(stdout, QIODevice::WriteOnly);
|
||||
out << QCoreApplication::translate("Main", "Database password: ") << flush;
|
||||
out << QObject::tr("Database password: ") << flush;
|
||||
password = Utils::getPassword();
|
||||
}
|
||||
|
||||
|
||||
@@ -55,10 +55,16 @@ QSharedPointer<Totp::Settings> Totp::parseSettings(const QString& rawSettings, c
|
||||
QUrlQuery query(rawSettings);
|
||||
if (query.hasQueryItem("key")) {
|
||||
// Compatibility with "KeeOtp" plugin
|
||||
// if settings are changed, will convert to semi-colon format
|
||||
settings->keeOtp = true;
|
||||
settings->key = query.queryItemValue("key");
|
||||
settings->digits = query.queryItemValue("size").toUInt();
|
||||
settings->step = query.queryItemValue("step").toUInt();
|
||||
settings->digits = DEFAULT_DIGITS;
|
||||
settings->step = DEFAULT_STEP;
|
||||
if (query.hasQueryItem("size")) {
|
||||
settings->digits = query.queryItemValue("size").toUInt();
|
||||
}
|
||||
if (query.hasQueryItem("step")) {
|
||||
settings->step = query.queryItemValue("step").toUInt();
|
||||
}
|
||||
} else {
|
||||
// Parse semi-colon separated values ([step];[digits|S])
|
||||
auto vars = rawSettings.split(";");
|
||||
@@ -88,12 +94,24 @@ QSharedPointer<Totp::Settings> Totp::parseSettings(const QString& rawSettings, c
|
||||
return settings;
|
||||
}
|
||||
|
||||
QSharedPointer<Totp::Settings>
|
||||
Totp::createSettings(const QString& key, const uint digits, const uint step, const QString& encoderShortName)
|
||||
QSharedPointer<Totp::Settings> Totp::createSettings(const QString& key,
|
||||
const uint digits,
|
||||
const uint step,
|
||||
const QString& encoderShortName,
|
||||
QSharedPointer<Totp::Settings> prevSettings)
|
||||
{
|
||||
bool isCustom = digits != DEFAULT_DIGITS || step != DEFAULT_STEP;
|
||||
return QSharedPointer<Totp::Settings>(
|
||||
new Totp::Settings{getEncoderByShortName(encoderShortName), key, false, isCustom, digits, step});
|
||||
if (prevSettings) {
|
||||
prevSettings->key = key;
|
||||
prevSettings->digits = digits;
|
||||
prevSettings->step = step;
|
||||
prevSettings->encoder = Totp::getEncoderByShortName(encoderShortName);
|
||||
prevSettings->custom = isCustom;
|
||||
return prevSettings;
|
||||
} else {
|
||||
return QSharedPointer<Totp::Settings>(
|
||||
new Totp::Settings{getEncoderByShortName(encoderShortName), key, false, false, isCustom, digits, step});
|
||||
}
|
||||
}
|
||||
|
||||
QString Totp::writeSettings(const QSharedPointer<Totp::Settings>& settings,
|
||||
@@ -118,15 +136,19 @@ QString Totp::writeSettings(const QSharedPointer<Totp::Settings>& settings,
|
||||
urlstring.append("&encoder=").append(settings->encoder.name);
|
||||
}
|
||||
return urlstring;
|
||||
}
|
||||
|
||||
// Semicolon output [step];[encoder]
|
||||
if (!settings->encoder.shortName.isEmpty()) {
|
||||
} else if (settings->keeOtp) {
|
||||
// KeeOtp output
|
||||
return QString("key=%1&size=%2&step=%3")
|
||||
.arg(QString(Base32::sanitizeInput(settings->key.toLatin1())))
|
||||
.arg(settings->digits)
|
||||
.arg(settings->step);
|
||||
} else if (!settings->encoder.shortName.isEmpty()) {
|
||||
// Semicolon output [step];[encoder]
|
||||
return QString("%1;%2").arg(settings->step).arg(settings->encoder.shortName);
|
||||
} else {
|
||||
// Semicolon output [step];[digits]
|
||||
return QString("%1;%2").arg(settings->step).arg(settings->digits);
|
||||
}
|
||||
|
||||
// Semicolon output [step];[digits]
|
||||
return QString("%1;%2").arg(settings->step).arg(settings->digits);
|
||||
}
|
||||
|
||||
QString Totp::generateTotp(const QSharedPointer<Totp::Settings>& settings, const quint64 time)
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace Totp
|
||||
Totp::Encoder encoder;
|
||||
QString key;
|
||||
bool otpUrl;
|
||||
bool keeOtp;
|
||||
bool custom;
|
||||
uint digits;
|
||||
uint step;
|
||||
@@ -59,8 +60,11 @@ namespace Totp
|
||||
static const QString ATTRIBUTE_SETTINGS = "TOTP Settings";
|
||||
|
||||
QSharedPointer<Totp::Settings> parseSettings(const QString& rawSettings, const QString& key = {});
|
||||
QSharedPointer<Totp::Settings>
|
||||
createSettings(const QString& key, const uint digits, const uint step, const QString& encoderShortName = {});
|
||||
QSharedPointer<Totp::Settings> createSettings(const QString& key,
|
||||
const uint digits,
|
||||
const uint step,
|
||||
const QString& encoderShortName = {},
|
||||
QSharedPointer<Totp::Settings> prevSettings = {});
|
||||
QString writeSettings(const QSharedPointer<Totp::Settings>& settings,
|
||||
const QString& title = {},
|
||||
const QString& username = {},
|
||||
|
||||
Reference in New Issue
Block a user