Messagelib

localdatabasefile.cpp
1/*
2 SPDX-FileCopyrightText: 2016-2024 Laurent Montel <montel@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "localdatabasefile.h"
8#include "checkphishingurlutil.h"
9#include "updatedatabaseinfo.h"
10#include "webengineviewer_debug.h"
11#include <QDateTime>
12#include <QElapsedTimer>
13#include <QFileInfo>
14
15using namespace WebEngineViewer;
16
17WEBENGINEVIEWER_EXPORT int webengineview_LocalDataBaseFile = 1000 * 60 * 60;
18
19class WebEngineViewer::LocalDataBaseFilePrivate
20{
21public:
22 LocalDataBaseFilePrivate(const QString &filename, LocalDataBaseFile *qq)
23 : mFile(filename)
24 , q(qq)
25 {
26 }
27
28 bool load();
29 bool reload();
30 void close();
31
32 QElapsedTimer mLastCheck;
33 QFile mFile;
34 uchar *mData = nullptr;
35 QDateTime mMtime;
36 LocalDataBaseFile *const q;
37 bool mValid = false;
38};
39
40bool LocalDataBaseFilePrivate::load()
41{
42 if (!mFile.open(QIODevice::ReadOnly)) {
43 return false;
44 }
45 mData = mFile.map(0, mFile.size());
46 if (mData) {
47 const int major = q->getUint16(0);
48 const int minor = q->getUint16(2);
49
50 // Check version in binary file. => version value == 1.0 for the moment see CheckPhishingUrlUtil
51 mValid = (major == WebEngineViewer::CheckPhishingUrlUtil::majorVersion() && minor == WebEngineViewer::CheckPhishingUrlUtil::minorVersion());
52 }
53 mMtime = QFileInfo(mFile).lastModified();
54 return mValid;
55}
56
57void LocalDataBaseFilePrivate::close()
58{
59 mValid = false;
60 if (mFile.isOpen()) {
61 mFile.close();
62 }
63 mData = nullptr;
64}
65
66bool LocalDataBaseFilePrivate::reload()
67{
68 qCDebug(WEBENGINEVIEWER_LOG) << "Reload File" << mFile.fileName();
69 close();
70 return load();
71}
72
73LocalDataBaseFile::LocalDataBaseFile(const QString &filename)
74 : d(new WebEngineViewer::LocalDataBaseFilePrivate(filename, this))
75{
76 d->load();
77}
78
79LocalDataBaseFile::~LocalDataBaseFile() = default;
80
81void LocalDataBaseFile::close()
82{
83 d->close();
84}
85
86bool LocalDataBaseFile::isValid() const
87{
88 return d->mValid;
89}
90
91quint16 LocalDataBaseFile::getUint16(int offset) const
92{
93 return *reinterpret_cast<quint16 *>(d->mData + offset);
94}
95
96quint32 LocalDataBaseFile::getUint32(int offset) const
97{
98 return *reinterpret_cast<quint32 *>(d->mData + offset);
99}
100
101quint64 LocalDataBaseFile::getUint64(int offset) const
102{
103 return *reinterpret_cast<quint64 *>(d->mData + offset);
104}
105
106const char *LocalDataBaseFile::getCharStar(int offset) const
107{
108 return reinterpret_cast<const char *>(d->mData + offset);
109}
110
111bool LocalDataBaseFile::reload()
112{
113 return d->reload();
114}
115
116QByteArray LocalDataBaseFile::searchHash(const QByteArray &hashToSearch)
117{
118 /* database file has:
119 * - one getUint16 => major
120 * - one getUint16 => minor
121 * - one getUint64 => number of item
122 * => 12
123 */
124 const int numHash = getUint64(4);
125 int end = numHash - 1;
126 QByteArray previousValue;
127 if (end > 0) {
128 QByteArray currentValue;
129 int begin = 0;
130 int posListOffset = 12;
131 do {
132 previousValue = currentValue;
133 const int medium = (begin + end) / 2;
134 const int off = posListOffset + 8 * medium;
135 const int hashOffset = getUint64(off);
136 const char *hashCharStar = getCharStar(hashOffset);
137 const int cmp = qstrcmp(hashCharStar, hashToSearch.constData());
138 currentValue = QByteArray(hashCharStar);
139 qCWarning(WEBENGINEVIEWER_LOG) << "search " << hashToSearch.toBase64() << " begin " << begin << " end " << end << " hashCharStar"
140 << currentValue.toBase64();
141 if (end == begin) {
142 return currentValue;
143 }
144 if (cmp < 0) {
145 begin = medium + 1;
146 } else if (cmp > 0) {
147 end = medium - 1;
148 } else {
149 return currentValue;
150 }
151 } while (begin <= end);
152 }
153 return previousValue;
154}
155
156bool LocalDataBaseFile::shouldCheck() const
157{
158 // 1 hours
159 if (d->mLastCheck.isValid() && d->mLastCheck.elapsed() < webengineview_LocalDataBaseFile) {
160 return false;
161 }
162 d->mLastCheck.start();
163 return true;
164}
165
166bool LocalDataBaseFile::checkFileChanged()
167{
168 bool somethingChanged = false;
169 QFileInfo fileInfo(d->mFile);
170 if (!fileInfo.exists() || fileInfo.lastModified() > d->mMtime) {
171 // But the user could use rm -rf :-)
172 reload(); // will mark itself as invalid on failure
173 somethingChanged = true;
174 }
175 if (somethingChanged) {
176 return isValid();
177 }
178 return somethingChanged;
179}
180
181QList<WebEngineViewer::Addition> LocalDataBaseFile::extractAllInfo() const
182{
184 quint64 numberOfElement = getUint64(4);
185 lst.reserve(numberOfElement);
186 int index = 12; // quint16 major + quint16 minor + quint64 number of element
187 for (quint64 i = 0; i < numberOfElement; ++i) {
188 const quint64 value = getUint64(index);
189 Addition tmp;
190 tmp.hashString = QByteArray(getCharStar(value));
191 tmp.prefixSize = tmp.hashString.size();
192 tmp.compressionType = WebEngineViewer::UpdateDataBaseInfo::RawCompression;
193 index += 8; // next index based on quint64
194 lst.append(tmp);
195 }
196 return lst;
197}
198
199bool LocalDataBaseFile::fileExists() const
200{
201 QFileInfo fileInfo(d->mFile);
202 return fileInfo.exists();
203}
const QList< QKeySequence > & begin()
const QList< QKeySequence > & end()
const char * constData() const const
qsizetype size() const const
QByteArray toBase64(Base64Options options) const const
virtual QString fileName() const const override
bool open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
virtual qint64 size() const const override
virtual void close() override
uchar * map(qint64 offset, qint64 size, MemoryMapFlags flags)
QDateTime lastModified() const const
bool isOpen() const const
void append(QList< T > &&value)
void reserve(qsizetype size)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Dec 6 2024 11:58:49 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.