From aa0d32f4b675e155e6e004604bf8b6ee4e607873 Mon Sep 17 00:00:00 2001 From: Sebastian Hahn Date: Tue, 11 Aug 2009 13:43:06 +0200 Subject: Add ability to create .torrent metadata when making a package Also update the spec with the information where the .torrent metadata file will be stored. --- lib/thandy/SignerCLI.py | 14 +++++++++ lib/thandy/bt_compat.py | 76 +++++++++++++++++++++++++++++++++++++++++++++++ lib/thandy/master_keys.py | 3 ++ 3 files changed, 93 insertions(+) create mode 100644 lib/thandy/bt_compat.py (limited to 'lib/thandy') diff --git a/lib/thandy/SignerCLI.py b/lib/thandy/SignerCLI.py index d0feef6..06536aa 100644 --- a/lib/thandy/SignerCLI.py +++ b/lib/thandy/SignerCLI.py @@ -7,6 +7,7 @@ import sys import thandy.keys import thandy.formats import thandy.util +import thandy.bt_compat json = thandy.util.importJSON() @@ -78,6 +79,19 @@ def makepackage(args): f = open(location, 'w') json.dump(signable, f, indent=1, sort_keys=True) f.close() + btcomp = thandy.bt_compat.BtCompat() + # If we have bittorrent support, we always create the appropriate metadata. + thandy.bt_compat.BtCompat.setUseBt(True) + if not thandy.bt_compat.BtCompat.shouldUseBt(): + print "Not generating BitTorrent metadata files" + return + print "Generating BitTorrent metadata file" + metaFile = btcomp.makeMetaFile(dataFile) + mfLocation = os.path.split(btcomp.getBtMetadataLocation(location, dataFile))[-1] + print "Writing BitTorrent Metadata file to %s"%mfLocation + f = open(mfLocation, 'w') + f.write(metaFile) + f.close() def makebundle(args): options, args = getopt.getopt(args, "", "keyid=") diff --git a/lib/thandy/bt_compat.py b/lib/thandy/bt_compat.py new file mode 100644 index 0000000..43cecad --- /dev/null +++ b/lib/thandy/bt_compat.py @@ -0,0 +1,76 @@ +# Copyright 2008 The Tor Project, Inc. See LICENSE for licensing information. + +import os.path +import time + +import thandy.master_keys + +no_bt = None +try: + import BitTorrent.bencode + import BitTorrent.btformats + import BitTorrent.download +except ImportError: + no_bt = True +from sha import sha # XXX Use PyCrypto here? + + +class BtCompat: + """Interface for different bittorrent implementations""" + + usingBt = False + + def __init__(self): + self.tUrl = thandy.master_keys.DEFAULT_TRACKER + if not no_bt: + assert(self.tUrl is not None and self.tUrl != "") + self.pieceLength = 2 ** 18 # Piece length of 262144 bytes + + # XXX Do we need to be thread-safe here and below? + @staticmethod + def shouldUseBt(): + return BtCompat.usingBt + + @staticmethod + def setUseBt(useBt): + if no_bt: + return + BtCompat.usingBt = useBt + + @staticmethod + def getBtMetadataLocation(packagepath, filepath, pathprefix=""): + """Given a path for the package, the path for a file of that + package, and an optional prefix, return the path for the + .torrent metadata file. Always return Unix-like paths, to + ensure compatibility with fetching the path from a + webserver. + """ + return (os.path.join(pathprefix, os.path.dirname(packagepath), + os.path.basename(filepath)) + ".torrent" + ).replace("\\", "/") + + def makeMetaFile(self, file): + """Given a path to a file, create the contents of a .torrent + metadata file and return them. + """ + size = os.path.getsize(file) + filename = os.path.basename(file) + pieces = [] + p = 0 + h = open(file, 'rb') + while p < size: + x = h.read(min(self.pieceLength, size - p)) + pieces.append(sha(x).digest()) + p += self.pieceLength + if p > size: + p = size + h.close() + info = {'pieces': ''.join(pieces), + 'piece length': self.pieceLength, 'length': size, + 'name': filename} + # Check we didn't screw up with the info + BitTorrent.btformats.check_info(info) + data = {'info': info, 'announce': self.tUrl, + 'creation date': long(time.time())} + return BitTorrent.bencode.bencode(data) + diff --git a/lib/thandy/master_keys.py b/lib/thandy/master_keys.py index 05c50a8..be13f52 100644 --- a/lib/thandy/master_keys.py +++ b/lib/thandy/master_keys.py @@ -17,3 +17,6 @@ DEFAULT_MIRRORLIST = { } ], } + +DEFAULT_TRACKER = NONE + -- cgit v1.2.3