summaryrefslogtreecommitdiffstats
path: root/pyload/webui/app
diff options
context:
space:
mode:
Diffstat (limited to 'pyload/webui/app')
-rw-r--r--pyload/webui/app/__init__.py3
-rw-r--r--pyload/webui/app/api.py99
-rw-r--r--pyload/webui/app/cnl.py166
-rw-r--r--pyload/webui/app/json.py314
-rw-r--r--pyload/webui/app/pyload.py526
-rw-r--r--pyload/webui/app/utils.py124
6 files changed, 0 insertions, 1232 deletions
diff --git a/pyload/webui/app/__init__.py b/pyload/webui/app/__init__.py
deleted file mode 100644
index 39d0fadd5..000000000
--- a/pyload/webui/app/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.webui.app import api, cnl, json, pyload
diff --git a/pyload/webui/app/api.py b/pyload/webui/app/api.py
deleted file mode 100644
index 99a7c2998..000000000
--- a/pyload/webui/app/api.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import itertools
-import traceback
-import urllib
-
-import SafeEval
-import bottle
-
-from pyload.Api import BaseObject
-from pyload.utils import json
-from pyload.webui import PYLOAD
-from pyload.webui.app.utils import toDict, set_session
-
-
-# json encoder that accepts TBase objects
-class TBaseEncoder(json.JSONEncoder):
-
- def default(self, o):
- if isinstance(o, BaseObject):
- return toDict(o)
- return json.JSONEncoder.default(self, o)
-
-
-# accepting positional arguments, as well as kwargs via post and get
-@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")
-
- s = request.environ.get('beaker.session')
- if 'session' in request.POST:
- s = s.get_by_id(request.POST['session'])
-
- if not s or not s.get("authenticated", False):
- return bottle.HTTPError(403, json.dumps("Forbidden"))
-
- if not PYLOAD.isAuthorized(func, {"role": s['role'], "permission": s['perms']}):
- return bottle.HTTPError(401, json.dumps("Unauthorized"))
-
- args = args.split("/")[1:]
- kwargs = {}
-
- for x, y in itertools.chain(request.GET.iteritems(), request.POST.iteritems()):
- if x == "session":
- continue
- kwargs[x] = urllib.unquote(y)
-
- try:
- return callApi(func, *args, **kwargs)
- except Exception, e:
- traceback.print_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 bottle.HTTPError(404, json.dumps("Not Found"))
-
- 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
-@bottle.route('/api/login', method='POST')
-def login():
- response.headers.replace("Content-type", "application/json")
- response.headers.append("Cache-Control", "no-cache, must-revalidate")
-
- user = request.forms.get("username")
- password = request.forms.get("password")
-
- info = PYLOAD.checkAuth(user, password)
-
- if not info:
- return json.dumps(False)
-
- s = set_session(request, info)
-
- # get the session id by dirty way, documentations seems wrong
- try:
- sid = s._headers['cookie_out'].split("=")[1].split(";")[0]
- return json.dumps(sid)
- except Exception:
- return json.dumps(True)
-
-
-@bottle.route('/api/logout')
-def logout():
- response.headers.replace("Content-type", "application/json")
- response.headers.append("Cache-Control", "no-cache, must-revalidate")
-
- s = request.environ.get('beaker.session')
- s.delete()
diff --git a/pyload/webui/app/cnl.py b/pyload/webui/app/cnl.py
deleted file mode 100644
index 07b966f5e..000000000
--- a/pyload/webui/app/cnl.py
+++ /dev/null
@@ -1,166 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-
-import base64
-import binascii
-import os
-import re
-import urllib
-
-import Crypto
-import bottle
-
-from pyload.webui import PYLOAD, DL_ROOT, JS
-
-
-def local_check(function):
-
- def _view(*args, **kwargs):
- if request.environ.get("REMOTE_ADDR", "0") in ("127.0.0.1", "localhost") \
- or request.environ.get("HTTP_HOST", "0") in ("127.0.0.1:9666", "localhost:9666"):
- return function(*args, **kwargs)
- else:
- return bottle.HTTPError(403, "Forbidden")
-
- return _view
-
-
-@bottle.route('/flash')
-@bottle.route('/flash/<id>')
-@bottle.route('/flash', method='POST')
-@local_check
-def flash(id="0"):
- return "JDownloader\r\n"
-
-
-@bottle.route('/flash/add', method='POST')
-@local_check
-def add(request):
- package = request.POST.get('referer', None)
- urls = filter(lambda x: x != "", request.POST['urls'].split("\n"))
-
- if package:
- PYLOAD.addPackage(package, urls, 0)
- else:
- PYLOAD.generateAndAddPackages(urls, 0)
-
- return ""
-
-
-@bottle.route('/flash/addcrypted', method='POST')
-@local_check
-def addcrypted():
- package = request.forms.get('referer', 'ClickNLoad Package')
- dlc = request.forms['crypted'].replace(" ", "+")
-
- dlc_path = os.path.join(DL_ROOT, package.replace("/", "").replace("\\", "").replace(":", "") + ".dlc")
- with open(dlc_path, "wb") as dlc_file:
- dlc_file.write(dlc)
-
- try:
- PYLOAD.addPackage(package, [dlc_path], 0)
- except Exception:
- return bottle.HTTPError()
- else:
- return "success\r\n"
-
-
-@bottle.route('/flash/addcrypted2', method='POST')
-@local_check
-def addcrypted2():
- package = request.forms.get("source", None)
- crypted = request.forms['crypted']
- jk = request.forms['jk']
-
- crypted = base64.standard_b64decode(urllib.unquote(crypted.replace(" ", "+")))
- if JS:
- jk = "%s f()" % jk
- jk = JS.eval(jk)
-
- else:
- try:
- jk = re.findall(r"return ('|\")(.+)('|\")", jk)[0][1]
- except Exception:
- # Test for some known js functions to decode
- if jk.find("dec") > -1 and jk.find("org") > -1:
- org = re.findall(r"var org = ('|\")([^\"']+)", jk)[0][1]
- jk = list(org)
- jk.reverse()
- jk = "".join(jk)
- else:
- print "Could not decrypt key, please install py-spidermonkey or ossp-js"
-
- try:
- Key = binascii.unhexlify(jk)
- except Exception:
- print "Could not decrypt key, please install py-spidermonkey or ossp-js"
- return "failed"
-
- IV = Key
-
- obj = Crypto.Cipher.AES.new(Key, Crypto.Cipher.AES.MODE_CBC, IV)
- result = obj.decrypt(crypted).replace("\x00", "").replace("\r", "").split("\n")
-
- result = filter(lambda x: x != "", result)
-
- try:
- if package:
- PYLOAD.addPackage(package, result, 0)
- else:
- PYLOAD.generateAndAddPackages(result, 0)
- except Exception:
- return "failed can't add"
- else:
- return "success\r\n"
-
-
-@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 bottle.HTTPError()
-
- autostart = int(request.forms.get('autostart', 0))
- package = request.forms.get('package', None)
- urls = filter(lambda x: x != "", request.forms['urls'].split("\n"))
- folder = request.forms.get('dir', None)
-
- if package:
- PYLOAD.addPackage(package, urls, autostart)
- else:
- PYLOAD.generateAndAddPackages(urls, autostart)
-
- return ""
-
-
-@bottle.route('/crossdomain.xml')
-@local_check
-def crossdomain():
- rep = "<?xml version=\"1.0\"?>\n"
- rep += "<!DOCTYPE cross-domain-policy SYSTEM \"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd\">\n"
- rep += "<cross-domain-policy>\n"
- rep += "<allow-access-from domain=\"*\" />\n"
- rep += "</cross-domain-policy>"
- return rep
-
-
-@bottle.route('/flash/checkSupportForUrl')
-@local_check
-def checksupport():
- url = request.GET.get("url")
- res = PYLOAD.checkURLs([url])
- supported = (not res[0][1] is None)
-
- return str(supported).lower()
-
-
-@bottle.route('/jdcheck.js')
-@local_check
-def jdcheck():
- rep = "jdownloader=true;\n"
- rep += "var version='9.581;'"
- return rep
diff --git a/pyload/webui/app/json.py b/pyload/webui/app/json.py
deleted file mode 100644
index a7fe8dcfb..000000000
--- a/pyload/webui/app/json.py
+++ /dev/null
@@ -1,314 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-
-import os
-import shutil
-import traceback
-
-import bottle
-
-from pyload.utils import decode, formatSize
-from pyload.webui import PYLOAD
-from pyload.webui.app.utils import login_required, render_to_response, toDict
-
-
-def format_time(seconds):
- seconds = int(seconds)
-
- hours, seconds = divmod(seconds, 3600)
- minutes, seconds = divmod(seconds, 60)
- return "%.2i:%.2i:%.2i" % (hours, minutes, seconds)
-
-
-def get_sort_key(item):
- return item['order']
-
-
-@bottle.route('/json/status')
-@bottle.route('/json/status', method='POST')
-@login_required('LIST')
-def status():
- try:
- status = toDict(PYLOAD.statusServer())
- status['captcha'] = PYLOAD.isCaptchaWaiting()
- return status
- except Exception:
- return bottle.HTTPError()
-
-
-@bottle.route('/json/links')
-@bottle.route('/json/links', method='POST')
-@login_required('LIST')
-def links():
- try:
- links = [toDict(x) for x in PYLOAD.statusDownloads()]
- ids = []
- for link in links:
- ids.append(link['fid'])
-
- if link['status'] == 12:
- link['info'] = "%s @ %s/s" % (link['format_eta'], formatSize(link['speed']))
- elif link['status'] == 5:
- link['percent'] = 0
- link['size'] = 0
- link['bleft'] = 0
- link['info'] = _("waiting %s") % link['format_wait']
- else:
- link['info'] = ""
-
- data = {'links': links, 'ids': ids}
- return data
- except Exception, e:
- traceback.print_exc()
- return bottle.HTTPError()
-
-
-@bottle.route('/json/packages')
-@login_required('LIST')
-def packages():
- print "/json/packages"
- try:
- data = PYLOAD.getQueue()
-
- for package in data:
- package['links'] = []
- for file in PYLOAD.get_package_files(package['id']):
- package['links'].append(PYLOAD.get_file_info(file))
-
- return data
-
- except Exception:
- return bottle.HTTPError()
-
-
-@bottle.route('/json/package/<id:int>')
-@login_required('LIST')
-def package(id):
- try:
- data = toDict(PYLOAD.getPackageData(id))
- data['links'] = [toDict(x) for x in data['links']]
-
- for pyfile in data['links']:
- if pyfile['status'] == 0:
- pyfile['icon'] = "status_finished.png"
- elif pyfile['status'] in (2, 3):
- pyfile['icon'] = "status_queue.png"
- elif pyfile['status'] in (9, 1):
- pyfile['icon'] = "status_offline.png"
- elif pyfile['status'] == 5:
- pyfile['icon'] = "status_waiting.png"
- elif pyfile['status'] == 8:
- pyfile['icon'] = "status_failed.png"
- elif pyfile['status'] == 4:
- pyfile['icon'] = "arrow_right.png"
- elif pyfile['status'] in (11, 13):
- pyfile['icon'] = "status_proc.png"
- else:
- pyfile['icon'] = "status_downloading.png"
-
- tmp = data['links']
- tmp.sort(key=get_sort_key)
- data['links'] = tmp
- return data
-
- except Exception:
- traceback.print_exc()
- return bottle.HTTPError()
-
-
-@bottle.route('/json/package_order/<ids>')
-@login_required('ADD')
-def package_order(ids):
- try:
- pid, pos = ids.split("|")
- PYLOAD.orderPackage(int(pid), int(pos))
- return {"response": "success"}
- except Exception:
- return bottle.HTTPError()
-
-
-@bottle.route('/json/abort_link/<id:int>')
-@login_required('DELETE')
-def abort_link(id):
- try:
- PYLOAD.stopDownloads([id])
- return {"response": "success"}
- except Exception:
- return bottle.HTTPError()
-
-
-@bottle.route('/json/link_order/<ids>')
-@login_required('ADD')
-def link_order(ids):
- try:
- pid, pos = ids.split("|")
- PYLOAD.orderFile(int(pid), int(pos))
- return {"response": "success"}
- except Exception:
- return bottle.HTTPError()
-
-
-@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()
- queue = int(request.forms['add_dest'])
- links = decode(request.forms['add_links'])
- links = links.split("\n")
- pw = request.forms.get("add_password", "").strip("\n\r")
-
- try:
- f = request.files['add_file']
-
- if not name or name == "New Package":
- name = f.name
-
- fpath = os.path.join(PYLOAD.getConfigValue("general", "download_folder"), "tmp_" + f.filename)
- with open(fpath, 'wb') as destination:
- shutil.copyfileobj(f.file, destination)
- links.insert(0, fpath)
- except Exception:
- pass
-
- name = name.decode("utf8", "ignore")
-
- links = map(lambda x: x.strip(), links)
- links = filter(lambda x: x != "", links)
-
- pack = PYLOAD.addPackage(name, links, queue)
- if pw:
- pw = pw.decode("utf8", "ignore")
- data = {"password": pw}
- PYLOAD.setPackageData(pack, data)
-
-
-@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 bottle.HTTPError()
-
-
-@bottle.route('/json/edit_package', method='POST')
-@login_required('MODIFY')
-def edit_package():
- try:
- id = int(request.forms.get("pack_id"))
- data = {"name": request.forms.get("pack_name").decode("utf8", "ignore"),
- "folder": request.forms.get("pack_folder").decode("utf8", "ignore"),
- "password": request.forms.get("pack_pws").decode("utf8", "ignore")}
-
- PYLOAD.setPackageData(id, data)
- return {"response": "success"}
-
- except Exception:
- return bottle.HTTPError()
-
-
-@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":
- try:
- PYLOAD.setCaptchaResult(request.forms['cap_id'], request.forms['cap_result'])
- except Exception:
- pass
-
- task = PYLOAD.getCaptchaTask()
-
- if task.tid >= 0:
- src = "data:image/%s;base64,%s" % (task.type, task.data)
-
- return {'captcha': True, 'id': task.tid, 'src': src, 'result_type': task.resultType}
- else:
- return {'captcha': False}
-
-
-@bottle.route('/json/load_config/<category>/<section>')
-@login_required("SETTINGS")
-def load_config(category, section):
- conf = None
- if category == "general":
- conf = PYLOAD.getConfigDict()
- elif category == "plugin":
- conf = PYLOAD.getPluginConfigDict()
-
- for key, option in conf[section].iteritems():
- if key in ("desc", "outline"):
- continue
-
- if ";" in option['type']:
- option['list'] = option['type'].split(";")
-
- option['value'] = decode(option['value'])
-
- return render_to_response("settings_item.html", {"sorted_conf": lambda c: sorted(c.items(), key=lambda i: i[1]['idx'] if i[0] not in ("desc", "outline") else 0),
- "skey": section, "section": conf[section]})
-
-
-@bottle.route('/json/save_config/<category>', method='POST')
-@login_required("SETTINGS")
-def save_config(category):
- for key, value in request.POST.iteritems():
- try:
- section, option = key.split("|")
- except Exception:
- continue
-
- if category == "general": category = "core"
-
- PYLOAD.setConfigValue(section, option, decode(value), category)
-
-
-@bottle.route('/json/add_account', method='POST')
-@login_required("ACCOUNTS")
-def add_account():
- login = request.POST['account_login']
- password = request.POST['account_password']
- type = request.POST['account_type']
-
- PYLOAD.updateAccount(type, login, password)
-
-
-@bottle.route('/json/update_accounts', method='POST')
-@login_required("ACCOUNTS")
-def update_accounts():
- deleted = [] #: dont update deleted accs or they will be created again
-
- for name, value in request.POST.iteritems():
- value = value.strip()
- if not value:
- continue
-
- tmp, user = name.split(";")
- plugin, action = tmp.split("|")
-
- if (plugin, user) in deleted:
- continue
-
- if action == "password":
- PYLOAD.updateAccount(plugin, user, value)
- elif action == "time" and "-" in value:
- PYLOAD.updateAccount(plugin, user, options={"time": [value]})
- elif action == "limitdl" and value.isdigit():
- PYLOAD.updateAccount(plugin, user, options={"limitDL": [value]})
- elif action == "delete":
- deleted.append((plugin, user))
- PYLOAD.removeAccount(plugin, user)
-
-
-@bottle.route('/json/change_password', method='POST')
-def change_password():
- user = request.POST['user_login']
- oldpw = request.POST['login_current_password']
- newpw = request.POST['login_new_password']
-
- if not PYLOAD.changePassword(user, oldpw, newpw):
- print "Wrong password"
- return bottle.HTTPError()
diff --git a/pyload/webui/app/pyload.py b/pyload/webui/app/pyload.py
deleted file mode 100644
index 58acdf12c..000000000
--- a/pyload/webui/app/pyload.py
+++ /dev/null
@@ -1,526 +0,0 @@
-# -*- coding: utf-8 -*-
-# @author: RaNaN
-
-import datetime
-import operator
-import os
-import sys
-import time
-import urllib
-
-import bottle
-
-from pyload.webui import PYLOAD, PYLOAD_DIR, THEME_DIR, THEME, SETUP, env
-
-from pyload.webui.app.utils import render_to_response, parse_permissions, parse_userdata, \
- login_required, get_permission, set_permission, permlist, toDict, set_session
-
-from pyload.utils.filters import relpath, unquotepath
-
-from pyload.utils import formatSize, fs_join, fs_encode, fs_decode
-
-# Helper
-
-
-def pre_processor():
- s = request.environ.get('beaker.session')
- user = parse_userdata(s)
- perms = parse_permissions(s)
- status = {}
- captcha = False
- update = False
- plugins = False
- if user['is_authenticated']:
- status = PYLOAD.statusServer()
- info = PYLOAD.getInfoByPlugin("UpdateManager")
- captcha = PYLOAD.isCaptchaWaiting()
-
- # check if update check is available
- if info:
- if info['pyload'] == "True":
- update = info['version']
- if info['plugins'] == "True":
- plugins = True
-
- return {"user": user,
- 'status': status,
- 'captcha': captcha,
- 'perms': perms,
- 'url': request.url,
- 'update': update,
- 'plugins': plugins}
-
-
-def base(messages):
- return render_to_response('base.html', {'messages': messages}, [pre_processor])
-
-
-# Views
-@bottle.error(403)
-def error403(code):
- return "The parameter you passed has the wrong format"
-
-
-@bottle.error(404)
-def error404(code):
- return "Sorry, this page does not exist"
-
-
-@bottle.error(500)
-def error500(error):
- traceback = error.traceback
- if traceback:
- print traceback
- return base(["An Error occured, please enable debug mode to get more details.", error,
- traceback.replace("\n", "<br>") if traceback else "No Traceback"])
-
-
-@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):
- file = file.replace(".min.", ".")
- if file.endswith(".js"):
- return server_js(theme, file)
- else:
- return server_static(theme, file)
-
-
-@bottle.route('/<theme>/<file:re:.+\.js>')
-def server_js(theme, file):
- response.headers['Content-Type'] = "text/javascript; charset=UTF-8"
-
- if "/render/" in file or ".render." in file or True:
- 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"
-
- path = "/".join((theme, file))
- return env.get_template(path).render()
- else:
- return server_static(theme, file)
-
-
-@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 bottle.static_file(file, root=join(THEME_DIR, THEME, theme))
-
-
-@bottle.route('/favicon.ico')
-def favicon():
- return bottle.static_file("icon.ico", root=join(PYLOAD_DIR, "docs", "resources"))
-
-
-@bottle.route('/login', method="GET")
-def login():
- if not PYLOAD and SETUP:
- bottle.redirect("/setup")
- else:
- return render_to_response("login.html", proc=[pre_processor])
-
-
-@bottle.route('/nopermission')
-def nopermission():
- return base([_("You dont have permission to access this page.")])
-
-
-@bottle.route('/login', method='POST')
-def login_post():
- user = request.forms.get("username")
- password = request.forms.get("password")
-
- info = PYLOAD.checkAuth(user, password)
-
- if not info:
- return render_to_response("login.html", {"errors": True}, [pre_processor])
-
- set_session(request, info)
- return bottle.redirect("/")
-
-
-@bottle.route('/logout')
-def logout():
- s = request.environ.get('beaker.session')
- s.delete()
- return render_to_response("logout.html", proc=[pre_processor])
-
-
-@bottle.route('/')
-@bottle.route('/home')
-@login_required("LIST")
-def home():
- try:
- res = [toDict(x) for x in PYLOAD.statusDownloads()]
- except Exception:
- s = request.environ.get('beaker.session')
- s.delete()
- return bottle.redirect("/login")
-
- for link in res:
- if link['status'] == 12:
- link['information'] = "%s kB @ %s kB/s" % (link['size'] - link['bleft'], link['speed'])
-
- return render_to_response("home.html", {"res": res}, [pre_processor])
-
-
-@bottle.route('/queue')
-@login_required("LIST")
-def queue():
- queue = PYLOAD.getQueue()
-
- queue.sort(key=operator.attrgetter("order"))
-
- return render_to_response('queue.html', {'content': queue, 'target': 1}, [pre_processor])
-
-
-@bottle.route('/collector')
-@login_required('LIST')
-def collector():
- queue = PYLOAD.getCollector()
-
- queue.sort(key=operator.attrgetter("order"))
-
- return render_to_response('queue.html', {'content': queue, 'target': 0}, [pre_processor])
-
-
-@bottle.route('/downloads')
-@login_required('DOWNLOAD')
-def downloads():
- root = PYLOAD.getConfigValue("general", "download_folder")
-
- if not os.path.isdir(root):
- return base([_('Download directory not found.')])
- data = {
- 'folder': [],
- 'files': []
- }
-
- items = os.listdir(fs_encode(root))
-
- for item in sorted([fs_decode(x) for x in items]):
- if os.path.isdir(fs_join(root, item)):
- folder = {
- 'name': item,
- 'path': item,
- 'files': []
- }
- files = os.listdir(fs_join(root, item))
- for file in sorted([fs_decode(x) for x in files]):
- try:
- if os.path.isfile(fs_join(root, item, file)):
- folder['files'].append(file)
- except Exception:
- pass
-
- data['folder'].append(folder)
- elif os.path.isfile(os.path.join(root, item)):
- data['files'].append(item)
-
- return render_to_response('downloads.html', {'files': data}, [pre_processor])
-
-
-@bottle.route('/downloads/get/<path:path>')
-@login_required("DOWNLOAD")
-def get_download(path):
- path = urllib.unquote(path).decode("utf8")
- #@TODO some files can not be downloaded
-
- root = PYLOAD.getConfigValue("general", "download_folder")
-
- path = path.replace("..", "")
- return bottle.static_file(fs_encode(path), fs_encode(root))
-
-
-@bottle.route('/settings')
-@login_required('SETTINGS')
-def config():
- conf = PYLOAD.getConfig()
- plugin = PYLOAD.getPluginConfig()
- conf_menu = []
- plugin_menu = []
-
- for entry in sorted(conf.keys()):
- conf_menu.append((entry, conf[entry].description))
-
- last_name = None
- for entry in sorted(plugin.keys()):
- desc = plugin[entry].description
- name, none, type = desc.partition("_")
-
- if type in PYLOAD.core.pluginManager.TYPES:
- if name == last_name or len([a for a, b in plugin.iteritems() if b.description.startswith(name + "_")]) > 1:
- desc = name + " (" + type.title() + ")"
- else:
- desc = name
- last_name = name
- plugin_menu.append((entry, desc))
-
- accs = PYLOAD.getAccounts(False)
-
- for data in accs:
- if data.trafficleft == -1:
- data.trafficleft = _("unlimited")
- elif not data.trafficleft:
- data.trafficleft = _("not available")
- else:
- data.trafficleft = formatSize(data.trafficleft)
-
- if data.validuntil == -1:
- data.validuntil = _("unlimited")
- elif not data.validuntil:
- data.validuntil = _("not available")
- else:
- t = time.localtime(data.validuntil)
- data.validuntil = time.strftime("%d.%m.%Y - %H:%M:%S", t)
-
- try:
- data.options['time'] = data.options['time'][0]
- except Exception:
- data.options['time'] = "0:00-0:00"
-
- if "limitDL" in data.options:
- data.options['limitdl'] = data.options['limitDL'][0]
- else:
- data.options['limitdl'] = "0"
-
- return render_to_response('settings.html',
- {'conf': {'plugin': plugin_menu, 'general': conf_menu, 'accs': accs},
- 'types': PYLOAD.getAccountTypes()},
- [pre_processor])
-
-
-@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"
-
- path = os.path.normpath(unquotepath(path))
-
- if os.path.isfile(path):
- oldfile = path
- path = os.path.dirname(path)
- else:
- oldfile = ''
-
- abs = False
-
- if os.path.isdir(path):
- if os.path.isabs(path):
- cwd = os.path.abspath(path)
- abs = True
- else:
- cwd = os.relpath(path)
- else:
- cwd = os.getcwd()
-
- try:
- cwd = cwd.encode("utf8")
- except Exception:
- pass
-
- cwd = os.path.normpath(os.path.abspath(cwd))
- parentdir = os.path.dirname(cwd)
- if not abs:
- if os.path.abspath(cwd) == "/":
- cwd = os.relpath(cwd)
- else:
- cwd = os.relpath(cwd) + os.path.sep
- parentdir = os.relpath(parentdir) + os.path.sep
-
- if os.path.abspath(cwd) == "/":
- parentdir = ""
-
- try:
- folders = os.listdir(cwd)
- except Exception:
- folders = []
-
- files = []
-
- for f in folders:
- try:
- f = f.decode(sys.getfilesystemencoding())
- data = {'name': f, 'fullpath': os.path.join(cwd, f)}
- data['sort'] = data['fullpath'].lower()
- data['modified'] = datetime.datetime.fromtimestamp(int(os.path.getmtime(os.path.join(cwd, f))))
- data['ext'] = os.path.splitext(f)[1]
- except Exception:
- continue
-
- data['type'] = 'dir' if os.path.isdir(os.path.join(cwd, f)) else 'file'
-
- if os.path.isfile(os.path.join(cwd, f)):
- data['size'] = os.path.getsize(os.path.join(cwd, f))
-
- power = 0
- while (data['size'] / 1024) > 0.3:
- power += 1
- data['size'] /= 1024.
- units = ('', 'K', 'M', 'G', 'T')
- data['unit'] = units[power] + 'Byte'
- else:
- data['size'] = ''
-
- files.append(data)
-
- 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}, [])
-
-
-@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')
-
- perpage = s.get('perpage', 34)
- reversed = s.get('reversed', False)
-
- warning = ""
- conf = PYLOAD.getConfigValue("log", "file_log")
- color_template = PYLOAD.getConfigValue("log", "color_template") if PYLOAD.getConfigValue("log", "color_console") else ""
- if not conf:
- warning = "Warning: File log is disabled, see settings page."
-
- perpage_p = ((20, 20), (34, 34), (40, 40), (100, 100), (0, 'all'))
- fro = None
-
- if request.environ.get('REQUEST_METHOD', "GET") == "POST":
- try:
- fro = datetime.datetime.strptime(request.forms['from'], '%d.%m.%Y %H:%M:%S')
- except Exception:
- pass
- try:
- perpage = int(request.forms['perpage'])
- s['perpage'] = perpage
-
- reversed = bool(request.forms.get('reversed', False))
- s['reversed'] = reversed
- except Exception:
- pass
-
- s.save()
-
- try:
- item = int(item)
- except Exception:
- pass
-
- log = PYLOAD.getLog()
- if not perpage:
- item = 1
-
- if item < 1 or type(item) is not int:
- item = 1 if len(log) - perpage + 1 < 1 else len(log) - perpage + 1
-
- if type(fro) is datetime.datetime: #: we will search for datetime.datetime
- item = -1
-
- data = []
- counter = 0
- perpagecheck = 0
- for l in log:
- counter += 1
-
- if counter >= item:
- try:
- date, time, level, message = l.decode("utf8", "ignore").split(" ", 3)
- dtime = datetime.datetime.strptime(date + ' ' + time, '%Y-%m-%d %H:%M:%S')
- except Exception:
- dtime = None
- date = '?'
- time = ' '
- level = '?'
- message = l
- if item == -1 and dtime is not None and fro <= dtime:
- item = counter #: found our datetime.datetime
- if item >= 0:
- data.append({'line': counter, 'date': date + " " + time, 'level': level, 'message': message})
- perpagecheck += 1
- if fro is None and dtime is not None: #: if fro not set set it to first showed line
- fro = dtime
- if perpagecheck >= perpage > 0:
- break
-
- if fro is None: #: still not set, empty log?
- fro = datetime.datetime.now()
- if reversed:
- data.reverse()
- return render_to_response('logs.html', {'warning': warning, 'log': data, 'from': fro.strftime('%d.%m.%Y %H:%M:%S'),
- 'reversed': reversed, 'perpage': perpage, 'perpage_p': sorted(perpage_p),
- 'iprev': 1 if item - perpage < 1 else item - perpage,
- 'inext': (item + perpage) if item + perpage < len(log) else item,
- 'color_template': color_template.title()},
- [pre_processor])
-
-
-@bottle.route('/admin')
-@bottle.route('/admin', method='POST')
-@login_required("ADMIN")
-def admin():
- # convert to dict
- user = dict((name, toDict(y)) for name, y in PYLOAD.getAllUserData().iteritems())
- perms = permlist()
-
- for data in user.itervalues():
- data['perms'] = {}
- get_permission(data['perms'], data['permission'])
- data['perms']['admin'] = data['role'] is 0
-
- s = request.environ.get('beaker.session')
- if request.environ.get('REQUEST_METHOD', "GET") == "POST":
- for name in user:
- if request.POST.get("%s|admin" % name, False):
- user[name]['role'] = 0
- user[name]['perms']['admin'] = True
- elif name != s['name']:
- user[name]['role'] = 1
- user[name]['perms']['admin'] = False
-
- # set all perms to false
- for perm in perms:
- user[name]['perms'][perm] = False
-
- for perm in request.POST.getall("%s|perms" % name):
- user[name]['perms'][perm] = True
-
- user[name]['permission'] = set_permission(user[name]['perms'])
-
- PYLOAD.setUserPermission(name, user[name]['permission'], user[name]['role'])
-
- return render_to_response("admin.html", {"users": user, "permlist": perms}, [pre_processor])
-
-
-@bottle.route('/setup')
-def setup():
- return base([_("Run pyload.py -s to access the setup.")])
-
-
-@bottle.route('/info')
-def info():
- conf = PYLOAD.getConfigDict()
- extra = os.uname() if hasattr(os, "uname") else tuple()
-
- data = {"python" : sys.version,
- "os" : " ".join((os.name, sys.platform) + extra),
- "version" : PYLOAD.getServerVersion(),
- "folder" : os.path.abspath(PYLOAD_DIR), "config": os.path.abspath(""),
- "download" : os.path.abspath(conf['general']['download_folder']['value']),
- "freespace": formatSize(PYLOAD.freeSpace()),
- "remote" : conf['remote']['port']['value'],
- "webif" : conf['webui']['port']['value'],
- "language" : conf['general']['language']['value']}
-
- return render_to_response("info.html", data, [pre_processor])
diff --git a/pyload/webui/app/utils.py b/pyload/webui/app/utils.py
deleted file mode 100644
index 5663c6f58..000000000
--- a/pyload/webui/app/utils.py
+++ /dev/null
@@ -1,124 +0,0 @@
-# -*- coding: utf-8 -*-
-# @author: RaNaN, vuolter
-
-import os
-
-import bottle
-
-from pyload.Api import has_permission, PERMS, ROLE
-from pyload.webui import env, THEME
-
-
-def render_to_response(file, args={}, proc=[]):
- for p in proc:
- args.update(p())
- path = "tml/" + file
- return env.get_template(path).render(**args)
-
-
-def parse_permissions(session):
- perms = dict((x, False) for x in dir(PERMS) if not x.startswith("_"))
- perms['ADMIN'] = False
- perms['is_admin'] = False
-
- if not session.get("authenticated", False):
- return perms
-
- if session.get("role") == ROLE.ADMIN:
- for k in perms.iterkeys():
- perms[k] = True
-
- elif session.get("perms"):
- p = session.get("perms")
- get_permission(perms, p)
-
- return perms
-
-
-def permlist():
- return [x for x in dir(PERMS) if not x.startswith("_") and x != "ALL"]
-
-
-def get_permission(perms, p):
- """Returns a dict with permission key
-
- :param perms: dictionary
- :param p: bits
- """
- for name in permlist():
- perms[name] = has_permission(p, getattr(PERMS, name))
-
-
-def set_permission(perms):
- """generates permission bits from dictionary
-
- :param perms: dict
- """
- permission = 0
- for name in dir(PERMS):
- if name.startswith("_"):
- continue
-
- if name in perms and perms[name]:
- permission |= getattr(PERMS, name)
-
- return permission
-
-
-def set_session(request, info):
- s = request.environ.get('beaker.session')
- s['authenticated'] = True
- s['user_id'] = info['id']
- s['name'] = info['name']
- s['role'] = info['role']
- s['perms'] = info['permission']
- s['template'] = info['template']
- s.save()
-
- return s
-
-
-def parse_userdata(session):
- return {"name" : session.get("name", "Anonymous"),
- "is_admin" : session.get("role", 1) == 0,
- "is_authenticated": session.get("authenticated", False)}
-
-
-def login_required(perm=None):
-
- def _dec(func):
-
- def _view(*args, **kwargs):
- s = request.environ.get('beaker.session')
- if s.get("name", None) and s.get("authenticated", False):
- if perm:
- perms = parse_permissions(s)
- if perm not in perms or not perms[perm]:
- if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
- return bottle.HTTPError(403, "Forbidden")
- else:
- return bottle.redirect("/nopermission")
-
- return func(*args, **kwargs)
- else:
- if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
- return bottle.HTTPError(403, "Forbidden")
- else:
- return bottle.redirect("/login")
-
- return _view
-
- return _dec
-
-
-def toDict(obj):
- return dict((att, getattr(obj, att)) for att in obj.__slots__)
-
-
-class CherryPyWSGI(ServerAdapter):
-
- def run(self, handler):
- from wsgiserver import CherryPyWSGIServer
-
- server = CherryPyWSGIServer((self.host, self.port), handler)
- server.start()