summaryrefslogtreecommitdiffstats
path: root/pyload/webui
diff options
context:
space:
mode:
Diffstat (limited to 'pyload/webui')
-rw-r--r--pyload/webui/__init__.py34
-rw-r--r--pyload/webui/app/api.py29
-rw-r--r--pyload/webui/app/cnl.py39
-rw-r--r--pyload/webui/app/json.py62
-rw-r--r--pyload/webui/app/pyloadweb.py83
-rw-r--r--pyload/webui/app/utils.py10
6 files changed, 126 insertions, 131 deletions
diff --git a/pyload/webui/__init__.py b/pyload/webui/__init__.py
index 58d60b5cc..472e1a4f7 100644
--- a/pyload/webui/__init__.py
+++ b/pyload/webui/__init__.py
@@ -3,27 +3,27 @@
import os
import sys
-import pyload.utils.pylgettext as gettext
-THEME_DIR = os.path.abspath(os.path.join(dirname(__file__), "themes"))
-PYLOAD_DIR = os.path.abspath(os.path.join(THEME_DIR, "..", "..", ".."))
+import bottle
-sys.path.append(PYLOAD_DIR)
+import pyload.utils.pylgettext as gettext
+
+from jinja2 import Environment, FileSystemLoader, PrefixLoader, FileSystemBytecodeCache
+from pyload.Thread import Server
+from pyload.Webui.middlewares import StripPathMiddleware, GZipMiddleWare, PrefixMiddleware
+from pyload.network.JsEngine import JsEngine
from pyload.utils import decode, formatSize
-import bottle
-from bottle import run, app
-from jinja2 import Environment, FileSystemLoader, PrefixLoader, FileSystemBytecodeCache
-from middlewares import StripPathMiddleware, GZipMiddleWare, PrefixMiddleware
+THEME_DIR = os.path.abspath(os.path.join(dirname(__file__), "themes"))
+PYLOAD_DIR = os.path.abspath(os.path.join(THEME_DIR, "..", "..", ".."))
+
+sys.path.append(PYLOAD_DIR)
SETUP = None
PYLOAD = None
-from pyload.Thread import Server
-from pyload.network.JsEngine import JsEngine
-
if not Server.core:
if Server.setup:
SETUP = Server.setup
@@ -91,7 +91,7 @@ session_opts = {
'session.auto': False
}
-web = StripPathMiddleware(SessionMiddleware(app(), session_opts))
+web = StripPathMiddleware(SessionMiddleware(bottle.app(), session_opts))
web = GZipMiddleWare(web)
if PREFIX:
@@ -101,11 +101,11 @@ import pyload.webui.app
def run_auto(host="0.0.0.0", port="8000"):
- run(app=web, host=host, port=port, server="auto", quiet=True)
+ bottle.run(app=web, host=host, port=port, server="auto", quiet=True)
def run_lightweight(host="0.0.0.0", port="8000"):
- run(app=web, host=host, port=port, server="bjoern", quiet=True)
+ bottle.run(app=web, host=host, port=port, server="bjoern", quiet=True)
def run_threaded(host="0.0.0.0", port="8000", theads=3, cert="", key=""):
@@ -119,10 +119,8 @@ def run_threaded(host="0.0.0.0", port="8000", theads=3, cert="", key=""):
from pyload.webui.app.utils import CherryPyWSGI
- run(app=web, host=host, port=port, server=CherryPyWSGI, quiet=True)
+ bottle.run(app=web, host=host, port=port, server=CherryPyWSGI, quiet=True)
def run_fcgi(host="0.0.0.0", port="8000"):
- from bottle import FlupFCGIServer
-
- run(app=web, host=host, port=port, server=FlupFCGIServer, quiet=True)
+ bottle.run(app=web, host=host, port=port, server=bottle.FlupFCGIServer, quiet=True)
diff --git a/pyload/webui/app/api.py b/pyload/webui/app/api.py
index 35dbe9009..99a7c2998 100644
--- a/pyload/webui/app/api.py
+++ b/pyload/webui/app/api.py
@@ -1,12 +1,11 @@
# -*- coding: utf-8 -*-
+import itertools
import traceback
import urllib
-from itertools import chain
-
-from SafeEval import const_eval as literal_eval
-from bottle import route, request, response, HTTPError
+import SafeEval
+import bottle
from pyload.Api import BaseObject
from pyload.utils import json
@@ -24,8 +23,8 @@ class TBaseEncoder(json.JSONEncoder):
# accepting positional arguments, as well as kwargs via post and get
-@route('/api/<func><args:re:[a-zA-Z0-9\-_/\"\'\[\]%{},]*>')
-@route('/api/<func><args:re:[a-zA-Z0-9\-_/\"\'\[\]%{},]*>', method='POST')
+@bottle.route('/api/<func><args:re:[a-zA-Z0-9\-_/\"\'\[\]%{},]*>')
+@bottle.route('/api/<func><args:re:[a-zA-Z0-9\-_/\"\'\[\]%{},]*>', method='POST')
def call_api(func, args=""):
response.headers.replace("Content-type", "application/json")
response.headers.append("Cache-Control", "no-cache, must-revalidate")
@@ -35,15 +34,15 @@ def call_api(func, args=""):
s = s.get_by_id(request.POST['session'])
if not s or not s.get("authenticated", False):
- return HTTPError(403, json.dumps("Forbidden"))
+ return bottle.HTTPError(403, json.dumps("Forbidden"))
if not PYLOAD.isAuthorized(func, {"role": s['role'], "permission": s['perms']}):
- return HTTPError(401, json.dumps("Unauthorized"))
+ return bottle.HTTPError(401, json.dumps("Unauthorized"))
args = args.split("/")[1:]
kwargs = {}
- for x, y in chain(request.GET.iteritems(), request.POST.iteritems()):
+ for x, y in itertools.chain(request.GET.iteritems(), request.POST.iteritems()):
if x == "session":
continue
kwargs[x] = urllib.unquote(y)
@@ -52,23 +51,23 @@ def call_api(func, args=""):
return callApi(func, *args, **kwargs)
except Exception, e:
traceback.print_exc()
- return HTTPError(500, json.dumps({"error": e.message, "traceback": traceback.format_exc()}))
+ return bottle.HTTPError(500, json.dumps({"error": e.message, "traceback": traceback.format_exc()}))
def callApi(func, *args, **kwargs):
if not hasattr(PYLOAD.EXTERNAL, func) or func.startswith("_"):
print "Invalid API call", func
- return HTTPError(404, json.dumps("Not Found"))
+ return bottle.HTTPError(404, json.dumps("Not Found"))
- result = getattr(PYLOAD, func)(*[literal_eval(x) for x in args],
- **dict((x, literal_eval(y)) for x, y in kwargs.iteritems()))
+ result = getattr(PYLOAD, func)(*[SafeEval.const_eval(x) for x in args],
+ **dict((x, SafeEval.const_eval(y)) for x, y in kwargs.iteritems()))
# null is invalid json response
return json.dumps(result or True, cls=TBaseEncoder)
# post -> username, password
-@route('/api/login', method='POST')
+@bottle.route('/api/login', method='POST')
def login():
response.headers.replace("Content-type", "application/json")
response.headers.append("Cache-Control", "no-cache, must-revalidate")
@@ -91,7 +90,7 @@ def login():
return json.dumps(True)
-@route('/api/logout')
+@bottle.route('/api/logout')
def logout():
response.headers.replace("Content-type", "application/json")
response.headers.append("Cache-Control", "no-cache, must-revalidate")
diff --git a/pyload/webui/app/cnl.py b/pyload/webui/app/cnl.py
index 7202a2db4..465e087e5 100644
--- a/pyload/webui/app/cnl.py
+++ b/pyload/webui/app/cnl.py
@@ -3,13 +3,12 @@
from __future__ import with_statement
import base64
+import binascii
import os
import re
import urllib
-from binascii import unhexlify
-
-from bottle import route, request, HTTPError
+import bottle
from pyload.webui import PYLOAD, DL_ROOT, JS
@@ -28,20 +27,20 @@ def local_check(function):
or request.environ.get("HTTP_HOST", "0") in ("127.0.0.1:9666", "localhost:9666"):
return function(*args, **kwargs)
else:
- return HTTPError(403, "Forbidden")
+ return bottle.HTTPError(403, "Forbidden")
return _view
-@route('/flash')
-@route('/flash/<id>')
-@route('/flash', method='POST')
+@bottle.route('/flash')
+@bottle.route('/flash/<id>')
+@bottle.route('/flash', method='POST')
@local_check
def flash(id="0"):
return "JDownloader\r\n"
-@route('/flash/add', method='POST')
+@bottle.route('/flash/add', method='POST')
@local_check
def add(request):
package = request.POST.get('referer', None)
@@ -55,7 +54,7 @@ def add(request):
return ""
-@route('/flash/addcrypted', method='POST')
+@bottle.route('/flash/addcrypted', method='POST')
@local_check
def addcrypted():
package = request.forms.get('referer', 'ClickNLoad Package')
@@ -68,12 +67,12 @@ def addcrypted():
try:
PYLOAD.addPackage(package, [dlc_path], 0)
except Exception:
- return HTTPError()
+ return bottle.HTTPError()
else:
return "success\r\n"
-@route('/flash/addcrypted2', method='POST')
+@bottle.route('/flash/addcrypted2', method='POST')
@local_check
def addcrypted2():
package = request.forms.get("source", None)
@@ -99,7 +98,7 @@ def addcrypted2():
print "Could not decrypt key, please install py-spidermonkey or ossp-js"
try:
- Key = unhexlify(jk)
+ Key = binascii.unhexlify(jk)
except Exception:
print "Could not decrypt key, please install py-spidermonkey or ossp-js"
return "failed"
@@ -122,14 +121,14 @@ def addcrypted2():
return "success\r\n"
-@route('/flashgot_pyload')
-@route('/flashgot_pyload', method='POST')
-@route('/flashgot')
-@route('/flashgot', method='POST')
+@bottle.route('/flashgot_pyload')
+@bottle.route('/flashgot_pyload', method='POST')
+@bottle.route('/flashgot')
+@bottle.route('/flashgot', method='POST')
@local_check
def flashgot():
if request.environ['HTTP_REFERER'] not in ("http://localhost:9666/flashgot", "http://127.0.0.1:9666/flashgot"):
- return HTTPError()
+ return bottle.HTTPError()
autostart = int(request.forms.get('autostart', 0))
package = request.forms.get('package', None)
@@ -144,7 +143,7 @@ def flashgot():
return ""
-@route('/crossdomain.xml')
+@bottle.route('/crossdomain.xml')
@local_check
def crossdomain():
rep = "<?xml version=\"1.0\"?>\n"
@@ -155,7 +154,7 @@ def crossdomain():
return rep
-@route('/flash/checkSupportForUrl')
+@bottle.route('/flash/checkSupportForUrl')
@local_check
def checksupport():
url = request.GET.get("url")
@@ -165,7 +164,7 @@ def checksupport():
return str(supported).lower()
-@route('/jdcheck.js')
+@bottle.route('/jdcheck.js')
@local_check
def jdcheck():
rep = "jdownloader=true;\n"
diff --git a/pyload/webui/app/json.py b/pyload/webui/app/json.py
index 24952cc34..a7fe8dcfb 100644
--- a/pyload/webui/app/json.py
+++ b/pyload/webui/app/json.py
@@ -6,7 +6,7 @@ import os
import shutil
import traceback
-from bottle import route, request, HTTPError
+import bottle
from pyload.utils import decode, formatSize
from pyload.webui import PYLOAD
@@ -25,8 +25,8 @@ def get_sort_key(item):
return item['order']
-@route('/json/status')
-@route('/json/status', method='POST')
+@bottle.route('/json/status')
+@bottle.route('/json/status', method='POST')
@login_required('LIST')
def status():
try:
@@ -34,11 +34,11 @@ def status():
status['captcha'] = PYLOAD.isCaptchaWaiting()
return status
except Exception:
- return HTTPError()
+ return bottle.HTTPError()
-@route('/json/links')
-@route('/json/links', method='POST')
+@bottle.route('/json/links')
+@bottle.route('/json/links', method='POST')
@login_required('LIST')
def links():
try:
@@ -61,10 +61,10 @@ def links():
return data
except Exception, e:
traceback.print_exc()
- return HTTPError()
+ return bottle.HTTPError()
-@route('/json/packages')
+@bottle.route('/json/packages')
@login_required('LIST')
def packages():
print "/json/packages"
@@ -79,10 +79,10 @@ def packages():
return data
except Exception:
- return HTTPError()
+ return bottle.HTTPError()
-@route('/json/package/<id:int>')
+@bottle.route('/json/package/<id:int>')
@login_required('LIST')
def package(id):
try:
@@ -114,10 +114,10 @@ def package(id):
except Exception:
traceback.print_exc()
- return HTTPError()
+ return bottle.HTTPError()
-@route('/json/package_order/<ids>')
+@bottle.route('/json/package_order/<ids>')
@login_required('ADD')
def package_order(ids):
try:
@@ -125,20 +125,20 @@ def package_order(ids):
PYLOAD.orderPackage(int(pid), int(pos))
return {"response": "success"}
except Exception:
- return HTTPError()
+ return bottle.HTTPError()
-@route('/json/abort_link/<id:int>')
+@bottle.route('/json/abort_link/<id:int>')
@login_required('DELETE')
def abort_link(id):
try:
PYLOAD.stopDownloads([id])
return {"response": "success"}
except Exception:
- return HTTPError()
+ return bottle.HTTPError()
-@route('/json/link_order/<ids>')
+@bottle.route('/json/link_order/<ids>')
@login_required('ADD')
def link_order(ids):
try:
@@ -146,11 +146,11 @@ def link_order(ids):
PYLOAD.orderFile(int(pid), int(pos))
return {"response": "success"}
except Exception:
- return HTTPError()
+ return bottle.HTTPError()
-@route('/json/add_package')
-@route('/json/add_package', method='POST')
+@bottle.route('/json/add_package')
+@bottle.route('/json/add_package', method='POST')
@login_required('ADD')
def add_package():
name = request.forms.get("add_name", "New Package").strip()
@@ -184,17 +184,17 @@ def add_package():
PYLOAD.setPackageData(pack, data)
-@route('/json/move_package/<dest:int>/<id:int>')
+@bottle.route('/json/move_package/<dest:int>/<id:int>')
@login_required('MODIFY')
def move_package(dest, id):
try:
PYLOAD.movePackage(dest, id)
return {"response": "success"}
except Exception:
- return HTTPError()
+ return bottle.HTTPError()
-@route('/json/edit_package', method='POST')
+@bottle.route('/json/edit_package', method='POST')
@login_required('MODIFY')
def edit_package():
try:
@@ -207,11 +207,11 @@ def edit_package():
return {"response": "success"}
except Exception:
- return HTTPError()
+ return bottle.HTTPError()
-@route('/json/set_captcha')
-@route('/json/set_captcha', method='POST')
+@bottle.route('/json/set_captcha')
+@bottle.route('/json/set_captcha', method='POST')
@login_required('ADD')
def set_captcha():
if request.environ.get('REQUEST_METHOD', "GET") == "POST":
@@ -230,7 +230,7 @@ def set_captcha():
return {'captcha': False}
-@route('/json/load_config/<category>/<section>')
+@bottle.route('/json/load_config/<category>/<section>')
@login_required("SETTINGS")
def load_config(category, section):
conf = None
@@ -252,7 +252,7 @@ def load_config(category, section):
"skey": section, "section": conf[section]})
-@route('/json/save_config/<category>', method='POST')
+@bottle.route('/json/save_config/<category>', method='POST')
@login_required("SETTINGS")
def save_config(category):
for key, value in request.POST.iteritems():
@@ -266,7 +266,7 @@ def save_config(category):
PYLOAD.setConfigValue(section, option, decode(value), category)
-@route('/json/add_account', method='POST')
+@bottle.route('/json/add_account', method='POST')
@login_required("ACCOUNTS")
def add_account():
login = request.POST['account_login']
@@ -276,7 +276,7 @@ def add_account():
PYLOAD.updateAccount(type, login, password)
-@route('/json/update_accounts', method='POST')
+@bottle.route('/json/update_accounts', method='POST')
@login_required("ACCOUNTS")
def update_accounts():
deleted = [] #: dont update deleted accs or they will be created again
@@ -303,7 +303,7 @@ def update_accounts():
PYLOAD.removeAccount(plugin, user)
-@route('/json/change_password', method='POST')
+@bottle.route('/json/change_password', method='POST')
def change_password():
user = request.POST['user_login']
oldpw = request.POST['login_current_password']
@@ -311,4 +311,4 @@ def change_password():
if not PYLOAD.changePassword(user, oldpw, newpw):
print "Wrong password"
- return HTTPError()
+ return bottle.HTTPError()
diff --git a/pyload/webui/app/pyloadweb.py b/pyload/webui/app/pyloadweb.py
index 8974e0896..27532b86e 100644
--- a/pyload/webui/app/pyloadweb.py
+++ b/pyload/webui/app/pyloadweb.py
@@ -2,14 +2,13 @@
# @author: RaNaN
import datetime
+import operator
import os
import sys
import time
import urllib
-from operator import itemgetter, attrgetter
-
-from bottle import route, static_file, request, response, redirect, error
+import bottle
from pyload.webui import PYLOAD, PYLOAD_DIR, THEME_DIR, THEME, SETUP, env
@@ -57,17 +56,17 @@ def base(messages):
# Views
-@error(403)
+@bottle.error(403)
def error403(code):
return "The parameter you passed has the wrong format"
-@error(404)
+@bottle.error(404)
def error404(code):
return "Sorry, this page does not exist"
-@error(500)
+@bottle.error(500)
def error500(error):
traceback = error.traceback
if traceback:
@@ -76,7 +75,7 @@ def error500(error):
traceback.replace("\n", "<br>") if traceback else "No Traceback"])
-@route('/<theme>/<file:re:(.+/)?[^/]+\.min\.[^/]+>')
+@bottle.route('/<theme>/<file:re:(.+/)?[^/]+\.min\.[^/]+>')
def server_min(theme, file):
filename = os.path.join(THEME_DIR, THEME, theme, file)
if not os.path.isfile(filename):
@@ -87,7 +86,7 @@ def server_min(theme, file):
return server_static(theme, file)
-@route('/<theme>/<file:re:.+\.js>')
+@bottle.route('/<theme>/<file:re:.+\.js>')
def server_js(theme, file):
response.headers['Content-Type'] = "text/javascript; charset=UTF-8"
@@ -102,34 +101,34 @@ def server_js(theme, file):
return server_static(theme, file)
-@route('/<theme>/<file:path>')
+@bottle.route('/<theme>/<file:path>')
def server_static(theme, file):
response.headers['Expires'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT",
time.gmtime(time.time() + 24 * 7 * 60 * 60))
response.headers['Cache-control'] = "public"
- return static_file(file, root=join(THEME_DIR, THEME, theme))
+ return bottle.static_file(file, root=join(THEME_DIR, THEME, theme))
-@route('/favicon.ico')
+@bottle.route('/favicon.ico')
def favicon():
- return static_file("icon.ico", root=join(PYLOAD_DIR, "docs", "resources"))
+ return bottle.static_file("icon.ico", root=join(PYLOAD_DIR, "docs", "resources"))
-@route('/login', method="GET")
+@bottle.route('/login', method="GET")
def login():
if not PYLOAD and SETUP:
- redirect("/setup")
+ bottle.redirect("/setup")
else:
return render_to_response("login.html", proc=[pre_processor])
-@route('/nopermission')
+@bottle.route('/nopermission')
def nopermission():
return base([_("You dont have permission to access this page.")])
-@route('/login', method='POST')
+@bottle.route('/login', method='POST')
def login_post():
user = request.forms.get("username")
password = request.forms.get("password")
@@ -140,18 +139,18 @@ def login_post():
return render_to_response("login.html", {"errors": True}, [pre_processor])
set_session(request, info)
- return redirect("/")
+ return bottle.redirect("/")
-@route('/logout')
+@bottle.route('/logout')
def logout():
s = request.environ.get('beaker.session')
s.delete()
return render_to_response("logout.html", proc=[pre_processor])
-@route('/')
-@route('/home')
+@bottle.route('/')
+@bottle.route('/home')
@login_required("LIST")
def home():
try:
@@ -159,7 +158,7 @@ def home():
except Exception:
s = request.environ.get('beaker.session')
s.delete()
- return redirect("/login")
+ return bottle.redirect("/login")
for link in res:
if link['status'] == 12:
@@ -168,27 +167,27 @@ def home():
return render_to_response("home.html", {"res": res}, [pre_processor])
-@route('/queue')
+@bottle.route('/queue')
@login_required("LIST")
def queue():
queue = PYLOAD.getQueue()
- queue.sort(key=attrgetter("order"))
+ queue.sort(key=operator.attrgetter("order"))
return render_to_response('queue.html', {'content': queue, 'target': 1}, [pre_processor])
-@route('/collector')
+@bottle.route('/collector')
@login_required('LIST')
def collector():
queue = PYLOAD.getCollector()
- queue.sort(key=attrgetter("order"))
+ queue.sort(key=operator.attrgetter("order"))
return render_to_response('queue.html', {'content': queue, 'target': 0}, [pre_processor])
-@route('/downloads')
+@bottle.route('/downloads')
@login_required('DOWNLOAD')
def downloads():
root = PYLOAD.getConfigValue("general", "download_folder")
@@ -224,7 +223,7 @@ def downloads():
return render_to_response('downloads.html', {'files': data}, [pre_processor])
-@route('/downloads/get/<path:path>')
+@bottle.route('/downloads/get/<path:path>')
@login_required("DOWNLOAD")
def get_download(path):
path = urllib.unquote(path).decode("utf8")
@@ -233,10 +232,10 @@ def get_download(path):
root = PYLOAD.getConfigValue("general", "download_folder")
path = path.replace("..", "")
- return static_file(fs_encode(path), fs_encode(root))
+ return bottle.static_file(fs_encode(path), fs_encode(root))
-@route('/settings')
+@bottle.route('/settings')
@login_required('SETTINGS')
def config():
conf = PYLOAD.getConfig()
@@ -294,10 +293,10 @@ def config():
[pre_processor])
-@route('/filechooser')
-@route('/pathchooser')
-@route('/filechooser/<file:path>')
-@route('/pathchooser/<path:path>')
+@bottle.route('/filechooser')
+@bottle.route('/pathchooser')
+@bottle.route('/filechooser/<file:path>')
+@bottle.route('/pathchooser/<path:path>')
@login_required('STATUS')
def os.path(file="", path=""):
type = "file" if file else "folder"
@@ -371,17 +370,17 @@ def os.path(file="", path=""):
files.append(data)
- files = sorted(files, key=itemgetter('type', 'sort'))
+ files = sorted(files, key=operator.itemgetter('type', 'sort'))
return render_to_response('pathchooser.html',
{'cwd': cwd, 'files': files, 'parentdir': parentdir, 'type': type, 'oldfile': oldfile,
'absolute': abs}, [])
-@route('/logs')
-@route('/logs', method='POST')
-@route('/logs/<item>')
-@route('/logs/<item>', method='POST')
+@bottle.route('/logs')
+@bottle.route('/logs', method='POST')
+@bottle.route('/logs/<item>')
+@bottle.route('/logs/<item>', method='POST')
@login_required('LOGS')
def logs(item=-1):
s = request.environ.get('beaker.session')
@@ -467,8 +466,8 @@ def logs(item=-1):
[pre_processor])
-@route('/admin')
-@route('/admin', method='POST')
+@bottle.route('/admin')
+@bottle.route('/admin', method='POST')
@login_required("ADMIN")
def admin():
# convert to dict
@@ -504,12 +503,12 @@ def admin():
return render_to_response("admin.html", {"users": user, "permlist": perms}, [pre_processor])
-@route('/setup')
+@bottle.route('/setup')
def setup():
return base([_("Run pyload.py -s to access the setup.")])
-@route('/info')
+@bottle.route('/info')
def info():
conf = PYLOAD.getConfigDict()
extra = os.uname() if hasattr(os, "uname") else tuple()
diff --git a/pyload/webui/app/utils.py b/pyload/webui/app/utils.py
index 695162f91..3526f2615 100644
--- a/pyload/webui/app/utils.py
+++ b/pyload/webui/app/utils.py
@@ -3,7 +3,7 @@
import os
-from bottle import request, HTTPError, redirect, ServerAdapter
+import bottle
from pyload.Api import has_permission, PERMS, ROLE
from pyload.webui import env, THEME
@@ -97,16 +97,16 @@ def login_required(perm=None):
perms = parse_permissions(s)
if perm not in perms or not perms[perm]:
if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
- return HTTPError(403, "Forbidden")
+ return bottle.HTTPError(403, "Forbidden")
else:
- return redirect("/nopermission")
+ return bottle.redirect("/nopermission")
return func(*args, **kwargs)
else:
if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
- return HTTPError(403, "Forbidden")
+ return bottle.HTTPError(403, "Forbidden")
else:
- return redirect("/login")
+ return bottle.redirect("/login")
return _view