mirror of
https://github.com/codex-storage/deluge.git
synced 2025-02-02 22:53:40 +00:00
webui https
This commit is contained in:
parent
b3cda61961
commit
f2b057bd30
@ -34,6 +34,7 @@
|
|||||||
from deluge.ui.client import sclient as proxy
|
from deluge.ui.client import sclient as proxy
|
||||||
from deluge.log import LOG as log
|
from deluge.log import LOG as log
|
||||||
|
|
||||||
|
|
||||||
import utils
|
import utils
|
||||||
import lib.newforms_plus as forms
|
import lib.newforms_plus as forms
|
||||||
import config_forms
|
import config_forms
|
||||||
@ -61,12 +62,28 @@ class Template(config_forms.WebCfgForm):
|
|||||||
|
|
||||||
class Server(config_forms.WebCfgForm):
|
class Server(config_forms.WebCfgForm):
|
||||||
title = _("Server")
|
title = _("Server")
|
||||||
|
info = _("Manually restart webui to apply changes.")
|
||||||
|
|
||||||
port = forms.IntegerField(label = _("Port"),min_value=80)
|
port = forms.IntegerField(label = _("Port"),min_value=80)
|
||||||
|
https = forms.CheckBox(_("Https"))
|
||||||
|
|
||||||
|
def validate(self, data):
|
||||||
|
import os
|
||||||
|
from deluge.common import get_default_config_dir
|
||||||
|
|
||||||
|
if data.https:
|
||||||
|
cert_path = os.path.join(get_default_config_dir("ssl") ,"deluge.cert.pem" )
|
||||||
|
if not os.path.exists (cert_path):
|
||||||
|
raise forms.ValidationError(_("Certificate not found at '%s'" % cert_path))
|
||||||
|
key_path = os.path.join(get_default_config_dir("ssl") ,"deluge.key.pem" )
|
||||||
|
if not os.path.exists (key_path):
|
||||||
|
raise forms.ValidationError(_("Key not found at '%s'" % key_path))
|
||||||
|
|
||||||
|
|
||||||
def post_save(self):
|
def post_save(self):
|
||||||
pass
|
pass
|
||||||
#raise forms.ValidationError(
|
#raise forms.ValidationError(
|
||||||
# _("Manually restart server to apply these changes."))
|
# )
|
||||||
|
|
||||||
class Password(forms.Form):
|
class Password(forms.Form):
|
||||||
title = _("Password")
|
title = _("Password")
|
||||||
|
@ -38,6 +38,7 @@ from deluge.ui.client import sclient
|
|||||||
import components
|
import components
|
||||||
from deluge.log import LOG as log
|
from deluge.log import LOG as log
|
||||||
|
|
||||||
|
|
||||||
# Initialize gettext
|
# Initialize gettext
|
||||||
if deluge.common.windows_check() or deluge.common.osx_check():
|
if deluge.common.windows_check() or deluge.common.osx_check():
|
||||||
locale.setlocale(locale.LC_ALL, '')
|
locale.setlocale(locale.LC_ALL, '')
|
||||||
@ -121,7 +122,21 @@ def create_webserver(debug = False, base_url =None):
|
|||||||
server_address=("0.0.0.0", int(config.get('port')))
|
server_address=("0.0.0.0", int(config.get('port')))
|
||||||
server = CherryPyWSGIServer(server_address, wsgi_app, server_name="localhost")
|
server = CherryPyWSGIServer(server_address, wsgi_app, server_name="localhost")
|
||||||
|
|
||||||
log.info("http://%s:%d/" % server_address)
|
https = False
|
||||||
|
if config.get("https"):
|
||||||
|
import os
|
||||||
|
from deluge.common import get_default_config_dir
|
||||||
|
cert_path = os.path.join(get_default_config_dir("ssl") ,"deluge.cert.pem" )
|
||||||
|
key_path = os.path.join(get_default_config_dir("ssl") ,"deluge.key.pem" )
|
||||||
|
if os.path.exists (key_path) and os.path.exists (cert_path):
|
||||||
|
server.ssl_certificate = cert_path
|
||||||
|
server.ssl_private_key = key_path
|
||||||
|
https = True
|
||||||
|
|
||||||
|
if https:
|
||||||
|
log.info("https://%s:%d/" % server_address)
|
||||||
|
else:
|
||||||
|
log.info("http://%s:%d/" % server_address)
|
||||||
return server
|
return server
|
||||||
|
|
||||||
def run(debug = False, base_url = ""):
|
def run(debug = False, base_url = ""):
|
||||||
|
@ -9,7 +9,7 @@ __all__ = [
|
|||||||
"header", "output", "flush", "debug",
|
"header", "output", "flush", "debug",
|
||||||
"input", "data",
|
"input", "data",
|
||||||
"setcookie", "cookies",
|
"setcookie", "cookies",
|
||||||
"ctx",
|
"ctx",
|
||||||
"loadhooks", "load", "unloadhooks", "unload", "_loadhooks",
|
"loadhooks", "load", "unloadhooks", "unload", "_loadhooks",
|
||||||
"wsgifunc"
|
"wsgifunc"
|
||||||
]
|
]
|
||||||
@ -59,19 +59,19 @@ def internalerror():
|
|||||||
def header(hdr, value, unique=False):
|
def header(hdr, value, unique=False):
|
||||||
"""
|
"""
|
||||||
Adds the header `hdr: value` with the response.
|
Adds the header `hdr: value` with the response.
|
||||||
|
|
||||||
If `unique` is True and a header with that name already exists,
|
If `unique` is True and a header with that name already exists,
|
||||||
it doesn't add a new one.
|
it doesn't add a new one.
|
||||||
"""
|
"""
|
||||||
hdr, value = utf8(hdr), utf8(value)
|
hdr, value = utf8(hdr), utf8(value)
|
||||||
# protection against HTTP response splitting attack
|
# protection against HTTP response splitting attack
|
||||||
if '\n' in hdr or '\r' in hdr or '\n' in value or '\r' in value:
|
if '\n' in hdr or '\r' in hdr or '\n' in value or '\r' in value:
|
||||||
raise ValueError, 'invalid characters in header'
|
raise ValueError, 'invalid characters in header'
|
||||||
|
|
||||||
if unique is True:
|
if unique is True:
|
||||||
for h, v in ctx.headers:
|
for h, v in ctx.headers:
|
||||||
if h.lower() == hdr.lower(): return
|
if h.lower() == hdr.lower(): return
|
||||||
|
|
||||||
ctx.headers.append((hdr, value))
|
ctx.headers.append((hdr, value))
|
||||||
|
|
||||||
def output(string_):
|
def output(string_):
|
||||||
@ -88,20 +88,20 @@ def flush():
|
|||||||
|
|
||||||
def input(*requireds, **defaults):
|
def input(*requireds, **defaults):
|
||||||
"""
|
"""
|
||||||
Returns a `storage` object with the GET and POST arguments.
|
Returns a `storage` object with the GET and POST arguments.
|
||||||
See `storify` for how `requireds` and `defaults` work.
|
See `storify` for how `requireds` and `defaults` work.
|
||||||
"""
|
"""
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
def dictify(fs): return dict([(k, fs[k]) for k in fs.keys()])
|
def dictify(fs): return dict([(k, fs[k]) for k in fs.keys()])
|
||||||
|
|
||||||
_method = defaults.pop('_method', 'both')
|
_method = defaults.pop('_method', 'both')
|
||||||
|
|
||||||
e = ctx.env.copy()
|
e = ctx.env.copy()
|
||||||
a = b = {}
|
a = b = {}
|
||||||
|
|
||||||
if _method.lower() in ['both', 'post']:
|
if _method.lower() in ['both', 'post']:
|
||||||
if e['REQUEST_METHOD'] == 'POST':
|
if e['REQUEST_METHOD'] == 'POST':
|
||||||
a = cgi.FieldStorage(fp = StringIO(data()), environ=e,
|
a = cgi.FieldStorage(fp = StringIO(data()), environ=e,
|
||||||
keep_blank_values=1)
|
keep_blank_values=1)
|
||||||
a = dictify(a)
|
a = dictify(a)
|
||||||
|
|
||||||
@ -125,15 +125,15 @@ def data():
|
|||||||
|
|
||||||
def setcookie(name, value, expires="", domain=None):
|
def setcookie(name, value, expires="", domain=None):
|
||||||
"""Sets a cookie."""
|
"""Sets a cookie."""
|
||||||
if expires < 0:
|
if expires < 0:
|
||||||
expires = -1000000000
|
expires = -1000000000
|
||||||
kargs = {'expires': expires, 'path':'/'}
|
kargs = {'expires': expires, 'path':'/'}
|
||||||
if domain:
|
if domain:
|
||||||
kargs['domain'] = domain
|
kargs['domain'] = domain
|
||||||
# @@ should we limit cookies to a different path?
|
# @@ should we limit cookies to a different path?
|
||||||
cookie = Cookie.SimpleCookie()
|
cookie = Cookie.SimpleCookie()
|
||||||
cookie[name] = value
|
cookie[name] = value
|
||||||
for key, val in kargs.iteritems():
|
for key, val in kargs.iteritems():
|
||||||
cookie[name][key] = val
|
cookie[name][key] = val
|
||||||
header('Set-Cookie', cookie.items()[0][1].OutputString())
|
header('Set-Cookie', cookie.items()[0][1].OutputString())
|
||||||
|
|
||||||
@ -154,18 +154,18 @@ def debug(*args):
|
|||||||
"""
|
"""
|
||||||
Prints a prettyprinted version of `args` to stderr.
|
Prints a prettyprinted version of `args` to stderr.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
out = ctx.environ['wsgi.errors']
|
out = ctx.environ['wsgi.errors']
|
||||||
except:
|
except:
|
||||||
out = sys.stderr
|
out = sys.stderr
|
||||||
for arg in args:
|
for arg in args:
|
||||||
print >> out, pprint.pformat(arg)
|
print >> out, pprint.pformat(arg)
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
def _debugwrite(x):
|
def _debugwrite(x):
|
||||||
try:
|
try:
|
||||||
out = ctx.environ['wsgi.errors']
|
out = ctx.environ['wsgi.errors']
|
||||||
except:
|
except:
|
||||||
out = sys.stderr
|
out = sys.stderr
|
||||||
out.write(x)
|
out.write(x)
|
||||||
debug.write = _debugwrite
|
debug.write = _debugwrite
|
||||||
@ -173,8 +173,8 @@ debug.write = _debugwrite
|
|||||||
class _outputter:
|
class _outputter:
|
||||||
"""Wraps `sys.stdout` so that print statements go into the response."""
|
"""Wraps `sys.stdout` so that print statements go into the response."""
|
||||||
def __init__(self, file): self.file = file
|
def __init__(self, file): self.file = file
|
||||||
def write(self, string_):
|
def write(self, string_):
|
||||||
if hasattr(ctx, 'output'):
|
if hasattr(ctx, 'output'):
|
||||||
return output(string_)
|
return output(string_)
|
||||||
else:
|
else:
|
||||||
self.file.write(string_)
|
self.file.write(string_)
|
||||||
@ -186,7 +186,7 @@ def _capturedstdout():
|
|||||||
while hasattr(sysstd, 'file'):
|
while hasattr(sysstd, 'file'):
|
||||||
if isinstance(sys.stdout, _outputter): return True
|
if isinstance(sys.stdout, _outputter): return True
|
||||||
sysstd = sysstd.file
|
sysstd = sysstd.file
|
||||||
if isinstance(sys.stdout, _outputter): return True
|
if isinstance(sys.stdout, _outputter): return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not _capturedstdout():
|
if not _capturedstdout():
|
||||||
@ -197,7 +197,7 @@ ctx = context = threadeddict(_context)
|
|||||||
|
|
||||||
ctx.__doc__ = """
|
ctx.__doc__ = """
|
||||||
A `storage` object containing various information about the request:
|
A `storage` object containing various information about the request:
|
||||||
|
|
||||||
`environ` (aka `env`)
|
`environ` (aka `env`)
|
||||||
: A dictionary containing the standard WSGI environment variables.
|
: A dictionary containing the standard WSGI environment variables.
|
||||||
|
|
||||||
@ -215,7 +215,7 @@ A `storage` object containing various information about the request:
|
|||||||
|
|
||||||
`path`
|
`path`
|
||||||
: The path request.
|
: The path request.
|
||||||
|
|
||||||
`query`
|
`query`
|
||||||
: If there are no query arguments, the empty string. Otherwise, a `?` followed
|
: If there are no query arguments, the empty string. Otherwise, a `?` followed
|
||||||
by the query string.
|
by the query string.
|
||||||
@ -241,8 +241,8 @@ _loadhooks = {}
|
|||||||
def load():
|
def load():
|
||||||
"""
|
"""
|
||||||
Loads a new context for the thread.
|
Loads a new context for the thread.
|
||||||
|
|
||||||
You can ask for a function to be run at loadtime by
|
You can ask for a function to be run at loadtime by
|
||||||
adding it to the dictionary `loadhooks`.
|
adding it to the dictionary `loadhooks`.
|
||||||
"""
|
"""
|
||||||
_context[threading.currentThread()] = storage()
|
_context[threading.currentThread()] = storage()
|
||||||
@ -251,7 +251,7 @@ def load():
|
|||||||
if config.get('db_parameters'):
|
if config.get('db_parameters'):
|
||||||
import db
|
import db
|
||||||
db.connect(**config.db_parameters)
|
db.connect(**config.db_parameters)
|
||||||
|
|
||||||
for x in loadhooks.values(): x()
|
for x in loadhooks.values(): x()
|
||||||
|
|
||||||
def _load(env):
|
def _load(env):
|
||||||
@ -259,7 +259,13 @@ def _load(env):
|
|||||||
ctx.output = ''
|
ctx.output = ''
|
||||||
ctx.environ = ctx.env = env
|
ctx.environ = ctx.env = env
|
||||||
ctx.host = env.get('HTTP_HOST')
|
ctx.host = env.get('HTTP_HOST')
|
||||||
ctx.homedomain = 'http://' + env.get('HTTP_HOST', '[unknown]')
|
|
||||||
|
#http://groups.google.com/group/webpy/browse_thread/thread/2a4665e54b07c991?pli=1
|
||||||
|
if env.get('HTTPS'):
|
||||||
|
ctx.protocol = "https"
|
||||||
|
else:
|
||||||
|
ctx.protocol = "http"
|
||||||
|
ctx.homedomain = ctx.protocol + "://" + env.get('HTTP_HOST','[unknown]')
|
||||||
ctx.homepath = os.environ.get('REAL_SCRIPT_NAME', env.get('SCRIPT_NAME', ''))
|
ctx.homepath = os.environ.get('REAL_SCRIPT_NAME', env.get('SCRIPT_NAME', ''))
|
||||||
ctx.home = ctx.homedomain + ctx.homepath
|
ctx.home = ctx.homedomain + ctx.homepath
|
||||||
ctx.ip = env.get('REMOTE_ADDR')
|
ctx.ip = env.get('REMOTE_ADDR')
|
||||||
@ -267,14 +273,14 @@ def _load(env):
|
|||||||
ctx.path = env.get('PATH_INFO')
|
ctx.path = env.get('PATH_INFO')
|
||||||
# http://trac.lighttpd.net/trac/ticket/406 requires:
|
# http://trac.lighttpd.net/trac/ticket/406 requires:
|
||||||
if env.get('SERVER_SOFTWARE', '').startswith('lighttpd/'):
|
if env.get('SERVER_SOFTWARE', '').startswith('lighttpd/'):
|
||||||
ctx.path = lstrips(env.get('REQUEST_URI').split('?')[0],
|
ctx.path = lstrips(env.get('REQUEST_URI').split('?')[0],
|
||||||
os.environ.get('REAL_SCRIPT_NAME', env.get('SCRIPT_NAME', '')))
|
os.environ.get('REAL_SCRIPT_NAME', env.get('SCRIPT_NAME', '')))
|
||||||
|
|
||||||
if env.get('QUERY_STRING'):
|
if env.get('QUERY_STRING'):
|
||||||
ctx.query = '?' + env.get('QUERY_STRING', '')
|
ctx.query = '?' + env.get('QUERY_STRING', '')
|
||||||
else:
|
else:
|
||||||
ctx.query = ''
|
ctx.query = ''
|
||||||
|
|
||||||
ctx.fullpath = ctx.path + ctx.query
|
ctx.fullpath = ctx.path + ctx.query
|
||||||
for x in _loadhooks.values(): x()
|
for x in _loadhooks.values(): x()
|
||||||
|
|
||||||
@ -283,7 +289,7 @@ unloadhooks = {}
|
|||||||
def unload():
|
def unload():
|
||||||
"""
|
"""
|
||||||
Unloads the context for the thread.
|
Unloads the context for the thread.
|
||||||
|
|
||||||
You can ask for a function to be run at loadtime by
|
You can ask for a function to be run at loadtime by
|
||||||
adding it ot the dictionary `unloadhooks`.
|
adding it ot the dictionary `unloadhooks`.
|
||||||
"""
|
"""
|
||||||
@ -297,7 +303,7 @@ def _unload():
|
|||||||
def wsgifunc(func, *middleware):
|
def wsgifunc(func, *middleware):
|
||||||
"""Returns a WSGI-compatible function from a webpy-function."""
|
"""Returns a WSGI-compatible function from a webpy-function."""
|
||||||
middleware = list(middleware)
|
middleware = list(middleware)
|
||||||
|
|
||||||
def wsgifunc(env, start_resp):
|
def wsgifunc(env, start_resp):
|
||||||
_load(env)
|
_load(env)
|
||||||
try:
|
try:
|
||||||
@ -307,7 +313,7 @@ def wsgifunc(func, *middleware):
|
|||||||
except:
|
except:
|
||||||
print >> debug, traceback.format_exc()
|
print >> debug, traceback.format_exc()
|
||||||
result = internalerror()
|
result = internalerror()
|
||||||
|
|
||||||
is_generator = result and hasattr(result, 'next')
|
is_generator = result and hasattr(result, 'next')
|
||||||
if is_generator:
|
if is_generator:
|
||||||
# wsgi requires the headers first
|
# wsgi requires the headers first
|
||||||
@ -322,19 +328,19 @@ def wsgifunc(func, *middleware):
|
|||||||
ctx._write = start_resp(status, headers)
|
ctx._write = start_resp(status, headers)
|
||||||
|
|
||||||
# and now, the fun:
|
# and now, the fun:
|
||||||
|
|
||||||
def cleanup():
|
def cleanup():
|
||||||
# we insert this little generator
|
# we insert this little generator
|
||||||
# at the end of our itertools.chain
|
# at the end of our itertools.chain
|
||||||
# so that it unloads the request
|
# so that it unloads the request
|
||||||
# when everything else is done
|
# when everything else is done
|
||||||
|
|
||||||
yield '' # force it to be a generator
|
yield '' # force it to be a generator
|
||||||
_unload()
|
_unload()
|
||||||
|
|
||||||
# result is the output of calling the webpy function
|
# result is the output of calling the webpy function
|
||||||
# it could be a generator...
|
# it could be a generator...
|
||||||
|
|
||||||
if is_generator:
|
if is_generator:
|
||||||
if firstchunk is flush:
|
if firstchunk is flush:
|
||||||
# oh, it's just our special flush mode
|
# oh, it's just our special flush mode
|
||||||
@ -348,22 +354,22 @@ def wsgifunc(func, *middleware):
|
|||||||
return []
|
return []
|
||||||
else:
|
else:
|
||||||
return itertools.chain([firstchunk], result, cleanup())
|
return itertools.chain([firstchunk], result, cleanup())
|
||||||
|
|
||||||
# ... but it's usually just None
|
# ... but it's usually just None
|
||||||
#
|
#
|
||||||
# output is the stuff in ctx.output
|
# output is the stuff in ctx.output
|
||||||
# it's usually a string...
|
# it's usually a string...
|
||||||
if isinstance(output, str): #@@ other stringlikes?
|
if isinstance(output, str): #@@ other stringlikes?
|
||||||
_unload()
|
_unload()
|
||||||
return [output]
|
return [output]
|
||||||
# it could be a generator...
|
# it could be a generator...
|
||||||
elif hasattr(output, 'next'):
|
elif hasattr(output, 'next'):
|
||||||
return itertools.chain(output, cleanup())
|
return itertools.chain(output, cleanup())
|
||||||
else:
|
else:
|
||||||
_unload()
|
_unload()
|
||||||
raise Exception, "Invalid ctx.output"
|
raise Exception, "Invalid ctx.output"
|
||||||
|
|
||||||
for mw_func in middleware:
|
for mw_func in middleware:
|
||||||
wsgifunc = mw_func(wsgifunc)
|
wsgifunc = mw_func(wsgifunc)
|
||||||
|
|
||||||
return wsgifunc
|
return wsgifunc
|
||||||
|
@ -5,6 +5,15 @@ $def with (title, active_tab="NONE")
|
|||||||
<link rel="icon" href="$base/static/images/deluge-icon.png" type="image/png" />
|
<link rel="icon" href="$base/static/images/deluge-icon.png" type="image/png" />
|
||||||
<link rel="shortcut icon" href="$base/static/images/deluge-icon.png" type="image/png" />
|
<link rel="shortcut icon" href="$base/static/images/deluge-icon.png" type="image/png" />
|
||||||
<link rel="stylesheet" type="text/css" href="$base/static/simple_site_style.css" />
|
<link rel="stylesheet" type="text/css" href="$base/static/simple_site_style.css" />
|
||||||
|
<!--javascript is only used for plugins in the classic-ui
|
||||||
|
classic ui should function without js.
|
||||||
|
-->
|
||||||
|
<script language="javascript" src="$base/gettext.js"></script>
|
||||||
|
<script language="javascript" src="$base/static/mootools-1.2-core.js"></script>
|
||||||
|
<script language="javascript" src="$base/static/mootools-1.2-more.js"></script>
|
||||||
|
<script language="javascript" src="$base/static/mooui.js"></script>
|
||||||
|
$for js in include_javascript:
|
||||||
|
<script language="javascript" src="$base$js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="page">
|
<div id="page">
|
||||||
|
@ -7,6 +7,7 @@ $def with (title, active_tab="NONE")
|
|||||||
<link rel="icon" href="$base/static/images/deluge-icon.png" type="image/png" />
|
<link rel="icon" href="$base/static/images/deluge-icon.png" type="image/png" />
|
||||||
<link rel="shortcut icon" href="$base/static/images/deluge-icon.png" type="image/png" />
|
<link rel="shortcut icon" href="$base/static/images/deluge-icon.png" type="image/png" />
|
||||||
<link rel="stylesheet" type="text/css" href="$base/template_style.css" />
|
<link rel="stylesheet" type="text/css" href="$base/template_style.css" />
|
||||||
|
<script language="javascript" src="$base/gettext.js"></script>
|
||||||
<script language="javascript" src="$base/static/deluge.js"></script>
|
<script language="javascript" src="$base/static/deluge.js"></script>
|
||||||
<script language="javascript" src="$base/static/mootools-1.2-core.js"></script>
|
<script language="javascript" src="$base/static/mootools-1.2-core.js"></script>
|
||||||
<script language="javascript" src="$base/static/mootools-1.2-more.js"></script>
|
<script language="javascript" src="$base/static/mootools-1.2-more.js"></script>
|
||||||
|
@ -65,5 +65,6 @@ CONFIG_DEFAULTS = {
|
|||||||
"sidebar_show_zero":False,
|
"sidebar_show_zero":False,
|
||||||
"sidebar_show_trackers":False,
|
"sidebar_show_trackers":False,
|
||||||
"show_keyword_search":False,
|
"show_keyword_search":False,
|
||||||
"show_sidebar":True
|
"show_sidebar":True,
|
||||||
|
"https":False
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user