-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for custom data #1494
Conversation
8e5c201
to
616732d
Compare
616732d
to
1e4dfa0
Compare
FYI: the Remove button doesn't have a confirmation when removing custom data. Removing attributes does that. Should that be done here too? |
KeePass2 does not pop up any dialog - but this is may change in the future. Sounds like a good idea since removing data is potentially tinkering with the data of some plugin which may lead to unexpected behavior. |
src/core/CustomData.cpp
Outdated
while (i.hasNext()) { | ||
i.next(); | ||
size += i.key().toUtf8().size() + i.value().toUtf8().size(); | ||
size += i.key().toUtf8().size() + i.value().toString().toUtf8().size(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may look at this again - QVariant::toString()
does give the correct size for arbitrary variants afaik. To calculate the correct size, one should cast to the correct type and than calculate the size for the specific type. KeePass2 does implement CustomData with a StringDictionary so I would suggest going back to QString
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please rethink the change of CustomData
from QString
to QVariant
since this does not match the use in KeePass2.
KeePass2 uses a StringDictionary for custom entry/group data, but a VariantDictionary for custom header data. A variant map can do both, a string map can only be used for string data. |
Do you want to merge the data container for PulicCustomData and CustomData? PublicCustomData is currently a variant dict, but when I interpret the KeePass2 source code comment correctly, it is not encouraged to use this for plugin development since the data is not encrypted (and not exported to xml). I would suggest to keep both separate - the |
This is again where the KDBX4 specification is incomplete and totally misleading. I didn't realize that a database has both custom data and public custom data. I think we really need to work on a specification document ourselves. It is so annoying when I need to browse the KeePass source code only to understand the spec. If those are two fields, I think it makes sense to restrict it to QString and then use a plain QVariantMap for public custom data (although it's possible to use arbitrary data types for the XML stuff, too, which are then automatically converted to QString). |
1e4dfa0
to
0425d20
Compare
I updated the PR to properly handle both public custom data and custom data on database level. Please have a look. |
9901683
to
94ec995
Compare
@varjolintu Fixed. I also enable the button only when a row is selected and I activated column headers. |
9a32448
to
202338a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please look at my annotations, not sure if I introduced the error, but entries in Metadata::customData()
are supported in formats below Kdbx4.
bool KeePass2Writer::writeDatabase(QIODevice* device, Database* db) { | ||
m_error = false; | ||
m_errorStr.clear(); | ||
|
||
// determine KDBX3 vs KDBX4 | ||
if (db->kdf()->uuid() == KeePass2::KDF_AES_KDBX3 && db->publicCustomData().isEmpty()) { | ||
bool hasCustomData = !db->publicCustomData().isEmpty() || (db->metadata()->customData() && !db->metadata()->customData()->isEmpty()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Entries in Metadata::customData()
do not force KeePass2::FILE_VERSION_4
. Just entries within Database::publicCustomData()
, Entry::customData()
and Group::customData()
force the new format .
@@ -129,7 +129,9 @@ void KdbxXmlWriter::writeMetadata() | |||
if (m_kdbxVersion < KeePass2::FILE_VERSION_4) { | |||
writeBinaries(); | |||
} | |||
writeCustomData(); | |||
if (m_kdbxVersion >= KeePass2::FILE_VERSION_4) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Metadata::customData()
was supported in versions below KeePass2::FILE_VERSION_4
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True. I verified it by exporting an XML database with KeePass 2.34.
I think now we got everything the way KeePass does. Again, KDBX4 spec is pretty useless.
1bff019
to
64bb614
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, couple changes
emit modified(); | ||
} | ||
|
||
void CustomData::rename(const QString& oldKey, const QString& newKey) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is never used and I don't see a case for it either. Custom Data is not directly user editable. Recommend remove.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may be useful for plugins, but I don't know how often a plugin needs to rename a field.
return m_data.contains(key); | ||
} | ||
|
||
bool CustomData::containsValue(const QString& value) const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Function never used, recommend remove.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed both.
@@ -632,6 +645,7 @@ Entry* Entry::clone(CloneFlags flags) const | |||
entry->m_uuid = m_uuid; | |||
} | |||
entry->m_data = m_data; | |||
entry->m_customData->copyDataFrom(m_customData); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we just call entry->copyDataFrom(this)
for all these since we are duplicating code from below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very good point. Fixed.
if (config()->get("IgnoreGroupExpansion").toBool()) { | ||
updateTimeinfo(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't you want to do this AFTER the conditional (or not at all)? I'd imagine if you were ignoring group expansion you wouldn't want to update the time info.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After the conditional, the modified()-self-updating mechanism does update the timestamp. The conditional does a short-cut return, explicitly preventing the modified() signal, so a manual update was necessary to keep the existing behavior. I would suggest to move this discussion to another ticket since it is not related to the issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed it. It contradicts the purpose of that setting and calling updateTimeinfo() without emitting modified() makes no sense anyway.
@@ -186,6 +191,8 @@ class Group : public QObject | |||
QList<Group*> m_children; | |||
QList<Entry*> m_entries; | |||
|
|||
QPointer<CustomData> m_customData; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove extra space
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
tests/TestKdbx4.cpp
Outdated
QVariantMap publicCustomData; | ||
publicCustomData.insert("CustomPublicData", "Hey look, I turned myself into a pickle!"); | ||
sourceDb->setPublicCustomData(publicCustomData); | ||
sourceDb->rootGroup()->customData()->set("CustomGroupData", "I just killed my family! I don't care who they were!"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A little morbid...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a quote. :-D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha, I don't watch Rick and Morty... although maybe I should!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should.
e6af788
to
5691806
Compare
Introduce missing CustomData-attributes of KDBX4 format to allow storing of plugin data for groups and entries - adopt Metadata to use the same storage mechanism Add simple view for CustomData as part of EditWidgetProperties Tracking of CustomData-Modification using SIGNAL-SLOT update-mechanism
Ensure adding custom data upgrades to KDBX4 Implement review feedback
5691806
to
f4246d9
Compare
- Add support for KDBX 4.0, Argon2 and ChaCha20 [#148, #1179, #1230, #1494] - Add SSH Agent feature [#1098, #1450, #1463] - Add preview panel with details of the selected entry [#879, #1338] - Add more and configurable columns to entry table and allow copying of values by double click [#1305] - Add KeePassXC-Browser API as a replacement for KeePassHTTP [#608] - Deprecate KeePassHTTP [#1392] - Add support for Steam one-time passwords [#1206] - Add support for multiple Auto-Type sequences for a single entry [#1390] - Adjust YubiKey HMAC-SHA1 challenge-response key generation for KDBX 4.0 [#1060] - Replace qHttp with cURL for website icon downloads [#1460] - Remove lock file [#1231] - Add option to create backup file before saving [#1385] - Ask to save a generated password before closing the entry password generator [#1499] - Resolve placeholders recursively [#1078] - Add Auto-Type button to the toolbar [#1056] - Improve window focus handling for Auto-Type dialogs [#1204, #1490] - Auto-Type dialog and password generator can now be exited with ESC [#1252, #1412] - Add optional dark tray icon [#1154] - Add new "Unsafe saving" option to work around saving problems with file sync services [#1385] - Add IBus support to AppImage and additional image formats to Windows builds [#1534, #1537] - Add diceware password generator to CLI [#1406] - Add --key-file option to CLI [#816, #824] - Add DBus interface for opening and closing KeePassXC databases [#283] - Add KDBX compression options to database settings [#1419] - Discourage use of old fixed-length key files in favor of arbitrary files [#1326, #1327] - Correct reference resolution in entry fields [#1486] - Fix window state and recent databases not being remembered on exit [#1453] - Correct history item generation when configuring TOTP for an entry [#1446] - Correct multiple TOTP bugs [#1414] - Automatic saving after every change is now a default [#279] - Allow creation of new entries during search [#1398] - Correct menu issues on macOS [#1335] - Allow compilation on OpenBSD [#1328] - Improve entry attachments view [#1139, #1298] - Fix auto lock for Gnome and Xfce [#910, #1249] - Don't remember key files in file dialogs when the setting is disabled [#1188] - Improve database merging and conflict resolution [#807, #1165] - Fix macOS pasteboard issues [#1202] - Improve startup times on some platforms [#1205] - Hide the notes field by default [#1124] - Toggle main window by clicking tray icon with the middle mouse button [#992] - Fix custom icons not copied over when databases are merged [#1008] - Allow use of DEL key to delete entries [#914] - Correct intermittent crash due to stale history items [#1527] - Sanitize newline characters in title, username and URL fields [#1502] - Reopen previously opened databases in correct order [#774] - Use system's zxcvbn library if available [#701] - Implement various i18n improvements [#690, #875, #1436]
Description
Adds support for custom plugin data, which were previously discarded silently.
This is the same as #1477, but with these additional fixes (I can't push to the original PR, because the repository is private):
Types of changes
Checklist:
-DWITH_ASAN=ON
. [REQUIRED]