summaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
Diffstat (limited to 'module')
-rw-r--r--module/network/HTTPRequest.py1
-rw-r--r--module/plugins/accounts/AlldebridCom.py27
-rw-r--r--module/plugins/accounts/BayfilesCom.py17
-rw-r--r--module/plugins/hooks/AlldebridCom.py26
-rw-r--r--module/plugins/hoster/AlldebridCom.py65
-rw-r--r--module/plugins/hoster/BitshareCom.py2
-rw-r--r--module/plugins/hoster/CramitIn.py20
-rw-r--r--module/plugins/hoster/EasybytezCom.py106
-rw-r--r--module/plugins/hoster/FiledinoCom.py18
-rw-r--r--module/plugins/hoster/FreakshareCom.py27
-rw-r--r--module/plugins/hoster/RarefileNet.py26
-rw-r--r--module/plugins/hoster/XFileSharingPro.py224
-rw-r--r--module/plugins/internal/SimpleHoster.py54
13 files changed, 482 insertions, 131 deletions
diff --git a/module/network/HTTPRequest.py b/module/network/HTTPRequest.py
index 40f18f2a5..d4c33bbff 100644
--- a/module/network/HTTPRequest.py
+++ b/module/network/HTTPRequest.py
@@ -31,6 +31,7 @@ def myquote(url):
return quote(url.encode('utf_8') if isinstance(url, unicode) else url, safe="%/:=&?~#+!$,;'@()*[]")
def myurlencode(data):
+ data = dict(data)
return urlencode(dict((x.encode('utf_8') if isinstance(x, unicode) else x, \
y.encode('utf_8') if isinstance(y, unicode) else y ) for x, y in data.iteritems()))
diff --git a/module/plugins/accounts/AlldebridCom.py b/module/plugins/accounts/AlldebridCom.py
new file mode 100644
index 000000000..4968e9bdd
--- /dev/null
+++ b/module/plugins/accounts/AlldebridCom.py
@@ -0,0 +1,27 @@
+from module.plugins.Account import Account
+import xml.dom.minidom as dom
+from time import time
+
+class AlldebridCom(Account):
+ __name__ = "AlldebridCom"
+ __version__ = "0.1"
+ __type__ = "account"
+ __description__ = """AllDebrid.com account plugin"""
+ __author_name__ = ("Andy, Voigt")
+ __author_mail__ = ("spamsales@online.de")
+
+ def loadAccountInfo(self, user, req):
+ data = self.getAccountData(user)
+ page = req.load("http://www.alldebrid.com/api.php?action=info_user&login=%s&pw=%s" % (user, data["password"]))
+ self.log.debug(page)
+ xml = dom.parseString(page)
+ account_info = {"validuntil": (time()+int(xml.getElementsByTagName("date")[0].childNodes[0].nodeValue)*86400),
+ "trafficleft": -1}
+
+ return account_info
+
+ def login(self, user, data, req):
+ page = req.load("http://www.alldebrid.com/register/?action=login&login_login=%s&login_password=%s" % (user, data["password"]))
+
+ if "This login doesn't exist" in page:
+ self.wrongPassword()
diff --git a/module/plugins/accounts/BayfilesCom.py b/module/plugins/accounts/BayfilesCom.py
index 803e602cb..0d036488b 100644
--- a/module/plugins/accounts/BayfilesCom.py
+++ b/module/plugins/accounts/BayfilesCom.py
@@ -20,23 +20,28 @@
from module.plugins.Account import Account
from module.common.json_layer import json_loads
import re
-from time import mktime, strptime
+from time import time, mktime, strptime
class BayfilesCom(Account):
__name__ = "BayfilesCom"
- __version__ = "0.01"
+ __version__ = "0.02"
__type__ = "account"
__description__ = """bayfiles.com account plugin"""
__author_name__ = ("zoidberg")
__author_mail__ = ("zoidberg@mujmail.cz")
def loadAccountInfo(self, user, req):
- response = json_loads(req.load("http://api.bayfiles.com/v1/account/info"))
- self.logDebug(response)
-
+ for i in range(2):
+ response = json_loads(req.load("http://api.bayfiles.com/v1/account/info"))
+ self.logDebug(response)
+ if not response["error"]:
+ break
+ self.logWarning(response["error"])
+ self.relogin()
+
return {"premium": bool(response['premium']), \
"trafficleft": -1, \
- "validuntil": response['expires'] if response['expires'] > 0 else -1}
+ "validuntil": response['expires'] if response['expires'] >= int(time()) else -1}
def login(self, user, data, req):
response = json_loads(req.load("http://api.bayfiles.com/v1/account/login/%s/%s" % (user, data["password"])))
diff --git a/module/plugins/hooks/AlldebridCom.py b/module/plugins/hooks/AlldebridCom.py
new file mode 100644
index 000000000..d3d6ff294
--- /dev/null
+++ b/module/plugins/hooks/AlldebridCom.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+
+# should be working
+
+from module.network.RequestFactory import getURL
+from module.plugins.internal.MultiHoster import MultiHoster
+
+class AlldebridCom(MultiHoster):
+ __name__ = "AlldebridCom"
+ __version__ = "0.1"
+ __type__ = "hook"
+
+ __config__ = [("activated", "bool", "Activated", "False"),
+ ("https", "bool", "Enable HTTPS", "False")]
+
+ __description__ = """Real-Debrid.com hook plugin"""
+ __author_name__ = ("Andy, Voigt")
+ __author_mail__ = ("spamsales@online.de")
+
+ replacements = [("freakshare.net", "freakshare.com")]
+
+ def getHoster(self):
+ https = "https" if self.getConfig("https") else "http"
+ page = getURL(https + "://www.alldebrid.com/api.php?action=get_host").replace("\"","").strip()
+
+ return[x.strip() for x in page.split(",") if x.strip()]
diff --git a/module/plugins/hoster/AlldebridCom.py b/module/plugins/hoster/AlldebridCom.py
new file mode 100644
index 000000000..56e3a9040
--- /dev/null
+++ b/module/plugins/hoster/AlldebridCom.py
@@ -0,0 +1,65 @@
+#!/usr/nv python
+# -*- coding: utf-8 -*-
+
+import BeautifulSoup
+from urllib import quote, unquote
+from random import randrange
+
+from module.plugins.Hoster import Hoster
+
+class AlldebridCom(Hoster):
+ __name__ = "AlldebridCom"
+ __version__ = "0.1"
+ __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):
+ url="http://www.alldebrid.com/service.php?link=%s" %(pyfile.url)
+
+ page = self.load(url)
+
+ soup = BeautifulSoup.BeautifulSoup(page)
+ for link in soup.findAll("a"):
+ new_url = link.get("href")
+
+
+ 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>"})
+
+ 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/BitshareCom.py b/module/plugins/hoster/BitshareCom.py
index 794e978b2..d6288883d 100644
--- a/module/plugins/hoster/BitshareCom.py
+++ b/module/plugins/hoster/BitshareCom.py
@@ -92,6 +92,8 @@ class BitshareCom(Hoster):
self.handleFree()
def handleFree(self):
+ if "Only Premium members can access this file" in self.html:
+ self.fail("Only Premium members can access this file")
# Get download info
self.logDebug("Getting download info")
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/EasybytezCom.py b/module/plugins/hoster/EasybytezCom.py
index 4fbd08756..25de9b341 100644
--- a/module/plugins/hoster/EasybytezCom.py
+++ b/module/plugins/hoster/EasybytezCom.py
@@ -16,129 +16,59 @@
@author: zoidberg
"""
-import re
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
-from random import random
+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+).*"
- __version__ = "0.05"
+ __version__ = "0.06"
__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>'
- 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))
+ 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)
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))
+
+ action, inputs = self.parseHtmlForm('name="F1"')
if not inputs: parseError('TEXTAREA')
- self.logDebug(inputs)
+ self.logDebug(inputs)
if inputs['st'] == 'OK':
self.html = self.load(action, post = inputs)
else:
self.fail(inputs['st'])
-
+
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/FiledinoCom.py b/module/plugins/hoster/FiledinoCom.py
new file mode 100644
index 000000000..7d1a82df4
--- /dev/null
+++ b/module/plugins/hoster/FiledinoCom.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo
+
+class FiledinoCom(XFileSharingPro):
+ __name__ = "FiledinoCom"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:\w*\.)*filedino.com/\w{12}"
+ __version__ = "0.01"
+ __description__ = """FileDino.com hoster plugin"""
+ __author_name__ = ("zoidberg")
+ __author_mail__ = ("zoidberg@mujmail.cz")
+
+ FILE_SIZE_PATTERN = r'File Size : </span><span class="runninggreysmall">(?P<S>.+?)</span>'
+
+ HOSTER_NAME = "filedino.com"
+ DIRECT_LINK_PATTERN = r'http://www\.filedino\.com/cgi-bin/dl\.cgi/'
+
+getInfo = create_getInfo(FiledinoCom) \ No newline at end of file
diff --git a/module/plugins/hoster/FreakshareCom.py b/module/plugins/hoster/FreakshareCom.py
index 869b8a99e..a36fe7207 100644
--- a/module/plugins/hoster/FreakshareCom.py
+++ b/module/plugins/hoster/FreakshareCom.py
@@ -9,7 +9,7 @@ class FreakshareCom(Hoster):
__name__ = "FreakshareCom"
__type__ = "hoster"
__pattern__ = r"http://(?:www\.)?freakshare\.(net|com)/files/\S*?/"
- __version__ = "0.33"
+ __version__ = "0.34"
__description__ = """Freakshare.com Download Hoster"""
__author_name__ = ("sitacuisses","spoob","mkaay")
__author_mail__ = ("sitacuisses@yahoo.de","spoob@pyload.org","mkaay@mkaay.de")
@@ -36,10 +36,15 @@ 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. <"})
+
if check == "bad":
self.fail("Bad Try.")
-
+ if check == "paralell":
+ self.setWait(300, True)
+ self.wait()
+ self.retry()
def prepare(self):
pyfile = self.pyfile
@@ -134,10 +139,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 = {n: v for v, n in to_sort}
herewego = self.load(self.pyfile.url, None, request_options) # the actual download-Page
@@ -146,21 +148,16 @@ class FreakshareCom(Hoster):
# fp.write(herewego)
to_sort = re.findall(r"<input\stype=\".*?\"\svalue=\"(\S*?)\".*?name=\"(\S*?)\"\s.*?\/>", herewego)
- request_options = []
+ request_options = {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/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/XFileSharingPro.py b/module/plugins/hoster/XFileSharingPro.py
new file mode 100644
index 000000000..c7a59c81e
--- /dev/null
+++ b/module/plugins/hoster/XFileSharingPro.py
@@ -0,0 +1,224 @@
+# -*- 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 pycurl import FOLLOWLOCATION
+from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
+from module.plugins.ReCaptcha import ReCaptcha
+
+class XFileSharingPro(SimpleHoster):
+ """
+ Common base for XFileSharingPro hosters like EasybytezCom, CramitIn, FiledinoCom...
+ Some hosters may work straight away when added to __pattern__
+ """
+ __name__ = "XFileSharingPro"
+ __type__ = "hoster"
+ __pattern__ = r"http://(?:\w*\.)*(boosterking\.com|migahost\.com|fileband\.com|ravishare\.com)/\w{12}"
+ __version__ = "0.01"
+ __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>'
+ 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=([^"\']+)"'
+ ERROR_PATTERN = r'class="err">(.*?)<'
+
+ DIRECT_LINK_PATTERN = r'This direct link.*?href=["\'](.*?)["\']'
+
+ def setup(self):
+ self.HOSTER_NAME = re.search(self.__pattern__, self.pyfile.url).group(1)
+ self.multiDL = True
+
+ def process(self, pyfile):
+ 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:
+ self.html = self.load(pyfile.url, cookies = False, decode = True)
+ self.file_info = self.getFileInfo()
+
+ self.header = self.load(self.pyfile.url, just_header = True, cookies = True)
+ self.logDebug(self.header)
+
+ if 'location' in self.header and re.match(self.DIRECT_LINK_PATTERN, self.header['location']):
+ self.startDownload(self.header['location'])
+ elif self.premium:
+ self.handlePremium()
+ else:
+ self.handleFree()
+
+ def handleFree(self):
+ for i in range(5):
+ data = self.getPostParameters()
+
+ self.req.http.c.setopt(FOLLOWLOCATION, 0)
+ self.html = self.load(self.pyfile.url, post = data, ref = 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
+ elif not self.checkErrors():
+ found = re.search(self.DIRECT_LINK_PATTERN, self.html, re.S)
+ if not found: self.parseError('Download Link')
+ break
+
+ else: self.fail("No valid captcha code entered")
+
+ self.startDownload(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):
+ 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(action, inputs)
+ self.html = self.load(action, post = inputs)
+
+ action, inputs = self.parseHtmlForm('name="F1"')
+ if not inputs: parseError('TEXTAREA')
+ self.logDebug(inputs)
+ if inputs['st'] == 'OK':
+ self.html = self.load(action, post = inputs)
+ else:
+ self.fail(inputs['st'])
+
+ 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(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 'captcha' in self.errmsg:
+ self.invalidCaptcha()
+ elif 'countdown' in self.errmsg:
+ self.retry(3)
+
+ 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("action=['\"]{2}")
+ if not inputs:
+ if self.errmsg:
+ self.retry()
+ else:
+ self.parseError("Form not found")
+
+ self.logDebug(inputs)
+
+ if 'op' in inputs and inputs['op'] == 'download2':
+ 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()
+
+ 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
+ return 0
+
+ def urlParseFileName(self):
+ return html_unescape(urlparse(self.pyfile.url).path.split("/")[-1])
+
+getInfo = create_getInfo(XFileSharingPro) \ No newline at end of file
diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py
index 555eefee3..3ae780ba2 100644
--- a/module/plugins/internal/SimpleHoster.py
+++ b/module/plugins/internal/SimpleHoster.py
@@ -42,8 +42,11 @@ def parseHtmlTagAttrValue(attr_name, tag):
m = re.search(r"%s\s*=\s*([\"']?)((?<=\")[^\"]+|(?<=')[^']+|[^\s\"'][^>\s]+)\1" % attr_name, tag)
return m.group(2) if m else ''
-def parseFileInfo(self, url = '', html = '', infomode = False):
+def parseFileInfo(self, url = '', html = ''):
info = {"name" : url, "size" : 0, "status" : 3}
+
+ if hasattr(self, "pyfile"):
+ url = self.pyfile.url
if hasattr(self, "req") and self.req.http.code == '404':
info['status'] = 1
@@ -58,9 +61,14 @@ def parseFileInfo(self, url = '', html = '', infomode = False):
info['status'] = 1
else:
online = False
+ try:
+ info.update(re.match(self.__pattern__, url).groupdict())
+ except:
+ pass
+
for pattern in ("FILE_INFO_PATTERN", "FILE_NAME_PATTERN", "FILE_SIZE_PATTERN"):
try:
- info = dict(info, **re.search(getattr(self, pattern), html).groupdict())
+ info.update(re.search(getattr(self, pattern), html).groupdict())
online = True
except AttributeError:
continue
@@ -77,12 +85,10 @@ def parseFileInfo(self, url = '', html = '', infomode = False):
if 'units' in info: info['size'] += info['units']
info['size'] = parseFileSize(info['size'])
- if infomode:
- if hasattr(self, "pyfile"):
- info = dict(info, **re.match(self.__pattern__, self.pyfile.url).groupdict())
- return info
- else:
- return info['name'], info['size'], info['status'], url
+ if hasattr(self, "file_info"):
+ self.file_info = info
+
+ return info['name'], info['size'], info['status'], url
def create_getInfo(plugin):
def getInfo(urls):
@@ -106,7 +112,7 @@ class PluginParseError(Exception):
class SimpleHoster(Hoster):
__name__ = "SimpleHoster"
- __version__ = "0.20"
+ __version__ = "0.22"
__pattern__ = None
__type__ = "hoster"
__description__ = """Base hoster plugin"""
@@ -127,7 +133,10 @@ class SimpleHoster(Hoster):
SH_BROKEN_ENCODING = False # Set to True or encoding name if encoding in http header is not correct
SH_COOKIES = True # or False or list of tuples [(domain, name, value)]
- SH_CHECK_TRAFFIC = False # True = force check traffic left for a premium account
+ SH_CHECK_TRAFFIC = False # True = force check traffic left for a premium account
+
+ def init(self):
+ self.file_info = {}
def setup(self):
self.resumeDownload = self.multiDL = True if self.premium else False
@@ -136,7 +145,7 @@ class SimpleHoster(Hoster):
def process(self, pyfile):
pyfile.url = replace_patterns(pyfile.url, self.FILE_URL_REPLACEMENTS)
self.html = self.load(pyfile.url, decode = not self.SH_BROKEN_ENCODING, cookies = self.SH_COOKIES)
- self.file_info = self.getFileInfo()
+ self.getFileInfo()
if self.premium and (not self.SH_CHECK_TRAFFIC or self.checkTrafficLeft()):
self.handlePremium()
else:
@@ -147,25 +156,26 @@ class SimpleHoster(Hoster):
if hasattr(self, "TEMP_OFFLINE_PATTERN") and re.search(self.TEMP_OFFLINE_PATTERN, self.html):
self.tempOffline()
- file_info = parseFileInfo(self, infomode = True)
- if file_info['status'] == 1:
+ name, size, status = parseFileInfo(self)[:3]
+
+ if status == 1:
self.offline()
- elif file_info['status'] != 2:
- self.logDebug(file_info)
+ elif status != 2:
+ self.logDebug(self.file_info)
self.parseError('File info')
- if file_info['name']:
- self.pyfile.name = file_info['name']
+ if name:
+ self.pyfile.name = name
else:
self.pyfile.name = html_unescape(urlparse(self.pyfile.url).path.split("/")[-1])
- if file_info['size']:
- self.pyfile.size = file_info['size']
+ if size:
+ self.pyfile.size = size
else:
self.logError("File size not parsed")
self.logDebug("FILE NAME: %s FILE SIZE: %s" % (self.pyfile.name, self.pyfile.size))
- return file_info
+ return self.file_info
def handleFree(self):
self.fail("Free download not implemented")
@@ -179,10 +189,10 @@ class SimpleHoster(Hoster):
def parseHtmlForm(self, attr_str):
inputs = {}
action = None
- form = re.search(r"(?P<tag><form[^>]*%s[^>]*>)(?P<content>.*?)</form[^>]*>" % attr_str, self.html, re.S)
+ form = re.search(r"(?P<tag><form[^>]*%s[^>]*>)(?P<content>.*?)</(form|body|html)[^>]*>" % attr_str, self.html, re.S | re.I)
if form:
action = parseHtmlTagAttrValue("action", form.group('tag'))
- for input in re.finditer(r'(<(?:input|textarea)[^>]*>)', form.group('content')):
+ for input in re.finditer(r'(<(?:input|textarea)[^>]*>)', form.group('content'), re.S | re.I):
name = parseHtmlTagAttrValue("name", input.group(1))
if name:
inputs[name] = parseHtmlTagAttrValue("value", input.group(1))