File indexing completed on 2025-01-05 04:37:22

0001 /*
0002     SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 #include "peerid.h"
0007 
0008 #include <QMap>
0009 #include <QRandomGenerator>
0010 
0011 #include <KLocalizedString>
0012 
0013 #include "version.h"
0014 
0015 namespace bt
0016 {
0017 char RandomLetterOrNumber()
0018 {
0019     int i = QRandomGenerator::global()->bounded(62);
0020     if (i < 26)
0021         return 'a' + i;
0022     else if (i < 52)
0023         return 'A' + (i - 26);
0024     else
0025         return '0' + (i - 52);
0026 }
0027 
0028 QString charToNumber(QChar c)
0029 {
0030     if (c >= 'A' && c <= 'F')
0031         return QString::number(c.toLatin1() - 'A' + 10);
0032     else if (c >= 'z' && c <= 'f')
0033         return QString::number(c.toLatin1() - 'a' + 10);
0034     else
0035         return c;
0036 }
0037 
0038 PeerID::PeerID()
0039 {
0040     memcpy(id, bt::PeerIDPrefix().toLatin1().constData(), 10);
0041     for (int i = 10; i < 20; i++)
0042         id[i] = RandomLetterOrNumber();
0043     client_name = identifyClient();
0044 }
0045 
0046 PeerID::PeerID(const char *pid)
0047 {
0048     if (pid)
0049         memcpy(id, pid, 20);
0050     else
0051         memset(id, 0, 20);
0052     client_name = identifyClient();
0053 }
0054 
0055 PeerID::PeerID(const PeerID &pid)
0056 {
0057     memcpy(id, pid.id, 20);
0058     client_name = pid.client_name;
0059 }
0060 
0061 PeerID::~PeerID()
0062 {
0063 }
0064 
0065 PeerID &PeerID::operator=(const PeerID &pid)
0066 {
0067     memcpy(id, pid.id, 20);
0068     client_name = pid.client_name;
0069     return *this;
0070 }
0071 
0072 bool operator==(const PeerID &a, const PeerID &b)
0073 {
0074     for (int i = 0; i < 20; i++)
0075         if (a.id[i] != b.id[i])
0076             return false;
0077 
0078     return true;
0079 }
0080 
0081 bool operator!=(const PeerID &a, const PeerID &b)
0082 {
0083     return !operator==(a, b);
0084 }
0085 
0086 bool operator<(const PeerID &a, const PeerID &b)
0087 {
0088     for (int i = 0; i < 20; i++)
0089         if (a.id[i] < b.id[i])
0090             return true;
0091 
0092     return false;
0093 }
0094 
0095 QString PeerID::toString() const
0096 {
0097     QString r;
0098     r.reserve(20);
0099     for (int i = 0; i < 20; i++)
0100         r += id[i] == 0 ? ' ' : id[i];
0101     return r;
0102 }
0103 
0104 QString PeerID::identifyClient() const
0105 {
0106     if (!client_name.isNull())
0107         return client_name;
0108 
0109     QString peer_id = toString();
0110     // we only need to create this map once
0111     // so make it static
0112     static QMap<QString, QString> Map;
0113     static bool first = true;
0114 
0115     if (first) {
0116         // Keep things a bit alphabetic to make it easier add new ones
0117         // AZUREUS STYLE
0118         Map[QStringLiteral("7T")] = QStringLiteral("aTorrent");
0119         Map[QStringLiteral("AB")] = QStringLiteral("AnyEvent::BitTorrent");
0120         Map[QStringLiteral("AG")] = QStringLiteral("Ares");
0121         Map[QStringLiteral("AR")] = QStringLiteral("Arctic");
0122         Map[QStringLiteral("AT")] = QStringLiteral("Artemis");
0123         Map[QStringLiteral("AV")] = QStringLiteral("Avicora");
0124         Map[QStringLiteral("AX")] = QStringLiteral("BitPump");
0125         Map[QStringLiteral("AZ")] = QStringLiteral("Azureus");
0126         Map[QStringLiteral("A~")] = QStringLiteral("Ares");
0127         Map[QStringLiteral("BB")] = QStringLiteral("BitBuddy");
0128         Map[QStringLiteral("BC")] = QStringLiteral("BitComet");
0129         Map[QStringLiteral("BE")] = QStringLiteral("Baretorrent");
0130         Map[QStringLiteral("BF")] = QStringLiteral("Bitflu");
0131         Map[QStringLiteral("BG")] = QStringLiteral("BTGetit");
0132         Map[QStringLiteral("BL")] = QStringLiteral("BitBlinder");
0133         Map[QStringLiteral("BM")] = QStringLiteral("BitMagnet");
0134         Map[QStringLiteral("BO")] = QStringLiteral("BitsOnWheels");
0135         Map[QStringLiteral("BP")] = QStringLiteral("BitTorrent Pro");
0136         Map[QStringLiteral("BR")] = QStringLiteral("BitRocket");
0137         Map[QStringLiteral("BS")] = QStringLiteral("BTSlave");
0138         Map[QStringLiteral("BT")] = QStringLiteral("mainline BitTorrent");
0139         Map[QStringLiteral("Bt")] = QStringLiteral("Bt");
0140         Map[QStringLiteral("BW")] = QStringLiteral("BitWombat");
0141         Map[QStringLiteral("BX")] = QStringLiteral("BitTorrent X");
0142         Map[QStringLiteral("CD")] = QStringLiteral("Enhanced CTorrent");
0143         Map[QStringLiteral("CS")] = QStringLiteral("SpywareTerminator");
0144         Map[QStringLiteral("CT")] = QStringLiteral("CTorrent");
0145         Map[QStringLiteral("DE")] = QStringLiteral("DelugeTorrent");
0146         Map[QStringLiteral("DP")] = QStringLiteral("Propagate Data Client");
0147         Map[QStringLiteral("EB")] = QStringLiteral("EBit");
0148         Map[QStringLiteral("ES")] = QStringLiteral("electric sheep");
0149         Map[QStringLiteral("FC")] = QStringLiteral("FileCroc");
0150         Map[QStringLiteral("FD")] = QStringLiteral("Free Download Manager");
0151         Map[QStringLiteral("FT")] = QStringLiteral("FoxTorrent");
0152         Map[QStringLiteral("FX")] = QStringLiteral("Freebox BitTorrent");
0153         Map[QStringLiteral("G3")] = QStringLiteral("G3 Torrent");
0154         Map[QStringLiteral("GS")] = QStringLiteral("GSTorrent");
0155         Map[QStringLiteral("HK")] = QStringLiteral("Hekate");
0156         Map[QStringLiteral("HL")] = QStringLiteral("Halite");
0157         Map[QStringLiteral("HM")] = QStringLiteral("hMule");
0158         Map[QStringLiteral("HN")] = QStringLiteral("Hydranode");
0159         Map[QStringLiteral("IL")] = QStringLiteral("iLivid");
0160         Map[QStringLiteral("JS")] = QStringLiteral("Justseed.it client");
0161         Map[QStringLiteral("JT")] = QStringLiteral("JavaTorrent");
0162         Map[QStringLiteral("KG")] = QStringLiteral("KGet");
0163         Map[QStringLiteral("KT")] = QStringLiteral("KTorrent"); // lets not forget our own client
0164         Map[QStringLiteral("LC")] = QStringLiteral("LeechCraft");
0165         Map[QStringLiteral("LH")] = QStringLiteral("LH-ABC");
0166         Map[QStringLiteral("LP")] = QStringLiteral("Lphant");
0167         Map[QStringLiteral("LT")] = QStringLiteral("libtorrent");
0168         Map[QStringLiteral("lt")] = QStringLiteral("libTorrent");
0169         Map[QStringLiteral("LW")] = QStringLiteral("LimeWire");
0170         Map[QStringLiteral("MK")] = QStringLiteral("Meerkat");
0171         Map[QStringLiteral("ML")] = QStringLiteral("MLDonkey");
0172         Map[QStringLiteral("MO")] = QStringLiteral("MonoTorrent");
0173         Map[QStringLiteral("MP")] = QStringLiteral("MooPolice");
0174         Map[QStringLiteral("MR")] = QStringLiteral("Miro");
0175         Map[QStringLiteral("MT")] = QStringLiteral("MoonLight");
0176         Map[QStringLiteral("NB")] = QStringLiteral("Net::BitTorrent");
0177         Map[QStringLiteral("NE")] = QStringLiteral("BT Next Evolution");
0178         Map[QStringLiteral("NX")] = QStringLiteral("Net Transport");
0179         Map[QStringLiteral("OS")] = QStringLiteral("OneSwarm");
0180         Map[QStringLiteral("OT")] = QStringLiteral("OmegaTorrent");
0181         Map[QStringLiteral("PB")] = QStringLiteral("Protocol::BitTorrent");
0182         Map[QStringLiteral("PD")] = QStringLiteral("Pando");
0183         Map[QStringLiteral("qB")] = QStringLiteral("qBittorrent");
0184         Map[QStringLiteral("QD")] = QStringLiteral("QQDownload");
0185         Map[QStringLiteral("QT")] = QStringLiteral("Qt 4 Torrent example");
0186         Map[QStringLiteral("RT")] = QStringLiteral("Retriever");
0187         Map[QStringLiteral("RZ")] = QStringLiteral("RezTorrent");
0188         Map[QStringLiteral("SB")] = QStringLiteral("Swiftbit");
0189         Map[QStringLiteral("SD")] = QStringLiteral("Thunder");
0190         Map[QStringLiteral("SM")] = QStringLiteral("SoMud");
0191         Map[QStringLiteral("SP")] = QStringLiteral("BitSpirit");
0192         Map[QStringLiteral("SS")] = QStringLiteral("SwarmScope");
0193         Map[QStringLiteral("st")] = QStringLiteral("sharktorrent");
0194         Map[QStringLiteral("ST")] = QStringLiteral("SymTorrent");
0195         Map[QStringLiteral("SZ")] = QStringLiteral("Shareaza");
0196         Map[QStringLiteral("S~")] = QStringLiteral("Shareaza alpha/beta");
0197         Map[QStringLiteral("TB")] = QStringLiteral("Torch");
0198         Map[QStringLiteral("TE")] = QStringLiteral("terasaur Seed Bank");
0199         Map[QStringLiteral("TL")] = QStringLiteral("Tribler");
0200         Map[QStringLiteral("TN")] = QStringLiteral("Torrent .NET");
0201         Map[QStringLiteral("TR")] = QStringLiteral("Transmission");
0202         Map[QStringLiteral("TS")] = QStringLiteral("Torrent Storm");
0203         Map[QStringLiteral("TT")] = QStringLiteral("TuoTu");
0204         Map[QStringLiteral("UL")] = QStringLiteral("uLeecher!");
0205         Map[QStringLiteral("UM")] = QStringLiteral("%1Torrent for Mac").arg(QChar(0x00B5)); // µTorrent, 0x00B5 is unicode for µ
0206         Map[QStringLiteral("UT")] = QStringLiteral("%1Torrent").arg(QChar(0x00B5)); // µTorrent, 0x00B5 is unicode for µ
0207         Map[QStringLiteral("VG")] = QStringLiteral("Vagaa");
0208         Map[QStringLiteral("WD")] = QStringLiteral("WebTorrent Desktop");
0209         Map[QStringLiteral("WT")] = QStringLiteral("BitLet");
0210         Map[QStringLiteral("WW")] = QStringLiteral("WebTorrent");
0211         Map[QStringLiteral("WY")] = QStringLiteral("FireTorrent");
0212         Map[QStringLiteral("XF")] = QStringLiteral("Xfplay");
0213         Map[QStringLiteral("XL")] = QStringLiteral("Xunlei");
0214         Map[QStringLiteral("XS")] = QStringLiteral("XSwifter");
0215         Map[QStringLiteral("XT")] = QStringLiteral("Xan Torrent");
0216         Map[QStringLiteral("XX")] = QStringLiteral("Xtorrent");
0217         Map[QStringLiteral("ZT")] = QStringLiteral("Zip Torrent");
0218 
0219         // SHADOWS STYLE
0220         Map[QStringLiteral("A")] = QStringLiteral("ABC");
0221         Map[QStringLiteral("O")] = QStringLiteral("Osprey Permaseed");
0222         Map[QStringLiteral("Q")] = QStringLiteral("BTQueue");
0223         Map[QStringLiteral("R")] = QStringLiteral("Tribler");
0224         Map[QStringLiteral("S")] = QStringLiteral("Shadow's");
0225         Map[QStringLiteral("T")] = QStringLiteral("BitTornado");
0226         Map[QStringLiteral("U")] = QStringLiteral("UPnP NAT BitTorrent");
0227         // OTHER
0228         Map[QStringLiteral("Plus")] = QStringLiteral("Plus! II");
0229         Map[QStringLiteral("OP")] = QStringLiteral("Opera");
0230         Map[QStringLiteral("BOW")] = QStringLiteral("Bits on Wheels");
0231         Map[QStringLiteral("M")] = QStringLiteral("BitTorrent");
0232         Map[QStringLiteral("exbc")] = QStringLiteral("BitComet");
0233         Map[QStringLiteral("Mbrst")] = QStringLiteral("Burst!");
0234         Map[QStringLiteral("XBT")] = QStringLiteral("XBT Client");
0235         Map[QStringLiteral("SP")] = QStringLiteral("BitSpirit");
0236         Map[QStringLiteral("FG")] = QStringLiteral("FlashGet");
0237         Map[QStringLiteral("RS")] = QStringLiteral("Rufus");
0238         Map[QStringLiteral("Q1")] = QStringLiteral("Queen Bee");
0239         Map[QStringLiteral("AP")] = QStringLiteral("AllPeers");
0240         Map[QStringLiteral("QVOD")] = QStringLiteral("Qvod");
0241         Map[QStringLiteral("TIX")] = QStringLiteral("Tixati");
0242         first = false;
0243     }
0244 
0245     QString name;
0246     if (peer_id.at(0) == '-' && peer_id.at(1).isLetter() && peer_id.at(2).isLetter()) { // AZ style
0247         QString ID(peer_id.mid(1, 2));
0248         if (ID == QLatin1String("ML")) {
0249             name = Map[ID];
0250             const int dash_pos = peer_id.indexOf('-', 3);
0251             if (dash_pos != -1)
0252                 name += ' ' + peer_id.mid(3, dash_pos - 3);
0253         } else if (Map.contains(ID)) {
0254             if (peer_id.at(9) == '-') {
0255                 name = Map[ID] + ' ' + charToNumber(peer_id.at(3)) + charToNumber(peer_id.at(4)) + '.' + charToNumber(peer_id.at(5))
0256                     + charToNumber(peer_id.at(6)) + '.' + charToNumber(peer_id.at(7)) + charToNumber(peer_id.at(8));
0257             } else {
0258                 name = Map[ID] + ' ' + charToNumber(peer_id.at(3)) + '.' + charToNumber(peer_id.at(4)) + '.' + charToNumber(peer_id.at(5));
0259             }
0260         }
0261     } else if (peer_id.at(0).isLetter() && peer_id.at(1).isDigit() && peer_id.at(2).isDigit()) { // Shadow's style
0262         QString ID = QString(peer_id.at(0));
0263         if (Map.contains(ID))
0264             name = Map[ID] + ' ' + peer_id.at(1) + '.' + peer_id.at(2) + '.' + peer_id.at(3);
0265     } else if (peer_id.at(0) == 'M' && peer_id.at(2) == '-' && (peer_id.at(4) == '-' || peer_id.at(5) == '-')) {
0266         name = Map[QStringLiteral("M")] + ' ' + peer_id.at(1) + '.' + peer_id.at(3);
0267         if (peer_id.at(4) == '-')
0268             name += QStringLiteral(".%1").arg(peer_id.at(5));
0269         else
0270             name += QStringLiteral("%1.%2").arg(peer_id.at(4)).arg(peer_id.at(6));
0271     } else if (peer_id.startsWith(QLatin1String("OP"))) {
0272         name = Map[QStringLiteral("OP")];
0273     } else if (peer_id.startsWith(QLatin1String("exbc"))) {
0274         name = Map[QStringLiteral("exbc")];
0275     } else if (peer_id.mid(1, 3) == QLatin1String("BOW")) {
0276         name = Map[QStringLiteral("BOW")];
0277     } else if (peer_id.startsWith(QLatin1String("Plus"))) {
0278         name = Map[QStringLiteral("Plus")];
0279     } else if (peer_id.startsWith(QLatin1String("Mbrst"))) {
0280         name = Map[QStringLiteral("Mbrst")] + ' ' + peer_id.at(5) + '.' + peer_id.at(7);
0281     } else if (peer_id.startsWith(QLatin1String("XBT"))) {
0282         name = Map[QStringLiteral("XBT")] + ' ' + peer_id.at(3) + '.' + peer_id.at(4) + '.' + peer_id.at(5);
0283     } else if (peer_id.startsWith(QLatin1String("SP"))) {
0284         name = Map[QStringLiteral("SP")] + ' ' + peer_id.at(2) + '.' + peer_id.at(3) + '.' + peer_id.at(4) + '.' + peer_id.at(5);
0285     } else if (peer_id.startsWith(QLatin1String("FG"))) {
0286         name = Map[QStringLiteral("FG")] + ' ' + peer_id.at(2) + '.' + peer_id.at(3) + '.' + peer_id.at(4) + '.' + peer_id.at(5);
0287     } else if (QStringView(peer_id).mid(2, 2) == QLatin1String("RS")) {
0288         name = Map[QStringLiteral("RS")];
0289     } else if (peer_id.startsWith(QLatin1String("Q1"))) {
0290         name = Map[QStringLiteral("Q1")];
0291     } else if (peer_id.startsWith(QLatin1String("AP"))) {
0292         name = Map[QStringLiteral("AP")];
0293     } else if (peer_id.startsWith(QLatin1String("QVOD"))) {
0294         name = Map[QStringLiteral("QVOD")];
0295     } else if (peer_id.startsWith(QLatin1String("TIX"))) {
0296         name = Map[QStringLiteral("TIX")] + ' ' + peer_id.at(3) + peer_id.at(4) + '.' + peer_id.at(5) + peer_id.at(6);
0297     }
0298     if (name.isEmpty()) {
0299         name = i18n("Unknown client");
0300     }
0301 
0302     return name;
0303 }
0304 }