Merge branch 'release/2.4.0' into develop

This commit is contained in:
Jonathan White
2019-02-15 09:01:09 -05:00
297 changed files with 129410 additions and 151299 deletions

View File

@@ -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()

View File

@@ -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();
}

View File

@@ -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;
};

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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();
}

View File

@@ -137,7 +137,6 @@ void EntryAttributes::remove(const QString& key)
Q_ASSERT(!isDefaultAttribute(key));
if (!m_attributes.contains(key)) {
Q_ASSERT(false);
return;
}

View File

@@ -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?

View File

@@ -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;
}

View File

@@ -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&auml;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()));

View File

@@ -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">&lt;ul&gt;
&lt;li&gt;Jonathan White (&lt;a href=&quot;https://github.com/droidmonkey&quot;&gt;droidmonkey&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Janek Bevendorff (&lt;a href=&quot;https://github.com/phoerious&quot;&gt;phoerious&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/TheZ3ro&quot;&gt;TheZ3ro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Louis-Bertrand (&lt;a href=&quot;https://github.com/louib&quot;&gt;louib&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Weslly Honorato (&lt;a href=&quot;https://github.com/weslly&quot;&gt;weslly&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Toni Spets (&lt;a href=&quot;https://github.com/hifi&quot;&gt;hifi&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Sami V&amp;auml;nttinen (&lt;a href=&quot;https://github.com/varjolintu&quot;&gt;varjolintu&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;</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">&lt;h3&gt;VIP Patreon Supporters:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;John Cook&lt;/li&gt;
&lt;li&gt;Max Anderson&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Notable Code Contributions:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;droidmonkey&lt;/li&gt;
&lt;li&gt;phoerious&lt;/li&gt;
&lt;li&gt;TheZ3ro&lt;/li&gt;
&lt;li&gt;louib&lt;/li&gt;
&lt;li&gt;weslly&lt;/li&gt;
&lt;li&gt;varjolintu (KeePassXC-Browser)&lt;/li&gt;
&lt;li&gt;hifi (SSH Agent)&lt;/li&gt;
&lt;li&gt;frostasm&lt;/li&gt;
&lt;li&gt;fonic (Entry Table View)&lt;/li&gt;
&lt;li&gt;kylemanna (YubiKey)&lt;/li&gt;
&lt;li&gt;keithbennett (KeePassHTTP)&lt;/li&gt;
&lt;li&gt;Typz (KeePassHTTP)&lt;/li&gt;
&lt;li&gt;denk-mal (KeePassHTTP)&lt;/li&gt;
&lt;li&gt;angelsl (KDBX 4)&lt;/li&gt;
&lt;li&gt;seatedscribe (CSV Import)&lt;/li&gt;
&lt;li&gt;debfx (KeePassX)&lt;/li&gt;
&lt;li&gt;BlueIce (KeePassX)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Patreon Supporters:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ashura&lt;/li&gt;
&lt;li&gt;Alexanderjb&lt;/li&gt;
&lt;li&gt;Andreas Kollmann&lt;/li&gt;
&lt;li&gt;Richard Ames&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Translations:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Basque&lt;/strong&gt;: azken_tximinoa, Hey_neken&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Catalan&lt;/strong&gt;: capitantrueno, dsoms, mcus, raulua, ZJaume&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Chinese (China)&lt;/strong&gt;: Biggulu, Brandon_c, hoilc, ligyxy, vc5, Small_Ku&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Chinese (Taiwan)&lt;/strong&gt;: BestSteve, MiauLightouch, Small_Ku, yan12125, ymhuang0808&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Czech&lt;/strong&gt;: DanielMilde, JosefVitu, pavelb, tpavelek&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Danish&lt;/strong&gt;: nlkl&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dutch&lt;/strong&gt;: apie, bartlibert, evanoosten, fvw, KnooL, srgvg, Vistaus, wanderingidea&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Finnish&lt;/strong&gt;: artnay, Jarppi, MawKKe&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;French&lt;/strong&gt;: A1RO, aghilas.messara, bisaloo, frgnca, ggtr1138, gilbsgilbs, gtalbot, Gui13, iannick, jlutran, kyodev, logut, MartialBis, narzb, pBouillon, plunkets, Raphi111, Scrat15, tl_pierre, wilfriedroset&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;German&lt;/strong&gt;: 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&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Greek&lt;/strong&gt;: magkopian, nplatis, tassos.b, xinomilo&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hungarian&lt;/strong&gt;: bubu, meskobalazs, urbalazs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Indonesian&lt;/strong&gt;: zk&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Italian&lt;/strong&gt;: amaxis, bovirus, duncanmid, FranzMari, lucaim, Mte90, Peo, TheZ3ro, tosky, VosaxAlo&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Japanese&lt;/strong&gt;: masoo, metalic_cat, p2635, Shinichirou_Yamada, vargas.peniel, vmemjp, yukinakato&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Korean&lt;/strong&gt;: cancantun, peremen&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lithuanian&lt;/strong&gt;: Moo&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Polish&lt;/strong&gt;: keypress, konradmb, mrerexx, psobczak&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Portuguese (Brazil)&lt;/strong&gt;: danielbibit, fabiom, flaviobn, vitor895, weslly&lt;/li&gt;
&lt;/ul&gt;
</string>
<string notr="true"/>
</property>
<property name="textFormat">
<enum>Qt::AutoText</enum>

View File

@@ -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();
}

View File

@@ -1162,7 +1162,7 @@ void MainWindow::hideYubiKeyPopup()
void MainWindow::bringToFront()
{
ensurePolished();
setWindowState(windowState() & ~Qt::WindowMinimized);
setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
show();
raise();
activateWindow();

View File

@@ -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();

View File

@@ -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);

View File

@@ -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();

View File

@@ -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

View File

@@ -46,6 +46,7 @@ protected:
private slots:
void yubikeyDetected(int slot, bool blocking);
void yubikeyDetectComplete();
void noYubikeyFound();
void pollYubikey();

View File

@@ -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);

View File

@@ -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();
}

View File

@@ -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)

View File

@@ -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 = {},