-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
Copy pathDatabaseStats.cpp
119 lines (101 loc) · 3.32 KB
/
DatabaseStats.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*
* Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
*
* 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 "DatabaseStats.h"
// Ctor does all the work
DatabaseStats::DatabaseStats(QSharedPointer<Database> db)
: modified(QFileInfo(db->filePath()).lastModified())
, m_db(db)
{
gatherStats(db->rootGroup()->groupsRecursive(true));
}
// Get average password length
int DatabaseStats::averagePwdLength() const
{
const auto passwords = uniquePasswords + reusedPasswords;
return passwords == 0 ? 0 : std::round(totalPasswordLength / double(passwords));
}
// Get max number of password reuse (=how many entries
// share the same password)
int DatabaseStats::maxPwdReuse() const
{
int ret = 0;
for (const auto& count : m_passwords) {
ret = std::max(ret, count);
}
return ret;
}
// A warning sign is displayed if one of the
// following returns true.
bool DatabaseStats::isAnyExpired() const
{
return expiredEntries > 0;
}
bool DatabaseStats::areTooManyPwdsReused() const
{
return reusedPasswords > uniquePasswords / 10;
}
bool DatabaseStats::arePwdsReusedTooOften() const
{
return maxPwdReuse() > 3;
}
bool DatabaseStats::isAvgPwdTooShort() const
{
return averagePwdLength() < 10;
}
void DatabaseStats::gatherStats(const QList<Group*>& groups)
{
auto checker = HealthChecker(m_db);
for (const auto* group : groups) {
// Don't count anything in the recycle bin
if (group->isRecycled()) {
continue;
}
++groupCount;
for (const auto* entry : group->entries()) {
// Don't count anything in the recycle bin
if (entry->isRecycled()) {
continue;
}
++entryCount;
if (entry->isExpired()) {
++expiredEntries;
}
// Get password statistics
const auto pwd = entry->password();
if (!pwd.isEmpty()) {
if (!m_passwords.contains(pwd)) {
++uniquePasswords;
} else {
++reusedPasswords;
}
if (pwd.size() < PasswordHealth::Length::Short) {
++shortPasswords;
}
// Speed up Zxcvbn process by excluding very long passwords and most passphrases
if (pwd.size() < PasswordHealth::Length::Long
&& checker.evaluate(entry)->quality() <= PasswordHealth::Quality::Weak) {
++weakPasswords;
}
if (entry->excludeFromReports()) {
++excludedEntries;
}
totalPasswordLength += pwd.size();
m_passwords[pwd]++;
}
}
}
}