diff options
30 files changed, 334 insertions, 1267 deletions
| diff --git a/module/Api.py b/module/Api.py index 975b43709..5328fb617 100644 --- a/module/Api.py +++ b/module/Api.py @@ -49,11 +49,9 @@ class Api(Iface):          return f      def _convertConfigFormat(self, c): -        sections = [] +        sections = {}          for sectionName, sub in c.iteritems(): -            section = ConfigSection() -            section.name = sectionName -            section.description = sub["desc"] +            section = ConfigSection(sectionName, sub["desc"])              items = []              for key, data in sub.iteritems():                  if key == "desc": @@ -65,10 +63,10 @@ class Api(Iface):                  item.type = data["type"]                  items.append(item)              section.items = items -            sections.append(section) +            sections[sectionName] = section          return sections -    def getConfigValue(self, category, option, section): +    def getConfigValue(self, category, option, section="core"):          """Retrieve config value.          :param category: name of category, or plugin @@ -81,7 +79,7 @@ class Api(Iface):          elif section == "plugin":              return self.core.config.getPlugin(category, option) -    def setConfigValue(self, category, option, value, section): +    def setConfigValue(self, category, option, value, section="core"):          """Set new config value.          :param category: @@ -105,6 +103,13 @@ class Api(Iface):          """          return self._convertConfigFormat(self.core.config.config) +    def getConfigDict(self): +        """Retrieves complete config in dict format, not for RPC. + +        :return: dict +        """ +        return self.core.config.config +      def getPluginConfig(self):          """Retrieves complete config for all plugins. @@ -112,6 +117,14 @@ class Api(Iface):          """          return self._convertConfigFormat(self.core.config.plugin) +    def getPluginConfigDict(self): +        """Plugin config as dict, not for RPC. + +        :return: dict +        """ +        return self.core.config.plugin + +          def pauseServer(self):          """Pause server: Tt wont start any new downloads, but nothing gets aborted."""          self.core.threadManager.pause = True @@ -167,7 +180,7 @@ class Api(Iface):          """Untested"""          self.core.do_restart = True -    def getLog(self, offset): +    def getLog(self, offset=0):          """Returns most recent log entries.          :param offset: line offset @@ -639,14 +652,14 @@ class Api(Iface):          :return: list          """ -        return self.core.accountManager.getAccountInfos(False, False).keys() +        return self.core.accountManager.accounts.keys() -    def updateAccounts(self, data): +    def updateAccount(self, plugin, account, password=None, options={}):          """Changes pw/options for specific account.          :param data: `AccountData`          """ -        self.core.accountManager.updateAccount(data.type, data.login, data.password, data.options) +        self.core.accountManager.updateAccount(plugin, account, password, options)      def removeAccount(self, plugin, account):          """Remove account from pyload. @@ -689,6 +702,10 @@ class Api(Iface):          return self.checkAuth(username, password) +    def getAllUserData(self): +        """returns all known user and info""" +        return self.core.db.getAllUserData() +      def getServices(self):          """ A dict of available services, these can be defined by hook plugins. @@ -749,4 +766,12 @@ class Api(Iface):          if info.has_key(plugin):              return info[plugin]          else: -            return {}
\ No newline at end of file +            return {} + +    def changePassword(self, user, oldpw, newpw): +        """ changes password for specific user """ +        return self.core.db.changePassword(user, oldpw, newpw) + +    def setUserPermission(self, user, permission, role): +        self.core.db.setPermission(user, permission) +        self.core.db.setRole(user, role)
\ No newline at end of file diff --git a/module/PluginThread.py b/module/PluginThread.py index 228ba4e6a..ff5014f63 100644 --- a/module/PluginThread.py +++ b/module/PluginThread.py @@ -46,7 +46,7 @@ class PluginThread(Thread):      def writeDebugReport(self, pyfile): -        dump = "pyLoad %s Debug Report of %s \n\nTRACEBACK:\n %s \n\nFRAMESTACK:\n" % (self.m.core.server_methods.get_server_version(), pyfile.pluginname, format_exc()) +        dump = "pyLoad %s Debug Report of %s \n\nTRACEBACK:\n %s \n\nFRAMESTACK:\n" % (self.m.core.api.getServerVersion(), pyfile.pluginname, format_exc())          tb = exc_info()[2]          stack = [] diff --git a/module/ThreadManager.py b/module/ThreadManager.py index adf17ee8c..a0025879c 100644 --- a/module/ThreadManager.py +++ b/module/ThreadManager.py @@ -114,7 +114,7 @@ class ThreadManager:      def tryReconnect(self):          """checks if reconnect needed""" -        if not (self.core.config["reconnect"]["activated"] and self.core.server_methods.is_time_reconnect()): +        if not (self.core.config["reconnect"]["activated"] and self.core.api.isTimeReconnect()):              return False          active = [x.active.plugin.wantReconnect and x.active.plugin.waiting for x in self.threads if x.active] @@ -209,7 +209,7 @@ class ThreadManager:      def assignJob(self):          """assing a job to a thread if possible""" -        if self.pause or not self.core.server_methods.is_time_download(): return +        if self.pause or not self.core.api.isTimeDownload(): return          #if self.downloaded > 20:          #    if not self.cleanPyCurl(): return diff --git a/module/common/APIExerciser.py b/module/common/APIExerciser.py index f645f12df..b9e67d824 100644 --- a/module/common/APIExerciser.py +++ b/module/common/APIExerciser.py @@ -24,16 +24,19 @@ def createURLs():  AVOID = (0,3,8)  class APIExerciser(Thread): -    """ tests api randomly """ - -    def __init__(self, core): +    def __init__(self, core, thrift=False):          Thread.__init__(self)          self.setDaemon(True)          self.core = core -        self.methods = core.server_methods          self.count = 0 #number of methods          self.time = time() +        if thrift: +            self.api = ThriftClient() +            self.api.login("user", "pw") +        else: +            self.api = core.api +          self.start()      def run(self): @@ -60,89 +63,8 @@ class APIExerciser(Thread):                  #sleep(random() / 500)      def testAPI(self): -        m = ["status_downloads", "status_server", "add_package", "get_package_data", "get_file_data", "del_links", -             "del_packages", -             "get_queue", "get_collector", "get_queue_info", "get_collector_info", "is_captcha_waiting"] - -        method = choice(m) -        #print "Testing:", method - -        if hasattr(self, method): -            res = getattr(self, method)() -        else: -            res = getattr(self.methods, method)() - -        self.count += 1 - -        #print res - -    def add_package(self): -        name = "".join(sample(string.ascii_letters, 10)) -        urls = createURLs() - -        self.methods.add_package(name, urls, 1) - - -    def del_links(self): -        info = self.methods.get_queue() -        if not info: return - -        pid = choice(info.keys()) -        pack = info[pid] -        links = pack["links"] -        #filter links which are not queued, finished or failed -        fids = filter(lambda x: links[x]["status"] not in AVOID, links.keys()) - -        if len(fids): -            fids = sample(fids, randint(1, max(len(fids) / 2, 1))) -            self.methods.del_links(fids) - - -    def del_packages(self): -        info = self.methods.get_queue_info() -        if not info: return - -        pids = info.keys() -        if len(pids): -            pids = sample(pids, randint(1, max(len(pids) / 2, 1))) -            filtered = [] - -            for p in pids: -                info = self.methods.get_package_data(p) -                append = True -                for link in info["links"].itervalues(): -                    if link["status"] not in AVOID: -                        append = False -                        break - -                if append: filtered.append(p) - -            self.methods.del_packages(filtered) - -    def get_file_data(self): -        info = self.methods.get_queue() -        if info: -            p = info[choice(info.keys())] -            if p["links"]: -                self.methods.get_file_data(choice(p["links"].keys())) - -    def get_package_data(self): -        info = self.methods.get_queue_info() -        if info: -            self.methods.get_package_data(choice(info.keys())) - - -class ThriftExerciser(APIExerciser): -    def __init__(self, core): -        self.thrift = ThriftClient() -        self.thrift.login("user", "pw") - -        APIExerciser.__init__(self, core) - -    def testAPI(self):          m = ["statusDownloads", "statusServer", "addPackage", "getPackageData", "getFileData", "deleteFiles", -             "deletePackages", -             "getQueue", "getCollector", "getQueueData", "getCollectorData", "isCaptchaWaiting"] +             "deletePackages", "getQueue", "getCollector", "getQueueData", "getCollectorData", "isCaptchaWaiting"]          method = choice(m)          #print "Testing:", method @@ -150,7 +72,7 @@ class ThriftExerciser(APIExerciser):          if hasattr(self, method):              res = getattr(self, method)()          else: -            res = getattr(self.thrift, method)() +            res = getattr(self.api, method)()          self.count += 1 @@ -160,11 +82,11 @@ class ThriftExerciser(APIExerciser):          name = "".join(sample(string.ascii_letters, 10))          urls = createURLs() -        self.thrift.addPackage(name, urls, 0) +        self.api.addPackage(name, urls, 0)      def deleteFiles(self): -        info = self.thrift.getQueueData() +        info = self.api.getQueueData()          if not info: return          pack = choice(info) @@ -172,26 +94,26 @@ class ThriftExerciser(APIExerciser):          if len(fids):              fids = [f.fid for f in sample(fids, randint(1, max(len(fids) / 2, 1)))] -            self.thrift.deleteFiles(fids) +            self.api.deleteFiles(fids)      def deletePackages(self): -        info = self.thrift.getQueue() +        info = self.api.getQueue()          if not info: return          pids = [p.pid for p in info]          if len(pids):              pids = sample(pids, randint(1, max(len(pids) / 2, 1))) -            self.thrift.deletePackages(pids) +            self.api.deletePackages(pids)      def getFileData(self): -        info = self.thrift.getQueueData() +        info = self.api.getQueueData()          if info:              p = choice(info)              if p.links: -                self.thrift.getFileData(choice(p.links).fid) +                self.api.getFileData(choice(p.links).fid)      def getPackageData(self): -        info = self.thrift.getQueue() +        info = self.api.getQueue()          if info: -            self.thrift.getPackageData(choice(info).pid)
\ No newline at end of file +            self.api.getPackageData(choice(info).pid)
\ No newline at end of file diff --git a/module/plugins/Crypter.py b/module/plugins/Crypter.py index 7ba739dc4..9c56eb91b 100644 --- a/module/plugins/Crypter.py +++ b/module/plugins/Crypter.py @@ -64,8 +64,8 @@ class Crypter(Plugin):              links = [x.decode("utf-8") for x in pack[1]] -            pid = self.core.server_methods.add_package(pack[0], links, self.pyfile.package().queue) +            pid = self.core.api.addPackage(pack[0], links, self.pyfile.package().queue)              if self.pyfile.package().password: -                self.core.server_methods.set_package_data(pid, {"password": self.pyfile.package().password}) +                self.core.api.setPackageData(pid, {"password": self.pyfile.package().password}) diff --git a/module/plugins/hooks/Ev0InFetcher.py b/module/plugins/hooks/Ev0InFetcher.py index f573d28a3..5eb4e09c1 100644 --- a/module/plugins/hooks/Ev0InFetcher.py +++ b/module/plugins/hooks/Ev0InFetcher.py @@ -75,7 +75,7 @@ class Ev0InFetcher(Hook, PluginStorage):                      links = self.filterLinks(item['description'].split("<br />"))                      packagename = item['title'].encode("utf-8")                      self.core.log.info("Ev0InFetcher: new episode '%s' (matched '%s')" % (packagename, show)) -                    self.core.server_methods.add_package(packagename, links, queue=(1 if self.getConfig("queue") else 0)) +                    self.core.api.addPackage(packagename, links, queue=(1 if self.getConfig("queue") else 0))                      self.setStorage("show_%s_lastfound" % show, int(mktime(item.date_parsed)))                      found = True          if not found: diff --git a/module/plugins/hooks/HotFolder.py b/module/plugins/hooks/HotFolder.py index 1e320b87c..ee1031ad5 100644 --- a/module/plugins/hooks/HotFolder.py +++ b/module/plugins/hooks/HotFolder.py @@ -68,7 +68,7 @@ class HotFolder(Hook):                  f.write(content)                  f.close() -                self.core.server_methods.add_package(f.name, [f.name], 1) +                self.core.api.addPackage(f.name, [f.name], 1)          for f in listdir(self.getConfig("folder")):              path = join(self.getConfig("folder"), f) @@ -80,6 +80,6 @@ class HotFolder(Hook):              move(path, newpath)              self.log.info(_("Added %s from HotFolder") % f) -            self.core.server_methods.add_package(f, [newpath], 1) +            self.core.api.addPackage(f, [newpath], 1)          
\ No newline at end of file diff --git a/module/plugins/hooks/IRCInterface.py b/module/plugins/hooks/IRCInterface.py index 8be84f863..ae0a51385 100644 --- a/module/plugins/hooks/IRCInterface.py +++ b/module/plugins/hooks/IRCInterface.py @@ -53,7 +53,8 @@ class IRCInterface(Thread, Hook):          Thread.__init__(self)          Hook.__init__(self, core, manager)          self.setDaemon(True) -        self.sm = core.server_methods +        #self.sm = core.server_methods +        self.api = core.api #todo, only use api      def coreReady(self):          self.new_package = {} diff --git a/module/plugins/hooks/UpdateManager.py b/module/plugins/hooks/UpdateManager.py index 10f50d1f0..dc8eafbb8 100644 --- a/module/plugins/hooks/UpdateManager.py +++ b/module/plugins/hooks/UpdateManager.py @@ -65,7 +65,7 @@ class UpdateManager(Hook):          """checks if an update is available"""          try: -            version_check = getURL("http://get.pyload.org/check/%s/" % self.core.server_methods.get_server_version()) +            version_check = getURL("http://get.pyload.org/check/%s/" % self.core.api.getServerVersion())              if version_check == "":                  return False              else: diff --git a/module/plugins/hoster/BasePlugin.py b/module/plugins/hoster/BasePlugin.py index 49bab50f1..4b55f0357 100644 --- a/module/plugins/hoster/BasePlugin.py +++ b/module/plugins/hoster/BasePlugin.py @@ -33,7 +33,7 @@ class BasePlugin(Hoster):  #        self.decryptCaptcha("http://localhost:9000/captcha")  #  #        if pyfile.url == "79": -#            self.core.server_methods.add_package("test", [str(i) for i in range(80)], 1) +#            self.core.api.addPackage("test", [str(i) for i in range(80)], 1)  #  #        return          if pyfile.url.startswith("http"): diff --git a/module/remote/XMLRPCBackend.py b/module/remote/XMLRPCBackend.py index 50b37f17b..003dc29ea 100644 --- a/module/remote/XMLRPCBackend.py +++ b/module/remote/XMLRPCBackend.py @@ -34,7 +34,7 @@ class XMLRPCBackend(BackendBase):          else:              self.server = Server.AuthXMLRPCServer(server_addr, self.checkAuth) -        self.server.register_instance(self.core.server_methods) +        self.server.register_instance(self.core.api)      def serve(self):          self.server.serve_forever() diff --git a/module/remote/thriftbackend/Handler.py b/module/remote/thriftbackend/Handler.py deleted file mode 100644 index 998ace06b..000000000 --- a/module/remote/thriftbackend/Handler.py +++ /dev/null @@ -1,568 +0,0 @@ -# -*- coding: utf-8 -*- - -from thriftgen.pyload.ttypes import * -from thriftgen.pyload.Pyload import Iface - -from module.PyFile import PyFile -from module.utils import freeSpace - -from base64 import standard_b64encode - -class Handler(Iface): -    def __init__(self, backend): -        self.backend = backend -        self.core = backend.core -        self.serverMethods = self.core.server_methods - - -    def _convertPyFile(self, p): -        f = FileData(p["id"], p["url"], p["name"], p["plugin"], p["size"], -                     p["format_size"], p["status"], p["statusmsg"], -                     p["package"], p["error"], p["order"], p["progress"]) -        return f - -    def _convertConfigFormat(self, c): -        sections = [] -        for sectionName, sub in c.iteritems(): -            section = ConfigSection() -            section.name = sectionName -            section.description = sub["desc"] -            items = [] -            for key, data in sub.iteritems(): -                if key == "desc": -                    continue -                item = ConfigItem() -                item.name = key -                item.description = data["desc"] -                item.value = str(data["value"]) if type(data["value"]) != basestring else data["value"] -                item.type = data["type"] -                items.append(item) -            section.items = items -            sections.append(section) -        return sections - -    #general -    def getConfigValue(self, category, option, section): -        """ -        Parameters: -         - category -         - option -         - section -        """ -        self.serverMethods.get_conf_val(category, option, section) - -    def setConfigValue(self, category, option, value, section): -        """ -        Parameters: -         - category -         - option -         - value -         - section -        """ -        pass - -    def getConfig(self): -        c = self.serverMethods.get_config() -        return self._convertConfigFormat(c) - -    def getPluginConfig(self): -        c = self.serverMethods.get_plugin_config() -        return self._convertConfigFormat(c) - -    def pauseServer(self): -        self.serverMethods.pause_server() - -    def unpauseServer(self): -        self.serverMethods.unpause_server() - -    def togglePause(self): -        return self.serverMethods.toggle_pause() - -    def toggleReconnect(self): -        return self.serverMethods.toggle_reconnect() - -    def statusServer(self): -        status = self.serverMethods.status_server() -        serverStatus = ServerStatus() -        serverStatus.pause = status["pause"] -        serverStatus.active = status["activ"] -        serverStatus.queue = status["queue"] -        serverStatus.total = status["total"] -        serverStatus.speed = 0 -        for pyfile in [x.active for x in self.core.threadManager.threads if x.active and x.active != "quit"]: -            serverStatus.speed += pyfile.getSpeed() #bytes/s -        serverStatus.download = status["download"] -        serverStatus.reconnect = status["reconnect"] -        return serverStatus - -    def freeSpace(self): -        return freeSpace(self.core.config["general"]["download_folder"]) - -    def getServerVersion(self): -        return self.serverMethods.get_server_version() - -    def kill(self): -        self.serverMethods.kill() - -    def restart(self): -        self.serverMethods.restart() - -    def getLog(self, offset): -        """ -        Parameters: -         - offset -        """ -        log = self.serverMethods.get_log(offset) -        return log or [] - -    def checkURL(self, urls): -        """ -        Parameters: -         - urls -        """ -        checked = {} -        for u, p in self.core.pluginManager.parseUrls(urls): -            if p == "BasePlugin": -                checked[u] = "" -            else: -                checked[u] = p -        return checked - -    def isTimeDownload(self): -        return self.serverMethods.is_time_download() - -    def isTimeReconnect(self): -        return self.serverMethods.is_time_reconnect() - -    #downloads -    def statusDownloads(self): -        data = [] -        for pyfile in [x.active for x in self.core.threadManager.threads + self.core.threadManager.localThreads if -                       x.active and x.active != "quit"]: -            if not isinstance(pyfile, PyFile): -                continue -            status = DownloadInfo() -            status.fid = pyfile.id -            status.name = pyfile.name -            status.speed = pyfile.getSpeed() #bytes -            status.eta = pyfile.getETA() -            status.format_eta = pyfile.formatETA() -            status.bleft = pyfile.getBytesLeft() -            status.size = pyfile.getSize() -            status.format_size = pyfile.formatSize() -            status.percent = pyfile.getPercent() -            status.status = pyfile.status -            status.statusmsg = pyfile.m.statusMsg[pyfile.status] -            status.format_wait = pyfile.formatWait() -            status.wait_until = pyfile.waitUntil -            status.packageName = pyfile.package().name -            status.packageID = pyfile.package().id -            status.plugin = pyfile.pluginname -            data.append(status) -        return data - -    def addPackage(self, name, links, dest): -        """ -        Parameters: -         - name -         - links -         - dest -        """ -        return self.serverMethods.add_package(name, links, 0 if dest == Destination.Collector else 1) - -    def getPackageData(self, pid): -        """ -        Parameters: -         - pid -        """ -        pdata = PackageData() -        rawData = self.serverMethods.get_package_data(pid) - -        if not rawData: -            raise PackageDoesNotExists(pid) - -        pdata.pid = rawData["id"] -        pdata.name = rawData["name"] -        pdata.folder = rawData["folder"] -        pdata.site = rawData["site"] -        pdata.password = rawData["password"] -        pdata.dest = rawData["queue"] -        pdata.order = rawData["order"] -        pdata.priority = rawData["priority"] -        pdata.links = [] -        for id, pyfile in rawData["links"].iteritems(): -            pdata.links.append(self._convertPyFile(pyfile)) -             -        return pdata - -    def getFileData(self, fid): -        """ -        Parameters: -         - fid -        """ -        rawData = self.serverMethods.get_file_data(fid) -        if rawData: -            rawData = rawData.values()[0] -        else: -            raise FileDoesNotExists(fid) - -        fdata = self._convertPyFile(rawData) -        return fdata - -    def deleteFiles(self, fids): -        """ -        Parameters: -         - fids -        """ -        self.serverMethods.del_links(fids) - -    def deletePackages(self, pids): -        """ -        Parameters: -         - pids -        """ -        self.serverMethods.del_packages(pids) - -    def getQueue(self): -        packs = self.serverMethods.get_queue() -        ret = [] -        for pid, pack in packs.iteritems(): -            pdata = PackageInfo() -            pdata.pid = pack["id"] -            pdata.name = pack["name"] -            pdata.folder = pack["folder"] -            pdata.site = pack["site"] -            pdata.password = pack["password"] -            pdata.dest = pack["queue"] -            pdata.order = pack["order"] -            pdata.priority = pack["priority"] -            pdata.links = [int(x) for x in pack["links"].keys()] -            ret.append(pdata) -        return ret - -    def getQueueData(self): -        packs = self.serverMethods.get_queue() -        ret = [] -        for pid, pack in packs.iteritems(): -            pdata = PackageData() -            pdata.pid = pack["id"] -            pdata.name = pack["name"] -            pdata.folder = pack["folder"] -            pdata.site = pack["site"] -            pdata.password = pack["password"] -            pdata.dest = pack["queue"] -            pdata.order = pack["order"] -            pdata.priority = pack["priority"] -            pdata.links = [self._convertPyFile(x) for x in pack["links"].values()] -            ret.append(pdata) -        return ret - -    def getCollector(self): -        packs = self.serverMethods.get_collector() -        ret = [] -        for pid, pack in packs.iteritems(): -            pdata = PackageInfo() -            pdata.pid = pack["id"] -            pdata.name = pack["name"] -            pdata.folder = pack["folder"] -            pdata.site = pack["site"] -            pdata.password = pack["password"] -            pdata.dest = pack["queue"] -            pdata.order = pack["order"] -            pdata.priority = pack["priority"] -            pdata.links = [int(x) for x in pack["links"].keys()] -            ret.append(pdata) -        return ret - -    def getCollectorData(self): -        packs = self.serverMethods.get_collector() -        ret = [] -        for pid, pack in packs.iteritems(): -            pdata = PackageData() -            pdata.pid = pack["id"] -            pdata.name = pack["name"] -            pdata.folder = pack["folder"] -            pdata.site = pack["site"] -            pdata.password = pack["password"] -            pdata.dest = pack["queue"] -            pdata.order = pack["order"] -            pdata.priority = pack["priority"] -            pdata.links = [self._convertPyFile(x) for x in pack["links"].values()] -            ret.append(pdata) -        return ret - -    def addFiles(self, pid, links): -        """ -        Parameters: -         - pid -         - links -        """ -        self.serverMethods.add_files(pid, links) - -    def pushToQueue(self, pid): -        """ -        Parameters: -         - pid -        """ -        self.serverMethods.push_package_to_queue(pid) - -    def pullFromQueue(self, pid): -        """ -        Parameters: -         - pid -        """ -        self.serverMethods.pull_out_package(pid) - -    def restartPackage(self, pid): -        """ -        Parameters: -         - pid -        """ -        self.serverMethods.restart_package(pid) - -    def restartFile(self, fid): -        """ -        Parameters: -         - fid -        """ -        self.serverMethods.restart_file(fid) - -    def recheckPackage(self, pid): -        """ -        Parameters: -         - pid -        """ -        self.serverMethods.recheck_package(pid) - -    def stopAllDownloads(self): -        self.serverMethods.stop_downloads() - -    def stopDownloads(self, fids): -        """ -        Parameters: -         - fids -        """ -        self.serverMethods.abort_files(fids) - -    def setPackageName(self, pid, name): -        """ -        Parameters: -         - pid -         - name -        """ -        self.serverMethods.set_package_name(pid, name) - -    def movePackage(self, destination, pid): -        """ -        Parameters: -         - destination -         - pid -        """ -        self.serverMethods.move_package(destination, pid) - -    def uploadContainer(self, filename, data): -        """ -        Parameters: -         - filename -         - data -        """ -        self.serverMethods.upload_container(filename, data) - -    def setPriority(self, pid, priority): -        """ -        Parameters: -         - pid -         - priority -        """ -        self.serverMethods.set_priority(pid, priority) - -    def orderPackage(self, pid, position): -        """ -        Parameters: -         - pid -         - position -        """ -        self.serverMethods.order_package(pid, position) - -    def orderFile(self, fid, position): -        """ -        Parameters: -         - fid -         - position -        """ -        self.serverMethods.order_file(fid, position) - -    def setPackageData(self, pid, data): -        """ -        Parameters: -         - pid -         - data -        """ -        self.serverMethods.set_package_data(pid, data) - -    def deleteFinished(self): -        self.serverMethods.delete_finished() - -    def restartFailed(self): -        self.serverMethods.restart_failed() - -    def getPackageOrder(self, destination): -        """ -        Parameters: -         - destination -        """ -        order = {} -        if destination == Destination.Queue: -            packs = self.serverMethods.get_queue() -        else: -            packs = self.serverMethods.get_collector() -        for pid in packs: -            pack = self.serverMethods.get_package_data(pid) -            while pack["order"] in order.keys(): #just in case -                pack["order"] += 1 -            order[pack["order"]] = pack["id"] -        return order - -    def getFileOrder(self, pid): -        """ -        Parameters: -         - pid -        """ -        rawData = self.serverMethods.get_package_data(pid) -        order = {} -        for id, pyfile in rawData["links"].iteritems(): -            while pyfile["order"] in order.keys(): #just in case -                pyfile["order"] += 1 -            order[pyfile["order"]] = pyfile["id"] -        return order - -    #captcha -    def isCaptchaWaiting(self): -        return self.serverMethods.is_captcha_waiting() - -    def getCaptchaTask(self, exclusive): -        """ -        Parameters: -         - exclusive -        """ -        tid, data, type, result = self.serverMethods.get_captcha_task(exclusive) -        t = CaptchaTask(int(tid), standard_b64encode(data), type, result) -        return t - -    def getCaptchaTaskStatus(self, tid): -        """ -        Parameters: -         - tid -        """ -        return self.serverMethods.get_task_status(tid) - -    def setCaptchaResult(self, tid, result): -        """ -        Parameters: -         - tid -         - result -        """ -        self.serverMethods.set_captcha_result(tid, result) - -    #events -    def getEvents(self, uuid): -        events = self.serverMethods.get_events(uuid) -        newEvents = [] -        def convDest(d): -            return Destination.Queue if d == "queue" else Destination.Collector -        for e in events: -            event = Event() -            event.event = e[0] -            if e[0] in ("update", "remove", "insert"): -                event.id = e[3] -                event.type = ElementType.Package if e[2] == "pack" else ElementType.File -                event.destination = convDest(e[1]) -            elif e[0] == "order": -                if e[1]: -                    event.id = e[1] -                    event.type = ElementType.Package if e[2] == "pack" else ElementType.File -                    event.destination = convDest(e[3]) -            elif e[0] == "reload": -                event.destination = convDest(e[1]) -            newEvents.append(event) -        return newEvents - -    #accounts -    def getAccounts(self, refresh): -        """ -        Parameters: -         - refresh -        """ -        accs = self.serverMethods.get_accounts(False, refresh) -        accounts = [] -        for group in accs.values(): -            for acc in group: -                account = AccountInfo() -                account.validuntil = acc["validuntil"] -                account.login = acc["login"] -                account.options = acc["options"] -                account.valid = acc["valid"] -                account.trafficleft = acc["trafficleft"] -                account.maxtraffic = acc["maxtraffic"] -                account.premium = acc["premium"] -                account.type = acc["type"] -                accounts.append(account) -        return accounts -     -    def getAccountTypes(self): -        return self.serverMethods.get_accounts().keys() - -    def updateAccounts(self, data): -        """ -        Parameters: -         - data -        """ -        self.serverMethods.update_account(data.type, data.login, data.password, data.options) - -    def removeAccount(self, plugin, account): -        """ -        Parameters: -         - plugin -         - account -        """ -        self.serverMethods.remove_account(plugin, account) - -    #auth -    def login(self, username, password, remoteip=None): -        """ -        Parameters: -         - username -         - password -        """ -        return self.backend.checkAuth(username, password, remoteip) - -    def getUserData(self, username, password): -        return self.serverMethods.checkAuth(username, password) - - -    def getServices(self): -        data = {} -        for plugin, funcs in self.core.hookManager.methods.iteritems(): -            data[plugin] = funcs - -        return data - -    def hasService(self, plugin, func): -        cont = self.core.hookManager.methods -        return cont.has_key(plugin) and cont[plugin].has_key(func) - -    def call(self, info): -        plugin = info.plugin -        func = info.func -        args = info.arguments -        parse = info.parseArguments - -        if not self.hasService(plugin, func): -            raise ServiceDoesNotExists(plugin, func) - -        try: -            ret = self.core.hookManager.callRPC(plugin, func, args, parse) -            return str(ret) -        except Exception, e: -            raise ServiceException(e.message) -        
\ No newline at end of file diff --git a/module/remote/thriftbackend/pyload.thrift b/module/remote/thriftbackend/pyload.thrift index 45d7f5eeb..32fe69d13 100644 --- a/module/remote/thriftbackend/pyload.thrift +++ b/module/remote/thriftbackend/pyload.thrift @@ -187,8 +187,8 @@ service Pyload {    //config    string getConfigValue(1: string category, 2: string option, 3: string section),    void setConfigValue(1: string category, 2: string option, 3: string value, 4: string section), -  list<ConfigSection> getConfig(), -  list<ConfigSection> getPluginConfig(), +  map<string, ConfigSection> getConfig(), +  map<string, ConfigSection> getPluginConfig(),    // server status    void pauseServer(), @@ -259,7 +259,7 @@ service Pyload {    //accounts    list<AccountInfo> getAccounts(1: bool refresh),    list<string> getAccountTypes() -  void updateAccounts(1: AccountData data), +  void updateAccount(1: PluginName plugin, 2: string account, 3: string password, 4: map<string, string> options),    void removeAccount(1: PluginName plugin, 2: string account),    //auth diff --git a/module/remote/thriftbackend/thriftgen/pyload/Pyload-remote b/module/remote/thriftbackend/thriftgen/pyload/Pyload-remote index 0e454c816..2b055321b 100755 --- a/module/remote/thriftbackend/thriftgen/pyload/Pyload-remote +++ b/module/remote/thriftbackend/thriftgen/pyload/Pyload-remote @@ -80,7 +80,7 @@ if len(sys.argv) <= 1 or sys.argv[1] == '--help':    print '   getEvents(string uuid)'    print '   getAccounts(bool refresh)'    print '   getAccountTypes()' -  print '  void updateAccounts(AccountData data)' +  print '  void updateAccount(PluginName plugin, string account, string password,  options)'    print '  void removeAccount(PluginName plugin, string account)'    print '  bool login(string username, string password)'    print '  UserData getUserData(string username, string password)' @@ -88,7 +88,7 @@ if len(sys.argv) <= 1 or sys.argv[1] == '--help':    print '  bool hasService(PluginName plugin, string func)'    print '  string call(ServiceCall info)'    print '   getAllInfo()' -  print '   getInfoByPlugin(string plugin)' +  print '   getInfoByPlugin(PluginName plugin)'    print ''    sys.exit(0) @@ -481,11 +481,11 @@ elif cmd == 'getAccountTypes':      sys.exit(1)    pp.pprint(client.getAccountTypes()) -elif cmd == 'updateAccounts': -  if len(args) != 1: -    print 'updateAccounts requires 1 args' +elif cmd == 'updateAccount': +  if len(args) != 4: +    print 'updateAccount requires 4 args'      sys.exit(1) -  pp.pprint(client.updateAccounts(eval(args[0]),)) +  pp.pprint(client.updateAccount(eval(args[0]),args[1],args[2],eval(args[3]),))  elif cmd == 'removeAccount':    if len(args) != 2: @@ -533,7 +533,7 @@ elif cmd == 'getInfoByPlugin':    if len(args) != 1:      print 'getInfoByPlugin requires 1 args'      sys.exit(1) -  pp.pprint(client.getInfoByPlugin(args[0],)) +  pp.pprint(client.getInfoByPlugin(eval(args[0]),))  else:    print 'Unrecognized method %s' % cmd diff --git a/module/remote/thriftbackend/thriftgen/pyload/Pyload.py b/module/remote/thriftbackend/thriftgen/pyload/Pyload.py index ec850b70c..de3611b6d 100644 --- a/module/remote/thriftbackend/thriftgen/pyload/Pyload.py +++ b/module/remote/thriftbackend/thriftgen/pyload/Pyload.py @@ -336,10 +336,13 @@ class Iface(object):    def getAccountTypes(self, ):      pass -  def updateAccounts(self, data): +  def updateAccount(self, plugin, account, password, options):      """      Parameters: -     - data +     - plugin +     - account +     - password +     - options      """      pass @@ -1988,30 +1991,36 @@ class Client(Iface):        return result.success      raise TApplicationException(TApplicationException.MISSING_RESULT, "getAccountTypes failed: unknown result"); -  def updateAccounts(self, data): +  def updateAccount(self, plugin, account, password, options):      """      Parameters: -     - data +     - plugin +     - account +     - password +     - options      """ -    self.send_updateAccounts(data) -    self.recv_updateAccounts() +    self.send_updateAccount(plugin, account, password, options) +    self.recv_updateAccount() -  def send_updateAccounts(self, data): -    self._oprot.writeMessageBegin('updateAccounts', TMessageType.CALL, self._seqid) -    args = updateAccounts_args() -    args.data = data +  def send_updateAccount(self, plugin, account, password, options): +    self._oprot.writeMessageBegin('updateAccount', TMessageType.CALL, self._seqid) +    args = updateAccount_args() +    args.plugin = plugin +    args.account = account +    args.password = password +    args.options = options      args.write(self._oprot)      self._oprot.writeMessageEnd()      self._oprot.trans.flush() -  def recv_updateAccounts(self, ): +  def recv_updateAccount(self, ):      (fname, mtype, rseqid) = self._iprot.readMessageBegin()      if mtype == TMessageType.EXCEPTION:        x = TApplicationException()        x.read(self._iprot)        self._iprot.readMessageEnd()        raise x -    result = updateAccounts_result() +    result = updateAccount_result()      result.read(self._iprot)      self._iprot.readMessageEnd()      return @@ -2318,7 +2327,7 @@ class Processor(Iface, TProcessor):      self._processMap["getEvents"] = Processor.process_getEvents      self._processMap["getAccounts"] = Processor.process_getAccounts      self._processMap["getAccountTypes"] = Processor.process_getAccountTypes -    self._processMap["updateAccounts"] = Processor.process_updateAccounts +    self._processMap["updateAccount"] = Processor.process_updateAccount      self._processMap["removeAccount"] = Processor.process_removeAccount      self._processMap["login"] = Processor.process_login      self._processMap["getUserData"] = Processor.process_getUserData @@ -2982,13 +2991,13 @@ class Processor(Iface, TProcessor):      oprot.writeMessageEnd()      oprot.trans.flush() -  def process_updateAccounts(self, seqid, iprot, oprot): -    args = updateAccounts_args() +  def process_updateAccount(self, seqid, iprot, oprot): +    args = updateAccount_args()      args.read(iprot)      iprot.readMessageEnd() -    result = updateAccounts_result() -    self._handler.updateAccounts(args.data) -    oprot.writeMessageBegin("updateAccounts", TMessageType.REPLY, seqid) +    result = updateAccount_result() +    self._handler.updateAccount(args.plugin, args.account, args.password, args.options) +    oprot.writeMessageBegin("updateAccount", TMessageType.REPLY, seqid)      result.write(oprot)      oprot.writeMessageEnd()      oprot.trans.flush() @@ -3194,7 +3203,7 @@ class getConfig_result(TBase):     ]    thrift_spec = ( -    (0, TType.LIST, 'success', (TType.STRUCT,(ConfigSection, ConfigSection.thrift_spec)), None, ), # 0 +    (0, TType.MAP, 'success', (TType.STRING,None,TType.STRUCT,(ConfigSection, ConfigSection.thrift_spec)), None, ), # 0    )    def __init__(self, success=None,): @@ -3221,7 +3230,7 @@ class getPluginConfig_result(TBase):     ]    thrift_spec = ( -    (0, TType.LIST, 'success', (TType.STRUCT,(ConfigSection, ConfigSection.thrift_spec)), None, ), # 0 +    (0, TType.MAP, 'success', (TType.STRING,None,TType.STRUCT,(ConfigSection, ConfigSection.thrift_spec)), None, ), # 0    )    def __init__(self, success=None,): @@ -4829,26 +4838,38 @@ class getAccountTypes_result(TBase):      self.success = success -class updateAccounts_args(TBase): +class updateAccount_args(TBase):    """    Attributes: -   - data +   - plugin +   - account +   - password +   - options    """    __slots__ = [  -    'data', +    'plugin', +    'account', +    'password', +    'options',     ]    thrift_spec = (      None, # 0 -    (1, TType.STRUCT, 'data', (AccountData, AccountData.thrift_spec), None, ), # 1 +    (1, TType.STRING, 'plugin', None, None, ), # 1 +    (2, TType.STRING, 'account', None, None, ), # 2 +    (3, TType.STRING, 'password', None, None, ), # 3 +    (4, TType.MAP, 'options', (TType.STRING,None,TType.STRING,None), None, ), # 4    ) -  def __init__(self, data=None,): -    self.data = data +  def __init__(self, plugin=None, account=None, password=None, options=None,): +    self.plugin = plugin +    self.account = account +    self.password = password +    self.options = options -class updateAccounts_result(TBase): +class updateAccount_result(TBase):    __slots__ = [      ] diff --git a/module/web/json_app.py b/module/web/json_app.py index d35ca1ad7..bc95b5ffd 100644 --- a/module/web/json_app.py +++ b/module/web/json_app.py @@ -1,22 +1,21 @@  #!/usr/bin/env python  # -*- coding: utf-8 -*- -import base64 -from os.path import join, exists +import os +import os.path +from os.path import join  from traceback import print_exc +import shutil  from shutil import copyfileobj  from bottle import route, request, HTTPError, validate  from webinterface import PYLOAD -from utils import login_required, render_to_response +from utils import login_required, render_to_response, toDict -from module.utils import decode +from module.utils import decode, formatSize -import os -import shutil -import os.path  def format_time(seconds):      seconds = int(seconds) @@ -35,8 +34,8 @@ def get_sort_key(item):  @login_required('see_downloads')  def status():      try: -        status = PYLOAD.status_server() -        status['captcha'] = PYLOAD.is_captcha_waiting() +        status = toDict(PYLOAD.statusServer()) +        status['captcha'] = PYLOAD.isCaptchaWaiting()          return status      except:          return HTTPError() @@ -47,17 +46,17 @@ def status():  @login_required('see_downloads')  def links():      try: -        links = PYLOAD.status_downloads() +        links = [toDict(x) for x in PYLOAD.statusDownloads()]          ids = []          for link in links: -            ids.append(link['id']) +            ids.append(link['fid'])              if link['status'] == 12: -                link['info'] = "%s @ %s kb/s" % (link['format_eta'], round(link['speed'], 2)) +                link['info'] = "%s @ %s/s" % (link['format_eta'], formatSize(link['speed']))              elif link['status'] == 5:                  link['percent'] = 0                  link['size'] = 0 -                link['kbleft'] = 0 +                link['bleft'] = 0                  link['info'] = _("waiting %s") % link['format_wait']              else:                  link['info'] = "" @@ -65,14 +64,16 @@ def links():          data = {'links': links, 'ids': ids}          return data      except Exception, e: +        print_exc()          return HTTPError()  @route("/json/queue")  @login_required('see_downloads')  def queue(): +    print "/json/queue"      try: -        return PYLOAD.get_queue() +        return PYLOAD.getQueue()      except:          return HTTPError() @@ -82,7 +83,7 @@ def queue():  @login_required('status')  def pause():      try: -        return PYLOAD.pause_server() +        return PYLOAD.pauseServer()      except:          return HTTPError() @@ -92,7 +93,7 @@ def pause():  @login_required('status')  def unpause():      try: -        return PYLOAD.unpause_server() +        return PYLOAD.unpauseServer()      except:          return HTTPError() @@ -102,7 +103,7 @@ def unpause():  @login_required('status')  def cancel():      try: -        return PYLOAD.stop_downloads() +        return PYLOAD.stopDownloads()      except:          return HTTPError() @@ -110,8 +111,9 @@ def cancel():  @route("/json/packages")  @login_required('see_downloads')  def packages(): +    print "/json/packages"      try: -        data = PYLOAD.get_queue() +        data = PYLOAD.getQueue()          for package in data:              package['links'] = [] @@ -129,9 +131,10 @@ def packages():  @login_required('see_downloads')  def package(id):      try: -        data = PYLOAD.get_package_data(id) +        data = toDict(PYLOAD.getPackageData(id)) +        data["links"] = [toDict(x) for x in data["links"]] -        for pyfile in data["links"].itervalues(): +        for pyfile in data["links"]:              if pyfile["status"] == 0:                  pyfile["icon"] = "status_finished.png"              elif pyfile["status"] in (2, 3): @@ -149,12 +152,13 @@ def package(id):              else:                  pyfile["icon"] = "status_downloading.png" -        tmp = data["links"].values() +        tmp = data["links"]          tmp.sort(key=get_sort_key)          data["links"] = tmp          return data      except: +        print_exc()          return HTTPError() @@ -163,7 +167,7 @@ def package(id):  def package_order(ids):      try:          pid, pos = ids.split("|") -        PYLOAD.order_package(int(pid), int(pos)) +        PYLOAD.orderPackage(int(pid), int(pos))          return {"response": "success"}      except:          return HTTPError() @@ -173,8 +177,9 @@ def package_order(ids):  @validate(id=int)  @login_required('see_downloads')  def link(id): +    print "/json/link/%d" % id      try: -        data = PYLOAD.get_file_info(id) +        data = toDict(PYLOAD.getFileData(id))          return data      except:          return HTTPError() @@ -185,7 +190,7 @@ def link(id):  @login_required('delete')  def remove_link(id):      try: -        PYLOAD.del_links([id]) +        PYLOAD.deleteFiles([id])          return {"response": "success"}      except Exception, e:          return HTTPError() @@ -196,7 +201,7 @@ def remove_link(id):  @login_required('add')  def restart_link(id):      try: -        PYLOAD.restart_file(id) +        PYLOAD.restartFile(id)          return {"response": "success"}      except Exception:          return HTTPError() @@ -207,7 +212,7 @@ def restart_link(id):  @login_required('delete')  def abort_link(id):      try: -        PYLOAD.stop_download("link", id) +        PYLOAD.stopDownload("link", id)          return {"response": "success"}      except:          return HTTPError() @@ -218,7 +223,7 @@ def abort_link(id):  def link_order(ids):      try:          pid, pos = ids.split("|") -        PYLOAD.order_file(int(pid), int(pos)) +        PYLOAD.orderFile(int(pid), int(pos))          return {"response": "success"}      except:          return HTTPError() @@ -240,7 +245,7 @@ def add_package():          if not name or name == "New Package":              name = f.name -        fpath = join(PYLOAD.get_conf_val("general", "download_folder"), "tmp_" + f.filename) +        fpath = join(PYLOAD.getConfigValue("general", "download_folder"), "tmp_" + f.filename)          destination = open(fpath, 'wb')          copyfileobj(f.file, destination)          destination.close() @@ -253,11 +258,11 @@ def add_package():      links = map(lambda x: x.strip(), links)      links = filter(lambda x: x != "", links) -    pack = PYLOAD.add_package(name, links, queue) +    pack = PYLOAD.addPackage(name, links, queue)      if pw:          pw = pw.decode("utf8", "ignore")          data = {"password": pw} -        PYLOAD.set_package_data(pack, data) +        PYLOAD.setPackageData(pack, data)  @route("/json/remove_package/:id") @@ -265,7 +270,7 @@ def add_package():  @login_required('delete')  def remove_package(id):      try: -        PYLOAD.del_packages([id]) +        PYLOAD.deletePackages([id])          return {"response": "success"}      except Exception, e:          return HTTPError() @@ -276,7 +281,7 @@ def remove_package(id):  @login_required('add')  def restart_package(id):      try: -        PYLOAD.restart_package(id) +        PYLOAD.restartPackage(id)          return {"response": "success"}      except Exception:          print_exc() @@ -288,7 +293,7 @@ def restart_package(id):  @login_required('add')  def move_package(dest, id):      try: -        PYLOAD.move_package(dest, id) +        PYLOAD.movePackage(dest, id)          return {"response": "success"}      except:          return HTTPError() @@ -304,7 +309,7 @@ def edit_package():                  "priority": request.forms.get("pack_prio"),                  "password": request.forms.get("pack_pws").decode("utf8", "ignore")} -        PYLOAD.set_package_data(id, data) +        PYLOAD.setPackageData(id, data)          return {"response": "success"}      except: @@ -317,17 +322,16 @@ def edit_package():  def set_captcha():      if request.environ.get('REQUEST_METHOD', "GET") == "POST":          try: -            PYLOAD.set_captcha_result(request.forms["cap_id"], request.forms["cap_result"]) +            PYLOAD.setCaptchaResult(request.forms["cap_id"], request.forms["cap_result"])          except:              pass -    id, binary, format, result_type = PYLOAD.get_captcha_task() +    task = PYLOAD.getCaptchaTask()      if id: -        binary = base64.standard_b64encode(str(binary)) -        src = "data:image/%s;base64,%s" % (format, binary) +        src = "data:image/%s;base64,%s" % (task.type, task.data) -        return {'captcha': True, 'id': id, 'src': src, 'result_type' : result_type} +        return {'captcha': True, 'id': task.tid, 'src': src, 'result_type' : task.resultType}      else:          return {'captcha': False} @@ -335,13 +339,13 @@ def set_captcha():  @route("/json/delete_finished")  @login_required('delete')  def delete_finished(): -    return {"del": PYLOAD.delete_finished()} +    return {"del": PYLOAD.deleteFinished()}  @route("/json/restart_failed")  @login_required('delete')  def restart_failed(): -    restart = PYLOAD.restart_failed() +    restart = PYLOAD.restartFailed()      if restart: return restart      return {"response": "success"} @@ -352,17 +356,15 @@ def restart_failed():  def load_config(category, section):      conf = None      if category == "general": -        conf = PYLOAD.get_config() +        conf = PYLOAD.getConfig()      elif category == "plugin": -        conf = PYLOAD.get_plugin_config() - -    for key, option in conf[section].iteritems(): -        if key == "desc": continue +        conf = PYLOAD.getPluginConfig() -        if ";" in option["type"]: -            option["list"] = option["type"].split(";") +    for option in conf[section].items: +        if ";" in option.type: +            option.type = option.type.split(";") -        option["value"] = decode(option["value"]) +        option.value = decode(option.value)      return render_to_response("settings_item.html", {"skey": section, "section": conf[section]}) @@ -378,7 +380,7 @@ def save_config(category):          if category == "general": category = "core" -        PYLOAD.set_conf_val(section, option, decode(value), category) +        PYLOAD.setConfigValue(section, option, decode(value), category)  @route("/json/add_account", method="POST") @@ -388,7 +390,7 @@ def add_account():      password = request.POST["account_password"]      type = request.POST["account_type"] -    PYLOAD.update_account(type, login, password) +    PYLOAD.updateAccount(type, login, password)  @route("/json/update_accounts", method="POST") @@ -406,14 +408,14 @@ def update_accounts():          if (plugin, user) in deleted: continue          if action == "password": -            PYLOAD.update_account(plugin, user, value) +            PYLOAD.updateAccount(plugin, user, value)          elif action == "time" and "-" in value: -            PYLOAD.update_account(plugin, user, options={"time": [value]}) +            PYLOAD.updateAccount(plugin, user, options={"time": [value]})          elif action == "limitdl" and value.isdigit(): -            PYLOAD.update_account(plugin, user, options={"limitDL": [value]}) +            PYLOAD.updateAccount(plugin, user, options={"limitDL": [value]})          elif action == "delete":              deleted.append((plugin,user)) -            PYLOAD.remove_account(plugin, user) +            PYLOAD.removeAccount(plugin, user)  @route("/json/change_password", method="POST")  def change_password(): @@ -422,7 +424,7 @@ def change_password():      oldpw = request.POST["login_current_password"]      newpw = request.POST["login_new_password"] -    if not PYLOAD.change_password(user, oldpw, newpw): +    if not PYLOAD.changePassword(user, oldpw, newpw):          print "Wrong password"          return HTTPError() diff --git a/module/web/media/default/js/funktions.js b/module/web/media/default/js/funktions.js index 8d9d332b3..529b7056b 100644 --- a/module/web/media/default/js/funktions.js +++ b/module/web/media/default/js/funktions.js @@ -1,6 +1,6 @@  // JavaScript Document
 -function HumanFileSize(size) {
 -    var filesizename = new Array("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB");
 +function humanFileSize(size) {
 +    var filesizename = new Array("B", "KiB", "MiB", "GiB", "TiB", "PiB");
      var loga = Math.log(size) / Math.log(1024);
      var i = Math.floor(loga);
      var a = Math.pow(1024, i);
 diff --git a/module/web/pyload_app.py b/module/web/pyload_app.py index 3bd314a40..0131e888f 100644 --- a/module/web/pyload_app.py +++ b/module/web/pyload_app.py @@ -16,9 +16,8 @@      @author: RaNaN  """ -from copy import deepcopy  from datetime import datetime -from operator import itemgetter +from operator import itemgetter, attrgetter  import time  import os @@ -26,14 +25,15 @@ import sys  from os import listdir  from os.path import isdir, isfile, join, abspath  from sys import getfilesystemencoding -from hashlib import sha1  from urllib import unquote  from bottle import route, static_file, request, response, redirect, HTTPError, error  from webinterface import PYLOAD, PYLOAD_DIR, PROJECT_DIR, SETUP -from utils import render_to_response, parse_permissions, parse_userdata, login_required, get_permission, set_permission +from utils import render_to_response, parse_permissions, parse_userdata, \ +    login_required, get_permission, set_permission, toDict +  from filters import relpath, unquotepath  from module.utils import formatSize, decode, fs_decode, freeSpace @@ -46,10 +46,10 @@ def pre_processor():      perms = parse_permissions(s)      status = {}      if user["is_authenticated"]: -        status = PYLOAD.status_server() +        status = PYLOAD.statusServer()      captcha = False      if user["is_authenticated"]: -        captcha = PYLOAD.is_captcha_waiting() +        captcha = PYLOAD.isCaptchaWaiting()      return {"user": user,              'status': status,              'captcha': captcha, @@ -57,10 +57,6 @@ def pre_processor():              'url': request.url} -def get_sort_key(item): -    return item[1]["order"] - -  def base(messages):      return render_to_response('base.html', {'messages': messages}, [pre_processor]) @@ -79,7 +75,7 @@ def error500(error):  @route('/media/:path#.+#')  def server_static(path):      response.headers['Expires'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT", -                                                time.gmtime(time.time() + 60 * 60 * 24 * 7)) +                                                time.gmtime(time.time() + 60 * 60 * 24 * 2))      response.headers['Cache-control'] = "public"      return static_file(path, root=join(PROJECT_DIR, "media")) @@ -136,7 +132,7 @@ def logout():  @login_required("see_downloads")  def home():      try: -        res = PYLOAD.status_downloads() +        res = [toDict(x) for x in PYLOAD.statusDownloads()]      except:          s = request.environ.get('beaker.session')          s.delete() @@ -152,29 +148,27 @@ def home():  @route("/queue")  @login_required("see_downloads")  def queue(): -    queue = PYLOAD.get_queue_info() +    queue = PYLOAD.getQueue() -    data = zip(queue.keys(), queue.values()) -    data.sort(key=get_sort_key) +    queue.sort(key=attrgetter("order")) -    return render_to_response('queue.html', {'content': data}, [pre_processor]) +    return render_to_response('queue.html', {'content': queue}, [pre_processor])  @route("/collector")  @login_required('see_downloads')  def collector(): -    queue = PYLOAD.get_collector_info() +    queue = PYLOAD.getCollector() -    data = zip(queue.keys(), queue.values()) -    data.sort(key=get_sort_key) +    queue.sort(key=attrgetter("order")) -    return render_to_response('collector.html', {'content': data}, [pre_processor]) +    return render_to_response('collector.html', {'content': queue}, [pre_processor])  @route("/downloads")  @login_required('download')  def downloads(): -    root = PYLOAD.get_conf_val("general", "download_folder") +    root = PYLOAD.getConfigValue("general", "download_folder")      if not isdir(root):          return base([_('Download directory not found.')]) @@ -213,7 +207,7 @@ def get_download(path):      path = unquote(path)      #@TODO some files can not be downloaded -    root = PYLOAD.get_conf_val("general", "download_folder") +    root = PYLOAD.getConfigValue("general", "download_folder")      path = path.replace("..", "")      try: @@ -227,7 +221,7 @@ def get_download(path):  #@route("/filemanager")  #@login_required('filemanager')  def filemanager(): -    root = PYLOAD.get_conf_val("general", "download_folder") +    root = PYLOAD.getConfigValue("general", "download_folder")      if not isdir(root):          return base([_('Download directory not found.')]) @@ -283,48 +277,49 @@ def folder():  @route("/settings")  @login_required('settings')  def config(): -    conf = PYLOAD.get_config() -    plugin = PYLOAD.get_plugin_config() +    conf = PYLOAD.getConfig() +    plugin = PYLOAD.getPluginConfig()      conf_menu = []      plugin_menu = []      for entry in sorted(conf.keys()): -        conf_menu.append((entry, conf[entry]["desc"])) +        conf_menu.append((entry, conf[entry].description))      for entry in sorted(plugin.keys()): -        plugin_menu.append((entry, plugin[entry]["desc"])) - -    accs = deepcopy(PYLOAD.get_accounts(False, False)) -    for accounts in accs.itervalues(): -        for data in accounts: -            if data["trafficleft"] == -1: -                data["trafficleft"] = _("unlimited") -            elif not data["trafficleft"]: -                data["trafficleft"] = _("not available") -            else: -                data["trafficleft"] = formatSize(data["trafficleft"] * 1024) +        plugin_menu.append((entry, plugin[entry].description)) -            if data["validuntil"] == -1: -                data["validuntil"] = _("unlimited") -            elif not data["validuntil"]: -                data["validuntil"] = _("not available") -            else: -                t = time.localtime(data["validuntil"]) -                data["validuntil"] = time.strftime("%d.%m.%Y", t) +    accs = PYLOAD.getAccounts(False) -            if data["options"].has_key("time"): -                try: -                    data["time"] = data["options"]["time"][0] -                except: -                    data["time"] = "0:00-0:00" -            if data["options"].has_key("limitDL"): -                data["limitdl"] = data["options"]["limitDL"][0] -            else: -                data["limitdl"] = "0" +    for data in accs: +        if data.trafficleft == -1: +            data.trafficleft = _("unlimited") +        elif not data.trafficleft: +            data.trafficleft = _("not available") +        else: +            data.trafficleft = formatSize(data.trafficleft * 1024) + +        if data.validuntil == -1: +            data.validuntil  = _("unlimited") +        elif not data.validuntil : +            data.validuntil  = _("not available") +        else: +            t = time.localtime(data.validuntil) +            data.validuntil  = time.strftime("%d.%m.%Y", t) + +        if data.options.has_key("time"): +            try: +                data.options["time"] = data.options["time"][0] +            except: +                data.options["time"] = "0:00-0:00" + +        if data.options.has_key("limitDL"): +            data.options["limitdl"] = data.options["limitDL"][0] +        else: +            data.options["limitdl"] = "0"      return render_to_response('settings.html', -            {'conf': {'plugin': plugin_menu, 'general': conf_menu, 'accs': accs}}, +            {'conf': {'plugin': plugin_menu, 'general': conf_menu, 'accs': accs}, 'types': PYLOAD.getAccountTypes()},          [pre_processor]) @@ -448,8 +443,8 @@ def logs(item=-1):      reversed = s.get('reversed', False)      warning = "" -    conf = PYLOAD.get_config() -    if not conf['log']['file_log']['value']: +    conf = PYLOAD.getConfigValue("log","file_log") +    if not conf:          warning = "Warning: File log is disabled, see settings page."      perpage_p = ((20, 20), (34, 34), (40, 40), (100, 100), (0, 'all')) @@ -476,7 +471,7 @@ def logs(item=-1):      except:          pass -    log = PYLOAD.get_log() +    log = PYLOAD.getLog()      if not perpage:          item = 0 @@ -527,7 +522,7 @@ def logs(item=-1):  @route("/admin", method="POST")  @login_required("is_admin")  def admin(): -    user = PYLOAD.get_user_data() +    user = PYLOAD.getAllUserData()      for data in user.itervalues():          data["perms"] = {}          get_permission(data["perms"], data["permission"]) @@ -580,7 +575,7 @@ def admin():              user[name]["permission"] = set_permission(user[name]["perms"]) -            PYLOAD.set_user_permission(name, user[name]["permission"], user[name]["role"]) +            PYLOAD.setUserPermission(name, user[name]["permission"], user[name]["role"])      return render_to_response("admin.html", {"users": user}, [pre_processor]) @@ -595,7 +590,7 @@ def setup():  @route("/info")  def info(): -    conf = PYLOAD.get_config() +    conf = PYLOAD.getConfigDict()      if hasattr(os, "uname"):          extra = os.uname() @@ -604,10 +599,10 @@ def info():      data = {"python": sys.version,              "os": " ".join((os.name, sys.platform) + extra), -            "version": PYLOAD.get_server_version(), +            "version": PYLOAD.getServerVersion(),              "folder": abspath(PYLOAD_DIR), "config": abspath(""),              "download": abspath(conf["general"]["download_folder"]["value"]), -            "freespace": formatSize(freeSpace(conf["general"]["download_folder"]["value"])), +            "freespace": formatSize(PYLOAD.freeSpace()),              "remote": conf["remote"]["port"]["value"],              "webif": conf["webinterface"]["port"]["value"],              "language": conf["general"]["language"]["value"]} diff --git a/module/web/templates/default/base.html b/module/web/templates/default/base.html index 6eb71f737..13538cf08 100644 --- a/module/web/templates/default/base.html +++ b/module/web/templates/default/base.html @@ -86,7 +86,7 @@ document.addEvent("domready", function(){  function LoadJsonToContent(data)
  {
      $("speed").set('text', Math.round(data.speed*100)/100);
 -    $("aktiv").set('text', data.activ);
 +    $("aktiv").set('text', data.active);
      $("aktiv_from").set('text', data.queue);
      $("aktiv_total").set('text', data.total);
 @@ -257,7 +257,7 @@ function AddBox(){      <li><span class="time">{{_("Download:")}}</span><a id="time" style=" background-color: {% if status.download %}#8ffc25{% else %} #fc6e26{% endif %}; padding-left: 0cm; padding-right: 0.1cm; "> {% if status.download %}{{_("on")}}{% else %}{{_("off")}}{% endif %}</a></li>
      <li><span class="reconnect">{{_("Reconnect:")}}</span><a id="reconnect" style=" background-color: {% if status.reconnect %}#8ffc25{% else %} #fc6e26{% endif %}; padding-left: 0cm; padding-right: 0.1cm; "> {% if status.reconnect %}{{_("on")}}{% else %}{{_("off")}}{% endif %}</a></li>
      <li><a class="action backlink">{{_("Speed:")}} <b id="speed">{{ status.speed }}</b> kb/s</a></li>
 -    <li><a class="action cog">{{_("Active:")}} <b id="aktiv">{{ status.activ }}</b> / <b id="aktiv_from">{{ status.queue }}</b> / <b id="aktiv_total">{{ status.total }}</b></a></li>
 +    <li><a class="action cog">{{_("Active:")}} <b id="aktiv">{{ status.active }}</b> / <b id="aktiv_from">{{ status.queue }}</b> / <b id="aktiv_total">{{ status.total }}</b></a></li>
      <li><a href=""  class="action revisions" accesskey="o" rel="nofollow">{{_("Reload page")}}</a></li>
  </ul>
  {% endif %}
 diff --git a/module/web/templates/default/collector.html b/module/web/templates/default/collector.html index 2683d8ee5..20221b899 100644 --- a/module/web/templates/default/collector.html +++ b/module/web/templates/default/collector.html @@ -24,9 +24,9 @@ document.addEvent("domready", function(){  {% block content %}
  <ul id="package-list" style="list-style: none; padding-left: 0; margin-top: -10px;">
 -{% for id, package in content %}
 +{% for package in content %}
      <li>
 -<div id="package_{{id}}" class="package">
 +<div id="package_{{package.pid}}" class="package">
      <div class="order" style="display: none;">{{ package.order }}</div>
      <div class="packagename" style="cursor: pointer;">
 @@ -43,9 +43,9 @@ document.addEvent("domready", function(){          <img title="{{_("Move Package to Queue")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/media/default/img/package_go.png" />
          </span>
      </div>
 -    <div id="children_{{id}}" style="display: none;" class="children">
 +    <div id="children_{{package.pid}}" style="display: none;" class="children">
      <span class="child_secrow">{{_("Folder:")}} <span class="folder">{{package.folder}}</span> | {{_("Password:")}} <span class="password">{{package.password}}</span> | {{_("Priority:")}} <span class="prio">{{package.priority}}</span></span>
 -    <ul id="sort_children_{{id}}" style="list-style: none; padding-left: 0">
 +    <ul id="sort_children_{{package.pid}}" style="list-style: none; padding-left: 0">
      </ul>
      </div>
  </div>
 diff --git a/module/web/templates/default/home.html b/module/web/templates/default/home.html index 1239d381d..0efb1bcf8 100644 --- a/module/web/templates/default/home.html +++ b/module/web/templates/default/home.html @@ -48,7 +48,7 @@ var EntryManager = new Class({          try{
          this.ids = this.entries.map(function(item){
 -            return item.id
 +            return item.fid
              });
          this.ids.filter(function(id){
 @@ -56,21 +56,21 @@ var EntryManager = new Class({          },data).each(function(id){
              var index = this.ids.indexOf(id);
              this.entries[index].remove();
 -            this.entries = this.entries.filter(function(item){return item.id != this},id);
 +            this.entries = this.entries.filter(function(item){return item.fid != this},id);
              this.ids = this.ids.erase(id)
              }, this);
          data.links.each(function(link, i){
 -            if (this.ids.contains(link.id)){
 +            if (this.ids.contains(link.fid)){
 -                var index = this.ids.indexOf(link.id);
 +                var index = this.ids.indexOf(link.fid);
                  this.entries[index].update(link)
              }else{
 -                var entry = new LinkEntry(link.id);
 +                var entry = new LinkEntry(link.fid);
                  entry.insert(link);
                  this.entries.push(entry);
 -                this.ids.push(link.id);
 +                this.ids.push(link.fid);
                  this.container.adopt(entry.elements.tr,entry.elements.pgbTr);
                  entry.fade.start('opacity', 1);
                  entry.fadeBar.start('opacity', 1);
 @@ -86,7 +86,8 @@ var EntryManager = new Class({  var LinkEntry = new Class({
          initialize: function(id){
 -            this.id = id
 +            this.fid = id;
 +            this.id = id;
          },
          parse: function(){
              this.elements = {
 @@ -94,7 +95,7 @@ var LinkEntry = new Class({                  name: $("link_{id}_name".substitute({id: this.id})),
                  status: $("link_{id}_status".substitute({id: this.id})),
                  info: $("link_{id}_info".substitute({id: this.id})),
 -                bleft: $("link_{id}_kbleft".substitute({id: this.id})),
 +                bleft: $("link_{id}_bleft".substitute({id: this.id})),
                  percent: $("link_{id}_percent".substitute({id: this.id})),
                  remove: $("link_{id}_remove".substitute({id: this.id})),
                  pgbTr: $("link_{id}_pgb_tr".substitute({id: this.id})),
 @@ -122,10 +123,10 @@ var LinkEntry = new Class({                  'html': item.info
                  }),
                  bleft: new Element('td', {
 -                'html': HumanFileSize(item.size)
 +                'html': humanFileSize(item.size)
                  }),
                  percent: new Element('span', {
 -                'html': item.percent+ '% / '+ HumanFileSize(item.size-item.bleft)
 +                'html': item.percent+ '% / '+ humanFileSize(item.size-item.bleft)
                  }),
                  remove: new Element('img',{
                  'src': 'media/default/img/control_cancel.png',
 @@ -173,7 +174,7 @@ var LinkEntry = new Class({                  this.elements.status.set('text', item.statusmsg);
                  this.elements.info.set('text', item.info);
                  this.elements.bleft.set('text', item.format_size);
 -                this.elements.percent.set('text', item.percent+ '% / '+ HumanFileSize(item.size-item.bleft));
 +                this.elements.percent.set('text', item.percent+ '% / '+ humanFileSize(item.size-item.bleft));
                  if(!operafix)
                  {
                      this.bar.start({
 @@ -247,9 +248,9 @@ var LinkEntry = new Class({      <td id="link_{{ link.id }}_name">{{ link.name }}</td>
      <td id="link_{{ link.id }}_status">{{ link.status }}</td>
      <td id="link_{{ link.id }}_info">{{ link.info }}</td>
 -    <td id="link_{{ link.id }}_kbleft">{{ link.format_size }}</td>
 +    <td id="link_{{ link.id }}_bleft">{{ link.format_size }}</td>
      <td>
 -        <span id="link_{{ link.id }}_percent">{{ link.percent }}% /{{ link.kbleft }}</span>
 +        <span id="link_{{ link.id }}_percent">{{ link.percent }}% /{{ link.bleft }}</span>
          <img id="link_{{ link.id }}_remove" style="vertical-align: middle; margin-right: -20px; margin-left: 5px; margin-top: -2px; cursor:pointer;" src="media/default/img/control_cancel.png"/>
      </td>
    </tr>
 diff --git a/module/web/templates/default/info.html b/module/web/templates/default/info.html index 14f5a734f..77ae57376 100644 --- a/module/web/templates/default/info.html +++ b/module/web/templates/default/info.html @@ -21,9 +21,14 @@      <h3>{{ _("Support") }}</h3>      <ul> -        <li style="font-weight:bold;"><a href="http://pyload.org/wiki" target="_blank">Wiki</a></li> -        <li style="font-weight:bold;"><a href="http://forum.pyload.org/" target="_blank">Forum</a></li> -        <li style="font-weight:bold;"><a href="http://pyload.org/irc/" target="_blank">Chat</a></li> +        <li style="font-weight:bold;"> +            <a href="http://pyload.org/wiki" target="_blank">Wiki</a> +              |   +            <a href="http://forum.pyload.org/" target="_blank">Forum</a> +              |   +            <a href="http://pyload.org/irc/" target="_blank">Chat</a> +        </li> +        <li style="font-weight:bold;"><a href="http://docs.pyload.org" target="_blank">Documentation</a></li>          <li style="font-weight:bold;"><a href="https://bitbucket.org/spoob/pyload/overview" target="_blank">Development</a></li>          <li style="font-weight:bold;"><a href="https://bitbucket.org/spoob/pyload/issues?status=new&status=open" target="_blank">Issue Tracker</a></li> diff --git a/module/web/templates/default/package_ui.js b/module/web/templates/default/package_ui.js index cee29dfd8..0b938910a 100644 --- a/module/web/templates/default/package_ui.js +++ b/module/web/templates/default/package_ui.js @@ -204,6 +204,7 @@ var Package = new Class({          var ul = $("sort_children_{id}".substitute({"id": this.id}));          ul.erase("html");          data.links.each(function(link) { +            link.id = link.fid;              var li = new Element("li", {                  "style": {                      "margin-left": 0 diff --git a/module/web/templates/default/queue.html b/module/web/templates/default/queue.html index 104369c11..b9ec525a1 100644 --- a/module/web/templates/default/queue.html +++ b/module/web/templates/default/queue.html @@ -25,9 +25,9 @@ document.addEvent("domready", function(){  <ul id="package-list" style="list-style: none; padding-left: 0; margin-top: -10px;">
 -{% for id, package in content %}
 +{% for package in content %}
      <li>
 -<div id="package_{{id}}" class="package">
 +<div id="package_{{package.pid}}" class="package">
      <div class="order" style="display: none;">{{ package.order }}</div>
      <div class="packagename" style="cursor: pointer;">
 @@ -44,9 +44,9 @@ document.addEvent("domready", function(){          <img title="{{_("Move Package to Collector")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/media/default/img/package_go.png" />
          </span>
      </div>
 -    <div id="children_{{id}}" style="display: none;" class="children">
 +    <div id="children_{{package.pid}}" style="display: none;" class="children">
      <span class="child_secrow">{{_("Folder:")}} <span class="folder">{{package.folder}}</span> | {{_("Password:")}} <span class="password">{{package.password}}</span> | {{_("Priority:")}} <span class="prio">{{package.priority}}</span></span>
 -    <ul id="sort_children_{{id}}" style="list-style: none; padding-left: 0">
 +    <ul id="sort_children_{{package.pid}}" style="list-style: none; padding-left: 0">
      </ul>
      </div>
  </div>
 diff --git a/module/web/templates/default/settings.html b/module/web/templates/default/settings.html index a74fe4261..d5484f06e 100644 --- a/module/web/templates/default/settings.html +++ b/module/web/templates/default/settings.html @@ -131,10 +131,9 @@                          </tr>                          </thead> -                         {% for plugin, accounts in conf.accs.iteritems() %} - -                            {% for account in accounts %} +                            {% for account in conf.accs %} +                                {% set plugin = account.type %}                                         <tr>                                              <td>                                                  <span style="padding:5px">{{ plugin }}</span> @@ -193,11 +192,9 @@                                                        value="True"/>                                             </td>                                         </tr> -                                    {% endfor %}                                  {% endfor %}                              </table> -              <button id="account_submit" type="submit" class="styled_button">{{_("Submit")}}</button>              <button id="account_add" style="margin-left: 0" type="submit" class="styled_button">{{_("Add")}}</button>              </form> @@ -223,12 +220,11 @@  <span class="small">{{_("Choose the hoster for your account.")}}</span>  </label>      <select name=account_type id="account_type"> -        {% for type in conf.accs.iterkeys()|sort %} +        {% for type in types|sort %}              <option value="{{ type }}">{{ type }}</option>          {% endfor %}      </select> -  <button id="account_add_button" type="submit">{{_("Add")}}</button>  <button id="account_reset" style="margin-left: 0" type="reset">{{_("Reset")}}</button>  <div class="spacer"></div> diff --git a/module/web/templates/default/settings_item.html b/module/web/templates/default/settings_item.html index 593050bd2..92223557d 100644 --- a/module/web/templates/default/settings_item.html +++ b/module/web/templates/default/settings_item.html @@ -1,45 +1,45 @@  <table class="settable"> -    {% for okey, option in section.iteritems() %} -        {% if okey != "desc" %} -            <tr> -                <td><label for="{{skey}}|{{okey}}" -                           style="color:#424242;">{{ option.desc }}:</label></td> -                <td> -                    {% if option.type == "bool" %} -                        <select id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}"> -                            <option {% if option.value %} selected="selected" -                                                          {% endif %}value="True">{{ _("on") }}</option> -                            <option {% if not option.value %} selected="selected" -                                                              {% endif %}value="False">{{ _("off") }}</option> -                        </select> -                        {% elif ";" in option.type %} -                        <select id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}"> -                            {% for entry in option.list %} -                                <option {% if option.value == entry %} -                                        selected="selected" {% endif %}>{{ entry }}</option> -                            {% endfor %} -                        </select> -                        {% elif option.type == "folder" %} -                        <input name="{{skey}}|{{okey}}" type="text" -                               id="{{skey}}|{{okey}}" value="{{option.value}}"/> -                        <input name="browsebutton" type="button" -                               onclick="ifield = document.getElementById('{{skey}}|{{okey}}'); pathchooser = window.open('{% if option.value %}{{ "/pathchooser/" + option.value|quotepath }}{% else %}{{ pathroot }}{% endif %}', 'pathchooser', 'scrollbars=yes,toolbar=no,menubar=no,statusbar=no,width=650,height=300'); pathchooser.ifield = ifield; window.ifield = ifield;" -                               value="{{_("Browse")}}"/> -                        {% elif option.type == "file" %} -                        <input name="{{skey}}|{{okey}}" type="text" -                               id="{{skey}}|{{okey}}" value="{{option.value}}"/> -                        <input name="browsebutton" type="button" -                               onclick="ifield = document.getElementById('{{skey}}|{{okey}}'); filechooser = window.open('{% if option.value %}{{ "/filechooser/" + option.value|quotepath }}{% else %}{{ fileroot }}{% endif %}', 'filechooser', 'scrollbars=yes,toolbar=no,menubar=no,statusbar=no,width=650,height=300'); filechooser.ifield = ifield; window.ifield = ifield;" -                               value="{{_("Browse")}}"/> -                        {% elif option.type == "password" %} -                        <input id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}" -                               type="password" value="{{option.value}}"/> -                    {% else %} -                        <input id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}" -                               type="text" value="{{option.value}}"/> -                    {% endif %} -                </td> -            </tr> -        {% endif %} +    {% set skey = section.name %} +    {% for option in section.items %} +        {% set okey = option.name %} +        <tr> +            <td><label for="{{skey}}|{{okey}}" +                       style="color:#424242;">{{ option.description }}:</label></td> +            <td> +                {% if option.type == "bool" %} +                    <select id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}"> +                        <option {% if option.value %} selected="selected" +                                                      {% endif %}value="True">{{ _("on") }}</option> +                        <option {% if not option.value %} selected="selected" +                                                          {% endif %}value="False">{{ _("off") }}</option> +                    </select> +                    {% elif option.type|type == "<type 'list'>" %} +                    <select id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}"> +                        {% for entry in option.type %} +                            <option {% if option.value == entry %} +                                    selected="selected" {% endif %}>{{ entry }}</option> +                        {% endfor %} +                    </select> +                    {% elif option.type == "folder" %} +                    <input name="{{skey}}|{{okey}}" type="text" +                           id="{{skey}}|{{okey}}" value="{{option.value}}"/> +                    <input name="browsebutton" type="button" +                           onclick="ifield = document.getElementById('{{skey}}|{{okey}}'); pathchooser = window.open('{% if option.value %}{{ "/pathchooser/" + option.value|quotepath }}{% else %}{{ pathroot }}{% endif %}', 'pathchooser', 'scrollbars=yes,toolbar=no,menubar=no,statusbar=no,width=650,height=300'); pathchooser.ifield = ifield; window.ifield = ifield;" +                           value="{{_("Browse")}}"/> +                    {% elif option.type == "file" %} +                    <input name="{{skey}}|{{okey}}" type="text" +                           id="{{skey}}|{{okey}}" value="{{option.value}}"/> +                    <input name="browsebutton" type="button" +                           onclick="ifield = document.getElementById('{{skey}}|{{okey}}'); filechooser = window.open('{% if option.value %}{{ "/filechooser/" + option.value|quotepath }}{% else %}{{ fileroot }}{% endif %}', 'filechooser', 'scrollbars=yes,toolbar=no,menubar=no,statusbar=no,width=650,height=300'); filechooser.ifield = ifield; window.ifield = ifield;" +                           value="{{_("Browse")}}"/> +                    {% elif option.type == "password" %} +                    <input id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}" +                           type="password" value="{{option.value}}"/> +                {% else %} +                    <input id="{{skey}}|{{okey}}" name="{{skey}}|{{okey}}" +                           type="text" value="{{option.value}}"/> +                {% endif %} +            </td> +        </tr>      {% endfor %}  </table>
\ No newline at end of file diff --git a/module/web/utils.py b/module/web/utils.py index 81baa4fd2..1455c3c01 100644 --- a/module/web/utils.py +++ b/module/web/utils.py @@ -109,6 +109,12 @@ def login_required(perm=None):      return _dec +def toDict(obj): +    ret = {} +    for att in obj.__slots__: +        ret[att] = getattr(obj, att) +    return ret +  class CherryPyWSGI(ServerAdapter):      def run(self, handler): diff --git a/module/web/webinterface.py b/module/web/webinterface.py index 69e67f9e4..e54c8b137 100644 --- a/module/web/webinterface.py +++ b/module/web/webinterface.py @@ -49,7 +49,7 @@ if not ServerThread.core:      else:          raise Exception("Could not access pyLoad Core")  else: -    PYLOAD = ServerThread.core.server_methods +    PYLOAD = ServerThread.core.api      config = ServerThread.core.config  from module.common.JsEngine import JsEngine @@ -72,7 +72,7 @@ loader = PrefixLoader({                        })  env = Environment(loader=loader, extensions=['jinja2.ext.i18n'], trim_blocks=True, auto_reload=False, bytecode_cache=bcc) -from filters import quotepath, path_make_relative, path_make_absolute, truncate,date +from filters import quotepath, path_make_relative, path_make_absolute, truncate, date  env.filters["quotepath"] = quotepath  env.filters["truncate"] = truncate @@ -80,6 +80,7 @@ env.filters["date"] = date  env.filters["path_make_relative"] = path_make_relative  env.filters["path_make_absolute"] = path_make_absolute  env.filters["decode"] = decode +env.filters["type"] = lambda x: str(type(x))  translation = gettext.translation("django", join(PYLOAD_DIR, "locale"), diff --git a/pyLoadCore.py b/pyLoadCore.py index b0196c3c5..3e0979b57 100755 --- a/pyLoadCore.py +++ b/pyLoadCore.py @@ -49,7 +49,6 @@ from module.PullEvents import PullManager  from module.network.RequestFactory import RequestFactory  from module.ThreadManager import ThreadManager  from module.web.ServerThread import WebServer -from module.PyFile import PyFile  from module.Scheduler import Scheduler  from module.common.JsEngine import JsEngine  from module.remote.RemoteManager import RemoteManager @@ -337,8 +336,6 @@ class Core(object):          self.lastClientConnected = 0          from module.Api import Api - -        self.server_methods = ServerMethods(self)          self.api = Api(self)          self.scheduler = Scheduler(self) @@ -354,7 +351,7 @@ class Core(object):          self.js = JsEngine() -        self.log.info(_("Downloadtime: %s") % self.server_methods.is_time_download()) +        self.log.info(_("Downloadtime: %s") % self.api.isTimeDownload())          if rpc:              self.remoteManager.startBackends() @@ -375,14 +372,14 @@ class Core(object):          if exists(link_file):              f = open(link_file, "rb")              if f.read().strip(): -                self.server_methods.add_package("links.txt", [link_file], 1) +                self.api.addPackage("links.txt", [link_file], 1)              f.close()          link_file = "links.txt"          if exists(link_file):              f = open(link_file, "rb")              if f.read().strip(): -                self.server_methods.add_package("links.txt", [link_file], 1) +                self.api.addPackage("links.txt", [link_file], 1)              f.close()          #self.scheduler.addJob(0, self.accountManager.getAccountInfos) @@ -550,344 +547,6 @@ class Core(object):      def path(self, * args):          return join(pypath, * args) - -#TODO: replace with api class -class ServerMethods(): -    """ deprecated""" - -    def __init__(self, core): -        self.core = core -     -    def _dispatch(self, method, params): -        f = getattr(self, method) -        try: -            return f(*params) -        except: -            print_exc() -            raise -     -    def status_downloads(self): -        """ gives status about all files currently processed """ -        downloads = [] -        for pyfile in [x.active for x in self.core.threadManager.threads + self.core.threadManager.localThreads if -                       x.active and x.active != "quit"]: -            if not isinstance(pyfile, PyFile) or not hasattr(pyfile, "plugin"): -                continue -            download = {'id': pyfile.id, -                        'name': pyfile.name, -                        'speed': pyfile.getSpeed() / 1024, -                        'eta': pyfile.getETA(), -                        'format_eta': pyfile.formatETA(), -                        'kbleft': pyfile.getBytesLeft(), -                        'bleft': pyfile.getBytesLeft(), -                        'size': pyfile.getSize(), -                        'format_size': pyfile.formatSize(), -                        'percent': pyfile.getPercent(), -                        'status': pyfile.status, -                        'statusmsg': pyfile.m.statusMsg[pyfile.status], -                        'format_wait': pyfile.formatWait(), -                        'wait_until': pyfile.waitUntil, -                        'package': pyfile.package().name} -            downloads.append(download) -        return downloads - -    def get_conf_val(self, cat, var, sec="core"): -        """ get config value """ -        if sec == "core": -            return self.core.config[cat][var] -        elif sec == "plugin": -            return self.core.config.getPlugin(cat, var) - -    def set_conf_val(self, cat, opt, val, sec="core"): -        """ set config value """ -        if sec == "core": -            opt = str(opt) -            self.core.config[str(cat)][opt] = val - -            if opt in ("limit_speed", "max_speed"): #not so nice to update the limit -                self.core.requestFactory.updateBucket() - -        elif sec == "plugin": -            self.core.config.setPlugin(cat, opt, val) - -    def get_config(self): -        """ gets complete config """ -        return self.core.config.config - -    def get_plugin_config(self): -        """ gets complete plugin config """ -        return self.core.config.plugin - -    def pause_server(self): -        self.core.threadManager.pause = True - -    def unpause_server(self): -        self.core.threadManager.pause = False - -    def toggle_pause(self): -        self.core.threadManager.pause ^= True -        return self.core.threadManager.pause - -    def toggle_reconnect(self): -        self.core.config["reconnect"]["activated"] ^= True -        return self.core.config["reconnect"]["activated"] - -    def status_server(self): -        """ dict with current server status """ -        status = {'pause': self.core.threadManager.pause, -                  'activ': len(self.core.threadManager.processingIds()), -                  'queue': self.core.files.getQueueCount(), -                  'total': self.core.files.getFileCount(), -                  'speed': 0} - -        for pyfile in [x.active for x in self.core.threadManager.threads if x.active and x.active != "quit"]: -            status['speed'] += pyfile.getSpeed()/1024 - -        status['download'] = not self.core.threadManager.pause and self.is_time_download() -        status['reconnect'] = self.core.config['reconnect']['activated'] and self.is_time_reconnect() - -        return status -     -    def free_space(self): -        return freeSpace(self.core.config["general"]["download_folder"]) / 1024 / 1024 #mb - -    def get_server_version(self): -        return CURRENT_VERSION - -    def add_package(self, name, links, queue=0): -    #0 is collector -        if self.core.config['general']['folder_per_package']: -            folder = name -        else: -            folder = "" - -        folder = folder.replace("http://","").replace(":","").replace("/","_").replace("\\","_") - -        pid = self.core.files.addPackage(name, folder, queue) - -        self.core.files.addLinks(links, pid) - -        self.core.log.info(_("Added package %(name)s containing %(count)d links") % {"name": name, "count": len(links)}) - -        self.core.files.save() - -        return pid - - -    def get_package_data(self, id): -        return self.core.files.getPackageData(int(id)) - -    def get_file_data(self, id): -        info = self.core.files.getFileData(int(id)) -        if not info: -            return None -        info = {str(info.keys()[0]): info[info.keys()[0]]} -        return info - -    def del_links(self, ids): -        for id in ids: -            self.core.files.deleteLink(int(id)) - -        self.core.files.save() - -    def del_packages(self, ids): -        for id in ids: -            self.core.files.deletePackage(int(id)) - -        self.core.files.save() - -    def kill(self): -        self.core.do_kill = True -        return True - -    def restart(self): -        self.core.do_restart = True - -    def get_queue(self): -        return self.core.files.getCompleteData(1) - -    def get_collector(self): -        return self.core.files.getCompleteData(0) - -    def get_queue_info(self): -        return self.core.files.getInfoData(1) - -    def get_collector_info(self): -        return self.core.files.getInfoData(0) - -    def add_files(self, pid, links): -        pid = int(pid) -        self.core.files.addLinks(links, pid) - -        self.core.log.info(_("Added %(count)d links to package #%(package)d ") % {"count": len(links), "package": pid}) -        self.core.files.save() - -        return pid - -    def push_package_to_queue(self, id): -        self.core.files.setPackageLocation(id, 1) - -    def restart_package(self, packid): -        self.core.files.restartPackage(int(packid)) - -    def recheck_package(self, packid): -        self.core.files.reCheckPackage(int(packid)) - -    def restart_file(self, fileid): -        self.core.files.restartFile(int(fileid)) - -    def upload_container(self, filename, content): -        th = open(join(self.core.config["general"]["download_folder"], "tmp_" + filename), "wb") -        th.write(str(content)) -        th.close() - -        self.add_package(th.name, [th.name], 1) - -    def get_log(self, offset=0): -        filename = join(self.core.config['log']['log_folder'], 'log.txt') -        try: -            fh = open(filename, "r") -            lines = fh.readlines() -            fh.close() -            if offset >= len(lines): -                return None -            return lines[offset:] -        except: -            return ('No log available', ) - -    def stop_downloads(self): -        pyfiles = self.core.files.cache.values() - -        for pyfile in pyfiles: -            pyfile.abortDownload() - -    def abort_files(self, fids): -        pyfiles = self.core.files.cache.values() - -        for pyfile in pyfiles: -            if pyfile.id in fids: -                pyfile.abortDownload() - -    def stop_download(self, type, id): -        if self.core.files.cache.has_key(id): -            self.core.files.cache[id].abortDownload() - - -    def set_package_name(self, pid, name): -        pack = self.core.files.getPackage(pid) -        pack.name = name -        pack.sync() - -    def pull_out_package(self, pid): -        """put package back to collector""" -        self.core.files.setPackageLocation(pid, 0) - -    def move_package(self, dest, pid): -        if dest not in (0,1): return -        self.core.files.setPackageLocation(pid, dest) - -    def is_captcha_waiting(self): -        self.core.lastClientConnected = time() -        task = self.core.captchaManager.getTask() -        return not task is None - -    def get_captcha_task(self, exclusive=False): -        """ returns tid, data, type, resulttype """ -        self.core.lastClientConnected = time() -        task = self.core.captchaManager.getTask() -        if task: -            task.setWatingForUser(exclusive=exclusive) -            captcha_info = task.getCaptcha() -            return (task.id,) + captcha_info -        else: -            return None, None, None, None - -    def get_task_status(self, tid): -        self.core.lastClientConnected = time() -        t = self.core.captchaManager.getTaskByID(tid) -        return t.getStatus() if t else "" - -    def set_captcha_result(self, tid, result): -        self.core.lastClientConnected = time() -        task = self.core.captchaManager.getTaskByID(tid) -        if task: -            task.setResult(result) -            self.core.captchaManager.removeTask(task) -            return True -        else: -            return False - -    def get_events(self, uuid): -        return self.core.pullManager.getEvents(uuid) - -    def get_accounts(self, force=False, refresh=True): -        return self.core.accountManager.getAccountInfos(force, refresh) - -    def update_account(self, plugin, account, password=None, options={}): -        """ create and update account """ -        self.core.accountManager.updateAccount(plugin, account, password, options) - -    def remove_account(self, plugin, account): -        self.core.accountManager.removeAccount(plugin, account) - -    def set_priority(self, id, priority): -        p = self.core.files.getPackage(id) -        p.setPriority(priority) - -    def order_package(self, id, pos): -        self.core.files.reorderPackage(id, pos) - -    def order_file(self, id, pos): -        self.core.files.reorderFile(id, pos) - -    def set_package_data(self, id, data): -        p = self.core.files.getPackage(id) -        if not p: return -         -        for key, value in data.iteritems(): -            if key == "id": continue -            setattr(p, key, value) - -        p.sync() -        self.core.files.save() -     -    def checkURLs(self, urls): -        support = self.core.pluginManager.parseUrls(urls) -        return [(u, p) if not p == "BasePlugin" else (u, None) for u, p in support] - -    def is_time_download(self): -        start = self.core.config['downloadTime']['start'].split(":") -        end = self.core.config['downloadTime']['end'].split(":") -        return compare_time(start, end) - -    def is_time_reconnect(self): -        start = self.core.config['reconnect']['startTime'].split(":") -        end = self.core.config['reconnect']['endTime'].split(":") -        return compare_time(start, end) and self.core.config["reconnect"]["activated"] - -    def delete_finished(self): -        """ delete all finished links + packages, returns deleted packages """ -        deleted = self.core.files.deleteFinishedLinks() -        return deleted - -    def restart_failed(self): -        """ restart all failed links """ -        self.core.files.restartFailed() -     -    def checkAuth(self, username, password): -        return self.core.db.checkAuth(username, password) - -    def get_user_data(self): -        return self.core.db.getAllUserData() - -    def set_user_permission(self, user, permission, role): -        self.core.db.setPermission(user, permission) -        self.core.db.setRole(user, role) - -    def change_password(self, user, oldpw, newpw): -        return self.core.db.changePassword(user, oldpw, newpw) - -  def deamon():      try:          pid = os.fork() diff --git a/pyLoadGui.py b/pyLoadGui.py index 87b501ee2..33326c416 100755 --- a/pyLoadGui.py +++ b/pyLoadGui.py @@ -694,7 +694,7 @@ class main(QObject):      def quitInternal(self):          if self.core: -            self.core.server_methods.kill() +            self.core.api.kill()              for i in range(10):                  if self.core.shuttedDown:                      break | 
