1 /*
2  *  Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
3  *
4  *  This program is free software: you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation, either version 2 or (at your option)
7  *  version 3 of the License.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "Metadata.h"
19 
20 #include "core/Entry.h"
21 #include "core/Group.h"
22 #include "core/Tools.h"
23 
24 const int Metadata::DefaultHistoryMaxItems = 10;
25 const int Metadata::DefaultHistoryMaxSize = 6 * 1024 * 1024;
26 
Metadata(QObject * parent)27 Metadata::Metadata(QObject* parent)
28     : QObject(parent)
29     , m_updateDatetime(true)
30 {
31     m_data.generator = "KeePassX";
32     m_data.maintenanceHistoryDays = 365;
33     m_data.masterKeyChangeRec = -1;
34     m_data.masterKeyChangeForce = -1;
35     m_data.historyMaxItems = DefaultHistoryMaxItems;
36     m_data.historyMaxSize = DefaultHistoryMaxSize;
37     m_data.recycleBinEnabled = true;
38     m_data.protectTitle = false;
39     m_data.protectUsername = false;
40     m_data.protectPassword = true;
41     m_data.protectUrl = false;
42     m_data.protectNotes = false;
43     // m_data.autoEnableVisualHiding = false;
44 
45     QDateTime now = QDateTime::currentDateTimeUtc();
46     m_data.nameChanged = now;
47     m_data.descriptionChanged = now;
48     m_data.defaultUserNameChanged = now;
49     m_recycleBinChanged = now;
50     m_entryTemplatesGroupChanged = now;
51     m_masterKeyChanged = now;
52 }
53 
set(P & property,const V & value)54 template <class P, class V> bool Metadata::set(P& property, const V& value)
55 {
56     if (property != value) {
57         property = value;
58         Q_EMIT modified();
59         return true;
60     }
61     else {
62         return false;
63     }
64 }
65 
set(P & property,const V & value,QDateTime & dateTime)66 template <class P, class V> bool Metadata::set(P& property, const V& value, QDateTime& dateTime) {
67     if (property != value) {
68         property = value;
69         if (m_updateDatetime) {
70             dateTime = QDateTime::currentDateTimeUtc();
71         }
72         Q_EMIT modified();
73         return true;
74     }
75     else {
76         return false;
77     }
78 }
79 
setUpdateDatetime(bool value)80 void Metadata::setUpdateDatetime(bool value)
81 {
82     m_updateDatetime = value;
83 }
84 
copyAttributesFrom(const Metadata * other)85 void Metadata::copyAttributesFrom(const Metadata* other)
86 {
87     m_data = other->m_data;
88 }
89 
generator() const90 QString Metadata::generator() const
91 {
92     return m_data.generator;
93 }
94 
name() const95 QString Metadata::name() const
96 {
97     return m_data.name;
98 }
99 
nameChanged() const100 QDateTime Metadata::nameChanged() const
101 {
102     return m_data.nameChanged;
103 }
104 
description() const105 QString Metadata::description() const
106 {
107     return m_data.description;
108 }
109 
descriptionChanged() const110 QDateTime Metadata::descriptionChanged() const
111 {
112     return m_data.descriptionChanged;
113 }
114 
defaultUserName() const115 QString Metadata::defaultUserName() const
116 {
117     return m_data.defaultUserName;
118 }
119 
defaultUserNameChanged() const120 QDateTime Metadata::defaultUserNameChanged() const
121 {
122     return m_data.defaultUserNameChanged;
123 }
124 
maintenanceHistoryDays() const125 int Metadata::maintenanceHistoryDays() const
126 {
127     return m_data.maintenanceHistoryDays;
128 }
129 
color() const130 QColor Metadata::color() const
131 {
132     return m_data.color;
133 }
134 
protectTitle() const135 bool Metadata::protectTitle() const
136 {
137     return m_data.protectTitle;
138 }
139 
protectUsername() const140 bool Metadata::protectUsername() const
141 {
142     return m_data.protectUsername;
143 }
144 
protectPassword() const145 bool Metadata::protectPassword() const
146 {
147     return m_data.protectPassword;
148 }
149 
protectUrl() const150 bool Metadata::protectUrl() const
151 {
152     return m_data.protectUrl;
153 }
154 
protectNotes() const155 bool Metadata::protectNotes() const
156 {
157     return m_data.protectNotes;
158 }
159 
160 /*bool Metadata::autoEnableVisualHiding() const
161 {
162     return m_autoEnableVisualHiding;
163 }*/
164 
customIcon(const Uuid & uuid) const165 QImage Metadata::customIcon(const Uuid& uuid) const
166 {
167     return m_customIcons.value(uuid);
168 }
169 
customIconPixmap(const Uuid & uuid) const170 QPixmap Metadata::customIconPixmap(const Uuid& uuid) const
171 {
172     QPixmap pixmap;
173 
174     if (!m_customIcons.contains(uuid)) {
175         return pixmap;
176     }
177 
178     QPixmapCache::Key& cacheKey = m_customIconCacheKeys[uuid];
179 
180     if (!QPixmapCache::find(cacheKey, &pixmap)) {
181         pixmap = QPixmap::fromImage(m_customIcons.value(uuid));
182         cacheKey = QPixmapCache::insert(pixmap);
183     }
184 
185     return pixmap;
186 }
187 
customIconScaledPixmap(const Uuid & uuid) const188 QPixmap Metadata::customIconScaledPixmap(const Uuid& uuid) const
189 {
190     QPixmap pixmap;
191 
192     if (!m_customIcons.contains(uuid)) {
193         return pixmap;
194     }
195 
196     QPixmapCache::Key& cacheKey = m_customIconScaledCacheKeys[uuid];
197 
198     if (!QPixmapCache::find(cacheKey, &pixmap)) {
199         QImage image = m_customIcons.value(uuid).scaled(16, 16, Qt::KeepAspectRatio, Qt::SmoothTransformation);
200         pixmap = QPixmap::fromImage(image);
201         cacheKey = QPixmapCache::insert(pixmap);
202     }
203 
204     return pixmap;
205 }
206 
containsCustomIcon(const Uuid & uuid) const207 bool Metadata::containsCustomIcon(const Uuid& uuid) const
208 {
209     return m_customIcons.contains(uuid);
210 }
211 
customIcons() const212 QHash<Uuid, QImage> Metadata::customIcons() const
213 {
214     return m_customIcons;
215 }
216 
customIconsScaledPixmaps() const217 QHash<Uuid, QPixmap> Metadata::customIconsScaledPixmaps() const
218 {
219     QHash<Uuid, QPixmap> result;
220 
221     for (const Uuid& uuid : m_customIconsOrder) {
222         result.insert(uuid, customIconScaledPixmap(uuid));
223     }
224 
225     return result;
226 }
227 
customIconsOrder() const228 QList<Uuid> Metadata::customIconsOrder() const
229 {
230     return m_customIconsOrder;
231 }
232 
recycleBinEnabled() const233 bool Metadata::recycleBinEnabled() const
234 {
235     return m_data.recycleBinEnabled;
236 }
237 
recycleBin()238 Group* Metadata::recycleBin()
239 {
240     return m_recycleBin;
241 }
242 
recycleBin() const243 const Group* Metadata::recycleBin() const
244 {
245     return m_recycleBin;
246 }
247 
recycleBinChanged() const248 QDateTime Metadata::recycleBinChanged() const
249 {
250     return m_recycleBinChanged;
251 }
252 
entryTemplatesGroup() const253 const Group* Metadata::entryTemplatesGroup() const
254 {
255     return m_entryTemplatesGroup;
256 }
257 
entryTemplatesGroupChanged() const258 QDateTime Metadata::entryTemplatesGroupChanged() const
259 {
260     return m_entryTemplatesGroupChanged;
261 }
262 
lastSelectedGroup() const263 const Group* Metadata::lastSelectedGroup() const
264 {
265     return m_lastSelectedGroup;
266 }
267 
lastTopVisibleGroup() const268 const Group* Metadata::lastTopVisibleGroup() const
269 {
270     return m_lastTopVisibleGroup;
271 }
272 
masterKeyChanged() const273 QDateTime Metadata::masterKeyChanged() const
274 {
275     return m_masterKeyChanged;
276 }
277 
masterKeyChangeRec() const278 int Metadata::masterKeyChangeRec() const
279 {
280     return m_data.masterKeyChangeRec;
281 }
282 
masterKeyChangeForce() const283 int Metadata::masterKeyChangeForce() const
284 {
285     return m_data.masterKeyChangeForce;
286 }
287 
historyMaxItems() const288 int Metadata::historyMaxItems() const
289 {
290     return m_data.historyMaxItems;
291 }
292 
historyMaxSize() const293 int Metadata::historyMaxSize() const
294 {
295     return m_data.historyMaxSize;
296 }
297 
customFields() const298 QHash<QString, QString> Metadata::customFields() const
299 {
300     return m_customFields;
301 }
302 
setGenerator(const QString & value)303 void Metadata::setGenerator(const QString& value)
304 {
305     set(m_data.generator, value);
306 }
307 
setName(const QString & value)308 void Metadata::setName(const QString& value)
309 {
310     if (set(m_data.name, value, m_data.nameChanged)) {
311         Q_EMIT nameTextChanged();
312     }
313 }
314 
setNameChanged(const QDateTime & value)315 void Metadata::setNameChanged(const QDateTime& value)
316 {
317     Q_ASSERT(value.timeSpec() == Qt::UTC);
318     m_data.nameChanged = value;
319 }
320 
setDescription(const QString & value)321 void Metadata::setDescription(const QString& value)
322 {
323     set(m_data.description, value, m_data.descriptionChanged);
324 }
325 
setDescriptionChanged(const QDateTime & value)326 void Metadata::setDescriptionChanged(const QDateTime& value)
327 {
328     Q_ASSERT(value.timeSpec() == Qt::UTC);
329     m_data.descriptionChanged = value;
330 }
331 
setDefaultUserName(const QString & value)332 void Metadata::setDefaultUserName(const QString& value)
333 {
334     set(m_data.defaultUserName, value, m_data.defaultUserNameChanged);
335 }
336 
setDefaultUserNameChanged(const QDateTime & value)337 void Metadata::setDefaultUserNameChanged(const QDateTime& value)
338 {
339     Q_ASSERT(value.timeSpec() == Qt::UTC);
340     m_data.defaultUserNameChanged = value;
341 }
342 
setMaintenanceHistoryDays(int value)343 void Metadata::setMaintenanceHistoryDays(int value)
344 {
345     set(m_data.maintenanceHistoryDays, value);
346 }
347 
setColor(const QColor & value)348 void Metadata::setColor(const QColor& value)
349 {
350     set(m_data.color, value);
351 }
352 
setProtectTitle(bool value)353 void Metadata::setProtectTitle(bool value)
354 {
355     set(m_data.protectTitle, value);
356 }
357 
setProtectUsername(bool value)358 void Metadata::setProtectUsername(bool value)
359 {
360     set(m_data.protectUsername, value);
361 }
362 
setProtectPassword(bool value)363 void Metadata::setProtectPassword(bool value)
364 {
365     set(m_data.protectPassword, value);
366 }
367 
setProtectUrl(bool value)368 void Metadata::setProtectUrl(bool value)
369 {
370     set(m_data.protectUrl, value);
371 }
372 
setProtectNotes(bool value)373 void Metadata::setProtectNotes(bool value)
374 {
375     set(m_data.protectNotes, value);
376 }
377 
378 /*void Metadata::setAutoEnableVisualHiding(bool value)
379 {
380     set(m_autoEnableVisualHiding, value);
381 }*/
382 
addCustomIcon(const Uuid & uuid,const QImage & icon)383 void Metadata::addCustomIcon(const Uuid& uuid, const QImage& icon)
384 {
385     Q_ASSERT(!uuid.isNull());
386     Q_ASSERT(!m_customIcons.contains(uuid));
387 
388     m_customIcons.insert(uuid, icon);
389     // reset cache in case there is also an icon with that uuid
390     m_customIconCacheKeys[uuid] = QPixmapCache::Key();
391     m_customIconScaledCacheKeys[uuid] = QPixmapCache::Key();
392     m_customIconsOrder.append(uuid);
393     Q_ASSERT(m_customIcons.count() == m_customIconsOrder.count());
394     Q_EMIT modified();
395 }
396 
addCustomIconScaled(const Uuid & uuid,const QImage & icon)397 void Metadata::addCustomIconScaled(const Uuid& uuid, const QImage& icon)
398 {
399     QImage iconScaled;
400 
401     // scale down to 128x128 if icon is larger
402     if (icon.width() > 128 || icon.height() > 128) {
403         iconScaled = icon.scaled(QSize(128, 128), Qt::KeepAspectRatio,
404                                  Qt::SmoothTransformation);
405     }
406     else {
407         iconScaled = icon;
408     }
409 
410     addCustomIcon(uuid, iconScaled);
411 }
412 
removeCustomIcon(const Uuid & uuid)413 void Metadata::removeCustomIcon(const Uuid& uuid)
414 {
415     Q_ASSERT(!uuid.isNull());
416     Q_ASSERT(m_customIcons.contains(uuid));
417 
418     m_customIcons.remove(uuid);
419     QPixmapCache::remove(m_customIconCacheKeys.value(uuid));
420     m_customIconCacheKeys.remove(uuid);
421     QPixmapCache::remove(m_customIconScaledCacheKeys.value(uuid));
422     m_customIconScaledCacheKeys.remove(uuid);
423     m_customIconsOrder.removeAll(uuid);
424     Q_ASSERT(m_customIcons.count() == m_customIconsOrder.count());
425     Q_EMIT modified();
426 }
427 
copyCustomIcons(const QSet<Uuid> & iconList,const Metadata * otherMetadata)428 void Metadata::copyCustomIcons(const QSet<Uuid>& iconList, const Metadata* otherMetadata)
429 {
430     for (const Uuid& uuid : iconList) {
431         Q_ASSERT(otherMetadata->containsCustomIcon(uuid));
432 
433         if (!containsCustomIcon(uuid) && otherMetadata->containsCustomIcon(uuid)) {
434             addCustomIcon(uuid, otherMetadata->customIcon(uuid));
435         }
436     }
437 }
438 
setRecycleBinEnabled(bool value)439 void Metadata::setRecycleBinEnabled(bool value)
440 {
441     set(m_data.recycleBinEnabled, value);
442 }
443 
setRecycleBin(Group * group)444 void Metadata::setRecycleBin(Group* group)
445 {
446     set(m_recycleBin, group, m_recycleBinChanged);
447 }
448 
setRecycleBinChanged(const QDateTime & value)449 void Metadata::setRecycleBinChanged(const QDateTime& value)
450 {
451     Q_ASSERT(value.timeSpec() == Qt::UTC);
452     m_recycleBinChanged = value;
453 }
454 
setEntryTemplatesGroup(Group * group)455 void Metadata::setEntryTemplatesGroup(Group* group)
456 {
457     set(m_entryTemplatesGroup, group, m_entryTemplatesGroupChanged);
458 }
459 
setEntryTemplatesGroupChanged(const QDateTime & value)460 void Metadata::setEntryTemplatesGroupChanged(const QDateTime& value)
461 {
462     Q_ASSERT(value.timeSpec() == Qt::UTC);
463     m_entryTemplatesGroupChanged = value;
464 }
465 
setLastSelectedGroup(Group * group)466 void Metadata::setLastSelectedGroup(Group* group)
467 {
468     set(m_lastSelectedGroup, group);
469 }
470 
setLastTopVisibleGroup(Group * group)471 void Metadata::setLastTopVisibleGroup(Group* group)
472 {
473     set(m_lastTopVisibleGroup, group);
474 }
475 
setMasterKeyChanged(const QDateTime & value)476 void Metadata::setMasterKeyChanged(const QDateTime& value)
477 {
478     Q_ASSERT(value.timeSpec() == Qt::UTC);
479     m_masterKeyChanged = value;
480 }
481 
setMasterKeyChangeRec(int value)482 void Metadata::setMasterKeyChangeRec(int value)
483 {
484     set(m_data.masterKeyChangeRec, value);
485 }
486 
setMasterKeyChangeForce(int value)487 void Metadata::setMasterKeyChangeForce(int value)
488 {
489     set(m_data.masterKeyChangeForce, value);
490 }
491 
setHistoryMaxItems(int value)492 void Metadata::setHistoryMaxItems(int value)
493 {
494     set(m_data.historyMaxItems, value);
495 }
496 
setHistoryMaxSize(int value)497 void Metadata::setHistoryMaxSize(int value)
498 {
499     set(m_data.historyMaxSize, value);
500 }
501 
addCustomField(const QString & key,const QString & value)502 void Metadata::addCustomField(const QString& key, const QString& value)
503 {
504     Q_ASSERT(!m_customFields.contains(key));
505 
506     m_customFields.insert(key, value);
507     Q_EMIT modified();
508 }
509 
removeCustomField(const QString & key)510 void Metadata::removeCustomField(const QString& key)
511 {
512     Q_ASSERT(m_customFields.contains(key));
513 
514     m_customFields.remove(key);
515     Q_EMIT modified();
516 }
517