source: trunk/libtransmission/clients.c @ 6389

Last change on this file since 6389 was 6389, checked in by charles, 13 years ago

(libT) make the licensing consistent across all the files which only contain my code

  • Property svn:keywords set to Date Rev Author Id
File size: 15.1 KB
Line 
1/*
2 * This file Copyright (C) 2008 Charles Kerr <charles@rebelbase.com>
3 *
4 * This file is licensed by the GPL version 2.  Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: clients.c 6389 2008-07-22 23:28:28Z charles $
11 */
12
13/* thanks amc1! */
14
15#include <ctype.h> /* isprint, tolower */
16#include <stdio.h>
17#include <stdlib.h> /* strtol */
18#include <string.h>
19
20#include "transmission.h"
21#include "utils.h"
22
23static int
24charint( char ch )
25{
26    if( '0' <= ch && ch <= '9' ) return      ch - '0';
27    if( 'A' <= ch && ch <= 'Z' ) return 10 + ch - 'A';
28    if( 'a' <= ch && ch <= 'z' ) return 36 + ch - 'a';
29    return 0;
30}
31
32static int
33strint( const void * pch, int span )
34{
35    char tmp[64];
36    memcpy( tmp, pch, span );
37    tmp[span] = '\0';
38    return strtol( tmp, NULL, 0 );
39}
40
41static const char*
42getMnemonicEnd( char ch )
43{
44    switch( ch )
45    {
46        case 'b': case 'B': return " (Beta)";
47        case 'd': return " (Debug)";
48        case 'x': case 'X': case 'Z': return " (Dev)";
49        default: return "";
50    }
51}
52
53static void
54three_digits( char * buf, size_t buflen, const char * name, const uint8_t * digits )
55{
56    tr_snprintf( buf, buflen, "%s %d.%d.%d", name,
57                 charint( digits[0] ),
58                 charint( digits[1] ),
59                 charint( digits[2] ) );
60}
61static void
62four_digits( char * buf, size_t buflen, const char * name, const uint8_t * digits )
63{
64    tr_snprintf( buf, buflen, "%s %d.%d.%d.%d", name,
65                 charint( digits[0] ),
66                 charint( digits[1] ),
67                 charint( digits[2] ),
68                 charint( digits[3] ) );
69}
70static void
71two_major_two_minor( char * buf, size_t buflen, const char * name, const uint8_t * digits )
72{
73    tr_snprintf( buf, buflen, "%s %d.%02d", name,
74                 strint( digits, 2 ),
75                 strint( digits+2, 2 ) );
76}
77static void
78no_version( char * buf, size_t buflen, const char * name )
79{
80    tr_strlcpy( buf, name, buflen );
81}
82
83static void
84mainline_style( char * buf, size_t buflen, const char * name, const uint8_t * id )
85{
86    if( id[4] == '-' && id[6] == '-' )
87        tr_snprintf( buf, buflen, "%s %c.%c.%c", name, id[1], id[3], id[5] );
88    else if( id[5] == '-' )
89        tr_snprintf( buf, buflen, "%s %c.%c%c.%c", name, id[1], id[3], id[4], id[6] );
90}
91
92static int
93isMainlineStyle( const uint8_t * peer_id )
94{
95    /**
96     * One of the following styles will be used:
97     *   Mx-y-z--
98     *   Mx-yy-z-
99     */ 
100    return peer_id[2]=='-'
101        && peer_id[7]=='-'
102        && ( peer_id[4]=='-' || peer_id[5]=='-' );
103}
104
105static int
106decodeBitCometClient( char * buf, size_t buflen, const uint8_t * id )
107{
108    int is_bitlord;
109    int major, minor;
110    const char * name;
111    const char * mod = NULL;
112
113    if( !memcmp( id, "exbc", 4 ) ) mod = "";
114    else if( !memcmp( id, "FUTB", 4 )) mod = "(Solidox Mod) ";
115    else if( !memcmp( id, "xUTB", 4 )) mod = "(Mod 2) ";
116    else return FALSE;
117
118    is_bitlord = !memcmp( id+6, "LORD", 4 );
119    name = (is_bitlord) ? "BitLord " : "BitComet ";
120    major = id[4];
121    minor = id[5];
122
123    /**
124     * Bitcomet, and older versions of BitLord, are of the form x.yy.
125     * Bitcoment 1.0 and onwards are of the form x.y.
126     */
127    if( is_bitlord && major>0 )
128        tr_snprintf( buf, buflen, "%s%s%d.%d", name, mod, major, minor );
129    else
130        tr_snprintf( buf, buflen, "%s%s%d.%02d", name, mod, major, minor );
131
132    return TRUE;
133}
134
135void
136tr_clientForId( char * buf, size_t buflen, const void * id_in )
137{
138    const uint8_t * id = id_in;
139
140    *buf = '\0';
141
142    if( !id )
143        return;
144   
145    /* Azureus-style */
146    if( id[0] == '-' && id[7] == '-' )
147    {
148        if( !memcmp( id+1, "UT", 2 ) )
149        {
150            tr_snprintf( buf, buflen, "\xc2\xb5Torrent %d.%d.%d%s",
151                         strint(id+3,1), strint(id+4,1), strint(id+5,1), getMnemonicEnd(id[6]) );
152        }
153
154        else if( !memcmp( id+1, "TR", 2 ) )
155        {
156            if( !memcmp( id+3, "000", 3 ) ) /* very old client style: -TR0006- is 0.6 */
157                tr_snprintf( buf, buflen, "Transmission 0.%c", id[6] );
158            else if( !memcmp( id+3, "00", 2) ) /* previous client style: -TR0072- is 0.72 */
159                tr_snprintf( buf, buflen, "Transmission 0.%02d", strint(id+5,2) );
160            else /* current client style: -TR111Z- is 1.11+ */
161                tr_snprintf( buf, buflen, "Transmission %d.%02d%s", strint(id+3,1), strint(id+4,2),
162                          id[6]=='Z' || id[6]=='X' ? "+" : "" );
163        }
164       
165        else if( !memcmp( id+1, "AZ", 2 ) )
166        {
167            if( id[3] > '3' || ( id[3] == '3' && id[4] >= '1' ) ) /* Vuze starts at version 3.1.0.0 */
168                four_digits( buf, buflen, "Vuze", id+3 );
169            else
170                four_digits( buf, buflen, "Azureus", id+3 );
171        }
172       
173        else if( !memcmp( id+1, "KT", 2 ) )
174        {
175            if( id[5] == 'D' )
176                tr_snprintf( buf, buflen, "KTorrent %d.%d Dev %d", charint(id[3]), charint(id[4]), charint(id[6]) );
177            else if( id[5] == 'R' )
178                tr_snprintf( buf, buflen, "KTorrent %d.%d RC %d", charint(id[3]), charint(id[4]), charint(id[6]) );
179            else
180                three_digits( buf, buflen, "KTorrent", id+3 );
181        }
182
183        else if( !memcmp( id+1, "AR", 2 ) ) four_digits( buf, buflen, "Ares", id+3 );
184        else if( !memcmp( id+1, "AT", 2 ) ) four_digits( buf, buflen, "Artemis", id+3 );
185        else if( !memcmp( id+1, "AV", 2 ) ) four_digits( buf, buflen, "Avicora", id+3 );
186        else if( !memcmp( id+1, "BG", 2 ) ) four_digits( buf, buflen, "BTGetit", id+3 );
187        else if( !memcmp( id+1, "BM", 2 ) ) four_digits( buf, buflen, "BitMagnet", id+3 );
188        else if( !memcmp( id+1, "BX", 2 ) ) four_digits( buf, buflen, "BittorrentX", id+3 );
189        else if( !memcmp( id+1, "bk", 2 ) ) four_digits( buf, buflen, "BitKitten (libtorrent)", id+3 );
190        else if( !memcmp( id+1, "BS", 2 ) ) four_digits( buf, buflen, "BTSlave", id+3 );
191        else if( !memcmp( id+1, "BX", 2 ) ) four_digits( buf, buflen, "BittorrentX", id+3 );
192        else if( !memcmp( id+1, "EB", 2 ) ) four_digits( buf, buflen, "EBit", id+3 );
193        else if( !memcmp( id+1, "DE", 2 ) ) four_digits( buf, buflen, "Deluge", id+3 );
194        else if( !memcmp( id+1, "DP", 2 ) ) four_digits( buf, buflen, "Propogate Data Client", id+3 );
195        else if( !memcmp( id+1, "FC", 2 ) ) four_digits( buf, buflen, "FileCroc", id+3 );
196        else if( !memcmp( id+1, "FT", 2 ) ) four_digits( buf, buflen, "FoxTorrent/RedSwoosh", id+3 );
197        else if( !memcmp( id+1, "GR", 2 ) ) four_digits( buf, buflen, "GetRight", id+3 );
198        else if( !memcmp( id+1, "HN", 2 ) ) four_digits( buf, buflen, "Hydranode", id+3 );
199        else if( !memcmp( id+1, "LH", 2 ) ) four_digits( buf, buflen, "LH-ABC", id+3 );
200        else if( !memcmp( id+1, "NX", 2 ) ) four_digits( buf, buflen, "Net Transport", id+3 );
201        else if( !memcmp( id+1, "MO", 2 ) ) four_digits( buf, buflen, "MonoTorrent", id+3 );
202        else if( !memcmp( id+1, "MR", 2 ) ) four_digits( buf, buflen, "Miro", id+3 );
203        else if( !memcmp( id+1, "MT", 2 ) ) four_digits( buf, buflen, "Moonlight", id+3 );
204        else if( !memcmp( id+1, "PD", 2 ) ) four_digits( buf, buflen, "Pando", id+3 );
205        else if( !memcmp( id+1, "RS", 2 ) ) four_digits( buf, buflen, "Rufus", id+3 );
206        else if( !memcmp( id+1, "RT", 2 ) ) four_digits( buf, buflen, "Retriever", id+3 );
207        else if( !memcmp( id+1, "SS", 2 ) ) four_digits( buf, buflen, "SwarmScope", id+3 );
208        else if( !memcmp( id+1, "SZ", 2 ) ) four_digits( buf, buflen, "Shareaza", id+3 );
209        else if( !memcmp( id+1, "S~", 2 ) ) four_digits( buf, buflen, "Shareaza", id+3 );
210        else if( !memcmp( id+1, "st", 2 ) ) four_digits( buf, buflen, "SharkTorrent", id+3 );
211        else if( !memcmp( id+1, "TN", 2 ) ) four_digits( buf, buflen, "Torrent .NET", id+3 );
212        else if( !memcmp( id+1, "TS", 2 ) ) four_digits( buf, buflen, "TorrentStorm", id+3 );
213        else if( !memcmp( id+1, "UL", 2 ) ) four_digits( buf, buflen, "uLeecher!", id+3 );
214        else if( !memcmp( id+1, "VG", 2 ) ) four_digits( buf, buflen, "Vagaa", id+3 );
215        else if( !memcmp( id+1, "WT", 2 ) ) four_digits( buf, buflen, "BitLet", id+3 );
216        else if( !memcmp( id+1, "WY", 2 ) ) four_digits( buf, buflen, "Wyzo", id+3 );
217        else if( !memcmp( id+1, "XL", 2 ) ) four_digits( buf, buflen, "Xunlei", id+3 );
218        else if( !memcmp( id+1, "XT", 2 ) ) four_digits( buf, buflen, "XanTorrent", id+3 );
219        else if( !memcmp( id+1, "ZT", 2 ) ) four_digits( buf, buflen, "Zip Torrent", id+3 );
220
221        else if( !memcmp( id+1, "AG", 2 ) ) three_digits( buf, buflen, "Ares", id+3 );
222        else if( !memcmp( id+1, "A~", 2 ) ) three_digits( buf, buflen, "Ares", id+3 );
223        else if( !memcmp( id+1, "ES", 2 ) ) three_digits( buf, buflen, "Electric Sheep", id+3 );
224        else if( !memcmp( id+1, "HL", 2 ) ) three_digits( buf, buflen, "Halite", id+3 );
225        else if( !memcmp( id+1, "LT", 2 ) ) three_digits( buf, buflen, "libtorrent (Rasterbar)", id+3 );
226        else if( !memcmp( id+1, "lt", 2 ) ) three_digits( buf, buflen, "libTorrent (Rakshasa)", id+3 );
227        else if( !memcmp( id+1, "MP", 2 ) ) three_digits( buf, buflen, "MooPolice", id+3 );
228        else if( !memcmp( id+1, "TT", 2 ) ) three_digits( buf, buflen, "TuoTu", id+3 );
229        else if( !memcmp( id+1, "qB", 2 ) ) three_digits( buf, buflen, "qBittorrent", id+3 );
230
231        else if( !memcmp( id+1, "AX", 2 ) ) two_major_two_minor( buf, buflen, "BitPump", id+3 );
232        else if( !memcmp( id+1, "BC", 2 ) ) two_major_two_minor( buf, buflen, "BitComet", id+3 );
233        else if( !memcmp( id+1, "CD", 2 ) ) two_major_two_minor( buf, buflen, "Enhanced CTorrent", id+3 );
234        else if( !memcmp( id+1, "LP", 2 ) ) two_major_two_minor( buf, buflen, "Lphant", id+3 );
235
236        else if( !memcmp( id+1, "BF", 2 ) ) no_version( buf, buflen, "BitFlu" );
237        else if( !memcmp( id+1, "LW", 2 ) ) no_version( buf, buflen, "LimeWire" );
238
239        else if( !memcmp( id+1, "BB", 2 ) )
240        {
241            tr_snprintf( buf, buflen, "BitBuddy %c.%c%c%c", id[3], id[4], id[5], id[6] );
242        }
243        else if( !memcmp( id+1, "BR", 2 ) )
244        {
245            tr_snprintf( buf, buflen, "BitRocket %c.%c (%c%c)", id[3], id[4], id[5], id[6] );
246        }
247        else if( !memcmp( id+1, "CT", 2 ) )
248        {
249            tr_snprintf( buf, buflen, "CTorrent %d.%d.%02d", charint(id[3]), charint(id[4]), strint(id+5,2) );
250        }
251        else if( !memcmp( id+1, "XX", 2 ) )
252        {
253            tr_snprintf( buf, buflen, "Xtorrent %d.%d (%d)", charint(id[3]), charint(id[4]), strint(id+5,2) );
254        }
255        else if( !memcmp( id+1, "BOW", 3 ) )
256        {
257                 if( !memcmp( &id[4], "A0B", 3 ) ) tr_snprintf( buf, buflen, "Bits on Wheels 1.0.5" );
258            else if( !memcmp( &id[4], "A0C", 3 ) ) tr_snprintf( buf, buflen, "Bits on Wheels 1.0.6" );
259            else                                   tr_snprintf( buf, buflen, "Bits on Wheels %c.%c.%c", id[4], id[5], id[5] );
260        }
261
262        if( *buf )
263            return;
264    }
265   
266    /* Shad0w-style */
267    if( !memcmp( &id[4], "----", 4 ) || !memcmp( &id[4], "--0", 3 ) )
268    {
269        switch( *id ) {
270            case 'A': three_digits( buf, buflen, "ABC", id+1 ); break;
271            case 'O': three_digits( buf, buflen, "Osprey", id+1 ); break;
272            case 'Q': three_digits( buf, buflen, "BTQueue", id+1 ); break;
273            case 'R': three_digits( buf, buflen, "Tribler", id+1 ); break;
274            case 'S': three_digits( buf, buflen, "Shad0w", id+1 ); break;
275            case 'T': three_digits( buf, buflen, "BitTornado", id+1 ); break;
276            default: break;
277        }
278        if( *buf ) return;
279    }
280
281    /* Mainline */
282    if( isMainlineStyle( id ) )
283    {
284        if( *id=='M' ) mainline_style( buf, buflen, "BitTorrent", id );
285        if( *id=='Q' ) mainline_style( buf, buflen, "Queen Bee", id );
286        if( *buf ) return;
287    }
288
289    if( decodeBitCometClient( buf, buflen, id ) )
290        return;
291
292    /* Clients with no version */
293         if( !memcmp( id, "AZ2500BT", 8 ) )  no_version( buf, buflen, "BitTyrant (Azureus Mod)" );
294    else if( !memcmp( id, "LIME", 4 ) )      no_version( buf, buflen, "Limewire" );
295    else if( !memcmp( id, "martini", 7 ) )   no_version( buf, buflen, "Martini Man" );
296    else if( !memcmp( id, "Pando", 5 ) )     no_version( buf, buflen, "Pando" );
297    else if( !memcmp( id, "a00---0", 7 ) )   no_version( buf, buflen, "Swarmy" );
298    else if( !memcmp( id, "a02---0", 7 ) )   no_version( buf, buflen, "Swarmy" );
299    else if( !memcmp( id, "-G3", 3 ) )       no_version( buf, buflen, "G3 Torrent" );
300    else if( !memcmp( id, "10-------", 9 ) ) no_version( buf, buflen, "JVtorrent" );
301    else if( !memcmp( id, "346-", 4 ) )      no_version( buf, buflen, "TorrentTopia" );
302    else if( !memcmp( id, "eX", 2 ) )        no_version( buf, buflen, "eXeem" );
303    else if( !memcmp( id, "-FG", 3 ) )       two_major_two_minor( buf, buflen, "FlashGet", id+3 );
304   
305    /* Everything else */ 
306    else if( !memcmp( id, "S3", 2 ) && id[2] == '-' && id[4] == '-' && id[6] == '-' )
307    {
308        tr_snprintf( buf, buflen, "Amazon S3 %c.%c.%c", id[3], id[5], id[7] );
309    }
310    else if( !memcmp( id, "OP", 2 ) )
311    {
312        tr_snprintf( buf, buflen, "Opera (Build %c%c%c%c)", id[2], id[3], id[4], id[5] );
313    }
314    else if( !memcmp( id, "-ML", 3 ) )
315    {
316        tr_snprintf( buf, buflen, "MLDonkey %c%c%c%c%c", id[3], id[4], id[5], id[6], id[7] );
317    }
318    else if( !memcmp( id, "DNA", 3 ) )
319    {
320        tr_snprintf( buf, buflen, "BitTorrent DNA %d.%d.%d", strint(id+3,2),
321                                                             strint(id+5,2),
322                                                             strint(id+7,2) );
323    }
324    else if( !memcmp( id, "Plus", 4 ) )
325    {
326        tr_snprintf( buf, buflen, "Plus! v2 %c.%c%c", id[4], id[5], id[6] );
327    }
328    else if( !memcmp( id, "XBT", 3 ) )
329    {
330        tr_snprintf( buf, buflen, "XBT Client %c.%c.%c%s", id[3], id[4], id[5], getMnemonicEnd(id[6]) );
331    }
332    else if( !memcmp( id, "Mbrst", 5 ) )
333    {
334        tr_snprintf( buf, buflen, "burst! %c.%c.%c", id[5], id[7], id[9] );
335    }
336    else if( !memcmp( id, "btpd", 4 ) )
337    {
338        tr_snprintf( buf, buflen, "BT Protocol Daemon %c%c%c", id[5], id[6], id[7] );
339    }
340    else if( !memcmp( id, "BLZ", 3 ) )
341    {
342        tr_snprintf( buf, buflen, "Blizzard Downloader %d.%d", id[3]+1, id[4] );
343    }
344    else if( '\0' == id[0] && !memcmp( &id[1], "BS", 2 ) )
345    {
346        tr_snprintf( buf, buflen, "BitSpirit %u", ( id[1] == 0 ? 1 : id[1] ) );
347    }
348
349    /* No match */
350    if( !*buf )
351    {
352        if( isprint( id[0] ) && isprint( id[1] ) && isprint( id[2] ) &&
353            isprint( id[3] ) && isprint( id[4] ) && isprint( id[5] ) &&
354            isprint( id[6] ) && isprint( id[7] ) )
355                tr_snprintf( buf, buflen, "%c%c%c%c%c%c%c%c",
356                             id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7] );
357        else
358                tr_snprintf( buf, buflen, "0x%02x%02x%02x%02x%02x%02x%02x%02x",
359                             id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7] );
360    }
361}
Note: See TracBrowser for help on using the repository browser.