def test(peerid):
    client, version = ClientIdentifier.identify_client(peerid)
    try:
        try:
            out = peerid.encode('utf8')
        except:
            out = peerid.encode('ascii')
    except:
        out = repr(peerid)

    if client != 'unknown':
        print 'identified %s %s\t(from %s)' % (client.encode('utf8'),
                                               version, out)
    else:
        print 'failed:\t\t\t\t', out
def test(peerid):
    client, version = ClientIdentifier.identify_client(peerid)
    try:
        try:
            out = peerid.encode('utf8')
        except:
            out = peerid.encode('ascii')
    except:
        out = repr(peerid)

    if client != 'unknown':
        print 'identified %s %s\t(from %s)' % (client.encode('utf8'), version,
                                               out)
    else:
        print 'failed:\t\t\t\t', out
def run_tests():
    print 'running tests'
    for client, version, peerid in (
    #  0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16  17  18  19 
    ('BitTorrent', '3.4.2',
     '\x4D\x33\x2D\x34\x2D\x32\x2D\x2D\x34\x50\x77\x19\x9F\xAE\xC4\xA6\x73\xBE\xCA\x01'),
    ('BitTorrent (obsolete)', '',
     '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4C\x53\x44\x19\x33\x10\x42\x77'),
    ('Shareaza', '',
     '\x8A\x92\x36\xB1\x67\x33\x5B\xDA\xAF\xCC\x85\x34\x5D\x59\x49\xAA\x20\xDB\x6F\xEC'),
    ('Shareaza', '',
     '\x95\xAD\x85\x2D\x0A\x2C\x6B\xFD\x3C\x97\xEB\x23\x15\xE5\x68\x59\xCC\xC5\x60\x38'),
    ('Shareaza', '2.1.3.2',
     '\x2D\x53\x5A\x32\x31\x33\x32\x2D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'),
    ('ABC', '2.6.9',
     '\x41\x32\x36\x39\x2D\x2D\x2D\x2D\x34\x50\x77\x19\x9F\xAE\xC4\xA6\x73\xBE\xCA\x01'),
    ('BitComet', '0.56',
     '\x65\x78\x62\x63\x00\x38\x7A\x44\x63\x10\x2D\x6E\x9A\xD6\x72\x3B\x33\x9F\x35\xA9'),
    ('Azureus', '2.2.0.0',
     '\x2D\x41\x5A\x32\x32\x30\x30\x2D\x36\x77\x66\x47\x32\x77\x6B\x36\x77\x57\x4C\x63'),
    ('burst!', '1.1.3',
     '\x4D\x62\x72\x73\x74\x31\x2D\x31\x2D\x33\x61\x32\x30\x34\x38\x39\x33\x30\x33\x31'),
    ("Shadow's", '5.8.11',
     '\x53\x35\x38\x42\x2D\x2D\x2D\x2D\x2D\x7A\x78\x70\x70\x52\x4C\x4E\x48\x42\x6F\x35'),
    ('Experimental 3.2.1b2', '',
     '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x61\x61\xD2\x31\x4F\x4C\x62\xBA'),
    ('XanTorrent', '',
     '\x44\x61\x6E\x73\x43\x6C\x69\x65\x6E\x74\x20\x26\x4E\x2A\x12\x0B\xFB\xD1\xC4\x72'),
    ('XBT', '0.3.6',
     '\x58\x42\x54\x30\x33\x36\x2D\x2D\x61\x31\x6A\x71\x63\x71\x66\x53\x36\x44\x35\x66'),
    ('BitMagnet', '0.3.1',
     '\x00\x1f\x42\x4d\x64\x30\x63\x35\x34\x76\x34\x67\x33\x34\xf4\x3d\x98\x23\x06\x62'),
    ('eXeem beta', '0.10.0.0',
     '\x2D\x65\x58\x30\x41\x30\x30\x2D\x79\x4C\x72\x6A\x31\x6B\x48\x6A\x4C\x45\x33\x62'),
    ('eXeem beta', '0.12.0.0',
     '\x2D\x65\x58\x30\x43\x30\x30\x2D\x59\x4C\x29\x7A\x4E\x5A\x33\x7A\x30\x6E\x27\x73'),
    ('eXeem beta', '0.13.0.0',
     '\x2D\x65\x58\x30\x44\x30\x30\x2D\x67\x70\x21\x2E\x59\x52\x39\x50\x29\x45\x67\x45'),
    ('eXeem beta', '0.14.0.0',
     '\x2D\x65\x58\x30\x45\x30\x30\x2D\x6A\x49\x56\x45\x43\x6E\x76\x42\x68\x59\x51\x56'),
    ('BitBuddy', '0.9.6.1',
     '\x2D\x42\x42\x30\x39\x36\x31\x2D\x54\x42\x37\x6A\x4A\x5F\x67\x2D\x6F\x55\x47\x66'),
    ('TorrenTres 0.0.2', '',
     '\x58\x54\x4F\x52\x52\x33\x30\x32\x2D\xC8\xB2\x84\xCC\x6C\x0F\xD0\xFE\xCD\x46\x5B'),
    ('TorrentTopia 1.70', '',
     '\x33\x34\x36\x2D\x2D\x2D\x2D\x2D\x2D\x6E\x2E\x4B\x7A\x65\x46\x50\x30\x6E\x56\x68'),
    ('TurboBT', '5.0',
     '\x74\x75\x72\x62\x6F\x62\x74\x35\x2E\x30\x2E\x30\xD1\xA5\x27\xD4\x52\x0D\x7E\x3E'),
    ('BitSpirit', 'HTTPBT', #2.6.3, 2.7.3
     '\x00\x00\x00\x00\x00\x00\x00\x00\x70\x98\x28\xCC\x22\xB7\x48\x54\x54\x50\x42\x54'),
    ('BitSpirit', 'UDP0',
     '\x00\x1F\x42\x4D\x41\x6E\x6F\x6E\x2E\x27\xC2\x67\x9C\xC3\xA9\xF8\x55\x44\x50\x30'),
    ('BitSpirit v2', 'HTTPBT',
     '\x00\x02\x42\x53\x9B\x7E\xD3\xE0\x58\xA8\x38\x4A\xA7\x48\x48\x54\x54\x50\x42\x54'),
    ('BitSpirit v2', '',
     '\x00\x02\x42\x53\x07\x2A\xDB\x18\x34\x50\x77\x19\x9F\xAE\xC4\xA6\x73\xBE\xCA\x01'),
    ('Deadman', '',
     '\x44\x65\x61\x64\x6D\x61\x6E\x20\x57\x61\x6C\x6B\x69\x6E\x67\x2D\x36\x35\x5A\x56'),
    ('BTGetit', '0.7.0.8',
     '\x42\x47\x30\x37\x30\x38\x58\x01\xE8\xCA\x76\x5B\xA7\x8C\x7D\x0B\xBE\xCB\x3D\xB2'),
    ('eXeem', '',  # 2.1
     '\x65\x58\x64\x30\x63\x35\x34\x76\x34\x67\x33\x00\x00\x00\x00\x00\x00\x00\x00\x00'),
    ('Bits on Wheels', '0.3',
     '\x2D\x42\x4F\x57\x50\x30\x33\x2D\x30\x30\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36'),
    ('BitLord', '0.56',
     '\x65\x78\x62\x63\x00\x38\x4C\x4F\x52\x44\x32\x00\x04\x8E\xCE\xD5\x7B\xD7\x10\x28'),
    ('BitComet', '0.56',
     '\x65\x78\x62\x63\x00\x38\x2A\x8A\x6B\x37\x6D\x84\xBD\xCF\x82\x8C\x25\x9B\x07\x04'),
    ('CTorrent', '1.3.0.4',
     '\x2D\x43\x54\x31\x33\x30\x34\x2D\x9C\x74\x41\xCE\xD7\x3E\x6E\x98\x41\x1F\x67\xD7'),
    ('BitVampire 1.3.1', '', # (spoofs BitComet 0.54 with extra '---'),',
     '\x65\x78\x62\x63\x00\x36\x2D\x2D\x2D\x55\x21\xE5\xF0\x3A\x78\xC3\x3F\x54\x21\xF1'),
    ('Plus! II', 'RC 10',
     '\x50\x6C\x75\x73\x31\x32\x52\x31\x30\x2D\x66\x4E\x36\x6E\x69\x32\x41\x7A\x4F\x4B'),
    ('GreedBT 2.7.0', '',
     '\x32\x37\x30\x2D\x2D\x2D\x2D\x2D\x2D\x68\x34\x69\x66\x4B\x7A\x4B\x6E\x4A\x4F\x50'),
    ('BitTornado', '0.3.10',
     '\x54\x30\x33\x41\x2D\x2D\x2D\x2D\x2D\x63\x51\x37\x4B\x58\x48\x42\x4E\x73\x32\x64'),
    ('BitComet', '0.57',
     '\x65\x78\x62\x63\x00\x39\x2A\x8A\x6B\x37\x6D\x84\xBD\xCF\x82\x8C\x25\x9B\x07\x04'),
    ('ZipTorrent', '1.2.1.0',
     '\x2D\x5A\x54\x31\x32\x31\x30\x2D\x6C\x61\x42\x7A\x46\x38\x37\x35\x38\x54\x61\x79'),
    ('Azureus 2.0.3.2', '',
     '\x2D\x2D\x2D\x2D\x2D\x41\x7A\x75\x72\x65\x75\x73\x54\x69\x4E\x7A\x2A\x64\x54\xA7'),
    ('Rufus', '0.6.5',
     '\x00\x41\x52\x53\x64\x30\x63\x35\x34\x76\x34\x67\x33\xf0\x9a\x46\xca\xa0\x65\x95'),
    ('Rufus Anonymous', '0.6.5',
     '\x00\x41\x52\x53\x41\x6e\x6f\x6e\x79\x6d\x6f\x75\x73\x6d\x72\x25\x16\x95\x03\x33'),
    ('PO (unknown)', '0.0.0.1',
     '\x2D\x50\x4F\x30\x30\x30\x31\x2D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'),
    ('UR (unknown)', '0.1.1.2',
     '\x2D\x55\x52\x30\x31\x31\x32\x2D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'),
    ('Opera', '7685', 
     'OP7685f2c1495b1680bf'),
    ('KTorrent', '1.1 RC 1',
     '-KT11R1-693649213030'),
    ):
        id_client, id_version = ClientIdentifier.identify_client(peerid)
        show = False
        if id_client != client:
            show = True
            print client, 'misidentified as', id_client, '\t', 
        if id_version != version:
            show = True
            print version, 'misidentified as', id_version,
        if show:
            print 
            print '  based on', peerid
def run_tests():
    print 'running tests'
    for client, version, peerid in (
            #  0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16  17  18  19
        ('BitTorrent', '3.4.2',
         '\x4D\x33\x2D\x34\x2D\x32\x2D\x2D\x34\x50\x77\x19\x9F\xAE\xC4\xA6\x73\xBE\xCA\x01'
         ),
        ('BitTorrent (obsolete)', '',
         '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4C\x53\x44\x19\x33\x10\x42\x77'
         ),
        ('Shareaza', '',
         '\x8A\x92\x36\xB1\x67\x33\x5B\xDA\xAF\xCC\x85\x34\x5D\x59\x49\xAA\x20\xDB\x6F\xEC'
         ),
        ('Shareaza', '',
         '\x95\xAD\x85\x2D\x0A\x2C\x6B\xFD\x3C\x97\xEB\x23\x15\xE5\x68\x59\xCC\xC5\x60\x38'
         ),
        ('Shareaza', '2.1.3.2',
         '\x2D\x53\x5A\x32\x31\x33\x32\x2D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
         ),
        ('ABC', '2.6.9',
         '\x41\x32\x36\x39\x2D\x2D\x2D\x2D\x34\x50\x77\x19\x9F\xAE\xC4\xA6\x73\xBE\xCA\x01'
         ),
        ('BitComet', '0.56',
         '\x65\x78\x62\x63\x00\x38\x7A\x44\x63\x10\x2D\x6E\x9A\xD6\x72\x3B\x33\x9F\x35\xA9'
         ),
        ('Azureus', '2.2.0.0',
         '\x2D\x41\x5A\x32\x32\x30\x30\x2D\x36\x77\x66\x47\x32\x77\x6B\x36\x77\x57\x4C\x63'
         ),
        ('burst!', '1.1.3',
         '\x4D\x62\x72\x73\x74\x31\x2D\x31\x2D\x33\x61\x32\x30\x34\x38\x39\x33\x30\x33\x31'
         ),
        ("Shadow's", '5.8.11',
         '\x53\x35\x38\x42\x2D\x2D\x2D\x2D\x2D\x7A\x78\x70\x70\x52\x4C\x4E\x48\x42\x6F\x35'
         ),
        ('Experimental 3.2.1b2', '',
         '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x61\x61\xD2\x31\x4F\x4C\x62\xBA'
         ),
        ('XanTorrent', '',
         '\x44\x61\x6E\x73\x43\x6C\x69\x65\x6E\x74\x20\x26\x4E\x2A\x12\x0B\xFB\xD1\xC4\x72'
         ),
        ('XBT', '0.3.6',
         '\x58\x42\x54\x30\x33\x36\x2D\x2D\x61\x31\x6A\x71\x63\x71\x66\x53\x36\x44\x35\x66'
         ),
        ('BitMagnet', '0.3.1',
         '\x00\x1f\x42\x4d\x64\x30\x63\x35\x34\x76\x34\x67\x33\x34\xf4\x3d\x98\x23\x06\x62'
         ),
        ('eXeem beta', '0.10.0.0',
         '\x2D\x65\x58\x30\x41\x30\x30\x2D\x79\x4C\x72\x6A\x31\x6B\x48\x6A\x4C\x45\x33\x62'
         ),
        ('eXeem beta', '0.12.0.0',
         '\x2D\x65\x58\x30\x43\x30\x30\x2D\x59\x4C\x29\x7A\x4E\x5A\x33\x7A\x30\x6E\x27\x73'
         ),
        ('eXeem beta', '0.13.0.0',
         '\x2D\x65\x58\x30\x44\x30\x30\x2D\x67\x70\x21\x2E\x59\x52\x39\x50\x29\x45\x67\x45'
         ),
        ('eXeem beta', '0.14.0.0',
         '\x2D\x65\x58\x30\x45\x30\x30\x2D\x6A\x49\x56\x45\x43\x6E\x76\x42\x68\x59\x51\x56'
         ),
        ('BitBuddy', '0.9.6.1',
         '\x2D\x42\x42\x30\x39\x36\x31\x2D\x54\x42\x37\x6A\x4A\x5F\x67\x2D\x6F\x55\x47\x66'
         ),
        ('TorrenTres 0.0.2', '',
         '\x58\x54\x4F\x52\x52\x33\x30\x32\x2D\xC8\xB2\x84\xCC\x6C\x0F\xD0\xFE\xCD\x46\x5B'
         ),
        ('TorrentTopia 1.70', '',
         '\x33\x34\x36\x2D\x2D\x2D\x2D\x2D\x2D\x6E\x2E\x4B\x7A\x65\x46\x50\x30\x6E\x56\x68'
         ),
        ('TurboBT', '5.0',
         '\x74\x75\x72\x62\x6F\x62\x74\x35\x2E\x30\x2E\x30\xD1\xA5\x27\xD4\x52\x0D\x7E\x3E'
         ),
        (
            'BitSpirit',
            'HTTPBT',  #2.6.3, 2.7.3
            '\x00\x00\x00\x00\x00\x00\x00\x00\x70\x98\x28\xCC\x22\xB7\x48\x54\x54\x50\x42\x54'
        ),
        ('BitSpirit', 'UDP0',
         '\x00\x1F\x42\x4D\x41\x6E\x6F\x6E\x2E\x27\xC2\x67\x9C\xC3\xA9\xF8\x55\x44\x50\x30'
         ),
        ('BitSpirit v2', 'HTTPBT',
         '\x00\x02\x42\x53\x9B\x7E\xD3\xE0\x58\xA8\x38\x4A\xA7\x48\x48\x54\x54\x50\x42\x54'
         ),
        ('BitSpirit v2', '',
         '\x00\x02\x42\x53\x07\x2A\xDB\x18\x34\x50\x77\x19\x9F\xAE\xC4\xA6\x73\xBE\xCA\x01'
         ),
        ('Deadman', '',
         '\x44\x65\x61\x64\x6D\x61\x6E\x20\x57\x61\x6C\x6B\x69\x6E\x67\x2D\x36\x35\x5A\x56'
         ),
        ('BTGetit', '0.7.0.8',
         '\x42\x47\x30\x37\x30\x38\x58\x01\xE8\xCA\x76\x5B\xA7\x8C\x7D\x0B\xBE\xCB\x3D\xB2'
         ),
        (
            'eXeem',
            '',  # 2.1
            '\x65\x58\x64\x30\x63\x35\x34\x76\x34\x67\x33\x00\x00\x00\x00\x00\x00\x00\x00\x00'
        ),
        ('Bits on Wheels', '0.3',
         '\x2D\x42\x4F\x57\x50\x30\x33\x2D\x30\x30\x36\x36\x36\x36\x36\x36\x36\x36\x36\x36'
         ),
        ('BitLord', '0.56',
         '\x65\x78\x62\x63\x00\x38\x4C\x4F\x52\x44\x32\x00\x04\x8E\xCE\xD5\x7B\xD7\x10\x28'
         ),
        ('BitComet', '0.56',
         '\x65\x78\x62\x63\x00\x38\x2A\x8A\x6B\x37\x6D\x84\xBD\xCF\x82\x8C\x25\x9B\x07\x04'
         ),
        ('CTorrent', '1.3.0.4',
         '\x2D\x43\x54\x31\x33\x30\x34\x2D\x9C\x74\x41\xCE\xD7\x3E\x6E\x98\x41\x1F\x67\xD7'
         ),
        (
            'BitVampire 1.3.1',
            '',  # (spoofs BitComet 0.54 with extra '---'),',
            '\x65\x78\x62\x63\x00\x36\x2D\x2D\x2D\x55\x21\xE5\xF0\x3A\x78\xC3\x3F\x54\x21\xF1'
        ),
        ('Plus! II', 'RC 10',
         '\x50\x6C\x75\x73\x31\x32\x52\x31\x30\x2D\x66\x4E\x36\x6E\x69\x32\x41\x7A\x4F\x4B'
         ),
        ('GreedBT 2.7.0', '',
         '\x32\x37\x30\x2D\x2D\x2D\x2D\x2D\x2D\x68\x34\x69\x66\x4B\x7A\x4B\x6E\x4A\x4F\x50'
         ),
        ('BitTornado', '0.3.10',
         '\x54\x30\x33\x41\x2D\x2D\x2D\x2D\x2D\x63\x51\x37\x4B\x58\x48\x42\x4E\x73\x32\x64'
         ),
        ('BitComet', '0.57',
         '\x65\x78\x62\x63\x00\x39\x2A\x8A\x6B\x37\x6D\x84\xBD\xCF\x82\x8C\x25\x9B\x07\x04'
         ),
        ('ZipTorrent', '1.2.1.0',
         '\x2D\x5A\x54\x31\x32\x31\x30\x2D\x6C\x61\x42\x7A\x46\x38\x37\x35\x38\x54\x61\x79'
         ),
        ('Azureus 2.0.3.2', '',
         '\x2D\x2D\x2D\x2D\x2D\x41\x7A\x75\x72\x65\x75\x73\x54\x69\x4E\x7A\x2A\x64\x54\xA7'
         ),
        ('Rufus', '0.6.5',
         '\x00\x41\x52\x53\x64\x30\x63\x35\x34\x76\x34\x67\x33\xf0\x9a\x46\xca\xa0\x65\x95'
         ),
        ('Rufus Anonymous', '0.6.5',
         '\x00\x41\x52\x53\x41\x6e\x6f\x6e\x79\x6d\x6f\x75\x73\x6d\x72\x25\x16\x95\x03\x33'
         ),
        ('PO (unknown)', '0.0.0.1',
         '\x2D\x50\x4F\x30\x30\x30\x31\x2D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
         ),
        ('UR (unknown)', '0.1.1.2',
         '\x2D\x55\x52\x30\x31\x31\x32\x2D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
         ),
        ('Opera', '7685', 'OP7685f2c1495b1680bf'),
        ('KTorrent', '1.1 RC 1', '-KT11R1-693649213030'),
    ):
        id_client, id_version = ClientIdentifier.identify_client(peerid)
        show = False
        if id_client != client:
            show = True
            print client, 'misidentified as', id_client, '\t',
        if id_version != version:
            show = True
            print version, 'misidentified as', id_version,
        if show:
            print
            print '  based on', peerid