Compare commits

...

151 Commits

Author SHA1 Message Date
Felix Geyer
43a1d54bba Prepare 2.0 alpha 6 release. 2014-04-12 15:29:20 +02:00
Felix Geyer
2963752585 Disallow global auto-typing when the database is locked. 2014-04-12 15:29:03 +02:00
Florian Geyer
1decdc6c11 Only save geometry when close event is accepted. 2014-03-24 20:03:40 +01:00
Florian Geyer
6659745e2b Rename settings key for window geometry. 2014-03-24 20:03:40 +01:00
Florian Geyer
1e2d1a1b17 Refactor saving of window geometry.
Closes #154
2014-03-24 20:03:40 +01:00
Florian Geyer
f300ca5b7b Remember window size.
Refs #154
2014-03-24 20:03:40 +01:00
Felix Geyer
b9370c6e79 More careful null checking and member initalization. 2014-03-22 12:10:49 +01:00
Florian Geyer
54bb7462f6 Add find action to entries menu.
Closes #122
2014-03-08 11:42:26 +01:00
Florian Geyer
4a08101a60 Remove obsolete ArgumentParser files. 2014-03-08 10:45:40 +01:00
Felix Geyer
809be5f89e Use the correct modifiers after remapping.
Sometimes the keysym is not mapped to the first column (no modifiers)
but to a diffferent column that needs modifiers.
Therefore we need re-read the table and search the whole row for the
correct keysym.
2014-01-19 23:32:00 +01:00
Felix Geyer
bf9a755bea Check all modifiers before declaring the remap keycode invalid.
Sometimes XChangeKeyboardMapping() maps the keysym to a modifier.
2014-01-19 21:40:25 +01:00
Felix Geyer
34b82da9aa Initialize cur_focus before it's used. 2014-01-19 20:09:19 +01:00
Felix Geyer
e0c59395da Merge branch 'AlbertWeichselbraun-bug-116-autotype-single-keycode' 2014-01-19 20:06:12 +01:00
Felix Geyer
b07de47e35 Add transform key benchmark to TestKeys. 2014-01-19 15:26:32 +01:00
Felix Geyer
586de64293 Restore compatibility with old Qt versions. 2014-01-19 10:46:53 +01:00
Felix Geyer
9321943e64 Install mime info package on Linux. 2014-01-18 23:43:44 +01:00
Felix Geyer
c00550078c Add KeePass 2 document icons. 2014-01-18 23:35:34 +01:00
Felix Geyer
2190260a68 Small optimization in SymmetricCipherGcrypt::processInPlace(). 2014-01-18 20:47:45 +01:00
Felix Geyer
678c4a8ece Set the application name and version in QApplication. 2014-01-18 15:31:24 +01:00
Felix Geyer
c2781274a0 Fix include guards of config-keepassx.h. 2014-01-18 15:30:58 +01:00
Felix Geyer
bc14898b13 Replace ArgumentParser with a backport of QCommandLineParser from Qt 5.2. 2014-01-18 15:23:55 +01:00
Felix Geyer
b6497d9245 Coding style fixes. 2014-01-14 21:00:27 +01:00
Felix Geyer
79d827ffa4 Add 22x22 icons for actions that are in the toolbar. 2014-01-14 19:55:38 +01:00
Felix Geyer
811eb2714f Add copy username and password actions to the clipboard.
Also add corresponding icons that I've put together from
various Oxygen icons.
2014-01-14 19:53:42 +01:00
Felix Geyer
a914b837a1 Drop new database action from the toolbar.
It's not a common operation.
2014-01-14 19:40:20 +01:00
Felix Geyer
04c9332a99 Drop superfluous PasswordGeneratorWidget::togglePassword slot. 2014-01-13 21:40:23 +01:00
Felix Geyer
97f374a189 Use monospace font in the password generator combo box. 2014-01-13 21:39:55 +01:00
Felix Geyer
6f3648d63e Uncheck the correct widget in ChangeMasterKeyWidget.
We want to enable the password group but mask the password in the line edit.
2014-01-13 00:24:29 +01:00
Felix Geyer
350cf4b00a Move password generator widget to the right row. 2014-01-13 00:24:29 +01:00
Felix Geyer
3af2307468 Reworked the PasswordGeneratorWidget.
It's loosely based on OS X PasswordAssistant. Generation happens as soon as a
change is made, and on open of the widget. A combobox has been added to allow
one to choose from some randomally-generated alternatives, and the UI is
generally been made a bit more compact.

Written by Michael Curtis <michael@moltenmercury.org> and revised by me.

Closes #119

https://github.com/keepassx/keepassx/pull/38
2014-01-13 00:24:25 +01:00
Felix Geyer
29c997e1bc Add an option to show passwords by default.
Closes #93
2014-01-12 17:23:47 +01:00
Felix Geyer
223c5a1651 Use an icon for the button that shows/masks passwords.
Closes #38

Additionally make use of the new PasswordEdit class where possible.
2014-01-12 17:13:10 +01:00
Felix Geyer
8b437821a2 Add ability to load icons with on/off state. 2014-01-12 17:13:10 +01:00
Felix Geyer
4ded95a060 Add PasswordEdit class.
It displays passwords in monospace which closes #51
2014-01-12 17:13:03 +01:00
Felix Geyer
0b6b149351 Use the libgcrypt SALSA20 cipher if available. 2014-01-12 13:42:56 +01:00
Felix Geyer
eee909e948 Parse the libgcrypt version in the cmake module. 2014-01-12 13:42:19 +01:00
Felix Geyer
8c7e655274 Add compatibility with libgcrypt 1.6.
Closes #129
2014-01-12 12:39:39 +01:00
Felix Geyer
8e86437e89 Disable settings spinboxes by default.
They get enabled when the corresponding checkboxes are checked.
2014-01-07 21:58:49 +01:00
Felix Geyer
a8edad1e27 Add option to lock databases after user inactivity.
Closes #62
2014-01-07 21:57:38 +01:00
Felix Geyer
41162ea2e8 Only try to click the focused button when pressing enter.
It makes no sense when pressing the escape button.
2014-01-02 10:51:51 +01:00
Felix Geyer
0cbf59209b Prepare the next alpha release. 2013-12-20 12:41:45 +01:00
Albert Weichselbraun
0f91e0d141 Better naming & actually save m_currentRemapKeysym. 2013-12-16 09:41:43 +01:00
Albert Weichselbraun
6a50a76466 Track the last remapped keysym in m_currentRemapKeycode to enforce
a new computation of m_remapKeycode when the keyboard layout
changes.
(This fixes a potential problem with AddKeysym overwriting
 used keysyms after applying a new keyboard layout).
2013-12-16 09:28:16 +01:00
Felix Geyer
1fce1ac905 Remove wrong check in TestGui.
When the window is not wide enough some actions are hidden.
2013-12-08 16:11:49 +01:00
Felix Geyer
b9a955c048 Add some more actions to the toolbar. 2013-12-05 22:14:01 +01:00
Felix Geyer
5a577e5e4c Document license of document-encrypt.png. 2013-12-05 22:12:13 +01:00
Felix Geyer
f648172625 Rename EntryAttributes::URLNameKey to URLKey. 2013-12-02 00:10:47 +01:00
Florian Geyer
4b41dd30e6 Merge branch 'attributes'. 2013-12-02 00:01:20 +01:00
Felix Geyer
2a416d1f1d Make sure the remapping keycode is reset to NoSymbol.
Previously the dtor of AutoTypePlatformX11 wasn't called.
2013-12-01 23:32:53 +01:00
Felix Geyer
23f338b0c3 Add some error handling in case we can't remap a key. 2013-12-01 19:14:07 +01:00
Felix Geyer
cdcea91b50 Use nanosleep() instead of the deprecated usleep(). 2013-12-01 19:09:20 +01:00
Felix Geyer
4549c97e51 Merge branch 'bug-116-autotype-single-keycode' of github.com:AlbertWeichselbraun/keepassx
https://github.com/keepassx/keepassx/pull/32

Closes #116
2013-12-01 18:40:31 +01:00
Florian Geyer
fc3cc12038 Optimize deletion of copy to clipboard actions. 2013-12-01 15:58:19 +01:00
Albert Weichselbraun
62ea117f45 Significantly reduce the number of re-mappings required by
a) dynamically fetching the modifier masks for Mod1 to Mod5 (Alt, AltGr, Meta,
    etc.)

 b) integrating commit bfec222 from Felix Geyer <debfx@fobos.de> which creates a
    unicode -> x11 keysym mapping table by parsing keysymdefs.h.

    This avoids adding new keysyms because keyboard layouts seem to prefer the
    lower keysyms over unicode | 0x01000000 mapping.
    An example of this is the euro sign with a German keyboard layout.
2013-12-01 15:34:27 +01:00
Felix Geyer
3d8ff5b585 Hide auto-type settings when the plugin is not available.
Closes #121
2013-12-01 12:20:05 +01:00
Florian Geyer
a3b95c1c38 Remove unnecessary removeAction call in MainWindow. 2013-12-01 10:36:50 +01:00
Florian Geyer
2308099260 Small refactoring in DatabaseWidget. 2013-12-01 09:59:43 +01:00
Florian Geyer
4a3da3abe7 Hard code copy action for default attributes. 2013-12-01 09:43:41 +01:00
Florian Geyer
3e4811791a Delete actions after removal from menu. 2013-11-30 16:19:48 +01:00
Florian Geyer
34f12ac39c Remove duplicate menu entries to copy username and password. 2013-11-30 16:05:10 +01:00
Felix Geyer
af98c2636c Fix compatibility with Qt < 4.7. 2013-11-30 13:47:39 +01:00
Felix Geyer
f21b331844 Drop OS specific instructions from INSTALL file.
Moved to https://www.keepassx.org/dev/projects/keepassx/wiki/Install_instructions
2013-11-30 12:50:24 +01:00
Felix Geyer
ea628af580 Merge branch 'staging' 2013-11-30 12:15:16 +01:00
Veeti Paananen
9cae8a412a Save password generator settings
Remember the used values for the password generator and restore them the
next time the user opens the generation dialog.
2013-11-30 11:27:39 +01:00
Felix Geyer
47b7befd2f Set default build type to RelWithDebInfo. 2013-11-24 22:09:52 +01:00
Felix Geyer
2fcc369c41 Enable the foritfy source build flag only for optimized builds.
https://github.com/keepassx/keepassx/pull/27
2013-11-24 21:40:19 +01:00
Ben Boeckel
66b3d22041 Use QString::toLatin1() rather than ::toAscii()
The toAscii (and fromAscii) are removed from Qt5 in favor of Latin1.
2013-11-24 21:19:20 +01:00
Felix Geyer
03e4b2d13c Merge branch 'master' of github.com:nohn/keepassx into master
https://github.com/keepassx/keepassx/pull/29
2013-11-24 21:11:15 +01:00
Albert Weichselbraun
c83579ecdb Merge commit '755241df5c' into bug-116-autotype-single-keycode 2013-11-23 09:37:09 +01:00
Albert Weichselbraun
a26119ea20 Use a dedicated keycode for keys that require another modifier than shift. 2013-11-23 09:07:16 +01:00
Felix Geyer
98c821df05 Add Group::exportToDb(). 2013-11-22 13:36:46 +01:00
Felix Geyer
a992c76d6a Allow passing entry cloning flags to Group::clone(). 2013-11-22 13:34:34 +01:00
Felix Geyer
f2dfef8c41 Add flags to Entry::clone() for customized cloning. 2013-11-22 13:32:13 +01:00
Felix Geyer
cb804eb143 Document clone() methods. 2013-11-22 10:30:50 +01:00
Felix Geyer
74e912ccd3 Remember the dir when opening/saving attachments. 2013-11-22 10:30:50 +01:00
Felix Geyer
1f47033835 Make sure icon() and iconPixmap() never crash. 2013-11-22 10:30:50 +01:00
Albert Weichselbraun
3fcfc348ed Cleanup: use break rather than nested if/else constructs. 2013-11-18 06:17:56 +01:00
Albert Weichselbraun
6b33298a6e Merge branch 'bug-116-autotype-new' into bug-116-autotype 2013-11-17 21:10:29 +01:00
Albert Weichselbraun
68e1fc0cd0 Use XKeysymToKeycode together with XkbTranslateKeyCode for translating KeySyms to the corresponding keycode and modifier sequences. 2013-11-17 21:08:55 +01:00
Sebastian Nohn
31796d33fb ignore build dir 2013-11-17 13:38:42 +01:00
Felix Geyer
755241df5c Focus entryView when pressing enter in the search field. 2013-11-17 10:55:58 +01:00
Felix Geyer
9080864167 Fix tab focus order in ui files. 2013-11-17 10:15:50 +01:00
Albert Weichselbraun
d25e883983 Fixed bug #116 - certain characters not working with de keyboard layout 2013-11-17 07:48:25 +01:00
Felix Geyer
091e87aeb3 EditEntryWidget: move the URL field beneath the password. 2013-11-16 22:30:39 +01:00
Charles Brunet
4a870f61f1 Added option to minimize window when copying data to clipboard
https://github.com/keepassx/keepassx/pull/24
2013-10-29 20:54:56 +01:00
Felix Geyer
5daf0853c9 Coding style fixes. 2013-10-13 18:08:50 +02:00
Felix Geyer
ef3d7b7772 Merge branch 'modulo-bias'
https://github.com/keepassx/keepassx/pull/21
2013-10-12 19:12:51 +02:00
Felix Geyer
7dde8a771f Use QUINT32_MAX in tests instead of hardcoding the number. 2013-10-12 19:11:57 +02:00
Felix Geyer
3dd4681e69 Fix EntryView not emitting activated() signals on return key press.
AutoTypeSelectDialog relies on this behavior.
2013-10-10 22:47:32 +02:00
Felix Geyer
98d888063b Add tests for Random::randomUInt() and randomUIntRange(). 2013-10-09 23:11:18 +02:00
Felix Geyer
9c788a6e84 Support custom backends in Random.
Useful for tests.
2013-10-09 22:06:32 +02:00
Felix Geyer
e087baeb48 Avoid modulo bias in Random::randomUInt(). 2013-10-09 21:59:24 +02:00
Felix Geyer
b64276c4e8 Make use of the TestGui::clickIndex() helper function. 2013-10-08 22:40:47 +02:00
Felix Geyer
f7dd63a126 Add gui tests for deleting entries from the recycle bin. 2013-10-08 22:36:27 +02:00
Felix Geyer
a68a86f19b Test that the delete action moves entries to the recycle bin. 2013-10-08 22:14:02 +02:00
Felix Geyer
984b23de70 Add tests for the multi-entry delete feature. 2013-10-08 22:11:40 +02:00
Felix Geyer
d5b70b1bef Add a QMessageBox wrapper class to help gui tests.
QMessageBox displays modal dialogs which blocks the gui tests.
To work around this we add a MessageBox wrapper class where
the tests can set the answer for the next dialog.
The answer is then returned without actually showing the dialog.
2013-10-08 22:09:20 +02:00
Felix Geyer
551637f0c2 Allow removing multiple entries. 2013-10-08 21:36:01 +02:00
Felix Geyer
8778df5789 Drop entries from search results when moved to the recycle bin. 2013-10-08 21:13:20 +02:00
Felix Geyer
67338aac7b Avoid using QApplication in core. 2013-10-08 17:37:12 +02:00
Felix Geyer
626351c5da Add several private header files to CMakeLists.txt. 2013-10-03 16:26:01 +02:00
Felix Geyer
6504b6f2bd Drop Qt module name from include statements.
This is a preparation to be able to build KeePassX against Qt 5.
2013-10-03 15:18:16 +02:00
Jens Dieskau
035271d469 Only edit entries on doubleclick (not single) or with enter key.
https://github.com/keepassx/keepassx/pull/19
2013-09-29 17:35:34 +02:00
Felix Geyer
5c84aa308d Improve error messages for reading and wriiting databases.
Closes #7
2013-06-30 14:43:02 +02:00
Felix Geyer
e1c82a4453 Print a cmake feature log.
This let's users know when the dependnecies for auto-type are missing.
Available only in cmake >= 2.8.3.

Closes #71
2013-06-30 14:07:25 +02:00
Felix Geyer
db6ac26794 Initialize variables to silence compiler warnings. 2013-05-01 12:03:03 +02:00
Felix Geyer
a505d85792 Fix compatbility with clang 3.2.
Pass --param=ssp-buffer-size=4 to clang instead of
-mllvm -stack-protector-buffer-size=4 which clang 3.2 doesn't seem
to support anymore.
2013-04-30 18:38:44 +02:00
Felix Geyer
6df30df992 Really fix parsing when the db contains two Root (Group) elements. 2013-04-30 17:04:54 +02:00
Felix Geyer
0ec29b2354 Raise error if we don't find exactly one root group. 2013-04-29 22:31:50 +02:00
Felix Geyer
f1bebe904a Add tests for broken databases.
Make sure we detect the error and don't crash.
2013-04-29 22:31:50 +02:00
Felix Geyer
e16720d06d When parsing make sure that databases contain at least the root group. 2013-04-29 22:31:50 +02:00
Felix Geyer
3be7fa6b3b Raise error when required xml elements are missing. 2013-04-29 22:31:50 +02:00
Felix Geyer
e99e3ae6ca Initalize SymmetricCipherGcrypt::m_blockSize. 2013-04-29 22:31:50 +02:00
Felix Geyer
d182586557 Make sure KeePass1Reader::key() isn't used before the variables are set. 2013-04-29 22:31:50 +02:00
Felix Geyer
1f5564760f Make sure groupId and groupLevel are set in KeePass1Reader::readGroup(). 2013-04-29 22:31:50 +02:00
Felix Geyer
2be045eb8f Initalize m_database in EditGroupWidget ctor. 2013-04-29 22:31:50 +02:00
Felix Geyer
7a89510916 Make more key/value-type functions safe against reordered xml elements. 2013-04-29 22:31:50 +02:00
Felix Geyer
5588792344 Make KeePass2XmlReader::parseGroup() safe against reordered xml elements. 2013-04-29 22:31:50 +02:00
Felix Geyer
3acb33e05a Make KeePass2XmlReader::parseEntry() safe against reordered xml elements. 2013-04-29 22:31:50 +02:00
Felix Geyer
61ee763515 Add Entry::copyDataFrom(). 2013-04-29 22:31:49 +02:00
Felix Geyer
3658a65380 Use Q_NULLPTR instead of 0. 2013-04-29 22:31:49 +02:00
Felix Geyer
fd18bc0330 Use standard GNU install dirs and make them overridable. 2013-04-29 22:17:31 +02:00
Florian Geyer
b499a6df77 Fix coding style. 2013-04-27 11:40:10 +02:00
Florian Geyer
cabec57631 Make argument keys immutable. 2013-04-27 11:40:10 +02:00
Florian Geyer
63f7a0685f Small ArgumentParser refactoring. 2013-04-27 11:40:10 +02:00
Florian Geyer
94e6d3f89b Fix coding style. 2013-04-27 11:23:51 +02:00
Florian Geyer
94ac9c9ea1 Rename config key for last opened databases. 2013-04-27 11:22:38 +02:00
Florian Geyer
bbf183bef7 Add settings option to control if previous databases are opened on startup.
Closes #36
2013-04-18 22:42:22 +02:00
Florian Geyer
6f92188323 Open last used databases on startup.
Refs #36
2013-04-18 22:37:04 +02:00
Florian Geyer
f0985ff9d9 Remember opened databases on quit.
Refs #36
2013-04-18 21:52:08 +02:00
Florian Geyer
ba3baf3595 Open EditEntryWidget when empty url column is activated. 2013-04-14 19:14:06 +02:00
Florian Geyer
34c6b416b0 Add enum for EntryModel column. 2013-04-07 22:17:32 +02:00
Florian Geyer
bf906a7867 Open url when an entry is activated via its url column.
Closes #55
2013-04-07 22:17:32 +02:00
Felix Geyer
5786e2620a Add unit test for Metadata::copyCustomIcons(). 2013-04-07 19:38:18 +02:00
Felix Geyer
fe42861bed Add safety check so we don't insert empty icons. 2013-04-07 19:37:44 +02:00
Felix Geyer
5a96e19ce9 Copy custom icons when copying/moving entries/groups to another database. 2013-04-07 18:32:43 +02:00
Felix Geyer
8ed0379136 Enable the frame for QLineEdits in EditWidgetProperties. 2013-04-07 12:49:05 +02:00
Felix Geyer
4e2f5b1a5b Return true from dropMimeData() when IgnoreAction is passed. 2013-04-07 12:43:20 +02:00
Felix Geyer
317f603262 Support copying entries and groups using drag'n'drop.
Closes #74
2013-04-07 12:43:19 +02:00
Felix Geyer
701013baab Turn two for loops into Q_FOREACH. 2013-04-07 12:43:13 +02:00
Felix Geyer
4b3bee6400 Add extra checks so we never return empty QMimeData from mimeData(). 2013-04-07 11:50:42 +02:00
Felix Geyer
91868969ca Make sure we don't add entries/groups multiple times to the drag'n'drop data. 2013-04-07 11:47:50 +02:00
Tobias Tangemann
ef46b3e8ad Disable menu icons for osx.
https://gitorious.org/keepassx/keepassx/merge_requests/23
2013-04-06 18:02:43 +02:00
Felix Geyer
9e87230102 Use -fvisibility-inlines-hidden only for C++ files.
gcc emits a warning that the flag cannot be used for C.
2013-04-06 17:45:05 +02:00
Florian Geyer
2558e6db79 First draft of an argument parser.
Possibility to set custom config path.
2013-04-06 11:00:45 +02:00
Felix Geyer
bee570c3cf Add Group::clone().
Move all the data we want to clone into a GroupData struct.
2013-04-04 21:48:55 +02:00
Felix Geyer
be288d26ca Change Entry::clone() to set a random uuid. 2013-04-04 21:25:11 +02:00
Felix Geyer
b055780984 Add and install a desktop file. 2013-04-04 21:18:14 +02:00
Felix Geyer
e805a6ff82 Coding style fix. 2013-03-30 17:27:28 +01:00
Felix Geyer
60335452a4 Add compiler flags to hide all symbols by default. 2013-03-30 00:14:32 +01:00
Felix Geyer
3a822c24e2 Add some more header files to CMakeLists.txt.
This makes them show up in the Qt Creator project.
2013-03-29 23:36:07 +01:00
254 changed files with 6285 additions and 1509 deletions

1
.gitignore vendored
View File

@@ -1 +1,2 @@
CMakeLists.txt.* CMakeLists.txt.*
build/

View File

@@ -1,3 +1,29 @@
2.0 Alpha 6 (2014-04-06)
=========================
- Add option to lock databases after user inactivity [#62]
- Add compatibility with libgcrypt 1.6 [#129]
- Display passwords in monospace font [#51]
- Use an icon for the button that shows/masks passwords [#38]
- Add an option to show passwords by default [#93]
- Improve password generator design [#122]
- On Linux link .kdbx files with KeePassX
- Remember window size [#154]
- Disallow global auto-typing when the database is locked
2.0 Alpha 5 (2013-12-20)
=========================
- Support copying entries and groups using drag'n'drop [#74]
- Open last used databases on startup [#36]
- Made the kdbx file parser more robust
- Only edit entries on doubleclick (not single) or with enter key
- Allow removing multiple entries
- Added option to minimize window when copying data to clipboard
- Save password generator settings
- Fixed auto-type producing wrong chars in some keyboard configurations [#116]
- Added some more actions to the toolbar
2.0 Alpha 4 (2013-03-29) 2.0 Alpha 4 (2013-03-29)
========================= =========================
@@ -29,7 +55,6 @@
- Sortable entry view - Sortable entry view
- Support building Mac OS X bundles - Support building Mac OS X bundles
2.0 Alpha 1 (2012-05-07) 2.0 Alpha 1 (2012-05-07)
========================= =========================

View File

@@ -13,6 +13,12 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo Debug Debugfull Profile MinSizeRel."
FORCE)
endif()
project(KeePassX) project(KeePassX)
cmake_minimum_required(VERSION 2.6.4) cmake_minimum_required(VERSION 2.6.4)
@@ -28,8 +34,8 @@ option(WITH_GUI_TESTS "Enable building of GUI tests" OFF)
option(WITH_LTO "Enable Link Time Optimization (LTO)" OFF) option(WITH_LTO "Enable Link Time Optimization (LTO)" OFF)
option(WITH_CXX11 "Build with the C++ 11 standard" OFF) option(WITH_CXX11 "Build with the C++ 11 standard" OFF)
set(KEEPASSX_VERSION "2.0 alpha 4") set(KEEPASSX_VERSION "2.0 alpha 6")
set(KEEPASSX_VERSION_NUM "1.9.83") set(KEEPASSX_VERSION_NUM "1.9.85")
if("${CMAKE_C_COMPILER}" MATCHES "clang$" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") if("${CMAKE_C_COMPILER}" MATCHES "clang$" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_COMPILER_IS_CLANG 1) set(CMAKE_COMPILER_IS_CLANG 1)
@@ -58,14 +64,21 @@ endmacro(add_gcc_compiler_flags)
add_definitions(-DQT_NO_KEYWORDS -DQT_NO_EXCEPTIONS -DQT_NO_STL -DQT_STRICT_ITERATORS -DQT_NO_CAST_TO_ASCII) add_definitions(-DQT_NO_KEYWORDS -DQT_NO_EXCEPTIONS -DQT_NO_STL -DQT_STRICT_ITERATORS -DQT_NO_CAST_TO_ASCII)
add_gcc_compiler_flags("-fno-common -fstack-protector -D_FORTIFY_SOURCE=2") add_gcc_compiler_flags("-fno-common -fstack-protector --param=ssp-buffer-size=4")
add_gcc_compiler_flags("-Wall -Wextra -Wundef -Wpointer-arith -Wno-long-long") add_gcc_compiler_flags("-Wall -Wextra -Wundef -Wpointer-arith -Wno-long-long")
add_gcc_compiler_flags("-Wformat=2 -Wmissing-format-attribute") add_gcc_compiler_flags("-Wformat=2 -Wmissing-format-attribute")
add_gcc_compiler_flags("-fvisibility=hidden")
add_gcc_compiler_cxxflags("-fvisibility-inlines-hidden")
add_gcc_compiler_cxxflags("-fno-exceptions -fno-rtti") add_gcc_compiler_cxxflags("-fno-exceptions -fno-rtti")
add_gcc_compiler_cxxflags("-Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual") add_gcc_compiler_cxxflags("-Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual")
add_gcc_compiler_cflags("-Wchar-subscripts -Wwrite-strings") add_gcc_compiler_cflags("-Wchar-subscripts -Wwrite-strings")
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
if (CMAKE_BUILD_TYPE_LOWER MATCHES (release|relwithdebinfo|minsizerel))
add_gcc_compiler_flags("-D_FORTIFY_SOURCE=2")
endif()
check_c_compiler_flag("-Werror=format-security -Werror=implicit-function-declaration" WERROR_C_AVAILABLE) check_c_compiler_flag("-Werror=format-security -Werror=implicit-function-declaration" WERROR_C_AVAILABLE)
check_cxx_compiler_flag("-Werror=format-security" WERROR_CXX_AVAILABLE) check_cxx_compiler_flag("-Werror=format-security" WERROR_CXX_AVAILABLE)
if(WERROR_C_AVAILABLE AND WERROR_CXX_AVAILABLE) if(WERROR_C_AVAILABLE AND WERROR_CXX_AVAILABLE)
@@ -73,16 +86,12 @@ if(WERROR_C_AVAILABLE AND WERROR_CXX_AVAILABLE)
add_gcc_compiler_cflags("-Werror=implicit-function-declaration") add_gcc_compiler_cflags("-Werror=implicit-function-declaration")
endif() endif()
if(CMAKE_COMPILER_IS_CLANGXX) if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mllvm -stack-protector-buffer-size=4") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wcast-align")
elseif(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wcast-align --param=ssp-buffer-size=4")
endif() endif()
if(CMAKE_COMPILER_IS_CLANG) if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mllvm -stack-protector-buffer-size=4") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wcast-align")
elseif(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wcast-align --param=ssp-buffer-size=4")
endif() endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Linux") if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
@@ -138,9 +147,11 @@ elseif(APPLE)
set(PLUGIN_INSTALL_DIR ".") set(PLUGIN_INSTALL_DIR ".")
set(DATA_INSTALL_DIR "${PROGNAME}.app/Contents/Resources") set(DATA_INSTALL_DIR "${PROGNAME}.app/Contents/Resources")
else() else()
set(BIN_INSTALL_DIR "bin") include(GNUInstallDirs)
set(PLUGIN_INSTALL_DIR "lib/keepassx")
set(DATA_INSTALL_DIR "share/keepassx") set(BIN_INSTALL_DIR "${CMAKE_INSTALL_BINDIR}")
set(PLUGIN_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/keepassx")
set(DATA_INSTALL_DIR "${CMAKE_INSTALL_DATAROOTDIR}/keepassx")
endif() endif()
if(WITH_TESTS) if(WITH_TESTS)
@@ -153,16 +164,13 @@ if(UNIX AND NOT APPLE)
endif() endif()
find_package(Qt4 4.6.0 REQUIRED ${QT_REQUIRED_MODULES}) find_package(Qt4 4.6.0 REQUIRED ${QT_REQUIRED_MODULES})
add_definitions(${QT_DEFINITIONS} -DQT_CORE_LIB -DQT_GUI_LIB) include(${QT_USE_FILE})
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_DEBUG QT_DEBUG)
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_RELEASE QT_NO_DEBUG)
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_RELWITHDEBINFO QT_NO_DEBUG)
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_MINSIZEREL QT_NO_DEBUG)
if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS QT_NO_DEBUG)
endif()
find_package(Gcrypt REQUIRED) find_package(Gcrypt REQUIRED)
if(NOT (${GCRYPT_VERSION_STRING} VERSION_LESS "1.6.0"))
message(STATUS "Gcrypt ${GCRYPT_VERSION_STRING} supports the SALSA20 cipher")
set(GCRYPT_HAS_SALSA20 1)
endif()
find_package(ZLIB REQUIRED) find_package(ZLIB REQUIRED)
@@ -201,7 +209,12 @@ if(UNIX)
endif() endif()
endif() endif()
include_directories(SYSTEM ${QT_INCLUDE_DIR} ${GCRYPT_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}) include_directories(SYSTEM ${GCRYPT_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR})
if(NOT (${CMAKE_VERSION} VERSION_LESS 2.8.3))
set(PRINT_SUMMARY ON)
include(FeatureSummary)
endif()
add_subdirectory(src) add_subdirectory(src)
add_subdirectory(share) add_subdirectory(share)
@@ -209,3 +222,7 @@ add_subdirectory(utils)
if(WITH_TESTS) if(WITH_TESTS)
add_subdirectory(tests) add_subdirectory(tests)
endif(WITH_TESTS) endif(WITH_TESTS)
if(PRINT_SUMMARY)
feature_summary(WHAT ALL)
endif()

11
COPYING
View File

@@ -25,8 +25,15 @@ Copyright: 2010-2012, Felix Geyer <debfx@fobos.de>
2012, Intel Corporation 2012, Intel Corporation
2012, Nokia Corporation and/or its subsidiary(-ies) 2012, Nokia Corporation and/or its subsidiary(-ies)
2000-2008, Tom Sato <VEF00200@nifty.ne.jp> 2000-2008, Tom Sato <VEF00200@nifty.ne.jp>
2013, Laszlo Papp <lpapp@kde.org>
2013, David Faure <faure@kde.org>
License: GPL-2 or GPL-3 License: GPL-2 or GPL-3
Files: cmake/GNUInstallDirs.cmake
Copyright: 2011 Nikita Krupen'ko <krnekit@gmail.com>
2011 Kitware, Inc.
License: BSD-3-clause
Files: share/icons/application/*/apps/keepassx.png Files: share/icons/application/*/apps/keepassx.png
share/icons/application/scalable/apps/keepassx.svgz share/icons/application/scalable/apps/keepassx.svgz
Copyright: 2006, Otto Salminen Copyright: 2006, Otto Salminen
@@ -122,16 +129,20 @@ Files: share/icons/application/*/actions/application-exit.png
share/icons/application/*/actions/dialog-ok.png share/icons/application/*/actions/dialog-ok.png
share/icons/application/*/actions/document-close.png share/icons/application/*/actions/document-close.png
share/icons/application/*/actions/document-edit.png share/icons/application/*/actions/document-edit.png
share/icons/application/*/actions/document-encrypt.png
share/icons/application/*/actions/document-new.png share/icons/application/*/actions/document-new.png
share/icons/application/*/actions/document-open.png share/icons/application/*/actions/document-open.png
share/icons/application/*/actions/document-save.png share/icons/application/*/actions/document-save.png
share/icons/application/*/actions/document-save-as.png share/icons/application/*/actions/document-save-as.png
share/icons/application/*/actions/edit-clear-locationbar-ltr.png share/icons/application/*/actions/edit-clear-locationbar-ltr.png
share/icons/application/*/actions/edit-clear-locationbar-rtl.png share/icons/application/*/actions/edit-clear-locationbar-rtl.png
share/icons/application/*/actions/password-copy.png
share/icons/application/*/actions/password-show-*.png
share/icons/application/*/actions/system-search.png share/icons/application/*/actions/system-search.png
share/icons/application/*/status/dialog-error.png share/icons/application/*/status/dialog-error.png
share/icons/application/*/status/dialog-information.png share/icons/application/*/status/dialog-information.png
share/icons/application/*/status/dialog-warning.png share/icons/application/*/status/dialog-warning.png
share/icons/application/*/status/username-copy.png
share/icons/svg/*.svgz share/icons/svg/*.svgz
Copyright: 2007, Nuno Pinheiro <nuno@oxygen-icons.org> Copyright: 2007, Nuno Pinheiro <nuno@oxygen-icons.org>
2007, David Vignoni <david@icon-king.com> 2007, David Vignoni <david@icon-king.com>

14
INSTALL
View File

@@ -16,15 +16,13 @@ Installing:
=========== ===========
make install [DESTDIR=X] make install [DESTDIR=X]
Create a bundle on Mac:
make package
Run tests: Run tests:
========== ==========
make test [CTEST_OUTPUT_ON_FAILURE=1] [ARGS+=-jX] [ARGS+="-E testgui"] make test [CTEST_OUTPUT_ON_FAILURE=1] [ARGS+=-jX] [ARGS+="-E testgui"]
Building on Mac OS X: OS specific instructions:
===================== =========================
Install macports and cmake https://www.keepassx.org/dev/projects/keepassx/wiki/Install_instructions
Open /opt/local/etc/macports/macports.conf and set the architecture(s) you want to build for.
Run: sudo port install qt4-mac libgcrypt zlib
If you want to build a universal binary append " +universal" to the above command.
Pass -DCMAKE_OSX_ARCHITECTURES="<ARCH1>;<ARCH2>" to cmake
Run: make package

View File

@@ -17,7 +17,15 @@ find_path(GCRYPT_INCLUDE_DIR gcrypt.h)
find_library(GCRYPT_LIBRARIES gcrypt) find_library(GCRYPT_LIBRARIES gcrypt)
mark_as_advanced(GCRYPT_LIBRARIES GCRYPT_INCLUDE_DIR)
if(GCRYPT_INCLUDE_DIR AND EXISTS "${GCRYPT_INCLUDE_DIR}/gcrypt.h")
file(STRINGS "${GCRYPT_INCLUDE_DIR}/gcrypt.h" GCRYPT_H REGEX "^#define GCRYPT_VERSION \"[^\"]*\"$")
string(REGEX REPLACE "^.*GCRYPT_VERSION \"([0-9]+).*$" "\\1" GCRYPT_VERSION_MAJOR "${GCRYPT_H}")
string(REGEX REPLACE "^.*GCRYPT_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" GCRYPT_VERSION_MINOR "${GCRYPT_H}")
string(REGEX REPLACE "^.*GCRYPT_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" GCRYPT_VERSION_PATCH "${GCRYPT_H}")
set(GCRYPT_VERSION_STRING "${GCRYPT_VERSION_MAJOR}.${GCRYPT_VERSION_MINOR}.${GCRYPT_VERSION_PATCH}")
endif()
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Gcrypt DEFAULT_MSG GCRYPT_LIBRARIES GCRYPT_INCLUDE_DIR) find_package_handle_standard_args(Gcrypt DEFAULT_MSG GCRYPT_LIBRARIES GCRYPT_INCLUDE_DIR)
mark_as_advanced(GCRYPT_LIBRARIES GCRYPT_INCLUDE_DIR)

188
cmake/GNUInstallDirs.cmake Normal file
View File

@@ -0,0 +1,188 @@
# - Define GNU standard installation directories
# Provides install directory variables as defined for GNU software:
# http://www.gnu.org/prep/standards/html_node/Directory-Variables.html
# Inclusion of this module defines the following variables:
# CMAKE_INSTALL_<dir> - destination for files of a given type
# CMAKE_INSTALL_FULL_<dir> - corresponding absolute path
# where <dir> is one of:
# BINDIR - user executables (bin)
# SBINDIR - system admin executables (sbin)
# LIBEXECDIR - program executables (libexec)
# SYSCONFDIR - read-only single-machine data (etc)
# SHAREDSTATEDIR - modifiable architecture-independent data (com)
# LOCALSTATEDIR - modifiable single-machine data (var)
# LIBDIR - object code libraries (lib or lib64 or lib/<multiarch-tuple> on Debian)
# INCLUDEDIR - C header files (include)
# OLDINCLUDEDIR - C header files for non-gcc (/usr/include)
# DATAROOTDIR - read-only architecture-independent data root (share)
# DATADIR - read-only architecture-independent data (DATAROOTDIR)
# INFODIR - info documentation (DATAROOTDIR/info)
# LOCALEDIR - locale-dependent data (DATAROOTDIR/locale)
# MANDIR - man documentation (DATAROOTDIR/man)
# DOCDIR - documentation root (DATAROOTDIR/doc/PROJECT_NAME)
# Each CMAKE_INSTALL_<dir> value may be passed to the DESTINATION options of
# install() commands for the corresponding file type. If the includer does
# not define a value the above-shown default will be used and the value will
# appear in the cache for editing by the user.
# Each CMAKE_INSTALL_FULL_<dir> value contains an absolute path constructed
# from the corresponding destination by prepending (if necessary) the value
# of CMAKE_INSTALL_PREFIX.
#=============================================================================
# Copyright 2011 Nikita Krupen'ko <krnekit@gmail.com>
# Copyright 2011 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
# Installation directories
#
if(NOT DEFINED CMAKE_INSTALL_BINDIR)
set(CMAKE_INSTALL_BINDIR "bin" CACHE PATH "user executables (bin)")
endif()
if(NOT DEFINED CMAKE_INSTALL_SBINDIR)
set(CMAKE_INSTALL_SBINDIR "sbin" CACHE PATH "system admin executables (sbin)")
endif()
if(NOT DEFINED CMAKE_INSTALL_LIBEXECDIR)
set(CMAKE_INSTALL_LIBEXECDIR "libexec" CACHE PATH "program executables (libexec)")
endif()
if(NOT DEFINED CMAKE_INSTALL_SYSCONFDIR)
set(CMAKE_INSTALL_SYSCONFDIR "etc" CACHE PATH "read-only single-machine data (etc)")
endif()
if(NOT DEFINED CMAKE_INSTALL_SHAREDSTATEDIR)
set(CMAKE_INSTALL_SHAREDSTATEDIR "com" CACHE PATH "modifiable architecture-independent data (com)")
endif()
if(NOT DEFINED CMAKE_INSTALL_LOCALSTATEDIR)
set(CMAKE_INSTALL_LOCALSTATEDIR "var" CACHE PATH "modifiable single-machine data (var)")
endif()
if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(_LIBDIR_DEFAULT "lib")
# Override this default 'lib' with 'lib64' iff:
# - we are on Linux system but NOT cross-compiling
# - we are NOT on debian
# - we are on a 64 bits system
# reason is: amd64 ABI: http://www.x86-64.org/documentation/abi.pdf
# For Debian with multiarch, use 'lib/${CMAKE_LIBRARY_ARCHITECTURE}' if
# CMAKE_LIBRARY_ARCHITECTURE is set (which contains e.g. "i386-linux-gnu"
# See http://wiki.debian.org/Multiarch
if((CMAKE_SYSTEM_NAME MATCHES "Linux|kFreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "GNU")
AND NOT CMAKE_CROSSCOMPILING)
if (EXISTS "/etc/debian_version") # is this a debian system ?
if(CMAKE_LIBRARY_ARCHITECTURE)
set(_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
endif()
else() # not debian, rely on CMAKE_SIZEOF_VOID_P:
if(NOT DEFINED CMAKE_SIZEOF_VOID_P)
message(AUTHOR_WARNING
"Unable to determine default CMAKE_INSTALL_LIBDIR directory because no target architecture is known. "
"Please enable at least one language before including GNUInstallDirs.")
else()
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
set(_LIBDIR_DEFAULT "lib64")
endif()
endif()
endif()
endif()
set(CMAKE_INSTALL_LIBDIR "${_LIBDIR_DEFAULT}" CACHE PATH "object code libraries (${_LIBDIR_DEFAULT})")
endif()
if(NOT DEFINED CMAKE_INSTALL_INCLUDEDIR)
set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE PATH "C header files (include)")
endif()
if(NOT DEFINED CMAKE_INSTALL_OLDINCLUDEDIR)
set(CMAKE_INSTALL_OLDINCLUDEDIR "/usr/include" CACHE PATH "C header files for non-gcc (/usr/include)")
endif()
if(NOT DEFINED CMAKE_INSTALL_DATAROOTDIR)
set(CMAKE_INSTALL_DATAROOTDIR "share" CACHE PATH "read-only architecture-independent data root (share)")
endif()
#-----------------------------------------------------------------------------
# Values whose defaults are relative to DATAROOTDIR. Store empty values in
# the cache and store the defaults in local variables if the cache values are
# not set explicitly. This auto-updates the defaults as DATAROOTDIR changes.
if(NOT CMAKE_INSTALL_DATADIR)
set(CMAKE_INSTALL_DATADIR "" CACHE PATH "read-only architecture-independent data (DATAROOTDIR)")
set(CMAKE_INSTALL_DATADIR "${CMAKE_INSTALL_DATAROOTDIR}")
endif()
if(NOT CMAKE_INSTALL_INFODIR)
set(CMAKE_INSTALL_INFODIR "" CACHE PATH "info documentation (DATAROOTDIR/info)")
set(CMAKE_INSTALL_INFODIR "${CMAKE_INSTALL_DATAROOTDIR}/info")
endif()
if(NOT CMAKE_INSTALL_LOCALEDIR)
set(CMAKE_INSTALL_LOCALEDIR "" CACHE PATH "locale-dependent data (DATAROOTDIR/locale)")
set(CMAKE_INSTALL_LOCALEDIR "${CMAKE_INSTALL_DATAROOTDIR}/locale")
endif()
if(NOT CMAKE_INSTALL_MANDIR)
set(CMAKE_INSTALL_MANDIR "" CACHE PATH "man documentation (DATAROOTDIR/man)")
set(CMAKE_INSTALL_MANDIR "${CMAKE_INSTALL_DATAROOTDIR}/man")
endif()
if(NOT CMAKE_INSTALL_DOCDIR)
set(CMAKE_INSTALL_DOCDIR "" CACHE PATH "documentation root (DATAROOTDIR/doc/PROJECT_NAME)")
set(CMAKE_INSTALL_DOCDIR "${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME}")
endif()
#-----------------------------------------------------------------------------
mark_as_advanced(
CMAKE_INSTALL_BINDIR
CMAKE_INSTALL_SBINDIR
CMAKE_INSTALL_LIBEXECDIR
CMAKE_INSTALL_SYSCONFDIR
CMAKE_INSTALL_SHAREDSTATEDIR
CMAKE_INSTALL_LOCALSTATEDIR
CMAKE_INSTALL_LIBDIR
CMAKE_INSTALL_INCLUDEDIR
CMAKE_INSTALL_OLDINCLUDEDIR
CMAKE_INSTALL_DATAROOTDIR
CMAKE_INSTALL_DATADIR
CMAKE_INSTALL_INFODIR
CMAKE_INSTALL_LOCALEDIR
CMAKE_INSTALL_MANDIR
CMAKE_INSTALL_DOCDIR
)
# Result directories
#
foreach(dir
BINDIR
SBINDIR
LIBEXECDIR
SYSCONFDIR
SHAREDSTATEDIR
LOCALSTATEDIR
LIBDIR
INCLUDEDIR
OLDINCLUDEDIR
DATAROOTDIR
DATADIR
INFODIR
LOCALEDIR
MANDIR
DOCDIR
)
if(NOT IS_ABSOLUTE ${CMAKE_INSTALL_${dir}})
set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_${dir}}")
else()
set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_${dir}}")
endif()
endforeach()

View File

@@ -20,6 +20,10 @@ install(FILES ${DATABASE_ICONS} DESTINATION ${DATA_INSTALL_DIR}/icons/database)
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
install(DIRECTORY icons/application/ DESTINATION share/icons/hicolor install(DIRECTORY icons/application/ DESTINATION share/icons/hicolor
FILES_MATCHING PATTERN "keepassx.png" PATTERN "keepassx.svgz") FILES_MATCHING PATTERN "keepassx.png" PATTERN "keepassx.svgz")
install(DIRECTORY icons/application/ DESTINATION share/icons/hicolor
FILES_MATCHING PATTERN "application-x-keepassx.png" PATTERN "application-x-keepassx.svgz")
install(FILES linux/keepassx.desktop DESTINATION share/applications)
install(FILES linux/keepassx.xml DESTINATION share/mime/packages)
endif(UNIX AND NOT APPLE) endif(UNIX AND NOT APPLE)
if(APPLE) if(APPLE)

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 783 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 838 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 711 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 798 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 966 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,12 @@
[Desktop Entry]
Name=KeePassX
GenericName=Cross Platform Password Manager
GenericName[de]=Passwortverwaltung
GenericName[es]=Gestor de contraseñas multiplataforma
GenericName[fr]=Gestionnaire de mot de passe
Exec=keepassx %f
Icon=keepassx
Terminal=false
Type=Application
Categories=Qt;Utility;
MimeType=application/x-keepass2;

8
share/linux/keepassx.xml Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
<mime-type type="application/x-keepass2">
<comment>KeePass 2 database</comment>
<glob pattern="*.kdbx"/>
<icon name="application-x-keepassx"/>
</mime-type>
</mime-info>

View File

@@ -20,11 +20,13 @@ configure_file(config-keepassx.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-keepas
set(keepassx_SOURCES set(keepassx_SOURCES
autotype/AutoType.cpp autotype/AutoType.cpp
autotype/AutoTypeAction.cpp autotype/AutoTypeAction.cpp
autotype/AutoTypePlatformPlugin.h
autotype/AutoTypeSelectDialog.cpp autotype/AutoTypeSelectDialog.cpp
autotype/AutoTypeSelectView.cpp autotype/AutoTypeSelectView.cpp
autotype/ShortcutWidget.cpp autotype/ShortcutWidget.cpp
autotype/WildcardMatcher.cpp autotype/WildcardMatcher.cpp
autotype/WindowSelectComboBox.cpp autotype/WindowSelectComboBox.cpp
autotype/test/AutoTypeTestInterface.h
core/AutoTypeAssociations.cpp core/AutoTypeAssociations.cpp
core/Config.cpp core/Config.cpp
core/Database.cpp core/Database.cpp
@@ -34,28 +36,27 @@ set(keepassx_SOURCES
core/EntryAttachments.cpp core/EntryAttachments.cpp
core/EntryAttributes.cpp core/EntryAttributes.cpp
core/FilePath.cpp core/FilePath.cpp
core/Global.h
core/Group.cpp core/Group.cpp
core/InactivityTimer.cpp
core/ListDeleter.h core/ListDeleter.h
core/Metadata.cpp core/Metadata.cpp
core/PasswordGenerator.cpp core/PasswordGenerator.cpp
core/qsavefile.cpp core/qsavefile.cpp
core/qsavefile_p.h
core/SignalMultiplexer.cpp core/SignalMultiplexer.cpp
core/TimeDelta.cpp core/TimeDelta.cpp
core/TimeInfo.cpp core/TimeInfo.cpp
core/Tools.cpp core/Tools.cpp
core/Uuid.cpp core/Uuid.cpp
core/qcommandlineoption.cpp
core/qcommandlineparser.cpp
crypto/Crypto.cpp crypto/Crypto.cpp
crypto/CryptoHash.cpp crypto/CryptoHash.cpp
crypto/Random.cpp crypto/Random.cpp
crypto/salsa20/ecrypt-config.h
crypto/salsa20/ecrypt-machine.h
crypto/salsa20/ecrypt-portable.h
crypto/salsa20/ecrypt-sync.h
crypto/salsa20/salsa20.c
crypto/SymmetricCipher.cpp crypto/SymmetricCipher.cpp
crypto/SymmetricCipherBackend.h crypto/SymmetricCipherBackend.h
crypto/SymmetricCipherGcrypt.cpp crypto/SymmetricCipherGcrypt.cpp
crypto/SymmetricCipherSalsa20.cpp
format/KeePass1.h format/KeePass1.h
format/KeePass1Reader.cpp format/KeePass1Reader.cpp
format/KeePass2.h format/KeePass2.h
@@ -82,13 +83,17 @@ set(keepassx_SOURCES
gui/KeePass1OpenWidget.cpp gui/KeePass1OpenWidget.cpp
gui/LineEdit.cpp gui/LineEdit.cpp
gui/MainWindow.cpp gui/MainWindow.cpp
gui/MessageBox.cpp
gui/PasswordEdit.cpp
gui/PasswordGeneratorWidget.cpp gui/PasswordGeneratorWidget.cpp
gui/PasswordComboBox.cpp
gui/SettingsWidget.cpp gui/SettingsWidget.cpp
gui/SortFilterHideProxyModel.cpp gui/SortFilterHideProxyModel.cpp
gui/UnlockDatabaseWidget.cpp gui/UnlockDatabaseWidget.cpp
gui/WelcomeWidget.cpp gui/WelcomeWidget.cpp
gui/entry/AutoTypeAssociationsModel.cpp gui/entry/AutoTypeAssociationsModel.cpp
gui/entry/EditEntryWidget.cpp gui/entry/EditEntryWidget.cpp
gui/entry/EditEntryWidget_p.h
gui/entry/EntryAttachmentsModel.cpp gui/entry/EntryAttachmentsModel.cpp
gui/entry/EntryAttributesModel.cpp gui/entry/EntryAttributesModel.cpp
gui/entry/EntryHistoryModel.cpp gui/entry/EntryHistoryModel.cpp
@@ -98,6 +103,7 @@ set(keepassx_SOURCES
gui/group/GroupModel.cpp gui/group/GroupModel.cpp
gui/group/GroupView.cpp gui/group/GroupView.cpp
keys/CompositeKey.cpp keys/CompositeKey.cpp
keys/CompositeKey_p.h
keys/FileKey.cpp keys/FileKey.cpp
keys/Key.h keys/Key.h
keys/PasswordKey.cpp keys/PasswordKey.cpp
@@ -108,6 +114,18 @@ set(keepassx_SOURCES
streams/SymmetricCipherStream.cpp streams/SymmetricCipherStream.cpp
) )
if(NOT GCRYPT_HAS_SALSA20)
set(keepassx_SOURCES
${keepassx_SOURCES}
crypto/salsa20/ecrypt-config.h
crypto/salsa20/ecrypt-machine.h
crypto/salsa20/ecrypt-portable.h
crypto/salsa20/ecrypt-sync.h
crypto/salsa20/salsa20.c
crypto/SymmetricCipherSalsa20.cpp
)
endif()
set(keepassx_SOURCES_MAINEXE set(keepassx_SOURCES_MAINEXE
main.cpp main.cpp
) )
@@ -125,6 +143,7 @@ set(keepassx_MOC
core/EntryAttachments.h core/EntryAttachments.h
core/EntryAttributes.h core/EntryAttributes.h
core/Group.h core/Group.h
core/InactivityTimer.h
core/Metadata.h core/Metadata.h
core/qsavefile.h core/qsavefile.h
gui/AboutDialog.h gui/AboutDialog.h
@@ -144,7 +163,9 @@ set(keepassx_MOC
gui/KeePass1OpenWidget.h gui/KeePass1OpenWidget.h
gui/LineEdit.h gui/LineEdit.h
gui/MainWindow.h gui/MainWindow.h
gui/PasswordEdit.h
gui/PasswordGeneratorWidget.h gui/PasswordGeneratorWidget.h
gui/PasswordComboBox.h
gui/SettingsWidget.h gui/SettingsWidget.h
gui/SortFilterHideProxyModel.h gui/SortFilterHideProxyModel.h
gui/UnlockDatabaseWidget.h gui/UnlockDatabaseWidget.h

View File

@@ -17,8 +17,8 @@
#include "AutoType.h" #include "AutoType.h"
#include <QtCore/QPluginLoader> #include <QApplication>
#include <QtGui/QApplication> #include <QPluginLoader>
#include "autotype/AutoTypePlatformPlugin.h" #include "autotype/AutoTypePlatformPlugin.h"
#include "autotype/AutoTypeSelectDialog.h" #include "autotype/AutoTypeSelectDialog.h"
@@ -40,6 +40,7 @@ AutoType::AutoType(QObject* parent, bool test)
, m_pluginLoader(new QPluginLoader(this)) , m_pluginLoader(new QPluginLoader(this))
, m_plugin(Q_NULLPTR) , m_plugin(Q_NULLPTR)
, m_executor(Q_NULLPTR) , m_executor(Q_NULLPTR)
, m_windowFromGlobal(0)
{ {
// prevent crash when the plugin has unresolved symbols // prevent crash when the plugin has unresolved symbols
m_pluginLoader->setLoadHints(QLibrary::ResolveAllSymbolsHint); m_pluginLoader->setLoadHints(QLibrary::ResolveAllSymbolsHint);
@@ -57,11 +58,16 @@ AutoType::AutoType(QObject* parent, bool test)
if (!pluginPath.isEmpty()) { if (!pluginPath.isEmpty()) {
loadPlugin(pluginPath); loadPlugin(pluginPath);
} }
connect(qApp, SIGNAL(aboutToQuit()), SLOT(unloadPlugin()));
} }
AutoType::~AutoType() AutoType::~AutoType()
{ {
delete m_executor; if (m_executor) {
delete m_executor;
m_executor = Q_NULLPTR;
}
} }
void AutoType::loadPlugin(const QString& pluginPath) void AutoType::loadPlugin(const QString& pluginPath)
@@ -215,6 +221,19 @@ void AutoType::resetInAutoType()
m_inAutoType = false; m_inAutoType = false;
} }
void AutoType::unloadPlugin()
{
if (m_executor) {
delete m_executor;
m_executor = Q_NULLPTR;
}
if (m_plugin) {
m_plugin->unload();
m_plugin = Q_NULLPTR;
}
}
bool AutoType::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) bool AutoType::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers)
{ {
Q_ASSERT(key); Q_ASSERT(key);

View File

@@ -18,9 +18,9 @@
#ifndef KEEPASSX_AUTOTYPE_H #ifndef KEEPASSX_AUTOTYPE_H
#define KEEPASSX_AUTOTYPE_H #define KEEPASSX_AUTOTYPE_H
#include <QtCore/QObject> #include <QObject>
#include <QtCore/QStringList> #include <QStringList>
#include <QtGui/QWidget> #include <QWidget>
#include "core/Global.h" #include "core/Global.h"
@@ -59,6 +59,7 @@ Q_SIGNALS:
private Q_SLOTS: private Q_SLOTS:
void performAutoTypeFromGlobal(Entry* entry, const QString& sequence); void performAutoTypeFromGlobal(Entry* entry, const QString& sequence);
void resetInAutoType(); void resetInAutoType();
void unloadPlugin();
private: private:
explicit AutoType(QObject* parent = Q_NULLPTR, bool test = false); explicit AutoType(QObject* parent = Q_NULLPTR, bool test = false);

View File

@@ -18,8 +18,8 @@
#ifndef KEEPASSX_AUTOTYPEACTION_H #ifndef KEEPASSX_AUTOTYPEACTION_H
#define KEEPASSX_AUTOTYPEACTION_H #define KEEPASSX_AUTOTYPEACTION_H
#include <QtCore/QChar> #include <QChar>
#include <QtCore/Qt> #include <Qt>
#include "core/Global.h" #include "core/Global.h"

View File

@@ -18,7 +18,7 @@
#ifndef KEEPASSX_AUTOTYPEPLATFORMPLUGIN_H #ifndef KEEPASSX_AUTOTYPEPLATFORMPLUGIN_H
#define KEEPASSX_AUTOTYPEPLATFORMPLUGIN_H #define KEEPASSX_AUTOTYPEPLATFORMPLUGIN_H
#include <QtGui/QWidget> #include <QWidget>
#include "autotype/AutoTypeAction.h" #include "autotype/AutoTypeAction.h"
@@ -33,6 +33,7 @@ public:
virtual void unregisterGlobalShortcut(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 platformEventFilter(void* event) = 0;
virtual int initialTimeout() = 0; virtual int initialTimeout() = 0;
virtual void unload() {}
virtual AutoTypeExecutor* createExecutor() = 0; virtual AutoTypeExecutor* createExecutor() = 0;

View File

@@ -17,11 +17,11 @@
#include "AutoTypeSelectDialog.h" #include "AutoTypeSelectDialog.h"
#include <QtGui/QApplication> #include <QApplication>
#include <QtGui/QDesktopWidget> #include <QDesktopWidget>
#include <QtGui/QDialogButtonBox> #include <QDialogButtonBox>
#include <QtGui/QLabel> #include <QLabel>
#include <QtGui/QVBoxLayout> #include <QVBoxLayout>
#include "autotype/AutoTypeSelectView.h" #include "autotype/AutoTypeSelectView.h"
#include "core/FilePath.h" #include "core/FilePath.h"

View File

@@ -18,9 +18,9 @@
#ifndef KEEPASSX_AUTOTYPESELECTDIALOG_H #ifndef KEEPASSX_AUTOTYPESELECTDIALOG_H
#define KEEPASSX_AUTOTYPESELECTDIALOG_H #define KEEPASSX_AUTOTYPESELECTDIALOG_H
#include <QtCore/QAbstractItemModel> #include <QAbstractItemModel>
#include <QtCore/QHash> #include <QDialog>
#include <QtGui/QDialog> #include <QHash>
#include "core/Global.h" #include "core/Global.h"

View File

@@ -17,7 +17,7 @@
#include "AutoTypeSelectView.h" #include "AutoTypeSelectView.h"
#include <QtGui/QMouseEvent> #include <QMouseEvent>
AutoTypeSelectView::AutoTypeSelectView(QWidget* parent) AutoTypeSelectView::AutoTypeSelectView(QWidget* parent)
: EntryView(parent) : EntryView(parent)

View File

@@ -1,5 +1,8 @@
if(Q_WS_X11) if(Q_WS_X11)
find_package(X11) find_package(X11)
if(PRINT_SUMMARY)
add_feature_info(libXtest X11_XTest_FOUND "The X11 XTEST Protocol library is required for auto-type")
endif()
if(X11_FOUND AND X11_XTest_FOUND) if(X11_FOUND AND X11_XTest_FOUND)
add_subdirectory(x11) add_subdirectory(x11)

View File

@@ -17,7 +17,7 @@
#include "ShortcutWidget.h" #include "ShortcutWidget.h"
#include <QtGui/QKeyEvent> #include <QKeyEvent>
#include "autotype/AutoType.h" #include "autotype/AutoType.h"

View File

@@ -18,7 +18,7 @@
#ifndef KEEPASSX_SHORTCUTWIDGET_H #ifndef KEEPASSX_SHORTCUTWIDGET_H
#define KEEPASSX_SHORTCUTWIDGET_H #define KEEPASSX_SHORTCUTWIDGET_H
#include <QtGui/QLineEdit> #include <QLineEdit>
#include "core/Global.h" #include "core/Global.h"

View File

@@ -17,7 +17,7 @@
#include "WildcardMatcher.h" #include "WildcardMatcher.h"
#include <QtCore/QStringList> #include <QStringList>
const QChar WildcardMatcher::Wildcard = '*'; const QChar WildcardMatcher::Wildcard = '*';
const Qt::CaseSensitivity WildcardMatcher::Sensitivity = Qt::CaseInsensitive; const Qt::CaseSensitivity WildcardMatcher::Sensitivity = Qt::CaseInsensitive;

View File

@@ -18,7 +18,7 @@
#ifndef KEEPASSX_WILDCARDMATCHER_H #ifndef KEEPASSX_WILDCARDMATCHER_H
#define KEEPASSX_WILDCARDMATCHER_H #define KEEPASSX_WILDCARDMATCHER_H
#include <QtCore/QStringList> #include <QStringList>
class WildcardMatcher class WildcardMatcher
{ {

View File

@@ -17,7 +17,7 @@
#include "WindowSelectComboBox.h" #include "WindowSelectComboBox.h"
#include <QtGui/QLineEdit> #include <QLineEdit>
#include "autotype/AutoType.h" #include "autotype/AutoType.h"

View File

@@ -18,7 +18,7 @@
#ifndef KEEPASSX_WINDOWSELECTCOMBOBOX_H #ifndef KEEPASSX_WINDOWSELECTCOMBOBOX_H
#define KEEPASSX_WINDOWSELECTCOMBOBOX_H #define KEEPASSX_WINDOWSELECTCOMBOBOX_H
#include <QtGui/QComboBox> #include <QComboBox>
#include "core/Global.h" #include "core/Global.h"

View File

@@ -18,7 +18,7 @@
#ifndef KEEPASSX_AUTOTYPETEST_H #ifndef KEEPASSX_AUTOTYPETEST_H
#define KEEPASSX_AUTOTYPETEST_H #define KEEPASSX_AUTOTYPETEST_H
#include <QtCore/QtPlugin> #include <QtPlugin>
#include "autotype/AutoTypePlatformPlugin.h" #include "autotype/AutoTypePlatformPlugin.h"
#include "autotype/AutoTypeAction.h" #include "autotype/AutoTypeAction.h"

View File

@@ -17,6 +17,9 @@
*/ */
#include "AutoTypeX11.h" #include "AutoTypeX11.h"
#include "KeySymMap.h"
#include <time.h>
bool AutoTypePlatformX11::m_catchXErrors = false; bool AutoTypePlatformX11::m_catchXErrors = false;
bool AutoTypePlatformX11::m_xErrorOccured = false; bool AutoTypePlatformX11::m_xErrorOccured = false;
@@ -42,14 +45,32 @@ AutoTypePlatformX11::AutoTypePlatformX11()
m_currentGlobalModifiers = 0; m_currentGlobalModifiers = 0;
m_keysymTable = Q_NULLPTR; m_keysymTable = Q_NULLPTR;
m_altMask = 0; m_xkb = Q_NULLPTR;
m_metaMask = 0; m_remapKeycode = 0;
m_altgrMask = 0; m_currentRemapKeysym = NoSymbol;
m_altgrKeysym = NoSymbol; m_modifierMask = ControlMask | ShiftMask | Mod1Mask | Mod4Mask;
m_loaded = true;
updateKeymap(); updateKeymap();
} }
void AutoTypePlatformX11::unload()
{
// Restore the KeyboardMapping to its original state.
AddKeysym(NoSymbol);
if (m_keysymTable) {
XFree(m_keysymTable);
}
if (m_xkb) {
XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True);
}
m_loaded = false;
}
QStringList AutoTypePlatformX11::windowTitles() QStringList AutoTypePlatformX11::windowTitles()
{ {
return windowTitlesRecursive(m_rootWindow); return windowTitlesRecursive(m_rootWindow);
@@ -125,10 +146,10 @@ uint AutoTypePlatformX11::qtToNativeModifiers(Qt::KeyboardModifiers modifiers)
nativeModifiers |= ControlMask; nativeModifiers |= ControlMask;
} }
if (modifiers & Qt::AltModifier) { if (modifiers & Qt::AltModifier) {
nativeModifiers |= m_altMask; nativeModifiers |= Mod1Mask;
} }
if (modifiers & Qt::MetaModifier) { if (modifiers & Qt::MetaModifier) {
nativeModifiers |= m_metaMask; nativeModifiers |= Mod4Mask;
} }
return nativeModifiers; return nativeModifiers;
@@ -158,13 +179,15 @@ int AutoTypePlatformX11::platformEventFilter(void* event)
&& m_currentGlobalKey && m_currentGlobalKey
&& xevent->xkey.keycode == m_currentGlobalKeycode && xevent->xkey.keycode == m_currentGlobalKeycode
&& (xevent->xkey.state & m_modifierMask) == m_currentGlobalNativeModifiers && (xevent->xkey.state & m_modifierMask) == m_currentGlobalNativeModifiers
&& !QApplication::focusWidget()) { && !QApplication::focusWidget()
&& m_loaded) {
if (xevent->type == KeyPress) { if (xevent->type == KeyPress) {
Q_EMIT globalShortcutTriggered(); Q_EMIT globalShortcutTriggered();
} }
return 1; return 1;
} }
if (xevent->type == MappingNotify) { if (xevent->type == MappingNotify && m_loaded) {
XRefreshKeyboardMapping(reinterpret_cast<XMappingEvent*>(xevent));
updateKeymap(); updateKeymap();
} }
@@ -326,12 +349,21 @@ KeySym AutoTypePlatformX11::charToKeySym(const QChar& ch)
|| (unicode >= 0x00a0 && unicode <= 0x00ff)) { || (unicode >= 0x00a0 && unicode <= 0x00ff)) {
return unicode; return unicode;
} }
else if (unicode >= 0x0100) {
/* mapping table generated from keysymdef.h */
const uint* match = qBinaryFind(m_unicodeToKeysymKeys,
m_unicodeToKeysymKeys + m_unicodeToKeysymLen,
unicode);
int index = match - m_unicodeToKeysymKeys;
if (index != m_unicodeToKeysymLen) {
return m_unicodeToKeysymValues[index];
}
if (unicode >= 0x0100) {
return unicode | 0x01000000; return unicode | 0x01000000;
} }
else {
return NoSymbol; return NoSymbol;
}
} }
KeySym AutoTypePlatformX11::keyToKeySym(Qt::Key key) KeySym AutoTypePlatformX11::keyToKeySym(Qt::Key key)
@@ -387,24 +419,65 @@ KeySym AutoTypePlatformX11::keyToKeySym(Qt::Key key)
} }
} }
/*
* Update the keyboard and modifier mapping.
* We need the KeyboardMapping for AddKeysym.
* Modifier mapping is required for clearing the modifiers.
*/
void AutoTypePlatformX11::updateKeymap() void AutoTypePlatformX11::updateKeymap()
{ {
ReadKeymap(); int keycode, inx;
int mod_index, mod_key;
XModifierKeymap *modifiers;
if (!m_altgrMask) { /* read keyboard map */
AddModifier(XK_Mode_switch); if (m_xkb != NULL) XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True);
} m_xkb = XkbGetKeyboard (m_dpy, XkbCompatMapMask | XkbGeometryMask, XkbUseCoreKbd);
if (!m_metaMask) {
m_metaMask = Mod4Mask; XDisplayKeycodes(m_dpy, &m_minKeycode, &m_maxKeycode);
if (m_keysymTable != NULL) XFree(m_keysymTable);
m_keysymTable = XGetKeyboardMapping(m_dpy,
m_minKeycode, m_maxKeycode - m_minKeycode + 1,
&m_keysymPerKeycode);
/* determine the keycode to use for remapped keys */
inx = (m_remapKeycode - m_minKeycode) * m_keysymPerKeycode;
if (m_remapKeycode == 0 || !isRemapKeycodeValid()) {
for (keycode = m_minKeycode; keycode <= m_maxKeycode; keycode++) {
inx = (keycode - m_minKeycode) * m_keysymPerKeycode;
if (m_keysymTable[inx] == NoSymbol) {
m_remapKeycode = keycode;
m_currentRemapKeysym = NoSymbol;
break;
}
}
} }
m_modifierMask = ControlMask | ShiftMask | m_altMask | m_metaMask; /* determine the keycode to use for modifiers */
modifiers = XGetModifierMapping(m_dpy);
for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
m_modifier_keycode[mod_index] = 0;
for (mod_key = 0; mod_key < modifiers->max_keypermod; mod_key++) {
keycode = modifiers->modifiermap[mod_index * modifiers->max_keypermod + mod_key];
if (keycode) {
m_modifier_keycode[mod_index] = keycode;
break;
}
}
}
XFreeModifiermap(modifiers);
}
// TODO: figure out why this breaks after the first global auto-type bool AutoTypePlatformX11::isRemapKeycodeValid()
/*if (m_currentGlobalKey && m_currentGlobalModifiers) { {
unregisterGlobalShortcut(m_currentGlobalKey, m_currentGlobalModifiers); int baseKeycode = (m_remapKeycode - m_minKeycode) * m_keysymPerKeycode;
registerGlobalShortcut(m_currentGlobalKey, m_currentGlobalModifiers); for (int i = 0; i < m_keysymPerKeycode; i++) {
}*/ if (m_keysymTable[baseKeycode + i] == m_currentRemapKeysym) {
return true;
}
}
return false;
} }
void AutoTypePlatformX11::startCatchXErrors() void AutoTypePlatformX11::startCatchXErrors()
@@ -442,141 +515,31 @@ int AutoTypePlatformX11::x11ErrorHandler(Display* display, XErrorEvent* error)
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
/* /*
* Insert a specified keysym to unused position in the keymap table. * Insert a specified keysym on the dedicated position in the keymap
* This will be called to add required keysyms on-the-fly. * table.
* if the second parameter is TRUE, the keysym will be added to the
* non-shifted position - this may be required for modifier keys
* (e.g. Mode_switch) and some special keys (e.g. F20).
*/ */
int AutoTypePlatformX11::AddKeysym(KeySym keysym, bool top) int AutoTypePlatformX11::AddKeysym(KeySym keysym)
{ {
int keycode, pos, max_pos, inx, phase; if (m_remapKeycode == 0) {
return 0;
if (top) {
max_pos = 0;
} else {
max_pos = m_keysymPerKeycode - 1;
if (4 <= max_pos) max_pos = 3;
if (2 <= max_pos && m_altgrKeysym != XK_Mode_switch) max_pos = 1;
} }
for (phase = 0; phase < 2; phase++) { int inx = (m_remapKeycode- m_minKeycode) * m_keysymPerKeycode;
for (keycode = m_maxKeycode; m_minKeycode <= keycode; keycode--) { m_keysymTable[inx] = keysym;
for (pos = max_pos; 0 <= pos; pos--) { m_currentRemapKeysym = keysym;
inx = (keycode - m_minKeycode) * m_keysymPerKeycode;
if ((phase != 0 || m_keysymTable[inx] == NoSymbol) && m_keysymTable[inx] < 0xFF00) {
/* In the first phase, to avoid modifing existing keys, */
/* add the keysym only to the keys which has no keysym in the first position. */
/* If no place fuond in the first phase, add the keysym for any keys except */
/* for modifier keys and other special keys */
if (m_keysymTable[inx + pos] == NoSymbol) {
m_keysymTable[inx + pos] = keysym;
XChangeKeyboardMapping(m_dpy, keycode, m_keysymPerKeycode, &m_keysymTable[inx], 1);
XFlush(m_dpy);
return keycode;
}
}
}
}
}
qWarning("Couldn't add \"%s\" to keymap", XKeysymToString(keysym));
return NoSymbol;
}
/* XChangeKeyboardMapping(m_dpy, m_remapKeycode, m_keysymPerKeycode, &m_keysymTable[inx], 1);
* Add the specified key as a new modifier. XFlush(m_dpy);
* This is used to use Mode_switch (AltGr) as a modifier. updateKeymap();
*/
void AutoTypePlatformX11::AddModifier(KeySym keysym)
{
XModifierKeymap *modifiers;
int keycode, i, pos;
keycode = XKeysymToKeycode(m_dpy, keysym); /* Xlib needs some time until the mapping is distributed to
if (keycode == NoSymbol) keycode = AddKeysym(keysym, TRUE); all clients */
timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 10 * 1000 * 1000;
nanosleep(&ts, Q_NULLPTR);
modifiers = XGetModifierMapping(m_dpy); return m_remapKeycode;
for (i = 7; 3 < i; i--) {
if (modifiers->modifiermap[i * modifiers->max_keypermod] == NoSymbol
|| ((m_keysymTable[(modifiers->modifiermap[i * modifiers->max_keypermod]
- m_minKeycode) * m_keysymPerKeycode]) == XK_ISO_Level3_Shift
&& keysym == XK_Mode_switch))
{
for (pos = 0; pos < modifiers->max_keypermod; pos++) {
if (modifiers->modifiermap[i * modifiers->max_keypermod + pos] == NoSymbol) {
modifiers->modifiermap[i * modifiers->max_keypermod + pos] = keycode;
XSetModifierMapping(m_dpy, modifiers);
return;
}
}
}
}
qWarning("Couldn't add \"%s\" as modifier", XKeysymToString(keysym));
}
/*
* Read keyboard mapping and modifier mapping.
* Keyboard mapping is used to know what keys are in shifted position.
* Modifier mapping is required because we should know Alt and Meta
* key are used as which modifier.
*/
void AutoTypePlatformX11::ReadKeymap()
{
int i;
int keycode, inx, pos;
KeySym keysym;
XModifierKeymap *modifiers;
XDisplayKeycodes(m_dpy, &m_minKeycode, &m_maxKeycode);
if (m_keysymTable != NULL) XFree(m_keysymTable);
m_keysymTable = XGetKeyboardMapping(m_dpy,
m_minKeycode, m_maxKeycode - m_minKeycode + 1,
&m_keysymPerKeycode);
for (keycode = m_minKeycode; keycode <= m_maxKeycode; keycode++) {
/* if the first keysym is alphabet and the second keysym is NoSymbol,
it is equivalent to pair of lowercase and uppercase alphabet */
inx = (keycode - m_minKeycode) * m_keysymPerKeycode;
if (m_keysymTable[inx + 1] == NoSymbol
&& ((XK_A <= m_keysymTable[inx] && m_keysymTable[inx] <= XK_Z)
|| (XK_a <= m_keysymTable[inx] && m_keysymTable[inx] <= XK_z)))
{
if (XK_A <= m_keysymTable[inx] && m_keysymTable[inx] <= XK_Z)
m_keysymTable[inx] = m_keysymTable[inx] - XK_A + XK_a;
m_keysymTable[inx + 1] = m_keysymTable[inx] - XK_a + XK_A;
}
}
m_altMask = 0;
m_metaMask = 0;
m_altgrMask = 0;
m_altgrKeysym = NoSymbol;
modifiers = XGetModifierMapping(m_dpy);
for (i = 0; i < 8; i++) {
for (pos = 0; pos < modifiers->max_keypermod; pos++) {
keycode = modifiers->modifiermap[i * modifiers->max_keypermod + pos];
if (keycode < m_minKeycode || m_maxKeycode < keycode) continue;
keysym = m_keysymTable[(keycode - m_minKeycode) * m_keysymPerKeycode];
if (keysym == XK_Alt_L || keysym == XK_Alt_R) {
m_altMask = 1 << i;
} else if (keysym == XK_Meta_L || keysym == XK_Meta_R) {
m_metaMask = 1 << i;
} else if (keysym == XK_Mode_switch) {
if (m_altgrKeysym == XK_ISO_Level3_Shift) {
} else {
m_altgrMask = 0x0101 << i;
/* I don't know why, but 0x2000 was required for mod3 on my Linux box */
m_altgrKeysym = keysym;
}
} else if (keysym == XK_ISO_Level3_Shift) {
/* if no Mode_switch, try to use ISO_Level3_Shift instead */
/* however, it may not work as intended - I don't know why */
m_altgrMask = 1 << i;
m_altgrKeysym = keysym;
}
}
}
XFreeModifiermap(modifiers);
} }
/* /*
@@ -584,80 +547,101 @@ void AutoTypePlatformX11::ReadKeymap()
* If input focus is specified explicitly, select the window * If input focus is specified explicitly, select the window
* before send event to the window. * before send event to the window.
*/ */
void AutoTypePlatformX11::SendEvent(XKeyEvent* event) void AutoTypePlatformX11::SendEvent(XKeyEvent* event, int event_type)
{ {
XSync(event->display, FALSE); XSync(event->display, FALSE);
int (*oldHandler) (Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler); int (*oldHandler) (Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler);
event->type = event_type;
XTestFakeKeyEvent(event->display, event->keycode, event->type == KeyPress, 0); XTestFakeKeyEvent(event->display, event->keycode, event->type == KeyPress, 0);
XFlush(event->display); XFlush(event->display);
XSetErrorHandler(oldHandler); XSetErrorHandler(oldHandler);
} }
/*
* Send a modifier press/release event for all modifiers
* which are set in the mask variable.
*/
void AutoTypePlatformX11::SendModifier(XKeyEvent *event, unsigned int mask, int event_type)
{
int mod_index;
for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
if (mask & (1 << mod_index)) {
event->keycode = m_modifier_keycode[mod_index];
SendEvent(event, event_type);
if (event_type == KeyPress)
event->state |= (1 << mod_index);
else
event->state &= (1 << mod_index);
}
}
}
/*
* Determines the keycode and modifier mask for the given
* keysym.
*/
int AutoTypePlatformX11::GetKeycode(KeySym keysym, unsigned int *mask)
{
int keycode = XKeysymToKeycode(m_dpy, keysym);
if (keycode && keysymModifiers(keysym, keycode, mask)) {
return keycode;
}
/* no modifier matches => resort to remapping */
keycode = AddKeysym(keysym);
if (keycode && keysymModifiers(keysym, keycode, mask)) {
return keycode;
}
*mask = 0;
return 0;
}
bool AutoTypePlatformX11::keysymModifiers(KeySym keysym, int keycode, unsigned int *mask)
{
int shift, mod;
unsigned int mods_rtrn;
/* determine whether there is a combination of the modifiers
(Mod1-Mod5) with or without shift which returns keysym */
for (shift = 0; shift < 2; shift ++) {
for (mod = ControlMapIndex; mod <= Mod5MapIndex; mod ++) {
KeySym keysym_rtrn;
*mask = (mod == ControlMapIndex) ? shift : shift | (1 << mod);
XkbTranslateKeyCode(m_xkb, keycode, *mask, &mods_rtrn, &keysym_rtrn);
if (keysym_rtrn == keysym) {
return true;
}
}
}
return false;
}
/* /*
* Send sequence of KeyPressed/KeyReleased events to the focused * Send sequence of KeyPressed/KeyReleased events to the focused
* window to simulate keyboard. If modifiers (shift, control, etc) * window to simulate keyboard. If modifiers (shift, control, etc)
* are set ON, many events will be sent. * are set ON, many events will be sent.
*/ */
void AutoTypePlatformX11::SendKeyPressedEvent(KeySym keysym, unsigned int shift) void AutoTypePlatformX11::SendKeyPressedEvent(KeySym keysym)
{ {
Window cur_focus; Window cur_focus;
int revert_to; int revert_to;
XKeyEvent event; XKeyEvent event;
int keycode; int keycode;
int phase, inx;
bool found; if (keysym == NoSymbol) {
qWarning("No such key: keysym=0x%lX", static_cast<long>(keysym));
return;
}
XGetInputFocus(m_dpy, &cur_focus, &revert_to); XGetInputFocus(m_dpy, &cur_focus, &revert_to);
found = FALSE;
keycode = 0;
if (keysym != NoSymbol) {
for (phase = 0; phase < 2; phase++) {
for (keycode = m_minKeycode; !found && (keycode <= m_maxKeycode); keycode++) {
/* Determine keycode for the keysym: we use this instead
of XKeysymToKeycode() because we must know shift_state, too */
inx = (keycode - m_minKeycode) * m_keysymPerKeycode;
if (m_keysymTable[inx] == keysym) {
shift &= ~m_altgrMask;
if (m_keysymTable[inx + 1] != NoSymbol) shift &= ~ShiftMask;
found = TRUE;
break;
} else if (m_keysymTable[inx + 1] == keysym) {
shift &= ~m_altgrMask;
shift |= ShiftMask;
found = TRUE;
break;
}
}
if (!found && m_altgrMask && 3 <= m_keysymPerKeycode) {
for (keycode = m_minKeycode; !found && (keycode <= m_maxKeycode); keycode++) {
inx = (keycode - m_minKeycode) * m_keysymPerKeycode;
if (m_keysymTable[inx + 2] == keysym) {
shift &= ~ShiftMask;
shift |= m_altgrMask;
found = TRUE;
break;
} else if (4 <= m_keysymPerKeycode && m_keysymTable[inx + 3] == keysym) {
shift |= ShiftMask | m_altgrMask;
found = TRUE;
break;
}
}
}
if (found) break;
if (0xF000 <= keysym) {
/* for special keys such as function keys,
first try to add it in the non-shifted position of the keymap */
if (AddKeysym(keysym, TRUE) == NoSymbol) AddKeysym(keysym, FALSE);
} else {
AddKeysym(keysym, FALSE);
}
}
}
event.display = m_dpy; event.display = m_dpy;
event.window = cur_focus; event.window = cur_focus;
event.root = m_rootWindow; event.root = m_rootWindow;
@@ -672,106 +656,33 @@ void AutoTypePlatformX11::SendKeyPressedEvent(KeySym keysym, unsigned int shift)
Window root, child; Window root, child;
int root_x, root_y, x, y; int root_x, root_y, x, y;
unsigned int mask; unsigned int mask;
unsigned int saved_mask;
XQueryPointer(m_dpy, event.root, &root, &child, &root_x, &root_y, &x, &y, &mask); XQueryPointer(m_dpy, event.root, &root, &child, &root_x, &root_y, &x, &y, &mask);
saved_mask = mask;
event.type = KeyRelease; /* determine keycode and mask for the given keysym */
event.state = 0; keycode = GetKeycode(keysym, &mask);
if (mask & ControlMask) { if (keycode < 8 || keycode > 255) {
event.keycode = XKeysymToKeycode(m_dpy, XK_Control_L); qWarning("Unable to get valid keycode for key: keysym=0x%lX", static_cast<long>(keysym));
SendEvent(&event); return;
}
if (mask & m_altMask) {
event.keycode = XKeysymToKeycode(m_dpy, XK_Alt_L);
SendEvent(&event);
}
if (mask & m_metaMask) {
event.keycode = XKeysymToKeycode(m_dpy, XK_Meta_L);
SendEvent(&event);
}
if (mask & m_altgrMask) {
event.keycode = XKeysymToKeycode(m_dpy, m_altgrKeysym);
SendEvent(&event);
}
if (mask & ShiftMask) {
event.keycode = XKeysymToKeycode(m_dpy, XK_Shift_L);
SendEvent(&event);
}
if (mask & LockMask) {
event.keycode = XKeysymToKeycode(m_dpy, XK_Caps_Lock);
SendEvent(&event);
} }
event.type = KeyPress; /* release all modifiers */
event.state = 0; SendModifier(&event, mask, KeyRelease);
if (shift & ControlMask) {
event.keycode = XKeysymToKeycode(m_dpy, XK_Control_L);
SendEvent(&event);
event.state |= ControlMask;
}
if (shift & m_altMask) {
event.keycode = XKeysymToKeycode(m_dpy, XK_Alt_L);
SendEvent(&event);
event.state |= m_altMask;
}
if (shift & m_metaMask) {
event.keycode = XKeysymToKeycode(m_dpy, XK_Meta_L);
SendEvent(&event);
event.state |= m_metaMask;
}
if (shift & m_altgrMask) {
event.keycode = XKeysymToKeycode(m_dpy, m_altgrKeysym);
SendEvent(&event);
event.state |= m_altgrMask;
}
if (shift & ShiftMask) {
event.keycode = XKeysymToKeycode(m_dpy, XK_Shift_L);
SendEvent(&event);
event.state |= ShiftMask;
}
if (keysym != NoSymbol) { /* send event for the key itself */ SendModifier(&event, mask, KeyPress);
event.keycode = found ? keycode : XKeysymToKeycode(m_dpy, keysym);
if (event.keycode == NoSymbol) {
if ((keysym & ~0x7f) == 0 && QChar(static_cast<char>(keysym)).isPrint())
qWarning("No such key: %c", static_cast<char>(keysym));
else if (XKeysymToString(keysym) != NULL)
qWarning("No such key: keysym=%s (0x%lX)", XKeysymToString(keysym), static_cast<long>(keysym));
else
qWarning("No such key: keysym=0x%lX", static_cast<long>(keysym));
} else {
SendEvent(&event);
event.type = KeyRelease;
SendEvent(&event);
}
}
event.type = KeyRelease; /* press and release key */
if (shift & ShiftMask) { event.keycode = keycode;
event.keycode = XKeysymToKeycode(m_dpy, XK_Shift_L); SendEvent(&event, KeyPress);
SendEvent(&event); SendEvent(&event, KeyRelease);
event.state &= ~ShiftMask;
} /* release the modifiers */
if (shift & m_altgrMask) { SendModifier(&event, mask, KeyRelease);
event.keycode = XKeysymToKeycode(m_dpy, m_altgrKeysym);
SendEvent(&event); /* restore the old keyboard mask */
event.state &= ~m_altgrMask; SendModifier(&event, saved_mask, KeyPress);
}
if (shift & m_metaMask) {
event.keycode = XKeysymToKeycode(m_dpy, XK_Meta_L);
SendEvent(&event);
event.state &= ~m_metaMask;
}
if (shift & m_altMask) {
event.keycode = XKeysymToKeycode(m_dpy, XK_Alt_L);
SendEvent(&event);
event.state &= ~m_altMask;
}
if (shift & ControlMask) {
event.keycode = XKeysymToKeycode(m_dpy, XK_Control_L);
SendEvent(&event);
event.state &= ~ControlMask;
}
} }
int AutoTypePlatformX11::MyErrorHandler(Display* my_dpy, XErrorEvent* event) int AutoTypePlatformX11::MyErrorHandler(Display* my_dpy, XErrorEvent* event)

View File

@@ -19,19 +19,22 @@
#ifndef KEEPASSX_AUTOTYPEX11_H #ifndef KEEPASSX_AUTOTYPEX11_H
#define KEEPASSX_AUTOTYPEX11_H #define KEEPASSX_AUTOTYPEX11_H
#include <QtCore/QSet> #include <QApplication>
#include <QtCore/QtPlugin> #include <QSet>
#include <QtGui/QApplication> #include <QtPlugin>
#include <QtGui/QWidget> #include <QWidget>
#include <QtGui/QX11Info> #include <QX11Info>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <X11/extensions/XTest.h> #include <X11/extensions/XTest.h>
#include <X11/XKBlib.h>
#include "autotype/AutoTypePlatformPlugin.h" #include "autotype/AutoTypePlatformPlugin.h"
#include "autotype/AutoTypeAction.h" #include "autotype/AutoTypeAction.h"
#include "core/Global.h" #include "core/Global.h"
#define N_MOD_INDICES (Mod5MapIndex + 1)
class AutoTypePlatformX11 : public QObject, public AutoTypePlatformInterface class AutoTypePlatformX11 : public QObject, public AutoTypePlatformInterface
{ {
Q_OBJECT Q_OBJECT
@@ -39,6 +42,7 @@ class AutoTypePlatformX11 : public QObject, public AutoTypePlatformInterface
public: public:
AutoTypePlatformX11(); AutoTypePlatformX11();
void unload() Q_DECL_OVERRIDE;
QStringList windowTitles(); QStringList windowTitles();
WId activeWindow(); WId activeWindow();
QString activeWindowTitle(); QString activeWindowTitle();
@@ -51,7 +55,7 @@ public:
KeySym charToKeySym(const QChar& ch); KeySym charToKeySym(const QChar& ch);
KeySym keyToKeySym(Qt::Key key); KeySym keyToKeySym(Qt::Key key);
void SendKeyPressedEvent(KeySym keysym, unsigned int shift = 0); void SendKeyPressedEvent(KeySym keysym);
Q_SIGNALS: Q_SIGNALS:
void globalShortcutTriggered(); void globalShortcutTriggered();
@@ -68,10 +72,14 @@ private:
static int x11ErrorHandler(Display* display, XErrorEvent* error); static int x11ErrorHandler(Display* display, XErrorEvent* error);
void updateKeymap(); void updateKeymap();
int AddKeysym(KeySym keysym, bool top); bool isRemapKeycodeValid();
int AddKeysym(KeySym keysym);
void AddModifier(KeySym keysym); void AddModifier(KeySym keysym);
void ReadKeymap(); void SendEvent(XKeyEvent* event, int event_type);
void SendEvent(XKeyEvent* event); void SendModifier(XKeyEvent *event, unsigned int mask, int event_type);
int GetKeycode(KeySym keysym, unsigned int *mask);
bool keysymModifiers(KeySym keysym, int keycode, unsigned int *mask);
static int MyErrorHandler(Display* my_dpy, XErrorEvent* event); static int MyErrorHandler(Display* my_dpy, XErrorEvent* event);
Display* m_dpy; Display* m_dpy;
@@ -91,14 +99,20 @@ private:
static bool m_xErrorOccured; static bool m_xErrorOccured;
static int (*m_oldXErrorHandler)(Display*, XErrorEvent*); static int (*m_oldXErrorHandler)(Display*, XErrorEvent*);
static const int m_unicodeToKeysymLen;
static const uint m_unicodeToKeysymKeys[];
static const uint m_unicodeToKeysymValues[];
XkbDescPtr m_xkb;
KeySym* m_keysymTable; KeySym* m_keysymTable;
int m_minKeycode; int m_minKeycode;
int m_maxKeycode; int m_maxKeycode;
int m_keysymPerKeycode; int m_keysymPerKeycode;
int m_altMask; /* dedicated keycode for remapped keys */
int m_metaMask; unsigned int m_remapKeycode;
int m_altgrMask; KeySym m_currentRemapKeysym;
KeySym m_altgrKeysym; KeyCode m_modifier_keycode[N_MOD_INDICES];
bool m_loaded;
}; };
class AutoTypeExecturorX11 : public AutoTypeExecutor class AutoTypeExecturorX11 : public AutoTypeExecutor

View File

@@ -0,0 +1,169 @@
/*
* Automatically generated by keysymmap.py from parsing keysymdef.h.
*/
const int AutoTypePlatformX11::m_unicodeToKeysymLen = 632;
const uint AutoTypePlatformX11::m_unicodeToKeysymKeys[] = {
0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107,
0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e, 0x010f,
0x0110, 0x0111, 0x0112, 0x0113, 0x0116, 0x0117, 0x0118, 0x0119,
0x011a, 0x011b, 0x011c, 0x011d, 0x011e, 0x011f, 0x0120, 0x0121,
0x0122, 0x0123, 0x0124, 0x0125, 0x0126, 0x0127, 0x0128, 0x0129,
0x012a, 0x012b, 0x012e, 0x012f, 0x0130, 0x0131, 0x0134, 0x0135,
0x0136, 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d,
0x013e, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0147,
0x0148, 0x014a, 0x014b, 0x014c, 0x014d, 0x0150, 0x0151, 0x0152,
0x0153, 0x0154, 0x0155, 0x0156, 0x0157, 0x0158, 0x0159, 0x015a,
0x015b, 0x015c, 0x015d, 0x015e, 0x015f, 0x0160, 0x0161, 0x0162,
0x0163, 0x0164, 0x0165, 0x0166, 0x0167, 0x0168, 0x0169, 0x016a,
0x016b, 0x016c, 0x016d, 0x016e, 0x016f, 0x0170, 0x0171, 0x0172,
0x0173, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d, 0x017e,
0x0192, 0x02c7, 0x02d8, 0x02d9, 0x02db, 0x02dd, 0x0385, 0x0386,
0x0388, 0x0389, 0x038a, 0x038c, 0x038e, 0x038f, 0x0390, 0x0391,
0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399,
0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, 0x03a0, 0x03a1,
0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03aa,
0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03b0, 0x03b1, 0x03b2,
0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba,
0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c0, 0x03c1, 0x03c2,
0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03ca,
0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x0401, 0x0402, 0x0403, 0x0404,
0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040b, 0x040c,
0x040e, 0x040f, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415,
0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d,
0x041e, 0x041f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425,
0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d,
0x042e, 0x042f, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435,
0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d,
0x043e, 0x043f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445,
0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d,
0x044e, 0x044f, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456,
0x0457, 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x045e, 0x045f,
0x0490, 0x0491, 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5,
0x05d6, 0x05d7, 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd,
0x05de, 0x05df, 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5,
0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0x060c, 0x061b, 0x061f,
0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628,
0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, 0x0630,
0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638,
0x0639, 0x063a, 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645,
0x0646, 0x0647, 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d,
0x064e, 0x064f, 0x0650, 0x0651, 0x0652, 0x0e01, 0x0e02, 0x0e03,
0x0e04, 0x0e05, 0x0e06, 0x0e07, 0x0e08, 0x0e09, 0x0e0a, 0x0e0b,
0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, 0x0e10, 0x0e11, 0x0e12, 0x0e13,
0x0e14, 0x0e15, 0x0e16, 0x0e17, 0x0e18, 0x0e19, 0x0e1a, 0x0e1b,
0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, 0x0e20, 0x0e21, 0x0e22, 0x0e23,
0x0e24, 0x0e25, 0x0e26, 0x0e27, 0x0e28, 0x0e29, 0x0e2a, 0x0e2b,
0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, 0x0e30, 0x0e31, 0x0e32, 0x0e33,
0x0e34, 0x0e35, 0x0e36, 0x0e37, 0x0e38, 0x0e39, 0x0e3a, 0x0e3f,
0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e50, 0x0e51,
0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, 0x0e58, 0x0e59,
0x2002, 0x2003, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009, 0x200a,
0x2012, 0x2013, 0x2014, 0x2015, 0x2017, 0x2018, 0x2019, 0x201a,
0x201c, 0x201d, 0x201e, 0x2020, 0x2021, 0x2025, 0x2026, 0x2030,
0x2032, 0x2033, 0x2038, 0x203e, 0x20ac, 0x2105, 0x2116, 0x2117,
0x211e, 0x2122, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158,
0x2159, 0x215a, 0x215b, 0x215c, 0x215d, 0x215e, 0x2190, 0x2191,
0x2192, 0x2193, 0x21d2, 0x21d4, 0x2202, 0x2207, 0x2218, 0x221a,
0x221d, 0x221e, 0x2227, 0x2228, 0x2229, 0x222a, 0x222b, 0x2234,
0x223c, 0x2243, 0x2260, 0x2261, 0x2264, 0x2265, 0x2282, 0x2283,
0x22a2, 0x22a3, 0x22a4, 0x22a5, 0x2308, 0x230a, 0x2315, 0x2320,
0x2321, 0x2395, 0x239b, 0x239d, 0x239e, 0x23a0, 0x23a1, 0x23a3,
0x23a4, 0x23a6, 0x23a8, 0x23ac, 0x23b7, 0x23ba, 0x23bb, 0x23bc,
0x23bd, 0x2409, 0x240a, 0x240b, 0x240c, 0x240d, 0x2424, 0x2500,
0x2502, 0x250c, 0x2510, 0x2514, 0x2518, 0x251c, 0x2524, 0x252c,
0x2534, 0x253c, 0x2592, 0x25c6, 0x25cb, 0x260e, 0x2640, 0x2642,
0x2663, 0x2665, 0x2666, 0x266d, 0x266f, 0x2713, 0x2717, 0x271d,
0x2720, 0x3001, 0x3002, 0x300c, 0x300d, 0x309b, 0x309c, 0x30a1,
0x30a2, 0x30a3, 0x30a4, 0x30a5, 0x30a6, 0x30a7, 0x30a8, 0x30a9,
0x30aa, 0x30ab, 0x30ad, 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7,
0x30b9, 0x30bb, 0x30bd, 0x30bf, 0x30c1, 0x30c3, 0x30c4, 0x30c6,
0x30c8, 0x30ca, 0x30cb, 0x30cc, 0x30cd, 0x30ce, 0x30cf, 0x30d2,
0x30d5, 0x30d8, 0x30db, 0x30de, 0x30df, 0x30e0, 0x30e1, 0x30e2,
0x30e3, 0x30e4, 0x30e5, 0x30e6, 0x30e7, 0x30e8, 0x30e9, 0x30ea,
0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f2, 0x30f3, 0x30fb, 0x30fc
};
const uint AutoTypePlatformX11::m_unicodeToKeysymValues[] = {
0x03c0, 0x03e0, 0x01c3, 0x01e3, 0x01a1, 0x01b1, 0x01c6, 0x01e6,
0x02c6, 0x02e6, 0x02c5, 0x02e5, 0x01c8, 0x01e8, 0x01cf, 0x01ef,
0x01d0, 0x01f0, 0x03aa, 0x03ba, 0x03cc, 0x03ec, 0x01ca, 0x01ea,
0x01cc, 0x01ec, 0x02d8, 0x02f8, 0x02ab, 0x02bb, 0x02d5, 0x02f5,
0x03ab, 0x03bb, 0x02a6, 0x02b6, 0x02a1, 0x02b1, 0x03a5, 0x03b5,
0x03cf, 0x03ef, 0x03c7, 0x03e7, 0x02a9, 0x02b9, 0x02ac, 0x02bc,
0x03d3, 0x03f3, 0x03a2, 0x01c5, 0x01e5, 0x03a6, 0x03b6, 0x01a5,
0x01b5, 0x01a3, 0x01b3, 0x01d1, 0x01f1, 0x03d1, 0x03f1, 0x01d2,
0x01f2, 0x03bd, 0x03bf, 0x03d2, 0x03f2, 0x01d5, 0x01f5, 0x13bc,
0x13bd, 0x01c0, 0x01e0, 0x03a3, 0x03b3, 0x01d8, 0x01f8, 0x01a6,
0x01b6, 0x02de, 0x02fe, 0x01aa, 0x01ba, 0x01a9, 0x01b9, 0x01de,
0x01fe, 0x01ab, 0x01bb, 0x03ac, 0x03bc, 0x03dd, 0x03fd, 0x03de,
0x03fe, 0x02dd, 0x02fd, 0x01d9, 0x01f9, 0x01db, 0x01fb, 0x03d9,
0x03f9, 0x13be, 0x01ac, 0x01bc, 0x01af, 0x01bf, 0x01ae, 0x01be,
0x08f6, 0x01b7, 0x01a2, 0x01ff, 0x01b2, 0x01bd, 0x07ae, 0x07a1,
0x07a2, 0x07a3, 0x07a4, 0x07a7, 0x07a8, 0x07ab, 0x07b6, 0x07c1,
0x07c2, 0x07c3, 0x07c4, 0x07c5, 0x07c6, 0x07c7, 0x07c8, 0x07c9,
0x07ca, 0x07cb, 0x07cc, 0x07cd, 0x07ce, 0x07cf, 0x07d0, 0x07d1,
0x07d2, 0x07d4, 0x07d5, 0x07d6, 0x07d7, 0x07d8, 0x07d9, 0x07a5,
0x07a9, 0x07b1, 0x07b2, 0x07b3, 0x07b4, 0x07ba, 0x07e1, 0x07e2,
0x07e3, 0x07e4, 0x07e5, 0x07e6, 0x07e7, 0x07e8, 0x07e9, 0x07ea,
0x07eb, 0x07ec, 0x07ed, 0x07ee, 0x07ef, 0x07f0, 0x07f1, 0x07f3,
0x07f2, 0x07f4, 0x07f5, 0x07f6, 0x07f7, 0x07f8, 0x07f9, 0x07b5,
0x07b9, 0x07b7, 0x07b8, 0x07bb, 0x06b3, 0x06b1, 0x06b2, 0x06b4,
0x06b5, 0x06b6, 0x06b7, 0x06b8, 0x06b9, 0x06ba, 0x06bb, 0x06bc,
0x06be, 0x06bf, 0x06e1, 0x06e2, 0x06f7, 0x06e7, 0x06e4, 0x06e5,
0x06f6, 0x06fa, 0x06e9, 0x06ea, 0x06eb, 0x06ec, 0x06ed, 0x06ee,
0x06ef, 0x06f0, 0x06f2, 0x06f3, 0x06f4, 0x06f5, 0x06e6, 0x06e8,
0x06e3, 0x06fe, 0x06fb, 0x06fd, 0x06ff, 0x06f9, 0x06f8, 0x06fc,
0x06e0, 0x06f1, 0x06c1, 0x06c2, 0x06d7, 0x06c7, 0x06c4, 0x06c5,
0x06d6, 0x06da, 0x06c9, 0x06ca, 0x06cb, 0x06cc, 0x06cd, 0x06ce,
0x06cf, 0x06d0, 0x06d2, 0x06d3, 0x06d4, 0x06d5, 0x06c6, 0x06c8,
0x06c3, 0x06de, 0x06db, 0x06dd, 0x06df, 0x06d9, 0x06d8, 0x06dc,
0x06c0, 0x06d1, 0x06a3, 0x06a1, 0x06a2, 0x06a4, 0x06a5, 0x06a6,
0x06a7, 0x06a8, 0x06a9, 0x06aa, 0x06ab, 0x06ac, 0x06ae, 0x06af,
0x06bd, 0x06ad, 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5,
0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced,
0x0cee, 0x0cef, 0x0cf0, 0x0cf1, 0x0cf2, 0x0cf3, 0x0cf4, 0x0cf5,
0x0cf6, 0x0cf7, 0x0cf8, 0x0cf9, 0x0cfa, 0x05ac, 0x05bb, 0x05bf,
0x05c1, 0x05c2, 0x05c3, 0x05c4, 0x05c5, 0x05c6, 0x05c7, 0x05c8,
0x05c9, 0x05ca, 0x05cb, 0x05cc, 0x05cd, 0x05ce, 0x05cf, 0x05d0,
0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, 0x05d8,
0x05d9, 0x05da, 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5,
0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0x05eb, 0x05ec, 0x05ed,
0x05ee, 0x05ef, 0x05f0, 0x05f1, 0x05f2, 0x0da1, 0x0da2, 0x0da3,
0x0da4, 0x0da5, 0x0da6, 0x0da7, 0x0da8, 0x0da9, 0x0daa, 0x0dab,
0x0dac, 0x0dad, 0x0dae, 0x0daf, 0x0db0, 0x0db1, 0x0db2, 0x0db3,
0x0db4, 0x0db5, 0x0db6, 0x0db7, 0x0db8, 0x0db9, 0x0dba, 0x0dbb,
0x0dbc, 0x0dbd, 0x0dbe, 0x0dbf, 0x0dc0, 0x0dc1, 0x0dc2, 0x0dc3,
0x0dc4, 0x0dc5, 0x0dc6, 0x0dc7, 0x0dc8, 0x0dc9, 0x0dca, 0x0dcb,
0x0dcc, 0x0dcd, 0x0dce, 0x0dcf, 0x0dd0, 0x0dd1, 0x0dd2, 0x0dd3,
0x0dd4, 0x0dd5, 0x0dd6, 0x0dd7, 0x0dd8, 0x0dd9, 0x0dda, 0x0ddf,
0x0de0, 0x0de1, 0x0de2, 0x0de3, 0x0de4, 0x0de5, 0x0de6, 0x0de7,
0x0de8, 0x0de9, 0x0dea, 0x0deb, 0x0dec, 0x0ded, 0x0df0, 0x0df1,
0x0df2, 0x0df3, 0x0df4, 0x0df5, 0x0df6, 0x0df7, 0x0df8, 0x0df9,
0x0aa2, 0x0aa1, 0x0aa3, 0x0aa4, 0x0aa5, 0x0aa6, 0x0aa7, 0x0aa8,
0x0abb, 0x0aaa, 0x0aa9, 0x07af, 0x0cdf, 0x0ad0, 0x0ad1, 0x0afd,
0x0ad2, 0x0ad3, 0x0afe, 0x0af1, 0x0af2, 0x0aaf, 0x0aae, 0x0ad5,
0x0ad6, 0x0ad7, 0x0afc, 0x047e, 0x20ac, 0x0ab8, 0x06b0, 0x0afb,
0x0ad4, 0x0ac9, 0x0ab0, 0x0ab1, 0x0ab2, 0x0ab3, 0x0ab4, 0x0ab5,
0x0ab6, 0x0ab7, 0x0ac3, 0x0ac4, 0x0ac5, 0x0ac6, 0x08fb, 0x08fc,
0x08fd, 0x08fe, 0x08ce, 0x08cd, 0x08ef, 0x08c5, 0x0bca, 0x08d6,
0x08c1, 0x08c2, 0x08de, 0x08df, 0x08dc, 0x08dd, 0x08bf, 0x08c0,
0x08c8, 0x08c9, 0x08bd, 0x08cf, 0x08bc, 0x08be, 0x08da, 0x08db,
0x0bfc, 0x0bdc, 0x0bc2, 0x0bce, 0x0bd3, 0x0bc4, 0x0afa, 0x08a4,
0x08a5, 0x0bcc, 0x08ab, 0x08ac, 0x08ad, 0x08ae, 0x08a7, 0x08a8,
0x08a9, 0x08aa, 0x08af, 0x08b0, 0x08a1, 0x09ef, 0x09f0, 0x09f2,
0x09f3, 0x09e2, 0x09e5, 0x09e9, 0x09e3, 0x09e4, 0x09e8, 0x09f1,
0x09f8, 0x09ec, 0x09eb, 0x09ed, 0x09ea, 0x09f4, 0x09f5, 0x09f7,
0x09f6, 0x09ee, 0x09e1, 0x09e0, 0x0bcf, 0x0af9, 0x0af8, 0x0af7,
0x0aec, 0x0aee, 0x0aed, 0x0af6, 0x0af5, 0x0af3, 0x0af4, 0x0ad9,
0x0af0, 0x04a4, 0x04a1, 0x04a2, 0x04a3, 0x04de, 0x04df, 0x04a7,
0x04b1, 0x04a8, 0x04b2, 0x04a9, 0x04b3, 0x04aa, 0x04b4, 0x04ab,
0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc,
0x04bd, 0x04be, 0x04bf, 0x04c0, 0x04c1, 0x04af, 0x04c2, 0x04c3,
0x04c4, 0x04c5, 0x04c6, 0x04c7, 0x04c8, 0x04c9, 0x04ca, 0x04cb,
0x04cc, 0x04cd, 0x04ce, 0x04cf, 0x04d0, 0x04d1, 0x04d2, 0x04d3,
0x04ac, 0x04d4, 0x04ad, 0x04d5, 0x04ae, 0x04d6, 0x04d7, 0x04d8,
0x04d9, 0x04da, 0x04db, 0x04dc, 0x04a6, 0x04dd, 0x04a5, 0x04b0
};

107
src/autotype/x11/keysymmap.py Executable file
View File

@@ -0,0 +1,107 @@
#!/usr/bin/python3
#
# Copyright (C) 2013 Felix Geyer <debfx@fobos.de>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 or (at your option)
# version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#
# Parses keysymdef.h to construct a unicode symbol -> keysym mapping table.
#
# The lines that are parsed look like this:
# #define XK_Aogonek 0x01a1 /* U+0104 LATIN CAPITAL LETTER A WITH OGONEK */
#
# This would create a 0x0104 -> 0x01a1 mapping.
#
import sys
import re
import collections
cols = 8
if len(sys.argv) >= 2:
keysymdef = sys.argv[1]
else:
keysymdef = "/usr/include/X11/keysymdef.h"
keysymMap = {}
f = open(keysymdef, "r")
for line in f:
match = re.search(r'0x([0-9a-fA-F]+)\s+/\* U\+([0-9a-fA-F]+)', line)
if match:
keysym = int(match.group(1), 16)
unicodeVal = int(match.group(2), 16)
# ignore 1:1 mappings
if keysym >= 0x0020 and keysym <= 0x007e:
continue
if keysym >= 0x00a0 and keysym <= 0x00ff:
continue
# ignore unicode | 0x01000000 mappings
if keysym >= 0x1000000:
continue
keysymMap[unicodeVal] = keysym
keysymMap = collections.OrderedDict(sorted(keysymMap.items(), key=lambda t: t[0]))
print("""/*
* Automatically generated by keysymmap.py from parsing keysymdef.h.
*/
""")
print("const int AutoTypePlatformX11::m_unicodeToKeysymLen = " + str(len(keysymMap)) + ";")
print()
print("const uint AutoTypePlatformX11::m_unicodeToKeysymKeys[] = {")
keys = keysymMap.keys()
keyLen = len(keys)
i = 1
for val in keys:
hexVal = "{0:#0{1}x}".format(val, 6)
if i == keyLen:
print(hexVal)
elif (i % cols) == 0:
print(hexVal + ",")
elif ((i - 1) % cols) == 0:
print(" " + hexVal + ", ", end="")
else:
print(hexVal + ", ", end="")
i += 1
print("};")
print()
print("const uint AutoTypePlatformX11::m_unicodeToKeysymValues[] = {")
values = keysymMap.values()
valuesLen = len(values)
i = 1
for val in values:
hexVal = "{0:#0{1}x}".format(val, 6)
if i == valuesLen:
print(hexVal)
elif (i % cols) == 0:
print(hexVal + ",")
elif ((i - 1) % cols) == 0:
print(" " + hexVal + ", ", end="")
else:
print(hexVal + ", ", end="")
i += 1
print("};")

View File

@@ -1,14 +1,18 @@
/* config-keepassx.h. Generated by cmake from config-keepassx.h.cmake */ /* config-keepassx.h. Generated by cmake from config-keepassx.h.cmake */
#ifndef KEEPASSX_CONFIG_H #ifndef KEEPASSX_CONFIG_KEEPASSX_H
#define KEEPASSX_CONFIG_H #define KEEPASSX_CONFIG_KEEPASSX_H
#define KEEPASSX_VERSION "${KEEPASSX_VERSION}" #define KEEPASSX_VERSION "${KEEPASSX_VERSION}"
#define KEEPASSX_SOURCE_DIR "${CMAKE_SOURCE_DIR}" #define KEEPASSX_SOURCE_DIR "${CMAKE_SOURCE_DIR}"
#define KEEPASSX_PLUGIN_DIR "${PLUGIN_INSTALL_DIR}"
#cmakedefine HAVE_PR_SET_DUMPABLE 1 #cmakedefine HAVE_PR_SET_DUMPABLE 1
#cmakedefine HAVE_RLIMIT_CORE 1 #cmakedefine HAVE_RLIMIT_CORE 1
#cmakedefine HAVE_PT_DENY_ATTACH 1 #cmakedefine HAVE_PT_DENY_ATTACH 1
#endif // KEEPASSX_CONFIG_H #cmakedefine GCRYPT_HAS_SALSA20
#endif // KEEPASSX_CONFIG_KEEPASSX_H

View File

@@ -18,7 +18,7 @@
#ifndef KEEPASSX_AUTOTYPEASSOCIATIONS_H #ifndef KEEPASSX_AUTOTYPEASSOCIATIONS_H
#define KEEPASSX_AUTOTYPEASSOCIATIONS_H #define KEEPASSX_AUTOTYPEASSOCIATIONS_H
#include <QtCore/QObject> #include <QObject>
#include "core/Global.h" #include "core/Global.h"

View File

@@ -17,11 +17,11 @@
#include "Config.h" #include "Config.h"
#include <QtCore/QDir> #include <QCoreApplication>
#include <QtCore/QSettings> #include <QDesktopServices>
#include <QtCore/QTemporaryFile> #include <QDir>
#include <QtGui/QApplication> #include <QSettings>
#include <QtGui/QDesktopServices> #include <QTemporaryFile>
Config* Config::m_instance(Q_NULLPTR); Config* Config::m_instance(Q_NULLPTR);
@@ -71,7 +71,7 @@ Config::Config(QObject* parent)
userPath += "/keepassx/"; userPath += "/keepassx/";
#else #else
userPath = QDir::fromNativeSeparators(QDesktopServices::storageLocation(QDesktopServices::DataLocation)); userPath = QDir::fromNativeSeparators(QDesktopServices::storageLocation(QDesktopServices::DataLocation));
userPath += "/keepassx/"; // storageLocation() appends the application name ("/keepassx/") to the end
#endif #endif
userPath += "keepassx2.ini"; userPath += "keepassx2.ini";
@@ -88,12 +88,17 @@ void Config::init(const QString& fileName)
m_settings.reset(new QSettings(fileName, QSettings::IniFormat)); m_settings.reset(new QSettings(fileName, QSettings::IniFormat));
m_defaults.insert("RememberLastDatabases", true); m_defaults.insert("RememberLastDatabases", true);
m_defaults.insert("OpenPreviousDatabasesOnStartup", true);
m_defaults.insert("ModifiedOnExpandedStateChanges", true); m_defaults.insert("ModifiedOnExpandedStateChanges", true);
m_defaults.insert("AutoSaveAfterEveryChange", false); m_defaults.insert("AutoSaveAfterEveryChange", false);
m_defaults.insert("AutoSaveOnExit", false); m_defaults.insert("AutoSaveOnExit", false);
m_defaults.insert("ShowToolbar", true); m_defaults.insert("ShowToolbar", true);
m_defaults.insert("MinimizeOnCopy", false);
m_defaults.insert("security/clearclipboard", true); m_defaults.insert("security/clearclipboard", true);
m_defaults.insert("security/clearclipboardtimeout", 10); m_defaults.insert("security/clearclipboardtimeout", 10);
m_defaults.insert("security/lockdatabaseidle", false);
m_defaults.insert("security/lockdatabaseidlesec", 10);
m_defaults.insert("security/passwordscleartext", false);
} }
Config* Config::instance() Config* Config::instance()
@@ -105,6 +110,12 @@ Config* Config::instance()
return m_instance; return m_instance;
} }
void Config::createConfigFromFile(QString file)
{
Q_ASSERT(!m_instance);
m_instance = new Config(file, qApp);
}
void Config::createTempFileInstance() void Config::createTempFileInstance()
{ {
Q_ASSERT(!m_instance); Q_ASSERT(!m_instance);

View File

@@ -18,8 +18,8 @@
#ifndef KEEPASSX_CONFIG_H #ifndef KEEPASSX_CONFIG_H
#define KEEPASSX_CONFIG_H #define KEEPASSX_CONFIG_H
#include <QtCore/QScopedPointer> #include <QScopedPointer>
#include <QtCore/QVariant> #include <QVariant>
#include "core/Global.h" #include "core/Global.h"
@@ -36,6 +36,7 @@ public:
void set(const QString& key, const QVariant& value); void set(const QString& key, const QVariant& value);
static Config* instance(); static Config* instance();
static void createConfigFromFile(QString file);
static void createTempFileInstance(); static void createTempFileInstance();
private: private:

View File

@@ -17,9 +17,9 @@
#include "Database.h" #include "Database.h"
#include <QtCore/QFile> #include <QFile>
#include <QtCore/QTimer> #include <QTimer>
#include <QtCore/QXmlStreamReader> #include <QXmlStreamReader>
#include "core/Group.h" #include "core/Group.h"
#include "core/Metadata.h" #include "core/Metadata.h"
@@ -32,13 +32,14 @@ QHash<Uuid, Database*> Database::m_uuidMap;
Database::Database() Database::Database()
: m_metadata(new Metadata(this)) : m_metadata(new Metadata(this))
, m_timer(new QTimer(this)) , m_timer(new QTimer(this))
, m_cipher(KeePass2::CIPHER_AES)
, m_compressionAlgo(CompressionGZip)
, m_transformRounds(50000)
, m_hasKey(false)
, m_emitModified(false) , m_emitModified(false)
, m_uuid(Uuid::random()) , m_uuid(Uuid::random())
{ {
m_data.cipher = KeePass2::CIPHER_AES;
m_data.compressionAlgo = CompressionGZip;
m_data.transformRounds = 50000;
m_data.hasKey = false;
setRootGroup(new Group()); setRootGroup(new Group());
rootGroup()->setUuid(Uuid::random()); rootGroup()->setUuid(Uuid::random());
m_timer->setSingleShot(true); m_timer->setSingleShot(true);
@@ -150,60 +151,60 @@ void Database::addDeletedObject(const Uuid& uuid)
Uuid Database::cipher() const Uuid Database::cipher() const
{ {
return m_cipher; return m_data.cipher;
} }
Database::CompressionAlgorithm Database::compressionAlgo() const Database::CompressionAlgorithm Database::compressionAlgo() const
{ {
return m_compressionAlgo; return m_data.compressionAlgo;
} }
QByteArray Database::transformSeed() const QByteArray Database::transformSeed() const
{ {
return m_transformSeed; return m_data.transformSeed;
} }
quint64 Database::transformRounds() const quint64 Database::transformRounds() const
{ {
return m_transformRounds; return m_data.transformRounds;
} }
QByteArray Database::transformedMasterKey() const QByteArray Database::transformedMasterKey() const
{ {
return m_transformedMasterKey; return m_data.transformedMasterKey;
} }
void Database::setCipher(const Uuid& cipher) void Database::setCipher(const Uuid& cipher)
{ {
Q_ASSERT(!cipher.isNull()); Q_ASSERT(!cipher.isNull());
m_cipher = cipher; m_data.cipher = cipher;
} }
void Database::setCompressionAlgo(Database::CompressionAlgorithm algo) void Database::setCompressionAlgo(Database::CompressionAlgorithm algo)
{ {
Q_ASSERT(static_cast<quint32>(algo) <= CompressionAlgorithmMax); Q_ASSERT(static_cast<quint32>(algo) <= CompressionAlgorithmMax);
m_compressionAlgo = algo; m_data.compressionAlgo = algo;
} }
void Database::setTransformRounds(quint64 rounds) void Database::setTransformRounds(quint64 rounds)
{ {
if (m_transformRounds != rounds) { if (m_data.transformRounds != rounds) {
m_transformRounds = rounds; m_data.transformRounds = rounds;
if (m_hasKey) { if (m_data.hasKey) {
setKey(m_key); setKey(m_data.key);
} }
} }
} }
void Database::setKey(const CompositeKey& key, const QByteArray& transformSeed, bool updateChangedTime) void Database::setKey(const CompositeKey& key, const QByteArray& transformSeed, bool updateChangedTime)
{ {
m_key = key; m_data.key = key;
m_transformSeed = transformSeed; m_data.transformSeed = transformSeed;
m_transformedMasterKey = key.transform(transformSeed, transformRounds()); m_data.transformedMasterKey = key.transform(transformSeed, transformRounds());
m_hasKey = true; m_data.hasKey = true;
if (updateChangedTime) { if (updateChangedTime) {
m_metadata->setMasterKeyChanged(Tools::currentDateTimeUtc()); m_metadata->setMasterKeyChanged(Tools::currentDateTimeUtc());
} }
@@ -212,19 +213,19 @@ void Database::setKey(const CompositeKey& key, const QByteArray& transformSeed,
void Database::setKey(const CompositeKey& key) void Database::setKey(const CompositeKey& key)
{ {
setKey(key, Random::randomArray(32)); setKey(key, randomGen()->randomArray(32));
} }
bool Database::hasKey() const bool Database::hasKey() const
{ {
return m_hasKey; return m_data.hasKey;
} }
bool Database::verifyKey(const CompositeKey& key) const bool Database::verifyKey(const CompositeKey& key) const
{ {
Q_ASSERT(hasKey()); Q_ASSERT(hasKey());
return (m_key.rawKey() == key.rawKey()); return (m_data.key.rawKey() == key.rawKey());
} }
void Database::createRecycleBin() void Database::createRecycleBin()
@@ -269,6 +270,12 @@ void Database::setEmitModified(bool value)
m_emitModified = value; m_emitModified = value;
} }
void Database::copyAttributesFrom(const Database* other)
{
m_data = other->m_data;
m_metadata->copyAttributesFrom(other->m_metadata);
}
Uuid Database::uuid() Uuid Database::uuid()
{ {
return m_uuid; return m_uuid;

View File

@@ -18,8 +18,8 @@
#ifndef KEEPASSX_DATABASE_H #ifndef KEEPASSX_DATABASE_H
#define KEEPASSX_DATABASE_H #define KEEPASSX_DATABASE_H
#include <QtCore/QDateTime> #include <QDateTime>
#include <QtCore/QHash> #include <QHash>
#include "core/Uuid.h" #include "core/Uuid.h"
#include "keys/CompositeKey.h" #include "keys/CompositeKey.h"
@@ -49,6 +49,17 @@ public:
}; };
static const quint32 CompressionAlgorithmMax = CompressionGZip; static const quint32 CompressionAlgorithmMax = CompressionGZip;
struct DatabaseData
{
Uuid cipher;
CompressionAlgorithm compressionAlgo;
QByteArray transformSeed;
quint64 transformRounds;
QByteArray transformedMasterKey;
CompositeKey key;
bool hasKey;
};
Database(); Database();
~Database(); ~Database();
Group* rootGroup(); Group* rootGroup();
@@ -91,6 +102,7 @@ public:
void recycleEntry(Entry* entry); void recycleEntry(Entry* entry);
void recycleGroup(Group* group); void recycleGroup(Group* group);
void setEmitModified(bool value); void setEmitModified(bool value);
void copyAttributesFrom(const Database* other);
/** /**
* Returns a unique id that is only valid as long as the Database exists. * Returns a unique id that is only valid as long as the Database exists.
@@ -124,15 +136,7 @@ private:
Group* m_rootGroup; Group* m_rootGroup;
QList<DeletedObject> m_deletedObjects; QList<DeletedObject> m_deletedObjects;
QTimer* m_timer; QTimer* m_timer;
DatabaseData m_data;
Uuid m_cipher;
CompressionAlgorithm m_compressionAlgo;
QByteArray m_transformSeed;
quint64 m_transformRounds;
QByteArray m_transformedMasterKey;
CompositeKey m_key;
bool m_hasKey;
bool m_emitModified; bool m_emitModified;
Uuid m_uuid; Uuid m_uuid;

View File

@@ -18,10 +18,10 @@
#ifndef KEEPASSX_DATABASEICONS_H #ifndef KEEPASSX_DATABASEICONS_H
#define KEEPASSX_DATABASEICONS_H #define KEEPASSX_DATABASEICONS_H
#include <QtCore/QVector> #include <QImage>
#include <QtGui/QImage> #include <QPixmap>
#include <QtGui/QPixmap> #include <QPixmapCache>
#include <QtGui/QPixmapCache> #include <QVector>
#include "core/Global.h" #include "core/Global.h"

View File

@@ -17,8 +17,8 @@
#include "Endian.h" #include "Endian.h"
#include <QtCore/QtEndian> #include <QtEndian>
#include <QtCore/QIODevice> #include <QIODevice>
namespace Endian { namespace Endian {

View File

@@ -18,8 +18,8 @@
#ifndef KEEPASSX_ENDIAN_H #ifndef KEEPASSX_ENDIAN_H
#define KEEPASSX_ENDIAN_H #define KEEPASSX_ENDIAN_H
#include <QtCore/QByteArray> #include <QByteArray>
#include <QtCore/QSysInfo> #include <QSysInfo>
class QIODevice; class QIODevice;

View File

@@ -30,6 +30,7 @@ Entry::Entry()
, m_attachments(new EntryAttachments(this)) , m_attachments(new EntryAttachments(this))
, m_autoTypeAssociations(new AutoTypeAssociations(this)) , m_autoTypeAssociations(new AutoTypeAssociations(this))
, m_tmpHistoryItem(Q_NULLPTR) , m_tmpHistoryItem(Q_NULLPTR)
, m_modifiedSinceBegin(false)
, m_updateTimeinfo(true) , m_updateTimeinfo(true)
{ {
m_data.iconNumber = DefaultIconNumber; m_data.iconNumber = DefaultIconNumber;
@@ -94,8 +95,14 @@ QImage Entry::icon() const
return databaseIcons()->icon(m_data.iconNumber); return databaseIcons()->icon(m_data.iconNumber);
} }
else { else {
// TODO: check if database() is 0 Q_ASSERT(database());
return database()->metadata()->customIcon(m_data.customIcon);
if (database()) {
return database()->metadata()->customIcon(m_data.customIcon);
}
else {
return QImage();
}
} }
} }
@@ -105,9 +112,10 @@ QPixmap Entry::iconPixmap() const
return databaseIcons()->iconPixmap(m_data.iconNumber); return databaseIcons()->iconPixmap(m_data.iconNumber);
} }
else { else {
Q_ASSERT(database());
QPixmap pixmap; QPixmap pixmap;
if (!QPixmapCache::find(m_pixmapCacheKey, &pixmap)) { if (database() && !QPixmapCache::find(m_pixmapCacheKey, &pixmap)) {
// TODO: check if database() is 0
pixmap = QPixmap::fromImage(database()->metadata()->customIcon(m_data.customIcon)); pixmap = QPixmap::fromImage(database()->metadata()->customIcon(m_data.customIcon));
m_pixmapCacheKey = QPixmapCache::insert(pixmap); m_pixmapCacheKey = QPixmapCache::insert(pixmap);
} }
@@ -178,27 +186,27 @@ const AutoTypeAssociations* Entry::autoTypeAssociations() const
QString Entry::title() const QString Entry::title() const
{ {
return m_attributes->value("Title"); return m_attributes->value(EntryAttributes::TitleKey);
} }
QString Entry::url() const QString Entry::url() const
{ {
return m_attributes->value("URL"); return m_attributes->value(EntryAttributes::URLKey);
} }
QString Entry::username() const QString Entry::username() const
{ {
return m_attributes->value("UserName"); return m_attributes->value(EntryAttributes::UserNameKey);
} }
QString Entry::password() const QString Entry::password() const
{ {
return m_attributes->value("Password"); return m_attributes->value(EntryAttributes::PasswordKey);
} }
QString Entry::notes() const QString Entry::notes() const
{ {
return m_attributes->value("Notes"); return m_attributes->value(EntryAttributes::NotesKey);
} }
bool Entry::isExpired() const bool Entry::isExpired() const
@@ -304,27 +312,27 @@ void Entry::setDefaultAutoTypeSequence(const QString& sequence)
void Entry::setTitle(const QString& title) void Entry::setTitle(const QString& title)
{ {
m_attributes->set("Title", title, m_attributes->isProtected("Title")); m_attributes->set(EntryAttributes::TitleKey, title, m_attributes->isProtected(EntryAttributes::TitleKey));
} }
void Entry::setUrl(const QString& url) void Entry::setUrl(const QString& url)
{ {
m_attributes->set("URL", url, m_attributes->isProtected("URL")); m_attributes->set(EntryAttributes::URLKey, url, m_attributes->isProtected(EntryAttributes::URLKey));
} }
void Entry::setUsername(const QString& username) void Entry::setUsername(const QString& username)
{ {
m_attributes->set("UserName", username, m_attributes->isProtected("UserName")); m_attributes->set(EntryAttributes::UserNameKey, username, m_attributes->isProtected(EntryAttributes::UserNameKey));
} }
void Entry::setPassword(const QString& password) void Entry::setPassword(const QString& password)
{ {
m_attributes->set("Password", password, m_attributes->isProtected("Password")); m_attributes->set(EntryAttributes::PasswordKey, password, m_attributes->isProtected(EntryAttributes::PasswordKey));
} }
void Entry::setNotes(const QString& notes) void Entry::setNotes(const QString& notes)
{ {
m_attributes->set("Notes", notes, m_attributes->isProtected("Notes")); m_attributes->set(EntryAttributes::NotesKey, notes, m_attributes->isProtected(EntryAttributes::NotesKey));
} }
void Entry::setExpires(const bool& value) void Entry::setExpires(const bool& value)
@@ -432,26 +440,54 @@ void Entry::truncateHistory()
} }
} }
Entry* Entry::clone() const Entry* Entry::clone(CloneFlags flags) const
{ {
Entry* entry = new Entry(); Entry* entry = new Entry();
entry->setUpdateTimeinfo(false); entry->setUpdateTimeinfo(false);
entry->m_uuid = m_uuid; if (flags & CloneNewUuid) {
entry->m_uuid = Uuid::random();
}
else {
entry->m_uuid = m_uuid;
}
entry->m_data = m_data; entry->m_data = m_data;
entry->m_attributes->copyDataFrom(m_attributes); entry->m_attributes->copyDataFrom(m_attributes);
entry->m_attachments->copyDataFrom(m_attachments); entry->m_attachments->copyDataFrom(m_attachments);
entry->m_autoTypeAssociations->copyDataFrom(this->m_autoTypeAssociations); entry->m_autoTypeAssociations->copyDataFrom(this->m_autoTypeAssociations);
if (flags & CloneIncludeHistory) {
Q_FOREACH (Entry* historyItem, m_history) {
Entry* historyItemClone = historyItem->clone(flags & ~CloneIncludeHistory & ~CloneNewUuid);
historyItemClone->setUpdateTimeinfo(false);
historyItemClone->setUuid(entry->uuid());
historyItemClone->setUpdateTimeinfo(true);
entry->addHistoryItem(historyItemClone);
}
}
entry->setUpdateTimeinfo(true); entry->setUpdateTimeinfo(true);
QDateTime now = Tools::currentDateTimeUtc(); if (flags & CloneResetTimeInfo) {
entry->m_data.timeInfo.setCreationTime(now); QDateTime now = Tools::currentDateTimeUtc();
entry->m_data.timeInfo.setLastModificationTime(now); entry->m_data.timeInfo.setCreationTime(now);
entry->m_data.timeInfo.setLastAccessTime(now); entry->m_data.timeInfo.setLastModificationTime(now);
entry->m_data.timeInfo.setLocationChanged(now); entry->m_data.timeInfo.setLastAccessTime(now);
entry->m_data.timeInfo.setLocationChanged(now);
}
return entry; return entry;
} }
void Entry::copyDataFrom(const Entry* other)
{
setUpdateTimeinfo(false);
m_data = other->m_data;
m_attributes->copyDataFrom(other->m_attributes);
m_attachments->copyDataFrom(other->m_attachments);
m_autoTypeAssociations->copyDataFrom(other->m_autoTypeAssociations);
setUpdateTimeinfo(true);
}
void Entry::beginUpdate() void Entry::beginUpdate()
{ {
Q_ASSERT(!m_tmpHistoryItem); Q_ASSERT(!m_tmpHistoryItem);

View File

@@ -18,14 +18,14 @@
#ifndef KEEPASSX_ENTRY_H #ifndef KEEPASSX_ENTRY_H
#define KEEPASSX_ENTRY_H #define KEEPASSX_ENTRY_H
#include <QtCore/QMap> #include <QColor>
#include <QtCore/QPointer> #include <QImage>
#include <QtCore/QSet> #include <QMap>
#include <QtCore/QUrl> #include <QPixmap>
#include <QtGui/QColor> #include <QPixmapCache>
#include <QtGui/QImage> #include <QPointer>
#include <QtGui/QPixmap> #include <QSet>
#include <QtGui/QPixmapCache> #include <QUrl>
#include "core/AutoTypeAssociations.h" #include "core/AutoTypeAssociations.h"
#include "core/EntryAttachments.h" #include "core/EntryAttachments.h"
@@ -110,7 +110,23 @@ public:
void addHistoryItem(Entry* entry); void addHistoryItem(Entry* entry);
void removeHistoryItems(const QList<Entry*>& historyEntries); void removeHistoryItems(const QList<Entry*>& historyEntries);
void truncateHistory(); void truncateHistory();
Entry* clone() const;
enum CloneFlag {
CloneNoFlags = 0,
CloneNewUuid = 1, // generate a random uuid for the clone
CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time
CloneIncludeHistory = 4 // clone the history items
};
Q_DECLARE_FLAGS(CloneFlags, CloneFlag)
/**
* Creates a duplicate of this entry except that the returned entry isn't
* part of any group.
* Note that you need to copy the custom icons manually when inserting the
* new entry into another database.
*/
Entry* clone(CloneFlags flags) const;
void copyDataFrom(const Entry* other);
QString resolvePlaceholders(const QString& str) const; QString resolvePlaceholders(const QString& str) const;
/** /**
@@ -159,4 +175,6 @@ private:
bool m_updateTimeinfo; bool m_updateTimeinfo;
}; };
Q_DECLARE_OPERATORS_FOR_FLAGS(Entry::CloneFlags)
#endif // KEEPASSX_ENTRY_H #endif // KEEPASSX_ENTRY_H

View File

@@ -18,8 +18,8 @@
#ifndef KEEPASSX_ENTRYATTACHMENTS_H #ifndef KEEPASSX_ENTRYATTACHMENTS_H
#define KEEPASSX_ENTRYATTACHMENTS_H #define KEEPASSX_ENTRYATTACHMENTS_H
#include <QtCore/QMap> #include <QMap>
#include <QtCore/QObject> #include <QObject>
#include "core/Global.h" #include "core/Global.h"

View File

@@ -17,8 +17,13 @@
#include "EntryAttributes.h" #include "EntryAttributes.h"
const QStringList EntryAttributes::DefaultAttributes(QStringList() << "Title" << "UserName" const QString EntryAttributes::TitleKey = "Title";
<< "Password" << "URL" << "Notes"); const QString EntryAttributes::UserNameKey = "UserName";
const QString EntryAttributes::PasswordKey = "Password";
const QString EntryAttributes::URLKey = "URL";
const QString EntryAttributes::NotesKey = "Notes";
const QStringList EntryAttributes::DefaultAttributes(QStringList() << TitleKey << UserNameKey
<< PasswordKey << URLKey << NotesKey);
EntryAttributes::EntryAttributes(QObject* parent) EntryAttributes::EntryAttributes(QObject* parent)
: QObject(parent) : QObject(parent)

View File

@@ -18,10 +18,10 @@
#ifndef KEEPASSX_ENTRYATTRIBUTES_H #ifndef KEEPASSX_ENTRYATTRIBUTES_H
#define KEEPASSX_ENTRYATTRIBUTES_H #define KEEPASSX_ENTRYATTRIBUTES_H
#include <QtCore/QMap> #include <QMap>
#include <QtCore/QSet> #include <QObject>
#include <QtCore/QObject> #include <QSet>
#include <QtCore/QStringList> #include <QStringList>
#include "core/Global.h" #include "core/Global.h"
@@ -46,6 +46,11 @@ public:
bool operator==(const EntryAttributes& other) const; bool operator==(const EntryAttributes& other) const;
bool operator!=(const EntryAttributes& other) const; bool operator!=(const EntryAttributes& other) const;
static const QString TitleKey;
static const QString UserNameKey;
static const QString PasswordKey;
static const QString URLKey;
static const QString NotesKey;
static const QStringList DefaultAttributes; static const QStringList DefaultAttributes;
static bool isDefaultAttribute(const QString& key); static bool isDefaultAttribute(const QString& key);

View File

@@ -17,9 +17,9 @@
#include "FilePath.h" #include "FilePath.h"
#include <QtCore/QCoreApplication> #include <QCoreApplication>
#include <QtCore/QDir> #include <QDir>
#include <QtCore/QLibrary> #include <QLibrary>
#include "config-keepassx.h" #include "config-keepassx.h"
@@ -48,7 +48,15 @@ QString FilePath::pluginPath(const QString& name)
pluginPaths << QCoreApplication::applicationDirPath() + "/../src/autotype/test"; pluginPaths << QCoreApplication::applicationDirPath() + "/../src/autotype/test";
pluginPaths << QCoreApplication::applicationDirPath(); pluginPaths << QCoreApplication::applicationDirPath();
pluginPaths << QCoreApplication::applicationDirPath() + "/../lib/keepassx";
QString systemPluginDir = KEEPASSX_PLUGIN_DIR;
if (systemPluginDir != ".") {
if (!QDir(systemPluginDir).isAbsolute()) {
systemPluginDir = QCoreApplication::applicationDirPath() + "/../" + systemPluginDir;
systemPluginDir = QDir(systemPluginDir).canonicalPath();
}
pluginPaths << systemPluginDir;
}
QStringList dirFilter; QStringList dirFilter;
dirFilter << QString("*%1*").arg(name); dirFilter << QString("*%1*").arg(name);
@@ -109,6 +117,51 @@ QIcon FilePath::icon(const QString& category, const QString& name, bool fromThem
return icon; return icon;
} }
QIcon FilePath::onOffIcon(const QString& category, const QString& name)
{
QString combinedName = category + "/" + name;
QString cacheName = "onoff/" + combinedName;
QIcon icon = m_iconCache.value(cacheName);
if (!icon.isNull()) {
return icon;
}
for (int i = 0; i < 2; i++) {
QIcon::State state;
QString stateName;
if (i == 0) {
state = QIcon::Off;
stateName = "off";
}
else {
state = QIcon::On;
stateName = "on";
}
QList<int> pngSizes;
pngSizes << 16 << 22 << 24 << 32 << 48 << 64 << 128;
QString filename;
Q_FOREACH (int size, pngSizes) {
filename = QString("%1/icons/application/%2x%2/%3-%4.png").arg(m_dataPath, QString::number(size),
combinedName, stateName);
if (QFile::exists(filename)) {
icon.addFile(filename, QSize(size, size), QIcon::Normal, state);
}
}
filename = QString("%1/icons/application/scalable/%3-%4.svgz").arg(m_dataPath, combinedName, stateName);
if (QFile::exists(filename)) {
icon.addFile(filename, QSize(), QIcon::Normal, state);
}
}
m_iconCache.insert(cacheName, icon);
return icon;
}
FilePath::FilePath() FilePath::FilePath()
{ {
if (false) { if (false) {

View File

@@ -18,9 +18,9 @@
#ifndef KEEPASSX_FILEPATH_H #ifndef KEEPASSX_FILEPATH_H
#define KEEPASSX_FILEPATH_H #define KEEPASSX_FILEPATH_H
#include <QtCore/QHash> #include <QHash>
#include <QtCore/QString> #include <QIcon>
#include <QtGui/QIcon> #include <QString>
#include "core/Global.h" #include "core/Global.h"
@@ -31,6 +31,7 @@ public:
QString pluginPath(const QString& name); QString pluginPath(const QString& name);
QIcon applicationIcon(); QIcon applicationIcon();
QIcon icon(const QString& category, const QString& name, bool fromTheme = true); QIcon icon(const QString& category, const QString& name, bool fromTheme = true);
QIcon onOffIcon(const QString& category, const QString& name);
static FilePath* instance(); static FilePath* instance();

View File

@@ -22,7 +22,7 @@
// mostly copied from qcompilerdetection.h which is part of Qt 5 // mostly copied from qcompilerdetection.h which is part of Qt 5
#include <QtCore/QtGlobal> #include <QtGlobal>
#ifdef Q_CC_CLANG #ifdef Q_CC_CLANG
# if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) # if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
@@ -125,7 +125,11 @@ template <> class QStaticAssertFailure<true> {};
# define KEEPASSX_EXPORT Q_DECL_IMPORT # define KEEPASSX_EXPORT Q_DECL_IMPORT
# endif # endif
#else #else
# define KEEPASSX_EXPORT # define KEEPASSX_EXPORT Q_DECL_EXPORT
#endif
#ifndef QUINT32_MAX
#define QUINT32_MAX 4294967295U
#endif #endif
#endif // KEEPASSX_GLOBAL_H #endif // KEEPASSX_GLOBAL_H

View File

@@ -26,12 +26,12 @@ const int Group::DefaultIconNumber = 48;
const int Group::RecycleBinIconNumber = 43; const int Group::RecycleBinIconNumber = 43;
Group::Group() Group::Group()
: m_iconNumber(DefaultIconNumber) : m_updateTimeinfo(true)
, m_isExpanded(true)
, m_autoTypeEnabled(Inherit)
, m_searchingEnabled(Inherit)
, m_updateTimeinfo(true)
{ {
m_data.iconNumber = DefaultIconNumber;
m_data.isExpanded = true;
m_data.autoTypeEnabled = Inherit;
m_data.searchingEnabled = Inherit;
} }
Group::~Group() Group::~Group()
@@ -84,8 +84,8 @@ template <class P, class V> inline bool Group::set(P& property, const V& value)
void Group::updateTimeinfo() void Group::updateTimeinfo()
{ {
if (m_updateTimeinfo) { if (m_updateTimeinfo) {
m_timeInfo.setLastModificationTime(Tools::currentDateTimeUtc()); m_data.timeInfo.setLastModificationTime(Tools::currentDateTimeUtc());
m_timeInfo.setLastAccessTime(Tools::currentDateTimeUtc()); m_data.timeInfo.setLastAccessTime(Tools::currentDateTimeUtc());
} }
} }
@@ -101,35 +101,42 @@ Uuid Group::uuid() const
QString Group::name() const QString Group::name() const
{ {
return m_name; return m_data.name;
} }
QString Group::notes() const QString Group::notes() const
{ {
return m_notes; return m_data.notes;
} }
QImage Group::icon() const QImage Group::icon() const
{ {
if (m_customIcon.isNull()) { if (m_data.customIcon.isNull()) {
return databaseIcons()->icon(m_iconNumber); return databaseIcons()->icon(m_data.iconNumber);
} }
else { else {
// TODO: check if m_db is 0 Q_ASSERT(m_db);
return m_db->metadata()->customIcon(m_customIcon);
if (m_db) {
return m_db->metadata()->customIcon(m_data.customIcon);
}
else {
return QImage();
}
} }
} }
QPixmap Group::iconPixmap() const QPixmap Group::iconPixmap() const
{ {
if (m_customIcon.isNull()) { if (m_data.customIcon.isNull()) {
return databaseIcons()->iconPixmap(m_iconNumber); return databaseIcons()->iconPixmap(m_data.iconNumber);
} }
else { else {
Q_ASSERT(m_db);
QPixmap pixmap; QPixmap pixmap;
if (!QPixmapCache::find(m_pixmapCacheKey, &pixmap)) { if (m_db && !QPixmapCache::find(m_pixmapCacheKey, &pixmap)) {
// TODO: check if m_db is 0 pixmap = QPixmap::fromImage(m_db->metadata()->customIcon(m_data.customIcon));
pixmap = QPixmap::fromImage(m_db->metadata()->customIcon(m_customIcon));
m_pixmapCacheKey = QPixmapCache::insert(pixmap); m_pixmapCacheKey = QPixmapCache::insert(pixmap);
} }
@@ -139,37 +146,37 @@ QPixmap Group::iconPixmap() const
int Group::iconNumber() const int Group::iconNumber() const
{ {
return m_iconNumber; return m_data.iconNumber;
} }
Uuid Group::iconUuid() const Uuid Group::iconUuid() const
{ {
return m_customIcon; return m_data.customIcon;
} }
TimeInfo Group::timeInfo() const TimeInfo Group::timeInfo() const
{ {
return m_timeInfo; return m_data.timeInfo;
} }
bool Group::isExpanded() const bool Group::isExpanded() const
{ {
return m_isExpanded; return m_data.isExpanded;
} }
QString Group::defaultAutoTypeSequence() const QString Group::defaultAutoTypeSequence() const
{ {
return m_defaultAutoTypeSequence; return m_data.defaultAutoTypeSequence;
} }
Group::TriState Group::autoTypeEnabled() const Group::TriState Group::autoTypeEnabled() const
{ {
return m_autoTypeEnabled; return m_data.autoTypeEnabled;
} }
Group::TriState Group::searchingEnabled() const Group::TriState Group::searchingEnabled() const
{ {
return m_searchingEnabled; return m_data.searchingEnabled;
} }
Entry* Group::lastTopVisibleEntry() const Entry* Group::lastTopVisibleEntry() const
@@ -179,7 +186,7 @@ Entry* Group::lastTopVisibleEntry() const
bool Group::isExpired() const bool Group::isExpired() const
{ {
return m_timeInfo.expires() && m_timeInfo.expiryTime() < Tools::currentDateTimeUtc(); return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < Tools::currentDateTimeUtc();
} }
void Group::setUuid(const Uuid& uuid) void Group::setUuid(const Uuid& uuid)
@@ -189,23 +196,23 @@ void Group::setUuid(const Uuid& uuid)
void Group::setName(const QString& name) void Group::setName(const QString& name)
{ {
if (set(m_name, name)) { if (set(m_data.name, name)) {
Q_EMIT dataChanged(this); Q_EMIT dataChanged(this);
} }
} }
void Group::setNotes(const QString& notes) void Group::setNotes(const QString& notes)
{ {
set(m_notes, notes); set(m_data.notes, notes);
} }
void Group::setIcon(int iconNumber) void Group::setIcon(int iconNumber)
{ {
Q_ASSERT(iconNumber >= 0); Q_ASSERT(iconNumber >= 0);
if (m_iconNumber != iconNumber || !m_customIcon.isNull()) { if (m_data.iconNumber != iconNumber || !m_data.customIcon.isNull()) {
m_iconNumber = iconNumber; m_data.iconNumber = iconNumber;
m_customIcon = Uuid(); m_data.customIcon = Uuid();
m_pixmapCacheKey = QPixmapCache::Key(); m_pixmapCacheKey = QPixmapCache::Key();
@@ -219,9 +226,9 @@ void Group::setIcon(const Uuid& uuid)
{ {
Q_ASSERT(!uuid.isNull()); Q_ASSERT(!uuid.isNull());
if (m_customIcon != uuid) { if (m_data.customIcon != uuid) {
m_customIcon = uuid; m_data.customIcon = uuid;
m_iconNumber = 0; m_data.iconNumber = 0;
m_pixmapCacheKey = QPixmapCache::Key(); m_pixmapCacheKey = QPixmapCache::Key();
@@ -233,13 +240,13 @@ void Group::setIcon(const Uuid& uuid)
void Group::setTimeInfo(const TimeInfo& timeInfo) void Group::setTimeInfo(const TimeInfo& timeInfo)
{ {
m_timeInfo = timeInfo; m_data.timeInfo = timeInfo;
} }
void Group::setExpanded(bool expanded) void Group::setExpanded(bool expanded)
{ {
if (m_isExpanded != expanded) { if (m_data.isExpanded != expanded) {
m_isExpanded = expanded; m_data.isExpanded = expanded;
updateTimeinfo(); updateTimeinfo();
if (config()->get("ModifiedOnExpandedStateChanges").toBool()) { if (config()->get("ModifiedOnExpandedStateChanges").toBool()) {
Q_EMIT modified(); Q_EMIT modified();
@@ -249,17 +256,17 @@ void Group::setExpanded(bool expanded)
void Group::setDefaultAutoTypeSequence(const QString& sequence) void Group::setDefaultAutoTypeSequence(const QString& sequence)
{ {
set(m_defaultAutoTypeSequence, sequence); set(m_data.defaultAutoTypeSequence, sequence);
} }
void Group::setAutoTypeEnabled(TriState enable) void Group::setAutoTypeEnabled(TriState enable)
{ {
set(m_autoTypeEnabled, enable); set(m_data.autoTypeEnabled, enable);
} }
void Group::setSearchingEnabled(TriState enable) void Group::setSearchingEnabled(TriState enable)
{ {
set(m_searchingEnabled, enable); set(m_data.searchingEnabled, enable);
} }
void Group::setLastTopVisibleEntry(Entry* entry) void Group::setLastTopVisibleEntry(Entry* entry)
@@ -269,8 +276,8 @@ void Group::setLastTopVisibleEntry(Entry* entry)
void Group::setExpires(bool value) void Group::setExpires(bool value)
{ {
if (m_timeInfo.expires() != value) { if (m_data.timeInfo.expires() != value) {
m_timeInfo.setExpires(value); m_data.timeInfo.setExpires(value);
updateTimeinfo(); updateTimeinfo();
Q_EMIT modified(); Q_EMIT modified();
} }
@@ -278,8 +285,8 @@ void Group::setExpires(bool value)
void Group::setExpiryTime(const QDateTime& dateTime) void Group::setExpiryTime(const QDateTime& dateTime)
{ {
if (m_timeInfo.expiryTime() != dateTime) { if (m_data.timeInfo.expiryTime() != dateTime) {
m_timeInfo.setExpiryTime(dateTime); m_data.timeInfo.setExpiryTime(dateTime);
updateTimeinfo(); updateTimeinfo();
Q_EMIT modified(); Q_EMIT modified();
} }
@@ -347,7 +354,7 @@ void Group::setParent(Group* parent, int index)
} }
if (m_updateTimeinfo) { if (m_updateTimeinfo) {
m_timeInfo.setLocationChanged(Tools::currentDateTimeUtc()); m_data.timeInfo.setLocationChanged(Tools::currentDateTimeUtc());
} }
Q_EMIT modified(); Q_EMIT modified();
@@ -436,6 +443,79 @@ QList<const Group*> Group::groupsRecursive(bool includeSelf) const
return groupList; return groupList;
} }
QSet<Uuid> Group::customIconsRecursive() const
{
QSet<Uuid> result;
if (!iconUuid().isNull()) {
result.insert(iconUuid());
}
Q_FOREACH (Entry* entry, entriesRecursive(true)) {
if (!entry->iconUuid().isNull()) {
result.insert(entry->iconUuid());
}
}
Q_FOREACH (Group* group, m_children) {
result.unite(group->customIconsRecursive());
}
return result;
}
Group* Group::clone(Entry::CloneFlags entryFlags) const
{
Group* clonedGroup = new Group();
clonedGroup->setUpdateTimeinfo(false);
clonedGroup->setUuid(Uuid::random());
clonedGroup->m_data = m_data;
Q_FOREACH (Entry* entry, entries()) {
Entry* clonedEntry = entry->clone(entryFlags);
clonedEntry->setGroup(clonedGroup);
}
Q_FOREACH (Group* groupChild, children()) {
Group* clonedGroupChild = groupChild->clone();
clonedGroupChild->setParent(clonedGroup);
}
clonedGroup->setUpdateTimeinfo(true);
QDateTime now = Tools::currentDateTimeUtc();
clonedGroup->m_data.timeInfo.setCreationTime(now);
clonedGroup->m_data.timeInfo.setLastModificationTime(now);
clonedGroup->m_data.timeInfo.setLastAccessTime(now);
clonedGroup->m_data.timeInfo.setLocationChanged(now);
return clonedGroup;
}
void Group::copyDataFrom(const Group* other)
{
m_data = other->m_data;
m_lastTopVisibleEntry = other->m_lastTopVisibleEntry;
}
Database* Group::exportToDb()
{
Q_ASSERT(database());
Database* db = new Database();
Group* clonedGroup = clone(Entry::CloneNewUuid | Entry::CloneIncludeHistory);
clonedGroup->setParent(db->rootGroup());
QSet<Uuid> customIcons = customIconsRecursive();
db->metadata()->copyCustomIcons(customIcons, database()->metadata());
db->copyAttributesFrom(database());
return db;
}
void Group::addEntry(Entry* entry) void Group::addEntry(Entry* entry)
{ {
Q_ASSERT(entry); Q_ASSERT(entry);
@@ -551,7 +631,7 @@ QList<Entry*> Group::search(const QString& searchTerm, Qt::CaseSensitivity caseS
bool Group::includeInSearch(bool resolveInherit) bool Group::includeInSearch(bool resolveInherit)
{ {
switch (m_searchingEnabled) { switch (m_data.searchingEnabled) {
case Inherit: case Inherit:
if (!m_parent) { if (!m_parent) {
return true; return true;

View File

@@ -18,10 +18,10 @@
#ifndef KEEPASSX_GROUP_H #ifndef KEEPASSX_GROUP_H
#define KEEPASSX_GROUP_H #define KEEPASSX_GROUP_H
#include <QtCore/QPointer> #include <QImage>
#include <QtGui/QImage> #include <QPixmap>
#include <QtGui/QPixmap> #include <QPixmapCache>
#include <QtGui/QPixmapCache> #include <QPointer>
#include "core/Database.h" #include "core/Database.h"
#include "core/Entry.h" #include "core/Entry.h"
@@ -35,6 +35,19 @@ class Group : public QObject
public: public:
enum TriState { Inherit, Enable, Disable }; enum TriState { Inherit, Enable, Disable };
struct GroupData
{
QString name;
QString notes;
int iconNumber;
Uuid customIcon;
TimeInfo timeInfo;
bool isExpanded;
QString defaultAutoTypeSequence;
Group::TriState autoTypeEnabled;
Group::TriState searchingEnabled;
};
Group(); Group();
~Group(); ~Group();
@@ -86,6 +99,17 @@ public:
const QList<Entry*>& entries() const; const QList<Entry*>& entries() const;
QList<Entry*> entriesRecursive(bool includeHistoryItems = false) const; QList<Entry*> entriesRecursive(bool includeHistoryItems = false) const;
QList<const Group*> groupsRecursive(bool includeSelf) const; QList<const Group*> groupsRecursive(bool includeSelf) const;
QSet<Uuid> customIconsRecursive() const;
/**
* Creates a duplicate of this group including all child entries and groups.
* The exceptions are that the returned group doesn't have a parent group
* and all TimeInfo attributes are set to the current time.
* Note that you need to copy the custom icons manually when inserting the
* new group into another database.
*/
Group* clone(Entry::CloneFlags entryFlags = Entry::CloneNewUuid | Entry::CloneResetTimeInfo) const;
void copyDataFrom(const Group* other);
Database* exportToDb();
QList<Entry*> search(const QString& searchTerm, Qt::CaseSensitivity caseSensitivity, QList<Entry*> search(const QString& searchTerm, Qt::CaseSensitivity caseSensitivity,
bool resolveInherit = true); bool resolveInherit = true);
@@ -127,15 +151,7 @@ private:
QPointer<Database> m_db; QPointer<Database> m_db;
Uuid m_uuid; Uuid m_uuid;
QString m_name; GroupData m_data;
QString m_notes;
int m_iconNumber;
Uuid m_customIcon;
TimeInfo m_timeInfo;
bool m_isExpanded;
QString m_defaultAutoTypeSequence;
TriState m_autoTypeEnabled;
TriState m_searchingEnabled;
QPointer<Entry> m_lastTopVisibleEntry; QPointer<Entry> m_lastTopVisibleEntry;
QList<Group*> m_children; QList<Group*> m_children;
QList<Entry*> m_entries; QList<Entry*> m_entries;

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) 2014 Felix Geyer <debfx@fobos.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "InactivityTimer.h"
#include <QCoreApplication>
#include <QTimer>
InactivityTimer::InactivityTimer(QObject* parent)
: QObject(parent)
, m_timer(new QTimer(this))
, m_active(false)
{
m_timer->setSingleShot(true);
connect(m_timer, SIGNAL(timeout()), SLOT(timeout()));
}
void InactivityTimer::setInactivityTimeout(int inactivityTimeout)
{
Q_ASSERT(inactivityTimeout > 0);
m_timer->setInterval(inactivityTimeout);
}
void InactivityTimer::activate()
{
if (!m_active) {
qApp->installEventFilter(this);
}
m_active = true;
m_timer->start();
}
void InactivityTimer::deactivate()
{
qApp->removeEventFilter(this);
m_active = false;
m_timer->stop();
}
bool InactivityTimer::eventFilter(QObject* watched, QEvent* event)
{
const QEvent::Type type = event->type();
if ( (type >= QEvent::MouseButtonPress && type <= QEvent::KeyRelease)
|| (type >= QEvent::HoverEnter && type <= QEvent::HoverMove)
|| (type == QEvent::Wheel) ) {
m_timer->start();
}
return QObject::eventFilter(watched, event);
}
void InactivityTimer::timeout()
{
if (m_active && !m_timer->isActive()) {
Q_EMIT inactivityDetected();
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2014 Felix Geyer <debfx@fobos.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KEEPASSX_INACTIVITYTIMER_H
#define KEEPASSX_INACTIVITYTIMER_H
#include <QObject>
#include "core/Global.h"
class QTimer;
class InactivityTimer : public QObject
{
Q_OBJECT
public:
explicit InactivityTimer(QObject* parent = Q_NULLPTR);
void setInactivityTimeout(int inactivityTimeout);
void activate();
void deactivate();
Q_SIGNALS:
void inactivityDetected();
protected:
bool eventFilter(QObject* watched, QEvent* event);
private Q_SLOTS:
void timeout();
private:
QTimer* m_timer;
bool m_active;
};
#endif // KEEPASSX_INACTIVITYTIMER_H

View File

@@ -18,7 +18,7 @@
#ifndef KEEPASSX_LISTDELETER_H #ifndef KEEPASSX_LISTDELETER_H
#define KEEPASSX_LISTDELETER_H #define KEEPASSX_LISTDELETER_H
#include <QtCore/QList> #include <QList>
template <typename T> template <typename T>
class ListDeleter class ListDeleter

View File

@@ -26,25 +26,26 @@ const int Metadata::DefaultHistoryMaxSize = 6 * 1024 * 1024;
Metadata::Metadata(QObject* parent) Metadata::Metadata(QObject* parent)
: QObject(parent) : QObject(parent)
, m_generator("KeePassX")
, m_maintenanceHistoryDays(365)
, m_protectTitle(false)
, m_protectUsername(false)
, m_protectPassword(true)
, m_protectUrl(false)
, m_protectNotes(false)
// , m_autoEnableVisualHiding(false)
, m_recycleBinEnabled(true)
, m_masterKeyChangeRec(-1)
, m_masterKeyChangeForce(-1)
, m_historyMaxItems(DefaultHistoryMaxItems)
, m_historyMaxSize(DefaultHistoryMaxSize)
, m_updateDatetime(true) , m_updateDatetime(true)
{ {
m_data.generator = "KeePassX";
m_data.maintenanceHistoryDays = 365;
m_data.masterKeyChangeRec = -1;
m_data.masterKeyChangeForce = -1;
m_data.historyMaxItems = DefaultHistoryMaxItems;
m_data.historyMaxSize = DefaultHistoryMaxSize;
m_data.recycleBinEnabled = true;
m_data.protectTitle = false;
m_data.protectUsername = false;
m_data.protectPassword = true;
m_data.protectUrl = false;
m_data.protectNotes = false;
// m_data.autoEnableVisualHiding = false;
QDateTime now = Tools::currentDateTimeUtc(); QDateTime now = Tools::currentDateTimeUtc();
m_nameChanged = now; m_data.nameChanged = now;
m_descriptionChanged = now; m_data.descriptionChanged = now;
m_defaultUserNameChanged = now; m_data.defaultUserNameChanged = now;
m_recycleBinChanged = now; m_recycleBinChanged = now;
m_entryTemplatesGroupChanged = now; m_entryTemplatesGroupChanged = now;
m_masterKeyChanged = now; m_masterKeyChanged = now;
@@ -81,74 +82,79 @@ void Metadata::setUpdateDatetime(bool value)
m_updateDatetime = value; m_updateDatetime = value;
} }
void Metadata::copyAttributesFrom(const Metadata* other)
{
m_data = other->m_data;
}
QString Metadata::generator() const QString Metadata::generator() const
{ {
return m_generator; return m_data.generator;
} }
QString Metadata::name() const QString Metadata::name() const
{ {
return m_name; return m_data.name;
} }
QDateTime Metadata::nameChanged() const QDateTime Metadata::nameChanged() const
{ {
return m_nameChanged; return m_data.nameChanged;
} }
QString Metadata::description() const QString Metadata::description() const
{ {
return m_description; return m_data.description;
} }
QDateTime Metadata::descriptionChanged() const QDateTime Metadata::descriptionChanged() const
{ {
return m_descriptionChanged; return m_data.descriptionChanged;
} }
QString Metadata::defaultUserName() const QString Metadata::defaultUserName() const
{ {
return m_defaultUserName; return m_data.defaultUserName;
} }
QDateTime Metadata::defaultUserNameChanged() const QDateTime Metadata::defaultUserNameChanged() const
{ {
return m_defaultUserNameChanged; return m_data.defaultUserNameChanged;
} }
int Metadata::maintenanceHistoryDays() const int Metadata::maintenanceHistoryDays() const
{ {
return m_maintenanceHistoryDays; return m_data.maintenanceHistoryDays;
} }
QColor Metadata::color() const QColor Metadata::color() const
{ {
return m_color; return m_data.color;
} }
bool Metadata::protectTitle() const bool Metadata::protectTitle() const
{ {
return m_protectTitle; return m_data.protectTitle;
} }
bool Metadata::protectUsername() const bool Metadata::protectUsername() const
{ {
return m_protectUsername; return m_data.protectUsername;
} }
bool Metadata::protectPassword() const bool Metadata::protectPassword() const
{ {
return m_protectPassword; return m_data.protectPassword;
} }
bool Metadata::protectUrl() const bool Metadata::protectUrl() const
{ {
return m_protectUrl; return m_data.protectUrl;
} }
bool Metadata::protectNotes() const bool Metadata::protectNotes() const
{ {
return m_protectNotes; return m_data.protectNotes;
} }
/*bool Metadata::autoEnableVisualHiding() const /*bool Metadata::autoEnableVisualHiding() const
@@ -178,7 +184,7 @@ QList<Uuid> Metadata::customIconsOrder() const
bool Metadata::recycleBinEnabled() const bool Metadata::recycleBinEnabled() const
{ {
return m_recycleBinEnabled; return m_data.recycleBinEnabled;
} }
Group* Metadata::recycleBin() Group* Metadata::recycleBin()
@@ -223,22 +229,22 @@ QDateTime Metadata::masterKeyChanged() const
int Metadata::masterKeyChangeRec() const int Metadata::masterKeyChangeRec() const
{ {
return m_masterKeyChangeRec; return m_data.masterKeyChangeRec;
} }
int Metadata::masterKeyChangeForce() const int Metadata::masterKeyChangeForce() const
{ {
return m_masterKeyChangeForce; return m_data.masterKeyChangeForce;
} }
int Metadata::historyMaxItems() const int Metadata::historyMaxItems() const
{ {
return m_historyMaxItems; return m_data.historyMaxItems;
} }
int Metadata::historyMaxSize() const int Metadata::historyMaxSize() const
{ {
return m_historyMaxSize; return m_data.historyMaxSize;
} }
QHash<QString, QString> Metadata::customFields() const QHash<QString, QString> Metadata::customFields() const
@@ -248,12 +254,12 @@ QHash<QString, QString> Metadata::customFields() const
void Metadata::setGenerator(const QString& value) void Metadata::setGenerator(const QString& value)
{ {
set(m_generator, value); set(m_data.generator, value);
} }
void Metadata::setName(const QString& value) void Metadata::setName(const QString& value)
{ {
if (set(m_name, value, m_nameChanged)) { if (set(m_data.name, value, m_data.nameChanged)) {
Q_EMIT nameTextChanged(); Q_EMIT nameTextChanged();
} }
} }
@@ -261,64 +267,64 @@ void Metadata::setName(const QString& value)
void Metadata::setNameChanged(const QDateTime& value) void Metadata::setNameChanged(const QDateTime& value)
{ {
Q_ASSERT(value.timeSpec() == Qt::UTC); Q_ASSERT(value.timeSpec() == Qt::UTC);
m_nameChanged = value; m_data.nameChanged = value;
} }
void Metadata::setDescription(const QString& value) void Metadata::setDescription(const QString& value)
{ {
set(m_description, value, m_descriptionChanged); set(m_data.description, value, m_data.descriptionChanged);
} }
void Metadata::setDescriptionChanged(const QDateTime& value) void Metadata::setDescriptionChanged(const QDateTime& value)
{ {
Q_ASSERT(value.timeSpec() == Qt::UTC); Q_ASSERT(value.timeSpec() == Qt::UTC);
m_descriptionChanged = value; m_data.descriptionChanged = value;
} }
void Metadata::setDefaultUserName(const QString& value) void Metadata::setDefaultUserName(const QString& value)
{ {
set(m_defaultUserName, value, m_defaultUserNameChanged); set(m_data.defaultUserName, value, m_data.defaultUserNameChanged);
} }
void Metadata::setDefaultUserNameChanged(const QDateTime& value) void Metadata::setDefaultUserNameChanged(const QDateTime& value)
{ {
Q_ASSERT(value.timeSpec() == Qt::UTC); Q_ASSERT(value.timeSpec() == Qt::UTC);
m_defaultUserNameChanged = value; m_data.defaultUserNameChanged = value;
} }
void Metadata::setMaintenanceHistoryDays(int value) void Metadata::setMaintenanceHistoryDays(int value)
{ {
set(m_maintenanceHistoryDays, value); set(m_data.maintenanceHistoryDays, value);
} }
void Metadata::setColor(const QColor& value) void Metadata::setColor(const QColor& value)
{ {
set(m_color, value); set(m_data.color, value);
} }
void Metadata::setProtectTitle(bool value) void Metadata::setProtectTitle(bool value)
{ {
set(m_protectTitle, value); set(m_data.protectTitle, value);
} }
void Metadata::setProtectUsername(bool value) void Metadata::setProtectUsername(bool value)
{ {
set(m_protectUsername, value); set(m_data.protectUsername, value);
} }
void Metadata::setProtectPassword(bool value) void Metadata::setProtectPassword(bool value)
{ {
set(m_protectPassword, value); set(m_data.protectPassword, value);
} }
void Metadata::setProtectUrl(bool value) void Metadata::setProtectUrl(bool value)
{ {
set(m_protectUrl, value); set(m_data.protectUrl, value);
} }
void Metadata::setProtectNotes(bool value) void Metadata::setProtectNotes(bool value)
{ {
set(m_protectNotes, value); set(m_data.protectNotes, value);
} }
/*void Metadata::setAutoEnableVisualHiding(bool value) /*void Metadata::setAutoEnableVisualHiding(bool value)
@@ -348,9 +354,20 @@ void Metadata::removeCustomIcon(const Uuid& uuid)
Q_EMIT modified(); Q_EMIT modified();
} }
void Metadata::copyCustomIcons(const QSet<Uuid>& iconList, const Metadata* otherMetadata)
{
Q_FOREACH (const Uuid& uuid, iconList) {
Q_ASSERT(otherMetadata->containsCustomIcon(uuid));
if (!containsCustomIcon(uuid) && otherMetadata->containsCustomIcon(uuid)) {
addCustomIcon(uuid, otherMetadata->customIcon(uuid));
}
}
}
void Metadata::setRecycleBinEnabled(bool value) void Metadata::setRecycleBinEnabled(bool value)
{ {
set(m_recycleBinEnabled, value); set(m_data.recycleBinEnabled, value);
} }
void Metadata::setRecycleBin(Group* group) void Metadata::setRecycleBin(Group* group)
@@ -393,22 +410,22 @@ void Metadata::setMasterKeyChanged(const QDateTime& value)
void Metadata::setMasterKeyChangeRec(int value) void Metadata::setMasterKeyChangeRec(int value)
{ {
set(m_masterKeyChangeRec, value); set(m_data.masterKeyChangeRec, value);
} }
void Metadata::setMasterKeyChangeForce(int value) void Metadata::setMasterKeyChangeForce(int value)
{ {
set(m_masterKeyChangeForce, value); set(m_data.masterKeyChangeForce, value);
} }
void Metadata::setHistoryMaxItems(int value) void Metadata::setHistoryMaxItems(int value)
{ {
set(m_historyMaxItems, value); set(m_data.historyMaxItems, value);
} }
void Metadata::setHistoryMaxSize(int value) void Metadata::setHistoryMaxSize(int value)
{ {
set(m_historyMaxSize, value); set(m_data.historyMaxSize, value);
} }
void Metadata::addCustomField(const QString& key, const QString& value) void Metadata::addCustomField(const QString& key, const QString& value)

View File

@@ -18,11 +18,11 @@
#ifndef KEEPASSX_METADATA_H #ifndef KEEPASSX_METADATA_H
#define KEEPASSX_METADATA_H #define KEEPASSX_METADATA_H
#include <QtCore/QDateTime> #include <QColor>
#include <QtCore/QHash> #include <QDateTime>
#include <QtCore/QPointer> #include <QHash>
#include <QtGui/QColor> #include <QImage>
#include <QtGui/QImage> #include <QPointer>
#include "core/Global.h" #include "core/Global.h"
#include "core/Uuid.h" #include "core/Uuid.h"
@@ -37,6 +37,31 @@ class Metadata : public QObject
public: public:
explicit Metadata(QObject* parent = Q_NULLPTR); explicit Metadata(QObject* parent = Q_NULLPTR);
struct MetadataData
{
QString generator;
QString name;
QDateTime nameChanged;
QString description;
QDateTime descriptionChanged;
QString defaultUserName;
QDateTime defaultUserNameChanged;
int maintenanceHistoryDays;
QColor color;
bool recycleBinEnabled;
int historyMaxItems;
int historyMaxSize;
int masterKeyChangeRec;
int masterKeyChangeForce;
bool protectTitle;
bool protectUsername;
bool protectPassword;
bool protectUrl;
bool protectNotes;
// bool autoEnableVisualHiding;
};
QString generator() const; QString generator() const;
QString name() const; QString name() const;
QDateTime nameChanged() const; QDateTime nameChanged() const;
@@ -91,6 +116,7 @@ public:
// void setAutoEnableVisualHiding(bool value); // void setAutoEnableVisualHiding(bool value);
void addCustomIcon(const Uuid& uuid, const QImage& icon); void addCustomIcon(const Uuid& uuid, const QImage& icon);
void removeCustomIcon(const Uuid& uuid); void removeCustomIcon(const Uuid& uuid);
void copyCustomIcons(const QSet<Uuid>& iconList, const Metadata* otherMetadata);
void setRecycleBinEnabled(bool value); void setRecycleBinEnabled(bool value);
void setRecycleBin(Group* group); void setRecycleBin(Group* group);
void setRecycleBinChanged(const QDateTime& value); void setRecycleBinChanged(const QDateTime& value);
@@ -106,6 +132,14 @@ public:
void addCustomField(const QString& key, const QString& value); void addCustomField(const QString& key, const QString& value);
void removeCustomField(const QString& key); void removeCustomField(const QString& key);
void setUpdateDatetime(bool value); void setUpdateDatetime(bool value);
/*
* Copy all attributes from other except:
* - Group pointers/uuids
* - Master key changed date
* - Custom icons
* - Custom fields
*/
void copyAttributesFrom(const Metadata* other);
Q_SIGNALS: Q_SIGNALS:
void nameTextChanged(); void nameTextChanged();
@@ -115,27 +149,11 @@ private:
template <class P, class V> bool set(P& property, const V& value); template <class P, class V> bool set(P& property, const V& value);
template <class P, class V> bool set(P& property, const V& value, QDateTime& dateTime); template <class P, class V> bool set(P& property, const V& value, QDateTime& dateTime);
QString m_generator; MetadataData m_data;
QString m_name;
QDateTime m_nameChanged;
QString m_description;
QDateTime m_descriptionChanged;
QString m_defaultUserName;
QDateTime m_defaultUserNameChanged;
int m_maintenanceHistoryDays;
QColor m_color;
bool m_protectTitle;
bool m_protectUsername;
bool m_protectPassword;
bool m_protectUrl;
bool m_protectNotes;
// bool m_autoEnableVisualHiding;
QHash<Uuid, QImage> m_customIcons; QHash<Uuid, QImage> m_customIcons;
QList<Uuid> m_customIconsOrder; QList<Uuid> m_customIconsOrder;
bool m_recycleBinEnabled;
QPointer<Group> m_recycleBin; QPointer<Group> m_recycleBin;
QDateTime m_recycleBinChanged; QDateTime m_recycleBinChanged;
QPointer<Group> m_entryTemplatesGroup; QPointer<Group> m_entryTemplatesGroup;
@@ -144,10 +162,6 @@ private:
QPointer<Group> m_lastTopVisibleGroup; QPointer<Group> m_lastTopVisibleGroup;
QDateTime m_masterKeyChanged; QDateTime m_masterKeyChanged;
int m_masterKeyChangeRec;
int m_masterKeyChangeForce;
int m_historyMaxItems;
int m_historyMaxSize;
QHash<QString, QString> m_customFields; QHash<QString, QString> m_customFields;

View File

@@ -19,15 +19,33 @@
#include "crypto/Random.h" #include "crypto/Random.h"
PasswordGenerator* PasswordGenerator::m_instance = Q_NULLPTR; PasswordGenerator::PasswordGenerator()
: m_length(0)
QString PasswordGenerator::generatePassword(int length, , m_classes(0)
const PasswordGenerator::CharClasses& classes, , m_flags(0)
const PasswordGenerator::GeneratorFlags& flags)
{ {
Q_ASSERT(isValidCombination(length, classes, flags)); }
QVector<PasswordGroup> groups = passwordGroups(classes, flags); void PasswordGenerator::setLength(int length)
{
m_length = length;
}
void PasswordGenerator::setCharClasses(const CharClasses& classes)
{
m_classes = classes;
}
void PasswordGenerator::setFlags(const GeneratorFlags& flags)
{
m_flags = flags;
}
QString PasswordGenerator::generatePassword() const
{
Q_ASSERT(isValid());
QVector<PasswordGroup> groups = passwordGroups();
QVector<QChar> passwordChars; QVector<QChar> passwordChars;
Q_FOREACH (const PasswordGroup& group, groups) { Q_FOREACH (const PasswordGroup& group, groups) {
@@ -38,22 +56,22 @@ QString PasswordGenerator::generatePassword(int length,
QString password; QString password;
if (flags & CharFromEveryGroup) { if (m_flags & CharFromEveryGroup) {
for (int i = 0; i < groups.size(); i++) { for (int i = 0; i < groups.size(); i++) {
int pos = Random::randomUInt(groups[i].size()); int pos = randomGen()->randomUInt(groups[i].size());
password.append(groups[i][pos]); password.append(groups[i][pos]);
} }
for (int i = groups.size(); i < length; i++) { for (int i = groups.size(); i < m_length; i++) {
int pos = Random::randomUInt(passwordChars.size()); int pos = randomGen()->randomUInt(passwordChars.size());
password.append(passwordChars[pos]); password.append(passwordChars[pos]);
} }
// shuffle chars // shuffle chars
for (int i = (password.size() - 1); i >= 1; i--) { for (int i = (password.size() - 1); i >= 1; i--) {
int j = Random::randomUInt(i + 1); int j = randomGen()->randomUInt(i + 1);
QChar tmp = password[i]; QChar tmp = password[i];
password[i] = password[j]; password[i] = password[j];
@@ -61,8 +79,8 @@ QString PasswordGenerator::generatePassword(int length,
} }
} }
else { else {
for (int i = 0; i < length; i++) { for (int i = 0; i < m_length; i++) {
int pos = Random::randomUInt(passwordChars.size()); int pos = randomGen()->randomUInt(passwordChars.size());
password.append(passwordChars[pos]); password.append(passwordChars[pos]);
} }
@@ -71,34 +89,31 @@ QString PasswordGenerator::generatePassword(int length,
return password; return password;
} }
bool PasswordGenerator::isValidCombination(int length, bool PasswordGenerator::isValid() const
const PasswordGenerator::CharClasses& classes,
const PasswordGenerator::GeneratorFlags& flags)
{ {
if (classes == 0) { if (m_classes == 0) {
return false; return false;
} }
else if (length == 0) { else if (m_length == 0) {
return false; return false;
} }
if ((flags & CharFromEveryGroup) && (length < numCharClasses(classes))) { if ((m_flags & CharFromEveryGroup) && (m_length < numCharClasses())) {
return false; return false;
} }
return true; return true;
} }
QVector<PasswordGroup> PasswordGenerator::passwordGroups(const PasswordGenerator::CharClasses& classes, QVector<PasswordGroup> PasswordGenerator::passwordGroups() const
const PasswordGenerator::GeneratorFlags& flags)
{ {
QVector<PasswordGroup> passwordGroups; QVector<PasswordGroup> passwordGroups;
if (classes & LowerLetters) { if (m_classes & LowerLetters) {
PasswordGroup group; PasswordGroup group;
for (int i = 97; i < (97 + 26); i++) { for (int i = 97; i < (97 + 26); i++) {
if ((flags & ExcludeLookAlike) && (i == 108)) { // "l" if ((m_flags & ExcludeLookAlike) && (i == 108)) { // "l"
continue; continue;
} }
@@ -107,11 +122,11 @@ QVector<PasswordGroup> PasswordGenerator::passwordGroups(const PasswordGenerator
passwordGroups.append(group); passwordGroups.append(group);
} }
if (classes & UpperLetters) { if (m_classes & UpperLetters) {
PasswordGroup group; PasswordGroup group;
for (int i = 65; i < (65 + 26); i++) { for (int i = 65; i < (65 + 26); i++) {
if ((flags & ExcludeLookAlike) && (i == 73 || i == 79)) { // "I" and "O" if ((m_flags & ExcludeLookAlike) && (i == 73 || i == 79)) { // "I" and "O"
continue; continue;
} }
@@ -120,11 +135,11 @@ QVector<PasswordGroup> PasswordGenerator::passwordGroups(const PasswordGenerator
passwordGroups.append(group); passwordGroups.append(group);
} }
if (classes & Numbers) { if (m_classes & Numbers) {
PasswordGroup group; PasswordGroup group;
for (int i = 48; i < (48 + 10); i++) { for (int i = 48; i < (48 + 10); i++) {
if ((flags & ExcludeLookAlike) && (i == 48 || i == 49)) { // "0" and "1" if ((m_flags & ExcludeLookAlike) && (i == 48 || i == 49)) { // "0" and "1"
continue; continue;
} }
@@ -133,7 +148,7 @@ QVector<PasswordGroup> PasswordGenerator::passwordGroups(const PasswordGenerator
passwordGroups.append(group); passwordGroups.append(group);
} }
if (classes & SpecialCharacters) { if (m_classes & SpecialCharacters) {
PasswordGroup group; PasswordGroup group;
for (int i = 33; i <= 47; i++) { for (int i = 33; i <= 47; i++) {
@@ -149,7 +164,7 @@ QVector<PasswordGroup> PasswordGenerator::passwordGroups(const PasswordGenerator
} }
for (int i = 123; i <= 126; i++) { for (int i = 123; i <= 126; i++) {
if ((flags & ExcludeLookAlike) && (i == 124)) { // "|" if ((m_flags & ExcludeLookAlike) && (i == 124)) { // "|"
continue; continue;
} }
@@ -162,35 +177,22 @@ QVector<PasswordGroup> PasswordGenerator::passwordGroups(const PasswordGenerator
return passwordGroups; return passwordGroups;
} }
int PasswordGenerator::numCharClasses(const PasswordGenerator::CharClasses& classes) int PasswordGenerator::numCharClasses() const
{ {
int numClasses = 0; int numClasses = 0;
if (classes & LowerLetters) { if (m_classes & LowerLetters) {
numClasses++; numClasses++;
} }
if (classes & UpperLetters) { if (m_classes & UpperLetters) {
numClasses++; numClasses++;
} }
if (classes & Numbers) { if (m_classes & Numbers) {
numClasses++; numClasses++;
} }
if (classes & SpecialCharacters) { if (m_classes & SpecialCharacters) {
numClasses++; numClasses++;
} }
return numClasses; return numClasses;
} }
PasswordGenerator* PasswordGenerator::instance()
{
if (!m_instance) {
m_instance = new PasswordGenerator();
}
return m_instance;
}
PasswordGenerator::PasswordGenerator()
{
}

View File

@@ -18,9 +18,9 @@
#ifndef KEEPASSX_PASSWORDGENERATOR_H #ifndef KEEPASSX_PASSWORDGENERATOR_H
#define KEEPASSX_PASSWORDGENERATOR_H #define KEEPASSX_PASSWORDGENERATOR_H
#include <QtCore/QFlags> #include <QFlags>
#include <QtCore/QString> #include <QString>
#include <QtCore/QVector> #include <QVector>
#include "core/Global.h" #include "core/Global.h"
@@ -45,29 +45,28 @@ public:
}; };
Q_DECLARE_FLAGS(GeneratorFlags, GeneratorFlag) Q_DECLARE_FLAGS(GeneratorFlags, GeneratorFlag)
QString generatePassword(int length, const PasswordGenerator::CharClasses& classes, public:
const PasswordGenerator::GeneratorFlags& flags);
bool isValidCombination(int length, const PasswordGenerator::CharClasses& classes,
const PasswordGenerator::GeneratorFlags& flags);
static PasswordGenerator* instance();
private:
PasswordGenerator(); PasswordGenerator();
QVector<PasswordGroup> passwordGroups(const PasswordGenerator::CharClasses& classes, void setLength(int length);
const PasswordGenerator::GeneratorFlags& flags); void setCharClasses(const CharClasses& classes);
int numCharClasses(const PasswordGenerator::CharClasses& classes); void setFlags(const GeneratorFlags& flags);
static PasswordGenerator* m_instance; bool isValid() const;
QString generatePassword() const;
private:
QVector<PasswordGroup> passwordGroups() const;
int numCharClasses() const;
int m_length;
CharClasses m_classes;
GeneratorFlags m_flags;
Q_DISABLE_COPY(PasswordGenerator) Q_DISABLE_COPY(PasswordGenerator)
}; };
inline PasswordGenerator* passwordGenerator() {
return PasswordGenerator::instance();
}
Q_DECLARE_OPERATORS_FOR_FLAGS(PasswordGenerator::CharClasses) Q_DECLARE_OPERATORS_FOR_FLAGS(PasswordGenerator::CharClasses)
Q_DECLARE_OPERATORS_FOR_FLAGS(PasswordGenerator::GeneratorFlags) Q_DECLARE_OPERATORS_FOR_FLAGS(PasswordGenerator::GeneratorFlags)

View File

@@ -18,8 +18,8 @@
#ifndef KEEPASSX_SIGNALMULTIPLEXER_H #ifndef KEEPASSX_SIGNALMULTIPLEXER_H
#define KEEPASSX_SIGNALMULTIPLEXER_H #define KEEPASSX_SIGNALMULTIPLEXER_H
#include <QtCore/QObject> #include <QObject>
#include <QtCore/QPointer> #include <QPointer>
#include "core/Global.h" #include "core/Global.h"

View File

@@ -17,7 +17,7 @@
#include "TimeDelta.h" #include "TimeDelta.h"
#include <QtCore/QDateTime> #include <QDateTime>
QDateTime operator+(const QDateTime& dateTime, const TimeDelta& delta) { QDateTime operator+(const QDateTime& dateTime, const TimeDelta& delta) {
return dateTime.addDays(delta.getDays()) return dateTime.addDays(delta.getDays())

View File

@@ -18,7 +18,7 @@
#ifndef KEEPASSX_TIMEDELTA_H #ifndef KEEPASSX_TIMEDELTA_H
#define KEEPASSX_TIMEDELTA_H #define KEEPASSX_TIMEDELTA_H
#include <QtCore/QMetaType> #include <QMetaType>
class QDateTime; class QDateTime;
class TimeDelta; class TimeDelta;

View File

@@ -18,7 +18,7 @@
#ifndef KEEPASSX_TIMEINFO_H #ifndef KEEPASSX_TIMEINFO_H
#define KEEPASSX_TIMEINFO_H #define KEEPASSX_TIMEINFO_H
#include <QtCore/QDateTime> #include <QDateTime>
class TimeInfo class TimeInfo
{ {

View File

@@ -17,16 +17,16 @@
#include "Tools.h" #include "Tools.h"
#include <QtCore/QCoreApplication> #include <QCoreApplication>
#include <QtCore/QIODevice> #include <QImageReader>
#include <QtCore/QLocale> #include <QIODevice>
#include <QtCore/QStringList> #include <QLocale>
#include <QtGui/QImageReader> #include <QStringList>
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
#include <QtCore/QElapsedTimer> #include <QElapsedTimer>
#else #else
#include <QtCore/QTime> #include <QTime>
#endif #endif
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
@@ -141,7 +141,7 @@ QString imageReaderFilter()
} }
} }
formatsStringList.append("*." + QString::fromAscii(format).toLower()); formatsStringList.append("*." + QString::fromLatin1(format).toLower());
} }
return formatsStringList.join(" "); return formatsStringList.join(" ");

View File

@@ -18,9 +18,9 @@
#ifndef KEEPASSX_TOOLS_H #ifndef KEEPASSX_TOOLS_H
#define KEEPASSX_TOOLS_H #define KEEPASSX_TOOLS_H
#include <QtCore/QObject> #include <QDateTime>
#include <QtCore/QString> #include <QObject>
#include <QtCore/QDateTime> #include <QString>
#include "core/Global.h" #include "core/Global.h"

View File

@@ -17,7 +17,7 @@
#include "Uuid.h" #include "Uuid.h"
#include <QtCore/QHash> #include <QHash>
#include "crypto/Random.h" #include "crypto/Random.h"
@@ -37,17 +37,17 @@ Uuid::Uuid(const QByteArray& data)
Uuid Uuid::random() Uuid Uuid::random()
{ {
return Uuid(Random::randomArray(Length)); return Uuid(randomGen()->randomArray(Length));
} }
QString Uuid::toBase64() const QString Uuid::toBase64() const
{ {
return QString::fromAscii(m_data.toBase64()); return QString::fromLatin1(m_data.toBase64());
} }
QString Uuid::toHex() const QString Uuid::toHex() const
{ {
return QString::fromAscii(m_data.toHex()); return QString::fromLatin1(m_data.toHex());
} }
QByteArray Uuid::toByteArray() const QByteArray Uuid::toByteArray() const
@@ -85,7 +85,7 @@ bool Uuid::operator!=(const Uuid& other) const
Uuid Uuid::fromBase64(const QString& str) Uuid Uuid::fromBase64(const QString& str)
{ {
QByteArray data = QByteArray::fromBase64(str.toAscii()); QByteArray data = QByteArray::fromBase64(str.toLatin1());
return Uuid(data); return Uuid(data);
} }

View File

@@ -18,8 +18,8 @@
#ifndef KEEPASSX_UUID_H #ifndef KEEPASSX_UUID_H
#define KEEPASSX_UUID_H #define KEEPASSX_UUID_H
#include <QtCore/QByteArray> #include <QByteArray>
#include <QtCore/QString> #include <QString>
class Uuid class Uuid
{ {

View File

@@ -0,0 +1,305 @@
/****************************************************************************
**
** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
** Copyright (C) 2013 David Faure <faure@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qcommandlineoption.h"
#include <QSet>
class QCommandLineOptionPrivate : public QSharedData
{
public:
inline QCommandLineOptionPrivate()
{ }
void setNames(const QStringList &nameList);
//! The list of names used for this option.
QStringList names;
//! The documentation name for the value, if one is expected
//! Example: "-o <file>" means valueName == "file"
QString valueName;
//! The description used for this option.
QString description;
//! The list of default values used for this option.
QStringList defaultValues;
};
/*!
\since 5.2
\class QCommandLineOption
\brief The QCommandLineOption class defines a possible command-line option.
\inmodule QtCore
\ingroup shared
\ingroup tools
This class is used to describe an option on the command line. It allows
different ways of defining the same option with multiple aliases possible.
It is also used to describe how the option is used - it may be a flag (e.g. \c{-v})
or take an argument (e.g. \c{-o file}).
Examples:
\snippet code/src_corelib_tools_qcommandlineoption.cpp 0
\sa QCommandLineParser
*/
/*!
Constructs a command line option object with the given arguments.
The name of the option is set to \a name.
The name can be either short or long. If the name is one character in
length, it is considered a short name. Option names must not be empty,
must not start with a dash or a slash character, must not contain a \c{=}
and cannot be repeated.
The description is set to \a description. It is customary to add a "."
at the end of the description.
In addition, the \a valueName can be set if the option expects a value.
The default value for the option is set to \a defaultValue.
\sa setDescription(), setValueName(), setDefaultValues()
*/
QCommandLineOption::QCommandLineOption(const QString &name, const QString &description,
const QString &valueName,
const QString &defaultValue)
: d(new QCommandLineOptionPrivate)
{
d->setNames(QStringList(name));
setValueName(valueName);
setDescription(description);
setDefaultValue(defaultValue);
}
/*!
Constructs a command line option object with the given arguments.
This overload allows to set multiple names for the option, for instance
\c{o} and \c{output}.
The names of the option are set to \a names.
The names can be either short or long. Any name in the list that is one
character in length is a short name. Option names must not be empty,
must not start with a dash or a slash character, must not contain a \c{=}
and cannot be repeated.
The description is set to \a description. It is customary to add a "."
at the end of the description.
In addition, the \a valueName can be set if the option expects a value.
The default value for the option is set to \a defaultValue.
\sa setDescription(), setValueName(), setDefaultValues()
*/
QCommandLineOption::QCommandLineOption(const QStringList &names, const QString &description,
const QString &valueName,
const QString &defaultValue)
: d(new QCommandLineOptionPrivate)
{
d->setNames(names);
setValueName(valueName);
setDescription(description);
setDefaultValue(defaultValue);
}
/*!
Constructs a QCommandLineOption object that is a copy of the QCommandLineOption
object \a other.
\sa operator=()
*/
QCommandLineOption::QCommandLineOption(const QCommandLineOption &other)
: d(other.d)
{
}
/*!
Destroys the command line option object.
*/
QCommandLineOption::~QCommandLineOption()
{
}
/*!
Makes a copy of the \a other object and assigns it to this QCommandLineOption
object.
*/
QCommandLineOption &QCommandLineOption::operator=(const QCommandLineOption &other)
{
d = other.d;
return *this;
}
/*!
Returns the names set for this option.
*/
QStringList QCommandLineOption::names() const
{
return d->names;
}
void QCommandLineOptionPrivate::setNames(const QStringList &nameList)
{
QStringList newNames;
if (nameList.isEmpty())
qWarning("QCommandLineOption: Options must have at least one name");
Q_FOREACH (const QString &name, nameList) {
if (name.isEmpty()) {
qWarning("QCommandLineOption: Option names cannot be empty");
} else {
const QChar c = name.at(0);
if (c == QLatin1Char('-'))
qWarning("QCommandLineOption: Option names cannot start with a '-'");
else if (c == QLatin1Char('/'))
qWarning("QCommandLineOption: Option names cannot start with a '/'");
else if (name.contains(QLatin1Char('=')))
qWarning("QCommandLineOption: Option names cannot contain a '='");
else
newNames.append(name);
}
}
// commit
names = newNames;
}
/*!
Sets the name of the expected value, for the documentation, to \a valueName.
Options without a value assigned have a boolean-like behavior:
either the user specifies --option or they don't.
Options with a value assigned need to set a name for the expected value,
for the documentation of the option in the help output. An option with names \c{o} and \c{output},
and a value name of \c{file} will appear as \c{-o, --output <file>}.
Call QCommandLineParser::argument() if you expect the option to be present
only once, and QCommandLineParser::arguments() if you expect that option
to be present multiple times.
\sa valueName()
*/
void QCommandLineOption::setValueName(const QString &valueName)
{
d->valueName = valueName;
}
/*!
Returns the name of the expected value.
If empty, the option doesn't take a value.
\sa setValueName()
*/
QString QCommandLineOption::valueName() const
{
return d->valueName;
}
/*!
Sets the description used for this option to \a description.
It is customary to add a "." at the end of the description.
The description is used by QCommandLineParser::showHelp().
\sa description()
*/
void QCommandLineOption::setDescription(const QString &description)
{
d->description = description;
}
/*!
Returns the description set for this option.
\sa setDescription()
*/
QString QCommandLineOption::description() const
{
return d->description;
}
/*!
Sets the default value used for this option to \a defaultValue.
The default value is used if the user of the application does not specify
the option on the command line.
If \a defaultValue is empty, the option has no default values.
\sa defaultValues() setDefaultValues()
*/
void QCommandLineOption::setDefaultValue(const QString &defaultValue)
{
QStringList newDefaultValues;
if (!defaultValue.isEmpty()) {
newDefaultValues << defaultValue;
}
// commit:
d->defaultValues = newDefaultValues;
}
/*!
Sets the list of default values used for this option to \a defaultValues.
The default values are used if the user of the application does not specify
the option on the command line.
\sa defaultValues() setDefaultValue()
*/
void QCommandLineOption::setDefaultValues(const QStringList &defaultValues)
{
d->defaultValues = defaultValues;
}
/*!
Returns the default values set for this option.
\sa setDefaultValues()
*/
QStringList QCommandLineOption::defaultValues() const
{
return d->defaultValues;
}

View File

@@ -0,0 +1,81 @@
/****************************************************************************
**
** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QCOMMANDLINEOPTION_H
#define QCOMMANDLINEOPTION_H
#include <QStringList>
#include <QSharedData>
class QCommandLineOptionPrivate;
class QCommandLineOption
{
public:
explicit QCommandLineOption(const QString &name, const QString &description = QString(),
const QString &valueName = QString(),
const QString &defaultValue = QString());
explicit QCommandLineOption(const QStringList &names, const QString &description = QString(),
const QString &valueName = QString(),
const QString &defaultValue = QString());
QCommandLineOption(const QCommandLineOption &other);
~QCommandLineOption();
QCommandLineOption &operator=(const QCommandLineOption &other);
QStringList names() const;
void setValueName(const QString &name);
QString valueName() const;
void setDescription(const QString &description);
QString description() const;
void setDefaultValue(const QString &defaultValue);
void setDefaultValues(const QStringList &defaultValues);
QStringList defaultValues() const;
private:
QSharedDataPointer<QCommandLineOptionPrivate> d;
};
#endif // QCOMMANDLINEOPTION_H

View File

@@ -0,0 +1,944 @@
/****************************************************************************
**
** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
** Copyright (C) 2013 David Faure <faure@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qcommandlineparser.h"
#include <QCoreApplication>
#include <QHash>
#include <QVector>
#include <stdio.h>
#include <stdlib.h>
typedef QHash<QString, int> NameHash_t;
class QCommandLineParserPrivate
{
public:
inline QCommandLineParserPrivate()
: singleDashWordOptionMode(QCommandLineParser::ParseAsCompactedShortOptions),
builtinVersionOption(false),
builtinHelpOption(false),
needsParsing(true)
{ }
bool parse(const QStringList &args);
void checkParsed(const char *method);
QStringList aliases(const QString &name) const;
QString helpText() const;
bool registerFoundOption(const QString &optionName);
bool parseOptionValue(const QString &optionName, const QString &argument,
QStringList::const_iterator *argumentIterator,
QStringList::const_iterator argsEnd);
//! Error text set when parse() returns false
QString errorText;
//! The command line options used for parsing
QList<QCommandLineOption> commandLineOptionList;
//! Hash mapping option names to their offsets in commandLineOptionList and optionArgumentList.
NameHash_t nameHash;
//! Option values found (only for options with a value)
QHash<int, QStringList> optionValuesHash;
//! Names of options found on the command line.
QStringList optionNames;
//! Arguments which did not belong to any option.
QStringList positionalArgumentList;
//! Names of options which were unknown.
QStringList unknownOptionNames;
//! Application description
QString description;
//! Documentation for positional arguments
struct PositionalArgumentDefinition
{
QString name;
QString description;
QString syntax;
};
QVector<PositionalArgumentDefinition> positionalArgumentDefinitions;
//! The parsing mode for "-abc"
QCommandLineParser::SingleDashWordOptionMode singleDashWordOptionMode;
//! Whether addVersionOption was called
bool builtinVersionOption;
//! Whether addHelpOption was called
bool builtinHelpOption;
//! True if parse() needs to be called
bool needsParsing;
};
QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const
{
const NameHash_t::const_iterator it = nameHash.find(optionName);
if (it == nameHash.end()) {
qWarning("QCommandLineParser: option not defined: \"%s\"", qPrintable(optionName));
return QStringList();
}
return commandLineOptionList.at(*it).names();
}
/*!
\since 5.2
\class QCommandLineParser
\inmodule QtCore
\ingroup tools
\brief The QCommandLineParser class provides a means for handling the
command line options.
QCoreApplication provides the command-line arguments as a simple list of strings.
QCommandLineParser provides the ability to define a set of options, parse the
command-line arguments, and store which options have actually been used, as
well as option values.
Any argument that isn't an option (i.e. doesn't start with a \c{-}) is stored
as a "positional argument".
The parser handles short names, long names, more than one name for the same
option, and option values.
Options on the command line are recognized as starting with a single or
double \c{-} character(s).
The option \c{-} (single dash alone) is a special case, often meaning standard
input, and not treated as an option. The parser will treat everything after the
option \c{--} (double dash) as positional arguments.
Short options are single letters. The option \c{v} would be specified by
passing \c{-v} on the command line. In the default parsing mode, short options
can be written in a compact form, for instance \c{-abc} is equivalent to \c{-a -b -c}.
The parsing mode for can be set to ParseAsLongOptions, in which case \c{-abc}
will be parsed as the long option \c{abc}.
Long options are more than one letter long and cannot be compacted together.
The long option \c{verbose} would be passed as \c{--verbose} or \c{-verbose}.
Passing values to options can be done using the assignment operator: \c{-v=value}
\c{--verbose=value}, or a space: \c{-v value} \c{--verbose value}, i.e. the next
argument is used as value (even if it starts with a \c{-}).
The parser does not support optional values - if an option is set to
require a value, one must be present. If such an option is placed last
and has no value, the option will be treated as if it had not been
specified.
The parser does not automatically support negating or disabling long options
by using the format \c{--disable-option} or \c{--no-option}. However, it is
possible to handle this case explicitly by making an option with \c{no-option}
as one of its names, and handling the option explicitly.
Example:
\snippet code/src_corelib_tools_qcommandlineparser_main.cpp 0
Known limitation: the parsing of Qt options inside QCoreApplication and subclasses
happens before QCommandLineParser exists, so it can't take it into account. This
means any option value that looks like a builtin Qt option, will be treated by
QCoreApplication as a builtin Qt option. Example: \c{--profile -reverse} will
lead to QGuiApplication seeing the -reverse option set, and removing it from
QCoreApplication::arguments() before QCommandLineParser defines the \c{profile}
option and parses the command line.
\sa QCommandLineOption, QCoreApplication
*/
/*!
Constructs a command line parser object.
*/
QCommandLineParser::QCommandLineParser()
: d(new QCommandLineParserPrivate)
{
}
/*!
Destroys the command line parser object.
*/
QCommandLineParser::~QCommandLineParser()
{
delete d;
}
/*!
\enum QCommandLineParser::SingleDashWordOptionMode
This enum describes the way the parser interprets command-line
options that use a single dash followed by multiple letters, as as \c{-abc}.
\value ParseAsCompactedShortOptions \c{-abc} is interpreted as \c{-a -b -c},
i.e. as three short options that have been compacted on the command-line,
if none of the options take a value. If \c{a} takes a value, then it
is interpreted as \c{-a bc}, i.e. the short option \c{a} followed by the value \c{bc}.
This is typically used in tools that behave like compilers, in order
to handle options such as \c{-DDEFINE=VALUE} or \c{-I/include/path}.
This is the default parsing mode. New applications are recommended to
use this mode.
\value ParseAsLongOptions \c{-abc} is interpreted as \c{--abc},
i.e. as the long option named \c{abc}. This is how Qt's own tools
(uic, rcc...) have always been parsing arguments. This mode should be
used for preserving compatibility in applications that were parsing
arguments in such a way.
\sa setSingleDashWordOptionMode()
*/
/*!
Sets the parsing mode to \a singleDashWordOptionMode.
This must be called before process() or parse().
*/
void QCommandLineParser::setSingleDashWordOptionMode(QCommandLineParser::SingleDashWordOptionMode singleDashWordOptionMode)
{
d->singleDashWordOptionMode = singleDashWordOptionMode;
}
/*!
Adds the option \a option to look for while parsing.
Returns \c true if adding the option was successful; otherwise returns \c false.
Adding the option fails if there is no name attached to the option, or
the option has a name that clashes with an option name added before.
*/
bool QCommandLineParser::addOption(const QCommandLineOption &option)
{
QStringList optionNames = option.names();
if (!optionNames.isEmpty()) {
Q_FOREACH (const QString &name, optionNames) {
if (d->nameHash.contains(name))
return false;
}
d->commandLineOptionList.append(option);
const int offset = d->commandLineOptionList.size() - 1;
Q_FOREACH (const QString &name, optionNames)
d->nameHash.insert(name, offset);
return true;
}
return false;
}
/*!
Adds the \c{-v} / \c{--version} option, which displays the version string of the application.
This option is handled automatically by QCommandLineParser.
You can set the actual version string by using QCoreApplication::setApplicationVersion().
Returns the option instance, which can be used to call isSet().
*/
QCommandLineOption QCommandLineParser::addVersionOption()
{
QCommandLineOption opt(QStringList() << "v" << "version", tr("Displays version information."));
addOption(opt);
d->builtinVersionOption = true;
return opt;
}
/*!
Adds the help option (\c{-h}, \c{--help} and \c{-?} on Windows)
This option is handled automatically by QCommandLineParser.
Remember to use setApplicationDescription to set the application description,
which will be displayed when this option is used.
Example:
\snippet code/src_corelib_tools_qcommandlineparser_main.cpp 0
Returns the option instance, which can be used to call isSet().
*/
QCommandLineOption QCommandLineParser::addHelpOption()
{
QCommandLineOption opt(QStringList()
#ifdef Q_OS_WIN
<< "?"
#endif
<< "h"
<< "help", tr("Displays this help."));
addOption(opt);
d->builtinHelpOption = true;
return opt;
}
/*!
Sets the application \a description shown by helpText().
*/
void QCommandLineParser::setApplicationDescription(const QString &description)
{
d->description = description;
}
/*!
Returns the application description set in setApplicationDescription().
*/
QString QCommandLineParser::applicationDescription() const
{
return d->description;
}
/*!
Defines an additional argument to the application, for the benefit of the help text.
The argument \a name and \a description will appear under the \c{Arguments:} section
of the help. If \a syntax is specified, it will be appended to the Usage line, otherwise
the \a name will be appended.
Example:
\snippet code/src_corelib_tools_qcommandlineparser.cpp 2
\sa addHelpOption(), helpText()
*/
void QCommandLineParser::addPositionalArgument(const QString &name, const QString &description, const QString &syntax)
{
QCommandLineParserPrivate::PositionalArgumentDefinition arg;
arg.name = name;
arg.description = description;
arg.syntax = syntax.isEmpty() ? name : syntax;
d->positionalArgumentDefinitions.append(arg);
}
/*!
Clears the definitions of additional arguments from the help text.
This is only needed for the special case of tools which support multiple commands
with different options. Once the actual command has been identified, the options
for this command can be defined, and the help text for the command can be adjusted
accordingly.
Example:
\snippet code/src_corelib_tools_qcommandlineparser.cpp 3
*/
void QCommandLineParser::clearPositionalArguments()
{
d->positionalArgumentDefinitions.clear();
}
/*!
Parses the command line \a arguments.
Most programs don't need to call this, a simple call to process() is enough.
parse() is more low-level, and only does the parsing. The application will have to
take care of the error handling, using errorText() if parse() returns \c false.
This can be useful for instance to show a graphical error message in graphical programs.
Calling parse() instead of process() can also be useful in order to ignore unknown
options temporarily, because more option definitions will be provided later on
(depending on one of the arguments), before calling process().
Don't forget that \a arguments must start with the name of the executable (ignored, though).
Returns \c false in case of a parse error (unknown option or missing value); returns \c true otherwise.
\sa process()
*/
bool QCommandLineParser::parse(const QStringList &arguments)
{
return d->parse(arguments);
}
/*!
Returns a translated error text for the user.
This should only be called when parse() returns \c false.
*/
QString QCommandLineParser::errorText() const
{
if (!d->errorText.isEmpty())
return d->errorText;
if (d->unknownOptionNames.count() == 1)
return tr("Unknown option '%1'.").arg(d->unknownOptionNames.first());
if (d->unknownOptionNames.count() > 1)
return tr("Unknown options: %1.").arg(d->unknownOptionNames.join(", "));
return QString();
}
/*!
Processes the command line \a arguments.
In addition to parsing the options (like parse()), this function also handles the builtin
options and handles errors.
The builtin options are \c{--version} if addVersionOption was called and \c{--help} if addHelpOption was called.
When invoking one of these options, or when an error happens (for instance an unknown option was
passed), the current process will then stop, using the exit() function.
\sa QCoreApplication::arguments(), parse()
*/
void QCommandLineParser::process(const QStringList &arguments)
{
if (!d->parse(arguments)) {
fprintf(stderr, "%s\n", qPrintable(errorText()));
::exit(EXIT_FAILURE);
}
if (d->builtinVersionOption && isSet("version")) {
printf("%s %s\n", qPrintable(QCoreApplication::applicationName()), qPrintable(QCoreApplication::applicationVersion()));
::exit(EXIT_SUCCESS);
}
if (d->builtinHelpOption && isSet("help"))
showHelp(EXIT_SUCCESS);
}
/*!
\overload
The command line is obtained from the QCoreApplication instance \a app.
*/
void QCommandLineParser::process(const QCoreApplication &app)
{
// QCoreApplication::arguments() is static, but the app instance must exist so we require it as parameter
Q_UNUSED(app);
process(QCoreApplication::arguments());
}
void QCommandLineParserPrivate::checkParsed(const char *method)
{
if (needsParsing)
qWarning("QCommandLineParser: call process() or parse() before %s", method);
}
/*!
\internal
Looks up the option \a optionName (found on the command line) and register it as found.
Returns \c true on success.
*/
bool QCommandLineParserPrivate::registerFoundOption(const QString &optionName)
{
if (nameHash.contains(optionName)) {
optionNames.append(optionName);
return true;
} else {
unknownOptionNames.append(optionName);
return false;
}
}
/*!
\internal
\brief Parse the value for a given option, if it was defined to expect one.
The value is taken from the next argument, or after the equal sign in \a argument.
\param optionName the short option name
\param argument the argument from the command line currently parsed. Only used for -k=value parsing.
\param argumentIterator iterator to the currently parsed argument. Incremented if the next argument contains the value.
\param argsEnd args.end(), to check if ++argumentIterator goes out of bounds
Returns \c true on success.
*/
bool QCommandLineParserPrivate::parseOptionValue(const QString &optionName, const QString &argument,
QStringList::const_iterator *argumentIterator, QStringList::const_iterator argsEnd)
{
const QLatin1Char assignChar('=');
const NameHash_t::const_iterator nameHashIt = nameHash.constFind(optionName);
if (nameHashIt != nameHash.constEnd()) {
const int assignPos = argument.indexOf(assignChar);
const NameHash_t::mapped_type optionOffset = *nameHashIt;
const bool withValue = !commandLineOptionList.at(optionOffset).valueName().isEmpty();
if (withValue) {
if (assignPos == -1) {
++(*argumentIterator);
if (*argumentIterator == argsEnd) {
errorText = QCommandLineParser::tr("Missing value after '%1'.").arg(argument);
return false;
}
optionValuesHash[optionOffset].append(*(*argumentIterator));
} else {
optionValuesHash[optionOffset].append(argument.mid(assignPos + 1));
}
} else {
if (assignPos != -1) {
errorText = QCommandLineParser::tr("Unexpected value after '%1'.").arg(argument.left(assignPos));
return false;
}
}
}
return true;
}
/*!
\internal
Parse the list of arguments \a args, and fills in
optionNames, optionValuesHash, unknownOptionNames, positionalArguments, and errorText.
Any results from a previous parse operation are removed.
The parser will not look for further options once it encounters the option
\c{--}; this does not include when \c{--} follows an option that requires a value.
*/
bool QCommandLineParserPrivate::parse(const QStringList &args)
{
needsParsing = false;
bool error = false;
const QString doubleDashString("--");
const QLatin1Char dashChar('-');
const QLatin1Char assignChar('=');
bool doubleDashFound = false;
errorText.clear();
positionalArgumentList.clear();
optionNames.clear();
unknownOptionNames.clear();
optionValuesHash.clear();
if (args.isEmpty()) {
qWarning("QCommandLineParser: argument list cannot be empty, it should contain at least the executable name");
return false;
}
QStringList::const_iterator argumentIterator = args.begin();
++argumentIterator; // skip executable name
for (; argumentIterator != args.end() ; ++argumentIterator) {
QString argument = *argumentIterator;
if (doubleDashFound) {
positionalArgumentList.append(argument);
} else if (argument.startsWith(doubleDashString)) {
if (argument.length() > 2) {
QString optionName = argument.mid(2).section(assignChar, 0, 0);
if (registerFoundOption(optionName)) {
if (!parseOptionValue(optionName, argument, &argumentIterator, args.end()))
error = true;
} else {
error = true;
}
} else {
doubleDashFound = true;
}
} else if (argument.startsWith(dashChar)) {
if (argument.size() == 1) { // single dash ("stdin")
positionalArgumentList.append(argument);
continue;
}
switch (singleDashWordOptionMode) {
case QCommandLineParser::ParseAsCompactedShortOptions:
{
QString optionName;
bool valueFound = false;
for (int pos = 1 ; pos < argument.size(); ++pos) {
optionName = argument.mid(pos, 1);
if (!registerFoundOption(optionName)) {
error = true;
} else {
const NameHash_t::const_iterator nameHashIt = nameHash.constFind(optionName);
Q_ASSERT(nameHashIt != nameHash.constEnd()); // checked by registerFoundOption
const NameHash_t::mapped_type optionOffset = *nameHashIt;
const bool withValue = !commandLineOptionList.at(optionOffset).valueName().isEmpty();
if (withValue) {
if (pos + 1 < argument.size()) {
if (argument.at(pos + 1) == assignChar)
++pos;
optionValuesHash[optionOffset].append(argument.mid(pos + 1));
valueFound = true;
}
break;
}
if (pos + 1 < argument.size() && argument.at(pos + 1) == assignChar)
break;
}
}
if (!valueFound && !parseOptionValue(optionName, argument, &argumentIterator, args.end()))
error = true;
break;
}
case QCommandLineParser::ParseAsLongOptions:
{
const QString optionName = argument.mid(1).section(assignChar, 0, 0);
if (registerFoundOption(optionName)) {
if (!parseOptionValue(optionName, argument, &argumentIterator, args.end()))
error = true;
} else {
error = true;
}
break;
}
}
} else {
positionalArgumentList.append(argument);
}
if (argumentIterator == args.end())
break;
}
return !error;
}
/*!
Checks whether the option \a name was passed to the application.
Returns \c true if the option \a name was set, false otherwise.
The name provided can be any long or short name of any option that was
added with \c addOption(). All the options names are treated as being
equivalent. If the name is not recognized or that option was not present,
false is returned.
Example:
\snippet code/src_corelib_tools_qcommandlineparser.cpp 0
*/
bool QCommandLineParser::isSet(const QString &name) const
{
d->checkParsed("isSet");
if (d->optionNames.contains(name))
return true;
const QStringList aliases = d->aliases(name);
Q_FOREACH (const QString &optionName, d->optionNames) {
if (aliases.contains(optionName))
return true;
}
return false;
}
/*!
Returns the option value found for the given option name \a optionName, or
an empty string if not found.
The name provided can be any long or short name of any option that was
added with \c addOption(). All the option names are treated as being
equivalent. If the name is not recognized or that option was not present, an
empty string is returned.
For options found by the parser, the last value found for
that option is returned. If the option wasn't specified on the command line,
the default value is returned.
An empty string is returned if the option does not take a value.
\sa values(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues()
*/
QString QCommandLineParser::value(const QString &optionName) const
{
d->checkParsed("value");
const QStringList valueList = values(optionName);
if (!valueList.isEmpty())
return valueList.last();
return QString();
}
/*!
Returns a list of option values found for the given option name \a
optionName, or an empty list if not found.
The name provided can be any long or short name of any option that was
added with \c addOption(). All the options names are treated as being
equivalent. If the name is not recognized or that option was not present, an
empty list is returned.
For options found by the parser, the list will contain an entry for
each time the option was encountered by the parser. If the option wasn't
specified on the command line, the default values are returned.
An empty list is returned if the option does not take a value.
\sa value(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues()
*/
QStringList QCommandLineParser::values(const QString &optionName) const
{
d->checkParsed("values");
const NameHash_t::const_iterator it = d->nameHash.constFind(optionName);
if (it != d->nameHash.constEnd()) {
const int optionOffset = *it;
QStringList values = d->optionValuesHash.value(optionOffset);
if (values.isEmpty())
values = d->commandLineOptionList.at(optionOffset).defaultValues();
return values;
}
qWarning("QCommandLineParser: option not defined: \"%s\"", qPrintable(optionName));
return QStringList();
}
/*!
\overload
Checks whether the \a option was passed to the application.
Returns \c true if the \a option was set, false otherwise.
This is the recommended way to check for options with no values.
Example:
\snippet code/src_corelib_tools_qcommandlineparser.cpp 1
*/
bool QCommandLineParser::isSet(const QCommandLineOption &option) const
{
// option.names() might be empty if the constructor failed
return !option.names().isEmpty() && isSet(option.names().first());
}
/*!
\overload
Returns the option value found for the given \a option, or
an empty string if not found.
For options found by the parser, the last value found for
that option is returned. If the option wasn't specified on the command line,
the default value is returned.
An empty string is returned if the option does not take a value.
\sa values(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues()
*/
QString QCommandLineParser::value(const QCommandLineOption &option) const
{
return value(option.names().first());
}
/*!
\overload
Returns a list of option values found for the given \a option,
or an empty list if not found.
For options found by the parser, the list will contain an entry for
each time the option was encountered by the parser. If the option wasn't
specified on the command line, the default values are returned.
An empty list is returned if the option does not take a value.
\sa value(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues()
*/
QStringList QCommandLineParser::values(const QCommandLineOption &option) const
{
return values(option.names().first());
}
/*!
Returns a list of positional arguments.
These are all of the arguments that were not recognized as part of an
option.
*/
QStringList QCommandLineParser::positionalArguments() const
{
d->checkParsed("positionalArguments");
return d->positionalArgumentList;
}
/*!
Returns a list of option names that were found.
This returns a list of all the recognized option names found by the
parser, in the order in which they were found. For any long options
that were in the form {--option=value}, the value part will have been
dropped.
The names in this list do not include the preceding dash characters.
Names may appear more than once in this list if they were encountered
more than once by the parser.
Any entry in the list can be used with \c value() or with
\c values() to get any relevant option values.
*/
QStringList QCommandLineParser::optionNames() const
{
d->checkParsed("optionNames");
return d->optionNames;
}
/*!
Returns a list of unknown option names.
This list will include both long an short name options that were not
recognized. For any long options that were in the form {--option=value},
the value part will have been dropped and only the long name is added.
The names in this list do not include the preceding dash characters.
Names may appear more than once in this list if they were encountered
more than once by the parser.
\sa optionNames()
*/
QStringList QCommandLineParser::unknownOptionNames() const
{
d->checkParsed("unknownOptionNames");
return d->unknownOptionNames;
}
/*!
Displays the help information, and exits the application.
This is automatically triggered by the --help option, but can also
be used to display the help when the user is not invoking the
application correctly.
The exit code is set to \a exitCode. It should be set to 0 if the
user requested to see the help, and to any other value in case of
an error.
\sa helpText()
*/
void QCommandLineParser::showHelp(int exitCode)
{
fprintf(stdout, "%s", qPrintable(d->helpText()));
::exit(exitCode);
}
/*!
Returns a string containing the complete help information.
\sa showHelp()
*/
QString QCommandLineParser::helpText() const
{
return d->helpText();
}
static QString wrapText(const QString &names, int longestOptionNameString, const QString &description)
{
const QLatin1Char nl('\n');
QString text = QString(" ") + names.leftJustified(longestOptionNameString) + QLatin1Char(' ');
const int indent = text.length();
int lineStart = 0;
int lastBreakable = -1;
const int max = 79 - indent;
int x = 0;
const int len = description.length();
for (int i = 0; i < len; ++i) {
++x;
const QChar c = description.at(i);
if (c.isSpace())
lastBreakable = i;
int breakAt = -1;
int nextLineStart = -1;
if (x > max && lastBreakable != -1) {
// time to break and we know where
breakAt = lastBreakable;
nextLineStart = lastBreakable + 1;
} else if ((x > max - 1 && lastBreakable == -1) || i == len - 1) {
// time to break but found nowhere [-> break here], or end of last line
breakAt = i + 1;
nextLineStart = breakAt;
} else if (c == nl) {
// forced break
breakAt = i;
nextLineStart = i + 1;
}
if (breakAt != -1) {
const int numChars = breakAt - lineStart;
//qDebug() << "breakAt=" << description.at(breakAt) << "breakAtSpace=" << breakAtSpace << lineStart << "to" << breakAt << description.mid(lineStart, numChars);
if (lineStart > 0)
text += QString(indent, QLatin1Char(' '));
text += description.mid(lineStart, numChars) + nl;
x = 0;
lastBreakable = -1;
lineStart = nextLineStart;
if (lineStart < len && description.at(lineStart).isSpace())
++lineStart; // don't start a line with a space
i = lineStart;
}
}
return text;
}
QString QCommandLineParserPrivate::helpText() const
{
const QLatin1Char nl('\n');
QString text;
const QString exeName = QCoreApplication::instance()->arguments().first();
QString usage = exeName;
if (!commandLineOptionList.isEmpty()) {
usage += QLatin1Char(' ');
usage += QCommandLineParser::tr("[options]");
}
Q_FOREACH (const PositionalArgumentDefinition &arg, positionalArgumentDefinitions) {
usage += QLatin1Char(' ');
usage += arg.syntax;
}
text += QCommandLineParser::tr("Usage: %1").arg(usage) + nl;
if (!description.isEmpty())
text += description + nl;
text += nl;
if (!commandLineOptionList.isEmpty())
text += QCommandLineParser::tr("Options:") + nl;
QStringList optionNameList;
int longestOptionNameString = 0;
Q_FOREACH (const QCommandLineOption &option, commandLineOptionList) {
QStringList optionNames;
Q_FOREACH (const QString &optionName, option.names()) {
if (optionName.length() == 1)
optionNames.append(QLatin1Char('-') + optionName);
else
optionNames.append(QString("--") + optionName);
}
QString optionNamesString = optionNames.join(", ");
if (!option.valueName().isEmpty())
optionNamesString += QString(" <") + option.valueName() + QLatin1Char('>');
optionNameList.append(optionNamesString);
longestOptionNameString = qMax(longestOptionNameString, optionNamesString.length());
}
++longestOptionNameString;
for (int i = 0; i < commandLineOptionList.count(); ++i) {
const QCommandLineOption &option = commandLineOptionList.at(i);
text += wrapText(optionNameList.at(i), longestOptionNameString, option.description());
}
if (!positionalArgumentDefinitions.isEmpty()) {
if (!commandLineOptionList.isEmpty())
text += nl;
text += QCommandLineParser::tr("Arguments:") + nl;
Q_FOREACH (const PositionalArgumentDefinition &arg, positionalArgumentDefinitions) {
text += wrapText(arg.name, longestOptionNameString, arg.description);
}
}
return text;
}

View File

@@ -0,0 +1,102 @@
/****************************************************************************
**
** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QCOMMANDLINEPARSER_H
#define QCOMMANDLINEPARSER_H
#include <QStringList>
#include <QCoreApplication>
#include "qcommandlineoption.h"
class QCommandLineParserPrivate;
class QCoreApplication;
class QCommandLineParser
{
Q_DECLARE_TR_FUNCTIONS(QCommandLineParser)
public:
QCommandLineParser();
~QCommandLineParser();
enum SingleDashWordOptionMode {
ParseAsCompactedShortOptions,
ParseAsLongOptions
};
void setSingleDashWordOptionMode(SingleDashWordOptionMode parsingMode);
bool addOption(const QCommandLineOption &commandLineOption);
QCommandLineOption addVersionOption();
QCommandLineOption addHelpOption();
void setApplicationDescription(const QString &description);
QString applicationDescription() const;
void addPositionalArgument(const QString &name, const QString &description, const QString &syntax = QString());
void clearPositionalArguments();
void process(const QStringList &arguments);
void process(const QCoreApplication &app);
bool parse(const QStringList &arguments);
QString errorText() const;
bool isSet(const QString &name) const;
QString value(const QString &name) const;
QStringList values(const QString &name) const;
bool isSet(const QCommandLineOption &option) const;
QString value(const QCommandLineOption &option) const;
QStringList values(const QCommandLineOption &option) const;
QStringList positionalArguments() const;
QStringList optionNames() const;
QStringList unknownOptionNames() const;
void showHelp(int exitCode = 0);
QString helpText() const;
private:
Q_DISABLE_COPY(QCommandLineParser)
QCommandLineParserPrivate * const d;
};
#endif // QCOMMANDLINEPARSER_H

View File

@@ -42,9 +42,9 @@
#include "qsavefile.h" #include "qsavefile.h"
#include "qsavefile_p.h" #include "qsavefile_p.h"
#include <QtCore/QAbstractFileEngine> #include <QAbstractFileEngine>
#include <QtCore/QFileInfo> #include <QFileInfo>
#include <QtCore/QTemporaryFile> #include <QTemporaryFile>
QSaveFilePrivate::QSaveFilePrivate() QSaveFilePrivate::QSaveFilePrivate()
: tempFile(0), error(QFile::NoError) : tempFile(0), error(QFile::NoError)

View File

@@ -42,8 +42,8 @@
#ifndef QSAVEFILE_H #ifndef QSAVEFILE_H
#define QSAVEFILE_H #define QSAVEFILE_H
#include <QtCore/QFile> #include <QFile>
#include <QtCore/QString> #include <QString>
#ifdef open #ifdef open
#error qsavefile.h must be included before any header file that defines open #error qsavefile.h must be included before any header file that defines open

View File

@@ -53,7 +53,7 @@
// We mean it. // We mean it.
// //
#include <QtCore/QTemporaryFile> #include <QTemporaryFile>
class QSaveFilePrivate class QSaveFilePrivate
{ {

View File

@@ -17,12 +17,13 @@
#include "Crypto.h" #include "Crypto.h"
#include <QtCore/QMutex> #include <QMutex>
#include <gcrypt.h> #include <gcrypt.h>
bool Crypto::m_initalized(false); bool Crypto::m_initalized(false);
#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600)
static int gcry_qt_mutex_init(void** p_sys) static int gcry_qt_mutex_init(void** p_sys)
{ {
*p_sys = new QMutex(); *p_sys = new QMutex();
@@ -57,6 +58,7 @@ static const struct gcry_thread_cbs gcry_threads_qt =
gcry_qt_mutex_unlock, gcry_qt_mutex_unlock,
0, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0, 0
}; };
#endif
Crypto::Crypto() Crypto::Crypto()
{ {
@@ -69,7 +71,10 @@ void Crypto::init()
return; return;
} }
// libgcrypt >= 1.6 doesn't allow custom thread callbacks anymore.
#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600)
gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_qt); gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_qt);
#endif
gcry_check_version(0); gcry_check_version(0);
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);

View File

@@ -18,7 +18,7 @@
#ifndef KEEPASSX_CRYPTOHASH_H #ifndef KEEPASSX_CRYPTOHASH_H
#define KEEPASSX_CRYPTOHASH_H #define KEEPASSX_CRYPTOHASH_H
#include <QtCore/QByteArray> #include <QByteArray>
class CryptoHashPrivate; class CryptoHashPrivate;

View File

@@ -21,9 +21,17 @@
#include "crypto/Crypto.h" #include "crypto/Crypto.h"
class RandomBackendGcrypt : public RandomBackend
{
public:
void randomize(void* data, int len) Q_DECL_OVERRIDE;
};
Random* Random::m_instance(Q_NULLPTR);
void Random::randomize(QByteArray& ba) void Random::randomize(QByteArray& ba)
{ {
randomize(ba.data(), ba.size()); m_backend->randomize(ba.data(), ba.size());
} }
QByteArray Random::randomArray(int len) QByteArray Random::randomArray(int len)
@@ -38,8 +46,18 @@ QByteArray Random::randomArray(int len)
quint32 Random::randomUInt(quint32 limit) quint32 Random::randomUInt(quint32 limit)
{ {
Q_ASSERT(limit != 0);
Q_ASSERT(limit <= QUINT32_MAX);
quint32 rand; quint32 rand;
randomize(&rand, 4); const quint32 ceil = QUINT32_MAX - (QUINT32_MAX % limit) - 1;
// To avoid modulo bias:
// Make sure rand is below the largest number where rand%limit==0
do {
m_backend->randomize(&rand, 4);
} while (rand > ceil);
return (rand % limit); return (rand % limit);
} }
@@ -48,13 +66,32 @@ quint32 Random::randomUIntRange(quint32 min, quint32 max)
return min + randomUInt(max - min); return min + randomUInt(max - min);
} }
void Random::randomize(void* data, int len) Random* Random::instance()
{
if (!m_instance) {
m_instance = new Random(new RandomBackendGcrypt());
}
return m_instance;
}
void Random::createWithBackend(RandomBackend* backend)
{
Q_ASSERT(backend);
Q_ASSERT(!m_instance);
m_instance = new Random(backend);
}
Random::Random(RandomBackend* backend)
: m_backend(backend)
{
}
void RandomBackendGcrypt::randomize(void* data, int len)
{ {
Q_ASSERT(Crypto::initalized()); Q_ASSERT(Crypto::initalized());
gcry_randomize(data, len, GCRY_STRONG_RANDOM); gcry_randomize(data, len, GCRY_STRONG_RANDOM);
} }
Random::Random()
{
}

View File

@@ -18,27 +18,46 @@
#ifndef KEEPASSX_RANDOM_H #ifndef KEEPASSX_RANDOM_H
#define KEEPASSX_RANDOM_H #define KEEPASSX_RANDOM_H
#include <QtCore/QByteArray> #include <QByteArray>
#include <QScopedPointer>
class RandomBackend
{
public:
virtual void randomize(void* data, int len) = 0;
virtual ~RandomBackend() {}
};
class Random class Random
{ {
public: public:
static void randomize(QByteArray& ba); void randomize(QByteArray& ba);
static QByteArray randomArray(int len); QByteArray randomArray(int len);
/** /**
* Generate a random quint32 in the range [0, @p limit) * Generate a random quint32 in the range [0, @p limit)
*/ */
static quint32 randomUInt(quint32 limit); quint32 randomUInt(quint32 limit);
/** /**
* Generate a random quint32 in the range [@p min, @p max) * Generate a random quint32 in the range [@p min, @p max)
*/ */
static quint32 randomUIntRange(quint32 min, quint32 max); quint32 randomUIntRange(quint32 min, quint32 max);
static Random* instance();
static void createWithBackend(RandomBackend* backend);
private: private:
static void randomize(void* data, int len); explicit Random(RandomBackend* backend);
Random();
QScopedPointer<RandomBackend> m_backend;
static Random* m_instance;
Q_DISABLE_COPY(Random)
}; };
inline Random* randomGen() {
return Random::instance();
}
#endif // KEEPASSX_RANDOM_H #endif // KEEPASSX_RANDOM_H

View File

@@ -17,6 +17,7 @@
#include "SymmetricCipher.h" #include "SymmetricCipher.h"
#include "config-keepassx.h"
#include "crypto/SymmetricCipherGcrypt.h" #include "crypto/SymmetricCipherGcrypt.h"
#include "crypto/SymmetricCipherSalsa20.h" #include "crypto/SymmetricCipherSalsa20.h"
@@ -24,7 +25,6 @@ SymmetricCipher::SymmetricCipher(SymmetricCipher::Algorithm algo, SymmetricCiphe
SymmetricCipher::Direction direction, const QByteArray& key, const QByteArray& iv) SymmetricCipher::Direction direction, const QByteArray& key, const QByteArray& iv)
: m_backend(createBackend(algo, mode, direction)) : m_backend(createBackend(algo, mode, direction))
{ {
m_backend->init();
m_backend->setKey(key); m_backend->setKey(key);
m_backend->setIv(iv); m_backend->setIv(iv);
} }
@@ -39,10 +39,15 @@ SymmetricCipherBackend* SymmetricCipher::createBackend(SymmetricCipher::Algorith
switch (algo) { switch (algo) {
case SymmetricCipher::Aes256: case SymmetricCipher::Aes256:
case SymmetricCipher::Twofish: case SymmetricCipher::Twofish:
#if defined(GCRYPT_HAS_SALSA20)
case SymmetricCipher::Salsa20:
#endif
return new SymmetricCipherGcrypt(algo, mode, direction); return new SymmetricCipherGcrypt(algo, mode, direction);
#if !defined(GCRYPT_HAS_SALSA20)
case SymmetricCipher::Salsa20: case SymmetricCipher::Salsa20:
return new SymmetricCipherSalsa20(algo, mode, direction); return new SymmetricCipherSalsa20(algo, mode, direction);
#endif
default: default:
Q_ASSERT(false); Q_ASSERT(false);

View File

@@ -18,8 +18,8 @@
#ifndef KEEPASSX_SYMMETRICCIPHER_H #ifndef KEEPASSX_SYMMETRICCIPHER_H
#define KEEPASSX_SYMMETRICCIPHER_H #define KEEPASSX_SYMMETRICCIPHER_H
#include <QtCore/QByteArray> #include <QByteArray>
#include <QtCore/QScopedPointer> #include <QScopedPointer>
#include "core/Global.h" #include "core/Global.h"
#include "crypto/SymmetricCipherBackend.h" #include "crypto/SymmetricCipherBackend.h"

View File

@@ -18,13 +18,12 @@
#ifndef KEEPASSX_SYMMETRICCIPHERBACKEND_H #ifndef KEEPASSX_SYMMETRICCIPHERBACKEND_H
#define KEEPASSX_SYMMETRICCIPHERBACKEND_H #define KEEPASSX_SYMMETRICCIPHERBACKEND_H
#include <QtCore/QByteArray> #include <QByteArray>
class SymmetricCipherBackend class SymmetricCipherBackend
{ {
public: public:
virtual ~SymmetricCipherBackend() {} virtual ~SymmetricCipherBackend() {}
virtual void init() = 0;
virtual void setKey(const QByteArray& key) = 0; virtual void setKey(const QByteArray& key) = 0;
virtual void setIv(const QByteArray& iv) = 0; virtual void setIv(const QByteArray& iv) = 0;

View File

@@ -17,6 +17,7 @@
#include "SymmetricCipherGcrypt.h" #include "SymmetricCipherGcrypt.h"
#include "config-keepassx.h"
#include "crypto/Crypto.h" #include "crypto/Crypto.h"
SymmetricCipherGcrypt::SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode, SymmetricCipherGcrypt::SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode,
@@ -24,8 +25,19 @@ SymmetricCipherGcrypt::SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, Sy
: m_algo(gcryptAlgo(algo)) : m_algo(gcryptAlgo(algo))
, m_mode(gcryptMode(mode)) , m_mode(gcryptMode(mode))
, m_direction(direction) , m_direction(direction)
, m_blockSize(-1)
{ {
Q_ASSERT(Crypto::initalized()); Q_ASSERT(Crypto::initalized());
gcry_error_t error;
error = gcry_cipher_open(&m_ctx, m_algo, m_mode, 0);
Q_ASSERT(error == 0); // TODO: real error checking
size_t blockSizeT;
error = gcry_cipher_algo_info(m_algo, GCRYCTL_GET_BLKLEN, Q_NULLPTR, &blockSizeT);
Q_ASSERT(error == 0);
m_blockSize = blockSizeT;
} }
SymmetricCipherGcrypt::~SymmetricCipherGcrypt() SymmetricCipherGcrypt::~SymmetricCipherGcrypt()
@@ -42,6 +54,11 @@ int SymmetricCipherGcrypt::gcryptAlgo(SymmetricCipher::Algorithm algo)
case SymmetricCipher::Twofish: case SymmetricCipher::Twofish:
return GCRY_CIPHER_TWOFISH; return GCRY_CIPHER_TWOFISH;
#ifdef GCRYPT_HAS_SALSA20
case SymmetricCipher::Salsa20:
return GCRY_CIPHER_SALSA20;
#endif
default: default:
Q_ASSERT(false); Q_ASSERT(false);
return -1; return -1;
@@ -57,25 +74,15 @@ int SymmetricCipherGcrypt::gcryptMode(SymmetricCipher::Mode mode)
case SymmetricCipher::Cbc: case SymmetricCipher::Cbc:
return GCRY_CIPHER_MODE_CBC; return GCRY_CIPHER_MODE_CBC;
case SymmetricCipher::Stream:
return GCRY_CIPHER_MODE_STREAM;
default: default:
Q_ASSERT(false); Q_ASSERT(false);
return -1; return -1;
} }
} }
void SymmetricCipherGcrypt::init()
{
gcry_error_t error;
error = gcry_cipher_open(&m_ctx, m_algo, m_mode, 0);
Q_ASSERT(error == 0); // TODO: real error checking
size_t blockSizeT;
error = gcry_cipher_algo_info(m_algo, GCRYCTL_GET_BLKLEN, Q_NULLPTR, &blockSizeT);
Q_ASSERT(error == 0);
m_blockSize = blockSizeT;
}
void SymmetricCipherGcrypt::setKey(const QByteArray& key) void SymmetricCipherGcrypt::setKey(const QByteArray& key)
{ {
m_key = key; m_key = key;
@@ -133,15 +140,18 @@ void SymmetricCipherGcrypt::processInPlace(QByteArray& data, quint64 rounds)
gcry_error_t error; gcry_error_t error;
char* rawData = data.data();
int size = data.size();
if (m_direction == SymmetricCipher::Decrypt) { if (m_direction == SymmetricCipher::Decrypt) {
for (quint64 i = 0; i != rounds; ++i) { for (quint64 i = 0; i != rounds; ++i) {
error = gcry_cipher_decrypt(m_ctx, data.data(), data.size(), Q_NULLPTR, 0); error = gcry_cipher_decrypt(m_ctx, rawData, size, Q_NULLPTR, 0);
Q_ASSERT(error == 0); Q_ASSERT(error == 0);
} }
} }
else { else {
for (quint64 i = 0; i != rounds; ++i) { for (quint64 i = 0; i != rounds; ++i) {
error = gcry_cipher_encrypt(m_ctx, data.data(), data.size(), Q_NULLPTR, 0); error = gcry_cipher_encrypt(m_ctx, rawData, size, Q_NULLPTR, 0);
Q_ASSERT(error == 0); Q_ASSERT(error == 0);
} }
} }

View File

@@ -29,7 +29,6 @@ public:
SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode, SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode,
SymmetricCipher::Direction direction); SymmetricCipher::Direction direction);
~SymmetricCipherGcrypt(); ~SymmetricCipherGcrypt();
void init();
void setKey(const QByteArray& key); void setKey(const QByteArray& key);
void setIv(const QByteArray& iv); void setIv(const QByteArray& iv);

View File

@@ -33,10 +33,6 @@ SymmetricCipherSalsa20::~SymmetricCipherSalsa20()
{ {
} }
void SymmetricCipherSalsa20::init()
{
}
void SymmetricCipherSalsa20::setKey(const QByteArray& key) void SymmetricCipherSalsa20::setKey(const QByteArray& key)
{ {
Q_ASSERT((key.size() == 16) || (key.size() == 32)); Q_ASSERT((key.size() == 16) || (key.size() == 32));

View File

@@ -31,7 +31,6 @@ public:
void setAlgorithm(SymmetricCipher::Algorithm algo); void setAlgorithm(SymmetricCipher::Algorithm algo);
void setMode(SymmetricCipher::Mode mode); void setMode(SymmetricCipher::Mode mode);
void setDirection(SymmetricCipher::Direction direction); void setDirection(SymmetricCipher::Direction direction);
void init();
void setKey(const QByteArray& key); void setKey(const QByteArray& key);
void setIv(const QByteArray& iv); void setIv(const QByteArray& iv);

Some files were not shown because too many files have changed in this diff Show More