| Server IP : 182.53.201.61 / Your IP : 216.73.217.175 Web Server : Apache/2.2.15 (Fedora) System : Linux km10.dyndns.org 2.6.31.5-127.fc12.i686.PAE #1 SMP Sat Nov 7 21:25:57 EST 2009 i686 User : apache ( 48) PHP Version : 5.3.3 Disable Function : NONE MySQL : ON | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /proc/self/root/usr/bin/ |
Upload File : |
#!/usr/bin/python
# The contents of this file are subject to the BitTorrent Open Source License
# Version 1.1 (the License). You may not copy or use this file, in either
# source code or executable form, except in compliance with the License. You
# may obtain a copy of the License at http://www.bittorrent.com/license/.
#
# Software distributed under the License is distributed on an AS IS basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
# Original version written by Henry 'Pi' James, modified by (at least)
# John Hoffman and Uoti Urpala
from __future__ import division
from BitTorrent.platform import install_translation
install_translation()
SPEW_SCROLL_RATE = 1
import sys
import os
import threading
from time import time, strftime
from BitTorrent.download import Feedback, Multitorrent
from BitTorrent.defaultargs import get_defaults
from BitTorrent.parseargs import printHelp
from BitTorrent.zurllib import urlopen
from BitTorrent.bencode import bdecode
from BitTorrent.ConvertedMetainfo import ConvertedMetainfo
from BitTorrent.prefs import Preferences
from BitTorrent.obsoletepythonsupport import import_curses
from BitTorrent import configfile
from BitTorrent import BTFailure
from BitTorrent import version
from BitTorrent import GetTorrent
try:
curses = import_curses()
import curses.panel
from curses.wrapper import wrapper as curses_wrapper
from signal import signal, SIGWINCH
except:
print _("Textmode GUI initialization failed, cannot proceed.")
print
print _("This download interface requires the standard Python module "
"\"curses\", which is unfortunately not available for the native "
"Windows port of Python. It is however available for the Cygwin "
"port of Python, running on all Win32 systems (www.cygwin.com).")
print
print _('You may still use "bittorrent-console" to download.')
sys.exit(1)
def fmttime(n):
if n == 0:
return _("download complete!")
try:
n = int(n)
assert n >= 0 and n < 5184000 # 60 days
except:
return _("<unknown>")
m, s = divmod(n, 60)
h, m = divmod(m, 60)
return _("finishing in %d:%02d:%02d") % (h, m, s)
def fmtsize(n):
s = str(n)
size = s[-3:]
while len(s) > 3:
s = s[:-3]
size = '%s,%s' % (s[-3:], size)
if n > 999:
unit = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']
i = 1
while i + 1 < len(unit) and (n >> 10) >= 999:
i += 1
n >>= 10
n /= (1 << 10)
size = '%s (%.0f %s)' % (size, n, unit[i])
return size
class CursesDisplayer(object):
def __init__(self, scrwin, errlist, doneflag, reread_config, ulrate):
self.scrwin = scrwin
self.errlist = errlist
self.doneflag = doneflag
signal(SIGWINCH, self.winch_handler)
self.changeflag = threading.Event()
self.done = False
self.reread_config = reread_config
self.ulrate = ulrate
self.activity = ''
self.status = ''
self.progress = ''
self.downRate = '---'
self.upRate = '---'
self.shareRating = ''
self.seedStatus = ''
self.peerStatus = ''
self.errors = []
self.file = ''
self.downloadTo = ''
self.fileSize = ''
self.numpieces = 0
self.spew_scroll_time = 0
self.spew_scroll_pos = 0
self._remake_window()
curses.use_default_colors()
def set_torrent_values(self, name, path, size, numpieces):
self.file = name
self.downloadTo = path
self.fileSize = fmtsize(size)
self.numpieces = numpieces
self._remake_window()
def winch_handler(self, signum, stackframe):
self.changeflag.set()
curses.endwin()
self.scrwin.refresh()
self.scrwin = curses.newwin(0, 0, 0, 0)
self._remake_window()
def _remake_window(self):
self.scrh, self.scrw = self.scrwin.getmaxyx()
self.scrpan = curses.panel.new_panel(self.scrwin)
self.labelh, self.labelw, self.labely, self.labelx = 11, 9, 1, 2
self.labelwin = curses.newwin(self.labelh, self.labelw,
self.labely, self.labelx)
self.labelpan = curses.panel.new_panel(self.labelwin)
self.fieldh, self.fieldw, self.fieldy, self.fieldx = (
self.labelh, self.scrw-2 - self.labelw-3,
1, self.labelw+3)
self.fieldwin = curses.newwin(self.fieldh, self.fieldw,
self.fieldy, self.fieldx)
self.fieldwin.nodelay(1)
self.fieldpan = curses.panel.new_panel(self.fieldwin)
self.spewh, self.speww, self.spewy, self.spewx = (
self.scrh - self.labelh - 2, self.scrw - 3, 1 + self.labelh, 2)
self.spewwin = curses.newwin(self.spewh, self.speww,
self.spewy, self.spewx)
self.spewpan = curses.panel.new_panel(self.spewwin)
try:
self.scrwin.border(ord('|'),ord('|'),ord('-'),ord('-'),ord(' '),ord(' '),ord(' '),ord(' '))
except:
pass
self.labelwin.addstr(0, 0, _("file:"))
self.labelwin.addstr(1, 0, _("size:"))
self.labelwin.addstr(2, 0, _("dest:"))
self.labelwin.addstr(3, 0, _("progress:"))
self.labelwin.addstr(4, 0, _("status:"))
self.labelwin.addstr(5, 0, _("dl speed:"))
self.labelwin.addstr(6, 0, _("ul speed:"))
self.labelwin.addstr(7, 0, _("sharing:"))
self.labelwin.addstr(8, 0, _("seeds:"))
self.labelwin.addstr(9, 0, _("peers:"))
curses.panel.update_panels()
curses.doupdate()
self.changeflag.clear()
def finished(self):
self.done = True
self.downRate = '---'
self.display({'activity':_("download succeeded"), 'fractionDone':1})
def error(self, errormsg):
newerrmsg = strftime('[%H:%M:%S] ') + errormsg
self.errors.append(newerrmsg.split('\n')[0])
self.errlist.append(newerrmsg)
self.display({})
def display(self, statistics):
fractionDone = statistics.get('fractionDone')
activity = statistics.get('activity')
timeEst = statistics.get('timeEst')
downRate = statistics.get('downRate')
upRate = statistics.get('upRate')
spew = statistics.get('spew')
inchar = self.fieldwin.getch()
if inchar == 12: # ^L
self._remake_window()
elif inchar in (ord('q'),ord('Q')):
self.doneflag.set()
elif inchar in (ord('r'),ord('R')):
self.reread_config()
elif inchar in (ord('u'),ord('U')):
curses.echo()
self.fieldwin.nodelay(0)
s = self.fieldwin.getstr(6,10)
curses.noecho()
self.fieldwin.nodelay(1)
r = None
try:
r = int(s)
except ValueError:
pass
if r is not None:
self.ulrate(r)
if timeEst is not None:
self.activity = fmttime(timeEst)
elif activity is not None:
self.activity = activity
if self.changeflag.isSet():
return
if fractionDone is not None:
blocknum = int(self.fieldw * fractionDone)
self.progress = blocknum * '#' + (self.fieldw - blocknum) * '_'
self.status = '%s (%.1f%%)' % (self.activity, fractionDone * 100)
if downRate is not None:
self.downRate = '%.1f KB/s' % (downRate / (1 << 10))
if upRate is not None:
self.upRate = '%.1f KB/s' % (upRate / (1 << 10))
downTotal = statistics.get('downTotal')
if downTotal is not None:
upTotal = statistics['upTotal']
if downTotal <= upTotal / 100:
self.shareRating = _("oo (%.1f MB up / %.1f MB down)") % (
upTotal / (1<<20), downTotal / (1<<20))
else:
self.shareRating = _("%.3f (%.1f MB up / %.1f MB down)") % (
upTotal / downTotal, upTotal / (1<<20), downTotal / (1<<20))
numCopies = statistics['numCopies']
nextCopies = ', '.join(["%d:%.1f%%" % (a,int(b*1000)/10) for a,b in
zip(xrange(numCopies+1, 1000), statistics['numCopyList'])])
if not self.done:
self.seedStatus = _("%d seen now, plus %d distributed copies"
"(%s)") % (statistics['numSeeds' ],
statistics['numCopies'],
nextCopies)
else:
self.seedStatus = _("%d distributed copies (next: %s)") % (
statistics['numCopies'], nextCopies)
self.peerStatus = _("%d seen now") % statistics['numPeers']
self.fieldwin.erase()
self.fieldwin.addnstr(0, 0, self.file, self.fieldw, curses.A_BOLD)
self.fieldwin.addnstr(1, 0, self.fileSize, self.fieldw)
self.fieldwin.addnstr(2, 0, self.downloadTo, self.fieldw)
if self.progress:
self.fieldwin.addnstr(3, 0, self.progress, self.fieldw, curses.A_BOLD)
self.fieldwin.addnstr(4, 0, self.status, self.fieldw)
self.fieldwin.addnstr(5, 0, self.downRate, self.fieldw)
self.fieldwin.addnstr(6, 0, self.upRate, self.fieldw)
self.fieldwin.addnstr(7, 0, self.shareRating, self.fieldw)
self.fieldwin.addnstr(8, 0, self.seedStatus, self.fieldw)
self.fieldwin.addnstr(9, 0, self.peerStatus, self.fieldw)
self.spewwin.erase()
if not spew:
errsize = self.spewh
if self.errors:
self.spewwin.addnstr(0, 0, _("error(s):"), self.speww, curses.A_BOLD)
errsize = len(self.errors)
displaysize = min(errsize, self.spewh)
displaytop = errsize - displaysize
for i in range(displaysize):
self.spewwin.addnstr(i, self.labelw, self.errors[displaytop + i],
self.speww-self.labelw-1, curses.A_BOLD)
else:
if self.errors:
self.spewwin.addnstr(0, 0, _("error:"), self.speww, curses.A_BOLD)
self.spewwin.addnstr(0, self.labelw, self.errors[-1],
self.speww-self.labelw-1, curses.A_BOLD)
self.spewwin.addnstr(2, 0, _(" # IP Upload Download Completed Speed"), self.speww, curses.A_BOLD)
if self.spew_scroll_time + SPEW_SCROLL_RATE < time():
self.spew_scroll_time = time()
if len(spew) > self.spewh-5 or self.spew_scroll_pos > 0:
self.spew_scroll_pos += 1
if self.spew_scroll_pos > len(spew):
self.spew_scroll_pos = 0
for i in range(len(spew)):
spew[i]['lineno'] = i+1
spew.append({'lineno': None})
spew = spew[self.spew_scroll_pos:] + spew[:self.spew_scroll_pos]
for i in range(min(self.spewh - 5, len(spew))):
if not spew[i]['lineno']:
continue
self.spewwin.addnstr(i+3, 0, '%3d' % spew[i]['lineno'], 3)
self.spewwin.addnstr(i+3, 4, spew[i]['ip'], 15)
ul = spew[i]['upload']
if ul[1] > 100:
self.spewwin.addnstr(i+3, 20, '%6.0f KB/s' % (
ul[1] / 1000), 11)
self.spewwin.addnstr(i+3, 32, '-----', 5)
if ul[2]:
self.spewwin.addnstr(i+3, 33, 'I', 1)
if ul[3]:
self.spewwin.addnstr(i+3, 35, 'C', 1)
dl = spew[i]['download']
if dl[1] > 100:
self.spewwin.addnstr(i+3, 38, '%6.0f KB/s' % (
dl[1] / 1000), 11)
self.spewwin.addnstr(i+3, 50, '-------', 7)
if dl[2]:
self.spewwin.addnstr(i+3, 51, 'I', 1)
if dl[3]:
self.spewwin.addnstr(i+3, 53, 'C', 1)
if dl[4]:
self.spewwin.addnstr(i+3, 55, 'S', 1)
self.spewwin.addnstr(i+3, 58, '%5.1f%%' % (int(spew[i]['completed']*1000)/10), 6)
if spew[i]['speed'] is not None:
self.spewwin.addnstr(i+3, 64, '%5.0f KB/s' % (spew[i]['speed']/1000), 10)
self.spewwin.addnstr(self.spewh-1, 0,
_("downloading %d pieces, have %d fragments, "
"%d of %d pieces completed") %
(statistics['storage_active'], statistics['storage_dirty'],
statistics['storage_numcomplete'], self.numpieces),
self.speww-1)
curses.panel.update_panels()
curses.doupdate()
class DL(Feedback):
def __init__(self, metainfo, config, errlist):
self.doneflag = threading.Event()
self.metainfo = metainfo
self.config = Preferences().initWithDict(config)
self.errlist = errlist
def run(self, scrwin):
def reread():
self.multitorrent.rawserver.external_add_task(self.reread_config,0)
def ulrate(value):
self.multitorrent.set_option('max_upload_rate', value)
self.torrent.set_option('max_upload_rate', value)
self.d = CursesDisplayer(scrwin, self.errlist, self.doneflag, reread, ulrate)
try:
self.multitorrent = Multitorrent(self.config, self.doneflag,
self.global_error)
# raises BTFailure if bad
metainfo = ConvertedMetainfo(bdecode(self.metainfo))
torrent_name = metainfo.name_fs
if config['save_as']:
if config['save_in']:
raise BTFailure(_("You cannot specify both --save_as and "
"--save_in"))
saveas = config['save_as']
elif config['save_in']:
saveas = os.path.join(config['save_in'], torrent_name)
else:
saveas = torrent_name
self.d.set_torrent_values(metainfo.name, os.path.abspath(saveas),
metainfo.total_bytes, len(metainfo.hashes))
self.torrent = self.multitorrent.start_torrent(metainfo,
Preferences(self.config), self, saveas)
except BTFailure, e:
errlist.append(str(e))
return
self.get_status()
self.multitorrent.rawserver.install_sigint_handler()
self.multitorrent.rawserver.listen_forever()
self.d.display({'activity':_("shutting down"), 'fractionDone':0})
self.torrent.shutdown()
def reread_config(self):
try:
newvalues = configfile.get_config(self.config, 'bittorrent-curses')
except Exception, e:
self.d.error(_("Error reading config: ") + str(e))
return
self.config.update(newvalues)
# The set_option call can potentially trigger something that kills
# the torrent (when writing this the only possibility is a change in
# max_files_open causing an IOError while closing files), and so
# the self.failed() callback can run during this loop.
for option, value in newvalues.iteritems():
self.multitorrent.set_option(option, value)
for option, value in newvalues.iteritems():
self.torrent.set_option(option, value)
def get_status(self):
self.multitorrent.rawserver.add_task(self.get_status,
self.config['display_interval'])
status = self.torrent.get_status(self.config['spew'])
self.d.display(status)
def global_error(self, level, text):
self.d.error(text)
def error(self, torrent, level, text):
self.d.error(text)
def failed(self, torrent, is_external):
self.doneflag.set()
def finished(self, torrent):
self.d.finished()
if __name__ == '__main__':
uiname = 'bittorrent-curses'
defaults = get_defaults(uiname)
metainfo = None
if len(sys.argv) <= 1:
printHelp(uiname, defaults)
sys.exit(1)
try:
config, args = configfile.parse_configuration_and_args(defaults,
uiname, sys.argv[1:], 0, 1)
torrentfile = None
if len(args):
torrentfile = args[0]
for opt in ('responsefile', 'url'):
if config[opt]:
print '"--%s"' % opt, _("deprecated, do not use")
torrentfile = config[opt]
if torrentfile is not None:
metainfo, errors = GetTorrent.get(torrentfile)
if errors:
raise BTFailure(_("Error reading .torrent file: ") + '\n'.join(errors))
else:
raise BTFailure(_("you must specify a .torrent file"))
except BTFailure, e:
print str(e)
sys.exit(1)
errlist = []
dl = DL(metainfo, config, errlist)
curses_wrapper(dl.run)
if errlist:
print _("These errors occurred during execution:")
for error in errlist:
print error