Merge remote-tracking branch 'upstream/develop' into develop

This commit is contained in:
Vladimir Svyatski 2018-05-10 22:34:38 +03:00
commit 30ccc102d2
53 changed files with 9817 additions and 1144 deletions

View File

@ -1,3 +1,24 @@
2.3.3 (2018-05-09)
=========================
- Fix crash when browser integration is enabled [#1923]
2.3.2 (2018-05-07)
=========================
- Enable high entropy ASLR on Windows [#1747]
- Enhance favicon fetching [#1786]
- Fix crash on Windows due to autotype [#1691]
- Fix dark tray icon changing all icons [#1680]
- Fix --pw-stdin not using getPassword function [#1686]
- Fix placeholders being resolved in notes [#1907]
- Enable auto-type start delay to be configurable [#1908]
- Browser: Fix native messaging reply size [#1719]
- Browser: Increase maximum buffer size [#1720]
- Browser: Enhance usability and functionality [#1810, #1822, #1830, #1884, #1906]
- SSH Agent: Parse aes-256-cbc/ctr keys [#1682]
- SSH Agent: Enhance usability and functionality [#1677, #1679, #1681, #1787]
2.3.1 (2018-03-06)
=========================

View File

@ -62,7 +62,7 @@ set(CMAKE_AUTOUIC ON)
set(KEEPASSXC_VERSION_MAJOR "2")
set(KEEPASSXC_VERSION_MINOR "3")
set(KEEPASSXC_VERSION_PATCH "1")
set(KEEPASSXC_VERSION_PATCH "3")
set(KEEPASSXC_VERSION "${KEEPASSXC_VERSION_MAJOR}.${KEEPASSXC_VERSION_MINOR}.${KEEPASSXC_VERSION_PATCH}")
set(KEEPASSXC_BUILD_TYPE "Snapshot" CACHE STRING "Set KeePassXC build type to distinguish between stable releases and snapshots")
@ -117,6 +117,10 @@ elseif(KEEPASSXC_DIST_TYPE STREQUAL "Other")
unset(KEEPASSXC_DIST)
endif()
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "4")
set(IS_32BIT TRUE)
endif()
if("${CMAKE_C_COMPILER}" MATCHES "clang$" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_COMPILER_IS_CLANG 1)
endif()
@ -237,8 +241,13 @@ if(MINGW)
set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> <FLAGS> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>")
if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"))
# Enable DEP and ASLR
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--nxcompat -Wl,--dynamicbase -Wl,--high-entropy-va")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--nxcompat -Wl,--dynamicbase -Wl,--high-entropy-va")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--nxcompat -Wl,--dynamicbase")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--nxcompat -Wl,--dynamicbase")
# Enable high entropy ASLR for 64-bit builds
if(NOT IS_32BIT)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--high-entropy-va")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--high-entropy-va")
endif()
endif()
endif()

View File

@ -50,6 +50,31 @@
</screenshots>
<releases>
<release version="2.3.3" date="2018-05-09">
<description>
<ul>
<li>Fix crash when browser integration is enabled [#1923]</li>
</ul>
</description>
</release>
<release version="2.3.2" date="2018-05-07">
<description>
<ul>
<li>Enable high entropy ASLR on Windows [#1747]</li>
<li>Enhance favicon fetching [#1786]</li>
<li>Fix crash on Windows due to autotype [#1691]</li>
<li>Fix dark tray icon changing all icons [#1680]</li>
<li>Fix --pw-stdin not using getPassword function [#1686]</li>
<li>Fix placeholders being resolved in notes [#1907]</li>
<li>Enable auto-type start delay to be configurable [#1908]</li>
<li>Browser: Fix native messaging reply size [#1719]</li>
<li>Browser: Increase maximum buffer size [#1720]</li>
<li>Browser: Enhance usability and functionality [#1810, #1822, #1830, #1884, #1906]</li>
<li>SSH Agent: Parse aes-256-cbc/ctr keys [#1682]</li>
<li>SSH Agent: Enhance usability and functionality [#1677, #1679, #1681, #1787]</li>
</ul>
</description>
</release>
<release version="2.3.1" date="2018-03-06">
<description>
<ul>

File diff suppressed because it is too large Load Diff

View File

@ -73,12 +73,13 @@ Nucli: %3 %4</translation>
</message>
<message>
<source>Special thanks from the KeePassXC team go to debfx for creating the original KeePassX.</source>
<translation type="unfinished"/>
<translation>Agraïments de l&apos;equip de KeePassXC a debfx per crear el KeePassX original.</translation>
</message>
<message>
<source>Build Type: %1
</source>
<translation type="unfinished"/>
<translation>Tipus de construcció: %1
</translation>
</message>
</context>
<context>
@ -110,7 +111,7 @@ Seleccioneu si voleu permetre l&apos;accés.</translation>
<name>AgentSettingsWidget</name>
<message>
<source>Enable SSH Agent (requires restart)</source>
<translation type="unfinished"/>
<translation>Habilita l&apos;agent SSH (requereix reiniciar-se)</translation>
</message>
</context>
<context>
@ -129,7 +130,7 @@ Seleccioneu si voleu permetre l&apos;accés.</translation>
</message>
<message>
<source>The Syntax of your Auto-Type statement is incorrect!</source>
<translation type="unfinished"/>
<translation>La sintaxi de l&apos;Auto-Type no és correcte!</translation>
</message>
<message>
<source>This Auto-Type command contains a very long delay. Do you really want to proceed?</source>
@ -193,7 +194,7 @@ Seleccioneu si voleu permetre l&apos;accés.</translation>
<name>BrowserAccessControlDialog</name>
<message>
<source>KeePassXC-Browser Confirm Access</source>
<translation type="unfinished"/>
<translation>Confirma l&apos;accés al navegador KeePassXC</translation>
</message>
<message>
<source>Remember this decision</source>
@ -222,11 +223,11 @@ Seleccioneu si voleu permetre l&apos;accés.</translation>
</message>
<message>
<source>This is required for accessing your databases with KeePassXC-Browser</source>
<translation type="unfinished"/>
<translation>Requerit per l&apos;accés a les teues bases de dades amb el navegador KeePassXC</translation>
</message>
<message>
<source>Enable KeepassXC browser integration</source>
<translation type="unfinished"/>
<translation>Habilita la integració de KeePassXC amb el navegador</translation>
</message>
<message>
<source>General</source>
@ -234,7 +235,7 @@ Seleccioneu si voleu permetre l&apos;accés.</translation>
</message>
<message>
<source>Enable integration for these browsers:</source>
<translation type="unfinished"/>
<translation>Habilita la integració amb els següents navegadors:</translation>
</message>
<message>
<source>&amp;Google Chrome</source>
@ -255,19 +256,19 @@ Seleccioneu si voleu permetre l&apos;accés.</translation>
<message>
<source>Show a &amp;notification when credentials are requested</source>
<extracomment>Credentials mean login data requested via browser extension</extracomment>
<translation type="unfinished"/>
<translation>Mostra una &amp;notificació quan es demanen credencials</translation>
</message>
<message>
<source>Re&amp;quest to unlock the database if it is locked</source>
<translation>Sol·licitar el desbloqueig de la base de dades si està blocada</translation>
<translation>Sol·licita el desbloqueig de la base de dades si està blocada</translation>
</message>
<message>
<source>Only entries with the same scheme (http://, https://, ...) are returned.</source>
<translation type="unfinished"/>
<translation>Només es retornen les entrades amb el mateix patró (http://, https://, ...)</translation>
</message>
<message>
<source>&amp;Match URL scheme (e.g., https://...)</source>
<translation type="unfinished"/>
<translation>Torna les coincidències a&amp;mb patrons URL (e.g., https://...)</translation>
</message>
<message>
<source>Only returns the best matches for a specific URL instead of all entries for the whole domain.</source>
@ -275,25 +276,25 @@ Seleccioneu si voleu permetre l&apos;accés.</translation>
</message>
<message>
<source>&amp;Return only best-matching credentials</source>
<translation type="unfinished"/>
<translation>&amp;Retorna només les millors coincidències de les credencials</translation>
</message>
<message>
<source>Sort &amp;matching credentials by title</source>
<extracomment>Credentials mean login data requested via browser extension</extracomment>
<translation type="unfinished"/>
<translation>Ordena les entrades coincidents per títol (ctrl + &amp;m)</translation>
</message>
<message>
<source>Sort matching credentials by &amp;username</source>
<extracomment>Credentials mean login data requested via browser extension</extracomment>
<translation type="unfinished"/>
<translation>Ordena les entrades coincidents per nom d&apos;&amp;usuari</translation>
</message>
<message>
<source>&amp;Disconnect all browsers</source>
<translation type="unfinished"/>
<translation>&amp;Desconnecta tots els navegadors</translation>
</message>
<message>
<source>Forget all remembered &amp;permissions</source>
<translation type="unfinished"/>
<translation>Oblida tots els &amp;permisos recordats</translation>
</message>
<message>
<source>Advanced</source>
@ -302,12 +303,12 @@ Seleccioneu si voleu permetre l&apos;accés.</translation>
<message>
<source>Never &amp;ask before accessing credentials</source>
<extracomment>Credentials mean login data requested via browser extension</extracomment>
<translation type="unfinished"/>
<translation>No torn&amp;ar a preguntar abans d&apos;accedir a les credencials</translation>
</message>
<message>
<source>Never ask before &amp;updating credentials</source>
<extracomment>Credentials mean login data requested via browser extension</extracomment>
<translation type="unfinished"/>
<translation>No preguntar abans d&apos;act&amp;ualitzar les credencials</translation>
</message>
<message>
<source>Only the selected database has to be connected with a client.</source>
@ -316,7 +317,7 @@ Seleccioneu si voleu permetre l&apos;accés.</translation>
<message>
<source>Searc&amp;h in all opened databases for matching credentials</source>
<extracomment>Credentials mean login data requested via browser extension</extracomment>
<translation type="unfinished"/>
<translation>Cerca en totes les bases de dades obertes, entrades coincidents (crtl + &amp;h)</translation>
</message>
<message>
<source>Automatically creating or updating string fields is not supported.</source>
@ -354,19 +355,19 @@ Seleccioneu si voleu permetre l&apos;accés.</translation>
<message>
<source>Browse...</source>
<extracomment>Button for opening file dialog</extracomment>
<translation type="unfinished"/>
<translation>Navega...</translation>
</message>
<message>
<source>&lt;b&gt;Warning:&lt;/b&gt; The following options can be dangerous!</source>
<translation type="unfinished"/>
<translation>&lt;b&gt;Atenció:&lt;/b&gt; Canviar les següents opcions és perillós!</translation>
</message>
<message>
<source>Executable Files (*.exe);;All Files (*.*)</source>
<translation type="unfinished"/>
<translation>Arxius executables (*.exe);;Tots els arxius (*.*)</translation>
</message>
<message>
<source>Executable Files (*)</source>
<translation type="unfinished"/>
<translation>Arxius executables (*)</translation>
</message>
<message>
<source>Select custom proxy location</source>
@ -392,7 +393,7 @@ give it a unique name to identify and accept it.</source>
</message>
<message>
<source>Save and allow access</source>
<translation type="unfinished"/>
<translation>Desa i autoritza l&apos;accés</translation>
</message>
<message>
<source>KeePassXC: Overwrite existing key?</source>
@ -401,7 +402,8 @@ give it a unique name to identify and accept it.</source>
<message>
<source>A shared encryption key with the name &quot;%1&quot; already exists.
Do you want to overwrite it?</source>
<translation type="unfinished"/>
<translation>Ja existeix una clau de xifratge compartida amb el nom &quot;%1&quot;.
Voleu sobreescriure-la?</translation>
</message>
<message>
<source>KeePassXC: Update Entry</source>
@ -427,7 +429,7 @@ Per favor, desbloqueu la base de dades seleccionada o escolliu-ne una altra.</t
</message>
<message>
<source>The active database does not contain a settings entry.</source>
<translation type="unfinished"/>
<translation>La base de dades activa no conté cap entrada de configuració.</translation>
</message>
<message>
<source>KeePassXC: No keys found</source>
@ -435,7 +437,7 @@ Per favor, desbloqueu la base de dades seleccionada o escolliu-ne una altra.</t
</message>
<message>
<source>No shared encryption keys found in KeePassXC Settings.</source>
<translation type="unfinished"/>
<translation>No s&apos;han trobat claus de xifratge compartides en la configuració de KeePassHttp.</translation>
</message>
<message>
<source>KeePassXC: Removed keys from database</source>
@ -443,11 +445,11 @@ Per favor, desbloqueu la base de dades seleccionada o escolliu-ne una altra.</t
</message>
<message numerus="yes">
<source>Successfully removed %n encryption key(s) from KeePassXC settings.</source>
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
<translation><numerusform>Reeixidament eliminat %n encriptació clau (s) de configuració KeePassXC.</numerusform><numerusform>Eliminada(es) correctament %n clau(s) de xifratge de la configuració de KeePassXC.</numerusform></translation>
</message>
<message>
<source>Removing stored permissions</source>
<translation type="unfinished"/>
<translation>Eliminant permisos emmagatzemats...</translation>
</message>
<message>
<source>Abort</source>
@ -573,7 +575,7 @@ Please consider generating a new key file.</source>
</message>
<message>
<source>Copy history</source>
<translation>Còpia el historial</translation>
<translation>Copia el historial</translation>
</message>
</context>
<context>
@ -1246,7 +1248,7 @@ Do you want to merge your changes?</source>
</message>
<message>
<source>Never</source>
<translation type="unfinished"/>
<translation>Mai</translation>
</message>
<message>
<source>[PROTECTED]</source>
@ -1565,7 +1567,7 @@ Do you want to merge your changes?</source>
<message>
<source>Browse...</source>
<extracomment>Button for opening file dialog</extracomment>
<translation type="unfinished"/>
<translation>Navega...</translation>
</message>
<message>
<source>Attachment</source>
@ -1895,7 +1897,7 @@ This may cause the affected plugins to malfunction.</source>
</message>
<message>
<source>Never</source>
<translation type="unfinished"/>
<translation>Mai</translation>
</message>
<message>
<source>Password</source>
@ -1911,15 +1913,15 @@ This may cause the affected plugins to malfunction.</source>
</message>
<message>
<source>Created</source>
<translation type="unfinished"/>
<translation>Creat</translation>
</message>
<message>
<source>Modified</source>
<translation type="unfinished"/>
<translation>Modificat</translation>
</message>
<message>
<source>Accessed</source>
<translation type="unfinished"/>
<translation>Accedit</translation>
</message>
<message>
<source>Attachments</source>
@ -2665,7 +2667,7 @@ Es tracta d&apos;una migració unidireccional. No obrir la base de dades importa
</message>
<message>
<source>&amp;Close database</source>
<translation>Tanca base de dades</translation>
<translation>Tanca la base de dades</translation>
</message>
<message>
<source>&amp;New database</source>
@ -2725,11 +2727,11 @@ Es tracta d&apos;una migració unidireccional. No obrir la base de dades importa
</message>
<message>
<source>Copy &amp;username</source>
<translation>Còpia el nom d&apos;&amp;usuari</translation>
<translation>Copia el nom d&apos;&amp;usuari</translation>
</message>
<message>
<source>Copy username to clipboard</source>
<translation>Còpia el nom d&apos;usuari al porta-retalls</translation>
<translation>Copia el nom d&apos;usuari al porta-retalls</translation>
</message>
<message>
<source>Cop&amp;y password</source>
@ -2737,11 +2739,11 @@ Es tracta d&apos;una migració unidireccional. No obrir la base de dades importa
</message>
<message>
<source>Copy password to clipboard</source>
<translation>Còpia la contrasenya al porta-retalls</translation>
<translation>Copia la contrasenya al porta-retalls</translation>
</message>
<message>
<source>&amp;Settings</source>
<translation>&amp;Conficuració</translation>
<translation>&amp;Configuració</translation>
</message>
<message>
<source>Password Generator</source>
@ -2749,7 +2751,7 @@ Es tracta d&apos;una migració unidireccional. No obrir la base de dades importa
</message>
<message>
<source>&amp;Perform Auto-Type</source>
<translation>Realitza complació automètica</translation>
<translation>Realitza compleció automàtica</translation>
</message>
<message>
<source>&amp;Open URL</source>
@ -2757,7 +2759,7 @@ Es tracta d&apos;una migració unidireccional. No obrir la base de dades importa
</message>
<message>
<source>&amp;Lock databases</source>
<translation>&amp;bloqueja la bases de dades</translation>
<translation>&amp;Bloqueja la bases de dades</translation>
</message>
<message>
<source>&amp;Title</source>
@ -3078,7 +3080,7 @@ This version is not meant for production use.</source>
</message>
<message>
<source>&lt;b&gt;Warning:&lt;/b&gt; The following options can be dangerous!</source>
<translation type="unfinished"/>
<translation>&lt;b&gt;Atenció:&lt;/b&gt; Canviar les següents opcions és perillós!</translation>
</message>
<message>
<source>&lt;p&gt;KeePassHTTP has been deprecated and will be removed in the future.&lt;br&gt;Please switch to KeePassXC-Browser instead! For help with migration, visit our &lt;a href=&quot;https://keepassxc.org/docs/keepassxc-browser-migration&quot;&gt;migration guide&lt;/a&gt;.&lt;/p&gt;</source>
@ -3508,11 +3510,11 @@ Available commands:
</message>
<message>
<source>Last Modified</source>
<translation type="unfinished"/>
<translation>Darrera modificació</translation>
</message>
<message>
<source>Created</source>
<translation type="unfinished"/>
<translation>Creat</translation>
</message>
<message>
<source>Legacy Browser Integration</source>

View File

@ -2623,6 +2623,10 @@ This is a one-way migration. You won&apos;t be able to open the imported databas
<source>KeePassXC - Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Database password: </source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MainWindow</name>
@ -3645,10 +3649,6 @@ Available commands:
<source>No agent running, cannot add identity.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Agent refused this identity.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>No agent running, cannot remove identity.</source>
<translation type="unfinished"></translation>
@ -3657,6 +3657,22 @@ Available commands:
<source>Agent does not have this identity.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Agent refused this identity. Possible reasons include:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>The key has already been added.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Restricted lifetime is not supported by the agent (check options).</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>A confirmation request is not supported by the agent (check options).</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SearchWidget</name>
@ -3887,10 +3903,6 @@ Please unlock the selected database or choose another one which is unlocked.</so
<source>Global Auto-Type shortcut</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Auto-Type delay</source>
<translation type="unfinished"></translation>
</message>
<message>
<source> ms</source>
<comment>Milliseconds</comment>
@ -3920,6 +3932,14 @@ Please unlock the selected database or choose another one which is unlocked.</so
<source>General</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Auto-Type typing delay</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Auto-Type start delay</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsWidgetSecurity</name>
@ -4059,6 +4079,17 @@ Please unlock the selected database or choose another one which is unlocked.</so
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>UrlFetchProgressDialog</name>
<message>
<source>Download Progress</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Downloading %1.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>WelcomeWidget</name>
<message>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -374,7 +374,7 @@ Ole hyvä ja valitse sallitaanko pääsy.</translation>
</message>
<message>
<source>We&apos;re sorry, but KeePassXC-Browser is not supported for Snap releases at the moment.</source>
<translation type="unfinished"/>
<translation>Valitettavasti KeePassXC-Browser ei ole vielä tuettu Snap-julkaisuissa.</translation>
</message>
</context>
<context>
@ -1976,7 +1976,7 @@ Tämä voi vikaannuttaa tietoa käyttävän liitännäisen.</translation>
</message>
<message>
<source>Attachments (icon)</source>
<translation type="unfinished"/>
<translation>Liitteet (kuvake)</translation>
</message>
</context>
<context>

View File

@ -73,7 +73,7 @@ Kernel: %3 %4</translation>
</message>
<message>
<source>Special thanks from the KeePassXC team go to debfx for creating the original KeePassX.</source>
<translation type="unfinished"/>
<translation>Terima kasih dari tim KeePassXC kepada debfx yang telah membuat KeepassX original.</translation>
</message>
<message>
<source>Build Type: %1
@ -218,7 +218,7 @@ Silakan pilih apakah Anda ingin mengizinkannya.</translation>
<name>BrowserOptionDialog</name>
<message>
<source>Dialog</source>
<translation type="unfinished"/>
<translation>Dialog</translation>
</message>
<message>
<source>This is required for accessing your databases with KeePassXC-Browser</source>
@ -374,7 +374,7 @@ Silakan pilih apakah Anda ingin mengizinkannya.</translation>
</message>
<message>
<source>We&apos;re sorry, but KeePassXC-Browser is not supported for Snap releases at the moment.</source>
<translation type="unfinished"/>
<translation>Maaf, KeePassXC-Browser saat ini tidak mendukung rilisan Snap.</translation>
</message>
</context>
<context>
@ -447,7 +447,7 @@ Silakan buka kunci atau pilih yang lainnya yang tidak terkunci.</translation>
</message>
<message numerus="yes">
<source>Successfully removed %n encryption key(s) from KeePassXC settings.</source>
<translation type="unfinished"><numerusform></numerusform></translation>
<translation><numerusform>Berhasil membuang %n kunci enkripsi dari pengaturan KeePassXC.</numerusform></translation>
</message>
<message>
<source>Removing stored permissions</source>
@ -463,7 +463,7 @@ Silakan buka kunci atau pilih yang lainnya yang tidak terkunci.</translation>
</message>
<message numerus="yes">
<source>Successfully removed permissions from %n entry(s).</source>
<translation type="unfinished"><numerusform></numerusform></translation>
<translation><numerusform>Berhasil membuang perizinan dari %n entri.</numerusform></translation>
</message>
<message>
<source>KeePassXC: No entry with permissions found!</source>
@ -856,7 +856,7 @@ If you keep this number, your database may be too easy to crack!</source>
<message numerus="yes">
<source> MiB</source>
<comment>Abbreviation for Mebibytes (KDF settings)</comment>
<translation type="unfinished"><numerusform></numerusform></translation>
<translation><numerusform> MiB</numerusform></translation>
</message>
<message numerus="yes">
<source> thread(s)</source>
@ -1378,15 +1378,15 @@ Apakah Anda ingin menggabungkan ubahan Anda?</translation>
</message>
<message>
<source>Apply generated password?</source>
<translation type="unfinished"/>
<translation>Gunakan sandi yang dibuat?</translation>
</message>
<message>
<source>Do you want to apply the generated password to this entry?</source>
<translation type="unfinished"/>
<translation>Apakah Anda ingin menggunakan sandi yang dibuat untuk entri ini?</translation>
</message>
<message>
<source>Entry updated successfully.</source>
<translation type="unfinished"/>
<translation>Entri berhasil diperbarui.</translation>
</message>
</context>
<context>
@ -1421,11 +1421,11 @@ Apakah Anda ingin menggabungkan ubahan Anda?</translation>
</message>
<message>
<source>Foreground Color:</source>
<translation type="unfinished"/>
<translation>Warna Latar Depan:</translation>
</message>
<message>
<source>Background Color:</source>
<translation type="unfinished"/>
<translation>Warna Latar Belakang:</translation>
</message>
</context>
<context>
@ -1742,7 +1742,7 @@ Apakah Anda ingin menggabungkan ubahan Anda?</translation>
</message>
<message>
<source>Plugin Data</source>
<translation type="unfinished"/>
<translation>Data Plugin</translation>
</message>
<message>
<source>Remove</source>
@ -1750,12 +1750,13 @@ Apakah Anda ingin menggabungkan ubahan Anda?</translation>
</message>
<message>
<source>Delete plugin data?</source>
<translation type="unfinished"/>
<translation>Hapus data plugin?</translation>
</message>
<message>
<source>Do you really want to delete the selected plugin data?
This may cause the affected plugins to malfunction.</source>
<translation type="unfinished"/>
<translation>Apakah Anda benar-benar ingin menghapus data plugin?
Ini mungkin akan menyebabkan plugin terkait tidak berfungsi.</translation>
</message>
<message>
<source>Key</source>
@ -1813,7 +1814,7 @@ This may cause the affected plugins to malfunction.</source>
</message>
<message numerus="yes">
<source>Are you sure you want to remove %n attachment(s)?</source>
<translation type="unfinished"><numerusform></numerusform></translation>
<translation><numerusform>Apakah Anda yakin ingin membuang %n lampiran?</numerusform></translation>
</message>
<message>
<source>Confirm Remove</source>
@ -1972,7 +1973,7 @@ This may cause the affected plugins to malfunction.</source>
</message>
<message>
<source>Attachments (icon)</source>
<translation type="unfinished"/>
<translation>Lampiran (ikon)</translation>
</message>
</context>
<context>
@ -2997,7 +2998,7 @@ Versi ini tidak dimaksudkan untuk penggunaan sehari-hari.</translation>
<name>OptionDialog</name>
<message>
<source>Dialog</source>
<translation type="unfinished"/>
<translation>Dialog</translation>
</message>
<message>
<source>This is required for accessing your databases from ChromeIPass or PassIFox</source>
@ -3566,11 +3567,11 @@ Perintah yang tersedia:
</message>
<message>
<source>Generate a new random diceware passphrase.</source>
<translation type="unfinished"/>
<translation>Buat frasa sandi diceware acak yang baru.</translation>
</message>
<message>
<source>Word count for the diceware passphrase.</source>
<translation type="unfinished"/>
<translation>Jumlah kata untuk frasa sandi diceware.</translation>
</message>
<message>
<source>count</source>
@ -3579,7 +3580,8 @@ Perintah yang tersedia:
<message>
<source>Wordlist for the diceware generator.
[Default: EFF English]</source>
<translation type="unfinished"/>
<translation>Daftar kata untuk generator diceware.
[Bawaan: Inggris EFF]</translation>
</message>
<message>
<source>Generate a new random password.</source>
@ -3607,7 +3609,7 @@ Perintah yang tersedia:
</message>
<message>
<source>Use extended ASCII in the generated password.</source>
<translation type="unfinished"/>
<translation>Gunakan ASCII yang diperluas di dalam sandi yang dibuat.</translation>
</message>
</context>
<context>
@ -3962,7 +3964,7 @@ Silakan buka kunci atau pilih yang lainnya yang tidak terkunci.</translation>
</message>
<message>
<source>Re-lock previously locked database after performing Auto-Type</source>
<translation type="unfinished"/>
<translation>Kunci ulang basis data yang sebelumnya terkunci setelah menjalankan Ketik-Otomatis</translation>
</message>
</context>
<context>

File diff suppressed because it is too large Load Diff

View File

@ -375,7 +375,7 @@ Geef aan of je toegang wilt verlenen of niet.</translation>
</message>
<message>
<source>We&apos;re sorry, but KeePassXC-Browser is not supported for Snap releases at the moment.</source>
<translation>Het spijt ons, maar KeePassXC-Browser wordt momenteel niet ondersteund voor tussentijdse versies.</translation>
<translation>Het spijt ons, maar KeePassXC-Browser wordt momenteel niet ondersteund voor Snap releases.</translation>
</message>
</context>
<context>
@ -1361,7 +1361,7 @@ Wil je de wijzigingen samenvoegen?</translation>
</message>
<message>
<source>Press reveal to view or edit</source>
<translation>Druk Tonen om te bekijken of bewerken</translation>
<translation>Druk Weergeven om te bekijken of bewerken</translation>
</message>
<message>
<source>Tomorrow</source>
@ -1416,7 +1416,7 @@ Wil je de wijzigingen samenvoegen?</translation>
</message>
<message>
<source>Reveal</source>
<translation>Tonen</translation>
<translation>Weergeven</translation>
</message>
<message>
<source>Attachments</source>
@ -1470,7 +1470,7 @@ Wil je de wijzigingen samenvoegen?</translation>
<name>EditEntryWidgetHistory</name>
<message>
<source>Show</source>
<translation>Tonen</translation>
<translation>Weergeven</translation>
</message>
<message>
<source>Restore</source>
@ -1513,7 +1513,7 @@ Wil je de wijzigingen samenvoegen?</translation>
</message>
<message>
<source>Toggle the checkbox to reveal the notes section.</source>
<translation>Schakelen aan om notities te tonen.</translation>
<translation>Selecteer om notities weer te geven.</translation>
</message>
<message>
<source>Username:</source>
@ -3483,7 +3483,7 @@ Beschikbare opdrachten:
</message>
<message>
<source>Names of the attributes to show. This option can be specified more than once, with each attribute shown one-per-line in the given order. If no attributes are specified, a summary of the default attributes is given.</source>
<translation>Namen van de te tonen kenmerken. Deze optie kan meer dan eens worden opgegeven, waarbij elk kenmerk op een regel wordt getoond in de opgegeven volgorde. Als er geen kenmerken worden opgegeven, wordt een samenvatting van de standaardkenmerken gegeven.</translation>
<translation>Namen van de weer te geven kenmerken. Deze optie kan meer dan eens worden opgegeven, waarbij elk kenmerk op een regel wordt getoond in de opgegeven volgorde. Als er geen kenmerken worden opgegeven, wordt een samenvatting van de standaardkenmerken gegeven.</translation>
</message>
<message>
<source>attribute</source>
@ -3837,7 +3837,7 @@ Ontgrendel de geselecteerde database of kies een ontgrendelde database.</transla
</message>
<message>
<source>Show a system tray icon</source>
<translation>Icoon in het systeemvak tonen</translation>
<translation>Icoon in het systeemvak weergeven</translation>
</message>
<message>
<source>Hide window to system tray when minimized</source>

View File

@ -3548,7 +3548,7 @@ Dostępne polecenia:
</message>
<message>
<source>Legacy Browser Integration</source>
<translation>Integracja ze starą przeglądarką</translation>
<translation>Przestarzała integracja z przeglądarką</translation>
</message>
<message>
<source>Browser Integration</source>

View File

@ -23,11 +23,11 @@
</message>
<message>
<source>&lt;a href=&quot;https://github.com/keepassxreboot/keepassxc/graphs/contributors&quot;&gt;See Contributions on GitHub&lt;/a&gt;</source>
<translation>&lt;a href=&quot;https://github.com/keepassxreboot/keepassxc/graphs/contributors&quot;&gt;Ver Colaborações no GitHub&lt;/a&gt;</translation>
<translation>&lt;a href=&quot;https://github.com/keepassxreboot/keepassxc/graphs/contributors&quot;&gt;Ver colaborações no GitHub&lt;/a&gt;</translation>
</message>
<message>
<source>Debug Info</source>
<translation>Informações de Depuração</translation>
<translation>Informações de depuração</translation>
</message>
<message>
<source>Include the following information whenever you report a bug:</source>
@ -69,11 +69,11 @@ Kernel: %3 %4</translation>
</message>
<message>
<source>Project Maintainers:</source>
<translation>Mantedores do Projeto:</translation>
<translation>Mantedores do projeto:</translation>
</message>
<message>
<source>Special thanks from the KeePassXC team go to debfx for creating the original KeePassX.</source>
<translation>A equipe KeePassXC agradece especialmente a debfx pela criação do KeePassX original.</translation>
<translation>A equipe do KeePassXC agradece especialmente a debfx pela criação do KeePassX original.</translation>
</message>
<message>
<source>Build Type: %1
@ -111,7 +111,7 @@ Selecione se deseja permitir o acesso.</translation>
<name>AgentSettingsWidget</name>
<message>
<source>Enable SSH Agent (requires restart)</source>
<translation>Habilitar Agente SSH (requer reinicialização)</translation>
<translation>Habilitar agente SSH (requer reinicialização)</translation>
</message>
</context>
<context>
@ -122,27 +122,27 @@ Selecione se deseja permitir o acesso.</translation>
</message>
<message>
<source>Auto-Type - KeePassXC</source>
<translation>Auto-Digitação - KeePassXC</translation>
<translation>Autodigitação - KeePassXC</translation>
</message>
<message>
<source>Auto-Type</source>
<translation>Auto-Digitação</translation>
<translation>Autodigitação</translation>
</message>
<message>
<source>The Syntax of your Auto-Type statement is incorrect!</source>
<translation>A sintaxe da sua sequência de Auto-Digitação está incorreta!</translation>
<translation>A sintaxe da sua sequência de autodigitação está incorreta!</translation>
</message>
<message>
<source>This Auto-Type command contains a very long delay. Do you really want to proceed?</source>
<translation>Este comando de Auto-Digitação contém um tempo de espera muito longo. Você tem certeza que deseja continuar?</translation>
<translation>Este comando de autodigitação contém um tempo de espera muito longo. Você tem certeza de que deseja continuar?</translation>
</message>
<message>
<source>This Auto-Type command contains very slow key presses. Do you really want to proceed?</source>
<translation>Este comando Autotipo contém pressionamentos de teclas muito lentos. Você realmente deseja prosseguir?</translation>
<translation>Este comando de autodigitação contém pressionamentos de teclas muito lentos. Você tem certeza de que deseja continuar?</translation>
</message>
<message>
<source>This Auto-Type command contains arguments which are repeated very often. Do you really want to proceed?</source>
<translation>Este comando Auto-Type contém os argumentos que são repetidos muitas vezes. Você realmente deseja prosseguir?</translation>
<translation>Este comando de autodigitação contém parâmetros que são repetidos muitas vezes. Você tem certeza de que deseja continuar?</translation>
</message>
</context>
<context>
@ -183,11 +183,11 @@ Selecione se deseja permitir o acesso.</translation>
<name>AutoTypeSelectDialog</name>
<message>
<source>Auto-Type - KeePassXC</source>
<translation>Auto-Digitação - KeePassXC</translation>
<translation>Autodigitação - KeePassXC</translation>
</message>
<message>
<source>Select entry to Auto-Type:</source>
<translation>Escolha uma entrada para Auto-Digitar:</translation>
<translation>Escolha uma entrada para digitar automaticamente:</translation>
</message>
</context>
<context>

View File

@ -360,11 +360,11 @@ Please select whether you want to allow access.</source>
</message>
<message>
<source>Executable Files (*.exe);;All Files (*.*)</source>
<translation type="unfinished"/>
<translation>Fișiere Executabile (*.exe);;Toate Fișierele (*.*)</translation>
</message>
<message>
<source>Executable Files (*)</source>
<translation type="unfinished"/>
<translation>Fișiere Executabile (*)</translation>
</message>
<message>
<source>Select custom proxy location</source>
@ -390,11 +390,11 @@ give it a unique name to identify and accept it.</source>
</message>
<message>
<source>Save and allow access</source>
<translation type="unfinished"/>
<translation>Salvează și permite acces</translation>
</message>
<message>
<source>KeePassXC: Overwrite existing key?</source>
<translation type="unfinished"/>
<translation>KeePassXC: Suprascriere cheie existentă?</translation>
</message>
<message>
<source>A shared encryption key with the name &quot;%1&quot; already exists.
@ -593,7 +593,7 @@ Please consider generating a new key file.</source>
</message>
<message>
<source>Codec</source>
<translation type="unfinished"/>
<translation>Codec</translation>
</message>
<message>
<source>Text is qualified by</source>
@ -641,7 +641,7 @@ Please consider generating a new key file.</source>
</message>
<message>
<source>Imported from CSV file</source>
<translation type="unfinished"/>
<translation>Importat din fișier CSV</translation>
</message>
<message>
<source>Original data: </source>
@ -797,7 +797,7 @@ You can now save it.</source>
</message>
<message>
<source>Encryption</source>
<translation type="unfinished"/>
<translation>Criptare</translation>
</message>
<message>
<source>Number of rounds too high</source>
@ -816,7 +816,7 @@ If you keep this number, your database may take hours or days (or even longer) t
</message>
<message>
<source>Cancel</source>
<translation type="unfinished"/>
<translation>Anulare</translation>
</message>
<message>
<source>Number of rounds too low</source>
@ -852,7 +852,7 @@ If you keep this number, your database may be too easy to crack!</source>
<name>DatabaseSettingsWidgetEncryption</name>
<message>
<source>Encryption Algorithm:</source>
<translation type="unfinished"/>
<translation>Algoritm Criptare:</translation>
</message>
<message>
<source>AES: 256 Bit (default)</source>
@ -864,7 +864,7 @@ If you keep this number, your database may be too easy to crack!</source>
</message>
<message>
<source>Key Derivation Function:</source>
<translation type="unfinished"/>
<translation>Funcție Derivare Cheie:</translation>
</message>
<message>
<source>Transform rounds:</source>
@ -876,18 +876,18 @@ If you keep this number, your database may be too easy to crack!</source>
</message>
<message>
<source>Memory Usage:</source>
<translation type="unfinished"/>
<translation>Utilizare Memorie:</translation>
</message>
<message>
<source>Parallelism:</source>
<translation type="unfinished"/>
<translation>Paralelism:</translation>
</message>
</context>
<context>
<name>DatabaseSettingsWidgetGeneral</name>
<message>
<source>Database Meta Data</source>
<translation type="unfinished"/>
<translation>Meta Date Bază de Date</translation>
</message>
<message>
<source>Database name:</source>
@ -903,7 +903,7 @@ If you keep this number, your database may be too easy to crack!</source>
</message>
<message>
<source>History Settings</source>
<translation type="unfinished"/>
<translation>Setări Istoric</translation>
</message>
<message>
<source>Max. history items:</source>
@ -923,7 +923,7 @@ If you keep this number, your database may be too easy to crack!</source>
</message>
<message>
<source>Additional Database Settings</source>
<translation type="unfinished"/>
<translation>Setări Adiționale Bază de Date</translation>
</message>
<message>
<source>Enable &amp;compression (recommended)</source>
@ -1006,7 +1006,7 @@ Salvați modificările?</translation>
</message>
<message>
<source>Writing the database failed.</source>
<translation type="unfinished"/>
<translation>Scrierea în baza de date a eșuat.</translation>
</message>
<message>
<source>Passwords</source>
@ -1141,11 +1141,11 @@ Disable safe saves and try again?</source>
</message>
<message>
<source>File has changed</source>
<translation type="unfinished"/>
<translation>Fișierul a fost modificat</translation>
</message>
<message>
<source>The database file has changed. Do you want to load the changes?</source>
<translation type="unfinished"/>
<translation>Fișierul bazei de date a fost modificat. Doriți încărcați ultimele modificări?</translation>
</message>
<message>
<source>Merge Request</source>
@ -1264,7 +1264,7 @@ Do you want to merge your changes?</source>
</message>
<message>
<source>Icon</source>
<translation type="unfinished"/>
<translation>Icon</translation>
</message>
<message>
<source>Auto-Type</source>
@ -1583,7 +1583,7 @@ Do you want to merge your changes?</source>
</message>
<message>
<source>Icon</source>
<translation type="unfinished"/>
<translation>Icon</translation>
</message>
<message>
<source>Properties</source>
@ -1653,11 +1653,11 @@ Do you want to merge your changes?</source>
</message>
<message>
<source>Add custom icon</source>
<translation type="unfinished"/>
<translation>Adaugă icon personalizat</translation>
</message>
<message>
<source>Delete custom icon</source>
<translation type="unfinished"/>
<translation>Șterge icon personalizat</translation>
</message>
<message>
<source>Download favicon</source>
@ -1665,7 +1665,7 @@ Do you want to merge your changes?</source>
</message>
<message>
<source>Unable to fetch favicon.</source>
<translation type="unfinished"/>
<translation>Nu pot descărca favicon.</translation>
</message>
<message>
<source>Hint: You can enable Google as a fallback under Tools&gt;Settings&gt;Security</source>
@ -1685,11 +1685,11 @@ Do you want to merge your changes?</source>
</message>
<message>
<source>Can&apos;t read icon</source>
<translation type="unfinished"/>
<translation>Nu pot citi icon</translation>
</message>
<message>
<source>Custom icon already exists</source>
<translation type="unfinished"/>
<translation>Icon personalizat deja există</translation>
</message>
<message>
<source>Confirm Delete</source>
@ -1945,7 +1945,7 @@ This may cause the affected plugins to malfunction.</source>
</message>
<message>
<source>Attachments (icon)</source>
<translation type="unfinished"/>
<translation>Atașamente (icon)</translation>
</message>
</context>
<context>
@ -2849,7 +2849,7 @@ This is a one-way migration. You won&apos;t be able to open the imported databas
</message>
<message>
<source>Writing the database failed.</source>
<translation type="unfinished"/>
<translation>Scrierea în baza de date a eșuat.</translation>
</message>
<message>
<source>Please touch the button on your YubiKey!</source>
@ -3645,7 +3645,7 @@ give it a unique name to identify and accept it.</source>
</message>
<message>
<source>KeePassXC: Overwrite existing key?</source>
<translation type="unfinished"/>
<translation>KeePassXC: Suprascriere cheie existentă?</translation>
</message>
<message>
<source>A shared encryption-key with the name &quot;%1&quot; already exists.
@ -3918,7 +3918,7 @@ Please unlock the selected database or choose another one which is unlocked.</so
</message>
<message>
<source>Use Google as fallback for downloading website icons</source>
<translation type="unfinished"/>
<translation>Folosește Google ca variantă de rezervă pentru descărcare favicon site</translation>
</message>
<message>
<source>Re-lock previously locked database after performing Auto-Type</source>

View File

@ -35,7 +35,7 @@
</message>
<message>
<source>Copy to clipboard</source>
<translation>Скопіювати у буфер обміну</translation>
<translation>Скопіювати в кишеню</translation>
</message>
<message>
<source>Version %1
@ -73,12 +73,13 @@ Kernel: %3 %4</source>
</message>
<message>
<source>Special thanks from the KeePassXC team go to debfx for creating the original KeePassX.</source>
<translation type="unfinished"/>
<translation>Команда KeePassXC щиро дякує debfx за створення первісної версії KeePassX.</translation>
</message>
<message>
<source>Build Type: %1
</source>
<translation type="unfinished"/>
<translation>Тип збірки: %1
</translation>
</message>
</context>
<context>
@ -103,7 +104,7 @@ Kernel: %3 %4</source>
<source>%1 has requested access to passwords for the following item(s).
Please select whether you want to allow access.</source>
<translation>%1 запросила доступ до гасел для таких записів(-у).
Будь ласка, вкажіть чи хочете ви дозволити доступ?</translation>
Будь ласка, вкажіть чи хочете Ви дозволити доступ?</translation>
</message>
</context>
<context>
@ -211,7 +212,7 @@ Please select whether you want to allow access.</source>
<source>%1 has requested access to passwords for the following item(s).
Please select whether you want to allow access.</source>
<translation>%1 запросила доступ до гасел для таких записів(-у).
Будь ласка, вкажіть чи хочете ви дозволити доступ?</translation>
Будь ласка, вкажіть чи хочете Ви дозволити доступ?</translation>
</message>
</context>
<context>
@ -374,7 +375,7 @@ Please select whether you want to allow access.</source>
</message>
<message>
<source>We&apos;re sorry, but KeePassXC-Browser is not supported for Snap releases at the moment.</source>
<translation type="unfinished"/>
<translation>Вибачте, але переглядач KeePassXC поки що не працює у версіях Snap.</translation>
</message>
</context>
<context>
@ -443,11 +444,11 @@ Please unlock the selected database or choose another one which is unlocked.</so
</message>
<message>
<source>KeePassXC: Removed keys from database</source>
<translation>KeePassXC: ключі видалені зі сховища</translation>
<translation>KeePassXC: ключі видалено зі сховища</translation>
</message>
<message numerus="yes">
<source>Successfully removed %n encryption key(s) from KeePassXC settings.</source>
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform><numerusform></numerusform></translation>
<translation><numerusform>Успішно видалено %n шифрувальний ключ з налаштувань KeePassXC.</numerusform><numerusform>Успішно видалено %n шифрувальні ключа з налаштувань KeePassXC.</numerusform><numerusform>Успішно видалено %n шифрувальних ключів з налаштувань KeePassXC.</numerusform></translation>
</message>
<message>
<source>Removing stored permissions</source>
@ -459,11 +460,11 @@ Please unlock the selected database or choose another one which is unlocked.</so
</message>
<message>
<source>KeePassXC: Removed permissions</source>
<translation>KeePassXC: привілеї видалені</translation>
<translation>KeePassXC: привілеї видалено</translation>
</message>
<message numerus="yes">
<source>Successfully removed permissions from %n entry(s).</source>
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform><numerusform></numerusform></translation>
<translation><numerusform>Успішно видалено привілеї для %n запису.</numerusform><numerusform>Успішно видалено привілеї для %n записів.</numerusform><numerusform>Успішно видалено привілеї для %n записів.</numerusform></translation>
</message>
<message>
<source>KeePassXC: No entry with permissions found!</source>
@ -788,7 +789,7 @@ Please consider generating a new key file.</source>
</message>
<message>
<source>Database opened fine. Nothing to do.</source>
<translation>Сховище відкрите без помилок. Обробка не потрібна.</translation>
<translation>Сховище відкрито без помилок. Обробка не потрібна.</translation>
</message>
<message>
<source>Success</source>
@ -797,8 +798,8 @@ Please consider generating a new key file.</source>
<message>
<source>The database has been successfully repaired
You can now save it.</source>
<translation>Лагодження сховища успішно завершене.
Тепер ви можете його зберегти.</translation>
<translation>Лагодження сховища успішно завершено.
Тепер Ви можете його зберегти.</translation>
</message>
<message>
<source>Unable to repair the database.</source>
@ -830,7 +831,7 @@ If you keep this number, your database may take hours or days (or even longer) t
</message>
<message>
<source>Understood, keep number</source>
<translation>Зрозуміло, зберігайте число</translation>
<translation>Зрозуміло, кількість залишено</translation>
</message>
<message>
<source>Cancel</source>
@ -860,12 +861,12 @@ If you keep this number, your database may be too easy to crack!</source>
<message numerus="yes">
<source> MiB</source>
<comment>Abbreviation for Mebibytes (KDF settings)</comment>
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform><numerusform></numerusform></translation>
<translation><numerusform>МіБ</numerusform><numerusform>МіБ</numerusform><numerusform>МіБ</numerusform></translation>
</message>
<message numerus="yes">
<source> thread(s)</source>
<comment>Threads for parallel execution (KDF settings)</comment>
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform><numerusform></numerusform></translation>
<translation><numerusform>потік</numerusform><numerusform>потоки</numerusform><numerusform>потоків</numerusform></translation>
</message>
</context>
<context>
@ -1382,15 +1383,15 @@ Do you want to merge your changes?</source>
</message>
<message>
<source>Apply generated password?</source>
<translation type="unfinished"/>
<translation>Застосувати створене гасло?</translation>
</message>
<message>
<source>Do you want to apply the generated password to this entry?</source>
<translation type="unfinished"/>
<translation>Бажаєте застосувати створене гасло до цього запису?</translation>
</message>
<message>
<source>Entry updated successfully.</source>
<translation type="unfinished"/>
<translation>Запис успішно оновлено.</translation>
</message>
</context>
<context>
@ -1425,11 +1426,11 @@ Do you want to merge your changes?</source>
</message>
<message>
<source>Foreground Color:</source>
<translation type="unfinished"/>
<translation>Колір переднього плану:</translation>
</message>
<message>
<source>Background Color:</source>
<translation type="unfinished"/>
<translation> Колір тла:</translation>
</message>
</context>
<context>
@ -1464,7 +1465,7 @@ Do you want to merge your changes?</source>
</message>
<message>
<source>Use a specific sequence for this association:</source>
<translation type="unfinished"/>
<translation>Використовувати певну послідовність для цієї прив&apos;язки:</translation>
</message>
</context>
<context>
@ -1569,7 +1570,7 @@ Do you want to merge your changes?</source>
</message>
<message>
<source>Copy to clipboard</source>
<translation>Скопіювати у буфер обміну</translation>
<translation>Скопіювати в кишеню</translation>
</message>
<message>
<source>Private key</source>
@ -1746,7 +1747,7 @@ Do you want to merge your changes?</source>
</message>
<message>
<source>Plugin Data</source>
<translation type="unfinished"/>
<translation>Дані модуля</translation>
</message>
<message>
<source>Remove</source>
@ -1754,20 +1755,21 @@ Do you want to merge your changes?</source>
</message>
<message>
<source>Delete plugin data?</source>
<translation type="unfinished"/>
<translation>Видалити дані модуля?</translation>
</message>
<message>
<source>Do you really want to delete the selected plugin data?
This may cause the affected plugins to malfunction.</source>
<translation type="unfinished"/>
<translation>Ви дійсно хочете видалити всі дані позначеного модуля?
Це може призвести до порушень у роботі інших модулів.</translation>
</message>
<message>
<source>Key</source>
<translation type="unfinished"/>
<translation>Ключ</translation>
</message>
<message>
<source>Value</source>
<translation type="unfinished"/>
<translation>Значення</translation>
</message>
</context>
<context>
@ -1817,7 +1819,7 @@ This may cause the affected plugins to malfunction.</source>
</message>
<message numerus="yes">
<source>Are you sure you want to remove %n attachment(s)?</source>
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform><numerusform></numerusform></translation>
<translation><numerusform>Ви дійсно хочете видалити %n вкладення?</numerusform><numerusform>Ви дійсно хочете видалити %n вкладення?</numerusform><numerusform>Ви дійсно хочете видалити %n вкладень?</numerusform></translation>
</message>
<message>
<source>Confirm Remove</source>
@ -1976,7 +1978,7 @@ This may cause the affected plugins to malfunction.</source>
</message>
<message>
<source>Attachments (icon)</source>
<translation type="unfinished"/>
<translation>Вкладення (значок)</translation>
</message>
</context>
<context>
@ -2075,7 +2077,7 @@ This may cause the affected plugins to malfunction.</source>
</message>
<message>
<source>Wrong key or database file is corrupt.</source>
<translation>Неправильний ключ або файл сховища пошкоджено.</translation>
<translation>Неправильний ключ або пошкоджене сховище.</translation>
</message>
</context>
<context>
@ -2221,7 +2223,7 @@ This may cause the affected plugins to malfunction.</source>
<message>
<source>Invalid symmetric cipher IV size.</source>
<comment>IV = Initialization Vector for symmetric cipher</comment>
<translation>Хибний розмір IV симетричного шифру.</translation>
<translation>Хибний розмір симетричного шифру IV.</translation>
</message>
<message>
<source>Unable to calculate master key</source>
@ -2441,11 +2443,11 @@ This is a one-way migration. You won&apos;t be able to open the imported databas
</message>
<message>
<source>Unsupported encryption algorithm.</source>
<translation>Алгоритм шифрування не підтримується.</translation>
<translation>Цей алгоритм шифрування не підтримується.</translation>
</message>
<message>
<source>Unsupported KeePass database version.</source>
<translation>Версія сховища KeePass не підтримується.</translation>
<translation>Ця версія сховища KeePass не підтримується.</translation>
</message>
<message>
<source>Unable to read encryption IV</source>
@ -2486,7 +2488,7 @@ This is a one-way migration. You won&apos;t be able to open the imported databas
</message>
<message>
<source>Wrong key or database file is corrupt.</source>
<translation>Неправильний ключ або файл сховища пошкоджено.</translation>
<translation>Неправильний ключ або пошкоджене сховище.</translation>
</message>
<message>
<source>Key transformation failed</source>
@ -2655,7 +2657,7 @@ This is a one-way migration. You won&apos;t be able to open the imported databas
</message>
<message>
<source>Copy att&amp;ribute to clipboard</source>
<translation>Копіювати атрибут до буферу обміну</translation>
<translation>Копіювати атрибут до кишені</translation>
</message>
<message>
<source>Time-based one-time password</source>
@ -2743,7 +2745,7 @@ This is a one-way migration. You won&apos;t be able to open the imported databas
</message>
<message>
<source>&amp;Find</source>
<translation>Пошук</translation>
<translation>Знайти</translation>
</message>
<message>
<source>Copy &amp;username</source>
@ -2751,7 +2753,7 @@ This is a one-way migration. You won&apos;t be able to open the imported databas
</message>
<message>
<source>Copy username to clipboard</source>
<translation>Копіювати імя користувача в буфер обміну</translation>
<translation>Копіювати імя користувача в кишеню</translation>
</message>
<message>
<source>Cop&amp;y password</source>
@ -2759,7 +2761,7 @@ This is a one-way migration. You won&apos;t be able to open the imported databas
</message>
<message>
<source>Copy password to clipboard</source>
<translation>Копіювати гасло в буфер обміну</translation>
<translation>Копіювати гасло в кишеню</translation>
</message>
<message>
<source>&amp;Settings</source>
@ -2978,23 +2980,23 @@ This version is not meant for production use.</source>
</message>
<message>
<source>Unsupported key type: %1</source>
<translation type="unfinished"/>
<translation>Непідтримуваний вид ключа: %1</translation>
</message>
<message>
<source>Unknown cipher: %1</source>
<translation type="unfinished"/>
<translation>Невідомий шифр: %1</translation>
</message>
<message>
<source>Cipher IV is too short for MD5 kdf</source>
<translation type="unfinished"/>
<translation>Шифр IV занадто короткий для ФОК MD5</translation>
</message>
<message>
<source>Unknown KDF: %1</source>
<translation type="unfinished"/>
<translation>Невідома ФОК: %1</translation>
</message>
<message>
<source>Unknown key type: %1</source>
<translation type="unfinished"/>
<translation>Невідомий тип ключа: %1</translation>
</message>
</context>
<context>
@ -3372,7 +3374,7 @@ Using default port 19455.</source>
</message>
<message>
<source>Timeout in seconds before clearing the clipboard.</source>
<translation>Час очікування у </translation>
<translation>Час очікування перед очищенням кишені.</translation>
</message>
<message>
<source>Edit an entry.</source>
@ -3468,7 +3470,7 @@ Available commands:
</message>
<message>
<source>Path of the database to merge from.</source>
<translation>Шлях до сховища, яке об&apos;єднати.</translation>
<translation>Шлях до сховища, яке підлягає об&apos;єднанню.</translation>
</message>
<message>
<source>Use the same credentials for both database files.</source>
@ -3476,7 +3478,7 @@ Available commands:
</message>
<message>
<source>Key file of the database to merge from.</source>
<translation>Файл ключа для сховища, з якого треба взяти дані для об&apos;єднання.</translation>
<translation>Файл ключа для сховища, яке підлягає об&apos;єднанню.</translation>
</message>
<message>
<source>Show an entry&apos;s information.</source>
@ -3570,48 +3572,49 @@ Available commands:
</message>
<message>
<source>Generate a new random diceware passphrase.</source>
<translation type="unfinished"/>
<translation>Створити новий вираз гасла методом гральних кісточок (diceware).</translation>
</message>
<message>
<source>Word count for the diceware passphrase.</source>
<translation type="unfinished"/>
<translation>Кількість слів у виразі гасла.</translation>
</message>
<message>
<source>count</source>
<translation type="unfinished"/>
<translation>кількість</translation>
</message>
<message>
<source>Wordlist for the diceware generator.
[Default: EFF English]</source>
<translation type="unfinished"/>
<translation>Список слів для виробника гасел методом diceware.
[Типово: англійська версія EFF]</translation>
</message>
<message>
<source>Generate a new random password.</source>
<translation type="unfinished"/>
<translation>Створити нове випадкове гасло.</translation>
</message>
<message>
<source>Length of the generated password.</source>
<translation type="unfinished"/>
<translation>Довжина створюваного гасла.</translation>
</message>
<message>
<source>Use lowercase characters in the generated password.</source>
<translation type="unfinished"/>
<translation>Використовувати малі літери для створення гасла.</translation>
</message>
<message>
<source>Use uppercase characters in the generated password.</source>
<translation type="unfinished"/>
<translation>Використовувати великі літери для створення гасла.</translation>
</message>
<message>
<source>Use numbers in the generated password.</source>
<translation type="unfinished"/>
<translation>Використовувати числа для створення гасла.</translation>
</message>
<message>
<source>Use special characters in the generated password.</source>
<translation type="unfinished"/>
<translation>Використовувати спеціальні символи для створення гасла.</translation>
</message>
<message>
<source>Use extended ASCII in the generated password.</source>
<translation type="unfinished"/>
<translation>Використовувати розширені ASCII для створення гасла.</translation>
</message>
</context>
<context>
@ -3652,7 +3655,7 @@ Available commands:
<name>SearchWidget</name>
<message>
<source>Search...</source>
<translation>Шукати...</translation>
<translation>Знайти...</translation>
</message>
<message>
<source>Search</source>
@ -3715,11 +3718,11 @@ Please unlock the selected database or choose another one which is unlocked.</so
</message>
<message>
<source>KeePassXC: Removed keys from database</source>
<translation>KeePassXC: ключі видалені зі сховища</translation>
<translation>KeePassXC: ключі видалено зі сховища</translation>
</message>
<message numerus="yes">
<source>Successfully removed %n encryption-key(s) from KeePassX/Http Settings.</source>
<translation><numerusform>Успішно видалив %n шифрувальний ключ з HTTP налаштувань KeePassX.</numerusform><numerusform>Успішно видалив %n шифрувальних ключа з HTTP налаштувань KeePassX.</numerusform><numerusform>Успішно видалив %n шифрувальних ключів з HTTP налаштувань KeePassX.</numerusform></translation>
<translation><numerusform>Успішно видалено %n шифрувальний ключ з HTTP налаштувань KeePassX.</numerusform><numerusform>Успішно видалено %n шифрувальних ключа з HTTP налаштувань KeePassX.</numerusform><numerusform>Успішно видалено %n шифрувальних ключів з HTTP налаштувань KeePassX.</numerusform></translation>
</message>
<message>
<source>KeePassXC: No keys found</source>
@ -3747,11 +3750,11 @@ Please unlock the selected database or choose another one which is unlocked.</so
</message>
<message>
<source>KeePassXC: Removed permissions</source>
<translation>KeePassXC: привілеї видалені</translation>
<translation>KeePassXC: привілеї видалено</translation>
</message>
<message numerus="yes">
<source>Successfully removed permissions from %n entries.</source>
<translation><numerusform>Успішно видалив привілеї для %n запису.</numerusform><numerusform>Успішно видалив привілеї для %n записів.</numerusform><numerusform>Успішно видалив привілеї для %n записів.</numerusform></translation>
<translation><numerusform>Успішно видалено привілеї для %n запису.</numerusform><numerusform>Успішно видалено привілеї для %n записів.</numerusform><numerusform>Успішно видалено привілеї для %n записів.</numerusform></translation>
</message>
<message>
<source>KeePassXC: No entry with permissions found!</source>
@ -3817,7 +3820,7 @@ Please unlock the selected database or choose another one which is unlocked.</so
</message>
<message>
<source>Minimize when copying to clipboard</source>
<translation>Згортати при копіюванні до буфера обміну</translation>
<translation>Згортати при копіюванні до кишені</translation>
</message>
<message>
<source>Minimize window at application startup</source>
@ -3917,7 +3920,7 @@ Please unlock the selected database or choose another one which is unlocked.</so
</message>
<message>
<source>Clear clipboard after</source>
<translation>Очищати буфер обміну через</translation>
<translation>Очищати кишеню через</translation>
</message>
<message>
<source> sec</source>
@ -3966,7 +3969,7 @@ Please unlock the selected database or choose another one which is unlocked.</so
</message>
<message>
<source>Re-lock previously locked database after performing Auto-Type</source>
<translation type="unfinished"/>
<translation>Заблоковувати попередньо заблоковане сховище після завершення автозаповнення</translation>
</message>
</context>
<context>

View File

@ -73,7 +73,7 @@ CPU 架构:%2
</message>
<message>
<source>Special thanks from the KeePassXC team go to debfx for creating the original KeePassX.</source>
<translation type="unfinished"/>
<translation>KeePassXC debfx KeePassX</translation>
</message>
<message>
<source>Build Type: %1
@ -255,7 +255,7 @@ Please select whether you want to allow access.</source>
<message>
<source>Show a &amp;notification when credentials are requested</source>
<extracomment>Credentials mean login data requested via browser extension</extracomment>
<translation type="unfinished"/>
<translation> (&amp;N)</translation>
</message>
<message>
<source>Re&amp;quest to unlock the database if it is locked</source>
@ -280,12 +280,12 @@ Please select whether you want to allow access.</source>
<message>
<source>Sort &amp;matching credentials by title</source>
<extracomment>Credentials mean login data requested via browser extension</extracomment>
<translation type="unfinished"/>
<translation></translation>
</message>
<message>
<source>Sort matching credentials by &amp;username</source>
<extracomment>Credentials mean login data requested via browser extension</extracomment>
<translation type="unfinished"/>
<translation></translation>
</message>
<message>
<source>&amp;Disconnect all browsers</source>
@ -293,7 +293,7 @@ Please select whether you want to allow access.</source>
</message>
<message>
<source>Forget all remembered &amp;permissions</source>
<translation type="unfinished"/>
<translation></translation>
</message>
<message>
<source>Advanced</source>
@ -302,7 +302,7 @@ Please select whether you want to allow access.</source>
<message>
<source>Never &amp;ask before accessing credentials</source>
<extracomment>Credentials mean login data requested via browser extension</extracomment>
<translation type="unfinished"/>
<translation></translation>
</message>
<message>
<source>Never ask before &amp;updating credentials</source>
@ -316,7 +316,7 @@ Please select whether you want to allow access.</source>
<message>
<source>Searc&amp;h in all opened databases for matching credentials</source>
<extracomment>Credentials mean login data requested via browser extension</extracomment>
<translation type="unfinished"/>
<translation></translation>
</message>
<message>
<source>Automatically creating or updating string fields is not supported.</source>
@ -328,11 +328,11 @@ Please select whether you want to allow access.</source>
</message>
<message>
<source>Updates KeePassXC or keepassxc-proxy binary path automatically to native messaging scripts on startup.</source>
<translation type="unfinished"/>
<translation> KeePassXC keepassxc-proxy native messaging </translation>
</message>
<message>
<source>Update &amp;native messaging manifest files at startup</source>
<translation type="unfinished"/>
<translation> native messaging manifest </translation>
</message>
<message>
<source>Support a proxy application between KeePassXC and browser extension.</source>
@ -340,16 +340,16 @@ Please select whether you want to allow access.</source>
</message>
<message>
<source>Use a &amp;proxy application between KeePassXC and browser extension</source>
<translation type="unfinished"/>
<translation> KeePassXC 使</translation>
</message>
<message>
<source>Use a custom proxy location if you installed a proxy manually.</source>
<translation type="unfinished"/>
<translation></translation>
</message>
<message>
<source>Use a &amp;custom proxy location</source>
<comment>Meant is the proxy for KeePassXC-Browser</comment>
<translation type="unfinished"/>
<translation></translation>
</message>
<message>
<source>Browse...</source>

View File

@ -1,5 +1,5 @@
name: keepassxc
version: 2.3.1
version: 2.3.3
grade: stable
summary: Community-driven port of the Windows application “KeePass Password Safe”
description: |
@ -33,7 +33,7 @@ parts:
- -DWITH_XC_ALL=ON
build-packages:
- g++
- libgcrypt20-dev
- libgcrypt20-18-dev
- libqt5x11extras5-dev
- qtbase5-dev
- qttools5-dev
@ -45,9 +45,11 @@ parts:
- libykpers-1-dev
- libcurl4-openssl-dev
- libsodium-dev
- libargon2-0-dev
stage-packages:
- dbus
- qttranslations5-l10n # common translations
- libgcrypt20-18
install: |
sed -i 's|Icon=keepassxc|Icon=${SNAP}/usr/share/icons/hicolor/256x256/apps/keepassxc.png|g' $SNAPCRAFT_PART_INSTALL/usr/share/applications/org.keepassxc.KeePassXC.desktop
organize:

View File

@ -200,10 +200,6 @@ add_feature_info(KeePassXC-Browser WITH_XC_BROWSER "Browser integration with Kee
add_feature_info(SSHAgent WITH_XC_SSHAGENT "SSH agent integration compatible with KeeAgent")
add_feature_info(YubiKey WITH_XC_YUBIKEY "YubiKey HMAC-SHA1 challenge-response")
if(WITH_XC_NETWORKING)
find_package(CURL REQUIRED)
endif()
set(BROWSER_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/browser)
add_subdirectory(browser)
add_subdirectory(proxy)
@ -276,7 +272,7 @@ if (UNIX AND NOT APPLE)
target_link_libraries(keepassx_core Qt5::DBus)
endif()
if(MINGW)
target_link_libraries(keepassx_core Wtsapi32.lib)
target_link_libraries(keepassx_core Wtsapi32.lib Ws2_32.lib)
endif()
if(MINGW)

View File

@ -220,7 +220,7 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c
#endif
}
Tools::wait(m_plugin->initialTimeout());
Tools::wait(qMax(100, config()->get("AutoTypeStartDelay", 500).toInt()));
if (!window) {
window = m_plugin->activeWindow();
@ -364,7 +364,7 @@ bool AutoType::parseActions(const QString& actionSequence, const Entry* entry, Q
{
QString tmpl;
bool inTmpl = false;
m_autoTypeDelay = config()->get("AutoTypeDelay").toInt();
m_autoTypeDelay = qMax(config()->get("AutoTypeDelay").toInt(), 0);
QString sequence = actionSequence;
sequence.replace("{{}", "{LEFTBRACE}");

View File

@ -35,7 +35,6 @@ public:
virtual bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) = 0;
virtual void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) = 0;
virtual int platformEventFilter(void* event) = 0;
virtual int initialTimeout() = 0;
virtual bool raiseWindow(WId window) = 0;
virtual void unload()
{

View File

@ -154,11 +154,6 @@ AutoTypeExecutor* AutoTypePlatformMac::createExecutor()
return new AutoTypeExecutorMac(this);
}
int AutoTypePlatformMac::initialTimeout()
{
return 500;
}
//
// Activate window by process id
//

View File

@ -42,7 +42,6 @@ public:
bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
int platformEventFilter(void* event) override;
int initialTimeout() override;
bool raiseWindow(WId pid) override;
AutoTypeExecutor* createExecutor() override;

View File

@ -103,11 +103,6 @@ void AutoTypePlatformTest::addActionKey(AutoTypeKey* action)
m_actionChars.append(keyToString(action->key));
}
int AutoTypePlatformTest::initialTimeout()
{
return 0;
}
bool AutoTypePlatformTest::raiseWindow(WId window)
{
Q_UNUSED(window);

View File

@ -40,7 +40,6 @@ public:
bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
int platformEventFilter(void* event) override;
int initialTimeout() override;
bool raiseWindow(WId window) override;
AutoTypeExecutor* createExecutor() override;

View File

@ -109,11 +109,6 @@ AutoTypeExecutor* AutoTypePlatformWin::createExecutor()
return new AutoTypeExecutorWin(this);
}
int AutoTypePlatformWin::initialTimeout()
{
return 500;
}
//
// Set foreground window
//

View File

@ -39,7 +39,6 @@ public:
bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
int platformEventFilter(void* event) override;
int initialTimeout() override;
bool raiseWindow(WId window) override;
AutoTypeExecutor* createExecutor() override;

View File

@ -830,11 +830,6 @@ void AutoTypeExecutorX11::execClearField(AutoTypeClearField* action = nullptr)
nanosleep(&ts, nullptr);
}
int AutoTypePlatformX11::initialTimeout()
{
return 500;
}
bool AutoTypePlatformX11::raiseWindow(WId window)
{
if (m_atomNetActiveWindow == None) {

View File

@ -51,7 +51,6 @@ public:
bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
int platformEventFilter(void* event) override;
int initialTimeout() override;
bool raiseWindow(WId window) override;
AutoTypeExecutor* createExecutor() override;

View File

@ -18,6 +18,7 @@
#include "BrowserAction.h"
#include "BrowserSettings.h"
#include "NativeMessagingBase.h"
#include "config-keepassx.h"
#include "sodium.h"
#include "sodium/crypto_box.h"
@ -237,9 +238,17 @@ QJsonObject BrowserAction::handleGetLogins(const QJsonObject& json, const QStrin
return getErrorReply(action, ERROR_KEEPASS_NO_URL_PROVIDED);
}
const QJsonArray keys = decrypted.value("keys").toArray();
StringPairList keyList;
for (const QJsonValue val : keys) {
const QJsonObject keyObject = val.toObject();
keyList.push_back(qMakePair(keyObject.value("id").toString(), keyObject.value("key").toString()));
}
const QString id = decrypted.value("id").toString();
const QString submit = decrypted.value("submitUrl").toString();
const QJsonArray users = m_browserService.findMatchingEntries(id, url, submit, "");
const QJsonArray users = m_browserService.findMatchingEntries(id, url, submit, "", keyList);
if (users.isEmpty()) {
return getErrorReply(action, ERROR_KEEPASS_NO_LOGINS_FOUND);
@ -472,7 +481,7 @@ QString BrowserAction::encrypt(const QString plaintext, const QString nonce)
std::vector<unsigned char> sk(sa.cbegin(), sa.cend());
std::vector<unsigned char> e;
e.resize(max_length);
e.resize(NATIVE_MSG_MAX_LENGTH);
if (m.empty() || n.empty() || ck.empty() || sk.empty()) {
return QString();
@ -500,7 +509,7 @@ QByteArray BrowserAction::decrypt(const QString encrypted, const QString nonce)
std::vector<unsigned char> sk(sa.cbegin(), sa.cend());
std::vector<unsigned char> d;
d.resize(max_length);
d.resize(NATIVE_MSG_MAX_LENGTH);
if (m.empty() || n.empty() || ck.empty() || sk.empty()) {
return QByteArray();

View File

@ -68,7 +68,6 @@ void BrowserOptionDialog::loadSettings()
// hide unimplemented options
// TODO: fix this
m_ui->showNotification->hide();
m_ui->bestMatchOnly->hide();
if (settings.sortByUsername()) {
m_ui->sortByUsername->setChecked(true);

View File

@ -47,6 +47,7 @@ static int KEEPASSXCBROWSER_DEFAULT_ICON = 1;
BrowserService::BrowserService(DatabaseTabWidget* parent)
: m_dbTabWidget(parent)
, m_dialogActive(false)
, m_bringToFrontRequested(false)
{
connect(m_dbTabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), this, SLOT(databaseLocked(DatabaseWidget*)));
connect(m_dbTabWidget, SIGNAL(databaseUnlocked(DatabaseWidget*)), this, SLOT(databaseUnlocked(DatabaseWidget*)));
@ -83,6 +84,7 @@ bool BrowserService::openDatabase(bool triggerUnlock)
if (triggerUnlock) {
KEEPASSXC_MAIN_WINDOW->bringToFront();
m_bringToFrontRequested = true;
}
return false;
@ -228,7 +230,8 @@ QString BrowserService::getKey(const QString& id)
QJsonArray BrowserService::findMatchingEntries(const QString& id,
const QString& url,
const QString& submitUrl,
const QString& realm)
const QString& realm,
const StringPairList& keyList)
{
QJsonArray result;
if (thread() != QThread::currentThread()) {
@ -239,7 +242,8 @@ QJsonArray BrowserService::findMatchingEntries(const QString& id,
Q_ARG(const QString&, id),
Q_ARG(const QString&, url),
Q_ARG(const QString&, submitUrl),
Q_ARG(const QString&, realm));
Q_ARG(const QString&, realm),
Q_ARG(const StringPairList&, keyList));
return result;
}
@ -250,7 +254,7 @@ QJsonArray BrowserService::findMatchingEntries(const QString& id,
// Check entries for authorization
QList<Entry*> pwEntriesToConfirm;
QList<Entry*> pwEntries;
for (Entry* entry : searchEntries(url)) {
for (Entry* entry : searchEntries(url, keyList)) {
switch (checkAccess(entry, host, submitHost, realm)) {
case Denied:
continue;
@ -356,15 +360,19 @@ void BrowserService::updateEntry(const QString& id,
return;
}
if (username.compare(login, Qt::CaseSensitive) != 0
|| entry->password().compare(password, Qt::CaseSensitive) != 0) {
QMessageBox::StandardButton dialogResult = QMessageBox::No;
if (username.compare(login, Qt::CaseSensitive) != 0 || entry->password().compare(password, Qt::CaseSensitive) != 0) {
int dialogResult = QMessageBox::No;
if (!BrowserSettings::alwaysAllowUpdate()) {
dialogResult = QMessageBox::warning(
0,
tr("KeePassXC: Update Entry"),
tr("Do you want to update the information in %1 - %2?").arg(QUrl(url).host()).arg(username),
QMessageBox::Yes | QMessageBox::No);
QMessageBox msgBox;
msgBox.setWindowTitle(tr("KeePassXC: Update Entry"));
msgBox.setText(tr("Do you want to update the information in %1 - %2?").arg(QUrl(url).host()).arg(username));
msgBox.setStandardButtons(QMessageBox::Yes);
msgBox.addButton(QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::No);
msgBox.setWindowFlags(Qt::WindowStaysOnTopHint);
msgBox.activateWindow();
msgBox.raise();
dialogResult = msgBox.exec();
}
if (BrowserSettings::alwaysAllowUpdate() || dialogResult == QMessageBox::Yes) {
@ -399,7 +407,7 @@ QList<Entry*> BrowserService::searchEntries(Database* db, const QString& hostnam
return entries;
}
QList<Entry*> BrowserService::searchEntries(const QString& text)
QList<Entry*> BrowserService::searchEntries(const QString& text, const StringPairList& keyList)
{
// Get the list of databases to search
QList<Database*> databases;
@ -408,7 +416,16 @@ QList<Entry*> BrowserService::searchEntries(const QString& text)
for (int i = 0; i < count; ++i) {
if (DatabaseWidget* dbWidget = qobject_cast<DatabaseWidget*>(m_dbTabWidget->widget(i))) {
if (Database* db = dbWidget->database()) {
databases << db;
// Check if database is connected with KeePassXC-Browser
for (const StringPair keyPair : keyList) {
Entry* entry = db->resolveEntry(KEEPASSXCBROWSER_UUID);
if (entry) {
QString key = entry->attributes()->value(QLatin1String(ASSOCIATE_KEY_PREFIX) + keyPair.first);
if (!key.isEmpty() && keyPair.second == key) {
databases << db;
}
}
}
}
}
}
@ -537,21 +554,30 @@ QList<Entry*> BrowserService::sortEntries(QList<Entry*>& pwEntries, const QStrin
const QString baseSubmitUrl =
url.toString(QUrl::StripTrailingSlash | QUrl::RemovePath | QUrl::RemoveQuery | QUrl::RemoveFragment);
QMultiMap<int, const Entry*> priorities;
for (const Entry* entry : pwEntries) {
// Build map of prioritized entries
QMultiMap<int, Entry*> priorities;
for (Entry* entry : pwEntries) {
priorities.insert(sortPriority(entry, host, submitUrl, baseSubmitUrl), entry);
}
QList<Entry*> results;
QString field = BrowserSettings::sortByTitle() ? "Title" : "UserName";
std::sort(pwEntries.begin(), pwEntries.end(), [&priorities, &field](const Entry* left, const Entry* right) {
int res = priorities.key(left) - priorities.key(right);
if (res == 0) {
return QString::localeAwareCompare(left->attributes()->value(field), right->attributes()->value(field)) < 0;
for (int i = 100; i >= 0; i -= 5) {
if (priorities.count(i) > 0) {
// Sort same priority entries by Title or UserName
auto entries = priorities.values(i);
std::sort(entries.begin(), entries.end(), [&priorities, &field](Entry* left, Entry* right) {
return QString::localeAwareCompare(left->attributes()->value(field), right->attributes()->value(field)) < 0;
});
results << entries;
if (BrowserSettings::bestMatchOnly() && !pwEntries.isEmpty()) {
// Early out once we find the highest batch of matches
break;
}
}
return res < 0;
});
}
return pwEntries;
return results;
}
bool BrowserService::confirmEntries(QList<Entry*>& pwEntriesToConfirm,
@ -607,6 +633,10 @@ QJsonObject BrowserService::prepareEntry(const Entry* entry)
res["name"] = entry->resolveMultiplePlaceholders(entry->title());
res["uuid"] = entry->resolveMultiplePlaceholders(entry->uuid().toHex());
if (entry->hasTotp()) {
res["totp"] = entry->totp();
}
if (BrowserSettings::supportKphFields()) {
const EntryAttributes* attr = entry->attributes();
QJsonArray stringFields;
@ -762,6 +792,10 @@ void BrowserService::databaseLocked(DatabaseWidget* dbWidget)
void BrowserService::databaseUnlocked(DatabaseWidget* dbWidget)
{
if (dbWidget) {
if (m_bringToFrontRequested) {
KEEPASSXC_MAIN_WINDOW->lower();
m_bringToFrontRequested = false;
}
emit databaseUnlocked();
}
}

View File

@ -25,6 +25,9 @@
#include <QObject>
#include <QtCore>
typedef QPair<QString, QString> StringPair;
typedef QList<StringPair> StringPairList;
enum
{
max_length = 16 * 1024
@ -50,13 +53,16 @@ public:
const QString& submitUrl,
const QString& realm);
QList<Entry*> searchEntries(Database* db, const QString& hostname);
QList<Entry*> searchEntries(const QString& text);
QList<Entry*> searchEntries(const QString& text, const StringPairList& keyList);
void removeSharedEncryptionKeys();
void removeStoredPermissions();
public slots:
QJsonArray
findMatchingEntries(const QString& id, const QString& url, const QString& submitUrl, const QString& realm);
QJsonArray findMatchingEntries(const QString& id,
const QString& url,
const QString& submitUrl,
const QString& realm,
const StringPairList& keyList);
QString storeKey(const QString& key);
void updateEntry(const QString& id,
const QString& uuid,
@ -100,6 +106,7 @@ private:
private:
DatabaseTabWidget* const m_dbTabWidget;
bool m_dialogActive;
bool m_bringToFrontRequested;
};
#endif // BROWSERSERVICE_H

View File

@ -32,7 +32,7 @@ public:
static bool showNotification(); // TODO!!
static void setShowNotification(bool showNotification);
static bool bestMatchOnly(); // TODO!!
static bool bestMatchOnly();
static void setBestMatchOnly(bool bestMatchOnly);
static bool unlockDatabase();
static void setUnlockDatabase(bool unlockDatabase);
@ -46,7 +46,7 @@ public:
static void setAlwaysAllowAccess(bool alwaysAllowAccess);
static bool alwaysAllowUpdate();
static void setAlwaysAllowUpdate(bool alwaysAllowUpdate);
static bool searchInAllDatabases(); // TODO!!
static bool searchInAllDatabases();
static void setSearchInAllDatabases(bool searchInAllDatabases);
static bool supportKphFields();
static void setSupportKphFields(bool supportKphFields);

View File

@ -36,14 +36,17 @@
#include <io.h>
#endif
NativeMessagingBase::NativeMessagingBase()
NativeMessagingBase::NativeMessagingBase(const bool enabled)
{
#ifdef Q_OS_WIN
Q_UNUSED(enabled);
_setmode(_fileno(stdin), _O_BINARY);
_setmode(_fileno(stdout), _O_BINARY);
#else
m_notifier.reset(new QSocketNotifier(fileno(stdin), QSocketNotifier::Read, this));
connect(m_notifier.data(), SIGNAL(activated(int)), this, SLOT(newNativeMessage()));
if (enabled) {
m_notifier.reset(new QSocketNotifier(fileno(stdin), QSocketNotifier::Read, this));
connect(m_notifier.data(), SIGNAL(activated(int)), this, SLOT(newNativeMessage()));
}
#endif
}

View File

@ -32,12 +32,19 @@
#include <iostream>
#include <unistd.h>
#ifndef Q_OS_WIN
#include <sys/types.h>
#include <sys/socket.h>
#endif
static const int NATIVE_MSG_MAX_LENGTH = 1024*1024;
class NativeMessagingBase : public QObject
{
Q_OBJECT
public:
explicit NativeMessagingBase();
explicit NativeMessagingBase(const bool enabled);
~NativeMessagingBase() = default;
protected slots:

View File

@ -23,8 +23,12 @@
#include <QtNetwork>
#include <iostream>
NativeMessagingHost::NativeMessagingHost(DatabaseTabWidget* parent)
: NativeMessagingBase()
#ifdef Q_OS_WIN
#include <Winsock2.h>
#endif
NativeMessagingHost::NativeMessagingHost(DatabaseTabWidget* parent, const bool enabled)
: NativeMessagingBase(enabled)
, m_mutex(QMutex::Recursive)
, m_browserClients(m_browserService)
, m_browserService(parent)
@ -75,6 +79,11 @@ void NativeMessagingHost::run()
QString serverPath = getLocalServerPath();
QFile::remove(serverPath);
// Ensure that STDIN is not being listened when proxy is used
if (m_notifier && m_notifier->isEnabled()) {
m_notifier->setEnabled(false);
}
if (m_localServer->isListening()) {
m_localServer->close();
}
@ -144,11 +153,17 @@ void NativeMessagingHost::newLocalConnection()
void NativeMessagingHost::newLocalMessage()
{
QLocalSocket* socket = qobject_cast<QLocalSocket*>(QObject::sender());
if (!socket || socket->bytesAvailable() <= 0) {
return;
}
socket->setReadBufferSize(NATIVE_MSG_MAX_LENGTH);
int socketDesc = socket->socketDescriptor();
if (socketDesc) {
int max = NATIVE_MSG_MAX_LENGTH;
setsockopt(socketDesc, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<char*>(&max), sizeof(max));
}
QByteArray arr = socket->readAll();
if (arr.isEmpty()) {
return;

View File

@ -31,7 +31,7 @@ class NativeMessagingHost : public NativeMessagingBase
typedef QList<QLocalSocket*> SocketList;
public:
explicit NativeMessagingHost(DatabaseTabWidget* parent = 0);
explicit NativeMessagingHost(DatabaseTabWidget* parent = 0, const bool enabled = false);
~NativeMessagingHost();
int init();
void run();

View File

@ -135,6 +135,7 @@ void Config::init(const QString& fileName)
m_defaults.insert("AutoTypeEntryTitleMatch", true);
m_defaults.insert("AutoTypeEntryURLMatch", true);
m_defaults.insert("AutoTypeDelay", 25);
m_defaults.insert("AutoTypeStartDelay", 500);
m_defaults.insert("UseGroupIconOnEntryCreation", true);
m_defaults.insert("IgnoreGroupExpansion", true);
m_defaults.insert("security/clearclipboard", true);

View File

@ -197,7 +197,7 @@ void DetailsWidget::updateEntryNotesTab()
Q_ASSERT(m_currentEntry);
const QString notes = m_currentEntry->notes();
setTabEnabled(m_ui->entryTabWidget, m_ui->entryNotesTab, !notes.isEmpty());
m_ui->entryNotesEdit->setText(m_currentEntry->resolveMultiplePlaceholders(notes));
m_ui->entryNotesEdit->setText(notes);
}
void DetailsWidget::updateEntryAttributesTab()

View File

@ -31,9 +31,7 @@
#include "gui/MessageBox.h"
#ifdef WITH_XC_NETWORKING
#include "core/AsyncTask.h"
#include <curl/curl.h>
#undef MessageBox
#include <QtNetwork>
#endif
IconStruct::IconStruct()
@ -42,10 +40,31 @@ IconStruct::IconStruct()
{
}
UrlFetchProgressDialog::UrlFetchProgressDialog(const QUrl &url, QWidget *parent)
: QProgressDialog(parent)
{
setWindowTitle(tr("Download Progress"));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setLabelText(tr("Downloading %1.").arg(url.toDisplayString()));
setMinimum(0);
setValue(0);
setMinimumDuration(0);
setMinimumSize(QSize(400, 75));
}
void UrlFetchProgressDialog::networkReplyProgress(qint64 bytesRead, qint64 totalBytes)
{
setMaximum(totalBytes);
setValue(bytesRead);
}
EditWidgetIcons::EditWidgetIcons(QWidget* parent)
: QWidget(parent)
, m_ui(new Ui::EditWidgetIcons())
, m_database(nullptr)
#ifdef WITH_XC_NETWORKING
, m_reply(nullptr)
#endif
, m_defaultIconModel(new DefaultIconModel(this))
, m_customIconModel(new CustomIconModel(this))
{
@ -146,7 +165,7 @@ void EditWidgetIcons::load(const Uuid& currentUuid,
void EditWidgetIcons::setUrl(const QString& url)
{
#ifdef WITH_XC_NETWORKING
m_url = url;
m_url = QUrl(url);
m_ui->faviconButton->setVisible(!url.isEmpty());
#else
Q_UNUSED(url);
@ -154,87 +173,152 @@ void EditWidgetIcons::setUrl(const QString& url)
#endif
}
#ifdef WITH_XC_NETWORKING
namespace {
// Try to get the 2nd level domain of the host part of a QUrl. For example,
// "foo.bar.example.com" would become "example.com", and "foo.bar.example.co.uk"
// would become "example.co.uk".
QString getSecondLevelDomain(QUrl url)
{
QString fqdn = url.host();
fqdn.truncate(fqdn.length() - url.topLevelDomain().length());
QStringList parts = fqdn.split('.');
QString newdom = parts.takeLast() + url.topLevelDomain();
return newdom;
}
QUrl convertVariantToUrl(QVariant var)
{
QUrl url;
if (var.canConvert<QUrl>())
url = var.value<QUrl>();
return url;
}
QUrl getRedirectTarget(QNetworkReply *reply)
{
QVariant var = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
QUrl url = convertVariantToUrl(var);
return url;
}
}
#endif
void EditWidgetIcons::downloadFavicon()
{
#ifdef WITH_XC_NETWORKING
m_ui->faviconButton->setDisabled(true);
QUrl url = QUrl(m_url);
url.setPath("/favicon.ico");
m_redirects = 0;
m_urlsToTry.clear();
QString fullyQualifiedDomain = m_url.host();
QString secondLevelDomain = getSecondLevelDomain(m_url);
// Attempt to simply load the favicon.ico file
QImage image = fetchFavicon(url);
if (fullyQualifiedDomain != secondLevelDomain) {
m_urlsToTry.append(QUrl(m_url.scheme() + "://" + fullyQualifiedDomain + "/favicon.ico"));
}
m_urlsToTry.append(QUrl(m_url.scheme() + "://" + secondLevelDomain + "/favicon.ico"));
// Try to use Google fallback, if enabled
if (config()->get("security/IconDownloadFallbackToGoogle", false).toBool()) {
QUrl urlGoogle = QUrl("https://www.google.com/s2/favicons");
urlGoogle.setQuery("domain=" + QUrl::toPercentEncoding(secondLevelDomain));
m_urlsToTry.append(urlGoogle);
}
startFetchFavicon(m_urlsToTry.takeFirst());
#endif
}
void EditWidgetIcons::fetchReadyRead()
{
#ifdef WITH_XC_NETWORKING
m_bytesReceived += m_reply->readAll();
#endif
}
void EditWidgetIcons::fetchFinished()
{
#ifdef WITH_XC_NETWORKING
QImage image;
bool googleFallbackEnabled = config()->get("security/IconDownloadFallbackToGoogle", false).toBool();
bool error = (m_reply->error() != QNetworkReply::NoError);
QUrl redirectTarget = getRedirectTarget(m_reply);
m_reply->deleteLater();
m_reply = nullptr;
if (!error) {
if (redirectTarget.isValid()) {
// Redirected, we need to follow it, or fall through if we have
// done too many redirects already.
if (m_redirects < 5) {
m_redirects++;
if (redirectTarget.isRelative())
redirectTarget = m_fetchUrl.resolved(redirectTarget);
startFetchFavicon(redirectTarget);
return;
}
} else {
// No redirect, and we theoretically have some icon data now.
image.loadFromData(m_bytesReceived);
}
}
if (!image.isNull()) {
addCustomIcon(image);
} else if (config()->get("security/IconDownloadFallbackToGoogle", false).toBool()) {
QUrl faviconUrl = QUrl("https://www.google.com/s2/favicons");
faviconUrl.setQuery("domain=" + QUrl::toPercentEncoding(url.host()));
// Attempt to load favicon from Google
image = fetchFavicon(faviconUrl);
if (!image.isNull()) {
addCustomIcon(image);
} else if (!m_urlsToTry.empty()) {
m_redirects = 0;
startFetchFavicon(m_urlsToTry.takeFirst());
return;
} else {
if (!googleFallbackEnabled) {
emit messageEditEntry(tr("Unable to fetch favicon.") + "\n" +
tr("Hint: You can enable Google as a fallback under Tools>Settings>Security"),
MessageWidget::Error);
} else {
emit messageEditEntry(tr("Unable to fetch favicon."), MessageWidget::Error);
}
} else {
emit messageEditEntry(tr("Unable to fetch favicon.") + "\n"
+ tr("Hint: You can enable Google as a fallback under Tools>Settings>Security"),
MessageWidget::Error);
}
m_ui->faviconButton->setDisabled(false);
#endif
}
void EditWidgetIcons::fetchCanceled()
{
#ifdef WITH_XC_NETWORKING
namespace
{
std::size_t writeCurlResponse(char* ptr, std::size_t size, std::size_t nmemb, void* data)
{
QByteArray* response = static_cast<QByteArray*>(data);
std::size_t realsize = size * nmemb;
response->append(ptr, realsize);
return realsize;
}
m_reply->abort();
#endif
}
QImage EditWidgetIcons::fetchFavicon(const QUrl& url)
void EditWidgetIcons::startFetchFavicon(const QUrl& url)
{
QImage image;
CURL* curl = curl_easy_init();
if (curl) {
QByteArray imagedata;
QByteArray baUrl = url.url().toLatin1();
#ifdef WITH_XC_NETWORKING
m_bytesReceived.clear();
curl_easy_setopt(curl, CURLOPT_URL, baUrl.data());
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5L);
curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &imagedata);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &writeCurlResponse);
#ifdef Q_OS_WIN
const QDir appDir = QFileInfo(QCoreApplication::applicationFilePath()).absoluteDir();
if (appDir.exists("ssl\\certs")) {
curl_easy_setopt(
curl, CURLOPT_CAINFO, (appDir.absolutePath() + "\\ssl\\certs\\ca-bundle.crt").toLatin1().data());
}
m_fetchUrl = url;
QNetworkRequest request(url);
m_reply = m_netMgr.get(request);
connect(m_reply, &QNetworkReply::finished, this, &EditWidgetIcons::fetchFinished);
connect(m_reply, &QIODevice::readyRead, this, &EditWidgetIcons::fetchReadyRead);
UrlFetchProgressDialog *progress = new UrlFetchProgressDialog(url, this);
progress->setAttribute(Qt::WA_DeleteOnClose);
connect(m_reply, &QNetworkReply::finished, progress, &QProgressDialog::hide);
connect(m_reply, &QNetworkReply::downloadProgress, progress, &UrlFetchProgressDialog::networkReplyProgress);
connect(progress, &QProgressDialog::canceled, this, &EditWidgetIcons::fetchCanceled);
progress->show();
#else
Q_UNUSED(url);
#endif
// Perform the request in another thread
CURLcode result = AsyncTask::runAndWaitForFuture([curl]() { return curl_easy_perform(curl); });
if (result == CURLE_OK) {
image.loadFromData(imagedata);
}
curl_easy_cleanup(curl);
}
return image;
}
#endif
void EditWidgetIcons::addCustomIconFromFile()
{

View File

@ -20,8 +20,10 @@
#define KEEPASSX_EDITWIDGETICONS_H
#include <QSet>
#include <QProgressDialog>
#include <QUrl>
#include <QWidget>
#include <QNetworkAccessManager>
#include "config-keepassx.h"
#include "core/Global.h"
@ -31,6 +33,9 @@
class Database;
class DefaultIconModel;
class CustomIconModel;
#ifdef WITH_XC_NETWORKING
class QNetworkReply;
#endif
namespace Ui
{
@ -45,6 +50,17 @@ struct IconStruct
int number;
};
class UrlFetchProgressDialog : public QProgressDialog
{
Q_OBJECT
public:
explicit UrlFetchProgressDialog(const QUrl &url, QWidget *parent = nullptr);
public slots:
void networkReplyProgress(qint64 bytesRead, qint64 totalBytes);
};
class EditWidgetIcons : public QWidget
{
Q_OBJECT
@ -67,9 +83,10 @@ signals:
private slots:
void downloadFavicon();
#ifdef WITH_XC_NETWORKING
QImage fetchFavicon(const QUrl& url);
#endif
void startFetchFavicon(const QUrl& url);
void fetchFinished();
void fetchReadyRead();
void fetchCanceled();
void addCustomIconFromFile();
void addCustomIcon(const QImage& icon);
void removeCustomIcon();
@ -82,7 +99,15 @@ private:
const QScopedPointer<Ui::EditWidgetIcons> m_ui;
Database* m_database;
Uuid m_currentUuid;
QString m_url;
#ifdef WITH_XC_NETWORKING
QUrl m_url;
QUrl m_fetchUrl;
QList<QUrl> m_urlsToTry;
QByteArray m_bytesReceived;
QNetworkAccessManager m_netMgr;
QNetworkReply *m_reply;
int m_redirects;
#endif
DefaultIconModel* const m_defaultIconModel;
CustomIconModel* const m_customIconModel;

View File

@ -65,7 +65,7 @@ class BrowserPlugin : public ISettingsPage
public:
BrowserPlugin(DatabaseTabWidget* tabWidget)
{
m_nativeMessagingHost = QSharedPointer<NativeMessagingHost>(new NativeMessagingHost(tabWidget));
m_nativeMessagingHost = QSharedPointer<NativeMessagingHost>(new NativeMessagingHost(tabWidget, BrowserSettings::isEnabled()));
}
~BrowserPlugin()
@ -686,7 +686,7 @@ void MainWindow::closeEvent(QCloseEvent* event)
bool minimizeOnClose = isTrayIconEnabled() && config()->get("GUI/MinimizeOnClose").toBool();
if (minimizeOnClose && !m_appExitCalled) {
event->ignore();
event->accept();
hideWindow();
if (config()->get("security/lockdatabaseminimize").toBool()) {

View File

@ -157,6 +157,7 @@ void SettingsWidget::loadSettings()
}
m_generalUi->autoTypeShortcutWidget->setAttribute(Qt::WA_MacShowFocusRect, true);
m_generalUi->autoTypeDelaySpinBox->setValue(config()->get("AutoTypeDelay").toInt());
m_generalUi->autoTypeStartDelaySpinBox->setValue(config()->get("AutoTypeStartDelay").toInt());
}
m_secUi->clearClipboardCheckBox->setChecked(config()->get("security/clearclipboard").toBool());
@ -223,6 +224,7 @@ void SettingsWidget::saveSettings()
config()->set("GlobalAutoTypeKey", m_generalUi->autoTypeShortcutWidget->key());
config()->set("GlobalAutoTypeModifiers", static_cast<int>(m_generalUi->autoTypeShortcutWidget->modifiers()));
config()->set("AutoTypeDelay", m_generalUi->autoTypeDelaySpinBox->value());
config()->set("AutoTypeStartDelay", m_generalUi->autoTypeStartDelaySpinBox->value());
}
config()->set("security/clearclipboard", m_secUi->clearClipboardCheckBox->isChecked());
config()->set("security/clearclipboardtimeout", m_secUi->clearClipboardSpinBox->value());

View File

@ -26,7 +26,7 @@
<item>
<widget class="QTabWidget" name="generalSettingsTabWidget">
<property name="currentIndex">
<number>0</number>
<number>1</number>
</property>
<widget class="QWidget" name="tabGeneral">
<attribute name="title">
@ -411,7 +411,7 @@
<number>10</number>
</property>
<item row="1" column="0">
<widget class="QLabel" name="autoTypeShortcutLabel_2">
<widget class="QLabel" name="autoTypeShortcutLabel">
<property name="text">
<string>Global Auto-Type shortcut</string>
</property>
@ -427,14 +427,14 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="autoTypeDelayLabel_2">
<item row="3" column="0">
<widget class="QLabel" name="autoTypeDelayLabel">
<property name="text">
<string>Auto-Type delay</string>
<string>Auto-Type typing delay</string>
</property>
</widget>
</item>
<item row="2" column="1">
<item row="3" column="1">
<widget class="QSpinBox" name="autoTypeDelaySpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
@ -449,13 +449,48 @@
<string/>
</property>
<property name="maximum">
<number>999</number>
<number>1000</number>
</property>
<property name="value">
<number>25</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="autoTypeStartDelayLabel">
<property name="text">
<string>Auto-Type start delay</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="autoTypeStartDelaySpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string comment="Milliseconds"> ms</string>
</property>
<property name="prefix">
<string/>
</property>
<property name="minimum">
<number>100</number>
</property>
<property name="maximum">
<number>10000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="value">
<number>500</number>
</property>
</widget>
</item>
</layout>
</item>
<item>

View File

@ -339,7 +339,7 @@ void EditEntryWidget::setupSSHAgent()
connect(m_sshAgentUi->decryptButton, SIGNAL(clicked()), SLOT(decryptPrivateKey()));
connect(m_sshAgentUi->copyToClipboardButton, SIGNAL(clicked()), SLOT(copyPublicKey()));
connect(m_advancedUi->attachmentsWidget->entryAttachments(), SIGNAL(modified()), SLOT(updateAttachments()));
connect(m_advancedUi->attachmentsWidget->entryAttachments(), SIGNAL(modified()), SLOT(updateSSHAgentAttachments()));
addPage(tr("SSH Agent"), FilePath::instance()->icon("apps", "utilities-terminal"), m_sshAgentWidget);
}

View File

@ -185,7 +185,7 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const
return result;
case Notes:
// Display only first line of notes in simplified format
result = entry->resolveMultiplePlaceholders(entry->notes().section("\n", 0, 0).simplified());
result = entry->notes().section("\n", 0, 0).simplified();
if (attr->isReference(EntryAttributes::NotesKey)) {
result.prepend(tr("Ref: ", "Reference abbreviation"));
}

View File

@ -45,6 +45,21 @@ Q_IMPORT_PLUGIN(QXcbIntegrationPlugin)
#endif
#endif
static inline void earlyQNetworkAccessManagerWorkaround()
{
// When QNetworkAccessManager is instantiated it regularly starts polling
// all network interfaces to see if anything changes and if so, what. This
// creates a latency spike every 10 seconds on Mac OS 10.12+ and Windows 7 >=
// when on a wifi connection.
// So here we disable it for lack of better measure.
// This will also cause this message: QObject::startTimer: Timers cannot
// have negative intervals
// For more info see:
// - https://bugreports.qt.io/browse/QTBUG-40332
// - https://bugreports.qt.io/browse/QTBUG-46015
qputenv("QT_BEARER_POLL_TIMEOUT", QByteArray::number(-1));
}
int main(int argc, char** argv)
{
#ifdef QT_NO_DEBUG
@ -52,6 +67,8 @@ int main(int argc, char** argv)
#endif
Tools::setupSearchPaths();
earlyQNetworkAccessManagerWorkaround();
Application app(argc, argv);
Application::setApplicationName("keepassxc");
Application::setApplicationVersion(KEEPASSX_VERSION);

View File

@ -55,4 +55,7 @@ if(WITH_XC_BROWSER)
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src
COMMENT "Changing linking of keepassxc-proxy")
endif()
if(MINGW)
target_link_libraries(keepassxc-proxy Wtsapi32.lib Ws2_32.lib)
endif()
endif()

View File

@ -18,11 +18,21 @@
#include "NativeMessagingHost.h"
#include <QCoreApplication>
NativeMessagingHost::NativeMessagingHost()
: NativeMessagingBase()
#ifdef Q_OS_WIN
#include <Winsock2.h>
#endif
NativeMessagingHost::NativeMessagingHost() : NativeMessagingBase(true)
{
m_localSocket = new QLocalSocket();
m_localSocket->connectToServer(getLocalServerPath());
m_localSocket->setReadBufferSize(NATIVE_MSG_MAX_LENGTH);
int socketDesc = m_localSocket->socketDescriptor();
if (socketDesc) {
int max = NATIVE_MSG_MAX_LENGTH;
setsockopt(socketDesc, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<char*>(&max), sizeof(max));
}
#ifdef Q_OS_WIN
m_running.store(true);
m_future =

View File

@ -317,9 +317,9 @@ bool OpenSSHKey::openPrivateKey(const QString& passphrase)
if (m_cipherName.compare("aes-128-cbc", Qt::CaseInsensitive) == 0) {
cipher.reset(new SymmetricCipher(SymmetricCipher::Aes128, SymmetricCipher::Cbc, SymmetricCipher::Decrypt));
} else if (m_cipherName == "aes256-cbc") {
} else if (m_cipherName == "aes256-cbc" || m_cipherName.compare("aes-256-cbc", Qt::CaseInsensitive) == 0) {
cipher.reset(new SymmetricCipher(SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Decrypt));
} else if (m_cipherName == "aes256-ctr") {
} else if (m_cipherName == "aes256-ctr" || m_cipherName.compare("aes-256-ctr", Qt::CaseInsensitive) == 0) {
cipher.reset(new SymmetricCipher(SymmetricCipher::Aes256, SymmetricCipher::Ctr, SymmetricCipher::Decrypt));
} else if (m_cipherName != "none") {
m_error = tr("Unknown cipher: %1").arg(m_cipherName);
@ -370,10 +370,22 @@ bool OpenSSHKey::openPrivateKey(const QString& passphrase)
return false;
}
QCryptographicHash hash(QCryptographicHash::Md5);
hash.addData(passphrase.toUtf8());
hash.addData(m_cipherIV.data(), 8);
QByteArray keyData = hash.result();
QByteArray keyData;
QByteArray mdBuf;
do {
QCryptographicHash hash(QCryptographicHash::Md5);
hash.addData(mdBuf);
hash.addData(passphrase.toUtf8());
hash.addData(m_cipherIV.data(), 8);
mdBuf = hash.result();
keyData.append(mdBuf);
} while(keyData.size() < cipher->keySize());
if (keyData.size() > cipher->keySize()) {
// If our key size isn't a multiple of 16 (e.g. AES-192 or something),
// then we will need to truncate it.
keyData.resize(cipher->keySize());
}
if (!cipher->init(keyData, m_cipherIV)) {
m_error = cipher->errorString();

View File

@ -86,38 +86,40 @@ void TestOpenSSHKey::testParseDSA()
QCOMPARE(key.fingerprint(), QString("SHA256:tbbNuLN1hja8JNASDTlLOZQsbTlJDzJlz/oAGK3sX18"));
}
void TestOpenSSHKey::testDecryptAES128CBC()
void TestOpenSSHKey::testDecryptRSAAES128CBC()
{
const QString keyString = QString("-----BEGIN RSA PRIVATE KEY-----\n"
"Proc-Type: 4,ENCRYPTED\n"
"DEK-Info: AES-128-CBC,804E4D214D1263FF94E3743FE799DBB4\n"
"\n"
"lM9TDfOTbiRhaGGDh7Hn+rqw8CCWcYBZYu7smyYLdnWKXKPmbne8CQFZBAS1FJwZ\n"
"6Mj6n075yFGyzN9/OfeqKiUA4adlbwLbGwB+yyKsC2FlsvRIEr4hup02WWM47vHj\n"
"DS4TRmNkE7MKFLhpNCyt5OGGM45s+/lwVTw51K0Hm99TBd72IrX4jfY9ZxAVbL3l\n"
"aTohL8x6oOTe7q318QgJoFi+DjJhDWLGLLJ7fBqD2imz2fmrY4j8Jpw2sDe1rj82\n"
"gMqqNG3FrfN0S4uYlWYH5pAh+BUcB1UdmTU/rV5wJMK1oUytmZv/J2+X/0k3Y93F\n"
"aw6JWOy28OizW+TQXvv8gREWsp5PEclqUZhhGQbVbCQCiDOxg+xiXNySdRH1IqjR\n"
"zQiKgD4SPzkxQekExPaIQT/KutWZdMNYybEqooCx8YyeDoN31z7Wa2rv6OulOn/j\n"
"wJFvyd2PT/6brHKI4ky8RYroDf4FbVYKfyEW5CSAg2OyL/tY/kSPgy/k0WT7fDwq\n"
"dPSuYM9yeWNL6kAhDqDOv8+s3xvOVEljktBvQvItQwVLmHszC3E2AcnaxzdblKPu\n"
"e3+mBT80NXHjERK2ht+/9JYseK1ujNbNAaG8SbKfU3FF0VlyJ0QW6TuIEdpNnymT\n"
"0fm0cDfKNaoeJIFnBRZhgIOJAic9DM0cTe/vSG69DaUYsaQPp36al7Fbux3GpFHS\n"
"OtJEySYGro/6zvJ9dDIEfIGZjA3RaMt6+DuyJZXQdT2RNXa9j60xW7dXh0En4n82\n"
"JUKTxYhDPLS5c8BzpJqoopxpKwElmrJ7Y3xpd6z2vIlD8ftuZrkk6siTMNQ2s7MI\n"
"Xl332O+0H4k7uSfczHPOOw36TFhNjGQAP0b7O+0/RVG0ttOIoAn7ZkX3nfdbtG5B\n"
"DWKvDaopvrcC2/scQ5uLUnqnBiGw1XiYpdg5ang7knHNzHZAIekVaYYZigpCAKp+\n"
"OtoaDeUEzqFhYVmF8ad1fgvC9ZUsuxS4XUHCKl0H6CJcvW9MJPVbveqYoK+j9qKd\n"
"iMIkQBP1kE2rzGZVGUkZTpM9LVD9nP0nsbr6E8BatFcNgRirsg2BTJglNpXlCmY6\n"
"ldzJ/ELBbzoXIn+0wTGai0o4eBPx55baef69JfPuZqEB9pLNE+mHstrqIwcfqYu4\n"
"M+Vzun1QshRMj9a1PVkIHfs1fLeebI4QCHO0vJlc9K4iYPM4rsDNO3YaAgGRuARS\n"
"f3McGiGFxkv5zxe8i05ZBnn+exE77jpRKxd223jAMe2wu4WiFB7ZVo4Db6b5Oo2T\n"
"TPh3VuY7TNMEKkcUi+mGLKjroocQ5j8WQYlfnyOaTalUVQDzOTNb67QIIoiszR0U\n"
"+AXGyxHj0QtotZFoPME+AbS9Zqy3SgSOuIzPBPU5zS4uoKNdD5NPE5YAuafCjsDy\n"
"MT4DVy+cPOQYUK022S7T2nsA1btmvUvD5LL2Mc8VuKsWOn/7FKZua6OCfipt6oX0\n"
"1tzYrw0/ALK+CIdVdYIiPPfxGZkr+JSLOOg7u50tpmen9GzxgNTv63miygwUAIDF\n"
"u0GbQwOueoA453/N75FcXOgrbqTdivyadUbRP+l7YJk/SfIytyJMOigejp+Z1lzF\n"
"-----END RSA PRIVATE KEY-----\n");
const QString keyString = QString(
"-----BEGIN RSA PRIVATE KEY-----\n"
"Proc-Type: 4,ENCRYPTED\n"
"DEK-Info: AES-128-CBC,804E4D214D1263FF94E3743FE799DBB4\n"
"\n"
"lM9TDfOTbiRhaGGDh7Hn+rqw8CCWcYBZYu7smyYLdnWKXKPmbne8CQFZBAS1FJwZ\n"
"6Mj6n075yFGyzN9/OfeqKiUA4adlbwLbGwB+yyKsC2FlsvRIEr4hup02WWM47vHj\n"
"DS4TRmNkE7MKFLhpNCyt5OGGM45s+/lwVTw51K0Hm99TBd72IrX4jfY9ZxAVbL3l\n"
"aTohL8x6oOTe7q318QgJoFi+DjJhDWLGLLJ7fBqD2imz2fmrY4j8Jpw2sDe1rj82\n"
"gMqqNG3FrfN0S4uYlWYH5pAh+BUcB1UdmTU/rV5wJMK1oUytmZv/J2+X/0k3Y93F\n"
"aw6JWOy28OizW+TQXvv8gREWsp5PEclqUZhhGQbVbCQCiDOxg+xiXNySdRH1IqjR\n"
"zQiKgD4SPzkxQekExPaIQT/KutWZdMNYybEqooCx8YyeDoN31z7Wa2rv6OulOn/j\n"
"wJFvyd2PT/6brHKI4ky8RYroDf4FbVYKfyEW5CSAg2OyL/tY/kSPgy/k0WT7fDwq\n"
"dPSuYM9yeWNL6kAhDqDOv8+s3xvOVEljktBvQvItQwVLmHszC3E2AcnaxzdblKPu\n"
"e3+mBT80NXHjERK2ht+/9JYseK1ujNbNAaG8SbKfU3FF0VlyJ0QW6TuIEdpNnymT\n"
"0fm0cDfKNaoeJIFnBRZhgIOJAic9DM0cTe/vSG69DaUYsaQPp36al7Fbux3GpFHS\n"
"OtJEySYGro/6zvJ9dDIEfIGZjA3RaMt6+DuyJZXQdT2RNXa9j60xW7dXh0En4n82\n"
"JUKTxYhDPLS5c8BzpJqoopxpKwElmrJ7Y3xpd6z2vIlD8ftuZrkk6siTMNQ2s7MI\n"
"Xl332O+0H4k7uSfczHPOOw36TFhNjGQAP0b7O+0/RVG0ttOIoAn7ZkX3nfdbtG5B\n"
"DWKvDaopvrcC2/scQ5uLUnqnBiGw1XiYpdg5ang7knHNzHZAIekVaYYZigpCAKp+\n"
"OtoaDeUEzqFhYVmF8ad1fgvC9ZUsuxS4XUHCKl0H6CJcvW9MJPVbveqYoK+j9qKd\n"
"iMIkQBP1kE2rzGZVGUkZTpM9LVD9nP0nsbr6E8BatFcNgRirsg2BTJglNpXlCmY6\n"
"ldzJ/ELBbzoXIn+0wTGai0o4eBPx55baef69JfPuZqEB9pLNE+mHstrqIwcfqYu4\n"
"M+Vzun1QshRMj9a1PVkIHfs1fLeebI4QCHO0vJlc9K4iYPM4rsDNO3YaAgGRuARS\n"
"f3McGiGFxkv5zxe8i05ZBnn+exE77jpRKxd223jAMe2wu4WiFB7ZVo4Db6b5Oo2T\n"
"TPh3VuY7TNMEKkcUi+mGLKjroocQ5j8WQYlfnyOaTalUVQDzOTNb67QIIoiszR0U\n"
"+AXGyxHj0QtotZFoPME+AbS9Zqy3SgSOuIzPBPU5zS4uoKNdD5NPE5YAuafCjsDy\n"
"MT4DVy+cPOQYUK022S7T2nsA1btmvUvD5LL2Mc8VuKsWOn/7FKZua6OCfipt6oX0\n"
"1tzYrw0/ALK+CIdVdYIiPPfxGZkr+JSLOOg7u50tpmen9GzxgNTv63miygwUAIDF\n"
"u0GbQwOueoA453/N75FcXOgrbqTdivyadUbRP+l7YJk/SfIytyJMOigejp+Z1lzF\n"
"-----END RSA PRIVATE KEY-----\n"
);
const QByteArray keyData = keyString.toLatin1();
@ -173,7 +175,7 @@ void TestOpenSSHKey::testParseRSA()
QCOMPARE(key.fingerprint(), QString("SHA256:DYdaZciYNxCejr+/8x+OKYxeTU1D5UsuIFUG4PWRFkk"));
}
void TestOpenSSHKey::testDecryptAES256CBC()
void TestOpenSSHKey::testDecryptOpenSSHAES256CBC()
{
const QString keyString = QString("-----BEGIN OPENSSH PRIVATE KEY-----\n"
"b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABD2A0agtd\n"
@ -205,7 +207,55 @@ void TestOpenSSHKey::testDecryptAES256CBC()
QVERIFY(privateKey.length() == 158);
}
void TestOpenSSHKey::testDecryptAES256CTR()
void TestOpenSSHKey::testDecryptRSAAES256CBC()
{
const QString keyString = QString(
"-----BEGIN RSA PRIVATE KEY-----\n"
"Proc-Type: 4,ENCRYPTED\n"
"DEK-Info: AES-256-CBC,D51E3F558B621BD9384627762CBD16AC\n"
"\n"
"b6nr/06Gj8/Nw3ZFMePFyZeuBodExvZZtZPSH3t/2ArcxXOkoqUhLmlcY/JrvnBF\n"
"JHc34wx/6Yng7mqtUMuk2iMemTzOj3JRx8zHUhwPLnjM/tmeOm0wBUb3WB4+rFZW\n"
"s1PaIgeKywKgFK0UkcSRpMuSaxheWmHrtJkBsHTF7Tg3ogPL8Dc+nhQlbe/ZGaQb\n"
"vMdSYcBMaXngS5ZiOafXeY8+l+IMMOZwy5vPTFQGqKHIzOxFhShs1hSExnwOXy69\n"
"wxrA/QftjNEy5ixIeGT7iQfRB04tEVg0DjYphTPmI2ophzFlwJVBjhj2cmmnsMZg\n"
"a2TdT/78KZsw2cA5ieMcU6d7Yz5p5nu5dyTbZonn6qWficdZRJwZnVb5ikPnJYbZ\n"
"1YJRHHND+RWtpanxz7WhStscTCLeI9w9j2gqBJSjKDPgJaoMiA+tyEoakNlPYg+9\n"
"DadJkBGP0g5E9zw0n4niqQ7eCxk7qolmW6Wtn2zL4UyeJKGi9NWFSGW9x/PmAIse\n"
"E2KVodiJMRNa8/qUZcW58ZG2uRnFTsW4BXdmzOy/Zp53TVGWStBVLDcldSD03ItD\n"
"JIWQWDgWp5xyVqPl+8mkW7xDY0GRVSJCyRkctQeGTGysy0BcNjgQQtiA3lPC0rY5\n"
"m2VxrCYU1KuyHsAjs/V8THcW4a1UdPcVBg1QbCh29bMoM6u4MuXVt7rkwxAV9HJa\n"
"VbwPsKy7V6G60KaAFIiOs0wdOzBZBoPGd9vBQOEzATh2FYJruDo2OfzEnhv25RxE\n"
"1q+C/Jds9cWqaNY8kNtUG799XIKkjrC6KvnoV6UA4BkGs2DAcO9rnwtl/hToEoBe\n"
"ZVj72dlTuS6l9rHqKaz2GI0k0SEt/ZoakPHeDRgPNcDvEZWitV8MuD6Mwb47Y88u\n"
"sjBmS5k4sJOtB4bLg/UShcqYfkv2OTsK90qGQtba9vMk04Xh1FuxB4fHa5VoKrsX\n"
"Th/LB34xoYugd16NPmLuawhSo70o4bT70GYpxnb4brGfjWiuthRdegAG9ESSX+M6\n"
"rNKQPnn2GSroIpkoA4k0PaflcE5tpzeIiJdv0h65N3vw6MFnCaWy8sRSy9fMyRim\n"
"U8QZB2jcp+YjUU/eny3scuh0Vqt6g1tfFbI84pCC5bArBirf63MeMtwDU/IVImax\n"
"xzKOzl7k8ropA+rhAJ4Z9X35EmUncBXhf8g39w6nFuSlqjE6rMxCrsrehljQ1Iuz\n"
"bujaJ2PKpf98OejHDKnMDOfBBq0DdeERCYWlCcqWSgrEgHh4vB5dEQAPP5bAkdZj\n"
"m0Dq+gF99yadioxf3/MUZVTa1dHklBJJkXTYVPeyH07Th5j7bGCcVb9Zd2Ao/Dia\n"
"MPWf6xViCC6d0njCLQY2R8mOR5OMVsdlFrsKZMQ/lqjS/WSM6URDkuGb0Cq94TQd\n"
"7DoblcA50FTwYrVXMygWygbjzJxhcoJDHztzwoqLT/ghh+6zRg6R/fY222tHHbhz\n"
"nePf421NILzfxnuW+GOwRCM5+IHE3OBS/PYDGijjRFHU4ky0rRRDE64m9CeFzeBh\n"
"CnFvW6Yx3Hrh5tXBP7kRZ6KjyrPP7tI4ciVSJceSBLRzFmoBr10kRMm+VsUh2xZH\n"
"-----END RSA PRIVATE KEY-----\n"
);
const QByteArray keyData = keyString.toLatin1();
OpenSSHKey key;
QVERIFY(key.parse(keyData));
QVERIFY(key.encrypted());
QCOMPARE(key.cipherName(), QString("AES-256-CBC"));
QVERIFY(!key.openPrivateKey("incorrectpassphrase"));
QVERIFY(key.openPrivateKey("correctpassphrase"));
QCOMPARE(key.type(), QString("ssh-rsa"));
QCOMPARE(key.comment(), QString(""));
QCOMPARE(key.fingerprint(), QString("SHA256:1Hsebt2WWnmc72FERsUOgvaajIGHkrMONxXylcmk87U"));
}
void TestOpenSSHKey::testDecryptOpenSSHAES256CTR()
{
const QString keyString = QString("-----BEGIN OPENSSH PRIVATE KEY-----\n"
"b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABAMhIAypt\n"
@ -236,3 +286,51 @@ void TestOpenSSHKey::testDecryptAES256CTR()
QVERIFY(publicKey.length() == 51);
QVERIFY(privateKey.length() == 158);
}
void TestOpenSSHKey::testDecryptRSAAES256CTR()
{
const QString keyString = QString(
"-----BEGIN RSA PRIVATE KEY-----\n"
"Proc-Type: 4,ENCRYPTED\n"
"DEK-Info: AES-256-CTR,192421854316290DFA8F469A1E8CB9BB\n"
"\n"
"3h7gUWua+jcvhYj1vUusbMdOG9j8SmNWFV5Hfersi8nF4ddsWEQDnMrRuhtIn4tU\n"
"GcLY+SXguim5XXwF8gG1tmvpvFMhudTfX+0cIAX7eAVmqLy2RTA18DWqDwWokVP0\n"
"RJPgRJJSorjMtu2F0YGVVjElW7pHIal7luNk3BDgYUMlgSg0BGOWb+9BkXcEnfc8\n"
"KEwsJw2onoR2eXo6rYnczGaqPhAPu+I+PfUn0J8PFiffWc1KebRntLdRWeNsBS4p\n"
"oxtqByzMYIu/WPSJJ5iFoNdKaWQPiZJB+juwI1wNLEtpzKkhpc7/6mOy87h+0eGV\n"
"fF7javrbHv37eE+k2iZXrcLfvRpiBqt5+uhhCaM8TivBeUho5J38ru/wt/dk+OvY\n"
"tzXboWA4zVnaYmqta1CkXYKOmb5a8TWEwtxmAuE6kCz/n3pPa6gwkwsyGI65IEyX\n"
"ycJsbwUilAzXTcz5bIruGx38Sa9fndAN9llOQMS/hdyNs5W5dO1XZ5gU+ARPce+j\n"
"+A2R8oCUv+2ciEu8z3F++U9aTRmTlD3xeIM0IWUFXKt8Y9fSRC5XoPCbZYNxnV6/\n"
"hn9NPKCb890Faxies3MABOB5IZ0aTPWkx9ntxFhMaXyfkX2YthNO0GzAENPP9Knt\n"
"DYhQePlKQ7sNi8+wzsHNeDxNuL/+Rib2MN3ankDtHIsqFz/Em+rD0+3ya8bLy3pP\n"
"eeUiNpezL+uxI5llq/pikzK4sOgvH1r5YEkMxt9I09grkBwxR7DMBo0vgRE2MLiL\n"
"nlri8TDwArC1+0gE8NspkkClsBOHXuVlGZo5lup2tn5MzERQcLvuFnAby/GnaVXQ\n"
"Hm76teb1wMdL58FrdZsKR6e80E+F6JpTsz0a3XJqptgAwGsoxqizkUNJG5hRP8bi\n"
"NBCFQZPeYi/GxgN5O2UkxhgRkKAcrHg+G87nhLk1ipsc214rb6iOspNizP6fGDuv\n"
"/bsNTpYRgMNxCLh5Nv0HSUqckoNKOcIVe/9nF5/LLFGfhz95agjKTbBygThFK28N\n"
"bnHq5fO9yKCMrGCRBQ6No1wwexyS4IAq17LcQP3k4w4n+Wt2GjO5HIldGOEyGqCE\n"
"zeHYrPpGXF/yf3XTm00XghdQtVtRJptdddXVGZN3EN2w7/ghOSIIlsJO9C4IRgU3\n"
"WkhX7oOpSE4wmXd5Ada+D1U46snW5nWANWko2NmQNVDeJcvuymL6t2ccNYeFWiA+\n"
"Hlv0avBnqng7ZWPxYacqZI3+vU0rN9usN1pzwY/4NsBa34o3M7u6KvzEkyewbyUT\n"
"VfXLJ8XRzb2u4NqQv0WiTBIRxvVB1sRPcrwB4HWKHwRFT8T7f1fefteROrKV7aKm\n"
"Q48pckidDM0ORh1yIET8u24Mreo5eeWXjVJ9MHoM0486VySYxMwk8yp4tnaHx5kd\n"
"fGlBbbwFOifhzjAk0u3KJRAG85t2GZhfTMo1IHS2kdu4Xs1N00ZmK0hjeGG+DCwy\n"
"06ZKHOF5BHWU3SpQEjCsPDwfIpOINWGAJJnp6NIVf7FkHwViV50GWWGSZal4NqZy\n"
"kR19buHiOb7KnGoPCw8MUmIym8v30FePhM4YQ7ASmRtsXlAhQNRX\n"
"-----END RSA PRIVATE KEY-----\n"
);
const QByteArray keyData = keyString.toLatin1();
OpenSSHKey key;
QVERIFY(key.parse(keyData));
QVERIFY(key.encrypted());
QCOMPARE(key.cipherName(), QString("AES-256-CTR"));
QVERIFY(!key.openPrivateKey("incorrectpassphrase"));
QVERIFY(key.openPrivateKey("correctpassphrase"));
QCOMPARE(key.type(), QString("ssh-rsa"));
QCOMPARE(key.comment(), QString(""));
QCOMPARE(key.fingerprint(), QString("SHA256:1Hsebt2WWnmc72FERsUOgvaajIGHkrMONxXylcmk87U"));
}

View File

@ -31,9 +31,11 @@ private slots:
void testParse();
void testParseDSA();
void testParseRSA();
void testDecryptAES128CBC();
void testDecryptAES256CBC();
void testDecryptAES256CTR();
void testDecryptRSAAES128CBC();
void testDecryptOpenSSHAES256CBC();
void testDecryptRSAAES256CBC();
void testDecryptOpenSSHAES256CTR();
void testDecryptRSAAES256CTR();
};
#endif // TESTOPENSSHKEY_H