Commits

Anonymous committed 9b96c99 Merge

Updated to latest code

Comments (0)

Files changed (50)

module/HookManager.py

                 self.core.log.error(_("Error executing hooks: %s") % str(e))
                 if self.core.debug:
                     traceback.print_exc()
-            
-            self.core.scheduler.addJob(plugin.interval, wrapPeriodical, args=[plugin])
+
+            self.core.scheduler.addJob(plugin.interval, wrapPeriodical, args=[plugin], threaded=False)
         
         for plugin in self.plugins:
             if plugin.isActivated():
-                self.core.scheduler.addJob(0, wrapPeriodical, args=[plugin])
+                self.core.scheduler.addJob(0, wrapPeriodical, args=[plugin], threaded=False)
 
     
     @try_catch
 
 from time import time
 from heapq import heappop, heappush
-from threading import Thread, Lock
+from thread import start_new_thread
+from threading import Lock
 
 class AlreadyCalled(Exception):
     pass
 
-def callInThread(f, *args, **kwargs):
-    class FThread(Thread):
-        def run(self):
-            f(*args, **kwargs)
-    t = FThread()
-    t.start()
 
 class Deferred(object):
     def __init__(self):
         self.call = []
         self.result = ()
-    
+
     def addCallback(self, f, *cargs, **ckwargs):
         self.call.append((f, cargs, ckwargs))
-        if self.result:
-            args, kwargs = self.result
-            args.extend(cargs)
-            kwargs.update(ckwargs)
-            callInThread(f, *args, **kwargs)
-    
+
     def callback(self, *args, **kwargs):
         if self.result:
             raise AlreadyCalled
         for f, cargs, ckwargs in self.call:
             args+=tuple(cargs)
             kwargs.update(ckwargs)
-            callInThread(f, *args, **kwargs)
+            f(*args **kwargs)
 
 class Scheduler(object):
     def __init__(self, core):
         
         self.queue = PriorityQueue()
     
-    def addJob(self, t, call, args=[], kwargs={}):
+    def addJob(self, t, call, args=[], kwargs={}, threaded=True):
         d = Deferred()
         t += time()
-        j = Job(t, call, args, kwargs, d)
+        j = Job(t, call, args, kwargs, d, threaded)
         self.queue.put((t, j))
         return d
     
                     self.queue.put((t, j))
                     break
 
-class Job(Thread):
-    def __init__(self, time, call, args=[], kwargs={}, deferred=None):
-        Thread.__init__(self)
+class Job():
+    def __init__(self, time, call, args=[], kwargs={}, deferred=None, threaded=True):
         self.time = float(time)
         self.call = call
-        self.deferred = deferred
         self.args = args
         self.kwargs = kwargs
-    
+        self.deferred = deferred
+        self.threaded = threaded
+
     def run(self):
         ret = self.call(*self.args, **self.kwargs)
         if self.deferred is None:
             return
-        if ret is None:
-            self.deferred.callback()
         else:
             self.deferred.callback(ret)
 
+    def start(self):
+        if self.threaded:
+            start_new_thread(self.run, ())
+        else:
+            self.run()
 
 class PriorityQueue(object):
     """ a non blocking priority queue """

module/ThreadManager.py

                     ("http://checkip.dyndns.org/",".*Current IP Address: (\S+)</body>.*")]
 
         ip = ""
-        while not ip:
+        for i in range(10):
             try:
                 sv = choice(services)
                 ip = getURL(sv[0])
                 ip = re.match(sv[1], ip).group(1)
+                break
             except:
                 ip = ""
                 sleep(1)

module/config/default.conf

 remote - "Remote":
 	int port : "Port" = 7227
 	ip listenaddr : "Adress" = 0.0.0.0
+	bool xmlrpc : "Activate old XMLRPC Backend" = False
 	bool nolocalauth : "No authentication on local connections" = True
 ssl - "SSL":
 	bool activated : "Activated"= False

module/database/FileDatabase.py

         """deletes links"""
         
         f = self.getFile(id)
-        pid = f.packageid
-        
         if not f:
             return None
-        
+
+        pid = f.packageid
         e = RemoveEvent("file", id, "collector" if not f.package().queue else "queue")
         
         

module/database/UserDatabase.py

 from hashlib import sha1
 import random
 
+class PERMS:
+    ADD = 1  # can add packages
+    DELETE = 2 # can delete packages
+    STATUS = 4   # see and change server status
+    SEE_DOWNLOADS = 16 # see queue and collector
+    DOWNLOAD = 32  # can download from webinterface
+    SETTINGS = 64 # can access settings
+
+class ROLE:
+    ADMIN = 0  #admin has all permissions implicit
+    USER = 1
+
+def has_permission(current, perms):
+    # bytewise or perms before if needed
+    return current == (current & perms)
+
 class UserMethods():
     @style.queue
     def checkAuth(db, user, password):
         c = db.c
-        c.execute('SELECT name, password, role, permission, template FROM "users" WHERE name=?', (user, ))
+        c.execute('SELECT id, name, password, role, permission, template FROM "users" WHERE name=?', (user, ))
         r = c.fetchone()
         if not r:
             return {}
         
-        salt = r[1][:5]
-        pw = r[1][5:]
+        salt = r[2][:5]
+        pw = r[2][5:]
         h = sha1(salt + password)
         if h.hexdigest() == pw:
-            return {"name": r[0], "role": r[2], "permission": r[3], "template": r[4]}
+            return {"id": r[0], "name": r[1], "role": r[3], "permission": r[4], "template": r[5]}
         else:
             return {}
     
             c.execute('UPDATE users SET password=? WHERE name=?', (password, user))
         else:
             c.execute('INSERT INTO users (name, password) VALUES (?, ?)', (user, password))
+
+
+    @style.queue
+    def setPermission(db, userid, perms):
+        db.c.execute("UPDATE users SET permission=? WHERE id=?", (perms, userid))
     
     @style.queue
     def listUsers(db):
     
     @style.queue
     def removeUser(db, user):
-        c = db.c
-        c.execute('SELECT name FROM users WHERE name=?', (user, ))
-        if c.fetchone() is not None:
-            c.execute('DELETE FROM users WHERE name=?', (user, ))
+        db.c.execute('DELETE FROM users WHERE name=?', (user, ))
     
 
 DatabaseBackend.registerSub(UserMethods)

module/gui/AccountEdit.py

 from os.path import join
 
 class AccountEdit(QWidget):
+    """
+        account editor widget
+    """
+    
     def __init__(self):
         QMainWindow.__init__(self)
 
         self.connect(save, SIGNAL("clicked()"), self.slotSave)
     
     def slotSave(self):
+        """
+            save entered data
+        """
         data = {"login": str(self.login.text()), "acctype": str(self.acctype.currentText()), "password": False}
         if self.changePw.isChecked():
             data["password"] = str(self.password.text())
     
     @staticmethod
     def newAccount(types):
+        """
+            create empty editor instance
+        """
         w = AccountEdit()
         w.setWindowTitle(_("Create account"))
         
     
     @staticmethod
     def editAccount(types, base):
+        """
+            create editor instance with given data
+        """
         w = AccountEdit()
         
         w.acctype.addItems(types)

module/gui/Accounts.py

 from time import strftime, gmtime
 
 class AccountModel(QAbstractItemModel):
+    """
+        model for account view
+    """
+    
     def __init__(self, view, connector):
         QAbstractItemModel.__init__(self)
         self.connector = connector
         self.mutex = QMutex()
     
     def reloadData(self, force=False):
+        """
+            reload account list
+        """
         accounts = self.connector.proxy.getAccounts(False)
 
         if self._data == accounts:
             self.endInsertRows()
     
     def toData(self, index):
+        """
+            return index pointer
+        """
         return index.internalPointer()
     
     def data(self, index, role=Qt.DisplayRole):
+        """
+            return cell data
+        """
         if not index.isValid():
             return QVariant()
         if role == Qt.DisplayRole:
         return QVariant()
         
     def index(self, row, column, parent=QModelIndex()):
+        """
+            create index with data pointer
+        """
         if parent == QModelIndex() and len(self._data) > row:
             pointer = self._data[row]
             index = self.createIndex(row, column, pointer)
         return index
     
     def parent(self, index):
+        """
+            no parents, everything on top level
+        """
         return QModelIndex()
     
     def rowCount(self, parent=QModelIndex()):
+        """
+            account count
+        """
         if parent == QModelIndex():
             return len(self._data)
         return 0
         return self.cols
     
     def hasChildren(self, parent=QModelIndex()):
+        """
+            everything on top level
+        """
         if parent == QModelIndex():
             return True
         else:
         return False
     
     def headerData(self, section, orientation, role=Qt.DisplayRole):
+        """
+            returns column heading
+        """
         if orientation == Qt.Horizontal and role == Qt.DisplayRole:
             if section == 0:
                 return QVariant(_("Type"))
         return QVariant()
     
     def flags(self, index):
-        return Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled
-   
-    #def setData(self, index, value, role=Qt.EditRole):
-    #    if index.column() == 0 and self.parent(index) == QModelIndex() and role == Qt.EditRole:
-    #        self.connector.setPackageName(index.internalPointer().id, str(value.toString()))
-    #    return True
+        """
+            cell flags
+        """
+        return Qt.ItemIsSelectable | Qt.ItemIsEnabled
     
 class AccountView(QTreeView):
+    """
+        view component for accounts
+    """
+    
     def __init__(self, connector):
         QTreeView.__init__(self)
         self.setModel(AccountModel(self, connector))
         self.setItemDelegateForColumn(3, self.delegate)
 
 class AccountDelegate(QItemDelegate):
+    """
+        used to display a progressbar for the traffic in the traffic cell
+    """
+    
     def __init__(self, parent, model):
         QItemDelegate.__init__(self, parent)
         self.model = model
 
     def paint(self, painter, option, index):
+        """
+            paint the progressbar
+        """
         if not index.isValid():
             return
         if index.column() == 3:

module/gui/CaptchaDock.py

 from PyQt4.QtGui import *
 
 class CaptchaDock(QDockWidget):
+    """
+        dock widget for captcha input
+    """
+    
     def __init__(self):
         QDockWidget.__init__(self, _("Captcha"))
         self.setObjectName("Captcha Dock")
         self.show()
 
 class CaptchaDockWidget(QWidget):
+    """
+        widget for the input widgets
+    """
+    
     def __init__(self, dock):
         QWidget.__init__(self)
         self.dock = dock

module/gui/Collector.py

     return "%.2f %s" % (size, sizes[steps])
 
 class CollectorModel(QAbstractItemModel):
+    """
+        model for the collector view
+    """
+    
     def __init__(self, view, connector):
         QAbstractItemModel.__init__(self)
         self.connector = connector
         }
     
     def translateStatus(self, string):
+        """
+            used to convert to locale specific status
+        """
         return translatedStatusMap[string]
     
     def addEvent(self, event):
+        """
+            called from main loop, pass events to the correct methods
+        """
         locker = QMutexLocker(self.mutex)
         if event.event == "reload":
             self.fullReload()
             self.updateEvent(event)
     
     def fullReload(self):
+        """
+            reload whole model, used at startup to load initial data
+        """
         self._data = []
         order = self.connector.getPackageOrder(Destination.Collector)
         self.beginInsertRows(QModelIndex(), 0, len(order.values()))
         self.endInsertRows()
     
     def removeEvent(self, event):
+        """
+            remove an element from model
+        """
         if event.type == ElementType.File:
             for p, package in enumerate(self._data):
                 for k, child in enumerate(package.children):
                     break
     
     def insertEvent(self, event):
+        """
+            inserts a new element in the model
+        """
         if event.type == ElementType.File:
             info = self.connector.getFileData(event.id)
             
             self.endInsertRows()
     
     def updateEvent(self, event):
+        """
+            update an element in the model
+        """
         if event.type == ElementType.File:
             info = self.connector.proxy.getFileData(event.id)
             if not info:
                     break
     
     def data(self, index, role=Qt.DisplayRole):
+        """
+            return cell data
+        """
         if not index.isValid():
             return QVariant()
         if role == Qt.DisplayRole:
         return QVariant()
         
     def index(self, row, column, parent=QModelIndex()):
+        """
+            creates a cell index with pointer to the data
+        """
         if parent == QModelIndex() and len(self._data) > row:
             pointer = self._data[row]
             index = self.createIndex(row, column, pointer)
         return index
     
     def parent(self, index):
+        """
+            return index of parent element
+            only valid for links
+        """
         if index == QModelIndex():
             return QModelIndex()
         if index.isValid():
         return QModelIndex()
     
     def rowCount(self, parent=QModelIndex()):
+        """
+            returns row count for the element
+        """
         if parent == QModelIndex():
             #return package count
             return len(self._data)
         return False
     
     def headerData(self, section, orientation, role=Qt.DisplayRole):
+        """
+            returns column heading
+        """
         if orientation == Qt.Horizontal and role == Qt.DisplayRole:
             if section == 0:
                 return QVariant(_("Name"))
         return QVariant()
     
     def flags(self, index):
+        """
+            cell flags
+        """
         if index.column() == 0 and self.parent(index) == QModelIndex():
             return Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled
         return Qt.ItemIsSelectable | Qt.ItemIsEnabled
    
     def setData(self, index, value, role=Qt.EditRole):
+        """
+            called if package name editing is finished, sets new name
+        """
         if index.column() == 0 and self.parent(index) == QModelIndex() and role == Qt.EditRole:
             self.connector.setPackageName(index.internalPointer().id, str(value.toString()))
         return True
 
 class Package(object):
+    """
+        package object in the model
+    """
+    
     def __init__(self, pack):
         self.id = pack.pid
         self.children = []
         self.update(pack)
     
     def update(self, pack):
+        """
+            update data dict from thift object
+        """
         data = {
             "name": pack.name,
             "folder": pack.folder,
         self.data.update(data)
     
     def addChild(self, f):
+        """
+            add child (Link) to package
+        """
         self.children.insert(f.order, Link(f, self))
         self.children = sorted(self.children, key=lambda l: l.data["order"])
     
     def getChild(self, fid):
+        """
+            get child from package
+        """
         for child in self.children:
             if child.id == int(fid):
                 return child
         return None
     
     def getChildKey(self, fid):
+        """
+            get child index
+        """
         for k, child in enumerate(self.children):
             if child.id == int(fid):
                 return k
         return None
     
     def removeChild(self, fid):
+        """
+            remove child
+        """
         for k, child in enumerate(self.children):
             if child.id == int(fid):
                 del self.children[k]
         self.package = pack
     
     def update(self, f):
+        """
+            update data dict from thift object
+        """
         data = {
             "url": f.url,
             "name": f.name,
         self.data.update(data)
 
 class CollectorView(QTreeView):
+    """
+        view component for collector
+    """
+    
     def __init__(self, connector):
         QTreeView.__init__(self)
         self.setModel(CollectorModel(self, connector))

module/gui/Connector.py

 from thrift.Thrift import TException
 
 class Connector(QObject):
+    """
+        manages the connection to the pyload core via thrift
+    """
+    
+    firstAttempt = True
+    
     def __init__(self):
         QObject.__init__(self)
         self.mutex = QMutex()
         self.proxy = self.Dummy()
     
     def setConnectionData(self, host, port, user, password, ssl=False):
+        """
+            set connection data for connection attempt, called from slotConnect
+        """
         self.host = host
         self.port = port
         self.user = user
         self.ssl = ssl
     
     def connectProxy(self):
+        """
+            initialize thrift rpc client,
+            check for ssl, check auth,
+            setup dispatcher,
+            connect error signals,
+            check server version
+        """
+        err = None
         try:
             client = ThriftClient(self.host, self.port, self.user, self.password)
         except WrongLogin:
-            self.emit(SIGNAL("error_box"), "bad login credentials")
-            return False
+            err = _("bad login credentials")
         except NoSSL:
-            self.emit(SIGNAL("error_box"), "no ssl support")
-            return False
+            err = _("no ssl support")
         except NoConnection:
-            self.emit(SIGNAL("connectionLost"))
+            err = _("can't connect to host")
+        if err:
+            if not Connector.firstAttempt:
+                self.emit(SIGNAL("errorBox"), err)
+            Connector.firstAttempt = False
             return False
         
         self.proxy = DispatchRPC(self.mutex, client)
-        self.connect(self.proxy, SIGNAL("proxy_error"), self._proxyError)
         self.connect(self.proxy, SIGNAL("connectionLost"), self, SIGNAL("connectionLost"))
         
         server_version = self.proxy.getServerVersion()
         self.connectionID = uuid().hex
         
         if not server_version == SERVER_VERSION:
-            self.emit(SIGNAL("error_box"), "server is version %s client accepts version %s" % (server_version, SERVER_VERSION))
+            self.emit(SIGNAL("errorBox"), _("server is version %s client accepts version %s") % (server_version, SERVER_VERSION))
             return False
         
         return True
     
-    def _proxyError(self, func, e):
+    def __getattr__(self, attr):
         """
-            formats proxy error msg
+            redirect rpc calls to dispatcher
         """
-        msg = "proxy error in '%s':\n%s" % (func, e)
-        print msg
-        self.emit(SIGNAL("error_box"), msg)
-    
-    def __getattr__(self, attr):
         return getattr(self.proxy, attr)
     
     class Dummy(object):
+        """
+            dummy rpc proxy, to prevent errors
+        """
         def __getattr__(self, attr):
             def dummy(*args, **kwargs):
                 return None
             return dummy
 
 class DispatchRPC(QObject):
+    """
+        wraps the thrift client, to catch critical exceptions (connection lost)
+        adds thread safety
+    """
+    
     def __init__(self, mutex, server):
         QObject.__init__(self)
         self.mutex = mutex
         self.server = server
     
     def __getattr__(self, attr):
+        """
+            redirect and wrap call in Wrapper instance, locks dispatcher
+        """
         self.mutex.lock()
         self.fname = attr
         f = self.Wrapper(getattr(self.server, attr), self.mutex, self)
         return f
     
     class Wrapper(object):
+        """
+            represents a rpc call
+        """
+        
         def __init__(self, f, mutex, dispatcher):
             self.f = f
             self.mutex = mutex
             self.dispatcher = dispatcher
         
         def __call__(self, *args, **kwargs):
+            """
+                instance is called, rpc is executed
+                exceptions are processed
+                finally dispatcher is unlocked
+            """
             lost = False
-            error = False
             try:
                 return self.f(*args, **kwargs)
-            except socket.error:
+            except socket.error: #necessary?
                 lost = True
             except TException:
                 lost = True
-            except Exception, e:
-                err = e
             finally:
                 self.mutex.unlock()
             if lost:
                 self.dispatcher.emit(SIGNAL("connectionLost"))
-            if error:
-                self.dispatcher.emit(SIGNAL("proxy_error"), self.dispatcher.fname, error)

module/gui/MainWindow.py

             self.emit(SIGNAL("refreshStatus"), pid)
     
     def slotNewAccount(self):
-        types = self.connector.proxy.get_accounts(False, False).keys()
+        types = self.connector.proxy.getAccountTypes()
         self.accountEdit = AccountEdit.newAccount(types)
         
         def save(data):
             
         data = data[0].internalPointer()
         
-        self.connector.removeAccount(data["type"], data["login"])
+        self.connector.removeAccount(data.type, data.login)
     
     def slotAccountContextMenu(self, pos):
         globalPos = self.tabs["accounts"]["view"].mapToGlobal(pos)
     return "%.2f %s" % (speed, sizes[steps])
 
 class QueueModel(CollectorModel):
+    """
+        model for the queue view, inherits from CollectorModel
+    """
+    
     def __init__(self, view, connector):
         CollectorModel.__init__(self, view, connector)
         self.cols = 7
         self.connect(self.updater, SIGNAL("update()"), self.update)
     
     class QueueUpdater(QObject):
+        """
+            timer which emits signal for a download status reload
+            @TODO: make intervall configurable
+        """
+        
         def __init__(self, interval):
             QObject.__init__(self)
             
         self.updater.stop()
     
     def fullReload(self):
+        """
+            reimplements CollectorModel.fullReload, because we want the Queue data
+        """
         self._data = []
         order = self.connector.getPackageOrder(Destination.Queue)
         self.beginInsertRows(QModelIndex(), 0, len(order.values()))
         self.updateCount()
     
     def insertEvent(self, event):
+        """
+            wrap CollectorModel.insertEvent to update the element count
+        """
         CollectorModel.insertEvent(self, event)
         self.updateCount()
     
     def removeEvent(self, event):
+        """
+            wrap CollectorModel.removeEvent to update the element count
+        """
         CollectorModel.removeEvent(self, event)
         self.updateCount()
     
     def updateEvent(self, event):
+        """
+            wrap CollectorModel.updateEvent to update the element count
+        """
         CollectorModel.updateEvent(self, event)
         self.updateCount()
     
     def updateCount(self):
+        """
+            calculate package- and filecount for statusbar,
+            ugly?: Overview connects to this signal for updating
+        """
         packageCount = len(self._data)
         fileCount = 0
         for p in self._data:
         self.mutex.lock()
     
     def update(self):
+        """
+            update slot for download status updating
+        """
         locker = QMutexLocker(self.mutex)
         downloading = self.connector.statusDownloads()
         if not downloading:
             return
         for p, pack in enumerate(self._data):
             for d in downloading:
-                child = pack.getChild(d.id)
+                child = pack.getChild(d.fid)
                 if child:
                     dd = {
                         "name": d.name,
                         "wait_until": d.wait_until
                     }
                     child.data["downloading"] = dd
-                    k = pack.getChildKey(d.id)
+                    k = pack.getChildKey(d.fid)
                     self.emit(SIGNAL("dataChanged(const QModelIndex &, const QModelIndex &)"), self.index(k, 0, self.index(p, 0)), self.index(k, self.cols, self.index(p, self.cols)))
         self.updateCount()
                     
     def headerData(self, section, orientation, role=Qt.DisplayRole):
+        """
+            returns column heading
+        """
         if orientation == Qt.Horizontal and role == Qt.DisplayRole:
             if section == 0:
                 return QVariant(_("Name"))
         return QVariant()
     
     def getWaitingProgress(self, item):
+        """
+            returns time to wait, caches startingtime to provide progress
+        """
         locker = QMutexLocker(self.mutex)
         if isinstance(item, Link):
             if item.data["status"] == 5 and item.data["downloading"]:
         return None
     
     def getProgress(self, item, locked=True):
+        """
+            return download progress, locks by default
+            since it's used in already locked calls,
+            it provides an option to not lock
+        """
         if locked:
             locker = QMutexLocker(self.mutex)
         if isinstance(item, Link):
         return 0
     
     def getSpeed(self, item):
+        """
+            calculate download speed
+        """
         if isinstance(item, Link):
             if item.data["downloading"]:
                 return int(item.data["downloading"]["speed"])
         return None
     
     def data(self, index, role=Qt.DisplayRole):
+        """
+            return cell data
+        """
         if not index.isValid():
             return QVariant()
         if role == Qt.DisplayRole:
         return QVariant()
     
     def flags(self, index):
+        """
+            cell flags
+        """
         if index.column() == 0 and self.parent(index) == QModelIndex():
             return Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled
         return Qt.ItemIsSelectable | Qt.ItemIsEnabled
     
 class QueueView(CollectorView):
+    """
+        view component for queue
+    """
+    
     def __init__(self, connector):
         CollectorView.__init__(self, connector)
         self.setModel(QueueModel(self, connector))
         self.setItemDelegateForColumn(6, self.delegate)
 
 class QueueProgressBarDelegate(QItemDelegate):
+    """
+        used to display a progressbar in the progress cell
+    """
+    
     def __init__(self, parent, queue):
         QItemDelegate.__init__(self, parent)
         self.queue = queue
     
     def paint(self, painter, option, index):
+        """
+            paint the progressbar
+        """
         if not index.isValid():
             return
         if index.column() == 6:

module/network/Browser.py

 
     def httpDownload(self, url, filename, get={}, post={}, ref=True, cookies=True, chunks=1, resume=False, progressNotify=None):
         """ this can also download ftp """
+        self._size = 0
         self.dl = HTTPDownload(url, filename, get, post, self.lastEffectiveURL if ref else None,
                                self.cj if cookies else None, self.bucket, self.interface,
                                self.proxies, progressNotify)

module/network/HTTPDownload.py

         self.lastChecked = 0
         self.lastArrived = []
         self.speeds = []
+        self.lastSpeeds = [0, 0]
         
         self.progressNotify = progressNotify
 
     @property
     def speed(self):
-        return sum(self.speeds)
+        last = [sum(x) for x in self.lastSpeeds if x]
+        return (sum(self.speeds) + sum(last)) / (1 + len(last))
 
     @property
     def arrived(self):
                 diff = [c.arrived - (self.lastArrived[i] if len(self.lastArrived) > i else 0) for i, c in
                         enumerate(self.chunks)]
 
-                #for i, c in enumerate(self.chunks):
-                #    diff[i] = c.arrived - (self.lastArrived[i] if len(self.lastArrived) > i else 0)
-
+                self.lastSpeeds[1] = self.lastSpeeds[0]
+                self.lastSpeeds[0] = self.speeds
                 self.speeds = [float(a) / (t - self.lastChecked) for a in diff]
                 self.lastArrived = [c.arrived for c in self.chunks]
                 self.lastChecked = t
                 self.updateProgress()
-                #print "------------------------"
-                #print self.speed / 1024, "kb/s"
-                #print "Arrived:", self.arrived
-                #print "Size:", self.size
-                #print self.percent, "%"
 
             if self.abort:
                 raise Abort()

module/network/XDCCRequest.py

 import socket
 import re
 
+from os import remove
 from os.path import exists
 
 from time import time
 import struct
 from select import select
 
-class XDCCError(Exception):
-    pass
+from module.plugins.Plugin import Abort
+
 
 class XDCCRequest():
     def __init__(self, timeout=30, proxies={}):
         # recv loop for dcc socket
         while True:
             if self.abort:
-                break
+                dccsock.close()
+                fh.close()
+                remove(filename)
+                raise Abort()
             
             data = dccsock.recv(4096)
             dataLen = len(data)
         return filename
     
     
+    def abortDownloads(self):
+        self.abort = True
+    
     @property
     def size(self):
         return self.filesize

module/plugins/AccountManager.py

             
             for name,data in accounts.iteritems():
                 f.write("\n\t%s:%s\n" % (name,data["password"]) )
-                for option, values in data["options"].iteritems():
-                    f.write("\t@%s %s\n" % (option, " ".join(values)))
+                if data["options"]:
+                    for option, values in data["options"].iteritems():
+                        f.write("\t@%s %s\n" % (option, " ".join(values)))
                     
         f.close()
         chmod(f.name, 0600)

module/plugins/Hook.py

     @interface-version: 0.2
 """
 
+from thread import start_new_thread
+
+def threaded(f):
+    def run(*args,**kwargs):
+        return start_new_thread(f, args, kwargs)
+    return run
 
 
 class Hook(object):
         self.setup()
 
     def __repr__(self):
-        return self.__name__
+        return "<Hook %s>" % self.__name__
                
     def setup(self):
         """ more init stuff if needed"""

module/plugins/Plugin.py

 
     def preprocessing(self, thread):
         """ handles important things to do before starting """
-        self.setup()
         self.thread = thread
 
         if self.account:
         else:
             self.req.clearCookies()
 
+        self.setup()
+
         self.pyfile.setStatus("starting")
 
         return self.process(self.pyfile)

module/plugins/PluginManager.py

             if value.has_key("class"):
                 classes.append(value["class"])
                 continue
-            
-            if not self.core.config.getPlugin(name, "load"):
+
+            try:
+                if not self.core.config.getPlugin(name, "load"):
+                    continue
+            except:
+                self.log.debug("Failed to load %s" % name)
                 continue
             
             try:

module/plugins/accounts/ShareonlineBiz.py

     __author_name__ = ("mkaay")
     __author_mail__ = ("mkaay@mkaay.de")
     
-    def getUserAPI(self, user):
-        req = self.getAccountRequest(user)
+    def getUserAPI(self, user, req):
         src = req.load("http://api.share-online.biz/account.php?username=%s&password=%s&act=userDetails" % (user, self.accounts[user]["password"]))
         info = {}
         for line in src.splitlines():
     
     def loadAccountInfo(self, user, req):
         try:
-            info = self.getUserAPI(user)
+            info = self.getUserAPI(user, req)
             return {"validuntil": int(info["expire_date"]), "trafficleft": -1, "premium": not info["group"] == "Sammler"}
         except:
             pass

module/plugins/crypter/NCryptIn.py

         if not self.isOnline():
             self.offline()
         
-        # Check for password protection    
+        # Check for password/captcha protection    
         if self.isProtected():
-            self.html = self.submitProtection()
+            self.html = self.unlockProtection()
 
         # Get package name and folder
         (package_name, folder_name) = self.getPackageInfo()
 
-        # Get package links
+        # Extract package links
         try:
             package_links = []
             (vcrypted, vjk) = self.getCipherParams()
             for (crypted, jk) in zip(vcrypted, vjk):
                 package_links = package_links + self.getLinks(crypted, jk)
         except:
-            self.fail("Unable to decrypt package")
+            self.fail("NCryptIn: Unable to decrypt package")
 
         # Pack
         self.packages = [(package_name, package_links, folder_name)]
+        
+    def requestPackage(self):
+        return self.load(self.pyfile.url)
 
-    def isOnline(self):
+    def isOnline(self):        
         if "Your folder does not exist" in self.html:
-            self.log.debug("NCryptIn: File not found")
-            return False
+            pattern = r'[^"]*(display\s*\:\s*none)[^"]*'
+            m = re.search(pattern, self.html)
+            if m is None:
+                self.log.debug("NCryptIn: File not found")
+                return False
         return True
     
     def isProtected(self):
-        p1 = r'''<form.*?name.*?protected.*?>'''
-        p2 = r'''<input.*?name.*?password.*?>'''
-        m1 = re.search(p1, self.html)
-        m2 = re.search(p2, self.html)
-
-        captcha = False
-        if "<!-- CAPTCHA PROTECTED -->" in self.html:
-            captcha = True
-        
-        if m1 is not None and m2 is not None or captcha:
+        pattern = r'''<form.*?name.*?protected.*?>'''
+        m = re.search(pattern, self.html)
+        if m is not None:
             self.log.debug("NCryptIn: Links are protected")
             return True
         return False
     
-    def requestPackage(self):
-        return self.load(self.pyfile.url)
-    
-    def submitProtection(self):
+    def unlockProtection(self):
+
         # Gather data
-        password = self.package.password
+        url = self.pyfile.url        
+        post = {'submit_protected' : 'Weiter zum Ordner '}
+        
+        # Resolve captcha
+        if "anicaptcha" in self.html:
+            self.log.debug("NCryptIn: Captcha protected, resolving captcha")
+            url = re.search(r'src="(/temp/anicaptcha/[^"]+)', self.html).group(1)
+            captcha = self.decryptCaptcha("http://ncrypt.in" + url)
+            self.log.debug("NCryptIn: Captcha resolved [%s]" % (captcha, ))
+            post.update({"captcha" : captcha})
+                   
+        # Submit package password
+        pattern = r'''<input.*?name.*?password.*?>'''
+        m = re.search(pattern, self.html)
+        if m is not None:
+            password = self.package.password
+            self.log.debug("NCryptIn: Submitting password [%s] for protected links" % (password,))
+            post.update({'password' : password })
 
-        post = {}
-
-
-        if "<!-- CAPTCHA PROTECTED -->" in self.html:
-            url = re.search(r'src="(/temp/anicaptcha/[^"]+)', self.html).group(1)
-            print url
-            captcha = self.decryptCaptcha("http://ncrypt.in"+ url)
-            post.update({"captcha" : captcha})
-
-                   
-        # Submit package password and captcha
-        url = self.pyfile.url
-        post.update({ 'submit_protected' : 'Weiter zum Ordner', 'password' : password })
-        self.log.debug("NCryptIn: Submitting password [%s] for protected links" % (password,))
+        # Unlock protection
         html = self.load(url, {}, post)
         
         # Check for invalid password
         if "This password is invalid!" in html:
-            self.log.debug("NCryptIn: Incorrect password, please set right password on Add package form and retry")
-            self.fail("Incorrect password, please set right password on Edit package form and retry")
+            self.log.debug("NCryptIn: Incorrect password, please set right password on 'Edit package' form and retry")
+            self.fail("Incorrect password, please set right password on 'Edit package' form and retry")
+            
         if "The securitycheck was wrong!" in html:
-            return self.submitProtection()
+            self.log.debug("NCryptIn: Invalid captcha, retrying")
+            html = self.unlockProtection()
 
         return html
 
     def getPackageInfo(self):
         title_re = r'<h2><span.*?class="arrow".*?>(?P<title>[^<]+).*?</span>.*?</h2>'
         regex = re.compile(title_re, re.DOTALL)
-        m = regex.search(self.html)
+        m = regex.findall(self.html)
         if m is not None:
-            title = m.group('title').strip()
+            title = m[-1].strip()
             name = folder = title
             self.log.debug("NCryptIn: Found name [%s] and folder [%s] in package info" % (name, folder))
             return (name, folder)

module/plugins/hooks/UpdateManager.py

 from os.path import join
 
 from module.network.RequestFactory import getURL
-from module.plugins.Hook import Hook
+from module.plugins.Hook import threaded, Hook
 
 class UpdateManager(Hook):
     __name__ = "UpdateManager"
         self.interval = self.getConfig("interval") * 60
         self.updated = False
 
+    @threaded
     def periodical(self):
         update = self.checkForUpdate()
         if not update:

module/plugins/hoster/BasePlugin.py

     def process(self, pyfile):
         """main function"""
 
+#        self.__name__ = "NetloadIn"
+#        pyfile.name = "test"
+#        self.html = self.load("http://localhost:9000/short")
+#        self.download("http://localhost:9000/short")
+#        self.api = self.load("http://localhost:9000/short")
+#        self.decryptCaptcha("http://localhost:9000/captcha")
+#
+#        if pyfile.url == "79":
+#            self.core.server_methods.add_package("test", [str(i) for i in range(80)], 1)
+#
+#        return
+
         if pyfile.url.startswith("http"):
 
             pyfile.name = re.findall("([^/=]+)", pyfile.url)[-1]

module/plugins/hoster/MegauploadCom.py

 
 from module.unescape import unescape
 
+from pycurl import error
+
 def getInfo(urls):
     url = "http://megaupload.com/mgr_linkcheck.php"
     
         else:
             self.download_api()
             pyfile.name = self.get_file_name()
-            self.download(pyfile.url)
+
+            try:
+                self.download(pyfile.url)
+            except error, e:
+                if e.args and e.args[0] == 33:
+                    # undirect download and resume , not a good idea
+                    page = self.load(pyfile.url)
+                    self.download(re.search(r'href=\"(http://[^\"]*?)\" class=\"down_ad_butt1\">', page).group(1))
+                    return 
+                else:
+                    raise
+
+            check = self.checkDownload({"dllink": re.compile(r'href=\"(http://[^\"]*?)\" class=\"down_ad_butt1\">')})
+            if check == "dllink":
+                self.log.warning(_("You should enable direct Download in your Megaupload Account settings"))
+
+                pyfile.size = 0
+                self.download(self.lastCheck.group(1))
 
     def download_html(self):        
         for i in range(3):

module/plugins/hoster/NetloadIn.py

         t = time() + 30
         
         if "/share/templates/download_hddcrash.tpl" in page:
+            self.log.error("Netload HDD Crash")
             self.fail(_("File temporarily not available"))
-            self.log.debug("Netload HDD Crash")
         
         if not self.api_data:
             self.log.debug("API Data may be useless, get details from html page")
                 page = self.load(self.url)
                 t = time() + 30
             
+            if "/share/templates/download_hddcrash.tpl" in page:
+                self.log.error("Netload HDD Crash")
+                self.fail(_("File temporarily not available"))
+            
             self.log.debug("Netload: try number %d " % i)
             if self.getConf('dumpgen'):
                 print page

module/plugins/hoster/ShareonlineBiz.py

     
     def handleAPIPremium(self): #should be working better
         self.resumeDownload = True
-        
-        pw = self.account.accounts[self.user]["password"]
-        info = self.account.getUserAPI(self.user)
+
+        info = self.account.getUserAPI(self.user, self.req)
         if info["dl"].lower() == "not_available":
             self.fail("DL API error")
         self.req.cj.setCookie("share-online.biz", "dl", info["dl"])

module/plugins/hoster/YoutubeCom.py

         if self.getConf("quality") == "sd":
             desired_fmt = "6"
         elif self.getConf("quality") == "hd" and hd_available:
-            desired_fmt = "2"
+            desired_fmt = "22"
+        elif self.getConf("quality") == "fullhd" and hd_available:
+            desired_fmt = "37"
 
         fmt_pattern = 'fmt_url_map=(.+?)&'
         fmt_url_map = re.search(fmt_pattern, html).group(1)

module/remote/RemoteManager.py

         self.core = manager.core
     
     def run(self):
-        self.core.log.info(_("Starting %s") % self.__class__.__name__)
         try:
             self.serve()
         except:
             if self.core.debug:
                 print_exc()
     
-    def setup(self):
+    def setup(self, host, port):
         pass
     
     def checkDeps(self):
         return self.manager.checkAuth(user, password, remoteip)
 
 class RemoteManager():
-    available = ("XMLRPCBackend", "ThriftBackend")
-    #available = ("ThriftBackend", )
+    available = ["ThriftBackend"]
 
     def __init__(self, core):
         self.core = core
         self.backends = []
     
     def startBackends(self):
+
+        host = self.core.config["remote"]["listenaddr"]
+        port = self.core.config["remote"]["port"]
+
+        if self.core.config["remote"]["xmlrpc"]:
+            self.available.append("XMLRPCBackend")
+
         for b in self.available:
             klass = getattr(__import__("module.remote.%s" % b, globals(), locals(), [b] , -1), b)
             backend = klass(self)
             if not backend.checkDeps():
                 continue
             try:
-                backend.setup()
+                backend.setup(host, port)
+                self.core.log.info(_("Starting %(name)s: %(addr)s:%(port)s") % {"name": b, "addr": host, "port": port})
             except:
                 self.core.log.error(_("Failed loading backend %s") % b)
                 if self.core.debug:
                 backend.start()
                 self.backends.append(backend)
 
+            port += 1
+
     def checkAuth(self, user, password, remoteip=None):
         if self.core.config["remote"]["nolocalauth"] and remoteip == "127.0.0.1":
             return True

module/remote/ThriftBackend.py

 from thrift.server import TServer
 
 class ThriftBackend(BackendBase):
-    def setup(self):
+    def setup(self, host, port):
         handler = Handler(self)
         processor = Processor(handler)
 
                 key = self.core.config['ssl']['key']
                 cert = self.core.config['ssl']['cert']
 
-        transport = ServerSocket(int(self.core.config['remote']['port'])+1, self.core.config["remote"]["listenaddr"], key, cert)
+        transport = ServerSocket(port, host, key, cert)
 
         tfactory = TransportFactory()
         pfactory = ProtocolFactory()

module/remote/XMLRPCBackend.py

 from module.remote.RemoteManager import BackendBase
 
 class XMLRPCBackend(BackendBase):
-    def setup(self):
-        server_addr = (self.core.config['remote']['listenaddr'], int(self.core.config['remote']['port']))
+    def setup(self, host, port):
+        server_addr = (host, port)
         if self.core.config['ssl']['activated']:
             if exists(self.core.config['ssl']['cert']) and exists(self.core.config['ssl']['key']):
                 self.core.log.info(_("Using SSL XMLRPCBackend"))

module/remote/thriftbackend/Handler.py

         self.serverMethods.unpause_server()
 
     def togglePause(self):
-        return self.serverMethods.toggle_server()
+        return self.serverMethods.toggle_pause()
 
     def statusServer(self):
         status = self.serverMethods.status_server()
             if not isinstance(pyfile, PyFile):
                 continue
             status = DownloadInfo()
-            status.id = pyfile.id
+            status.fid = pyfile.id
             status.name = pyfile.name
             status.speed = pyfile.getSpeed() #bytes
             status.eta = pyfile.getETA()
          - links
          - dest
         """
-        return self.serverMethods.add_package(name, links, dest)
+        return self.serverMethods.add_package(name, links, 0 if dest == Destination.Collector else 1)
 
     def getPackageData(self, pid):
         """
         pdata = PackageData()
         rawData = self.serverMethods.get_package_data(pid)
 
+        if not rawData:
+            raise PackageDoesNotExists(pid)
+
         pdata.pid = rawData["id"]
         pdata.name = rawData["name"]
         pdata.folder = rawData["folder"]
         if rawData:
             rawData = rawData.values()[0]
         else:
-            return None
+            raise FileDoesNotExists(fid)
+
         fdata = self._convertPyFile(rawData)
         return fdata
 
     def getQueue(self):
         packs = self.serverMethods.get_queue()
         ret = []
-        for pid in packs:
-            pack = self.serverMethods.get_package_data(pid)
+        for pid, pack in packs.iteritems():
             pdata = PackageInfo()
             pdata.pid = pack["id"]
             pdata.name = pack["name"]
             ret.append(pdata)
         return ret
 
-    def getCollector(self):
+    def getQueueData(self):
         packs = self.serverMethods.get_queue()
         ret = []
-        for pid in packs:
-            pack = self.serverMethods.get_package_data(pid)
+        for pid, pack in packs.iteritems():
+            pdata = PackageData()
+            pdata.pid = pack["id"]
+            pdata.name = pack["name"]
+            pdata.folder = pack["folder"]
+            pdata.site = pack["site"]
+            pdata.password = pack["password"]
+            pdata.dest = pack["queue"]
+            pdata.order = pack["order"]
+            pdata.priority = pack["priority"]
+            pdata.links = [self._convertPyFile(x) for x in pack["links"].values()]
+            ret.append(pdata)
+        return ret
+
+    def getCollector(self):
+        packs = self.serverMethods.get_collector()
+        ret = []
+        for pid, pack in packs.iteritems():
             pdata = PackageInfo()
             pdata.pid = pack["id"]
             pdata.name = pack["name"]
             pdata.dest = pack["queue"]
             pdata.order = pack["order"]
             pdata.priority = pack["priority"]
+            pdata.links = [self._convertPyFile(x) for x in pack["links"].values()]
+            ret.append(pdata)
+        return ret
+
+    def getCollectorData(self):
+        packs = self.serverMethods.get_collector()
+        ret = []
+        for pid, pack in packs.iteritems():
+            pdata = PackageData()
+            pdata.pid = pack["id"]
+            pdata.name = pack["name"]
+            pdata.folder = pack["folder"]
+            pdata.site = pack["site"]
+            pdata.password = pack["password"]
+            pdata.dest = pack["queue"]
+            pdata.order = pack["order"]
+            pdata.priority = pack["priority"]
             pdata.links = [int(x) for x in pack["links"].keys()]
             ret.append(pdata)
         return ret
         """
         rawData = self.serverMethods.get_package_data(pid)
         order = {}
-        for pyfile in rawData["links"]:
+        for id, pyfile in rawData["links"].iteritems():
             while pyfile["order"] in order.keys(): #just in case
                 pyfile["order"] += 1
             order[pyfile["order"]] = pyfile["id"]

module/remote/thriftbackend/Socket.py

 
 from thrift.transport.TSocket import TSocket, TServerSocket, TTransportException
 
+WantReadError = Exception #overwritten when ssl is used
+
 class SecureSocketConnection:
     def __init__(self, connection):
         self.__dict__["connection"] = connection
     def accept(self):
         connection, address = self.__dict__["connection"].accept()
         return SecureSocketConnection(connection), address
+    
+    def send(self, buff):
+        try:
+            return self.__dict__["connection"].send(buff)
+        except WantReadError:
+            return self.send(buff)
+    
+    def recv(self, buff):
+        try:
+            return self.__dict__["connection"].recv(buff)
+        except WantReadError:
+            return self.recv(buff)
 
 class Socket(TSocket):
     def __init__(self, host='localhost', port=7228, ssl=False):
     def open(self):
         if self.ssl:
             SSL = __import__("OpenSSL", globals(), locals(), "SSL", -1).SSL
+            WantReadError = SSL.WantReadError
             ctx = SSL.Context(SSL.SSLv23_METHOD)
-            self.handle = SecureSocketConnection(SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM)))
+            c = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
+            c.set_connect_state()
+            self.handle = SecureSocketConnection(c)
         else:
             self.handle = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
                 raise
             
         if not len(buff):
-          raise TTransportException(type=TTransportException.END_OF_FILE, message='TSocket read 0 bytes')
+            raise TTransportException(type=TTransportException.END_OF_FILE, message='TSocket read 0 bytes')
         return buff
 
 
     def listen(self):
         if self.cert and self.key:
             SSL = __import__("OpenSSL", globals(), locals(), "SSL", -1).SSL
+            WantReadError = SSL.WantReadError
             ctx = SSL.Context(SSL.SSLv23_METHOD)
             ctx.use_privatekey_file(self.key)
             ctx.use_certificate_file(self.cert)
 
             tmpConnection = SSL.Connection(ctx, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
+            tmpConnection.set_accept_state()
             self.handle = SecureSocketConnection(tmpConnection)
 
         else:
 
         self.handle.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
         if hasattr(self.handle, 'set_timeout'):
-          self.handle.set_timeout(None)
+            self.handle.set_timeout(None)
         self.handle.bind((self.host, self.port))
         self.handle.listen(128)
 

module/remote/thriftbackend/ThriftClient.py

 import sys
 from socket import error
 from os.path import dirname, abspath, join
+from traceback import print_exc
 
 try:
     import thrift
 from Protocol import Protocol
 
 from thriftgen.pyload import Pyload
+from thriftgen.pyload.Pyload import PackageDoesNotExists
+from thriftgen.pyload.Pyload import FileDoesNotExists
+
+
+ConnectionClosed = TTransport.TTransportException
 
 class WrongLogin(Exception):
     pass
     pass
 
 class ThriftClient:
-    def __init__(self, host="localhost", port=7228, user="", password=""):
+    def __init__(self, host="localhost", port=7227, user="", password=""):
 
         self.createConnection(host, port)
         try:
             self.transport.open()
         except error, e:
-            if e.args and e.args[0] == 111:
+            if e.args and e.args[0] in (111, 10061):
+                raise NoConnection
+            else:
+                print_exc()
                 raise NoConnection
 
         try:
                    correct = self.client.login(user, password)
                 finally:
                     self.socket.setTimeout(None)
+            elif e.args and e.args[0] == 32:
+                raise NoConnection
+            else:
+                print_exc()
+                raise NoConnection
 
         if not correct:
             self.transport.close()
 
 if __name__ == "__main__":
 
-    client = ThriftClient(user="User", password="pyloadweb")
+    client = ThriftClient(user="User", password="")
 
     print client.getServerVersion()
     print client.statusServer()

module/remote/thriftbackend/pyload.thrift

 }
 
 struct DownloadInfo {
-  1: FileID id,
+  1: FileID fid,
   2: string name,
   3: i64 speed,
   4: i32 eta,
   4: optional map<string, string> options
 }
 
+exception PackageDoesNotExists{
+  1: PackageID pid
+}
+
+exception FileDoesNotExists{
+  1: FileID fid
+}
+
+
 service Pyload {
   //general
   string getConfigValue(1: string category, 2: string option, 3: string section),
   //downloads
   list<DownloadInfo> statusDownloads(),
   PackageID addPackage(1: string name, 2: LinkList links, 3: Destination dest),
-  PackageData getPackageData(1: PackageID pid),
-  FileData getFileData(1: FileID fid),
+  PackageData getPackageData(1: PackageID pid) throws (1: PackageDoesNotExists e),
+  FileData getFileData(1: FileID fid) throws (1: FileDoesNotExists e),
   void deleteFiles(1: list<FileID> fids),
   void deletePackages(1: list<PackageID> pids),
   list<PackageInfo> getQueue(),
   list<PackageInfo> getCollector(),
+  list<PackageData> getQueueData(),
+  list<PackageData> getCollectorData(),
   void addFiles(1: PackageID pid, 2: LinkList links),
   void pushToQueue(1: PackageID pid),
   void pullFromQueue(1: PackageID pid),

module/remote/thriftbackend/thriftgen/pyload/Pyload-remote

   print '  void deletePackages( pids)'
   print '   getQueue()'
   print '   getCollector()'
+  print '   getQueueData()'
+  print '   getCollectorData()'
   print '  void addFiles(PackageID pid, LinkList links)'
   print '  void pushToQueue(PackageID pid)'
   print '  void pullFromQueue(PackageID pid)'
     sys.exit(1)
   pp.pprint(client.getCollector())
 
+elif cmd == 'getQueueData':
+  if len(args) != 0:
+    print 'getQueueData requires 0 args'
+    sys.exit(1)
+  pp.pprint(client.getQueueData())
+
+elif cmd == 'getCollectorData':
+  if len(args) != 0:
+    print 'getCollectorData requires 0 args'
+    sys.exit(1)
+  pp.pprint(client.getCollectorData())
+
 elif cmd == 'addFiles':
   if len(args) != 2:
     print 'addFiles requires 2 args'

module/remote/thriftbackend/thriftgen/pyload/Pyload.py

   def getCollector(self, ):
     pass
 
+  def getQueueData(self, ):
+    pass
+
+  def getCollectorData(self, ):
+    pass
+
   def addFiles(self, pid, links):
     """
     Parameters:
     self._iprot.readMessageEnd()
     if result.success != None:
       return result.success
+    if result.e != None:
+      raise result.e
     raise TApplicationException(TApplicationException.MISSING_RESULT, "getPackageData failed: unknown result");
 
   def getFileData(self, fid):
     self._iprot.readMessageEnd()
     if result.success != None:
       return result.success
+    if result.e != None:
+      raise result.e
     raise TApplicationException(TApplicationException.MISSING_RESULT, "getFileData failed: unknown result");
 
   def deleteFiles(self, fids):
       return result.success
     raise TApplicationException(TApplicationException.MISSING_RESULT, "getCollector failed: unknown result");
 
+  def getQueueData(self, ):
+    self.send_getQueueData()
+    return self.recv_getQueueData()
+
+  def send_getQueueData(self, ):
+    self._oprot.writeMessageBegin('getQueueData', TMessageType.CALL, self._seqid)
+    args = getQueueData_args()
+    args.write(self._oprot)
+    self._oprot.writeMessageEnd()
+    self._oprot.trans.flush()
+
+  def recv_getQueueData(self, ):
+    (fname, mtype, rseqid) = self._iprot.readMessageBegin()
+    if mtype == TMessageType.EXCEPTION:
+      x = TApplicationException()
+      x.read(self._iprot)
+      self._iprot.readMessageEnd()
+      raise x
+    result = getQueueData_result()
+    result.read(self._iprot)
+    self._iprot.readMessageEnd()
+    if result.success != None:
+      return result.success
+    raise TApplicationException(TApplicationException.MISSING_RESULT, "getQueueData failed: unknown result");
+
+  def getCollectorData(self, ):
+    self.send_getCollectorData()
+    return self.recv_getCollectorData()
+
+  def send_getCollectorData(self, ):
+    self._oprot.writeMessageBegin('getCollectorData', TMessageType.CALL, self._seqid)
+    args = getCollectorData_args()
+    args.write(self._oprot)
+    self._oprot.writeMessageEnd()
+    self._oprot.trans.flush()
+
+  def recv_getCollectorData(self, ):
+    (fname, mtype, rseqid) = self._iprot.readMessageBegin()
+    if mtype == TMessageType.EXCEPTION:
+      x = TApplicationException()
+      x.read(self._iprot)
+      self._iprot.readMessageEnd()
+      raise x
+    result = getCollectorData_result()
+    result.read(self._iprot)
+    self._iprot.readMessageEnd()
+    if result.success != None:
+      return result.success
+    raise TApplicationException(TApplicationException.MISSING_RESULT, "getCollectorData failed: unknown result");
+
   def addFiles(self, pid, links):
     """