7#include "searchfullhashjob.h"
9#include <PimCommon/NetworkManager>
10#include <QJsonDocument>
11#include <QNetworkAccessManager>
13#include <webengineviewer_debug.h>
15using namespace WebEngineViewer;
17WEBENGINEVIEWER_EXPORT
bool webengineview_useCompactJson_SearchFullHashJob =
true;
19class WebEngineViewer::SearchFullHashJobPrivate
22 SearchFullHashJobPrivate() =
default;
24 [[nodiscard]]
bool foundExactHash(
const QList<QByteArray> &listLongHash);
25 QHash<QByteArray, QByteArray> mHashs;
27 QStringList mDatabaseHashes;
28 QNetworkAccessManager *mNetworkAccessManager =
nullptr;
31SearchFullHashJob::SearchFullHashJob(
QObject *parent)
33 , d(new SearchFullHashJobPrivate)
37 d->mNetworkAccessManager->setStrictTransportSecurityEnabled(
true);
38 d->mNetworkAccessManager->enableStrictTransportSecurityStore(
true);
41 connect(d->mNetworkAccessManager, &QNetworkAccessManager::sslErrors,
this, &SearchFullHashJob::slotSslErrors);
44SearchFullHashJob::~SearchFullHashJob() =
default;
48 qCDebug(WEBENGINEVIEWER_LOG) <<
" void SearchFullHashJob::slotSslErrors(QNetworkReply *reply, const QList<QSslError> &error)" <<
error.count();
52void SearchFullHashJob::parse(
const QByteArray &replyStr)
89 Q_EMIT result(WebEngineViewer::CheckPhishingUrlUtil::Unknown, d->mUrl);
92 if (answer.isEmpty()) {
93 Q_EMIT result(WebEngineViewer::CheckPhishingUrlUtil::Ok, d->mUrl);
96 const QVariantList info = answer.value(QStringLiteral(
"matches")).toList();
101 const auto numberOfInfo{info.count()};
102 if (numberOfInfo == 1) {
103 const QVariantMap
map = info.at(0).toMap();
104 const QString threatTypeStr =
map[QStringLiteral(
"threatType")].toString();
108 if (threatTypeStr == QLatin1StringView(
"MALWARE")) {
109 const QVariantMap urlMap =
map[QStringLiteral(
"threat")].toMap();
110 QList<QByteArray> hashList;
111 QMap<QString, QVariant>::const_iterator urlMapIt = urlMap.cbegin();
112 const QMap<QString, QVariant>::const_iterator urlMapItEnd = urlMap.cend();
113 hashList.
reserve(urlMap.count());
114 for (; urlMapIt != urlMapItEnd; ++urlMapIt) {
115 const QByteArray hashStr = urlMapIt.value().toByteArray();
119 if (d->foundExactHash(hashList)) {
120 Q_EMIT result(WebEngineViewer::CheckPhishingUrlUtil::MalWare, d->mUrl);
122 Q_EMIT result(WebEngineViewer::CheckPhishingUrlUtil::Unknown, d->mUrl);
124 const QVariantMap threatEntryMetadataMap =
map[QStringLiteral(
"threatEntryMetadata")].toMap();
125 if (!threatEntryMetadataMap.isEmpty()) {
129 qCWarning(WEBENGINEVIEWER_LOG) <<
" SearchFullHashJob::parse threatTypeStr : " << threatTypeStr;
131 }
else if (numberOfInfo == 0) {
132 Q_EMIT result(WebEngineViewer::CheckPhishingUrlUtil::Ok, d->mUrl);
134 qCWarning(WEBENGINEVIEWER_LOG) <<
" SearchFullHashJob::parse matches multi element : " << info.count();
135 Q_EMIT result(WebEngineViewer::CheckPhishingUrlUtil::Unknown, d->mUrl);
142bool SearchFullHashJobPrivate::foundExactHash(
const QList<QByteArray> &listLongHash)
144 const QList<QByteArray> lstLongHash = mHashs.keys();
145 for (
const QByteArray &ba : lstLongHash) {
153void SearchFullHashJob::slotCheckUrlFinished(QNetworkReply *reply)
159void SearchFullHashJob::setSearchHashs(
const QHash<QByteArray, QByteArray> &hash)
164QByteArray SearchFullHashJob::jsonRequest()
const
188 QVariantMap clientMap;
191 clientMap.insert(QStringLiteral(
"clientId"), QStringLiteral(
"KDE"));
192 clientMap.insert(QStringLiteral(
"clientVersion"), CheckPhishingUrlUtil::versionApps());
193 map.insert(QStringLiteral(
"client"), clientMap);
196 QVariantList clientStatesList;
197 for (
const QString &str : std::as_const(d->mDatabaseHashes)) {
198 if (!str.isEmpty()) {
199 clientStatesList.append(str);
202 map.insert(QStringLiteral(
"clientStates"), clientStatesList);
204 QVariantMap threatMap;
205 QVariantList platformList;
206 platformList.append(QLatin1StringView(
"WINDOWS"));
207 threatMap.insert(QStringLiteral(
"platformTypes"), platformList);
209 const QVariantList threatTypesList = {QStringLiteral(
"MALWARE")};
210 threatMap.insert(QStringLiteral(
"threatTypes"), threatTypesList);
211 const QVariantList threatEntryTypesList = {QStringLiteral(
"URL")};
212 threatMap.insert(QStringLiteral(
"threatEntryTypes"), threatEntryTypesList);
214 QVariantList threatEntriesList;
216 QVariantMap hashUrlMap;
217 QHashIterator<QByteArray, QByteArray> i(d->mHashs);
218 while (i.hasNext()) {
220 hashUrlMap.insert(QStringLiteral(
"hash"), i.value());
222 threatEntriesList.append(hashUrlMap);
224 threatMap.insert(QStringLiteral(
"threatEntries"), threatEntriesList);
226 map.insert(QStringLiteral(
"threatInfo"), threatMap);
233void SearchFullHashJob::start()
235 if (!PimCommon::NetworkManager::self()->isOnline()) {
236 Q_EMIT result(WebEngineViewer::CheckPhishingUrlUtil::BrokenNetwork, d->mUrl);
238 }
else if (canStart()) {
240 query.addQueryItem(QStringLiteral(
"key"), WebEngineViewer::CheckPhishingUrlUtil::apiKey());
241 QUrl safeUrl = QUrl(QStringLiteral(
"https://safebrowsing.googleapis.com/v4/fullHashes:find"));
243 QNetworkRequest request(safeUrl);
246 const QByteArray baPostData = jsonRequest();
248 Q_EMIT debugJson(baPostData);
249 QNetworkReply *reply = d->mNetworkAccessManager->post(request, baPostData);
252 Q_EMIT result(WebEngineViewer::CheckPhishingUrlUtil::InvalidUrl, d->mUrl);
260 qCWarning(WEBENGINEVIEWER_LOG) <<
" error " <<
error <<
" error string : " << reply->
errorString();
265bool SearchFullHashJob::canStart()
const
267 return !d->mHashs.isEmpty() && !d->mDatabaseHashes.isEmpty() && !d->mUrl.isEmpty();
270void SearchFullHashJob::setDatabaseState(
const QStringList &hash)
272 d->mDatabaseHashes = hash;
275void SearchFullHashJob::setSearchFullHashForUrl(
const QUrl &url)
280#include "moc_searchfullhashjob.cpp"
KSERVICE_EXPORT KService::List query(FilterFunc filterFunc)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
QString errorString() const const
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
QJsonDocument fromVariant(const QVariant &variant)
bool isNull() const const
QByteArray toJson(JsonFormat format) const const
QVariant toVariant() const const
bool contains(const AT &value) const const
void reserve(qsizetype size)
void finished(QNetworkReply *reply)
void errorOccurred(QNetworkReply::NetworkError code)
virtual void ignoreSslErrors()
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
T qobject_cast(QObject *object)
QObject * sender() const const
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void setQuery(const QString &query, ParsingMode mode)
QMap< QString, QVariant > toMap() const const