summaryrefslogtreecommitdiffstats
path: root/pyload/plugins
diff options
context:
space:
mode:
authorGravatar Walter Purcaro <vuolter@gmail.com> 2014-11-22 18:08:10 +0100
committerGravatar Walter Purcaro <vuolter@gmail.com> 2014-11-22 18:08:10 +0100
commit48f911c4c49551ae58068c51412d935dd6f920ad (patch)
treea0429857027ecb8cff3e713bcfb3b55ed055cad5 /pyload/plugins
parent[SimpleCrypter][SimpleHoster] Fix info attr init (diff)
parent[XFSHoster] Improve ERROR_PATTERN + revert direct link detection in getDownlo... (diff)
downloadpyload-48f911c4c49551ae58068c51412d935dd6f920ad.tar.xz
Merge branch 'stable' into 0.4.10
Conflicts: module/PluginThread.py pyload/plugins/Plugin.py pyload/plugins/hoster/RarefileNet.py pyload/plugins/internal/MultiHoster.py pyload/plugins/internal/SimpleCrypter.py pyload/plugins/internal/SimpleHoster.py pyload/plugins/internal/XFSHoster.py
Diffstat (limited to 'pyload/plugins')
-rw-r--r--pyload/plugins/Plugin.py3
-rw-r--r--pyload/plugins/account/UptoboxCom.py3
-rw-r--r--pyload/plugins/hoster/EasybytezCom.py3
-rw-r--r--pyload/plugins/hoster/RarefileNet.py16
-rw-r--r--pyload/plugins/internal/SimpleCrypter.py47
-rw-r--r--pyload/plugins/internal/SimpleHoster.py129
-rw-r--r--pyload/plugins/internal/XFSAccount.py5
-rw-r--r--pyload/plugins/internal/XFSHoster.py152
8 files changed, 200 insertions, 158 deletions
diff --git a/pyload/plugins/Plugin.py b/pyload/plugins/Plugin.py
index a81fbef33..cf4debd37 100644
--- a/pyload/plugins/Plugin.py
+++ b/pyload/plugins/Plugin.py
@@ -16,7 +16,8 @@ from itertools import islice
from traceback import print_exc
from urlparse import urlparse
-from pyload.utils import encode, fs_decode, fs_encode, html_unescape, safe_join
+from pyload.utils import fs_decode, fs_encode, safe_join, safe_path
+
def chunks(iterable, size):
it = iter(iterable)
diff --git a/pyload/plugins/account/UptoboxCom.py b/pyload/plugins/account/UptoboxCom.py
index 36f541e96..9438888e3 100644
--- a/pyload/plugins/account/UptoboxCom.py
+++ b/pyload/plugins/account/UptoboxCom.py
@@ -6,7 +6,7 @@ from pyload.plugins.internal.XFSAccount import XFSAccount
class UptoboxCom(XFSAccount):
__name__ = "UptoboxCom"
__type__ = "account"
- __version__ = "0.06"
+ __version__ = "0.07"
__description__ = """DDLStorage.com account plugin"""
__license__ = "GPLv3"
@@ -14,3 +14,4 @@ class UptoboxCom(XFSAccount):
HOSTER_DOMAIN = "uptobox.com"
+ HOSTER_URL = "https://uptobox.com/"
diff --git a/pyload/plugins/hoster/EasybytezCom.py b/pyload/plugins/hoster/EasybytezCom.py
index b233e52ee..d02cb371b 100644
--- a/pyload/plugins/hoster/EasybytezCom.py
+++ b/pyload/plugins/hoster/EasybytezCom.py
@@ -6,7 +6,7 @@ from pyload.plugins.internal.XFSHoster import XFSHoster, create_getInfo
class EasybytezCom(XFSHoster):
__name__ = "EasybytezCom"
__type__ = "hoster"
- __version__ = "0.22"
+ __version__ = "0.23"
__pattern__ = r'http://(?:www\.)?easybytez\.com/\w{12}'
@@ -18,7 +18,6 @@ class EasybytezCom(XFSHoster):
HOSTER_DOMAIN = "easybytez.com"
- INFO_PATTERN = r'<span class="name">(?P<N>.+)</span><br>\s*<span class="size">(?P<S>[^<]+)</span>'
OFFLINE_PATTERN = r'>File not available'
LINK_PATTERN = r'(http://(\w+\.(easybytez|easyload|ezbytez|zingload)\.(com|to)|\d+\.\d+\.\d+\.\d+)/files/\d+/\w+/.+?)["\'<]'
diff --git a/pyload/plugins/hoster/RarefileNet.py b/pyload/plugins/hoster/RarefileNet.py
index fb54f6431..ce54b4dc7 100644
--- a/pyload/plugins/hoster/RarefileNet.py
+++ b/pyload/plugins/hoster/RarefileNet.py
@@ -3,13 +3,12 @@
import re
from pyload.plugins.internal.XFSHoster import XFSHoster, create_getInfo
-from pyload.utils import html_unescape
class RarefileNet(XFSHoster):
__name__ = "RarefileNet"
__type__ = "hoster"
- __version__ = "0.06"
+ __version__ = "0.08"
__pattern__ = r'http://(?:www\.)?rarefile\.net/\w{12}'
@@ -20,19 +19,10 @@ class RarefileNet(XFSHoster):
HOSTER_DOMAIN = "rarefile.net"
- NAME_PATTERN = r'<td><font color="red">(?P<N>.*?)</font></td>'
- SIZE_PATTERN = r'<td>Size : (?P<S>.+?)&nbsp;'
+ NAME_PATTERN = r'<font color="red">(?P<N>.+?)<'
+ SIZE_PATTERN = r'>Size : (?P<S>[\d.,]+) (?P<U>[\w^_]+)'
LINK_PATTERN = r'<a href="(?P<link>[^"]+)">(?P=link)</a>'
- def handleCaptcha(self, inputs):
- captcha_div = re.search(r'<b>Enter code.*?<div.*?>(.*?)</div>', self.html, re.S).group(1)
- self.logDebug(captcha_div)
- numerals = re.findall('<span.*?padding-left\s*:\s*(\d+).*?>(\d)</span>', html_unescape(captcha_div))
- inputs['code'] = "".join([a[1] for a in sorted(numerals, key=lambda num: int(num[0]))])
- self.logDebug("CAPTCHA", inputs['code'], numerals)
- return 3
-
-
getInfo = create_getInfo(RarefileNet)
diff --git a/pyload/plugins/internal/SimpleCrypter.py b/pyload/plugins/internal/SimpleCrypter.py
index eb0f8a323..ead5cefba 100644
--- a/pyload/plugins/internal/SimpleCrypter.py
+++ b/pyload/plugins/internal/SimpleCrypter.py
@@ -5,15 +5,14 @@ import re
from urlparse import urlparse
from pyload.plugins.internal.Crypter import Crypter
-from pyload.plugins.Plugin import Fail
-from pyload.plugins.internal.SimpleHoster import _error, _wait, parseFileInfo, replace_patterns, set_cookies
-from pyload.utils import fixup, html_unescape
+from pyload.plugins.internal.SimpleHoster import SimpleHoster, replace_patterns, set_cookies
+from pyload.utils import fixup
-class SimpleCrypter(Crypter):
+class SimpleCrypter(Crypter, SimpleHoster):
__name__ = "SimpleCrypter"
__type__ = "crypter"
- __version__ = "0.30"
+ __version__ = "0.31"
__pattern__ = r'^unmatchable$'
__config__ = [("use_subfolder", "bool", "Save package to subfolder", True), #: Overrides core.config['general']['folder_per_package']
@@ -70,15 +69,15 @@ class SimpleCrypter(Crypter):
def prepare(self):
+ self.info = {}
+ self.links = []
+
if self.LOGIN_ACCOUNT and not self.account:
self.fail(_("Required account not found"))
if self.LOGIN_PREMIUM and not self.premium:
self.fail(_("Required premium account not found"))
- self.info = {}
- self.links = []
-
self.req.setOption("timeout", 120)
if isinstance(self.COOKIES, list):
@@ -87,13 +86,6 @@ class SimpleCrypter(Crypter):
self.pyfile.url = replace_patterns(self.pyfile.url, self.URL_REPLACEMENTS)
- def preload(self):
- self.html = self.load(self.pyfile.url, cookies=bool(self.COOKIES), decode=not self.TEXT_ENCODING)
-
- if isinstance(self.TEXT_ENCODING, basestring):
- self.html = unicode(self.html, self.TEXT_ENCODING)
-
-
def decrypt(self, pyfile):
self.prepare()
@@ -125,30 +117,19 @@ class SimpleCrypter(Crypter):
self.tempOffline()
- def checkName(self):
+ def checkNameSize(self):
name = self.info['name']
url = self.info['url']
if name and name != url:
self.pyfile.name = name
else:
- self.pyfile.name = self.info['name'] = urlparse(html_unescape(name)).path.split('/')[-1]
-
- self.info['folder'] = self.pyfile.name
-
- self.logDebug("File name: %s" % self.pyfile.name)
-
+ self.pyfile.name = name = self.info['name'] = urlparse(name).path.split('/')[-1]
- def checkInfo(self):
- self.logDebug(_("File info (previous): %s") % self.info)
+ folder = self.info['folder'] = name
- info = parseFileInfo(self.pyfile.url, self.html or "")
- self.info.update(info)
-
- self.logDebug(_("File info (current): %s") % self.info)
-
- self.checkName()
- self.checkStatus()
+ self.logDebug("File name: %s" % name,
+ "File folder: %s" % folder)
def getLinks(self):
@@ -169,7 +150,3 @@ class SimpleCrypter(Crypter):
for p in xrange(2, pages + 1):
self.html = self.loadPage(p)
self.links += self.getLinks()
-
-
- def error(self, reason="", type="parse"):
- return super(SimpleCrypter, self).error(self, reason, type)
diff --git a/pyload/plugins/internal/SimpleHoster.py b/pyload/plugins/internal/SimpleHoster.py
index 9fd4268dc..0a3d5cf95 100644
--- a/pyload/plugins/internal/SimpleHoster.py
+++ b/pyload/plugins/internal/SimpleHoster.py
@@ -7,12 +7,14 @@ from urlparse import urlparse
from pycurl import FOLLOWLOCATION
-from pyload.datatype.PyFile import statusMap
+from pyload.datatype.PyFile import statusMap as _statusMap
from pyload.network.CookieJar import CookieJar
from pyload.network.RequestFactory import getURL
from pyload.plugins.internal.Hoster import Hoster
from pyload.plugins.Plugin import Fail
-from pyload.utils import fixup, html_unescape, parseFileSize
+from pyload.utils import fixup, parseFileSize
+#@TODO: Adapt and move to PyFile in 0.4.10
+statusMap = {v: k for k, v in _statusMap.iteritems()}
def replace_patterns(string, ruleslist):
@@ -70,13 +72,15 @@ def parseHtmlForm(attr_str, html, input_names=None):
return {}, None #: no matching form found
+#: Deprecated
def parseFileInfo(plugin, url="", html=""):
info = plugin.getInfo(url, html)
return info['name'], info['size'], info['status'], info['url']
+#@TODO: Remove in 0.4.10
def create_getInfo(plugin):
- return lambda urls: list(plugin.parseInfo(urls))
+ return lambda urls: [(info['name'], info['size'], info['status'], info['url']) for info in plugin.parseInfo(urls)]
def timestamp():
@@ -101,7 +105,7 @@ def _getDirectLink(self, url):
class SimpleHoster(Hoster):
__name__ = "SimpleHoster"
__type__ = "hoster"
- __version__ = "0.56"
+ __version__ = "0.59"
__pattern__ = r'^unmatchable$'
@@ -113,7 +117,7 @@ class SimpleHoster(Hoster):
"""
- Following patterns should be defined by each hoster:
+ Info patterns should be defined by each hoster:
INFO_PATTERN: (optional) Name and Size of the file
example: INFO_PATTERN = r'(?P<N>file_name) (?P<S>file_size) (?P<U>size_unit)'
@@ -123,17 +127,26 @@ class SimpleHoster(Hoster):
SIZE_PATTERN: (optional) Size that will be checked for the file
example: SIZE_PATTERN = r'(?P<S>file_size) (?P<U>size_unit)'
- OFFLINE_PATTERN: (optional) Checks if the file is yet available online
+ OFFLINE_PATTERN: (optional) Check if the file is yet available online
example: OFFLINE_PATTERN = r'File (deleted|not found)'
- TEMP_OFFLINE_PATTERN: (optional) Checks if the file is temporarily offline
+ TEMP_OFFLINE_PATTERN: (optional) Check if the file is temporarily offline
example: TEMP_OFFLINE_PATTERN = r'Server (maintenance|maintainance)'
- PREMIUM_ONLY_PATTERN: (optional) Checks if the file can be downloaded only with a premium account
+
+ Error handling patterns are all optional:
+
+ WAIT_PATTERN: (optional) Detect waiting time
+ example: WAIT_PATTERN = r''
+
+ PREMIUM_ONLY_PATTERN: (optional) Check if the file can be downloaded only with a premium account
example: PREMIUM_ONLY_PATTERN = r'Premium account required'
+ ERROR_PATTERN: (optional) Detect any error preventing download
+ example: ERROR_PATTERN = r''
+
- Instead overriding handleFree and handlePremium methods now you can define patterns for direct download:
+ Instead overriding handleFree and handlePremium methods you can define the following patterns for direct download:
LINK_FREE_PATTERN: (optional) group(1) should be the direct link for free download
example: LINK_FREE_PATTERN = r'<div class="link"><a href="(.+?)"'
@@ -149,7 +162,8 @@ class SimpleHoster(Hoster):
TEXT_ENCODING = False #: Set to True or encoding name if encoding value in http header is not correct
COOKIES = True #: or False or list of tuples [(domain, name, value)]
FORCE_CHECK_TRAFFIC = False #: Set to True to force checking traffic left for premium account
- CHECK_DIRECT_LINK = None #: Set to None self-set to True if self.account else to False
+ CHECK_DIRECT_LINK = None #: when None self-set to True if self.account else False
+ MULTI_HOSTER = False #: Set to True to leech other hoster link
CONTENT_DISPOSITION = False #: Set to True to replace file name with content-disposition value in http header
@@ -157,7 +171,7 @@ class SimpleHoster(Hoster):
def parseInfo(cls, urls):
for url in urls:
url = replace_patterns(url, cls.URL_REPLACEMENTS)
- yield cls.getInfo(cls, url)
+ yield cls.getInfo(url)
@classmethod
@@ -217,17 +231,31 @@ class SimpleHoster(Hoster):
def prepare(self):
- self.info = {}
- self.link = "" #@TODO: Move to hoster class in 0.4.10
-
- if self.CHECK_DIRECT_LINK is None:
- self.CHECK_DIRECT_LINK = bool(self.account)
+ self.info = {}
+ self.link = "" #@TODO: Move to hoster class in 0.4.10
+ self.directDL = False #@TODO: Move to hoster class in 0.4.10
+ self.multihost = False #@TODO: Move to hoster class in 0.4.10
self.req.setOption("timeout", 120)
if isinstance(self.COOKIES, list):
set_cookies(self.req.cj, self.COOKIES)
+ if (self.MULTI_HOSTER
+ and self.__pattern__ != self.core.pluginManager.hosterPlugins[self.__name__]['pattern']
+ and re.match(self.__pattern__, self.pyfile.url) is None):
+
+ self.logInfo("Multi hoster detected")
+
+ if self.account:
+ self.multihost = True
+ return
+ else:
+ self.fail(_("Only registered or premium users can use url leech feature"))
+
+ if self.CHECK_DIRECT_LINK is None:
+ self.directDL = bool(self.account)
+
self.pyfile.url = replace_patterns(self.pyfile.url, self.URL_REPLACEMENTS)
@@ -241,24 +269,31 @@ class SimpleHoster(Hoster):
def process(self, pyfile):
self.prepare()
- if self.CHECK_DIRECT_LINK:
+ if self.multihost:
+ self.logDebug("Looking for leeched download link...")
+ self.handleMulti()
+
+ elif self.directDL:
self.logDebug("Looking for direct download link...")
self.handleDirect()
if not self.link:
self.preload()
- #@TODO: Remove in 0.4.10
if self.html is None:
self.fail(_("No html retrieved"))
+ self.checkErrors()
+
+ premium_only = 'error' in self.info and self.info['error'] == "premium-only"
+
info = self.getInfo(pyfile.url, self.html)
self._updateInfo(info)
self.checkNameSize()
- premium_only = hasattr(self, 'PREMIUM_ONLY_PATTERN') and re.search(self.PREMIUM_ONLY_PATTERN, self.html)
- if not premium_only: #: Usually premium only pages doesn't show any file information
+ #: Usually premium only pages doesn't show any file information
+ if not premium_only:
self.checkStatus()
if self.premium and (not self.FORCE_CHECK_TRAFFIC or self.checkTrafficLeft()):
@@ -276,6 +311,30 @@ class SimpleHoster(Hoster):
self.download(self.link, disposition=self.CONTENT_DISPOSITION)
+ def checkErrors(self):
+ if hasattr(self, 'WAIT_PATTERN'):
+ m = re.search(self.WAIT_PATTERN, self.html)
+ if m:
+ wait_time = sum([int(v) * {"hr": 3600, "hour": 3600, "min": 60, "sec": 1}[u.lower()] for v, u in
+ re.findall(r'(\d+)\s*(hr|hour|min|sec)', m, re.I)])
+ self.wait(wait_time, False)
+ return
+
+ if hasattr(self, 'PREMIUM_ONLY_PATTERN'):
+ m = re.search(self.PREMIUM_ONLY_PATTERN, self.html)
+ if m:
+ self.info['error'] = "premium-only"
+ return
+
+ if hasattr(self, 'ERROR_PATTERN'):
+ m = re.search(self.ERROR_PATTERN, self.html)
+ if m:
+ e = self.info['error'] = m.group(1)
+ self.error(e)
+
+ self.info.pop('error', None)
+
+
def checkStatus(self):
status = self.info['status']
@@ -286,8 +345,9 @@ class SimpleHoster(Hoster):
self.tempOffline()
elif status is not 2:
- self.error(_("File status: %s") % filter(lambda key, val: val == status, statusMap.iteritems())[0],
- _("File info: %s") % self.info)
+ self.logInfo(_("File status: %s") % statusMap[status],
+ _("File info: %s") % self.info)
+ self.error(_("No file info retrieved"))
def checkNameSize(self):
@@ -298,26 +358,35 @@ class SimpleHoster(Hoster):
if name and name != url:
self.pyfile.name = name
else:
- self.pyfile.name = self.info['name'] = urlparse(html_unescape(name)).path.split('/')[-1]
+ self.pyfile.name = name = self.info['name'] = urlparse(name).path.split('/')[-1]
if size > 0:
self.pyfile.size = size
else:
- self.logError(_("File size not found"))
+ size = "Unknown"
- self.logDebug("File name: %s" % self.pyfile.name, "File size: %s" % self.pyfile.size or _("Unknown"))
+ self.logDebug("File name: %s" % name,
+ "File size: %s" % size)
def checkInfo(self):
+ self.checkErrors()
+
self._updateInfo(self.getInfo(self.pyfile.url, self.html or ""))
+
self.checkNameSize()
self.checkStatus()
- def _updateInfo(self, info)
- self.logDebug(_("File info (previous): %s") % self.info)
+ #: Deprecated
+ def getFileInfo(self):
+ return self.checkInfo()
+
+
+ def _updateInfo(self, info):
+ self.logDebug(_("File info (before update): %s") % self.info)
self.info.update(info)
- self.logDebug(_("File info (current): %s") % self.info)
+ self.logDebug(_("File info (after update): %s") % self.info)
def handleDirect(self):
@@ -333,6 +402,10 @@ class SimpleHoster(Hoster):
self.logDebug(_("Direct download link not found"))
+ def handleMulti(self): #: Multi-hoster handler
+ pass
+
+
def handleFree(self):
if not hasattr(self, 'LINK_FREE_PATTERN'):
self.fail(_("Free download not implemented"))
diff --git a/pyload/plugins/internal/XFSAccount.py b/pyload/plugins/internal/XFSAccount.py
index df28191f1..1e18c09bd 100644
--- a/pyload/plugins/internal/XFSAccount.py
+++ b/pyload/plugins/internal/XFSAccount.py
@@ -12,7 +12,7 @@ from pyload.plugins.internal.SimpleHoster import parseHtmlForm, set_cookies
class XFSAccount(Account):
__name__ = "XFSAccount"
__type__ = "account"
- __version__ = "0.25"
+ __version__ = "0.26"
__description__ = """XFileSharing account plugin"""
__license__ = "GPLv3"
@@ -92,6 +92,9 @@ class XFSAccount(Account):
except Exception, e:
self.logError(e)
+ else:
+ if premium:
+ trafficleft = -1
return {'validuntil': validuntil, 'trafficleft': trafficleft, 'premium': premium}
diff --git a/pyload/plugins/internal/XFSHoster.py b/pyload/plugins/internal/XFSHoster.py
index a9fe2d0ad..3ae9ee05a 100644
--- a/pyload/plugins/internal/XFSHoster.py
+++ b/pyload/plugins/internal/XFSHoster.py
@@ -16,7 +16,7 @@ from pyload.utils import html_unescape
class XFSHoster(SimpleHoster):
__name__ = "XFSHoster"
__type__ = "hoster"
- __version__ = "0.17"
+ __version__ = "0.22"
__pattern__ = r'^unmatchable$'
@@ -32,27 +32,30 @@ class XFSHoster(SimpleHoster):
URL_REPLACEMENTS = [(r'/(?:embed-)?(\w{12}).*', r'/\1')] #: plus support embedded files
- COOKIES = [(HOSTER_DOMAIN, "lang", "english")]
+ TEXT_ENCODING = False
+ COOKIES = [(HOSTER_DOMAIN, "lang", "english")]
+ CHECK_DIRECT_LINK = None
+ MULTI_HOSTER = False
INFO_PATTERN = r'<tr><td align=right><b>Filename:</b></td><td nowrap>(?P<N>[^<]+)</td></tr>\s*.*?<small>\((?P<S>[^<]+)\)</small>'
- NAME_PATTERN = r'<input type="hidden" name="fname" value="(?P<N>[^"]+)"'
- SIZE_PATTERN = r'You have requested .*\((?P<S>[\d.,]+) ?(?P<U>[\w^_]+)?\)</font>'
+ NAME_PATTERN = r'(>Filename:</b></td><td nowrap>|name="fname" value="|<span class="name">|<[Tt]itle>.*?Download )(?P<N>.+?)(\s*<|")'
+ SIZE_PATTERN = r'(>Size:</b></td><td>|>File:.*>|<span class="size">)(?P<S>[\d.,]+)\s*(?P<U>[\w^_]+)'
OFFLINE_PATTERN = r'>\s*\w+ (Not Found|file (was|has been) removed)'
TEMP_OFFLINE_PATTERN = r'>\s*\w+ server (is in )?(maintenance|maintainance)'
- WAIT_PATTERN = r'<span id="countdown_str">.*?>(\d+)</span>|id="countdown" value=".*?(\d+).*?"'
+ WAIT_PATTERN = r'<span id="countdown_str">.*?>(\d+)</span>|id="countdown" value=".*?(\d+).*?"'
+ PREMIUM_ONLY_PATTERN = r'>This file is available for Premium Users only'
+ ERROR_PATTERN = r'(?:class=["\']err["\'].*?>|<[Cc]enter><b>|>Error</td>|>\(ERROR:)(?:\s*<.+?>\s*)*(.+?)(?:["\']|<|\))'
OVR_LINK_PATTERN = r'<h2>Download Link</h2>\s*<textarea[^>]*>([^<]+)'
LINK_PATTERN = None #: final download url pattern
- CAPTCHA_PATTERN = r'(http://[^"\']+?/captchas?/[^"\']+)'
+ CAPTCHA_PATTERN = r'(https?://[^"\']+?/captchas?/[^"\']+)'
CAPTCHA_DIV_PATTERN = r'>Enter code.*?<div.*?>(.+?)</div>'
RECAPTCHA_PATTERN = None
SOLVEMEDIA_PATTERN = None
- ERROR_PATTERN = r'(?:class=["\']err["\'][^>]*>|<[Cc]enter><b>)(.+?)(?:["\']|</)|>\(ERROR:(.+?)\)'
-
def setup(self):
self.chunkLimit = 1
@@ -71,23 +74,14 @@ class XFSHoster(SimpleHoster):
pattern = r'(https?://(www\.)?([^/]*?%s|\d+\.\d+\.\d+\.\d+)(\:\d+)?(/d/|(/files)?/\d+/\w+/).+?)["\'<]'
self.LINK_PATTERN = pattern % self.HOSTER_DOMAIN.replace('.', '\.')
- if self.CHECK_DIRECT_LINK is None:
- self.CHECK_DIRECT_LINK = bool(self.premium)
-
- self.captcha = None
- self.errmsg = None
+ self.captcha = None
+ self.errmsg = None
self.passwords = self.getPassword().splitlines()
- if (self.__pattern__ != self.core.pluginManager.hosterPlugins[self.__name__]['pattern']
- and re.match(self.__pattern__, self.pyfile.url) is None):
- self.logInfo(_("Multi hoster detected"))
- if self.premium:
- self.logDebug(_("Looking for download link..."))
- self.handleOverriden()
- else:
- self.fail(_("Only premium users can use url leech feature"))
+ super(XFSHoster, self).prepare()
- return super(XFSHoster, self).prepare()
+ if self.CHECK_DIRECT_LINK is None:
+ self.directDL = bool(self.premium)
def handleFree(self):
@@ -128,26 +122,26 @@ class XFSHoster(SimpleHoster):
self.req.http.c.setopt(FOLLOWLOCATION, 0)
self.html = self.load(self.pyfile.url, post=data, ref=True, decode=True)
- self.header = self.req.http.header
self.req.http.c.setopt(FOLLOWLOCATION, 1)
- m = re.search(r'Location\s*:\s*(.+)', self.header, re.I)
- if m:
+ m = re.search(r'Location\s*:\s*(.+)', self.req.http.header, re.I)
+ if m and not "op=" in m.group(1):
break
m = re.search(self.LINK_PATTERN, self.html, re.S)
if m:
break
else:
- return
+ self.logError(data['op'] if 'op' in data else _("UNKNOWN"))
+ return ""
self.errmsg = None
return m.group(1)
- def handleOverriden(self):
+ def handleMulti(self):
#only tested with easybytez.com
self.html = self.load("http://www.%s/" % self.HOSTER_DOMAIN)
@@ -197,27 +191,36 @@ class XFSHoster(SimpleHoster):
self.error(_("OVR_LINK_PATTERN not found"))
header = self.load(m.group(1), just_header=True, decode=True)
+
if 'location' in header: #: Direct download link
- self.download(header['location'], ref=True, cookies=True, disposition=True)
+ self.link = header['location']
else:
self.fail(_("Download link not found"))
def checkErrors(self):
+ m = re.search(self.PREMIUM_ONLY_PATTERN, self.html)
+ if m:
+ self.info['error'] = "premium-only"
+ return
+
m = re.search(self.ERROR_PATTERN, self.html)
if m is None:
self.errmsg = None
else:
- self.errmsg = m.group(1)
+ self.errmsg = m.group(1).strip()
self.logWarning(re.sub(r"<.*?>", " ", self.errmsg))
if 'wait' in self.errmsg:
- wait_time = sum([int(v) * {"hour": 3600, "minute": 60, "second": 1}[u] for v, u in
- re.findall(r'(\d+)\s*(hour|minute|second)', self.errmsg)])
+ wait_time = sum([int(v) * {"hr": 3600, "hour": 3600, "min": 60, "sec": 1}[u.lower()] for v, u in
+ re.findall(r'(\d+)\s*(hr|hour|min|sec)', self.errmsg, re.I)])
self.wait(wait_time, True)
+ elif 'country' in self.errmsg:
+ self.fail(_("Downloads are disabled for your country"))
+
elif 'captcha' in self.errmsg:
self.invalidCaptcha()
@@ -247,62 +250,57 @@ class XFSHoster(SimpleHoster):
else:
self.retry(wait_time=60, reason=self.errmsg)
+ if self.errmsg:
+ self.info['error'] = self.errmsg
+ else:
+ self.info.pop('error', None)
+
return self.errmsg
def getPostParameters(self):
- for _i in xrange(3):
- if hasattr(self, "FORM_PATTERN"):
- action, inputs = self.parseHtmlForm(self.FORM_PATTERN)
- else:
- action, inputs = self.parseHtmlForm(input_names={"op": re.compile("^download")})
+ if hasattr(self, "FORM_PATTERN"):
+ action, inputs = self.parseHtmlForm(self.FORM_PATTERN)
+ else:
+ action, inputs = self.parseHtmlForm(input_names={"op": re.compile("^download")})
+ if not inputs:
+ action, inputs = self.parseHtmlForm('F1')
if not inputs:
- action, inputs = self.parseHtmlForm('F1')
- if not inputs:
- if self.errmsg:
- self.retry(reason=self.errmsg)
- else:
- self.error(_("TEXTAREA F1 not found"))
-
- self.logDebug(inputs)
-
- if 'op' in inputs and inputs['op'] in ("download1", "download2", "download3"):
- if "password" in inputs:
- if self.passwords:
- inputs['password'] = self.passwords.pop(0)
- else:
- self.fail(_("No or invalid passport"))
-
- if not self.premium:
- m = re.search(self.WAIT_PATTERN, self.html)
- if m:
- wait_time = int(m.group(1))
- self.setWait(wait_time, False)
- else:
- wait_time = 0
-
- self.captcha = self.handleCaptcha(inputs)
-
- if wait_time:
- self.wait()
-
- return inputs
- else:
- inputs['referer'] = self.pyfile.url
+ if self.errmsg:
+ self.retry(reason=self.errmsg)
+ else:
+ self.error(_("TEXTAREA F1 not found"))
- if self.premium:
- inputs['method_premium'] = "Premium Download"
- if 'method_free' in inputs:
- del inputs['method_free']
+ self.logDebug(inputs)
+
+ if 'op' in inputs:
+ if "password" in inputs:
+ if self.passwords:
+ inputs['password'] = self.passwords.pop(0)
else:
- inputs['method_free'] = "Free Download"
- if 'method_premium' in inputs:
- del inputs['method_premium']
+ self.fail(_("Missing password"))
+
+ if not self.premium:
+ m = re.search(self.WAIT_PATTERN, self.html)
+ if m:
+ wait_time = int(m.group(1))
+ self.setWait(wait_time, False)
+
+ self.captcha = self.handleCaptcha(inputs)
- self.html = self.load(self.pyfile.url, post=inputs, ref=True)
+ self.wait()
else:
- self.error(_("FORM: %s") % (inputs['op'] if 'op' in inputs else _("UNKNOWN")))
+ inputs['referer'] = self.pyfile.url
+
+ if self.premium:
+ inputs['method_premium'] = "Premium Download"
+ inputs.pop('method_free', None)
+ else:
+ inputs['method_free'] = "Free Download"
+ inputs.pop('method_premium', None)
+
+ return inputs
def handleCaptcha(self, inputs):