@@ -92,6 +92,29 @@ void Entry::setUpdateTimeinfo(bool value)
92
92
m_updateTimeinfo = value;
93
93
}
94
94
95
+ EntryReferenceType Entry::referenceType (const QString& referenceStr)
96
+ {
97
+ const QString referenceLowerStr = referenceStr.toLower ();
98
+ EntryReferenceType result = EntryReferenceType::Unknown;
99
+ if (referenceLowerStr == QLatin1String (" t" )) {
100
+ result = EntryReferenceType::Title;
101
+ } else if (referenceLowerStr == QLatin1String (" u" )) {
102
+ result = EntryReferenceType::UserName;
103
+ } else if (referenceLowerStr == QLatin1String (" p" )) {
104
+ result = EntryReferenceType::Password;
105
+ } else if (referenceLowerStr == QLatin1String (" a" )) {
106
+ result = EntryReferenceType::Url;
107
+ } else if (referenceLowerStr == QLatin1String (" n" )) {
108
+ result = EntryReferenceType::Notes;
109
+ } else if (referenceLowerStr == QLatin1String (" i" )) {
110
+ result = EntryReferenceType::Uuid;
111
+ } else if (referenceLowerStr == QLatin1String (" o" )) {
112
+ result = EntryReferenceType::CustomAttributes;
113
+ }
114
+
115
+ return result;
116
+ }
117
+
95
118
Uuid Entry::uuid () const
96
119
{
97
120
return m_uuid;
@@ -699,7 +722,7 @@ void Entry::updateModifiedSinceBegin()
699
722
m_modifiedSinceBegin = true ;
700
723
}
701
724
702
- QString Entry::resolveMultiplePlaceholdersRecursive (const QString & str, int maxDepth) const
725
+ QString Entry::resolveMultiplePlaceholdersRecursive (const QString& str, int maxDepth) const
703
726
{
704
727
if (maxDepth <= 0 ) {
705
728
qWarning (" Maximum depth of replacement has been reached. Entry uuid: %s" , qPrintable (uuid ().toHex ()));
@@ -723,15 +746,12 @@ QString Entry::resolveMultiplePlaceholdersRecursive(const QString &str, int maxD
723
746
return result;
724
747
}
725
748
726
- QString Entry::resolvePlaceholderRecursive (const QString & placeholder, int maxDepth) const
749
+ QString Entry::resolvePlaceholderRecursive (const QString& placeholder, int maxDepth) const
727
750
{
728
751
const PlaceholderType typeOfPlaceholder = placeholderType (placeholder);
729
752
switch (typeOfPlaceholder) {
730
753
case PlaceholderType::NotPlaceholder:
731
- return placeholder;
732
754
case PlaceholderType::Unknown:
733
- qWarning (" Can't resolve placeholder %s for entry with uuid %s" , qPrintable (placeholder),
734
- qPrintable (uuid ().toHex ()));
735
755
return placeholder;
736
756
case PlaceholderType::Title:
737
757
return title ();
@@ -762,43 +782,62 @@ QString Entry::resolvePlaceholderRecursive(const QString &placeholder, int maxDe
762
782
const QString key = placeholder.mid (3 , placeholder.length () - 4 ); // {S:attr} => mid(3, len - 4)
763
783
return attributes ()->hasKey (key) ? attributes ()->value (key) : QString ();
764
784
}
765
- case PlaceholderType::Reference: {
766
- // resolving references in format: {REF:<WantedField>@I:<uuid of referenced entry>}
767
- // using format from http://keepass.info/help/base/fieldrefs.html at the time of writing,
768
- // but supporting lookups of standard fields and references by UUID only
769
-
770
- QString result;
771
- QRegExp* referenceRegExp = m_attributes->referenceRegExp ();
772
- if (referenceRegExp->indexIn (placeholder) != -1 ) {
773
- constexpr int wantedFieldIndex = 1 ;
774
- constexpr int referencedUuidIndex = 2 ;
775
- const Uuid referencedUuid (QByteArray::fromHex (referenceRegExp->cap (referencedUuidIndex).toLatin1 ()));
776
- const Entry* refEntry = m_group->database ()->resolveEntry (referencedUuid);
777
- if (refEntry) {
778
- const QString wantedField = referenceRegExp->cap (wantedFieldIndex).toLower ();
779
- if (wantedField == " t" ) {
780
- result = refEntry->title ();
781
- } else if (wantedField == " u" ) {
782
- result = refEntry->username ();
783
- } else if (wantedField == " p" ) {
784
- result = refEntry->password ();
785
- } else if (wantedField == " a" ) {
786
- result = refEntry->url ();
787
- } else if (wantedField == " n" ) {
788
- result = refEntry->notes ();
789
- }
785
+ case PlaceholderType::Reference:
786
+ return resolveReferencePlaceholderRecursive (placeholder, maxDepth);
787
+ }
790
788
791
- // Referencing fields of other entries only works with standard fields, not with custom user strings.
792
- // If you want to reference a custom user string, you need to place a redirection in a standard field
793
- // of the entry with the custom string, using {S:<Name>}, and reference the standard field.
794
- result = refEntry->resolveMultiplePlaceholdersRecursive (result, maxDepth - 1 );
795
- }
796
- }
797
- return result;
789
+ return placeholder;
790
+ }
791
+
792
+ QString Entry::resolveReferencePlaceholderRecursive (const QString& placeholder, int maxDepth) const
793
+ {
794
+ // resolving references in format: {REF:<WantedField>@<SearchIn>:<SearchText>}
795
+ // using format from http://keepass.info/help/base/fieldrefs.html at the time of writing
796
+
797
+ QRegularExpressionMatch match = EntryAttributes::matchReference (placeholder);
798
+ if (!match.hasMatch ()) {
799
+ return placeholder;
798
800
}
801
+
802
+ QString result;
803
+ const QString searchIn = match.captured (EntryAttributes::SearchInGroupName);
804
+ const QString searchText = match.captured (EntryAttributes::SearchTextGroupName);
805
+
806
+ const EntryReferenceType searchInType = Entry::referenceType (searchIn);
807
+ const Entry* refEntry = m_group->database ()->resolveEntry (searchText, searchInType);
808
+
809
+ if (refEntry) {
810
+ const QString wantedField = match.captured (EntryAttributes::WantedFieldGroupName);
811
+ result = refEntry->referenceFieldValue (Entry::referenceType (wantedField));
812
+
813
+ // Referencing fields of other entries only works with standard fields, not with custom user strings.
814
+ // If you want to reference a custom user string, you need to place a redirection in a standard field
815
+ // of the entry with the custom string, using {S:<Name>}, and reference the standard field.
816
+ result = refEntry->resolveMultiplePlaceholdersRecursive (result, maxDepth - 1 );
799
817
}
800
818
801
- return placeholder;
819
+ return result;
820
+ }
821
+
822
+ QString Entry::referenceFieldValue (EntryReferenceType referenceType) const
823
+ {
824
+ switch (referenceType) {
825
+ case EntryReferenceType::Title:
826
+ return title ();
827
+ case EntryReferenceType::UserName:
828
+ return username ();
829
+ case EntryReferenceType::Password:
830
+ return password ();
831
+ case EntryReferenceType::Url:
832
+ return url ();
833
+ case EntryReferenceType::Notes:
834
+ return notes ();
835
+ case EntryReferenceType::Uuid:
836
+ return uuid ().toHex ();
837
+ default :
838
+ break ;
839
+ }
840
+ return QString ();
802
841
}
803
842
804
843
Group* Entry::group ()
@@ -858,7 +897,7 @@ const Database* Entry::database() const
858
897
}
859
898
}
860
899
861
- QString Entry::maskPasswordPlaceholders (const QString & str) const
900
+ QString Entry::maskPasswordPlaceholders (const QString& str) const
862
901
{
863
902
QString result = str;
864
903
result.replace (QRegExp (" (\\ {PASSWORD\\ })" , Qt::CaseInsensitive, QRegExp::RegExp2), " ******" );
@@ -875,7 +914,7 @@ QString Entry::resolvePlaceholder(const QString& placeholder) const
875
914
return resolvePlaceholderRecursive (placeholder, ResolveMaximumDepth);
876
915
}
877
916
878
- QString Entry::resolveUrlPlaceholder (const QString & str, Entry::PlaceholderType placeholderType) const
917
+ QString Entry::resolveUrlPlaceholder (const QString& str, Entry::PlaceholderType placeholderType) const
879
918
{
880
919
if (str.isEmpty ())
881
920
return QString ();
@@ -911,7 +950,7 @@ QString Entry::resolveUrlPlaceholder(const QString &str, Entry::PlaceholderType
911
950
return QString ();
912
951
}
913
952
914
- Entry::PlaceholderType Entry::placeholderType (const QString & placeholder) const
953
+ Entry::PlaceholderType Entry::placeholderType (const QString& placeholder) const
915
954
{
916
955
if (!placeholder.startsWith (QLatin1Char (' {' )) || !placeholder.endsWith (QLatin1Char (' }' ))) {
917
956
return PlaceholderType::NotPlaceholder;
0 commit comments