diff options
Diffstat (limited to 'module')
-rw-r--r-- | module/Api.py | 34 | ||||
-rw-r--r-- | module/PyPackage.py | 9 | ||||
-rw-r--r-- | module/database/FileDatabase.py | 3 | ||||
-rw-r--r-- | module/plugins/Account.py | 30 | ||||
-rw-r--r-- | module/plugins/Crypter.py | 92 | ||||
-rw-r--r-- | module/plugins/crypter/LinkList.py (renamed from module/plugins/container/LinkList.py) | 32 | ||||
-rw-r--r-- | module/plugins/hoster/YoutubeCom.py | 6 | ||||
-rw-r--r-- | module/remote/thriftbackend/pyload.thrift | 2 | ||||
-rw-r--r-- | module/threads/BaseThread.py | 30 | ||||
-rw-r--r-- | module/threads/DecrypterThread.py | 65 | ||||
-rw-r--r-- | module/threads/DownloadThread.py | 4 | ||||
-rw-r--r-- | module/threads/InfoThread.py | 51 | ||||
-rw-r--r-- | module/threads/ThreadManager.py | 11 | ||||
-rw-r--r-- | module/utils/__init__.py | 4 | ||||
-rw-r--r-- | module/utils/fs.py | 5 | ||||
-rw-r--r-- | module/web/templates/default/base.html | 2 |
16 files changed, 223 insertions, 157 deletions
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): diff --git a/module/PyPackage.py b/module/PyPackage.py index dce501d93..d4b468f9c 100644 --- a/module/PyPackage.py +++ b/module/PyPackage.py @@ -69,6 +69,13 @@ class PyPackage(): def delete(self): self.m.deletePackage(self.id) - + + def deleteIfEmpty(self): + """ True if deleted """ + if not len(self.getChildren()): + self.delete() + return True + return False + def notifyChange(self): self.m.core.eventManager.dispatchEvent("packageUpdated", self.id) diff --git a/module/database/FileDatabase.py b/module/database/FileDatabase.py index abe7c8fc9..116f2b02b 100644 --- a/module/database/FileDatabase.py +++ b/module/database/FileDatabase.py @@ -190,8 +190,7 @@ class FileHandler: self.ev.dispatchEvent("linkDeleted", id, pid) p = self.getPackage(pid) - if not len(p.getChildren()): - p.delete() + p.deleteIfEmpty() pyfiles = self.cache.values() for pyfile in pyfiles: diff --git a/module/plugins/Account.py b/module/plugins/Account.py index 6b65051db..dcf36f8a0 100644 --- a/module/plugins/Account.py +++ b/module/plugins/Account.py @@ -48,10 +48,6 @@ class Account(Base, AccountInfo): else: activated = Account.activated - for opt in self.known_opt: - if opt not in options: - options[opt] = "" - for opt in options.keys(): if opt not in self.known_opt: del options[opt] @@ -74,12 +70,9 @@ class Account(Base, AccountInfo): def init(self): pass - #TODO: remove user, data - def login(self, user, data, req): + def login(self, req): """login into account, the cookies will be saved so user can be recognized - :param user: Deprecated - :param data: Deprecated :param req: `Request` instance """ raise NotImplemented @@ -98,7 +91,13 @@ class Account(Base, AccountInfo): self.login_ts = time() try: - self.login(self.loginname, {"password": self.password}, req) + try: + self.login(req) + except TypeError: #TODO: temporary + self.logDebug("Deprecated .login(...) signature ommit user, data") + self.login(self.loginname, {"password": self.password}, req) + + self.valid = True except WrongPassword: self.logWarning( @@ -117,24 +116,23 @@ class Account(Base, AccountInfo): return self.valid def restoreDefaults(self): - self.valid = Account.valid self.validuntil = Account.validuntil self.trafficleft = Account.trafficleft self.maxtraffic = Account.maxtraffic self.premium = Account.premium - self.activated = Account.activated - def update(self, password=None, options={}): + def update(self, password=None, options=None): """ updates account and return true if anything changed """ self.login_ts = 0 + self.valid = True #set valid so it will be retried to login if "activated" in options: self.activated = from_string(options["avtivated"], "bool") if password: self.password = password - self._login() + self.relogin() return True if options: # remove unknown options @@ -172,7 +170,11 @@ class Account(Base, AccountInfo): self.checkLogin(req) self.logDebug("Get Account Info for %s" % self.loginname) try: - infos = self.loadAccountInfo(self.loginname, req) + try: + infos = self.loadAccountInfo(req) + except TypeError: #TODO: temporary + self.logDebug("Deprecated .loadAccountInfo(...) signature, ommit user argument.") + infos = self.loadAccountInfo(self.loginname, req) except Exception, e: infos = {"error": str(e)} finally: diff --git a/module/plugins/Crypter.py b/module/plugins/Crypter.py index fc54b32d7..7c76afee7 100644 --- a/module/plugins/Crypter.py +++ b/module/plugins/Crypter.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- +from traceback import print_exc + from module.Api import Destination from module.common.packagetools import parseNames -from module.utils import to_list -from module.utils.fs import exists +from module.utils import to_list, has_method +from module.utils.fs import exists, remove, fs_encode from Base import Base, Retry @@ -17,6 +19,12 @@ class Package: def addUrl(self, url): self.urls.append(url) + def __eq__(self, other): + return self.name == other.name and self.urls == other.urls + + def __repr__(self): + return "<CrypterPackage name=%s, links=%s, dest=%s" % (self.name, self.urls, self.dest) + class PyFileMockup: """ Legacy class needed by old crypter plugins """ def __init__(self, url): @@ -49,8 +57,8 @@ class Crypter(Base): """Static method to decrypt, something. Can be used by other plugins. :param core: pyLoad `Core`, needed in decrypt context - :param url_or_urls: List of urls or urls - :return: List of decrypted urls, all packages info removed + :param url_or_urls: List of urls or single url/ file content + :return: List of decrypted urls, all package info removed """ urls = to_list(url_or_urls) p = cls(core) @@ -66,18 +74,19 @@ class Crypter(Base): ret.extend(url_or_pack.urls) else: # single url ret.append(url_or_pack) + # eliminate duplicates + return set(ret) - return ret - - def __init__(self, core, pid=-1, password=None): + def __init__(self, core, package=None, password=None): Base.__init__(self, core) self.req = core.requestFactory.getRequest(self.__name__) - # Package id plugin was initilized for, dont use this, its not guaranteed to be set - self.pid = pid - + # Package the plugin was initialized for, dont use this, its not guaranteed to be set + self.package = package #: Password supplied by user self.password = password + #: Propose a renaming of the owner package + self.rename = None # For old style decrypter, do not use these ! self.packages = [] @@ -125,7 +134,7 @@ class Crypter(Base): """ return [Package(name, purls) for name, purls in parseNames([(url,url) for url in urls]).iteritems()] - def processDecrypt(self, urls): + def _decrypt(self, urls): """ Internal method to select decrypting method :param urls: List of urls/content @@ -136,28 +145,47 @@ class Crypter(Base): # seperate local and remote files content, urls = self.getLocalContent(urls) - if hasattr(cls, "decryptURLs"): + if has_method(cls, "decryptURLs"): self.setup() result = to_list(self.decryptURLs(urls)) - elif hasattr(cls, "decryptURL"): + elif has_method(cls, "decryptURL"): result = [] for url in urls: self.setup() result.extend(to_list(self.decryptURL(url))) - elif hasattr(cls, "decrypt"): + elif has_method(cls, "decrypt"): self.logDebug("Deprecated .decrypt() method in Crypter plugin") - result = [] # TODO + self.setup() + self.decrypt() + result = self.convertPackages() else: - self.logError("No Decrypting method was overwritten") + if not has_method(cls, "decryptFile"): + self.logDebug("No Decrypting method was overwritten in plugin %s" % self.__name__) result = [] - if hasattr(cls, "decryptFile"): - for c in content: + if has_method(cls, "decryptFile"): + for f, c in content: self.setup() result.extend(to_list(self.decryptFile(c))) + try: + if f.startswith("tmp_"): remove(f) + except : + pass return result + def processDecrypt(self, urls): + """ Catches all exceptions in decrypt methods and return results + + :return: Decrypting results + """ + try: + return self._decrypt(urls) + except Exception: + if self.core.debug: + print_exc() + return [] + def getLocalContent(self, urls): """Load files from disk @@ -178,9 +206,13 @@ class Crypter(Base): path = self.core.path(url) if path: - f = open(path, "wb") - content.append(f.read()) - f.close() + try: + f = open(fs_encode(path), "rb") + content.append((f.name, f.read())) + f.close() + except IOError, e: + self.logError("IOError", e) + remote.append(url) else: remote.append(url) @@ -193,20 +225,12 @@ class Crypter(Base): """ Retry decrypting, will only work once. Somewhat deprecated method, should be avoided. """ raise Retry() - def createPackages(self): + def convertPackages(self): """ Deprecated """ - self.logDebug("Deprecated method .createPackages()") - for pack in self.packages: - - self.log.debug("Parsed package %(name)s with %(len)d links" % { "name" : pack[0], "len" : len(pack[1]) } ) - - links = [x.decode("utf-8") for x in pack[1]] - - pid = self.core.api.files.addLinks(self.pid, links) - - - if self.urls: - self.core.api.generateAndAddPackages(self.urls) + self.logDebug("Deprecated method .convertPackages()") + res = [Package(name, urls) for name, urls in self.packages] + res.extend(self.urls) + return res def clean(self): if hasattr(self, "req"): diff --git a/module/plugins/container/LinkList.py b/module/plugins/crypter/LinkList.py index 614c76c90..8e46f88a9 100644 --- a/module/plugins/container/LinkList.py +++ b/module/plugins/crypter/LinkList.py @@ -1,25 +1,21 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- - -from module.plugins.Crypter import Crypter +from module.plugins.Crypter import Crypter, Package class LinkList(Crypter): __name__ = "LinkList" __version__ = "0.11" __pattern__ = r".+\.txt$" __description__ = """Read Link Lists in txt format""" - __config__ = [("clear", "bool", "Clear Linklist after adding", False)] __author_name__ = ("spoob", "jeix") __author_mail__ = ("spoob@pyload.org", "jeix@hasnomail.com") + def decryptFile(self, content): + links = content.splitlines() - def decrypt(self, pyfile): - txt = open(pyfile.url, 'r') - links = txt.readlines() - curPack = "Parsed links from %s" % pyfile.name - - packages = {curPack:[],} + curPack = "default" + packages = {curPack:[]} for link in links: link = link.strip() @@ -33,10 +29,8 @@ class LinkList(Crypter): packages[curPack] = [] continue packages[curPack].append(link) - txt.close() # empty packages fix - delete = [] for key,value in packages.iteritems(): @@ -46,12 +40,12 @@ class LinkList(Crypter): for key in delete: del packages[key] - if self.getConfig("clear"): - try: - txt = open(pyfile.url, 'wb') - txt.close() - except: - self.log.warning(_("LinkList could not be cleared.")) - + urls = [] + for name, links in packages.iteritems(): - self.packages.append((name, links, name)) + if name == "default": + urls.extend(links) + else: + urls.append(Package(name, links)) + + return urls
\ No newline at end of file diff --git a/module/plugins/hoster/YoutubeCom.py b/module/plugins/hoster/YoutubeCom.py index 2b3ea7ed7..b6ea36a3c 100644 --- a/module/plugins/hoster/YoutubeCom.py +++ b/module/plugins/hoster/YoutubeCom.py @@ -75,10 +75,10 @@ class YoutubeCom(Hoster): fmt_dict[fmt] = unquote(url) self.logDebug("Found links: %s" % fmt_dict) - for fmt in fmt_dict.keys(): + for fmt in fmt_dict.keys(): if fmt not in self.formats: - self.logDebug("FMT not supported: %s" % fmt) - del fmt_dict[fmt] + self.logDebug("FMT not supported: %s" % fmt) + del fmt_dict[fmt] allowed = lambda x: self.getConfig(self.formats[x][0]) sel = lambda x: self.formats[x][3] #select quality index diff --git a/module/remote/thriftbackend/pyload.thrift b/module/remote/thriftbackend/pyload.thrift index a6c0a259c..d33b468c3 100644 --- a/module/remote/thriftbackend/pyload.thrift +++ b/module/remote/thriftbackend/pyload.thrift @@ -177,7 +177,7 @@ struct AccountInfo { 6: i64 maxtraffic, 7: bool premium, 8: bool activated, - 9: map<string, list<string>> options, + 9: map<string, string> options, } struct ServiceCall { diff --git a/module/threads/BaseThread.py b/module/threads/BaseThread.py index b5856c856..1ba3f7a9f 100644 --- a/module/threads/BaseThread.py +++ b/module/threads/BaseThread.py @@ -1,6 +1,10 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +import os +import sys +import locale + from threading import Thread from time import strftime, gmtime from sys import exc_info @@ -14,32 +18,33 @@ class BaseThread(Thread): """abstract base class for thread types""" def __init__(self, manager): - """Constructor""" Thread.__init__(self) self.setDaemon(True) self.m = manager #thread manager self.log = manager.core.log - - def writeDebugReport(self, pyfile): + def writeDebugReport(self, name, pyfile=None, plugin=None): """ writes a debug report to disk """ - dump_name = "debug_%s_%s.zip" % (pyfile.pluginname, strftime("%d-%m-%Y_%H-%M-%S")) - dump = self.getDebugDump(pyfile) + dump_name = "debug_%s_%s.zip" % (name, strftime("%d-%m-%Y_%H-%M-%S")) + if pyfile: + dump = self.getFileDump(pyfile) + else: + dump = self.getPluginDump(plugin) try: import zipfile zip = zipfile.ZipFile(dump_name, "w") - for f in listdir(join("tmp", pyfile.pluginname)): + for f in listdir(join("tmp", name)): try: # avoid encoding errors - zip.write(join("tmp", pyfile.pluginname, f), save_join(pyfile.pluginname, f)) + zip.write(join("tmp", name, f), save_join(name, f)) except: pass - info = zipfile.ZipInfo(save_join(pyfile.pluginname, "debug_Report.txt"), gmtime()) + info = zipfile.ZipInfo(save_join(name, "debug_Report.txt"), gmtime()) info.external_attr = 0644 << 16L # change permissions zip.writestr(info, dump) @@ -58,7 +63,7 @@ class BaseThread(Thread): self.log.info("Debug Report written to %s" % dump_name) - def getDebugDump(self, pyfile): + def getFileDump(self, pyfile): dump = "pyLoad %s Debug Report of %s %s \n\nTRACEBACK:\n %s \n\nFRAMESTACK:\n" % ( self.m.core.api.getServerVersion(), pyfile.pluginname, pyfile.plugin.__version__, format_exc()) @@ -111,6 +116,13 @@ class BaseThread(Thread): return dump + #TODO + def getPluginDump(self, plugin): + return "" + + def getSystemDump(self): + return "" + def clean(self, pyfile): """ set thread unactive and release pyfile """ self.active = False diff --git a/module/threads/DecrypterThread.py b/module/threads/DecrypterThread.py index 5ce59a65e..a1b7e4f38 100644 --- a/module/threads/DecrypterThread.py +++ b/module/threads/DecrypterThread.py @@ -1,35 +1,78 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +from time import sleep +from traceback import print_exc + +from module.plugins.Base import Retry +from module.plugins.Crypter import Package + from BaseThread import BaseThread class DecrypterThread(BaseThread): """thread for decrypting""" - def __init__(self, manager, data, package): + def __init__(self, manager, data, pid): """constructor""" BaseThread.__init__(self, manager) - self.queue = data - self.package = package - - self.m.log.debug("Starting Decrypt thread") + self.data = data + self.pid = pid self.start() - def add(self, data): - self.queue.extend(data) - def run(self): plugin_map = {} - for plugin, url in self.queue: + for url, plugin in self.data: if plugin in plugin_map: plugin_map[plugin].append(url) else: plugin_map[plugin] = [url] - self.decrypt(plugin_map) def decrypt(self, plugin_map): + pack = self.m.core.files.getPackage(self.pid) + result = [] + for name, urls in plugin_map.iteritems(): - p = self.m.core.pluginManager.loadClass("crypter", name) + klass = self.m.core.pluginManager.loadClass("crypter", name) + plugin = klass(self.m.core, pack, pack.password) + plugin_result = [] + + try: + try: + plugin_result = plugin._decrypt(urls) + except Retry: + sleep(1) + plugin_result = plugin._decrypt(urls) + except Exception, e: + plugin.logError(_("Decrypting failed"), e) + if self.m.core.debug: + print_exc() + self.writeDebugReport(plugin.__name__, plugin=plugin) + + plugin.logDebug("Decrypted", plugin_result) + result.extend(plugin_result) + + pack_names = {} + urls = [] + + for p in result: + if isinstance(p, Package): + if p.name in pack_names: + pack_names[p.name].urls.extend(p.urls) + else: + pack_names[p.name] = p + else: + urls.append(p) + + if urls: + self.log.info(_("Decrypted %(count)d links into package %(name)s") % {"count": len(urls), "name": pack.name}) + self.m.core.api.addFiles(self.pid, urls) + + for p in pack_names: + self.m.core.api.addPackage(p.name, p.urls, p.dest, pack.password) + + if not result: + self.log.info(_("No links decrypted")) + diff --git a/module/threads/DownloadThread.py b/module/threads/DownloadThread.py index 3d444686b..638861338 100644 --- a/module/threads/DownloadThread.py +++ b/module/threads/DownloadThread.py @@ -156,7 +156,7 @@ class DownloadThread(BaseThread): self.m.log.error("pycurl error %s: %s" % (code, msg)) if self.m.core.debug: print_exc() - self.writeDebugReport(pyfile) + self.writeDebugReport(pyfile.pluginname, pyfile) self.m.core.hookManager.downloadFailed(pyfile) @@ -186,7 +186,7 @@ class DownloadThread(BaseThread): if self.m.core.debug: print_exc() - self.writeDebugReport(pyfile) + self.writeDebugReport(pyfile.pluginname, pyfile) self.m.core.hookManager.downloadFailed(pyfile) self.clean(pyfile) diff --git a/module/threads/InfoThread.py b/module/threads/InfoThread.py index 4cba7da38..596153c4b 100644 --- a/module/threads/InfoThread.py +++ b/module/threads/InfoThread.py @@ -7,11 +7,12 @@ from traceback import print_exc from module.Api import OnlineStatus from module.PyFile import PyFile from module.common.packagetools import parseNames +from module.utils import has_method from BaseThread import BaseThread class InfoThread(BaseThread): - def __init__(self, manager, data, pid=-1, rid=-1, add=False): + def __init__(self, manager, data, pid=-1, rid=-1): """Constructor""" BaseThread.__init__(self, manager) @@ -20,7 +21,6 @@ class InfoThread(BaseThread): # [ .. (name, plugin) .. ] self.rid = rid #result id - self.add = add #add packages instead of return result self.cache = [] #accumulated data @@ -39,8 +39,8 @@ class InfoThread(BaseThread): plugins[plugin] = [url] - # filter out container plugins - for name in self.m.core.pluginManager.getPlugins("container"): + # filter out crypter plugins + for name in self.m.core.pluginManager.getPlugins("crypter"): if name in plugins: container.extend([(name, url) for url in plugins[name]]) @@ -50,35 +50,17 @@ class InfoThread(BaseThread): if self.pid > -1: for pluginname, urls in plugins.iteritems(): plugin = self.m.core.pluginManager.getPlugin(pluginname, True) - if hasattr(plugin, "getInfo"): + klass = getattr(plugin, pluginname) + if has_method(klass, "getInfo"): + self.fetchForPlugin(pluginname, klass, urls, self.updateDB) + self.m.core.files.save() + elif has_method(plugin, "getInfo"): + self.log.debug("Deprecated .getInfo() method on module level, use classmethod instead") self.fetchForPlugin(pluginname, plugin, urls, self.updateDB) self.m.core.files.save() - elif self.add: - for pluginname, urls in plugins.iteritems(): - plugin = self.m.core.pluginManager.getPlugin(pluginname, True) - if hasattr(plugin, "getInfo"): - self.fetchForPlugin(pluginname, plugin, urls, self.updateCache, True) - - else: - #generate default result - result = [(url, 0, 3, url) for url in urls] - - self.updateCache(pluginname, result) - - packs = parseNames([(name, url) for name, x, y, url in self.cache]) - - self.m.log.debug("Fetched and generated %d packages" % len(packs)) - - for k, v in packs: - self.m.core.api.addPackage(k, v) - - #empty cache - del self.cache[:] - else: #post the results - - + #TODO: finer crypter control for name, url in container: #attach container content try: @@ -98,13 +80,18 @@ class InfoThread(BaseThread): for pluginname, urls in plugins.iteritems(): plugin = self.m.core.pluginManager.getPlugin(pluginname, True) - if hasattr(plugin, "getInfo"): + klass = getattr(plugin, pluginname) + if has_method(klass, "getInfo"): + self.fetchForPlugin(pluginname, plugin, urls, self.updateResult, True) + #force to process cache + if self.cache: + self.updateResult(pluginname, [], True) + elif has_method(plugin, "getInfo"): + self.log.debug("Deprecated .getInfo() method on module level, use staticmethod instead") self.fetchForPlugin(pluginname, plugin, urls, self.updateResult, True) - #force to process cache if self.cache: self.updateResult(pluginname, [], True) - else: #generate default result result = [(url, 0, 3, url) for url in urls] diff --git a/module/threads/ThreadManager.py b/module/threads/ThreadManager.py index c32286eb9..612da2536 100644 --- a/module/threads/ThreadManager.py +++ b/module/threads/ThreadManager.py @@ -71,7 +71,7 @@ class ThreadManager: pycurl.global_init(pycurl.GLOBAL_DEFAULT) - for i in range(0, self.core.config.get("download", "max_downloads")): + for i in range(self.core.config.get("download", "max_downloads")): self.createThread() @@ -84,25 +84,24 @@ class ThreadManager: def createInfoThread(self, data, pid): """ start a thread whichs fetches online status and other infos """ self.timestamp = time() + 5 * 60 - - InfoThread(self, data, pid) + if data: InfoThread(self, data, pid) @lock - def createResultThread(self, data, add=False): + def createResultThread(self, data): """ creates a thread to fetch online status, returns result id """ self.timestamp = time() + 5 * 60 rid = self.resultIDs self.resultIDs += 1 - InfoThread(self, data, rid=rid, add=add) + InfoThread(self, data, rid=rid) return rid @lock def createDecryptThread(self, data, pid): """ Start decrypting of entered data, all links in one package are accumulated to one thread.""" - DecrypterThread(self, data, pid) + if data: DecrypterThread(self, data, pid) @lock diff --git a/module/utils/__init__.py b/module/utils/__init__.py index 0d68448cb..a237fde9b 100644 --- a/module/utils/__init__.py +++ b/module/utils/__init__.py @@ -157,6 +157,10 @@ def fixup(m): return text # leave as is +def has_method(obj, name): + """ checks if 'name' was defined in obj, (false if it was inhereted) """ + return name in obj.__dict__ + def html_unescape(text): """Removes HTML or XML character references and entities from a text string""" return re.sub("&#?\w+;", fixup, text) diff --git a/module/utils/fs.py b/module/utils/fs.py index 23f87a326..037165b6b 100644 --- a/module/utils/fs.py +++ b/module/utils/fs.py @@ -20,7 +20,10 @@ else: # FS utilities def chmod(path, mode): - return os.chmod(fs_encode(path), mode) + try: + return os.chmod(fs_encode(path), mode) + except : + pass def chown(path, uid, gid): return os.chown(fs_encode(path), uid, gid) diff --git a/module/web/templates/default/base.html b/module/web/templates/default/base.html index 0b20ecdb0..1f77c04ba 100644 --- a/module/web/templates/default/base.html +++ b/module/web/templates/default/base.html @@ -162,7 +162,7 @@ <hr style="clear: both;" />
-<div id="foot">© 2008-2011 pyLoad Team
+<div id="foot">© 2008-2012 pyLoad Team
<a href="#top" class="action top" accesskey="x"><span>{{_("Back to top")}}</span></a><br />
<!--<div class="breadcrumbs"></div>-->
|