From: <bel...@us...> - 2003-02-25 23:43:21
|
Update of /cvsroot/btplusplus/BT++/src/WebServer In directory sc8-pr-cvs1:/tmp/cvs-serv4449/src/WebServer Added Files: BTWebServer.py HTTPConfigFile.py __init__.py Log Message: WebServer & Completed abstraction of LoaderManager --- NEW FILE: BTWebServer.py --- from BaseHTTPServer import * from ConfigFile import Config from HTTPConfigFile import HTTPConfig from threading import Event from os import listdir, path from TabTrans.LoaderManager import LoaderManager from urlparse import urlparse from urllib import unquote from urllib2 import urlopen from time import sleep, localtime, strftime from BTConstants import * import socket import posixpath import sys __version__ = "0.1" Checked = {0: '', 1:'CHECKED', '0': '', '1':'CHECKED'} HTTP_ROOT = """\ <html> <head> <title>WebTorrent++</title> </head> <frameset rows="50,*"> <frame name="top" src="menu"> <frame name="body" src="torrents"> </frameset> </html> """ HTTP_MENU = """\ <head> <title>Success</title> </head> <body bgcolor=#%s> <table width=100%%><tr> <td><form method=get action="torrents" target="body"><button type=submit>Torrents</button></form></td> <td nowrap><form method=get action="log" target="body"><button type=submit>View Log</button></form></td> <td><form method=get action="config" target="body"><button type=submit>Config</button></form></td> <td width=80%%><form method=post action="torrents" target="body"> <table width=100%% border=1 bgcolor=#%s><tr> <td width=100%%><input type=text style="width:100%%" name=torr title="Paste Torrent URLs here"></td> <td><input type=hidden name=command value=Add><button type=submit>Add</button></td> </tr></table> </form></td> <td nowrap><form method=get action="exit" target="body"><button type=submit>Kill server</button></form></td> </tr></table> </body> """ HTTP_EXIT = """\ <head> <title>Exit</title> </head> <body> <h1>Server Killed.</h1> </body> """ HTTP_DL_ERROR = """\ <head> <title>Download Error</title> </head> <body> <h1>Error downloading Torrent %s</h1> </body> """ LOG_LEVEL_DESC = """\ <table style="font-size:x-small"> <tr><td width=1%%></td><td align=right>0</td><td width=100%%>Trivial</td></tr> <tr><td width=1%%></td><td align=right>1</td><td width=100%%>Info</td></tr> <tr><td width=1%%></td><td align=right>2</td><td width=100%%>Errors</td></tr> <tr><td width=1%%></td><td align=right>3</td><td width=100%%>Critical Errors</td></tr> </table> """ ########################################################################################################### ########################################################################################################### ########################################################################################################### ########################################################################################################### BTWait = Event() ########################################################################################################### ########################################################################################################### ########################################################################################################### ########################################################################################################### WebLog = [] def WebLogit(a, loglevel = LOG_INFO): if loglevel >= int(HTTPConfig.Get('Display', 'LogLevel')): WebLog.append(strftime("[%a, %d %b %Y %H:%M:%S]_", localtime()) + a) if len(WebLog) > int(HTTPConfig.Get('Display', 'LogCount')): WebLog.pop() BTHandler = LoaderManager(log = WebLogit) ########################################################################################################### ########################################################################################################### ########################################################################################################### ########################################################################################################### class BTHTTPHandler(BaseHTTPRequestHandler): server_version = "BTHTTP/" + __version__ def do_GET(self): """Serve a GET request.""" self.send_head() if self.requested == '': self.wfile.write(HTTP_ROOT) elif self.requested == 'torrents': BTHandler.Update() sleep(0.5) self.send_torrents() elif self.requested == 'config': self.send_config() elif self.requested == 'menu': self.wfile.write(HTTP_MENU % (HTTPConfig.Get('WebColors','MenuBackground'),HTTPConfig.Get('WebColors','MenuAddbar'))) elif self.requested == 'log': self.send_log() elif self.requested == 'exit': self.wfile.write(HTTP_EXIT) for loader in BTHandler.Loaders: if loader.IsRunning(): loader.PauseDownload() # for loader in BTHandler.Seeds: # if loader.IsRunning(): loader.PauseDownload() BTWait.set() def do_HEAD(self): """Serve a HEAD request.""" self.send_head() def do_POST(self): self.send_head() length = self.headers.getheader('content-length') res = self.rfile.read(int(length)) res = res.replace('+', ' ') result = dict([x.split('=') for x in res.split('&')]) #self.wfile.write(HTTP_TEST % (result['command'])) if self.requested == 'torrents': if result['command']=='Pause': if result['seed']=='0': BTHandler.Loaders[int(result['nr'])-1].PauseDownload() else: BTHandler.Seeds[int(result['nr'])-1].PauseDownload() elif result['command']=='Resume': if result['seed']=='0': BTHandler.Loaders[int(result['nr'])-1].StartDownload() else: BTHandler.Seeds[int(result['nr'])-1].StartDownload() elif result['command']=='MoveUp': c = int(result['nr']) if result['seed']=='0': BTHandler.Move(c-1, c-2) else: BTHandler.MoveSeed(c-1, c-2) elif result['command']=='MoveDown': c = int(result['nr']) if result['seed']=='0': BTHandler.Move(c-1, c) else: BTHandler.MoveSeed(c-1, c) elif result['command']=='Add': url = result['torr'] if url!='': try: url = unquote(url) h = urlopen(url) spl = urlparse(url) file = path.split(spl[2])[1] if file == '': raise data = h.read() h.close() f = open( path.join(Config.Get('Paths', 'Torrent'), file), 'wb' ) f.write( data ) f.close() except: self.wfile.write(HTTP_DL_ERROR % url) return elif result['command']=='Config': for key in result: if key != 'command': majkey, minkey = key.split('_') if majkey in ['Host','Access','Display','WebColors']: HTTPConfig.Set(majkey, minkey, result[key]) elif (majkey == 'Paths') or (minkey == 'Ip'): Config.Set(majkey, minkey, result[key]) else: Config.Set(majkey, minkey, int(result[key])) Config.Save() HTTPConfig.Save() WebLogit("Configuration Changed.", loglevel = LOG_TRIVIAL) BTHandler.Update() sleep(0.5) self.send_torrents() def send_head(self): """Common code for GET and HEAD commands. This sends the response code and MIME headers. Return value is either a file object (which has to be copied to the outputfile by the caller unless the command was HEAD, and must be closed by the caller under all circumstances), or None, in which case the caller has nothing further to do. """ #path = self.translate_path(self.path) #f = None #if os.path.isdir(path): # for index in "index.html", "index.htm": # index = os.path.join(path, index) # if os.path.exists(index): # path = index # break # else: # return self.list_directory(path) temp = posixpath.normpath(unquote(self.path)) dummy, self.requested = temp.split('/') self.requested = self.requested.replace('?',''); if self.requested in ['','exit','menu','torrents','config','log']: self.send_response(200) self.send_header("Content-type", "text/html") self.send_header("Expires", "Mon, 26 Jul 1997 05:00:00 GMT") self.end_headers() else: self.send_error(404, "File not found") def send_torrents(self): ret = "<html>\n<head>\n<title>WebTorrent++ Download Status</title>\n" ret = ret + "<META HTTP-EQUIV=\"Refresh\" CONTENT=\""+HTTPConfig.Get('Display', 'Refresh')+"\">\n" ret = ret + "</head>\n<body bgcolor=#%s>" % HTTPConfig.Get('WebColors','TorrBackground') if BTHandler.Loaders: ret = ret + "<table border=1 width=100% cellpadding=3>\n<tr bgcolor=#DDDDDD><th colspan=2>Incomplete</th><th align=left>File</th><th>Size</th><th>Transfered</th><th>Speed</th><th>Status</th><th width=15%>Progress</th><th>Remaining</th></tr>\n" c = 0 for loader in BTHandler.Loaders: c = c + 1 if loader.IsFinished(): ret = ret + "<tr bgcolor=#%s>" % HTTPConfig.Get('WebColors','TorrFinished') if c <= Config.Get('Download', 'MaxSimDown'): ret = ret + "<tr bgcolor=#%s>" % HTTPConfig.Get('WebColors','TorrAuto') else: ret = ret + "<tr bgcolor=#%s>" % HTTPConfig.Get('WebColors','TorrNonAuto') if loader.Info['Status']!='Paused': cc = 'Pause' else: cc = 'Resume' ret = ret + "<form method=\"POST\" action=\"torrents\"><td>" ret = ret + "<button type=submit name=command value=%s>%s</button></td><td>" % (cc,cc) if c == 1: cc = 'DISABLED' else: cc = '' ret = ret + "<table><tr><td><button type=submit name=command %s value=MoveUp style=\"font-size:xx-small; font-weight:bold\">↑</button></td></tr>" % (cc) if c == len(BTHandler.Loaders): cc = 'DISABLED' else: cc = '' ret = ret + "<tr><td><button type=submit name=command %s value=MoveDown style=\"font-size:xx-small; font-weight:bold\">↓</button></td></tr></table>" % (cc) ret = ret + "<input type=hidden name=seed value=0><input type=hidden name=nr value=%d>" % (c) ret = ret + "</td></form>" ret = ret + "<td align=left>" + loader.Config['File'] + "</td>" ret = ret + "<td align=center>" + ('%.2f MB' % (loader.Config['Size'] / 1024 / 1024)) + "</td><td align=center>" if loader.Info['FractionDone'] == -1: ret = ret + '?' else: ret = ret + ('%.2f MB' % (loader.Info['FractionDone'] * loader.Config['Size'] / 1024 / 1024)) ret = ret + "</td><td align=center>" + ('%.1f / %.1f' % (loader.Info['SpeedDown'], loader.Info['SpeedUp'])) + "</td>" ret = ret + "<td align=center>" + loader.Info['Status'] ret = ret + "</td><td><table width=100% bordercolor=#0000BB border=1><tr><td><table width=100% height=100%><tr>" if loader.Info['Status']=='Hashing': c1='#FF0000' c2='#0000FF' else: c1='#00FF00' c2='#FF0000' if loader.Info['FractionDone'] == -1: ret = ret + '<td bgcolor=#0000FF width=100%> </td>' else: ret = ret + ('<td bgcolor=%s width=%d%%> </td><td bgcolor=%s width=%d%%> </td>' % (c1, loader.Info['FractionDone']*100, c2, loader.Info['FractionRemain']*100)) ret = ret + "</tr></table></td></tr></table></td>" ret = ret + ('<td align=center>%.1f%% [%.2f MB]</td>' % (loader.Info['FractionRemain'] * 100, loader.Info['FractionRemain'] * loader.Config['Size'] / 1024 / 1024)) ret = ret + "</tr>\n" ret = ret + "</table>\n" else: ret = ret + "<p> No Torrents" ## if BTHandler.Seeds: ## ret = ret + "<p><table border=1 width=100% cellpadding=3>\n<tr bgcolor=#DDDDDD><th colspan=2>Seeds</th><th align=left>File</th><th>Size</th><th>Status</th><th>Speed</th></tr>\n" ## c = 0 ## for loader in BTHandler.Seeds: ## c = c + 1 ## if c <= HTTPConfig.Get('Seed', 'MaxSimSeed'): ## ret = ret + "<tr bgcolor=#FFCCCC>" ## else: ## ret = ret + "<tr bgcolor=#D8BFBC>" ## if loader.Info['Status']!='Paused': ## cc = 'Pause' ## else: ## cc = 'Resume' ## ret = ret + "<form method=\"POST\" action=\"torrents\"><td>" ## ret = ret + "<button type=submit name=command value=%s>%s</button></td><td>" % (cc,cc) ## if c == 1: ## cc = 'DISABLED' ## else: ## cc = '' ## ret = ret + "<table><tr><td><button type=submit name=command %s value=MoveUp style=\"font-size:xx-small; font-weight:bold\">↑</button></td></tr>" % (cc) ## if c == len(BTHandler.Seeds): ## cc = 'DISABLED' ## else: ## cc = '' ## ret = ret + "<tr><td><button type=submit name=command %s value=MoveDown style=\"font-size:xx-small; font-weight:bold\">↓</button></td></tr></table>" % (cc) ## ret = ret + "<input type=hidden name=seed value=1><input type=hidden name=nr value=%d>" % (c) ## ret = ret + "</td></form>" ## ret = ret + "<td align=left width=70%>" + loader.Config['File'] + "</td>" ## ret = ret + "<td align=center>" + ('%.2f MB' % (loader.Config['Size'] / 1024 / 1024)) + "</td>" ## if loader.Info['Status']!='Hashing': ## ret = ret + "<td align=center>" + loader.Info['Status'] ## else: ## ret = ret + ('<td align=center>Hashing (%.1f%%)' % (loader.Info['FractionDone'] * 100)) ## ret = ret + "</td><td align=center>" + ('%.1f' % (loader.Info['SpeedUp'])) + "</td>" ## ret = ret + "</tr>\n" ## ret = ret + "</table>\n" ## if BTHandler.StaleSeeds: ## ret = ret + "<p><table border=1 cellpadding=10><tr><td><b style=\"color:red\">Stale Seeds (content lacking):</b></td></tr><tr><td><b>" ## for s in BTHandler.StaleSeeds: ## ret = ret + s + "<br>" ## ret = ret + "</b></td></tr></table>" ret = ret + "</body>\n</html>\n" self.wfile.write(ret) def send_config(self): ret = "<html>\n<head>\n<title>WebTorrent++ Configuration</title>\n" ret = ret + "</head>\n<body bgcolor=#%s>\n<form method=post action=\"torrents\">\n" % HTTPConfig.Get('WebColors','ConfBackground') ret = ret + "<table width=100%% border=1 bgcolor=#%s><tr><th colspan=2 align=left>Directories</th></tr>\n" % HTTPConfig.Get('WebColors','ConfTable') ret = ret + "<tr><td>Torrent</td><td width=80%%><input type=text style=\"width:100%%\" name=Paths_Torrent value=\"%s\"></td></tr>\n" % (Config.Get('Paths', 'Torrent')) ret = ret + "<tr><td>History</td><td width=80%%><input type=text style=\"width:100%%\" name=Paths_History value=\"%s\"></td></tr>\n" % (Config.Get('Paths', 'History')) ret = ret + "<tr><td>Incoming</td><td width=80%%><input type=text style=\"width:100%%\" name=Paths_Incoming value=\"%s\"></td></tr>\n" % (Config.Get('Paths', 'Incoming')) ret = ret + "<tr><td>Temp</td><td width=80%%><input type=text style=\"width:100%%\" name=Paths_Temp value=\"%s\"></td></tr>\n" % (Config.Get('Paths', 'Temp')) ret = ret + "</table>\n" ret = ret + "<p><table width=100%% border=1 bgcolor=#%s><tr><th align=left>Basic</th></tr>\n" % HTTPConfig.Get('WebColors','ConfTable') ret = ret + "<tr><td><table border=1 width=100%>" ret = ret + "<tr><td>Automatically start new downloads</td><td width=5%% align=center><input type=checkbox name=Download_AutoStart %s value=\"1\"></td></tr>\n" % (Checked[Config.Get('Download', 'AutoStart')]) ret = ret + "<tr><td>Automatically pause downloads (if current>max)</td><td width=5%% align=center><input type=checkbox name=Download_AutoPause %s value=\"1\"></td></tr>\n" % (Checked[Config.Get('Download', 'AutoPause')]) ret = ret + "<tr><td>Maximal simultanous downloads (1-10)</td><td width=5%%><input type=text style=\"width:100%%\" name=Download_MaxSimDown value=\"%s\"></td></tr>\n" % (Config.Get('Download', 'MaxSimDown')) ret = ret + "</table></td></tr>" ## ret = ret + "<tr><td><table border=1 width=100%>" ## ret = ret + "<tr><td>Automatically pause downloads (if current>max)</td><td width=5%% align=center><input type=checkbox name=Seed_AutoPause %s value=\"1\"></td></tr>\n" % (Checked[HTTPConfig.Get('Seed', 'AutoStart')]) ## ret = ret + "<tr><td>Maximal simultanous downloads (1-10)</td><td width=5%%><input type=text style=\"width:100%%\" name=Seed_MaxSimDown value=\"%s\"></td></tr>\n" % (HTTPConfig.Get('Seed', 'MaxSimSeed')) ## ret = ret + "</table></td></tr>" ret = ret + "<tr><td><table border=1 width=100%>" ret = ret + "<tr><td>Maximal download speed (0=unlimited)</td><td width=5%%><input type=text style=\"width:100%%\" name=Download_MaxSpeedDown value=\"%s\"></td></tr>\n" % (Config.Get('Download', 'MaxSpeedDown')) ret = ret + "<tr><td>Maximal upload speed (0=unlimited)</td><td width=5%%><input type=text style=\"width:100%%\" name=Download_MaxSpeedUp value=\"%s\"></td></tr>\n" % (Config.Get('Download', 'MaxSpeedUp')) ret = ret + "</table></td></tr>" ret = ret + "<tr><td><table border=1 width=100%>" ret = ret + "<tr><td>Use background hashing</td><td width=5%% align=center><input type=checkbox name=Hash_Background %s value=\"1\"></td></tr>\n" % (Checked[Config.Get('Hash', 'Background')]) ret = ret + "<tr><td>Maximal simultanous files hashed (1-5)</td><td width=5%%><input type=text style=\"width:100%%\" name=Hash_NumSimHash value=\"%s\"></td></tr>\n" % (Config.Get('Hash', 'NumSimHash')) ret = ret + "</table></td></tr>" ret = ret + "</table>\n" ret = ret + "<p><table width=100%% border=1 bgcolor=#%s><tr><th align=left>Net Config</th></tr>\n" % HTTPConfig.Get('WebColors','ConfTable') ret = ret + "<tr><td><table border=1 width=100%>" ret = ret + "<tr><td>Bind to IP for BitTorrent (*)</td><td width=10%%><input type=text style=\"width:100%%\" name=Bind_Ip value=\"%s\"></td></tr>\n" % (Config.Get('Bind', 'Ip')) ret = ret + "<tr><td>First Port for BitTorrent (*)</td><td width=5%%><input type=text style=\"width:100%%\" name=Bind_PortMin value=\"%s\"></td></tr>\n" % (Config.Get('Bind', 'PortMin')) ret = ret + "<tr><td>Last Port for BitTorrent (*)</td><td width=5%%><input type=text style=\"width:100%%\" name=Bind_PortMax value=\"%s\"></td></tr>\n" % (Config.Get('Bind', 'PortMax')) ret = ret + "</table></td></tr>" ret = ret + "<tr><td><table border=1 width=100%>" ret = ret + "<tr><td>Bind to IP for webserver (*)</td><td width=10%%><input type=text style=\"width:100%%\" name=Host_IP value=\"%s\"></td></tr>\n" % (HTTPConfig.Get('Host', 'IP')) ret = ret + "<tr><td>Webserver port (*)</td><td width=5%%><input type=text style=\"width:100%%\" name=Host_Port value=\"%s\"></td></tr>\n" % (HTTPConfig.Get('Host', 'Port')) ## ret = ret + "</table></td></tr>" ## ret = ret + "<tr><td><table border=1 width=100%>" ret = ret + "<tr><td>Allow access from localhost</td><td width=5%% align=center><input type=checkbox name=Access_AllowLocal %s value=\"1\"></td></tr>\n" % (Checked[HTTPConfig.Get('Access', 'AllowLocal')]) ret = ret + "<tr><td>Allow access from external IPs (separated by space)</td><td width=30%%><input type=text style=\"width:100%%\" name=Access_ValidIPs value=\"%s\"></td></tr>\n" % (HTTPConfig.Get('Access', 'ValidIPs')) ret = ret + "</table></td></tr>" ret = ret + "<tr><td><table border=1 width=100%>" ret = ret + "<tr><td>Refresh torrent page every (seconds)</td><td width=5%%><input type=text style=\"width:100%%\" name=Display_Refresh value=\"%s\"></td></tr>\n" % (HTTPConfig.Get('Display', 'Refresh')) ret = ret + "<tr><td>Log Level (default = 1)<br>" + LOG_LEVEL_DESC + "</td><td width=5%%><input type=text style=\"width:100%%\" name=Display_LogLevel value=\"%s\"></td></tr>\n" % (HTTPConfig.Get('Display', 'LogLevel')) ret = ret + "<tr><td>Number of kept Log entries (default = 200)</td><td width=5%%><input type=text style=\"width:100%%\" name=Display_LogCount value=\"%s\"></td></tr>\n" % (HTTPConfig.Get('Display', 'LogCount')) ret = ret + "</table></td></tr>" ret = ret + "</table>\n" ret = ret + "(*) changes require restart.\n" ret = ret + "<p><center><input type=hidden name=command value=Config><button type=submit>Submit Changes</button></center>\n</form>\n</body>\n</html>\n" self.wfile.write(ret) def send_log(self): ret = "<html>\n<head>\n<title>WebTorrent++ Log</title>\n" ret = ret + "</head>\n<body bgcolor=#%s>\n" % HTTPConfig.Get('WebColors','LogBackground') ret = ret + "<h1>WebTorrent++ Log</h1>\n<table bgcolor=#%s border=1 cellpadding=4>\n" % HTTPConfig.Get('WebColors','LogTable') t = WebLog[:] try: t.reverse() except: pass for line in t: sp = str(line).split('_',1) ret = ret + "<tr><td nowrap>%s</td><td width=100%%>%s</td></tr>\n" % (sp[0], sp[1]) ret = ret + "</table>\n</body>\n</html>" self.wfile.write(ret) ########################################################################################################### ########################################################################################################### ########################################################################################################### ########################################################################################################### class BTWebServer(HTTPServer): def __init__(self): try: mkdir(Config.Get('Paths', 'Incoming')) except: pass try: mkdir(Config.Get('Paths', 'Torrent')) except: pass try: mkdir(Config.Get('Paths', 'History')) except: pass try: mkdir(Config.Get('Paths', 'Temp')) except: pass self.localIP = socket.gethostbyname(socket.gethostname()) HTTPServer.__init__(self, (HTTPConfig.Get('Host','IP'), int(HTTPConfig.Get('Host', 'Port'))), BTHTTPHandler) def verify_request(self, request, client_address): validIPList = HTTPConfig.Get('Access', 'ValidIPs').split(' ') if int(HTTPConfig.Get('Access', 'AllowLocal')) == 1: validIPList.append(self.localIP) validIPList.append('127.0.0.1') if client_address[0] in validIPList: return 1 else: return 0 def server(self): self.serve_forever() --- NEW FILE: HTTPConfigFile.py --- from ConfigFile import ConfigFile http_cfg_default = { 'Host': { 'IP': '', 'Port': '5080' }, 'Access': { 'ValidIPs': '', 'AllowLocal': '1' }, 'Display': { 'Refresh': '10', 'LogLevel': '1', 'LogCount': '200' }, ## 'Seed': { ## 'AutoStart': 1, ## 'MaxSimSeed': 3 ## }, 'WebColors': { 'MenuBackground': 'FFFFCC', 'MenuAddbar': 'FFCCCC', 'TorrBackground': 'CCCC00', 'TorrFinished': 'FFCCCC', 'TorrAuto': 'CCFFCC', 'TorrNonAuto': 'BFD8BC', 'ConfBackground': '6666AA', 'ConfTable': 'CCCCFF', 'LogBackground': 'AA6666', 'LogTable': 'FF6666' } } HTTPConfig = ConfigFile() HTTPConfig.Read('http.ini') HTTPConfig.InstallDefaults(http_cfg_default) --- NEW FILE: __init__.py --- |