sync webui plugin with rev48
This commit is contained in:
parent
9a050065a9
commit
53e65e9554
@ -33,18 +33,24 @@
|
|||||||
plugin_name = "Web User interface"
|
plugin_name = "Web User interface"
|
||||||
plugin_author = "Martijn Voncken"
|
plugin_author = "Martijn Voncken"
|
||||||
plugin_version = "rev."
|
plugin_version = "rev."
|
||||||
plugin_description = """A Web based User Interface (and dbus-ipc)
|
plugin_description = "A Web based User Interface\n"
|
||||||
beta test version, disclaimer, etc..
|
|
||||||
"""
|
|
||||||
|
|
||||||
import deluge.common, deluge.pref
|
import deluge.common
|
||||||
|
import deluge.pref
|
||||||
|
from deluge.dialogs import show_popup_warning
|
||||||
from dbus_interface import DbusManager
|
from dbus_interface import DbusManager
|
||||||
|
|
||||||
import gtk
|
import gtk
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from subprocess import Popen
|
from subprocess import Popen
|
||||||
|
from md5 import md5
|
||||||
|
import random
|
||||||
|
random.seed()
|
||||||
|
|
||||||
plugin_version += open(os.path.join(os.path.dirname(__file__),'revno')).read()
|
plugin_version += open(os.path.join(os.path.dirname(__file__),'revno')).read()
|
||||||
|
plugin_description += (
|
||||||
|
open(os.path.join(os.path.dirname(__file__),'version')).read())
|
||||||
|
|
||||||
|
|
||||||
def deluge_init(deluge_path):
|
def deluge_init(deluge_path):
|
||||||
global path
|
global path
|
||||||
@ -72,19 +78,24 @@ class plugin_WebUi:
|
|||||||
if not self.config.get('port'): #ugly way to detect new config file.
|
if not self.config.get('port'): #ugly way to detect new config file.
|
||||||
#set default values:
|
#set default values:
|
||||||
self.config.set("port", 8112)
|
self.config.set("port", 8112)
|
||||||
self.config.set("user", "deluge")
|
|
||||||
self.config.set("pwd", "deluge")
|
|
||||||
#future->use deluge-core setting for download_dir (if it is set)
|
#future->use deluge-core setting for download_dir (if it is set)
|
||||||
self.config.set("download_dir", os.path.expanduser("~/"))
|
self.config.set("download_dir", os.path.expanduser("~/"))
|
||||||
self.config.set("torrent_dir", os.path.expanduser("~/"))
|
self.config.set("torrent_dir", os.path.expanduser("~/"))
|
||||||
|
self.config.set("button_style", 2)
|
||||||
self.config.set("auto_refresh", False)
|
self.config.set("auto_refresh", False)
|
||||||
self.config.set("auto_refresh_secs", 4)
|
self.config.set("auto_refresh_secs", 4)
|
||||||
self.config.set("template", "deluge")
|
self.config.set("template", "deluge")
|
||||||
self.config.save(self.config_file)
|
self.config.save(self.config_file)
|
||||||
|
|
||||||
|
if not self.config.get("pwd_salt"):
|
||||||
|
self.config.set("pwd_salt", "invalid")
|
||||||
|
self.config.set("pwd_md5", "invalid")
|
||||||
|
|
||||||
|
|
||||||
self.dbusManager = DbusManager(deluge_core, deluge_interface
|
self.dbusManager = DbusManager(deluge_core, deluge_interface
|
||||||
, self.config, self.config_file)
|
, self.config, self.config_file)
|
||||||
|
|
||||||
|
print dir(self.dbusManager)
|
||||||
self.start_server()
|
self.start_server()
|
||||||
|
|
||||||
def unload(self):
|
def unload(self):
|
||||||
@ -135,9 +146,11 @@ class ConfigDialog(gtk.Dialog):
|
|||||||
if os.path.isdir(os.path.join(template_path, dirname))]
|
if os.path.isdir(os.path.join(template_path, dirname))]
|
||||||
|
|
||||||
self.port = self.add_widget(_('Port Number'), gtk.SpinButton())
|
self.port = self.add_widget(_('Port Number'), gtk.SpinButton())
|
||||||
self.user = self.add_widget(_('User'), gtk.Entry())
|
self.pwd1 = self.add_widget(_('New Password'), gtk.Entry())
|
||||||
self.pwd = self.add_widget(_('Password'), gtk.Entry())
|
self.pwd2 = self.add_widget(_('New Password(confirm)'), gtk.Entry())
|
||||||
self.template = self.add_widget(_('Template'), gtk.combo_box_new_text())
|
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.download_dir = self.add_widget(_('Download Directory'),
|
self.download_dir = self.add_widget(_('Download Directory'),
|
||||||
gtk.FileChooserButton(_('Download Directory')))
|
gtk.FileChooserButton(_('Download Directory')))
|
||||||
self.torrent_dir = self.add_widget(_('Torrent Directory'),
|
self.torrent_dir = self.add_widget(_('Torrent Directory'),
|
||||||
@ -147,16 +160,24 @@ class ConfigDialog(gtk.Dialog):
|
|||||||
self.torrent_dir.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
|
self.torrent_dir.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
|
||||||
self.port.set_range(80, 65536)
|
self.port.set_range(80, 65536)
|
||||||
self.port.set_increments(1, 10)
|
self.port.set_increments(1, 10)
|
||||||
|
self.pwd1.set_visibility(False)
|
||||||
|
self.pwd2.set_visibility(False)
|
||||||
|
|
||||||
for item in self.templates:
|
for item in self.templates:
|
||||||
self.template.append_text(item)
|
self.template.append_text(item)
|
||||||
|
self.button_style
|
||||||
if not self.config.get("template") in self.templates:
|
if not self.config.get("template") in self.templates:
|
||||||
self.config.set("template","deluge")
|
self.config.set("template","deluge")
|
||||||
|
|
||||||
self.user.set_text(self.config.get("user"))
|
for item in [_('Text and image'), _('Image Only'), _('Text Only')]:
|
||||||
self.pwd.set_text(self.config.get("pwd"))
|
self.button_style.append_text(item)
|
||||||
|
if not self.config.get("button_style"):
|
||||||
|
self.config.set("button_style", 2)
|
||||||
|
|
||||||
self.port.set_value(int(self.config.get("port")))
|
self.port.set_value(int(self.config.get("port")))
|
||||||
self.template.set_active(
|
self.template.set_active(
|
||||||
self.templates.index(self.config.get("template")))
|
self.templates.index(self.config.get("template")))
|
||||||
|
self.button_style.set_active(self.config.get("button_style"))
|
||||||
self.torrent_dir.set_filename(self.config.get("torrent_dir"))
|
self.torrent_dir.set_filename(self.config.get("torrent_dir"))
|
||||||
self.download_dir.set_filename(self.config.get("download_dir"))
|
self.download_dir.set_filename(self.config.get("download_dir"))
|
||||||
self.vbox.pack_start(self.vb, True, True, 0)
|
self.vbox.pack_start(self.vb, True, True, 0)
|
||||||
@ -177,11 +198,21 @@ class ConfigDialog(gtk.Dialog):
|
|||||||
self.add_buttons(dgtk.STOCK_CLOSE, dgtk.RESPONSE_CLOSE)
|
self.add_buttons(dgtk.STOCK_CLOSE, dgtk.RESPONSE_CLOSE)
|
||||||
|
|
||||||
def save_config(self):
|
def save_config(self):
|
||||||
print 'save config'
|
if self.pwd1.get_text() > '':
|
||||||
self.config.set("user", self.user.get_text())
|
if self.pwd1.get_text() <> self.pwd2.get_text():
|
||||||
self.config.set("pwd", self.pwd.get_text())
|
show_popup_warning(self,_("Confirmed Password <> New Password\n"
|
||||||
|
+ "Password was not changed"))
|
||||||
|
else:
|
||||||
|
salt = str(random.getrandbits(500))
|
||||||
|
m = md5()
|
||||||
|
m.update(salt)
|
||||||
|
m.update(unicode(self.pwd1.get_text()))
|
||||||
|
self.config.set("pwd_salt", salt)
|
||||||
|
self.config.set("pwd_md5", m.digest())
|
||||||
|
|
||||||
self.config.set("port", int(self.port.get_value()))
|
self.config.set("port", int(self.port.get_value()))
|
||||||
self.config.set("template", self.template.get_active_text())
|
self.config.set("template", self.template.get_active_text())
|
||||||
|
self.config.set("button_style", self.button_style.get_active())
|
||||||
self.config.set("torrent_dir", self.torrent_dir.get_filename())
|
self.config.set("torrent_dir", self.torrent_dir.get_filename())
|
||||||
self.config.set("download_dir",self.download_dir.get_filename())
|
self.config.set("download_dir",self.download_dir.get_filename())
|
||||||
self.config.save(self.plugin.config_file)
|
self.config.save(self.plugin.config_file)
|
||||||
|
|||||||
1
plugins/WebUi/curl-example
Normal file
1
plugins/WebUi/curl-example
Normal file
@ -0,0 +1 @@
|
|||||||
|
curl -F torrent=@./test1.torrent -F pwd=deluge http://localhost:8112/remote/torrent/add
|
||||||
@ -39,6 +39,7 @@ import dbus
|
|||||||
import deluge.common as common
|
import deluge.common as common
|
||||||
from dbus_pythonize import pythonize
|
from dbus_pythonize import pythonize
|
||||||
import base64
|
import base64
|
||||||
|
from md5 import md5
|
||||||
import random
|
import random
|
||||||
random.seed()
|
random.seed()
|
||||||
|
|
||||||
@ -182,7 +183,7 @@ class DbusManager(dbus.service.Object):
|
|||||||
not in 0.6
|
not in 0.6
|
||||||
"""
|
"""
|
||||||
retval = self.config.get(str(key))
|
retval = self.config.get(str(key))
|
||||||
print 'get webui config:', str(key), retval
|
#print 'get webui config:', str(key), retval
|
||||||
if retval == None:
|
if retval == None:
|
||||||
retval = False #dbus does not accept None :(
|
retval = False #dbus does not accept None :(
|
||||||
|
|
||||||
@ -195,10 +196,18 @@ class DbusManager(dbus.service.Object):
|
|||||||
return data from wevbui config.
|
return data from wevbui config.
|
||||||
not in 0.6
|
not in 0.6
|
||||||
"""
|
"""
|
||||||
print 'set webui config:', str(key), pythonize(value)
|
#print 'set webui config:', str(key), pythonize(value)
|
||||||
self.config.set(str(key), pythonize(value))
|
self.config.set(str(key), pythonize(value))
|
||||||
self.config.save(self.config_file)
|
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
|
#internal
|
||||||
def _add_torrent(self, filename):
|
def _add_torrent(self, filename):
|
||||||
#dbus types break pickle, again.....
|
#dbus types break pickle, again.....
|
||||||
|
|||||||
@ -50,7 +50,7 @@ from webpy022 import template
|
|||||||
|
|
||||||
import dbus
|
import dbus
|
||||||
|
|
||||||
import gettext, os, platform, locale
|
import gettext, os, platform, locale, traceback
|
||||||
import random
|
import random
|
||||||
import base64
|
import base64
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
@ -105,7 +105,7 @@ def deluge_page_noauth(func):
|
|||||||
web.header("Content-Type", "text/html; charset=utf-8")
|
web.header("Content-Type", "text/html; charset=utf-8")
|
||||||
web.header("Cache-Control", "no-cache, must-revalidate")
|
web.header("Cache-Control", "no-cache, must-revalidate")
|
||||||
res = func(self, name)
|
res = func(self, name)
|
||||||
print res
|
print unicode(res)
|
||||||
return deco
|
return deco
|
||||||
|
|
||||||
def check_session(func):
|
def check_session(func):
|
||||||
@ -139,6 +139,17 @@ def error_page(error):
|
|||||||
web.header("Cache-Control", "no-cache, must-revalidate")
|
web.header("Cache-Control", "no-cache, must-revalidate")
|
||||||
print render.error(error)
|
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
|
#/framework
|
||||||
|
|
||||||
#utils:
|
#utils:
|
||||||
@ -191,7 +202,7 @@ def template_crop(text, end):
|
|||||||
return text[0:end - 3] + '...'
|
return text[0:end - 3] + '...'
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def sort_head(id,name):
|
def template_sort_head(id,name):
|
||||||
#got tired of doing these complex things inside templetor..
|
#got tired of doing these complex things inside templetor..
|
||||||
vars = web.input(sort=None, order=None)
|
vars = web.input(sort=None, order=None)
|
||||||
active_up = False
|
active_up = False
|
||||||
@ -210,18 +221,23 @@ def sort_head(id,name):
|
|||||||
|
|
||||||
render = template.render('templates/%s/' % proxy.get_webui_config('template'))
|
render = template.render('templates/%s/' % proxy.get_webui_config('template'))
|
||||||
|
|
||||||
template.Template.globals['crop'] = template_crop
|
template.Template.globals.update({
|
||||||
template.Template.globals['fspeed'] = common.fspeed
|
'sort_head': template_sort_head,
|
||||||
template.Template.globals['fsize'] = common.fsize
|
'crop': template_crop,
|
||||||
template.Template.globals['sorted'] = sorted
|
'_': _ , #gettext/translations
|
||||||
template.Template.globals['_'] = _ #gettext/translations
|
'str': str, #because % in templetor is broken.
|
||||||
template.Template.globals['deluge_web_version'] = ('rev.'
|
'sorted': sorted,
|
||||||
+ open(os.path.join(os.path.dirname(__file__),'revno')).read())
|
'get_config': proxy.get_webui_config,
|
||||||
template.Template.globals['render'] = render #for easy resuse of templates
|
'self_url': web.changequery,
|
||||||
template.Template.globals['sort_head'] = sort_head
|
'fspeed': common.fspeed,
|
||||||
template.Template.globals['get_config'] = proxy.get_webui_config
|
'fsize': common.fsize,
|
||||||
template.Template.globals['self_url'] = web.changequery
|
'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())
|
||||||
|
})
|
||||||
#/template-defs
|
#/template-defs
|
||||||
|
|
||||||
#routing:
|
#routing:
|
||||||
@ -237,9 +253,12 @@ urls = (
|
|||||||
"/refresh/set(.*)", "refresh_set",
|
"/refresh/set(.*)", "refresh_set",
|
||||||
"/refresh/(.*)", "refresh",
|
"/refresh/(.*)", "refresh",
|
||||||
"/home(.*)", "home",
|
"/home(.*)", "home",
|
||||||
|
"/about(.*)", "about",
|
||||||
#default-pages
|
#default-pages
|
||||||
"/", "login",
|
"/", "login",
|
||||||
"", "login"
|
"", "login",
|
||||||
|
#remote-api:
|
||||||
|
"/remote/torrent/add(.*)", "remote_torrent_add"
|
||||||
)
|
)
|
||||||
|
|
||||||
#/routing
|
#/routing
|
||||||
@ -248,20 +267,20 @@ urls = (
|
|||||||
class login:
|
class login:
|
||||||
@deluge_page_noauth
|
@deluge_page_noauth
|
||||||
def GET(self, name):
|
def GET(self, name):
|
||||||
return render.login()
|
vars = web.input(error = None)
|
||||||
|
return render.login(vars.error)
|
||||||
|
|
||||||
def POST(self, name):
|
def POST(self, name):
|
||||||
vars = web.input(var = None, pwd = None)
|
vars = web.input(pwd = None)
|
||||||
|
|
||||||
if (vars.user == proxy.get_webui_config('user')
|
if proxy.check_pwd(vars.pwd):
|
||||||
and vars.pwd == proxy.get_webui_config('pwd')):
|
|
||||||
#start new session
|
#start new session
|
||||||
session_id = str(random.random())
|
session_id = str(random.random())
|
||||||
SESSIONS[session_id] = {"user":vars.user}
|
SESSIONS[session_id] = {"not":"used"}
|
||||||
setcookie("session_id", session_id)
|
setcookie("session_id", session_id)
|
||||||
do_redirect()
|
do_redirect()
|
||||||
else:
|
else:
|
||||||
error_page(_("Username or Password is invalid."))
|
seeother('/login?error=1')
|
||||||
|
|
||||||
class home:
|
class home:
|
||||||
@check_session
|
@check_session
|
||||||
@ -332,6 +351,23 @@ class torrent_add:
|
|||||||
else:
|
else:
|
||||||
error_page(_("no data."))
|
error_page(_("no data."))
|
||||||
|
|
||||||
|
class remote_torrent_add:
|
||||||
|
"""
|
||||||
|
For use in remote scripts etc.
|
||||||
|
POST user and file
|
||||||
|
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 proxy.check_pwd(vars.pwd):
|
||||||
|
return 'error:wrong password'
|
||||||
|
|
||||||
|
data_b64 = base64.b64encode(vars.torrent.file.read())
|
||||||
|
proxy.add_torrent_filecontent(vars.torrent.filename,data_b64)
|
||||||
|
return 'ok'
|
||||||
|
|
||||||
class torrent_delete:
|
class torrent_delete:
|
||||||
@deluge_page
|
@deluge_page
|
||||||
def GET(self, torrent_id):
|
def GET(self, torrent_id):
|
||||||
@ -383,6 +419,12 @@ class refresh_set:
|
|||||||
else:
|
else:
|
||||||
error_page(_('refresh must be > 0'))
|
error_page(_('refresh must be > 0'))
|
||||||
|
|
||||||
|
class about:
|
||||||
|
@deluge_page_noauth
|
||||||
|
def GET(self, name):
|
||||||
|
return render.about()
|
||||||
|
|
||||||
|
|
||||||
#/pages
|
#/pages
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
40
|
48
|
||||||
|
|||||||
@ -31,6 +31,15 @@ button.deluge_button {
|
|||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.error {
|
||||||
|
background-color:#FFFFFF;
|
||||||
|
color:#AA0000;
|
||||||
|
font-weight:bold;
|
||||||
|
-moz-border-radius:10px;
|
||||||
|
width:200px;
|
||||||
|
margin-bottom:20px;
|
||||||
|
padding:10px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Hides from IE-mac \*/
* html .clearfix {height: 1%;}
.clearfix {display: block;}
/* End hide from IE-mac */
|
/* Hides from IE-mac \*/
* html .clearfix {height: 1%;}
.clearfix {display: block;}
/* End hide from IE-mac */
|
||||||
39
plugins/WebUi/templates/deluge/about.html
Normal file
39
plugins/WebUi/templates/deluge/about.html
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
$:render.header(_('About'))
|
||||||
|
<div class="panel" style="text-align:left">
|
||||||
|
<h2>Version</h2>
|
||||||
|
<pre>$version </pre>
|
||||||
|
<h2>Links</h2>
|
||||||
|
<ul>
|
||||||
|
<li><a href="http://deluge-torrent.org">Deluge</a></li>
|
||||||
|
<li><a href="http://forum.deluge-torrent.org/viewtopic.php?f=9&t=425">
|
||||||
|
WebUi forum Thread</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html">GPL v2
|
||||||
|
</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>Authors</h2>
|
||||||
|
<ul>
|
||||||
|
<h3>WebUi</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Martijn Voncken</li>
|
||||||
|
</ul>
|
||||||
|
<h3>Template</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Martijn Voncken</li>
|
||||||
|
<li>somedude</li>
|
||||||
|
</ul>
|
||||||
|
<h3>Deluge</h3>
|
||||||
|
<ul>
|
||||||
|
<li>Zach Tibbitts</li>
|
||||||
|
<li>Alon Zakai</li>
|
||||||
|
<li>Alon Zakai</li>
|
||||||
|
<li>Marcos Pinto</li>
|
||||||
|
<li>Andrew Resch</li>
|
||||||
|
<li>Alex Dedul</li>
|
||||||
|
</ul>
|
||||||
|
</ul>
|
||||||
|
*and all other authors/helpers/contributors I forgot to mention.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
$:render.footer()
|
||||||
@ -1,6 +1,6 @@
|
|||||||
$def with (error_msg)
|
$def with (error_msg)
|
||||||
$:header(_('Error'))
|
$:render.header(_('Error'))
|
||||||
<pre class="error">
|
<pre class="error">
|
||||||
$error_msg
|
$error_msg
|
||||||
</pre>
|
</pre>
|
||||||
$:footer()
|
$:render.footer()
|
||||||
|
|||||||
@ -1,15 +1,13 @@
|
|||||||
$def with (title)
|
$def with (title)
|
||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
||||||
|
|
||||||
<title>Deluge:$title</title>
|
<title>Deluge:$title</title>
|
||||||
<link rel="icon" href="/static/images/deluge_icon.gif" type="image/gif" />
|
<link rel="icon" href="/static/images/deluge_icon.gif" type="image/gif" />
|
||||||
<link rel="shortcut icon" href="/static/images/deluge_icon.gif" type="image/gif" />
|
<link rel="shortcut icon" href="/static/images/deluge_icon.gif" type="image/gif" />
|
||||||
<link rel="stylesheet" type="text/css" href="/static/simple_site_style.css" />
|
<link rel="stylesheet" type="text/css" href="/static/simple_site_style.css" />
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="page">
|
<div id="page">
|
||||||
|
|
||||||
|
|||||||
@ -54,5 +54,4 @@ $:render.part_button('POST', '/resume_all', _('Resume all'), 'tango/media-playba
|
|||||||
|
|
||||||
$:render.part_refresh()
|
$:render.part_refresh()
|
||||||
|
|
||||||
|
|
||||||
$:render.footer()
|
$:render.footer()
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
|
$def with (error)
|
||||||
$:render.header(_('Login'))
|
$:render.header(_('Login'))
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
|
$if error > 0:
|
||||||
|
<div class="error">$_("Password is invalid,try again")</div>
|
||||||
|
|
||||||
<form method="POST" id="loginform" action='/login'>
|
<form method="POST" id="loginform" action='/login'>
|
||||||
<div id="loginpanel">
|
<div id="loginpanel">
|
||||||
<div class="form_row">
|
<div class="form_row">
|
||||||
<span class="form_label">$_('User')</span>
|
<span class="form_label">$_('Password')</span>
|
||||||
<input type="text" name="user" id="user" class="form_input">
|
|
||||||
</div>
|
|
||||||
<div class="form_row">
|
|
||||||
<span class="form_label">$_('Pass')</span>
|
|
||||||
<input type="password" name="pwd" id="pwd" class="form_input">
|
<input type="password" name="pwd" id="pwd" class="form_input">
|
||||||
</div>
|
</div>
|
||||||
<div class="form_row">
|
<div class="form_row">
|
||||||
@ -15,6 +15,9 @@ $:render.header(_('Login'))
|
|||||||
<input type="submit" name="submit"
|
<input type="submit" name="submit"
|
||||||
id="submit" value="Submit" class="form_input">
|
id="submit" value="Submit" class="form_input">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<a href="/about">$_('About')</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -3,11 +3,20 @@ $def with (method, url, title, image='')
|
|||||||
<form method="$method" action="$url" class="deluge_button">
|
<form method="$method" action="$url" class="deluge_button">
|
||||||
<button type="submit" class="deluge_button">
|
<button type="submit" class="deluge_button">
|
||||||
<input type="hidden" name="redir" value="$self_url()">
|
<input type="hidden" name="redir" value="$self_url()">
|
||||||
$if image:
|
$if (button_style == 0):
|
||||||
<image src="/static/images/$image" class="button"/>
|
$title
|
||||||
$else:
|
$if image:
|
||||||
<!--no image-->
|
<image src="/static/images/$image" class="button" alt="$title"/>
|
||||||
$title
|
|
||||||
|
$if (button_style == 1):
|
||||||
|
$if image:
|
||||||
|
<image src="/static/images/$image" class="button" alt="$title"/>
|
||||||
|
$else:
|
||||||
|
$title
|
||||||
|
|
||||||
|
$if (button_style == 2):
|
||||||
|
$title
|
||||||
|
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@ -1,5 +1,5 @@
|
|||||||
<div class="panel">
|
<div id='refresh_panel'>
|
||||||
<div id='refresh'>
|
<div class="panel" >
|
||||||
$_('Auto refresh:')
|
$_('Auto refresh:')
|
||||||
$if get_config('auto_refresh'):
|
$if get_config('auto_refresh'):
|
||||||
($(get_config('refresh')) $_('seconds'))
|
($(get_config('refresh')) $_('seconds'))
|
||||||
|
|||||||
@ -3,7 +3,7 @@ $:render.header(_('Set Timeout'))
|
|||||||
<form action="/refresh/set" method="POST">
|
<form action="/refresh/set" method="POST">
|
||||||
$_('Refresh page every:')
|
$_('Refresh page every:')
|
||||||
<input type="text" name="refresh" value="$get_config('refresh')" size="3">
|
<input type="text" name="refresh" value="$get_config('refresh')" size="3">
|
||||||
$_('Seconds')
|
$_('seconds')
|
||||||
<input type="submit" value="$_('Set')">
|
<input type="submit" value="$_('Set')">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -80,17 +80,7 @@ class="deluge_button">
|
|||||||
name="$torrent.action" value="$torrent.id">
|
name="$torrent.action" value="$torrent.id">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class="deluge_button">
|
$:render.part_button('GET', '/torrent/delete/' + str(torrent.id), _('Remove'), 'tango/user-trash.png')
|
||||||
<form method="GET" action="/torrent/delete/$torrent.id" class="deluge_button">
|
|
||||||
|
|
||||||
<button type="submit" class="deluge_button">
|
|
||||||
<image src="/static/images/tango/user-trash.png" /> $_('Delete')
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
[<a onclick="javascript:toggle_dump()">$_('Debug:Data Dump')</a>]
|
[<a onclick="javascript:toggle_dump()">$_('Debug:Data Dump')</a>]
|
||||||
|
|||||||
@ -10,16 +10,21 @@ Or use scite and my config: http://mvoncken.sohosted.com/deluge/SciTEUser.proper
|
|||||||
template language: http://webpy.org/templetor
|
template language: http://webpy.org/templetor
|
||||||
|
|
||||||
Exposed methods and variables (c&p from deluge_webserver):
|
Exposed methods and variables (c&p from deluge_webserver):
|
||||||
|
'sort_head': template_sort_head,
|
||||||
template.Template.globals['crop'] = template_crop
|
'crop': template_crop,
|
||||||
template.Template.globals['fspeed'] = common.fspeed
|
'_': _ , #gettext/translations
|
||||||
template.Template.globals['fsize'] = common.fsize
|
'str': str, #because % in templetor is broken.
|
||||||
template.Template.globals['sorted'] = sorted
|
'sorted': sorted,
|
||||||
template.Template.globals['_'] = _ #gettext/translations
|
'get_config': proxy.get_webui_config,
|
||||||
template.Template.globals['deluge_web_version'] = '0.3alfa'
|
'self_url': web.changequery,
|
||||||
template.Template.globals['render'] = render #for easy resuse of templates
|
'fspeed': common.fspeed,
|
||||||
template.Template.globals['sort_head'] = sort_head
|
'fsize': common.fsize,
|
||||||
template.Template.globals['get_config'] = proxy.get_webui_config
|
'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())
|
||||||
|
|
||||||
I will update this file if there is interest in making templates.
|
I will update this file if there is interest in making templates.
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1 @@
|
|||||||
revision-id: mvoncken@gmail.com-20070923193628-omqar5yaxatdmfu0
|
48
|
||||||
date: 2007-09-23 21:36:28 +0200
|
|
||||||
build-date: 2007-09-23 21:54:09 +0200
|
|
||||||
revno: 30
|
|
||||||
branch-nick: WebUi
|
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
Commented out some code to enable a relative redirect.
|
1:Commented out some code to enable a relative redirect.
|
||||||
This is not according to HTTP/1.1 Spec
|
This is not according to HTTP/1.1 Spec
|
||||||
But many deluge users will want to route the webui through firewalls/routers or use apache redirects.
|
But many deluge users will want to route the webui through firewalls/routers or use apache redirects.
|
||||||
|
|
||||||
|
2:Disabled logging in the builtin http-server.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -6,11 +6,11 @@ import net
|
|||||||
|
|
||||||
def runbasic(func, server_address=("0.0.0.0", 8080)):
|
def runbasic(func, server_address=("0.0.0.0", 8080)):
|
||||||
"""
|
"""
|
||||||
Runs a simple HTTP server hosting WSGI app `func`. The directory `static/`
|
Runs a simple HTTP server hosting WSGI app `func`. The directory `static/`
|
||||||
is hosted statically.
|
is hosted statically.
|
||||||
|
|
||||||
Based on [WsgiServer][ws] from [Colin Stewart][cs].
|
Based on [WsgiServer][ws] from [Colin Stewart][cs].
|
||||||
|
|
||||||
[ws]: http://www.owlfish.com/software/wsgiutils/documentation/wsgi-server-api.html
|
[ws]: http://www.owlfish.com/software/wsgiutils/documentation/wsgi-server-api.html
|
||||||
[cs]: http://www.owlfish.com/
|
[cs]: http://www.owlfish.com/
|
||||||
"""
|
"""
|
||||||
@ -62,17 +62,17 @@ def runbasic(func, server_address=("0.0.0.0", 8080)):
|
|||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
for data in result:
|
for data in result:
|
||||||
if data:
|
if data:
|
||||||
self.wsgi_write_data(data)
|
self.wsgi_write_data(data)
|
||||||
finally:
|
finally:
|
||||||
if hasattr(result, 'close'):
|
if hasattr(result, 'close'):
|
||||||
result.close()
|
result.close()
|
||||||
except socket.error, socket_err:
|
except socket.error, socket_err:
|
||||||
# Catch common network errors and suppress them
|
# Catch common network errors and suppress them
|
||||||
if (socket_err.args[0] in \
|
if (socket_err.args[0] in \
|
||||||
(errno.ECONNABORTED, errno.EPIPE)):
|
(errno.ECONNABORTED, errno.EPIPE)):
|
||||||
return
|
return
|
||||||
except socket.timeout, socket_timeout:
|
except socket.timeout, socket_timeout:
|
||||||
return
|
return
|
||||||
except:
|
except:
|
||||||
print >> web.debug, traceback.format_exc(),
|
print >> web.debug, traceback.format_exc(),
|
||||||
@ -92,7 +92,7 @@ def runbasic(func, server_address=("0.0.0.0", 8080)):
|
|||||||
else:
|
else:
|
||||||
self.run_wsgi_app()
|
self.run_wsgi_app()
|
||||||
|
|
||||||
def wsgi_start_response(self, response_status, response_headers,
|
def wsgi_start_response(self, response_status, response_headers,
|
||||||
exc_info=None):
|
exc_info=None):
|
||||||
if (self.wsgi_sent_headers):
|
if (self.wsgi_sent_headers):
|
||||||
raise Exception \
|
raise Exception \
|
||||||
@ -117,8 +117,8 @@ def runbasic(func, server_address=("0.0.0.0", 8080)):
|
|||||||
|
|
||||||
class WSGIServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
|
class WSGIServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
|
||||||
def __init__(self, func, server_address):
|
def __init__(self, func, server_address):
|
||||||
BaseHTTPServer.HTTPServer.__init__(self,
|
BaseHTTPServer.HTTPServer.__init__(self,
|
||||||
server_address,
|
server_address,
|
||||||
WSGIHandler)
|
WSGIHandler)
|
||||||
self.app = func
|
self.app = func
|
||||||
self.serverShuttingDown = 0
|
self.serverShuttingDown = 0
|
||||||
@ -128,7 +128,7 @@ def runbasic(func, server_address=("0.0.0.0", 8080)):
|
|||||||
|
|
||||||
def runsimple(func, server_address=("0.0.0.0", 8080)):
|
def runsimple(func, server_address=("0.0.0.0", 8080)):
|
||||||
"""
|
"""
|
||||||
Runs [CherryPy][cp] WSGI server hosting WSGI app `func`.
|
Runs [CherryPy][cp] WSGI server hosting WSGI app `func`.
|
||||||
The directory `static/` is hosted statically.
|
The directory `static/` is hosted statically.
|
||||||
|
|
||||||
[cp]: http://www.cherrypy.org
|
[cp]: http://www.cherrypy.org
|
||||||
@ -180,7 +180,7 @@ def runsimple(func, server_address=("0.0.0.0", 8080)):
|
|||||||
else:
|
else:
|
||||||
value = self.wfile.getvalue()
|
value = self.wfile.getvalue()
|
||||||
yield value
|
yield value
|
||||||
|
|
||||||
class WSGIWrapper(BaseHTTPRequestHandler):
|
class WSGIWrapper(BaseHTTPRequestHandler):
|
||||||
"""WSGI wrapper for logging the status and serving static files."""
|
"""WSGI wrapper for logging the status and serving static files."""
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
@ -200,20 +200,23 @@ def runsimple(func, server_address=("0.0.0.0", 8080)):
|
|||||||
return self.app(environ, xstart_response)
|
return self.app(environ, xstart_response)
|
||||||
|
|
||||||
def log(self, status, environ):
|
def log(self, status, environ):
|
||||||
|
#mvoncken,no logging..
|
||||||
|
return
|
||||||
|
|
||||||
outfile = environ.get('wsgi.errors', web.debug)
|
outfile = environ.get('wsgi.errors', web.debug)
|
||||||
req = environ.get('PATH_INFO', '_')
|
req = environ.get('PATH_INFO', '_')
|
||||||
protocol = environ.get('ACTUAL_SERVER_PROTOCOL', '-')
|
protocol = environ.get('ACTUAL_SERVER_PROTOCOL', '-')
|
||||||
method = environ.get('REQUEST_METHOD', '-')
|
method = environ.get('REQUEST_METHOD', '-')
|
||||||
host = "%s:%s" % (environ.get('REMOTE_ADDR','-'),
|
host = "%s:%s" % (environ.get('REMOTE_ADDR','-'),
|
||||||
environ.get('REMOTE_PORT','-'))
|
environ.get('REMOTE_PORT','-'))
|
||||||
|
|
||||||
#@@ It is really bad to extend from
|
#@@ It is really bad to extend from
|
||||||
#@@ BaseHTTPRequestHandler just for this method
|
#@@ BaseHTTPRequestHandler just for this method
|
||||||
time = self.log_date_time_string()
|
time = self.log_date_time_string()
|
||||||
|
|
||||||
print >> outfile, self.format % (host, time, protocol,
|
print >> outfile, self.format % (host, time, protocol,
|
||||||
method, req, status)
|
method, req, status)
|
||||||
|
|
||||||
func = WSGIWrapper(func)
|
func = WSGIWrapper(func)
|
||||||
server = CherryPyWSGIServer(server_address, func, server_name="localhost")
|
server = CherryPyWSGIServer(server_address, func, server_name="localhost")
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user