diff options
Diffstat (limited to 'module/remote')
-rw-r--r-- | module/remote/ClickAndLoadBackend.py | 170 | ||||
-rw-r--r-- | module/remote/RemoteManager.py | 20 | ||||
-rw-r--r-- | module/remote/SocketBackend.py | 25 | ||||
-rw-r--r-- | module/remote/XMLRPCBackend.py | 40 | ||||
-rw-r--r-- | module/remote/__init__.py | 3 | ||||
-rw-r--r-- | module/remote/socketbackend/__init__.py | 2 | ||||
-rw-r--r-- | module/remote/socketbackend/create_ttypes.py | 87 | ||||
-rw-r--r-- | module/remote/socketbackend/ttypes.py | 352 |
8 files changed, 657 insertions, 42 deletions
diff --git a/module/remote/ClickAndLoadBackend.py b/module/remote/ClickAndLoadBackend.py new file mode 100644 index 000000000..ad8031587 --- /dev/null +++ b/module/remote/ClickAndLoadBackend.py @@ -0,0 +1,170 @@ +# -*- 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/RemoteManager.py b/module/remote/RemoteManager.py index 2ac26a677..6caedad90 100644 --- a/module/remote/RemoteManager.py +++ b/module/remote/RemoteManager.py @@ -24,14 +24,19 @@ class BackendBase(Thread): 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 @@ -42,14 +47,27 @@ class BackendBase(Thread): 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 = ["ThriftBackend"] + available = [] def __init__(self, core): self.core = core self.backends = [] + if self.core.remote: + self.available.append("ThriftBackend") + else: + self.available.append("SocketBackend") + + def startBackends(self): host = self.core.config["remote"]["listenaddr"] port = self.core.config["remote"]["port"] diff --git a/module/remote/SocketBackend.py b/module/remote/SocketBackend.py new file mode 100644 index 000000000..1a157cf1d --- /dev/null +++ b/module/remote/SocketBackend.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +import SocketServer + +from RemoteManager import BackendBase + +class RequestHandler(SocketServer.BaseRequestHandler): + + def setup(self): + pass + + def handle(self): + + print self.request.recv(1024) + + + +class SocketBackend(BackendBase): + + def setup(self, host, port): + #local only + self.server = SocketServer.ThreadingTCPServer(("localhost", port), RequestHandler) + + def serve(self): + self.server.serve_forever() diff --git a/module/remote/XMLRPCBackend.py b/module/remote/XMLRPCBackend.py deleted file mode 100644 index 003dc29ea..000000000 --- a/module/remote/XMLRPCBackend.py +++ /dev/null @@ -1,40 +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, RaNaN -""" -from os.path import exists - -import module.lib.SecureXMLRPCServer as Server -from module.remote.RemoteManager import BackendBase - -class XMLRPCBackend(BackendBase): - def setup(self, host, port): - server_addr = (host, port) - if self.core.config['ssl']['activated']: - if exists(self.core.config['ssl']['cert']) and exists(self.core.config['ssl']['key']): - self.core.log.info(_("Using SSL XMLRPCBackend")) - self.server = Server.SecureXMLRPCServer(server_addr, self.core.config['ssl']['cert'], - self.core.config['ssl']['key'], self.checkAuth) - else: - self.core.log.warning(_("SSL Certificates not found, fallback to auth XMLRPC server")) - self.server = Server.AuthXMLRPCServer(server_addr, self.checkAuth) - else: - self.server = Server.AuthXMLRPCServer(server_addr, self.checkAuth) - - self.server.register_instance(self.core.api) - - def serve(self): - self.server.serve_forever() diff --git a/module/remote/__init__.py b/module/remote/__init__.py index 8d1c8b69c..9298f5337 100644 --- a/module/remote/__init__.py +++ b/module/remote/__init__.py @@ -1 +1,2 @@ - +# -*- coding: utf-8 -*- +activated = True diff --git a/module/remote/socketbackend/__init__.py b/module/remote/socketbackend/__init__.py new file mode 100644 index 000000000..de6d13128 --- /dev/null +++ b/module/remote/socketbackend/__init__.py @@ -0,0 +1,2 @@ +__author__ = 'christian' +
\ No newline at end of file diff --git a/module/remote/socketbackend/create_ttypes.py b/module/remote/socketbackend/create_ttypes.py new file mode 100644 index 000000000..db27bd02f --- /dev/null +++ b/module/remote/socketbackend/create_ttypes.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys +from os.path import abspath, dirname, join + +path = dirname(abspath(__file__)) +module = join(path, "..", "..") + +sys.path.append(join(module, "lib")) +sys.path.append(join(module, "remote")) + +from thriftbackend.thriftgen.pyload import ttypes +from thriftbackend.thriftgen.pyload.Pyload import Iface + + +def main(): + + enums = [] + classes = [] + + print "generating lightweight ttypes.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, "ttypes.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): + __slots__ = [] + +""") + + ## generate enums + for enum in enums: + name = enum.__name__ + f.write("class %s:\n" % name) + + for attr in dir(enum): + if attr.startswith("_") or attr in ("read", "write"): continue + + f.write("\t%s = %s\n" % (attr, getattr(enum, attr))) + + f.write("\n") + + for klass in classes: + name = klass.__name__ + base = "BaseException" if issubclass(klass, ttypes.TExceptionBase) else "BaseObject" + f.write("class %s(%s):\n" % (name, base)) + f.write("\t__slots__ = %s\n\n" % klass.__slots__) + + #create init + args = ["self"] + ["%s=None" % x for x in klass.__slots__] + + f.write("\tdef init(%s):\n" % ", ".join(args)) + for attr in klass.__slots__: + f.write("\t\tself.%s = %s\n" % (attr, attr)) + + f.write("\n") + + f.write("class Iface:\n") + + for name in dir(Iface): + if name.startswith("_"): continue + f.write("\tdef %s():\n\t\tpass\n" % name) + + f.write("\n") + + f.close() + +if __name__ == "__main__": + main()
\ No newline at end of file diff --git a/module/remote/socketbackend/ttypes.py b/module/remote/socketbackend/ttypes.py new file mode 100644 index 000000000..30a7d3adc --- /dev/null +++ b/module/remote/socketbackend/ttypes.py @@ -0,0 +1,352 @@ +#!/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__ = [] + +class Destination: + Collector = 0 + Queue = 1 + +class DownloadStatus: + Aborted = 9 + Custom = 11 + Decrypting = 10 + Downloading = 12 + Failed = 8 + Finished = 0 + Offline = 1 + Online = 2 + Processing = 13 + Queued = 3 + Skipped = 4 + Starting = 7 + TempOffline = 6 + Unknown = 14 + Waiting = 5 + +class ElementType: + File = 1 + Package = 0 + +class AccountInfo(BaseObject): + __slots__ = ['validuntil', 'login', 'options', 'valid', 'trafficleft', 'maxtraffic', 'premium', 'type'] + + def init(self, validuntil=None, login=None, options=None, valid=None, trafficleft=None, maxtraffic=None, premium=None, type=None): + self.validuntil = validuntil + self.login = login + self.options = options + self.valid = valid + self.trafficleft = trafficleft + self.maxtraffic = maxtraffic + self.premium = premium + self.type = type + +class CaptchaTask(BaseObject): + __slots__ = ['tid', 'data', 'type', 'resultType'] + + def init(self, tid=None, data=None, type=None, resultType=None): + self.tid = tid + self.data = data + self.type = type + self.resultType = resultType + +class ConfigItem(BaseObject): + __slots__ = ['name', 'description', 'value', 'type'] + + def init(self, name=None, description=None, value=None, type=None): + self.name = name + self.description = description + self.value = value + self.type = type + +class ConfigSection(BaseObject): + __slots__ = ['name', 'description', 'items', 'outline'] + + def init(self, name=None, description=None, items=None, outline=None): + self.name = name + self.description = description + self.items = items + self.outline = outline + +class DownloadInfo(BaseObject): + __slots__ = ['fid', 'name', 'speed', 'eta', 'format_eta', 'bleft', 'size', 'format_size', 'percent', 'status', 'statusmsg', 'format_wait', 'wait_until', 'packageID', 'packageName', 'plugin'] + + def init(self, fid=None, name=None, speed=None, eta=None, format_eta=None, bleft=None, size=None, format_size=None, percent=None, status=None, statusmsg=None, format_wait=None, wait_until=None, packageID=None, packageName=None, plugin=None): + self.fid = fid + self.name = name + self.speed = speed + self.eta = eta + self.format_eta = format_eta + self.bleft = bleft + self.size = size + self.format_size = format_size + self.percent = percent + self.status = status + self.statusmsg = statusmsg + self.format_wait = format_wait + self.wait_until = wait_until + self.packageID = packageID + self.packageName = packageName + self.plugin = plugin + +class EventInfo(BaseObject): + __slots__ = ['eventname', 'id', 'type', 'destination'] + + def init(self, eventname=None, id=None, type=None, destination=None): + self.eventname = eventname + self.id = id + self.type = type + self.destination = destination + +class FileData(BaseObject): + __slots__ = ['fid', 'url', 'name', 'plugin', 'size', 'format_size', 'status', 'statusmsg', 'packageID', 'error', 'order'] + + def init(self, fid=None, url=None, name=None, plugin=None, size=None, format_size=None, status=None, statusmsg=None, packageID=None, error=None, order=None): + self.fid = fid + self.url = url + self.name = name + self.plugin = plugin + self.size = size + self.format_size = format_size + self.status = status + self.statusmsg = statusmsg + self.packageID = packageID + self.error = error + self.order = order + +class FileDoesNotExists(BaseException): + __slots__ = ['fid'] + + def init(self, fid=None): + self.fid = fid + +class OnlineCheck(BaseObject): + __slots__ = ['rid', 'data'] + + def init(self, rid=None, data=None): + self.rid = rid + self.data = data + +class OnlineStatus(BaseObject): + __slots__ = ['name', 'plugin', 'packagename', 'status', 'size'] + + def init(self, name=None, plugin=None, packagename=None, status=None, size=None): + self.name = name + self.plugin = plugin + self.packagename = packagename + self.status = status + self.size = size + +class PackageData(BaseObject): + __slots__ = ['pid', 'name', 'folder', 'site', 'password', 'dest', 'order', 'linksdone', 'sizedone', 'sizetotal', 'linkstotal', 'links', 'fids'] + + def init(self, pid=None, name=None, folder=None, site=None, password=None, dest=None, order=None, linksdone=None, sizedone=None, sizetotal=None, linkstotal=None, links=None, fids=None): + self.pid = pid + self.name = name + self.folder = folder + self.site = site + self.password = password + self.dest = dest + self.order = order + self.linksdone = linksdone + self.sizedone = sizedone + self.sizetotal = sizetotal + self.linkstotal = linkstotal + self.links = links + self.fids = fids + +class PackageDoesNotExists(BaseException): + __slots__ = ['pid'] + + def init(self, pid=None): + self.pid = pid + +class ServerStatus(BaseObject): + __slots__ = ['pause', 'active', 'queue', 'total', 'speed', 'download', 'reconnect'] + + def init(self, pause=None, active=None, queue=None, total=None, speed=None, download=None, reconnect=None): + self.pause = pause + self.active = active + self.queue = queue + self.total = total + self.speed = speed + self.download = download + self.reconnect = reconnect + +class ServiceCall(BaseObject): + __slots__ = ['plugin', 'func', 'arguments', 'parseArguments'] + + def init(self, plugin=None, func=None, arguments=None, parseArguments=None): + self.plugin = plugin + self.func = func + self.arguments = arguments + self.parseArguments = parseArguments + +class ServiceDoesNotExists(BaseException): + __slots__ = ['plugin', 'func'] + + def init(self, plugin=None, func=None): + self.plugin = plugin + self.func = func + +class ServiceException(BaseException): + __slots__ = ['msg'] + + def init(self, msg=None): + self.msg = msg + +class UserData(BaseObject): + __slots__ = ['name', 'email', 'role', 'permission', 'templateName'] + + def init(self, name=None, email=None, role=None, permission=None, templateName=None): + self.name = name + self.email = email + self.role = role + self.permission = permission + self.templateName = templateName + +class Iface: + def addFiles(): + pass + def addPackage(): + pass + def call(): + pass + def checkOnlineStatus(): + pass + def checkOnlineStatusContainer(): + pass + def checkURLs(): + pass + def deleteFiles(): + pass + def deleteFinished(): + pass + def deletePackages(): + pass + def freeSpace(): + pass + def generateAndAddPackages(): + pass + def generatePackages(): + pass + def getAccountTypes(): + pass + def getAccounts(): + pass + def getAllInfo(): + pass + def getAllUserData(): + pass + def getCaptchaTask(): + pass + def getCaptchaTaskStatus(): + pass + def getCollector(): + pass + def getCollectorData(): + pass + def getConfig(): + pass + def getConfigValue(): + pass + def getEvents(): + pass + def getFileData(): + pass + def getFileOrder(): + pass + def getInfoByPlugin(): + pass + def getLog(): + pass + def getPackageData(): + pass + def getPackageInfo(): + pass + def getPackageOrder(): + pass + def getPluginConfig(): + pass + def getQueue(): + pass + def getQueueData(): + pass + def getServerVersion(): + pass + def getServices(): + pass + def getUserData(): + pass + def hasService(): + pass + def isCaptchaWaiting(): + pass + def isTimeDownload(): + pass + def isTimeReconnect(): + pass + def kill(): + pass + def login(): + pass + def moveFiles(): + pass + def movePackage(): + pass + def orderFile(): + pass + def orderPackage(): + pass + def parseURLs(): + pass + def pauseServer(): + pass + def pollResults(): + pass + def pullFromQueue(): + pass + def pushToQueue(): + pass + def recheckPackage(): + pass + def removeAccount(): + pass + def restart(): + pass + def restartFailed(): + pass + def restartFile(): + pass + def restartPackage(): + pass + def setCaptchaResult(): + pass + def setConfigValue(): + pass + def setPackageData(): + pass + def setPackageName(): + pass + def statusDownloads(): + pass + def statusServer(): + pass + def stopAllDownloads(): + pass + def stopDownloads(): + pass + def togglePause(): + pass + def toggleReconnect(): + pass + def unpauseServer(): + pass + def updateAccount(): + pass + def uploadContainer(): + pass + |