File indexing completed on 2024-05-12 16:23:45
0001 // SPDX-FileCopyrightText: 2020 Jonah BrĂ¼chert <jbb@kaidan.im> 0002 // 0003 // SPDX-License-Identifier: GPL-2.0-or-later 0004 0005 #include "adblockfilterlistsmanager.h" 0006 0007 #include <QDir> 0008 #include <QFile> 0009 #include <QNetworkReply> 0010 #include <QStandardPaths> 0011 0012 #include "angelfishsettings.h" 0013 0014 void copyStream(QIODevice &input, QIODevice &output) 0015 { 0016 constexpr auto BUFFER_SIZE = 1024; 0017 0018 QByteArray buffer; 0019 buffer.reserve(BUFFER_SIZE); 0020 0021 while (true) { 0022 int64_t read = input.read(buffer.data(), BUFFER_SIZE); 0023 0024 if (read > 0) { 0025 output.write(buffer.data(), read); 0026 } else { 0027 break; 0028 } 0029 } 0030 } 0031 0032 const QString filterListIdFromUrl(const QString &url) { 0033 QCryptographicHash fileNameHash(QCryptographicHash::Sha256); 0034 fileNameHash.addData(url.toUtf8()); 0035 return QString::fromUtf8(fileNameHash.result().toHex()); 0036 } 0037 0038 AdblockFilterListsManager::AdblockFilterListsManager(QObject *parent) 0039 : QObject(parent) 0040 , m_filterLists(loadFromConfig()) 0041 { 0042 connect(&m_networkManager, &QNetworkAccessManager::finished, this, &AdblockFilterListsManager::handleListFetched); 0043 m_networkManager.setRedirectPolicy(QNetworkRequest::SameOriginRedirectPolicy); 0044 } 0045 0046 void AdblockFilterListsManager::refreshLists() 0047 { 0048 // Delete old lists, in case the names change. 0049 // Otherwise we might not be overwriting all of them. 0050 const QDir dir(filterListPath()); 0051 const auto entries = dir.entryList(); 0052 for (const auto &entry : entries) { 0053 QFile::remove(dir.path() + QDir::separator() + entry); 0054 } 0055 0056 for (const auto &list : std::as_const(m_filterLists)) { 0057 m_runningRequests++; 0058 m_networkManager.get(QNetworkRequest(list.url)); 0059 } 0060 } 0061 0062 QString AdblockFilterListsManager::filterListPath() 0063 { 0064 static const auto path = []() -> QString { 0065 QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/filterlists/"); 0066 QDir(path).mkpath(QStringLiteral(".")); 0067 return path; 0068 }(); 0069 return path; 0070 } 0071 0072 void AdblockFilterListsManager::handleListFetched(QNetworkReply *reply) 0073 { 0074 Q_ASSERT(reply); 0075 0076 m_runningRequests--; 0077 0078 if (m_runningRequests < 1) { 0079 Q_EMIT refreshFinished(); 0080 } 0081 0082 const auto id = filterListIdFromUrl(reply->url().toString()); 0083 0084 QFile file(filterListPath() + id); 0085 if (!file.open(QIODevice::WriteOnly)) { 0086 qDebug() << "Failed to open" << file.fileName() << "for writing." 0087 << "Filter list not updated"; 0088 return; 0089 } 0090 0091 copyStream(*reply, file); 0092 } 0093 0094 QVector<AdblockFilterListsManager::FilterList> AdblockFilterListsManager::loadFromConfig() 0095 { 0096 const auto &filterNames = AngelfishSettings::adblockFilterNames(); 0097 const auto &filterUrls = AngelfishSettings::adblockFilterUrls(); 0098 0099 auto namesIt = filterNames.begin(); 0100 auto urlsIt = filterUrls.begin(); 0101 0102 QVector<AdblockFilterListsManager::FilterList> out; 0103 0104 // Otherwise list is corrupted, but we will still not crash in release mode 0105 Q_ASSERT(filterNames.size() == filterUrls.size()); 0106 0107 while (namesIt != filterNames.end() && urlsIt != filterUrls.end()) { 0108 out.push_back(FilterList{*namesIt, *urlsIt}); 0109 0110 namesIt++; 0111 urlsIt++; 0112 } 0113 0114 return out; 0115 } 0116 0117 void AdblockFilterListsManager::writeToConfig(const QVector<AdblockFilterListsManager::FilterList> &filters) 0118 { 0119 QStringList filterNames; 0120 QList<QUrl> filterUrls; 0121 0122 for (const auto &filterList : filters) { 0123 filterNames.push_back(filterList.name); 0124 filterUrls.push_back(filterList.url); 0125 } 0126 0127 AngelfishSettings::setAdblockFilterNames(filterNames); 0128 AngelfishSettings::setAdblockFilterUrls(filterUrls); 0129 } 0130 0131 const QVector<AdblockFilterListsManager::FilterList> &AdblockFilterListsManager::filterLists() const 0132 { 0133 return m_filterLists; 0134 } 0135 0136 void AdblockFilterListsManager::addFilterList(const QString &name, const QUrl &url) 0137 { 0138 m_filterLists.push_back(FilterList{name, url}); 0139 writeToConfig(m_filterLists); 0140 } 0141 0142 void AdblockFilterListsManager::removeFilterList(const int index) 0143 { 0144 m_filterLists.removeAt(index); 0145 writeToConfig(m_filterLists); 0146 } 0147 0148 #include "moc_adblockfilterlistsmanager.cpp"