예제 #1
0
    def test_metainfo_success(self):
        """Compare metainfo() output to torrent files generated by other software"""
        # List directories in DATA_DIR/files which will be used for this test. Matching
        # torrent files generated by another software must be found in DATA_DIR/torrent files/
        test_cases = ['single_file', 'multiple_files']

        for directory in test_cases:
            dirpath = os.path.join(DATA_DIR, 'files', directory)
            torrent_file = os.path.join(DATA_DIR, 'torrent_files', directory + '.torrent')

            with self.subTest(directory=directory):
                with open(torrent_file, "rb") as f:
                    m_target = bdecode(f.read())

                piece_length = m_target[b'info'][b'piece length']
                announce_list = [['http://example.com:8080/announce']]
                m_computed = metainfo(dirpath, piece_length, announce_list)

                if b'files' in m_target[b'info']:
                    info_keys = [b'files']
                else:
                    info_keys = [b'length']
                info_keys += [b'pieces']

                for key in info_keys:
                    self.assertEqual(m_computed[b'info'][key], m_target[b'info'][key])
예제 #2
0
 def test_Bdecode_failure(self):
     fail_cases = [
         # Invalid string lengths
         b"4:spa",
         b"2:spa"
         b"-1:x",
         b"-4:spam",
         b"0-4:spam",
         b"0:e",
         # Dictionary key must be a string
         b"di42e4:spame",
         # Dictionary with no terminating "e"
         b"d4:spami42e4:spomi43e",
         # Wrong key ordering
         b"d3:tow3:moo4:spam4:eggse",
         # Invalid integers
         b"i2Fe",
         b"ie",
         b"i42",
         b"i--23e",
         b"i1+1e",
         b"i1,2e",
         b"i1.2e",
         b"i1.0e",
         b"i1,0e",
         b"i-0e",
         b"i01e",
         # List with no terminating "e"
         b"li42ei43e"
     ]
     for testCase in fail_cases:
         with self.subTest(testCase=testCase):
             with self.assertRaises(ValueError,
                                    msg="case '{0}'".format(testCase)):
                 print(bdecode(testCase))
예제 #3
0
 async def _query_tracker(self, url: str) -> Iterator[Tuple[str, int]]:
     """Send the request to the tracker"""
     self._logger.debug("request: {}".format(url))
     async with aiohttp.ClientSession() as session:
         async with session.get(url) as response:
             if response.status != 200:
                 raise ConnectionError
             d = bdecode(await response.read())
             return map(decode_ipv4, split(d[b'peers'], 6))
예제 #4
0
 def test_bencode_bdecode(self):
     # Decode whole Torrent files
     torrent_dir = os.path.join(DATA_DIR, "torrent_files")
     for file in os.listdir(torrent_dir):
         filename = os.path.join(torrent_dir, os.fsdecode(file))
         with open(filename, "rb") as f:
             with self.subTest(filename=filename):
                 s = f.read()
                 self.assertEqual(s, bencode(bdecode(s)))
예제 #5
0
파일: torrent.py 프로젝트: techierishi/PyTo
    def _from_file(cls, torrent_file: str):
        """Create an instance of Torrent from a metainfo file"""
        with open(torrent_file, "rb") as f:
            m = bdecode(f.read())

        # TODO: check type of optional items
        if validate_structure(m, METAINFO_SINGLE_FILE):
            single_file_mode = True
        elif validate_structure(m, METAINFO_MULTIPLE_FILES):
            single_file_mode = False
        else:
            raise ValueError("Invalid torrent file")

        info = m[b'info']
        info_hash = sha1(bencode(info)).digest()
        if b'announce-list' in m:
            announce = m[b'announce-list']
        else:
            announce = [[m[b'announce']]]

        announce_decoded = []
        for trackers in announce:
            announce_decoded.append(list(map(lambda x: x.decode('utf-8'), trackers)))

        name = info[b'name'].decode("utf-8")
        hashes = split(info[b'pieces'], sha1().digest_size)
        piece_length = info[b'piece length']

        contents = []
        if single_file_mode:
            contents.append(("", sanitize(name), info[b"length"]))
        else:
            for file_dict in info[b'files']:
                path_str = [sanitize(b.decode("utf-8")) for b in file_dict[b'path']]
                directory = os.path.join("", *path_str[:-1])
                filename = path_str[-1]
                contents.append((directory, filename, file_dict[b'length']))

        return cls(announce_decoded, name, contents, info_hash, hashes, piece_length)
예제 #6
0
 def test_Bdecode_success(self):
     for (key, value) in validBEncodings.items():
         with self.subTest(case=key, expected=value, result=bdecode(key)):
             self.assertEqual(bdecode(key), value)