summaryrefslogtreecommitdiffstats
path: root/module/remote
diff options
context:
space:
mode:
Diffstat (limited to 'module/remote')
-rw-r--r--module/remote/ClickAndLoadBackend.py170
-rw-r--r--module/remote/JSONClient.py56
-rw-r--r--module/remote/RemoteManager.py89
-rw-r--r--module/remote/WSClient.py59
-rw-r--r--module/remote/WebSocketBackend.py49
-rw-r--r--module/remote/__init__.py0
-rw-r--r--module/remote/apitypes.py536
-rw-r--r--module/remote/apitypes_debug.py135
-rw-r--r--module/remote/create_apitypes.py180
-rw-r--r--module/remote/create_jstypes.py36
-rw-r--r--module/remote/json_converter.py64
-rw-r--r--module/remote/pyload.thrift538
-rw-r--r--module/remote/ttypes.py534
-rw-r--r--module/remote/wsbackend/AbstractHandler.py133
-rw-r--r--module/remote/wsbackend/ApiHandler.py81
-rw-r--r--module/remote/wsbackend/AsyncHandler.py167
-rw-r--r--module/remote/wsbackend/Dispatcher.py31
-rw-r--r--module/remote/wsbackend/Server.py733
-rw-r--r--module/remote/wsbackend/__init__.py2
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