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..0d6192a5a --- /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): +\t__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 = "Exception" 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(self):\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..527dff767 --- /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(Exception): +	__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(Exception): +	__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(Exception): +	__slots__ = ['plugin', 'func'] + +	def init(self, plugin=None, func=None): +		self.plugin = plugin +		self.func = func + +class ServiceException(Exception): +	__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(self): +		pass +	def addPackage(self): +		pass +	def call(self): +		pass +	def checkOnlineStatus(self): +		pass +	def checkOnlineStatusContainer(self): +		pass +	def checkURLs(self): +		pass +	def deleteFiles(self): +		pass +	def deleteFinished(self): +		pass +	def deletePackages(self): +		pass +	def freeSpace(self): +		pass +	def generateAndAddPackages(self): +		pass +	def generatePackages(self): +		pass +	def getAccountTypes(self): +		pass +	def getAccounts(self): +		pass +	def getAllInfo(self): +		pass +	def getAllUserData(self): +		pass +	def getCaptchaTask(self): +		pass +	def getCaptchaTaskStatus(self): +		pass +	def getCollector(self): +		pass +	def getCollectorData(self): +		pass +	def getConfig(self): +		pass +	def getConfigValue(self): +		pass +	def getEvents(self): +		pass +	def getFileData(self): +		pass +	def getFileOrder(self): +		pass +	def getInfoByPlugin(self): +		pass +	def getLog(self): +		pass +	def getPackageData(self): +		pass +	def getPackageInfo(self): +		pass +	def getPackageOrder(self): +		pass +	def getPluginConfig(self): +		pass +	def getQueue(self): +		pass +	def getQueueData(self): +		pass +	def getServerVersion(self): +		pass +	def getServices(self): +		pass +	def getUserData(self): +		pass +	def hasService(self): +		pass +	def isCaptchaWaiting(self): +		pass +	def isTimeDownload(self): +		pass +	def isTimeReconnect(self): +		pass +	def kill(self): +		pass +	def login(self): +		pass +	def moveFiles(self): +		pass +	def movePackage(self): +		pass +	def orderFile(self): +		pass +	def orderPackage(self): +		pass +	def parseURLs(self): +		pass +	def pauseServer(self): +		pass +	def pollResults(self): +		pass +	def pullFromQueue(self): +		pass +	def pushToQueue(self): +		pass +	def recheckPackage(self): +		pass +	def removeAccount(self): +		pass +	def restart(self): +		pass +	def restartFailed(self): +		pass +	def restartFile(self): +		pass +	def restartPackage(self): +		pass +	def setCaptchaResult(self): +		pass +	def setConfigValue(self): +		pass +	def setPackageData(self): +		pass +	def setPackageName(self): +		pass +	def statusDownloads(self): +		pass +	def statusServer(self): +		pass +	def stopAllDownloads(self): +		pass +	def stopDownloads(self): +		pass +	def togglePause(self): +		pass +	def toggleReconnect(self): +		pass +	def unpauseServer(self): +		pass +	def updateAccount(self): +		pass +	def uploadContainer(self): +		pass + | 
