File indexing completed on 2025-01-26 04:57:22

0001 /*
0002    SPDX-FileCopyrightText: 2016-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "hashcachemanager.h"
0008 #include "checkphishingurlutil.h"
0009 #include "webengineviewer_debug.h"
0010 #include <KConfig>
0011 #include <KConfigGroup>
0012 
0013 using namespace WebEngineViewer;
0014 
0015 struct HashCacheInfo {
0016     HashCacheInfo() = default;
0017 
0018     [[nodiscard]] bool isValid() const;
0019     HashCacheManager::UrlStatus status = HashCacheManager::Unknown;
0020     uint verifyCacheAfterThisTime = 0;
0021 };
0022 
0023 bool HashCacheInfo::isValid() const
0024 {
0025     return status != HashCacheManager::Unknown;
0026 }
0027 
0028 class WebEngineViewer::HashCacheManagerPrivate
0029 {
0030 public:
0031     HashCacheManagerPrivate()
0032     {
0033         load();
0034     }
0035 
0036     void clearCache();
0037     void save();
0038     void load();
0039     void addHashStatus(const QByteArray &hash, HashCacheManager::UrlStatus status, uint cacheDuration);
0040     [[nodiscard]] HashCacheManager::UrlStatus hashStatus(const QByteArray &hash);
0041 
0042 private:
0043     void clear();
0044 
0045     QMap<QByteArray, HashCacheInfo> mHashList;
0046 };
0047 
0048 void HashCacheManagerPrivate::clear()
0049 {
0050     mHashList.clear();
0051 }
0052 
0053 void HashCacheManagerPrivate::clearCache()
0054 {
0055     clear();
0056     save();
0057 }
0058 
0059 void HashCacheManagerPrivate::save()
0060 {
0061     KConfig phishingurlKConfig(WebEngineViewer::CheckPhishingUrlUtil::configFileName());
0062     KConfigGroup grp = phishingurlKConfig.group(QStringLiteral("Hash"));
0063 
0064     QList<QByteArray> lstMalware;
0065     QList<double> lstMalwareDuration;
0066 
0067     QList<QByteArray> lstOk;
0068     QList<double> lstOkDuration;
0069 
0070     QMapIterator<QByteArray, HashCacheInfo> i(mHashList);
0071     while (i.hasNext()) {
0072         i.next();
0073         switch (i.value().status) {
0074         case HashCacheManager::UrlOk:
0075             lstOk << i.key();
0076             lstOkDuration << i.value().verifyCacheAfterThisTime;
0077             break;
0078         case HashCacheManager::MalWare:
0079             lstMalware << i.key();
0080             lstMalwareDuration << i.value().verifyCacheAfterThisTime;
0081             break;
0082         case HashCacheManager::Unknown:
0083             break;
0084         }
0085     }
0086     grp.writeEntry("malware", lstMalware);
0087     grp.writeEntry("malwareCacheDuration", lstMalwareDuration);
0088 
0089     grp.writeEntry("safe", lstOk);
0090     grp.writeEntry("safeCacheDuration", lstOkDuration);
0091     grp.sync();
0092 }
0093 
0094 void HashCacheManagerPrivate::load()
0095 {
0096     clear();
0097     KConfig phishingurlKConfig(WebEngineViewer::CheckPhishingUrlUtil::configFileName());
0098     KConfigGroup grp = phishingurlKConfig.group(QStringLiteral("Hash"));
0099     QList<QByteArray> lstMalware = grp.readEntry("malware", QList<QByteArray>());
0100     QList<double> lstMalwareDuration = grp.readEntry("malwareCacheDuration", QList<double>());
0101 
0102     QList<QByteArray> lstOk = grp.readEntry("safe", QList<QByteArray>());
0103     QList<double> lstOkDuration = grp.readEntry("safeCacheDuration", QList<double>());
0104     if (lstMalware.count() != lstMalwareDuration.count()) {
0105         qCWarning(WEBENGINEVIEWER_LOG) << "unsafe url: HashCacheManagerPrivate invalid number of data stored";
0106         return;
0107     }
0108     if (lstOk.count() != lstOkDuration.count()) {
0109         qCWarning(WEBENGINEVIEWER_LOG) << "safe url: HashCacheManagerPrivate invalid number of data stored";
0110         return;
0111     }
0112 
0113     const int nb(lstOk.count());
0114     for (int i = 0; i < nb; ++i) {
0115         HashCacheInfo info;
0116         info.status = HashCacheManager::UrlOk;
0117         info.verifyCacheAfterThisTime = lstOkDuration.at(i);
0118         if (info.isValid()) {
0119             mHashList.insert(lstOk.at(i), info);
0120         }
0121     }
0122 
0123     const int nb2(lstMalware.count());
0124     for (int i = 0; i < nb2; ++i) {
0125         HashCacheInfo info;
0126         info.status = HashCacheManager::MalWare;
0127         info.verifyCacheAfterThisTime = lstMalwareDuration.at(i);
0128         if (info.isValid()) {
0129             mHashList.insert(lstMalware.at(i), info);
0130         }
0131     }
0132 }
0133 
0134 HashCacheManager::UrlStatus HashCacheManagerPrivate::hashStatus(const QByteArray &hash)
0135 {
0136     const HashCacheInfo info = mHashList.value(hash, HashCacheInfo());
0137     if (info.isValid()) {
0138         if (CheckPhishingUrlUtil::cachedValueStillValid(info.verifyCacheAfterThisTime)) {
0139             return info.status;
0140         } else {
0141             return HashCacheManager::Unknown;
0142         }
0143     } else {
0144         return HashCacheManager::Unknown;
0145     }
0146 }
0147 
0148 void HashCacheManagerPrivate::addHashStatus(const QByteArray &hash, HashCacheManager::UrlStatus status, uint cacheDuration)
0149 {
0150     HashCacheInfo info;
0151     info.status = status;
0152     info.verifyCacheAfterThisTime = cacheDuration;
0153     switch (status) {
0154     case HashCacheManager::UrlOk:
0155         mHashList.insert(hash, info);
0156         break;
0157     case HashCacheManager::MalWare:
0158         mHashList.insert(hash, info);
0159         break;
0160     case HashCacheManager::Unknown:
0161         qCWarning(WEBENGINEVIEWER_LOG()) << "HashCacheManagerPrivate::addHashStatus unknown status detected!";
0162         return;
0163     }
0164     save();
0165 }
0166 
0167 HashCacheManager *HashCacheManager::self()
0168 {
0169     static HashCacheManager s_self;
0170     return &s_self;
0171 }
0172 
0173 HashCacheManager::HashCacheManager(QObject *parent)
0174     : QObject(parent)
0175     , d(new HashCacheManagerPrivate)
0176 {
0177 }
0178 
0179 HashCacheManager::~HashCacheManager() = default;
0180 
0181 void HashCacheManager::clearCache()
0182 {
0183     d->clearCache();
0184 }
0185 
0186 void HashCacheManager::addHashStatus(const QByteArray &hash, HashCacheManager::UrlStatus status, uint cacheDuration)
0187 {
0188     d->addHashStatus(hash, status, cacheDuration);
0189 }
0190 
0191 HashCacheManager::UrlStatus HashCacheManager::hashStatus(const QByteArray &hash)
0192 {
0193     return d->hashStatus(hash);
0194 }
0195 
0196 #include "moc_hashcachemanager.cpp"