summaryrefslogtreecommitdiffstats
path: root/module/plugins/hoster
diff options
context:
space:
mode:
Diffstat (limited to 'module/plugins/hoster')
-rw-r--r--module/plugins/hoster/AlldebridCom.py91
-rw-r--r--module/plugins/hoster/BasePlugin.py33
-rw-r--r--module/plugins/hoster/BayfilesCom.py30
-rw-r--r--module/plugins/hoster/BitshareCom.py53
-rw-r--r--module/plugins/hoster/CoolshareCz.py61
-rw-r--r--module/plugins/hoster/CramitIn.py20
-rw-r--r--module/plugins/hoster/CrockoCom.py4
-rw-r--r--module/plugins/hoster/CzshareCom.py26
-rw-r--r--module/plugins/hoster/DataportCz.py54
-rw-r--r--module/plugins/hoster/DateiTo.py92
-rw-r--r--module/plugins/hoster/DdlstorageCom.py20
-rw-r--r--module/plugins/hoster/DepositfilesCom.py62
-rw-r--r--module/plugins/hoster/DlFreeFr.py182
-rw-r--r--module/plugins/hoster/EasybytezCom.py119
-rw-r--r--module/plugins/hoster/ExtabitCom.py84
-rw-r--r--module/plugins/hoster/FastshareCz.py52
-rw-r--r--module/plugins/hoster/FilecloudIo.py112
-rw-r--r--module/plugins/hoster/FiledinoCom.py21
-rw-r--r--module/plugins/hoster/FilefactoryCom.py174
-rw-r--r--module/plugins/hoster/FilejungleCom.py75
-rw-r--r--module/plugins/hoster/FilepostCom.py26
-rw-r--r--module/plugins/hoster/FilerioCom.py20
-rw-r--r--module/plugins/hoster/FileserveCom.py379
-rw-r--r--module/plugins/hoster/FourSharedCom.py24
-rw-r--r--module/plugins/hoster/FreakshareCom.py51
-rw-r--r--module/plugins/hoster/FshareVn.py44
-rw-r--r--module/plugins/hoster/GigapetaCom.py73
-rw-r--r--module/plugins/hoster/HellshareCz.py11
-rw-r--r--module/plugins/hoster/HotfileCom.py29
-rw-r--r--module/plugins/hoster/IcyFilesCom.py112
-rw-r--r--module/plugins/hoster/IfileIt.py37
-rw-r--r--module/plugins/hoster/IfolderRu.py6
-rw-r--r--module/plugins/hoster/JumbofilesCom.py31
-rw-r--r--module/plugins/hoster/LetitbitNet.py61
-rw-r--r--module/plugins/hoster/LoadTo.py22
-rw-r--r--module/plugins/hoster/MediafireCom.py17
-rw-r--r--module/plugins/hoster/NarodRu.py66
-rw-r--r--module/plugins/hoster/NetloadIn.py30
-rw-r--r--module/plugins/hoster/OneFichierCom.py51
-rwxr-xr-xmodule/plugins/hoster/OronCom.py24
-rw-r--r--module/plugins/hoster/PremiumizeMe.py50
-rw-r--r--module/plugins/hoster/PutlockerCom.py126
-rw-r--r--module/plugins/hoster/RapidgatorNet.py181
-rw-r--r--module/plugins/hoster/RapidshareCom.py16
-rw-r--r--module/plugins/hoster/RarefileNet.py26
-rw-r--r--module/plugins/hoster/RealdebridCom.py174
-rw-r--r--module/plugins/hoster/RyushareCom.py18
-rw-r--r--module/plugins/hoster/Share4webCom.py16
-rw-r--r--module/plugins/hoster/ShareRapidCom.py82
-rw-r--r--module/plugins/hoster/ShareonlineBiz.py176
-rw-r--r--module/plugins/hoster/ShragleCom.py149
-rw-r--r--module/plugins/hoster/StahnuTo.py27
-rw-r--r--module/plugins/hoster/TurbobitNet.py169
-rw-r--r--module/plugins/hoster/TwoSharedCom.py7
-rw-r--r--module/plugins/hoster/UlozTo.py155
-rw-r--r--module/plugins/hoster/UnibytesCom.py80
-rw-r--r--module/plugins/hoster/UploadStationCom.py150
-rw-r--r--module/plugins/hoster/UploadedTo.py82
-rw-r--r--module/plugins/hoster/UploadheroCom.py84
-rw-r--r--module/plugins/hoster/UploadingCom.py74
-rw-r--r--module/plugins/hoster/WarserverCz.py34
-rw-r--r--module/plugins/hoster/WebshareCz.py45
-rw-r--r--module/plugins/hoster/WrzucTo.py58
-rw-r--r--module/plugins/hoster/XFileSharingPro.py286
-rw-r--r--module/plugins/hoster/YibaishiwuCom.py54
-rw-r--r--module/plugins/hoster/ZeveraCom.py191
-rw-r--r--module/plugins/hoster/ZippyshareCom.py165
67 files changed, 3819 insertions, 1335 deletions
diff --git a/module/plugins/hoster/AlldebridCom.py b/module/plugins/hoster/AlldebridCom.py
new file mode 100644
index 000000000..e93e7beb9
--- /dev/null
+++ b/module/plugins/hoster/AlldebridCom.py
@@ -0,0 +1,91 @@
+#!/usr/nv python
+# -*- coding: utf-8 -*-
+
+import re
+from urllib import quote, unquote
+from random import randrange
+from os import stat
+
+from module.plugins.Hoster import Hoster
+from module.common.json_layer import json_loads
+from module.utils import parseFileSize, fs_encode
+
+
+class AlldebridCom(Hoster):
+ __name__ = "AlldebridCom"
+ __version__ = "0.2"
+ __type__ = "hoster"
+
+ __pattern__ = r"https?://.*alldebrid\..*"
+ __description__ = """Alldebrid.com hoster plugin"""
+ __author_name__ = ("Andy, Voigt")
+ __author_mail__ = ("spamsales@online.de")
+
+ def getFilename(self, url):
+ try:
+ name = unquote(url.rsplit("/", 1)[1])
+ except IndexError:
+ name = "Unknown_Filename..."
+ if name.endswith("..."): #incomplete filename, append random stuff
+ name += "%s.tmp" % randrange(100,999)
+ return name
+
+ def init(self):
+ self.tries = 0
+ self.chunkLimit = 3
+ self.resumeDownload = True
+
+
+ def process(self, pyfile):
+ if not self.account:
+ self.logError(_("Please enter your AllDebrid account or deactivate this plugin"))
+ self.fail("No AllDebrid account provided")
+
+ self.log.debug("AllDebrid: Old URL: %s" % pyfile.url)
+ if re.match(self.__pattern__, pyfile.url):
+ new_url = pyfile.url
+ else:
+ password = self.getPassword().splitlines()
+ if not password: password = ""
+ else: password = password[0]
+
+ url = "http://www.alldebrid.com/service.php?link=%s&json=true&pw=%s" %(pyfile.url, password)
+ page = self.load(url)
+ data = json_loads(page)
+
+ self.log.debug("Json data: %s" % str(data))
+
+ if data["error"]:
+ if data["error"] == "This link isn't available on the hoster website.":
+ self.offline()
+ else:
+ self.logWarning(data["error"])
+ self.tempOffline()
+ else:
+ if self.pyfile.name and not self.pyfile.name.endswith('.tmp'):
+ self.pyfile.name = data["filename"]
+ self.pyfile.size = parseFileSize(data["filesize"])
+ new_url = data["link"]
+
+ if self.getConfig("https"):
+ new_url = new_url.replace("http://", "https://")
+ else:
+ new_url = new_url.replace("https://", "http://")
+
+ self.log.debug("AllDebrid: New URL: %s" % new_url)
+
+ if pyfile.name.startswith("http") or pyfile.name.startswith("Unknown"):
+ #only use when name wasnt already set
+ pyfile.name = self.getFilename(new_url)
+
+ self.download(new_url, disposition=True)
+
+ check = self.checkDownload(
+ {"error": "<title>An error occured while processing your request</title>","empty": re.compile(r"^$")})
+
+ if check == "error":
+ self.retry(reason="An error occured while generating link.", wait_time=60)
+ else:
+ if check == "empty":
+ self.retry(reason="Downloaded File was empty.", wait_time=60)
+
diff --git a/module/plugins/hoster/BasePlugin.py b/module/plugins/hoster/BasePlugin.py
index 0e9595265..f1e3006d0 100644
--- a/module/plugins/hoster/BasePlugin.py
+++ b/module/plugins/hoster/BasePlugin.py
@@ -1,16 +1,18 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from urlparse import urlparse
+from re import search
+from urllib import unquote
from module.network.HTTPRequest import BadHeader
from module.plugins.Hoster import Hoster
-from module.utils import html_unescape
+from module.utils import html_unescape, remove_chars
class BasePlugin(Hoster):
__name__ = "BasePlugin"
__type__ = "hoster"
__pattern__ = r"^unmatchable$"
- __version__ = "0.14"
+ __version__ = "0.15"
__description__ = """Base Plugin when any other didnt fit"""
__author_name__ = ("RaNaN")
__author_mail__ = ("RaNaN@pyload.org")
@@ -60,5 +62,28 @@ class BasePlugin(Hoster):
def downloadFile(self, pyfile):
- pyfile.name = html_unescape(urlparse(pyfile.url).path.split("/")[-1])
- self.download(pyfile.url, disposition=True)
+ header = self.load(pyfile.url, just_header = True)
+ #self.logDebug(header)
+
+ if 'location' in header:
+ self.logDebug("Location: " + header['location'])
+ url = unquote(header['location'])
+ else:
+ url = pyfile.url
+
+ name = html_unescape(unquote(urlparse(url).path.split("/")[-1]))
+
+ if 'content-disposition' in header:
+ self.logDebug("Content-Disposition: " + header['content-disposition'])
+ m = search("filename(?P<type>=|\*=(?P<enc>.+)'')(?P<name>.*)", header['content-disposition'])
+ if m:
+ disp = m.groupdict()
+ self.logDebug(disp)
+ if not disp['enc']: disp['enc'] = 'utf-8'
+ name = remove_chars(disp['name'], "\"';").strip()
+ name = unicode(unquote(name), disp['enc'])
+
+ if not name: name = url
+ pyfile.name = name
+ self.logDebug("Filename: %s" % pyfile.name)
+ self.download(url, disposition=True) \ No newline at end of file
diff --git a/module/plugins/hoster/BayfilesCom.py b/module/plugins/hoster/BayfilesCom.py
index c771f28c6..190d9a952 100644
--- a/module/plugins/hoster/BayfilesCom.py
+++ b/module/plugins/hoster/BayfilesCom.py
@@ -26,18 +26,19 @@ class BayfilesCom(SimpleHoster):
__name__ = "BayfilesCom"
__type__ = "hoster"
__pattern__ = r"http://(?:www\.)?bayfiles\.com/file/\w+/\w+/.*"
- __version__ = "0.01"
+ __version__ = "0.04"
__description__ = """Bayfiles.com plugin - free only"""
__author_name__ = ("zoidberg")
__author_mail__ = ("zoidberg@mujmail.cz")
FILE_INFO_PATTERN = r'<p title="(?P<N>[^"]+)">[^<]*<strong>(?P<S>[0-9., ]+)(?P<U>[kKMG])i?B</strong></p>'
- FILE_OFFLINE_PATTERN = r'<p>The requested file could not be found.</p>'
+ FILE_OFFLINE_PATTERN = r'(<p>The requested file could not be found.</p>|<title>404 Not Found</title>)'
WAIT_PATTERN = r'>Your IP [0-9.]* has recently downloaded a file\. Upgrade to premium or wait (\d+) minutes\.<'
VARS_PATTERN = r'var vfid = (\d+);\s*var delay = (\d+);'
LINK_PATTERN = r"javascript:window.location.href = '([^']+)';"
-
+ PREMIUM_LINK_PATTERN = r'(?:<a class="highlighted-btn" href="|(?=http://s\d+\.baycdn\.com/dl/))(.*?)"'
+
def handleFree(self):
found = re.search(self.WAIT_PATTERN, self.html)
if found:
@@ -69,9 +70,24 @@ class BayfilesCom(SimpleHoster):
# Get final link and download
found = re.search(self.LINK_PATTERN, self.html)
if not found: self.parseError("Free link")
- url = found.group(1)
- self.logDebug("URL: " + url)
-
+ self.startDownload(found.group(1))
+
+ def handlePremium(self):
+ found = re.search(self.PREMIUM_LINK_PATTERN, self.html)
+ if not found: self.parseError("Premium link")
+ self.startDownload(found.group(1))
+
+ def startDownload(self, url):
+ self.logDebug("%s URL: %s" % ("Premium" if self.premium else "Free", url))
self.download(url)
+ # check download
+ check = self.checkDownload({
+ "waitforfreeslots": re.compile(r"<title>BayFiles</title>"),
+ "notfound": re.compile(r"<title>404 Not Found</title>")
+ })
+ if check == "waitforfreeslots":
+ self.retry(60, 300, "Wait for free slot")
+ elif check == "notfound":
+ self.retry(60, 300, "404 Not found")
-getInfo = create_getInfo(BayfilesCom) \ No newline at end of file
+getInfo = create_getInfo(BayfilesCom)
diff --git a/module/plugins/hoster/BitshareCom.py b/module/plugins/hoster/BitshareCom.py
index 794e978b2..f5d59d428 100644
--- a/module/plugins/hoster/BitshareCom.py
+++ b/module/plugins/hoster/BitshareCom.py
@@ -2,6 +2,7 @@
from __future__ import with_statement
import re
+from pycurl import FOLLOWLOCATION
from module.plugins.Hoster import Hoster
from module.plugins.ReCaptcha import ReCaptcha
@@ -45,22 +46,24 @@ class BitshareCom(Hoster):
__name__ = "BitshareCom"
__type__ = "hoster"
__pattern__ = r"http://(www\.)?bitshare\.com/(files/(?P<id1>[a-zA-Z0-9]+)(/(?P<name>.*?)\.html)?|\?f=(?P<id2>[a-zA-Z0-9]+))"
- __version__ = "0.41"
+ __version__ = "0.45"
__description__ = """Bitshare.Com File Download Hoster"""
__author_name__ = ("paulking", "fragonib")
__author_mail__ = (None, "fragonib[AT]yahoo[DOT]es")
HOSTER_DOMAIN = "bitshare.com"
FILE_OFFLINE_PATTERN = r'''(>We are sorry, but the requested file was not found in our database|>Error - File not available<|The file was deleted either by the uploader, inactivity or due to copyright claim)'''
- FILE_INFO_PATTERN = r'<h1>Downloading\s(?P<name>.+?)\s-\s(?P<size>[\d.]+)\s(?P<units>..)yte</h1>'
+ FILE_INFO_PATTERN = r'<h1>(Downloading|Streaming)\s(?P<name>.+?)\s-\s(?P<size>[\d.]+)\s(?P<units>..)yte</h1>'
FILE_AJAXID_PATTERN = r'var ajaxdl = "(.*?)";'
CAPTCHA_KEY_PATTERN = r"http://api\.recaptcha\.net/challenge\?k=(.*?) "
def setup(self):
- self.multiDL = False
+ self.multiDL = self.premium
self.chunkLimit = 1
def process(self, pyfile):
+ if self.premium:
+ self.account.relogin(self.user)
self.pyfile = pyfile
@@ -71,7 +74,7 @@ class BitshareCom(Hoster):
# Load main page
self.req.cj.setCookie(self.HOSTER_DOMAIN, "language_selection", "EN")
- self.html = self.load(self.pyfile.url, ref=False, decode=True)
+ self.html = self.load(self.pyfile.url, ref=False, decode=True, cookies = False)
# Check offline
if re.search(self.FILE_OFFLINE_PATTERN, self.html) is not None:
@@ -87,12 +90,20 @@ class BitshareCom(Hoster):
# Ajax file id
self.ajaxid = re.search(BitshareCom.FILE_AJAXID_PATTERN, self.html).group(1)
self.logDebug("File ajax id is [%s]" % self.ajaxid)
+
+ # This may either download our file or forward us to an error page
+ url = self.getDownloadUrl()
+ self.logDebug("Downloading file with url [%s]" % url)
+ self.download(url)
- # Handle free downloading
- self.handleFree()
-
- def handleFree(self):
-
+
+ def getDownloadUrl(self):
+ # Return location if direct download is active
+ if self.premium:
+ header = self.load(self.pyfile.url, cookies = True, just_header = True)
+ if 'location' in header:
+ return header['location']
+
# Get download info
self.logDebug("Getting download info")
response = self.load("http://bitshare.com/files-ajax/" + self.file_id + "/request.html",
@@ -107,8 +118,13 @@ class BitshareCom(Hoster):
# Waiting
if wait > 0:
self.logDebug("Waiting %d seconds." % wait)
- self.setWait(wait, True)
- self.wait()
+ if wait < 120:
+ self.setWait(wait, False)
+ self.wait()
+ else:
+ self.setWait(wait - 55, True)
+ self.wait()
+ self.retry()
# Resolve captcha
if captcha == 1:
@@ -131,15 +147,14 @@ class BitshareCom(Hoster):
post={"request" : "getDownloadURL", "ajaxid" : self.ajaxid})
self.handleErrors(response, '#')
url = response.split("#")[-1]
-
- # Request download URL
- # This may either download our file or forward us to an error page
- self.logDebug("Downloading file with url [%s]" % url)
- self.download(url)
+ return url
+
def handleErrors(self, response, separator):
self.logDebug("Checking response [%s]" % response)
- if "ERROR" in response:
+ if "ERROR:Session timed out" in response:
+ self.retry()
+ elif "ERROR" in response:
msg = response.split(separator)[-1]
self.fail(msg)
@@ -148,5 +163,7 @@ class BitshareCom(Hoster):
if "SUCCESS" in response:
self.correctCaptcha()
return True
+ elif "ERROR:SESSION ERROR" in response:
+ self.retry()
self.logDebug("Wrong captcha")
- self.invalidCaptcha() \ No newline at end of file
+ self.invalidCaptcha()
diff --git a/module/plugins/hoster/CoolshareCz.py b/module/plugins/hoster/CoolshareCz.py
new file mode 100644
index 000000000..7007b6fcb
--- /dev/null
+++ b/module/plugins/hoster/CoolshareCz.py
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: zoidberg
+"""
+
+#shares code with WarserverCz
+
+import re
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+from module.network.HTTPRequest import BadHeader
+from module.utils import html_unescape
+
+class CoolshareCz(SimpleHoster):
+ __name__ = "CoolshareCz"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:\w*\.)?coolshare.cz/stahnout/(?P<ID>\d+)/.+"
+ __version__ = "0.12"
+ __description__ = """CoolShare.cz"""
+ __author_name__ = ("zoidberg")
+
+ FILE_NAME_PATTERN = ur'<h1.*?>Stáhnout (?P<N>[^<]+)</h1>'
+ FILE_SIZE_PATTERN = r'<li>Velikost: <strong>(?P<S>[^<]+)</strong>'
+ FILE_OFFLINE_PATTERN = r'<h1>Soubor nenalezen</h1>'
+
+ PREMIUM_URL_PATTERN = r'href="(http://[^/]+/dwn-premium.php.*?)"'
+ DOMAIN = "http://csd01.coolshare.cz"
+
+ SH_CHECK_TRAFFIC = True
+
+ def handleFree(self):
+ try:
+ self.download("%s/dwn-free.php?fid=%s" % (self.DOMAIN, self.file_info['ID']))
+ except BadHeader, e:
+ if e.code == 403:
+ self.setWait(300, True)
+ self.wait()
+ self.retry(max_tries = 24, reason = "Download limit reached")
+ else: raise
+
+ def handlePremium(self):
+ found = re.search(self.PREMIUM_URL_PATTERN, self.html)
+ if not found: self.parseError("Premium URL")
+ url = html_unescape(found.group(1))
+ self.logDebug("Premium URL: " + url)
+ if not url.startswith("http://"): self.resetAccount()
+ self.download(url)
+
+getInfo = create_getInfo(CoolshareCz) \ No newline at end of file
diff --git a/module/plugins/hoster/CramitIn.py b/module/plugins/hoster/CramitIn.py
new file mode 100644
index 000000000..a7935c744
--- /dev/null
+++ b/module/plugins/hoster/CramitIn.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo
+
+class CramitIn(XFileSharingPro):
+ __name__ = "CramitIn"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:\w*\.)*cramit.in/\w{12}"
+ __version__ = "0.03"
+ __description__ = """Cramit.in hoster plugin"""
+ __author_name__ = ("zoidberg")
+ __author_mail__ = ("zoidberg@mujmail.cz")
+
+ FILE_INFO_PATTERN = r'<span class=t2>\s*(?P<N>.*?)</span>.*?<small>\s*\((?P<S>.*?)\)'
+ DIRECT_LINK_PATTERN = r'href="(http://cramit.in/file_download/.*?)"'
+ HOSTER_NAME = "cramit.in"
+
+ def setup(self):
+ self.multiDL = self.premium
+
+getInfo = create_getInfo(CramitIn) \ No newline at end of file
diff --git a/module/plugins/hoster/CrockoCom.py b/module/plugins/hoster/CrockoCom.py
index bf058b613..27ab52436 100644
--- a/module/plugins/hoster/CrockoCom.py
+++ b/module/plugins/hoster/CrockoCom.py
@@ -9,13 +9,13 @@ class CrockoCom(SimpleHoster):
__name__ = "CrockoCom"
__type__ = "hoster"
__pattern__ = r"http://(www\.)?(crocko|easy-share).com/.*"
- __version__ = "0.12"
+ __version__ = "0.13"
__description__ = """Crocko Download Hoster"""
__author_name__ = ("zoidberg")
__author_mail__ = ("zoidberg@mujmail.cz")
FILE_NAME_PATTERN = r'<span class="fz24">Download:\s*<strong>(?P<N>.*)'
- FILE_NAME_PATTERN = r'<span class="tip1"><span class="inner">(?P<S>[^<]+)</span></span>'
+ FILE_SIZE_PATTERN = r'<span class="tip1"><span class="inner">(?P<S>[^<]+)</span></span>'
FILE_OFFLINE_PATTERN = r"<h1>Sorry,<br />the page you're looking for <br />isn't here.</h1>"
DOWNLOAD_URL_PATTERN = r"window.location ='([^']+)';"
CAPTCHA_URL_PATTERN = re.compile(r"u='(/file_contents/captcha/\w+)';\s*w='(\d+)';")
diff --git a/module/plugins/hoster/CzshareCom.py b/module/plugins/hoster/CzshareCom.py
index 0ef9c267c..538e3ed86 100644
--- a/module/plugins/hoster/CzshareCom.py
+++ b/module/plugins/hoster/CzshareCom.py
@@ -45,7 +45,7 @@ class CzshareCom(SimpleHoster):
__name__ = "CzshareCom"
__type__ = "hoster"
__pattern__ = r"http://(\w*\.)*czshare\.(com|cz)/(\d+/|download.php\?).*"
- __version__ = "0.86"
+ __version__ = "0.88"
__description__ = """CZshare.com"""
__author_name__ = ("zoidberg")
@@ -62,7 +62,7 @@ class CzshareCom(SimpleHoster):
USER_CREDIT_PATTERN = r'<div class="credit">\s*kredit: <strong>([0-9., ]+)([kKMG]i?B)</strong>\s*</div><!-- .credit -->'
def setup(self):
- self.resumeDownload = self.multiDL = True if self.premium else False
+ self.multiDL = self.resumeDownload = True if self.premium else False
self.chunkLimit = 1
def process(self, pyfile):
@@ -140,16 +140,29 @@ class CzshareCom(SimpleHoster):
inputs['captchastring2'] = self.decryptCaptcha(captcha_url)
self.logDebug('CAPTCHA_URL:' + captcha_url + ' CAPTCHA:' + inputs['captchastring2'])
+ self.html = self.load(parsed_url, cookies=True, post=inputs)
+
+ found = re.search("countdown_number = (\d+);", self.html)
+ self.setWait(int(found.group(1)) if found else 50)
+
# download the file, destination is determined by pyLoad
- self.download(parsed_url, cookies=True, post=inputs)
+ self.logDebug("WAIT URL", self.req.lastEffectiveURL)
+ found = re.search("free_wait.php\?server=(.*?)&(.*)", self.req.lastEffectiveURL)
+ if not found:
+ raise PluginParseError('Download URL')
+ url = "http://%s/download.php?%s" % (found.group(1), found.group(2))
+
+ self.wait()
+ self.multiDL = True
+ self.download(url)
def checkDownloadedFile(self):
# check download
check = self.checkDownload({
"tempoffline": re.compile(r"^Soubor je do.asn. nedostupn.$"),
"multi_dl": re.compile(self.MULTIDL_PATTERN),
- "captcha_err": re.compile(self.FREE_FORM_PATTERN)
+ "captcha_err": "<li>Zadaný ověřovací kód nesouhlasí!</li>"
})
if check == "tempoffline":
@@ -160,7 +173,8 @@ class CzshareCom(SimpleHoster):
self.invalidCaptcha()
self.retry()
- def waitForFreeSlot(self):
- self.setWait(900, True)
+ def waitForFreeSlot(self, wait_time = 300):
+ self.multiDL = False
+ self.setWait(wait_time, True)
self.wait()
self.retry() \ No newline at end of file
diff --git a/module/plugins/hoster/DataportCz.py b/module/plugins/hoster/DataportCz.py
index 487766201..cef115941 100644
--- a/module/plugins/hoster/DataportCz.py
+++ b/module/plugins/hoster/DataportCz.py
@@ -17,33 +17,51 @@
"""
import re
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, PluginParseError
+from pycurl import FOLLOWLOCATION
class DataportCz(SimpleHoster):
__name__ = "DataportCz"
__type__ = "hoster"
__pattern__ = r"http://.*dataport.cz/file/.*"
- __version__ = "0.33"
+ __version__ = "0.35"
__description__ = """Dataport.cz plugin - free only"""
__author_name__ = ("zoidberg")
- FILE_NAME_PATTERN = r'<h2 style="color: red;">(?P<N>[^<]+)</h2>'
- FILE_SIZE_PATTERN = r'<td>Velikost souboru:</td>\s*<td>(?P<S>[0-9.]+)(?P<U>[kKMG])i?B</td>'
- URL_PATTERN = r'<td><a href="([^"]+)"[^>]*class="ui-state-default button hover ui-corner-all "><strong>'
- NO_SLOTS_PATTERN = r'<td><a href="http://dataport.cz/kredit/"[^>]*class="ui-state-default button hover ui-corner-all ui-state-disabled">'
+ FILE_NAME_PATTERN = r'<span itemprop="name">(?P<N>[^<]+)</span>'
+ FILE_SIZE_PATTERN = r'<td class="fil">Velikost</td>\s*<td>(?P<S>[^<]+)</td>'
FILE_OFFLINE_PATTERN = r'<h2>Soubor nebyl nalezen</h2>'
- def handleFree(self):
- if re.search(self.NO_SLOTS_PATTERN, self.html):
- self.setWait(900, True)
- self.wait()
- self.retry(12, 0, "No free slots")
-
- found = re.search(self.URL_PATTERN, self.html)
- if found is None:
- self.fail("Parse error (URL)")
- download_url = found.group(1)
-
- self.download(download_url)
+ CAPTCHA_URL_PATTERN = r'<section id="captcha_bg">\s*<img src="(.*?)"'
+ FREE_SLOTS_PATTERN = ur'Počet volných slotů: <span class="darkblue">(\d+)</span><br />'
+ def handleFree(self):
+ captchas = {"1": "jkeG", "2": "hMJQ", "3": "vmEK", "4": "ePQM", "5": "blBd"}
+
+ for i in range(60):
+ action, inputs = self.parseHtmlForm('free_download_form')
+ self.logDebug(action, inputs)
+ if not action or not inputs:
+ raise PluginParseError('free_download_form')
+
+ if "captchaId" in inputs and inputs["captchaId"] in captchas:
+ inputs['captchaCode'] = captchas[inputs["captchaId"]]
+ else:
+ raise PluginParseError('captcha')
+
+ self.html = self.download("http://dataport.cz%s" % action, post = inputs)
+
+ check = self.checkDownload({"captcha": 'alert("\u0160patn\u011b opsan\u00fd k\u00f3d z obr\u00e1zu");',
+ "slot": 'alert("Je n\u00e1m l\u00edto, ale moment\u00e1ln\u011b nejsou'})
+ if check == "captcha":
+ raise PluginParseError('invalid captcha')
+ elif check == "slot":
+ self.logDebug("No free slots - wait 60s and retry")
+ self.setWait(60, False)
+ self.wait()
+ self.html = self.load(self.pyfile.url, decode = True)
+ continue
+ else:
+ break
+
create_getInfo(DataportCz) \ No newline at end of file
diff --git a/module/plugins/hoster/DateiTo.py b/module/plugins/hoster/DateiTo.py
new file mode 100644
index 000000000..529a5a06f
--- /dev/null
+++ b/module/plugins/hoster/DateiTo.py
@@ -0,0 +1,92 @@
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: zoidberg
+"""
+
+import re
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+from module.plugins.ReCaptcha import ReCaptcha
+
+class DateiTo(SimpleHoster):
+ __name__ = "DateiTo"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:www\.)?datei\.to/datei/(?P<ID>\w+)\.html"
+ __version__ = "0.01"
+ __description__ = """Datei.to plugin - free only"""
+ __author_name__ = ("zoidberg")
+ __author_mail__ = ("zoidberg@mujmail.cz")
+
+ FILE_NAME_PATTERN = r'Dateiname:</td>\s*<td colspan="2"><strong>(?P<N>.*?)</'
+ FILE_SIZE_PATTERN = r'Dateigr&ouml;&szlig;e:</td>\s*<td colspan="2">(?P<S>.*?)</'
+ FILE_OFFLINE_PATTERN = r'>Datei wurde nicht gefunden<|>Bitte wähle deine Datei aus... <'
+ PARALELL_PATTERN = r'>Du lädst bereits eine Datei herunter<'
+
+ WAIT_PATTERN = r'countdown\({seconds: (\d+)'
+ DATA_PATTERN = r'url: "(.*?)", data: "(.*?)",'
+ RECAPTCHA_KEY_PATTERN = r'Recaptcha.create\("(.*?)"'
+
+ def handleFree(self):
+ url = 'http://datei.to/ajax/download.php'
+ data = {'P': 'I', 'ID': self.file_info['ID']}
+
+ recaptcha = ReCaptcha(self)
+
+ for i in range(10):
+ self.logDebug("URL", url, "POST", data)
+ self.html = self.load(url, post = data)
+ self.checkErrors()
+
+ if url.endswith('download.php') and 'P' in data:
+ if data['P'] == 'I':
+ self.doWait()
+
+ elif data['P'] == 'IV':
+ break
+
+ found = re.search(self.DATA_PATTERN, self.html)
+ if not found: self.parseError('data')
+ url = 'http://datei.to/' + found.group(1)
+ data = dict(x.split('=') for x in found.group(2).split('&'))
+
+ if url.endswith('recaptcha.php'):
+ found = re.search(self.RECAPTCHA_KEY_PATTERN, self.html)
+ recaptcha_key = found.group(1) if found else "6LdBbL8SAAAAAI0vKUo58XRwDd5Tu_Ze1DA7qTao"
+
+ data['recaptcha_challenge_field'], data['recaptcha_response_field'] = recaptcha.challenge(recaptcha_key)
+
+ else:
+ self.fail('Too bad...')
+
+ download_url = self.html
+ self.logDebug('Download URL', download_url)
+ self.download(download_url)
+
+ def checkErrors(self):
+ found = re.search(self.PARALELL_PATTERN, self.html)
+ if found:
+ self.setWait(wait_time + 1, False)
+ self.wait(300)
+ self.retry()
+
+ def doWait(self):
+ found = re.search(self.WAIT_PATTERN, self.html)
+ wait_time = int(found.group(1)) if found else 30
+ self.setWait(wait_time + 1, False)
+
+ self.load('http://datei.to/ajax/download.php', post = {'P': 'Ads'})
+ self.wait()
+
+getInfo = create_getInfo(DateiTo)
diff --git a/module/plugins/hoster/DdlstorageCom.py b/module/plugins/hoster/DdlstorageCom.py
new file mode 100644
index 000000000..1ad5fa6d8
--- /dev/null
+++ b/module/plugins/hoster/DdlstorageCom.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo
+
+class DdlstorageCom(XFileSharingPro):
+ __name__ = "DdlstorageCom"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:\w*\.)*?ddlstorage.com/\w{12}"
+ __version__ = "0.06"
+ __description__ = """DDLStorage.com hoster plugin"""
+ __author_name__ = ("zoidberg")
+ __author_mail__ = ("zoidberg@mujmail.cz")
+
+ FILE_INFO_PATTERN = r'<h2>\s*Download File\s*<span[^>]*>(?P<N>[^>]+)</span></h2>\s*[^\(]*\((?P<S>[^\)]+)\)</h2>'
+ HOSTER_NAME = "ddlstorage.com"
+
+ def setup(self):
+ self.resumeDownload = self.multiDL = self.premium
+ self.chunkLimit = 1
+
+getInfo = create_getInfo(DdlstorageCom) \ No newline at end of file
diff --git a/module/plugins/hoster/DepositfilesCom.py b/module/plugins/hoster/DepositfilesCom.py
index 87e5e7254..9c13a5f3a 100644
--- a/module/plugins/hoster/DepositfilesCom.py
+++ b/module/plugins/hoster/DepositfilesCom.py
@@ -3,52 +3,35 @@
import re
from urllib import unquote
-from module.plugins.internal.SimpleHoster import SimpleHoster, parseFileInfo
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
from module.network.RequestFactory import getURL
from module.plugins.ReCaptcha import ReCaptcha
-def getInfo(urls):
- result = []
-
- for url in urls:
- file_info = parseFileInfo(DepositfilesCom, url, getURL(re.sub(r"\.com(/.*?)?/files", ".com/en/files", url), decode=True))
- result.append(file_info)
-
- yield result
-
class DepositfilesCom(SimpleHoster):
__name__ = "DepositfilesCom"
__type__ = "hoster"
__pattern__ = r"http://[\w\.]*?depositfiles\.com(/\w{1,3})?/files/[\w]+"
- __version__ = "0.36"
+ __version__ = "0.42"
__description__ = """Depositfiles.com Download Hoster"""
__author_name__ = ("spoob", "zoidberg")
__author_mail__ = ("spoob@pyload.org", "zoidberg@mujmail.cz")
- FILE_INFO_PATTERN = r'File name: <b title="(?P<N>[^"]+)">.*\s*<span class="nowrap">File size: <b>(?P<S>[0-9.]+)&nbsp;(?P<U>[kKMG])i?B</b>'
+ FILE_NAME_PATTERN = r'File name: <b title="(?P<N>[^"]+)'
+ FILE_SIZE_PATTERN = r'File size: <b>(?P<S>[0-9.]+)&nbsp;(?P<U>[kKMG])i?B</b>'
+ FILE_INFO_PATTERN = r'<script type="text/javascript">eval\( unescape\(\'(?P<N>.*?)\''
FILE_OFFLINE_PATTERN = r'<span class="html_download_api-not_exists"></span>'
- RECAPTCHA_PATTERN = r"Recaptcha.create\('([^']+)', this\);"
+ FILE_URL_REPLACEMENTS = [(r"\.com(/.*?)?/files", ".com/en/files"), (r"\.html$", "")]
+ FILE_NAME_REPLACEMENTS = [(r'\%u([0-9A-Fa-f]{4})', lambda m: unichr(int(m.group(1), 16))), (r'.*<b title="(?P<N>[^"]+).*', "\g<N>" )]
+
+ RECAPTCHA_PATTERN = r"Recaptcha.create\('([^']+)'"
DOWNLOAD_LINK_PATTERN = r'<form action="(http://.+?\.depositfiles.com/.+?)" method="get"'
def setup(self):
- self.resumeDownload = self.multiDL = True if self.account else False
-
- self.pyfile.url = re.sub(r"\.com(/.*?)?/files", ".com/en/files", self.pyfile.url)
-
- def process(self, pyfile):
- if re.search(r"(.*)\.html", self.pyfile.url):
- self.pyfile.url = re.search(r"(.*)\.html", self.pyfile.url).group(1)
-
- self.html = self.load(self.pyfile.url, cookies=True if self.account else False, decode = True)
- self.getFileInfo()
-
- if self.account:
- self.handlePremium()
- else:
- self.handleFree()
+ self.multiDL = False
+ self.resumeDownload = self.premium
def handleFree(self):
- self.html = self.load(self.pyfile.url, post={"gateway_result":"1"})
+ self.html = self.load(self.pyfile.url, post={"gateway_result":"1"}, cookies = True)
if re.search(self.FILE_OFFLINE_PATTERN, self.html): self.offline()
if re.search(r'File is checked, please try again in a minute.', self.html) is not None:
@@ -81,7 +64,7 @@ class DepositfilesCom(SimpleHoster):
params = {'fid' : found.group(1)}
self.logDebug ("FID: %s" % params['fid'])
- captcha_key = None
+ captcha_key = '6LdRTL8SAAAAAE9UOdWZ4d0Ky-aeA7XfSqyWDM2m'
found = re.search(self.RECAPTCHA_PATTERN, self.html)
if found: captcha_key = found.group(1)
self.logDebug ("CAPTCHA_KEY: %s" % captcha_key)
@@ -91,9 +74,9 @@ class DepositfilesCom(SimpleHoster):
for i in range(5):
self.html = self.load("http://depositfiles.com/get_file.php", get = params)
-
+
if '<input type=button value="Continue" onclick="check_recaptcha' in self.html:
- if not captcha_key: raise PluginParseError('Captcha key')
+ if not captcha_key: self.parseError('Captcha key')
if 'response' in params: self.invalidCaptcha()
params['challenge'], params['response'] = recaptcha.challenge(captcha_key)
self.logDebug(params)
@@ -106,15 +89,24 @@ class DepositfilesCom(SimpleHoster):
self.logDebug ("LINK: %s" % link)
break
else:
- raise PluginParseError('Download link')
+ self.parseError('Download link')
else:
self.fail('No valid captcha response received')
try:
- self.download(link)
+ self.download(link, disposition = True)
except:
self.retry(wait_time = 60)
def handlePremium(self):
+ if '<span class="html_download_api-gold_traffic_limit">' in self.html:
+ self.logWarning("Download limit reached")
+ self.retry(25, 3600, "Download limit reached")
+ elif 'onClick="show_gold_offer' in self.html:
+ self.account.relogin(self.user)
+ self.retry()
link = unquote(re.search('<div id="download_url">\s*<a href="(http://.+?\.depositfiles.com/.+?)"', self.html).group(1))
- self.download(link) \ No newline at end of file
+ self.multiDL = True
+ self.download(link, disposition = True)
+
+getInfo = create_getInfo(DepositfilesCom) \ No newline at end of file
diff --git a/module/plugins/hoster/DlFreeFr.py b/module/plugins/hoster/DlFreeFr.py
index 7cb58e6f4..5b318fd54 100644
--- a/module/plugins/hoster/DlFreeFr.py
+++ b/module/plugins/hoster/DlFreeFr.py
@@ -2,36 +2,182 @@
# -*- coding: utf-8 -*-
import re
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, replace_patterns
+from module.common.json_layer import json_loads
+
+import pycurl
+from module.network.Browser import Browser
+from module.network.CookieJar import CookieJar
+
+class CustomBrowser(Browser):
+ def __init__(self, bucket=None, options={}):
+ Browser.__init__(self, bucket, options)
+
+ def load(self, *args, **kwargs):
+ post = kwargs.get("post")
+ if post is None:
+ if len(args) > 2:
+ post = args[2]
+ if post:
+ self.http.c.setopt(pycurl.FOLLOWLOCATION, 0)
+ self.http.c.setopt(pycurl.POST, 1)
+ self.http.c.setopt(pycurl.CUSTOMREQUEST, "POST")
+ else:
+ self.http.c.setopt(pycurl.FOLLOWLOCATION, 1)
+ self.http.c.setopt(pycurl.POST, 0)
+ self.http.c.setopt(pycurl.CUSTOMREQUEST, "GET")
+ return Browser.load(self, *args, **kwargs)
+
+"""
+Class to support adyoulike captcha service
+"""
+class AdYouLike():
+ ADYOULIKE_INPUT_PATTERN = r'Adyoulike.create\((.*?)\);'
+ ADYOULIKE_CALLBACK = r'Adyoulike.g._jsonp_5579316662423138'
+ ADYOULIKE_CHALLENGE_PATTERN = ADYOULIKE_CALLBACK + r'\((.*?)\)'
+
+ def __init__(self, plugin, engine = "adyoulike"):
+ self.plugin = plugin
+ self.engine = engine
+
+ def challenge(self, html):
+ adyoulike_data_string = None
+ found = re.search(self.ADYOULIKE_INPUT_PATTERN, html)
+ if found:
+ adyoulike_data_string = found.group(1)
+ else:
+ self.plugin.fail("Can't read AdYouLike input data")
+
+ ayl_data = json_loads(adyoulike_data_string) #{"adyoulike":{"key":"P~zQ~O0zV0WTiAzC-iw0navWQpCLoYEP"},"all":{"element_id":"ayl_private_cap_92300","lang":"fr","env":"prod"}}
+
+ res = self.plugin.load(r'http://api-ayl.appspot.com/challenge?key=%(ayl_key)s&env=%(ayl_env)s&callback=%(callback)s' % {"ayl_key": ayl_data[self.engine]["key"], "ayl_env": ayl_data["all"]["env"], "callback": self.ADYOULIKE_CALLBACK})
+
+ found = re.search(self.ADYOULIKE_CHALLENGE_PATTERN, res)
+ challenge_string = None
+ if found:
+ challenge_string = found.group(1)
+ else:
+ self.plugin.fail("Invalid AdYouLike challenge")
+ challenge_data = json_loads(challenge_string)
+
+ return ayl_data, challenge_data
+
+ def result(self, ayl, challenge):
+ """
+ Adyoulike.g._jsonp_5579316662423138({"translations":{"fr":{"instructions_visual":"Recopiez « Soonnight » ci-dessous :"}},"site_under":true,"clickable":true,"pixels":{"VIDEO_050":[],"DISPLAY":[],"VIDEO_000":[],"VIDEO_100":[],"VIDEO_025":[],"VIDEO_075":[]},"medium_type":"image/adyoulike","iframes":{"big":"<iframe src=\"http://www.soonnight.com/campagn.html\" scrolling=\"no\" height=\"250\" width=\"300\" frameborder=\"0\"></iframe>"},"shares":{},"id":256,"token":"e6QuI4aRSnbIZJg02IsV6cp4JQ9~MjA1","formats":{"small":{"y":300,"x":0,"w":300,"h":60},"big":{"y":0,"x":0,"w":300,"h":250},"hover":{"y":440,"x":0,"w":300,"h":60}},"tid":"SqwuAdxT1EZoi4B5q0T63LN2AkiCJBg5"})
+ """
+ response = None
+ try:
+ instructions_visual = challenge["translations"][ayl["all"]["lang"]]["instructions_visual"]
+ found = re.search(u".*«(.*)».*", instructions_visual)
+ if found:
+ response = found.group(1).strip()
+ else:
+ self.plugin.fail("Can't parse instructions visual")
+ except KeyError:
+ self.plugin.fail("No instructions visual")
+
+ #TODO: Supports captcha
+
+ if not response:
+ self.plugin.fail("AdYouLike result failed")
+
+ return {"_ayl_captcha_engine" : self.engine,
+ "_ayl_env" : ayl["all"]["env"],
+ "_ayl_tid" : challenge["tid"],
+ "_ayl_token_challenge" : challenge["token"],
+ "_ayl_response": response }
class DlFreeFr(SimpleHoster):
__name__ = "DlFreeFr"
__type__ = "hoster"
- __pattern__ = r"http://dl\.free\.fr/([a-zA-Z0-9]+|getfile\.pl\?file=/[a-zA-Z0-9]+)$"
- __version__ = "0.2"
+ __pattern__ = r"http://dl\.free\.fr/([a-zA-Z0-9]+|getfile\.pl\?file=/[a-zA-Z0-9]+)"
+ __version__ = "0.23"
__description__ = """dl.free.fr download hoster"""
- __author_name__ = ("the-razer", "zoidberg")
- __author_mail__ = ("daniel_ AT gmx DOT net", "zoidberg@mujmail.cz")
+ __author_name__ = ("the-razer", "zoidberg", "Toilal")
+ __author_mail__ = ("daniel_ AT gmx DOT net", "zoidberg@mujmail.cz", "toilal.dev@gmail.com")
FILE_NAME_PATTERN = r"Fichier:</td>\s*<td[^>]*>(?P<N>[^>]*)</td>"
- FILE_SIZE_PATTERN = r"Taille:</td>\s*<td[^>]*>(?P<S>[\d.]+[KMG])</td>"
+ FILE_SIZE_PATTERN = r"Taille:</td>\s*<td[^>]*>(?P<S>[\d.]+[KMG])o"
FILE_OFFLINE_PATTERN = r"Erreur 404 - Document non trouv|Fichier inexistant|Le fichier demand&eacute; n'a pas &eacute;t&eacute; trouv&eacute;"
- FILE_URL_PATTERN = r'href="(?P<url>http://.*?)">T&eacute;l&eacute;charger ce fichier'
-
+ #FILE_URL_PATTERN = r'href="(?P<url>http://.*?)">T&eacute;l&eacute;charger ce fichier'
+
def setup(self):
self.limitDL = 5
self.resumeDownload = True
- self.chunkLimit = 1
+ self.chunkLimit = 1
- def handleFree(self):
- if "Trop de slots utilis&eacute;s" in self.html:
- self.retry(300)
+ def init(self):
+ factory = self.core.requestFactory
+ self.req = CustomBrowser(factory.bucket, factory.getOptions())
+
+ def process(self, pyfile):
+ self.req.setCookieJar(None)
+
+ pyfile.url = replace_patterns(pyfile.url, self.FILE_URL_REPLACEMENTS)
+ valid_url = pyfile.url
+ headers = self.load(valid_url, just_header = True)
- m = re.search(self.FILE_URL_PATTERN, self.html)
- if not m: self.parseError('URL')
+ self.html = None
+ if headers.get('code') == 302:
+ valid_url = headers.get('location')
+ headers = self.load(valid_url, just_header = True)
- url = m.group('url')
- self.logDebug("File URL [%s]" % url)
- self.download(url)
+ if headers.get('code') == 200:
+ content_type = headers.get('content-type')
+ if content_type and content_type.startswith("text/html"):
+ # Undirect acces to requested file, with a web page providing it (captcha)
+ self.html = self.load(valid_url)
+ self.handleFree()
+ else:
+ # Direct access to requested file for users using free.fr as Internet Service Provider.
+ self.download(valid_url, disposition=True)
+ elif headers.get('code') == 404:
+ self.offline()
+ else:
+ self.fail("Invalid return code: " + str(headers.get('code')))
+
+ def handleFree(self):
+ action, inputs = self.parseHtmlForm('action="getfile.pl"')
+
+ adyoulike = AdYouLike(self)
+ ayl, challenge = adyoulike.challenge(self.html)
+ result = adyoulike.result(ayl, challenge)
+ inputs.update(result)
+
+ data = self.load("http://dl.free.fr/getfile.pl", post = inputs)
+ headers = self.getLastHeaders()
+ if headers.get("code") == 302 and headers.has_key("set-cookie") and headers.has_key("location"):
+ found = re.search("(.*?)=(.*?); path=(.*?); domain=(.*?)", headers.get("set-cookie"))
+ cj = CookieJar(__name__)
+ if found:
+ cj.setCookie(found.group(4), found.group(1), found.group(2), found.group(3))
+ else:
+ self.fail("Cookie error")
+ location = headers.get("location")
+ self.req.setCookieJar(cj)
+ self.download(location, disposition=True);
+ else:
+ self.fail("Invalid response")
+
+ def getLastHeaders(self):
+ #parse header
+ header = {"code": self.req.code}
+ for line in self.req.http.header.splitlines():
+ line = line.strip()
+ if not line or ":" not in line: continue
+
+ key, none, value = line.partition(":")
+ key = key.lower().strip()
+ value = value.strip()
+
+ if key in header:
+ if type(header[key]) == list:
+ header[key].append(value)
+ else:
+ header[key] = [header[key], value]
+ else:
+ header[key] = value
+ return header
-getInfo = create_getInfo(DlFreeFr) \ No newline at end of file
+getInfo = create_getInfo(DlFreeFr)
diff --git a/module/plugins/hoster/EasybytezCom.py b/module/plugins/hoster/EasybytezCom.py
index 0b46acb83..5f3159b20 100644
--- a/module/plugins/hoster/EasybytezCom.py
+++ b/module/plugins/hoster/EasybytezCom.py
@@ -17,128 +17,67 @@
"""
import re
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
from random import random
+from pycurl import LOW_SPEED_TIME
+from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo
-class EasybytezCom(SimpleHoster):
+class EasybytezCom(XFileSharingPro):
__name__ = "EasybytezCom"
__type__ = "hoster"
- __pattern__ = r"http://(?:\w*\.)?easybytez.com/(\w{6,}).*"
- __version__ = "0.06"
+ __pattern__ = r"http://(?:\w*\.)?easybytez.com/(\w+).*"
+ __version__ = "0.11"
__description__ = """easybytez.com"""
__author_name__ = ("zoidberg")
__author_mail__ = ("zoidberg@mujmail.cz")
-
- # shares code with TurbouploadCom
FILE_NAME_PATTERN = r'<input type="hidden" name="fname" value="(?P<N>[^"]+)"'
FILE_SIZE_PATTERN = r'You have requested <font color="red">[^<]+</font> \((?P<S>[^<]+)\)</font>'
- FILE_INFO_PATTERN = r'<tr><td align=right><b>Filename:</b></td><td nowrap>(?P<N>[^<]+)</td></tr>\s*.*?<small>\((?P<S>[^<]+)\)</small>'
- FILE_OFFLINE_PATTERN = r'<h2>File Not Found</h2>'
+ FILE_INFO_PATTERN = r'<tr><td align=right><b>Filename:</b></td><td nowrap>(?P<N>[^<]+)</td></tr>\s*.*?<small>\((?P<S>[^<]+)\)</small>'
+ FILE_OFFLINE_PATTERN = r'<h1>File not available</h1>'
- FORM_INPUT_PATTERN = r'<input[^>]* name="([^"]+)"[^>]*value="([^"]*)"'
- WAIT_PATTERN = r'<span id="countdown_str">[^>]*>(\d+)</span> seconds</span>'
DIRECT_LINK_PATTERN = r'(http://(\w+\.easybytez\.com|\d+\.\d+\.\d+\.\d+)/files/\d+/\w+/[^"<]+)'
-
- FORM_PATTERN = r'<form name=["\']?%s[^>]*action=["\']?([^"\' ]+)(.*?)</form>'
OVR_DOWNLOAD_LINK_PATTERN = r'<h2>Download Link</h2>\s*<textarea[^>]*>([^<]+)'
OVR_KILL_LINK_PATTERN = r'<h2>Delete Link</h2>\s*<textarea[^>]*>([^<]+)'
- TEXTAREA_PATTERN = r"<textarea name='([^']+)'>([^<]+)</textarea>"
-
- HOSTER_URL = "www.easybytez.com"
-
- def process(self, pyfile):
- if not re.match(self.__pattern__, self.pyfile.url):
- if self.premium:
- self.handleOverriden()
- else:
- self.fail("Only premium users can download from other hosters with %s" % self.HOSTER_URL)
- else:
- self.html = self.load(pyfile.url, cookies = False, decode = True)
- self.file_info = self.getFileInfo()
-
- header = self.load(self.pyfile.url, just_header = True, cookies = True)
- self.logDebug(header)
-
- if 'location' in header and re.match(self.DIRECT_LINK_PATTERN, header['location']):
- self.downloadLink(header['location'])
- elif self.premium:
- self.handlePremium()
- else:
- self.handleFree()
- def handleFree(self):
- self.download(self.pyfile.url, post = self.getPostParameters(), ref = True, cookies = True)
+ HOSTER_NAME = "easybytez.com"
+ def setup(self):
+ self.resumeDownload = self.multiDL = self.premium
+
def handlePremium(self):
- self.html = self.load(self.pyfile.url, post = self.getPostParameters(premium=True))
+ self.html = self.load(self.pyfile.url, post = self.getPostParameters())
found = re.search(self.DIRECT_LINK_PATTERN, self.html)
if not found: self.parseError('DIRECT LINK')
- self.downloadLink(found.group(1))
-
+ self.startDownload(found.group(1))
+
def handleOverriden(self):
- self.html = self.load(self.HOSTER_URL)
- action, form = re.search(self.FORM_PATTERN % "url", self.html, re.DOTALL).groups()
- inputs = dict(re.findall(self.FORM_INPUT_PATTERN, form))
+ self.html = self.load("http://www.%s/" % self.HOSTER_NAME)
+ action, inputs = self.parseHtmlForm('')
upload_id = "%012d" % int(random()*10**12)
- action += upload_id + "&js_on=1&utype=prem&upload_type=url"
+ action += upload_id + "&js_on=1&utype=prem&upload_type=url"
inputs['tos'] = '1'
inputs['url_mass'] = self.pyfile.url
- inputs['up1oad_type'] = 'url'
-
+ inputs['up1oad_type'] = 'url'
+
self.logDebug(action, inputs)
+ #wait for file to upload to easybytez.com
+ self.req.http.c.setopt(LOW_SPEED_TIME, 600)
self.html = self.load(action, post = inputs)
-
- found = re.search(self.FORM_PATTERN % "F1", self.html, re.S | re.I)
- if not found:
- self.logDebug(self.html)
- self.fail("upload failed")
- action, form = found.groups()
-
- inputs = dict(re.findall(self.TEXTAREA_PATTERN, form))
- if not inputs: parseError('TEXTAREA')
- self.logDebug(inputs)
+
+ action, inputs = self.parseHtmlForm('F1')
+ if not inputs: self.parseError('TEXTAREA')
+ self.logDebug(inputs)
if inputs['st'] == 'OK':
self.html = self.load(action, post = inputs)
+ elif inputs['st'] == 'Can not leech file':
+ self.retry(max_tries=20, wait_time=180, reason=inputs['st'])
else:
- self.fail(inputs['st'])
+ self.fail(inputs['st'])
+ #get easybytez.com link for uploaded file
found = re.search(self.OVR_DOWNLOAD_LINK_PATTERN, self.html)
if not found: self.parseError('DIRECT LINK (OVR)')
self.pyfile.url = found.group(1)
self.retry()
-
- def downloadLink(self, link):
- self.logDebug('DIRECT LINK: %s' % link)
- self.download(link)
-
- def getPostParameters(self, premium=False):
- inputs = dict(re.findall(self.FORM_INPUT_PATTERN, self.html))
- self.logDebug(inputs)
-
- if 'op' in inputs and inputs['op'] == 'download2': return inputs
-
- inputs['referer'] = self.pyfile.url
-
- if premium:
- inputs['method_premium'] = "Premium Download"
- if 'method_free' in inputs: del inputs['method_free']
- else:
- inputs['method_free'] = "Free Download"
- if 'method_premium' in inputs: del inputs['method_premium']
-
- self.html = self.load(self.pyfile.url, post = inputs, ref = True, cookies = True)
- inputs = dict(re.findall(self.FORM_INPUT_PATTERN, self.html))
- self.logDebug(inputs)
-
- if not premium:
- found = re.search(self.WAIT_PATTERN, self.html)
- self.setWait(int(found.group(1)) + 1 if found else 60)
- self.wait()
-
- return inputs
-
- def urlParseFileName(self):
- return html_unescape(urlparse(self.pyfile.url).path.split("/")[-1])
getInfo = create_getInfo(EasybytezCom) \ No newline at end of file
diff --git a/module/plugins/hoster/ExtabitCom.py b/module/plugins/hoster/ExtabitCom.py
new file mode 100644
index 000000000..718423986
--- /dev/null
+++ b/module/plugins/hoster/ExtabitCom.py
@@ -0,0 +1,84 @@
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: zoidberg
+"""
+
+import re
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+from module.plugins.ReCaptcha import ReCaptcha
+from module.common.json_layer import json_loads
+
+class ExtabitCom(SimpleHoster):
+ __name__ = "ExtabitCom"
+ __type__ = "hoster"
+ __pattern__ = r"http://(\w+\.)*extabit\.com/(file|go)/(?P<ID>\w+)"
+ __version__ = "0.2"
+ __description__ = """Extabit.com"""
+ __author_name__ = ("zoidberg")
+
+ FILE_NAME_PATTERN = r'<th>File:</th>\s*<td class="col-fileinfo">\s*<div title="(?P<N>[^"]+)">'
+ FILE_SIZE_PATTERN = r'<th>Size:</th>\s*<td class="col-fileinfo">(?P<S>[^<]+)</td>'
+ FILE_OFFLINE_PATTERN = r'<h1>File not found</h1>'
+ TEMP_OFFLINE_PATTERN = r">(File is temporary unavailable|No download mirror)<"
+
+ DOWNLOAD_LINK_PATTERN = r'"(http://guest\d+\.extabit\.com/[a-z0-9]+/.*?)"'
+
+ def handleFree(self):
+ if r">Only premium users can download this file" in self.html:
+ self.fail("Only premium users can download this file")
+
+ m = re.search(r"Next free download from your ip will be available in <b>(\d+)\s*minutes", self.html)
+ if m:
+ self.setWait(int(m.group(1)) * 60, True)
+ self.wait()
+ elif "The daily downloads limit from your IP is exceeded" in self.html:
+ self.setWait(3600, True)
+ self.wait()
+
+ self.logDebug("URL: " + self.req.http.lastEffectiveURL)
+ m = re.match(self.__pattern__, self.req.http.lastEffectiveURL)
+ fileID = m.group('ID') if m else self.file_info('ID')
+
+ m = re.search(r'recaptcha/api/challenge\?k=(\w+)', self.html)
+ if m:
+ recaptcha = ReCaptcha(self)
+ captcha_key = m.group(1)
+
+ for i in range(5):
+ get_data = {"type": "recaptcha"}
+ get_data["challenge"], get_data["capture"] = recaptcha.challenge(captcha_key)
+ response = json_loads(self.load("http://extabit.com/file/%s/" % fileID, get = get_data))
+ if "ok" in response:
+ self.correctCaptcha()
+ break
+ else:
+ self.invalidCaptcha()
+ else:
+ self.fail("Invalid captcha")
+ else:
+ self.parseError('Captcha')
+
+ if not "href" in response: self.parseError('JSON')
+
+ self.html = self.load("http://extabit.com/file/%s%s" % (fileID, response['href']))
+ m = re.search(self.DOWNLOAD_LINK_PATTERN, self.html)
+ if not m:
+ self.parseError('Download URL')
+ url = m.group(1)
+ self.logDebug("Download URL: " + url)
+ self.download(url)
+
+getInfo = create_getInfo(ExtabitCom) \ No newline at end of file
diff --git a/module/plugins/hoster/FastshareCz.py b/module/plugins/hoster/FastshareCz.py
new file mode 100644
index 000000000..654a1abe8
--- /dev/null
+++ b/module/plugins/hoster/FastshareCz.py
@@ -0,0 +1,52 @@
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: zoidberg
+"""
+
+import re
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+
+class FastshareCz(SimpleHoster):
+ __name__ = "FastshareCz"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:\w*\.)?fastshare.cz/\d+/.+"
+ __version__ = "0.12"
+ __description__ = """FastShare.cz"""
+ __author_name__ = ("zoidberg")
+
+ FILE_NAME_PATTERN = r'<h3><b><span style=color:black;>(?P<N>[^<]+)</b></h3>'
+ FILE_SIZE_PATTERN = r'<tr><td>Velikost: </td><td style=font-weight:bold>(?P<S>[^<]+)</td></tr>'
+ FILE_OFFLINE_PATTERN = r'<div id="content">\s*<div style=background-color:white'
+ SH_HTML_ENCODING = 'cp1250'
+
+ FREE_URL_PATTERN = ur'<form method=post action=(/free/.*?)><b>Stáhnout FREE.*?<img src="([^"]*)">'
+
+ def handleFree(self):
+ found = re.search(self.FREE_URL_PATTERN, self.html)
+ if not found: self.parseError("Free URL")
+ action, captcha_src = found.groups()
+ captcha = self.decryptCaptcha("http://www.fastshare.cz/" + captcha_src)
+ self.download("http://www.fastshare.cz/" + action, post = {"code": captcha, "submit": u"stáhnout"})
+
+ check = self.checkDownload({"paralell_dl": "<script>alert('Pres FREE muzete stahovat jen jeden soubor najednou.')"})
+ self.logDebug(self.req.lastEffectiveURL, self.req.lastURL, self.req.code)
+
+ if check == "paralell_dl":
+ self.setWait(600, True)
+ self.wait()
+ self.retry()
+
+getInfo = create_getInfo(FastshareCz) \ No newline at end of file
diff --git a/module/plugins/hoster/FilecloudIo.py b/module/plugins/hoster/FilecloudIo.py
new file mode 100644
index 000000000..4a096e400
--- /dev/null
+++ b/module/plugins/hoster/FilecloudIo.py
@@ -0,0 +1,112 @@
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: zoidberg
+"""
+
+import re
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, PluginParseError
+from module.common.json_layer import json_loads
+from module.plugins.ReCaptcha import ReCaptcha
+from module.network.RequestFactory import getURL
+
+class FilecloudIo(SimpleHoster):
+ __name__ = "FilecloudIo"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:\w*\.)*(?:filecloud\.io|ifile\.it|mihd\.net)/(?P<ID>\w+).*"
+ __version__ = "0.01"
+ __description__ = """Filecloud.io (formerly Ifile.it) plugin - free account only"""
+ __author_name__ = ("zoidberg")
+
+ FILE_SIZE_PATTERN = r'{var __ab1 = (?P<S>\d+);}'
+ FILE_NAME_PATTERN = r'id="aliasSpan">(?P<N>.*?)&nbsp;&nbsp;<'
+ FILE_OFFLINE_PATTERN = r'l10n.(FILES__DOESNT_EXIST|REMOVED)'
+ TEMP_OFFLINE_PATTERN = r'l10n.FILES__WARNING'
+
+ UKEY_PATTERN = r"'ukey'\s*:'(\w+)',"
+ AB1_PATTERN = r"if\( __ab1 == '(\w+)' \)"
+ ERROR_MSG_PATTERN = r"var __error_msg\s*=\s*l10n\.(.*?);"
+ DOWNLOAD_LINK_PATTERN = r'"(http://s\d+.filecloud.io/%s/\d+/.*?)"'
+ RECAPTCHA_KEY_PATTERN = r"var __recaptcha_public\s*=\s*'([^']+)';"
+ RECAPTCHA_KEY = '6Lf5OdISAAAAAEZObLcx5Wlv4daMaASRov1ysDB1'
+
+ def setup(self):
+ self.resumeDownload = self.multiDL = True
+ self.chunkLimit = 1
+
+ def handleFree(self):
+ data = {"ukey": self.file_info['ID']}
+
+ found = re.search(self.AB1_PATTERN, self.html)
+ if not found:
+ raise PluginParseError("__AB1")
+ data["__ab1"] = found.group(1)
+
+ if not self.account:
+ self.fail("User not logged in")
+ elif not self.account.logged_in:
+ recaptcha = ReCaptcha(self)
+ captcha_challenge, captcha_response = recaptcha.challenge(self.RECAPTCHA_KEY)
+ self.account.form_data = {"recaptcha_challenge_field" : captcha_challenge,
+ "recaptcha_response_field" : captcha_response}
+ self.account.relogin(self.user)
+ self.retry(max_tries = 2)
+
+ json_url = "http://filecloud.io/download-request.json"
+ response = self.load(json_url, post = data)
+ self.logDebug(response)
+ response = json_loads(response)
+
+ if "error" in response and response["error"]:
+ self.fail(response)
+
+ self.logDebug(response)
+ if response["captcha"]:
+ recaptcha = ReCaptcha(self)
+ found = re.search(self.RECAPTCHA_KEY_PATTERN, self.html)
+ captcha_key = found.group(1) if found else self.RECAPTCHA_KEY
+ data["ctype"] = "recaptcha"
+
+ for i in range(5):
+ data["recaptcha_challenge"], data["recaptcha_response"] = recaptcha.challenge(captcha_key)
+
+ json_url = "http://filecloud.io/download-request.json"
+ response = self.load(json_url, post = data)
+ self.logDebug(response)
+ response = json_loads(response)
+
+ if "retry" in response and response["retry"]:
+ self.invalidCaptcha()
+ else:
+ self.correctCaptcha()
+ break
+ else:
+ self.fail("Incorrect captcha")
+
+ if response["dl"]:
+ self.html = self.load('http://filecloud.io/download.html')
+ found = re.search(self.DOWNLOAD_LINK_PATTERN % self.file_info['ID'], self.html)
+ if not found:
+ raise PluginParseError("Download URL")
+ download_url = found.group(1)
+ self.logDebug("Download URL: %s" % download_url)
+
+ if "size" in self.file_info and self.file_info['size']:
+ self.check_data = {"size": int(self.file_info['size'])}
+ self.download(download_url)
+ else:
+ self.fail("Unexpected server response")
+
+getInfo = create_getInfo(FilecloudIo) \ No newline at end of file
diff --git a/module/plugins/hoster/FiledinoCom.py b/module/plugins/hoster/FiledinoCom.py
new file mode 100644
index 000000000..6bdd01b51
--- /dev/null
+++ b/module/plugins/hoster/FiledinoCom.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo
+import re
+
+class FiledinoCom(XFileSharingPro):
+ __name__ = "FiledinoCom"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:\w*\.)*(file(dino|fat).com)/\w{12}"
+ __version__ = "0.02"
+ __description__ = """FileDino / FileFat hoster plugin"""
+ __author_name__ = ("zoidberg")
+ __author_mail__ = ("zoidberg@mujmail.cz")
+
+ FILE_SIZE_PATTERN = r'File Size : </(span|font)><(span|font)[^>]*>(?P<S>.+?)</(span|font)>'
+ DIRECT_LINK_PATTERN = r'http://www\.file(dino|fat)\.com/cgi-bin/dl\.cgi/'
+
+ def setup(self):
+ self.HOSTER_NAME = re.search(self.__pattern__, self.pyfile.url).group(1)
+ self.multiDL = False
+
+getInfo = create_getInfo(FiledinoCom) \ No newline at end of file
diff --git a/module/plugins/hoster/FilefactoryCom.py b/module/plugins/hoster/FilefactoryCom.py
index 37b2bb7ce..135dd90a1 100644
--- a/module/plugins/hoster/FilefactoryCom.py
+++ b/module/plugins/hoster/FilefactoryCom.py
@@ -1,122 +1,133 @@
# -*- coding: utf-8 -*-
-from __future__ import with_statement
-
from module.network.RequestFactory import getURL
from module.plugins.Hoster import Hoster
from module.plugins.ReCaptcha import ReCaptcha
+from module.utils import parseFileSize
+from module.plugins.Plugin import chunks
+from module.common.json_layer import json_loads
import re
-def getInfo(urls):
- result = []
+def checkFile(plugin, urls):
+ file_info = []
+ url_dict = {}
for url in urls:
-
- # Get file info html
- # @TODO: Force responses in english language so current patterns will be right
- html = getURL(url)
- if re.search(FilefactoryCom.FILE_OFFLINE_PATTERN, html):
- result.append((url, 0, 1, url))
+ url_dict[re.search(plugin.__pattern__, url).group('id')] = (url, 0, 0, url)
+ url_ids = url_dict.keys()
+ urls = map(lambda url_id: 'http://www.filefactory.com/file/' + url_id, url_ids)
- # Name
- name = re.search(FilefactoryCom.FILE_NAME_PATTERN, html).group('name')
- m = re.search(FilefactoryCom.FILE_INFO_PATTERN, html)
+ html = getURL("http://www.filefactory.com/tool/links.php", post = {"func": "links", "links": "\n".join(urls)}, decode=True)
- # Size
- value = float(m.group('size'))
- units = m.group('units')
- pow = {'KB' : 1, 'MB' : 2, 'GB' : 3}[units]
- size = int(value*1024**pow)
+ for m in re.finditer(plugin.LC_INFO_PATTERN, html):
+ if m.group('id') in url_ids:
+ url_dict[m.group('id')] = (m.group('name'), parseFileSize(m.group('size')), 2, url_dict[m.group('id')][3])
+
+ for m in re.finditer(plugin.LC_OFFLINE_PATTERN, html):
+ if m.group('id') in url_ids:
+ url_dict[m.group('id')] = (url_dict[m.group('id')][0], 0, 1, url_dict[m.group('id')][3])
- # Return info
- result.append((name, size, 2, url))
-
- yield result
+ file_info = url_dict.values()
+ return file_info
+
class FilefactoryCom(Hoster):
__name__ = "FilefactoryCom"
__type__ = "hoster"
- __pattern__ = r"http://(www\.)?filefactory\.com/file/(?P<id>[a-zA-Z0-9]+)" # URLs given out are often longer but this is the requirement
- __version__ = "0.3"
+ __pattern__ = r"http://(?:www\.)?filefactory\.com/file/(?P<id>[a-zA-Z0-9]+).*" # URLs given out are often longer but this is the requirement
+ __version__ = "0.34"
__description__ = """Filefactory.Com File Download Hoster"""
- __author_name__ = ("paulking")
+ __author_name__ = ("paulking", "zoidberg")
+ LC_INFO_PATTERN = r'<h1 class="name">(?P<name>[^<]+) \((?P<size>[0-9.]+ \w+)\)</h1>\s*<p>http://www.filefactory.com/file/(?P<id>\w+)/'
+ LC_OFFLINE_PATTERN = r'<p>http://www.filefactory.com/file/(?P<id>\w+)/</p>\s*<p class="errorResponse">'
+
FILE_OFFLINE_PATTERN = r'<title>File Not Found'
FILE_NAME_PATTERN = r'<span class="last">(?P<name>.*?)</span>'
FILE_INFO_PATTERN = r'<span>(?P<size>\d(\d|\.)*) (?P<units>..) file uploaded'
- FILE_CHECK_PATTERN = r'check:\'(?P<check>.*?)\''
- CAPTCHA_KEY_PATTERN = r'Recaptcha.create\("(?P<recaptchakey>.*?)",'
- WAIT_PATH_PATTERN = r'path:"(?P<path>.*?)"'
+
+ FILE_CHECK_PATTERN = r'check:\s*\'(?P<check>.*?)\''
+ CAPTCHA_KEY_PATTERN = r'Recaptcha.create\(\s*"(.*?)",'
WAIT_PATTERN = r'id="startWait" value="(?P<wait>\d+)"'
- FILE_URL_PATTERN = r'<a href="(?P<url>.*?)" id="downloadLinkTarget">'
-
+ FILE_URL_PATTERN = r'<p[^>]*?id="downloadLinkTarget"[^>]*>\s*<a href="(?P<url>.*?)"'
+
def setup(self):
- self.multiDL = False
+ self.multiDL = self.resumeDownloads = self.premium
def process(self, pyfile):
-
- self.pyfile = pyfile
+ # Check file
+ pyfile.name, pyfile.size, status, self.url = checkFile(self, [pyfile.url])[0]
+ if status != 2: self.offline()
+ self.logDebug("File Name: %s Size: %d" % (pyfile.name, pyfile.size))
- # Force responses language to US English
- self.req.cj.setCookie("filefactory.com", "ff_locale","")
-
- # Load main page
- self.html = self.load(self.pyfile.url, ref=False, decode=True)
-
- # Check offline
- if re.search(self.FILE_OFFLINE_PATTERN, self.html) is not None:
- self.offline()
+ # Handle downloading
+ url = self.checkDirectDownload(pyfile.url)
+ if url:
+ self.download(url)
+ else:
+ self.html = self.load(pyfile.url, decode = True)
+
+ if self.premium:
+ self.handlePremium()
+ else:
+ self.handleFree()
+
+ def checkDirectDownload(self, url):
+ for i in range(5):
+ header = self.load(url, just_header = True)
+ if 'location' in header:
+ url = header['location'].strip()
+ if not url.startswith("http://"):
+ url = "http://www.filefactory.com" + url
+ self.logDebug('URL: ' + url)
+ elif 'content-disposition' in header:
+ return url
- # File id
- self.file_id = re.match(self.__pattern__, self.pyfile.url).group('id')
- self.log.debug("%s: File id is [%s]" % (self.__name__, self.file_id))
-
- # File name
- self.pyfile.name = re.search(self.FILE_NAME_PATTERN, self.html).group('name')
-
- # Check Id
- self.check = re.search(self.FILE_CHECK_PATTERN, self.html).group('check')
- self.log.debug("%s: File check code is [%s]" % (self.__name__, self.check))
-
- # Handle free downloading
- self.handleFree()
+ return False
def handleFree(self):
-
+ if "Currently only Premium Members can download files larger than" in self.html:
+ self.fail("File too large for free download")
+ elif "All free download slots on this server are currently in use" in self.html:
+ self.retry(50, 900, "All free slots are busy")
+
+ # Check Id
+ self.check = re.search(self.FILE_CHECK_PATTERN, self.html).group('check')
+ self.logDebug("File check code is [%s]" % self.check)
+
# Resolve captcha
- self.log.debug("%s: File is captcha protected" % self.__name__)
- id = re.search(self.CAPTCHA_KEY_PATTERN, self.html).group('recaptchakey')
+ found = re.search(self.CAPTCHA_KEY_PATTERN, self.html)
+ recaptcha_key = found.group(1) if found else "6LeN8roSAAAAAPdC1zy399Qei4b1BwmSBSsBN8zm"
+ recaptcha = ReCaptcha(self)
+
# Try up to 5 times
- for i in range(5):
- self.log.debug("%s: Resolving ReCaptcha with key [%s], round %d" % (self.__name__, id, i+1))
- recaptcha = ReCaptcha(self)
- challenge, code = recaptcha.challenge(id)
- response = self.load("http://www.filefactory.com/file/checkCaptcha.php",
- post={"check" : self.check, "recaptcha_challenge_field" : challenge, "recaptcha_response_field" : code})
- captchavalid = self.handleCaptchaErrors(response)
- if captchavalid:
+ for i in range(5):
+ challenge, code = recaptcha.challenge(recaptcha_key)
+ response = json_loads(self.load("http://www.filefactory.com/file/checkCaptcha.php",
+ post={"check" : self.check, "recaptcha_challenge_field" : challenge, "recaptcha_response_field" : code}))
+ if response['status'] == 'ok':
+ self.correctCaptcha()
break
- if not captchavalid:
+ else:
+ self.invalidCaptcha()
+ else:
self.fail("No valid captcha after 5 attempts")
-
- # Get wait URL
- waitpath = re.search(self.WAIT_PATH_PATTERN, response).group('path')
- waiturl = "http://www.filefactory.com" + waitpath
# This will take us to a wait screen
- self.log.debug("%s: fetching wait with url [%s]" % (self.__name__, waiturl))
+ waiturl = "http://www.filefactory.com" + response['path']
+ self.logDebug("Fetching wait with url [%s]" % waiturl)
waithtml = self.load(waiturl, decode=True)
# Find the wait value and wait
wait = int(re.search(self.WAIT_PATTERN, waithtml).group('wait'))
- self.log.debug("%s: Waiting %d seconds." % (self.__name__, wait))
+ self.logDebug("Waiting %d seconds." % wait)
self.setWait(wait, True)
self.wait()
# Now get the real download url and retrieve the file
url = re.search(self.FILE_URL_PATTERN,waithtml).group('url')
# this may either download our file or forward us to an error page
- self.log.debug("%s: download url %s" % (self.__name__, url))
+ self.logDebug("Download URL: %s" % url)
dl = self.download(url)
check = self.checkDownload({"multiple": "You are currently downloading too many files at once.",
@@ -124,17 +135,14 @@ class FilefactoryCom(Hoster):
if check == "multiple":
self.setWait(15*60)
- self.log.debug("%s: Parallel downloads detected waiting 15 minutes" % self.__name__)
+ self.logDebug("Parallel downloads detected; waiting 15 minutes")
self.wait()
self.retry()
elif check == "error":
self.fail("Unknown error")
-
- def handleCaptchaErrors(self, response):
- self.log.debug("%s: Result of captcha resolving [%s]" % (self.__name__, response))
- if 'status:"ok"' in response:
- self.correctCaptcha()
- return True
+
+ def handlePremium(self):
+ self.fail('Please enable direct downloads')
- self.log.debug("%s: Wrong captcha" % self.__name__)
- self.invalidCaptcha()
+def getInfo(urls):
+ for chunk in chunks(urls, 100): yield checkFile(FilefactoryCom, chunk)
diff --git a/module/plugins/hoster/FilejungleCom.py b/module/plugins/hoster/FilejungleCom.py
index c49cc8506..fd833eef2 100644
--- a/module/plugins/hoster/FilejungleCom.py
+++ b/module/plugins/hoster/FilejungleCom.py
@@ -16,70 +16,23 @@
@author: zoidberg
"""
-import re
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
-from module.network.RequestFactory import getURL
-from module.plugins.ReCaptcha import ReCaptcha
+from module.plugins.hoster.FileserveCom import FileserveCom, checkFile
+from module.plugins.Plugin import chunks
-class FilejungleCom(SimpleHoster):
+class FilejungleCom(FileserveCom):
__name__ = "FilejungleCom"
__type__ = "hoster"
- __pattern__ = r"http://(?:www\.)?filejungle\.com/f/([^/]+).*"
- __version__ = "0.25"
+ __pattern__ = r"http://(?:www\.)?filejungle\.com/f/(?P<id>[^/]+).*"
+ __version__ = "0.51"
__description__ = """Filejungle.com plugin - free only"""
__author_name__ = ("zoidberg")
__author_mail__ = ("zoidberg@mujmail.cz")
-
- FILE_INFO_PATTERN = r'<div id="file_name">(?P<N>[^<]+) <span class="filename_normal">\((?P<S>[0-9.]+) (?P<U>[kKMG])i?B\)</span></div>'
- FILE_OFFLINE_PATTERN = r'(This file is no longer available.</h1>|class="error_msg_title"> Invalid or Deleted File. </div>)'
- RECAPTCHA_KEY_PATTERN = r"var reCAPTCHA_publickey='([^']+)'"
- WAIT_TIME_PATTERN = r'<h1>Please wait for (\d+) seconds to download the next file\.</h1>'
-
- def handleFree(self):
- file_id = re.search(self.__pattern__, self.pyfile.url).group(1)
- url = "http://www.filejungle.com/f/%s" % file_id
- self.logDebug("File ID: %s" % file_id)
-
- # Get captcha
- found = re.search(self.RECAPTCHA_KEY_PATTERN, self.html)
- if not found: self.fail("Captcha key not found")
- captcha_key = found.group(1)
-
- json_response = self.load(self.pyfile.url, post = {"checkDownload" : "check"}, decode = True)
- self.logDebug(json_response)
- if r'"success":"showCaptcha"' in json_response:
- recaptcha = ReCaptcha(self)
- for i in range(5):
- captcha_challenge, captcha_response = recaptcha.challenge(captcha_key)
- self.logDebug("RECAPTCHA: %s : %s : %s" % (captcha_key, captcha_challenge, captcha_response))
-
- json_response = self.load("http://www.filejungle.com/checkReCaptcha.php", post = {
- "recaptcha_challenge_field" : captcha_challenge,
- "recaptcha_response_field" : captcha_response,
- "recaptcha_shortencode_field" : file_id
- }, decode = True)
- self.logDebug(json_response)
- if r'{"success":1}' in json_response:
- self.correctCaptcha()
- break
- else:
- self.invalidCaptcha()
- else: self.fail("Invalid captcha")
- elif r'"fail":"timeLimit"' in json_response:
- self.html = self.load(url, post = {"checkDownload" : "showError", "errorType" : "timeLimit"})
- found = re.search(self.WAIT_TIME_PATTERN, self.html)
- self.retry(5, int(found.group(1)) if found else 1200, "Time limit reached")
- else:
- self.fail("Unknown server response")
-
- json_response = self.load(url, post = {"downloadLink" : "wait"}, decode = True)
- self.logDebug(json_response[:30])
- found = re.search(r'"waitTime":(\d+)', json_response)
- if not found: self.fail("Cannot get wait time")
- self.setWait(int(found.group(1)))
- self.wait()
-
- response = self.load(url, post = {"downloadLink" : "show"})
- self.download(url, post = {"download" : "normal"})
-
-getInfo = create_getInfo(FilejungleCom)
+
+ URLS = ['http://www.filejungle.com/f/', 'http://www.filejungle.com/check_links.php', 'http://www.filejungle.com/checkReCaptcha.php']
+ LINKCHECK_TR = r'<li>\s*(<div class="col1">.*?)</li>'
+ LINKCHECK_TD = r'<div class="(?:col )?col\d">(?:<[^>]*>|&nbsp;)*([^<]*)'
+
+ LONG_WAIT_PATTERN = r'<h1>Please wait for (\d+) (\w+)\s*to download the next file\.</h1>'
+
+def getInfo(urls):
+ for chunk in chunks(urls, 100): yield checkFile(FilejungleCom, chunk) \ No newline at end of file
diff --git a/module/plugins/hoster/FilepostCom.py b/module/plugins/hoster/FilepostCom.py
index 834ad7199..bc47856e5 100644
--- a/module/plugins/hoster/FilepostCom.py
+++ b/module/plugins/hoster/FilepostCom.py
@@ -14,6 +14,11 @@
along with this program; if not, see <http://www.gnu.org/licenses/>.
@author: zoidberg
+
+ changelog:
+ 0.27 - 2012-08-12 - hgg
+ fix "global name 'js_answer' is not defined" bug
+ fix captcha bug #1 (failed on non-english "captcha wrong" errors)
"""
import re
@@ -26,7 +31,7 @@ class FilepostCom(SimpleHoster):
__name__ = "FilepostCom"
__type__ = "hoster"
__pattern__ = r"https?://(?:www\.)?(?:filepost\.com/files|fp.io)/([^/]+).*"
- __version__ = "0.26"
+ __version__ = "0.27"
__description__ = """Filepost.com plugin - free only"""
__author_name__ = ("zoidberg")
__author_mail__ = ("zoidberg@mujmail.cz")
@@ -81,7 +86,7 @@ class FilepostCom(SimpleHoster):
get_dict['JsHttpRequest'] = str(int(time()*10000)) + '-xml'
if pokus:
post_dict["recaptcha_challenge_field"], post_dict["recaptcha_response_field"] = recaptcha.challenge(captcha_key)
- self.logDebug(u"RECAPTCHA: %s : %s : %s" % (captcha_key, post_dict["recaptcha_challenge_field"], post_dict["recaptcha_response_field"]))
+ self.logDebug(u"RECAPTCHA: %s : %s : %s" % (captcha_key, post_dict["recaptcha_challenge_field"], post_dict["recaptcha_response_field"]))
download_url = self.getJsonResponse(get_dict, post_dict, 'link')
if download_url:
@@ -101,19 +106,30 @@ class FilepostCom(SimpleHoster):
if not 'js' in json_response: self.parseError('JSON %s 1' % field)
+ # i changed js_answer to json_response['js'] since js_answer is nowhere set.
+ # i don't know the JSON-HTTP specs in detail, but the previous author
+ # accessed json_response['js']['error'] as well as js_answer['error'].
+ # see the two lines commented out with "# ~?".
if 'error' in json_response['js']:
if json_response['js']['error'] == 'download_delay':
- self.retry(js_answer['params']['next_download'])
+ self.retry(json_response['js']['params']['next_download'])
+ # ~? self.retry(js_answer['params']['next_download'])
elif 'Wrong file password' in json_response['js']['error']:
return None
elif 'You entered a wrong CAPTCHA code' in json_response['js']['error']:
return None
+ elif 'CAPTCHA Code nicht korrekt' in json_response['js']['error']:
+ return None
+ elif 'CAPTCHA' in json_response['js']['error']:
+ self.logDebug('error response is unknown, but mentions CAPTCHA -> return None')
+ return None
else:
- self.fail(js_answer['error'])
+ self.fail(json_response['js']['error'])
+ # ~? self.fail(js_answer['error'])
if not 'answer' in json_response['js'] or not field in json_response['js']['answer']:
self.parseError('JSON %s 2' % field)
return json_response['js']['answer'][field]
-getInfo = create_getInfo(FilepostCom) \ No newline at end of file
+getInfo = create_getInfo(FilepostCom)
diff --git a/module/plugins/hoster/FilerioCom.py b/module/plugins/hoster/FilerioCom.py
new file mode 100644
index 000000000..3d983bedf
--- /dev/null
+++ b/module/plugins/hoster/FilerioCom.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo
+
+class FilerioCom(XFileSharingPro):
+ __name__ = "FilerioCom"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:\w*\.)*file(rio|keen).com/\w{12}"
+ __version__ = "0.01"
+ __description__ = """FileRio.com hoster plugin"""
+ __author_name__ = ("zoidberg")
+ __author_mail__ = ("zoidberg@mujmail.cz")
+
+ FILE_OFFLINE_PATTERN = '<b>&quot;File Not Found&quot;</b>|File has been removed due to Copyright Claim'
+ HOSTER_NAME = "filerio.com"
+ DIRECT_LINK_PATTERN = r'Download Link:.*?<a href="(.*?)"'
+
+ def setup(self):
+ self.multiDL = False
+
+getInfo = create_getInfo(FilerioCom) \ No newline at end of file
diff --git a/module/plugins/hoster/FileserveCom.py b/module/plugins/hoster/FileserveCom.py
index ce3836a48..04c297661 100644
--- a/module/plugins/hoster/FileserveCom.py
+++ b/module/plugins/hoster/FileserveCom.py
@@ -1,168 +1,211 @@
-# -*- coding: utf-8 -*-
-from __future__ import with_statement
-
-import re
-
-from module.plugins.Hoster import Hoster
-from module.plugins.ReCaptcha import ReCaptcha
-
-from module.common.json_layer import json_loads
-from module.network.RequestFactory import getURL
-from module.utils import parseFileSize
-
-
-def getInfo(urls):
- yield [(url, 0, 1, url) for url in urls]
-
-class FileserveCom(Hoster):
- __name__ = "FileserveCom"
- __type__ = "hoster"
- __pattern__ = r"http://(www\.)?fileserve\.com/file/[a-zA-Z0-9]+"
- __version__ = "0.44"
- __description__ = """Fileserve.Com File Download Hoster"""
- __author_name__ = ("jeix", "mkaay", "paul king")
- __author_mail__ = ("jeix@hasnomail.de", "mkaay@mkaay.de", "")
-
- FILE_ID_KEY = r"fileserve\.com/file/(?P<id>\w+)"
- FILE_CHECK_KEY = r"<td>http://www.fileserve\.com/file/(?P<id>\w+)</td>.*?<td>(?P<name>.*?)</td>.*?<td>(?P<units>.*?) (?P<scale>.B)</td>.*?<td>(?P<online>.*?)</td>"
- CAPTCHA_KEY_PATTERN = r"var reCAPTCHA_publickey='(?P<key>.*?)';"
- LONG_WAIT_PATTERN = r"You need to wait (\d+) seconds to start another download"
-
- def init(self):
- if not self.premium:
- self.multiDL = False
- self.resumeDownload = False
- self.chunkLimit = 1
-
- def process(self, pyfile):
- self.fail("Hoster not longer available")
-
- def checkFile(self):
- self.file_id = re.search(self.FILE_ID_KEY, self.pyfile.url).group("id")
- self.logDebug("file id is %s" % self.file_id)
-
- self.pyfile.url = "http://www.fileserve.com/file/" + self.file_id
-
- linkCheck = self.load("http://www.fileserve.com/link-checker.php",
- post={"urls": self.pyfile.url},
- ref=False, cookies=False if self.account else True, decode=True)
-
- linkMatch = re.search(self.FILE_CHECK_KEY, linkCheck.replace("\r\n", ""))
- if not linkMatch:
- self.logDebug("couldn't extract file status")
- self.offline()
-
- if linkMatch.group("online").find("Available"):
- self.logDebug("file is not available : %s" % linkMatch.group("online"))
- self.offline()
-
- self.pyfile.name = linkMatch.group("name")
-
-
- def handlePremium(self):
- # TODO: handle login timeouts
- self.download(self.pyfile.url)
-
- check = self.checkDownload({"login": '<form action="/login.php" method="POST">'})
-
- if check == "login":
- self.account.relogin(self.user)
- self.retry(reason=_("Not logged in."))
-
-
- def handleFree(self):
- self.html = self.load(self.pyfile.url)
- action = self.load(self.pyfile.url, post={"checkDownload": "check"}, decode=True)
- action = json_loads(action.replace(u"\ufeff", ""))
- self.logDebug("action is : %s" % action)
-
- if "fail" in action:
- if action["fail"] == "timeLimit":
- html = self.load(self.pyfile.url,
- post={"checkDownload": "showError",
- "errorType": "timeLimit"},
- decode=True)
- wait = re.search(self.LONG_WAIT_PATTERN, html)
- if wait:
- wait = int(wait.group(1))
- else:
- wait = 720
- self.setWait(wait, True)
- self.wait()
- self.retry()
-
- elif action["fail"] == "parallelDownload":
- self.logWarning(_("Parallel download error, now waiting 60s."))
- self.retry(wait_time=60, reason="parallelDownload")
-
- else:
- self.fail("Download check returned %s" % action["fail"])
-
- if action["success"] == "showCaptcha":
- self.doCaptcha()
- self.doTimmer()
- elif action["success"] == "showTimmer":
- self.doTimmer()
-
- # show download link
- response = self.load(self.pyfile.url, post={"downloadLink": "show"}, decode=True)
- self.logDebug("show downloadLink response : %s" % response)
- if not response.find("fail"):
- self.fail("Couldn't retrieve download url")
-
- # this may either download our file or forward us to an error page
- self.download(self.pyfile.url, post={"download": "normal"})
-
- check = self.checkDownload({"expired": "Your download link has expired",
- "wait": re.compile(self.LONG_WAIT_PATTERN),
- "limit": "Your daily download limit has been reached"})
-
- if check == "expired":
- self.logDebug("Download link was expired")
- self.retry()
- elif check == "wait":
- wait_time = 720
- if self.lastCheck is not None:
- wait_time = int(self.lastCheck.group(1))
- self.setWait(wait_time + 3, True)
- self.wait()
- self.retry()
- elif check == "limit":
- #download limited reached for today (not a exact time known)
-
- self.setWait(180 * 60, True) # wait 3 hours
- self.wait()
- self.retry(max_tries=0)
-
- self.thread.m.reconnecting.wait(3) # Ease issue with later downloads appearing to be in parallel
-
- def doTimmer(self):
- wait = self.load(self.pyfile.url,
- post={"downloadLink": "wait"},
- decode=True).replace(u"\ufeff", "") # remove UTF8 BOM
- self.logDebug("wait response : %s" % wait)
-
- if not wait.find("fail"):
- self.fail("Failed getting wait time")
-
- self.setWait(int(wait)) # remove UTF8 BOM
- self.wait()
-
- def doCaptcha(self):
- captcha_key = re.search(self.CAPTCHA_KEY_PATTERN, self.html).group("key")
- recaptcha = ReCaptcha(self)
-
- for i in range(5):
- challenge, code = recaptcha.challenge(captcha_key)
-
- response = json_loads(self.load("http://www.fileserve.com/checkReCaptcha.php",
- post={'recaptcha_challenge_field': challenge,
- 'recaptcha_response_field': code,
- 'recaptcha_shortencode_field': self.file_id}).replace(u"\ufeff", ""))
- self.logDebug("reCaptcha response : %s" % response)
- if not response["success"]:
- self.invalidCaptcha()
- else:
- self.correctCaptcha()
- break
-
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+"""
+
+import re
+from module.plugins.Hoster import Hoster
+from module.network.RequestFactory import getURL
+from module.plugins.ReCaptcha import ReCaptcha
+from module.common.json_layer import json_loads
+from module.utils import parseFileSize
+from module.plugins.Plugin import chunks
+
+def checkFile(plugin, urls):
+ html = getURL(plugin.URLS[1], post = {"urls": "\n".join(urls)}, decode=True)
+
+ file_info = []
+ for li in re.finditer(plugin.LINKCHECK_TR, html, re.DOTALL):
+ try:
+ cols = re.findall(plugin.LINKCHECK_TD, li.group(1))
+ if cols:
+ file_info.append((
+ cols[1] if cols[1] != '--' else cols[0],
+ parseFileSize(cols[2]) if cols[2] != '--' else 0,
+ 2 if cols[3].startswith('Available') else 1,
+ cols[0]))
+ except Exception, e:
+ continue
+
+ return file_info
+
+class FileserveCom(Hoster):
+ __name__ = "FileserveCom"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:www\.)?fileserve\.com/file/(?P<id>[^/]+).*"
+ __version__ = "0.51"
+ __description__ = """Fileserve.Com File Download Hoster"""
+ __author_name__ = ("jeix", "mkaay", "paul king", "zoidberg")
+ __author_mail__ = ("jeix@hasnomail.de", "mkaay@mkaay.de", "", "zoidberg@mujmail.cz")
+
+ URLS = ['http://www.fileserve.com/file/', 'http://www.fileserve.com/link-checker.php', 'http://www.fileserve.com/checkReCaptcha.php']
+ LINKCHECK_TR = r'<tr>\s*(<td>http://www.fileserve\.com/file/.*?)</tr>'
+ LINKCHECK_TD = r'<td>(?:<[^>]*>|&nbsp;)*([^<]*)'
+
+ CAPTCHA_KEY_PATTERN = r"var reCAPTCHA_publickey='(?P<key>[^']+)'"
+ LONG_WAIT_PATTERN = r'<li class="title">You need to wait (\d+) (\w+) to start another download\.</li>'
+ LINK_EXPIRED_PATTERN = "Your download link has expired"
+ DAILY_LIMIT_PATTERN = "Your daily download limit has been reached"
+ NOT_LOGGED_IN_PATTERN = '<form (name="loginDialogBoxForm"|id="login_form")|<li><a href="/login.php">Login</a></li>'
+
+ # shares code with FilejungleCom and UploadstationCom
+
+ def setup(self):
+ self.resumeDownload = self.multiDL = True if self.premium else False
+
+ self.file_id = re.search(self.__pattern__, self.pyfile.url).group('id')
+ self.url = "%s%s" % (self.URLS[0], self.file_id)
+ self.logDebug("File ID: %s URL: %s" % (self.file_id, self.url))
+
+ def process(self, pyfile):
+ pyfile.name, pyfile.size, status, self.url = checkFile(self, [self.url])[0]
+ if status != 2: self.offline()
+ self.logDebug("File Name: %s Size: %d" % (pyfile.name, pyfile.size))
+
+ if self.premium:
+ self.handlePremium()
+ else:
+ self.handleFree()
+
+ def handleFree(self):
+ self.html = self.load(self.url)
+ action = self.load(self.url, post={"checkDownload": "check"}, decode=True)
+ action = json_loads(action)
+ self.logDebug(action)
+
+ if "fail" in action:
+ if action["fail"] == "timeLimit":
+ self.html = self.load(self.url,
+ post={"checkDownload": "showError",
+ "errorType": "timeLimit"},
+ decode=True)
+
+ self.doLongWait(re.search(self.LONG_WAIT_PATTERN, self.html))
+
+ elif action["fail"] == "parallelDownload":
+ self.logWarning(_("Parallel download error, now waiting 60s."))
+ self.retry(wait_time=60, reason="parallelDownload")
+
+ else:
+ self.fail("Download check returned %s" % action["fail"])
+
+ elif "success" in action:
+ if action["success"] == "showCaptcha":
+ self.doCaptcha()
+ self.doTimmer()
+ elif action["success"] == "showTimmer":
+ self.doTimmer()
+
+ else:
+ self.fail("Unknown server response")
+
+ # show download link
+ response = self.load(self.url, post={"downloadLink": "show"}, decode=True)
+ self.logDebug("show downloadLink response : %s" % response)
+ if "fail" in response:
+ self.fail("Couldn't retrieve download url")
+
+ # this may either download our file or forward us to an error page
+ self.download(self.url, post = {"download": "normal"})
+ self.logDebug(self.req.http.lastEffectiveURL)
+
+ check = self.checkDownload({"expired": self.LINK_EXPIRED_PATTERN,
+ "wait": re.compile(self.LONG_WAIT_PATTERN),
+ "limit": self.DAILY_LIMIT_PATTERN})
+
+ if check == "expired":
+ self.logDebug("Download link was expired")
+ self.retry()
+ elif check == "wait":
+ self.doLongWait(self.lastCheck)
+ elif check == "limit":
+ #download limited reached for today (not a exact time known)
+ self.setWait(180 * 60, True) # wait 3 hours
+ self.wait()
+ self.retry(max_tries=0)
+
+ self.thread.m.reconnecting.wait(3) # Ease issue with later downloads appearing to be in parallel
+
+ def doTimmer(self):
+ response = self.load(self.url,
+ post={"downloadLink": "wait"},
+ decode=True)
+ self.logDebug("wait response : %s" % response[:80])
+
+ if "fail" in response:
+ self.fail("Failed getting wait time")
+
+ if self.__name__ == "FilejungleCom":
+ found = re.search(r'"waitTime":(\d+)', response)
+ if not found: self.fail("Cannot get wait time")
+ wait_time = int(found.group(1))
+ else:
+ wait_time = int(response) + 3
+
+ self.setWait(wait_time)
+ self.wait()
+
+ def doCaptcha(self):
+ captcha_key = re.search(self.CAPTCHA_KEY_PATTERN, self.html).group("key")
+ recaptcha = ReCaptcha(self)
+
+ for i in range(5):
+ challenge, code = recaptcha.challenge(captcha_key)
+
+ response = json_loads(self.load(self.URLS[2],
+ post={'recaptcha_challenge_field': challenge,
+ 'recaptcha_response_field': code,
+ 'recaptcha_shortencode_field': self.file_id}))
+ self.logDebug("reCaptcha response : %s" % response)
+ if not response["success"]:
+ self.invalidCaptcha()
+ else:
+ self.correctCaptcha()
+ break
+ else: self.fail("Invalid captcha")
+
+ def doLongWait(self, m):
+ wait_time = (int(m.group(1)) * {'seconds':1, 'minutes':60, 'hours':3600}[m.group(2)]) if m else 720
+ self.setWait(wait_time, True)
+ self.wait()
+ self.retry()
+
+ def handlePremium(self):
+ premium_url = None
+ if self.__name__ == "FileserveCom":
+ #try api download
+ response = self.load("http://app.fileserve.com/api/download/premium/",
+ post = {"username": self.user,
+ "password": self.account.getAccountData(self.user)["password"],
+ "shorten": self.file_id},
+ decode = True)
+ if response:
+ response = json_loads(response)
+ if response['error_code'] == "302": premium_url = response['next']
+ elif response['error_code'] in ["305", "500"]: self.tempOffline()
+ elif response['error_code'] in ["403", "605"]: self.resetAccount()
+ elif response['error_code'] in ["606", "607", "608"]: self.offline()
+ else: self.logError(response['error_code'], response['error_message'])
+
+ self.download(premium_url or self.pyfile.url)
+
+ if not premium_url:
+ check = self.checkDownload({"login": re.compile(self.NOT_LOGGED_IN_PATTERN)})
+
+ if check == "login":
+ self.account.relogin(self.user)
+ self.retry(reason=_("Not logged in."))
+
+def getInfo(urls):
+ for chunk in chunks(urls, 100): yield checkFile(FileserveCom, chunk) \ No newline at end of file
diff --git a/module/plugins/hoster/FourSharedCom.py b/module/plugins/hoster/FourSharedCom.py
index 2b27eed28..551706283 100644
--- a/module/plugins/hoster/FourSharedCom.py
+++ b/module/plugins/hoster/FourSharedCom.py
@@ -7,33 +7,45 @@ import re
class FourSharedCom(SimpleHoster):
__name__ = "FourSharedCom"
__type__ = "hoster"
- __pattern__ = r"http://[\w\.]*?4shared(-china)?\.com/(account/)?(download|get|file|document|photo|video|audio)/.+?/.*"
- __version__ = "0.25"
+ __pattern__ = r"http://[\w\.]*?4shared(-china)?\.com/(account/)?(download|get|file|document|photo|video|audio|office)/.+?/.*"
+ __version__ = "0.28"
__description__ = """4Shared Download Hoster"""
__author_name__ = ("jeix", "zoidberg")
__author_mail__ = ("jeix@hasnomail.de", "zoidberg@mujmail.cz")
- FILE_NAME_PATTERN = '<meta name="title" content="(?P<N>[^"]+)" />'
+ FILE_NAME_PATTERN = r'<meta name="title" content="(?P<N>.+?)"'
FILE_SIZE_PATTERN = '<span title="Size: (?P<S>[0-9,.]+) (?P<U>[kKMG])i?B">'
FILE_OFFLINE_PATTERN = 'The file link that you requested is not valid\.|This file was deleted.'
FILE_NAME_REPLACEMENTS = [(r"&#(\d+).", lambda m: unichr(int(m.group(1))))]
+ FILE_SIZE_REPLACEMENTS = [(",", "")]
- DOWNLOAD_BUTTON_PATTERN = '<a href="([^"]+)"\s*class="dbtn'
- DOWNLOAD_URL_PATTERN = r"<a class=\"linkShowD3\" href='([^']+)'>Download file now</a>"
+ DOWNLOAD_BUTTON_PATTERN = 'id="btnLink" href="(.*?)"'
+ FID_PATTERN = 'name="d3fid" value="(.*?)"'
+ DOWNLOAD_URL_PATTERN = r'name="d3link" value="(.*?)"'
def handleFree(self):
+ if not self.account:
+ self.fail("User not logged in")
+
found = re.search(self.DOWNLOAD_BUTTON_PATTERN, self.html)
if found:
link = found.group(1)
else:
link = re.sub(r'/(download|get|file|document|photo|video|audio)/', r'/get/', self.pyfile.url)
-
+
self.html = self.load(link)
found = re.search(self.DOWNLOAD_URL_PATTERN, self.html)
if not found: self.parseError('Download link')
link = found.group(1)
+ try:
+ found = re.search(self.FID_PATTERN, self.html)
+ response = self.load('http://www.4shared.com/web/d2/getFreeDownloadLimitInfo?fileId=%s' % found.group(1))
+ self.logDebug(response)
+ except:
+ pass
+
self.setWait(20)
self.wait()
self.download(link)
diff --git a/module/plugins/hoster/FreakshareCom.py b/module/plugins/hoster/FreakshareCom.py
index 869b8a99e..56e02cbdc 100644
--- a/module/plugins/hoster/FreakshareCom.py
+++ b/module/plugins/hoster/FreakshareCom.py
@@ -9,10 +9,10 @@ class FreakshareCom(Hoster):
__name__ = "FreakshareCom"
__type__ = "hoster"
__pattern__ = r"http://(?:www\.)?freakshare\.(net|com)/files/\S*?/"
- __version__ = "0.33"
+ __version__ = "0.37"
__description__ = """Freakshare.com Download Hoster"""
- __author_name__ = ("sitacuisses","spoob","mkaay")
- __author_mail__ = ("sitacuisses@yahoo.de","spoob@pyload.org","mkaay@mkaay.de")
+ __author_name__ = ("sitacuisses","spoob","mkaay", "Toilal")
+ __author_mail__ = ("sitacuisses@yahoo.de","spoob@pyload.org","mkaay@mkaay.de", "toilal.dev@gmail.com")
def setup(self):
self.html = None
@@ -22,6 +22,7 @@ class FreakshareCom(Hoster):
def process(self, pyfile):
self.pyfile = pyfile
+
pyfile.url = pyfile.url.replace("freakshare.net/","freakshare.com/")
if self.account:
@@ -36,10 +37,22 @@ class FreakshareCom(Hoster):
self.download(self.pyfile.url, post=self.req_opts)
- check = self.checkDownload({"bad": "bad try"})
+ check = self.checkDownload({"bad": "bad try",
+ "paralell": "> Sorry, you cant download more then 1 files at time. <",
+ "empty": "Warning: Unknown: Filename cannot be empty",
+ "wrong_captcha": "Wrong Captcha!"})
+
if check == "bad":
self.fail("Bad Try.")
-
+ if check == "paralell":
+ self.setWait(300, True)
+ self.wait()
+ self.retry()
+ if check == "empty":
+ self.fail("File not downloadable")
+ if check == "wrong_captcha":
+ self.invalidCaptcha()
+ self.retry()
def prepare(self):
pyfile = self.pyfile
@@ -61,6 +74,7 @@ class FreakshareCom(Hoster):
return True
def download_html(self):
+ self.load("http://freakshare.com/index.php", {"language": "EN"}); # Set english language in server session
self.html = self.load(self.pyfile.url)
def get_file_url(self):
@@ -105,16 +119,11 @@ class FreakshareCom(Hoster):
if self.html is None:
self.download_html()
- if "Der Traffic f\xc3\xbcr heute ist verbraucht!" in self.html or "Your Traffic is used up for today" in self.html:
+ if "Your Traffic is used up for today" in self.html:
self.wantReconnect = True
return 24*3600
- if re.search(r"This file does not exist!", self.html) is not None:
- self.offline()
- timestring = re.search('\s*var\sdownloadWait\s=\s(\d*);', self.html)
- if timestring:
- return int(timestring.group(1)) + 1 #add 1 sec as tenths of seconds are cut off
- timestring = re.search('\s*var\stime\s=\s(\d*)[.0];', self.html)
+ timestring = re.search('\s*var\s(?:downloadWait|time)\s=\s(\d*)[.\d]*;', self.html)
if timestring:
return int(timestring.group(1)) + 1 #add 1 sec as tenths of seconds are cut off
else:
@@ -126,7 +135,7 @@ class FreakshareCom(Hoster):
"""
if self.html is None:
self.download_html()
- if re.search(r"Sorry, this Download doesnt exist anymore", self.html) is not None:
+ if re.search(r"This file does not exist!", self.html) is not None:
return False
else:
return True
@@ -134,10 +143,7 @@ class FreakshareCom(Hoster):
def get_download_options(self):
re_envelope = re.search(r".*?value=\"Free\sDownload\".*?\n*?(.*?<.*?>\n*)*?\n*\s*?</form>", self.html).group(0) #get the whole request
to_sort = re.findall(r"<input\stype=\"hidden\"\svalue=\"(.*?)\"\sname=\"(.*?)\"\s\/>", re_envelope)
- request_options = []
-
- for item in to_sort: #Name value pairs are output reversed from regex, so we reorder them
- request_options.append((item[1], item[0]))
+ request_options = dict((n, v) for (v, n) in to_sort)
herewego = self.load(self.pyfile.url, None, request_options) # the actual download-Page
@@ -146,21 +152,16 @@ class FreakshareCom(Hoster):
# fp.write(herewego)
to_sort = re.findall(r"<input\stype=\".*?\"\svalue=\"(\S*?)\".*?name=\"(\S*?)\"\s.*?\/>", herewego)
- request_options = []
+ request_options = dict((n, v) for (v, n) in to_sort)
# comment this in, when it doesnt work as well
#print "\n\n%s\n\n" % ";".join(["%s=%s" % x for x in to_sort])
-
- for item in to_sort: #Same as above
- request_options.append((item[1], item[0]))
challenge = re.search(r"http://api\.recaptcha\.net/challenge\?k=([0-9A-Za-z]+)", herewego)
if challenge:
re_captcha = ReCaptcha(self)
- challenge, result = re_captcha.challenge(challenge.group(1))
-
- request_options.append(("recaptcha_challenge_field", challenge))
- request_options.append(("recaptcha_response_field", result))
+ request_options["recaptcha_challenge_field"], request_options["recaptcha_response_field"] \
+ = re_captcha.challenge(challenge.group(1))
return request_options
diff --git a/module/plugins/hoster/FshareVn.py b/module/plugins/hoster/FshareVn.py
index 5a8b00c17..977e97211 100644
--- a/module/plugins/hoster/FshareVn.py
+++ b/module/plugins/hoster/FshareVn.py
@@ -16,23 +16,27 @@ def getInfo(urls):
yield file_info
+def doubleDecode(m):
+ return m.group(1).decode('raw_unicode_escape')
+
class FshareVn(SimpleHoster):
__name__ = "FshareVn"
__type__ = "hoster"
__pattern__ = r"http://(www\.)?fshare.vn/file/.*"
- __version__ = "0.12"
+ __version__ = "0.13"
__description__ = """FshareVn Download Hoster"""
__author_name__ = ("zoidberg")
__author_mail__ = ("zoidberg@mujmail.cz")
- FILE_INFO_PATTERN = r'<p>(?P<N>[^<]+)<\\/p>\\r\\n\s*<p>(?P<S>[0-9,.]+)\s*(?P<U>[kKMG])i?B<\\/p>'
+ FILE_INFO_PATTERN = r'<p>(?P<N>[^<]+)<\\/p>[\\trn\s]*<p>(?P<S>[0-9,.]+)\s*(?P<U>[kKMG])i?B<\\/p>'
FILE_OFFLINE_PATTERN = r'<div class=\\"f_left file_(enable|w)\\">'
+ FILE_NAME_REPLACEMENTS = [("(.*)", doubleDecode)]
DOWNLOAD_URL_PATTERN = r"<a class=\"bt_down\" id=\"down\".*window.location='([^']+)'\">"
FORM_PATTERN = r'<form action="" method="post" name="frm_download">(.*?)</form>'
FORM_INPUT_PATTERN = r'<input[^>]* name="?([^" ]+)"? value="?([^" ]+)"?[^>]*>'
VIP_URL_PATTERN = r'<form action="([^>]+)" method="get" name="frm_download">'
- WAIT_PATTERN = u"Vui lòng chờ cho lượt download kế tiếp !"
+ WAIT_PATTERN = u"Vui lòng chờ lượt download kế tiếp"
def process(self, pyfile):
self.html = self.load('http://www.fshare.vn/check_link.php', post = {
@@ -40,15 +44,17 @@ class FshareVn(SimpleHoster):
"arrlinks": pyfile.url
}, decode = True)
self.getFileInfo()
- if self.account and self.premium:
- self.handlePremium()
- else:
- self.handleFree()
+
+ url = self.handlePremium() if self.premium else self.handleFree()
+ self.download(url)
+ self.checkDownloadedFile()
def handleFree(self):
self.html = self.load(self.pyfile.url, decode = True)
if self.WAIT_PATTERN in self.html:
- self.retry(300, 20, "Try again later...")
+ self.retry(20, 300, "Try again later...")
+
+ self.checkErrors()
found = re.search(self.FORM_PATTERN, self.html, re.DOTALL)
if not found: self.parseError('FORM')
@@ -68,15 +74,18 @@ class FshareVn(SimpleHoster):
self.setWait(int(found.group(1)) if found else 30)
self.wait()
- self.download(url)
+ return url
def handlePremium(self):
header = self.load(self.pyfile.url, just_header = True)
if 'location' in header and header['location'].startswith('http://download'):
self.logDebug('Direct download')
- self.download(self.pyfile.url)
+ return self.pyfile.url
else:
self.html = self.load(self.pyfile.url)
+
+ self.checkErrors()
+
found = re.search(self.VIP_URL_PATTERN, self.html)
if not found:
if self.retries >= 3: self.resetAccount()
@@ -84,4 +93,17 @@ class FshareVn(SimpleHoster):
self.retry(5, 1, 'VIP URL not found')
url = found.group(1)
self.logDebug('VIP URL: ' + url)
- self.download(url) \ No newline at end of file
+ return url
+
+ def checkErrors(self):
+ if '/error.php?' in self.req.lastEffectiveURL:
+ self.offline()
+
+ def checkDownloadedFile(self):
+ # check download
+ check = self.checkDownload({
+ "not_found": ("<head><title>404 Not Found</title></head>")
+ })
+
+ if check == "not_found":
+ self.fail("File not found on server") \ No newline at end of file
diff --git a/module/plugins/hoster/GigapetaCom.py b/module/plugins/hoster/GigapetaCom.py
new file mode 100644
index 000000000..28ba35abe
--- /dev/null
+++ b/module/plugins/hoster/GigapetaCom.py
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: zoidberg
+"""
+
+import re
+from random import randint
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+from pycurl import FOLLOWLOCATION
+
+class GigapetaCom(SimpleHoster):
+ __name__ = "GigapetaCom"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:www\.)?gigapeta\.com/dl/\w+"
+ __version__ = "0.01"
+ __description__ = """GigaPeta.com plugin - free only"""
+ __author_name__ = ("zoidberg")
+ __author_mail__ = ("zoidberg@mujmail.cz")
+
+ SH_COOKIES = [("http://gigapeta.com", "lang", "us")]
+ FILE_NAME_PATTERN = r'<img src=".*" alt="file" />-->\s*(?P<N>.*?)\s*</td>'
+ FILE_SIZE_PATTERN = r'<th>\s*Size\s*</th>\s*<td>\s*(?P<S>.*?)\s*</td>'
+ FILE_OFFLINE_PATTERN = r'<div id="page_error">'
+
+ def handleFree(self):
+ captcha_key = str(randint(1,100000000))
+ captcha_url = "http://gigapeta.com/img/captcha.gif?x=%s" % captcha_key
+
+ self.req.http.c.setopt(FOLLOWLOCATION, 0)
+
+ for i in range(5):
+ self.checkErrors()
+
+ captcha = self.decryptCaptcha(captcha_url)
+ self.html = self.load(self.pyfile.url, post = {
+ "captcha_key": captcha_key,
+ "captcha": captcha,
+ "download": "Download"})
+
+ found = re.search(r"Location\s*:\s*(.*)", self.req.http.header, re.I)
+ if found:
+ download_url = found.group(1)
+ break
+ elif "Entered figures don&#96;t coincide with the picture" in self.html:
+ self.invalidCaptcha()
+ else:
+ self.fail("No valid captcha code entered")
+
+ self.req.http.c.setopt(FOLLOWLOCATION, 1)
+ self.logDebug("Download URL: %s" % download_url)
+ self.download(download_url)
+
+ def checkErrors(self):
+ if "All threads for IP" in self.html:
+ self.logDebug("Your IP is already downloading a file - wait and retry")
+ self.setWait(300, True)
+ self.wait()
+ self.retry()
+
+getInfo = create_getInfo(GigapetaCom) \ No newline at end of file
diff --git a/module/plugins/hoster/HellshareCz.py b/module/plugins/hoster/HellshareCz.py
index cc8341f8e..0add79ed9 100644
--- a/module/plugins/hoster/HellshareCz.py
+++ b/module/plugins/hoster/HellshareCz.py
@@ -26,7 +26,7 @@ class HellshareCz(SimpleHoster):
__name__ = "HellshareCz"
__type__ = "hoster"
__pattern__ = r"(http://(?:.*\.)*hellshare\.(?:cz|com|sk|hu)/[^?]*/\d+).*"
- __version__ = "0.76"
+ __version__ = "0.77"
__description__ = """Hellshare.cz"""
__author_name__ = ("zoidberg")
@@ -46,18 +46,15 @@ class HellshareCz(SimpleHoster):
self.chunkLimit = 1
def process(self, pyfile):
- if self.account:
- self.account.relogin(self.user)
-
pyfile.url = re.search(self.__pattern__, pyfile.url).group(1)
self.html = self.load(pyfile.url, decode = True)
self.getFileInfo()
found = re.search(self.SHOW_WINDOW_PATTERN, self.html)
if not found: self.parseError('SHOW WINDOW')
- url = found.group(1)
- self.logDebug("SHOW WINDOW: " + url)
- self.html = self.load("http://download.hellshare.com" + url, decode=True)
+ self.url = "http://www.hellshare.com" + found.group(1)
+ self.logDebug("SHOW WINDOW: " + self.url)
+ self.html = self.load(self.url, decode=True)
if self.account:
self.handlePremium()
diff --git a/module/plugins/hoster/HotfileCom.py b/module/plugins/hoster/HotfileCom.py
index e618d0f4f..df652edcc 100644
--- a/module/plugins/hoster/HotfileCom.py
+++ b/module/plugins/hoster/HotfileCom.py
@@ -32,24 +32,26 @@ class HotfileCom(Hoster):
__name__ = "HotfileCom"
__type__ = "hoster"
__pattern__ = r"http://(www.)?hotfile\.com/dl/\d+/[0-9a-zA-Z]+/"
- __version__ = "0.32"
+ __version__ = "0.34"
__description__ = """Hotfile.com Download Hoster"""
- __author_name__ = ("sitacuisses","spoob","mkaay")
- __author_mail__ = ("sitacuisses@yhoo.de","spoob@pyload.org","mkaay@mkaay.de")
+ __author_name__ = ("sitacuisses","spoob","mkaay","JoKoT3")
+ __author_mail__ = ("sitacuisses@yhoo.de","spoob@pyload.org","mkaay@mkaay.de","jokot3@gmail.com")
FILE_OFFLINE_PATTERN = r'File is removed'
def setup(self):
self.html = [None, None]
self.wantReconnect = False
- self.multiDL = False
self.htmlwithlink = None
self.url = None
- if self.account:
+ if self.premium:
self.multiDL = True
self.resumeDownload = True
self.chunkLimit = -1
+ else:
+ self.multiDL = False
+ self.chunkLimit = 1
def apiCall(self, method, post, login=False):
if not self.account and login:
@@ -73,7 +75,7 @@ class HotfileCom(Hoster):
pyfile.name = self.apiData["name"]
- if not self.account:
+ if not self.premium:
self.downloadHTML()
if self.FILE_OFFLINE_PATTERN in self.html[0]:
@@ -127,14 +129,9 @@ class HotfileCom(Hoster):
free_limit_pattern = re.compile(r"timerend=d\.getTime\(\)\+(\d+);")
matches = free_limit_pattern.findall(self.html[0])
if matches:
- for match in matches:
- if int(match) in (60000,15000,0):
- continue
- else:
- waittime = int(match)/1000 + 65
- if waittime > 300:
- self.wantReconnect = True
- return waittime
- return 65
+ wait_time = (sum([int(match) for match in matches])/1000) or 60
+ if wait_time > 300:
+ self.wantReconnect = True
+ return wait_time + 1
else:
- self.fail("Don't know how long to wait. Cannot proceed.")
+ self.fail("Don't know how long to wait. Cannot proceed.") \ No newline at end of file
diff --git a/module/plugins/hoster/IcyFilesCom.py b/module/plugins/hoster/IcyFilesCom.py
new file mode 100644
index 000000000..3f966d936
--- /dev/null
+++ b/module/plugins/hoster/IcyFilesCom.py
@@ -0,0 +1,112 @@
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: godofdream
+"""
+
+import re
+from module.plugins.Hoster import Hoster
+from module.network.RequestFactory import getURL
+
+def getInfo(urls):
+ result = []
+ for url in urls:
+ html = getURL(url, decode=True)
+ if re.search(IcyFilesCom.FILE_OFFLINE_PATTERN, html):
+ # File offline
+ result.append((url, 0, 1, url))
+ else:
+ # Get file info
+ name = re.search(IcyFilesCom.FILE_NAME_PATTERN, html)
+ size = re.search(IcyFilesCom.SIZE_PATTERN, html)
+ if name is not None:
+ name = name.group(1)
+ size = (int(size.group(1)) * 1000000)
+ result.append((name, size, 2, url))
+ yield result
+
+
+class IcyFilesCom(Hoster):
+ __name__ = "IcyFilesCom"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:www\.)?icyfiles\.com/(.*)"
+ __version__ = "0.04"
+ __description__ = """IcyFiles.com plugin - free only"""
+ __author_name__ = ("godofdream")
+ __author_mail__ = ("soilfiction@gmail.com")
+
+ FILE_NAME_PATTERN = r'<div id="file">(.*?)</div>'
+ SIZE_PATTERN = r'<li>(\d+) <span>Size/mb'
+ FILE_OFFLINE_PATTERN = r'The requested File cant be found'
+ WAIT_LONGER_PATTERN = r'All download tickets are in use\. please try it again in a few seconds'
+ WAIT_PATTERN = r'<div class="counter">(\d+)</div>'
+ TOOMUCH_PATTERN = r'Sorry dude, you have downloaded too much\. Please wait (\d+) seconds'
+
+
+ def setup(self):
+ self.multiDL = False
+
+ def process(self, pyfile):
+ self.html = self.load(pyfile.url, decode=True)
+ # check if offline
+ if re.search(self.FILE_OFFLINE_PATTERN, self.html):
+ self.offline()
+ # All Downloadtickets in use
+ timmy = re.search(self.WAIT_LONGER_PATTERN, self.html)
+ if timmy:
+ self.logDebug("waitforfreeslot")
+ self.waitForFreeSlot()
+ # Wait the waittime
+ timmy = re.search(self.WAIT_PATTERN, self.html)
+ if timmy:
+ self.logDebug("waiting", timmy.group(1))
+ self.setWait(int(timmy.group(1)) + 2, False)
+ self.wait()
+ # Downloaded to much
+ timmy = re.search(self.TOOMUCH_PATTERN, self.html)
+ if timmy:
+ self.logDebug("too much", timmy.group(1))
+ self.setWait(int(timmy.group(1)), True)
+ self.wait()
+ # Find Name
+ found = re.search(self.FILE_NAME_PATTERN, self.html)
+ if found is None:
+ self.fail("Parse error (NAME)")
+ pyfile.name = found.group(1)
+ # Get the URL
+ url = pyfile.url
+ found = re.search(self.__pattern__, url)
+ if found is None:
+ self.fail("Parse error (URL)")
+ download_url = "http://icyfiles.com/download.php?key=" + found.group(1)
+ self.download(download_url)
+ # check download
+ check = self.checkDownload({
+ "notfound": re.compile(r"^<head><title>404 Not Found</title>$"),
+ "skippedcountdown": re.compile(r"^Dont skip the countdown$"),
+ "waitforfreeslots": re.compile(self.WAIT_LONGER_PATTERN),
+ "downloadedtoomuch": re.compile(self.TOOMUCH_PATTERN)
+ })
+ if check == "skippedcountdown":
+ self.fail("Countdown error")
+ elif check == "notfound":
+ self.fail("404 Not found")
+ elif check == "waitforfreeslots":
+ self.waitForFreeSlot()
+ elif check == "downloadedtoomuch":
+ self.retry()
+
+ def waitForFreeSlot(self):
+ self.retry(60, 60, "Wait for free slot")
diff --git a/module/plugins/hoster/IfileIt.py b/module/plugins/hoster/IfileIt.py
index ec830f3b2..bf394f340 100644
--- a/module/plugins/hoster/IfileIt.py
+++ b/module/plugins/hoster/IfileIt.py
@@ -25,8 +25,8 @@ from module.network.RequestFactory import getURL
class IfileIt(SimpleHoster):
__name__ = "IfileIt"
__type__ = "hoster"
- __pattern__ = r"http://(?:\w*\.)*(?:ifile\.it|mihd\.net)/(\w+).*"
- __version__ = "0.24"
+ __pattern__ = r"^unmatchable$"
+ __version__ = "0.27"
__description__ = """Ifile.it"""
__author_name__ = ("zoidberg")
@@ -35,28 +35,29 @@ class IfileIt(SimpleHoster):
DOWNLOAD_LINK_PATTERN = r'</span> If it doesn\'t, <a target="_blank" href="([^"]+)">'
RECAPTCHA_KEY_PATTERN = r"var __recaptcha_public\s*=\s*'([^']+)';"
FILE_INFO_PATTERN = r'<span style="cursor: default;[^>]*>\s*(?P<N>.*?)\s*&nbsp;\s*<strong>\s*(?P<S>[0-9.]+)\s*(?P<U>[kKMG])i?B\s*</strong>\s*</span>'
- FILE_OFFLINE_PATTERN = r'$\("#errorPnl"\)\.empty\(\)\.append\( "no such file" \);'
+ FILE_OFFLINE_PATTERN = r'<span style="cursor: default;[^>]*>\s*&nbsp;\s*<strong>\s*</strong>\s*</span>'
+ TEMP_OFFLINE_PATTERN = r'<span class="msg_red">Downloading of this file is temporarily disabled</span>'
def handleFree(self):
ukey = re.search(self.__pattern__, self.pyfile.url).group(1)
- json_url = 'http://ifile.it/download-request2.json?ukey=' + ukey
-
- json_response = json_loads(self.load(json_url))
+ json_url = 'http://ifile.it/new_download-request.json'
+ post_data = {"ukey" : ukey, "ab": "0"}
+
+ json_response = json_loads(self.load(json_url, post = post_data))
self.logDebug(json_response)
+ if json_response['status'] == 3:
+ self.offline()
+
if json_response["captcha"]:
captcha_key = re.search(self.RECAPTCHA_KEY_PATTERN, self.html).group(1)
recaptcha = ReCaptcha(self)
+ post_data["ctype"] = "recaptcha"
for i in range(5):
- captcha_challenge, captcha_response = recaptcha.challenge(captcha_key)
-
- json_response = json_loads(self.load(json_url, post={
- "ctype": "recaptcha",
- "recaptcha_challenge": captcha_challenge,
- "recaptcha_response": captcha_response
- }))
-
+ post_data["recaptcha_challenge"], post_data["recaptcha_response"] = recaptcha.challenge(captcha_key)
+ json_response = json_loads(self.load(json_url, post = post_data))
self.logDebug(json_response)
+
if json_response["retry"]:
self.invalidCaptcha()
else:
@@ -65,11 +66,9 @@ class IfileIt(SimpleHoster):
else:
self.fail("Incorrect captcha")
- # load twice
- self.html = self.load(self.pyfile.url)
- self.html = self.load(self.pyfile.url)
- download_url = re.search(self.DOWNLOAD_LINK_PATTERN, self.html).group(1)
+ if not "ticket_url" in json_response:
+ self.parseError("Download URL")
- self.download(download_url)
+ self.download(json_response["ticket_url"])
getInfo = create_getInfo(IfileIt) \ No newline at end of file
diff --git a/module/plugins/hoster/IfolderRu.py b/module/plugins/hoster/IfolderRu.py
index 83b98ecc9..b84f77c5c 100644
--- a/module/plugins/hoster/IfolderRu.py
+++ b/module/plugins/hoster/IfolderRu.py
@@ -24,8 +24,8 @@ from module.network.RequestFactory import getURL
class IfolderRu(SimpleHoster):
__name__ = "IfolderRu"
__type__ = "hoster"
- __pattern__ = r"http://(?:\w*\.)?ifolder.ru/(\d+).*"
- __version__ = "0.33"
+ __pattern__ = r"http://(?:[^.]*\.)?ifolder.ru/(\d+).*"
+ __version__ = "0.35"
__description__ = """ifolder.ru"""
__author_name__ = ("zoidberg")
__author_mail__ = ("zoidberg@mujmail.cz")
@@ -33,7 +33,7 @@ class IfolderRu(SimpleHoster):
FILE_SIZE_REPLACEMENTS = [(u'Кб', 'KB'), (u'Мб', 'MB'), (u'Гб', 'GB')]
FILE_NAME_PATTERN = ur'(?:<div><span>)?Название:(?:</span>)? <b>(?P<N>[^<]+)</b><(?:/div|br)>'
FILE_SIZE_PATTERN = ur'(?:<div><span>)?Размер:(?:</span>)? <b>(?P<S>[^<]+)</b><(?:/div|br)>'
- FILE_OFFLINE_PATTERN = ur'<p>Файл номер <b>[^<]*</b> не найден !!!</p>'
+ FILE_OFFLINE_PATTERN = ur'<p>Файл номер <b>[^<]*</b> (не найден|удален) !!!</p>'
SESSION_ID_PATTERN = r'<a href=(http://ints.ifolder.ru/ints/sponsor/\?bi=\d*&session=([^&]+)&u=[^>]+)>'
FORM1_PATTERN = r'<form method=post name="form1" ID="Form1" style="margin-bottom:200px">(.*?)</form>'
diff --git a/module/plugins/hoster/JumbofilesCom.py b/module/plugins/hoster/JumbofilesCom.py
new file mode 100644
index 000000000..9e8adb512
--- /dev/null
+++ b/module/plugins/hoster/JumbofilesCom.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+import re
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+from module.utils import html_unescape
+
+class JumbofilesCom(SimpleHoster):
+ __name__ = "JumbofilesCom"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:\w*\.)*jumbofiles.com/(\w{12}).*"
+ __version__ = "0.02"
+ __description__ = """JumboFiles.com hoster plugin"""
+ __author_name__ = ("godofdream")
+ __author_mail__ = ("soilfiction@gmail.com")
+
+ FILE_INFO_PATTERN = '<TR><TD>(?P<N>[^<]+?)\s*<small>\((?P<S>[\d.]+)\s*(?P<U>[KMG][bB])\)</small></TD></TR>'
+ FILE_OFFLINE_PATTERN = 'Not Found or Deleted / Disabled due to inactivity or DMCA'
+ DIRECT_LINK_PATTERN = '<meta http-equiv="refresh" content="10;url=(.+)">'
+
+ def setup(self):
+ self.resumeDownload = True
+ self.multiDL = True
+
+ def handleFree(self):
+ ukey = re.search(self.__pattern__, self.pyfile.url).group(1)
+ post_data = {"id" : ukey, "op": "download3", "rand": ""}
+ html = self.load(self.pyfile.url, post = post_data, decode=True)
+ url = re.search(self.DIRECT_LINK_PATTERN, html).group(1)
+ self.logDebug("Download " + url)
+ self.download(url)
+
+getInfo = create_getInfo(JumbofilesCom)
diff --git a/module/plugins/hoster/LetitbitNet.py b/module/plugins/hoster/LetitbitNet.py
index 4ff2b9750..88e708bf5 100644
--- a/module/plugins/hoster/LetitbitNet.py
+++ b/module/plugins/hoster/LetitbitNet.py
@@ -19,12 +19,13 @@
import re
from random import random
from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+from module.common.json_layer import json_loads
class LetitbitNet(SimpleHoster):
__name__ = "LetitbitNet"
__type__ = "hoster"
- __pattern__ = r"http://(?:\w*\.)*letitbit.net/download/.*"
- __version__ = "0.13"
+ __pattern__ = r"http://(?:\w*\.)*(letitbit|shareflare).net/download/.*"
+ __version__ = "0.19"
__description__ = """letitbit.net"""
__author_name__ = ("zoidberg")
__author_mail__ = ("zoidberg@mujmail.cz")
@@ -32,8 +33,14 @@ class LetitbitNet(SimpleHoster):
CHECK_URL_PATTERN = r"ajax_check_url\s*=\s*'((http://[^/]+)[^']+)';"
SECONDS_PATTERN = r"seconds\s*=\s*(\d+);"
- FILE_INFO_PATTERN = r'<h1[^>]*>File: <a[^>]*><span>(?P<N>[^<]+)</span></a>\s*\[<span>(?P<S>[^<]+)</span>]</h1>'
- FILE_OFFLINE_PATTERN = r'<div id="download_content" class="hide-block">[^<]*<br>File not found<br /></div>'
+ FILE_INFO_PATTERN = r'<h1[^>]*>File:.*?<span>(?P<N>[^<]+)</span>.*?\[<span>(?P<S>[^<]+)</span>]</h1>'
+ FILE_OFFLINE_PATTERN = r'>File not found<'
+
+ DOMAIN = "http://letitbit.net"
+ FILE_URL_REPLACEMENTS = [(r"(?<=http://)([^/]+)", "letitbit.net")]
+
+ def setup(self):
+ self.resumeDownload = self.multiDL = True
def handleFree(self):
action, inputs = self.parseHtmlForm('id="ifree_form"')
@@ -42,8 +49,9 @@ class LetitbitNet(SimpleHoster):
#self.logDebug(action, inputs)
inputs['desc'] = ""
- self.html = self.load("http://letitbit.net" + action, post = inputs, cookies = True)
-
+ self.html = self.load(self.DOMAIN + action, post = inputs, cookies = True)
+
+ """
action, inputs = self.parseHtmlForm('id="d3_form"')
if not action: self.parseError("page 2 / d3_form")
#self.logDebug(action, inputs)
@@ -59,23 +67,44 @@ class LetitbitNet(SimpleHoster):
except Exception, e:
self.logError(e)
self.parseError("page 3 / js")
-
- response = self.load(ajax_check_url, post = inputs, cookies = True)
- if response != '1': self.fail('Unknown response (ajax_check_url)')
+ """
+
+ found = re.search(self.SECONDS_PATTERN, self.html)
+ seconds = int(found.group(1)) if found else 60
+ self.setWait(seconds+1)
+ self.wait()
+
+ response = self.load("%s/ajax/download3.php" % self.DOMAIN, post = " ", cookies = True)
+ if response != '1': self.parseError('Unknown response - ajax_check_url')
for i in range(5):
- captcha = self.decryptCaptcha('%s/captcha_new.php?rand=%d' % (captcha_url, random() * 100000), cookies = True)
- response = self.load(captcha_url + '/ajax/check_captcha.php', post = {"code": captcha}, cookies = True)
+ captcha = self.decryptCaptcha('%s/captcha_new.php?rand=%d' % (self.DOMAIN, random() * 100000), cookies = True)
+ response = self.load('%s/ajax/check_captcha.php' % self.DOMAIN, post = {"code": captcha}, cookies = True)
self.logDebug(response)
- if response.startswith('http://'):
- download_url = response
- self.correctCaptcha()
+ if not response:
+ self.invalidCaptcha()
+ elif response.startswith('['):
+ urls = json_loads(response)
+ break
+ elif response.startswith('http://'):
+ urls = [response]
break
else:
- self.invalidCaptcha()
+ self.parseError("Unknown response - captcha check")
+
else:
self.fail("No valid captcha solution received")
- self.download(download_url)
+ self.correctCaptcha()
+
+ for download_url in urls:
+ try:
+ self.logDebug("Download URL", download_url)
+ self.download(download_url)
+ break
+ except Exception, e:
+ self.logError(e)
+ else:
+ self.fail("Download did not finish correctly")
getInfo = create_getInfo(LetitbitNet) \ No newline at end of file
diff --git a/module/plugins/hoster/LoadTo.py b/module/plugins/hoster/LoadTo.py
index b1204cb2d..66bc6f407 100644
--- a/module/plugins/hoster/LoadTo.py
+++ b/module/plugins/hoster/LoadTo.py
@@ -33,7 +33,7 @@ def getInfo(urls):
# Get file info
name = re.search(LoadTo.FILE_NAME_PATTERN, html)
size = re.search(LoadTo.SIZE_PATTERN, html)
- if name is not None:
+ if name is not None and size is not None:
name = name.group(1)
size = size.group(1)
result.append((name, size, 2, url))
@@ -42,14 +42,14 @@ def getInfo(urls):
class LoadTo(Hoster):
__name__ = "LoadTo"
__type__ = "hoster"
- __pattern__ = r"http://.*load.to/.*"
- __version__ = "0.1"
+ __pattern__ = r"http://(www.*?\.)?load\.to/.{7,10}?/.*"
+ __version__ = "0.1002"
__description__ = """load.to"""
__author_name__ = ("halfman")
__author_mail__ = ("Pulpan3@gmail.com")
- FILE_NAME_PATTERN = r'<div class="toolarge"><h1>([^<]+)</h1></div>'
- URL_PATTERN = r'<form method="post" action="([^"]+)"'
+ FILE_NAME_PATTERN = r'<div class="toolarge"><h1>(.+?)</h1></div>'
+ URL_PATTERN = r'<form method="post" action="(.+?)"'
SIZE_PATTERN = r'<div class="download_table_right">(\d+) Bytes</div>'
FILE_OFFLINE_PATTERN = r'Can\'t find file. Please check URL.<br />'
WAIT_PATTERN = r'type="submit" value="Download \((\d+)\)"'
@@ -64,11 +64,6 @@ class LoadTo(Hoster):
if re.search(self.FILE_OFFLINE_PATTERN, self.html):
self.offline()
- timmy = re.search(self.WAIT_PATTERN, self.html)
- if timmy:
- self.setWait(timmy.group(1))
- self.wait()
-
found = re.search(self.FILE_NAME_PATTERN, self.html)
if found is None:
self.fail("Parse error (NAME)")
@@ -78,5 +73,10 @@ class LoadTo(Hoster):
if found is None:
self.fail("Parse error (URL)")
download_url = found.group(1)
+
+ timmy = re.search(self.WAIT_PATTERN, self.html)
+ if timmy:
+ self.setWait(timmy.group(1))
+ self.wait()
- self.download(download_url) \ No newline at end of file
+ self.download(download_url)
diff --git a/module/plugins/hoster/MediafireCom.py b/module/plugins/hoster/MediafireCom.py
index c1d6e3595..dce16118f 100644
--- a/module/plugins/hoster/MediafireCom.py
+++ b/module/plugins/hoster/MediafireCom.py
@@ -58,7 +58,7 @@ class MediafireCom(SimpleHoster):
__name__ = "MediafireCom"
__type__ = "hoster"
__pattern__ = r"http://(\w*\.)*mediafire\.com/(file/|(download.php)?\?)(\w{11}|\w{15})($|/)"
- __version__ = "0.74"
+ __version__ = "0.76"
__description__ = """Mediafire.com plugin - free only"""
__author_name__ = ("zoidberg")
__author_mail__ = ("zoidberg@mujmail.cz")
@@ -75,7 +75,7 @@ class MediafireCom(SimpleHoster):
FILE_OFFLINE_PATTERN = r'class="error_msg_title"> Invalid or Deleted File. </div>'
def setup(self):
- self.multiDL = True
+ self.multiDL = False
def process(self, pyfile):
self.url, result = checkHTMLHeader(pyfile.url)
@@ -83,15 +83,18 @@ class MediafireCom(SimpleHoster):
if result == 0:
self.html = self.load(self.url, decode = True)
- self.checkCaptcha()
+ self.checkCaptcha()
+ self.multiDL = True
self.getFileInfo()
+
if self.account:
self.handlePremium()
else:
self.handleFree()
elif result == 1:
self.offline()
- else:
+ else:
+ self.multiDL = True
self.download(self.url, disposition = True)
def handleFree(self):
@@ -104,6 +107,7 @@ class MediafireCom(SimpleHoster):
else:
self.fail("No or incorrect password")
+ """
links = re.findall(self.DOWNLOAD_LINK_PATTERN, self.html)
link_count = len(links)
self.logDebug('LINKS ', links)
@@ -131,6 +135,11 @@ class MediafireCom(SimpleHoster):
else:
zindex, download_url = links[0]
+ """
+ found = re.search(r'kNO = "(http://.*?)";', self.html)
+ if not found: self.parseError("Download URL")
+ download_url = found.group(1)
+ self.logDebug("DOWNLOAD LINK:", download_url)
self.download(download_url)
diff --git a/module/plugins/hoster/NarodRu.py b/module/plugins/hoster/NarodRu.py
new file mode 100644
index 000000000..335860de9
--- /dev/null
+++ b/module/plugins/hoster/NarodRu.py
@@ -0,0 +1,66 @@
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: zoidberg
+"""
+
+import re
+from random import random
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+
+class NarodRu(SimpleHoster):
+ __name__ = "NarodRu"
+ __type__ = "hoster"
+ __pattern__ = r"http://(www\.)?narod(\.yandex)?\.ru/(disk|start/[0-9]+\.\w+-narod\.yandex\.ru)/(?P<ID>\d+)/.+"
+ __version__ = "0.1"
+ __description__ = """Narod.ru"""
+ __author_name__ = ("zoidberg")
+
+ FILE_NAME_PATTERN = r'<dt class="name">(?:<[^<]*>)*(?P<N>[^<]+)</dt>'
+ FILE_SIZE_PATTERN = r'<dd class="size">(?P<S>\d[^<]*)</dd>'
+ FILE_OFFLINE_PATTERN = r'<title>404</title>|Файл удален с сервиса|Закончился срок хранения файла\.'
+
+ FILE_SIZE_REPLACEMENTS = [(u'КБ', 'KB'), (u'МБ', 'MB'), (u'ГБ', 'GB')]
+ FILE_URL_REPLACEMENTS = [("narod.yandex.ru/", "narod.ru/"), (r"/start/[0-9]+\.\w+-narod\.yandex\.ru/([0-9]{6,15})/\w+/(\w+)", r"/disk/\1/\2")]
+
+ CAPTCHA_PATTERN = r'<number url="(.*?)">(\w+)</number>'
+ DOWNLOAD_LINK_PATTERN = r'<a class="h-link" rel="yandex_bar" href="(.+?)">'
+
+ def handleFree(self):
+ for i in range(5):
+ self.html = self.load('http://narod.ru/disk/getcapchaxml/?rnd=%d' % int(random() * 777))
+ found = re.search(self.CAPTCHA_PATTERN, self.html)
+ if not found: self.parseError('Captcha')
+ post_data = {"action": "sendcapcha"}
+ captcha_url, post_data['key'] = found.groups()
+ post_data['rep'] = self.decryptCaptcha(captcha_url)
+
+ self.html = self.load(self.pyfile.url, post = post_data, decode = True)
+ found = re.search(self.DOWNLOAD_LINK_PATTERN, self.html)
+ if found:
+ url = 'http://narod.ru' + found.group(1)
+ self.correctCaptcha()
+ break
+ elif u'<b class="error-msg"><strong>Ошиблись?</strong>' in self.html:
+ self.invalidCaptcha()
+ else:
+ self.parseError('Download link')
+ else:
+ self.fail("No valid captcha code entered")
+
+ self.logDebug('Download link: ' + url)
+ self.download(url)
+
+getInfo = create_getInfo(NarodRu) \ No newline at end of file
diff --git a/module/plugins/hoster/NetloadIn.py b/module/plugins/hoster/NetloadIn.py
index d768090e8..9310b5c34 100644
--- a/module/plugins/hoster/NetloadIn.py
+++ b/module/plugins/hoster/NetloadIn.py
@@ -24,7 +24,7 @@ def getInfo(urls):
if match:
ids = ids + match.group(1) +";"
- api = getURL(apiurl+ids)
+ api = getURL(apiurl+ids, decode = True)
if api is None or len(api) < 10:
print "Netload prefetch: failed "
@@ -53,14 +53,14 @@ class NetloadIn(Hoster):
__name__ = "NetloadIn"
__type__ = "hoster"
__pattern__ = r"http://.*netload\.in/(?:datei(.*?)(?:\.htm|/)|index.php?id=10&file_id=)"
- __version__ = "0.33"
+ __version__ = "0.40"
__description__ = """Netload.in Download Hoster"""
__author_name__ = ("spoob", "RaNaN", "Gregy")
__author_mail__ = ("spoob@pyload.org", "ranan@pyload.org", "gregy@gregy.cz")
def setup(self):
self.multiDL = False
- if self.account:
+ if self.premium:
self.multiDL = True
self.chunkLimit = -1
self.resumeDownload = True
@@ -77,7 +77,7 @@ class NetloadIn(Hoster):
if self.api_data and self.api_data["filename"]:
self.pyfile.name = self.api_data["filename"]
- if self.account:
+ if self.premium:
self.log.debug("Netload: Use Premium Account")
return True
@@ -96,8 +96,8 @@ class NetloadIn(Hoster):
self.api_data = False
return
- apiurl = "http://netload.in/share/fileinfos2.php"
- src = self.load(apiurl, cookies=False, get={"file_id": match.group(1)}).strip()
+ apiurl = "http://api.netload.in/info.php"
+ src = self.load(apiurl, cookies=False, get={"file_id": match.group(1), "auth": "Zf9SnQh9WiReEsb18akjvQGqT0I830e8", "bz": "1", "md5": "1"}, decode = True).strip()
if not src and n <= 3:
sleep(0.2)
self.download_api_data(n+1)
@@ -105,7 +105,7 @@ class NetloadIn(Hoster):
self.log.debug("Netload: APIDATA: "+src)
self.api_data = {}
- if src and src not in ("unknown file_data", "unknown_server_data"):
+ if src and src not in ("unknown file_data", "unknown_server_data", "No input file specified."):
lines = src.split(";")
self.api_data["exists"] = True
self.api_data["fileid"] = lines[0]
@@ -145,7 +145,11 @@ class NetloadIn(Hoster):
self.offline()
name = re.search(r'class="dl_first_filename">([^<]+)', page, re.MULTILINE)
- self.pyfile.name = name.group(1).strip()
+ # the found filename is not truncated
+ if name:
+ name = name.group(1).strip()
+ if not name.endswith(".."):
+ self.pyfile.name = name
captchawaited = False
for i in range(10):
@@ -160,11 +164,11 @@ class NetloadIn(Hoster):
self.log.debug("Netload: try number %d " % i)
- if re.search(r"(We will prepare your download..)", page) is not None:
+ if ">Your download is being prepared.<" in page:
self.log.debug("Netload: We will prepare your download")
self.final_wait(page)
return True
- if re.search(r"(We had a reqeust with the IP)", page) is not None:
+ if ">An access request has been made from IP address <" in page:
wait = self.get_wait_time(page)
if wait == 0:
self.log.debug("Netload: Wait was 0 setting 30")
@@ -211,7 +215,7 @@ class NetloadIn(Hoster):
def get_file_url(self, page):
try:
- file_url_pattern = r"<a class=\"Orange_Link\" href=\"(http://.+)\".?>Click here"
+ file_url_pattern = r"<a class=\"Orange_Link\" href=\"(http://.+)\".?>Or click here"
attempt = re.search(file_url_pattern, page)
if attempt is not None:
return attempt.group(1)
@@ -232,12 +236,12 @@ class NetloadIn(Hoster):
def proceed(self, url):
self.log.debug("Netload: Downloading..")
- self.download(url)
+ self.download(url, disposition=True)
check = self.checkDownload({"empty": re.compile(r"^$"), "offline": re.compile("The file was deleted")})
if check == "empty":
- self.log.info(_("Downloaded File was empty"))
+ self.logInfo(_("Downloaded File was empty"))
self.retry()
elif check == "offline":
self.offline()
diff --git a/module/plugins/hoster/OneFichierCom.py b/module/plugins/hoster/OneFichierCom.py
index 16401891b..128942b75 100644
--- a/module/plugins/hoster/OneFichierCom.py
+++ b/module/plugins/hoster/OneFichierCom.py
@@ -6,49 +6,44 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
class OneFichierCom(SimpleHoster):
__name__ = "OneFichierCom"
__type__ = "hoster"
- __pattern__ = r"(http://\w+\.((1fichier|d(es)?fichiers|pjointe)\.(com|fr|net|org)|(cjoint|mesfichiers|piecejointe|oi)\.(org|net)|tenvoi\.(com|org|net)|dl4free\.com|alterupload\.com|megadl.fr))"
- __version__ = "0.4"
+ __pattern__ = r"(http://(\w+)\.((1fichier|d(es)?fichiers|pjointe)\.(com|fr|net|org)|(cjoint|mesfichiers|piecejointe|oi)\.(org|net)|tenvoi\.(com|org|net)|dl4free\.com|alterupload\.com|megadl.fr))"
+ __version__ = "0.43"
__description__ = """1fichier.com download hoster"""
__author_name__ = ("fragonib", "the-razer", "zoidberg")
__author_mail__ = ("fragonib[AT]yahoo[DOT]es", "daniel_ AT gmx DOT net", "zoidberg@mujmail.cz")
- FILE_NAME_PATTERN = r'">File name :</th>[\t\r\n ]+<td>(?P<N>.*?)</td>'
- FILE_SIZE_PATTERN = r'<th>File size :</th>\s+<td>(?P<S>[\d\.]*) (?P<U>\w+)</td>'
+ FILE_NAME_PATTERN = r'">File name :</th>\s*<td>(?P<N>[^<]+)</td>'
+ FILE_SIZE_PATTERN = r'<th>File size :</th>\s*<td>(?P<S>[^<]+)</td>'
FILE_OFFLINE_PATTERN = r'The (requested)? file (could not be found|has been deleted)'
FILE_URL_REPLACEMENTS = [(r'(http://[^/]*).*', r'\1/en/')]
DOWNLOAD_LINK_PATTERN = r'<br/>&nbsp;<br/>&nbsp;<br/>&nbsp;\s+<a href="(?P<url>http://.*?)"'
PASSWORD_PROTECTED_TOKEN = "protected by password"
- WAITING_TOKEN = "Please wait a few seconds"
+ WAITING_TOKEN = "Please wait a few seconds"
- def handleFree(self):
+ def process(self, pyfile):
+ found = re.search(self.__pattern__, pyfile.url)
+ file_id = found.group(2)
+ url = "http://%s.%s/en/" % (found.group(2), found.group(3))
+ self.html = self.load(url, decode = True)
+
if self.WAITING_TOKEN in self.html:
- self.waitAndRetry(60)
+ self.waitAndRetry(120)
+
+ self.getFileInfo()
+
+ url, inputs = self.parseHtmlForm('action="http://%s' % file_id)
+ if not url or not inputs:
+ self.parseError("Download link not found")
# Check for protection
- if self.isProtected():
- password = self.getPassword()
- self.logDebug("Submitting password [%s]" % password)
- self.download(url, post={"password" : password})
- else:
- downloadLink = self.getDownloadLink()
- self.download(downloadLink)
+ if "pass" in inputs:
+ inputs['pass'] = self.getPassword()
+
+ self.download(url, post = inputs)
# Check download
self.checkDownloadedFile()
-
- def isProtected(self):
- if self.PASSWORD_PROTECTED_TOKEN in self.html:
- self.logDebug("Links are password protected")
- return True
- return False
-
- def getDownloadLink(self):
- m = re.search(self.DOWNLOAD_LINK_PATTERN, self.html)
- if m is not None:
- url = m.group('url')
- self.logDebug("Got file URL [%s]" % url)
- return url
def checkDownloadedFile(self):
check = self.checkDownload({"wait": self.WAITING_TOKEN})
@@ -60,4 +55,4 @@ class OneFichierCom(SimpleHoster):
self.wait()
self.retry()
-getInfo = create_getInfo(OneFichierCom) \ No newline at end of file
+getInfo = create_getInfo(OneFichierCom)
diff --git a/module/plugins/hoster/OronCom.py b/module/plugins/hoster/OronCom.py
index e659beee5..864b7e96a 100755
--- a/module/plugins/hoster/OronCom.py
+++ b/module/plugins/hoster/OronCom.py
@@ -16,7 +16,7 @@ def getInfo(urls):
result.append((url, 0, 1, url))
continue
- m = re.search(OronCom.FILE_INFO_PATTERN, html)
+ m = re.search(OronCom.FILE_INFO_PATTERN, html, re.MULTILINE)
if m:
name = m.group(1)
size = parseFileSize(m.group(2), m.group(3))
@@ -31,11 +31,11 @@ def getInfo(urls):
class OronCom(Hoster):
__name__ = "OronCom"
__type__ = "hoster"
- __pattern__ = r"http://(?:www\.)?oron.com/(?!folder/)"
- __version__ = "0.14"
- __description__ = "File Hoster: Oron.com"
+ __pattern__ = r"http://(?:www.)?oron.com/(?!folder)\w+"
+ __version__ = "0.16"
+ __description__ = "Oron.com Hoster Plugin"
__author_name__ = ("chrox", "DHMH")
- __author_mail__ = ("chrox@pyload.org", "DHMH@pyload.org")
+ __author_mail__ = ("chrox@pyload.org", "webmaster@pcProfil.de")
FILE_INFO_PATTERN = r'(?:Filename|Dateiname): <b class="f_arial f_14px">(.*?)</b>\s*<br>\s*(?:Größe|File size): ([0-9,\.]+) (Kb|Mb|Gb)'
@@ -50,7 +50,8 @@ class OronCom(Hoster):
#self.load("http://oron.com/?op=change_lang&lang=german")
# already logged in, so the above line shouldn't be necessary
self.html = self.load(self.pyfile.url, ref=False, decode=True).encode("utf-8").replace("\n", "")
- if "File could not be found" in self.html or "Datei nicht gefunden" in self.html:
+ if "File could not be found" in self.html or "Datei nicht gefunden" in self.html or \
+ "This file has been blocked for TOS violation." in self.html:
self.offline()
self.html = self.html.replace("\t", "")
m = re.search(self.FILE_INFO_PATTERN, self.html)
@@ -126,13 +127,13 @@ class OronCom(Hoster):
self.logError("error in parsing site")
def handlePremium(self):
- self.account.getAccountInfo(True)
- self.logDebug("Traffic left: %s" % self.account.formatTrafficleft())
- self.logDebug("File Size: %s" % self.pyfile.formatSize())
+ info = self.account.getAccountInfo(self.user, True)
+ self.logDebug("Traffic left: %s" % info['trafficleft'])
+ self.logDebug("File Size: %d" % int(self.pyfile.size / 1024))
- if int(self.pyfile.size / 1024) > self.account.trafficleft:
+ if int(self.pyfile.size / 1024) > info["trafficleft"]:
self.logInfo(_("Not enough traffic left"))
- self.account.empty()
+ self.account.empty(self.user)
self.fail(_("Traffic exceeded"))
post_url = "http://oron.com/" + self.file_id
@@ -144,4 +145,3 @@ class OronCom(Hoster):
self.html = self.load(post_url, post=post_dict, ref=False, decode=True).encode("utf-8")
link = re.search('href="(.*?)" class="atitle"', self.html).group(1)
self.download(link)
-
diff --git a/module/plugins/hoster/PremiumizeMe.py b/module/plugins/hoster/PremiumizeMe.py
new file mode 100644
index 000000000..4ae59d198
--- /dev/null
+++ b/module/plugins/hoster/PremiumizeMe.py
@@ -0,0 +1,50 @@
+from module.plugins.Hoster import Hoster
+
+from module.common.json_layer import json_loads
+
+class PremiumizeMe(Hoster):
+ __name__ = "PremiumizeMe"
+ __version__ = "0.11"
+ __type__ = "hoster"
+ __description__ = """Premiumize.Me hoster plugin"""
+
+ # Since we want to allow the user to specify the list of hoster to use we let MultiHoster.coreReady create the regex patterns for us using getHosters in our PremiumizeMe hook.
+ __pattern__ = None
+
+ __author_name__ = ("Florian Franzen")
+ __author_mail__ = ("FlorianFranzen@gmail.com")
+
+ def process(self, pyfile):
+ # Check account
+ if not self.account or not self.account.canUse():
+ self.logError(_("Please enter a valid premiumize.me account or deactivate this plugin"))
+ self.fail("No valid premiumize.me account provided")
+
+ # In some cases hostsers do not supply us with a filename at download, so we are going to set a fall back filename (e.g. for freakshare or xfileshare)
+ self.pyfile.name = self.pyfile.name.split('/').pop() # Remove everthing before last slash
+
+ # Correction for automatic assigned filename: Removing html at end if needed
+ suffix_to_remove = ["html", "htm", "php", "php3", "asp", "shtm", "shtml", "cfml", "cfm"]
+ temp = self.pyfile.name.split('.')
+ if temp.pop() in suffix_to_remove:
+ self.pyfile.name = ".".join(temp)
+
+ # Get account data
+ (user, data) = self.account.selectAccount()
+
+ # Get rewritten link using the premiumize.me api v1 (see https://secure.premiumize.me/?show=api)
+ answer = self.load("https://api.premiumize.me/pm-api/v1.php?method=directdownloadlink&params[login]=%s&params[pass]=%s&params[link]=%s" % (user, data['password'], self.pyfile.url))
+ data = json_loads(answer)
+
+ # Check status and decide what to do
+ status = data['status']
+ if status == 200:
+ self.download(data['result']['location'], disposition=True)
+ elif status == 400:
+ self.fail("Invalid link")
+ elif status == 404:
+ self.offline()
+ elif status >= 500:
+ self.tempOffline()
+ else:
+ self.fail(data['statusmessage'])
diff --git a/module/plugins/hoster/PutlockerCom.py b/module/plugins/hoster/PutlockerCom.py
new file mode 100644
index 000000000..8cfcd4d9e
--- /dev/null
+++ b/module/plugins/hoster/PutlockerCom.py
@@ -0,0 +1,126 @@
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: jeix
+"""
+
+import re
+from module.plugins.Hoster import Hoster
+from module.network.RequestFactory import getURL
+
+def getInfo(urls):
+ result = []
+
+ for url in urls:
+
+ html = getURL(url)
+ if re.search(PutlockerCom.PATTERN_OFFLINE, html):
+ result.append((url, 0, 1, url))
+ else:
+ name = re.search(PutlockerCom.PATTERN_FILENAME_1, html)
+ if name is None:
+ name = re.search(PutlockerCom.PATTERN_FILENAME_2, html)
+ if name is None:
+ result.append((url, 0, 1, url))
+ continue
+
+ name = name.group(1)
+
+ # size = re.search(PutlockerCom.PATTERN_FILESIZE, html)
+ # if size is None:
+ # result.append((url, 0, 1, url))
+ # continue
+
+ # size = size.group(1)
+
+ result.append((name, 0, 2, url))
+ yield result
+
+class PutlockerCom(Hoster):
+ __name__ = "PutlockerCom"
+ __type__ = "hoster"
+ __pattern__ = r'http://(www\.)?putlocker\.com/(file|embed)/[A-Z0-9]+'
+ __version__ = "0.2"
+ __description__ = """Putlocker.Com"""
+ __author_name__ = ("jeix")
+
+ PATTERN_OFFLINE = r"This file doesn't exist, or has been removed."
+ PATTERN_FILENAME_1 = "site-content.*?<h1>(.*?)<strong"
+ PATTERN_FILENAME_2 = "<title>(.*?) \|"
+ PATTERN_FILESIZE = "site-content.*?<h1>.*?<strong>\\((.*?)\\)"
+
+
+ def process(self, pyfile):
+
+ self.pyfile = pyfile
+ self.html = self.load(pyfile.url, decode=True)
+
+ if not self._checkOnline():
+ self.offline()
+
+ self.pyfile.name = self._getName()
+
+ self.link = self._getLink()
+ if not self.link.startswith('http://'):
+ self.link = "http://www.putlocker.com" + self.link
+ self.download( self.link )
+
+ def _checkOnline(self):
+ if re.search(self.PATTERN_OFFLINE, self.html):
+ return False
+ else:
+ return True
+
+ def _getName(self):
+ name = re.search(self.PATTERN_FILENAME_1, self.html)
+ if name is None:
+ name = re.search(self.PATTERN_FILENAME_2, self.html)
+ # if name is None:
+ # self.fail("%s: Plugin broken." % self.__name__)
+
+ return name.group(1)
+
+ def _getLink(self):
+ self.hash = re.search("<input type=\"hidden\" value=\"([a-z0-9]+)\" name=\"hash\">", self.html)
+ # if self.hash is None:
+ # self.fail("%s: Plugin broken." % self.__name__)
+
+ self.param = "hash=" + self.hash.group(1) + "&confirm=Continue+as+Free+User"
+ self.html2 = self.load(self.pyfile.url, post=self.param)
+ if ">You have exceeded the daily stream limit for your country\\. You can wait until tomorrow" in self.html2 or "(>This content server has been temporarily disabled for upgrades|Try again soon\\. You can still download it below\\.<)" in self.html2:
+ self.waittime = 2 * 60 * 60
+ self.retry(wait_time=self.waittime, reason="Waiting %s seconds" % self.waittime)
+
+ self.link = re.search("<a href=\"/gopro\\.php\">Tired of ads and waiting\\? Go Pro\\!</a>[\t\n\rn ]+</div>[\t\n\rn ]+<a href=\"(/.*?)\"", self.html2)
+ if self.link is None:
+ self.link = re.search("\"(/get_file\\.php\\?download=[A-Z0-9]+\\&key=[a-z0-9]+)\"", self.html2)
+
+ if self.link is None:
+ self.link = re.search("\"(/get_file\\.php\\?download=[A-Z0-9]+\\&key=[a-z0-9]+&original=1)\"", self.html2)
+
+ if self.link is None:
+ self.link = re.search("playlist: \\'(/get_file\\.php\\?stream=[A-Za-z0-9=]+)\\'", self.html2)
+ if not self.link is None:
+ self.html3 = self.load("http://www.putlocker.com" + self.link.group(1))
+ self.link = re.search("media:content url=\"(http://.*?)\"", self.html3)
+ if self.link is None:
+ self.link = re.search("\"(http://media\\-b\\d+\\.putlocker\\.com/download/\\d+/.*?)\"", self.html3)
+
+ # if link is None:
+ # self.fail("%s: Plugin broken." % self.__name__)
+
+ return self.link.group(1).replace("&amp;", "&")
+
+
diff --git a/module/plugins/hoster/RapidgatorNet.py b/module/plugins/hoster/RapidgatorNet.py
new file mode 100644
index 000000000..678a3d707
--- /dev/null
+++ b/module/plugins/hoster/RapidgatorNet.py
@@ -0,0 +1,181 @@
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: zoidberg
+"""
+
+import re
+from pycurl import HTTPHEADER
+from random import random
+
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+from module.common.json_layer import json_loads
+from module.plugins.ReCaptcha import ReCaptcha
+
+class AdsCaptcha():
+ def __init__(self, plugin):
+ self.plugin = plugin
+
+ def challenge(self, src):
+ js = self.plugin.req.load(src, cookies=True)
+
+ try:
+ challenge = re.search("challenge: '(.*?)',", js).group(1)
+ server = re.search("server: '(.*?)',", js).group(1)
+ except:
+ self.plugin.fail("adscaptcha error")
+ result = self.result(server,challenge)
+
+ return challenge, result
+
+ def result(self, server, challenge):
+ return self.plugin.decryptCaptcha("%sChallenge.aspx" % server, get={"cid": challenge, "dummy": random()}, cookies=True, imgtype="jpg")
+
+class SolveMedia():
+ def __init__(self,plugin):
+ self.plugin = plugin
+
+ def challenge(self, src):
+ html = self.plugin.req.load("http://api.solvemedia.com/papi/challenge.script?k=%s" % src, cookies=True)
+ try:
+ ckey = re.search("ckey:.*?'(.*?)',",html).group(1)
+ html = self.plugin.req.load("http://api.solvemedia.com/papi/_challenge.js?k=%s" % ckey, cookies=True)
+ challenge = re.search('"chid".*?: "(.*?)"',html).group(1)
+ except:
+ self.plugin.fail("solvmedia error")
+ result = self.result(challenge)
+
+ return challenge, result
+
+ def result(self,challenge):
+ return self.plugin.decryptCaptcha("http://api.solvemedia.com/papi/media?c=%s" % challenge,imgtype="gif")
+
+
+class RapidgatorNet(SimpleHoster):
+ __name__ = "RapidgatorNet"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:www\.)?(rapidgator.net)/file/(\d+)"
+ __version__ = "0.06"
+ __description__ = """rapidgator.net"""
+ __author_name__ = ("zoidberg","chrox")
+
+ FILE_INFO_PATTERN = r'Downloading:(\s*<[^>]*>)*\s*(?P<N>.*?)(\s*<[^>]*>)*\s*File size:\s*<strong>(?P<S>.*?)</strong>'
+ FILE_OFFLINE_PATTERN = r'<title>File not found</title>'
+
+ JSVARS_PATTERN = r"\s+var\s*(startTimerUrl|getDownloadUrl|captchaUrl|fid|secs)\s*=\s*'?(.*?)'?;"
+ DOWNLOAD_LINK_PATTERN = r"location.href = '(.*?)'"
+ RECAPTCHA_KEY_PATTERN = r'"http://api.recaptcha.net/challenge?k=(.*?)"'
+ ADSCAPTCHA_SRC_PATTERN = r'(http://api.adscaptcha.com/Get.aspx[^"\']*)'
+ SOLVEMEDIA_PATTERN = r'http:\/\/api\.solvemedia\.com\/papi\/challenge\.script\?k=(.*?)"'
+
+ def handleFree(self):
+ if "You can download files up to 500 MB in free mode" in self.html \
+ or "This file can be downloaded by premium only" in self.html:
+ self.fail("Premium account needed for download")
+
+ self.checkWait()
+
+ jsvars = dict(re.findall(self.JSVARS_PATTERN, self.html))
+ self.logDebug(jsvars)
+
+ self.req.http.lastURL = self.pyfile.url
+ self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"])
+
+ url = "http://rapidgator.net%s?fid=%s" % (jsvars.get('startTimerUrl', '/download/AjaxStartTimer'), jsvars["fid"])
+ jsvars.update(self.getJsonResponse(url))
+
+ self.setWait(int(jsvars.get('secs', 30)) + 1, False)
+ self.wait()
+
+ url = "http://rapidgator.net%s?sid=%s" % (jsvars.get('getDownloadUrl', '/download/AjaxGetDownload'), jsvars["sid"])
+ jsvars.update(self.getJsonResponse(url))
+
+ self.req.http.lastURL = self.pyfile.url
+ self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With:"])
+
+ url = "http://rapidgator.net%s" % jsvars.get('captchaUrl', '/download/captcha')
+ self.html = self.load(url)
+ found = re.search(self.ADSCAPTCHA_SRC_PATTERN, self.html)
+ if found:
+ captcha_key = found.group(1)
+ captcha = AdsCaptcha(self)
+ else:
+ found = re.search(self.RECAPTCHA_KEY_PATTERN, self.html)
+ if found:
+ captcha_key = found.group(1)
+ captcha = ReCaptcha(self)
+
+ else:
+ found = re.search(self.SOLVEMEDIA_PATTERN, self.html)
+ if found:
+ captcha_key = found.group(1)
+ captcha = SolveMedia(self)
+ else:
+ self.parseError("Captcha:"+st)
+ if captcha.__class__.__name__ == "SolveMedia":
+ captcha_prov = "adcopy"
+ else:
+ captcha_prov = captcha.__class__.__name__.lower()
+
+ for i in range(5):
+ self.checkWait()
+ captcha_challenge, captcha_response = captcha.challenge(captcha_key)
+
+ self.html = self.load(url, post={
+ "DownloadCaptchaForm[captcha]": "",
+ "adcopy_challenge": captcha_challenge,
+ "adcopy_response": captcha_response
+ })
+
+ if 'The verification code is incorrect' in self.html:
+ self.invalidCaptcha()
+ else:
+ self.correctCaptcha()
+ break
+ else:
+ self.fail("No valid captcha solution received")
+
+ found = re.search(self.DOWNLOAD_LINK_PATTERN, self.html)
+ if not found:
+ self.parseError("download link")
+ download_url = found.group(1)
+ self.logDebug(download_url)
+ self.download(download_url)
+
+ def checkWait(self):
+ found = re.search(r"(?:Delay between downloads must be not less than|Try again in)\s*(\d+)\s*(hour|min)", self.html)
+ if found:
+ wait_time = int(found.group(1)) * {"hour": 60, "min": 1}[found.group(2)]
+ else:
+ found = re.search(r"You have reached your (daily|hourly) downloads limit", self.html)
+ if found:
+ wait_time = 60
+ else:
+ return
+
+ self.logDebug("Waiting %d minutes" % wait_time)
+ self.setWait(wait_time * 60, True)
+ self.wait()
+ self.retry(max_tries = 24)
+
+ def getJsonResponse(self, url):
+ response = self.load(url, decode = True)
+ if not response.startswith('{'):
+ self.retry()
+ self.logDebug(url, response)
+ return json_loads(response)
+
+getInfo = create_getInfo(RapidgatorNet)
+
diff --git a/module/plugins/hoster/RapidshareCom.py b/module/plugins/hoster/RapidshareCom.py
index a4a72eb53..6aacd684e 100644
--- a/module/plugins/hoster/RapidshareCom.py
+++ b/module/plugins/hoster/RapidshareCom.py
@@ -50,7 +50,7 @@ class RapidshareCom(Hoster):
__name__ = "RapidshareCom"
__type__ = "hoster"
__pattern__ = r"https?://[\w\.]*?rapidshare.com/(?:files/(?P<id>\d*?)/(?P<name>[^?]+)|#!download\|(?:\w+)\|(?P<id_new>\d+)\|(?P<name_new>[^|]+))"
- __version__ = "1.37"
+ __version__ = "1.38"
__description__ = """Rapidshare.com Download Hoster"""
__config__ = [("server", "Cogent;Deutsche Telekom;Level(3);Level(3) #2;GlobalCrossing;Level(3) #3;Teleglobe;GlobalCrossing #2;TeliaSonera #2;Teleglobe #2;TeliaSonera #3;TeliaSonera", "Preferred Server", "None")]
__author_name__ = ("spoob", "RaNaN", "mkaay")
@@ -60,17 +60,14 @@ class RapidshareCom(Hoster):
self.html = None
self.no_download = True
self.api_data = None
- self.multiDL = False
self.offset = 0
self.dl_dict = {}
self.id = None
self.name = None
-
- if self.account:
- self.multiDL = True
- self.chunkLimit = -1
- self.resumeDownload = True
+
+ self.chunkLimit = -1 if self.premium else 1
+ self.multiDL = self.resumeDownload = self.premium
def process(self, pyfile):
self.url = self.pyfile.url
@@ -90,7 +87,7 @@ class RapidshareCom(Hoster):
if self.api_data["status"] == "1":
self.pyfile.name = self.get_file_name()
- if self.account:
+ if self.premium:
self.handlePremium()
else:
self.handleFree()
@@ -225,5 +222,4 @@ class RapidshareCom(Hoster):
def get_file_name(self):
if self.api_data["filename"]:
return self.api_data["filename"]
- return self.url.split("/")[-1]
-
+ return self.url.split("/")[-1] \ No newline at end of file
diff --git a/module/plugins/hoster/RarefileNet.py b/module/plugins/hoster/RarefileNet.py
new file mode 100644
index 000000000..8339d40eb
--- /dev/null
+++ b/module/plugins/hoster/RarefileNet.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+import re
+from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo
+from module.utils import html_unescape
+
+class RarefileNet(XFileSharingPro):
+ __name__ = "RarefileNet"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:\w*\.)*rarefile.net/\w{12}"
+ __version__ = "0.01"
+ __description__ = """Rarefile.net hoster plugin"""
+ __author_name__ = ("zoidberg")
+ __author_mail__ = ("zoidberg@mujmail.cz")
+
+ FILE_NAME_PATTERN = r'<td><font color="red">(?P<N>.*?)</font></td>'
+ FILE_SIZE_PATTERN = r'<td>Size : (?P<S>.+?)&nbsp;'
+
+ 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) \ No newline at end of file
diff --git a/module/plugins/hoster/RealdebridCom.py b/module/plugins/hoster/RealdebridCom.py
index 46ac51c82..3c796232e 100644
--- a/module/plugins/hoster/RealdebridCom.py
+++ b/module/plugins/hoster/RealdebridCom.py
@@ -1,86 +1,88 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-import re
-from time import time
-from urllib import quote, unquote
-from random import randrange
-
-from module.utils import encode, parseFileSize
-from module.common.json_layer import json_loads
-from module.plugins.Hoster import Hoster
-
-class RealdebridCom(Hoster):
- __version__ = "0.43"
- __pattern__ = r"https?://.*real-debrid\..*"
- __description__ = """Real-Debrid.com hoster plugin"""
- __config__ = [("https", "bool", _("Enable HTTPS"), False)]
-
- __author_name__ = ("Devirex, Hazzard")
- __author_mail__ = ("naibaf_11@yahoo.de")
-
- def getFilename(self, url):
- try:
- name = unquote(url.rsplit("/", 1)[1])
- except IndexError:
- name = "Unknown_Filename..."
- if name.endswith("..."): #incomplete filename, append random stuff
- name += "%s.tmp" % randrange(100,999)
- return name
-
- def init(self):
- self.tries = 0
- self.chunkLimit = 3
- self.resumeDownload = True
-
-
- def process(self, pyfile):
- if not self.account:
- self.logError(_("Please enter your Real-debrid account or deactivate this plugin"))
- self.fail("No Real-debrid account provided")
-
- self.log.debug("Real-Debrid: Old URL: %s" % pyfile.url)
- if re.match(self.__pattern__, pyfile.url):
- new_url = pyfile.url
- else:
- password = self.getPassword().splitlines()
- if not password: password = ""
- else: password = password[0]
-
- url = "http://real-debrid.com/ajax/unrestrict.php?lang=en&link=%s&password=%s&time=%s" % (quote(encode(pyfile.url), ""), password, int(time()*1000))
- page = self.load(url)
- data = json_loads(page)
-
- self.logDebug("Returned Data: %s" % data)
-
- if data["error"] != 0:
- if data["message"] == "Your file is unavailable on the hoster.":
- self.offline()
- else:
- self.logWarning(data["message"])
- self.tempOffline()
- else:
- self.pyfile.name = data["file_name"]
- self.pyfile.size = parseFileSize(data["file_size"])
- new_url = data['generated_links'].split('|')[-1]
-
- if self.getConfig("https"):
- new_url = new_url.replace("http://", "https://")
- else:
- new_url = new_url.replace("https://", "http://")
-
- self.log.debug("Real-Debrid: New URL: %s" % new_url)
-
- if pyfile.name.startswith("http") or pyfile.name.startswith("Unknown"):
- #only use when name wasnt already set
- pyfile.name = self.getFilename(new_url)
-
- self.download(new_url, disposition=True)
-
- check = self.checkDownload(
- {"error": "<title>An error occured while processing your request</title>"})
-
- if check == "error":
- #usual this download can safely be retried
- self.retry(reason="An error occured while generating link.", wait_time=60)
-
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import re
+from time import time
+from urllib import quote, unquote
+from random import randrange
+
+from module.utils import parseFileSize, remove_chars
+from module.common.json_layer import json_loads
+from module.plugins.Hoster import Hoster
+
+class RealdebridCom(Hoster):
+ __name__ = "RealdebridCom"
+ __version__ = "0.49"
+ __type__ = "hoster"
+
+ __pattern__ = r"https?://.*real-debrid\..*"
+ __description__ = """Real-Debrid.com hoster plugin"""
+ __author_name__ = ("Devirex, Hazzard")
+ __author_mail__ = ("naibaf_11@yahoo.de")
+
+ def getFilename(self, url):
+ try:
+ name = unquote(url.rsplit("/", 1)[1])
+ except IndexError:
+ name = "Unknown_Filename..."
+ if not name or name.endswith(".."): #incomplete filename, append random stuff
+ name += "%s.tmp" % randrange(100,999)
+ return name
+
+ def init(self):
+ self.tries = 0
+ self.chunkLimit = 3
+ self.resumeDownload = True
+
+
+ def process(self, pyfile):
+ if not self.account:
+ self.logError(_("Please enter your Real-debrid account or deactivate this plugin"))
+ self.fail("No Real-debrid account provided")
+
+ self.log.debug("Real-Debrid: Old URL: %s" % pyfile.url)
+ if re.match(self.__pattern__, pyfile.url):
+ new_url = pyfile.url
+ else:
+ password = self.getPassword().splitlines()
+ if not password: password = ""
+ else: password = password[0]
+
+ url = "http://real-debrid.com/ajax/unrestrict.php?lang=en&link=%s&password=%s&time=%s" % (quote(pyfile.url, ""), password, int(time()*1000))
+ page = self.load(url)
+ data = json_loads(page)
+
+ self.logDebug("Returned Data: %s" % data)
+
+ if data["error"] != 0:
+ if data["message"] == "Your file is unavailable on the hoster.":
+ self.offline()
+ else:
+ self.logWarning(data["message"])
+ self.tempOffline()
+ else:
+ if self.pyfile.name is not None and self.pyfile.name.endswith('.tmp') and data["file_name"]:
+ self.pyfile.name = data["file_name"]
+ self.pyfile.size = parseFileSize(data["file_size"])
+ new_url = data['generated_links'][0][-1]
+
+ if self.getConfig("https"):
+ new_url = new_url.replace("http://", "https://")
+ else:
+ new_url = new_url.replace("https://", "http://")
+
+ self.log.debug("Real-Debrid: New URL: %s" % new_url)
+
+ if pyfile.name.startswith("http") or pyfile.name.startswith("Unknown") or pyfile.name.endswith('..'):
+ #only use when name wasnt already set
+ pyfile.name = self.getFilename(new_url)
+
+ self.download(new_url, disposition=True)
+
+ check = self.checkDownload(
+ {"error": "<title>An error occured while processing your request</title>"})
+
+ if check == "error":
+ #usual this download can safely be retried
+ self.retry(reason="An error occured while generating link.", wait_time=60)
+
diff --git a/module/plugins/hoster/RyushareCom.py b/module/plugins/hoster/RyushareCom.py
new file mode 100644
index 000000000..b3d7bafc6
--- /dev/null
+++ b/module/plugins/hoster/RyushareCom.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo
+
+class RyushareCom(XFileSharingPro):
+ __name__ = "RyushareCom"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:\w*\.)*?ryushare.com/\w{12}"
+ __version__ = "0.02"
+ __description__ = """ryushare.com hoster plugin"""
+ __author_name__ = ("zoidberg")
+ __author_mail__ = ("zoidberg@mujmail.cz")
+
+ HOSTER_NAME = "ryushare.com"
+
+ def setup(self):
+ self.resumeDownload = self.multiDL = self.premium
+
+getInfo = create_getInfo(RyushareCom) \ No newline at end of file
diff --git a/module/plugins/hoster/Share4webCom.py b/module/plugins/hoster/Share4webCom.py
new file mode 100644
index 000000000..ef9c2acf8
--- /dev/null
+++ b/module/plugins/hoster/Share4webCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from module.plugins.hoster.UnibytesCom import UnibytesCom
+from module.plugins.internal.SimpleHoster import create_getInfo
+
+class Share4webCom(UnibytesCom):
+ __name__ = "Share4webCom"
+ __type__ = "hoster"
+ __pattern__ = r"http://(www\.)?share4web\.com/get/\w+"
+ __version__ = "0.1"
+ __description__ = """Share4web.com"""
+ __author_name__ = ("zoidberg")
+
+ DOMAIN = 'http://www.share4web.com'
+
+getInfo = create_getInfo(UnibytesCom) \ No newline at end of file
diff --git a/module/plugins/hoster/ShareRapidCom.py b/module/plugins/hoster/ShareRapidCom.py
index b9ce61e18..4a25d4027 100644
--- a/module/plugins/hoster/ShareRapidCom.py
+++ b/module/plugins/hoster/ShareRapidCom.py
@@ -3,66 +3,102 @@
import re
from pycurl import HTTPHEADER
-from module.network.RequestFactory import getRequest
+from module.network.RequestFactory import getRequest, getURL
from module.network.HTTPRequest import BadHeader
from module.plugins.internal.SimpleHoster import SimpleHoster, parseFileInfo
+from module.common.json_layer import json_loads
+def checkFile(url):
+ info = {"name" : url, "size" : 0, "status" : 3}
+
+ response = getURL("http://share-rapid.com/checkfiles.php", post = {"files": url}, decode = True)
+ info = json_loads(response)
+
+ if "error" in info:
+ if info['error'] == False:
+ info['name'] = info['filename']
+ info['status'] = 2
+ elif info['msg'] == "Not found":
+ info['status'] = 1 #offline
+ elif info['msg'] == "Service Unavailable":
+ info['status'] = 6 #temp.offline
+
+ return info
+
def getInfo(urls):
- file_info = []
for url in urls:
- h = getRequest()
- try:
- h.c.setopt(HTTPHEADER, ["Accept: text/html"])
- html = h.load(url, cookies = True, decode = True)
- file_info = parseFileInfo(ShareRapidCom, url, html)
- finally:
- h.close()
- yield file_info
+ info = checkFile(url)
+ if "filename" in info:
+ yield info['name'], info['size'], info['status'], url
+ else:
+ file_info = (url, 0, 3, url)
+ h = getRequest()
+ try:
+ h.c.setopt(HTTPHEADER, ["Accept: text/html"])
+ html = h.load(url, cookies = True, decode = True)
+ file_info = parseFileInfo(ShareRapidCom, url, html)
+ finally:
+ h.close()
+ yield file_info
class ShareRapidCom(SimpleHoster):
__name__ = "ShareRapidCom"
__type__ = "hoster"
- __pattern__ = r"http://(?:www\.)?((share(-?rapid\.(biz|com|cz|info|eu|net|org|pl|sk)|-(central|credit|free|net)\.cz|-ms\.net)|(s-?rapid|rapids)\.(cz|sk))|(e-stahuj|mediatack|premium-rapidshare|rapidshare-premium|qiuck)\.cz|kadzet\.com|stahuj-zdarma\.eu|strelci\.net|universal-share\.com)/(stahuj/.+)"
- __version__ = "0.47"
+ __pattern__ = r"http://(?:www\.)?((share(-?rapid\.(biz|com|cz|info|eu|net|org|pl|sk)|-(central|credit|free|net)\.cz|-ms\.net)|(s-?rapid|rapids)\.(cz|sk))|(e-stahuj|mediatack|premium-rapidshare|rapidshare-premium|qiuck)\.cz|kadzet\.com|stahuj-zdarma\.eu|strelci\.net|universal-share\.com)/stahuj/(.+)"
+ __version__ = "0.50"
__description__ = """Share-rapid.com plugin - premium only"""
__author_name__ = ("MikyWoW", "zoidberg")
__author_mail__ = ("MikyWoW@seznam.cz", "zoidberg@mujmail.cz")
FILE_NAME_PATTERN = r'<h1[^>]*><span[^>]*>(?:<a[^>]*>)?(?P<N>[^<]+)'
FILE_SIZE_PATTERN = r'<td class="i">Velikost:</td>\s*<td class="h"><strong>\s*(?P<S>[0-9.]+) (?P<U>[kKMG])i?B</strong></td>'
+ FILE_OFFLINE_PATTERN = ur'Nastala chyba 404|Soubor byl smazán'
+
DOWNLOAD_URL_PATTERN = r'<a href="([^"]+)" title="Stahnout">([^<]+)</a>'
ERR_LOGIN_PATTERN = ur'<div class="error_div"><strong>Stahování je přístupné pouze přihlášeným uživatelům'
ERR_CREDIT_PATTERN = ur'<div class="error_div"><strong>Stahování zdarma je možné jen přes náš'
- FILE_OFFLINE_PATTERN = ur'Nastala chyba 404|Soubor byl smazán'
def setup(self):
self.chunkLimit = 1
self.resumeDownload = True
def process(self, pyfile):
- if not self.account: self.fail("User not logged in")
- url = "http://share-rapid.com/" + re.search(self.__pattern__, pyfile.url).groups()[-1]
- self.logDebug("URL: " + url)
-
+ if not self.account: self.fail("User not logged in")
+
+ self.info = checkFile(pyfile.url)
+ self.logDebug(self.info)
+
+ pyfile.status = self.info['status']
+
+ if pyfile.status == 2:
+ pyfile.name = self.info['name']
+ pyfile.size = self.info['size']
+ elif pyfile.status == 1:
+ self.offline()
+ elif pyfile.status == 6:
+ self.tempOffline()
+ else:
+ self.fail("Unexpected file status")
+
+ url = "http://share-rapid.com/stahuj/%s" % self.info['filepath']
try:
self.html = self.load(url, decode=True)
except BadHeader, e:
self.account.relogin(self.user)
self.retry(3, 0, str(e))
-
- self.getFileInfo()
found = re.search(self.DOWNLOAD_URL_PATTERN, self.html)
if found is not None:
- link, pyfile.name = found.groups()
+ link = found.group(1)
self.logDebug("Premium link: %s" % link)
+
+ self.check_data = {"size": pyfile.size}
self.download(link)
else:
- self.logError("Download URL not found")
if re.search(self.ERR_LOGIN_PATTERN, self.html):
- self.relogin()
+ self.relogin(self.user)
self.retry(3,0,"User login failed")
elif re.search(self.ERR_CREDIT_PATTERN, self.html):
self.fail("Not enough credit left")
else:
- self.fail("Download link not found") \ No newline at end of file
+ self.fail("Download link not found") \ No newline at end of file
diff --git a/module/plugins/hoster/ShareonlineBiz.py b/module/plugins/hoster/ShareonlineBiz.py
index 2d1fc8d85..b40cd51dd 100644
--- a/module/plugins/hoster/ShareonlineBiz.py
+++ b/module/plugins/hoster/ShareonlineBiz.py
@@ -5,10 +5,12 @@ import re
from base64 import b64decode
import hashlib
import random
-from time import sleep
+from time import time, sleep
-from module.plugins.Hoster import Hoster, chunks
+from module.plugins.Hoster import Hoster
from module.network.RequestFactory import getURL
+from module.plugins.Plugin import chunks
+from module.plugins.ReCaptcha import ReCaptcha as _ReCaptcha
def getInfo(urls):
api_url_base = "http://api.share-online.biz/linkcheck.php"
@@ -32,14 +34,21 @@ def getInfo(urls):
result.append((fields[2], int(fields[3]), status, chunk[i]))
yield result
+#suppress ocr plugin
+class ReCaptcha(_ReCaptcha):
+ def result(self, server, challenge):
+ return self.plugin.decryptCaptcha("%simage"%server, get={"c":challenge}, cookies=True, forceUser=True, imgtype="jpg")
+
class ShareonlineBiz(Hoster):
__name__ = "ShareonlineBiz"
__type__ = "hoster"
__pattern__ = r"http://[\w\.]*?(share\-online\.biz|egoshare\.com)/(download.php\?id\=|dl/)[\w]+"
- __version__ = "0.22"
+ __version__ = "0.33"
__description__ = """Shareonline.biz Download Hoster"""
- __author_name__ = ("spoob", "mkaay")
- __author_mail__ = ("spoob@pyload.org", "mkaay@mkaay.de")
+ __author_name__ = ("spoob", "mkaay", "zoidberg")
+ __author_mail__ = ("spoob@pyload.org", "mkaay@mkaay.de", "zoidberg@mujmail.cz")
+
+ ERROR_INFO_PATTERN = r'<p class="b">Information:</p>\s*<div>\s*<strong>(.*?)</strong>'
def setup(self):
# range request not working?
@@ -48,21 +57,29 @@ class ShareonlineBiz(Hoster):
self.file_id = re.search(r"(id\=|/dl/)([a-zA-Z0-9]+)", self.pyfile.url).group(2)
self.pyfile.url = "http://www.share-online.biz/dl/" + self.file_id
- self.multiDL = False
- self.chunkLimit = 1
- if self.premium:
- self.multiDL = True
-
- def process(self, pyfile):
- self.downloadAPIData()
- pyfile.name = self.api_data["filename"]
- pyfile.sync()
+ self.resumeDownload = self.multiDL = self.premium
+ #self.chunkLimit = 1
+ self.check_data = None
+
+ def process(self, pyfile):
if self.premium:
self.handleAPIPremium()
- #self.handleWebsitePremium()
+ #web-download fallback removed - didn't work anyway
else:
self.handleFree()
+
+ """
+ check = self.checkDownload({"failure": re.compile(self.ERROR_INFO_PATTERN)})
+ if check == "failure":
+ try:
+ self.retry(reason = self.lastCheck.group(1).decode("utf8"))
+ except:
+ self.retry(reason = "Unknown error")
+ """
+
+ if self.api_data:
+ self.check_data = {"size": int(self.api_data['size']), "md5": self.api_data['md5']}
def downloadAPIData(self):
api_url_base = "http://api.share-online.biz/linkcheck.php?md5=1"
@@ -76,101 +93,98 @@ class ShareonlineBiz(Hoster):
self.offline()
self.api_data["filename"] = fields[2]
self.api_data["size"] = fields[3] # in bytes
- self.api_data["checksum"] = fields[4].strip().lower().replace("\n\n", "") # md5
+ self.api_data["md5"] = fields[4].strip().lower().replace("\n\n", "") # md5
- def handleFree(self):
- self.resumeDownload = False
+ def handleFree(self):
+ self.downloadAPIData()
+ self.pyfile.name = self.api_data["filename"]
+ self.pyfile.size = int(self.api_data["size"])
- self.html = self.load(self.pyfile.url) #refer, stuff
- self.html = self.load("%s/free/" % self.pyfile.url, post={"dl_free":"1", "choice": "free"})
- if re.search(r"/failure/full/1", self.req.lastEffectiveURL):
- self.setWait(120)
- self.log.info("%s: no free slots, waiting 120 seconds" % self.__name__)
- self.wait()
- self.retry(max_tries=60)
+ self.html = self.load(self.pyfile.url, cookies = True) #refer, stuff
+ self.setWait(3)
+ self.wait()
+
+ self.html = self.load("%s/free/" % self.pyfile.url, post={"dl_free":"1", "choice": "free"}, decode = True)
+ self.checkErrors()
- if "Captcha number error or expired" in self.html:
- captcha = self.decryptCaptcha("http://www.share-online.biz/captcha.php", get={"rand":"0.%s" % random.randint(10**15,10**16)})
+ found = re.search(r'var wait=(\d+);', self.html)
- self.log.debug("%s Captcha: %s" % (self.__name__, captcha))
- sleep(3)
-
- self.html = self.load(self.pyfile.url, post={"captchacode": captcha})
+ recaptcha = ReCaptcha(self)
+ for i in range(5):
+ challenge, response = recaptcha.challenge("6LdatrsSAAAAAHZrB70txiV5p-8Iv8BtVxlTtjKX")
+ self.setWait(int(found.group(1)) if found else 30)
+ response = self.load("%s/free/captcha/%d" % (self.pyfile.url, int(time() * 1000)), post = {
+ 'dl_free': '1',
+ 'recaptcha_challenge_field': challenge,
+ 'recaptcha_response_field': response})
- if r"Der Download ist Ihnen zu langsam" not in self.html and r"The download is too slow for you" not in self.html:
- self.fail("Plugin defect. Save dumps and report.")
-
- if "Kein weiterer Download-Thread möglich!" in self.html: #TODO corresponding translation
- self.retry(wait_time=30, reason=_("Parallel download issue"))
+ if not response == '0':
+ break
- m = re.search("var wait=(\d+);", self.html[1])
- wait_time = int(m.group(1)) if m else 30
- self.setWait(wait_time)
- self.log.debug("%s: Waiting %d seconds." % (self.__name__, wait_time))
- self.wait()
+ else: self.fail("No valid captcha solution received")
- file_url_pattern = r'var\sdl="(.*?)"'
- download_url = b64decode(re.search(file_url_pattern, self.html).group(1))
+ download_url = response.decode("base64")
+ self.logDebug(download_url)
+ if not download_url.startswith("http://"):
+ self.parseError("download url")
+ self.wait()
self.download(download_url)
-
- check = self.checkDownload({"invalid" : "Dieses Download-Ticket ist ungültig!",
- "error" : "Es ist ein unbekannter Fehler aufgetreten"})
- if check == "invalid":
- self.retry(reason=_("Invalid download ticket"))
- elif check == "error":
- self.fail(reason=_("ShareOnline internal problems"))
-
- def handleAPIPremium(self): #should be working better
- self.resumeDownload = True
-
- info = self.account.getUserAPI(self.req)
- if info["dl"].lower() == "not_available":
- self.fail("DL API error")
- self.req.cj.setCookie("share-online.biz", "dl", info["dl"])
-
-
+ def checkErrors(self):
+ found = re.search(r"/failure/(.*?)/1", self.req.lastEffectiveURL)
+ if found:
+ err = found.group(1)
+ found = re.search(self.ERROR_INFO_PATTERN, self.html)
+ msg = found.group(1) if found else ""
+ self.logError(err, msg or "Unknown error occurred")
+
+ if err in ('freelimit', 'size', 'proxy'):
+ self.fail(msg or "Premium account needed")
+ if err in ('invalid'):
+ self.fail(msg or "File not available")
+ elif err in ('server'):
+ self.setWait(600, False)
+ elif err in ('expired'):
+ self.setWait(30, False)
+ else:
+ self.setWait(300, True)
+
+ self.wait()
+ self.retry(max_tries=25, reason = msg)
+
+ def handleAPIPremium(self): #should be working better
+ self.account.getAccountInfo(self.user, True)
src = self.load("http://api.share-online.biz/account.php?username=%s&password=%s&act=download&lid=%s" % (self.user, self.account.accounts[self.user]["password"], self.file_id), post={})
- dlinfo = {}
+ self.api_data = dlinfo = {}
for line in src.splitlines():
key, value = line.split(": ")
dlinfo[key.lower()] = value
- if not dlinfo["status"].lower() == "online":
+ self.logDebug(dlinfo)
+ if not dlinfo["status"] == "online":
self.offline()
+ self.pyfile.name = dlinfo["name"]
+ self.pyfile.size = int(dlinfo["size"])
+
dlLink = dlinfo["url"]
- if dlLink.startswith("/_dl.php"):
- self.log.debug("got invalid downloadlink, falling back")
- self.handleWebsitePremium()
+ if dlLink == "server_under_maintenance":
+ self.tempoffline()
else:
self.download(dlLink)
- def handleWebsitePremium(self): #seems to be buggy
- self.resumeDownload = False
-
- self.html = self.load(self.pyfile.url)
- if r"Die Nummer ist leider nicht richtig oder ausgelaufen!" in self.html:
- self.retry()
-
- try:
- download_url = re.search('loadfilelink\.decode\("(.*?)"\);', self.html, re.S).group(1)
- except:
- self.fail("Session issue")
-
- self.download(download_url)
-
def checksum(self, local_file):
- if self.api_data and self.api_data["checksum"]:
+ if self.api_data and "md5" in self.api_data and self.api_data["md5"]:
h = hashlib.md5()
f = open(local_file, "rb")
h.update(f.read())
f.close()
hexd = h.hexdigest()
- if hexd == self.api_data["checksum"]:
+ if hexd == self.api_data["md5"]:
return True, 0
else:
return False, 1
else:
+ self.logWarning("MD5 checksum missing")
return True, 5
diff --git a/module/plugins/hoster/ShragleCom.py b/module/plugins/hoster/ShragleCom.py
index 9ebf4917b..8fe05a2b9 100644
--- a/module/plugins/hoster/ShragleCom.py
+++ b/module/plugins/hoster/ShragleCom.py
@@ -2,84 +2,105 @@
# -*- coding: utf-8 -*-
import re
-import time
+from pycurl import FOLLOWLOCATION
from module.plugins.Hoster import Hoster
+from module.plugins.internal.SimpleHoster import parseHtmlForm
+from module.plugins.ReCaptcha import ReCaptcha
+from module.network.RequestFactory import getURL
+
+API_KEY = "078e5ca290d728fd874121030efb4a0d"
+
+def parseFileInfo(self, url):
+ file_id = re.match(self.__pattern__, url).group('ID')
+
+ data = getURL(
+ "http://www.cloudnator.com/api.php?key=%s&action=getStatus&fileID=%s" % (API_KEY, file_id),
+ decode = True
+ ).split()
+
+ if len(data) == 4:
+ name, size, md5, status = data
+ size = int(size)
+
+ if hasattr(self, "check_data"):
+ self.checkdata = {"size": size, "md5": md5}
+
+ return name, size, 2 if status == "0" else 1, url
+ else:
+ return url, 0, 1, url
+
+def getInfo(urls):
+ for url in urls:
+ file_info = parseFileInfo(plugin, url)
+ yield file_info
class ShragleCom(Hoster):
__name__ = "ShragleCom"
__type__ = "hoster"
- __pattern__ = r"http://(?:www.)?shragle.com/files/"
- __version__ = "0.1"
- __description__ = """Shragle Download PLugin"""
- __author_name__ = ("RaNaN")
- __author_mail__ = ("RaNaN@pyload.org")
+ __pattern__ = r"http://(?:www.)?(cloudnator|shragle).com/files/(?P<ID>.*?)/"
+ __version__ = "0.20"
+ __description__ = """Cloudnator.com (Shragle.com) Download PLugin"""
+ __author_name__ = ("RaNaN", "zoidberg")
+ __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz")
def setup(self):
self.html = None
self.multiDL = False
+ self.check_data = None
def process(self, pyfile):
- self.pyfile = pyfile
-
- if not self.file_exists():
+ #get file status and info
+ self.pyfile.name, self.pyfile.size, status = parseFileInfo(self, pyfile.url)[:3]
+ if status != 2:
self.offline()
-
- self.pyfile.name = self.get_file_name()
- self.setWait(self.get_waiting_time())
- self.wait()
+ self.handleFree()
- self.proceed(self.get_file_url())
-
- def get_waiting_time(self):
- if self.html is None:
- self.download_html()
-
- timestring = re.search('\s*var\sdownloadWait\s=\s(\d*);', self.html)
- if timestring:
- return int(timestring.group(1))
- else:
- return 10
-
- def download_html(self):
+ def handleFree(self):
self.html = self.load(self.pyfile.url)
-
- def get_file_url(self):
- """ returns the absolute downloadable filepath
- """
- if self.html is None:
- self.download_html()
-
- self.fileID = re.search(r'name="fileID"\svalue="(.*?)"', self.html).group(1)
- self.dlSession = re.search(r'name="dlSession"\svalue="(.*?)"', self.html).group(1)
- self.userID = re.search(r'name="userID"\svalue="(.*?)"', self.html).group(1)
- self.password = re.search(r'name="password"\svalue="(.*?)"', self.html).group(1)
- self.lang = re.search(r'name="lang"\svalue="(.*?)"', self.html).group(1)
- return re.search(r'id="download"\saction="(.*?)"', self.html).group(1)
-
- def get_file_name(self):
- if self.html is None:
- self.download_html()
-
- #file_name_pattern = r'You want to download \xc2\xbb<strong>(.*?)</strong>\xc2\xab'
- file_name_pattern = r'<h2 class="colorgrey center" style="overflow:hidden;width:1000px;"> (.*)<br /><span style="font-size:12px;font-weight:normal; width:100px;"> ([\d\.]*) MB</span></h2>'
- res = re.search(file_name_pattern, self.html)
- if res:
- return res.group(1)
- else:
- self.fail("filename cant be extracted")
-
- def file_exists(self):
- """ returns True or False
- """
- if self.html is None:
- self.download_html()
-
- if re.search(r"html", self.html) is None:
- return False
+
+ #get wait time
+ found = re.search('\s*var\sdownloadWait\s=\s(\d+);', self.html)
+ self.setWait(int(found.group(1)) if found else 30)
+
+ #parse download form
+ action, inputs = parseHtmlForm('id="download', self.html)
+
+ #solve captcha
+ found = re.search('recaptcha/api/(?:challenge|noscript)?k=(.+?)', self.html)
+ captcha_key = found.group(1) if found else "6LdEFb0SAAAAAAwM70vnYo2AkiVkCx-xmfniatHz"
+
+ recaptcha = ReCaptcha(self)
+
+ inputs['recaptcha_challenge_field'], inputs['recaptcha_response_field'] = recaptcha.challenge(captcha_key)
+ self.wait()
+
+ #validate
+ self.req.http.c.setopt(FOLLOWLOCATION, 0)
+ self.html = self.load(action, post = inputs)
+
+ found = re.search(r"Location\s*:\s*(\S*)", self.req.http.header, re.I)
+ if found:
+ self.correctCaptcha()
+ download_url = found.group(1)
else:
- return True
-
- def proceed(self, url):
- self.download(url, post={'fileID': self.fileID, 'dlSession': self.dlSession, 'userID': self.userID, 'password': self.password, 'lang': self.lang})
+ if "Sicherheitscode falsch" in self.html:
+ self.invalidCaptcha()
+ self.retry(max_tries = 5, reason = "Invalid captcha")
+ else:
+ self.fail("Invalid session")
+
+ #download
+ self.req.http.c.setopt(FOLLOWLOCATION, 1)
+ self.download(download_url)
+
+ check = self.checkDownload({
+ "ip_blocked": re.compile(r'<div class="error".*IP.*loading')
+ })
+ if check == "ip_blocked":
+ self.setWait(1800, True)
+ self.wait()
+ self.retry()
+
+ \ No newline at end of file
diff --git a/module/plugins/hoster/StahnuTo.py b/module/plugins/hoster/StahnuTo.py
index a78615dba..354a99b1a 100644
--- a/module/plugins/hoster/StahnuTo.py
+++ b/module/plugins/hoster/StahnuTo.py
@@ -32,29 +32,32 @@ def getInfo(urls):
class StahnuTo(SimpleHoster):
__name__ = "StahnuTo"
__type__ = "hoster"
- __pattern__ = r"http://(\w*\.)?stahnu.to/(files/get/|.*\?file=)([^/]+).*"
- __version__ = "0.12"
+ __pattern__ = r"http://(?:\w*\.)?stahnu.to/(?:files/get/|.*\?file=)(?P<ID>[^/]+).*"
+ __version__ = "0.14"
__description__ = """stahnu.to"""
__author_name__ = ("zoidberg")
- FILE_NAME_PATTERN = r"<div class='nadpis-01'><h2>(?<N>[^<]+)</h2></div>"
- FILE_SIZE_PATTERN = r'<td>Velikost souboru<br /><span>(?<S>[^<]+)\s*(?<U>[kKMG])i?[Bb]</span></td>'
+ FILE_NAME_PATTERN = r"<td colspan='2'>N&aacute;zev souboru<br /><span>(?P<N>[^<]+)</span>"
+ FILE_SIZE_PATTERN = r'<td>Velikost souboru<br /><span>(?P<S>[^<]+)\s*(?P<U>[kKMG])i?[Bb]</span></td>'
FILE_OFFLINE_PATTERN = r'<!-- Obsah - start -->\s*<!-- Obsah - end -->'
- #FILE_OFFLINE_PATTERN = r'<h2 align="center">Tento soubor neexistuje nebo byl odstran&#283;n! </h2>'
- CAPTCHA_PATTERN = r'<img src="captcha/captcha.php" id="captcha" /></td>'
def setup(self):
self.multiDL = True
def process(self, pyfile):
+ if not self.account:
+ self.fail("Please enter your stahnu.to account")
+
found = re.search(self.__pattern__, pyfile.url)
- file_id = found.group(3)
+ file_id = found.group(1)
- self.html = self.load("http://stahnu.to/?file=" + file_id, decode=True)
+ self.html = self.load("http://www.stahnu.to/getfile.php?file=%s" % file_id, decode=True)
self.getFileInfo()
+
+ if "K sta&#382;en&iacute; souboru se mus&iacute;te <strong>zdarma</strong> p&#345;ihl&aacute;sit!" in self.html:
+ self.account.relogin(self.user)
+ self.retry()
- self.download("http://stahnu.to/files/gen/" + file_id, post={
- "file": file_id,
- "user": "Anonym",
- "commenttext": ""
+ self.download("http://www.stahnu.to/files/gen/" + file_id, post={
+ "downloadbutton": u"STÁHNOUT"
})
diff --git a/module/plugins/hoster/TurbobitNet.py b/module/plugins/hoster/TurbobitNet.py
new file mode 100644
index 000000000..b3b01c92b
--- /dev/null
+++ b/module/plugins/hoster/TurbobitNet.py
@@ -0,0 +1,169 @@
+# -*- coding: utf-8 -*-
+"""
+ Copyright (C) 2012 pyLoad team
+ Copyright (C) 2012 JD-Team support@jdownloader.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: zoidberg
+"""
+
+import re
+import random
+from urllib import quote
+from binascii import hexlify, unhexlify
+from Crypto.Cipher import ARC4
+
+from module.network.RequestFactory import getURL
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, timestamp
+from module.plugins.ReCaptcha import ReCaptcha
+
+from pycurl import HTTPHEADER
+
+class TurbobitNet(SimpleHoster):
+ __name__ = "TurbobitNet"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:\w*\.)?(turbobit.net|unextfiles.com)/(?:download/free/)?(?P<ID>\w+).*"
+ __version__ = "0.07"
+ __description__ = """Turbobit.net plugin"""
+ __author_name__ = ("zoidberg")
+ __author_mail__ = ("zoidberg@mujmail.cz")
+
+ FILE_INFO_PATTERN = r"<span class='file-icon1[^>]*>(?P<N>[^<]+)</span>\s*\((?P<S>[^\)]+)\)\s*</h1>" #long filenames are shortened
+ FILE_NAME_PATTERN = r'<meta name="keywords" content="\s+(?P<N>[^,]+)' #full name but missing on page2
+ FILE_OFFLINE_PATTERN = r'<h2>File Not Found</h2>|html\(\'File was not found'
+ FILE_URL_REPLACEMENTS = [(r"http://(?:\w*\.)?(turbobit.net|unextfiles.com)/(?:download/free/)?(?P<ID>\w+).*", "http://turbobit.net/\g<ID>.html")]
+ SH_COOKIES = [("turbobit.net", "user_lang", "en")]
+
+ CAPTCHA_KEY_PATTERN = r'src="http://api\.recaptcha\.net/challenge\?k=([^"]+)"'
+ DOWNLOAD_URL_PATTERN = r'(?P<url>/download/redirect/[^"\']+)'
+ LIMIT_WAIT_PATTERN = r'<div id="time-limit-text">\s*.*?<span id=\'timeout\'>(\d+)</span>'
+ CAPTCHA_SRC_PATTERN = r'<img alt="Captcha" src="(.*?)"'
+
+ def handleFree(self):
+ self.url = "http://turbobit.net/download/free/%s" % self.file_info['ID']
+ self.html = self.load(self.url)
+
+ rtUpdate = self.getRtUpdate()
+
+ self.solveCaptcha()
+ self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"])
+ self.url = self.getDownloadUrl(rtUpdate)
+
+ self.wait()
+ self.html = self.load(self.url)
+ self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With:"])
+ self.downloadFile()
+
+ def solveCaptcha(self):
+ for i in range(5):
+ found = re.search(self.LIMIT_WAIT_PATTERN, self.html)
+ if found:
+ wait_time = int(found.group(1))
+ self.setWait(wait_time, wait_time > 60)
+ self.wait()
+ self.retry()
+
+ action, inputs = self.parseHtmlForm("action='#'")
+ if not inputs: self.parseError("captcha form")
+ self.logDebug(inputs)
+
+ if inputs['captcha_type'] == 'recaptcha':
+ recaptcha = ReCaptcha(self)
+ found = re.search(self.CAPTCHA_KEY_PATTERN, self.html)
+ captcha_key = found.group(1) if found else '6LcTGLoSAAAAAHCWY9TTIrQfjUlxu6kZlTYP50_c'
+ inputs['recaptcha_challenge_field'], inputs['recaptcha_response_field'] = recaptcha.challenge(captcha_key)
+ else:
+ found = re.search(self.CAPTCHA_SRC_PATTERN, self.html)
+ if not found: self.parseError('captcha')
+ captcha_url = found.group(1)
+ inputs['captcha_response'] = self.decryptCaptcha(captcha_url)
+
+ self.logDebug(inputs)
+ self.html = self.load(self.url, post = inputs)
+
+ if not "<div class='download-timer-header'>" in self.html:
+ self.invalidCaptcha()
+ else:
+ self.correctCaptcha()
+ break
+ else: self.fail("Invalid captcha")
+
+ def getRtUpdate(self):
+ rtUpdate = self.getStorage("rtUpdate")
+ if not rtUpdate:
+ if self.getStorage("version") != self.__version__ or int(self.getStorage("timestamp", 0)) + 86400000 < timestamp():
+ # that's right, we are even using jdownloader updates
+ rtUpdate = getURL("http://update0.jdownloader.org/pluginstuff/tbupdate.js")
+ rtUpdate = self.decrypt(rtUpdate.splitlines()[1])
+ # but we still need to fix the syntax to work with other engines than rhino
+ rtUpdate = re.sub(r'for each\(var (\w+) in(\[[^\]]+\])\)\{',r'zza=\2;for(var zzi=0;zzi<zza.length;zzi++){\1=zza[zzi];',rtUpdate)
+ rtUpdate = re.sub(r"for\((\w+)=",r"for(var \1=", rtUpdate)
+
+ self.logDebug("rtUpdate")
+ self.setStorage("rtUpdate", rtUpdate)
+ self.setStorage("timestamp", timestamp())
+ self.setStorage("version", self.__version__)
+ else:
+ self.logError("Unable to download, wait for update...")
+ self.tempOffline()
+
+ return rtUpdate
+
+ def getDownloadUrl(self, rtUpdate):
+ self.req.http.lastURL = self.url
+
+ found = re.search("(/\w+/timeout\.js\?\w+=)([^\"\'<>]+)", self.html)
+ url = "http://turbobit.net%s%s" % (found.groups() if found else ('/files/timeout.js?ver=', ''.join(random.choice('0123456789ABCDEF') for x in range(32))))
+ fun = self.load(url)
+
+ self.setWait(65, False)
+
+ for b in [1,3]:
+ self.jscode = "var id = \'%s\';var b = %d;var inn = \'%s\';%sout" % (self.file_info['ID'], b, quote(fun), rtUpdate)
+
+ try:
+ out = self.js.eval(self.jscode)
+ self.logDebug("URL", self.js.engine, out)
+ if out.startswith('/download/'):
+ return "http://turbobit.net%s" % out.strip()
+ except Exception, e:
+ self.logError(e)
+ else:
+ if self.retries >= 2:
+ # retry with updated js
+ self.delStorage("rtUpdate")
+ self.retry()
+
+ def decrypt(self, data):
+ cipher = ARC4.new(hexlify('E\x15\xa1\x9e\xa3M\xa0\xc6\xa0\x84\xb6H\x83\xa8o\xa0'))
+ return unhexlify(cipher.encrypt(unhexlify(data)))
+
+ def getLocalTimeString():
+ lt = time.localtime()
+ tz = time.altzone if lt.tm_isdst else time.timezone
+ return "%s GMT%+03d%02d" % (time.strftime("%a %b %d %Y %H:%M:%S", lt), -tz // 3600, tz % 3600)
+
+ def handlePremium(self):
+ self.logDebug("Premium download as user %s" % self.user)
+ self.downloadFile()
+
+ def downloadFile(self):
+ found = re.search(self.DOWNLOAD_URL_PATTERN, self.html)
+ if not found: self.parseError("download link")
+ self.url = "http://turbobit.net" + found.group('url')
+ self.logDebug(self.url)
+ self.download(self.url)
+
+getInfo = create_getInfo(TurbobitNet) \ No newline at end of file
diff --git a/module/plugins/hoster/TwoSharedCom.py b/module/plugins/hoster/TwoSharedCom.py
index 89c4b7781..8401e0cb0 100644
--- a/module/plugins/hoster/TwoSharedCom.py
+++ b/module/plugins/hoster/TwoSharedCom.py
@@ -8,15 +8,18 @@ class TwoSharedCom(SimpleHoster):
__name__ = "TwoSharedCom"
__type__ = "hoster"
__pattern__ = r"http://[\w\.]*?2shared.com/(account/)?(download|get|file|document|photo|video|audio)/.*"
- __version__ = "0.10"
+ __version__ = "0.11"
__description__ = """2Shared Download Hoster"""
__author_name__ = ("zoidberg")
__author_mail__ = ("zoidberg@mujmail.cz")
- FILE_NAME_PATTERN = r'<meta name="Description" content="(?P<N>.*) download free at 2shared'
+ FILE_NAME_PATTERN = r'<h1>(?P<N>.*)</h1>'
FILE_SIZE_PATTERN = r'<span class="dtitle">File size:</span>\s*(?P<S>[0-9,.]+) (?P<U>[kKMG])i?B'
FILE_OFFLINE_PATTERN = r'The file link that you requested is not valid\.|This file was deleted\.'
DOWNLOAD_URL_PATTERN = r"window.location ='([^']+)';"
+
+ def setup(self):
+ self.resumeDownload = self.multiDL = True
def handleFree(self):
found = re.search(self.DOWNLOAD_URL_PATTERN, self.html)
diff --git a/module/plugins/hoster/UlozTo.py b/module/plugins/hoster/UlozTo.py
index 6b699e39f..cf2f09311 100644
--- a/module/plugins/hoster/UlozTo.py
+++ b/module/plugins/hoster/UlozTo.py
@@ -21,116 +21,137 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
def convertDecimalPrefix(m):
# decimal prefixes used in filesize and traffic
- return ("%%.%df" % {'k':3,'M':6,'G':9}[m.group(2)] % float(m.group(1))).replace('.','')
+ return ("%%.%df" % {'k':3,'M':6,'G':9}[m.group(2)] % float(m.group(1))).replace('.','')
class UlozTo(SimpleHoster):
__name__ = "UlozTo"
__type__ = "hoster"
- __pattern__ = r"http://(\w*\.)?(uloz\.to|ulozto\.(cz|sk|net)|bagruj.cz|zachowajto.pl)/.*"
- __version__ = "0.81"
+ __pattern__ = r"http://(\w*\.)?(uloz\.to|ulozto\.(cz|sk|net)|bagruj.cz|zachowajto.pl)/(?:live/)?(?P<id>\w+/[^/?]*)"
+ __version__ = "0.89"
__description__ = """uloz.to"""
__author_name__ = ("zoidberg")
- FILE_NAME_PATTERN = r'<a share_url="[^&]*&amp;t=(?P<N>[^"]+)"'
- #FILE_NAME_PATTERN = r'<h2 class="nadpis" style="margin-left:196px;"><a href="[^"]+">(?P<N>[^<]+)</a></h2>'
- FILE_SIZE_PATTERN = r'<div class="info_velikost" style="top:-55px;">\s*<div>[^<]*\s+(?P<S>[0-9.]+\s[kMG]B)\s*</div>\s*</div>'
- FILE_SIZE_REPLACEMENTS = [('([0-9.]+)\s([kMG])B', convertDecimalPrefix)]
- FILE_OFFLINE_PATTERN = r'http://www.uloz.to/(neexistujici|smazano|nenalezeno)'
-
- PASSWD_PATTERN = r'<input type="password" class="text" name="file_password" id="frmfilepasswordForm-file_password" />'
- VIPLINK_PATTERN = r'<a href="[^"]*\?disclaimer=1" class="linkVip">'
- FREE_URL_PATTERN = r'<form name="dwn" action="([^"]+)"'
- PREMIUM_URL_PATTERN = r'<a onclick[^>]*href="([^"]+)[^>]*class="linkVip"'
- CAPTCHA_PATTERN = r'<img style=".*src="([^"]+)" alt="Captcha" class="captcha"'
- CAPTCHA_NB_PATTERN = r'<input class="captcha_nb" type="hidden" name="captcha_nb" value="([0-9]+)" >'
+ FILE_NAME_PATTERN = r'<a href="#download" class="jsShowDownload">(?P<N>[^<]+)</a>'
+ FILE_SIZE_PATTERN = r'<span id="fileSize">.*?(?P<S>[0-9.]+\s[kMG]B)</span>'
+ FILE_INFO_PATTERN = r'<p>File <strong>(?P<N>[^<]+)</strong> is password protected</p>'
+ FILE_OFFLINE_PATTERN = r'<title>404 - Page not found</title>|<h1 class="h1">File (has been deleted|was banned)</h1>'
+ FILE_SIZE_REPLACEMENTS = [('([0-9.]+)\s([kMG])B', convertDecimalPrefix)]
+ FILE_URL_REPLACEMENTS = [(r"(?<=http://)([^/]+)", "www.ulozto.net")]
+
+ PASSWD_PATTERN = r'<div class="passwordProtectedFile">'
+ VIPLINK_PATTERN = r'<a href="[^"]*\?disclaimer=1" class="linkVip">'
+ FREE_URL_PATTERN = r'<div class="freeDownloadForm"><form action="([^"]+)"'
+ PREMIUM_URL_PATTERN = r'<div class="downloadForm"><form action="([^"]+)"'
+
+ def setup(self):
+ self.multiDL = self.premium
+ self.resumeDownload = True
def process(self, pyfile):
- # check file online
- header = self.load(pyfile.url, just_header=True)
- if "location" in header:
- self.logDebug('LOCATION: ' + header['location'])
- if "utm_source=old" in header['location'] or re.search(self.FILE_OFFLINE_PATTERN, header['location']):
- self.offline()
-
- self.html = self.load(pyfile.url, decode=True)
-
- # password protected links
- passwords = self.getPassword().splitlines()
+ pyfile.url = re.sub(r"(?<=http://)([^/]+)", "www.ulozto.net", pyfile.url)
+ self.html = self.load(pyfile.url, decode = True, cookies = True)
+
+ passwords = self.getPassword().splitlines()
while self.PASSWD_PATTERN in self.html:
if passwords:
password = passwords.pop(0)
self.logInfo("Password protected link, trying " + password)
- self.html = self.load(pyfile.url, get = {"do": "filepasswordForm-submit"}, post={"file_password": password, "fpwdsend": 'Odeslat'}, cookies=True)
+ self.html = self.load(pyfile.url, get = {"do": "passwordProtectedForm-submit"},
+ post={"password": password, "password_send": 'Send'}, cookies=True)
else:
self.fail("No or incorrect password")
-
- self.file_info = self.getFileInfo()
-
- # adult content
+
if re.search(self.VIPLINK_PATTERN, self.html):
self.html = self.load(pyfile.url, get={"disclaimer": "1"})
-
+
+ self.file_info = self.getFileInfo()
+
if self.premium and self.checkTrafficLeft():
self.handlePremium()
- else:
+ else:
self.handleFree()
- def handleFree(self):
- parsed_url = self.findDownloadURL(premium=False)
+ self.doCheckDownload()
+ def handleFree(self):
+ action, inputs = self.parseHtmlForm('id="frm-downloadDialog-freeDownloadForm"')
+ if not action or not inputs:
+ self.parseError("free download form")
+
# get and decrypt captcha
- captcha = self.getStorage("captchaUser")
- captcha_nb = self.getStorage("captchaNb")
- captcha_url = "DUMMY"
-
- if not captcha or not captcha_nb:
- found = re.search(self.CAPTCHA_PATTERN, self.html)
- if not found: self.parseError("CAPTCHA")
- captcha_url = found.group(1)
-
- found = re.search(self.CAPTCHA_NB_PATTERN, self.html)
- if not found: self.parseError("CAPTCHA_NB")
- captcha_nb = found.group(1)
-
- captcha = self.decryptCaptcha(captcha_url)
+ captcha_id_field = captcha_text_field = None
+ captcha_id = captcha_text = None
- self.log.debug('CAPTCHA_URL:' + captcha_url + ' CAPTCHA:' + captcha + ' CAPTCHA_NB:' + captcha_nb)
+ for key in inputs.keys():
+ found = re.match("captcha.*(id|text|value)", key)
+ if found:
+ if found.group(1) == "id":
+ captcha_id_field = key
+ else:
+ captcha_text_field = key
+
+ if not captcha_id_field or not captcha_text_field:
+ self.parseError("CAPTCHA form changed")
+
+ """
+ captcha_id = self.getStorage("captcha_id")
+ captcha_text = self.getStorage("captcha_text")
+
+ if not captcha_id or not captcha_text:
+ """
+ captcha_id = inputs[captcha_id_field]
+ captcha_text = self.decryptCaptcha("http://img.uloz.to/captcha/%s.png" % captcha_id)
- # download and check
- self.download(parsed_url, post={"captcha_user": captcha, "captcha_nb": captcha_nb}, cookies=True)
- self.doCheckDownload()
+ self.log.debug(' CAPTCHA ID:' + captcha_id + ' CAPTCHA TEXT:' + captcha_text)
- self.setStorage("captchaUser", captcha)
- self.setStorage("captchaNb", captcha_nb)
-
- def handlePremium(self):
- parsed_url = self.findDownloadURL(premium=True)
- self.download(parsed_url)
- self.doCheckDownload()
+ """
+ self.setStorage("captcha_id", captcha_id)
+ self.setStorage("captcha_text", captcha_text)
+ """
+ self.multiDL = True
+
+ inputs.update({captcha_id_field: captcha_id, captcha_text_field: captcha_text})
+ self.download("http://www.ulozto.net" + action, post=inputs, cookies=True)
+
+ def handlePremium(self):
+ self.download(self.pyfile.url + "?do=directDownload")
+ #parsed_url = self.findDownloadURL(premium=True)
+ #self.download(parsed_url, post={"download": "Download"})
+
def findDownloadURL(self, premium=False):
msg = "%s link" % ("Premium" if premium else "Free")
found = re.search(self.PREMIUM_URL_PATTERN if premium else self.FREE_URL_PATTERN, self.html)
if not found: self.parseError(msg)
- parsed_url = found.group(1)
+ parsed_url = "http://www.ulozto.net" + found.group(1)
self.logDebug("%s: %s" % (msg, parsed_url))
return parsed_url
-
+
def doCheckDownload(self):
check = self.checkDownload({
- "wrong_captcha": re.compile(self.CAPTCHA_PATTERN),
+ "wrong_captcha": re.compile(r'<ul class="error">\s*<li>Error rewriting the text.</li>'),
"offline": re.compile(self.FILE_OFFLINE_PATTERN),
- "passwd": self.PASSWD_PATTERN
+ "passwd": self.PASSWD_PATTERN,
+ "server_error": 'src="http://img.ulozto.cz/error403/vykricnik.jpg"', #paralell dl, server overload etc.
+ "not_found": "<title>Ulož.to</title>"
})
if check == "wrong_captcha":
- self.delStorage("captchaUser")
- self.delStorage("captchaNb")
+ self.delStorage("captcha_id")
+ self.delStorage("captcha_text")
self.invalidCaptcha()
self.retry(reason="Wrong captcha code")
elif check == "offline":
self.offline()
elif check == "passwd":
self.fail("Wrong password")
+ elif check == "server_error":
+ self.logError("Server error, try downloading later")
+ self.multiDL = False
+ self.setWait(3600, True)
+ self.wait()
+ self.retry()
+ elif check == "not_found":
+ self.fail("Server error - file not downloadable")
-getInfo = create_getInfo(UlozTo) \ No newline at end of file
+getInfo = create_getInfo(UlozTo) \ No newline at end of file
diff --git a/module/plugins/hoster/UnibytesCom.py b/module/plugins/hoster/UnibytesCom.py
new file mode 100644
index 000000000..3c8552271
--- /dev/null
+++ b/module/plugins/hoster/UnibytesCom.py
@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: zoidberg
+"""
+
+import re
+from pycurl import FOLLOWLOCATION
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+
+class UnibytesCom(SimpleHoster):
+ __name__ = "UnibytesCom"
+ __type__ = "hoster"
+ __pattern__ = r"http://(www\.)?unibytes\.com/[a-zA-Z0-9-._ ]{11}B"
+ __version__ = "0.1"
+ __description__ = """UniBytes.com"""
+ __author_name__ = ("zoidberg")
+
+ FILE_INFO_PATTERN = r'<span[^>]*?id="fileName"[^>]*>(?P<N>[^>]+)</span>\s*\((?P<S>\d.*?)\)'
+ DOMAIN = 'http://www.unibytes.com'
+
+ WAIT_PATTERN = r'Wait for <span id="slowRest">(\d+)</span> sec'
+ DOWNLOAD_LINK_PATTERN = r'<a href="([^"]+)">Download</a>'
+
+ def handleFree(self):
+ action, post_data = self.parseHtmlForm('id="startForm"')
+ self.req.http.c.setopt(FOLLOWLOCATION, 0)
+
+ for i in range(8):
+ self.logDebug(action, post_data)
+ self.html = self.load(self.DOMAIN + action, post = post_data)
+
+ found = re.search(r'location:\s*(\S+)', self.req.http.header, re.I)
+ if found:
+ url = found.group(1)
+ break
+
+ if '>Somebody else is already downloading using your IP-address<' in self.html:
+ self.setWait(600, True)
+ self.wait()
+ self.retry()
+
+ if post_data['step'] == 'last':
+ found = re.search(self.DOWNLOAD_LINK_PATTERN, self.html)
+ if found:
+ url = found.group(1)
+ self.correctCaptcha()
+ break
+ else:
+ self.invalidCaptcha()
+
+ last_step = post_data['step']
+ action, post_data = self.parseHtmlForm('id="stepForm"')
+
+ if last_step == 'timer':
+ found = re.search(self.WAIT_PATTERN, self.html)
+ self.setWait(int(found.group(1)) if found else 60, False)
+ self.wait()
+ elif last_step in ('captcha', 'last'):
+ post_data['captcha'] = self.decryptCaptcha(self.DOMAIN + '/captcha.jpg')
+ else:
+ self.fail("No valid captcha code entered")
+
+ self.logDebug('Download link: ' + url)
+ self.req.http.c.setopt(FOLLOWLOCATION, 1)
+ self.download(url)
+
+getInfo = create_getInfo(UnibytesCom) \ No newline at end of file
diff --git a/module/plugins/hoster/UploadStationCom.py b/module/plugins/hoster/UploadStationCom.py
index fea5f4245..d24682e4d 100644
--- a/module/plugins/hoster/UploadStationCom.py
+++ b/module/plugins/hoster/UploadStationCom.py
@@ -1,141 +1,21 @@
# -*- coding: utf-8 -*-
-from __future__ import with_statement
+from module.plugins.hoster.FileserveCom import FileserveCom, checkFile
+from module.plugins.Plugin import chunks
-from module.network.RequestFactory import getURL
-from module.plugins.Hoster import Hoster
-from module.plugins.ReCaptcha import ReCaptcha
-
-import re
-
-def getInfo(urls):
- yield [(url, 0, 1, url) for url in urls]
-
-class UploadStationCom(Hoster):
+class UploadStationCom(FileserveCom):
__name__ = "UploadStationCom"
__type__ = "hoster"
- __pattern__ = r"http://(www\.)?uploadstation\.com/file/(?P<id>[A-Za-z0-9]+)"
- __version__ = "0.33"
+ __pattern__ = r"http://(?:www\.)?uploadstation\.com/file/(?P<id>[A-Za-z0-9]+)"
+ __version__ = "0.51"
__description__ = """UploadStation.Com File Download Hoster"""
- __author_name__ = ("fragonib")
- __author_mail__ = ("fragonib[AT]yahoo[DOT]es")
-
- FILE_OFFLINE_PATTERN = r'''<h1>File not available</h1>|<h1>File is not available</h1>'''
- FILE_TITLE_PATTERN = r'''<div class=\"download_item\">(.*?)</div>'''
- FILE_SIZE_PATTERN = r'''<div><span>File size: <b>(.*?) (KB|MB|GB)</b>'''
- CAPTCHA_PRESENT_TOKEN = '<div class="speedBox" id="showCaptcha" style="display:none;">'
- CAPTCHA_KEY_PATTERN = r"var reCAPTCHA_publickey='(.*?)';"
- CAPTCHA_WRONG_TOKEN = 'incorrect-captcha-sol'
- WAITING_PATTERN = r".*?(\d+).*?"
- TIME_LIMIT_TOKEN = '"fail":"timeLimit"'
- TIME_LIMIT_WAIT_PATTERN = r"You need to wait (\d+) seconds to download next file."
- DOWNLOAD_RESTRICTION_TOKEN = '"To remove download restriction, please choose your suitable plan as below</h1>"'
-
- def setup(self):
- self.multiDL = False
- self.fileId = ''
- self.html = ''
-
- def process(self, pyfile):
-
- self.fail("Hoster not longer available")
-
- # Get URL
- self.html = self.load(self.pyfile.url, ref=False, decode=True)
-
- # Is offline?
- m = re.search(UploadStationCom.FILE_OFFLINE_PATTERN, self.html)
- if m is not None:
- self.offline()
-
- # Id & Title
- self.fileId = re.search(self.__pattern__, self.pyfile.url).group('id')
- self.pyfile.name = re.search(UploadStationCom.FILE_TITLE_PATTERN, self.html).group(1)
-
- # Free account
- self.handleFree()
-
- def handleFree(self):
-
- # Not needed yet
- # pattern = r'''\"(/landing/.*?/download_captcha\.js)\"'''
- # jsPage = re.search(pattern, self.html).group(1)
- # self.jsPage = self.load("http://uploadstation.com" + jsPage)
-
- # Check download
- response = self.load(self.pyfile.url, post={"checkDownload" : "check"}, decode=True)
- self.logDebug("Checking download, response [%s]" % response.encode('ascii', 'ignore'))
- self.handleErrors(response)
-
- # We got a captcha?
- if UploadStationCom.CAPTCHA_PRESENT_TOKEN in self.html:
- id = re.search(UploadStationCom.CAPTCHA_KEY_PATTERN, self.html).group(1)
- self.logDebug("Resolving ReCaptcha with key [%s]" % id)
- recaptcha = ReCaptcha(self)
- challenge, code = recaptcha.challenge(id)
- response = self.load('http://www.uploadstation.com/checkReCaptcha.php',
- post={'recaptcha_challenge_field' : challenge,
- 'recaptcha_response_field' : code,
- 'recaptcha_shortencode_field' : self.fileId})
- self.logDebug("Result of captcha resolving [%s]" % response.encode('ascii', 'ignore'))
- self.handleCaptchaErrors(response)
-
- # Process waiting
- response = self.load(self.pyfile.url, post={"downloadLink" : "wait"})
- m = re.search(UploadStationCom.WAITING_PATTERN, response)
- if m is not None:
- wait = int(m.group(1))
- if wait == 404:
- self.logDebug("No wait time returned")
- self.fail("No wait time returned")
-
- self.logDebug("Waiting %d seconds." % wait)
- self.setWait(wait + 3)
- self.wait()
-
- # Show download link
- self.load(self.pyfile.url, post={"downloadLink" : "show"})
-
- # This may either download our file or forward us to an error page
- self.logDebug("Downloading file.")
- dl = self.download(self.pyfile.url, post={"download" : "normal"})
- self.handleDownloadedFile()
-
- def handleErrors(self, response):
-
- if UploadStationCom.TIME_LIMIT_TOKEN in response:
- wait = 300
- html = self.load(self.pyfile.url, post={"checkDownload" : "showError", "errorType" : "timeLimit"})
- m = re.search(UploadStationCom.TIME_LIMIT_WAIT_PATTERN, html)
- if m is not None:
- wait = int(m.group(1))
-
- self.logInfo("Time limit reached, waiting %d seconds." % wait)
- self.setWait(wait, True)
- self.wait()
- self.retry()
+ __author_name__ = ("fragonib", "zoidberg")
+ __author_mail__ = ("fragonib[AT]yahoo[DOT]es", "zoidberg@mujmail.cz")
- if UploadStationCom.DOWNLOAD_RESTRICTION_TOKEN in response:
- wait = 720
- self.logInfo("Free account time limit reached, waiting %d seconds." % wait)
- self.setWait(wait, True)
- self.wait()
- self.retry()
-
- def handleCaptchaErrors(self, response):
- if UploadStationCom.CAPTCHA_WRONG_TOKEN in response:
- self.logInfo("Invalid captcha response, retrying.")
- self.invalidCaptcha()
- self.retry()
- else:
- self.correctCaptcha()
-
- def handleDownloadedFile(self):
- check = self.checkDownload({"wait": re.compile(UploadStationCom.TIME_LIMIT_WAIT_PATTERN)})
- if check == "wait":
- wait = 720
- if self.lastCheck is not None:
- wait = int(self.lastCheck.group(1))
- self.logDebug("Failed, you need to wait %d seconds for another download." % wait)
- self.setWait(wait + 3, True)
- self.wait()
- self.retry()
+ URLS = ['http://www.uploadstation.com/file/', 'http://www.uploadstation.com/check-links.php', 'http://www.uploadstation.com/checkReCaptcha.php']
+ LINKCHECK_TR = r'<div class="details (?:white|grey)">(.*?)\t{9}</div>'
+ LINKCHECK_TD = r'<div class="(?:col )?col\d">(?:<[^>]*>|&nbsp;)*([^<]*)'
+
+ LONG_WAIT_PATTERN = r'<h1>You have to wait (\d+) (\w+) to download the next file\.</h1>'
+
+def getInfo(urls):
+ for chunk in chunks(urls, 100): yield checkFile(UploadStationCom, chunk) \ No newline at end of file
diff --git a/module/plugins/hoster/UploadedTo.py b/module/plugins/hoster/UploadedTo.py
index 751dcda25..3cb1e71ff 100644
--- a/module/plugins/hoster/UploadedTo.py
+++ b/module/plugins/hoster/UploadedTo.py
@@ -10,19 +10,10 @@ from module.plugins.ReCaptcha import ReCaptcha
key = "bGhGMkllZXByd2VEZnU5Y2NXbHhYVlZ5cEE1bkEzRUw=".decode('base64')
-def correctDownloadLink(url):
- url = re.sub("http://.*?/", "http://uploaded.to/",url, 1)
- url = re.sub("\\.to/.*?id=", ".to/file/", url, 1)
-
- if "/file/" not in url:
- url = url.replace("uploaded.to/", "uploaded.to/file/")
-
- parts = url.split("/")
- return "/".join(parts[:min(5,len(parts))]) + "/"
-
def getID(url):
- """ returns id of corrected url"""
- return re.search(r"uploaded.to/file/([^/]+)", url).group(1)
+ """ returns id from file url"""
+ m = re.match(r"http://[\w\.-]*?(uploaded\.(to|net)(/file/|/?\?id=|.*?&id=)|ul\.to/)(?P<ID>\w+)", url)
+ return m.group('ID')
def getAPIData(urls):
post = {"apikey" : key}
@@ -30,18 +21,17 @@ def getAPIData(urls):
idMap = {}
for i, url in enumerate(urls):
- newUrl = correctDownloadLink(url)
- id = getID(newUrl)
+ id = getID(url)
post["id_%s" % i] = id
idMap[id] = url
- api = unicode(getURL("http://uploaded.to/api/filemultiple", post=post, decode=False), 'iso-8859-1')
+ api = unicode(getURL("http://uploaded.net/api/filemultiple", post=post, decode=False), 'iso-8859-1')
result = {}
if api:
for line in api.splitlines():
- data = line.split(",")
+ data = line.split(",", 4)
if data[1] in idMap:
result[data[1]] = (data[0], data[2], data[4], data[3], idMap[data[1]])
@@ -82,11 +72,11 @@ def getInfo(urls):
class UploadedTo(Hoster):
__name__ = "UploadedTo"
__type__ = "hoster"
- __pattern__ = r"(http://[\w\.-]*?uploaded\.to/.*?(file/|\?id=|&id=)[\w]+/?)|(http://[\w\.]*?ul\.to/(\?id=|&id=)?[\w\-]+/.+)|(http://[\w\.]*?ul\.to/(\?id=|&id=)?[\w\-]+/?)"
- __version__ = "0.53"
- __description__ = """Uploaded.to Download Hoster"""
- __author_name__ = ("spoob", "mkaay")
- __author_mail__ = ("spoob@pyload.org", "mkaay@mkaay.de")
+ __pattern__ = r"http://[\w\.-]*?(uploaded\.(to|net)(/file/|/?\?id=|.*?&id=)|ul\.to/)\w+"
+ __version__ = "0.62"
+ __description__ = """Uploaded.net Download Hoster"""
+ __author_name__ = ("spoob", "mkaay", "zoidberg", "netpok")
+ __author_mail__ = ("spoob@pyload.org", "mkaay@mkaay.de", "zoidberg@mujmail.cz", "netpok@gmail.com")
FILE_INFO_PATTERN = r'<a href="file/(?P<ID>\w+)" id="filename">(?P<N>[^<]+)</a> &nbsp;\s*<small[^>]*>(?P<S>[^<]+)</small>'
FILE_OFFLINE_PATTERN = r'<small class="cL">Error: 404</small>'
@@ -103,12 +93,12 @@ class UploadedTo(Hoster):
self.multiDL = True
self.resumeDownload = True
-
- self.pyfile.url = correctDownloadLink(self.pyfile.url)
self.fileID = getID(self.pyfile.url)
+ self.pyfile.url = "http://uploaded.net/file/%s" % self.fileID
def process(self, pyfile):
- self.req.cj.setCookie("uploaded.to", "lang", "en")
+ self.req.cj.setCookie("uploaded.net", "lang", "en") # doesn't work anymore
+ self.load("http://uploaded.net/language/en")
api = getAPIData([pyfile.url])
@@ -156,24 +146,42 @@ class UploadedTo(Hoster):
self.resetAccount()
self.fail(_("Traffic exceeded"))
- self.download("http://uploaded.to/file/%s/ddl" % self.fileID)
-
+ header = self.load("http://uploaded.net/file/%s" % self.fileID, just_header=True)
+ if "location" in header:
+ #Direct download
+ print "Direct Download: " + header['location']
+ self.download(header['location'])
+ else:
+ #Indirect download
+ self.html = self.load("http://uploaded.net/file/%s" % self.fileID)
+ found = re.search(r'<div class="tfree".*\s*<form method="post" action="(.*?)"', self.html)
+ if not found:
+ self.fail("Download URL not found. Try to enable direct downloads.")
+ url = found.group(1)
+ print "Premium URL: " + url
+ self.download(url, post={})
def handleFree(self):
self.html = self.load(self.pyfile.url, decode=True)
+
+ if 'var free_enabled = false;' in self.html:
+ self.logError("Free-download capacities exhausted.")
+ self.retry(24, 300)
- wait = re.search(r"Current waiting period: <span>(\d+)</span> seconds", self.html).group(1)
- self.setWait(wait)
+ found = re.search(r"Current waiting period: <span>(\d+)</span> seconds", self.html)
+ if not found:
+ self.fail("File not downloadable for free users")
+ self.setWait(int(found.group(1)))
- js = self.load("http://uploaded.to/js/download.js", decode=True)
+ js = self.load("http://uploaded.net/js/download.js", decode=True)
challengeId = re.search(r'Recaptcha\.create\("([^"]+)', js)
- url = "http://uploaded.to/io/ticket/captcha/%s" % self.fileID
+ url = "http://uploaded.net/io/ticket/captcha/%s" % self.fileID
downloadURL = ""
for i in range(5):
- self.req.lastURL = str(self.url)
+ #self.req.lastURL = str(self.url)
re_captcha = ReCaptcha(self)
challenge, result = re_captcha.challenge(challengeId.group(1))
options = {"recaptcha_challenge_field" : challenge, "recaptcha_response_field": result}
@@ -190,18 +198,24 @@ class UploadedTo(Hoster):
self.retry()
elif "limit-parallel" in result:
self.fail("Cannot download in parallel")
- elif "limit-dl" in result:
- self.setWait(30 * 60, True)
+ elif "You have reached the max. number of possible free downloads for this hour" in result: # limit-dl
+ self.setWait(60 * 60, True)
self.wait()
self.retry()
elif 'err:"captcha"' in result:
+ self.logError("ul.net captcha is disabled")
self.invalidCaptcha()
elif "type:'download'" in result:
self.correctCaptcha()
downloadURL = re.search("url:'([^']+)", result).group(1)
break
+ else:
+ self.fail("Unknown error '%s'")
+ self.setWait(60 * 60, True)
+ self.wait()
+ self.retry()
if not downloadURL:
self.fail("No Download url retrieved/all captcha attempts failed")
- self.download(downloadURL) \ No newline at end of file
+ self.download(downloadURL)
diff --git a/module/plugins/hoster/UploadheroCom.py b/module/plugins/hoster/UploadheroCom.py
new file mode 100644
index 000000000..eb7b5fb23
--- /dev/null
+++ b/module/plugins/hoster/UploadheroCom.py
@@ -0,0 +1,84 @@
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: zoidberg
+"""
+
+import re
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+
+class UploadheroCom(SimpleHoster):
+ __name__ = "UploadheroCom"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:www\.)?uploadhero\.com/dl/\w+"
+ __version__ = "0.12"
+ __description__ = """UploadHero.com plugin"""
+ __author_name__ = ("mcmyst", "zoidberg")
+ __author_mail__ = ("mcmyst@hotmail.fr", "zoidberg@mujmail.cz")
+
+ SH_COOKIES = [("http://uploadhero.com", "lang", "en")]
+ FILE_NAME_PATTERN = r'<div class="nom_de_fichier">(?P<N>.*?)</div>'
+ FILE_SIZE_PATTERN = r'Taille du fichier : </span><strong>(?P<S>.*?)</strong>'
+ FILE_OFFLINE_PATTERN = r'<p class="titre_dl_2">|<div class="raison"><strong>Le lien du fichier ci-dessus n\'existe plus.'
+
+ DOWNLOAD_URL_PATTERN = r'<a href="([^"]+)" id="downloadnow"'
+
+ IP_BLOCKED_PATTERN = r'href="(/lightbox_block_download.php\?min=.*?)"'
+ IP_WAIT_PATTERN = r'<span id="minutes">(\d+)</span>.*\s*<span id="seconds">(\d+)</span>'
+
+ CAPTCHA_PATTERN = r'"(/captchadl\.php\?[a-z0-9]+)"'
+ FREE_URL_PATTERN = r'var magicomfg = \'<a href="(http://[^<>"]*?)"|"(http://storage\d+\.uploadhero\.com/\?d=[A-Za-z0-9]+/[^<>"/]+)"'
+
+ def handleFree(self):
+ self.checkErrors()
+
+ found = re.search(self.CAPTCHA_PATTERN, self.html)
+ if not found: self.parseError("Captcha URL")
+ captcha_url = "http://uploadhero.com" + found.group(1)
+
+ for i in range(5):
+ captcha = self.decryptCaptcha(captcha_url)
+ self.html = self.load(self.pyfile.url, get = {"code": captcha})
+ found = re.search(self.FREE_URL_PATTERN, self.html)
+ if found:
+ self.correctCaptcha()
+ download_url = found.group(1) or found.group(2)
+ break
+ else:
+ self.invalidCaptcha()
+ else:
+ self.fail("No valid captcha code entered")
+
+ self.download(download_url)
+
+ def handlePremium(self):
+ self.log.debug("%s: Use Premium Account" % self.__name__)
+ self.html = self.load(self.pyfile.url)
+ link = re.search(self.DOWNLOAD_URL_PATTERN, self.html).group(1)
+ self.log.debug("Downloading link : '%s'" % link)
+ self.download(link)
+
+ def checkErrors(self):
+ found = re.search(self.IP_BLOCKED_PATTERN, self.html)
+ if found:
+ self.html = self.load("http://uploadhero.com%s" % found.group(1))
+
+ found = re.search(self.IP_WAIT_PATTERN, self.html)
+ wait_time = (int(found.group(1)) * 60 + int(found.group(2))) if found else 300
+ self.setWait(wait_time, True)
+ self.wait()
+ self.retry()
+
+getInfo = create_getInfo(UploadheroCom) \ No newline at end of file
diff --git a/module/plugins/hoster/UploadingCom.py b/module/plugins/hoster/UploadingCom.py
index 1278bfc01..4a157a787 100644
--- a/module/plugins/hoster/UploadingCom.py
+++ b/module/plugins/hoster/UploadingCom.py
@@ -18,20 +18,22 @@
"""
import re
+from pycurl import HTTPHEADER
from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, timestamp
+from module.common.json_layer import json_loads
class UploadingCom(SimpleHoster):
__name__ = "UploadingCom"
__type__ = "hoster"
- __pattern__ = r"http://(?:www\.)?uploading\.com/files/(?:get/)?[\w\d]+/?"
- __version__ = "0.30"
+ __pattern__ = r"http://(?:www\.)?uploading\.com/files/(?:get/)?(?P<ID>[\w\d]+)"
+ __version__ = "0.32"
__description__ = """Uploading.Com File Download Hoster"""
__author_name__ = ("jeix", "mkaay", "zoidberg")
__author_mail__ = ("jeix@hasnomail.de", "mkaay@mkaay.de", "zoidberg@mujmail.cz")
FILE_NAME_PATTERN = r'<title>Download (?P<N>.*?) for free on uploading.com</title>'
FILE_SIZE_PATTERN = r'<span>File size: (?P<S>.*?)</span>'
- FILE_OFFLINE_PATTERN = r'<h2 style=".*?">The requested file is not found</h2>'
+ FILE_OFFLINE_PATTERN = r'<h2.*?>The requested file is not found</h2>'
def process(self, pyfile):
# set lang to english
@@ -47,21 +49,20 @@ class UploadingCom(SimpleHoster):
self.file_info = self.getFileInfo()
if self.premium:
- url = self.handlePremium()
+ self.handlePremium()
else:
- url = self.handleFree()
-
- self.download(url)
+ self.handleFree()
def handlePremium(self):
postData = {'action': 'get_link',
- 'code': re.search('code: "(.*?)",', self.html).group(1),
+ 'code': self.file_info['ID'],
'pass': 'undefined'}
self.html = self.load('http://uploading.com/files/get/?JsHttpRequest=%d-xml' % timestamp(), post=postData)
url = re.search(r'"link"\s*:\s*"(.*?)"', self.html)
if url:
- return url.group(1).replace("\\/", "/")
+ url = url.group(1).replace("\\/", "/")
+ self.download(url)
raise Exception("Plugin defect.")
@@ -72,39 +73,38 @@ class UploadingCom(SimpleHoster):
self.logWarning(self.pyfile.error)
self.retry(max_tries=6, wait_time = 21600 if found.group(2) else 900, reason = self.pyfile.error)
- self.code = re.search(r'name="code" value="(.*?)"', self.html).group(1)
- self.fileid = re.search(r'name="file_id" value="(.*?)"', self.html).group(1)
-
- postData = {'action': 'second_page',
- 'code': self.code,
- 'file_id': self.fileid}
-
- self.html = self.load(self.pyfile.url, post=postData)
+ ajax_url = "http://uploading.com/files/get/?ajax"
+ self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"])
+ self.req.http.lastURL = self.pyfile.url
- wait_time = re.search(r'timead_counter">(\d+)<', self.html)
- if not wait_time:
- wait_time = re.search(r'start_timer\((\d+)\)', self.html)
-
- if wait_time:
- wait_time = int(wait_time.group(1))
+ response = json_loads(self.load(ajax_url, post = {'action': 'second_page', 'code': self.file_info['ID']}))
+ if 'answer' in response and 'wait_time' in response['answer']:
+ wait_time = int(response['answer']['wait_time'])
self.log.info("%s: Waiting %d seconds." % (self.__name__, wait_time))
self.setWait(wait_time)
self.wait()
+ else:
+ self.pluginParseError("AJAX/WAIT")
+ response = json_loads(self.load(ajax_url, post = {'action': 'get_link', 'code': self.file_info['ID'], 'pass': 'false'}))
+ if 'answer' in response and 'link' in response['answer']:
+ url = response['answer']['link']
+ else:
+ self.pluginParseError("AJAX/URL")
+
+ self.html = self.load(url)
+ found = re.search(r'<form id="file_form" action="(.*?)"', self.html)
+ if found:
+ url = found.group(1)
+ else:
+ self.pluginParseError("URL")
- postData = {'action': 'get_link',
- 'code': self.code,
- 'pass': 'undefined'}
-
- if r'var captcha_src' in self.html[1]:
- captcha_url = "http://uploading.com/general/captcha/download%s/?ts=%d" % (self.fileid, timestamp())
- postData['captcha_code'] = self.decryptCaptcha(captcha_url)
-
- self.html = self.load('http://uploading.com/files/get/?JsHttpRequest=%d-xml' % timestamp(), post=postData)
- url = re.search(r'"link"\s*:\s*"(.*?)"', self.html)
- if url:
- return url.group(1).replace("\\/", "/")
-
- raise Exception("Plugin defect.")
+ self.download(url)
+
+ check = self.checkDownload({"html" : re.compile("\A<!DOCTYPE html PUBLIC")})
+ if check == "html":
+ self.logWarning("Redirected to a HTML page, wait 10 minutes and retry")
+ self.setWait(600, True)
+ self.wait()
getInfo = create_getInfo(UploadingCom) \ No newline at end of file
diff --git a/module/plugins/hoster/WarserverCz.py b/module/plugins/hoster/WarserverCz.py
new file mode 100644
index 000000000..423170319
--- /dev/null
+++ b/module/plugins/hoster/WarserverCz.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: zoidberg
+"""
+
+import re
+from module.plugins.hoster.CoolshareCz import CoolshareCz
+from module.plugins.internal.SimpleHoster import create_getInfo
+
+class WarserverCz(CoolshareCz):
+ __name__ = "WarserverCz"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:\w*\.)?warserver.cz/stahnout/(?P<ID>\d+)/.+"
+ __version__ = "0.11"
+ __description__ = """Warserver.cz"""
+ __author_name__ = ("zoidberg")
+
+ FILE_NAME_PATTERN = r'<h1.*?>(?P<N>[^<]+)</h1>'
+ DOMAIN = "http://s01.warserver.cz"
+
+getInfo = create_getInfo(WarserverCz) \ No newline at end of file
diff --git a/module/plugins/hoster/WebshareCz.py b/module/plugins/hoster/WebshareCz.py
new file mode 100644
index 000000000..b60fda7e4
--- /dev/null
+++ b/module/plugins/hoster/WebshareCz.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: zoidberg
+"""
+
+import re
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+from module.network.HTTPRequest import BadHeader
+
+class WebshareCz(SimpleHoster):
+ __name__ = "WebshareCz"
+ __type__ = "hoster"
+ __pattern__ = r"http://(\w+\.)?webshare.cz/(stahnout/)?(?P<ID>\w{10})-.+"
+ __version__ = "0.11"
+ __description__ = """WebShare.cz"""
+ __author_name__ = ("zoidberg")
+
+ FILE_NAME_PATTERN = r'<h3>Stahujete soubor: </h3>\s*<div class="textbox">(?P<N>[^<]+)</div>'
+ FILE_SIZE_PATTERN = r'<h3>Velikost souboru je: </h3>\s*<div class="textbox">(?P<S>[^<]+)</div>'
+ FILE_OFFLINE_PATTERN = r'<h3>Soubor ".*?" nebyl nalezen.</h3>'
+
+ DOWNLOAD_LINK_PATTERN = r'id="download_link" href="(?P<url>.*?)"'
+
+ def handleFree(self):
+ url_a = re.search(r"(var l.*)", self.html).group(1)
+ url_b = re.search(r"(var keyStr.*)", self.html).group(1)
+ url = self.js.eval("%s\n%s\ndec(l)" % (url_a, url_b))
+
+ self.logDebug('Download link: ' + url)
+ self.download(url)
+
+getInfo = create_getInfo(WebshareCz) \ No newline at end of file
diff --git a/module/plugins/hoster/WrzucTo.py b/module/plugins/hoster/WrzucTo.py
new file mode 100644
index 000000000..4a5e89f22
--- /dev/null
+++ b/module/plugins/hoster/WrzucTo.py
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: zoidberg
+"""
+
+import re
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+from pycurl import HTTPHEADER
+
+class WrzucTo(SimpleHoster):
+ __name__ = "WrzucTo"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:\w+\.)*?wrzuc\.to/([a-zA-Z0-9]+(\.wt|\.html)|(\w+/?linki/[a-zA-Z0-9]+))"
+ __version__ = "0.01"
+ __description__ = """Wrzuc.to plugin - free only"""
+ __author_name__ = ("zoidberg")
+ __author_mail__ = ("zoidberg@mujmail.cz")
+
+ SH_COOKIES = [("http://www.wrzuc.to", "language", "en")]
+ FILE_SIZE_PATTERN = r'class="info">\s*<tr>\s*<td>(?P<S>.*?)</td>'
+ FILE_NAME_PATTERN = r'id="file_info">\s*<strong>(?P<N>.*?)</strong>'
+
+ def setup(self):
+ self.multiDL = True
+
+ def handleFree(self):
+ data = dict(re.findall(r'(md5|file): "(.*?)"', self.html))
+ if len(data) != 2: self.parseError('File ID')
+
+ self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"])
+ self.req.http.lastURL = self.pyfile.url
+ self.load("http://www.wrzuc.to/ajax/server/prepair", post = {"md5": data['md5']})
+
+ self.req.http.lastURL = self.pyfile.url
+ self.html = self.load("http://www.wrzuc.to/ajax/server/download_link", post = {"file": data['file']})
+
+ data.update(re.findall(r'"(download_link|server_id)":"(.*?)"', self.html))
+ if len(data) != 4: self.parseError('Download URL')
+
+ download_url = "http://%s.wrzuc.to/pobierz/%s" % (data['server_id'], data['download_link'])
+ self.logDebug("Download URL: %s" % download_url)
+ self.download(download_url)
+
+getInfo = create_getInfo(WrzucTo)
+
diff --git a/module/plugins/hoster/XFileSharingPro.py b/module/plugins/hoster/XFileSharingPro.py
new file mode 100644
index 000000000..8e213e9bf
--- /dev/null
+++ b/module/plugins/hoster/XFileSharingPro.py
@@ -0,0 +1,286 @@
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: zoidberg
+"""
+
+import re
+from random import random
+from urllib import unquote
+from urlparse import urlparse
+from pycurl import FOLLOWLOCATION, LOW_SPEED_TIME
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, PluginParseError
+from module.plugins.ReCaptcha import ReCaptcha
+from module.utils import html_unescape
+
+class XFileSharingPro(SimpleHoster):
+ """
+ Common base for XFileSharingPro hosters like EasybytezCom, CramitIn, FiledinoCom...
+ Some hosters may work straight away when added to __pattern__
+ However, most of them will NOT work because they are either down or running a customized version
+ """
+ __name__ = "XFileSharingPro"
+ __type__ = "hoster"
+ __pattern__ = r"^unmatchable$"
+ __version__ = "0.11"
+ __description__ = """XFileSharingPro common hoster base"""
+ __author_name__ = ("zoidberg")
+ __author_mail__ = ("zoidberg@mujmail.cz")
+
+ FILE_NAME_PATTERN = r'<input type="hidden" name="fname" value="(?P<N>[^"]+)"'
+ FILE_SIZE_PATTERN = r'You have requested <font color="red">[^<]+</font> \((?P<S>[^<]+)\)</font>'
+ FILE_INFO_PATTERN = r'<tr><td align=right><b>Filename:</b></td><td nowrap>(?P<N>[^<]+)</td></tr>\s*.*?<small>\((?P<S>[^<]+)\)</small>'
+ FILE_OFFLINE_PATTERN = r'<(b|h2)>File Not Found</(b|h2)>'
+
+ WAIT_PATTERN = r'<span id="countdown_str">.*?>(\d+)</span>'
+ LONG_WAIT_PATTERN = r'(?P<H>\d+(?=\s*hour))?.*?(?P<M>\d+(?=\s*minute))?.*?(?P<S>\d+(?=\s*second))?'
+ OVR_DOWNLOAD_LINK_PATTERN = r'<h2>Download Link</h2>\s*<textarea[^>]*>([^<]+)'
+ OVR_KILL_LINK_PATTERN = r'<h2>Delete Link</h2>\s*<textarea[^>]*>([^<]+)'
+ CAPTCHA_URL_PATTERN = r'(http://[^"\']+?/captchas?/[^"\']+)'
+ RECAPTCHA_URL_PATTERN = r'http://[^"\']+?recaptcha[^"\']+?\?k=([^"\']+)"'
+ CAPTCHA_DIV_PATTERN = r'<b>Enter code.*?<div.*?>(.*?)</div>'
+ ERROR_PATTERN = r'class=["\']err["\'][^>]*>(.*?)</'
+
+ def setup(self):
+ self.__pattern__ = self.core.pluginManager.hosterPlugins[self.__name__]['pattern']
+ self.multiDL = True
+ self.chunkLimit = 1
+
+ def process(self, pyfile):
+ if not hasattr(self, "HOSTER_NAME"):
+ self.HOSTER_NAME = re.search(self.__pattern__, self.pyfile.url).group(1)
+ if not hasattr(self, "DIRECT_LINK_PATTERN"):
+ self.DIRECT_LINK_PATTERN = r'(http://(\w+\.%s|\d+\.\d+\.\d+\.\d+)(:\d+/d/|/files/\d+/\w+/)[^"\'<]+)' % self.HOSTER_NAME
+
+ self.captcha = self.errmsg = None
+ self.passwords = self.getPassword().splitlines()
+
+ if not re.match(self.__pattern__, self.pyfile.url):
+ if self.premium:
+ self.handleOverriden()
+ else:
+ self.fail("Only premium users can download from other hosters with %s" % self.HOSTER_NAME)
+ else:
+ try:
+ self.html = self.load(pyfile.url, cookies = False, decode = True)
+ self.file_info = self.getFileInfo()
+ except PluginParseError:
+ self.file_info = None
+
+ self.req.http.lastURL = self.pyfile.url
+
+ self.req.http.c.setopt(FOLLOWLOCATION, 0)
+ self.html = self.load(self.pyfile.url, cookies = True, decode = True)
+ self.header = self.req.http.header
+ self.req.http.c.setopt(FOLLOWLOCATION, 1)
+
+ self.location = None
+ found = re.search("Location\s*:\s*(.*)", self.header, re.I)
+ if found and re.match(self.DIRECT_LINK_PATTERN, found.group(1)):
+ self.location = found.group(1).strip()
+
+ if not self.file_info:
+ pyfile.name = html_unescape(unquote(urlparse(self.location if self.location else pyfile.url).path.split("/")[-1]))
+
+ if self.location:
+ self.startDownload(self.location)
+ elif self.premium:
+ self.handlePremium()
+ else:
+ self.handleFree()
+
+ def handleFree(self):
+ url = self.getDownloadLink()
+ self.logDebug("Download URL: %s" % url)
+ self.startDownload(url)
+
+ def getDownloadLink(self):
+ for i in range(5):
+ self.logDebug("Getting download link: #%d" % i)
+ data = self.getPostParameters()
+
+ 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)
+
+ found = re.search("Location\s*:\s*(.*)", self.header, re.I)
+ if found:
+ break
+
+ found = re.search(self.DIRECT_LINK_PATTERN, self.html, re.S)
+ if found:
+ break
+
+ else:
+ if captcha in self.err:
+ self.fail("No valid captcha code entered")
+ else:
+ self.fail("Download link not found")
+
+ return found.group(1)
+
+ def handlePremium(self):
+ self.html = self.load(self.pyfile.url, post = self.getPostParameters())
+ found = re.search(self.DIRECT_LINK_PATTERN, self.html)
+ if not found: self.parseError('DIRECT LINK')
+ self.startDownload(found.group(1))
+
+ def handleOverriden(self):
+ #only tested with easybytez.com
+ self.html = self.load("http://www.%s/" % self.HOSTER_NAME)
+ action, inputs = self.parseHtmlForm('')
+ upload_id = "%012d" % int(random()*10**12)
+ action += upload_id + "&js_on=1&utype=prem&upload_type=url"
+ inputs['tos'] = '1'
+ inputs['url_mass'] = self.pyfile.url
+ inputs['up1oad_type'] = 'url'
+
+ self.logDebug(self.HOSTER_NAME, action, inputs)
+ #wait for file to upload to easybytez.com
+ self.req.http.c.setopt(LOW_SPEED_TIME, 600)
+ self.html = self.load(action, post = inputs)
+
+ action, inputs = self.parseHtmlForm('F1')
+ if not inputs: self.parseError('TEXTAREA')
+ self.logDebug(self.HOSTER_NAME, inputs)
+ if inputs['st'] == 'OK':
+ self.html = self.load(action, post = inputs)
+ elif inputs['st'] == 'Can not leech file':
+ self.retry(max_tries=20, wait_time=180, reason=inputs['st'])
+ else:
+ self.fail(inputs['st'])
+
+ #get easybytez.com link for uploaded file
+ found = re.search(self.OVR_DOWNLOAD_LINK_PATTERN, self.html)
+ if not found: self.parseError('DIRECT LINK (OVR)')
+ self.pyfile.url = found.group(1)
+ self.retry()
+
+ def startDownload(self, link):
+ if self.captcha: self.correctCaptcha()
+ self.logDebug('DIRECT LINK: %s' % link)
+ self.download(link)
+
+ def checkErrors(self):
+ found = re.search(self.ERROR_PATTERN, self.html)
+ if found:
+ self.errmsg = found.group(1)
+ 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('(\d+)\s*(hour|minute|second)?', self.errmsg)])
+ self.setWait(wait_time, True)
+ self.wait()
+ elif 'limit' in self.errmsg:
+ self.setWait(3600, True)
+ self.wait()
+ self.retry(25)
+ elif 'captcha' in self.errmsg:
+ self.invalidCaptcha()
+ elif 'countdown' or 'Expired session' in self.errmsg:
+ self.retry(3)
+ elif 'maintenance' in self.errmsg:
+ self.tempOffline()
+ elif 'download files up to' in self.errmsg:
+ self.fail("File too large for free download")
+ elif 'requires premium' in self.errmsg:
+ self.fail("File can be downloaded by premium users only")
+ else:
+ self.fail(self.errmsg)
+
+ else:
+ self.errmsg = None
+
+ return self.errmsg
+
+ def getPostParameters(self):
+ for i in range(3):
+ if not self.errmsg: self.checkErrors()
+
+ action, inputs = self.parseHtmlForm('F1')
+ if not inputs:
+ action, inputs = self.parseHtmlForm("action=(''|\"\")")
+ if not inputs:
+ if self.errmsg:
+ self.retry()
+ else:
+ self.parseError("Form not found")
+
+ self.logDebug(self.HOSTER_NAME, inputs)
+
+ if 'op' in inputs and inputs['op'] in ('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:
+ found = re.search(self.WAIT_PATTERN, self.html)
+ if found:
+ wait_time = int(found.group(1)) + 1
+ self.setWait(wait_time, False)
+ else:
+ wait_time = 0
+
+ self.captcha = self.handleCaptcha(inputs)
+
+ if wait_time: self.wait()
+
+ self.errmsg = None
+ return inputs
+
+ else:
+ inputs['referer'] = self.pyfile.url
+
+ if self.premium:
+ inputs['method_premium'] = "Premium Download"
+ if 'method_free' in inputs: del inputs['method_free']
+ else:
+ inputs['method_free'] = "Free Download"
+ if 'method_premium' in inputs: del inputs['method_premium']
+
+ self.html = self.load(self.pyfile.url, post = inputs, ref = True)
+ self.errmsg = None
+
+ else: self.parseError('FORM: %s' % (inputs['op'] if 'op' in inputs else 'UNKNOWN'))
+
+ def handleCaptcha(self, inputs):
+ found = re.search(self.RECAPTCHA_URL_PATTERN, self.html)
+ if found:
+ recaptcha_key = unquote(found.group(1))
+ self.logDebug("RECAPTCHA KEY: %s" % recaptcha_key)
+ recaptcha = ReCaptcha(self)
+ inputs['recaptcha_challenge_field'], inputs['recaptcha_response_field'] = recaptcha.challenge(recaptcha_key)
+ return 1
+ else:
+ found = re.search(self.CAPTCHA_URL_PATTERN, self.html)
+ if found:
+ captcha_url = found.group(1)
+ inputs['code'] = self.decryptCaptcha(captcha_url)
+ return 2
+ else:
+ found = re.search(self.CAPTCHA_DIV_PATTERN, self.html, re.S)
+ if found:
+ captcha_div = found.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
+ return 0
+
+getInfo = create_getInfo(XFileSharingPro) \ No newline at end of file
diff --git a/module/plugins/hoster/YibaishiwuCom.py b/module/plugins/hoster/YibaishiwuCom.py
new file mode 100644
index 000000000..5926cc227
--- /dev/null
+++ b/module/plugins/hoster/YibaishiwuCom.py
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+"""
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License,
+ or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+ @author: zoidberg
+"""
+
+import re
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+from module.common.json_layer import json_loads
+
+class YibaishiwuCom(SimpleHoster):
+ __name__ = "YibaishiwuCom"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:www\.)?(?:u\.)?115.com/file/(?P<ID>\w+)"
+ __version__ = "0.11"
+ __description__ = """115.com"""
+ __author_name__ = ("zoidberg")
+
+ FILE_NAME_PATTERN = r"file_name: '(?P<N>[^']+)'"
+ FILE_SIZE_PATTERN = r"file_size: '(?P<S>[^']+)'"
+ FILE_OFFLINE_PATTERN = ur'<h3><i style="color:red;">哎呀!提取码不存在!不妨搜搜看吧!</i></h3>'
+
+ AJAX_URL_PATTERN = r'(/\?ct=(pickcode|download)[^"\']+)'
+
+ def handleFree(self):
+ found = re.search(self.AJAX_URL_PATTERN, self.html)
+ if not found: self.parseError("AJAX URL")
+ url = found.group(1)
+ self.logDebug(('FREEUSER' if found.group(2) == 'download' else 'GUEST') + ' URL', url)
+
+ response = json_loads(self.load("http://115.com" + url, decode = False))
+ for mirror in (response['urls'] if 'urls' in response else response['data'] if 'data' in response else []):
+ try:
+ url = mirror['url'].replace('\\','')
+ self.logDebug("Trying URL: " + url)
+ header = self.download(url)
+ break
+ except:
+ continue
+ else: self.fail('No working link found')
+
+getInfo = create_getInfo(YibaishiwuCom) \ No newline at end of file
diff --git a/module/plugins/hoster/ZeveraCom.py b/module/plugins/hoster/ZeveraCom.py
index d1fa80802..8be725d2f 100644
--- a/module/plugins/hoster/ZeveraCom.py
+++ b/module/plugins/hoster/ZeveraCom.py
@@ -1,83 +1,108 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-from module.plugins.Hoster import Hoster
-from module.utils import html_unescape
-from urllib import quote, unquote
-from time import sleep
-
-class ZeveraCom(Hoster):
- __name__ = "ZeveraCom"
- __version__ = "0.11"
- __type__ = "hoster"
- __pattern__ = r"http://zevera.com/.*"
- __description__ = """zevera.com hoster plugin"""
- __author_name__ = ("zoidberg")
- __author_mail__ = ("zoidberg@mujmail.cz")
-
- api_url = "http://zevera.com/API.ashx"
-
- def process(self, pyfile):
- if not self.account:
- self.logError(_("Please enter your zevera.com account or deactivate this plugin"))
- self.fail("No zevera.com account provided")
-
- self.logDebug("zevera.com: Old URL: %s" % pyfile.url)
-
- last_size = retries = 0
- olink = self.pyfile.url #quote(self.pyfile.url.encode('utf_8'))
-
- for i in range(100):
- self.retData = self.account.loadAPIRequest(self.req, cmd = 'download_request', olink = olink)
- self.checkAPIErrors(self.retData)
-
- if self.retData['FileInfo']['StatusID'] == 100:
- break
- elif self.retData['FileInfo']['StatusID'] == 99:
- self.fail('Failed to initialize download (99)')
- else:
- if self.retData['FileInfo']['Progress']['BytesReceived'] <= last_size:
- if retries >= 6:
- self.fail('Failed to initialize download (%d)' % self.retData['FileInfo']['StatusID'] )
- retries += 1
- else:
- retries = 0
-
- last_size = self.retData['FileInfo']['Progress']['BytesReceived']
-
- pyfile.progress = self.retData['FileInfo']['Progress']['Percentage']
-
- self.setWait(self.retData['Update_Wait'])
- self.wait()
-
- pyfile.progress = 0
- pyfile.name = self.crazyDecode(self.retData['FileInfo']['RealFileName'])
- pyfile.size = self.retData['FileInfo']['FileSizeInBytes']
-
- self.retData = self.account.loadAPIRequest(self.req, cmd = 'download_start', FileID = self.retData['FileInfo']['FileID'])
- self.checkAPIErrors(self.retData)
-
- self.download(self.api_url, get = {
- 'cmd': "open_stream",
- 'login': self.account.loginname,
- 'pass': self.account.password,
- 'FileID': self.retData['FileInfo']['FileID'],
- 'startBytes': 0
- }
- )
-
- def checkAPIErrors(self, retData):
- if not retData:
- self.fail('Unknown API response')
-
- if retData['ErrorCode']:
- self.logError(retData['ErrorCode'], retData['ErrorMessage'])
- self.fail('ERROR: ' + retData['ErrorMessage'])
-
- if self.pyfile.size / 1024000 > retData['AccountInfo']['AvailableTODAYTrafficForUseInMBytes']:
- self.logWarning("Not enough data left to download the file")
-
- def crazyDecode(self, ustring):
- # accepts decoded ie. unicode string - API response is double-quoted, double-utf8-encoded
- # no idea what the proper order of calling these functions would be :-/
- return html_unescape(unquote(unquote(ustring.replace('@DELIMITER@','#'))).encode('raw_unicode_escape').decode('utf-8')) \ No newline at end of file
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from module.plugins.Hoster import Hoster
+from module.utils import html_unescape
+from urllib import quote, unquote
+from time import sleep
+
+class ZeveraCom(Hoster):
+ __name__ = "ZeveraCom"
+ __version__ = "0.20"
+ __type__ = "hoster"
+ __pattern__ = r"http://zevera.com/.*"
+ __description__ = """zevera.com hoster plugin"""
+ __author_name__ = ("zoidberg")
+ __author_mail__ = ("zoidberg@mujmail.cz")
+
+ def setup(self):
+ self.resumeDownload = self.multiDL = True
+ self.chunkLimit = 1
+
+ def process(self, pyfile):
+ if not self.account:
+ self.logError(_("Please enter your zevera.com account or deactivate this plugin"))
+ self.fail("No zevera.com account provided")
+
+ self.logDebug("zevera.com: Old URL: %s" % pyfile.url)
+
+ if self.account.getAPIData(self.req, cmd = "checklink", olink = pyfile.url) != "Alive":
+ self.fail("Offline or not downloadable - contact Zevera support")
+
+ header = self.account.getAPIData(self.req, just_header = True, cmd="generatedownloaddirect", olink = pyfile.url)
+ if not "location" in header:
+ self.fail("Unable to initialize download - contact Zevera support")
+
+ self.download(header['location'], disposition = True)
+
+ check = self.checkDownload({"error" : 'action="ErrorDownload.aspx'})
+ if check == "error":
+ self.fail("Error response received - contact Zevera support")
+
+ """
+ # BitAPI not used - defunct, probably abandoned by Zevera
+
+ api_url = "http://zevera.com/API.ashx"
+
+ def process(self, pyfile):
+ if not self.account:
+ self.logError(_("Please enter your zevera.com account or deactivate this plugin"))
+ self.fail("No zevera.com account provided")
+
+ self.logDebug("zevera.com: Old URL: %s" % pyfile.url)
+
+ last_size = retries = 0
+ olink = self.pyfile.url #quote(self.pyfile.url.encode('utf_8'))
+
+ for i in range(100):
+ self.retData = self.account.loadAPIRequest(self.req, cmd = 'download_request', olink = olink)
+ self.checkAPIErrors(self.retData)
+
+ if self.retData['FileInfo']['StatusID'] == 100:
+ break
+ elif self.retData['FileInfo']['StatusID'] == 99:
+ self.fail('Failed to initialize download (99)')
+ else:
+ if self.retData['FileInfo']['Progress']['BytesReceived'] <= last_size:
+ if retries >= 6:
+ self.fail('Failed to initialize download (%d)' % self.retData['FileInfo']['StatusID'] )
+ retries += 1
+ else:
+ retries = 0
+
+ last_size = self.retData['FileInfo']['Progress']['BytesReceived']
+
+ self.setWait(self.retData['Update_Wait'])
+ self.wait()
+
+ pyfile.name = self.retData['FileInfo']['RealFileName']
+ pyfile.size = self.retData['FileInfo']['FileSizeInBytes']
+
+ self.retData = self.account.loadAPIRequest(self.req, cmd = 'download_start', FileID = self.retData['FileInfo']['FileID'])
+ self.checkAPIErrors(self.retData)
+
+ self.download(self.api_url, get = {
+ 'cmd': "open_stream",
+ 'login': self.account.loginname,
+ 'pass': self.account.password,
+ 'FileID': self.retData['FileInfo']['FileID'],
+ 'startBytes': 0
+ }
+ )
+
+ def checkAPIErrors(self, retData):
+ if not retData:
+ self.fail('Unknown API response')
+
+ if retData['ErrorCode']:
+ self.logError(retData['ErrorCode'], retData['ErrorMessage'])
+ #self.fail('ERROR: ' + retData['ErrorMessage'])
+
+ if self.pyfile.size / 1024000 > retData['AccountInfo']['AvailableTODAYTrafficForUseInMBytes']:
+ self.logWarning("Not enough data left to download the file")
+
+ def crazyDecode(self, ustring):
+ # accepts decoded ie. unicode string - API response is double-quoted, double-utf8-encoded
+ # no idea what the proper order of calling these functions would be :-/
+ return html_unescape(unquote(unquote(ustring.replace('@DELIMITER@','#'))).encode('raw_unicode_escape').decode('utf-8'))
+ """ \ No newline at end of file
diff --git a/module/plugins/hoster/ZippyshareCom.py b/module/plugins/hoster/ZippyshareCom.py
index 5b32b4068..6b0b01003 100644
--- a/module/plugins/hoster/ZippyshareCom.py
+++ b/module/plugins/hoster/ZippyshareCom.py
@@ -1,51 +1,186 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-import re
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+import re, subprocess, tempfile, os
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, timestamp
+from module.plugins.ReCaptcha import ReCaptcha
+from module.common.json_layer import json_loads
class ZippyshareCom(SimpleHoster):
__name__ = "ZippyshareCom"
__type__ = "hoster"
- __pattern__ = r"(http://www\d{0,2}\.zippyshare.com)/v(?:/|iew.jsp.*key=)(\d+)"
- __version__ = "0.31"
+ __pattern__ = r"(?P<HOST>http://www\d{0,2}\.zippyshare.com)/v(?:/|iew.jsp.*key=)(?P<KEY>\d+)"
+ __version__ = "0.36"
__description__ = """Zippyshare.com Download Hoster"""
__author_name__ = ("spoob", "zoidberg")
__author_mail__ = ("spoob@pyload.org", "zoidberg@mujmail.cz")
+ __config__ = [("swfdump_path", "string", "Path to swfdump", "")]
FILE_NAME_PATTERN = r'>Name:</font>\s*<font [^>]*>(?P<N>[^<]+)</font><br />'
FILE_SIZE_PATTERN = r'>Size:</font>\s*<font [^>]*>(?P<S>[0-9.,]+) (?P<U>[kKMG]+)i?B</font><br />'
FILE_OFFLINE_PATTERN = r'>File does not exist on this server</div>'
- DOWNLOAD_URL_PATTERN = r"document\.getElementById\('dlbutton'\).href = ([^;]+);"
- SEED_PATTERN = r"seed: (\d*)"
+ DOWNLOAD_URL_PATTERN = r"<script type=\"text/javascript\">([^<]*?)document\.getElementById\('dlbutton'\).href = ([^;]+);"
+ SEED_PATTERN = r'swfobject.embedSWF\("([^"]+)".*?seed: (\d+)'
+ CAPTCHA_KEY_PATTERN = r'Recaptcha.create\("([^"]+)"'
+ CAPTCHA_SHORTENCODE_PATTERN = r"shortencode: '([^']+)'"
+ CAPTCHA_DOWNLOAD_PATTERN = r"document.location = '([^']+)'"
+
+ LAST_KNOWN_VALUES = (9, 2374755) #time = (seed * multiply) % modulo
def setup(self):
self.html = None
self.wantReconnect = False
self.multiDL = True
- def handleFree(self):
+ def handleFree(self):
url = self.get_file_url()
+ if not url: self.fail("Download URL not found.")
self.logDebug("Download URL %s" % url)
self.download(url, cookies = True)
+ check = self.checkDownload({
+ "swf_values": re.compile(self.SEED_PATTERN)
+ })
+
+ if check == "swf_values":
+ swf_sts = self.getStorage("swf_sts")
+ if not swf_sts:
+ self.setStorage("swf_sts", 2)
+ self.setStorage("swf_stamp", 0)
+ elif swf_sts == '1':
+ self.setStorage("swf_sts", 2)
+
+ self.retry(max_tries = 1)
+
def get_file_url(self):
""" returns the absolute downloadable filepath
"""
- file_host, file_key = re.search(self.__pattern__, self.pyfile.url).groups()
+ url = multiply = modulo = None
- found = re.search(self.DOWNLOAD_URL_PATTERN, self.html)
+ found = re.search(self.DOWNLOAD_URL_PATTERN, self.html, re.S)
if found:
- url = self.js.eval(found.group(1))
+ #Method #1: JS eval
+ url = self.js.eval("\n".join(found.groups()))
else:
+ #Method #2: SWF eval
seed_search = re.search(self.SEED_PATTERN, self.html)
- if seed_search is None: self.parseError('SEED')
+ if seed_search:
+ swf_url, file_seed = seed_search.groups()
+
+ swf_sts = self.getStorage("swf_sts")
+ swf_stamp = int(self.getStorage("swf_stamp") or 0)
+ swf_version = self.getStorage("version")
+ self.logDebug("SWF", swf_sts, swf_stamp, swf_version)
+
+ if not swf_sts:
+ self.logDebug('Using default values')
+ multiply, modulo = self.LAST_KNOWN_VALUES
+ elif swf_sts == "1":
+ self.logDebug('Using stored values')
+ multiply = self.getStorage("multiply")
+ modulo = self.getStorage("modulo")
+ elif swf_sts == "2":
+ if swf_version < self.__version__:
+ self.logDebug('Reverting to default values')
+ self.setStorage("swf_sts", "")
+ self.setStorage("version", self.__version__)
+ multiply, modulo = self.LAST_KNOWN_VALUES
+ elif (swf_stamp + 3600000) < timestamp():
+ swfdump = self.get_swfdump_path()
+ if swfdump:
+ multiply, modulo = self.get_swf_values(self.file_info['HOST'] + swf_url, swfdump)
+ else:
+ self.logWarning("Swfdump not found. Install swftools to bypass captcha.")
+
+ if multiply and modulo:
+ self.logDebug("TIME = (%s * %s) %s" % (file_seed, multiply, modulo))
+ url = "/download?key=%s&time=%d" % (self.file_info['KEY'], (int(file_seed) * int(multiply)) % int(modulo))
+
+ if not url:
+ #Method #3: Captcha
+ url = self.do_recaptcha()
+
+ return self.file_info['HOST'] + url
+
+ def get_swf_values(self, swf_url, swfdump):
+ self.logDebug('Parsing values from %s' % swf_url)
+ multiply = modulo = None
+
+ fd, fpath = tempfile.mkstemp()
+ try:
+ swf_data = self.load(swf_url)
+ os.write(fd, swf_data)
+
+ p = subprocess.Popen([swfdump, '-a', fpath], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = p.communicate()
+
+ if err:
+ self.logError(err)
+ else:
+ m_str = re.search(r'::break.*?{(.*?)}', out, re.S).group(1)
+ multiply = re.search(r'pushbyte (\d+)', m_str).group(1)
+ modulo = re.search(r'pushint (\d+)', m_str).group(1)
+ finally:
+ os.close(fd)
+ os.remove(fpath)
+
+ if multiply and modulo:
+ self.setStorage("multiply", multiply)
+ self.setStorage("modulo", modulo)
+ self.setStorage("swf_sts", 1)
+ self.setStorage("version", self.__version__)
+ else:
+ self.logError("Parsing SWF failed: swfdump not installed or plugin out of date")
+ self.setStorage("swf_sts", 2)
- file_seed = int(seed_search.group(1))
- time = str((file_seed * 24) % 6743256)
- url = "/download?key=" + str(file_key) + "&time=" + str(time)
+ self.setStorage("swf_stamp", timestamp())
+
+ return multiply, modulo
+
+ def get_swfdump_path(self):
+ # used for detecting if swfdump is installed
+ def is_exe(ppath):
+ return os.path.isfile(ppath) and os.access(ppath, os.X_OK)
+
+ program = self.getConfig("swfdump_path") or "swfdump"
+ swfdump = None
+ ppath, pname = os.path.split(program)
+ if ppath:
+ if is_exe(program):
+ swfdump = program
+ else:
+ for ppath in os.environ["PATH"].split(os.pathsep):
+ exe_file = os.path.join(ppath, program)
+ if is_exe(exe_file):
+ swfdump = exe_file
+
+ # return path to the executable or None if not found
+ return swfdump
+
+ def do_recaptcha(self):
+ self.logDebug('Trying to solve captcha')
+ captcha_key = re.search(self.CAPTCHA_KEY_PATTERN, self.html).group(1)
+ shortencode = re.search(self.CAPTCHA_SHORTENCODE_PATTERN, self.html).group(1)
+ url = re.search(self.CAPTCHA_DOWNLOAD_PATTERN, self.html).group(1)
+
+ recaptcha = ReCaptcha(self)
+
+ for i in range(5):
+ challenge, code = recaptcha.challenge(captcha_key)
+
+ response = json_loads(self.load(self.file_info['HOST'] + '/rest/captcha/test',
+ post={'challenge': challenge,
+ 'response': code,
+ 'shortencode': shortencode}))
+ self.logDebug("reCaptcha response : %s" % response)
+ if response == True:
+ self.correctCaptcha
+ break
+ else:
+ self.invalidCaptcha()
+ else: self.fail("Invalid captcha")
- return file_host + url
+ return url
getInfo = create_getInfo(ZippyshareCom) \ No newline at end of file