From 6eae782f13953dd0ba2bbe1b582cf33fd4d7d90a Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Mon, 19 Dec 2011 23:10:49 +0100
Subject: configparser v2, warning CONFIG will be DELETED.

---
 module/Api.py | 135 ++++++++++++++++++++++++----------------------------------
 1 file changed, 56 insertions(+), 79 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index f0bf5e264..c787819e2 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -27,11 +27,13 @@ from utils import freeSpace, compare_time
 from common.packagetools import parseNames
 from network.RequestFactory import getURL
 from remote import activated
+from config.converter import to_string
 
 if activated:
     try:
         from remote.thriftbackend.thriftgen.pyload.ttypes import *
         from remote.thriftbackend.thriftgen.pyload.Pyload import Iface
+
         BaseObject = TBase
     except ImportError:
         print "Thrift not imported"
@@ -49,7 +51,7 @@ def permission(bits):
         def __new__(cls, func, *args, **kwargs):
             permMap[func.__name__] = bits
             return func
-        
+
     return _Dec
 
 
@@ -67,10 +69,12 @@ class PERMS:
     ACCOUNTS = 256 # can access accounts
     LOGS = 512 # can see server logs
 
+
 class ROLE:
     ADMIN = 0  #admin has all permissions implicit
     USER = 1
 
+
 def has_permission(userperms, perms):
     # bytewise or perms before if needed
     return perms == (userperms & perms)
@@ -97,65 +101,33 @@ class Api(Iface):
 
     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["format_size"], p["status"], p["statusmsg"],
+            p["package"], p["error"], p["order"])
         return f
 
-    def _convertConfigFormat(self, c):
-        sections = {}
-        for sectionName, sub in c.iteritems():
-            section = ConfigSection(sectionName, sub["desc"])
-            items = []
-            for key, data in sub.iteritems():
-                if key in ("desc", "outline"):
-                    continue
-                item = ConfigItem()
-                item.name = key
-                item.description = data["desc"]
-                item.value = str(data["value"]) if not isinstance(data["value"], basestring) else data["value"]
-                item.type = data["type"]
-                items.append(item)
-            section.items = items
-            sections[sectionName] = section
-            if "outline" in sub:
-                section.outline = sub["outline"]
-        return sections
-
     @permission(PERMS.SETTINGS)
-    def getConfigValue(self, category, option, section="core"):
+    def getConfigValue(self, section, option):
         """Retrieve config value.
 
-        :param category: name of category, or plugin
+        :param section: name of category, or plugin
         :param option: config option
-        :param section: 'plugin' or 'core'
         :return: config value as string
         """
-        if section == "core":
-            value = self.core.config[category][option]
-        else:
-            value = self.core.config.getPlugin(category, option)
-
-        return str(value) if not isinstance(value, basestring) else value
+        value = self.core.config.get(section, option)
+        return to_string(value)
 
     @permission(PERMS.SETTINGS)
-    def setConfigValue(self, category, option, value, section="core"):
+    def setConfigValue(self, section, option, value):
         """Set new config value.
 
-        :param category:
+        :param section:
         :param option:
         :param value: new config value
-        :param section: 'plugin' or 'core
         """
-        self.core.hookManager.dispatchEvent("configChanged", category, option, value, section)
+        if option in ("limit_speed", "max_speed"): #not so nice to update the limit
+            self.core.requestFactory.updateBucket()
 
-        if section == "core":
-            self.core.config[category][option] = value
-
-            if option in ("limit_speed", "max_speed"): #not so nice to update the limit
-                self.core.requestFactory.updateBucket()
-
-        elif section == "plugin":
-            self.core.config.setPlugin(category, option, value)
+        self.core.config.set(section, option, value)
 
     @permission(PERMS.SETTINGS)
     def getConfig(self):
@@ -163,14 +135,11 @@ class Api(Iface):
         
         :return: list of `ConfigSection`
         """
-        return self._convertConfigFormat(self.core.config.config)
+        return [ConfigSection(section, data.name, data.description, data.long_desc, [
+        ConfigItem(option, d.name, d.description, d.type, d.default, self.core.config.get(section, option)) for
+        option, d in data.config.iteritems()]) for
+                section, data in self.core.config.getBaseSectionns()]
 
-    def getConfigDict(self):
-        """Retrieves complete config in dict format, not for RPC.
-
-        :return: dict
-        """
-        return self.core.config.config
 
     @permission(PERMS.SETTINGS)
     def getPluginConfig(self):
@@ -178,15 +147,23 @@ class Api(Iface):
 
         :return: list of `ConfigSection`
         """
-        return self._convertConfigFormat(self.core.config.plugin)
+        return [ConfigSection(section, data.name, data.description, data.long_desc) for
+                section, data in self.core.config.getPluginSections()]
 
-    def getPluginConfigDict(self):
-        """Plugin config as dict, not for RPC.
+    def configureSection(self, section):
+        data = self.core.config.config[section]
+        sec = ConfigSection(section, data.name, data.description, data.long_desc)
+        sec.items = [ConfigItem(option, d.name, d.description, d.type, d.default, self.core.config.get(section, option))
+                     for
+                     option, d in data.config.iteritems()]
 
-        :return: dict
-        """
-        return self.core.config.plugin
+        #TODO: config handler
+
+        return sec
 
+    def getConfigPointer(self):
+        """Config instance, not for RPC"""
+        return self.core.config
 
     @permission(PERMS.STATUS)
     def pauseServer(self):
@@ -223,9 +200,9 @@ class Api(Iface):
         :return: `ServerStatus`
         """
         serverStatus = ServerStatus(self.core.threadManager.pause, len(self.core.threadManager.processingIds()),
-                                    self.core.files.getQueueCount(), self.core.files.getFileCount(), 0,
-                                    not self.core.threadManager.pause and self.isTimeDownload(),
-                                    self.core.config['reconnect']['activated'] and self.isTimeReconnect())
+            self.core.files.getQueueCount(), self.core.files.getFileCount(), 0,
+            not self.core.threadManager.pause and self.isTimeDownload(),
+            self.core.config['reconnect']['activated'] and self.isTimeReconnect())
 
         for pyfile in [x.active for x in self.core.threadManager.threads if x.active and isinstance(x.active, PyFile)]:
             serverStatus.speed += pyfile.getSpeed() #bytes/s
@@ -471,8 +448,8 @@ class Api(Iface):
             raise PackageDoesNotExists(pid)
 
         pdata = PackageData(data["id"], data["name"], data["folder"], data["site"], data["password"],
-                            data["queue"], data["order"],
-                            links=[self._convertPyFile(x) for x in data["links"].itervalues()])
+            data["queue"], data["order"],
+            links=[self._convertPyFile(x) for x in data["links"].itervalues()])
 
         return pdata
 
@@ -484,13 +461,13 @@ class Api(Iface):
         :return: `PackageData` with .fid attribute
         """
         data = self.core.files.getPackageData(int(pid))
-        
+
         if not data:
             raise PackageDoesNotExists(pid)
 
         pdata = PackageData(data["id"], data["name"], data["folder"], data["site"], data["password"],
-                            data["queue"], data["order"],
-                            fids=[int(x) for x in data["links"]])
+            data["queue"], data["order"],
+            fids=[int(x) for x in data["links"]])
 
         return pdata
 
@@ -538,9 +515,9 @@ class Api(Iface):
         :return: list of `PackageInfo`
         """
         return [PackageData(pack["id"], pack["name"], pack["folder"], pack["site"],
-                            pack["password"], pack["queue"], pack["order"],
-                            pack["linksdone"], pack["sizedone"], pack["sizetotal"],
-                            pack["linkstotal"])
+            pack["password"], pack["queue"], pack["order"],
+            pack["linksdone"], pack["sizedone"], pack["sizetotal"],
+            pack["linkstotal"])
                 for pack in self.core.files.getInfoData(Destination.Queue).itervalues()]
 
     @permission(PERMS.LIST)
@@ -551,9 +528,9 @@ class Api(Iface):
         :return: list of `PackageData`
         """
         return [PackageData(pack["id"], pack["name"], pack["folder"], pack["site"],
-                            pack["password"], pack["queue"], pack["order"],
-                            pack["linksdone"], pack["sizedone"], pack["sizetotal"],
-                            links=[self._convertPyFile(x) for x in pack["links"].itervalues()])
+            pack["password"], pack["queue"], pack["order"],
+            pack["linksdone"], pack["sizedone"], pack["sizetotal"],
+            links=[self._convertPyFile(x) for x in pack["links"].itervalues()])
                 for pack in self.core.files.getCompleteData(Destination.Queue).itervalues()]
 
     @permission(PERMS.LIST)
@@ -563,9 +540,9 @@ class Api(Iface):
         :return: list of `PackageInfo`
         """
         return [PackageData(pack["id"], pack["name"], pack["folder"], pack["site"],
-                            pack["password"], pack["queue"], pack["order"],
-                            pack["linksdone"], pack["sizedone"], pack["sizetotal"],
-                            pack["linkstotal"])
+            pack["password"], pack["queue"], pack["order"],
+            pack["linksdone"], pack["sizedone"], pack["sizetotal"],
+            pack["linkstotal"])
                 for pack in self.core.files.getInfoData(Destination.Collector).itervalues()]
 
     @permission(PERMS.LIST)
@@ -575,9 +552,9 @@ class Api(Iface):
         :return: list of `PackageInfo`
         """
         return [PackageData(pack["id"], pack["name"], pack["folder"], pack["site"],
-                            pack["password"], pack["queue"], pack["order"],
-                            pack["linksdone"], pack["sizedone"], pack["sizetotal"],
-                            links=[self._convertPyFile(x) for x in pack["links"].itervalues()])
+            pack["password"], pack["queue"], pack["order"],
+            pack["linksdone"], pack["sizedone"], pack["sizetotal"],
+            links=[self._convertPyFile(x) for x in pack["links"].itervalues()])
                 for pack in self.core.files.getCompleteData(Destination.Collector).itervalues()]
 
 
@@ -876,7 +853,7 @@ class Api(Iface):
         accounts = []
         for group in accs.values():
             accounts.extend([AccountInfo(acc["validuntil"], acc["login"], acc["options"], acc["valid"],
-                                         acc["trafficleft"], acc["maxtraffic"], acc["premium"], acc["type"])
+                acc["trafficleft"], acc["maxtraffic"], acc["premium"], acc["type"])
                              for acc in group])
         return accounts
 
@@ -946,7 +923,7 @@ class Api(Iface):
     @permission(PERMS.ALL)
     def getUserData(self, username, password):
         """similar to `checkAuth` but returns UserData thrift type """
-        user =  self.checkAuth(username, password)
+        user = self.checkAuth(username, password)
         if user:
             return UserData(user["name"], user["email"], user["role"], user["permission"], user["template"])
         else:
-- 
cgit v1.2.3


From 958bf611f5d9d117f19f824990ec6fd6b537e967 Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Thu, 22 Dec 2011 23:45:38 +0100
Subject: accountmanager v2, delete your accounts.conf and re-enter them in
 pyload, new nice debug functions, try core.shell() and core.breakpoint()

---
 module/Api.py | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index c787819e2..f6375f266 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -849,12 +849,11 @@ class Api(Iface):
         :param refresh: reload account info
         :return: list of `AccountInfo`
         """
-        accs = self.core.accountManager.getAccountInfos(False, refresh)
+        accs = self.core.accountManager.getAllAccounts(refresh)
         accounts = []
-        for group in accs.values():
-            accounts.extend([AccountInfo(acc["validuntil"], acc["login"], acc["options"], acc["valid"],
-                acc["trafficleft"], acc["maxtraffic"], acc["premium"], acc["type"])
-                             for acc in group])
+        for plugin in accs.itervalues():
+            accounts.extend(plugin.values())
+
         return accounts
 
     @permission(PERMS.ALL)
@@ -863,7 +862,7 @@ class Api(Iface):
 
         :return: list
         """
-        return self.core.accountManager.accounts.keys()
+        return self.core.pluginManager.getAccountPlugins()
 
     @permission(PERMS.ACCOUNTS)
     def updateAccount(self, plugin, account, password=None, options={}):
-- 
cgit v1.2.3


From f852c362fc6283246a9f9e690c456dd3fd245c29 Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Fri, 23 Dec 2011 12:15:56 +0100
Subject: closed #473

---
 module/Api.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index f6375f266..99fb4c1e7 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -862,7 +862,7 @@ class Api(Iface):
 
         :return: list
         """
-        return self.core.pluginManager.getAccountPlugins()
+        return self.core.pluginManager.getPlugins("account").keys()
 
     @permission(PERMS.ACCOUNTS)
     def updateAccount(self, plugin, account, password=None, options={}):
-- 
cgit v1.2.3


From d35c003cc53d4723d1dfe0d81eeb9bea78cee594 Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Sat, 31 Dec 2011 16:01:24 +0100
Subject: new crypter plugin API, now decrypting possible for now.

---
 module/Api.py | 52 ++++++++++++++++++++++++++--------------------------
 1 file changed, 26 insertions(+), 26 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index 99fb4c1e7..deac1a19f 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -285,12 +285,13 @@ class Api(Iface):
         return data
 
     @permission(PERMS.ADD)
-    def addPackage(self, name, links, dest=Destination.Queue):
+    def addPackage(self, name, links, dest=Destination.Queue, password=""):
         """Adds a package, with links to desired destination.
 
         :param name: name of the new package
         :param links: list of urls
         :param dest: `Destination`
+        :param password: password as string, can be empty
         :return: package id of the new package
         """
         if self.core.config['general']['folder_per_package']:
@@ -300,15 +301,28 @@ class Api(Iface):
 
         folder = folder.replace("http://", "").replace(":", "").replace("/", "_").replace("\\", "_")
 
-        pid = self.core.files.addPackage(name, folder, dest)
+        self.core.log.info(_("Added package %(name)s containing %(count)d links") % {"name": name, "count": len(links)})
+        pid = self.core.files.addPackage(name, folder, dest, password)
+        self.addFiles(pid, links)
 
-        self.core.files.addLinks(links, pid)
+        return pid
 
-        self.core.log.info(_("Added package %(name)s containing %(count)d links") % {"name": name, "count": len(links)})
+    @permission(PERMS.ADD)
+    def addFiles(self, pid, links):
+        """Adds files to specific package.
 
-        self.core.files.save()
+        :param pid: package id
+        :param links: list of urls
+        """
+        hoster, crypter = self.core.pluginManager.parseUrls(links)
 
-        return pid
+        self.core.files.addLinks(hoster, pid)
+
+        self.core.threadManager.createInfoThread(hoster, pid)
+        self.core.threadManager.createDecryptThread(crypter, pid)
+
+        self.core.log.info(_("Added %(count)d links to package #%(package)d ") % {"count": len(links), "package": pid})
+        self.core.files.save()
 
     @permission(PERMS.ADD)
     def parseURLs(self, html=None, url=None):
@@ -337,7 +351,7 @@ class Api(Iface):
         :param urls:
         :return: {plugin: urls}
         """
-        data = self.core.pluginManager.parseUrls(urls)
+        data, crypter = self.core.pluginManager.parseUrls(urls)
         plugins = {}
 
         for url, plugin in data:
@@ -355,7 +369,7 @@ class Api(Iface):
         :param urls:
         :return: initial set of data as `OnlineCheck` instance containing the result id
         """
-        data = self.core.pluginManager.parseUrls(urls)
+        data, crypter = self.core.pluginManager.parseUrls(urls)
 
         rid = self.core.threadManager.createResultThread(data, False)
 
@@ -431,7 +445,7 @@ class Api(Iface):
         :param dest: `Destination`
         :return: None
         """
-        data = self.core.pluginManager.parseUrls(links)
+        data, crypter = self.core.pluginManager.parseUrls(links)
         self.core.threadManager.createResultThread(data, True)
 
 
@@ -557,19 +571,6 @@ class Api(Iface):
             links=[self._convertPyFile(x) for x in pack["links"].itervalues()])
                 for pack in self.core.files.getCompleteData(Destination.Collector).itervalues()]
 
-
-    @permission(PERMS.ADD)
-    def addFiles(self, pid, links):
-        """Adds files to specific package.
-        
-        :param pid: package id
-        :param links: list of urls
-        """
-        self.core.files.addLinks(links, int(pid))
-
-        self.core.log.info(_("Added %(count)d links to package #%(package)d ") % {"count": len(links), "package": pid})
-        self.core.files.save()
-
     @permission(PERMS.MODIFY)
     def pushToQueue(self, pid):
         """Moves package from Collector to Queue.
@@ -925,8 +926,8 @@ class Api(Iface):
         user = self.checkAuth(username, password)
         if user:
             return UserData(user["name"], user["email"], user["role"], user["permission"], user["template"])
-        else:
-            return UserData()
+
+        raise UserDoesNotExists(username)
 
 
     def getAllUserData(self):
@@ -972,13 +973,12 @@ class Api(Iface):
         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)
+            ret = self.core.hookManager.callRPC(plugin, func, args)
             return str(ret)
         except Exception, e:
             raise ServiceException(e.message)
-- 
cgit v1.2.3


From 35742c2cb023ac49ab3056752d2040cdb030cc2b Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Sun, 1 Jan 2012 13:36:59 +0100
Subject: Happy new Year !

---
 module/Api.py | 34 +++++++++++++---------------------
 1 file changed, 13 insertions(+), 21 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index deac1a19f..810613b66 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -17,10 +17,12 @@
     @author: RaNaN
 """
 
+import re
 from base64 import standard_b64encode
 from os.path import join
 from time import time
-import re
+from itertools import chain
+
 
 from PyFile import PyFile
 from utils import freeSpace, compare_time
@@ -321,7 +323,7 @@ class Api(Iface):
         self.core.threadManager.createInfoThread(hoster, pid)
         self.core.threadManager.createDecryptThread(crypter, pid)
 
-        self.core.log.info(_("Added %(count)d links to package #%(package)d ") % {"count": len(links), "package": pid})
+        self.core.log.debug("Added %d links to package #%d " % (len(hoster), pid))
         self.core.files.save()
 
     @permission(PERMS.ADD)
@@ -354,7 +356,7 @@ class Api(Iface):
         data, crypter = self.core.pluginManager.parseUrls(urls)
         plugins = {}
 
-        for url, plugin in data:
+        for url, plugin in chain(data, crypter):
             if plugin in plugins:
                 plugins[plugin].append(url)
             else:
@@ -364,15 +366,14 @@ class Api(Iface):
 
     @permission(PERMS.ADD)
     def checkOnlineStatus(self, urls):
-        """ initiates online status check
+        """ initiates online status check, will also decrypt files.
 
         :param urls:
         :return: initial set of data as `OnlineCheck` instance containing the result id
         """
         data, crypter = self.core.pluginManager.parseUrls(urls)
 
-        rid = self.core.threadManager.createResultThread(data, False)
-
+        # initial result does not contain the crypter links
         tmp = [(url, (url, OnlineStatus(url, pluginname, "unknown", 3, 0))) for url, pluginname in data]
         data = parseNames(tmp)
         result = {}
@@ -382,6 +383,9 @@ class Api(Iface):
                 status.packagename = k
                 result[url] = status
 
+        data.update(crypter) # hoster and crypter will be processed
+        rid = self.core.threadManager.createResultThread(data, False)
+
         return OnlineCheck(rid, result)
 
     @permission(PERMS.ADD)
@@ -396,8 +400,8 @@ class Api(Iface):
         th = open(join(self.core.config["general"]["download_folder"], "tmp_" + container), "wb")
         th.write(str(data))
         th.close()
-
-        return self.checkOnlineStatus(urls + [th.name])
+        urls.append(th.name)
+        return self.checkOnlineStatus(urls)
 
     @permission(PERMS.ADD)
     def pollResults(self, rid):
@@ -436,18 +440,6 @@ class Api(Iface):
         return [self.addPackage(name, urls, dest) for name, urls
                 in self.generatePackages(links).iteritems()]
 
-    @permission(PERMS.ADD)
-    def checkAndAddPackages(self, links, dest=Destination.Queue):
-        """Checks online status, retrieves names, and will add packages.\
-        Because of this packages are not added immediatly, only for internal use.
-
-        :param links: list of urls
-        :param dest: `Destination`
-        :return: None
-        """
-        data, crypter = self.core.pluginManager.parseUrls(links)
-        self.core.threadManager.createResultThread(data, True)
-
 
     @permission(PERMS.LIST)
     def getPackageData(self, pid):
@@ -677,7 +669,7 @@ class Api(Iface):
         th.write(str(data))
         th.close()
 
-        self.addPackage(th.name, [th.name], Destination.Queue)
+        self.addPackage(th.name, [th.name])
 
     @permission(PERMS.MODIFY)
     def orderPackage(self, pid, position):
-- 
cgit v1.2.3


From 5a3e5a8228e4c5421b44d18c9c9ae2f1fe616400 Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Sun, 1 Jan 2012 18:01:25 +0100
Subject: fixed imports

---
 module/Api.py | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index 810613b66..e6bd10762 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -318,7 +318,8 @@ class Api(Iface):
         """
         hoster, crypter = self.core.pluginManager.parseUrls(links)
 
-        self.core.files.addLinks(hoster, pid)
+	if hoster:
+            self.core.files.addLinks(hoster, pid)
 
         self.core.threadManager.createInfoThread(hoster, pid)
         self.core.threadManager.createDecryptThread(crypter, pid)
@@ -998,4 +999,4 @@ class Api(Iface):
 
     def setUserPermission(self, user, permission, role):
         self.core.db.setPermission(user, permission)
-        self.core.db.setRole(user, role)
\ No newline at end of file
+        self.core.db.setRole(user, role)
-- 
cgit v1.2.3


From 593455fc8beca8c722bddb19e38d4a98e5dbf787 Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Tue, 3 Jan 2012 19:23:34 +0100
Subject: closed #483

---
 module/Api.py | 28 ++++------------------------
 1 file changed, 4 insertions(+), 24 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index e6bd10762..bafb69408 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -813,28 +813,8 @@ class Api(Iface):
         :param uuid:
         :return: list of `Events`
         """
-        events = self.core.pullManager.getEvents(uuid)
-        newEvents = []
-
-        def convDest(d):
-            return Destination.Queue if d == "queue" else Destination.Collector
-
-        for e in events:
-            event = EventInfo()
-            event.eventname = 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
+        # TODO
+        pass
 
     @permission(PERMS.ACCOUNTS)
     def getAccounts(self, refresh):
@@ -854,9 +834,9 @@ class Api(Iface):
     def getAccountTypes(self):
         """All available account types.
 
-        :return: list
+        :return: string list
         """
-        return self.core.pluginManager.getPlugins("account").keys()
+        return self.core.pluginManager.getPlugins("accounts").keys()
 
     @permission(PERMS.ACCOUNTS)
     def updateAccount(self, plugin, account, password=None, options={}):
-- 
cgit v1.2.3


From b877847094b0ba03a098dff0fd769eb456b48dd1 Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Fri, 6 Jan 2012 17:54:53 +0100
Subject: several improvements, also closes #486, #487

---
 module/Api.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index bafb69408..769fcdf0d 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -810,7 +810,7 @@ class Api(Iface):
     def getEvents(self, uuid):
         """Lists occured events, may be affected to changes in future.
 
-        :param uuid:
+        :param uuid: self assigned string uuid which has to be unique
         :return: list of `Events`
         """
         # TODO
-- 
cgit v1.2.3


From 03ec7f017c882c304be1d0759a348d5305f27d42 Mon Sep 17 00:00:00 2001
From: zoidberg10 <zoidberg@mujmail.cz>
Date: Sat, 7 Jan 2012 23:15:49 +0100
Subject: xfilesharengprofolder using new crypter api, allow slash in package
 name

---
 module/Api.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index 769fcdf0d..d707b18fc 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -301,7 +301,7 @@ class Api(Iface):
         else:
             folder = ""
 
-        folder = folder.replace("http://", "").replace(":", "").replace("/", "_").replace("\\", "_")
+        folder = folder.replace("http://", "").replace(":", "").replace("\\", "_")  #.replace("/", "_")
 
         self.core.log.info(_("Added package %(name)s containing %(count)d links") % {"name": name, "count": len(links)})
         pid = self.core.files.addPackage(name, folder, dest, password)
-- 
cgit v1.2.3


From 6eaa7bb25e2254c80c43fe46166142d590e86c64 Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Sat, 7 Jan 2012 23:58:28 +0100
Subject: some cleanups

---
 module/Api.py | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index d707b18fc..11b06ff32 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -25,11 +25,10 @@ from itertools import chain
 
 
 from PyFile import PyFile
-from utils import freeSpace, compare_time
+from utils import freeSpace, compare_time, to_string
 from common.packagetools import parseNames
 from network.RequestFactory import getURL
 from remote import activated
-from config.converter import to_string
 
 if activated:
     try:
@@ -134,7 +133,7 @@ class Api(Iface):
     @permission(PERMS.SETTINGS)
     def getConfig(self):
         """Retrieves complete config of core.
-        
+
         :return: list of `ConfigSection`
         """
         return [ConfigSection(section, data.name, data.description, data.long_desc, [
@@ -198,7 +197,7 @@ class Api(Iface):
     @permission(PERMS.LIST)
     def statusServer(self):
         """Some general information about the current status of pyLoad.
-        
+
         :return: `ServerStatus`
         """
         serverStatus = ServerStatus(self.core.threadManager.pause, len(self.core.threadManager.processingIds()),
@@ -318,7 +317,7 @@ class Api(Iface):
         """
         hoster, crypter = self.core.pluginManager.parseUrls(links)
 
-	if hoster:
+        if hoster:
             self.core.files.addLinks(hoster, pid)
 
         self.core.threadManager.createInfoThread(hoster, pid)
@@ -495,7 +494,7 @@ class Api(Iface):
     @permission(PERMS.DELETE)
     def deleteFiles(self, fids):
         """Deletes several file entries from pyload.
-        
+
         :param fids: list of file ids
         """
         for id in fids:
-- 
cgit v1.2.3


From 1ecdd9f6b53fec45e1d48592e3ff56aa7a576bec Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Sun, 8 Jan 2012 16:47:52 +0100
Subject: some cleanups, closed #490

---
 module/Api.py | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index 11b06ff32..fba02d574 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -19,7 +19,7 @@
 
 import re
 from base64 import standard_b64encode
-from os.path import join
+from os.path import join, isabs
 from time import time
 from itertools import chain
 
@@ -300,7 +300,10 @@ class Api(Iface):
         else:
             folder = ""
 
-        folder = folder.replace("http://", "").replace(":", "").replace("\\", "_")  #.replace("/", "_")
+        if isabs(folder):
+            folder = folder.replace("/", "_")
+
+        folder = folder.replace("http://", "").replace(":", "").replace("\\", "_").replace("..", "")
 
         self.core.log.info(_("Added package %(name)s containing %(count)d links") % {"name": name, "count": len(links)})
         pid = self.core.files.addPackage(name, folder, dest, password)
-- 
cgit v1.2.3


From cda057e979cbdc8022687e1810b876b371c8c11f Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Fri, 13 Jan 2012 10:58:51 +0100
Subject: fix info page, removed icons

---
 module/Api.py | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index fba02d574..ac9ea7f79 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -25,7 +25,8 @@ from itertools import chain
 
 
 from PyFile import PyFile
-from utils import freeSpace, compare_time, to_string
+from utils import compare_time, to_string
+from utils.fs import free_space
 from common.packagetools import parseNames
 from network.RequestFactory import getURL
 from remote import activated
@@ -213,7 +214,7 @@ class Api(Iface):
     @permission(PERMS.STATUS)
     def freeSpace(self):
         """Available free space at download directory in bytes"""
-        return freeSpace(self.core.config["general"]["download_folder"])
+        return free_space(self.core.config["general"]["download_folder"])
 
     @permission(PERMS.ALL)
     def getServerVersion(self):
-- 
cgit v1.2.3


From f791fb1a40240595ddc8d5b77b359f70253a0d10 Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Fri, 20 Jan 2012 21:28:55 +0100
Subject: closed #519

---
 module/Api.py | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index ac9ea7f79..5dc8916b1 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -137,10 +137,10 @@ class Api(Iface):
 
         :return: list of `ConfigSection`
         """
-        return [ConfigSection(section, data.name, data.description, data.long_desc, [
-        ConfigItem(option, d.name, d.description, d.type, d.default, self.core.config.get(section, option)) for
-        option, d in data.config.iteritems()]) for
-                section, data in self.core.config.getBaseSectionns()]
+        return dict([(section, ConfigSection(section, data.name, data.description, data.long_desc, [
+        ConfigItem(option, d.name, d.description, d.type, to_string(d.default), to_string(self.core.config.get(section, option))) for
+        option, d in data.config.iteritems()])) for
+                section, data in self.core.config.getBaseSections()])
 
 
     @permission(PERMS.SETTINGS)
@@ -149,13 +149,15 @@ class Api(Iface):
 
         :return: list of `ConfigSection`
         """
-        return [ConfigSection(section, data.name, data.description, data.long_desc) for
-                section, data in self.core.config.getPluginSections()]
+        return dict([(section, ConfigSection(section,
+            data.name, data.description, data.long_desc)) for
+                section, data in self.core.config.getPluginSections()])
 
     def configureSection(self, section):
         data = self.core.config.config[section]
         sec = ConfigSection(section, data.name, data.description, data.long_desc)
-        sec.items = [ConfigItem(option, d.name, d.description, d.type, d.default, self.core.config.get(section, option))
+        sec.items = [ConfigItem(option, d.name, d.description,
+            d.type, to_string(d.default), to_string(self.core.config.get(section, option)))
                      for
                      option, d in data.config.iteritems()]
 
-- 
cgit v1.2.3


From edb879de69bd258021aae8a600418d21ec2a377f Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Sat, 21 Jan 2012 18:21:06 +0100
Subject: return pid for uploadContainer

---
 module/Api.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index 5dc8916b1..e5d26631f 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -675,7 +675,7 @@ class Api(Iface):
         th.write(str(data))
         th.close()
 
-        self.addPackage(th.name, [th.name])
+        return self.addPackage(th.name, [th.name])
 
     @permission(PERMS.MODIFY)
     def orderPackage(self, pid, position):
-- 
cgit v1.2.3


From 4df2b77fdf42046fe19bd371be7c7255986b5980 Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Tue, 6 Mar 2012 13:36:39 +0100
Subject: renamed hooks to addons, new filemanager and database, many new api
 methods you will loose ALL your LINKS, webinterface will NOT work

---
 module/Api.py | 770 ++++++++++++++++++++++++++++------------------------------
 1 file changed, 377 insertions(+), 393 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index e5d26631f..84712af18 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -23,12 +23,6 @@ from os.path import join, isabs
 from time import time
 from itertools import chain
 
-
-from PyFile import PyFile
-from utils import compare_time, to_string
-from utils.fs import free_space
-from common.packagetools import parseNames
-from network.RequestFactory import getURL
 from remote import activated
 
 if activated:
@@ -43,6 +37,12 @@ if activated:
 else:
     from remote.socketbackend.ttypes import *
 
+from PyFile import PyFile
+from utils import compare_time, to_string, bits_set
+from utils.fs import free_space
+from common.packagetools import parseNames
+from network.RequestFactory import getURL
+
 # contains function names mapped to their permissions
 # unlisted functions are for admins only
 permMap = {}
@@ -64,12 +64,13 @@ class PERMS:
     ADD = 1  # can add packages
     DELETE = 2 # can delete packages
     STATUS = 4   # see and change server status
-    LIST = 16 # see queue and collector
+    LIST = 16 # see listed downloads
     MODIFY = 32 # moddify some attribute of downloads
     DOWNLOAD = 64  # can download from webinterface
     SETTINGS = 128 # can access settings
     ACCOUNTS = 256 # can access accounts
     LOGS = 512 # can see server logs
+    INTERACTION = 1024 # can interact with plugins
 
 
 class ROLE:
@@ -78,15 +79,14 @@ class ROLE:
 
 
 def has_permission(userperms, perms):
-    # bytewise or perms before if needed
-    return perms == (userperms & perms)
+    return bits_set(perms, userperms)
 
 
 class Api(Iface):
     """
     **pyLoads API**
 
-    This is accessible either internal via core.api or via thrift backend.
+    This is accessible either internal via core.api, thrift backend or json api.
 
     see Thrift specification file remote/thriftbackend/pyload.thrift\
     for information about data structures and what methods are usuable with rpc.
@@ -101,73 +101,30 @@ class Api(Iface):
     def __init__(self, core):
         self.core = core
 
-    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"])
-        return f
-
-    @permission(PERMS.SETTINGS)
-    def getConfigValue(self, section, option):
-        """Retrieve config value.
-
-        :param section: name of category, or plugin
-        :param option: config option
-        :return: config value as string
-        """
-        value = self.core.config.get(section, option)
-        return to_string(value)
-
-    @permission(PERMS.SETTINGS)
-    def setConfigValue(self, section, option, value):
-        """Set new config value.
-
-        :param section:
-        :param option:
-        :param value: new config value
-        """
-        if option in ("limit_speed", "max_speed"): #not so nice to update the limit
-            self.core.requestFactory.updateBucket()
-
-        self.core.config.set(section, option, value)
-
-    @permission(PERMS.SETTINGS)
-    def getConfig(self):
-        """Retrieves complete config of core.
-
-        :return: list of `ConfigSection`
-        """
-        return dict([(section, ConfigSection(section, data.name, data.description, data.long_desc, [
-        ConfigItem(option, d.name, d.description, d.type, to_string(d.default), to_string(self.core.config.get(section, option))) for
-        option, d in data.config.iteritems()])) for
-                section, data in self.core.config.getBaseSections()])
+    ##########################
+    #  Server Status
+    ##########################
 
+    @permission(PERMS.ALL)
+    def getServerVersion(self):
+        """pyLoad Core version """
+        return self.core.version
 
-    @permission(PERMS.SETTINGS)
-    def getPluginConfig(self):
-        """Retrieves complete config for all plugins.
+    @permission(PERMS.LIST)
+    def statusServer(self):
+        """Some general information about the current status of pyLoad.
 
-        :return: list of `ConfigSection`
+        :return: `ServerStatus`
         """
-        return dict([(section, ConfigSection(section,
-            data.name, data.description, data.long_desc)) for
-                section, data in self.core.config.getPluginSections()])
-
-    def configureSection(self, section):
-        data = self.core.config.config[section]
-        sec = ConfigSection(section, data.name, data.description, data.long_desc)
-        sec.items = [ConfigItem(option, d.name, d.description,
-            d.type, to_string(d.default), to_string(self.core.config.get(section, option)))
-                     for
-                     option, d in data.config.iteritems()]
-
-        #TODO: config handler
+        serverStatus = ServerStatus(self.core.threadManager.pause, len(self.core.threadManager.processingIds()),
+            self.core.files.getQueueCount(), self.core.files.getFileCount(), 0,
+            not self.core.threadManager.pause and self.isTimeDownload(),
+            self.core.config['reconnect']['activated'] and self.isTimeReconnect())
 
-        return sec
+        for pyfile in [x.active for x in self.core.threadManager.threads if x.active and isinstance(x.active, PyFile)]:
+            serverStatus.speed += pyfile.getSpeed() #bytes/s
 
-    def getConfigPointer(self):
-        """Config instance, not for RPC"""
-        return self.core.config
+        return serverStatus
 
     @permission(PERMS.STATUS)
     def pauseServer(self):
@@ -197,31 +154,11 @@ class Api(Iface):
         self.core.config["reconnect"]["activated"] ^= True
         return self.core.config["reconnect"]["activated"]
 
-    @permission(PERMS.LIST)
-    def statusServer(self):
-        """Some general information about the current status of pyLoad.
-
-        :return: `ServerStatus`
-        """
-        serverStatus = ServerStatus(self.core.threadManager.pause, len(self.core.threadManager.processingIds()),
-            self.core.files.getQueueCount(), self.core.files.getFileCount(), 0,
-            not self.core.threadManager.pause and self.isTimeDownload(),
-            self.core.config['reconnect']['activated'] and self.isTimeReconnect())
-
-        for pyfile in [x.active for x in self.core.threadManager.threads if x.active and isinstance(x.active, PyFile)]:
-            serverStatus.speed += pyfile.getSpeed() #bytes/s
-
-        return serverStatus
-
     @permission(PERMS.STATUS)
     def freeSpace(self):
         """Available free space at download directory in bytes"""
         return free_space(self.core.config["general"]["download_folder"])
 
-    @permission(PERMS.ALL)
-    def getServerVersion(self):
-        """pyLoad Core version """
-        return self.core.version
 
     def kill(self):
         """Clean way to quit pyLoad"""
@@ -269,18 +206,22 @@ class Api(Iface):
         end = self.core.config['reconnect']['endTime'].split(":")
         return compare_time(start, end) and self.core.config["reconnect"]["activated"]
 
-    @permission(PERMS.LIST)
-    def statusDownloads(self):
-        """ Status off all currently running downloads.
 
-        :return: list of `DownloadStatus`
+    def scanDownloadFolder(self):
+        pass
+
+    @permission(PERMS.STATUS)
+    def getProgressInfo(self):
+        """ Status of all currently running tasks
+
+        :return: list of `ProgressInfo`
         """
         data = []
         for pyfile in self.core.threadManager.getActiveFiles():
             if not isinstance(pyfile, PyFile):
                 continue
 
-            data.append(DownloadInfo(
+            data.append(ProgressInfo(
                 pyfile.id, pyfile.name, pyfile.getSpeed(), pyfile.getETA(), pyfile.formatETA(),
                 pyfile.getBytesLeft(), pyfile.getSize(), pyfile.formatSize(), pyfile.getPercent(),
                 pyfile.status, pyfile.getStatusName(), pyfile.formatWait(),
@@ -288,49 +229,81 @@ class Api(Iface):
 
         return data
 
-    @permission(PERMS.ADD)
-    def addPackage(self, name, links, dest=Destination.Queue, password=""):
-        """Adds a package, with links to desired destination.
+    ##########################
+    #  Configuration
+    ##########################
 
-        :param name: name of the new package
-        :param links: list of urls
-        :param dest: `Destination`
-        :param password: password as string, can be empty
-        :return: package id of the new package
+    @permission(PERMS.SETTINGS)
+    def getConfigValue(self, section, option):
+        """Retrieve config value.
+
+        :param section: name of category, or plugin
+        :param option: config option
+        :return: config value as string
         """
-        if self.core.config['general']['folder_per_package']:
-            folder = name
-        else:
-            folder = ""
+        value = self.core.config.get(section, option)
+        return to_string(value)
 
-        if isabs(folder):
-            folder = folder.replace("/", "_")
+    @permission(PERMS.SETTINGS)
+    def setConfigValue(self, section, option, value):
+        """Set new config value.
 
-        folder = folder.replace("http://", "").replace(":", "").replace("\\", "_").replace("..", "")
+        :param section:
+        :param option:
+        :param value: new config value
+        """
+        if option in ("limit_speed", "max_speed"): #not so nice to update the limit
+            self.core.requestFactory.updateBucket()
+
+        self.core.config.set(section, option, value)
 
-        self.core.log.info(_("Added package %(name)s containing %(count)d links") % {"name": name, "count": len(links)})
-        pid = self.core.files.addPackage(name, folder, dest, password)
-        self.addFiles(pid, links)
+    @permission(PERMS.SETTINGS)
+    def getConfig(self):
+        """Retrieves complete config of core.
 
-        return pid
+        :return: list of `ConfigSection`
+        """
+        return dict([(section, ConfigSection(section, data.name, data.description, data.long_desc, [
+        ConfigItem(option, d.name, d.description, d.type, to_string(d.default), to_string(self.core.config.get(section, option))) for
+        option, d in data.config.iteritems()])) for
+                section, data in self.core.config.getBaseSections()])
 
-    @permission(PERMS.ADD)
-    def addFiles(self, pid, links):
-        """Adds files to specific package.
 
-        :param pid: package id
-        :param links: list of urls
+    @permission(PERMS.SETTINGS)
+    def getPluginConfig(self):
+        """Retrieves complete config for all plugins.
+
+        :return: list of `ConfigSection`
         """
-        hoster, crypter = self.core.pluginManager.parseUrls(links)
+        return dict([(section, ConfigSection(section,
+            data.name, data.description, data.long_desc)) for
+                section, data in self.core.config.getPluginSections()])
 
-        if hoster:
-            self.core.files.addLinks(hoster, pid)
+    @permission(PERMS.SETTINGS)
+    def configureSection(self, section):
+        data = self.core.config.config[section]
+        sec = ConfigSection(section, data.name, data.description, data.long_desc)
+        sec.items = [ConfigItem(option, d.name, d.description,
+            d.type, to_string(d.default), to_string(self.core.config.get(section, option)))
+                     for
+                     option, d in data.config.iteritems()]
 
-        self.core.threadManager.createInfoThread(hoster, pid)
-        self.core.threadManager.createDecryptThread(crypter, pid)
+        #TODO: config handler
 
-        self.core.log.debug("Added %d links to package #%d " % (len(hoster), pid))
-        self.core.files.save()
+        return sec
+
+
+    @permission(PERMS.SETTINGS)
+    def setConfigHandler(self, plugin, iid, value):
+        pass
+
+    def getConfigRef(self):
+        """Config instance, not for RPC"""
+        return self.core.config
+
+    ##########################
+    #  Download Preparing
+    ##########################
 
     @permission(PERMS.ADD)
     def parseURLs(self, html=None, url=None):
@@ -375,12 +348,12 @@ class Api(Iface):
         """ initiates online status check, will also decrypt files.
 
         :param urls:
-        :return: initial set of data as `OnlineCheck` instance containing the result id
+        :return: initial set of data as :class:`OnlineCheck` instance containing the result id
         """
         data, crypter = self.core.pluginManager.parseUrls(urls)
 
         # initial result does not contain the crypter links
-        tmp = [(url, (url, OnlineStatus(url, pluginname, "unknown", 3, 0))) for url, pluginname in data]
+        tmp = [(url, (url, LinkStatus(url, pluginname, "unknown", 3, 0))) for url, pluginname in data]
         data = parseNames(tmp)
         result = {}
 
@@ -401,7 +374,7 @@ class Api(Iface):
         :param urls: list of urls
         :param container: container file name
         :param data: file content
-        :return: online check
+        :return: :class:`OnlineCheck`
         """
         th = open(join(self.core.config["general"]["download_folder"], "tmp_" + container), "wb")
         th.write(str(data))
@@ -435,67 +408,110 @@ class Api(Iface):
         result = parseNames((x, x) for x in links)
         return result
 
+    ##########################
+    #  Adding/Deleting
+    ##########################
+
     @permission(PERMS.ADD)
-    def generateAndAddPackages(self, links, dest=Destination.Queue):
+    def generateAndAddPackages(self, links, paused=False):
         """Generates and add packages
 
         :param links: list of urls
-        :param dest: `Destination`
+        :param paused: paused package
         :return: list of package ids
         """
-        return [self.addPackage(name, urls, dest) for name, urls
+        return [self.addPackageP(name, urls, "", paused) for name, urls
                 in self.generatePackages(links).iteritems()]
 
+    @permission(PERMS.ADD)
+    def autoAddLinks(self, links):
+        pass
 
-    @permission(PERMS.LIST)
-    def getPackageData(self, pid):
-        """Returns complete information about package, and included files.
+    @permission(PERMS.ADD)
+    def createPackage(self, name, folder, root, password="", site="", comment="", paused=False):
+        """Create a new package.
 
-        :param pid: package id
-        :return: `PackageData` with .links attribute
+        :param name: display name of the package
+        :param folder: folder name or relative path, abs path are not allowed
+        :param root: package id of root package, -1 for top level package
+        :param password: single pw or list of passwords seperated with new line
+        :param site: arbitrary url to site for more information
+        :param comment: arbitrary comment
+        :param paused: No downloads will be started when True
+        :return: pid of newly created package
         """
-        data = self.core.files.getPackageData(int(pid))
 
-        if not data:
-            raise PackageDoesNotExists(pid)
+        if isabs(folder):
+           folder = folder.replace("/", "_")
 
-        pdata = PackageData(data["id"], data["name"], data["folder"], data["site"], data["password"],
-            data["queue"], data["order"],
-            links=[self._convertPyFile(x) for x in data["links"].itervalues()])
+        folder = folder.replace("http://", "").replace(":", "").replace("\\", "_").replace("..", "")
 
-        return pdata
+        self.core.log.info(_("Added package %(name)s as folder %(folder)s") % {"name": name, "folder": folder})
+        pid = self.core.files.addPackage(name, folder, root, password, site, comment, paused)
 
-    @permission(PERMS.LIST)
-    def getPackageInfo(self, pid):
-        """Returns information about package, without detailed information about containing files
+        return pid
 
-        :param pid: package id
-        :return: `PackageData` with .fid attribute
+
+    @permission(PERMS.ADD)
+    def addPackage(self, name, links, password=""):
+        """Convenient method to add a package to top-level and adding links.
+
+        :return: package id
         """
-        data = self.core.files.getPackageData(int(pid))
+        self.addPackageChild(name, links, password, -1, False)
 
-        if not data:
-            raise PackageDoesNotExists(pid)
+    @permission(PERMS.ADD)
+    def addPackageP(self, name, links, password, paused):
+        """ Same as above with additional paused attribute. """
+        self.addPackageChild(name, links, password, -1, paused)
 
-        pdata = PackageData(data["id"], data["name"], data["folder"], data["site"], data["password"],
-            data["queue"], data["order"],
-            fids=[int(x) for x in data["links"]])
+    @permission(PERMS.ADD)
+    def addPackageChild(self, name, links, password, root, paused):
+       """Adds a package, with links to desired package.
 
-        return pdata
+       :param root: parents package id
+       :return: package id of the new package
+       """
+       if self.core.config['general']['folder_per_package']:
+           folder = name
+       else:
+           folder = ""
 
-    @permission(PERMS.LIST)
-    def getFileData(self, fid):
-        """Get complete information about a specific file.
+       pid = self.createPackage(name, folder, root, password)
+       self.addLinks(pid, links)
 
-        :param fid: file id
-        :return: `FileData`
-        """
-        info = self.core.files.getFileData(int(fid))
-        if not info:
-            raise FileDoesNotExists(fid)
+       return pid
+
+    @permission(PERMS.ADD)
+    def addLinks(self, pid, links):
+       """Adds links to specific package. Automatical starts online status fetching.
+
+       :param pid: package id
+       :param links: list of urls
+       """
+       hoster, crypter = self.core.pluginManager.parseUrls(links)
+
+       if hoster:
+           self.core.files.addLinks(hoster, pid)
+           self.core.threadManager.createInfoThread(hoster, pid)
+
+       self.core.threadManager.createDecryptThread(crypter, pid)
+
+       self.core.log.info((_("Added %d links to package") + " #%d" % pid) % len(hoster))
+       self.core.files.save()
+
+    @permission(PERMS.ADD)
+    def uploadContainer(self, filename, data):
+       """Uploads and adds a container file to pyLoad.
+
+       :param filename: filename, extension is important so it can correctly decrypted
+       :param data: file content
+       """
+       th = open(join(self.core.config["general"]["download_folder"], "tmp_" + filename), "wb")
+       th.write(str(data))
+       th.close()
 
-        fdata = self._convertPyFile(info.values()[0])
-        return fdata
+       return self.addPackage(th.name, [th.name])
 
     @permission(PERMS.DELETE)
     def deleteFiles(self, fids):
@@ -503,8 +519,8 @@ class Api(Iface):
 
         :param fids: list of file ids
         """
-        for id in fids:
-            self.core.files.deleteLink(int(id))
+        for fid in fids:
+            self.core.files.deleteFile(fid)
 
         self.core.files.save()
 
@@ -514,76 +530,113 @@ class Api(Iface):
 
         :param pids: list of package ids
         """
-        for id in pids:
-            self.core.files.deletePackage(int(id))
+        for pid in pids:
+            self.core.files.deletePackage(pid)
 
         self.core.files.save()
 
+    ##########################
+    #  Collector
+    ##########################
+
     @permission(PERMS.LIST)
-    def getQueue(self):
-        """Returns info about queue and packages, **not** about files, see `getQueueData` \
-        or `getPackageData` instead.
+    def getCollector(self):
+        pass
 
-        :return: list of `PackageInfo`
-        """
-        return [PackageData(pack["id"], pack["name"], pack["folder"], pack["site"],
-            pack["password"], pack["queue"], pack["order"],
-            pack["linksdone"], pack["sizedone"], pack["sizetotal"],
-            pack["linkstotal"])
-                for pack in self.core.files.getInfoData(Destination.Queue).itervalues()]
+    @permission(PERMS.ADD)
+    def addToCollector(self, links):
+        pass
+
+    @permission(PERMS.ADD)
+    def addFromCollector(self, name, paused):
+        pass
+
+    @permission(PERMS.DELETE)
+    def deleteCollPack(self, name):
+        pass
+
+    @permission(PERMS.DELETE)
+    def deleteCollLink(self, url):
+        pass
+
+    @permission(PERMS.ADD)
+    def renameCollPack(self, name, new_name):
+        pass
+
+    #############################
+    #  File Information retrival
+    #############################
 
     @permission(PERMS.LIST)
-    def getQueueData(self):
-        """Return complete data about everything in queue, this is very expensive use it sparely.\
-           See `getQueue` for alternative.
+    def getAllFiles(self):
+        """ same as `getFileTree` for toplevel root and full tree"""
+        return self.getFileTree(-1, True)
 
-        :return: list of `PackageData`
-        """
-        return [PackageData(pack["id"], pack["name"], pack["folder"], pack["site"],
-            pack["password"], pack["queue"], pack["order"],
-            pack["linksdone"], pack["sizedone"], pack["sizetotal"],
-            links=[self._convertPyFile(x) for x in pack["links"].itervalues()])
-                for pack in self.core.files.getCompleteData(Destination.Queue).itervalues()]
+    @permission(PERMS.LIST)
+    def getAllUnfinishedFiles(self):
+        """ same as `getUnfinishedFileTree for toplevel root and full tree"""
+        return self.getUnfinishedFileTree(-1, True)
 
     @permission(PERMS.LIST)
-    def getCollector(self):
-        """same as `getQueue` for collector.
+    def getFileTree(self, pid, full):
+        """ Retrieve data for specific package. full=True will retrieve all data available
+            and can result in greater delays.
 
-        :return: list of `PackageInfo`
+        :param pid: package id
+        :param full: go down the complete tree or only the first layer
+        :return: :class:`PackageView`
         """
-        return [PackageData(pack["id"], pack["name"], pack["folder"], pack["site"],
-            pack["password"], pack["queue"], pack["order"],
-            pack["linksdone"], pack["sizedone"], pack["sizetotal"],
-            pack["linkstotal"])
-                for pack in self.core.files.getInfoData(Destination.Collector).itervalues()]
+        return self.core.files.getView(pid, full, False)
 
     @permission(PERMS.LIST)
-    def getCollectorData(self):
-        """same as `getQueueData` for collector.
+    def getUnfinishedFileTree(self, pid, full):
+        """ Same as `getFileTree` but only contains unfinished files.
 
-        :return: list of `PackageInfo`
+        :param pid: package id
+        :param full: go down the complete tree or only the first layer
+        :return: :class:`PackageView`
         """
-        return [PackageData(pack["id"], pack["name"], pack["folder"], pack["site"],
-            pack["password"], pack["queue"], pack["order"],
-            pack["linksdone"], pack["sizedone"], pack["sizetotal"],
-            links=[self._convertPyFile(x) for x in pack["links"].itervalues()])
-                for pack in self.core.files.getCompleteData(Destination.Collector).itervalues()]
+        return self.core.files.getView(pid, full, False)
 
-    @permission(PERMS.MODIFY)
-    def pushToQueue(self, pid):
-        """Moves package from Collector to Queue.
+    @permission(PERMS.LIST)
+    def getPackageContent(self, pid):
+        """  Only retrieve content of a specific package. see `getFileTree`"""
+        return self.getFileTree(pid, False)
+
+    @permission(PERMS.LIST)
+    def getPackageInfo(self, pid):
+        """Returns information about package, without detailed information about containing files
 
         :param pid: package id
+        :raises PackageDoesNotExists:
+        :return: :class:`PackageInfo`
         """
-        self.core.files.setPackageLocation(pid, Destination.Queue)
+        info = self.core.files.getPackageInfo(pid)
+        if not info:
+            raise PackageDoesNotExists(pid)
+        return info
 
-    @permission(PERMS.MODIFY)
-    def pullFromQueue(self, pid):
-        """Moves package from Queue to Collector.
+    @permission(PERMS.LIST)
+    def getFileInfo(self, fid):
+        """ Info for specific file
+
+        :param fid: file id
+        :raises FileDoesNotExists:
+        :return: :class:`FileInfo`
 
-        :param pid: package id
         """
-        self.core.files.setPackageLocation(pid, Destination.Collector)
+        info = self.core.files.getFileInfo(fid)
+        if not info:
+            raise FileDoesNotExists(fid)
+        return info
+
+    @permission(PERMS.LIST)
+    def findFiles(self, pattern):
+        pass
+
+    #############################
+    #  Modify Downloads
+    #############################
 
     @permission(PERMS.MODIFY)
     def restartPackage(self, pid):
@@ -591,30 +644,26 @@ class Api(Iface):
 
         :param pid: package id
         """
-        self.core.files.restartPackage(int(pid))
+        self.core.files.restartPackage(pid)
 
     @permission(PERMS.MODIFY)
     def restartFile(self, fid):
         """Resets file status, so it will be downloaded again.
 
-        :param fid:  file id
+        :param fid: file id
         """
-        self.core.files.restartFile(int(fid))
+        self.core.files.restartFile(fid)
 
     @permission(PERMS.MODIFY)
     def recheckPackage(self, pid):
-        """Proofes online status of all files in a package, also a default action when package is added.
-
-        :param pid:
-        :return:
-        """
-        self.core.files.reCheckPackage(int(pid))
+        """Check online status of all files in a package, also a default action when package is added. """
+        self.core.files.reCheckPackage(pid)
 
     @permission(PERMS.MODIFY)
     def stopAllDownloads(self):
         """Aborts all running downloads."""
 
-        pyfiles = self.core.files.cache.values()
+        pyfiles = self.core.files.cachedFiles()
         for pyfile in pyfiles:
             pyfile.abortDownload()
 
@@ -625,75 +674,76 @@ class Api(Iface):
         :param fids: list of file ids
         :return:
         """
-        pyfiles = self.core.files.cache.values()
-
+        pyfiles = self.core.files.cachedFiles()
         for pyfile in pyfiles:
             if pyfile.id in fids:
                 pyfile.abortDownload()
 
     @permission(PERMS.MODIFY)
-    def setPackageName(self, pid, name):
-        """Renames a package.
+    def restartFailed(self):
+        """Restarts all failed failes."""
+        self.core.files.restartFailed()
 
-        :param pid: package id
-        :param name: new package name
-        """
-        pack = self.core.files.getPackage(pid)
-        pack.name = name
-        pack.sync()
+    #############################
+    #  Modify Files/Packages
+    #############################
 
     @permission(PERMS.MODIFY)
-    def movePackage(self, destination, pid):
-        """Set a new package location.
+    def setFilePaused(self, fid, paused):
+        pass
+
+    @permission(PERMS.MODIFY)
+    def setPackagePaused(self, pid, paused):
+        pass
+
+    @permission(PERMS.MODIFY)
+    def setPackageFolder(self, pid, path):
+        pass
+
+    @permission(PERMS.MODIFY)
+    def movePackage(self, pid, root):
+        """ Set a new root for specific package. This will also moves the files on disk\
+           and will only work when no file is currently downloading.
 
-        :param destination: `Destination`
         :param pid: package id
+        :param root: package id of new root
+        :raises PackageDoesNotExists: When pid or root is missing
+        :return: False if package can't be moved
         """
-        if destination not in (0, 1): return
-        self.core.files.setPackageLocation(pid, destination)
+        return self.core.files.movePackage(pid, root)
 
     @permission(PERMS.MODIFY)
     def moveFiles(self, fids, pid):
-        """Move multiple files to another package
+        """Move multiple files to another package. This will move the files on disk and\
+        only work when files are not downloading. All files needs to be continuous ordered
+        in the current package.
 
         :param fids: list of file ids
         :param pid: destination package
-        :return:
-        """
-        #TODO: implement
-        pass
-
-
-    @permission(PERMS.ADD)
-    def uploadContainer(self, filename, data):
-        """Uploads and adds a container file to pyLoad.
-
-        :param filename: filename, extension is important so it can correctly decrypted
-        :param data: file content
+        :return: False if files can't be moved
         """
-        th = open(join(self.core.config["general"]["download_folder"], "tmp_" + filename), "wb")
-        th.write(str(data))
-        th.close()
-
-        return self.addPackage(th.name, [th.name])
+        return self.core.files.moveFiles(fids, pid)
 
     @permission(PERMS.MODIFY)
     def orderPackage(self, pid, position):
-        """Gives a package a new position.
+        """Set new position for a package.
 
         :param pid: package id
-        :param position: 
+        :param position: new position, 0 for very beginning
         """
-        self.core.files.reorderPackage(pid, position)
+        self.core.files.orderPackage(pid, position)
 
     @permission(PERMS.MODIFY)
-    def orderFile(self, fid, position):
-        """Gives a new position to a file within its package.
+    def orderFiles(self, fids, pid, position):
+        """ Set a new position for a bunch of files within a package.
+        All files have to be in the same package and must be **continuous**\
+        in the package. That means no gaps between them.
 
-        :param fid: file id
-        :param position:
+        :param fids: list of file ids
+        :param pid: package id of parent package
+        :param position:  new position: 0 for very beginning
         """
-        self.core.files.reorderFile(fid, position)
+        self.core.files.orderFiles(fids, pid, position)
 
     @permission(PERMS.MODIFY)
     def setPackageData(self, pid, data):
@@ -712,104 +762,38 @@ class Api(Iface):
         p.sync()
         self.core.files.save()
 
-    @permission(PERMS.DELETE)
-    def deleteFinished(self):
-        """Deletes all finished files and completly finished packages.
-
-        :return: list of deleted package ids
-        """
-        return self.core.files.deleteFinishedLinks()
-
-    @permission(PERMS.MODIFY)
-    def restartFailed(self):
-        """Restarts all failed failes."""
-        self.core.files.restartFailed()
-
-    @permission(PERMS.LIST)
-    def getPackageOrder(self, destination):
-        """Returns information about package order.
+    #############################
+    #  User Interaction
+    #############################
 
-        :param destination: `Destination`
-        :return: dict mapping order to package id
-        """
-
-        packs = self.core.files.getInfoData(destination)
-        order = {}
-
-        for pid in packs:
-            pack = self.core.files.getPackageData(int(pid))
-            while pack["order"] in order.keys(): #just in case
-                pack["order"] += 1
-            order[pack["order"]] = pack["id"]
-        return order
-
-    @permission(PERMS.LIST)
-    def getFileOrder(self, pid):
-        """Information about file order within package.
-
-        :param pid:
-        :return: dict mapping order to file id
-        """
-        rawData = self.core.files.getPackageData(int(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
-
-
-    @permission(PERMS.STATUS)
-    def isCaptchaWaiting(self):
-        """Indicates wether a captcha task is available
 
-        :return: bool
-        """
-        self.core.lastClientConnected = time()
-        task = self.core.captchaManager.getTask()
-        return not task is None
+    @permission(PERMS.INTERACTION)
+    def isInteractionWaiting(self, mode):
+        pass
 
-    @permission(PERMS.STATUS)
-    def getCaptchaTask(self, exclusive=False):
-        """Returns a captcha task
-
-        :param exclusive: unused
-        :return: `CaptchaTask`
-        """
-        self.core.lastClientConnected = time()
-        task = self.core.captchaManager.getTask()
-        if task:
-            task.setWatingForUser(exclusive=exclusive)
-            data, type, result = task.getCaptcha()
-            t = CaptchaTask(int(task.id), standard_b64encode(data), type, result)
-            return t
-        else:
-            return CaptchaTask(-1)
+    @permission(PERMS.INTERACTION)
+    def getInteractionTask(self, mode):
+        pass
 
-    @permission(PERMS.STATUS)
-    def getCaptchaTaskStatus(self, tid):
-        """Get information about captcha task
+    @permission(PERMS.INTERACTION)
+    def setInteractionResult(self, iid, result):
+        pass
 
-        :param tid: task id
-        :return: string
-        """
-        self.core.lastClientConnected = time()
-        t = self.core.captchaManager.getTaskByID(tid)
-        return t.getStatus() if t else ""
+    @permission(PERMS.INTERACTION)
+    def getAddonHandler(self):
+        pass
 
-    @permission(PERMS.STATUS)
-    def setCaptchaResult(self, tid, result):
-        """Set result for a captcha task
+    @permission(PERMS.INTERACTION)
+    def callAddonHandler(self, plugin, func, pid_or_fid):
+        pass
 
-        :param tid: task id
-        :param result: captcha result
-        """
-        self.core.lastClientConnected = time()
-        task = self.core.captchaManager.getTaskByID(tid)
-        if task:
-            task.setResult(result)
-            self.core.captchaManager.removeTask(task)
+    @permission(PERMS.DOWNLOAD)
+    def generateDownloadLink(self, fid, timeout):
+        pass
 
+    #############################
+    #  Event Handling
+    #############################
 
     @permission(PERMS.STATUS)
     def getEvents(self, uuid):
@@ -821,6 +805,10 @@ class Api(Iface):
         # TODO
         pass
 
+    #############################
+    #  Account Methods
+    #############################
+
     @permission(PERMS.ACCOUNTS)
     def getAccounts(self, refresh):
         """Get information about all entered accounts.
@@ -857,6 +845,10 @@ class Api(Iface):
         """
         self.core.accountManager.removeAccount(plugin, account)
 
+    #############################
+    #  Auth+User Information
+    #############################
+
     @permission(PERMS.ALL)
     def login(self, username, password, remoteip=None):
         """Login into pyLoad, this **must** be called when using rpc before any methods can be used.
@@ -881,6 +873,8 @@ class Api(Iface):
         if self.core.startedInGui and remoteip == "127.0.0.1":
             return "local"
 
+        self.core.log.info(_("User '%s' tried to log in") % username)
+
         return self.core.db.checkAuth(username, password)
 
     def isAuthorized(self, func, userdata):
@@ -907,7 +901,6 @@ class Api(Iface):
 
         raise UserDoesNotExists(username)
 
-
     def getAllUserData(self):
         """returns all known user and info"""
         res = {}
@@ -916,58 +909,57 @@ class Api(Iface):
 
         return res
 
-    @permission(PERMS.STATUS)
+    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)
+
+    #############################
+    #  RPC Plugin Methods
+    #############################
+
+    @permission(PERMS.INTERACTION)
     def getServices(self):
-        """ A dict of available services, these can be defined by hook plugins.
+        """ A dict of available services, these can be defined by addon plugins.
 
         :return: dict with this style: {"plugin": {"method": "description"}}
         """
         data = {}
-        for plugin, funcs in self.core.hookManager.methods.iteritems():
+        for plugin, funcs in self.core.addonManager.methods.iteritems():
             data[plugin] = funcs
 
         return data
 
-    @permission(PERMS.STATUS)
+    @permission(PERMS.INTERACTION)
     def hasService(self, plugin, func):
-        """Checks wether a service is available.
+        pass
 
-        :param plugin:
-        :param func:
-        :return: bool
-        """
-        cont = self.core.hookManager.methods
-        return plugin in cont and func in cont[plugin]
+    @permission(PERMS.INTERACTION)
+    def call(self, plugin, func, arguments):
+        """Calls a service (a method in addon plugin).
 
-    @permission(PERMS.STATUS)
-    def call(self, info):
-        """Calls a service (a method in hook plugin).
-
-        :param info: `ServiceCall`
-        :return: result
         :raises: ServiceDoesNotExists, when its not available
         :raises: ServiceException, when a exception was raised
         """
-        plugin = info.plugin
-        func = info.func
-        args = info.arguments
-
         if not self.hasService(plugin, func):
             raise ServiceDoesNotExists(plugin, func)
 
         try:
-            ret = self.core.hookManager.callRPC(plugin, func, args)
-            return str(ret)
+            ret = self.core.addonManager.callRPC(plugin, func, arguments)
+            return to_string(ret)
         except Exception, e:
             raise ServiceException(e.message)
 
     @permission(PERMS.STATUS)
     def getAllInfo(self):
-        """Returns all information stored by hook plugins. Values are always strings
+        """Returns all information stored by addon plugins. Values are always strings
 
         :return: {"plugin": {"name": value } }
         """
-        return self.core.hookManager.getAllInfo()
+        return self.core.addonManager.getAllInfo()
 
     @permission(PERMS.STATUS)
     def getInfoByPlugin(self, plugin):
@@ -976,12 +968,4 @@ class Api(Iface):
         :param plugin: pluginname
         :return: dict of attr names mapped to value {"name": value}
         """
-        return self.core.hookManager.getInfo(plugin)
-
-    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)
+        return self.core.addonManager.getInfo(plugin)
-- 
cgit v1.2.3


From 50d4df8b4d48b855bd18e9922355b7f3f2b4da4e Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Tue, 20 Mar 2012 14:57:45 +0100
Subject: captcha decrypting for all plugin types, new interaction manager

---
 module/Api.py | 35 +++++++++++++++++++++++++++++++----
 1 file changed, 31 insertions(+), 4 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index 84712af18..6d7ac75b6 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -766,18 +766,45 @@ class Api(Iface):
     #  User Interaction
     #############################
 
-
     @permission(PERMS.INTERACTION)
     def isInteractionWaiting(self, mode):
-        pass
+        """ Check if task is waiting.
+
+        :param mode: binary or'ed output type
+        :return: boolean
+        """
+        return self.core.interactionManager.isTaskWaiting(mode)
 
     @permission(PERMS.INTERACTION)
     def getInteractionTask(self, mode):
-        pass
+        """Retrieve task for specific mode.
+
+        :param mode: binary or'ed output type
+        :return: :class:`InteractionTask`
+        """
+        task = self.core.interactionManager.getTask(mode)
+        return InteractionTask(-1) if  not task else task
+
 
     @permission(PERMS.INTERACTION)
     def setInteractionResult(self, iid, result):
-        pass
+        """Set Result for a interaction task. It will be immediately removed from task queue afterwards
+
+        :param iid: interaction id
+        :param result: result as string
+        """
+        task = self.core.interactionManager.getTaskByID(iid)
+        if task:
+            task.setResult(result)
+
+    @permission(PERMS.INTERACTION)
+    def getNotifications(self):
+        """List of all available notifcations. They stay in queue for some time, client should\
+           save which notifications it already has seen.
+
+        :return: list of :class:`InteractionTask`
+        """
+        return self.core.interactionManager.getNotifications()
 
     @permission(PERMS.INTERACTION)
     def getAddonHandler(self):
-- 
cgit v1.2.3


From b40b32ee05f611323a7827fad2a25fa0a28dcb24 Mon Sep 17 00:00:00 2001
From: X3n0m0rph59 <X3n0m0rph59@googlemail.com>
Date: Sun, 22 Apr 2012 19:56:17 +0200
Subject: a huge pile of spelling fixes

---
 module/Api.py | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index 6d7ac75b6..d85680cd5 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -89,10 +89,10 @@ class Api(Iface):
     This is accessible either internal via core.api, thrift backend or json api.
 
     see Thrift specification file remote/thriftbackend/pyload.thrift\
-    for information about data structures and what methods are usuable with rpc.
+    for information about data structures and what methods are usable with rpc.
 
     Most methods requires specific permissions, please look at the source code if you need to know.\
-    These can be configured via webinterface.
+    These can be configured via web interface.
     Admin user have all permissions, and are the only ones who can access the methods with no specific permission.
     """
 
@@ -128,7 +128,7 @@ class Api(Iface):
 
     @permission(PERMS.STATUS)
     def pauseServer(self):
-        """Pause server: Tt wont start any new downloads, but nothing gets aborted."""
+        """Pause server: It won't start any new downloads, but nothing gets aborted."""
         self.core.threadManager.pause = True
 
     @permission(PERMS.STATUS)
@@ -307,7 +307,7 @@ class Api(Iface):
 
     @permission(PERMS.ADD)
     def parseURLs(self, html=None, url=None):
-        """Parses html content or any arbitaty text for links and returns result of `checkURLs`
+        """Parses html content or any arbitrary text for links and returns result of `checkURLs`
 
         :param html: html source
         :return:
@@ -327,7 +327,7 @@ class Api(Iface):
 
     @permission(PERMS.ADD)
     def checkURLs(self, urls):
-        """ Gets urls and returns pluginname mapped to list of matches urls.
+        """ Gets urls and returns pluginname mapped to list of matching urls.
 
         :param urls:
         :return: {plugin: urls}
@@ -369,7 +369,7 @@ class Api(Iface):
 
     @permission(PERMS.ADD)
     def checkOnlineStatusContainer(self, urls, container, data):
-        """ checks online status of urls and a submited container file
+        """ checks online status of urls and a submitted container file
 
         :param urls: list of urls
         :param container: container file name
@@ -387,7 +387,7 @@ class Api(Iface):
         """ Polls the result available for ResultID
 
         :param rid: `ResultID`
-        :return: `OnlineCheck`, if rid is -1 then no more data available
+        :return: `OnlineCheck`, if rid is -1 then there is no more data available
         """
         result = self.core.threadManager.getInfoResult(rid)
 
@@ -434,7 +434,7 @@ class Api(Iface):
         :param name: display name of the package
         :param folder: folder name or relative path, abs path are not allowed
         :param root: package id of root package, -1 for top level package
-        :param password: single pw or list of passwords seperated with new line
+        :param password: single pw or list of passwords separated with new line
         :param site: arbitrary url to site for more information
         :param comment: arbitrary comment
         :param paused: No downloads will be started when True
@@ -454,7 +454,7 @@ class Api(Iface):
 
     @permission(PERMS.ADD)
     def addPackage(self, name, links, password=""):
-        """Convenient method to add a package to top-level and adding links.
+        """Convenient method to add a package to the top-level and for adding links.
 
         :return: package id
         """
@@ -484,7 +484,7 @@ class Api(Iface):
 
     @permission(PERMS.ADD)
     def addLinks(self, pid, links):
-       """Adds links to specific package. Automatical starts online status fetching.
+       """Adds links to specific package. Initiates online status fetching.
 
        :param pid: package id
        :param links: list of urls
-- 
cgit v1.2.3


From f36bb35cf296c74ff5a3676c038e2ef2a8be9068 Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Sun, 6 May 2012 17:22:13 +0200
Subject: concept for multiuser api

---
 module/Api.py | 152 +++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 113 insertions(+), 39 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index d85680cd5..c969045f8 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -18,10 +18,11 @@
 """
 
 import re
-from base64 import standard_b64encode
 from os.path import join, isabs
-from time import time
 from itertools import chain
+from functools import partial
+from new import code
+from dis import opmap
 
 from remote import activated
 
@@ -45,17 +46,57 @@ from network.RequestFactory import getURL
 
 # contains function names mapped to their permissions
 # unlisted functions are for admins only
-permMap = {}
+perm_map = {}
+
+# store which methods needs user context
+user_context = {}
 
 # decorator only called on init, never initialized, so has no effect on runtime
 def permission(bits):
     class _Dec(object):
         def __new__(cls, func, *args, **kwargs):
-            permMap[func.__name__] = bits
+            perm_map[func.__name__] = bits
             return func
 
     return _Dec
 
+# we will bytehacking the method to add user as keyword argument
+class UserContext(object):
+    """Decorator to mark methods that require a specific user"""
+
+    def __new__(cls, f, *args, **kwargs):
+        fc = f.func_code
+
+        try:
+            i = fc.co_names.index("user")
+        except ValueError: # functions does not uses user, so no need to modify
+            return f
+
+        user_context[f.__name__] = True
+        new_names = tuple([x for x in fc.co_names if f != "user"])
+        new_varnames = tuple([x for x in fc.co_varnames] + ["user"])
+        new_code = fc.co_code
+
+        # subtract 1 from higher LOAD_GLOBAL
+        for x in range(i + 1, len(fc.co_names)):
+            new_code = new_code.replace(chr(opmap['LOAD_GLOBAL']) + chr(x), chr(opmap['LOAD_GLOBAL']) + chr(x - 1))
+
+        # load argument instead of global
+        new_code = new_code.replace(chr(opmap['LOAD_GLOBAL']) + chr(i), chr(opmap['LOAD_FAST']) + chr(fc.co_argcount))
+
+        new_fc = code(fc.co_argcount + 1, fc.co_nlocals + 1, fc.co_stacksize, fc.co_flags, new_code, fc.co_consts,
+            new_names, new_varnames, fc.co_filename, fc.co_name, fc.co_firstlineno, fc.co_lnotab, fc.co_freevars,
+            fc.co_cellvars)
+
+        f.func_code = new_fc
+
+        # None as default argument for user
+        if f.func_defaults:
+            f.func_defaults = tuple([x for x in f.func_defaults] + [None])
+        else:
+            f.func_defaults = (None,)
+
+        return f
 
 urlmatcher = re.compile(r"((https?|ftps?|xdcc|sftp):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+\-=\\\.&]*)", re.IGNORECASE)
 
@@ -82,6 +123,21 @@ def has_permission(userperms, perms):
     return bits_set(perms, userperms)
 
 
+class UserApi(object):
+    """  Proxy object for api that provides all methods in user context """
+
+    def __init__(self, api, user):
+        self.api = api
+        self.user = user
+
+    def __getattr__(self, item):
+        f = self.api.__getattribute__(item)
+        if f.func_name in user_context:
+            return partial(f, user=self.user)
+
+        return f
+
+
 class Api(Iface):
     """
     **pyLoads API**
@@ -101,13 +157,30 @@ class Api(Iface):
     def __init__(self, core):
         self.core = core
 
+        self.t = self.inUserContext("TestUser")
+
+        print self.t.getServerVersion()
+
+
+    # TODO, create user instance, work
+    def inUserContext(self, user):
+        """ Returns a proxy version of the api, to call method in user context
+
+        :param user: user id
+        :return: :class:`UserApi`
+        """
+        return UserApi(self, user)
+
+
     ##########################
     #  Server Status
     ##########################
 
+    @UserContext #TODO: only for testing
     @permission(PERMS.ALL)
     def getServerVersion(self):
         """pyLoad Core version """
+        print user
         return self.core.version
 
     @permission(PERMS.LIST)
@@ -264,9 +337,10 @@ class Api(Iface):
         :return: list of `ConfigSection`
         """
         return dict([(section, ConfigSection(section, data.name, data.description, data.long_desc, [
-        ConfigItem(option, d.name, d.description, d.type, to_string(d.default), to_string(self.core.config.get(section, option))) for
+        ConfigItem(option, d.name, d.description, d.type, to_string(d.default),
+            to_string(self.core.config.get(section, option))) for
         option, d in data.config.iteritems()])) for
-                section, data in self.core.config.getBaseSections()])
+                                                section, data in self.core.config.getBaseSections()])
 
 
     @permission(PERMS.SETTINGS)
@@ -277,7 +351,7 @@ class Api(Iface):
         """
         return dict([(section, ConfigSection(section,
             data.name, data.description, data.long_desc)) for
-                section, data in self.core.config.getPluginSections()])
+                                                          section, data in self.core.config.getPluginSections()])
 
     @permission(PERMS.SETTINGS)
     def configureSection(self, section):
@@ -442,7 +516,7 @@ class Api(Iface):
         """
 
         if isabs(folder):
-           folder = folder.replace("/", "_")
+            folder = folder.replace("/", "_")
 
         folder = folder.replace("http://", "").replace(":", "").replace("\\", "_").replace("..", "")
 
@@ -467,51 +541,51 @@ class Api(Iface):
 
     @permission(PERMS.ADD)
     def addPackageChild(self, name, links, password, root, paused):
-       """Adds a package, with links to desired package.
+        """Adds a package, with links to desired package.
 
-       :param root: parents package id
-       :return: package id of the new package
-       """
-       if self.core.config['general']['folder_per_package']:
-           folder = name
-       else:
-           folder = ""
+        :param root: parents package id
+        :return: package id of the new package
+        """
+        if self.core.config['general']['folder_per_package']:
+            folder = name
+        else:
+            folder = ""
 
-       pid = self.createPackage(name, folder, root, password)
-       self.addLinks(pid, links)
+        pid = self.createPackage(name, folder, root, password)
+        self.addLinks(pid, links)
 
-       return pid
+        return pid
 
     @permission(PERMS.ADD)
     def addLinks(self, pid, links):
-       """Adds links to specific package. Initiates online status fetching.
+        """Adds links to specific package. Initiates online status fetching.
 
-       :param pid: package id
-       :param links: list of urls
-       """
-       hoster, crypter = self.core.pluginManager.parseUrls(links)
+        :param pid: package id
+        :param links: list of urls
+        """
+        hoster, crypter = self.core.pluginManager.parseUrls(links)
 
-       if hoster:
-           self.core.files.addLinks(hoster, pid)
-           self.core.threadManager.createInfoThread(hoster, pid)
+        if hoster:
+            self.core.files.addLinks(hoster, pid)
+            self.core.threadManager.createInfoThread(hoster, pid)
 
-       self.core.threadManager.createDecryptThread(crypter, pid)
+        self.core.threadManager.createDecryptThread(crypter, pid)
 
-       self.core.log.info((_("Added %d links to package") + " #%d" % pid) % len(hoster))
-       self.core.files.save()
+        self.core.log.info((_("Added %d links to package") + " #%d" % pid) % len(hoster))
+        self.core.files.save()
 
     @permission(PERMS.ADD)
     def uploadContainer(self, filename, data):
-       """Uploads and adds a container file to pyLoad.
+        """Uploads and adds a container file to pyLoad.
 
-       :param filename: filename, extension is important so it can correctly decrypted
-       :param data: file content
-       """
-       th = open(join(self.core.config["general"]["download_folder"], "tmp_" + filename), "wb")
-       th.write(str(data))
-       th.close()
+        :param filename: filename, extension is important so it can correctly decrypted
+        :param data: file content
+        """
+        th = open(join(self.core.config["general"]["download_folder"], "tmp_" + filename), "wb")
+        th.write(str(data))
+        th.close()
 
-       return self.addPackage(th.name, [th.name])
+        return self.addPackage(th.name, [th.name])
 
     @permission(PERMS.DELETE)
     def deleteFiles(self, fids):
@@ -913,7 +987,7 @@ class Api(Iface):
         """
         if userdata == "local" or userdata["role"] == ROLE.ADMIN:
             return True
-        elif func in permMap and has_permission(userdata["permission"], permMap[func]):
+        elif func in perm_map and has_permission(userdata["permission"], perm_map[func]):
             return True
         else:
             return False
-- 
cgit v1.2.3


From 84efa9d5ccd46a0adddc256a5eba4f8e33c76afd Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Mon, 7 May 2012 18:42:29 +0200
Subject: new multiuser api methods

---
 module/Api.py | 181 +++++++++++++++++++++++++---------------------------------
 1 file changed, 78 insertions(+), 103 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index c969045f8..bab039ea1 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -52,7 +52,7 @@ perm_map = {}
 user_context = {}
 
 # decorator only called on init, never initialized, so has no effect on runtime
-def permission(bits):
+def RequirePerm(bits):
     class _Dec(object):
         def __new__(cls, func, *args, **kwargs):
             perm_map[func.__name__] = bits
@@ -100,27 +100,9 @@ class UserContext(object):
 
 urlmatcher = re.compile(r"((https?|ftps?|xdcc|sftp):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+\-=\\\.&]*)", re.IGNORECASE)
 
-class PERMS:
-    ALL = 0  # requires no permission, but login
-    ADD = 1  # can add packages
-    DELETE = 2 # can delete packages
-    STATUS = 4   # see and change server status
-    LIST = 16 # see listed downloads
-    MODIFY = 32 # moddify some attribute of downloads
-    DOWNLOAD = 64  # can download from webinterface
-    SETTINGS = 128 # can access settings
-    ACCOUNTS = 256 # can access accounts
-    LOGS = 512 # can see server logs
-    INTERACTION = 1024 # can interact with plugins
 
-
-class ROLE:
-    ADMIN = 0  #admin has all permissions implicit
-    USER = 1
-
-
-def has_permission(userperms, perms):
-    return bits_set(perms, userperms)
+def has_permission(userPermission, Permission):
+    return bits_set(Permission, userPermission)
 
 
 class UserApi(object):
@@ -157,13 +139,13 @@ class Api(Iface):
     def __init__(self, core):
         self.core = core
 
-        self.t = self.inUserContext("TestUser")
+        self.t = self.withUserContext("TestUser")
 
         print self.t.getServerVersion()
 
 
     # TODO, create user instance, work
-    def inUserContext(self, user):
+    def withUserContext(self, user):
         """ Returns a proxy version of the api, to call method in user context
 
         :param user: user id
@@ -177,13 +159,13 @@ class Api(Iface):
     ##########################
 
     @UserContext #TODO: only for testing
-    @permission(PERMS.ALL)
+    @RequirePerm(Permission.All)
     def getServerVersion(self):
         """pyLoad Core version """
         print user
         return self.core.version
 
-    @permission(PERMS.LIST)
+    @RequirePerm(Permission.List)
     def statusServer(self):
         """Some general information about the current status of pyLoad.
 
@@ -199,17 +181,17 @@ class Api(Iface):
 
         return serverStatus
 
-    @permission(PERMS.STATUS)
+    @RequirePerm(Permission.Status)
     def pauseServer(self):
         """Pause server: It won't start any new downloads, but nothing gets aborted."""
         self.core.threadManager.pause = True
 
-    @permission(PERMS.STATUS)
+    @RequirePerm(Permission.Status)
     def unpauseServer(self):
         """Unpause server: New Downloads will be started."""
         self.core.threadManager.pause = False
 
-    @permission(PERMS.STATUS)
+    @RequirePerm(Permission.Status)
     def togglePause(self):
         """Toggle pause state.
 
@@ -218,7 +200,7 @@ class Api(Iface):
         self.core.threadManager.pause ^= True
         return self.core.threadManager.pause
 
-    @permission(PERMS.STATUS)
+    @RequirePerm(Permission.Status)
     def toggleReconnect(self):
         """Toggle reconnect activation.
 
@@ -227,7 +209,7 @@ class Api(Iface):
         self.core.config["reconnect"]["activated"] ^= True
         return self.core.config["reconnect"]["activated"]
 
-    @permission(PERMS.STATUS)
+    @RequirePerm(Permission.Status)
     def freeSpace(self):
         """Available free space at download directory in bytes"""
         return free_space(self.core.config["general"]["download_folder"])
@@ -241,7 +223,6 @@ class Api(Iface):
         """Restart pyload core"""
         self.core.do_restart = True
 
-    @permission(PERMS.LOGS)
     def getLog(self, offset=0):
         """Returns most recent log entries.
 
@@ -259,7 +240,7 @@ class Api(Iface):
         except:
             return ['No log available']
 
-    @permission(PERMS.STATUS)
+    @RequirePerm(Permission.Status)
     def isTimeDownload(self):
         """Checks if pyload will start new downloads according to time in config.
 
@@ -269,7 +250,7 @@ class Api(Iface):
         end = self.core.config['downloadTime']['end'].split(":")
         return compare_time(start, end)
 
-    @permission(PERMS.STATUS)
+    @RequirePerm(Permission.Status)
     def isTimeReconnect(self):
         """Checks if pyload will try to make a reconnect
 
@@ -283,7 +264,7 @@ class Api(Iface):
     def scanDownloadFolder(self):
         pass
 
-    @permission(PERMS.STATUS)
+    @RequirePerm(Permission.Status)
     def getProgressInfo(self):
         """ Status of all currently running tasks
 
@@ -306,7 +287,6 @@ class Api(Iface):
     #  Configuration
     ##########################
 
-    @permission(PERMS.SETTINGS)
     def getConfigValue(self, section, option):
         """Retrieve config value.
 
@@ -317,7 +297,6 @@ class Api(Iface):
         value = self.core.config.get(section, option)
         return to_string(value)
 
-    @permission(PERMS.SETTINGS)
     def setConfigValue(self, section, option, value):
         """Set new config value.
 
@@ -330,7 +309,6 @@ class Api(Iface):
 
         self.core.config.set(section, option, value)
 
-    @permission(PERMS.SETTINGS)
     def getConfig(self):
         """Retrieves complete config of core.
 
@@ -343,7 +321,6 @@ class Api(Iface):
                                                 section, data in self.core.config.getBaseSections()])
 
 
-    @permission(PERMS.SETTINGS)
     def getPluginConfig(self):
         """Retrieves complete config for all plugins.
 
@@ -353,7 +330,6 @@ class Api(Iface):
             data.name, data.description, data.long_desc)) for
                                                           section, data in self.core.config.getPluginSections()])
 
-    @permission(PERMS.SETTINGS)
     def configureSection(self, section):
         data = self.core.config.config[section]
         sec = ConfigSection(section, data.name, data.description, data.long_desc)
@@ -367,7 +343,6 @@ class Api(Iface):
         return sec
 
 
-    @permission(PERMS.SETTINGS)
     def setConfigHandler(self, plugin, iid, value):
         pass
 
@@ -379,7 +354,7 @@ class Api(Iface):
     #  Download Preparing
     ##########################
 
-    @permission(PERMS.ADD)
+    @RequirePerm(Permission.Add)
     def parseURLs(self, html=None, url=None):
         """Parses html content or any arbitrary text for links and returns result of `checkURLs`
 
@@ -399,7 +374,7 @@ class Api(Iface):
         return self.checkURLs(set(urls))
 
 
-    @permission(PERMS.ADD)
+    @RequirePerm(Permission.Add)
     def checkURLs(self, urls):
         """ Gets urls and returns pluginname mapped to list of matching urls.
 
@@ -417,7 +392,7 @@ class Api(Iface):
 
         return plugins
 
-    @permission(PERMS.ADD)
+    @RequirePerm(Permission.Add)
     def checkOnlineStatus(self, urls):
         """ initiates online status check, will also decrypt files.
 
@@ -441,7 +416,7 @@ class Api(Iface):
 
         return OnlineCheck(rid, result)
 
-    @permission(PERMS.ADD)
+    @RequirePerm(Permission.Add)
     def checkOnlineStatusContainer(self, urls, container, data):
         """ checks online status of urls and a submitted container file
 
@@ -456,7 +431,7 @@ class Api(Iface):
         urls.append(th.name)
         return self.checkOnlineStatus(urls)
 
-    @permission(PERMS.ADD)
+    @RequirePerm(Permission.Add)
     def pollResults(self, rid):
         """ Polls the result available for ResultID
 
@@ -472,7 +447,7 @@ class Api(Iface):
             return OnlineCheck(rid, result)
 
 
-    @permission(PERMS.ADD)
+    @RequirePerm(Permission.Add)
     def generatePackages(self, links):
         """ Parses links, generates packages names from urls
 
@@ -486,7 +461,7 @@ class Api(Iface):
     #  Adding/Deleting
     ##########################
 
-    @permission(PERMS.ADD)
+    @RequirePerm(Permission.Add)
     def generateAndAddPackages(self, links, paused=False):
         """Generates and add packages
 
@@ -497,11 +472,11 @@ class Api(Iface):
         return [self.addPackageP(name, urls, "", paused) for name, urls
                 in self.generatePackages(links).iteritems()]
 
-    @permission(PERMS.ADD)
+    @RequirePerm(Permission.Add)
     def autoAddLinks(self, links):
         pass
 
-    @permission(PERMS.ADD)
+    @RequirePerm(Permission.Add)
     def createPackage(self, name, folder, root, password="", site="", comment="", paused=False):
         """Create a new package.
 
@@ -526,7 +501,7 @@ class Api(Iface):
         return pid
 
 
-    @permission(PERMS.ADD)
+    @RequirePerm(Permission.Add)
     def addPackage(self, name, links, password=""):
         """Convenient method to add a package to the top-level and for adding links.
 
@@ -534,12 +509,12 @@ class Api(Iface):
         """
         self.addPackageChild(name, links, password, -1, False)
 
-    @permission(PERMS.ADD)
+    @RequirePerm(Permission.Add)
     def addPackageP(self, name, links, password, paused):
         """ Same as above with additional paused attribute. """
         self.addPackageChild(name, links, password, -1, paused)
 
-    @permission(PERMS.ADD)
+    @RequirePerm(Permission.Add)
     def addPackageChild(self, name, links, password, root, paused):
         """Adds a package, with links to desired package.
 
@@ -556,7 +531,7 @@ class Api(Iface):
 
         return pid
 
-    @permission(PERMS.ADD)
+    @RequirePerm(Permission.Add)
     def addLinks(self, pid, links):
         """Adds links to specific package. Initiates online status fetching.
 
@@ -574,7 +549,7 @@ class Api(Iface):
         self.core.log.info((_("Added %d links to package") + " #%d" % pid) % len(hoster))
         self.core.files.save()
 
-    @permission(PERMS.ADD)
+    @RequirePerm(Permission.Add)
     def uploadContainer(self, filename, data):
         """Uploads and adds a container file to pyLoad.
 
@@ -587,7 +562,7 @@ class Api(Iface):
 
         return self.addPackage(th.name, [th.name])
 
-    @permission(PERMS.DELETE)
+    @RequirePerm(Permission.Delete)
     def deleteFiles(self, fids):
         """Deletes several file entries from pyload.
 
@@ -598,7 +573,7 @@ class Api(Iface):
 
         self.core.files.save()
 
-    @permission(PERMS.DELETE)
+    @RequirePerm(Permission.Delete)
     def deletePackages(self, pids):
         """Deletes packages and containing links.
 
@@ -613,27 +588,27 @@ class Api(Iface):
     #  Collector
     ##########################
 
-    @permission(PERMS.LIST)
+    @RequirePerm(Permission.List)
     def getCollector(self):
         pass
 
-    @permission(PERMS.ADD)
+    @RequirePerm(Permission.Add)
     def addToCollector(self, links):
         pass
 
-    @permission(PERMS.ADD)
+    @RequirePerm(Permission.Add)
     def addFromCollector(self, name, paused):
         pass
 
-    @permission(PERMS.DELETE)
+    @RequirePerm(Permission.Delete)
     def deleteCollPack(self, name):
         pass
 
-    @permission(PERMS.DELETE)
+    @RequirePerm(Permission.Delete)
     def deleteCollLink(self, url):
         pass
 
-    @permission(PERMS.ADD)
+    @RequirePerm(Permission.Add)
     def renameCollPack(self, name, new_name):
         pass
 
@@ -641,17 +616,17 @@ class Api(Iface):
     #  File Information retrival
     #############################
 
-    @permission(PERMS.LIST)
+    @RequirePerm(Permission.List)
     def getAllFiles(self):
         """ same as `getFileTree` for toplevel root and full tree"""
         return self.getFileTree(-1, True)
 
-    @permission(PERMS.LIST)
+    @RequirePerm(Permission.List)
     def getAllUnfinishedFiles(self):
         """ same as `getUnfinishedFileTree for toplevel root and full tree"""
         return self.getUnfinishedFileTree(-1, True)
 
-    @permission(PERMS.LIST)
+    @RequirePerm(Permission.List)
     def getFileTree(self, pid, full):
         """ Retrieve data for specific package. full=True will retrieve all data available
             and can result in greater delays.
@@ -662,7 +637,7 @@ class Api(Iface):
         """
         return self.core.files.getView(pid, full, False)
 
-    @permission(PERMS.LIST)
+    @RequirePerm(Permission.List)
     def getUnfinishedFileTree(self, pid, full):
         """ Same as `getFileTree` but only contains unfinished files.
 
@@ -672,12 +647,12 @@ class Api(Iface):
         """
         return self.core.files.getView(pid, full, False)
 
-    @permission(PERMS.LIST)
+    @RequirePerm(Permission.List)
     def getPackageContent(self, pid):
         """  Only retrieve content of a specific package. see `getFileTree`"""
         return self.getFileTree(pid, False)
 
-    @permission(PERMS.LIST)
+    @RequirePerm(Permission.List)
     def getPackageInfo(self, pid):
         """Returns information about package, without detailed information about containing files
 
@@ -690,7 +665,7 @@ class Api(Iface):
             raise PackageDoesNotExists(pid)
         return info
 
-    @permission(PERMS.LIST)
+    @RequirePerm(Permission.List)
     def getFileInfo(self, fid):
         """ Info for specific file
 
@@ -704,7 +679,7 @@ class Api(Iface):
             raise FileDoesNotExists(fid)
         return info
 
-    @permission(PERMS.LIST)
+    @RequirePerm(Permission.List)
     def findFiles(self, pattern):
         pass
 
@@ -712,7 +687,7 @@ class Api(Iface):
     #  Modify Downloads
     #############################
 
-    @permission(PERMS.MODIFY)
+    @RequirePerm(Permission.Modify)
     def restartPackage(self, pid):
         """Restarts a package, resets every containing files.
 
@@ -720,7 +695,7 @@ class Api(Iface):
         """
         self.core.files.restartPackage(pid)
 
-    @permission(PERMS.MODIFY)
+    @RequirePerm(Permission.Modify)
     def restartFile(self, fid):
         """Resets file status, so it will be downloaded again.
 
@@ -728,12 +703,12 @@ class Api(Iface):
         """
         self.core.files.restartFile(fid)
 
-    @permission(PERMS.MODIFY)
+    @RequirePerm(Permission.Modify)
     def recheckPackage(self, pid):
         """Check online status of all files in a package, also a default action when package is added. """
         self.core.files.reCheckPackage(pid)
 
-    @permission(PERMS.MODIFY)
+    @RequirePerm(Permission.Modify)
     def stopAllDownloads(self):
         """Aborts all running downloads."""
 
@@ -741,7 +716,7 @@ class Api(Iface):
         for pyfile in pyfiles:
             pyfile.abortDownload()
 
-    @permission(PERMS.MODIFY)
+    @RequirePerm(Permission.Modify)
     def stopDownloads(self, fids):
         """Aborts specific downloads.
 
@@ -753,7 +728,7 @@ class Api(Iface):
             if pyfile.id in fids:
                 pyfile.abortDownload()
 
-    @permission(PERMS.MODIFY)
+    @RequirePerm(Permission.Modify)
     def restartFailed(self):
         """Restarts all failed failes."""
         self.core.files.restartFailed()
@@ -762,19 +737,19 @@ class Api(Iface):
     #  Modify Files/Packages
     #############################
 
-    @permission(PERMS.MODIFY)
+    @RequirePerm(Permission.Modify)
     def setFilePaused(self, fid, paused):
         pass
 
-    @permission(PERMS.MODIFY)
+    @RequirePerm(Permission.Modify)
     def setPackagePaused(self, pid, paused):
         pass
 
-    @permission(PERMS.MODIFY)
+    @RequirePerm(Permission.Modify)
     def setPackageFolder(self, pid, path):
         pass
 
-    @permission(PERMS.MODIFY)
+    @RequirePerm(Permission.Modify)
     def movePackage(self, pid, root):
         """ Set a new root for specific package. This will also moves the files on disk\
            and will only work when no file is currently downloading.
@@ -786,7 +761,7 @@ class Api(Iface):
         """
         return self.core.files.movePackage(pid, root)
 
-    @permission(PERMS.MODIFY)
+    @RequirePerm(Permission.Modify)
     def moveFiles(self, fids, pid):
         """Move multiple files to another package. This will move the files on disk and\
         only work when files are not downloading. All files needs to be continuous ordered
@@ -798,7 +773,7 @@ class Api(Iface):
         """
         return self.core.files.moveFiles(fids, pid)
 
-    @permission(PERMS.MODIFY)
+    @RequirePerm(Permission.Modify)
     def orderPackage(self, pid, position):
         """Set new position for a package.
 
@@ -807,7 +782,7 @@ class Api(Iface):
         """
         self.core.files.orderPackage(pid, position)
 
-    @permission(PERMS.MODIFY)
+    @RequirePerm(Permission.Modify)
     def orderFiles(self, fids, pid, position):
         """ Set a new position for a bunch of files within a package.
         All files have to be in the same package and must be **continuous**\
@@ -819,7 +794,7 @@ class Api(Iface):
         """
         self.core.files.orderFiles(fids, pid, position)
 
-    @permission(PERMS.MODIFY)
+    @RequirePerm(Permission.Modify)
     def setPackageData(self, pid, data):
         """Allows to modify several package attributes.
 
@@ -840,7 +815,7 @@ class Api(Iface):
     #  User Interaction
     #############################
 
-    @permission(PERMS.INTERACTION)
+    @RequirePerm(Permission.Interaction)
     def isInteractionWaiting(self, mode):
         """ Check if task is waiting.
 
@@ -849,7 +824,7 @@ class Api(Iface):
         """
         return self.core.interactionManager.isTaskWaiting(mode)
 
-    @permission(PERMS.INTERACTION)
+    @RequirePerm(Permission.Interaction)
     def getInteractionTask(self, mode):
         """Retrieve task for specific mode.
 
@@ -860,7 +835,7 @@ class Api(Iface):
         return InteractionTask(-1) if  not task else task
 
 
-    @permission(PERMS.INTERACTION)
+    @RequirePerm(Permission.Interaction)
     def setInteractionResult(self, iid, result):
         """Set Result for a interaction task. It will be immediately removed from task queue afterwards
 
@@ -871,7 +846,7 @@ class Api(Iface):
         if task:
             task.setResult(result)
 
-    @permission(PERMS.INTERACTION)
+    @RequirePerm(Permission.Interaction)
     def getNotifications(self):
         """List of all available notifcations. They stay in queue for some time, client should\
            save which notifications it already has seen.
@@ -880,15 +855,15 @@ class Api(Iface):
         """
         return self.core.interactionManager.getNotifications()
 
-    @permission(PERMS.INTERACTION)
+    @RequirePerm(Permission.Interaction)
     def getAddonHandler(self):
         pass
 
-    @permission(PERMS.INTERACTION)
+    @RequirePerm(Permission.Interaction)
     def callAddonHandler(self, plugin, func, pid_or_fid):
         pass
 
-    @permission(PERMS.DOWNLOAD)
+    @RequirePerm(Permission.Download)
     def generateDownloadLink(self, fid, timeout):
         pass
 
@@ -896,7 +871,7 @@ class Api(Iface):
     #  Event Handling
     #############################
 
-    @permission(PERMS.STATUS)
+    @RequirePerm(Permission.Status)
     def getEvents(self, uuid):
         """Lists occured events, may be affected to changes in future.
 
@@ -910,7 +885,7 @@ class Api(Iface):
     #  Account Methods
     #############################
 
-    @permission(PERMS.ACCOUNTS)
+    @RequirePerm(Permission.Accounts)
     def getAccounts(self, refresh):
         """Get information about all entered accounts.
 
@@ -924,7 +899,7 @@ class Api(Iface):
 
         return accounts
 
-    @permission(PERMS.ALL)
+    @RequirePerm(Permission.All)
     def getAccountTypes(self):
         """All available account types.
 
@@ -932,12 +907,12 @@ class Api(Iface):
         """
         return self.core.pluginManager.getPlugins("accounts").keys()
 
-    @permission(PERMS.ACCOUNTS)
+    @RequirePerm(Permission.Accounts)
     def updateAccount(self, plugin, account, password=None, options={}):
         """Changes pw/options for specific account."""
         self.core.accountManager.updateAccount(plugin, account, password, options)
 
-    @permission(PERMS.ACCOUNTS)
+    @RequirePerm(Permission.Accounts)
     def removeAccount(self, plugin, account):
         """Remove account from pyload.
 
@@ -950,7 +925,7 @@ class Api(Iface):
     #  Auth+User Information
     #############################
 
-    @permission(PERMS.ALL)
+    @RequirePerm(Permission.All)
     def login(self, username, password, remoteip=None):
         """Login into pyLoad, this **must** be called when using rpc before any methods can be used.
 
@@ -993,7 +968,7 @@ class Api(Iface):
             return False
 
 
-    @permission(PERMS.ALL)
+    @RequirePerm(Permission.All)
     def getUserData(self, username, password):
         """similar to `checkAuth` but returns UserData thrift type """
         user = self.checkAuth(username, password)
@@ -1022,7 +997,7 @@ class Api(Iface):
     #  RPC Plugin Methods
     #############################
 
-    @permission(PERMS.INTERACTION)
+    @RequirePerm(Permission.Interaction)
     def getServices(self):
         """ A dict of available services, these can be defined by addon plugins.
 
@@ -1034,11 +1009,11 @@ class Api(Iface):
 
         return data
 
-    @permission(PERMS.INTERACTION)
+    @RequirePerm(Permission.Interaction)
     def hasService(self, plugin, func):
         pass
 
-    @permission(PERMS.INTERACTION)
+    @RequirePerm(Permission.Interaction)
     def call(self, plugin, func, arguments):
         """Calls a service (a method in addon plugin).
 
@@ -1054,7 +1029,7 @@ class Api(Iface):
         except Exception, e:
             raise ServiceException(e.message)
 
-    @permission(PERMS.STATUS)
+    @RequirePerm(Permission.Status)
     def getAllInfo(self):
         """Returns all information stored by addon plugins. Values are always strings
 
@@ -1062,7 +1037,7 @@ class Api(Iface):
         """
         return self.core.addonManager.getAllInfo()
 
-    @permission(PERMS.STATUS)
+    @RequirePerm(Permission.Status)
     def getInfoByPlugin(self, plugin):
         """Returns information stored by a specific plugin.
 
-- 
cgit v1.2.3


From 0d2d6daef850ac6bcc7fafccd230e52d2a862c2c Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Sun, 3 Jun 2012 17:45:10 +0200
Subject: updates for database + api

---
 module/Api.py | 60 +++++++++++++++++++++++++++++------------------------------
 1 file changed, 30 insertions(+), 30 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index bab039ea1..388dfd283 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -1,21 +1,20 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-"""
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License,
-    or (at your option) any later version.
 
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-    See the GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, see <http://www.gnu.org/licenses/>.
-
-    @author: RaNaN
-"""
+###############################################################################
+#   Copyright(c) 2008-2012 pyLoad Team
+#   http://www.pyload.org
+#
+#   This file is part of pyLoad.
+#   pyLoad is free software: you can redistribute it and/or modify
+#   it under the terms of the GNU Affero General Public License as
+#   published by the Free Software Foundation, either version 3 of the
+#   License, or (at your option) any later version.
+#
+#   Subjected to the terms and conditions in LICENSE
+#
+#   @author: RaNaN
+###############################################################################
 
 import re
 from os.path import join, isabs
@@ -38,8 +37,8 @@ if activated:
 else:
     from remote.socketbackend.ttypes import *
 
-from PyFile import PyFile
-from utils import compare_time, to_string, bits_set
+from datatypes import PyFile
+from utils import compare_time, to_string, bits_set, get_index
 from utils.fs import free_space
 from common.packagetools import parseNames
 from network.RequestFactory import getURL
@@ -60,7 +59,7 @@ def RequirePerm(bits):
 
     return _Dec
 
-# we will bytehacking the method to add user as keyword argument
+# we will byte-hacking the method to add user as keyword argument
 class UserContext(object):
     """Decorator to mark methods that require a specific user"""
 
@@ -68,7 +67,7 @@ class UserContext(object):
         fc = f.func_code
 
         try:
-            i = fc.co_names.index("user")
+            i = get_index(fc.co_names, "user")
         except ValueError: # functions does not uses user, so no need to modify
             return f
 
@@ -119,6 +118,7 @@ class UserApi(object):
 
         return f
 
+# TODO: fix permissions, user context manager
 
 class Api(Iface):
     """
@@ -144,7 +144,7 @@ class Api(Iface):
         print self.t.getServerVersion()
 
 
-    # TODO, create user instance, work
+    # TODO, create user instance
     def withUserContext(self, user):
         """ Returns a proxy version of the api, to call method in user context
 
@@ -165,7 +165,7 @@ class Api(Iface):
         print user
         return self.core.version
 
-    @RequirePerm(Permission.List)
+    @RequirePerm(Permission.Status)
     def statusServer(self):
         """Some general information about the current status of pyLoad.
 
@@ -588,7 +588,7 @@ class Api(Iface):
     #  Collector
     ##########################
 
-    @RequirePerm(Permission.List)
+    @RequirePerm(Permission.All)
     def getCollector(self):
         pass
 
@@ -616,17 +616,17 @@ class Api(Iface):
     #  File Information retrival
     #############################
 
-    @RequirePerm(Permission.List)
+    @RequirePerm(Permission.All)
     def getAllFiles(self):
         """ same as `getFileTree` for toplevel root and full tree"""
         return self.getFileTree(-1, True)
 
-    @RequirePerm(Permission.List)
+    @RequirePerm(Permission.All)
     def getAllUnfinishedFiles(self):
         """ same as `getUnfinishedFileTree for toplevel root and full tree"""
         return self.getUnfinishedFileTree(-1, True)
 
-    @RequirePerm(Permission.List)
+    @RequirePerm(Permission.All)
     def getFileTree(self, pid, full):
         """ Retrieve data for specific package. full=True will retrieve all data available
             and can result in greater delays.
@@ -637,7 +637,7 @@ class Api(Iface):
         """
         return self.core.files.getView(pid, full, False)
 
-    @RequirePerm(Permission.List)
+    @RequirePerm(Permission.All)
     def getUnfinishedFileTree(self, pid, full):
         """ Same as `getFileTree` but only contains unfinished files.
 
@@ -647,12 +647,12 @@ class Api(Iface):
         """
         return self.core.files.getView(pid, full, False)
 
-    @RequirePerm(Permission.List)
+    @RequirePerm(Permission.All)
     def getPackageContent(self, pid):
         """  Only retrieve content of a specific package. see `getFileTree`"""
         return self.getFileTree(pid, False)
 
-    @RequirePerm(Permission.List)
+    @RequirePerm(Permission.All)
     def getPackageInfo(self, pid):
         """Returns information about package, without detailed information about containing files
 
@@ -665,7 +665,7 @@ class Api(Iface):
             raise PackageDoesNotExists(pid)
         return info
 
-    @RequirePerm(Permission.List)
+    @RequirePerm(Permission.All)
     def getFileInfo(self, fid):
         """ Info for specific file
 
@@ -679,7 +679,7 @@ class Api(Iface):
             raise FileDoesNotExists(fid)
         return info
 
-    @RequirePerm(Permission.List)
+    @RequirePerm(Permission.All)
     def findFiles(self, pattern):
         pass
 
-- 
cgit v1.2.3


From 941e3021000e59020f66419cc2156aee30972121 Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Mon, 13 Aug 2012 17:40:10 +0200
Subject: working login

---
 module/Api.py | 63 ++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 32 insertions(+), 31 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index 388dfd283..26a6c757f 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -37,7 +37,7 @@ if activated:
 else:
     from remote.socketbackend.ttypes import *
 
-from datatypes import PyFile
+from datatypes.PyFile import PyFile
 from utils import compare_time, to_string, bits_set, get_index
 from utils.fs import free_space
 from common.packagetools import parseNames
@@ -103,21 +103,26 @@ urlmatcher = re.compile(r"((https?|ftps?|xdcc|sftp):((//)|(\\\\))+[\w\d:#@%/;$()
 def has_permission(userPermission, Permission):
     return bits_set(Permission, userPermission)
 
+from datatypes.User import User
 
 class UserApi(object):
     """  Proxy object for api that provides all methods in user context """
 
     def __init__(self, api, user):
         self.api = api
-        self.user = user
+        self._user = user
 
     def __getattr__(self, item):
         f = self.api.__getattribute__(item)
         if f.func_name in user_context:
-            return partial(f, user=self.user)
+            return partial(f, user=self._user)
 
         return f
 
+    @property
+    def user(self):
+        return self._user
+
 # TODO: fix permissions, user context manager
 
 class Api(Iface):
@@ -138,31 +143,31 @@ class Api(Iface):
 
     def __init__(self, core):
         self.core = core
+        self.user_apis = {}
 
-        self.t = self.withUserContext("TestUser")
-
-        print self.t.getServerVersion()
 
-
-    # TODO, create user instance
-    def withUserContext(self, user):
+    def withUserContext(self, uid):
         """ Returns a proxy version of the api, to call method in user context
 
-        :param user: user id
+        :param uid: user or userData instance or uid
         :return: :class:`UserApi`
         """
-        return UserApi(self, user)
+        if uid not in self.user_apis:
+            user = self.core.db.getUserData(uid=uid)
+            if not user: #TODO: anonymous user?
+                return None
+
+            self.user_apis[uid] = UserApi(self, User.fromUserData(self, user))
 
+        return self.user_apis[uid]
 
     ##########################
     #  Server Status
     ##########################
 
-    @UserContext #TODO: only for testing
     @RequirePerm(Permission.All)
     def getServerVersion(self):
         """pyLoad Core version """
-        print user
         return self.core.version
 
     @RequirePerm(Permission.Status)
@@ -873,7 +878,7 @@ class Api(Iface):
 
     @RequirePerm(Permission.Status)
     def getEvents(self, uuid):
-        """Lists occured events, may be affected to changes in future.
+        """Lists occurred events, may be affected to changes in future.
 
         :param uuid: self assigned string uuid which has to be unique
         :return: list of `Events`
@@ -925,6 +930,8 @@ class Api(Iface):
     #  Auth+User Information
     #############################
 
+    # TODO
+
     @RequirePerm(Permission.All)
     def login(self, username, password, remoteip=None):
         """Login into pyLoad, this **must** be called when using rpc before any methods can be used.
@@ -946,48 +953,42 @@ class Api(Iface):
         """
         if self.core.config["remote"]["nolocalauth"] and remoteip == "127.0.0.1":
             return "local"
-        if self.core.startedInGui and remoteip == "127.0.0.1":
-            return "local"
 
         self.core.log.info(_("User '%s' tried to log in") % username)
 
         return self.core.db.checkAuth(username, password)
 
-    def isAuthorized(self, func, userdata):
+    def isAuthorized(self, func, user):
         """checks if the user is authorized for specific method
 
         :param func: function name
-        :param userdata: dictionary of user data
+        :param user: `User`
         :return: boolean
         """
-        if userdata == "local" or userdata["role"] == ROLE.ADMIN:
+        if user.isAdmin():
             return True
-        elif func in perm_map and has_permission(userdata["permission"], perm_map[func]):
+        elif func in perm_map and user.hasPermission(perm_map[func]):
             return True
         else:
             return False
 
-
+    # TODO
     @RequirePerm(Permission.All)
     def getUserData(self, username, password):
         """similar to `checkAuth` but returns UserData thrift type """
         user = self.checkAuth(username, password)
-        if user:
-            return UserData(user["name"], user["email"], user["role"], user["permission"], user["template"])
+        if not user:
+            raise UserDoesNotExists(username)
 
-        raise UserDoesNotExists(username)
+        return user.toUserData()
 
     def getAllUserData(self):
         """returns all known user and info"""
-        res = {}
-        for user, data in self.core.db.getAllUserData().iteritems():
-            res[user] = UserData(user, data["email"], data["role"], data["permission"], data["template"])
-
-        return res
+        return self.core.db.getAllUserData()
 
-    def changePassword(self, user, oldpw, newpw):
+    def changePassword(self, username, oldpw, newpw):
         """ changes password for specific user """
-        return self.core.db.changePassword(user, oldpw, newpw)
+        return self.core.db.changePassword(username, oldpw, newpw)
 
     def setUserPermission(self, user, permission, role):
         self.core.db.setPermission(user, permission)
-- 
cgit v1.2.3


From cbd4f4b5375f89362733e10a9b98e5a74c2a5734 Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Fri, 31 Aug 2012 23:25:26 +0200
Subject: first js models/views

---
 module/Api.py | 35 ++++++++++++++++-------------------
 1 file changed, 16 insertions(+), 19 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index 26a6c757f..4671b9cbd 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -170,7 +170,7 @@ class Api(Iface):
         """pyLoad Core version """
         return self.core.version
 
-    @RequirePerm(Permission.Status)
+    @RequirePerm(Permission.All)
     def statusServer(self):
         """Some general information about the current status of pyLoad.
 
@@ -186,17 +186,16 @@ class Api(Iface):
 
         return serverStatus
 
-    @RequirePerm(Permission.Status)
+    # TODO: user sensitive pausing, now only available for admins
+
     def pauseServer(self):
         """Pause server: It won't start any new downloads, but nothing gets aborted."""
         self.core.threadManager.pause = True
 
-    @RequirePerm(Permission.Status)
     def unpauseServer(self):
         """Unpause server: New Downloads will be started."""
         self.core.threadManager.pause = False
 
-    @RequirePerm(Permission.Status)
     def togglePause(self):
         """Toggle pause state.
 
@@ -205,7 +204,6 @@ class Api(Iface):
         self.core.threadManager.pause ^= True
         return self.core.threadManager.pause
 
-    @RequirePerm(Permission.Status)
     def toggleReconnect(self):
         """Toggle reconnect activation.
 
@@ -214,7 +212,6 @@ class Api(Iface):
         self.core.config["reconnect"]["activated"] ^= True
         return self.core.config["reconnect"]["activated"]
 
-    @RequirePerm(Permission.Status)
     def freeSpace(self):
         """Available free space at download directory in bytes"""
         return free_space(self.core.config["general"]["download_folder"])
@@ -245,7 +242,7 @@ class Api(Iface):
         except:
             return ['No log available']
 
-    @RequirePerm(Permission.Status)
+    @RequirePerm(Permission.All)
     def isTimeDownload(self):
         """Checks if pyload will start new downloads according to time in config.
 
@@ -255,7 +252,7 @@ class Api(Iface):
         end = self.core.config['downloadTime']['end'].split(":")
         return compare_time(start, end)
 
-    @RequirePerm(Permission.Status)
+    @RequirePerm(Permission.All)
     def isTimeReconnect(self):
         """Checks if pyload will try to make a reconnect
 
@@ -269,7 +266,7 @@ class Api(Iface):
     def scanDownloadFolder(self):
         pass
 
-    @RequirePerm(Permission.Status)
+    @RequirePerm(Permission.All)
     def getProgressInfo(self):
         """ Status of all currently running tasks
 
@@ -512,12 +509,12 @@ class Api(Iface):
 
         :return: package id
         """
-        self.addPackageChild(name, links, password, -1, False)
+        return self.addPackageChild(name, links, password, -1, False)
 
     @RequirePerm(Permission.Add)
     def addPackageP(self, name, links, password, paused):
         """ Same as above with additional paused attribute. """
-        self.addPackageChild(name, links, password, -1, paused)
+        return self.addPackageChild(name, links, password, -1, paused)
 
     @RequirePerm(Permission.Add)
     def addPackageChild(self, name, links, password, root, paused):
@@ -618,7 +615,7 @@ class Api(Iface):
         pass
 
     #############################
-    #  File Information retrival
+    #  File Information retrieval
     #############################
 
     @RequirePerm(Permission.All)
@@ -638,9 +635,9 @@ class Api(Iface):
 
         :param pid: package id
         :param full: go down the complete tree or only the first layer
-        :return: :class:`PackageView`
+        :return: :class:`TreeCollection`
         """
-        return self.core.files.getView(pid, full, False)
+        return self.core.files.getTree(pid, full, False)
 
     @RequirePerm(Permission.All)
     def getUnfinishedFileTree(self, pid, full):
@@ -648,9 +645,9 @@ class Api(Iface):
 
         :param pid: package id
         :param full: go down the complete tree or only the first layer
-        :return: :class:`PackageView`
+        :return: :class:`TreeCollection`
         """
-        return self.core.files.getView(pid, full, False)
+        return self.core.files.getTree(pid, full, False)
 
     @RequirePerm(Permission.All)
     def getPackageContent(self, pid):
@@ -876,13 +873,13 @@ class Api(Iface):
     #  Event Handling
     #############################
 
-    @RequirePerm(Permission.Status)
     def getEvents(self, uuid):
         """Lists occurred events, may be affected to changes in future.
 
         :param uuid: self assigned string uuid which has to be unique
         :return: list of `Events`
         """
+        # TODO: permissions?
         # TODO
         pass
 
@@ -1030,7 +1027,8 @@ class Api(Iface):
         except Exception, e:
             raise ServiceException(e.message)
 
-    @RequirePerm(Permission.Status)
+
+    #TODO: permissions
     def getAllInfo(self):
         """Returns all information stored by addon plugins. Values are always strings
 
@@ -1038,7 +1036,6 @@ class Api(Iface):
         """
         return self.core.addonManager.getAllInfo()
 
-    @RequirePerm(Permission.Status)
     def getInfoByPlugin(self, plugin):
         """Returns information stored by a specific plugin.
 
-- 
cgit v1.2.3


From 560958b70043ea5b7e0e32d41cb51bd44696d775 Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Sun, 9 Sep 2012 15:39:50 +0200
Subject: new config api

---
 module/Api.py | 72 ++++++++++++++++++++++++++++++++++-------------------------
 1 file changed, 42 insertions(+), 30 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index 4671b9cbd..d530556fa 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -123,8 +123,6 @@ class UserApi(object):
     def user(self):
         return self._user
 
-# TODO: fix permissions, user context manager
-
 class Api(Iface):
     """
     **pyLoads API**
@@ -263,9 +261,6 @@ class Api(Iface):
         return compare_time(start, end) and self.core.config["reconnect"]["activated"]
 
 
-    def scanDownloadFolder(self):
-        pass
-
     @RequirePerm(Permission.All)
     def getProgressInfo(self):
         """ Status of all currently running tasks
@@ -314,43 +309,64 @@ class Api(Iface):
     def getConfig(self):
         """Retrieves complete config of core.
 
-        :return: list of `ConfigSection`
+        :return: map of `ConfigHolder`
         """
-        return dict([(section, ConfigSection(section, data.name, data.description, data.long_desc, [
+        # TODO
+        return dict([(section, ConfigHolder(section, data.name, data.description, data.long_desc, [
         ConfigItem(option, d.name, d.description, d.type, to_string(d.default),
             to_string(self.core.config.get(section, option))) for
         option, d in data.config.iteritems()])) for
                                                 section, data in self.core.config.getBaseSections()])
 
 
-    def getPluginConfig(self):
-        """Retrieves complete config for all plugins.
+    def getConfigRef(self):
+        """Config instance, not for RPC"""
+        return self.core.config
+
+    def getGlobalPlugins(self):
+        """All global plugins/addons, only admin can use this
 
-        :return: list of `ConfigSection`
+        :return: list of `ConfigInfo`
         """
-        return dict([(section, ConfigSection(section,
-            data.name, data.description, data.long_desc)) for
-                                                          section, data in self.core.config.getPluginSections()])
+        pass
 
-    def configureSection(self, section):
-        data = self.core.config.config[section]
-        sec = ConfigSection(section, data.name, data.description, data.long_desc)
-        sec.items = [ConfigItem(option, d.name, d.description,
-            d.type, to_string(d.default), to_string(self.core.config.get(section, option)))
-                     for
-                     option, d in data.config.iteritems()]
+    @UserContext
+    @RequirePerm(Permission.Plugins)
+    def getUserPlugins(self):
+        """List of plugins every user can configure for himself
 
-        #TODO: config handler
+        :return: list of `ConfigInfo`
+        """
+        pass
 
-        return sec
+    @UserContext
+    @RequirePerm(Permission.Plugins)
+    def configurePlugin(self, plugin):
+        """Get complete config options for an plugin
 
+        :param plugin: Name of the plugin to configure
+        :return: :class:`ConfigHolder`
+        """
 
-    def setConfigHandler(self, plugin, iid, value):
         pass
 
-    def getConfigRef(self):
-        """Config instance, not for RPC"""
-        return self.core.config
+    @UserContext
+    @RequirePerm(Permission.Plugins)
+    def saveConfig(self, config):
+        """Used to save a configuration, core config can only be saved by admins
+
+        :param config: :class:`ConfigHolder
+        """
+        pass
+
+    @UserContext
+    @RequirePerm(Permission.Plugins)
+    def deleteConfig(self, config):
+        pass
+
+    @RequirePerm(Permission.Plugins)
+    def setConfigHandler(self, plugin, iid, value):
+        pass
 
     ##########################
     #  Download Preparing
@@ -474,10 +490,6 @@ class Api(Iface):
         return [self.addPackageP(name, urls, "", paused) for name, urls
                 in self.generatePackages(links).iteritems()]
 
-    @RequirePerm(Permission.Add)
-    def autoAddLinks(self, links):
-        pass
-
     @RequirePerm(Permission.Add)
     def createPackage(self, name, folder, root, password="", site="", comment="", paused=False):
         """Create a new package.
-- 
cgit v1.2.3


From 54bc92b4c5e0b3543a313f497cbc2276403c5980 Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Mon, 10 Sep 2012 11:49:35 +0200
Subject: changed config + progress api

---
 module/Api.py | 49 +++++++++++++++++++------------------------------
 1 file changed, 19 insertions(+), 30 deletions(-)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index d530556fa..182024775 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -184,8 +184,6 @@ class Api(Iface):
 
         return serverStatus
 
-    # TODO: user sensitive pausing, now only available for admins
-
     def pauseServer(self):
         """Pause server: It won't start any new downloads, but nothing gets aborted."""
         self.core.threadManager.pause = True
@@ -260,25 +258,13 @@ class Api(Iface):
         end = self.core.config['reconnect']['endTime'].split(":")
         return compare_time(start, end) and self.core.config["reconnect"]["activated"]
 
-
     @RequirePerm(Permission.All)
     def getProgressInfo(self):
         """ Status of all currently running tasks
 
         :return: list of `ProgressInfo`
         """
-        data = []
-        for pyfile in self.core.threadManager.getActiveFiles():
-            if not isinstance(pyfile, PyFile):
-                continue
-
-            data.append(ProgressInfo(
-                pyfile.id, pyfile.name, pyfile.getSpeed(), pyfile.getETA(), pyfile.formatETA(),
-                pyfile.getBytesLeft(), pyfile.getSize(), pyfile.formatSize(), pyfile.getPercent(),
-                pyfile.status, pyfile.getStatusName(), pyfile.formatWait(),
-                pyfile.waitUntil, pyfile.packageid, pyfile.package().name, pyfile.pluginname))
-
-        return data
+        pass
 
     ##########################
     #  Configuration
@@ -361,7 +347,12 @@ class Api(Iface):
 
     @UserContext
     @RequirePerm(Permission.Plugins)
-    def deleteConfig(self, config):
+    def deleteConfig(self, plugin):
+        """Deletes modified config
+
+        :param plugin: plugin name
+        :return:
+        """
         pass
 
     @RequirePerm(Permission.Plugins)
@@ -611,21 +602,21 @@ class Api(Iface):
         pass
 
     @RequirePerm(Permission.Add)
-    def addFromCollector(self, name, paused):
+    def addFromCollector(self, name, new_name):
         pass
 
     @RequirePerm(Permission.Delete)
     def deleteCollPack(self, name):
         pass
 
-    @RequirePerm(Permission.Delete)
-    def deleteCollLink(self, url):
-        pass
-
     @RequirePerm(Permission.Add)
     def renameCollPack(self, name, new_name):
         pass
 
+    @RequirePerm(Permission.Delete)
+    def deleteCollLink(self, url):
+        pass
+
     #############################
     #  File Information retrieval
     #############################
@@ -722,6 +713,11 @@ class Api(Iface):
         """Check online status of all files in a package, also a default action when package is added. """
         self.core.files.reCheckPackage(pid)
 
+    @RequirePerm(Permission.Modify)
+    def restartFailed(self):
+        """Restarts all failed failes."""
+        self.core.files.restartFailed()
+
     @RequirePerm(Permission.Modify)
     def stopAllDownloads(self):
         """Aborts all running downloads."""
@@ -742,19 +738,10 @@ class Api(Iface):
             if pyfile.id in fids:
                 pyfile.abortDownload()
 
-    @RequirePerm(Permission.Modify)
-    def restartFailed(self):
-        """Restarts all failed failes."""
-        self.core.files.restartFailed()
-
     #############################
     #  Modify Files/Packages
     #############################
 
-    @RequirePerm(Permission.Modify)
-    def setFilePaused(self, fid, paused):
-        pass
-
     @RequirePerm(Permission.Modify)
     def setPackagePaused(self, pid, paused):
         pass
@@ -1007,6 +994,8 @@ class Api(Iface):
     #  RPC Plugin Methods
     #############################
 
+    # TODO: obsolete
+
     @RequirePerm(Permission.Interaction)
     def getServices(self):
         """ A dict of available services, these can be defined by addon plugins.
-- 
cgit v1.2.3


From 1a55cb6a2eb8784253410b2e93510b5bcebf7f41 Mon Sep 17 00:00:00 2001
From: RaNaN <Mast3rRaNaN@hotmail.de>
Date: Mon, 10 Sep 2012 15:12:55 +0200
Subject: userApi for plugins

---
 module/Api.py | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'module/Api.py')

diff --git a/module/Api.py b/module/Api.py
index 182024775..dec1526b2 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -150,6 +150,9 @@ class Api(Iface):
         :param uid: user or userData instance or uid
         :return: :class:`UserApi`
         """
+        if isinstance(uid, User):
+            uid = uid.uid
+
         if uid not in self.user_apis:
             user = self.core.db.getUserData(uid=uid)
             if not user: #TODO: anonymous user?
-- 
cgit v1.2.3