def isSameTorrent(torrent1src, torrent2src): """ Compare two torrents to see if they are the same """ # Same location if torrent1src == torrent2src: return True metainfo1 = get_metainfo(torrent1src) if metainfo1 is None: return False metainfo2 = get_metainfo(torrent2src) if metainfo2 is None: return False metainfo_hash1 = sha1(bencode(metainfo1)).hexdigest() metainfo_hash2 = sha1(bencode(metainfo2)).hexdigest() # Hash values for both torrents are the same if metainfo_hash1 == metainfo_hash2: return True return False
def check_allowed(self, infohash, paramslist): if ( self.aggregator_key is not None and not ( paramslist.has_key('password') and paramslist['password'][0] == self.aggregator_key ) ): return (200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, bencode({'failure reason': 'Requested download is not authorized for use with this tracker.'})) if self.allowed is not None: if not self.allowed.has_key(infohash): return (200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, bencode({'failure reason': 'Requested download is not authorized for use with this tracker.'})) if self.config['allowed_controls']: if self.allowed[infohash].has_key('failure reason'): return (200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, bencode({'failure reason': self.allowed[infohash]['failure reason']})) if paramslist.has_key('tracker'): if ( self.config['multitracker_allowed'] == 'none' or # turned off paramslist['peer_id'][0] == self.trackerid ): # oops! contacted myself return (200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, bencode({'failure reason': 'disallowed'})) if ( self.config['multitracker_allowed'] == 'autodetect' and not self.allowed[infohash].has_key('multitracker') ): return (200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, bencode({'failure reason': 'Requested download is not authorized for multitracker use.'})) return None
def get_scrape(self, paramslist): fs = {} if 'info_hash' in paramslist: if self.config['scrape_allowed'] not in ['specific', 'full']: return (400, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, bencode({'failure reason': 'specific scrape function ' 'is not available with this tracker.'})) for hash in paramslist['info_hash']: if self.allowed is not None: if hash in self.allowed: fs[hash] = self.scrapedata(hash) elif hash in self.downloads: fs[hash] = self.scrapedata(hash) else: if self.config['scrape_allowed'] != 'full': return (400, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, bencode({'failure reason': 'full scrape function is ' 'not available with this tracker.'})) if self.allowed is not None: keys = self.allowed.iterkeys() else: keys = self.downloads.iterkeys() for hash in keys: fs[hash] = self.scrapedata(hash) return (200, 'OK', {'Content-Type': 'text/plain'}, bencode({'files': fs}))
def natcheckOK(self, infohash, peerid, ip, port, peer): seed = not peer['left'] bc = self.becache.setdefault(infohash, self.cache_default) cp = compact_peer_info(ip, port) reqc = peer['requirecrypto'] bc[2][seed][peerid] = (cp, chr(reqc)) if peer['supportcrypto']: bc[1][seed][peerid] = cp if not reqc: bc[0][seed][peerid] = cp if not self.config['compact_reqd']: bc[3][seed][peerid] = Bencached( bencode({'ip': ip, 'port': port, 'peer id': peerid})) bc[4][seed][peerid] = Bencached( bencode({'ip': ip, 'port': port}))
def writeSrc(self, torrentName): torrentsrc = os.path.join(utility.getConfigPath(), "torrent", torrentName) h = open(torrentsrc, 'wb') h.write(bencode(self.metainfo)) h.close() self.src = torrentsrc return self.src
def ValueToString(self, value, type): if type == "boolean": if value: text = "1" else: text = "0" elif type == "color": red = str(value.Red()) while len(red) < 3: red = "0" + red green = str(value.Green()) while len(green) < 3: green = "0" + green blue = str(value.Blue()) while len(blue) < 3: blue = "0" + blue text = str(red) + str(green) + str(blue) elif type.startswith("bencode"): text = bencode(value) else: text = str(value) return text
def render(self, context): context['info'] = {'leechers': 0, 'seeds': 0, 'downloaded': 0} if not context.has_key('torrent'): return '' from BitTornado.bencode import bdecode, bencode from sha import sha from urllib2 import URLError, urlopen fn = os.path.join(MEDIA_ROOT, 'torrents', context['torrent']) if not os.path.exists(fn): return '' try: f = open(fn, 'rb') meta = bdecode(f.read())['info'] meta = sha(bencode(meta)).digest() f.close() except (IOError, ValueError, KeyError): return '' try: f = urlopen(SCRAPE_URL) except URLError: return '' m = bdecode(f.read()) f.close() if not m.has_key('files'): return '' m = m['files'] if m.has_key(meta): m = m[meta] context['info']['seeds'], context['info']['leechers'], context['info']['downloaded'] = m['complete'], m['incomplete'], m['downloaded'] return ''
def save_thost(self, x): if not self.annCtl.GetValue(): dlg = wxMessageDialog(self.frame, message = 'You must specify a\nsingle tracker url', caption = 'Error', style = wxOK | wxICON_ERROR) dlg.ShowModal() dlg.Destroy() return try: metainfo = {} metainfo['announce'] = self.annCtl.GetValue() annlist = self.getannouncelist() if len(annlist)>0: warnings = '' for tier in annlist: if len(tier) > 1: warnings += ( 'WARNING: You should not specify multiple trackers\n' + ' on the same line of the tracker list unless\n' + ' you are certain they share peer data.\n') break if not self.annCtl.GetValue() in annlist[0]: warnings += ( 'WARNING: The single tracker url is not present in\n' + ' the first line of the tracker list. This\n' + ' may produce a dysfunctional torrent.\n') if warnings: warnings += ('Are you sure you wish to save a torrent host\n' + 'with these parameters?') dlg = wxMessageDialog(self.frame, message = warnings, caption = 'Warning', style = wxYES_NO | wxICON_QUESTION) if dlg.ShowModal() != wxID_YES: dlg.Destroy() return metainfo['announce-list'] = annlist metainfo = bencode(metainfo) except: return if self.thostselectnum: d = self.thostselection else: d = '.thost' dl = wxFileDialog (self.frame, 'Save tracker data as', join(basepath,'thosts'), d, '*.thost', wxSAVE|wxOVERWRITE_PROMPT) if dl.ShowModal() != wxID_OK: return d = dl.GetPath() try: f = open(d,'wb') f.write(metainfo) f.close() garbage, self.thostselection = os.path.split(d) except: pass self.refresh_thostlist()
def write(self, target, tracker, **params): """Write a .torrent file Parameters str target - target file name (full path) str tracker - URL of tracker Optional parameters str comment - comment to include in file str announce_list - unparsed announce list str[][] real_announce_list - hierarchical announce list str httpseeds - unparsed http seed list str[] real_httpseeds - list of http seeds """ # Whatever hash we have left, we'll add on to the end excess = [] if self.done > 0: excess.append(self.sh.digest()) info = { 'pieces': ''.join(self.pieces + excess), 'piece length': self.piece_length, 'name': self.name } # If there is only one file and it has the same name path as the # torrent name, then encode directly, not as a files dictionary if len(self.fs) == 1 and self.fs[0]['path'] == []: info['length'] = self.size else: info['files'] = self.fs check_info(info) data = {'info': info, 'announce': tracker, 'creation date': long(0)} # Optional data dictionary contents if params.has_key('comment') and params['comment']: data['comment'] = params['comment'] if params.has_key('real_announce_list'): data['announce-list'] = params['real_announce_list'] elif params.has_key('announce_list') and params['announce_list']: l = [] for tier in params['announce_list'].split('|'): l.append(tier.split(',')) data['announce-list'] = l if params.has_key('real_httpseeds'): data['httpseeds'] = params['real_httpseeds'] elif params.has_key('httpseeds') and params['httpseeds']: data['httpseeds'] = params['httpseeds'].split('|') # Write file h = open(target, 'wb') h.write(bencode(data)) h.close()
def get(self, *args): # Get Action params = self.request.parameters() action = params.get('action') # Invalid Action if not action or isinstance(action, list): self.response.out.write(bencode({"error": "Invalid action"})) # Quit LH-ABC elif action == "quit": utility.webserver.command(action, params) utility.webserver.stop() # Close WebServer elif action == "close": utility.webserver.stop() # Other command else: response = utility.webserver.command(action, params) self.response.out.write(bencode(to_utf8(response)))
def __init__(self, src = None, dest = None, forceasklocation = False, caller = ""): self.src = src # List values self.list = utility.window.list self.listbitmap = 0 # Meta data if self.src.startswith(MAGNET_PREFIX): self.metainfo = FakeMetaData(self.src) self.infohash = getHash(self.src, asHex = True) self.src = self.src[len(MAGNET_PREFIX):] self.info = self.metainfo['info'] self.rawinfo = "" self.hasMetadata = False else: self.metainfo = self.getResponse(force=True) if self.metainfo: self.infohash = sha1(bencode(self.metainfo['info'])).hexdigest() self.info = self.metainfo['info'] self.rawinfo = bencode(self.metainfo['info']) self.hasMetadata = True if self.metainfo is None: return # Tracker List if 'announce-list' in self.metainfo: self.originalTrackers = self.metainfo['announce-list'] elif 'announce' in self.metainfo: self.originalTrackers = [[self.metainfo['announce']]] else: self.originalTrackers = [] self.trackerlist = self.originalTrackers # Torrent Handlers self.torrentconfig = TorrentConfig(self) self.status = TorrentStatus(self) self.actions = TorrentActions(self) self.dialogs = TorrentDialogs(self) self.connection = TorrentConnections(self) # Info section self.InitializeInfo() self.files.setupDest(dest, forceasklocation, caller)
def write(self, target, tracker, **params): """Write a .torrent file Parameters str target - target file name (full path) str tracker - URL of tracker Optional parameters str comment - comment to include in file str announce_list - unparsed announce list str[][] real_announce_list - hierarchical announce list str httpseeds - unparsed http seed list str[] real_httpseeds - list of http seeds """ # Whatever hash we have left, we'll add on to the end excess = [] if self.done > 0: excess.append(self.sh.digest()) info = {'pieces': ''.join(self.pieces + excess), 'piece length': self.piece_length, 'name': self.name} # If there is only one file and it has the same name path as the # torrent name, then encode directly, not as a files dictionary if len(self.fs) == 1 and self.fs[0]['path'] == []: info['length'] = self.size else: info['files'] = self.fs check_info(info) data = {'info': info, 'announce': tracker, 'creation date': long(0)} # Optional data dictionary contents if params.has_key('comment') and params['comment']: data['comment'] = params['comment'] if params.has_key('real_announce_list'): data['announce-list'] = params['real_announce_list'] elif params.has_key('announce_list') and params['announce_list']: l = [] for tier in params['announce_list'].split('|'): l.append(tier.split(',')) data['announce-list'] = l if params.has_key('real_httpseeds'): data['httpseeds'] = params['real_httpseeds'] elif params.has_key('httpseeds') and params['httpseeds']: data['httpseeds'] = params['httpseeds'].split('|') # Write file h = open(target, 'wb') h.write(bencode(data)) h.close()
def get(self, *args): # Get page params = self.request.parameters() page = params.get('page') if page is None: page = "main" # Invalid page if not page or isinstance(page, list): self.response.out.write(bencode({"error": "Invalid page"})) # Main Page elif page == "main": s = self.response.out # head s.write('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n' \ '<html><head><title>LH-ABC Web Service</title>\n') s.write('</head>\n<body>\n' \ '<h3>LH-ABC Web Service</h3>\n'\ '<ul>\n' '<li><strong>Web Service Version:</strong> 5.0</li>\n\n') s.write(form) # query query = utility.webserver.command("query", {}) s.write('<table summary="transfers" border="1">\n') # columns s.write('<tr>') for column in query['columns']: s.write('<th>%s</th>' %(column)) s.write('<th>infohash</th>') s.write('</tr>\n') # table for torrent_hash in query['torrents']: s.write('<tr>') for val in query['torrents'][torrent_hash]: s.write('<td>%s</td>' % (val or "---")) s.write('<td><code>%s</code></td>' % (torrent_hash)) s.write('</tr>\n') # Unknown page else: self.response.out.write(bencode({"error": "Unknown page"}))
def isSameTorrent(self, torrent1src, torrent2src): # Same location if torrent1src == torrent2src: return True metainfo1 = self.utility.getMetainfo(torrent1src) if metainfo1 is None: return False metainfo2 = self.utility.getMetainfo(torrent2src) if metainfo2 is None: return False metainfo_hash1 = sha(bencode(metainfo1)).hexdigest() metainfo_hash2 = sha(bencode(metainfo2)).hexdigest() # Hash values for both torrents are the same if metainfo_hash1 == metainfo_hash2: return True return False
def hashcheck_callback(self): self.checking = False if self.is_dead(): self._shutdown() return if not self.d.startEngine(rawinfo = bencode(self.response['info']), ratelimiter = self.controller.ratelimiter): self._shutdown() return self.d.startRerequester() self.statsfunc = self.d.startStats() self.rawserver.start_listening(self.d.getPortHandler()) self.working = True
def check_allowed(self, infohash, paramslist): if self.aggregator_key is not None and not ( 'password' in paramslist and paramslist['password'][0] == self.aggregator_key): return (200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, bencode({'failure reason': 'Requested download is not ' 'authorized for use with this tracker.'})) if self.allowed is not None: if infohash not in self.allowed: return (200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, bencode({'failure reason': 'Requested download is not ' 'authorized for use with this tracker.'})) if self.config['allowed_controls']: if 'failure reason' in self.allowed[infohash]: return ( 200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, bencode({'failure reason': self.allowed[infohash]['failure reason']})) if 'tracker' in paramslist: # turned off or contacted self if self.config['multitracker_allowed'] == 'none' or \ paramslist['peer_id'][0] == self.trackerid: return (200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, bencode({'failure reason': 'disallowed'})) if self.config['multitracker_allowed'] == 'autodetect' and \ 'announce-list' not in self.allowed[infohash]: return (200, 'Not Authorized', {'Content-Type': 'text/plain', 'Pragma': 'no-cache'}, bencode({'failure reason': 'Requested download is not ' 'authorized for multitracker use.'})) return None
def write_metadata_packet(self, mType, piece): """ write a metadata packet """ msg = {"msg_type": mType, "piece": piece} metadata = "" if mType == 1: msg["total_size"] = len(self.rawmetadata) offset = piece * 16 * 1024 metadata_piece_size = min(len(self.rawmetadata) - offset, 16 * 1024) metadata = self.rawmetadata[offset:offset+metadata_piece_size] elif mType == 0: self.requested_metadata[piece] += 1 msg = bencode(msg) msg += metadata return msg
def AddTorrentFromMetainfo(self, metainfo, filename = None, dest = None, caller="", label = None): """ Given metainfo for a torrent, add it to the list """ try: info_filename = metainfo["info"]["name"] + ".torrent" except KeyError: # Unable to get the "name" attribute from the .torrent # looks like the file is likely invalid # No name in the torrent file errormsg = _('Failed : Invalid torrent file') + ":" + \ "\n" + \ _('Torrent file contains no \'name\'') if caller not in ["web", "command"]: dialog = wx.MessageDialog(None, errormsg, _('Error'), wx.ICON_ERROR) dialog.ShowModal() dialog.Destroy() return False, errormsg, None if not filename: # Try getting the filename from the torrent filename = info_filename if type(filename) is not unicode: filename = unicode(filename, sys.getfilesystemencoding()) torrentsrc = os.path.join(utility.getConfigPath(), "torrent", filename) fileexists = os.access(torrentsrc, os.R_OK) if not fileexists: f = open(torrentsrc, "wb") f.write(bencode(metainfo)) f.close() # Torrent either already existed or should exist now dotTorrentDuplicate = True return self.AddTorrentFromFile(torrentsrc, False, dotTorrentDuplicate, dest = dest, caller = caller, label = label)
def run(self): from sha import sha import os import time do_gui_operation(app.wTree.get_widget("label17").set_label , "<big><b>Planting Torrent " + os.path.basename(self.filename) +"</b></big>") infohash = sha(bencode(self.bdata['info'])).digest() url = ["http://anatomic.berlios.de/network/node-b/cache.php", "http://anatomic.berlios.de/network/node-a/cache.php"] if os.path.isfile('strackers.dat') is True and (time.time() - os.path.getmtime('strackers.dat')) < 2592000: # check if file exists and is recent(ish) try: f = open('strackers.dat', "r") except IOError, e: do_gui_operation(app.status.set_label, '<span color="red">Warning: Cannot open strackers.dat</span>') file = f.read() f.close() try: b2data = bdecode(file) url = b2data except ValueError, e: do_gui_operation(app.status.set_label, '<span color="red">Warning: strackers.dat cannot be decoded</span>')
def write(self): """Write a .torrent file""" # Whatever hash we have left, we'll take if self.done > 0: self.pieces.append(self.sh.digest()) info = {'pieces': ''.join(self.pieces), 'piece length': self.piece_length, 'files': self.fs, 'name': self.name} check_info(info) data = {'info': info, 'announce': self.tracker, 'creation data': long(time())} h = open(self.target, 'wb') h.write(bencode(data)) h.close()
def gather_info(self): self.fin = 0 resp = self.get_meta() info = resp["info"] self.announce = resp["announce"] infohash_sha = sha(bencode(info)) self.infohash_bin = infohash_sha.digest() self.infohash = infohash_sha.hexdigest() self.title = info["name"] if info.has_key("length"): self.size = info["length"] title = self.title.upper() if (title.startswith("AVSEQ") or title.startswith("MUSIC")) and title.endswith(".DAT") and len(title) == 11: self.dest_path = os.path.join(self.dest_path, self.infohash + "-" + self.title) else: self.dest_path = os.path.join(self.dest_path, self.title) else: self.size = 0 for i in info["files"]: self.size += i["length"] self.piece_length = info["piece length"] self.size_mb = self.size / 1024 / 1024
def run(autoDie,shareKill,statusFile,userName,params): if __debug__: traceMsg('run - begin') try: f=open(statusFile+".pid",'w') f.write(str(getpid()).strip() + "\n") f.flush() f.close() except: if __debug__: traceMsg('run - Failed to Create PID file') pass try: h = HeadlessDisplayer() h.statFile = statusFile h.autoShutdown = autoDie h.shareKill = shareKill h.user = userName while 1: try: config = parse_params(params) except ValueError, e: print 'error: ' + str(e) + '\nrun with no args for parameter explanations' break if not config: print get_usage() break myid = createPeerID() seed(myid) doneflag = Event() def disp_exception(text): print text rawserver = RawServer(doneflag, config['timeout_check_interval'], config['timeout'], ipv6_enable = config['ipv6_enabled'], failfunc = h.failed, errorfunc = disp_exception) upnp_type = UPnP_test(config['upnp_nat_access']) while True: try: listen_port = rawserver.find_and_bind(config['minport'], config['maxport'], config['bind'], ipv6_socket_style = config['ipv6_binds_v4'], upnp = upnp_type, randomizer = config['random_port']) break except socketerror, e: if upnp_type and e == UPnP_ERROR: print 'WARNING: COULD NOT FORWARD VIA UPnP' upnp_type = 0 continue print "error: Couldn't listen - " + str(e) h.failed() return response = get_response(config['responsefile'], config['url'], h.error) if not response: break infohash = sha(bencode(response['info'])).digest() dow = BT1Download(h.display, h.finished, h.error, disp_exception, doneflag, config, response, infohash, myid, rawserver, listen_port) if not dow.saveAs(h.chooseFile, h.newpath): break if not dow.initFiles(old_style = True): break if not dow.startEngine(): dow.shutdown() break dow.startRerequester() dow.autoStats() if not dow.am_I_finished(): h.display(activity = 'connecting to peers') rawserver.listen_forever(dow.getPortHandler()) h.display(activity = 'shutting down') dow.shutdown() break
def run(scrwin, errlist, params): doneflag = threading.Event() d = CursesDisplayer(scrwin, errlist, doneflag) try: while 1: configdir = ConfigDir('downloadcurses') defaultsToIgnore = ['responsefile', 'url', 'priority'] configdir.setDefaults(defaults, defaultsToIgnore) configdefaults = configdir.loadConfig() defaults.append( ('save_options', 0, 'whether to save the current options as ' 'the new default configuration (only for btdownloadcurses.py)' )) try: config = parse_params(params, configdefaults) except ValueError as e: d.error('error: {}\nrun with no args for parameter ' 'explanations'.format(e)) break if not config: d.error(get_usage(defaults, d.fieldw, configdefaults)) break if config['save_options']: configdir.saveConfig(config) configdir.deleteOldCacheData(config['expire_cache_data']) myid = createPeerID() random.seed(myid) rawserver = RawServer(doneflag, config['timeout_check_interval'], config['timeout'], ipv6_enable=config['ipv6_enabled'], failfunc=d.failed, errorfunc=d.error) upnp_type = UPnP_test(config['upnp_nat_access']) while True: try: listen_port = rawserver.find_and_bind( config['minport'], config['maxport'], config['bind'], ipv6_socket_style=config['ipv6_binds_v4'], upnp=upnp_type, randomizer=config['random_port']) break except socket.error as e: if upnp_type and e == UPnP_ERROR: d.error('WARNING: COULD NOT FORWARD VIA UPnP') upnp_type = 0 continue d.error("Couldn't listen - " + str(e)) d.failed() return response = get_response(config['responsefile'], config['url'], d.error) if not response: break infohash = hashlib.sha1(bencode(response['info'])).digest() dow = BT1Download(d.display, d.finished, d.error, d.error, doneflag, config, response, infohash, myid, rawserver, listen_port, configdir) if not dow.saveAs(d.chooseFile): break if not dow.initFiles(old_style=True): break if not dow.startEngine(): dow.shutdown() break dow.startRerequester() dow.autoStats() if not dow.am_I_finished(): d.display(activity='connecting to peers') rawserver.listen_forever(dow.getPortHandler()) d.display(activity='shutting down') dow.shutdown() break except KeyboardInterrupt: # ^C to exit... pass try: rawserver.shutdown() except: pass if not d.done: d.failed()
def __init__(self, queue, src=None, dest=None, forceasklocation=False, caller=""): self.queue = queue self.utility = self.queue.utility self.list = self.utility.list self.listindex = len(self.utility.torrents["all"]) self.src = src self.status = TorrentStatus(self) self.actions = TorrentActions(self) self.dialogs = TorrentDialogs(self) self.connection = TorrentConnections(self) ######### self.metainfo = self.getResponse() if self.metainfo is None: return # Get infohash first before doing anything else self.infohash = sha(bencode(self.metainfo['info'])).hexdigest() self.torrentconfig = TorrentConfig(self) # Check for valid windows filename if sys.platform == 'win32': fixedname = self.utility.fixWindowsName( self.metainfo['info']['name']) if fixedname: self.metainfo['info']['name'] = fixedname self.info = self.metainfo['info'] self.title = None # Initialize values to defaults self.files = TorrentFiles(self) # Setup the destination self.files.setupDest(dest, forceasklocation, caller) if self.files.dest is None: return ######### # Priority "Normal" priorities = [ self.utility.lang.get('highest'), self.utility.lang.get('high'), self.utility.lang.get('normal'), self.utility.lang.get('low'), self.utility.lang.get('lowest') ] currentprio = self.utility.config.Read('defaultpriority', "int") if currentprio < 0: currentprio = 0 elif currentprio >= len(priorities): currentprio = len(priorities) - 1 self.prio = currentprio self.color = {'text': None, 'bgcolor': None} # Done flag self.messages = {"current": "", "log": [], "timer": None} self.checkedonce = False self.totalpeers = "?" self.totalseeds = "?"
NAME, EXT = os.path.splitext(os.path.basename(sys.argv[0])) VERSION = '20130326' print '%s %s - decode BitTorrent metainfo files' % (NAME, VERSION) print if len(sys.argv) == 1: print '%s file1.torrent file2.torrent file3.torrent ...' % sys.argv[0] print sys.exit(2) # common exit code for syntax error for metainfo_name in sys.argv[1:]: metainfo = MetaInfo.read(metainfo_name) info = metainfo['info'] info_hash = hashlib.sha1(bencode(info)) print 'metainfo file.: %s' % os.path.basename(metainfo_name) print 'info hash.....: %s' % info_hash.hexdigest() piece_length = info['piece length'] if 'length' in info: # let's assume we just have a file print 'file name.....: %s' % info['name'] file_length = info['length'] name = 'file size.....:' else: # let's assume we have a directory structure print 'directory name: %s' % info['name'] print 'files.........: ' file_length = 0 for file in info['files']:
def run(scrwin, errlist, params): doneflag = Event() d = CursesDisplayer(scrwin, errlist, doneflag) try: while 1: configdir = ConfigDir('downloadcurses') defaultsToIgnore = ['responsefile', 'url', 'priority'] configdir.setDefaults(defaults,defaultsToIgnore) configdefaults = configdir.loadConfig() defaults.append(('save_options',0, "whether to save the current options as the new default configuration " + "(only for btdownloadcurses.py)")) try: config = parse_params(params, configdefaults) except ValueError, e: d.error('error: ' + str(e) + '\nrun with no args for parameter explanations') break if not config: d.error(get_usage(defaults, d.fieldw, configdefaults)) break if config['save_options']: configdir.saveConfig(config) configdir.deleteOldCacheData(config['expire_cache_data']) myid = createPeerID() seed(myid) rawserver = RawServer(doneflag, config['timeout_check_interval'], config['timeout'], ipv6_enable = config['ipv6_enabled'], failfunc = d.failed, errorfunc = d.error) upnp_type = UPnP_test(config['upnp_nat_access']) while True: try: listen_port = rawserver.find_and_bind(config['minport'], config['maxport'], config['bind'], ipv6_socket_style = config['ipv6_binds_v4'], upnp = upnp_type, randomizer = config['random_port']) break except socketerror, e: if upnp_type and e == UPnP_ERROR: d.error('WARNING: COULD NOT FORWARD VIA UPnP') upnp_type = 0 continue d.error("Couldn't listen - " + str(e)) d.failed() return response = get_response(config['responsefile'], config['url'], d.error) if not response: break infohash = sha(bencode(response['info'])).digest() dow = BT1Download(d.display, d.finished, d.error, d.error, doneflag, config, response, infohash, myid, rawserver, listen_port, configdir) if not dow.saveAs(d.chooseFile): break if not dow.initFiles(old_style = True): break if not dow.startEngine(): dow.shutdown() break dow.startRerequester() dow.autoStats() if not dow.am_I_finished(): d.display(activity = 'connecting to peers') rawserver.listen_forever(dow.getPortHandler()) d.display(activity = 'shutting down') dow.shutdown() break
def run(params): h = HeadlessDisplayer() while 1: configdir = ConfigDir('downloadheadless') defaultsToIgnore = ['responsefile', 'url', 'priority'] configdir.setDefaults(defaults, defaultsToIgnore) configdefaults = configdir.loadConfig() defaults.append( ('save_options', 0, 'whether to save the current options as the ' 'new default configuration (only for btdownloadheadless.py)')) try: config = parse_params(params, configdefaults) except ValueError as e: print 'error: {}\nrun with no args for parameter explanations' \ ''.format(e) break if not config: print get_usage(defaults, 80, configdefaults) break if config['save_options']: configdir.saveConfig(config) configdir.deleteOldCacheData(config['expire_cache_data']) myid = createPeerID() random.seed(myid) doneflag = threading.Event() def disp_exception(text): print text rawserver = RawServer( doneflag, config['timeout_check_interval'], config['timeout'], ipv6_enable=config['ipv6_enabled'], failfunc=h.failed, errorfunc=disp_exception) upnp_type = UPnP_test(config['upnp_nat_access']) while True: try: listen_port = rawserver.find_and_bind( config['minport'], config['maxport'], config['bind'], ipv6_socket_style=config['ipv6_binds_v4'], upnp=upnp_type, randomizer=config['random_port']) break except socket.error as e: if upnp_type and e == UPnP_ERROR: print 'WARNING: COULD NOT FORWARD VIA UPnP' upnp_type = 0 continue print "error: Couldn't listen - " + str(e) h.failed() return response = get_response(config['responsefile'], config['url'], h.error) if not response: break infohash = hashlib.sha1(bencode(response['info'])).digest() dow = BT1Download( h.display, h.finished, h.error, disp_exception, doneflag, config, response, infohash, myid, rawserver, listen_port, configdir) if not dow.saveAs(h.chooseFile, h.newpath): break if not dow.initFiles(old_style=True): break if not dow.startEngine(): dow.shutdown() break dow.startRerequester() dow.autoStats() if not dow.am_I_finished(): h.display(activity='connecting to peers') rawserver.listen_forever(dow.getPortHandler()) h.display(activity='shutting down') dow.shutdown() break try: rawserver.shutdown() except: pass if not h.done: h.failed()
def save_dfile(self): self.rawserver.add_task(self.save_dfile, self.save_dfile_interval) h = open(self.dfile, 'wb') h.write(bencode(self.state)) h.close()
def natcheckOK(self, infohash, peerid, ip, port, not_seed): bc = self.becache.setdefault(infohash,[[{}, {}], [{}, {}], [{}, {}]]) bc[0][not not_seed][peerid] = Bencached(bencode({'ip': ip, 'port': port, 'peer id': peerid})) bc[1][not not_seed][peerid] = Bencached(bencode({'ip': ip, 'port': port})) bc[2][not not_seed][peerid] = compact_peer_info(ip, port)
def doTheDownloadThing(self): """ This was copied and modified directly from btdownloadheadless.py """ if self.disabled: LOGERROR('Attempted to start DL but DISABLE_TORRENT is True') return while 1: # Use this var to identify if we've started downloading self.startTime = RightNow() configdir = ConfigDir(self.cacheDir) defaultsToIgnore = ['responsefile', 'url', 'priority'] configdir.setDefaults(defaults, defaultsToIgnore) config = configdir.loadConfig() config['responsefile'] = self.torrent config['url'] = '' config['priority'] = '' config['saveas'] = self.savePath_temp config['save_options'] = 0 config['max_uploads'] = 0 config['max_files_open'] = 25 configdir.deleteOldCacheData(config['expire_cache_data']) myid = createPeerID() seed(myid) rawserver = RawServer( self.doneObj, config['timeout_check_interval'], config['timeout'], ipv6_enable = config['ipv6_enabled'], failfunc = self.failedFunc, errorfunc = self.errorFunc) upnp_type = UPnP_test(config['upnp_nat_access']) while True: try: listen_port = rawserver.find_and_bind( \ config['minport'], config['maxport'], config['bind'], ipv6_socket_style = config['ipv6_binds_v4'], upnp = upnp_type, randomizer = config['random_port']) break except socketerror, e: if upnp_type and e == UPnP_ERROR: LOGWARN('WARNING: COULD NOT FORWARD VIA UPnP') upnp_type = 0 continue LOGERROR("error: Couldn't listen - " + str(e)) self.failedFunc() return if not self.response: break infohash = sha(bencode(self.response['info'])).digest() LOGINFO('Downloading: %s', self.torrentName) curr,tot = [float(a)/MEGABYTE for a in self.fileProgress()] if curr == 0: LOGINFO('Starting new download') elif curr==tot: LOGINFO('Torrent already finished!') return else: LOGINFO('Picking up where left off at %0.0f of %0.0f MB' % (curr,tot)) self.bt1dow = BT1Download( self.statusFunc, self.finishedFunc, self.errorFunc, self.excFunc, self.doneObj, config, self.response, infohash, myid, rawserver, listen_port, configdir) if not self.bt1dow.saveAs(self.chooseFileFunc): break if not self.bt1dow.initFiles(old_style = True): break if not self.bt1dow.startEngine(): self.bt1dow.shutdown() break if self.nHashFailures >= self.killAfterNHashFails: self.bt1dow.shutdown() self.customCallbacks['errorFunc']('hashFail') break self.bt1dow.startRerequester() self.bt1dow.autoStats() if not self.bt1dow.am_I_finished(): self.statusFunc(activity = 'Connecting to peers') rawserver.listen_forever(self.bt1dow.getPortHandler()) self.statusFunc(activity = 'Shutting down') self.bt1dow.shutdown() break
def save_thost(self, x): if not self.annCtl.GetValue(): dlg = wxMessageDialog( self.frame, message='You must specify a\nsingle tracker url', caption='Error', style=wxOK | wxICON_ERROR) dlg.ShowModal() dlg.Destroy() return try: metainfo = {} metainfo['announce'] = self.annCtl.GetValue() annlist = self.getannouncelist() if len(annlist) > 0: warnings = '' for tier in annlist: if len(tier) > 1: warnings += ( 'WARNING: You should not specify multiple trackers\n' + ' on the same line of the tracker list unless\n' + ' you are certain they share peer data.\n') break if not self.annCtl.GetValue() in annlist[0]: warnings += ( 'WARNING: The single tracker url is not present in\n' + ' the first line of the tracker list. This\n' + ' may produce a dysfunctional torrent.\n') if warnings: warnings += ( 'Are you sure you wish to save a torrent host\n' + 'with these parameters?') dlg = wxMessageDialog(self.frame, message=warnings, caption='Warning', style=wxYES_NO | wxICON_QUESTION) if dlg.ShowModal() != wxID_YES: dlg.Destroy() return metainfo['announce-list'] = annlist metainfo = bencode(metainfo) except: return if self.thostselectnum: d = self.thostselection else: d = '.thost' dl = wxFileDialog(self.frame, 'Save tracker data as', join(basepath, 'thosts'), d, '*.thost', wxSAVE | wxOVERWRITE_PROMPT) if dl.ShowModal() != wxID_OK: return d = dl.GetPath() try: f = open(d, 'wb') f.write(metainfo) f.close() garbage, self.thostselection = os.path.split(d) except: pass self.refresh_thostlist()
randomizer=config['random_port']) break except socketerror, e: if upnp_type and e == UPnP_ERROR: print 'WARNING: COULD NOT FORWARD VIA UPnP' upnp_type = 0 continue print "error: Couldn't listen - " + str(e) h.failed() return response = get_response(config['responsefile'], config['url'], h.error) if not response: break infohash = sha(bencode(response['info'])).digest() dow = BT1Download(h.display, h.finished, h.error, disp_exception, doneFlag, config, response, infohash, myid, rawserver, listen_port, configdir) if not dow.saveAs(h.chooseFile, h.newpath): break if not dow.initFiles(old_style=True): break if not dow.startEngine(): dow.shutdown() break dow.startRerequester() dow.autoStats()
upnp = upnp_type, randomizer = config['random_port']) break except socketerror, e: if upnp_type and e == UPnP_ERROR: print 'WARNING: COULD NOT FORWARD VIA UPnP' upnp_type = 0 continue print "error: Couldn't listen - " + str(e) h.failed() return response = get_response(config['responsefile'], config['url'], h.error) if not response: break infohash = sha(bencode(response['info'])).digest() h.dow = BT1Download(h.display, h.finished, h.error, disp_exception, doneflag, config, response, infohash, myid, rawserver, listen_port) if not h.dow.saveAs(h.chooseFile, h.newpath): break if not h.dow.initFiles(old_style = True): break if not h.dow.startEngine(): h.dow.shutdown() break h.dow.startRerequester() h.dow.autoStats()
for f in argv[2:]: h = open(f, 'rb') metainfo = bdecode(h.read()) h.close() print 'old announce for %s: %s' % (f, metainfo['announce']) metainfo['announce'] = announce if metainfo.has_key('announce-list'): list = [] for tier in metainfo['announce-list']: for tracker in tier: list+=[tracker,','] del list[-1] list+=['|'] del list[-1] liststring = '' for i in list: liststring+=i print 'old announce-list for %s: %s' % (f, liststring) if len(announce_list) > 0: metainfo['announce-list'] = announce_list elif metainfo.has_key('announce-list'): try: del metainfo['announce-list'] except: pass h = open(f, 'wb') h.write(bencode(metainfo)) h.close()
data['comment'] = params['comment'] if params.has_key('real_announce_list'): # shortcut for progs calling in from outside data['announce-list'] = params['real_announce_list'] elif params.has_key('announce_list') and params['announce_list']: l = [] for tier in params['announce_list'].split('|'): l.append(tier.split(',')) data['announce-list'] = l if params.has_key('real_httpseeds'): # shortcut for progs calling in from outside data['httpseeds'] = params['real_httpseeds'] elif params.has_key('httpseeds') and params['httpseeds']: data['httpseeds'] = params['httpseeds'].split('|') h.write(bencode(data)) h.close() def calcsize(file): if not isdir(file): return getsize(file) total = 0L for s in subfiles(abspath(file)): total += getsize(s[1]) return total def uniconvertl(l, e): r = [] try: for s in l:
for f in argv[2:]: h = open(f, 'rb') metainfo = bdecode(h.read()) h.close() print 'old announce for %s: %s' % (f, metainfo['announce']) metainfo['announce'] = announce if metainfo.has_key('announce-list'): list = [] for tier in metainfo['announce-list']: for tracker in tier: list += [tracker, ','] del list[-1] list += ['|'] del list[-1] liststring = '' for i in list: liststring += i print 'old announce-list for %s: %s' % (f, liststring) if len(announce_list) > 0: metainfo['announce-list'] = announce_list elif metainfo.has_key('announce-list'): try: del metainfo['announce-list'] except: pass h = open(f, 'wb') h.write(bencode(metainfo)) h.close()
l.append(tier.split(',')) data['announce-list'] = l # HTTP Seeds if 'real_httpseeds' in params: # shortcut for progs calling in from outside data['httpseeds'] = params['real_httpseeds'] elif 'httpseeds' in params and params['httpseeds']: data['httpseeds'] = params['httpseeds'].split('|') # DHT Nodes if not private: nodes = params.get('nodes') if nodes: data['nodes'] = nodes elif 'announce' not in data and 'announce-list' not in data: closestnodes = utility.dht.factory.table.findNodes(sha1(bencode(info)).digest()) data['nodes'] = " ".join([str.format("{0}:{1}", node.host, node.port) for node in closestnodes]) h.write(bencode(data)) h.close() fileCallback(file, f) def calcsize(file, filelist = None): if not isdir(file): return getsize(file) total = 0L if not filelist: filelist = subfiles(abspath(file)) for s in filelist:
def start(self): rawserver = None try: config = dict([(v[0], v[1]) for v in defaults]) config['ip'] = self.ip config['responsefile'] = self.torrent_file config['saveas'] = self.destination_file random.seed(self.id) rawserver = RawServer( doneflag=self.done_flag, timeout_check_interval=config['timeout_check_interval'], timeout=config['timeout'], ipv6_enable=config['ipv6_enabled'], failfunc=self.on_fail, errorfunc=self.on_exception) rawserver.bind(port=self.port, bind=config['bind'], reuse=True, ipv6_socket_style=config['ipv6_binds_v4']) # Download torrent metadata. response = get_response(file=config['responsefile'], url=config['url'], errorfunc=self.on_error) # Bail if tracker is done. if not response: return dow = BT1Download(statusfunc=self.on_status, finfunc=self.on_finish, errorfunc=self.on_error, excfunc=self.on_exception, doneflag=self.done_flag, config=config, response=response, infohash=hashlib.sha1(bencode( response['info'])).digest(), id=self.id, rawserver=rawserver, port=self.port) if not dow.saveAs(lambda default, size, saveas, dir: saveas if saveas else default): return if not dow.initFiles(old_style=True): return if not dow.startEngine(): dow.shutdown() return dow.startRerequester() dow.autoStats() if not dow.am_I_finished(): self.on_status(activity='connecting to peers') rawserver.listen_forever(dow.getPortHandler()) self.on_status(activity='shutting down') dow.shutdown() finally: if rawserver: rawserver.shutdown() if not self.finished_at: self.on_fail()