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 }