def save_global_config(defaults, section, error_callback, save_options=downloader_save_options): filename = os.path.join(defaults['data_dir'], MAIN_CONFIG_FILE) p = _read_config(filename) p.remove_section(section) if p.has_section(alt_uiname[section]): p.remove_section(alt_uiname[section]) p.add_section(section) for name in save_options: name.decode('ascii').encode('utf-8') # just to make sure we can if defaults.has_key(name): value = defaults[name] if isinstance(value, str): value = value.decode('ascii').encode('utf-8') elif isinstance(value, unicode): value = value.encode('utf-8') p.set(section, name, value) else: err_str = _("Configuration option mismatch: '%s'") % name if is_frozen_exe: err_str = _("You must quit %s and reinstall it. (%s)") % ( app_name, err_str) error_callback(err_str) _write_config(error_callback, filename, p)
def get_url(url): """Downloads the .torrent metainfo file specified by the passed URL and returns data, the raw contents of the metainfo file. Any exception raised while trying to obtain the metainfo file is caught and GetTorrent.URLException is raised instead. """ data = None err_str = ((_('Could not download or open "%s"')% url) + '\n' + _("Try using a web browser to download the torrent file.")) u = None # pending protocol changes, convert: # torrent://http://path.to/file # and: # bittorrent://http://path.to/file # to: # http://path.to/file url = urlpat_torrent.sub('', url) url = urlpat_bittorrent.sub('', url) try: u = zurllib.urlopen(url) data = u.read() u.close() except Exception, e: if u is not None: u.close() raise URLException(err_str + "\n(%s)" % e)
def _rerequest(self, url, peerid): if self.config['ip']: try: url += '&ip=' + socket.gethostbyname(self.config['ip']) except: self.errorfunc(logging.WARNING, _("Problem resolving config ip (%s), gethostbyname failed") % self.config['ip'], exc_info=sys.exc_info()) request = Request(url) request.add_header('User-Agent', 'BitTorrent/' + version) if self.config['tracker_proxy']: request.set_proxy(self.config['tracker_proxy'], 'http') try: h = urlopen(request) data = h.read() h.close() # urllib2 can raise various crap that doesn't have a common base # exception class especially when proxies are used, at least # ValueError and stuff from httplib except Exception, e: try: s = unicode(e.args[0]) except: s = unicode(e) r = _("Problem connecting to tracker - %s: %s") % (e.__class__, s) def f(): self._postrequest(errormsg=r, exc=e, peerid=peerid)
def bdecode(x): try: r, l = decode_func[x[0]](x, 0) except (IndexError, KeyError, ValueError): raise BTFailure, _("not a valid bencoded string") if l != len(x): raise BTFailure, _("invalid bencoded value (data after valid prefix)") return r
def huphandler(signum, frame, self = self): try: self.log.close () self.log = open(self.logfile, 'a') sys.stdout = self.log print _("# Log reopened: "), isotime() except: print _("***warning*** could not reopen logfile")
def fmttime(n): if n <= 0: return None n = int(n) m, s = divmod(n, 60) h, m = divmod(m, 60) if h > 1000000: return _("connecting to peers") return _("ETA in %d:%02d:%02d") % (h, m, s)
def parse_options(defaults, newvalues, encoding): """Given the type provided by the default value, this tries to cast/convert the corresponding newvalue to the type of the default value. By calling eval() on it, in some cases! Entertainly, newvalue sometimes holds strings and, apparently, sometimes holds values which have already been cast appropriately. This function is like a boat made of shit, floating on a river of shit. @param defaults: dict of key-value pairs where value is the default. @param newvalues: dict of key-value pairs which override the default. """ assert type(defaults) == dict assert type(newvalues) == dict for key, value in newvalues.iteritems(): if not defaults.has_key(key): raise UsageException(_("unknown option ") + format_key(key)) try: t = type(defaults[key]) if t is bool: if value in ("True", "1", True): value = True else: value = False newvalues[key] = value elif t in (StringType, NoneType): # force ASCII newvalues[key] = value.decode("ascii").encode("ascii") elif t in (IntType, LongType): if value == "False": newvalues[key] == 0 elif value == "True": newvalues[key] == 1 else: newvalues[key] = int(value) elif t is FloatType: newvalues[key] = float(value) elif t in (ListType, TupleType, DictType): if type(value) == StringType: try: n = eval(value) assert type(n) == t newvalues[key] = n except: newvalues[key] = t() elif t is UnicodeType: if type(value) == StringType: try: newvalues[key] = value.decode(encoding) except: newvalues[key] = value.decode("ascii") else: raise TypeError, str(t) except ValueError, e: raise UsageException(_("wrong format of %s - %s") % (format_key(key), unicode(e.args[0])))
def shutdown(): self.logger.critical(_("shutting down")) for t in self.multitorrent.get_torrents(): self.logger.info(_('dropped "%s"') % self.torrent_cache[t.infohash][0]) if self.multitorrent: df = self.multitorrent.shutdown() set_flag = lambda *a : self.rawserver.stop() df.addCallbacks(set_flag, set_flag) else: self.rawserver.stop()
def track(args): assert type(args) == list and \ len([x for x in args if type(x)==str])==len(args) config = {} defaults = get_defaults('bittorrent-tracker') # hard-coded defaults. try: config, files = parse_configuration_and_args(defaults, 'bittorrent-tracker', args, 0, 0 ) except ValueError, e: print _("error: ") + unicode(e.args[0]) print _("run with -? for parameter explanations") return
def create_torrent(self, metainfo, save_incomplete_as, save_as, hidden=False, is_auto_update=False, feedback=None): if self.is_single_torrent and len(self.torrents) > 0: raise TooManyTorrents(_("MultiTorrent is set to download only " "a single torrent, but tried to create more than one.")) #save_as, junk = encode_for_filesystem(save_as) #save_incomplete_as, junk = encode_for_filesystem(save_incomplete_as) infohash = metainfo.infohash if self.torrent_known(infohash): if self.torrent_running(infohash): msg = _("This torrent (or one with the same contents) is " "already running.") raise TorrentAlreadyRunning(msg) else: raise TorrentAlreadyInQueue(_("This torrent (or one with " "the same contents) is " "already waiting to run.")) self._dump_metainfo(metainfo) #BUG. Use _read_torrent_config for 5.0? --Dave config = configfile.read_torrent_config(self.config, self.data_dir, infohash, lambda s : self.global_error(logging.ERROR, s)) t = Torrent(metainfo, save_incomplete_as, save_as, self.config, self.data_dir, self.rawserver, self.choker, self.singleport_listener, self.ratelimiter, self.total_downmeasure, self.filepool, self.dht, self, self.log_root, hidden=hidden, is_auto_update=is_auto_update) if feedback: t.add_feedback(feedback) retdf = Deferred() def torrent_started(*args): if config: t.update_config(config) t._dump_torrent_config() if self.resume_from_torrent_config: self._dump_torrents() t.metainfo.show_encoding_errors(self.logger.log) retdf.callback(t) df = self._init_torrent(t, use_policy=False) df.addCallback(torrent_started) return retdf
def _get_available(self, url): self.debug('Updater.get_available() hitting url %s' % url) try: u = zurllib.urlopen(url) s = u.read() s = s.strip() except: raise BTFailure(_("Could not get latest version from %s")%url) try: assert len(s) == 5 availableversion = Version.from_str(s) except: raise BTFailure(_("Could not parse new version string from %s")%url) return availableversion
def _remake_window(self): self.scrh, self.scrw = self.scrwin.getmaxyx() self.scrpan = curses.panel.new_panel(self.scrwin) self.mainwinh = (2 * self.scrh) // 3 self.mainwinw = self.scrw - 4 # - 2 (bars) - 2 (spaces) self.mainwiny = 2 # + 1 (bar) + 1 (titles) self.mainwinx = 2 # + 1 (bar) + 1 (space) # + 1 to all windows so we can write at mainwinw self.mainwin = curses.newwin(self.mainwinh, self.mainwinw + 1, self.mainwiny, self.mainwinx) self.mainpan = curses.panel.new_panel(self.mainwin) self.mainwin.scrollok(0) self.mainwin.nodelay(1) self.headerwin = curses.newwin(1, self.mainwinw + 1, 1, self.mainwinx) self.headerpan = curses.panel.new_panel(self.headerwin) self.headerwin.scrollok(0) self.totalwin = curses.newwin(1, self.mainwinw + 1, self.mainwinh + 1, self.mainwinx) self.totalpan = curses.panel.new_panel(self.totalwin) self.totalwin.scrollok(0) self.statuswinh = self.scrh - 4 - self.mainwinh self.statuswin = curses.newwin(self.statuswinh, self.mainwinw + 1, self.mainwinh + 3, self.mainwinx) self.statuspan = curses.panel.new_panel(self.statuswin) self.statuswin.scrollok(0) try: self.scrwin.border(ord("|"), ord("|"), ord("-"), ord("-"), ord(" "), ord(" "), ord(" "), ord(" ")) except: pass rcols = (_("Size"), _("Download"), _("Upload")) rwids = (8, 10, 10) rwid = sum(rwids) start = self.mainwinw - rwid self.headerwin.addnstr(0, 2, "#", start, curses.A_BOLD) self.headerwin.addnstr(0, 4, _("Filename"), start, curses.A_BOLD) for s, w in zip(rcols, rwids): st = start + max(w - len(s), 0) self.headerwin.addnstr(0, st, s[:w], len(s[:w]), curses.A_BOLD) start += w self.totalwin.addnstr(0, self.mainwinw - 27, _("Totals:"), 7, curses.A_BOLD) self._display_messages() curses.panel.update_panels() curses.doupdate() self.changeflag.clear()
def create(self): filename = self.socket_filename if os.path.exists(filename): try: self.send_command('no-op') except BTFailure: pass else: raise BTFailure(_("Could not create control socket: already in use")) try: os.unlink(filename) except OSError, e: raise BTFailure(_("Could not remove old control socket filename:") + unicode(e.args[0]))
def parsedir(directory, parsed, files, blocked, errfunc, include_metainfo=True): """Recurses breadth-first starting from the passed 'directory' looking for .torrrent files. Stops recursing in any given branch at the first depth that .torrent files are encountered. The directory, parsed, files, and blocked arguments are passed from the previous iteration of parsedir. @param directory: root of the breadth-first search for .torrent files. @param parsed: dict mapping infohash to ConvertedMetainfo. @param files: dict mapping path -> [(modification time, size), infohash] @param blocked: dict used as set. keys are list of paths of files that were not parsed on a prior call to parsedir for some reason. Valid reasons are that the .torrent file is unparseable or that a torrent with a matching infohash is already in the parsed set. @param errfunc: error-reporting callback. @param include_metainfo: @return: The tuple (new parsed, new files, new blocked, added, removed) where 'new parsed', 'new files', and 'new blocked' are updated versions of 'parsed', 'files', and 'blocked' respectively. 'added' and 'removed' contain the changes made to the first three members of the tuple. 'added' and 'removed' are dicts mapping from infohash on to the same torrent-specific info dict that is in or was in parsed. """ if NOISY: errfunc('checking dir') dirs_to_check = [directory] new_files = {} # maps path -> [(modification time, size),infohash] new_blocked = set() while dirs_to_check: # first, recurse directories and gather torrents directory = dirs_to_check.pop() newtorrents = False try: dir_contents = os.listdir(directory) except (IOError, OSError), e: errfunc(_("Could not read directory ") + directory) continue for f in dir_contents: if f.endswith('.torrent'): newtorrents = True p = os.path.join(directory, f) try: new_files[p] = [(os.path.getmtime(p), os.path.getsize(p)), 0] except (IOError, OSError), e: errfunc(_("Could not stat ") + p + " : " + unicode(e.args[0]))
def display(self, data): try: if self.changeflag.isSet(): return inchar = self.mainwin.getch() if inchar == 12: # ^L self._remake_window() self.mainwin.erase() if data: self._display_data(data) else: self.mainwin.addnstr(1, self.mainwinw // 2 - 5, _("no torrents"), 12, curses.A_BOLD) totalup = 0 totaldn = 0 for ( name, status, progress, peers, seeds, seedsmsg, # dist, uprate, dnrate, upamt, dnamt, size, t, msg, ) in data: totalup += uprate totaldn += dnrate totalup = "%s/s" % fmtsize(totalup) totaldn = "%s/s" % fmtsize(totaldn) self.totalwin.erase() self.totalwin.addnstr(0, self.mainwinw - 27, _("Totals:"), 7, curses.A_BOLD) self.totalwin.addnstr(0, self.mainwinw - 20 + (10 - len(totaldn)), totaldn, 10, curses.A_BOLD) self.totalwin.addnstr(0, self.mainwinw - 10 + (10 - len(totalup)), totalup, 10, curses.A_BOLD) curses.panel.update_panels() curses.doupdate() except: pass return inchar in (ord("q"), ord("Q"))
def _rerequest(self, url, peerid): self.peers = "" try: self.dht.getPeersAndAnnounce(str(self.announce_infohash), self.port, self._got_peers) except Exception, e: self._postrequest(errormsg=_("Trackerless lookup failed: ") + unicode(e.args[0]), peerid=self.wanted_peerid)
def formatDefinitions(options, COLS): s = u"" indent = u" " * 10 width = COLS - 11 if width < 15: width = COLS - 2 indent = " " for option in options: (longname, default, doc) = option if doc == "": continue s += u"--" + longname is_boolean = type(default) is bool if is_boolean: s += u", --no_" + longname else: s += u" <arg>" s += u"\n" if default is not None: doc += _(u" (defaults to ") + repr(default) + u")" i = 0 for word in doc.split(): if i == 0: s += indent + word i = len(word) elif i + len(word) >= width: s += u"\n" + indent + word i = len(word) else: s += u" " + word i += len(word) + 1 s += u"\n\n" return s
def makeinfo(path, piece_length, flag, progress, name=None, content_type=None): # HEREDAVE. If path is directory, # how do we assign content type? def to_utf8(name): if isinstance(name, unicode): u = name else: try: u = decode_from_filesystem(name) except Exception, e: s = str_exc(e) raise BTFailure( _( "Could not convert file/directory name %r to " "Unicode (%s). Either the assumed filesystem " 'encoding "%s" is wrong or the filename contains ' "illegal bytes." ) % (name, s, get_filesystem_encoding()) ) if u.translate(noncharacter_translate) != u: raise BTFailure( _( 'File/directory name "%s" contains reserved ' "unicode values that do not correspond to " "characters." ) % name ) return u.encode("utf-8")
def _find_port(self, listen_fail_ok=True): """Run BitTorrent on the first available port found starting from minport in the range [minport, maxport].""" exc_info = None self.config['minport'] = max(1024, self.config['minport']) self.config['maxport'] = max(self.config['minport'], self.config['maxport']) e = (_("maxport less than minport - no ports to check") + (": %s %s" % (self.config['minport'], self.config['maxport']))) for port in xrange(self.config['minport'], self.config['maxport'] + 1): try: self.singleport_listener.open_port(port, self.config) if self.config['start_trackerless_client']: self.dht = UTKhashmir(self.config['bind'], self.singleport_listener.get_port(), self.data_dir, self.rawserver, int(self.config['max_upload_rate'] * 0.01), rlcount=self.ratelimiter.increase_offset, config=self.config) break except socket.error, e: exc_info = sys.exc_info()
def _restore_state(self, init_torrents): def decode_line(line): hashtext = line[:40] try: infohash = InfoHashType(hashtext.decode('hex')) except: raise BTFailure(_("Invalid state file contents")) if len(infohash) != 20: raise BTFailure(_("Invalid state file contents")) if infohash in self.torrents: raise BTFailure(_("Invalid state file (duplicate entry)")) try: metainfo = self._read_metainfo(infohash) except OSError, e: try: f.close() except: pass self.logger.error((_("Error reading metainfo file \"%s\".") % hashtext) + " (" + unicode(e.args[0])+ "), " + _("cannot restore state completely")) return None except Exception, e: self.logger.error((_("Corrupt data in metainfo \"%s\", cannot restore torrent.") % hashtext) + '('+unicode(e.args[0])+')') return None
def add_files(self, files, torrent): for filename in files: if filename in self.file_to_torrent: raise BTFailure(_("File %s belongs to another running torrent") % filename) for filename in files: self.file_to_torrent[filename] = torrent
def makeinfo(path, piece_length, flag, progress, name=None, content_type=None): # HEREDAVE. If path is directory, # how do we assign content type? def to_utf8(name): if isinstance(name, unicode): u = name else: try: u = decode_from_filesystem(name) except Exception, e: s = str_exc(e) raise BTFailure( _('Could not convert file/directory name %r to ' 'Unicode (%s). Either the assumed filesystem ' 'encoding "%s" is wrong or the filename contains ' 'illegal bytes.') % (name, s, get_filesystem_encoding())) if u.translate(noncharacter_translate) != u: raise BTFailure( _('File/directory name "%s" contains reserved ' 'unicode values that do not correspond to ' 'characters.') % name) return u.encode('utf-8')
def bad_config(filename): base_bad_filename = filename + ".broken" bad_filename = base_bad_filename i = 0 while os.access(bad_filename, os.F_OK): bad_filename = base_bad_filename + str(i) i += 1 os.rename(filename, bad_filename) sys.stderr.write(_("Error reading config file. " 'Old config file stored in "%s"') % bad_filename)
def stats(self): data = [] for d in self.multitorrent.get_torrents(): infohash = d.infohash path, metainfo = self.torrent_cache[infohash] if self.config['display_path']: name = path else: name = metainfo.name size = metainfo.total_bytes #d = self.downloads[infohash] progress = '0.0%' peers = 0 seeds = 0 seedsmsg = "S" dist = 0.0 uprate = 0.0 dnrate = 0.0 upamt = 0 dnamt = 0 t = 0 msg = '' #if d.state in ["created", "initializing"]: # status = _("waiting for hash check") #else: stats = d.get_status() status = stats['activity'] progress = '%.1f%%' % (int(stats['fractionDone']*1000)/10.0) if d.is_running(): s = stats #dist = s['numCopies'] if d.get_percent_complete()==1.0: seeds = 0 # s['numOldSeeds'] seedsmsg = "s" else: if s['numSeeds'] + s['numPeers']: t = stats['timeEst'] if t is None: t = -1 if t == 0: # unlikely t = 0.01 #status = _("downloading") else: t = -1 status = _("connecting to peers") seeds = s['numSeeds'] dnrate = stats['downRate'] peers = s['numPeers'] uprate = stats['upRate'] upamt = s['upTotal'] dnamt = s['downTotal'] data.append(( name, status, progress, peers, seeds, seedsmsg, uprate, dnrate, upamt, dnamt, size, t, msg )) stop = self.display(data) if stop: self.core_doneflag.set()
def make_meta_files(url, files, flag=Event(), progressfunc=dummy, filefunc=dummy, piece_len_pow2=0, target=None, title=None, comment=None, use_tracker=True, data_dir = None): if len(files) > 1 and target: raise BTFailure(_("You can't specify the name of the .torrent file " "when generating multiple torrents at once")) files.sort() ext = '.torrent' togen = [] for f in files: if not f.endswith(ext): togen.append(f) sizes = [] for f in togen: sizes.append(calcsize(f)) total = sum(sizes) subtotal = [0] def callback(x): subtotal[0] += x progressfunc(subtotal[0] / total) for i, f in enumerate(togen): if flag.isSet(): break if sizes[i] < 1: continue # duh, skip empty files/directories t = os.path.split(f) if t[1] == '': f = t[0] filefunc(f) if piece_len_pow2 > 0: my_piece_len_pow2 = piece_len_pow2 else: my_piece_len_pow2 = size_to_piece_len_pow2(sizes[i]) if use_tracker: make_meta_file(f, url, flag=flag, progress=callback, piece_len_exp=my_piece_len_pow2, target=target, title=title, comment=comment) else: make_meta_file_dht(f, url, flag=flag, progress=callback, piece_len_exp=my_piece_len_pow2, target=target, title=title, comment=comment, data_dir=data_dir)
def start_install(self): if not self.asked_for_install: if self.installer_downloaded(): self.asked_for_install = True self.installfunc() else: self.errorfunc(logging.WARNING, _("%s %s installer appears to be incomplete, " "missing, or corrupt.")%(app_name, self.version))
def check_nodes(nodes): ## note, these strings need changing for node in nodes: if type(node) != list: raise BTFailure, _("bad metainfo - node is not a list") if len(node) != 2: raise BTFailure, _("bad metainfo - node list must have only two elements") host, port = node if type(host) != str: raise BTFailure, _("bad metainfo - node host must be a string") if type(port) != int: raise BTFailure, _("bad metainfo - node port must be an integer")
def bad_config(filename): base_bad_filename = filename + '.broken' bad_filename = base_bad_filename i = 0 while os.access(bad_filename, os.F_OK): bad_filename = base_bad_filename + str(i) i+=1 os.rename(filename, bad_filename) sys.stderr.write(_("Error reading config file. " "Old config file stored in \"%s\"") % bad_filename)
def to_utf8(name): if isinstance(name, unicode): u = name else: try: u = decode_from_filesystem(name) except Exception, e: raise BTFailure(_('Could not convert file/directory name "%s" to ' 'Unicode (%s). Either the assumed filesystem ' 'encoding "%s" is wrong or the filename contains ' 'illegal bytes.') % (name, unicode(e.args[0]), get_filesystem_encoding()))
def _get_available(self, url): """Get the available version from the version site. The command line option --new_version X.Y.Z overrides this method and returns 'X.Y.Z' instead.""" self.debug('_get_available() run#%d: hitting url %s' % (self.runs, url)) try: u = zurllib.urlopen(url) s = u.read() s = s.strip() except: raise BTFailure(_("Could not get latest version from %s")%url) try: # we're luck asserts are turned off in production. # this assert is false for 4.20.X #assert len(s) == 5 available_version = Version.from_str(s) except: raise BTFailure(_("Could not parse new version string from %s")%url) return available_version
def calc_installer_dir(self): if hasattr(self, 'installer_dir'): return self.installer_dir temp_dir = get_temp_dir() if temp_dir is not None: return temp_dir else: self.errorfunc(logging.WARNING, _("Could not find a suitable temporary location to " "save the %s %s installer.") % (app_name, self.version))
def scan(self): self.rawserver.add_task(self.config['parse_dir_interval'], self.scan) r = parsedir(self.torrent_dir, self.torrent_cache, self.file_cache, self.blocked_files, self.logger.error) ( self.torrent_cache, self.file_cache, self.blocked_files, added, removed ) = r for infohash, (path, metainfo) in removed.items(): self.logger.info(_('dropped "%s"') % path) self.remove(infohash) for infohash, (path, metainfo) in added.items(): self.logger.info(_('added "%s"' ) % path) if self.config['launch_delay'] > 0: self.rawserver.add_task(self.config['launch_delay'], self.add, metainfo) # torrent may have been known from resume state. else: self.add(metainfo)
def get_file(self, infohash): if not self.allow_get: return (400, 'Not Authorized', default_headers, _("get function is not available with this tracker.")) if not self.allowed.has_key(infohash): return (404, 'Not Found', default_headers, alas) fname = self.allowed[infohash]['file'] fpath = self.allowed[infohash]['path'] return (200, 'OK', {'Content-Type': 'application/x-bittorrent', 'Content-Disposition': 'attachment; filename=' + fname}, open(fpath, 'rb').read())
def to_utf8(name): if isinstance(name, unicode): u = name else: try: u = decode_from_filesystem(name) except Exception, e: s = str_exc(e) raise BTFailure( _('Could not convert file/directory name %r to ' 'Unicode (%s). Either the assumed filesystem ' 'encoding "%s" is wrong or the filename contains ' 'illegal bytes.') % (name, s, get_filesystem_encoding()))
def _write_config(error_callback, filename, p): if not p.has_section('format'): p.add_section('format') p.set('format', 'encoding', 'utf-8') try: f = file(filename, 'wb') p.write(f) f.close() except Exception, e: try: f.close() except: pass error_callback(_("Could not permanently save options: ")+str_exc(e))
installing under Python %s Visit http://www.bittorrent.com/ to download BitTorrent. """ % (pythonversion, pythonversion) sys.exit(1) else: raise import time import BTL.stackthreading as threading import logging debug = True #debug=True from BTL import atexit_threads assert sys.version_info >= (2, 3), _("Install Python %s or greater") % '2.3' from BitTorrent import BTFailure, inject_main_logfile from BitTorrent import configfile from BTL.defer import DeferredEvent, wrap_task from BitTorrent.defaultargs import get_defaults from BitTorrent.IPC import ipc_interface from BitTorrent.prefs import Preferences from BitTorrent.RawServer_twisted import RawServer if os.name == 'nt': from BitTorrent.platform import win_version_num from BitTorrent import zurllib defaults = get_defaults('bittorrent') defaults.extend((
# # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # Written by Greg Hazel from __future__ import division app_name = "BitTorrent" import os import sys import time import shutil import logging from BitTorrent.translation import _ assert sys.version_info >= (2, 4), _("Install Python %s or greater") % '2.4' import BTL.stackthreading as threading from BTL import atexit_threads from BTL.defer import DeferredEvent from BTL.yielddefer import wrap_task from BTL.platform import efs2 from BitTorrent import zurllib from BitTorrent import configfile from BitTorrent import BTFailure, inject_main_logfile from BitTorrent.IPC import ipc_interface from BitTorrent.prefs import Preferences from BitTorrent.platform import no_really_makedirs from BitTorrent.defaultargs import get_defaults from BitTorrent.RawServer_twisted import RawServer from twisted.internet import task
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # Written by Henry 'Pi' James and Bram Cohen app_name = "BitTorrent" from BitTorrent.translation import _ from os.path import basename from sys import argv, exit from BTL.bencode import bencode, bdecode if len(argv) < 3: print _("Usage: %s TRACKER_URL [TORRENTFILE [TORRENTFILE ... ] ]") % basename(argv[0]) print exit(2) # common exit code for syntax error for f in argv[2:]: h = open(f, 'rb') metainfo = bdecode(h.read()) h.close() if metainfo['announce'] != argv[1]: print _("old announce for %s: %s") % (f, metainfo['announce']) metainfo['announce'] = argv[1] h = open(f, 'wb') h.write(bencode(metainfo)) h.close()
config = args = None try: config, args = parseargs.parseargs(arglist, defaults, minargs, maxargs, presets) except parseargs.UsageException, e: print e parseargs.printHelp(uiname, defaults) sys.exit(0) datadir = config.get('data_dir') found_4x_config = False if datadir: datadir,bad = encode_for_filesystem(datadir) if bad: raise BTFailure(_("Invalid path encoding.")) if not os.path.exists(datadir): os.mkdir(datadir) if uiname in ('bittorrent', 'maketorrent'): values = {} p = _read_config(os.path.join(datadir, MAIN_CONFIG_FILE)) if p.has_section('format'): encoding = p.get('format', 'encoding') else: encoding = old_broken_config_subencoding if not p.has_section(uiname) and p.has_section(alt_uiname[uiname]): uiname = alt_uiname[uiname] if p.has_section(uiname):
def make_meta_files( url, files, flag=Event(), progressfunc=dummy, filefunc=dummy, piece_len_pow2=0, target=None, title=None, comment=None, safe=None, content_type=None, # <---what to do for batch torrents? use_tracker=True, data_dir=None, url_list=None): if len(files) > 1 and target: raise BTFailure( _("You can't specify the name of the .torrent file " "when generating multiple torrents at once")) files.sort() ext = '.torrent' togen = [] for f in files: if not f.endswith(ext): togen.append(f) sizes = [] for f in togen: sizes.append(calcsize(f)) total = sum(sizes) subtotal = [0] def callback(x): subtotal[0] += x progressfunc(subtotal[0] / total) for i, f in enumerate(togen): if flag.isSet(): break if sizes[i] < 1: continue # duh, skip empty files/directories t = os.path.split(f) if t[1] == '': f = t[0] filefunc(f) if piece_len_pow2 > 0: my_piece_len_pow2 = piece_len_pow2 else: my_piece_len_pow2 = size_to_piece_len_pow2(sizes[i]) if use_tracker: make_meta_file(f, url, flag=flag, progress=callback, piece_len_exp=my_piece_len_pow2, target=target, title=title, comment=comment, safe=safe, content_type=content_type, url_list=url_list) else: make_meta_file_dht(f, url, flag=flag, progress=callback, piece_len_exp=my_piece_len_pow2, target=target, title=title, comment=comment, safe=safe, content_type=content_type, data_dir=data_dir)