diff options
Diffstat (limited to 'module/remote')
-rw-r--r-- | module/remote/ClickAndLoadBackend.py | 170 | ||||
-rw-r--r-- | module/remote/JSONClient.py | 56 | ||||
-rw-r--r-- | module/remote/RemoteManager.py | 89 | ||||
-rw-r--r-- | module/remote/WSClient.py | 59 | ||||
-rw-r--r-- | module/remote/WebSocketBackend.py | 49 | ||||
-rw-r--r-- | module/remote/__init__.py | 0 | ||||
-rw-r--r-- | module/remote/apitypes.py | 536 | ||||
-rw-r--r-- | module/remote/apitypes_debug.py | 135 | ||||
-rw-r--r-- | module/remote/create_apitypes.py | 180 | ||||
-rw-r--r-- | module/remote/create_jstypes.py | 36 | ||||
-rw-r--r-- | module/remote/json_converter.py | 64 | ||||
-rw-r--r-- | module/remote/pyload.thrift | 538 | ||||
-rw-r--r-- | module/remote/ttypes.py | 534 | ||||
-rw-r--r-- | module/remote/wsbackend/AbstractHandler.py | 133 | ||||
-rw-r--r-- | module/remote/wsbackend/ApiHandler.py | 81 | ||||
-rw-r--r-- | module/remote/wsbackend/AsyncHandler.py | 167 | ||||
-rw-r--r-- | module/remote/wsbackend/Dispatcher.py | 31 | ||||
-rw-r--r-- | module/remote/wsbackend/Server.py | 733 | ||||
-rw-r--r-- | module/remote/wsbackend/__init__.py | 2 |
19 files changed, 0 insertions, 3593 deletions
diff --git a/module/remote/ClickAndLoadBackend.py b/module/remote/ClickAndLoadBackend.py deleted file mode 100644 index ad8031587..000000000 --- a/module/remote/ClickAndLoadBackend.py +++ /dev/null @@ -1,170 +0,0 @@ -# -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: RaNaN -""" -import re -from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler -from cgi import FieldStorage -from urllib import unquote -from base64 import standard_b64decode -from binascii import unhexlify - -try: - from Crypto.Cipher import AES -except: - pass - -from RemoteManager import BackendBase - -core = None -js = None - -class ClickAndLoadBackend(BackendBase): - def setup(self, host, port): - self.httpd = HTTPServer((host, port), CNLHandler) - global core, js - core = self.m.core - js = core.js - - def serve(self): - while self.enabled: - self.httpd.handle_request() - -class CNLHandler(BaseHTTPRequestHandler): - - def add_package(self, name, urls, queue=0): - print "name", name - print "urls", urls - print "queue", queue - - def get_post(self, name, default=""): - if name in self.post: - return self.post[name] - else: - return default - - def start_response(self, string): - - self.send_response(200) - - self.send_header("Content-Length", len(string)) - self.send_header("Content-Language", "de") - self.send_header("Vary", "Accept-Language, Cookie") - self.send_header("Cache-Control", "no-cache, must-revalidate") - self.send_header("Content-type", "text/html") - self.end_headers() - - def do_GET(self): - path = self.path.strip("/").lower() - #self.wfile.write(path+"\n") - - self.map = [ (r"add$", self.add), - (r"addcrypted$", self.addcrypted), - (r"addcrypted2$", self.addcrypted2), - (r"flashgot", self.flashgot), - (r"crossdomain\.xml", self.crossdomain), - (r"checkSupportForUrl", self.checksupport), - (r"jdcheck.js", self.jdcheck), - (r"", self.flash) ] - - func = None - for r, f in self.map: - if re.match(r"(flash(got)?/?)?"+r, path): - func = f - break - - if func: - try: - resp = func() - if not resp: resp = "success" - resp += "\r\n" - self.start_response(resp) - self.wfile.write(resp) - except Exception,e : - self.send_error(500, str(e)) - else: - self.send_error(404, "Not Found") - - def do_POST(self): - form = FieldStorage( - fp=self.rfile, - headers=self.headers, - environ={'REQUEST_METHOD':'POST', - 'CONTENT_TYPE':self.headers['Content-Type'], - }) - - self.post = {} - for name in form.keys(): - self.post[name] = form[name].value - - return self.do_GET() - - def flash(self): - return "JDownloader" - - def add(self): - package = self.get_post('referer', 'ClickAndLoad Package') - urls = filter(lambda x: x != "", self.get_post('urls').split("\n")) - - self.add_package(package, urls, 0) - - def addcrypted(self): - package = self.get_post('referer', 'ClickAndLoad Package') - dlc = self.get_post('crypted').replace(" ", "+") - - core.upload_container(package, dlc) - - def addcrypted2(self): - package = self.get_post("source", "ClickAndLoad Package") - crypted = self.get_post("crypted") - jk = self.get_post("jk") - - crypted = standard_b64decode(unquote(crypted.replace(" ", "+"))) - jk = "%s f()" % jk - jk = js.eval(jk) - Key = unhexlify(jk) - IV = Key - - obj = AES.new(Key, AES.MODE_CBC, IV) - result = obj.decrypt(crypted).replace("\x00", "").replace("\r","").split("\n") - - result = filter(lambda x: x != "", result) - - self.add_package(package, result, 0) - - - def flashgot(self): - autostart = int(self.get_post('autostart', 0)) - package = self.get_post('package', "FlashGot") - urls = filter(lambda x: x != "", self.get_post('urls').split("\n")) - - self.add_package(package, urls, autostart) - - def crossdomain(self): - 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 - - def checksupport(self): - pass - - def jdcheck(self): - rep = "jdownloader=true;\n" - rep += "var version='10629';\n" - return rep diff --git a/module/remote/JSONClient.py b/module/remote/JSONClient.py deleted file mode 100644 index a2c07a132..000000000 --- a/module/remote/JSONClient.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from urllib import urlopen, urlencode -from httplib import UNAUTHORIZED, FORBIDDEN - -from json_converter import loads, dumps -from apitypes import Unauthorized, Forbidden - -class JSONClient: - URL = "http://localhost:8001/api" - - def __init__(self, url=None): - self.url = url or self.URL - self.session = None - - def request(self, path, data): - ret = urlopen(self.url + path, urlencode(data)) - if ret.code == 400: - raise loads(ret.read()) - if ret.code == 404: - raise AttributeError("Unknown Method") - if ret.code == 500: - raise Exception("Remote Exception") - if ret.code == UNAUTHORIZED: - raise Unauthorized() - if ret.code == FORBIDDEN: - raise Forbidden() - return ret.read() - - def login(self, username, password): - self.session = loads(self.request("/login", {'username': username, 'password': password})) - return self.session - - def logout(self): - self.call("logout") - self.session = None - - def call(self, func, *args, **kwargs): - # Add the current session - kwargs["session"] = self.session - path = "/" + func + "/" + "/".join(dumps(x) for x in args) - data = dict((k, dumps(v)) for k, v in kwargs.iteritems()) - rep = self.request(path, data) - return loads(rep) - - def __getattr__(self, item): - def call(*args, **kwargs): - return self.call(item, *args, **kwargs) - - return call - -if __name__ == "__main__": - api = JSONClient() - api.login("User", "test") - print api.getServerVersion()
\ No newline at end of file diff --git a/module/remote/RemoteManager.py b/module/remote/RemoteManager.py deleted file mode 100644 index dd567653b..000000000 --- a/module/remote/RemoteManager.py +++ /dev/null @@ -1,89 +0,0 @@ -# -*- coding: utf-8 -*- -""" - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. - - @author: mkaay -""" - -from threading import Thread -from traceback import print_exc - -class BackendBase(Thread): - def __init__(self, manager): - Thread.__init__(self) - self.m = manager - self.core = manager.core - self.enabled = True - self.running = False - - def run(self): - self.running = True - try: - self.serve() - except Exception, e: - self.core.log.error(_("Remote backend error: %s") % e) - if self.core.debug: - print_exc() - finally: - self.running = False - - def setup(self, host, port): - pass - - def checkDeps(self): - return True - - def serve(self): - pass - - def shutdown(self): - pass - - def stop(self): - self.enabled = False# set flag and call shutdowm message, so thread can react - self.shutdown() - - -class RemoteManager(): - available = [] - - def __init__(self, core): - self.core = core - self.backends = [] - - if self.core.remote: - self.available.append("WebSocketBackend") - - - def startBackends(self): - host = self.core.config["remote"]["listenaddr"] - port = self.core.config["remote"]["port"] - - for b in self.available: - klass = getattr(__import__("module.remote.%s" % b, globals(), locals(), [b], -1), b) - backend = klass(self) - if not backend.checkDeps(): - continue - try: - backend.setup(host, port) - self.core.log.info(_("Starting %(name)s: %(addr)s:%(port)s") % {"name": b, "addr": host, "port": port}) - except Exception, e: - self.core.log.error(_("Failed loading backend %(name)s | %(error)s") % {"name": b, "error": str(e)}) - if self.core.debug: - print_exc() - else: - backend.start() - self.backends.append(backend) - - port += 1 diff --git a/module/remote/WSClient.py b/module/remote/WSClient.py deleted file mode 100644 index 793a6ef28..000000000 --- a/module/remote/WSClient.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from websocket import create_connection -from httplib import UNAUTHORIZED, FORBIDDEN - -from json_converter import loads, dumps -from apitypes import Unauthorized, Forbidden - -class WSClient: - URL = "ws://localhost:7227/api" - - def __init__(self, url=None): - self.url = url or self.URL - self.ws = None - - def connect(self): - self.ws = create_connection(self.URL) - - def close(self): - self.ws.close() - - def login(self, username, password): - if not self.ws: self.connect() - return self.call("login", username, password) - - def call(self, func, *args, **kwargs): - if not self.ws: - raise Exception("Not Connected") - - if kwargs: - self.ws.send(dumps([func, args, kwargs])) - else: # omit kwargs - self.ws.send(dumps([func, args])) - - code, result = loads(self.ws.recv()) - if code == 400: - raise result - if code == 404: - raise AttributeError("Unknown Method") - elif code == 500: - raise Exception("Remote Exception: %s" % result) - elif code == UNAUTHORIZED: - raise Unauthorized() - elif code == FORBIDDEN: - raise Forbidden() - - return result - - def __getattr__(self, item): - def call(*args, **kwargs): - return self.call(item, *args, **kwargs) - - return call - -if __name__ == "__main__": - api = WSClient() - api.login("User", "test") - print api.getServerVersion()
\ No newline at end of file diff --git a/module/remote/WebSocketBackend.py b/module/remote/WebSocketBackend.py deleted file mode 100644 index 2d22664c6..000000000 --- a/module/remote/WebSocketBackend.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -############################################################################### -# Copyright(c) 2008-2012 pyLoad Team -# http://www.pyload.org -# -# This file is part of pyLoad. -# pyLoad is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Subjected to the terms and conditions in LICENSE -# -# @author: RaNaN -############################################################################### - -import logging - -from module.remote.RemoteManager import BackendBase - -from mod_pywebsocket import util -def get_class_logger(o=None): - return logging.getLogger('log') - -# Monkey patch for our logger -util.get_class_logger = get_class_logger - -class WebSocketBackend(BackendBase): - def setup(self, host, port): - - from wsbackend.Server import WebSocketServer, DefaultOptions - from wsbackend.Dispatcher import Dispatcher - from wsbackend.ApiHandler import ApiHandler - from wsbackend.AsyncHandler import AsyncHandler - - options = DefaultOptions() - options.server_host = host - options.port = port - options.dispatcher = Dispatcher() - options.dispatcher.addHandler(ApiHandler.PATH, ApiHandler(self.core.api)) - options.dispatcher.addHandler(AsyncHandler.PATH, AsyncHandler(self.core.api)) - - self.server = WebSocketServer(options) - - - def serve(self): - self.server.serve_forever() diff --git a/module/remote/__init__.py b/module/remote/__init__.py deleted file mode 100644 index e69de29bb..000000000 --- a/module/remote/__init__.py +++ /dev/null diff --git a/module/remote/apitypes.py b/module/remote/apitypes.py deleted file mode 100644 index 196491083..000000000 --- a/module/remote/apitypes.py +++ /dev/null @@ -1,536 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# Autogenerated by pyload -# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING - -class BaseObject(object): - __slots__ = [] - - def __str__(self): - return "<%s %s>" % (self.__class__.__name__, ", ".join("%s=%s" % (k,getattr(self,k)) for k in self.__slots__)) - -class ExceptionObject(Exception): - __slots__ = [] - -class DownloadState: - All = 0 - Finished = 1 - Unfinished = 2 - Failed = 3 - Unmanaged = 4 - -class DownloadStatus: - NA = 0 - Offline = 1 - Online = 2 - Queued = 3 - Paused = 4 - Finished = 5 - Skipped = 6 - Failed = 7 - Starting = 8 - Waiting = 9 - Downloading = 10 - TempOffline = 11 - Aborted = 12 - Decrypting = 13 - Processing = 14 - Custom = 15 - Unknown = 16 - -class FileStatus: - Ok = 0 - Missing = 1 - Remote = 2 - -class InputType: - NA = 0 - Text = 1 - Int = 2 - File = 3 - Folder = 4 - Textbox = 5 - Password = 6 - Bool = 7 - Click = 8 - Select = 9 - Multiple = 10 - List = 11 - Table = 12 - -class Interaction: - All = 0 - Notification = 1 - Captcha = 2 - Query = 4 - -class MediaType: - All = 0 - Other = 1 - Audio = 2 - Image = 4 - Video = 8 - Document = 16 - Archive = 32 - -class PackageStatus: - Ok = 0 - Paused = 1 - Folder = 2 - Remote = 3 - -class Permission: - All = 0 - Add = 1 - Delete = 2 - Modify = 4 - Download = 8 - Accounts = 16 - Interaction = 32 - Plugins = 64 - -class Role: - Admin = 0 - User = 1 - -class AccountInfo(BaseObject): - __slots__ = ['plugin', 'loginname', 'owner', 'valid', 'validuntil', 'trafficleft', 'maxtraffic', 'premium', 'activated', 'shared', 'options'] - - def __init__(self, plugin=None, loginname=None, owner=None, valid=None, validuntil=None, trafficleft=None, maxtraffic=None, premium=None, activated=None, shared=None, options=None): - self.plugin = plugin - self.loginname = loginname - self.owner = owner - self.valid = valid - self.validuntil = validuntil - self.trafficleft = trafficleft - self.maxtraffic = maxtraffic - self.premium = premium - self.activated = activated - self.shared = shared - self.options = options - -class AddonInfo(BaseObject): - __slots__ = ['func_name', 'description', 'value'] - - def __init__(self, func_name=None, description=None, value=None): - self.func_name = func_name - self.description = description - self.value = value - -class AddonService(BaseObject): - __slots__ = ['func_name', 'description', 'arguments', 'media'] - - def __init__(self, func_name=None, description=None, arguments=None, media=None): - self.func_name = func_name - self.description = description - self.arguments = arguments - self.media = media - -class ConfigHolder(BaseObject): - __slots__ = ['name', 'label', 'description', 'long_description', 'items', 'info'] - - def __init__(self, name=None, label=None, description=None, long_description=None, items=None, info=None): - self.name = name - self.label = label - self.description = description - self.long_description = long_description - self.items = items - self.info = info - -class ConfigInfo(BaseObject): - __slots__ = ['name', 'label', 'description', 'category', 'user_context', 'activated'] - - def __init__(self, name=None, label=None, description=None, category=None, user_context=None, activated=None): - self.name = name - self.label = label - self.description = description - self.category = category - self.user_context = user_context - self.activated = activated - -class ConfigItem(BaseObject): - __slots__ = ['name', 'label', 'description', 'input', 'default_value', 'value'] - - def __init__(self, name=None, label=None, description=None, input=None, default_value=None, value=None): - self.name = name - self.label = label - self.description = description - self.input = input - self.default_value = default_value - self.value = value - -class DownloadInfo(BaseObject): - __slots__ = ['url', 'plugin', 'hash', 'status', 'statusmsg', 'error'] - - def __init__(self, url=None, plugin=None, hash=None, status=None, statusmsg=None, error=None): - self.url = url - self.plugin = plugin - self.hash = hash - self.status = status - self.statusmsg = statusmsg - self.error = error - -class DownloadProgress(BaseObject): - __slots__ = ['fid', 'pid', 'speed', 'status'] - - def __init__(self, fid=None, pid=None, speed=None, status=None): - self.fid = fid - self.pid = pid - self.speed = speed - self.status = status - -class EventInfo(BaseObject): - __slots__ = ['eventname', 'event_args'] - - def __init__(self, eventname=None, event_args=None): - self.eventname = eventname - self.event_args = event_args - -class FileDoesNotExists(ExceptionObject): - __slots__ = ['fid'] - - def __init__(self, fid=None): - self.fid = fid - -class FileInfo(BaseObject): - __slots__ = ['fid', 'name', 'package', 'owner', 'size', 'status', 'media', 'added', 'fileorder', 'download'] - - def __init__(self, fid=None, name=None, package=None, owner=None, size=None, status=None, media=None, added=None, fileorder=None, download=None): - self.fid = fid - self.name = name - self.package = package - self.owner = owner - self.size = size - self.status = status - self.media = media - self.added = added - self.fileorder = fileorder - self.download = download - -class Forbidden(ExceptionObject): - pass - -class Input(BaseObject): - __slots__ = ['type', 'data'] - - def __init__(self, type=None, data=None): - self.type = type - self.data = data - -class InteractionTask(BaseObject): - __slots__ = ['iid', 'type', 'input', 'default_value', 'title', 'description', 'plugin'] - - def __init__(self, iid=None, type=None, input=None, default_value=None, title=None, description=None, plugin=None): - self.iid = iid - self.type = type - self.input = input - self.default_value = default_value - self.title = title - self.description = description - self.plugin = plugin - -class InvalidConfigSection(ExceptionObject): - __slots__ = ['section'] - - def __init__(self, section=None): - self.section = section - -class LinkStatus(BaseObject): - __slots__ = ['url', 'name', 'plugin', 'size', 'status', 'packagename'] - - def __init__(self, url=None, name=None, plugin=None, size=None, status=None, packagename=None): - self.url = url - self.name = name - self.plugin = plugin - self.size = size - self.status = status - self.packagename = packagename - -class OnlineCheck(BaseObject): - __slots__ = ['rid', 'data'] - - def __init__(self, rid=None, data=None): - self.rid = rid - self.data = data - -class PackageDoesNotExists(ExceptionObject): - __slots__ = ['pid'] - - def __init__(self, pid=None): - self.pid = pid - -class PackageInfo(BaseObject): - __slots__ = ['pid', 'name', 'folder', 'root', 'owner', 'site', 'comment', 'password', 'added', 'tags', 'status', 'shared', 'packageorder', 'stats', 'fids', 'pids'] - - def __init__(self, pid=None, name=None, folder=None, root=None, owner=None, site=None, comment=None, password=None, added=None, tags=None, status=None, shared=None, packageorder=None, stats=None, fids=None, pids=None): - self.pid = pid - self.name = name - self.folder = folder - self.root = root - self.owner = owner - self.site = site - self.comment = comment - self.password = password - self.added = added - self.tags = tags - self.status = status - self.shared = shared - self.packageorder = packageorder - self.stats = stats - self.fids = fids - self.pids = pids - -class PackageStats(BaseObject): - __slots__ = ['linkstotal', 'linksdone', 'sizetotal', 'sizedone'] - - def __init__(self, linkstotal=None, linksdone=None, sizetotal=None, sizedone=None): - self.linkstotal = linkstotal - self.linksdone = linksdone - self.sizetotal = sizetotal - self.sizedone = sizedone - -class ProgressInfo(BaseObject): - __slots__ = ['plugin', 'name', 'statusmsg', 'eta', 'done', 'total', 'download'] - - def __init__(self, plugin=None, name=None, statusmsg=None, eta=None, done=None, total=None, download=None): - self.plugin = plugin - self.name = name - self.statusmsg = statusmsg - self.eta = eta - self.done = done - self.total = total - self.download = download - -class ServerStatus(BaseObject): - __slots__ = ['speed', 'linkstotal', 'linksqueue', 'sizetotal', 'sizequeue', 'notifications', 'paused', 'download', 'reconnect'] - - def __init__(self, speed=None, linkstotal=None, linksqueue=None, sizetotal=None, sizequeue=None, notifications=None, paused=None, download=None, reconnect=None): - self.speed = speed - self.linkstotal = linkstotal - self.linksqueue = linksqueue - self.sizetotal = sizetotal - self.sizequeue = sizequeue - self.notifications = notifications - self.paused = paused - self.download = download - self.reconnect = reconnect - -class ServiceDoesNotExists(ExceptionObject): - __slots__ = ['plugin', 'func'] - - def __init__(self, plugin=None, func=None): - self.plugin = plugin - self.func = func - -class ServiceException(ExceptionObject): - __slots__ = ['msg'] - - def __init__(self, msg=None): - self.msg = msg - -class TreeCollection(BaseObject): - __slots__ = ['root', 'files', 'packages'] - - def __init__(self, root=None, files=None, packages=None): - self.root = root - self.files = files - self.packages = packages - -class Unauthorized(ExceptionObject): - pass - -class UserData(BaseObject): - __slots__ = ['uid', 'name', 'email', 'role', 'permission', 'folder', 'traffic', 'dllimit', 'dlquota', 'hddquota', 'user', 'templateName'] - - def __init__(self, uid=None, name=None, email=None, role=None, permission=None, folder=None, traffic=None, dllimit=None, dlquota=None, hddquota=None, user=None, templateName=None): - self.uid = uid - self.name = name - self.email = email - self.role = role - self.permission = permission - self.folder = folder - self.traffic = traffic - self.dllimit = dllimit - self.dlquota = dlquota - self.hddquota = hddquota - self.user = user - self.templateName = templateName - -class UserDoesNotExists(ExceptionObject): - __slots__ = ['user'] - - def __init__(self, user=None): - self.user = user - -class Iface(object): - def addFromCollector(self, name, paused): - pass - def addLinks(self, pid, links): - pass - def addLocalFile(self, pid, name, path): - pass - def addPackage(self, name, links, password): - pass - def addPackageChild(self, name, links, password, root, paused): - pass - def addPackageP(self, name, links, password, paused): - pass - def addToCollector(self, links): - pass - def addUser(self, username, password): - pass - def callAddon(self, plugin, func, arguments): - pass - def callAddonHandler(self, plugin, func, pid_or_fid): - pass - def checkOnlineStatus(self, urls): - pass - def checkOnlineStatusContainer(self, urls, filename, data): - pass - def checkURLs(self, urls): - pass - def createPackage(self, name, folder, root, password, site, comment, paused): - pass - def deleteCollLink(self, url): - pass - def deleteCollPack(self, name): - pass - def deleteConfig(self, plugin): - pass - def deleteFiles(self, fids): - pass - def deletePackages(self, pids): - pass - def findFiles(self, pattern): - pass - def findPackages(self, tags): - pass - def freeSpace(self): - pass - def generateAndAddPackages(self, links, paused): - pass - def generateDownloadLink(self, fid, timeout): - pass - def generatePackages(self, links): - pass - def getAccountTypes(self): - pass - def getAccounts(self, refresh): - pass - def getAddonHandler(self): - pass - def getAllFiles(self): - pass - def getAllUserData(self): - pass - def getAvailablePlugins(self): - pass - def getCollector(self): - pass - def getConfig(self): - pass - def getConfigValue(self, section, option): - pass - def getCoreConfig(self): - pass - def getFileInfo(self, fid): - pass - def getFileTree(self, pid, full): - pass - def getFilteredFileTree(self, pid, full, state): - pass - def getFilteredFiles(self, state): - pass - def getInteractionTasks(self, mode): - pass - def getLog(self, offset): - pass - def getPackageContent(self, pid): - pass - def getPackageInfo(self, pid): - pass - def getPluginConfig(self): - pass - def getProgressInfo(self): - pass - def getServerStatus(self): - pass - def getServerVersion(self): - pass - def getUserData(self): - pass - def getWSAddress(self): - pass - def hasAddonHandler(self, plugin, func): - pass - def isInteractionWaiting(self, mode): - pass - def loadConfig(self, name): - pass - def login(self, username, password): - pass - def moveFiles(self, fids, pid): - pass - def movePackage(self, pid, root): - pass - def orderFiles(self, fids, pid, position): - pass - def orderPackage(self, pids, position): - pass - def parseURLs(self, html, url): - pass - def pauseServer(self): - pass - def pollResults(self, rid): - pass - def quit(self): - pass - def recheckPackage(self, pid): - pass - def removeAccount(self, account): - pass - def removeUser(self, uid): - pass - def renameCollPack(self, name, new_name): - pass - def restart(self): - pass - def restartFailed(self): - pass - def restartFile(self, fid): - pass - def restartPackage(self, pid): - pass - def saveConfig(self, config): - pass - def searchSuggestions(self, pattern): - pass - def setConfigValue(self, section, option, value): - pass - def setInteractionResult(self, iid, result): - pass - def setPackageFolder(self, pid, path): - pass - def setPassword(self, username, old_password, new_password): - pass - def stopAllDownloads(self): - pass - def stopDownloads(self, fids): - pass - def togglePause(self): - pass - def toggleReconnect(self): - pass - def unpauseServer(self): - pass - def updateAccount(self, plugin, login, password): - pass - def updateAccountInfo(self, account): - pass - def updatePackage(self, pack): - pass - def updateUserData(self, data): - pass - def uploadContainer(self, filename, data): - pass - diff --git a/module/remote/apitypes_debug.py b/module/remote/apitypes_debug.py deleted file mode 100644 index 96673cc99..000000000 --- a/module/remote/apitypes_debug.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# Autogenerated by pyload -# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING - -from ttypes import * - -enums = [ - "DownloadState", - "DownloadStatus", - "FileStatus", - "InputType", - "Interaction", - "MediaType", - "PackageStatus", - "Permission", - "Role", -] - -classes = { - 'AccountInfo' : [basestring, basestring, int, bool, int, int, int, bool, bool, bool, (dict, basestring, basestring)], - 'AddonInfo' : [basestring, basestring, basestring], - 'AddonService' : [basestring, basestring, (list, basestring), (None, int)], - 'ConfigHolder' : [basestring, basestring, basestring, basestring, (list, ConfigItem), (None, (list, AddonInfo))], - 'ConfigInfo' : [basestring, basestring, basestring, basestring, bool, (None, bool)], - 'ConfigItem' : [basestring, basestring, basestring, Input, basestring, basestring], - 'DownloadInfo' : [basestring, basestring, basestring, int, basestring, basestring], - 'DownloadProgress' : [int, int, int, int], - 'EventInfo' : [basestring, (list, basestring)], - 'FileDoesNotExists' : [int], - 'FileInfo' : [int, basestring, int, int, int, int, int, int, int, (None, DownloadInfo)], - 'Input' : [int, (None, basestring)], - 'InteractionTask' : [int, int, Input, (None, basestring), basestring, basestring, basestring], - 'InvalidConfigSection' : [basestring], - 'LinkStatus' : [basestring, basestring, basestring, int, int, basestring], - 'OnlineCheck' : [int, (None, (dict, basestring, LinkStatus))], - 'PackageDoesNotExists' : [int], - 'PackageInfo' : [int, basestring, basestring, int, int, basestring, basestring, basestring, int, (list, basestring), int, bool, int, PackageStats, (list, int), (list, int)], - 'PackageStats' : [int, int, int, int], - 'ProgressInfo' : [basestring, basestring, basestring, int, int, int, (None, DownloadProgress)], - 'ServerStatus' : [int, int, int, int, int, bool, bool, bool, bool], - 'ServiceDoesNotExists' : [basestring, basestring], - 'ServiceException' : [basestring], - 'TreeCollection' : [PackageInfo, (dict, int, FileInfo), (dict, int, PackageInfo)], - 'UserData' : [int, basestring, basestring, int, int, basestring, int, int, basestring, int, int, basestring], - 'UserDoesNotExists' : [basestring], -} - -methods = { - 'addFromCollector': int, - 'addLinks': None, - 'addLocalFile': None, - 'addPackage': int, - 'addPackageChild': int, - 'addPackageP': int, - 'addToCollector': None, - 'addUser': UserData, - 'callAddon': None, - 'callAddonHandler': None, - 'checkOnlineStatus': OnlineCheck, - 'checkOnlineStatusContainer': OnlineCheck, - 'checkURLs': (dict, basestring, list), - 'createPackage': int, - 'deleteCollLink': None, - 'deleteCollPack': None, - 'deleteConfig': None, - 'deleteFiles': None, - 'deletePackages': None, - 'findFiles': TreeCollection, - 'findPackages': TreeCollection, - 'freeSpace': int, - 'generateAndAddPackages': (list, int), - 'generateDownloadLink': basestring, - 'generatePackages': (dict, basestring, list), - 'getAccountTypes': (list, basestring), - 'getAccounts': (list, AccountInfo), - 'getAddonHandler': (dict, basestring, list), - 'getAllFiles': TreeCollection, - 'getAllUserData': (dict, int, UserData), - 'getAvailablePlugins': (list, ConfigInfo), - 'getCollector': (list, LinkStatus), - 'getConfig': (dict, basestring, ConfigHolder), - 'getConfigValue': basestring, - 'getCoreConfig': (list, ConfigInfo), - 'getFileInfo': FileInfo, - 'getFileTree': TreeCollection, - 'getFilteredFileTree': TreeCollection, - 'getFilteredFiles': TreeCollection, - 'getInteractionTasks': (list, InteractionTask), - 'getLog': (list, basestring), - 'getPackageContent': TreeCollection, - 'getPackageInfo': PackageInfo, - 'getPluginConfig': (list, ConfigInfo), - 'getProgressInfo': (list, ProgressInfo), - 'getServerStatus': ServerStatus, - 'getServerVersion': basestring, - 'getUserData': UserData, - 'getWSAddress': basestring, - 'hasAddonHandler': bool, - 'isInteractionWaiting': bool, - 'loadConfig': ConfigHolder, - 'login': bool, - 'moveFiles': bool, - 'movePackage': bool, - 'orderFiles': None, - 'orderPackage': None, - 'parseURLs': (dict, basestring, list), - 'pauseServer': None, - 'pollResults': OnlineCheck, - 'quit': None, - 'recheckPackage': None, - 'removeAccount': None, - 'removeUser': None, - 'renameCollPack': None, - 'restart': None, - 'restartFailed': None, - 'restartFile': None, - 'restartPackage': None, - 'saveConfig': None, - 'searchSuggestions': (list, basestring), - 'setConfigValue': None, - 'setInteractionResult': None, - 'setPackageFolder': bool, - 'setPassword': bool, - 'stopAllDownloads': None, - 'stopDownloads': None, - 'togglePause': bool, - 'toggleReconnect': bool, - 'unpauseServer': None, - 'updateAccount': None, - 'updateAccountInfo': None, - 'updatePackage': None, - 'updateUserData': None, - 'uploadContainer': int, -} diff --git a/module/remote/create_apitypes.py b/module/remote/create_apitypes.py deleted file mode 100644 index d596f07ac..000000000 --- a/module/remote/create_apitypes.py +++ /dev/null @@ -1,180 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import re -import inspect -from os.path import abspath, dirname, join - -path = dirname(abspath(__file__)) -root = abspath(join(path, "..", "..")) - -from thrift.Thrift import TType -from thriftgen.pyload import ttypes -from thriftgen.pyload import Pyload - -# TODO: import and add version -# from pyload import CURRENT_VERSION - -type_map = { - TType.BOOL: 'bool', - TType.DOUBLE: 'float', - TType.I16: 'int', - TType.I32: 'int', - TType.I64: 'int', - TType.STRING: 'basestring', - TType.MAP: 'dict', - TType.LIST: 'list', - TType.SET: 'set', - TType.VOID: 'None', - TType.STRUCT: 'BaseObject', - TType.UTF8: 'unicode', -} - -def get_spec(spec, optional=False): - """ analyze the generated spec file and writes information into file """ - if spec[1] == TType.STRUCT: - return spec[3][0].__name__ - elif spec[1] == TType.LIST: - if spec[3][0] == TType.STRUCT: - ttype = spec[3][1][0].__name__ - else: - ttype = type_map[spec[3][0]] - return "(list, %s)" % ttype - elif spec[1] == TType.MAP: - if spec[3][2] == TType.STRUCT: - ttype = spec[3][3][0].__name__ - else: - ttype = type_map[spec[3][2]] - - return "(dict, %s, %s)" % (type_map[spec[3][0]], ttype) - else: - return type_map[spec[1]] - -optional_re = "%d: +optional +[a-z0-9<>_-]+ +%s" - -def main(): - - enums = [] - classes = [] - tf = open(join(path, "pyload.thrift"), "rb").read() - - print "generating apitypes.py" - - for name in dir(ttypes): - klass = getattr(ttypes, name) - - if name in ("TBase", "TExceptionBase") or name.startswith("_") or not (issubclass(klass, ttypes.TBase) or issubclass(klass, ttypes.TExceptionBase)): - continue - - if hasattr(klass, "thrift_spec"): - classes.append(klass) - else: - enums.append(klass) - - - f = open(join(path, "apitypes.py"), "wb") - f.write( - """#!/usr/bin/env python -# -*- coding: utf-8 -*- -# Autogenerated by pyload -# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING - -class BaseObject(object): -\t__slots__ = [] - -\tdef __str__(self): -\t\treturn "<%s %s>" % (self.__class__.__name__, ", ".join("%s=%s" % (k,getattr(self,k)) for k in self.__slots__)) - -class ExceptionObject(Exception): -\t__slots__ = [] - -""") - - dev = open(join(path, "apitypes_debug.py"), "wb") - dev.write("""#!/usr/bin/env python -# -*- coding: utf-8 -*- -# Autogenerated by pyload -# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n -from ttypes import *\n -""") - - dev.write("enums = [\n") - - ## generate enums - for enum in enums: - name = enum.__name__ - f.write("class %s:\n" % name) - - for attr in sorted(dir(enum), key=lambda x: getattr(enum, x)): - if attr.startswith("_") or attr in ("read", "write"): continue - f.write("\t%s = %s\n" % (attr, getattr(enum, attr))) - - dev.write('\t"%s",\n' % name) - f.write("\n") - - dev.write("]\n\n") - - dev.write("classes = {\n") - - for klass in classes: - name = klass.__name__ - base = "ExceptionObject" if issubclass(klass, ttypes.TExceptionBase) else "BaseObject" - f.write("class %s(%s):\n" % (name, base)) - - # No attributes, don't write further info - if not klass.__slots__: - f.write("\tpass\n\n") - continue - - f.write("\t__slots__ = %s\n\n" % klass.__slots__) - dev.write("\t'%s' : [" % name) - - #create init - args = ["self"] + ["%s=None" % x for x in klass.__slots__] - specs = [] - - f.write("\tdef __init__(%s):\n" % ", ".join(args)) - for i, attr in enumerate(klass.__slots__): - f.write("\t\tself.%s = %s\n" % (attr, attr)) - - spec = klass.thrift_spec[i+1] - # assert correct order, so the list of types is enough for check - assert spec[2] == attr - # dirty way to check optional attribute, since it is not in the generated code - # can produce false positives, but these are not critical - optional = re.search(optional_re % (i+1, attr), tf, re.I) - if optional: - specs.append("(None, %s)" % get_spec(spec)) - else: - specs.append(get_spec(spec)) - - f.write("\n") - dev.write(", ".join(specs) + "],\n") - - dev.write("}\n\n") - - f.write("class Iface(object):\n") - dev.write("methods = {\n") - - for name in dir(Pyload.Iface): - if name.startswith("_"): continue - - func = inspect.getargspec(getattr(Pyload.Iface, name)) - - f.write("\tdef %s(%s):\n\t\tpass\n" % (name, ", ".join(func.args))) - - spec = getattr(Pyload, "%s_result" % name).thrift_spec - if not spec or not spec[0]: - dev.write("\t'%s': None,\n" % name) - else: - spec = spec[0] - dev.write("\t'%s': %s,\n" % (name, get_spec(spec))) - - f.write("\n") - dev.write("}\n") - - f.close() - dev.close() - -if __name__ == "__main__": - main()
\ No newline at end of file diff --git a/module/remote/create_jstypes.py b/module/remote/create_jstypes.py deleted file mode 100644 index 90afa4c96..000000000 --- a/module/remote/create_jstypes.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from os.path import abspath, dirname, join - -path = dirname(abspath(__file__)) -module = join(path, "..") - -import apitypes -from apitypes_debug import enums - -# generate js enums -def main(): - - print "generating apitypes.js" - - f = open(join(module, 'web', 'app', 'scripts', 'utils', 'apitypes.js'), 'wb') - f.write("""// Autogenerated, do not edit! -/*jslint -W070: false*/ -define([], function() { -\t'use strict'; -\treturn { -""") - - for name in enums: - enum = getattr(apitypes, name) - values = dict([(attr, getattr(enum, attr)) for attr in dir(enum) if not attr.startswith("_")]) - - f.write("\t\t%s: %s,\n" % (name, str(values))) - - f.write("\t};\n});") - f.close() - - -if __name__ == "__main__": - main() diff --git a/module/remote/json_converter.py b/module/remote/json_converter.py deleted file mode 100644 index 50f0309bd..000000000 --- a/module/remote/json_converter.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -try: - from module.common.json_layer import json -except ImportError: - import json - - -import apitypes -from apitypes import BaseObject -from apitypes import ExceptionObject - -# compact json separator -separators = (',', ':') - -# json encoder that accepts api objects -class BaseEncoder(json.JSONEncoder): - - def default(self, o): - if isinstance(o, BaseObject) or isinstance(o, ExceptionObject): - ret = {"@class" : o.__class__.__name__} - for att in o.__slots__: - ret[att] = getattr(o, att) - return ret - - return json.JSONEncoder.default(self, o) - -# more compact representation, only clients with information of the classes can handle it -class BaseEncoderCompact(json.JSONEncoder): - - def default(self, o): - if isinstance(o, BaseObject) or isinstance(o, ExceptionObject): - ret = {"@compact" : [o.__class__.__name__]} - ret["@compact"].extend(getattr(o, attr) for attr in o.__slots__) - return ret - - return json.JSONEncoder.default(self, o) - -def convert_obj(dct): - if '@class' in dct: - cls = getattr(apitypes, dct['@class']) - del dct['@class'] - return cls(**dct) - elif '@compact' in dct: - cls = getattr(apitypes, dct['@compact'][0]) - return cls(*dct['@compact'][1:]) - - return dct - -def dumps(*args, **kwargs): - if 'compact' in kwargs: - kwargs['cls'] = BaseEncoderCompact - del kwargs['compact'] - else: - kwargs['cls'] = BaseEncoder - - kwargs['separators'] = separators - return json.dumps(*args, **kwargs) - - -def loads(*args, **kwargs): - kwargs['object_hook'] = convert_obj - return json.loads(*args, **kwargs)
\ No newline at end of file diff --git a/module/remote/pyload.thrift b/module/remote/pyload.thrift deleted file mode 100644 index 57d7e0a0a..000000000 --- a/module/remote/pyload.thrift +++ /dev/null @@ -1,538 +0,0 @@ -namespace java org.pyload.thrift - -typedef i32 FileID -typedef i32 PackageID -typedef i32 ResultID -typedef i32 InteractionID -typedef i32 UserID -typedef i64 UTCDate -typedef i64 ByteCount -typedef list<string> LinkList -typedef string PluginName -typedef string JSONString - -// NA - Not Available -enum DownloadStatus { - NA, - Offline, - Online, - Queued, - Paused, - Finished, - Skipped, - Failed, - Starting, - Waiting, - Downloading, - TempOffline, - Aborted, - Decrypting, - Processing, - Custom, - Unknown -} - -// Download states, combination of several downloadstatuses -// defined in Api -enum DownloadState { - All, - Finished, - Unfinished, - Failed, - Unmanaged // internal state -} - -enum MediaType { - All = 0 - Other = 1, - Audio = 2, - Image = 4, - Video = 8, - Document = 16, - Archive = 32, -} - -enum FileStatus { - Ok, - Missing, - Remote, // file is available at remote location -} - -enum PackageStatus { - Ok, - Paused, - Folder, - Remote, -} - -// types for user interaction -// some may only be place holder currently not supported -// also all input - output combination are not reasonable, see InteractionManager for further info -// Todo: how about: time, ip, s.o. -enum InputType { - NA, - Text, - Int, - File, - Folder, - Textbox, - Password, - Bool, // confirm like, yes or no dialog - Click, // for positional captchas - Select, // select from list - Multiple, // multiple choice from list of elements - List, // arbitary list of elements - Table // table like data structure -} -// more can be implemented by need - -// this describes the type of the outgoing interaction -// ensure they can be logcial or'ed -enum Interaction { - All = 0, - Notification = 1, - Captcha = 2, - Query = 4, -} - -enum Permission { - All = 0, // requires no permission, but login - Add = 1, // can add packages - Delete = 2, // can delete packages - Modify = 4, // modify some attribute of downloads - Download = 8, // can download from webinterface - Accounts = 16, // can access accounts - Interaction = 32, // can interact with plugins - Plugins = 64 // user can configure plugins and activate addons -} - -enum Role { - Admin = 0, //admin has all permissions implicit - User = 1 -} - -struct Input { - 1: InputType type, - 2: optional JSONString data, -} - -struct DownloadProgress { - 1: FileID fid, - 2: PackageID pid, - 3: ByteCount speed, // per second - 4: DownloadStatus status, -} - -struct ProgressInfo { - 1: PluginName plugin, - 2: string name, - 3: string statusmsg, - 4: i32 eta, // in seconds - 5: ByteCount done, - 6: ByteCount total, // arbitary number, size in case of files - 7: optional DownloadProgress download -} - -// download info for specific file -struct DownloadInfo { - 1: string url, - 2: PluginName plugin, - 3: string hash, - 4: DownloadStatus status, - 5: string statusmsg, - 6: string error, -} - -struct FileInfo { - 1: FileID fid, - 2: string name, - 3: PackageID package, - 4: UserID owner, - 5: ByteCount size, - 6: FileStatus status, - 7: MediaType media, - 8: UTCDate added, - 9: i16 fileorder, - 10: optional DownloadInfo download, -} - -struct PackageStats { - 1: i16 linkstotal, - 2: i16 linksdone, - 3: ByteCount sizetotal, - 4: ByteCount sizedone, -} - -struct PackageInfo { - 1: PackageID pid, - 2: string name, - 3: string folder, - 4: PackageID root, - 5: UserID owner, - 6: string site, - 7: string comment, - 8: string password, - 9: UTCDate added, - 10: list<string> tags, - 11: PackageStatus status, - 12: bool shared, - 13: i16 packageorder, - 14: PackageStats stats, - 15: list<FileID> fids, - 16: list<PackageID> pids, -} - -// thrift does not allow recursive datatypes, so all data is accumulated and mapped with id -struct TreeCollection { - 1: PackageInfo root, - 2: map<FileID, FileInfo> files, - 3: map<PackageID, PackageInfo> packages -} - -// general info about link, used for collector and online results -struct LinkStatus { - 1: string url, - 2: string name, - 3: PluginName plugin, - 4: ByteCount size, // size <= 0 : unknown - 5: DownloadStatus status, - 6: string packagename, -} - -struct ServerStatus { - 1: ByteCount speed, - 2: i16 linkstotal, - 3: i16 linksqueue, - 4: ByteCount sizetotal, - 5: ByteCount sizequeue, - 6: bool notifications, - 7: bool paused, - 8: bool download, - 9: bool reconnect, -} - -struct InteractionTask { - 1: InteractionID iid, - 2: Interaction type, - 3: Input input, - 4: optional JSONString default_value, - 5: string title, - 6: string description, - 7: PluginName plugin, -} - -struct AddonService { - 1: string func_name, - 2: string description, - 3: list<string> arguments, - 4: optional i16 media, -} - -struct AddonInfo { - 1: string func_name, - 2: string description, - 3: JSONString value, -} - -struct ConfigItem { - 1: string name, - 2: string label, - 3: string description, - 4: Input input, - 5: JSONString default_value, - 6: JSONString value, -} - -struct ConfigHolder { - 1: string name, // for plugin this is the PluginName - 2: string label, - 3: string description, - 4: string long_description, - 5: list<ConfigItem> items, - 6: optional list<AddonInfo> info, -} - -struct ConfigInfo { - 1: string name - 2: string label, - 3: string description, - 4: string category, - 5: bool user_context, - 6: optional bool activated, -} - -struct EventInfo { - 1: string eventname, - 2: list<JSONString> event_args, //will contain json objects -} - -struct UserData { - 1: UserID uid, - 2: string name, - 3: string email, - 4: i16 role, - 5: i16 permission, - 6: string folder, - 7: ByteCount traffic - 8: i16 dllimit - 9: string dlquota, - 10: ByteCount hddquota, - 11: UserID user, - 12: string templateName -} - -struct AccountInfo { - 1: PluginName plugin, - 2: string loginname, - 3: UserID owner, - 4: bool valid, - 5: UTCDate validuntil, - 6: ByteCount trafficleft, - 7: ByteCount maxtraffic, - 8: bool premium, - 9: bool activated, - 10: bool shared, - 11: map<string, string> options, -} - -struct OnlineCheck { - 1: ResultID rid, // -1 -> nothing more to get - 2: map<string, LinkStatus> data, // url to result -} - -// exceptions - -exception PackageDoesNotExists { - 1: PackageID pid -} - -exception FileDoesNotExists { - 1: FileID fid -} - -exception UserDoesNotExists { - 1: string user -} - -exception ServiceDoesNotExists { - 1: string plugin - 2: string func -} - -exception ServiceException { - 1: string msg -} - -exception InvalidConfigSection { - 1: string section -} - -exception Unauthorized { -} - -exception Forbidden { -} - - -service Pyload { - - /////////////////////// - // Core Status - /////////////////////// - - string getServerVersion(), - string getWSAddress(), - ServerStatus getServerStatus(), - list<ProgressInfo> getProgressInfo(), - - list<string> getLog(1: i32 offset), - ByteCount freeSpace(), - - void pauseServer(), - void unpauseServer(), - bool togglePause(), - bool toggleReconnect(), - - void quit(), - void restart(), - - /////////////////////// - // Configuration - /////////////////////// - - map<string, ConfigHolder> getConfig(), - string getConfigValue(1: string section, 2: string option), - - // two methods with ambigous classification, could be configuration or addon/plugin related - list<ConfigInfo> getCoreConfig(), - list<ConfigInfo> getPluginConfig(), - list<ConfigInfo> getAvailablePlugins(), - - ConfigHolder loadConfig(1: string name), - - void setConfigValue(1: string section, 2: string option, 3: string value), - void saveConfig(1: ConfigHolder config), - void deleteConfig(1: PluginName plugin), - - /////////////////////// - // Download Preparing - /////////////////////// - - map<PluginName, LinkList> checkURLs(1: LinkList urls), - map<PluginName, LinkList> parseURLs(1: string html, 2: string url), - - // parses results and generates packages - OnlineCheck checkOnlineStatus(1: LinkList urls), - OnlineCheck checkOnlineStatusContainer(1: LinkList urls, 2: string filename, 3: binary data) - - // poll results from previously started online check - OnlineCheck pollResults(1: ResultID rid), - - // packagename -> urls - map<string, LinkList> generatePackages(1: LinkList links), - - /////////////////////// - // Download - /////////////////////// - - list<PackageID> generateAndAddPackages(1: LinkList links, 2: bool paused), - - PackageID createPackage(1: string name, 2: string folder, 3: PackageID root, 4: string password, - 5: string site, 6: string comment, 7: bool paused), - - PackageID addPackage(1: string name, 2: LinkList links, 3: string password), - // same as above with paused attribute - PackageID addPackageP(1: string name, 2: LinkList links, 3: string password, 4: bool paused), - - // pid -1 is toplevel - PackageID addPackageChild(1: string name, 2: LinkList links, 3: string password, 4: PackageID root, 5: bool paused), - - PackageID uploadContainer(1: string filename, 2: binary data), - - void addLinks(1: PackageID pid, 2: LinkList links) throws (1: PackageDoesNotExists e), - void addLocalFile(1: PackageID pid, 2: string name, 3: string path) throws (1: PackageDoesNotExists e) - - // these are real file operations and WILL delete files on disk - void deleteFiles(1: list<FileID> fids), - void deletePackages(1: list<PackageID> pids), // delete the whole folder recursive - - // Modify Downloads - - void restartPackage(1: PackageID pid), - void restartFile(1: FileID fid), - void recheckPackage(1: PackageID pid), - void restartFailed(), - void stopDownloads(1: list<FileID> fids), - void stopAllDownloads(), - - /////////////////////// - // Collector - /////////////////////// - - list<LinkStatus> getCollector(), - - void addToCollector(1: LinkList links), - PackageID addFromCollector(1: string name, 2: bool paused), - void renameCollPack(1: string name, 2: string new_name), - void deleteCollPack(1: string name), - void deleteCollLink(1: string url), - - //////////////////////////// - // File Information retrieval - //////////////////////////// - - TreeCollection getAllFiles(), - TreeCollection getFilteredFiles(1: DownloadState state), - - // pid -1 for root, full=False only delivers first level in tree - TreeCollection getFileTree(1: PackageID pid, 2: bool full), - TreeCollection getFilteredFileTree(1: PackageID pid, 2: bool full, 3: DownloadState state), - - // same as above with full=False - TreeCollection getPackageContent(1: PackageID pid), - - PackageInfo getPackageInfo(1: PackageID pid) throws (1: PackageDoesNotExists e), - FileInfo getFileInfo(1: FileID fid) throws (1: FileDoesNotExists e), - - TreeCollection findFiles(1: string pattern), - TreeCollection findPackages(1: list<string> tags), - list<string> searchSuggestions(1: string pattern), - - // Modify Files/Packages - - // moving package while downloading is not possible, so they will return bool to indicate success - void updatePackage(1: PackageInfo pack) throws (1: PackageDoesNotExists e), - bool setPackageFolder(1: PackageID pid, 2: string path) throws (1: PackageDoesNotExists e), - - // as above, this will move files on disk - bool movePackage(1: PackageID pid, 2: PackageID root) throws (1: PackageDoesNotExists e), - bool moveFiles(1: list<FileID> fids, 2: PackageID pid) throws (1: PackageDoesNotExists e), - - void orderPackage(1: list<PackageID> pids, 2: i16 position), - void orderFiles(1: list<FileID> fids, 2: PackageID pid, 3: i16 position), - - /////////////////////// - // User Interaction - /////////////////////// - - // mode = interaction types binary ORed - bool isInteractionWaiting(1: i16 mode), - list<InteractionTask> getInteractionTasks(1: i16 mode), - void setInteractionResult(1: InteractionID iid, 2: JSONString result), - - // generate a download link, everybody can download the file until timeout reached - string generateDownloadLink(1: FileID fid, 2: i16 timeout), - - /////////////////////// - // Account Methods - /////////////////////// - - list<AccountInfo> getAccounts(1: bool refresh), - list<string> getAccountTypes(), - void updateAccount(1: PluginName plugin, 2: string login, 3: string password), - void updateAccountInfo(1: AccountInfo account), - void removeAccount(1: AccountInfo account), - - ///////////////////////// - // Auth+User Information - ///////////////////////// - - bool login(1: string username, 2: string password), - // returns own user data - UserData getUserData(), - - // all user, for admins only - map<UserID, UserData> getAllUserData(), - - UserData addUser(1: string username, 2:string password), - - // normal user can only update their own userdata and not all attributes - void updateUserData(1: UserData data), - void removeUser(1: UserID uid), - - // works contextual, admin can change every password - bool setPassword(1: string username, 2: string old_password, 3: string new_password), - - /////////////////////// - // Addon Methods - /////////////////////// - - //map<PluginName, list<AddonInfo>> getAllInfo(), - //list<AddonInfo> getInfoByPlugin(1: PluginName plugin), - - map<PluginName, list<AddonService>> getAddonHandler(), - bool hasAddonHandler(1: PluginName plugin, 2: string func), - - void callAddon(1: PluginName plugin, 2: string func, 3: list<JSONString> arguments) - throws (1: ServiceDoesNotExists e, 2: ServiceException ex), - - // special variant of callAddon that works on the media types, acccepting integer - void callAddonHandler(1: PluginName plugin, 2: string func, 3: PackageID pid_or_fid) - throws (1: ServiceDoesNotExists e, 2: ServiceException ex), - - - //scheduler - - // TODO - -} diff --git a/module/remote/ttypes.py b/module/remote/ttypes.py deleted file mode 100644 index 1f91403d5..000000000 --- a/module/remote/ttypes.py +++ /dev/null @@ -1,534 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# Autogenerated by pyload -# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING - -class BaseObject(object): - __slots__ = [] - - def __str__(self): - return "<%s %s>" % (self.__class__.__name__, ", ".join("%s=%s" % (k,getattr(self,k)) for k in self.__slots__)) - -class ExceptionObject(Exception): - __slots__ = [] - -class DownloadState: - All = 0 - Finished = 1 - Unfinished = 2 - Failed = 3 - Unmanaged = 4 - -class DownloadStatus: - NA = 0 - Offline = 1 - Online = 2 - Queued = 3 - Paused = 4 - Finished = 5 - Skipped = 6 - Failed = 7 - Starting = 8 - Waiting = 9 - Downloading = 10 - TempOffline = 11 - Aborted = 12 - Decrypting = 13 - Processing = 14 - Custom = 15 - Unknown = 16 - -class FileStatus: - Ok = 0 - Missing = 1 - Remote = 2 - -class Input: - NA = 0 - Text = 1 - Int = 2 - File = 3 - Folder = 4 - Textbox = 5 - Password = 6 - Bool = 7 - Click = 8 - Select = 9 - Multiple = 10 - List = 11 - Table = 12 - -class MediaType: - All = 0 - Other = 1 - Audio = 2 - Image = 4 - Video = 8 - Document = 16 - Archive = 32 - -class Output: - All = 0 - Notification = 1 - Captcha = 2 - Query = 4 - -class PackageStatus: - Ok = 0 - Paused = 1 - Folder = 2 - Remote = 3 - -class Permission: - All = 0 - Add = 1 - Delete = 2 - Modify = 4 - Download = 8 - Accounts = 16 - Interaction = 32 - Plugins = 64 - -class Role: - Admin = 0 - User = 1 - -class AccountInfo(BaseObject): - __slots__ = ['plugin', 'loginname', 'owner', 'valid', 'validuntil', 'trafficleft', 'maxtraffic', 'premium', 'activated', 'shared', 'options'] - - def __init__(self, plugin=None, loginname=None, owner=None, valid=None, validuntil=None, trafficleft=None, maxtraffic=None, premium=None, activated=None, shared=None, options=None): - self.plugin = plugin - self.loginname = loginname - self.owner = owner - self.valid = valid - self.validuntil = validuntil - self.trafficleft = trafficleft - self.maxtraffic = maxtraffic - self.premium = premium - self.activated = activated - self.shared = shared - self.options = options - -class AddonInfo(BaseObject): - __slots__ = ['func_name', 'description', 'value'] - - def __init__(self, func_name=None, description=None, value=None): - self.func_name = func_name - self.description = description - self.value = value - -class AddonService(BaseObject): - __slots__ = ['func_name', 'description', 'arguments', 'media'] - - def __init__(self, func_name=None, description=None, arguments=None, media=None): - self.func_name = func_name - self.description = description - self.arguments = arguments - self.media = media - -class ConfigHolder(BaseObject): - __slots__ = ['name', 'label', 'description', 'long_description', 'items', 'info', 'handler'] - - def __init__(self, name=None, label=None, description=None, long_description=None, items=None, info=None, handler=None): - self.name = name - self.label = label - self.description = description - self.long_description = long_description - self.items = items - self.info = info - self.handler = handler - -class ConfigInfo(BaseObject): - __slots__ = ['name', 'label', 'description', 'category', 'user_context', 'activated'] - - def __init__(self, name=None, label=None, description=None, category=None, user_context=None, activated=None): - self.name = name - self.label = label - self.description = description - self.category = category - self.user_context = user_context - self.activated = activated - -class ConfigItem(BaseObject): - __slots__ = ['name', 'label', 'description', 'type', 'default_value', 'value'] - - def __init__(self, name=None, label=None, description=None, type=None, default_value=None, value=None): - self.name = name - self.label = label - self.description = description - self.type = type - self.default_value = default_value - self.value = value - -class DownloadInfo(BaseObject): - __slots__ = ['url', 'plugin', 'hash', 'status', 'statusmsg', 'error'] - - def __init__(self, url=None, plugin=None, hash=None, status=None, statusmsg=None, error=None): - self.url = url - self.plugin = plugin - self.hash = hash - self.status = status - self.statusmsg = statusmsg - self.error = error - -class DownloadProgress(BaseObject): - __slots__ = ['fid', 'pid', 'speed', 'status'] - - def __init__(self, fid=None, pid=None, speed=None, status=None): - self.fid = fid - self.pid = pid - self.speed = speed - self.status = status - -class EventInfo(BaseObject): - __slots__ = ['eventname', 'event_args'] - - def __init__(self, eventname=None, event_args=None): - self.eventname = eventname - self.event_args = event_args - -class FileDoesNotExists(ExceptionObject): - __slots__ = ['fid'] - - def __init__(self, fid=None): - self.fid = fid - -class FileInfo(BaseObject): - __slots__ = ['fid', 'name', 'package', 'owner', 'size', 'status', 'media', 'added', 'fileorder', 'download'] - - def __init__(self, fid=None, name=None, package=None, owner=None, size=None, status=None, media=None, added=None, fileorder=None, download=None): - self.fid = fid - self.name = name - self.package = package - self.owner = owner - self.size = size - self.status = status - self.media = media - self.added = added - self.fileorder = fileorder - self.download = download - -class Forbidden(ExceptionObject): - pass - -class InteractionTask(BaseObject): - __slots__ = ['iid', 'input', 'data', 'output', 'default_value', 'title', 'description', 'plugin'] - - def __init__(self, iid=None, input=None, data=None, output=None, default_value=None, title=None, description=None, plugin=None): - self.iid = iid - self.input = input - self.data = data - self.output = output - self.default_value = default_value - self.title = title - self.description = description - self.plugin = plugin - -class InvalidConfigSection(ExceptionObject): - __slots__ = ['section'] - - def __init__(self, section=None): - self.section = section - -class LinkStatus(BaseObject): - __slots__ = ['url', 'name', 'plugin', 'size', 'status', 'packagename'] - - def __init__(self, url=None, name=None, plugin=None, size=None, status=None, packagename=None): - self.url = url - self.name = name - self.plugin = plugin - self.size = size - self.status = status - self.packagename = packagename - -class OnlineCheck(BaseObject): - __slots__ = ['rid', 'data'] - - def __init__(self, rid=None, data=None): - self.rid = rid - self.data = data - -class PackageDoesNotExists(ExceptionObject): - __slots__ = ['pid'] - - def __init__(self, pid=None): - self.pid = pid - -class PackageInfo(BaseObject): - __slots__ = ['pid', 'name', 'folder', 'root', 'owner', 'site', 'comment', 'password', 'added', 'tags', 'status', 'shared', 'packageorder', 'stats', 'fids', 'pids'] - - def __init__(self, pid=None, name=None, folder=None, root=None, owner=None, site=None, comment=None, password=None, added=None, tags=None, status=None, shared=None, packageorder=None, stats=None, fids=None, pids=None): - self.pid = pid - self.name = name - self.folder = folder - self.root = root - self.owner = owner - self.site = site - self.comment = comment - self.password = password - self.added = added - self.tags = tags - self.status = status - self.shared = shared - self.packageorder = packageorder - self.stats = stats - self.fids = fids - self.pids = pids - -class PackageStats(BaseObject): - __slots__ = ['linkstotal', 'linksdone', 'sizetotal', 'sizedone'] - - def __init__(self, linkstotal=None, linksdone=None, sizetotal=None, sizedone=None): - self.linkstotal = linkstotal - self.linksdone = linksdone - self.sizetotal = sizetotal - self.sizedone = sizedone - -class ProgressInfo(BaseObject): - __slots__ = ['plugin', 'name', 'statusmsg', 'eta', 'done', 'total', 'download'] - - def __init__(self, plugin=None, name=None, statusmsg=None, eta=None, done=None, total=None, download=None): - self.plugin = plugin - self.name = name - self.statusmsg = statusmsg - self.eta = eta - self.done = done - self.total = total - self.download = download - -class ServerStatus(BaseObject): - __slots__ = ['queuedDownloads', 'totalDownloads', 'speed', 'pause', 'download', 'reconnect'] - - def __init__(self, queuedDownloads=None, totalDownloads=None, speed=None, pause=None, download=None, reconnect=None): - self.queuedDownloads = queuedDownloads - self.totalDownloads = totalDownloads - self.speed = speed - self.pause = pause - self.download = download - self.reconnect = reconnect - -class ServiceDoesNotExists(ExceptionObject): - __slots__ = ['plugin', 'func'] - - def __init__(self, plugin=None, func=None): - self.plugin = plugin - self.func = func - -class ServiceException(ExceptionObject): - __slots__ = ['msg'] - - def __init__(self, msg=None): - self.msg = msg - -class TreeCollection(BaseObject): - __slots__ = ['root', 'files', 'packages'] - - def __init__(self, root=None, files=None, packages=None): - self.root = root - self.files = files - self.packages = packages - -class Unauthorized(ExceptionObject): - pass - -class UserData(BaseObject): - __slots__ = ['uid', 'name', 'email', 'role', 'permission', 'folder', 'traffic', 'dllimit', 'dlquota', 'hddquota', 'user', 'templateName'] - - def __init__(self, uid=None, name=None, email=None, role=None, permission=None, folder=None, traffic=None, dllimit=None, dlquota=None, hddquota=None, user=None, templateName=None): - self.uid = uid - self.name = name - self.email = email - self.role = role - self.permission = permission - self.folder = folder - self.traffic = traffic - self.dllimit = dllimit - self.dlquota = dlquota - self.hddquota = hddquota - self.user = user - self.templateName = templateName - -class UserDoesNotExists(ExceptionObject): - __slots__ = ['user'] - - def __init__(self, user=None): - self.user = user - -class Iface(object): - def addFromCollector(self, name, paused): - pass - def addLinks(self, pid, links): - pass - def addLocalFile(self, pid, name, path): - pass - def addPackage(self, name, links, password): - pass - def addPackageChild(self, name, links, password, root, paused): - pass - def addPackageP(self, name, links, password, paused): - pass - def addToCollector(self, links): - pass - def addUser(self, username, password): - pass - def callAddon(self, plugin, func, arguments): - pass - def callAddonHandler(self, plugin, func, pid_or_fid): - pass - def checkOnlineStatus(self, urls): - pass - def checkOnlineStatusContainer(self, urls, filename, data): - pass - def checkURLs(self, urls): - pass - def configurePlugin(self, plugin): - pass - def createPackage(self, name, folder, root, password, site, comment, paused): - pass - def deleteCollLink(self, url): - pass - def deleteCollPack(self, name): - pass - def deleteConfig(self, plugin): - pass - def deleteFiles(self, fids): - pass - def deletePackages(self, pids): - pass - def findFiles(self, pattern): - pass - def findPackages(self, tags): - pass - def freeSpace(self): - pass - def generateAndAddPackages(self, links, paused): - pass - def generateDownloadLink(self, fid, timeout): - pass - def generatePackages(self, links): - pass - def getAccountTypes(self): - pass - def getAccounts(self, refresh): - pass - def getAddonHandler(self): - pass - def getAllFiles(self): - pass - def getAllUserData(self): - pass - def getAutocompletion(self, pattern): - pass - def getAvailablePlugins(self): - pass - def getCollector(self): - pass - def getConfig(self): - pass - def getConfigValue(self, section, option): - pass - def getCoreConfig(self): - pass - def getEvents(self, uuid): - pass - def getFileInfo(self, fid): - pass - def getFileTree(self, pid, full): - pass - def getFilteredFileTree(self, pid, full, state): - pass - def getFilteredFiles(self, state): - pass - def getInteractionTask(self, mode): - pass - def getLog(self, offset): - pass - def getNotifications(self): - pass - def getPackageContent(self, pid): - pass - def getPackageInfo(self, pid): - pass - def getPluginConfig(self): - pass - def getProgressInfo(self): - pass - def getServerStatus(self): - pass - def getServerVersion(self): - pass - def getUserData(self): - pass - def getWSAddress(self): - pass - def hasAddonHandler(self, plugin, func): - pass - def isInteractionWaiting(self, mode): - pass - def login(self, username, password): - pass - def moveFiles(self, fids, pid): - pass - def movePackage(self, pid, root): - pass - def orderFiles(self, fids, pid, position): - pass - def orderPackage(self, pids, position): - pass - def parseURLs(self, html, url): - pass - def pauseServer(self): - pass - def pollResults(self, rid): - pass - def quit(self): - pass - def recheckPackage(self, pid): - pass - def removeAccount(self, plugin, account): - pass - def removeUser(self, uid): - pass - def renameCollPack(self, name, new_name): - pass - def restart(self): - pass - def restartFailed(self): - pass - def restartFile(self, fid): - pass - def restartPackage(self, pid): - pass - def saveConfig(self, config): - pass - def setConfigHandler(self, plugin, iid, value): - pass - def setConfigValue(self, section, option, value): - pass - def setInteractionResult(self, iid, result): - pass - def setPackageFolder(self, pid, path): - pass - def setPassword(self, username, old_password, new_password): - pass - def stopAllDownloads(self): - pass - def stopDownloads(self, fids): - pass - def togglePause(self): - pass - def toggleReconnect(self): - pass - def unpauseServer(self): - pass - def updateAccount(self, plugin, account, password): - pass - def updateAccountInfo(self, account): - pass - def updatePackage(self, pack): - pass - def updateUserData(self, data): - pass - def uploadContainer(self, filename, data): - pass - diff --git a/module/remote/wsbackend/AbstractHandler.py b/module/remote/wsbackend/AbstractHandler.py deleted file mode 100644 index 07cc79c74..000000000 --- a/module/remote/wsbackend/AbstractHandler.py +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -############################################################################### -# Copyright(c) 2008-2012 pyLoad Team -# http://www.pyload.org -# -# This file is part of pyLoad. -# pyLoad is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Subjected to the terms and conditions in LICENSE -# -# @author: RaNaN -############################################################################### - -from mod_pywebsocket.msgutil import send_message -from mod_pywebsocket.util import get_class_logger -from module.remote.json_converter import loads, dumps - - -class AbstractHandler: - """ - Abstract Handler providing common methods shared across WebSocket handlers - """ - PATH = "/" - - OK = 200 - BAD_REQUEST = 400 - UNAUTHORIZED = 401 - FORBIDDEN = 403 - NOT_FOUND = 404 - ERROR = 500 - - def __init__(self, api): - self.log = get_class_logger() - self.api = api - self.core = api.core - - def do_extra_handshake(self, req): - self.log.debug("WS Connected: %s" % req) - req.api = None #when api is set client is logged in - - # allow login via session when webinterface is active - if self.core.config['webinterface']['activated']: - cookie = req.headers_in.getheader('Cookie') - s = self.load_session(cookie) - if s: - uid = s.get('uid', None) - req.api = self.api.withUserContext(uid) - self.log.debug("WS authenticated user with cookie: %d" % uid) - - self.on_open(req) - - def on_open(self, req): - pass - - def load_session(self, cookies): - from Cookie import SimpleCookie - from beaker.session import Session - from module.web.webinterface import session - - cookies = SimpleCookie(cookies) - sid = cookies.get(session.options['key']) - if not sid: - return None - - s = Session({}, use_cookies=False, id=sid.value, **session.options) - if s.is_new: - return None - - return s - - def passive_closing_handshake(self, req): - self.log.debug("WS Closed: %s" % req) - self.on_close(req) - - def on_close(self, req): - pass - - def transfer_data(self, req): - raise NotImplemented - - def handle_call(self, msg, req): - """ Parses the msg for an argument call. If func is null an response was already sent. - - :return: func, args, kwargs - """ - try: - o = loads(msg) - except ValueError, e: #invalid json object - self.log.debug("Invalid Request: %s" % e) - self.send_result(req, self.ERROR, "No JSON request") - return None, None, None - - if not isinstance(o, basestring) and type(o) != list and len(o) not in range(1, 4): - self.log.debug("Invalid Api call: %s" % o) - self.send_result(req, self.ERROR, "Invalid Api call") - return None, None, None - - # called only with name, no args - if isinstance(o, basestring): - return o, [], {} - elif len(o) == 1: # arguments omitted - return o[0], [], {} - elif len(o) == 2: - func, args = o - if type(args) == list: - return func, args, {} - else: - return func, [], args - else: - return tuple(o) - - def do_login(self, req, args, kwargs): - user = self.api.checkAuth(*args, **kwargs) - if user: - req.api = self.api.withUserContext(user.uid) - return self.send_result(req, self.OK, True) - else: - return self.send_result(req, self.FORBIDDEN, "Forbidden") - - def do_logout(self, req): - req.api = None - return self.send_result(req, self.OK, True) - - def send_result(self, req, code, result): - return send_message(req, dumps([code, result])) - - def send(self, req, obj): - return send_message(req, dumps(obj))
\ No newline at end of file diff --git a/module/remote/wsbackend/ApiHandler.py b/module/remote/wsbackend/ApiHandler.py deleted file mode 100644 index e985e10be..000000000 --- a/module/remote/wsbackend/ApiHandler.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -############################################################################### -# Copyright(c) 2008-2012 pyLoad Team -# http://www.pyload.org -# -# This file is part of pyLoad. -# pyLoad is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Subjected to the terms and conditions in LICENSE -# -# @author: RaNaN -############################################################################### - -from mod_pywebsocket.msgutil import receive_message - -from module.Api import ExceptionObject - -from AbstractHandler import AbstractHandler - -class ApiHandler(AbstractHandler): - """Provides access to the API. - - Send your request as json encoded string in the following manner: - ["function", [*args]] or ["function", {**kwargs}] - - the result will be: - - [code, result] - - Don't forget to login first. - Non json request will be ignored. - """ - - PATH = "/api" - - def transfer_data(self, req): - while True: - try: - line = receive_message(req) - except TypeError, e: # connection closed - self.log.debug("WS Error: %s" % e) - return self.passive_closing_handshake(req) - - self.handle_message(line, req) - - def handle_message(self, msg, req): - - func, args, kwargs = self.handle_call(msg, req) - if not func: - return # handle_call already sent the result - - if func == 'login': - return self.do_login(req, args, kwargs) - elif func == 'logout': - return self.do_logout(req) - else: - if not req.api: - return self.send_result(req, self.FORBIDDEN, "Forbidden") - - if not self.api.isAuthorized(func, req.api.user): - return self.send_result(req, self.UNAUTHORIZED, "Unauthorized") - - try: - result = getattr(req.api, func)(*args, **kwargs) - except ExceptionObject, e: - return self.send_result(req, self.BAD_REQUEST, e) - except AttributeError: - return self.send_result(req, self.NOT_FOUND, "Not Found") - except Exception, e: - self.core.print_exc() - return self.send_result(req, self.ERROR, str(e)) - - # None is invalid json type - if result is None: result = True - - return self.send_result(req, self.OK, result)
\ No newline at end of file diff --git a/module/remote/wsbackend/AsyncHandler.py b/module/remote/wsbackend/AsyncHandler.py deleted file mode 100644 index 158033ee8..000000000 --- a/module/remote/wsbackend/AsyncHandler.py +++ /dev/null @@ -1,167 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -############################################################################### -# Copyright(c) 2008-2012 pyLoad Team -# http://www.pyload.org -# -# This file is part of pyLoad. -# pyLoad is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Subjected to the terms and conditions in LICENSE -# -# @author: RaNaN -############################################################################### - -import re -from Queue import Queue, Empty -from threading import Lock -from time import time - -from mod_pywebsocket.msgutil import receive_message - -from module.Api import EventInfo, Interaction -from module.utils import lock -from AbstractHandler import AbstractHandler - -class Mode: - STANDBY = 1 - RUNNING = 2 - -class AsyncHandler(AbstractHandler): - """ - Handler that provides asynchronous information about server status, running downloads, occurred events. - - Progress information are continuous and will be pushed in a fixed interval when available. - After connect you have to login and can set the interval by sending the json command ["setInterval", xy]. - To start receiving updates call "start", afterwards no more incoming messages will be accepted! - """ - - PATH = "/async" - COMMAND = "start" - - PROGRESS_INTERVAL = 2 - EVENT_PATTERN = re.compile(r"^(package|file|interaction)", re.I) - INTERACTION = Interaction.All - - def __init__(self, api): - AbstractHandler.__init__(self, api) - self.clients = [] - self.lock = Lock() - - self.core.evm.addEvent("event", self.add_event) - - @lock - def on_open(self, req): - req.queue = Queue() - req.interval = self.PROGRESS_INTERVAL - req.events = self.EVENT_PATTERN - req.interaction = self.INTERACTION - req.mode = Mode.STANDBY - req.t = time() # time when update should be pushed - self.clients.append(req) - - @lock - def on_close(self, req): - try: - del req.queue - self.clients.remove(req) - except ValueError: # ignore when not in list - pass - - @lock - def add_event(self, event, *args): - # Convert arguments to json suited instance - event = EventInfo(event, [x.toInfoData() if hasattr(x, 'toInfoData') else x for x in args]) - - for req in self.clients: - # Not logged in yet - if not req.api: continue - - # filter events that these user is no owner of - # TODO: events are security critical, this should be revised later - # TODO: permissions? interaction etc - if not req.api.user.isAdmin(): - skip = False - for arg in args: - if hasattr(arg, 'owner') and arg.owner != req.api.primaryUID: - skip = True - break - - # user should not get this event - if skip: break - - if req.events.search(event.eventname): - self.log.debug("Pushing event %s" % event) - req.queue.put(event) - - def transfer_data(self, req): - while True: - - if req.mode == Mode.STANDBY: - try: - line = receive_message(req) - except TypeError, e: # connection closed - self.log.debug("WS Error: %s" % e) - return self.passive_closing_handshake(req) - - self.mode_standby(line, req) - else: - if self.mode_running(req): - return self.passive_closing_handshake(req) - - def mode_standby(self, msg, req): - """ accepts calls before pushing updates """ - func, args, kwargs = self.handle_call(msg, req) - if not func: - return # Result was already sent - - if func == 'login': - return self.do_login(req, args, kwargs) - - elif func == 'logout': - return self.do_logout(req) - - else: - if not req.api: - return self.send_result(req, self.FORBIDDEN, "Forbidden") - - if func == "setInterval": - req.interval = args[0] - elif func == "setEvents": - req.events = re.compile(args[0], re.I) - elif func == "setInteraction": - req.interaction = args[0] - elif func == self.COMMAND: - req.mode = Mode.RUNNING - - - def mode_running(self, req): - """ Listen for events, closes socket when returning True """ - try: - # block length of update interval if necessary - ev = req.queue.get(True, req.interval) - try: - self.send(req, ev) - except TypeError: - self.log.debug("Event %s not converted" % ev) - ev.event_args = [] - # Resend the event without arguments - self.send(req, ev) - - except Empty: - pass - - if req.t <= time(): - # TODO: server status is not enough - # modify core api to include progress? think of other needed information to show - # eta is quite wrong currently - # notifications - self.send(req, self.api.getServerStatus()) - self.send(req, self.api.getProgressInfo()) - - # update time for next update - req.t = time() + req.interval
\ No newline at end of file diff --git a/module/remote/wsbackend/Dispatcher.py b/module/remote/wsbackend/Dispatcher.py deleted file mode 100644 index 44cc7555e..000000000 --- a/module/remote/wsbackend/Dispatcher.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -############################################################################### -# Copyright(c) 2008-2012 pyLoad Team -# http://www.pyload.org -# -# This file is part of pyLoad. -# pyLoad is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# Subjected to the terms and conditions in LICENSE -# -# @author: RaNaN -############################################################################### - -from mod_pywebsocket import util -from mod_pywebsocket.dispatch import Dispatcher as BaseDispatcher - -class Dispatcher(BaseDispatcher): - - def __init__(self): - self._logger = util.get_class_logger(self) - - self._handler_suite_map = {} - self._source_warnings = [] - - def addHandler(self, path, handler): - self._handler_suite_map[path] = handler
\ No newline at end of file diff --git a/module/remote/wsbackend/Server.py b/module/remote/wsbackend/Server.py deleted file mode 100644 index af5e1cf19..000000000 --- a/module/remote/wsbackend/Server.py +++ /dev/null @@ -1,733 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2012, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -# A copy of standalone.py with uneeded stuff removed -# some logging methods removed -# Added api attribute to request - -import BaseHTTPServer -import CGIHTTPServer -import SocketServer -import httplib -import logging -import os -import re -import select -import socket -import sys -import threading - -_HAS_SSL = False -_HAS_OPEN_SSL = False - -from mod_pywebsocket import common -from mod_pywebsocket import dispatch -from mod_pywebsocket import handshake -from mod_pywebsocket import http_header_util -from mod_pywebsocket import memorizingfile -from mod_pywebsocket import util - - -_DEFAULT_LOG_MAX_BYTES = 1024 * 256 -_DEFAULT_LOG_BACKUP_COUNT = 5 - -_DEFAULT_REQUEST_QUEUE_SIZE = 128 - -# 1024 is practically large enough to contain WebSocket handshake lines. -_MAX_MEMORIZED_LINES = 1024 - -def import_ssl(): - global _HAS_SSL, _HAS_OPEN_SSL - try: - import ssl - _HAS_SSL = True - except ImportError: - try: - import OpenSSL.SSL - _HAS_OPEN_SSL = True - except ImportError: - pass - - -class _StandaloneConnection(object): - """Mimic mod_python mp_conn.""" - - def __init__(self, request_handler): - """Construct an instance. - - Args: - request_handler: A WebSocketRequestHandler instance. - """ - - self._request_handler = request_handler - - def get_local_addr(self): - """Getter to mimic mp_conn.local_addr.""" - - return (self._request_handler.server.server_name, - self._request_handler.server.server_port) - local_addr = property(get_local_addr) - - def get_remote_addr(self): - """Getter to mimic mp_conn.remote_addr. - - Setting the property in __init__ won't work because the request - handler is not initialized yet there.""" - - return self._request_handler.client_address - remote_addr = property(get_remote_addr) - - def write(self, data): - """Mimic mp_conn.write().""" - - return self._request_handler.wfile.write(data) - - def read(self, length): - """Mimic mp_conn.read().""" - - return self._request_handler.rfile.read(length) - - def get_memorized_lines(self): - """Get memorized lines.""" - - return self._request_handler.rfile.get_memorized_lines() - - -class _StandaloneRequest(object): - """Mimic mod_python request.""" - - def __init__(self, request_handler, use_tls): - """Construct an instance. - - Args: - request_handler: A WebSocketRequestHandler instance. - """ - - self._logger = util.get_class_logger(self) - - self._request_handler = request_handler - self.connection = _StandaloneConnection(request_handler) - self._use_tls = use_tls - self.headers_in = request_handler.headers - - def get_uri(self): - """Getter to mimic request.uri.""" - - return self._request_handler.path - uri = property(get_uri) - - def get_method(self): - """Getter to mimic request.method.""" - - return self._request_handler.command - method = property(get_method) - - def get_protocol(self): - """Getter to mimic request.protocol.""" - - return self._request_handler.request_version - protocol = property(get_protocol) - - def is_https(self): - """Mimic request.is_https().""" - - return self._use_tls - - def _drain_received_data(self): - """Don't use this method from WebSocket handler. Drains unread data - in the receive buffer. - """ - - raw_socket = self._request_handler.connection - drained_data = util.drain_received_data(raw_socket) - - if drained_data: - self._logger.debug( - 'Drained data following close frame: %r', drained_data) - - -class _StandaloneSSLConnection(object): - """A wrapper class for OpenSSL.SSL.Connection to provide makefile method - which is not supported by the class. - """ - - def __init__(self, connection): - self._connection = connection - - def __getattribute__(self, name): - if name in ('_connection', 'makefile'): - return object.__getattribute__(self, name) - return self._connection.__getattribute__(name) - - def __setattr__(self, name, value): - if name in ('_connection', 'makefile'): - return object.__setattr__(self, name, value) - return self._connection.__setattr__(name, value) - - def makefile(self, mode='r', bufsize=-1): - return socket._fileobject(self._connection, mode, bufsize) - - -def _alias_handlers(dispatcher, websock_handlers_map_file): - """Set aliases specified in websock_handler_map_file in dispatcher. - - Args: - dispatcher: dispatch.Dispatcher instance - websock_handler_map_file: alias map file - """ - - fp = open(websock_handlers_map_file) - try: - for line in fp: - if line[0] == '#' or line.isspace(): - continue - m = re.match('(\S+)\s+(\S+)', line) - if not m: - logging.warning('Wrong format in map file:' + line) - continue - try: - dispatcher.add_resource_path_alias( - m.group(1), m.group(2)) - except dispatch.DispatchException, e: - logging.error(str(e)) - finally: - fp.close() - - -class WebSocketServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer): - """HTTPServer specialized for WebSocket.""" - - # Overrides SocketServer.ThreadingMixIn.daemon_threads - daemon_threads = True - # Overrides BaseHTTPServer.HTTPServer.allow_reuse_address - allow_reuse_address = True - - def __init__(self, options): - """Override SocketServer.TCPServer.__init__ to set SSL enabled - socket object to self.socket before server_bind and server_activate, - if necessary. - """ - # Removed dispatcher init here - self._logger = logging.getLogger("log") - - self.request_queue_size = options.request_queue_size - self.__ws_is_shut_down = threading.Event() - self.__ws_serving = False - - SocketServer.BaseServer.__init__( - self, (options.server_host, options.port), WebSocketRequestHandler) - - # Expose the options object to allow handler objects access it. We name - # it with websocket_ prefix to avoid conflict. - self.websocket_server_options = options - - self._create_sockets() - self.server_bind() - self.server_activate() - - def _create_sockets(self): - self.server_name, self.server_port = self.server_address - self._sockets = [] - if not self.server_name: - # On platforms that doesn't support IPv6, the first bind fails. - # On platforms that supports IPv6 - # - If it binds both IPv4 and IPv6 on call with AF_INET6, the - # first bind succeeds and the second fails (we'll see 'Address - # already in use' error). - # - If it binds only IPv6 on call with AF_INET6, both call are - # expected to succeed to listen both protocol. - addrinfo_array = [ - (socket.AF_INET6, socket.SOCK_STREAM, '', '', ''), - (socket.AF_INET, socket.SOCK_STREAM, '', '', '')] - else: - addrinfo_array = socket.getaddrinfo(self.server_name, - self.server_port, - socket.AF_UNSPEC, - socket.SOCK_STREAM, - socket.IPPROTO_TCP) - for addrinfo in addrinfo_array: - family, socktype, proto, canonname, sockaddr = addrinfo - try: - socket_ = socket.socket(family, socktype) - except Exception, e: - self._logger.info('Skip by failure: %r', e) - continue - if self.websocket_server_options.use_tls: - if _HAS_SSL: - if self.websocket_server_options.tls_client_auth: - client_cert_ = ssl.CERT_REQUIRED - else: - client_cert_ = ssl.CERT_NONE - socket_ = ssl.wrap_socket(socket_, - keyfile=self.websocket_server_options.private_key, - certfile=self.websocket_server_options.certificate, - ssl_version=ssl.PROTOCOL_SSLv23, - ca_certs=self.websocket_server_options.tls_client_ca, - cert_reqs=client_cert_) - if _HAS_OPEN_SSL: - ctx = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD) - ctx.use_privatekey_file( - self.websocket_server_options.private_key) - ctx.use_certificate_file( - self.websocket_server_options.certificate) - socket_ = OpenSSL.SSL.Connection(ctx, socket_) - self._sockets.append((socket_, addrinfo)) - - def server_bind(self): - """Override SocketServer.TCPServer.server_bind to enable multiple - sockets bind. - """ - - failed_sockets = [] - - for socketinfo in self._sockets: - socket_, addrinfo = socketinfo - if self.allow_reuse_address: - socket_.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - try: - socket_.bind(self.server_address) - except Exception, e: - self._logger.info('Skip by failure: %r', e) - socket_.close() - failed_sockets.append(socketinfo) - if self.server_address[1] == 0: - # The operating system assigns the actual port number for port - # number 0. This case, the second and later sockets should use - # the same port number. Also self.server_port is rewritten - # because it is exported, and will be used by external code. - self.server_address = ( - self.server_name, socket_.getsockname()[1]) - self.server_port = self.server_address[1] - self._logger.info('Port %r is assigned', self.server_port) - - for socketinfo in failed_sockets: - self._sockets.remove(socketinfo) - - def server_activate(self): - """Override SocketServer.TCPServer.server_activate to enable multiple - sockets listen. - """ - - failed_sockets = [] - - for socketinfo in self._sockets: - socket_, addrinfo = socketinfo - self._logger.debug('Listen on: %r', addrinfo) - try: - socket_.listen(self.request_queue_size) - except Exception, e: - self._logger.info('Skip by failure: %r', e) - socket_.close() - failed_sockets.append(socketinfo) - - for socketinfo in failed_sockets: - self._sockets.remove(socketinfo) - - if len(self._sockets) == 0: - self._logger.critical( - 'No sockets activated. Use info log level to see the reason.') - - def server_close(self): - """Override SocketServer.TCPServer.server_close to enable multiple - sockets close. - """ - - for socketinfo in self._sockets: - socket_, addrinfo = socketinfo - self._logger.info('Close on: %r', addrinfo) - socket_.close() - - def fileno(self): - """Override SocketServer.TCPServer.fileno.""" - - self._logger.critical('Not supported: fileno') - return self._sockets[0][0].fileno() - - def handle_error(self, rquest, client_address): - """Override SocketServer.handle_error.""" - - self._logger.error( - 'Exception in processing request from: %r\n%s', - client_address, - util.get_stack_trace()) - # Note: client_address is a tuple. - - def get_request(self): - """Override TCPServer.get_request to wrap OpenSSL.SSL.Connection - object with _StandaloneSSLConnection to provide makefile method. We - cannot substitute OpenSSL.SSL.Connection.makefile since it's readonly - attribute. - """ - - accepted_socket, client_address = self.socket.accept() - if self.websocket_server_options.use_tls and _HAS_OPEN_SSL: - accepted_socket = _StandaloneSSLConnection(accepted_socket) - return accepted_socket, client_address - - def serve_forever(self, poll_interval=0.5): - """Override SocketServer.BaseServer.serve_forever.""" - - self.__ws_serving = True - self.__ws_is_shut_down.clear() - handle_request = self.handle_request - if hasattr(self, '_handle_request_noblock'): - handle_request = self._handle_request_noblock - else: - self._logger.warning('Fallback to blocking request handler') - try: - while self.__ws_serving: - r, w, e = select.select( - [socket_[0] for socket_ in self._sockets], - [], [], poll_interval) - for socket_ in r: - self.socket = socket_ - handle_request() - self.socket = None - finally: - self.__ws_is_shut_down.set() - - def shutdown(self): - """Override SocketServer.BaseServer.shutdown.""" - - self.__ws_serving = False - self.__ws_is_shut_down.wait() - - -class WebSocketRequestHandler(CGIHTTPServer.CGIHTTPRequestHandler): - """CGIHTTPRequestHandler specialized for WebSocket.""" - - # Use httplib.HTTPMessage instead of mimetools.Message. - MessageClass = httplib.HTTPMessage - - def setup(self): - """Override SocketServer.StreamRequestHandler.setup to wrap rfile - with MemorizingFile. - - This method will be called by BaseRequestHandler's constructor - before calling BaseHTTPRequestHandler.handle. - BaseHTTPRequestHandler.handle will call - BaseHTTPRequestHandler.handle_one_request and it will call - WebSocketRequestHandler.parse_request. - """ - - # Call superclass's setup to prepare rfile, wfile, etc. See setup - # definition on the root class SocketServer.StreamRequestHandler to - # understand what this does. - CGIHTTPServer.CGIHTTPRequestHandler.setup(self) - - self.rfile = memorizingfile.MemorizingFile( - self.rfile, - max_memorized_lines=_MAX_MEMORIZED_LINES) - - def __init__(self, request, client_address, server): - self._logger = util.get_class_logger(self) - - self._options = server.websocket_server_options - - # Overrides CGIHTTPServerRequestHandler.cgi_directories. - self.cgi_directories = self._options.cgi_directories - # Replace CGIHTTPRequestHandler.is_executable method. - if self._options.is_executable_method is not None: - self.is_executable = self._options.is_executable_method - - # OWN MODIFICATION - # This actually calls BaseRequestHandler.__init__. - try: - CGIHTTPServer.CGIHTTPRequestHandler.__init__( - self, request, client_address, server) - except socket.error, e: - # Broken pipe, let it pass - if e.errno != 32: - raise - self._logger.debug("WS: Broken pipe") - - - - def parse_request(self): - """Override BaseHTTPServer.BaseHTTPRequestHandler.parse_request. - - Return True to continue processing for HTTP(S), False otherwise. - - See BaseHTTPRequestHandler.handle_one_request method which calls - this method to understand how the return value will be handled. - """ - - # We hook parse_request method, but also call the original - # CGIHTTPRequestHandler.parse_request since when we return False, - # CGIHTTPRequestHandler.handle_one_request continues processing and - # it needs variables set by CGIHTTPRequestHandler.parse_request. - # - # Variables set by this method will be also used by WebSocket request - # handling (self.path, self.command, self.requestline, etc. See also - # how _StandaloneRequest's members are implemented using these - # attributes). - if not CGIHTTPServer.CGIHTTPRequestHandler.parse_request(self): - return False - - if self._options.use_basic_auth: - auth = self.headers.getheader('Authorization') - if auth != self._options.basic_auth_credential: - self.send_response(401) - self.send_header('WWW-Authenticate', - 'Basic realm="Pywebsocket"') - self.end_headers() - self._logger.info('Request basic authentication') - return True - - host, port, resource = http_header_util.parse_uri(self.path) - if resource is None: - self._logger.info('Invalid URI: %r', self.path) - self._logger.info('Fallback to CGIHTTPRequestHandler') - return True - server_options = self.server.websocket_server_options - if host is not None: - validation_host = server_options.validation_host - if validation_host is not None and host != validation_host: - self._logger.info('Invalid host: %r (expected: %r)', - host, - validation_host) - self._logger.info('Fallback to CGIHTTPRequestHandler') - return True - if port is not None: - validation_port = server_options.validation_port - if validation_port is not None and port != validation_port: - self._logger.info('Invalid port: %r (expected: %r)', - port, - validation_port) - self._logger.info('Fallback to CGIHTTPRequestHandler') - return True - self.path = resource - - request = _StandaloneRequest(self, self._options.use_tls) - - try: - # Fallback to default http handler for request paths for which - # we don't have request handlers. - if not self._options.dispatcher.get_handler_suite(self.path): - self._logger.info('No handler for resource: %r', - self.path) - self._logger.info('Fallback to CGIHTTPRequestHandler') - return True - except dispatch.DispatchException, e: - self._logger.info('%s', e) - self.send_error(e.status) - return False - - # If any Exceptions without except clause setup (including - # DispatchException) is raised below this point, it will be caught - # and logged by WebSocketServer. - - try: - try: - handshake.do_handshake( - request, - self._options.dispatcher, - allowDraft75=self._options.allow_draft75, - strict=self._options.strict) - except handshake.VersionException, e: - self._logger.info('%s', e) - self.send_response(common.HTTP_STATUS_BAD_REQUEST) - self.send_header(common.SEC_WEBSOCKET_VERSION_HEADER, - e.supported_versions) - self.end_headers() - return False - except handshake.HandshakeException, e: - # Handshake for ws(s) failed. - self._logger.info('%s', e) - self.send_error(e.status) - return False - - request._dispatcher = self._options.dispatcher - self._options.dispatcher.transfer_data(request) - except handshake.AbortedByUserException, e: - self._logger.info('%s', e) - return False - - def log_request(self, code='-', size='-'): - """Override BaseHTTPServer.log_request.""" - - self._logger.info('"%s" %s %s', - self.requestline, str(code), str(size)) - - def log_error(self, *args): - """Override BaseHTTPServer.log_error.""" - - # Despite the name, this method is for warnings than for errors. - # For example, HTTP status code is logged by this method. - self._logger.warning('%s - %s', - self.address_string(), - args[0] % args[1:]) - - def is_cgi(self): - """Test whether self.path corresponds to a CGI script. - - Add extra check that self.path doesn't contains .. - Also check if the file is a executable file or not. - If the file is not executable, it is handled as static file or dir - rather than a CGI script. - """ - - if CGIHTTPServer.CGIHTTPRequestHandler.is_cgi(self): - if '..' in self.path: - return False - # strip query parameter from request path - resource_name = self.path.split('?', 2)[0] - # convert resource_name into real path name in filesystem. - scriptfile = self.translate_path(resource_name) - if not os.path.isfile(scriptfile): - return False - if not self.is_executable(scriptfile): - return False - return True - return False - - -def _get_logger_from_class(c): - return logging.getLogger('%s.%s' % (c.__module__, c.__name__)) - - -def _configure_logging(options): - logging.addLevelName(common.LOGLEVEL_FINE, 'FINE') - - logger = logging.getLogger() - logger.setLevel(logging.getLevelName(options.log_level.upper())) - if options.log_file: - handler = logging.handlers.RotatingFileHandler( - options.log_file, 'a', options.log_max, options.log_count) - else: - handler = logging.StreamHandler() - formatter = logging.Formatter( - '[%(asctime)s] [%(levelname)s] %(name)s: %(message)s') - handler.setFormatter(formatter) - logger.addHandler(handler) - - deflate_log_level_name = logging.getLevelName( - options.deflate_log_level.upper()) - _get_logger_from_class(util._Deflater).setLevel( - deflate_log_level_name) - _get_logger_from_class(util._Inflater).setLevel( - deflate_log_level_name) - -class DefaultOptions: - server_host = '' - port = common.DEFAULT_WEB_SOCKET_PORT - use_tls = False - private_key = '' - certificate = '' - ca_certificate = '' - dispatcher = None - request_queue_size = _DEFAULT_REQUEST_QUEUE_SIZE - use_basic_auth = False - - allow_draft75 = False - strict = False - validation_host = None - validation_port = None - cgi_directories = '' - is_executable_method = False - -def _main(args=None): - """You can call this function from your own program, but please note that - this function has some side-effects that might affect your program. For - example, util.wrap_popen3_for_win use in this method replaces implementation - of os.popen3. - """ - - options, args = _parse_args_and_config(args=args) - - os.chdir(options.document_root) - - _configure_logging(options) - - # TODO(tyoshino): Clean up initialization of CGI related values. Move some - # of code here to WebSocketRequestHandler class if it's better. - options.cgi_directories = [] - options.is_executable_method = None - if options.cgi_paths: - options.cgi_directories = options.cgi_paths.split(',') - if sys.platform in ('cygwin', 'win32'): - cygwin_path = None - # For Win32 Python, it is expected that CYGWIN_PATH - # is set to a directory of cygwin binaries. - # For example, websocket_server.py in Chromium sets CYGWIN_PATH to - # full path of third_party/cygwin/bin. - if 'CYGWIN_PATH' in os.environ: - cygwin_path = os.environ['CYGWIN_PATH'] - util.wrap_popen3_for_win(cygwin_path) - - def __check_script(scriptpath): - return util.get_script_interp(scriptpath, cygwin_path) - - options.is_executable_method = __check_script - - if options.use_tls: - if not (_HAS_SSL or _HAS_OPEN_SSL): - logging.critical('TLS support requires ssl or pyOpenSSL module.') - sys.exit(1) - if not options.private_key or not options.certificate: - logging.critical( - 'To use TLS, specify private_key and certificate.') - sys.exit(1) - - if options.tls_client_auth: - if not options.use_tls: - logging.critical('TLS must be enabled for client authentication.') - sys.exit(1) - if not _HAS_SSL: - logging.critical('Client authentication requires ssl module.') - - if not options.scan_dir: - options.scan_dir = options.websock_handlers - - if options.use_basic_auth: - options.basic_auth_credential = 'Basic ' + base64.b64encode( - options.basic_auth_credential) - - try: - if options.thread_monitor_interval_in_sec > 0: - # Run a thread monitor to show the status of server threads for - # debugging. - ThreadMonitor(options.thread_monitor_interval_in_sec).start() - - server = WebSocketServer(options) - server.serve_forever() - except Exception, e: - logging.critical('mod_pywebsocket: %s' % e) - logging.critical('mod_pywebsocket: %s' % util.get_stack_trace()) - sys.exit(1) - - -if __name__ == '__main__': - _main(sys.argv[1:]) - - -# vi:sts=4 sw=4 et diff --git a/module/remote/wsbackend/__init__.py b/module/remote/wsbackend/__init__.py deleted file mode 100644 index de6d13128..000000000 --- a/module/remote/wsbackend/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -__author__ = 'christian' -
\ No newline at end of file |