From 17f5ffcaec07975bb15893363fd8262cbc7be3c6 Mon Sep 17 00:00:00 2001 From: Ivan Sorokin Date: Tue, 4 Nov 2014 12:47:07 +0300 Subject: [PATCH] Split filterparserthread into .h and .cpp --- src/qtlibtorrent/filterparserthread.cpp | 389 ++++++++++++++++++++++++ src/qtlibtorrent/filterparserthread.h | 366 +--------------------- src/qtlibtorrent/qtlibtorrent.pri | 3 +- 3 files changed, 401 insertions(+), 357 deletions(-) create mode 100644 src/qtlibtorrent/filterparserthread.cpp diff --git a/src/qtlibtorrent/filterparserthread.cpp b/src/qtlibtorrent/filterparserthread.cpp new file mode 100644 index 000000000..84b9f3c3d --- /dev/null +++ b/src/qtlibtorrent/filterparserthread.cpp @@ -0,0 +1,389 @@ +/* + * Bittorrent Client using Qt4 and libtorrent. + * Copyright (C) 2006 Christophe Dumez + * + * 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 + * of the License, or (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + * + * Contact : chris@qbittorrent.org + */ + +#include "filterparserthread.h" + +FilterParserThread::FilterParserThread(QObject* parent, libtorrent::session *s) : QThread(parent), s(s), abort(false) { + +} + +FilterParserThread::~FilterParserThread() { + abort = true; + wait(); +} + +// Parser for eMule ip filter in DAT format +int FilterParserThread::parseDATFilterFile(QString filePath) { + int ruleCount = 0; + QFile file(filePath); + if (file.exists()) { + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + std::cerr << "I/O Error: Could not open ip filer file in read mode." << std::endl; + return ruleCount; + } + unsigned int nbLine = 0; + while (!file.atEnd() && !abort) { + ++nbLine; + QByteArray line = file.readLine(); + // Ignoring empty lines + line = line.trimmed(); + if (line.isEmpty()) continue; + // Ignoring commented lines + if (line.startsWith('#') || line.startsWith("//")) continue; + + // Line should be splitted by commas + QList partsList = line.split(','); + const uint nbElem = partsList.size(); + + // IP Range should be splitted by a dash + QList IPs = partsList.first().split('-'); + if (IPs.size() != 2) { + qDebug("Ipfilter.dat: line %d is malformed.", nbLine); + qDebug("Line was %s", line.constData()); + continue; + } + + boost::system::error_code ec; + const QString strStartIP = cleanupIPAddress(IPs.at(0)); + if (strStartIP.isEmpty()) { + qDebug("Ipfilter.dat: line %d is malformed.", nbLine); + qDebug("Start IP of the range is malformated: %s", qPrintable(strStartIP)); + continue; + } + libtorrent::address startAddr = libtorrent::address::from_string(qPrintable(strStartIP), ec); + if (ec) { + qDebug("Ipfilter.dat: line %d is malformed.", nbLine); + qDebug("Start IP of the range is malformated: %s", qPrintable(strStartIP)); + continue; + } + const QString strEndIP = cleanupIPAddress(IPs.at(1)); + if (strEndIP.isEmpty()) { + qDebug("Ipfilter.dat: line %d is malformed.", nbLine); + qDebug("End IP of the range is malformated: %s", qPrintable(strEndIP)); + continue; + } + libtorrent::address endAddr = libtorrent::address::from_string(qPrintable(strEndIP), ec); + if (ec) { + qDebug("Ipfilter.dat: line %d is malformed.", nbLine); + qDebug("End IP of the range is malformated: %s", qPrintable(strEndIP)); + continue; + } + if (startAddr.is_v4() != endAddr.is_v4()) { + qDebug("Ipfilter.dat: line %d is malformed.", nbLine); + qDebug("One IP is IPv4 and the other is IPv6!"); + continue; + } + + // Check if there is an access value (apparently not mandatory) + int nbAccess = 0; + if (nbElem > 1) { + // There is possibly one + nbAccess = partsList.at(1).trimmed().toInt(); + } + + if (nbAccess > 127) { + // Ignoring this rule because access value is too high + continue; + } + // Now Add to the filter + try { + filter.add_rule(startAddr, endAddr, libtorrent::ip_filter::blocked); + ++ruleCount; + }catch(exception) { + qDebug("Bad line in filter file, avoided crash..."); + } + } + file.close(); + } + return ruleCount; +} + +// Parser for PeerGuardian ip filter in p2p format +int FilterParserThread::parseP2PFilterFile(QString filePath) { + int ruleCount = 0; + QFile file(filePath); + if (file.exists()) { + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + std::cerr << "I/O Error: Could not open ip filer file in read mode." << std::endl; + return ruleCount; + } + unsigned int nbLine = 0; + while (!file.atEnd() && !abort) { + ++nbLine; + QByteArray line = file.readLine().trimmed(); + if (line.isEmpty()) continue; + // Ignoring commented lines + if (line.startsWith('#') || line.startsWith("//")) continue; + // Line is splitted by : + QList partsList = line.split(':'); + if (partsList.size() < 2) { + qDebug("p2p file: line %d is malformed.", nbLine); + continue; + } + // Get IP range + QList IPs = partsList.last().split('-'); + if (IPs.size() != 2) { + qDebug("p2p file: line %d is malformed.", nbLine); + qDebug("line was: %s", line.constData()); + continue; + } + boost::system::error_code ec; + QString strStartIP = cleanupIPAddress(IPs.at(0)); + if (strStartIP.isEmpty()) { + qDebug("p2p file: line %d is malformed.", nbLine); + qDebug("Start IP is invalid: %s", qPrintable(strStartIP)); + continue; + } + libtorrent::address startAddr = libtorrent::address::from_string(qPrintable(strStartIP), ec); + if (ec) { + qDebug("p2p file: line %d is malformed.", nbLine); + qDebug("Start IP is invalid: %s", qPrintable(strStartIP)); + continue; + } + QString strEndIP = cleanupIPAddress(IPs.at(1)); + if (strEndIP.isEmpty()) { + qDebug("p2p file: line %d is malformed.", nbLine); + qDebug("End IP is invalid: %s", qPrintable(strStartIP)); + continue; + } + libtorrent::address endAddr = libtorrent::address::from_string(qPrintable(strEndIP), ec); + if (ec) { + qDebug("p2p file: line %d is malformed.", nbLine); + qDebug("End IP is invalid: %s", qPrintable(strStartIP)); + continue; + } + if (startAddr.is_v4() != endAddr.is_v4()) { + qDebug("p2p file: line %d is malformed.", nbLine); + qDebug("Line was: %s", line.constData()); + continue; + } + try { + filter.add_rule(startAddr, endAddr, libtorrent::ip_filter::blocked); + ++ruleCount; + } catch(std::exception&) { + qDebug("p2p file: line %d is malformed.", nbLine); + qDebug("Line was: %s", line.constData()); + continue; + } + } + file.close(); + } + return ruleCount; +} + +int FilterParserThread::getlineInStream(QDataStream& stream, string& name, char delim) { + char c; + int total_read = 0; + int read; + do { + read = stream.readRawData(&c, 1); + total_read += read; + if (read > 0) { + if (c != delim) { + name += c; + } else { + // Delim found + return total_read; + } + } + } while(read > 0); + return total_read; +} + +// Parser for PeerGuardian ip filter in p2p format +int FilterParserThread::parseP2BFilterFile(QString filePath) { + int ruleCount = 0; + QFile file(filePath); + if (file.exists()) { + if (!file.open(QIODevice::ReadOnly)) { + std::cerr << "I/O Error: Could not open ip filer file in read mode." << std::endl; + return ruleCount; + } + QDataStream stream(&file); + // Read header + char buf[7]; + unsigned char version; + if ( + !stream.readRawData(buf, sizeof(buf)) || + memcmp(buf, "\xFF\xFF\xFF\xFFP2B", 7) || + !stream.readRawData((char*)&version, sizeof(version)) + ) { + std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl; + return ruleCount; + } + + if (version==1 || version==2) { + qDebug ("p2b version 1 or 2"); + unsigned int start, end; + + string name; + while(getlineInStream(stream, name, '\0') && !abort) { + if ( + !stream.readRawData((char*)&start, sizeof(start)) || + !stream.readRawData((char*)&end, sizeof(end)) + ) { + std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl; + return ruleCount; + } + // Network byte order to Host byte order + // asio address_v4 contructor expects it + // that way + libtorrent::address_v4 first(ntohl(start)); + libtorrent::address_v4 last(ntohl(end)); + // Apply to bittorrent session + try { + filter.add_rule(first, last, libtorrent::ip_filter::blocked); + ++ruleCount; + } catch(std::exception&) {} + } + } + else if (version==3) { + qDebug ("p2b version 3"); + unsigned int namecount; + if (!stream.readRawData((char*)&namecount, sizeof(namecount))) { + std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl; + return ruleCount; + } + namecount=ntohl(namecount); + // Reading names although, we don't really care about them + for (unsigned int i=0; iget_ip_filter(); + if (isRunning()) { + // Already parsing a filter, abort first + abort = true; + wait(); + } + abort = false; + filePath = _filePath; + // Run it + start(); +} + +void FilterParserThread::processFilterList(libtorrent::session *s, const QStringList& IPs) { + // First, import current filter + libtorrent::ip_filter filter = s->get_ip_filter(); + foreach (const QString &ip, IPs) { + qDebug("Manual ban of peer %s", ip.toLocal8Bit().constData()); + boost::system::error_code ec; + libtorrent::address addr = libtorrent::address::from_string(ip.toLocal8Bit().constData(), ec); + Q_ASSERT(!ec); + if (!ec) + filter.add_rule(addr, addr, libtorrent::ip_filter::blocked); + } + s->set_ip_filter(filter); +} + +QString FilterParserThread::cleanupIPAddress(QString _ip) { + QHostAddress ip(_ip.trimmed()); + if (ip.isNull()) { + return QString(); + } + return ip.toString(); +} + +void FilterParserThread::run() { + qDebug("Processing filter file"); + int ruleCount = 0; + if (filePath.endsWith(".p2p", Qt::CaseInsensitive)) { + // PeerGuardian p2p file + ruleCount = parseP2PFilterFile(filePath); + } else { + if (filePath.endsWith(".p2b", Qt::CaseInsensitive)) { + // PeerGuardian p2b file + ruleCount = parseP2BFilterFile(filePath); + } else { + // Default: eMule DAT format + ruleCount = parseDATFilterFile(filePath); + } + } + if (abort) + return; + try { + s->set_ip_filter(filter); + emit IPFilterParsed(ruleCount); + } catch(std::exception&) { + emit IPFilterError(); + } + qDebug("IP Filter thread: finished parsing, filter applied"); +} diff --git a/src/qtlibtorrent/filterparserthread.h b/src/qtlibtorrent/filterparserthread.h index 9ef911a9f..1991182a1 100644 --- a/src/qtlibtorrent/filterparserthread.h +++ b/src/qtlibtorrent/filterparserthread.h @@ -55,375 +55,29 @@ class FilterParserThread : public QThread { Q_OBJECT public: - FilterParserThread(QObject* parent, libtorrent::session *s) : QThread(parent), s(s), abort(false) { + FilterParserThread(QObject* parent, libtorrent::session *s); + ~FilterParserThread(); - } - - ~FilterParserThread() { - abort = true; - wait(); - } - - // Parser for eMule ip filter in DAT format - int parseDATFilterFile(QString filePath) { - int ruleCount = 0; - QFile file(filePath); - if (file.exists()) { - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - std::cerr << "I/O Error: Could not open ip filer file in read mode." << std::endl; - return ruleCount; - } - unsigned int nbLine = 0; - while (!file.atEnd() && !abort) { - ++nbLine; - QByteArray line = file.readLine(); - // Ignoring empty lines - line = line.trimmed(); - if (line.isEmpty()) continue; - // Ignoring commented lines - if (line.startsWith('#') || line.startsWith("//")) continue; - - // Line should be splitted by commas - QList partsList = line.split(','); - const uint nbElem = partsList.size(); - - // IP Range should be splitted by a dash - QList IPs = partsList.first().split('-'); - if (IPs.size() != 2) { - qDebug("Ipfilter.dat: line %d is malformed.", nbLine); - qDebug("Line was %s", line.constData()); - continue; - } - - boost::system::error_code ec; - const QString strStartIP = cleanupIPAddress(IPs.at(0)); - if (strStartIP.isEmpty()) { - qDebug("Ipfilter.dat: line %d is malformed.", nbLine); - qDebug("Start IP of the range is malformated: %s", qPrintable(strStartIP)); - continue; - } - libtorrent::address startAddr = libtorrent::address::from_string(qPrintable(strStartIP), ec); - if (ec) { - qDebug("Ipfilter.dat: line %d is malformed.", nbLine); - qDebug("Start IP of the range is malformated: %s", qPrintable(strStartIP)); - continue; - } - const QString strEndIP = cleanupIPAddress(IPs.at(1)); - if (strEndIP.isEmpty()) { - qDebug("Ipfilter.dat: line %d is malformed.", nbLine); - qDebug("End IP of the range is malformated: %s", qPrintable(strEndIP)); - continue; - } - libtorrent::address endAddr = libtorrent::address::from_string(qPrintable(strEndIP), ec); - if (ec) { - qDebug("Ipfilter.dat: line %d is malformed.", nbLine); - qDebug("End IP of the range is malformated: %s", qPrintable(strEndIP)); - continue; - } - if (startAddr.is_v4() != endAddr.is_v4()) { - qDebug("Ipfilter.dat: line %d is malformed.", nbLine); - qDebug("One IP is IPv4 and the other is IPv6!"); - continue; - } - - // Check if there is an access value (apparently not mandatory) - int nbAccess = 0; - if (nbElem > 1) { - // There is possibly one - nbAccess = partsList.at(1).trimmed().toInt(); - } - - if (nbAccess > 127) { - // Ignoring this rule because access value is too high - continue; - } - // Now Add to the filter - try { - filter.add_rule(startAddr, endAddr, libtorrent::ip_filter::blocked); - ++ruleCount; - }catch(exception) { - qDebug("Bad line in filter file, avoided crash..."); - } - } - file.close(); - } - return ruleCount; - } - - // Parser for PeerGuardian ip filter in p2p format - int parseP2PFilterFile(QString filePath) { - int ruleCount = 0; - QFile file(filePath); - if (file.exists()) { - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - std::cerr << "I/O Error: Could not open ip filer file in read mode." << std::endl; - return ruleCount; - } - unsigned int nbLine = 0; - while (!file.atEnd() && !abort) { - ++nbLine; - QByteArray line = file.readLine().trimmed(); - if (line.isEmpty()) continue; - // Ignoring commented lines - if (line.startsWith('#') || line.startsWith("//")) continue; - // Line is splitted by : - QList partsList = line.split(':'); - if (partsList.size() < 2) { - qDebug("p2p file: line %d is malformed.", nbLine); - continue; - } - // Get IP range - QList IPs = partsList.last().split('-'); - if (IPs.size() != 2) { - qDebug("p2p file: line %d is malformed.", nbLine); - qDebug("line was: %s", line.constData()); - continue; - } - boost::system::error_code ec; - QString strStartIP = cleanupIPAddress(IPs.at(0)); - if (strStartIP.isEmpty()) { - qDebug("p2p file: line %d is malformed.", nbLine); - qDebug("Start IP is invalid: %s", qPrintable(strStartIP)); - continue; - } - libtorrent::address startAddr = libtorrent::address::from_string(qPrintable(strStartIP), ec); - if (ec) { - qDebug("p2p file: line %d is malformed.", nbLine); - qDebug("Start IP is invalid: %s", qPrintable(strStartIP)); - continue; - } - QString strEndIP = cleanupIPAddress(IPs.at(1)); - if (strEndIP.isEmpty()) { - qDebug("p2p file: line %d is malformed.", nbLine); - qDebug("End IP is invalid: %s", qPrintable(strStartIP)); - continue; - } - libtorrent::address endAddr = libtorrent::address::from_string(qPrintable(strEndIP), ec); - if (ec) { - qDebug("p2p file: line %d is malformed.", nbLine); - qDebug("End IP is invalid: %s", qPrintable(strStartIP)); - continue; - } - if (startAddr.is_v4() != endAddr.is_v4()) { - qDebug("p2p file: line %d is malformed.", nbLine); - qDebug("Line was: %s", line.constData()); - continue; - } - try { - filter.add_rule(startAddr, endAddr, libtorrent::ip_filter::blocked); - ++ruleCount; - } catch(std::exception&) { - qDebug("p2p file: line %d is malformed.", nbLine); - qDebug("Line was: %s", line.constData()); - continue; - } - } - file.close(); - } - return ruleCount; - } - - int getlineInStream(QDataStream& stream, string& name, char delim) { - char c; - int total_read = 0; - int read; - do { - read = stream.readRawData(&c, 1); - total_read += read; - if (read > 0) { - if (c != delim) { - name += c; - } else { - // Delim found - return total_read; - } - } - } while(read > 0); - return total_read; - } - - // Parser for PeerGuardian ip filter in p2p format - int parseP2BFilterFile(QString filePath) { - int ruleCount = 0; - QFile file(filePath); - if (file.exists()) { - if (!file.open(QIODevice::ReadOnly)) { - std::cerr << "I/O Error: Could not open ip filer file in read mode." << std::endl; - return ruleCount; - } - QDataStream stream(&file); - // Read header - char buf[7]; - unsigned char version; - if ( - !stream.readRawData(buf, sizeof(buf)) || - memcmp(buf, "\xFF\xFF\xFF\xFFP2B", 7) || - !stream.readRawData((char*)&version, sizeof(version)) - ) { - std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl; - return ruleCount; - } - - if (version==1 || version==2) { - qDebug ("p2b version 1 or 2"); - unsigned int start, end; - - string name; - while(getlineInStream(stream, name, '\0') && !abort) { - if ( - !stream.readRawData((char*)&start, sizeof(start)) || - !stream.readRawData((char*)&end, sizeof(end)) - ) { - std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl; - return ruleCount; - } - // Network byte order to Host byte order - // asio address_v4 contructor expects it - // that way - libtorrent::address_v4 first(ntohl(start)); - libtorrent::address_v4 last(ntohl(end)); - // Apply to bittorrent session - try { - filter.add_rule(first, last, libtorrent::ip_filter::blocked); - ++ruleCount; - } catch(std::exception&) {} - } - } - else if (version==3) { - qDebug ("p2b version 3"); - unsigned int namecount; - if (!stream.readRawData((char*)&namecount, sizeof(namecount))) { - std::cerr << "Parsing Error: The filter file is not a valid PeerGuardian P2B file." << std::endl; - return ruleCount; - } - namecount=ntohl(namecount); - // Reading names although, we don't really care about them - for (unsigned int i=0; iget_ip_filter(); - if (isRunning()) { - // Already parsing a filter, abort first - abort = true; - wait(); - } - abort = false; - filePath = _filePath; - // Run it - start(); - } - - static void processFilterList(libtorrent::session *s, const QStringList& IPs) { - // First, import current filter - libtorrent::ip_filter filter = s->get_ip_filter(); - foreach (const QString &ip, IPs) { - qDebug("Manual ban of peer %s", ip.toLocal8Bit().constData()); - boost::system::error_code ec; - libtorrent::address addr = libtorrent::address::from_string(ip.toLocal8Bit().constData(), ec); - Q_ASSERT(!ec); - if (!ec) - filter.add_rule(addr, addr, libtorrent::ip_filter::blocked); - } - s->set_ip_filter(filter); - } + int parseDATFilterFile(QString filePath); + int parseP2PFilterFile(QString filePath); + int getlineInStream(QDataStream& stream, string& name, char delim); + int parseP2BFilterFile(QString filePath); + void processFilterFile(QString _filePath); + static void processFilterList(libtorrent::session *s, const QStringList& IPs); signals: void IPFilterParsed(int ruleCount); void IPFilterError(); protected: - QString cleanupIPAddress(QString _ip) { - QHostAddress ip(_ip.trimmed()); - if (ip.isNull()) { - return QString(); - } - return ip.toString(); - } - - void run() { - qDebug("Processing filter file"); - int ruleCount = 0; - if (filePath.endsWith(".p2p", Qt::CaseInsensitive)) { - // PeerGuardian p2p file - ruleCount = parseP2PFilterFile(filePath); - } else { - if (filePath.endsWith(".p2b", Qt::CaseInsensitive)) { - // PeerGuardian p2b file - ruleCount = parseP2BFilterFile(filePath); - } else { - // Default: eMule DAT format - ruleCount = parseDATFilterFile(filePath); - } - } - if (abort) - return; - try { - s->set_ip_filter(filter); - emit IPFilterParsed(ruleCount); - } catch(std::exception&) { - emit IPFilterError(); - } - qDebug("IP Filter thread: finished parsing, filter applied"); - } + QString cleanupIPAddress(QString _ip); + void run(); private: libtorrent::session *s; libtorrent::ip_filter filter; bool abort; QString filePath; - }; #endif diff --git a/src/qtlibtorrent/qtlibtorrent.pri b/src/qtlibtorrent/qtlibtorrent.pri index 72f16b04a..25acd8f73 100644 --- a/src/qtlibtorrent/qtlibtorrent.pri +++ b/src/qtlibtorrent/qtlibtorrent.pri @@ -13,7 +13,8 @@ SOURCES += $$PWD/qbtsession.cpp \ $$PWD/qtorrenthandle.cpp \ $$PWD/torrentspeedmonitor.cpp \ $$PWD/alertdispatcher.cpp \ - $$PWD/torrentstatistics.cpp + $$PWD/torrentstatistics.cpp \ + $$PWD/filterparserthread.cpp !contains(DEFINES, DISABLE_GUI) { HEADERS += $$PWD/torrentmodel.h \