diff --git a/plugins/WebUi/__init__.py b/plugins/WebUi/__init__.py index 220db62be..d7c28a3a1 100644 --- a/plugins/WebUi/__init__.py +++ b/plugins/WebUi/__init__.py @@ -36,13 +36,12 @@ plugin_description = "A Web based User Interface\n" import deluge.common import deluge.pref from deluge.dialogs import show_popup_warning -from dbus_interface import get_dbus_manager +from dbus_interface import DbusManager import gtk import os from subprocess import Popen from md5 import md5 -from threading import Thread import random random.seed() @@ -50,6 +49,10 @@ plugin_version += open(os.path.join(os.path.dirname(__file__),'revno')).read() plugin_description += ( open(os.path.join(os.path.dirname(__file__),'version')).read()) +#not found a way to stop a dbus manager. +#global so it does not get started twice. +dbus_manager = None + def deluge_init(deluge_path): global path path = deluge_path @@ -58,27 +61,15 @@ def enable(core, interface): global path return plugin_WebUi(path, core, interface) -class WebServerThread(Thread): - - def run(self): - #must be imported after plugin-load because of dbus: - import webserver_common - reload(webserver_common) #HACK!!! - from deluge_webserver import WebServer #only import in threaded mode - self.web_server = WebServer() - self.web_server.start() - - def stop(self): - print 'WebUi : Stop threaded server' - self.web_server.stop() - -class plugin_WebUi(object): +class plugin_WebUi: def __init__(self, path, deluge_core, deluge_interface): + global dbus_manager self.path = path self.core = deluge_core self.interface = deluge_interface self.proc = None - self.web_server_thread = None + + self.config_file = deluge.common.CONFIG_DIR + "/webui.conf" self.config = deluge.pref.Preferences(self.config_file, False) @@ -107,17 +98,19 @@ class plugin_WebUi(object): if self.config.get("cache_templates") == None: self.config.set("cache_templates", True) - if self.config.get("run_in_thread") == None: - self.config.set("run_in_thread", True) - self.dbus_manager = get_dbus_manager(deluge_core, deluge_interface, - self.config, self.config_file) + if not dbus_manager: + self.dbusManager = DbusManager(deluge_core, deluge_interface + , self.config, self.config_file) + + self.dbus_manager = dbus_manager self.start_server() def unload(self): print 'WebUI:unload..' self.kill_server() + #self.dbusManager. def update(self): pass @@ -131,30 +124,18 @@ class plugin_WebUi(object): def start_server(self): self.kill_server() - - if self.config.get("run_in_thread"): - print 'start Webui(in thread)..' - self.web_server_thread = WebServerThread() - self.web_server_thread.start() - else: - print 'start Webui(in process)..' - path = os.path.dirname(__file__) - server_bin = path + '/run_webserver' - port = str(self.config.get('port')) - self.proc = Popen((server_bin, port),cwd=path) + print 'start Webui..' + path = os.path.dirname(__file__) + server_bin = path + '/run_webserver' + port = str(self.config.get('port')) + self.proc = Popen((server_bin, port),cwd=path) def kill_server(self): - if self.web_server_thread: - self.web_server_thread.stop() if self.proc: - print "webserver: kill %i" % self.proc.pid - os.system("kill %i" % self.proc.pid) + print "webserver: kill %i"%self.proc.pid + os.system("kill %i"%self.proc.pid) self.proc = None - def __del__(self): - self.kill_server() - - class ConfigDialog(gtk.Dialog): """ @@ -179,15 +160,12 @@ class ConfigDialog(gtk.Dialog): self.template = self.add_widget(_('Template'), gtk.combo_box_new_text()) self.button_style = self.add_widget(_('Button Style'), gtk.combo_box_new_text()) + self.cache_templates = self.add_widget(_('Cache Templates'), + gtk.CheckButton()) self.download_dir = self.add_widget(_('Download Directory'), gtk.FileChooserButton(_('Download Directory'))) self.torrent_dir = self.add_widget(_('Torrent Directory'), gtk.FileChooserButton(_('Torrent Directory'))) - self.cache_templates = self.add_widget(_('Cache Templates'), - gtk.CheckButton()) - self.run_in_thread = self.add_widget(_('Run in thread'), - gtk.CheckButton()) - self.download_dir.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) self.torrent_dir.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) @@ -211,13 +189,10 @@ class ConfigDialog(gtk.Dialog): self.template.set_active( self.templates.index(self.config.get("template"))) self.button_style.set_active(self.config.get("button_style")) + self.cache_templates.set_active(self.config.get("cache_templates")) self.torrent_dir.set_filename(self.config.get("torrent_dir")) self.download_dir.set_filename(self.config.get("download_dir")) - - self.run_in_thread.set_active(self.config.get("run_in_thread")) - self.cache_templates.set_active(self.config.get("cache_templates")) - self.vbox.pack_start(self.vb, True, True, 0) self.vb.show_all() @@ -251,9 +226,17 @@ class ConfigDialog(gtk.Dialog): self.config.set("port", int(self.port.get_value())) self.config.set("template", self.template.get_active_text()) self.config.set("button_style", self.button_style.get_active()) + self.config.set("cache_templates", self.cache_templates.get_active()) self.config.set("torrent_dir", self.torrent_dir.get_filename()) self.config.set("download_dir",self.download_dir.get_filename()) - self.config.set("cache_templates", self.cache_templates.get_active()) - self.config.set("run_in_thread", self.run_in_thread.get_active()) self.config.save(self.plugin.config_file) self.plugin.start_server() #restarts server + + + + + + + + + diff --git a/plugins/WebUi/dbus_interface.py b/plugins/WebUi/dbus_interface.py index 79ba53666..d44666da6 100644 --- a/plugins/WebUi/dbus_interface.py +++ b/plugins/WebUi/dbus_interface.py @@ -32,25 +32,20 @@ # this exception statement from your version. If you delete this exception # statement from all source files in the program, then also delete it here. + import os import gtk import dbus import deluge.common as common from dbus_pythonize import pythonize import base64 +from md5 import md5 import random random.seed() dbus_interface="org.deluge_torrent.dbusplugin" dbus_service="/org/deluge_torrent/DelugeDbusPlugin" -dbus_manager = None -def get_dbus_manager(*args): - #another way to make a singleton. - global dbus_manager - if not dbus_manager: - dbus_manager = DbusManager(*args) - return dbus_manager class DbusManager(dbus.service.Object): def __init__(self, core, interface,config,config_file): @@ -94,7 +89,7 @@ class DbusManager(dbus.service.Object): "name": state["name"], "total_size": state["total_size"], "num_pieces": state["num_pieces"], - "state": state['state'], + #"state": int(status.state), #? "paused": self.core.is_user_paused(torrent_id), "progress": int(state["progress"] * 100), "next_announce": state["next_announce"], @@ -108,6 +103,7 @@ class DbusManager(dbus.service.Object): "eta": common.estimate_eta(state), "ratio": self.interface.manager.calc_ratio(torrent_id,state), #non 0.6 values follow here: + "message": self.interface.get_message_from_state(state), "tracker_status": state.get("tracker_status","?"), "uploaded_memory": torrent.uploaded_memory, } @@ -179,6 +175,39 @@ class DbusManager(dbus.service.Object): self._add_torrent(filename) return True + @dbus.service.method(dbus_interface=dbus_interface, + in_signature="s",out_signature="v") + def get_webui_config(self,key): + """ + return data from wevbui config. + not in 0.6 + """ + retval = self.config.get(str(key)) + #print 'get webui config:', str(key), retval + if retval == None: + retval = False #dbus does not accept None :( + + return retval + + @dbus.service.method(dbus_interface=dbus_interface, + in_signature="sv",out_signature="") + def set_webui_config(self, key, value): + """ + return data from wevbui config. + not in 0.6 + """ + #print 'set webui config:', str(key), pythonize(value) + self.config.set(str(key), pythonize(value)) + self.config.save(self.config_file) + + @dbus.service.method(dbus_interface=dbus_interface, + in_signature="s",out_signature="b") + def check_pwd(self, pwd): + m = md5() + m.update(self.config.get('pwd_salt')) + m.update(pwd) + return (m.digest() == self.config.get('pwd_md5')) + #internal def _add_torrent(self, filename): #dbus types break pickle, again..... diff --git a/plugins/WebUi/deluge_webserver.py b/plugins/WebUi/deluge_webserver.py index 4d2e9db40..5ba5104f3 100644 --- a/plugins/WebUi/deluge_webserver.py +++ b/plugins/WebUi/deluge_webserver.py @@ -31,33 +31,149 @@ # this exception statement from your version. If you delete this exception # statement from all source files in the program, then also delete it here. - -from webserver_common import proxy, config ,TORRENT_KEYS, STATE_MESSAGES -from webserver_framework import * - - +""" +Todo's before stable: +-__init__:kill->restart is not waiting for kill to be finished. +--later/features:--- +-alternating rows? +-set prio +-clear finished? +-torrent files. +""" import webpy022 as web -from webpy022.http import seeother, url -from webpy022.webapi import setcookie -from webpy022.utils import Storage -from md5 import md5 -from deluge.common import fsize +from webpy022.webapi import cookies, setcookie +from webpy022.http import seeother, url +from webpy022.utils import Storage +from webpy022.net import urlquote +from webpy022 import template, changequery as self_url + +import dbus + +import gettext, os, platform, locale, traceback +import random +import base64 from operator import attrgetter +from deluge import common +from deluge.common import INSTALL_PREFIX + + +#init: +APP = 'deluge' +DIR = os.path.join(INSTALL_PREFIX, 'share', 'locale') +if platform.system() != "Windows": + locale.setlocale(locale.LC_MESSAGES, '') + locale.bindtextdomain(APP, DIR) + locale.textdomain(APP) +else: + locale.setlocale(locale.LC_ALL, '') +gettext.bindtextdomain(APP, DIR) +gettext.textdomain(APP) +gettext.install(APP, DIR) + +random.seed() +bus = dbus.SessionBus() +proxy = bus.get_object("org.deluge_torrent.dbusplugin" + , "/org/deluge_torrent/DelugeDbusPlugin") + +web.webapi.internalerror = web.debugerror + +render = template.render('templates/%s/' % proxy.get_webui_config('template') + ,cache=proxy.get_webui_config('cache_templates')) +#/init + +#framework: + +SESSIONS = {} + +def do_redirect(): + """for redirects after a POST""" + vars = web.input(redir = None) + ck = cookies() + + if vars.redir: + seeother(vars.redir) + elif ("order" in ck and "sort" in ck): + seeother(url("/index", sort=ck['sort'], order=ck['order'])) + else: + seeother(url("/index")) + +def deluge_page_noauth(func): + """ + add http headers + print result of func + """ + def deco(self, name=None): + web.header("Content-Type", "text/html; charset=utf-8") + web.header("Cache-Control", "no-cache, must-revalidate") + res = func(self, name) + print res + return deco + +def check_session(func): + """ + a decorator + return func if session is valid, else redirect to login page. + """ + def deco(self, name): + vars = web.input(redir_after_login=None) + + ck = cookies() + if ck.has_key("session_id") and ck["session_id"] in SESSIONS: + return func(self, name) #ok, continue.. + elif vars.redir_after_login: + seeother("/login?redir=" + urlquote(self_url())) + else: + seeother("/login") #do not continue, and redirect to login page + return deco + +def deluge_page(func): + return check_session(deluge_page_noauth(func)) + +def auto_refreshed(func): + "decorator:adds a refresh header" + def deco(self, name): + if proxy.get_webui_config('auto_refresh'): + web.header("Refresh", "%i ; url=%s" % + (proxy.get_webui_config('auto_refresh_secs'),self_url())) + return func(self, name) + return deco + +def error_page(error): + web.header("Content-Type", "text/html; charset=utf-8") + web.header("Cache-Control", "no-cache, must-revalidate") + print render.error(error) + +def remote(func): + "decorator for remote api's" + def deco(self, name): + try: + print func(self, name) + except Exception, e: + print 'error:' + e.message + print '-'*20 + print traceback.format_exc() + return deco + +#/framework + #utils: -def check_pwd(pwd): - m = md5() - m.update(config.get('pwd_salt')) - m.update(pwd) - return (m.digest() == config.get('pwd_md5')) +torrent_keys = ['distributed_copies', 'download_payload_rate', + 'download_rate', 'eta', 'is_seed', 'message', 'name', 'next_announce', + 'num_files', 'num_peers', 'num_pieces', 'num_seeds', 'paused', + 'piece_length','progress', 'ratio', 'total_done', 'total_download', + 'total_payload_download', 'total_payload_upload', 'total_peers', + 'total_seeds', 'total_size', 'total_upload', 'total_wanted', + 'tracker_status', 'upload_payload_rate', 'upload_rate', + 'uploaded_memory','tracker'] def get_torrent_status(torrent_id): """ helper method. enhance proxy.get_torrent_status with some extra data """ - status = proxy.get_torrent_status(torrent_id,TORRENT_KEYS) + status = proxy.get_torrent_status(torrent_id,torrent_keys) status["id"] = torrent_id #for naming the status-images @@ -73,26 +189,61 @@ def get_torrent_status(torrent_id): else: status["action"] = "stop" - - if status["paused"]: - status["message"] = _("Paused %s%%") % status['progress'] - else: - status["message"] = "%s %i%%" % (STATE_MESSAGES[status["state"]] - , status['progress']) - #add some pre-calculated values status.update({ - "calc_total_downloaded" : (fsize(status["total_done"]) - + " (" + fsize(status["total_download"]) + ")"), - "calc_total_uploaded": (fsize(status['uploaded_memory'] + "calc_total_downloaded" : (common.fsize(status["total_done"]) + + " (" + common.fsize(status["total_download"]) + ")"), + "calc_total_uploaded": (common.fsize(status['uploaded_memory'] + status["total_payload_upload"]) + " (" - + fsize(status["total_upload"]) + ")"), + + common.fsize(status["total_upload"]) + ")"), }) return Storage(status) #Storage for easy templating. #/utils +#template-defs: +def template_crop(text, end): + if len(text) > end: + return text[0:end - 3] + '...' + return text + +def template_sort_head(id,name): + #got tired of doing these complex things inside templetor.. + vars = web.input(sort=None, order=None) + active_up = False + active_down = False + order = 'down' + + if vars.sort == id: + if vars.order == 'down': + order = 'up' + active_down = True + else: + active_up = True + + return render.sort_column_head(id, name, order, active_up, active_down) + +template.Template.globals.update({ + 'sort_head': template_sort_head, + 'crop': template_crop, + '_': _ , #gettext/translations + 'str': str, #because % in templetor is broken. + 'sorted': sorted, + 'get_config': proxy.get_webui_config, + 'self_url': self_url, + 'fspeed': common.fspeed, + 'fsize': common.fsize, + 'render': render, #for easy resuse of templates + 'button_style': (proxy.get_webui_config('button_style')), + 'rev': ('rev.' + + open(os.path.join(os.path.dirname(__file__),'revno')).read()), + 'version': ( + open(os.path.join(os.path.dirname(__file__),'version')).read()), + 'get': lambda (var): getattr(web.input(**{var:None}),var) # unreadable :-( +}) +#/template-defs + #routing: urls = ( "/login(.*)", "login", @@ -126,12 +277,14 @@ class login: def POST(self, name): vars = web.input(pwd = None ,redir = None) - if check_pwd(vars.pwd): + if proxy.check_pwd(vars.pwd): #start new session - start_session() + session_id = str(random.random()) + SESSIONS[session_id] = {"not":"used"} + setcookie("session_id", session_id) do_redirect() elif vars.redir: - seeother(url('/login',error=1,redir=vars.redir)) + seeother('/login?error=1&redir=' + urlquote(vars.redir)) else: seeother('/login?error=1') @@ -207,12 +360,13 @@ class remote_torrent_add: """ For use in remote scripts etc. POST pwd and torrent + Example : curl -F torrent=@./test1.torrent -F pwd=deluge http://localhost:8112/remote/torrent/add" """ @remote def POST(self, name): vars = web.input(pwd = None, torrent = {}) - if not check_pwd(vars.pwd): + if not proxy.check_pwd(vars.pwd): return 'error:wrong password' data_b64 = base64.b64encode(vars.torrent.file.read()) @@ -250,8 +404,8 @@ class resume_all: class refresh: @check_session def POST(self, name): - auto_refresh = {'off':'0', 'on':'1'}[name] - setcookie('auto_refresh',auto_refresh) + auto_refresh = {'off':False, 'on':True}[name] + proxy.set_webui_config('auto_refresh', auto_refresh) do_redirect() class refresh_set: @@ -264,8 +418,8 @@ class refresh_set: vars = web.input(refresh = 0) refresh = int(vars.refresh) if refresh > 0: - setcookie('auto_refresh','1') - setcookie('auto_refresh_secs', str(refresh)) + proxy.set_webui_config('refresh', refresh) + proxy.set_webui_config('auto_refresh', True) do_redirect() else: error_page(_('refresh must be > 0')) @@ -275,19 +429,10 @@ class about: def GET(self, name): return render.about() + #/pages - -def WebServer(): - return create_webserver(urls, globals()) - -def run(): - server = WebServer() - try: - server.start() - except KeyboardInterrupt: - server.stop() - if __name__ == "__main__": - run() + web.run(urls, globals()) + diff --git a/plugins/WebUi/webserver_common.py b/plugins/WebUi/webserver_common.py deleted file mode 100644 index ef6f18e34..000000000 --- a/plugins/WebUi/webserver_common.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright (C) Martijn Voncken 2007 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# 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, write to: -# The Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor -# Boston, MA 02110-1301, USA. -# -# In addition, as a special exception, the copyright holders give -# permission to link the code of portions of this program with the OpenSSL -# library. -# You must obey the GNU General Public License in all respects for all of -# the code used other than OpenSSL. If you modify file(s) with this -# exception, you may extend this exception to your version of the file(s), -# but you are not obligated to do so. If you do not wish to do so, delete -# this exception statement from your version. If you delete this exception -# statement from all source files in the program, then also delete it here. - -import os -import deluge -from deluge.common import INSTALL_PREFIX -import random -import pickle -random.seed() - -config_file = deluge.common.CONFIG_DIR + "/webui.conf" -#config = deluge.pref.Preferences(config_file, False) -config = pickle.load(open(config_file)) - -if config.get('run_in_thread'): - #do not use dbus ipc for threads! - from dbus_interface import get_dbus_manager - proxy = get_dbus_manager() -else: - import dbus - bus = dbus.SessionBus() - proxy = bus.get_object("org.deluge_torrent.dbusplugin" - , "/org/deluge_torrent/DelugeDbusPlugin") - -REVNO = open(os.path.join(os.path.dirname(__file__),'revno')).read() -VERSION = open(os.path.join(os.path.dirname(__file__),'version')).read() - -TORRENT_KEYS = ['distributed_copies', 'download_payload_rate', - 'download_rate', 'eta', 'is_seed', 'name', 'next_announce', - 'num_files', 'num_peers', 'num_pieces', 'num_seeds', 'paused', - 'piece_length','progress', 'ratio', 'total_done', 'total_download', - 'total_payload_download', 'total_payload_upload', 'total_peers', - 'total_seeds', 'total_size', 'total_upload', 'total_wanted', - 'tracker_status', 'upload_payload_rate', 'upload_rate', - 'uploaded_memory','tracker','state'] - -STATE_MESSAGES = (_("Queued"), - _("Checking"), - _("Connecting"), - _("Downloading Metadata"), - _("Downloading"), - _("Finished"), - _("Seeding"), - _("Allocating")) diff --git a/plugins/WebUi/webserver_framework.py b/plugins/WebUi/webserver_framework.py deleted file mode 100644 index c80c7e71d..000000000 --- a/plugins/WebUi/webserver_framework.py +++ /dev/null @@ -1,302 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# webserver_framework.py -# -# Copyright (C) Martijn Voncken 2007 -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# 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, write to: -# The Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor -# Boston, MA 02110-1301, USA. -# -# In addition, as a special exception, the copyright holders give -# permission to link the code of portions of this program with the OpenSSL -# library. -# You must obey the GNU General Public License in all respects for all of -# the code used other than OpenSSL. If you modify file(s) with this -# exception, you may extend this exception to your version of the file(s), -# but you are not obligated to do so. If you do not wish to do so, delete -# this exception statement from your version. If you delete this exception -# statement from all source files in the program, then also delete it here. - -""" -Todo's before stable: --__init__:kill->restart is not waiting for kill to be finished. ---later/features:--- --alternating rows? --set prio --clear finished? --torrent files. -""" -import webpy022 as web - -from webpy022.webapi import cookies, setcookie -from webpy022.http import seeother, url -from webpy022 import template, changequery as self_url - -import traceback -import random -from operator import attrgetter - -from deluge import common -from webserver_common import proxy, config , REVNO, VERSION - -#init: -web.webapi.internalerror = web.debugerror -render = template.render('templates/%s/' % config.get('template'), - cache=config.get('cache_templates')) - -#/init - -#methods: -SESSIONS = [] #dumb sessions. -def start_session(): - session_id = str(random.random()) - SESSIONS.append(session_id) - setcookie("session_id", session_id) - -def do_redirect(): - """for redirects after a POST""" - vars = web.input(redir = None) - ck = cookies() - - if vars.redir: - seeother(vars.redir) - elif ("order" in ck and "sort" in ck): - seeother(url("/index", sort=ck['sort'], order=ck['order'])) - else: - seeother(url("/index")) - -def error_page(error): - web.header("Content-Type", "text/html; charset=utf-8") - web.header("Cache-Control", "no-cache, must-revalidate") - print render.error(error) - -def getcookie(key, default=None): - ck = cookies() - return str(ck.get(key, default)) - -#deco's: -def deluge_page_noauth(func): - """ - add http headers - print result of func - """ - def deco(self, name=None): - web.header("Content-Type", "text/html; charset=utf-8") - web.header("Cache-Control", "no-cache, must-revalidate") - res = func(self, name) - print res - return deco - -def check_session(func): - """ - a decorator - return func if session is valid, else redirect to login page. - """ - def deco(self, name): - vars = web.input(redir_after_login=None) - - ck = cookies() - if ck.has_key("session_id") and ck["session_id"] in SESSIONS: - return func(self, name) #ok, continue.. - elif vars.redir_after_login: - seeother(url("/login",redir=self_url())) - else: - seeother("/login") #do not continue, and redirect to login page - return deco - -def deluge_page(func): - return check_session(deluge_page_noauth(func)) - -#combi-deco's: -def auto_refreshed(func): - "decorator:adds a refresh header" - def deco(self, name): - if getcookie('auto_refresh') == '1': - web.header("Refresh", "%i ; url=%s" % - (int(getcookie('auto_refresh_secs',10)),self_url())) - return func(self, name) - return deco - -def remote(func): - "decorator for remote api's" - def deco(self, name): - try: - print func(self, name) - except Exception, e: - print 'error:' + e.message - print '-'*20 - print traceback.format_exc() - return deco - -#template-defs: -def template_crop(text, end): - if len(text) > end: - return text[0:end - 3] + '...' - return text - -def template_sort_head(id,name): - #got tired of doing these complex things inside templetor.. - vars = web.input(sort=None, order=None) - active_up = False - active_down = False - order = 'down' - - if vars.sort == id: - if vars.order == 'down': - order = 'up' - active_down = True - else: - active_up = True - - return render.sort_column_head(id, name, order, active_up, active_down) - -template.Template.globals.update({ - 'sort_head': template_sort_head, - 'crop': template_crop, - '_': _ , #gettext/translations - 'str': str, #because % in templetor is broken. - 'sorted': sorted, - 'get_config': config.get, - 'self_url': self_url, - 'fspeed': common.fspeed, - 'fsize': common.fsize, - 'render': render, #for easy resuse of templates - 'button_style': (config.get('button_style')), - 'rev': 'rev.%s' % (REVNO, ), - 'version': VERSION, - 'get': lambda (var): getattr(web.input(**{var:None}),var) # unreadable :-( -}) -#/template-defs - - - -#------------------------------------------------------------------------------ -#Some copy and paste from web.py -#mostly caused by /static -#TODO : FIX THIS. -from SimpleHTTPServer import SimpleHTTPRequestHandler -from BaseHTTPServer import BaseHTTPRequestHandler -from webpy022.request import webpyfunc -from webpy022 import webapi -import os - -class StaticApp(SimpleHTTPRequestHandler): - """WSGI application for serving static files.""" - def __init__(self, environ, start_response): - self.headers = [] - self.environ = environ - self.start_response = start_response - - def send_response(self, status, msg=""): - self.status = str(status) + " " + msg - - def send_header(self, name, value): - self.headers.append((name, value)) - - def end_headers(self): - pass - - def log_message(*a): pass - - def __iter__(self): - environ = self.environ - - self.path = environ.get('PATH_INFO', '') - self.client_address = environ.get('REMOTE_ADDR','-'), \ - environ.get('REMOTE_PORT','-') - self.command = environ.get('REQUEST_METHOD', '-') - - from cStringIO import StringIO - self.wfile = StringIO() # for capturing error - - f = self.send_head() - self.start_response(self.status, self.headers) - - if f: - block_size = 16 * 1024 - while True: - buf = f.read(block_size) - if not buf: - break - yield buf - f.close() - else: - value = self.wfile.getvalue() - yield value - -class WSGIWrapper(BaseHTTPRequestHandler): - """WSGI wrapper for logging the status and serving static files.""" - def __init__(self, app): - self.app = app - self.format = '%s - - [%s] "%s %s %s" - %s' - - def __call__(self, environ, start_response): - def xstart_response(status, response_headers, *args): - write = start_response(status, response_headers, *args) - self.log(status, environ) - return write - - path = environ.get('PATH_INFO', '') - if path.startswith('/static/'): - return StaticApp(environ, xstart_response) - else: - return self.app(environ, xstart_response) - - def log(self, status, environ): - #mvoncken,no logging.. - return - - outfile = environ.get('wsgi.errors', web.debug) - req = environ.get('PATH_INFO', '_') - protocol = environ.get('ACTUAL_SERVER_PROTOCOL', '-') - method = environ.get('REQUEST_METHOD', '-') - host = "%s:%s" % (environ.get('REMOTE_ADDR','-'), - environ.get('REMOTE_PORT','-')) - - #@@ It is really bad to extend from - #@@ BaseHTTPRequestHandler just for this method - time = self.log_date_time_string() - - print >> outfile, self.format % (host, time, protocol, - method, req, status) - -def create_webserver(urls,methods): - from webpy022.wsgiserver import CherryPyWSGIServer - from BaseHTTPServer import BaseHTTPRequestHandler - - - os.chdir(os.path.dirname(__file__)) #HACK for /static.. - - func = webapi.wsgifunc(webpyfunc(urls,methods, False)) - server_address=("0.0.0.0",config.get('port')) - - func = WSGIWrapper(func) - server = CherryPyWSGIServer(server_address, func, server_name="localhost") - - - print "(created) http://%s:%d/" % server_address - - return server - -#------ -__all__ = ['deluge_page_noauth', 'deluge_page', 'remote', - 'auto_refreshed', 'check_session', - 'do_redirect', 'error_page', 'render', 'start_session','getcookie' - ,'create_webserver'] - - -