diff options
| author | 2013-07-21 12:58:42 +0200 | |
|---|---|---|
| committer | 2013-07-21 12:58:42 +0200 | |
| commit | 37d898f681e41fe9c9a8719a540eda59bfedd448 (patch) | |
| tree | faecf5455aa91155ed7c762701221f171d14bb0d | |
| parent | Using the same translatable string (diff) | |
| download | pyload-37d898f681e41fe9c9a8719a540eda59bfedd448.tar.xz | |
Normalize line endings to avoid line endings merge conflicts
41 files changed, 4697 insertions, 4676 deletions
| diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..e34533a0d --- /dev/null +++ b/.gitattributes @@ -0,0 +1,21 @@ +# Set default behaviour, in case users don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files we want to always be normalized and converted  +# to native line endings on checkout. +*.py text +*.js text +*.po text +*.cfg text +*.md text +*.in text +*.txt text +*.sh text +*.json text +*.html text +.htm text + +# Denote all files that are truly binary and should not be modified. +*.png binary +*.jpg binary +*.mo binary
\ No newline at end of file diff --git a/module/config/default.conf b/module/config/default.conf index 335ca10fe..2e9152ba2 100644 --- a/module/config/default.conf +++ b/module/config/default.conf @@ -1,65 +1,65 @@ -version: 1
 -
 -remote - "Remote":
 -	int port : "Port" = 7227
 -	ip listenaddr : "Adress" = 0.0.0.0
 -	bool nolocalauth : "No authentication on local connections" = True
 -	bool activated : "Activated" = True
 -ssl - "SSL":
 -	bool activated : "Activated"= False
 -	file cert : "SSL Certificate" = ssl.crt
 -	file key : "SSL Key" = ssl.key
 -webinterface - "Webinterface":
 -	bool activated : "Activated" = True
 -	builtin;threaded;fastcgi;lightweight server : "Server" = builtin
 -	bool https : "Use HTTPS" = False
 -	ip host : "IP" = 0.0.0.0
 -	int port : "Port" = 8001
 -	str template : "Template" = default
 -    str prefix: "Path Prefix" =
 -log - "Log":
 -	bool file_log : "File Log" = True
 -	folder log_folder : "Folder" = Logs
 -	int log_count : "Count" = 5
 -	int log_size : "Size in kb" = 100
 -	bool log_rotate : "Log Rotate" = True
 -general - "General":
 -	en;de;fr;it;es;nl;sv;ru;pl;cs;sr;pt_BR language : "Language" = en
 -	folder download_folder : "Download Folder" = Downloads
 -	bool debug_mode : "Debug Mode" = False
 -	bool checksum : "Use Checksum" = False
 -	int min_free_space : "Min Free Space (MB)" = 200
 -	bool folder_per_package : "Create folder for each package" = True
 -	int renice : "CPU Priority" = 0
 -download - "Download":
 -    int chunks : "Max connections for one download" = 3
 -    int max_downloads : "Max Parallel Downloads" = 3
 -    int max_speed : "Max Download Speed in kb/s" = -1
 -    bool limit_speed : "Limit Download Speed" = False
 -    str interface : "Download interface to bind (ip or Name)" = None
 -    bool ipv6 : "Allow IPv6" = False
 -    bool skip_existing : "Skip already existing files" = False
 -permission - "Permissions":
 -    bool change_user : "Change user of running process" = False
 -    str user : "Username" = user
 -    str folder : "Folder Permission mode" = 0755
 -    bool change_file : "Change file mode of downloads" = False
 -    str file : "Filemode for Downloads" = 0644
 -    bool change_group : "Change group of running process" = False
 -    str group : "Groupname" = users
 -    bool change_dl : "Change Group and User of Downloads" = False
 -reconnect - "Reconnect":
 -	bool activated : "Use Reconnect" = False
 -	str method : "Method" = None
 -	time startTime : "Start" = 0:00
 -	time endTime : "End" = 0:00
 -downloadTime - "Download Time":
 -	time start : "Start" = 0:00
 -	time end : "End" = 0:00
 -proxy - "Proxy":
 -	str address : "Address" = "localhost"
 -	int port : "Port" = 7070
 -	http;socks4;socks5 type : "Protocol" = http
 -	str username : "Username" = None
 -	password password : "Password" = None
 -    bool proxy : "Use Proxy" = False
 +version: 1 + +remote - "Remote": +	int port : "Port" = 7227 +	ip listenaddr : "Adress" = 0.0.0.0 +	bool nolocalauth : "No authentication on local connections" = True +	bool activated : "Activated" = True +ssl - "SSL": +	bool activated : "Activated"= False +	file cert : "SSL Certificate" = ssl.crt +	file key : "SSL Key" = ssl.key +webinterface - "Webinterface": +	bool activated : "Activated" = True +	builtin;threaded;fastcgi;lightweight server : "Server" = builtin +	bool https : "Use HTTPS" = False +	ip host : "IP" = 0.0.0.0 +	int port : "Port" = 8001 +	str template : "Template" = default +    str prefix: "Path Prefix" = +log - "Log": +	bool file_log : "File Log" = True +	folder log_folder : "Folder" = Logs +	int log_count : "Count" = 5 +	int log_size : "Size in kb" = 100 +	bool log_rotate : "Log Rotate" = True +general - "General": +	en;de;fr;it;es;nl;sv;ru;pl;cs;sr;pt_BR language : "Language" = en +	folder download_folder : "Download Folder" = Downloads +	bool debug_mode : "Debug Mode" = False +	bool checksum : "Use Checksum" = False +	int min_free_space : "Min Free Space (MB)" = 200 +	bool folder_per_package : "Create folder for each package" = True +	int renice : "CPU Priority" = 0 +download - "Download": +    int chunks : "Max connections for one download" = 3 +    int max_downloads : "Max Parallel Downloads" = 3 +    int max_speed : "Max Download Speed in kb/s" = -1 +    bool limit_speed : "Limit Download Speed" = False +    str interface : "Download interface to bind (ip or Name)" = None +    bool ipv6 : "Allow IPv6" = False +    bool skip_existing : "Skip already existing files" = False +permission - "Permissions": +    bool change_user : "Change user of running process" = False +    str user : "Username" = user +    str folder : "Folder Permission mode" = 0755 +    bool change_file : "Change file mode of downloads" = False +    str file : "Filemode for Downloads" = 0644 +    bool change_group : "Change group of running process" = False +    str group : "Groupname" = users +    bool change_dl : "Change Group and User of Downloads" = False +reconnect - "Reconnect": +	bool activated : "Use Reconnect" = False +	str method : "Method" = None +	time startTime : "Start" = 0:00 +	time endTime : "End" = 0:00 +downloadTime - "Download Time": +	time start : "Start" = 0:00 +	time end : "End" = 0:00 +proxy - "Proxy": +	str address : "Address" = "localhost" +	int port : "Port" = 7070 +	http;socks4;socks5 type : "Protocol" = http +	str username : "Username" = None +	password password : "Password" = None +    bool proxy : "Use Proxy" = False diff --git a/module/plugins/accounts/AlldebridCom.py b/module/plugins/accounts/AlldebridCom.py index beaddeac9..baaa9d264 100644 --- a/module/plugins/accounts/AlldebridCom.py +++ b/module/plugins/accounts/AlldebridCom.py @@ -1,46 +1,46 @@ -from module.plugins.Account import Account
 -import xml.dom.minidom as dom
 -from BeautifulSoup import BeautifulSoup
 -from time import time
 -import re
 +from module.plugins.Account import Account +import xml.dom.minidom as dom +from BeautifulSoup import BeautifulSoup +from time import time +import re  import urllib -
 -class AlldebridCom(Account):
 -    __name__ = "AlldebridCom"
 -    __version__ = "0.21"
 -    __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/account/")
 -        soup=BeautifulSoup(page)
 -        #Try to parse expiration date directly from the control panel page (better accuracy)        
 -        try:
 -            time_text=soup.find('div',attrs={'class':'remaining_time_text'}).strong.string
 -            self.log.debug("Account expires in: %s" % time_text)
 -            p = re.compile('\d+')
 -            exp_data=p.findall(time_text)
 -            exp_time=time()+int(exp_data[0])*24*60*60+int(exp_data[1])*60*60+(int(exp_data[2])-1)*60
 -        #Get expiration date from API
 -        except:
 -            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)
 -            exp_time=time()+int(xml.getElementsByTagName("date")[0].childNodes[0].nodeValue)*86400
 -        account_info = {"validuntil": exp_time, "trafficleft": -1}
 -        return account_info
 -
 -    def login(self, user, data, req):      
 + +class AlldebridCom(Account): +    __name__ = "AlldebridCom" +    __version__ = "0.21" +    __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/account/") +        soup=BeautifulSoup(page) +        #Try to parse expiration date directly from the control panel page (better accuracy)         +        try: +            time_text=soup.find('div',attrs={'class':'remaining_time_text'}).strong.string +            self.log.debug("Account expires in: %s" % time_text) +            p = re.compile('\d+') +            exp_data=p.findall(time_text) +            exp_time=time()+int(exp_data[0])*24*60*60+int(exp_data[1])*60*60+(int(exp_data[2])-1)*60 +        #Get expiration date from API +        except: +            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) +            exp_time=time()+int(xml.getElementsByTagName("date")[0].childNodes[0].nodeValue)*86400 +        account_info = {"validuntil": exp_time, "trafficleft": -1} +        return account_info + +    def login(self, user, data, req):                urlparams = urllib.urlencode({'action':'login','login_login':user,'login_password':data["password"]})          page = req.load("http://www.alldebrid.com/register/?%s" % (urlparams)) -
 -        if "This login doesn't exist" in page:
 -            self.wrongPassword()
 + +        if "This login doesn't exist" in page: +            self.wrongPassword()          if "The password is not valid" in page:              self.wrongPassword() diff --git a/module/plugins/accounts/Premium4Me.py b/module/plugins/accounts/Premium4Me.py index c95b9b129..fbca3ce84 100644 --- a/module/plugins/accounts/Premium4Me.py +++ b/module/plugins/accounts/Premium4Me.py @@ -1,23 +1,23 @@ -from module.plugins.Account import Account
 -
 -class Premium4Me(Account):
 -    __name__ = "Premium4Me"
 -    __version__ = "0.03"
 -    __type__ = "account"
 -    __description__ = """Premium.to account plugin"""
 -    __author_name__ = ("RaNaN", "zoidberg", "stickell")
 -    __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz", "l.stickell@yahoo.it")
 -
 -    def loadAccountInfo(self, user, req):
 -        traffic = req.load("http://premium.to/api/traffic.php?authcode=%s" % self.authcode)
 -
 -        account_info = {"trafficleft": int(traffic) / 1024,
 -                        "validuntil": -1}
 -
 -        return account_info
 -
 -    def login(self, user, data, req):
 -        self.authcode = req.load("http://premium.to/api/getauthcode.php?username=%s&password=%s" % (user, data["password"])).strip()
 -        
 -        if "wrong username" in self.authcode:
 +from module.plugins.Account import Account + +class Premium4Me(Account): +    __name__ = "Premium4Me" +    __version__ = "0.03" +    __type__ = "account" +    __description__ = """Premium.to account plugin""" +    __author_name__ = ("RaNaN", "zoidberg", "stickell") +    __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz", "l.stickell@yahoo.it") + +    def loadAccountInfo(self, user, req): +        traffic = req.load("http://premium.to/api/traffic.php?authcode=%s" % self.authcode) + +        account_info = {"trafficleft": int(traffic) / 1024, +                        "validuntil": -1} + +        return account_info + +    def login(self, user, data, req): +        self.authcode = req.load("http://premium.to/api/getauthcode.php?username=%s&password=%s" % (user, data["password"])).strip() +         +        if "wrong username" in self.authcode:              self.wrongPassword()
\ No newline at end of file diff --git a/module/plugins/accounts/PremiumizeMe.py b/module/plugins/accounts/PremiumizeMe.py index 1a446b842..696fdf88f 100644 --- a/module/plugins/accounts/PremiumizeMe.py +++ b/module/plugins/accounts/PremiumizeMe.py @@ -1,44 +1,44 @@ -from module.plugins.Account   import Account
 -
 -from module.common.json_layer import json_loads
 -
 -class PremiumizeMe(Account):
 -    __name__ = "PremiumizeMe"
 -    __version__ = "0.11"
 -    __type__ = "account"
 -    __description__ = """Premiumize.Me account plugin"""
 -    
 -    __author_name__ = ("Florian Franzen")
 -    __author_mail__ = ("FlorianFranzen@gmail.com")
 -
 -    def loadAccountInfo(self, user, req):
 -        
 -        # Get user data from premiumize.me
 -        status = self.getAccountStatus(user, req)
 -        self.logDebug(status)
 -            
 -        # Parse account info
 -        account_info = {"validuntil": float(status['result']['expires']),
 -                        "trafficleft": max(0, status['result']['trafficleft_bytes'] / 1024)}
 -
 -        if status['result']['type'] == 'free':
 -            account_info['premium'] = False
 -
 -        return account_info
 -
 -    def login(self, user, data, req):
 -        
 -        # Get user data from premiumize.me
 -        status = self.getAccountStatus(user, req)
 -        
 -        # Check if user and password are valid
 -        if status['status'] != 200:
 -            self.wrongPassword()
 -
 -    
 -    def getAccountStatus(self, user, req):
 -        
 -        # Use premiumize.me API v1 (see https://secure.premiumize.me/?show=api) to retrieve account info and return the parsed json answer
 -        answer = req.load("https://api.premiumize.me/pm-api/v1.php?method=accountstatus¶ms[login]=%s¶ms[pass]=%s" % (user, self.accounts[user]['password']))            
 -        return json_loads(answer)
 -        
 +from module.plugins.Account   import Account + +from module.common.json_layer import json_loads + +class PremiumizeMe(Account): +    __name__ = "PremiumizeMe" +    __version__ = "0.11" +    __type__ = "account" +    __description__ = """Premiumize.Me account plugin""" +     +    __author_name__ = ("Florian Franzen") +    __author_mail__ = ("FlorianFranzen@gmail.com") + +    def loadAccountInfo(self, user, req): +         +        # Get user data from premiumize.me +        status = self.getAccountStatus(user, req) +        self.logDebug(status) +             +        # Parse account info +        account_info = {"validuntil": float(status['result']['expires']), +                        "trafficleft": max(0, status['result']['trafficleft_bytes'] / 1024)} + +        if status['result']['type'] == 'free': +            account_info['premium'] = False + +        return account_info + +    def login(self, user, data, req): +         +        # Get user data from premiumize.me +        status = self.getAccountStatus(user, req) +         +        # Check if user and password are valid +        if status['status'] != 200: +            self.wrongPassword() + +     +    def getAccountStatus(self, user, req): +         +        # Use premiumize.me API v1 (see https://secure.premiumize.me/?show=api) to retrieve account info and return the parsed json answer +        answer = req.load("https://api.premiumize.me/pm-api/v1.php?method=accountstatus¶ms[login]=%s¶ms[pass]=%s" % (user, self.accounts[user]['password']))             +        return json_loads(answer) +         diff --git a/module/plugins/accounts/RealdebridCom.py b/module/plugins/accounts/RealdebridCom.py index adbd090db..847a925d4 100644 --- a/module/plugins/accounts/RealdebridCom.py +++ b/module/plugins/accounts/RealdebridCom.py @@ -1,25 +1,25 @@ -from module.plugins.Account import Account
 -import xml.dom.minidom as dom
 -
 -class RealdebridCom(Account):
 -    __name__ = "RealdebridCom"
 -    __version__ = "0.41"
 -    __type__ = "account"
 -    __description__ = """Real-Debrid.com account plugin"""
 -    __author_name__ = ("Devirex, Hazzard")
 -    __author_mail__ = ("naibaf_11@yahoo.de")
 -
 -    def loadAccountInfo(self, user, req):
 -        page = req.load("http://real-debrid.com/api/account.php")
 -        xml = dom.parseString(page)
 -        account_info = {"validuntil": int(xml.getElementsByTagName("expiration")[0].childNodes[0].nodeValue),
 -                        "trafficleft": -1}
 -
 -        return account_info
 -
 -    def login(self, user, data, req):
 -        page = req.load("https://real-debrid.com/ajax/login.php", get = {"user": user, "pass": data["password"]})
 -        #page = req.load("https://real-debrid.com/login.html", post={"user": user, "pass": data["password"]}, cookies=True)
 -
 -        if "Your login informations are incorrect" in page:
 -            self.wrongPassword()
 +from module.plugins.Account import Account +import xml.dom.minidom as dom + +class RealdebridCom(Account): +    __name__ = "RealdebridCom" +    __version__ = "0.41" +    __type__ = "account" +    __description__ = """Real-Debrid.com account plugin""" +    __author_name__ = ("Devirex, Hazzard") +    __author_mail__ = ("naibaf_11@yahoo.de") + +    def loadAccountInfo(self, user, req): +        page = req.load("http://real-debrid.com/api/account.php") +        xml = dom.parseString(page) +        account_info = {"validuntil": int(xml.getElementsByTagName("expiration")[0].childNodes[0].nodeValue), +                        "trafficleft": -1} + +        return account_info + +    def login(self, user, data, req): +        page = req.load("https://real-debrid.com/ajax/login.php", get = {"user": user, "pass": data["password"]}) +        #page = req.load("https://real-debrid.com/login.html", post={"user": user, "pass": data["password"]}, cookies=True) + +        if "Your login informations are incorrect" in page: +            self.wrongPassword() diff --git a/module/plugins/accounts/UploadheroCom.py b/module/plugins/accounts/UploadheroCom.py index f1e0649e6..18ed69ae6 100644 --- a/module/plugins/accounts/UploadheroCom.py +++ b/module/plugins/accounts/UploadheroCom.py @@ -1,35 +1,35 @@ -#!/usr/bin/env python
 -# -*- coding: utf-8 -*-
 -
 -from module.plugins.Account import Account
 -import re,datetime,time
 -
 -class UploadheroCom(Account):
 -    __name__ = "UploadheroCom"
 -    __version__ = "0.1"
 -    __type__ = "account"
 -    __description__ = """Uploadhero.com account plugin"""
 -    __author_name__ = ("mcmyst")
 -    __author_mail__ = ("mcmyst@hotmail.fr")
 -
 -
 -    def loadAccountInfo(self, user, req):
 -        premium_pattern = re.compile('Il vous reste <span class="bleu">([0-9]+)</span> jours premium.')
 -
 -        data = self.getAccountData(user)
 -        page = req.load("http://uploadhero.com/my-account")
 -
 -        if premium_pattern.search(page):
 -                end_date = datetime.date.today() + datetime.timedelta(days=int(premium_pattern.search(page).group(1)))
 -                end_date = time.mktime(future.timetuple())
 -                account_info = {"validuntil": end_date, "trafficleft": -1, "premium": True}
 -        else:
 -                account_info = {"validuntil": -1, "trafficleft": -1, "premium": False}
 -
 -        return account_info
 -
 -    def login(self, user, data, req):
 -        page = req.load("http://uploadhero.com/lib/connexion.php", post={"pseudo_login": user, "password_login": data["password"]})
 -
 -        if "mot de passe invalide" in page:
 +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from module.plugins.Account import Account +import re,datetime,time + +class UploadheroCom(Account): +    __name__ = "UploadheroCom" +    __version__ = "0.1" +    __type__ = "account" +    __description__ = """Uploadhero.com account plugin""" +    __author_name__ = ("mcmyst") +    __author_mail__ = ("mcmyst@hotmail.fr") + + +    def loadAccountInfo(self, user, req): +        premium_pattern = re.compile('Il vous reste <span class="bleu">([0-9]+)</span> jours premium.') + +        data = self.getAccountData(user) +        page = req.load("http://uploadhero.com/my-account") + +        if premium_pattern.search(page): +                end_date = datetime.date.today() + datetime.timedelta(days=int(premium_pattern.search(page).group(1))) +                end_date = time.mktime(future.timetuple()) +                account_info = {"validuntil": end_date, "trafficleft": -1, "premium": True} +        else: +                account_info = {"validuntil": -1, "trafficleft": -1, "premium": False} + +        return account_info + +    def login(self, user, data, req): +        page = req.load("http://uploadhero.com/lib/connexion.php", post={"pseudo_login": user, "password_login": data["password"]}) + +        if "mot de passe invalide" in page:              self.wrongPassword()
\ No newline at end of file diff --git a/module/plugins/accounts/X7To.py b/module/plugins/accounts/X7To.py index 8c2bf245a..90f65d55e 100644 --- a/module/plugins/accounts/X7To.py +++ b/module/plugins/accounts/X7To.py @@ -1,66 +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: ernieb
 -"""
 -
 -import re
 -from time import strptime, mktime
 -
 -from module.plugins.Account import Account
 -
 -class X7To(Account):
 -    __name__ = "X7To"
 -    __version__ = "0.1"
 -    __type__ = "account"
 -    __description__ = """X7.To account plugin"""
 -    __author_name__ = ("ernieb")
 -    __author_mail__ = ("ernieb")
 -
 -    def loadAccountInfo(self, user, req):
 -        page = req.load("http://www.x7.to/my")
 -
 -        validCheck = re.search("Premium-Mitglied bis ([0-9]*-[0-9]*-[0-9]*)", page, re.IGNORECASE)
 -        if validCheck:
 -            valid = validCheck.group(1)
 -            valid = int(mktime(strptime(valid, "%Y-%m-%d")))
 -        else:
 -            validCheck = re.search("Premium member until ([0-9]*-[0-9]*-[0-9]*)", page, re.IGNORECASE)
 -            if validCheck:
 -                valid = validCheck.group(1)
 -                valid = int(mktime(strptime(valid, "%Y-%m-%d")))
 -            else:
 -                valid = 0
 -
 -        trafficleft = re.search(r'<em style="white-space:nowrap">([\d]*[,]?[\d]?[\d]?) (KB|MB|GB)</em>', page, re.IGNORECASE)
 -        if trafficleft:
 -            units = float(trafficleft.group(1).replace(",", "."))
 -            pow = {'KB': 0, 'MB': 1, 'GB': 2}[trafficleft.group(2)]
 -            trafficleft = int(units * 1024 ** pow)
 -        else:
 -            trafficleft = -1
 -
 -        return {"trafficleft": trafficleft, "validuntil": valid}
 -
 -
 -    def login(self, user, data, req):
 -        #req.cj.setCookie("share.cx", "lang", "english")
 -        page = req.load("http://x7.to/lang/en", None, {})
 -        page = req.load("http://x7.to/james/login", None,
 -                {"redirect": "http://www.x7.to/", "id": user, "pw": data['password'], "submit": "submit"})
 -
 -        if "Username and password are not matching." in page:
 -            self.wrongPassword()
 +# -*- 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: ernieb +""" + +import re +from time import strptime, mktime + +from module.plugins.Account import Account + +class X7To(Account): +    __name__ = "X7To" +    __version__ = "0.1" +    __type__ = "account" +    __description__ = """X7.To account plugin""" +    __author_name__ = ("ernieb") +    __author_mail__ = ("ernieb") + +    def loadAccountInfo(self, user, req): +        page = req.load("http://www.x7.to/my") + +        validCheck = re.search("Premium-Mitglied bis ([0-9]*-[0-9]*-[0-9]*)", page, re.IGNORECASE) +        if validCheck: +            valid = validCheck.group(1) +            valid = int(mktime(strptime(valid, "%Y-%m-%d"))) +        else: +            validCheck = re.search("Premium member until ([0-9]*-[0-9]*-[0-9]*)", page, re.IGNORECASE) +            if validCheck: +                valid = validCheck.group(1) +                valid = int(mktime(strptime(valid, "%Y-%m-%d"))) +            else: +                valid = 0 + +        trafficleft = re.search(r'<em style="white-space:nowrap">([\d]*[,]?[\d]?[\d]?) (KB|MB|GB)</em>', page, re.IGNORECASE) +        if trafficleft: +            units = float(trafficleft.group(1).replace(",", ".")) +            pow = {'KB': 0, 'MB': 1, 'GB': 2}[trafficleft.group(2)] +            trafficleft = int(units * 1024 ** pow) +        else: +            trafficleft = -1 + +        return {"trafficleft": trafficleft, "validuntil": valid} + + +    def login(self, user, data, req): +        #req.cj.setCookie("share.cx", "lang", "english") +        page = req.load("http://x7.to/lang/en", None, {}) +        page = req.load("http://x7.to/james/login", None, +                {"redirect": "http://www.x7.to/", "id": user, "pw": data['password'], "submit": "submit"}) + +        if "Username and password are not matching." in page: +            self.wrongPassword() diff --git a/module/plugins/crypter/ILoadTo.py b/module/plugins/crypter/ILoadTo.py index 9815ae266..100ba2bc6 100644 --- a/module/plugins/crypter/ILoadTo.py +++ b/module/plugins/crypter/ILoadTo.py @@ -1,62 +1,62 @@ -
 -import re
 -import urllib
 -
 -from module.plugins.Crypter import Crypter
 -from module.lib.BeautifulSoup import BeautifulSoup
 -
 -class ILoadTo(Crypter):
 -    __name__ = "ILoadTo"
 -    __type__ = "crypter"
 -    __pattern__ = r"http://iload\.to/go/\d+-[\w\.-]+/"
 -    __config__ = []
 -    __version__ = "0.1"
 -    __description__ = """iload.to Crypter Plugin"""
 -    __author_name__ = ("hzpz")
 -    __author_mail__ = ("none")
 -    
 -    
 -    def decrypt(self, pyfile):
 -        url = pyfile.url
 -        src = self.req.load(str(url))
 -        soup = BeautifulSoup(src)
 -
 -        # find captcha URL and decrypt            
 -        captchaTag = soup.find("img", attrs={"id": "Captcha"})
 -        if not captchaTag:
 -            self.fail("Cannot find Captcha")
 -
 -        captchaUrl = "http://iload.to" + captchaTag["src"]
 -        self.logDebug("Captcha URL: %s" % captchaUrl)
 -        result = self.decryptCaptcha(str(captchaUrl))
 -
 -        # find captcha form URL 
 -        formTag = soup.find("form", attrs={"id": "CaptchaForm"})
 -        formUrl = "http://iload.to" + formTag["action"]
 -        self.logDebug("Form URL: %s" % formUrl)
 -        
 -        # submit decrypted captcha
 -        self.req.lastURL = url
 -        src = self.req.load(str(formUrl), post={'captcha': result})
 -        
 -        # find decrypted links
 -        links = re.findall(r"<a href=\"(.+)\" style=\"text-align:center;font-weight:bold;\" class=\"button\" target=\"_blank\" onclick=\"this.className\+=' success';\">", src)
 -        
 -        if not len(links) > 0:
 -            self.retry()
 -        
 -        self.correctCaptcha()
 -        
 -        cleanedLinks = []
 -        for link in links:
 -            if link.startswith("http://dontknow.me/at/?"):
 -                cleanedLink = urllib.unquote(link[23:])
 -            else:
 -                cleanedLink = link
 -            self.logDebug("Link: %s" % cleanedLink)
 -            cleanedLinks.append(cleanedLink)
 -        
 -        self.logDebug("Decrypted %d links" % len(links))
 -        
 -        self.pyfile.package().password = "iload.to"
 + +import re +import urllib + +from module.plugins.Crypter import Crypter +from module.lib.BeautifulSoup import BeautifulSoup + +class ILoadTo(Crypter): +    __name__ = "ILoadTo" +    __type__ = "crypter" +    __pattern__ = r"http://iload\.to/go/\d+-[\w\.-]+/" +    __config__ = [] +    __version__ = "0.1" +    __description__ = """iload.to Crypter Plugin""" +    __author_name__ = ("hzpz") +    __author_mail__ = ("none") +     +     +    def decrypt(self, pyfile): +        url = pyfile.url +        src = self.req.load(str(url)) +        soup = BeautifulSoup(src) + +        # find captcha URL and decrypt             +        captchaTag = soup.find("img", attrs={"id": "Captcha"}) +        if not captchaTag: +            self.fail("Cannot find Captcha") + +        captchaUrl = "http://iload.to" + captchaTag["src"] +        self.logDebug("Captcha URL: %s" % captchaUrl) +        result = self.decryptCaptcha(str(captchaUrl)) + +        # find captcha form URL  +        formTag = soup.find("form", attrs={"id": "CaptchaForm"}) +        formUrl = "http://iload.to" + formTag["action"] +        self.logDebug("Form URL: %s" % formUrl) +         +        # submit decrypted captcha +        self.req.lastURL = url +        src = self.req.load(str(formUrl), post={'captcha': result}) +         +        # find decrypted links +        links = re.findall(r"<a href=\"(.+)\" style=\"text-align:center;font-weight:bold;\" class=\"button\" target=\"_blank\" onclick=\"this.className\+=' success';\">", src) +         +        if not len(links) > 0: +            self.retry() +         +        self.correctCaptcha() +         +        cleanedLinks = [] +        for link in links: +            if link.startswith("http://dontknow.me/at/?"): +                cleanedLink = urllib.unquote(link[23:]) +            else: +                cleanedLink = link +            self.logDebug("Link: %s" % cleanedLink) +            cleanedLinks.append(cleanedLink) +         +        self.logDebug("Decrypted %d links" % len(links)) +         +        self.pyfile.package().password = "iload.to"          self.packages.append((self.pyfile.package().name, cleanedLinks, self.pyfile.package().folder))
\ No newline at end of file diff --git a/module/plugins/crypter/LinkSaveIn.py b/module/plugins/crypter/LinkSaveIn.py index 30cc61055..e021316bf 100644 --- a/module/plugins/crypter/LinkSaveIn.py +++ b/module/plugins/crypter/LinkSaveIn.py @@ -1,227 +1,227 @@ -# -*- coding: utf-8 -*-
 -
 -#
 -# v2.01 - hagg
 -# * cnl2 and web links are skipped if JS is not available (instead of failing the package)
 -# * only best available link source is used (priority: cnl2>rsdf>ccf>dlc>web
 -#
 -
 -from Crypto.Cipher import AES
 -from module.plugins.Crypter import Crypter
 -from module.unescape import unescape
 -import base64
 -import binascii
 -import re
 -
 -class LinkSaveIn(Crypter):
 -    __name__ = "LinkSaveIn"
 -    __type__ = "crypter"
 -    __pattern__ = r"http://(www\.)?linksave.in/(?P<id>\w+)$"
 -    __version__ = "2.01"
 -    __description__ = """LinkSave.in Crypter Plugin"""
 -    __author_name__ = ("fragonib")
 -    __author_mail__ = ("fragonib[AT]yahoo[DOT]es")
 -
 -    # Constants
 -    _JK_KEY_ = "jk"
 -    _CRYPTED_KEY_ = "crypted"
 -    HOSTER_DOMAIN = "linksave.in"
 -        
 -    def setup(self):
 -        self.html = None
 -        self.fileid = None
 -        self.captcha = False
 -        self.package = None
 -        self.preferred_sources = ['cnl2', 'rsdf', 'ccf', 'dlc', 'web']
 -        
 -    def decrypt(self, pyfile):
 -
 -        # Init
 -        self.package = pyfile.package()
 -        self.fileid = re.match(self.__pattern__, pyfile.url).group('id')
 -        self.req.cj.setCookie(self.HOSTER_DOMAIN, "Linksave_Language", "english")
 -        
 -        # Request package
 -        self.html = self.load(self.pyfile.url)
 -        if not self.isOnline():
 -            self.offline()
 -        
 -        # Check for protection    
 -        if self.isPasswordProtected():
 -            self.unlockPasswordProtection()
 -            self.handleErrors()
 -            
 -        if self.isCaptchaProtected():
 -            self.captcha = True
 -            self.unlockCaptchaProtection()
 -            self.handleErrors()
 -
 -        # Get package name and folder
 -        (package_name, folder_name) = self.getPackageInfo()
 -
 -        # Extract package links
 -        package_links = []
 -        for type_ in self.preferred_sources:
 -            package_links.extend(self.handleLinkSource(type_))
 -            if package_links:  # use only first source which provides links
 -                break
 -        package_links = set(package_links)
 -
 -        # Pack
 -        if package_links:
 -            self.packages = [(package_name, package_links, folder_name)]
 -        else:
 -            self.fail('Could not extract any links')
 -
 -    def isOnline(self):
 -        if "<big>Error 404 - Folder not found!</big>" in self.html:
 -            self.logDebug("File not found")
 -            return False
 -        return True
 -    
 -    def isPasswordProtected(self):
 -        if re.search(r'''<input.*?type="password"''', self.html):
 -            self.logDebug("Links are password protected")
 -            return True
 -        
 -    def isCaptchaProtected(self):
 -        if "<b>Captcha:</b>" in self.html:
 -            self.logDebug("Links are captcha protected")
 -            return True
 -        return False
 -        
 -    def unlockPasswordProtection(self):
 -        password = self.getPassword()
 -        self.logDebug("Submitting password [%s] for protected links" % password)
 -        post = {"id": self.fileid, "besucherpasswort": password, 'login': 'submit'}
 -        self.html = self.load(self.pyfile.url, post=post)
 -            
 -    def unlockCaptchaProtection(self):
 -        captcha_hash = re.search(r'name="hash" value="([^"]+)', self.html).group(1)
 -        captcha_url = re.search(r'src=".(/captcha/cap.php\?hsh=[^"]+)', self.html).group(1)
 -        captcha_code = self.decryptCaptcha("http://linksave.in" + captcha_url, forceUser=True)
 -        self.html = self.load(self.pyfile.url, post={"id": self.fileid, "hash": captcha_hash, "code": captcha_code})   
 -
 -    def getPackageInfo(self):
 -        name = self.pyfile.package().name
 -        folder = self.pyfile.package().folder
 -        self.logDebug("Defaulting to pyfile name [%s] and folder [%s] for package" % (name, folder))
 -        return name, folder
 -    
 -    def handleErrors(self):      
 -        if "The visitorpassword you have entered is wrong" in self.html:
 -            self.logDebug("Incorrect password, please set right password on 'Edit package' form and retry")
 -            self.fail("Incorrect password, please set right password on 'Edit package' form and retry")  
 -
 -        if self.captcha:          
 -            if "Wrong code. Please retry" in self.html:
 -                self.logDebug("Invalid captcha, retrying")
 -                self.invalidCaptcha()
 -                self.retry()
 -            else:
 -                self.correctCaptcha()
 -           
 -    def handleLinkSource(self, type_):
 -        if type_ == 'cnl2':
 -            return self.handleCNL2()
 -        elif type_ in ('rsdf', 'ccf', 'dlc'):
 -            return self.handleContainer(type_)
 -        elif type_ == 'web':
 -            return self.handleWebLinks()
 -        else:
 -            self.fail('unknown source type "%s" (this is probably a bug)' % type_)
 -
 -    def handleWebLinks(self):
 -        package_links = []
 -        self.logDebug("Search for Web links")
 -        if not self.js:
 -            self.logDebug("no JS -> skip Web links")
 -        else: 
 -            #@TODO: Gather paginated web links  
 -            pattern = r'<a href="http://linksave\.in/(\w{43})"'
 -            ids = re.findall(pattern, self.html)
 -            self.logDebug("Decrypting %d Web links" % len(ids))
 -            for i, weblink_id in enumerate(ids):
 -                try:
 -                    webLink = "http://linksave.in/%s" % weblink_id
 -                    self.logDebug("Decrypting Web link %d, %s" % (i+1, webLink))
 -                    fwLink = "http://linksave.in/fw-%s" % weblink_id
 -                    response = self.load(fwLink)
 -                    jscode = re.findall(r'<script type="text/javascript">(.*)</script>', response)[-1]
 -                    jseval = self.js.eval("document = { write: function(e) { return e; } }; %s" % jscode)
 -                    dlLink = re.search(r'http://linksave\.in/dl-\w+', jseval).group(0)
 -                    self.logDebug("JsEngine returns value [%s] for redirection link" % dlLink)
 -                    response = self.load(dlLink)
 -                    link = unescape(re.search(r'<iframe src="(.+?)"', response).group(1))
 -                    package_links.append(link)
 -                except Exception, detail:
 -                    self.logDebug("Error decrypting Web link %s, %s" % (webLink, detail))    
 -        return package_links
 -    
 -    def handleContainer(self, type_):
 -        package_links = []
 -        type_ = type_.lower()
 -        self.logDebug('Seach for %s Container links' % type_.upper())
 -        if not type_.isalnum():  # check to prevent broken re-pattern (cnl2,rsdf,ccf,dlc,web are all alpha-numeric)
 -            self.fail('unknown container type "%s" (this is probably a bug)' % type_)
 -        pattern = r"\('%s_link'\).href=unescape\('(.*?\.%s)'\)" % (type_, type_)
 -        containersLinks = re.findall(pattern, self.html)
 -        self.logDebug("Found %d %s Container links" % (len(containersLinks), type_.upper()))
 -        for containerLink in containersLinks:
 -            link = "http://linksave.in/%s" % unescape(containerLink)
 -            package_links.append(link)
 -        return package_links
 -
 -    def handleCNL2(self):
 -        package_links = []
 -        self.logDebug("Search for CNL2 links")
 -        if not self.js:
 -            self.logDebug("no JS -> skip CNL2 links")
 -        elif 'cnl2_load' in self.html:
 -            try:
 -                (vcrypted, vjk) = self._getCipherParams()
 -                for (crypted, jk) in zip(vcrypted, vjk):
 -                    package_links.extend(self._getLinks(crypted, jk))
 -            except:
 -                self.fail("Unable to decrypt CNL2 links")            
 -        return package_links
 -    
 -    def _getCipherParams(self):
 -            
 -        # Get jk
 -        jk_re = r'<INPUT.*?NAME="%s".*?VALUE="(.*?)"' % LinkSaveIn._JK_KEY_       
 -        vjk = re.findall(jk_re, self.html)
 -        
 -        # Get crypted
 -        crypted_re = r'<INPUT.*?NAME="%s".*?VALUE="(.*?)"' % LinkSaveIn._CRYPTED_KEY_       
 -        vcrypted = re.findall(crypted_re, self.html)
 -
 -        # Log and return
 -        self.logDebug("Detected %d crypted blocks" % len(vcrypted))
 -        return vcrypted, vjk
 -
 -    def _getLinks(self, crypted, jk):
 -
 -        # Get key
 -        jreturn = self.js.eval("%s f()" % jk)
 -        self.logDebug("JsEngine returns value [%s]" % jreturn)
 -        key = binascii.unhexlify(jreturn)
 -
 -        # Decode crypted
 -        crypted = base64.standard_b64decode(crypted)
 -
 -        # Decrypt
 -        Key = key
 -        IV = key
 -        obj = AES.new(Key, AES.MODE_CBC, IV)
 -        text = obj.decrypt(crypted)
 -
 -        # Extract links
 -        text = text.replace("\x00", "").replace("\r", "")
 -        links = text.split("\n")
 -        links = filter(lambda x: x != "", links)
 -
 -        # Log and return
 -        self.logDebug("Package has %d links" % len(links))
 -        return links
 -
 +# -*- coding: utf-8 -*- + +# +# v2.01 - hagg +# * cnl2 and web links are skipped if JS is not available (instead of failing the package) +# * only best available link source is used (priority: cnl2>rsdf>ccf>dlc>web +# + +from Crypto.Cipher import AES +from module.plugins.Crypter import Crypter +from module.unescape import unescape +import base64 +import binascii +import re + +class LinkSaveIn(Crypter): +    __name__ = "LinkSaveIn" +    __type__ = "crypter" +    __pattern__ = r"http://(www\.)?linksave.in/(?P<id>\w+)$" +    __version__ = "2.01" +    __description__ = """LinkSave.in Crypter Plugin""" +    __author_name__ = ("fragonib") +    __author_mail__ = ("fragonib[AT]yahoo[DOT]es") + +    # Constants +    _JK_KEY_ = "jk" +    _CRYPTED_KEY_ = "crypted" +    HOSTER_DOMAIN = "linksave.in" +         +    def setup(self): +        self.html = None +        self.fileid = None +        self.captcha = False +        self.package = None +        self.preferred_sources = ['cnl2', 'rsdf', 'ccf', 'dlc', 'web'] +         +    def decrypt(self, pyfile): + +        # Init +        self.package = pyfile.package() +        self.fileid = re.match(self.__pattern__, pyfile.url).group('id') +        self.req.cj.setCookie(self.HOSTER_DOMAIN, "Linksave_Language", "english") +         +        # Request package +        self.html = self.load(self.pyfile.url) +        if not self.isOnline(): +            self.offline() +         +        # Check for protection     +        if self.isPasswordProtected(): +            self.unlockPasswordProtection() +            self.handleErrors() +             +        if self.isCaptchaProtected(): +            self.captcha = True +            self.unlockCaptchaProtection() +            self.handleErrors() + +        # Get package name and folder +        (package_name, folder_name) = self.getPackageInfo() + +        # Extract package links +        package_links = [] +        for type_ in self.preferred_sources: +            package_links.extend(self.handleLinkSource(type_)) +            if package_links:  # use only first source which provides links +                break +        package_links = set(package_links) + +        # Pack +        if package_links: +            self.packages = [(package_name, package_links, folder_name)] +        else: +            self.fail('Could not extract any links') + +    def isOnline(self): +        if "<big>Error 404 - Folder not found!</big>" in self.html: +            self.logDebug("File not found") +            return False +        return True +     +    def isPasswordProtected(self): +        if re.search(r'''<input.*?type="password"''', self.html): +            self.logDebug("Links are password protected") +            return True +         +    def isCaptchaProtected(self): +        if "<b>Captcha:</b>" in self.html: +            self.logDebug("Links are captcha protected") +            return True +        return False +         +    def unlockPasswordProtection(self): +        password = self.getPassword() +        self.logDebug("Submitting password [%s] for protected links" % password) +        post = {"id": self.fileid, "besucherpasswort": password, 'login': 'submit'} +        self.html = self.load(self.pyfile.url, post=post) +             +    def unlockCaptchaProtection(self): +        captcha_hash = re.search(r'name="hash" value="([^"]+)', self.html).group(1) +        captcha_url = re.search(r'src=".(/captcha/cap.php\?hsh=[^"]+)', self.html).group(1) +        captcha_code = self.decryptCaptcha("http://linksave.in" + captcha_url, forceUser=True) +        self.html = self.load(self.pyfile.url, post={"id": self.fileid, "hash": captcha_hash, "code": captcha_code})    + +    def getPackageInfo(self): +        name = self.pyfile.package().name +        folder = self.pyfile.package().folder +        self.logDebug("Defaulting to pyfile name [%s] and folder [%s] for package" % (name, folder)) +        return name, folder +     +    def handleErrors(self):       +        if "The visitorpassword you have entered is wrong" in self.html: +            self.logDebug("Incorrect password, please set right password on 'Edit package' form and retry") +            self.fail("Incorrect password, please set right password on 'Edit package' form and retry")   + +        if self.captcha:           +            if "Wrong code. Please retry" in self.html: +                self.logDebug("Invalid captcha, retrying") +                self.invalidCaptcha() +                self.retry() +            else: +                self.correctCaptcha() +            +    def handleLinkSource(self, type_): +        if type_ == 'cnl2': +            return self.handleCNL2() +        elif type_ in ('rsdf', 'ccf', 'dlc'): +            return self.handleContainer(type_) +        elif type_ == 'web': +            return self.handleWebLinks() +        else: +            self.fail('unknown source type "%s" (this is probably a bug)' % type_) + +    def handleWebLinks(self): +        package_links = [] +        self.logDebug("Search for Web links") +        if not self.js: +            self.logDebug("no JS -> skip Web links") +        else:  +            #@TODO: Gather paginated web links   +            pattern = r'<a href="http://linksave\.in/(\w{43})"' +            ids = re.findall(pattern, self.html) +            self.logDebug("Decrypting %d Web links" % len(ids)) +            for i, weblink_id in enumerate(ids): +                try: +                    webLink = "http://linksave.in/%s" % weblink_id +                    self.logDebug("Decrypting Web link %d, %s" % (i+1, webLink)) +                    fwLink = "http://linksave.in/fw-%s" % weblink_id +                    response = self.load(fwLink) +                    jscode = re.findall(r'<script type="text/javascript">(.*)</script>', response)[-1] +                    jseval = self.js.eval("document = { write: function(e) { return e; } }; %s" % jscode) +                    dlLink = re.search(r'http://linksave\.in/dl-\w+', jseval).group(0) +                    self.logDebug("JsEngine returns value [%s] for redirection link" % dlLink) +                    response = self.load(dlLink) +                    link = unescape(re.search(r'<iframe src="(.+?)"', response).group(1)) +                    package_links.append(link) +                except Exception, detail: +                    self.logDebug("Error decrypting Web link %s, %s" % (webLink, detail))     +        return package_links +     +    def handleContainer(self, type_): +        package_links = [] +        type_ = type_.lower() +        self.logDebug('Seach for %s Container links' % type_.upper()) +        if not type_.isalnum():  # check to prevent broken re-pattern (cnl2,rsdf,ccf,dlc,web are all alpha-numeric) +            self.fail('unknown container type "%s" (this is probably a bug)' % type_) +        pattern = r"\('%s_link'\).href=unescape\('(.*?\.%s)'\)" % (type_, type_) +        containersLinks = re.findall(pattern, self.html) +        self.logDebug("Found %d %s Container links" % (len(containersLinks), type_.upper())) +        for containerLink in containersLinks: +            link = "http://linksave.in/%s" % unescape(containerLink) +            package_links.append(link) +        return package_links + +    def handleCNL2(self): +        package_links = [] +        self.logDebug("Search for CNL2 links") +        if not self.js: +            self.logDebug("no JS -> skip CNL2 links") +        elif 'cnl2_load' in self.html: +            try: +                (vcrypted, vjk) = self._getCipherParams() +                for (crypted, jk) in zip(vcrypted, vjk): +                    package_links.extend(self._getLinks(crypted, jk)) +            except: +                self.fail("Unable to decrypt CNL2 links")             +        return package_links +     +    def _getCipherParams(self): +             +        # Get jk +        jk_re = r'<INPUT.*?NAME="%s".*?VALUE="(.*?)"' % LinkSaveIn._JK_KEY_        +        vjk = re.findall(jk_re, self.html) +         +        # Get crypted +        crypted_re = r'<INPUT.*?NAME="%s".*?VALUE="(.*?)"' % LinkSaveIn._CRYPTED_KEY_        +        vcrypted = re.findall(crypted_re, self.html) + +        # Log and return +        self.logDebug("Detected %d crypted blocks" % len(vcrypted)) +        return vcrypted, vjk + +    def _getLinks(self, crypted, jk): + +        # Get key +        jreturn = self.js.eval("%s f()" % jk) +        self.logDebug("JsEngine returns value [%s]" % jreturn) +        key = binascii.unhexlify(jreturn) + +        # Decode crypted +        crypted = base64.standard_b64decode(crypted) + +        # Decrypt +        Key = key +        IV = key +        obj = AES.new(Key, AES.MODE_CBC, IV) +        text = obj.decrypt(crypted) + +        # Extract links +        text = text.replace("\x00", "").replace("\r", "") +        links = text.split("\n") +        links = filter(lambda x: x != "", links) + +        # Log and return +        self.logDebug("Package has %d links" % len(links)) +        return links + diff --git a/module/plugins/crypter/NCryptIn.py b/module/plugins/crypter/NCryptIn.py index e1cd30475..821636821 100644 --- a/module/plugins/crypter/NCryptIn.py +++ b/module/plugins/crypter/NCryptIn.py @@ -1,251 +1,251 @@ -# -*- coding: utf-8 -*-
 -
 -from Crypto.Cipher import AES
 -from module.plugins.Crypter import Crypter
 -from module.plugins.ReCaptcha import ReCaptcha
 -import base64
 -import binascii
 -import re
 -
 -class NCryptIn(Crypter):
 -    __name__ = "NCryptIn"
 -    __type__ = "crypter"
 -    __pattern__ = r"http://(?:www\.)?ncrypt.in/folder-([^/\?]+)"
 -    __version__ = "1.22"
 -    __description__ = """NCrypt.in Crypter Plugin"""
 -    __author_name__ = ("fragonib")
 -    __author_mail__ = ("fragonib[AT]yahoo[DOT]es")
 -
 -    # Constants
 -    _JK_KEY_ = "jk"
 -    _CRYPTED_KEY_ = "crypted"
 -        
 -    def setup(self):
 -        self.html = None
 -        self.cleanedHtml = None
 -        self.captcha = False
 -        self.package = None
 -
 -    def decrypt(self, pyfile):
 -        
 -        # Init
 -        self.package = pyfile.package()
 -        
 -        # Request package
 -        self.html = self.load(self.pyfile.url)
 -        self.cleanedHtml = self.removeCrap(self.html)
 -        if not self.isOnline():
 -            self.offline()
 -        
 -        # Check for protection    
 -        if self.isProtected():
 -            self.html = self.unlockProtection()
 -            self.cleanedHtml = self.removeCrap(self.html)
 -            self.handleErrors()
 -
 -        # Get package name and folder
 -        (package_name, folder_name) = self.getPackageInfo()
 -
 -        # Extract package links
 -        package_links = []
 -        package_links.extend(self.handleWebLinks())
 -        package_links.extend(self.handleContainers())
 -        package_links.extend(self.handleCNL2()) 
 -        package_links = self.removeContainers(package_links)
 -        package_links = set(package_links)
 -
 -        # Pack
 -        self.packages = [(package_name, package_links, folder_name)]
 -        
 -    def removeCrap(self, content):
 -        patterns = (r'(type="hidden".*?(name=".*?")?.*?value=".*?")',
 -                    r'display:none;">(.*?)</(div|span)>',
 -                    r'<div\s+class="jdownloader"(.*?)</div>',
 -                    r'<iframe\s+style="display:none(.*?)</iframe>')
 -        for pattern in patterns:
 -            rexpr = re.compile(pattern, re.DOTALL)
 -            content = re.sub(rexpr, "", content)
 -        return content
 -
 -    def removeContainers(self,package_links):
 -        tmp_package_links = package_links[:]      
 -        for link in tmp_package_links:
 -            self.logDebug(link)
 -            if ".dlc" in link or ".ccf" in link or ".rsdf" in link:
 -                self.logDebug("Removing [%s] from package_links" % link)
 -                package_links.remove(link)
 -
 -        if len(package_links) > 0:
 -            return package_links
 -        else:
 -            return tmp_package_links
 -
 -    def isOnline(self):        
 -        if "Your folder does not exist" in self.cleanedHtml:
 -            self.logDebug("File not found")
 -            return False
 -        return True
 -    
 -    def isProtected(self):
 -        if re.search(r'''<form.*?name.*?protected.*?>''', self.cleanedHtml):
 -            self.logDebug("Links are protected")
 -            return True
 -        return False
 -    
 -    def getPackageInfo(self):
 -        title_re = r'<h2><span.*?class="arrow".*?>(?P<title>[^<]+).*?</span>.*?</h2>'
 -        m = re.findall(title_re, self.html, re.DOTALL)
 -        if m is not None:
 -            title = m[-1].strip()
 -            name = folder = title
 -            self.logDebug("Found name [%s] and folder [%s] in package info" % (name, folder))
 -        else:
 -            name = self.package.name
 -            folder = self.package.folder
 -            self.logDebug("Package info not found, defaulting to pyfile name [%s] and folder [%s]" % (name, folder))
 -        return name, folder
 -    
 -    def unlockProtection(self):
 -        
 -        postData = {}
 -                
 -        form = re.search(r'''<form\ name="protected"(.*?)</form>''', self.cleanedHtml, re.DOTALL).group(1)
 -        
 -        # Submit package password
 -        if "password" in form:
 -            password = self.getPassword()
 -            self.logDebug("Submitting password [%s] for protected links" % password)
 -            postData['password'] = password
 -        
 -        # Resolve anicaptcha
 -        if "anicaptcha" in form:
 -            self.captcha = True
 -            self.logDebug("Captcha protected, resolving captcha")
 -            captchaUri = re.search(r'src="(/temp/anicaptcha/[^"]+)', form).group(1)
 -            captcha = self.decryptCaptcha("http://ncrypt.in" + captchaUri)
 -            self.logDebug("Captcha resolved [%s]" % captcha)
 -            postData['captcha'] = captcha
 -        
 -        # Resolve recaptcha           
 -        if "recaptcha" in form:
 -            self.captcha = True    
 -            id = re.search(r'\?k=(.*?)"', form).group(1)
 -            self.logDebug("Resolving ReCaptcha with key [%s]" % id)
 -            recaptcha = ReCaptcha(self)
 -            challenge, code = recaptcha.challenge(id)
 -            postData['recaptcha_challenge_field'] = challenge
 -            postData['recaptcha_response_field'] = code
 -
 -        # Resolve circlecaptcha
 -        if "circlecaptcha" in form:
 -            self.captcha = True
 -            self.logDebug("Captcha protected")
 -            captcha_img_url = "http://ncrypt.in/classes/captcha/circlecaptcha.php"
 -            coords = self.decryptCaptcha(captcha_img_url, forceUser=True, imgtype="png", result_type='positional')
 -            self.logDebug("Captcha resolved, coords [%s]" % str(coords))
 -            self.captcha_post_url = self.pyfile.url
 -
 -            postData['circle.x'] = coords[0]
 -            postData['circle.y'] = coords[1]
 -
 -                   
 -        # Unlock protection
 -        postData['submit_protected'] = 'Continue to folder '
 -        return self.load(self.pyfile.url, post=postData)
 -        
 -    def handleErrors(self):
 -                   
 -        if "This password is invalid!" in self.cleanedHtml:
 -            self.logDebug("Incorrect password, please set right password on 'Edit package' form and retry")
 -            self.fail("Incorrect password, please set right password on 'Edit package' form and retry")  
 -
 -        if self.captcha:          
 -            if "The securitycheck was wrong!" in self.cleanedHtml:
 -                self.logDebug("Invalid captcha, retrying")
 -                self.invalidCaptcha()
 -                self.retry()
 -            else:
 -                self.correctCaptcha()
 -
 -    def handleWebLinks(self):
 -        package_links = []
 -        self.logDebug("Handling Web links")
 -        
 -        pattern = r"(http://ncrypt\.in/link-.*?=)"
 -        links = re.findall(pattern, self.html)
 -        self.logDebug("Decrypting %d Web links" % len(links))
 -        for i, link in enumerate(links):
 -            self.logDebug("Decrypting Web link %d, %s" % (i+1, link))
 -            try:
 -                url = link.replace("link-", "frame-")
 -                link = self.load(url, just_header=True)['location']
 -                package_links.append(link)
 -            except Exception, detail:
 -                self.logDebug("Error decrypting Web link %s, %s" % (link, detail))    
 -        return package_links
 -    
 -    def handleContainers(self):
 -        package_links = []
 -        self.logDebug("Handling Container links")
 -        
 -        pattern = r"/container/(rsdf|dlc|ccf)/([a-z0-9]+)"
 -        containersLinks = re.findall(pattern, self.html)
 -        self.logDebug("Decrypting %d Container links" % len(containersLinks))
 -        for containerLink in containersLinks:
 -            link = "http://ncrypt.in/container/%s/%s.%s" % (containerLink[0], containerLink[1], containerLink[0])
 -            package_links.append(link)
 -        return package_links
 -                
 -    def handleCNL2(self):
 -        package_links = []
 -        self.logDebug("Handling CNL2 links")
 -        
 -        if 'cnl2_output' in self.cleanedHtml:
 -            try:
 -                (vcrypted, vjk) = self._getCipherParams()
 -                for (crypted, jk) in zip(vcrypted, vjk):
 -                    package_links.extend(self._getLinks(crypted, jk))
 -            except:
 -                self.fail("Unable to decrypt CNL2 links")            
 -        return package_links
 -    
 -    def _getCipherParams(self):
 -            
 -        pattern = r'<input.*?name="%s".*?value="(.*?)"'    
 -            
 -        # Get jk
 -        jk_re = pattern % NCryptIn._JK_KEY_       
 -        vjk = re.findall(jk_re, self.html)
 -        
 -        # Get crypted
 -        crypted_re = pattern % NCryptIn._CRYPTED_KEY_      
 -        vcrypted = re.findall(crypted_re, self.html)
 -
 -        # Log and return
 -        self.logDebug("Detected %d crypted blocks" % len(vcrypted))
 -        return vcrypted, vjk
 -
 -    def _getLinks(self, crypted, jk):
 -
 -        # Get key
 -        jreturn = self.js.eval("%s f()" % jk)
 -        self.logDebug("JsEngine returns value [%s]" % jreturn)
 -        key = binascii.unhexlify(jreturn)
 -
 -        # Decode crypted
 -        crypted = base64.standard_b64decode(crypted)
 -
 -        # Decrypt
 -        Key = key
 -        IV = key
 -        obj = AES.new(Key, AES.MODE_CBC, IV)
 -        text = obj.decrypt(crypted)
 -
 -        # Extract links
 -        text = text.replace("\x00", "").replace("\r", "")
 -        links = text.split("\n")
 -        links = filter(lambda x: x != "", links)
 -
 -        # Log and return
 -        self.logDebug("Block has %d links" % len(links))
 -        return links
 +# -*- coding: utf-8 -*- + +from Crypto.Cipher import AES +from module.plugins.Crypter import Crypter +from module.plugins.ReCaptcha import ReCaptcha +import base64 +import binascii +import re + +class NCryptIn(Crypter): +    __name__ = "NCryptIn" +    __type__ = "crypter" +    __pattern__ = r"http://(?:www\.)?ncrypt.in/folder-([^/\?]+)" +    __version__ = "1.22" +    __description__ = """NCrypt.in Crypter Plugin""" +    __author_name__ = ("fragonib") +    __author_mail__ = ("fragonib[AT]yahoo[DOT]es") + +    # Constants +    _JK_KEY_ = "jk" +    _CRYPTED_KEY_ = "crypted" +         +    def setup(self): +        self.html = None +        self.cleanedHtml = None +        self.captcha = False +        self.package = None + +    def decrypt(self, pyfile): +         +        # Init +        self.package = pyfile.package() +         +        # Request package +        self.html = self.load(self.pyfile.url) +        self.cleanedHtml = self.removeCrap(self.html) +        if not self.isOnline(): +            self.offline() +         +        # Check for protection     +        if self.isProtected(): +            self.html = self.unlockProtection() +            self.cleanedHtml = self.removeCrap(self.html) +            self.handleErrors() + +        # Get package name and folder +        (package_name, folder_name) = self.getPackageInfo() + +        # Extract package links +        package_links = [] +        package_links.extend(self.handleWebLinks()) +        package_links.extend(self.handleContainers()) +        package_links.extend(self.handleCNL2())  +        package_links = self.removeContainers(package_links) +        package_links = set(package_links) + +        # Pack +        self.packages = [(package_name, package_links, folder_name)] +         +    def removeCrap(self, content): +        patterns = (r'(type="hidden".*?(name=".*?")?.*?value=".*?")', +                    r'display:none;">(.*?)</(div|span)>', +                    r'<div\s+class="jdownloader"(.*?)</div>', +                    r'<iframe\s+style="display:none(.*?)</iframe>') +        for pattern in patterns: +            rexpr = re.compile(pattern, re.DOTALL) +            content = re.sub(rexpr, "", content) +        return content + +    def removeContainers(self,package_links): +        tmp_package_links = package_links[:]       +        for link in tmp_package_links: +            self.logDebug(link) +            if ".dlc" in link or ".ccf" in link or ".rsdf" in link: +                self.logDebug("Removing [%s] from package_links" % link) +                package_links.remove(link) + +        if len(package_links) > 0: +            return package_links +        else: +            return tmp_package_links + +    def isOnline(self):         +        if "Your folder does not exist" in self.cleanedHtml: +            self.logDebug("File not found") +            return False +        return True +     +    def isProtected(self): +        if re.search(r'''<form.*?name.*?protected.*?>''', self.cleanedHtml): +            self.logDebug("Links are protected") +            return True +        return False +     +    def getPackageInfo(self): +        title_re = r'<h2><span.*?class="arrow".*?>(?P<title>[^<]+).*?</span>.*?</h2>' +        m = re.findall(title_re, self.html, re.DOTALL) +        if m is not None: +            title = m[-1].strip() +            name = folder = title +            self.logDebug("Found name [%s] and folder [%s] in package info" % (name, folder)) +        else: +            name = self.package.name +            folder = self.package.folder +            self.logDebug("Package info not found, defaulting to pyfile name [%s] and folder [%s]" % (name, folder)) +        return name, folder +     +    def unlockProtection(self): +         +        postData = {} +                 +        form = re.search(r'''<form\ name="protected"(.*?)</form>''', self.cleanedHtml, re.DOTALL).group(1) +         +        # Submit package password +        if "password" in form: +            password = self.getPassword() +            self.logDebug("Submitting password [%s] for protected links" % password) +            postData['password'] = password +         +        # Resolve anicaptcha +        if "anicaptcha" in form: +            self.captcha = True +            self.logDebug("Captcha protected, resolving captcha") +            captchaUri = re.search(r'src="(/temp/anicaptcha/[^"]+)', form).group(1) +            captcha = self.decryptCaptcha("http://ncrypt.in" + captchaUri) +            self.logDebug("Captcha resolved [%s]" % captcha) +            postData['captcha'] = captcha +         +        # Resolve recaptcha            +        if "recaptcha" in form: +            self.captcha = True     +            id = re.search(r'\?k=(.*?)"', form).group(1) +            self.logDebug("Resolving ReCaptcha with key [%s]" % id) +            recaptcha = ReCaptcha(self) +            challenge, code = recaptcha.challenge(id) +            postData['recaptcha_challenge_field'] = challenge +            postData['recaptcha_response_field'] = code + +        # Resolve circlecaptcha +        if "circlecaptcha" in form: +            self.captcha = True +            self.logDebug("Captcha protected") +            captcha_img_url = "http://ncrypt.in/classes/captcha/circlecaptcha.php" +            coords = self.decryptCaptcha(captcha_img_url, forceUser=True, imgtype="png", result_type='positional') +            self.logDebug("Captcha resolved, coords [%s]" % str(coords)) +            self.captcha_post_url = self.pyfile.url + +            postData['circle.x'] = coords[0] +            postData['circle.y'] = coords[1] + +                    +        # Unlock protection +        postData['submit_protected'] = 'Continue to folder ' +        return self.load(self.pyfile.url, post=postData) +         +    def handleErrors(self): +                    +        if "This password is invalid!" in self.cleanedHtml: +            self.logDebug("Incorrect password, please set right password on 'Edit package' form and retry") +            self.fail("Incorrect password, please set right password on 'Edit package' form and retry")   + +        if self.captcha:           +            if "The securitycheck was wrong!" in self.cleanedHtml: +                self.logDebug("Invalid captcha, retrying") +                self.invalidCaptcha() +                self.retry() +            else: +                self.correctCaptcha() + +    def handleWebLinks(self): +        package_links = [] +        self.logDebug("Handling Web links") +         +        pattern = r"(http://ncrypt\.in/link-.*?=)" +        links = re.findall(pattern, self.html) +        self.logDebug("Decrypting %d Web links" % len(links)) +        for i, link in enumerate(links): +            self.logDebug("Decrypting Web link %d, %s" % (i+1, link)) +            try: +                url = link.replace("link-", "frame-") +                link = self.load(url, just_header=True)['location'] +                package_links.append(link) +            except Exception, detail: +                self.logDebug("Error decrypting Web link %s, %s" % (link, detail))     +        return package_links +     +    def handleContainers(self): +        package_links = [] +        self.logDebug("Handling Container links") +         +        pattern = r"/container/(rsdf|dlc|ccf)/([a-z0-9]+)" +        containersLinks = re.findall(pattern, self.html) +        self.logDebug("Decrypting %d Container links" % len(containersLinks)) +        for containerLink in containersLinks: +            link = "http://ncrypt.in/container/%s/%s.%s" % (containerLink[0], containerLink[1], containerLink[0]) +            package_links.append(link) +        return package_links +                 +    def handleCNL2(self): +        package_links = [] +        self.logDebug("Handling CNL2 links") +         +        if 'cnl2_output' in self.cleanedHtml: +            try: +                (vcrypted, vjk) = self._getCipherParams() +                for (crypted, jk) in zip(vcrypted, vjk): +                    package_links.extend(self._getLinks(crypted, jk)) +            except: +                self.fail("Unable to decrypt CNL2 links")             +        return package_links +     +    def _getCipherParams(self): +             +        pattern = r'<input.*?name="%s".*?value="(.*?)"'     +             +        # Get jk +        jk_re = pattern % NCryptIn._JK_KEY_        +        vjk = re.findall(jk_re, self.html) +         +        # Get crypted +        crypted_re = pattern % NCryptIn._CRYPTED_KEY_       +        vcrypted = re.findall(crypted_re, self.html) + +        # Log and return +        self.logDebug("Detected %d crypted blocks" % len(vcrypted)) +        return vcrypted, vjk + +    def _getLinks(self, crypted, jk): + +        # Get key +        jreturn = self.js.eval("%s f()" % jk) +        self.logDebug("JsEngine returns value [%s]" % jreturn) +        key = binascii.unhexlify(jreturn) + +        # Decode crypted +        crypted = base64.standard_b64decode(crypted) + +        # Decrypt +        Key = key +        IV = key +        obj = AES.new(Key, AES.MODE_CBC, IV) +        text = obj.decrypt(crypted) + +        # Extract links +        text = text.replace("\x00", "").replace("\r", "") +        links = text.split("\n") +        links = filter(lambda x: x != "", links) + +        # Log and return +        self.logDebug("Block has %d links" % len(links)) +        return links diff --git a/module/plugins/crypter/ShareLinksBiz.py b/module/plugins/crypter/ShareLinksBiz.py index 1ffa5d41a..b0e735896 100644 --- a/module/plugins/crypter/ShareLinksBiz.py +++ b/module/plugins/crypter/ShareLinksBiz.py @@ -1,269 +1,269 @@ -# -*- coding: utf-8 -*-
 -
 -from Crypto.Cipher import AES
 -from module.plugins.Crypter import Crypter
 -from module.plugins.ReCaptcha import ReCaptcha
 -import base64
 -import binascii
 -import re
 -
 -
 -class ShareLinksBiz(Crypter):
 -    __name__ = "ShareLinksBiz"
 -    __type__ = "crypter"
 -    __pattern__ = r"(?P<base>http://[\w\.]*?(share-links|s2l)\.biz)/(?P<id>_?[0-9a-z]+)(/.*)?"
 -    __version__ = "1.12"
 -    __description__ = """Share-Links.biz Crypter"""
 -    __author_name__ = ("fragonib")
 -    __author_mail__ = ("fragonib[AT]yahoo[DOT]es")
 -    
 -    
 -    def setup(self):
 -        self.baseUrl = None
 -        self.fileId = None
 -        self.package = None
 -        self.html = None
 -        self.captcha = False
 -
 -    def decrypt(self, pyfile):
 -
 -        # Init
 -        self.initFile(pyfile)
 -        
 -        # Request package
 -        url = self.baseUrl + '/' + self.fileId
 -        self.html = self.load(url, decode=True)
 -        
 -        # Unblock server (load all images)
 -        self.unblockServer()
 -           
 -        # Check for protection    
 -        if self.isPasswordProtected():
 -            self.unlockPasswordProtection()
 -            self.handleErrors()
 -            
 -        if self.isCaptchaProtected():
 -            self.captcha = True
 -            self.unlockCaptchaProtection()
 -            self.handleErrors()
 -            
 -        # Extract package links
 -        package_links = []
 -        package_links.extend(self.handleWebLinks())
 -        package_links.extend(self.handleContainers())
 -        package_links.extend(self.handleCNL2())
 -        package_links = set(package_links)
 -        
 -        # Get package info 
 -        package_name, package_folder = self.getPackageInfo()
 -
 -        # Pack
 -        self.packages = [(package_name, package_links, package_folder)]
 -
 -    def initFile(self, pyfile):
 -        url = pyfile.url
 -        if 's2l.biz' in url:
 -            url = self.load(url, just_header=True)['location']
 -        self.baseUrl = re.search(self.__pattern__, url).group(1)            
 -        self.fileId = re.match(self.__pattern__, url).group('id')
 -        self.package = pyfile.package()
 -
 -    def isOnline(self):
 -        if "No usable content was found" in self.html:
 -            self.logDebug("File not found")
 -            return False
 -        return True
 -    
 -    def isPasswordProtected(self):
 -        if re.search(r'''<form.*?id="passwordForm".*?>''', self.html):
 -            self.logDebug("Links are protected")
 -            return True
 -        return False
 -    
 -    def isCaptchaProtected(self):
 -        if '<map id="captchamap"' in self.html:
 -            self.logDebug("Links are captcha protected")
 -            return True
 -        return False
 -    
 -    def unblockServer(self):
 -        imgs = re.findall("(/template/images/.*?\.gif)", self.html)
 -        for img in imgs:
 -            self.load(self.baseUrl + img)
 -    
 -    def unlockPasswordProtection(self):
 -        password = self.getPassword()
 -        self.logDebug("Submitting password [%s] for protected links" % password)
 -        post = {"password": password, 'login': 'Submit form'}
 -        url = self.baseUrl + '/' + self.fileId
 -        self.html = self.load(url, post=post, decode=True)
 -
 -    def unlockCaptchaProtection(self):
 -        # Get captcha map
 -        captchaMap = self._getCaptchaMap()
 -        self.logDebug("Captcha map with [%d] positions" % len(captchaMap.keys()))
 -
 -        # Request user for captcha coords
 -        m = re.search(r'<img src="/captcha.gif\?d=(.*?)&PHPSESSID=(.*?)&legend=1"', self.html)
 -        captchaUrl = self.baseUrl + '/captcha.gif?d=%s&PHPSESSID=%s' % (m.group(1), m.group(2))
 -        self.logDebug("Waiting user for correct position")
 -        coords = self.decryptCaptcha(captchaUrl, forceUser=True, imgtype="gif", result_type='positional')
 -        self.logDebug("Captcha resolved, coords [%s]" % str(coords))
 -    
 -        # Resolve captcha
 -        href = self._resolveCoords(coords, captchaMap)
 -        if href is None:
 -            self.logDebug("Invalid captcha resolving, retrying")
 -            self.invalidCaptcha()
 -            self.setWait(5, False)
 -            self.wait()
 -            self.retry()
 -        url = self.baseUrl + href
 -        self.html = self.load(url, decode=True)
 -        
 -    def _getCaptchaMap(self):
 -        map = {}
 -        for m in re.finditer(r'<area shape="rect" coords="(.*?)" href="(.*?)"', self.html):
 -            rect = eval('(' + m.group(1) + ')')
 -            href = m.group(2)
 -            map[rect] = href
 -        return map
 -
 -    def _resolveCoords(self, coords, captchaMap):
 -        x, y = coords
 -        for rect, href in captchaMap.items():
 -            x1, y1, x2, y2 = rect
 -            if (x>=x1 and x<=x2) and (y>=y1 and y<=y2):
 -                return href
 -
 -    def handleErrors(self):
 -        if "The inserted password was wrong" in self.html:
 -            self.logDebug("Incorrect password, please set right password on 'Edit package' form and retry")
 -            self.fail("Incorrect password, please set right password on 'Edit package' form and retry")  
 -
 -        if self.captcha:
 -            if "Your choice was wrong" in self.html:
 -                self.logDebug("Invalid captcha, retrying")
 -                self.invalidCaptcha()
 -                self.setWait(5)
 -                self.wait()
 -                self.retry()
 -            else:
 -                self.correctCaptcha() 
 -
 -    def getPackageInfo(self):
 -        name = folder = None
 -        
 -        # Extract from web package header
 -        title_re = r'<h2><img.*?/>(.*)</h2>'
 -        m = re.search(title_re, self.html, re.DOTALL)
 -        if m is not None:
 -            title = m.group(1).strip()
 -            if 'unnamed' not in title:
 -                name = folder = title
 -                self.logDebug("Found name [%s] and folder [%s] in package info" % (name, folder))
 -                
 -        # Fallback to defaults
 -        if not name or not folder:
 -            name = self.package.name
 -            folder = self.package.folder
 -            self.logDebug("Package info not found, defaulting to pyfile name [%s] and folder [%s]" % (name, folder))
 -            
 -        # Return package info 
 -        return name, folder 
 -    
 -    def handleWebLinks(self):
 -        package_links = []
 -        self.logDebug("Handling Web links")
 -        
 -        #@TODO: Gather paginated web links  
 -        pattern = r"javascript:_get\('(.*?)', \d+, ''\)"
 -        ids = re.findall(pattern, self.html)
 -        self.logDebug("Decrypting %d Web links" % len(ids))
 -        for i, id in enumerate(ids):
 -            try:
 -                self.logDebug("Decrypting Web link %d, [%s]" % (i+1, id))
 -                dwLink = self.baseUrl + "/get/lnk/" + id
 -                response = self.load(dwLink)
 -                code = re.search(r'frm/(\d+)', response).group(1)
 -                fwLink = self.baseUrl + "/get/frm/" + code
 -                response = self.load(fwLink)
 -                jscode = re.search(r'<script language="javascript">\s*eval\((.*)\)\s*</script>', response, re.DOTALL).group(1)
 -                jscode = self.js.eval("f = %s" % jscode)
 -                jslauncher = "window=''; parent={frames:{Main:{location:{href:''}}},location:''}; %s; parent.frames.Main.location.href" 
 -                dlLink = self.js.eval(jslauncher % jscode)
 -                self.logDebug("JsEngine returns value [%s] for redirection link"  % dlLink)
 -                package_links.append(dlLink)
 -            except Exception, detail:
 -                self.logDebug("Error decrypting Web link [%s], %s" % (id, detail))
 -        return package_links
 -    
 -    def handleContainers(self):
 -        package_links = []
 -        self.logDebug("Handling Container links")
 -        
 -        pattern = r"javascript:_get\('(.*?)', 0, '(rsdf|ccf|dlc)'\)"
 -        containersLinks = re.findall(pattern, self.html)
 -        self.logDebug("Decrypting %d Container links" % len(containersLinks))
 -        for containerLink in containersLinks:
 -            link = "%s/get/%s/%s" % (self.baseUrl, containerLink[1], containerLink[0]) 
 -            package_links.append(link)
 -        return package_links
 -    
 -    def handleCNL2(self):
 -        package_links = []
 -        self.logDebug("Handling CNL2 links")
 -
 -        if '/lib/cnl2/ClicknLoad.swf' in self.html:
 -            try:
 -                (crypted, jk) = self._getCipherParams()
 -                package_links.extend(self._getLinks(crypted, jk))
 -            except:
 -                self.fail("Unable to decrypt CNL2 links")            
 -        return package_links
 -    
 -    def _getCipherParams(self):
 -        
 -        # Request CNL2
 -        code = re.search(r'ClicknLoad.swf\?code=(.*?)"', self.html).group(1)
 -        url = "%s/get/cnl2/%s" % (self.baseUrl, code)
 -        response = self.load(url)
 -        params = response.split(";;")
 -        
 -        # Get jk
 -        strlist = list(base64.standard_b64decode(params[1]))
 -        strlist.reverse()
 -        jk = ''.join(strlist)
 -
 -        # Get crypted
 -        strlist = list(base64.standard_b64decode(params[2]))
 -        strlist.reverse()
 -        crypted = ''.join(strlist)
 -
 -        # Log and return
 -        return crypted, jk
 -
 -    def _getLinks(self, crypted, jk):
 -        
 -        # Get key
 -        jreturn = self.js.eval("%s f()" % jk)
 -        self.logDebug("JsEngine returns value [%s]" % jreturn)
 -        key = binascii.unhexlify(jreturn)
 -
 -        # Decode crypted
 -        crypted = base64.standard_b64decode(crypted)
 -
 -        # Decrypt
 -        Key = key
 -        IV = key
 -        obj = AES.new(Key, AES.MODE_CBC, IV)
 -        text = obj.decrypt(crypted)
 -
 -        # Extract links
 -        text = text.replace("\x00", "").replace("\r", "")
 -        links = text.split("\n")
 -        links = filter(lambda x: x != "", links)
 -
 -        # Log and return
 -        self.logDebug("Block has %d links" % len(links))
 +# -*- coding: utf-8 -*- + +from Crypto.Cipher import AES +from module.plugins.Crypter import Crypter +from module.plugins.ReCaptcha import ReCaptcha +import base64 +import binascii +import re + + +class ShareLinksBiz(Crypter): +    __name__ = "ShareLinksBiz" +    __type__ = "crypter" +    __pattern__ = r"(?P<base>http://[\w\.]*?(share-links|s2l)\.biz)/(?P<id>_?[0-9a-z]+)(/.*)?" +    __version__ = "1.12" +    __description__ = """Share-Links.biz Crypter""" +    __author_name__ = ("fragonib") +    __author_mail__ = ("fragonib[AT]yahoo[DOT]es") +     +     +    def setup(self): +        self.baseUrl = None +        self.fileId = None +        self.package = None +        self.html = None +        self.captcha = False + +    def decrypt(self, pyfile): + +        # Init +        self.initFile(pyfile) +         +        # Request package +        url = self.baseUrl + '/' + self.fileId +        self.html = self.load(url, decode=True) +         +        # Unblock server (load all images) +        self.unblockServer() +            +        # Check for protection     +        if self.isPasswordProtected(): +            self.unlockPasswordProtection() +            self.handleErrors() +             +        if self.isCaptchaProtected(): +            self.captcha = True +            self.unlockCaptchaProtection() +            self.handleErrors() +             +        # Extract package links +        package_links = [] +        package_links.extend(self.handleWebLinks()) +        package_links.extend(self.handleContainers()) +        package_links.extend(self.handleCNL2()) +        package_links = set(package_links) +         +        # Get package info  +        package_name, package_folder = self.getPackageInfo() + +        # Pack +        self.packages = [(package_name, package_links, package_folder)] + +    def initFile(self, pyfile): +        url = pyfile.url +        if 's2l.biz' in url: +            url = self.load(url, just_header=True)['location'] +        self.baseUrl = re.search(self.__pattern__, url).group(1)             +        self.fileId = re.match(self.__pattern__, url).group('id') +        self.package = pyfile.package() + +    def isOnline(self): +        if "No usable content was found" in self.html: +            self.logDebug("File not found") +            return False +        return True +     +    def isPasswordProtected(self): +        if re.search(r'''<form.*?id="passwordForm".*?>''', self.html): +            self.logDebug("Links are protected") +            return True +        return False +     +    def isCaptchaProtected(self): +        if '<map id="captchamap"' in self.html: +            self.logDebug("Links are captcha protected") +            return True +        return False +     +    def unblockServer(self): +        imgs = re.findall("(/template/images/.*?\.gif)", self.html) +        for img in imgs: +            self.load(self.baseUrl + img) +     +    def unlockPasswordProtection(self): +        password = self.getPassword() +        self.logDebug("Submitting password [%s] for protected links" % password) +        post = {"password": password, 'login': 'Submit form'} +        url = self.baseUrl + '/' + self.fileId +        self.html = self.load(url, post=post, decode=True) + +    def unlockCaptchaProtection(self): +        # Get captcha map +        captchaMap = self._getCaptchaMap() +        self.logDebug("Captcha map with [%d] positions" % len(captchaMap.keys())) + +        # Request user for captcha coords +        m = re.search(r'<img src="/captcha.gif\?d=(.*?)&PHPSESSID=(.*?)&legend=1"', self.html) +        captchaUrl = self.baseUrl + '/captcha.gif?d=%s&PHPSESSID=%s' % (m.group(1), m.group(2)) +        self.logDebug("Waiting user for correct position") +        coords = self.decryptCaptcha(captchaUrl, forceUser=True, imgtype="gif", result_type='positional') +        self.logDebug("Captcha resolved, coords [%s]" % str(coords)) +     +        # Resolve captcha +        href = self._resolveCoords(coords, captchaMap) +        if href is None: +            self.logDebug("Invalid captcha resolving, retrying") +            self.invalidCaptcha() +            self.setWait(5, False) +            self.wait() +            self.retry() +        url = self.baseUrl + href +        self.html = self.load(url, decode=True) +         +    def _getCaptchaMap(self): +        map = {} +        for m in re.finditer(r'<area shape="rect" coords="(.*?)" href="(.*?)"', self.html): +            rect = eval('(' + m.group(1) + ')') +            href = m.group(2) +            map[rect] = href +        return map + +    def _resolveCoords(self, coords, captchaMap): +        x, y = coords +        for rect, href in captchaMap.items(): +            x1, y1, x2, y2 = rect +            if (x>=x1 and x<=x2) and (y>=y1 and y<=y2): +                return href + +    def handleErrors(self): +        if "The inserted password was wrong" in self.html: +            self.logDebug("Incorrect password, please set right password on 'Edit package' form and retry") +            self.fail("Incorrect password, please set right password on 'Edit package' form and retry")   + +        if self.captcha: +            if "Your choice was wrong" in self.html: +                self.logDebug("Invalid captcha, retrying") +                self.invalidCaptcha() +                self.setWait(5) +                self.wait() +                self.retry() +            else: +                self.correctCaptcha()  + +    def getPackageInfo(self): +        name = folder = None +         +        # Extract from web package header +        title_re = r'<h2><img.*?/>(.*)</h2>' +        m = re.search(title_re, self.html, re.DOTALL) +        if m is not None: +            title = m.group(1).strip() +            if 'unnamed' not in title: +                name = folder = title +                self.logDebug("Found name [%s] and folder [%s] in package info" % (name, folder)) +                 +        # Fallback to defaults +        if not name or not folder: +            name = self.package.name +            folder = self.package.folder +            self.logDebug("Package info not found, defaulting to pyfile name [%s] and folder [%s]" % (name, folder)) +             +        # Return package info  +        return name, folder  +     +    def handleWebLinks(self): +        package_links = [] +        self.logDebug("Handling Web links") +         +        #@TODO: Gather paginated web links   +        pattern = r"javascript:_get\('(.*?)', \d+, ''\)" +        ids = re.findall(pattern, self.html) +        self.logDebug("Decrypting %d Web links" % len(ids)) +        for i, id in enumerate(ids): +            try: +                self.logDebug("Decrypting Web link %d, [%s]" % (i+1, id)) +                dwLink = self.baseUrl + "/get/lnk/" + id +                response = self.load(dwLink) +                code = re.search(r'frm/(\d+)', response).group(1) +                fwLink = self.baseUrl + "/get/frm/" + code +                response = self.load(fwLink) +                jscode = re.search(r'<script language="javascript">\s*eval\((.*)\)\s*</script>', response, re.DOTALL).group(1) +                jscode = self.js.eval("f = %s" % jscode) +                jslauncher = "window=''; parent={frames:{Main:{location:{href:''}}},location:''}; %s; parent.frames.Main.location.href"  +                dlLink = self.js.eval(jslauncher % jscode) +                self.logDebug("JsEngine returns value [%s] for redirection link"  % dlLink) +                package_links.append(dlLink) +            except Exception, detail: +                self.logDebug("Error decrypting Web link [%s], %s" % (id, detail)) +        return package_links +     +    def handleContainers(self): +        package_links = [] +        self.logDebug("Handling Container links") +         +        pattern = r"javascript:_get\('(.*?)', 0, '(rsdf|ccf|dlc)'\)" +        containersLinks = re.findall(pattern, self.html) +        self.logDebug("Decrypting %d Container links" % len(containersLinks)) +        for containerLink in containersLinks: +            link = "%s/get/%s/%s" % (self.baseUrl, containerLink[1], containerLink[0])  +            package_links.append(link) +        return package_links +     +    def handleCNL2(self): +        package_links = [] +        self.logDebug("Handling CNL2 links") + +        if '/lib/cnl2/ClicknLoad.swf' in self.html: +            try: +                (crypted, jk) = self._getCipherParams() +                package_links.extend(self._getLinks(crypted, jk)) +            except: +                self.fail("Unable to decrypt CNL2 links")             +        return package_links +     +    def _getCipherParams(self): +         +        # Request CNL2 +        code = re.search(r'ClicknLoad.swf\?code=(.*?)"', self.html).group(1) +        url = "%s/get/cnl2/%s" % (self.baseUrl, code) +        response = self.load(url) +        params = response.split(";;") +         +        # Get jk +        strlist = list(base64.standard_b64decode(params[1])) +        strlist.reverse() +        jk = ''.join(strlist) + +        # Get crypted +        strlist = list(base64.standard_b64decode(params[2])) +        strlist.reverse() +        crypted = ''.join(strlist) + +        # Log and return +        return crypted, jk + +    def _getLinks(self, crypted, jk): +         +        # Get key +        jreturn = self.js.eval("%s f()" % jk) +        self.logDebug("JsEngine returns value [%s]" % jreturn) +        key = binascii.unhexlify(jreturn) + +        # Decode crypted +        crypted = base64.standard_b64decode(crypted) + +        # Decrypt +        Key = key +        IV = key +        obj = AES.new(Key, AES.MODE_CBC, IV) +        text = obj.decrypt(crypted) + +        # Extract links +        text = text.replace("\x00", "").replace("\r", "") +        links = text.split("\n") +        links = filter(lambda x: x != "", links) + +        # Log and return +        self.logDebug("Block has %d links" % len(links))          return links
\ No newline at end of file diff --git a/module/plugins/crypter/UploadedToFolder.py b/module/plugins/crypter/UploadedToFolder.py index c514f23d0..88d4e04e8 100644 --- a/module/plugins/crypter/UploadedToFolder.py +++ b/module/plugins/crypter/UploadedToFolder.py @@ -1,50 +1,50 @@ -# -*- coding: utf-8 -*-
 -
 -############################################################################
 -# This program is free software: you can redistribute it and/or modify     #
 -# it under the terms of the GNU Affero 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 Affero General Public License for more details.                      #
 -#                                                                          #
 -# You should have received a copy of the GNU Affero General Public License #
 -# along with this program.  If not, see <http://www.gnu.org/licenses/>.    #
 -############################################################################
 -
 -import re
 -
 -from module.plugins.internal.SimpleCrypter import SimpleCrypter
 -
 -
 -class UploadedToFolder(SimpleCrypter):
 -    __name__ = "UploadedToFolder"
 -    __type__ = "crypter"
 -    __pattern__ = r"http://(?:www\.)?(uploaded|ul)\.(to|net)/(f|folder|list)/(?P<id>\w+)"
 -    __version__ = "0.3"
 -    __description__ = """UploadedTo Crypter Plugin"""
 -    __author_name__ = ("stickell")
 -    __author_mail__ = ("l.stickell@yahoo.it")
 -
 -    PLAIN_PATTERN = r'<small class="date"><a href="(?P<plain>[\w/]+)" onclick='
 -    TITLE_PATTERN = r'<title>(?P<title>[^<]+)</title>'
 -
 -    def decrypt(self, pyfile):
 -        self.html = self.load(pyfile.url)
 -
 -        package_name, folder_name = self.getPackageNameAndFolder()
 -
 -        m = re.search(self.PLAIN_PATTERN, self.html)
 -        if m:
 -            plain_link = 'http://uploaded.net/' + m.group('plain')
 -        else:
 -            self.fail('Parse error - Unable to find plain url list')
 -
 -        self.html = self.load(plain_link)
 -        package_links = self.html.split('\n')[:-1]
 -        self.logDebug('Package has %d links' % len(package_links))
 -
 -        self.packages = [(package_name, package_links, folder_name)]
 +# -*- coding: utf-8 -*- + +############################################################################ +# This program is free software: you can redistribute it and/or modify     # +# it under the terms of the GNU Affero 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 Affero General Public License for more details.                      # +#                                                                          # +# You should have received a copy of the GNU Affero General Public License # +# along with this program.  If not, see <http://www.gnu.org/licenses/>.    # +############################################################################ + +import re + +from module.plugins.internal.SimpleCrypter import SimpleCrypter + + +class UploadedToFolder(SimpleCrypter): +    __name__ = "UploadedToFolder" +    __type__ = "crypter" +    __pattern__ = r"http://(?:www\.)?(uploaded|ul)\.(to|net)/(f|folder|list)/(?P<id>\w+)" +    __version__ = "0.3" +    __description__ = """UploadedTo Crypter Plugin""" +    __author_name__ = ("stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    PLAIN_PATTERN = r'<small class="date"><a href="(?P<plain>[\w/]+)" onclick=' +    TITLE_PATTERN = r'<title>(?P<title>[^<]+)</title>' + +    def decrypt(self, pyfile): +        self.html = self.load(pyfile.url) + +        package_name, folder_name = self.getPackageNameAndFolder() + +        m = re.search(self.PLAIN_PATTERN, self.html) +        if m: +            plain_link = 'http://uploaded.net/' + m.group('plain') +        else: +            self.fail('Parse error - Unable to find plain url list') + +        self.html = self.load(plain_link) +        package_links = self.html.split('\n')[:-1] +        self.logDebug('Package has %d links' % len(package_links)) + +        self.packages = [(package_name, package_links, folder_name)] diff --git a/module/plugins/crypter/WiiReloadedOrg.py b/module/plugins/crypter/WiiReloadedOrg.py index 574a147c4..ba101892d 100644 --- a/module/plugins/crypter/WiiReloadedOrg.py +++ b/module/plugins/crypter/WiiReloadedOrg.py @@ -1,52 +1,52 @@ -
 -import re
 -
 -from module.plugins.Crypter import Crypter
 -
 -class WiiReloadedOrg(Crypter):
 -    __name__ = "WiiReloadedOrg"
 -    __type__ = "crypter"
 -    __pattern__ = r"http://www\.wii-reloaded\.org/protect/get\.php\?i=.+"
 -    __config__ = [("changeName", "bool", "Use Wii-Reloaded.org folder name", "True")]
 -    __version__ = "0.1"
 -    __description__ = """Wii-Reloaded.org Crypter Plugin"""
 -    __author_name__ = ("hzpz")
 -    __author_mail__ = ("none")
 -    
 -    
 -    def decrypt(self, pyfile):
 -        url = pyfile.url
 -        src = self.req.load(str(url))
 -        
 -        ids = re.findall(r"onClick=\"popup_dl\((.+)\)\"", src)
 -        if len(ids) == 0:
 -            self.fail("Unable to decrypt links, this plugin probably needs to be updated")
 -        
 -        packageName = self.pyfile.package().name
 -        if self.getConfig("changeName"):
 -            packageNameMatch = re.search(r"<div id=\"foldername\">(.+)</div>", src)
 -            if not packageNameMatch:
 -                self.logWarning("Unable to get folder name, this plugin probably needs to be updated")
 -            else:
 -                packageName = packageNameMatch.group(1)
 -                
 -        self.pyfile.package().password = "wii-reloaded.info"
 -        
 -        self.logDebug("Processing %d links" % len(ids))
 -        links = []
 -        for id in ids:
 -            self.req.lastURL = str(url)
 -            header = self.req.load("http://www.wii-reloaded.org/protect/hastesosiehtsaus.php?i=" + id, just_header=True)
 -            self.logDebug("Header:\n" + header)
 -            redirectLocationMatch = re.search(r"^Location: (.+)$", header, flags=re.MULTILINE)
 -            if not redirectLocationMatch:
 -                self.offline()
 -            redirectLocation = redirectLocationMatch.group(1)
 -            self.logDebug(len(redirectLocation))
 -            if not redirectLocation.startswith("http"):
 -                self.offline()
 -            self.logDebug("Decrypted link: %s" % redirectLocation)
 -            links.append(redirectLocation)
 -            
 -        self.logDebug("Decrypted %d links" % len(links))
 + +import re + +from module.plugins.Crypter import Crypter + +class WiiReloadedOrg(Crypter): +    __name__ = "WiiReloadedOrg" +    __type__ = "crypter" +    __pattern__ = r"http://www\.wii-reloaded\.org/protect/get\.php\?i=.+" +    __config__ = [("changeName", "bool", "Use Wii-Reloaded.org folder name", "True")] +    __version__ = "0.1" +    __description__ = """Wii-Reloaded.org Crypter Plugin""" +    __author_name__ = ("hzpz") +    __author_mail__ = ("none") +     +     +    def decrypt(self, pyfile): +        url = pyfile.url +        src = self.req.load(str(url)) +         +        ids = re.findall(r"onClick=\"popup_dl\((.+)\)\"", src) +        if len(ids) == 0: +            self.fail("Unable to decrypt links, this plugin probably needs to be updated") +         +        packageName = self.pyfile.package().name +        if self.getConfig("changeName"): +            packageNameMatch = re.search(r"<div id=\"foldername\">(.+)</div>", src) +            if not packageNameMatch: +                self.logWarning("Unable to get folder name, this plugin probably needs to be updated") +            else: +                packageName = packageNameMatch.group(1) +                 +        self.pyfile.package().password = "wii-reloaded.info" +         +        self.logDebug("Processing %d links" % len(ids)) +        links = [] +        for id in ids: +            self.req.lastURL = str(url) +            header = self.req.load("http://www.wii-reloaded.org/protect/hastesosiehtsaus.php?i=" + id, just_header=True) +            self.logDebug("Header:\n" + header) +            redirectLocationMatch = re.search(r"^Location: (.+)$", header, flags=re.MULTILINE) +            if not redirectLocationMatch: +                self.offline() +            redirectLocation = redirectLocationMatch.group(1) +            self.logDebug(len(redirectLocation)) +            if not redirectLocation.startswith("http"): +                self.offline() +            self.logDebug("Decrypted link: %s" % redirectLocation) +            links.append(redirectLocation) +             +        self.logDebug("Decrypted %d links" % len(links))          self.packages.append((packageName, links, packageName))
\ No newline at end of file diff --git a/module/plugins/hooks/Captcha9kw.py b/module/plugins/hooks/Captcha9kw.py index 3bc00d8c2..cd622b7cd 100755 --- a/module/plugins/hooks/Captcha9kw.py +++ b/module/plugins/hooks/Captcha9kw.py @@ -1,163 +1,163 @@ -# -*- 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: mkaay, RaNaN, zoidberg
 -"""
 -from __future__ import with_statement
 -
 -from thread import start_new_thread
 -from base64 import b64encode
 -import cStringIO
 -import pycurl
 -import time
 -
 -from module.network.RequestFactory import getURL, getRequest
 -from module.network.HTTPRequest import BadHeader
 -
 -from module.plugins.Hook import Hook
 -
 -class Captcha9kw(Hook):
 -    __name__ = "Captcha9kw"
 -    __version__ = "0.07"
 -    __description__ = """send captchas to 9kw.eu"""
 -    __config__ = [("activated", "bool", "Activated", False),
 -                  ("force", "bool", "Force CT even if client is connected", True),
 -                  ("https", "bool", "Enable HTTPS", "False"),
 -                  ("confirm", "bool", "Confirm Captcha (Cost +6)", "False"),
 -                  ("captchaperhour", "int", "Captcha per hour (max. 9999)", "9999"),
 -                  ("prio", "int", "Prio 1-10 (Cost +1-10)", "0"),
 -                  ("timeout", "int", "Timeout (max. 300)", "220"),                  
 -                  ("passkey", "password", "API key", ""),]
 -    __author_name__ = ("RaNaN")
 -    __author_mail__ = ("RaNaN@pyload.org")
 -
 -    API_URL = "://www.9kw.eu/index.cgi"
 -
 -    def setup(self):
 -        self.API_URL = "https"+self.API_URL if self.getConfig("https") else "http"+self.API_URL
 -        self.info = {}
 -
 -    def getCredits(self):
 -        response = getURL(self.API_URL, get = { "apikey": self.getConfig("passkey"), "pyload": "1", "source": "pyload", "action": "usercaptchaguthaben" })
 -
 -        if response.isdigit():
 -            self.logInfo(_("%s credits left") % response)
 -            self.info["credits"] = credits = int(response)
 -            return credits
 -        else:
 -            self.logError(response)
 -            return 0
 -
 -    def processCaptcha(self, task):
 -        result = None
 -
 -        with open(task.captchaFile, 'rb') as f:
 -            data = f.read()
 -        data = b64encode(data)
 -        self.logDebug("%s : %s" % (task.captchaFile, data))
 -        if task.isPositional():
 -            mouse = 1
 -        else:
 -            mouse = 0
 -
 -        response = getURL(self.API_URL, post = { 
 -                          "apikey": self.getConfig("passkey"), 
 -                          "prio": self.getConfig("prio"),
 -                          "confirm": self.getConfig("confirm"),
 -                          "captchaperhour": self.getConfig("captchaperhour"),
 -                          "maxtimeout": self.getConfig("timeout"),
 -                          "pyload": "1", 
 -                          "source": "pyload", 
 -                          "base64": "1", 
 -                          "mouse": mouse,
 -                          "file-upload-01": data, 
 -                          "action": "usercaptchaupload" })
 -
 -        if response.isdigit():
 -            self.logInfo(_("New CaptchaID from upload: %s : %s") % (response,task.captchaFile))
 -
 -            for i in range(1, 100, 1): 
 -                response2 = getURL(self.API_URL, get = { "apikey": self.getConfig("passkey"), "id": response,"pyload": "1","source": "pyload", "action": "usercaptchacorrectdata" })
 -
 -                if(response2 != ""):
 -                    break;
 -
 -                time.sleep(3)
 -
 -            result = response2
 -            task.data["ticket"] = response
 -            self.logInfo("result %s : %s" % (response, result))
 -            task.setResult(result)
 -        else:
 -            self.logError("Bad upload: %s" % response)
 -            return False
 -
 -    def newCaptchaTask(self, task):
 -        if not task.isTextual() and not task.isPositional():
 -            return False
 -
 -        if not self.getConfig("passkey"):
 -            return False
 -
 -        if self.core.isClientConnected() and not self.getConfig("force"):
 -            return False
 -
 -        if self.getCredits() > 0:
 -            task.handler.append(self)
 -            task.setWaiting(self.getConfig("timeout"))
 -            start_new_thread(self.processCaptcha, (task,))
 -
 -        else:
 -            self.logError(_("Your Captcha 9kw.eu Account has not enough credits"))
 -
 -    def captchaCorrect(self, task):
 -        if "ticket" in task.data:
 -
 -            try:
 -                response = getURL(self.API_URL, 
 -                              post={ "action": "usercaptchacorrectback",
 -                                     "apikey": self.getConfig("passkey"),
 -                                     "api_key": self.getConfig("passkey"),
 -                                     "correct": "1",
 -                                     "pyload": "1",
 -                                     "source": "pyload", 
 -                                     "id": task.data["ticket"] }
 -                              )
 -                self.logInfo("Request correct: %s" % response)
 -
 -            except BadHeader, e:
 -                self.logError("Could not send correct request.", str(e))
 -        else:
 -             self.logError("No CaptchaID for correct request (task %s) found." % task)
 -
 -    def captchaInvalid(self, task):
 -        if "ticket" in task.data:
 -            
 -            try:
 -                response = getURL(self.API_URL, 
 -                              post={ "action": "usercaptchacorrectback",
 -                                     "apikey": self.getConfig("passkey"),
 -                                     "api_key": self.getConfig("passkey"),
 -                                     "correct": "2",
 -                                     "pyload": "1",
 -                                     "source": "pyload", 
 -                                     "id": task.data["ticket"] }
 -                              )
 -                self.logInfo("Request refund: %s" % response)
 -
 -            except BadHeader, e:
 -                self.logError("Could not send refund request.", str(e))
 -        else:
 -            self.logError("No CaptchaID for not correct request (task %s) found." % task)
 +# -*- 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: mkaay, RaNaN, zoidberg +""" +from __future__ import with_statement + +from thread import start_new_thread +from base64 import b64encode +import cStringIO +import pycurl +import time + +from module.network.RequestFactory import getURL, getRequest +from module.network.HTTPRequest import BadHeader + +from module.plugins.Hook import Hook + +class Captcha9kw(Hook): +    __name__ = "Captcha9kw" +    __version__ = "0.07" +    __description__ = """send captchas to 9kw.eu""" +    __config__ = [("activated", "bool", "Activated", False), +                  ("force", "bool", "Force CT even if client is connected", True), +                  ("https", "bool", "Enable HTTPS", "False"), +                  ("confirm", "bool", "Confirm Captcha (Cost +6)", "False"), +                  ("captchaperhour", "int", "Captcha per hour (max. 9999)", "9999"), +                  ("prio", "int", "Prio 1-10 (Cost +1-10)", "0"), +                  ("timeout", "int", "Timeout (max. 300)", "220"),                   +                  ("passkey", "password", "API key", ""),] +    __author_name__ = ("RaNaN") +    __author_mail__ = ("RaNaN@pyload.org") + +    API_URL = "://www.9kw.eu/index.cgi" + +    def setup(self): +        self.API_URL = "https"+self.API_URL if self.getConfig("https") else "http"+self.API_URL +        self.info = {} + +    def getCredits(self): +        response = getURL(self.API_URL, get = { "apikey": self.getConfig("passkey"), "pyload": "1", "source": "pyload", "action": "usercaptchaguthaben" }) + +        if response.isdigit(): +            self.logInfo(_("%s credits left") % response) +            self.info["credits"] = credits = int(response) +            return credits +        else: +            self.logError(response) +            return 0 + +    def processCaptcha(self, task): +        result = None + +        with open(task.captchaFile, 'rb') as f: +            data = f.read() +        data = b64encode(data) +        self.logDebug("%s : %s" % (task.captchaFile, data)) +        if task.isPositional(): +            mouse = 1 +        else: +            mouse = 0 + +        response = getURL(self.API_URL, post = {  +                          "apikey": self.getConfig("passkey"),  +                          "prio": self.getConfig("prio"), +                          "confirm": self.getConfig("confirm"), +                          "captchaperhour": self.getConfig("captchaperhour"), +                          "maxtimeout": self.getConfig("timeout"), +                          "pyload": "1",  +                          "source": "pyload",  +                          "base64": "1",  +                          "mouse": mouse, +                          "file-upload-01": data,  +                          "action": "usercaptchaupload" }) + +        if response.isdigit(): +            self.logInfo(_("New CaptchaID from upload: %s : %s") % (response,task.captchaFile)) + +            for i in range(1, 100, 1):  +                response2 = getURL(self.API_URL, get = { "apikey": self.getConfig("passkey"), "id": response,"pyload": "1","source": "pyload", "action": "usercaptchacorrectdata" }) + +                if(response2 != ""): +                    break; + +                time.sleep(3) + +            result = response2 +            task.data["ticket"] = response +            self.logInfo("result %s : %s" % (response, result)) +            task.setResult(result) +        else: +            self.logError("Bad upload: %s" % response) +            return False + +    def newCaptchaTask(self, task): +        if not task.isTextual() and not task.isPositional(): +            return False + +        if not self.getConfig("passkey"): +            return False + +        if self.core.isClientConnected() and not self.getConfig("force"): +            return False + +        if self.getCredits() > 0: +            task.handler.append(self) +            task.setWaiting(self.getConfig("timeout")) +            start_new_thread(self.processCaptcha, (task,)) + +        else: +            self.logError(_("Your Captcha 9kw.eu Account has not enough credits")) + +    def captchaCorrect(self, task): +        if "ticket" in task.data: + +            try: +                response = getURL(self.API_URL,  +                              post={ "action": "usercaptchacorrectback", +                                     "apikey": self.getConfig("passkey"), +                                     "api_key": self.getConfig("passkey"), +                                     "correct": "1", +                                     "pyload": "1", +                                     "source": "pyload",  +                                     "id": task.data["ticket"] } +                              ) +                self.logInfo("Request correct: %s" % response) + +            except BadHeader, e: +                self.logError("Could not send correct request.", str(e)) +        else: +             self.logError("No CaptchaID for correct request (task %s) found." % task) + +    def captchaInvalid(self, task): +        if "ticket" in task.data: +             +            try: +                response = getURL(self.API_URL,  +                              post={ "action": "usercaptchacorrectback", +                                     "apikey": self.getConfig("passkey"), +                                     "api_key": self.getConfig("passkey"), +                                     "correct": "2", +                                     "pyload": "1", +                                     "source": "pyload",  +                                     "id": task.data["ticket"] } +                              ) +                self.logInfo("Request refund: %s" % response) + +            except BadHeader, e: +                self.logError("Could not send refund request.", str(e)) +        else: +            self.logError("No CaptchaID for not correct request (task %s) found." % task) diff --git a/module/plugins/hooks/Premium4Me.py b/module/plugins/hooks/Premium4Me.py index 16b02ce87..edbdfbdb9 100644 --- a/module/plugins/hooks/Premium4Me.py +++ b/module/plugins/hooks/Premium4Me.py @@ -1,33 +1,33 @@ -# -*- coding: utf-8 -*-
 -
 -from module.network.RequestFactory import getURL
 -from module.plugins.internal.MultiHoster import MultiHoster
 -
 -class Premium4Me(MultiHoster):
 -    __name__ = "Premium4Me"
 -    __version__ = "0.03"
 -    __type__ = "hook"
 -
 -    __config__ = [("activated", "bool", "Activated", "False"),
 -        ("hosterListMode", "all;listed;unlisted", "Use for downloads from supported hosters:", "all"),
 -        ("hosterList", "str", "Hoster list (comma separated)", "")]
 -    __description__ = """Premium.to hook plugin"""
 -    __author_name__ = ("RaNaN", "zoidberg", "stickell")
 -    __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz", "l.stickell@yahoo.it")
 -
 -    def getHoster(self):
 -
 -        page = getURL("http://premium.to/api/hosters.php?authcode=%s" % self.account.authcode)
 -        return [x.strip() for x in page.replace("\"", "").split(";")]
 -
 -    def coreReady(self):
 -
 -        self.account = self.core.accountManager.getAccountPlugin("Premium4Me")
 -
 -        user = self.account.selectAccount()[0]
 -
 -        if not user:
 -            self.logError(_("Please add your premium.to account first and restart pyLoad"))
 -            return
 -
 +# -*- coding: utf-8 -*- + +from module.network.RequestFactory import getURL +from module.plugins.internal.MultiHoster import MultiHoster + +class Premium4Me(MultiHoster): +    __name__ = "Premium4Me" +    __version__ = "0.03" +    __type__ = "hook" + +    __config__ = [("activated", "bool", "Activated", "False"), +        ("hosterListMode", "all;listed;unlisted", "Use for downloads from supported hosters:", "all"), +        ("hosterList", "str", "Hoster list (comma separated)", "")] +    __description__ = """Premium.to hook plugin""" +    __author_name__ = ("RaNaN", "zoidberg", "stickell") +    __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz", "l.stickell@yahoo.it") + +    def getHoster(self): + +        page = getURL("http://premium.to/api/hosters.php?authcode=%s" % self.account.authcode) +        return [x.strip() for x in page.replace("\"", "").split(";")] + +    def coreReady(self): + +        self.account = self.core.accountManager.getAccountPlugin("Premium4Me") + +        user = self.account.selectAccount()[0] + +        if not user: +            self.logError(_("Please add your premium.to account first and restart pyLoad")) +            return +          return MultiHoster.coreReady(self)
\ No newline at end of file diff --git a/module/plugins/hoster/AlldebridCom.py b/module/plugins/hoster/AlldebridCom.py index 08a1d1cf9..cdb5ccc08 100644 --- a/module/plugins/hoster/AlldebridCom.py +++ b/module/plugins/hoster/AlldebridCom.py @@ -1,84 +1,84 @@ -# -*- coding: utf-8 -*-
 -
 -import re
 -from urllib import unquote
 -from random import randrange
 -from module.plugins.Hoster import Hoster
 -from module.common.json_layer import json_loads
 -from module.utils import parseFileSize
 -
 -
 -class AlldebridCom(Hoster):
 -    __name__ = "AlldebridCom"
 -    __version__ = "0.33"
 -    __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 %s account or deactivate this plugin") % "AllDebrid")
 -            self.fail("No AllDebrid account provided")
 -
 -        self.logDebug("AllDebrid: Old URL: %s" % pyfile.url)
 -        if re.match(self.__pattern__, pyfile.url):
 -            new_url = pyfile.url
 -        else:
 -            password = self.getPassword().splitlines()
 -            password = "" if not password else 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.logDebug("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.logDebug("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)
 -        elif check == "empty":
 -            self.retry(reason="Downloaded File was empty.", wait_time=60)
 +# -*- coding: utf-8 -*- + +import re +from urllib import unquote +from random import randrange +from module.plugins.Hoster import Hoster +from module.common.json_layer import json_loads +from module.utils import parseFileSize + + +class AlldebridCom(Hoster): +    __name__ = "AlldebridCom" +    __version__ = "0.33" +    __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 %s account or deactivate this plugin") % "AllDebrid") +            self.fail("No AllDebrid account provided") + +        self.logDebug("AllDebrid: Old URL: %s" % pyfile.url) +        if re.match(self.__pattern__, pyfile.url): +            new_url = pyfile.url +        else: +            password = self.getPassword().splitlines() +            password = "" if not password else 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.logDebug("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.logDebug("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) +        elif check == "empty": +            self.retry(reason="Downloaded File was empty.", wait_time=60) diff --git a/module/plugins/hoster/EgoFilesCom.py b/module/plugins/hoster/EgoFilesCom.py index e203e2a1b..274286cf1 100644 --- a/module/plugins/hoster/EgoFilesCom.py +++ b/module/plugins/hoster/EgoFilesCom.py @@ -1,103 +1,103 @@ -# -*- coding: utf-8 -*-
 -
 -############################################################################
 -# This program is free software: you can redistribute it and/or modify     #
 -# it under the terms of the GNU Affero 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 Affero General Public License for more details.                      #
 -#                                                                          #
 -# You should have received a copy of the GNU Affero General Public License #
 -# along with this program.  If not, see <http://www.gnu.org/licenses/>.    #
 -############################################################################
 -
 -# Test link (random.bin):
 -# http://egofiles.com/mOZfMI1WLZ6HBkGG/random.bin
 -
 -import re
 -
 -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
 -from module.plugins.internal.CaptchaService import ReCaptcha
 -
 -
 -class EgoFilesCom(SimpleHoster):
 -    __name__ = "EgoFilesCom"
 -    __type__ = "hoster"
 -    __pattern__ = r"https?://(www\.)?egofiles.com/(\w+)"
 -    __version__ = "0.13"
 -    __description__ = """Egofiles.com Download Hoster"""
 -    __author_name__ = ("stickell")
 -    __author_mail__ = ("l.stickell@yahoo.it")
 -
 -    FILE_INFO_PATTERN = r'<div class="down-file">\s+(?P<N>[^\t]+)\s+<div class="file-properties">\s+(File size|Rozmiar): (?P<S>[\w.]+) (?P<U>\w+) \|'
 -    FILE_OFFLINE_PATTERN = r'(File size|Rozmiar): 0 KB'
 -    WAIT_TIME_PATTERN = r'For next free download you have to wait <strong>((?P<m>\d*)m)? ?((?P<s>\d+)s)?</strong>'
 -    DIRECT_LINK_PATTERN = r'<a href="(?P<link>[^"]+)">Download ></a>'
 -    RECAPTCHA_KEY = '6LeXatQSAAAAAHezcjXyWAni-4t302TeYe7_gfvX'
 -
 -    def init(self):
 -        self.file_info = {}
 -        # Set English language
 -        self.load("https://egofiles.com/ajax/lang.php?lang=en", just_header=True)
 -
 -    def process(self, pyfile):
 -        if self.premium and (not self.SH_CHECK_TRAFFIC or self.checkTrafficLeft()):
 -            self.handlePremium()
 -        else:
 -            self.handleFree()
 -
 -    def handleFree(self):
 -        self.html = self.load(self.pyfile.url, decode=True)
 -        self.getFileInfo()
 -
 -        # Wait time between free downloads
 -        if 'For next free download you have to wait' in self.html:
 -            m = re.search(self.WAIT_TIME_PATTERN, self.html).groupdict('0')
 -            waittime = int(m['m']) * 60 + int(m['s'])
 -            self.setWait(waittime, True)
 -            self.wait()
 -
 -        downloadURL = ''
 -        recaptcha = ReCaptcha(self)
 -        for i in xrange(5):
 -            challenge, response = recaptcha.challenge(self.RECAPTCHA_KEY)
 -            post_data = {'recaptcha_challenge_field': challenge,
 -                         'recaptcha_response_field': response}
 -            self.html = self.load(self.pyfile.url, post=post_data, decode=True)
 -            m = re.search(self.DIRECT_LINK_PATTERN, self.html)
 -            if not m:
 -                self.logInfo('Wrong captcha')
 -                self.invalidCaptcha()
 -            elif hasattr(m, 'group'):
 -                downloadURL = m.group('link')
 -                self.correctCaptcha()
 -                break
 -            else:
 -                self.fail('Unknown error - Plugin may be out of date')
 -
 -        if not downloadURL:
 -            self.fail("No Download url retrieved/all captcha attempts failed")
 -
 -        self.download(downloadURL, disposition=True)
 -
 -    def handlePremium(self):
 -        header = self.load(self.pyfile.url, just_header=True)
 -        if header.has_key('location'):
 -            self.logDebug('DIRECT LINK from header: ' + header['location'])
 -            self.download(header['location'])
 -        else:
 -            self.html = self.load(self.pyfile.url, decode=True)
 -            self.getFileInfo()
 -            m = re.search(r'<a href="(?P<link>[^"]+)">Download ></a>', self.html)
 -            if not m:
 -                self.parseError('Unable to detect direct download url')
 -            else:
 -                self.logDebug('DIRECT URL from html: ' + m.group('link'))
 -                self.download(m.group('link'), disposition=True)
 -
 -
 -getInfo = create_getInfo(EgoFilesCom)
 +# -*- coding: utf-8 -*- + +############################################################################ +# This program is free software: you can redistribute it and/or modify     # +# it under the terms of the GNU Affero 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 Affero General Public License for more details.                      # +#                                                                          # +# You should have received a copy of the GNU Affero General Public License # +# along with this program.  If not, see <http://www.gnu.org/licenses/>.    # +############################################################################ + +# Test link (random.bin): +# http://egofiles.com/mOZfMI1WLZ6HBkGG/random.bin + +import re + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.plugins.internal.CaptchaService import ReCaptcha + + +class EgoFilesCom(SimpleHoster): +    __name__ = "EgoFilesCom" +    __type__ = "hoster" +    __pattern__ = r"https?://(www\.)?egofiles.com/(\w+)" +    __version__ = "0.13" +    __description__ = """Egofiles.com Download Hoster""" +    __author_name__ = ("stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    FILE_INFO_PATTERN = r'<div class="down-file">\s+(?P<N>[^\t]+)\s+<div class="file-properties">\s+(File size|Rozmiar): (?P<S>[\w.]+) (?P<U>\w+) \|' +    FILE_OFFLINE_PATTERN = r'(File size|Rozmiar): 0 KB' +    WAIT_TIME_PATTERN = r'For next free download you have to wait <strong>((?P<m>\d*)m)? ?((?P<s>\d+)s)?</strong>' +    DIRECT_LINK_PATTERN = r'<a href="(?P<link>[^"]+)">Download ></a>' +    RECAPTCHA_KEY = '6LeXatQSAAAAAHezcjXyWAni-4t302TeYe7_gfvX' + +    def init(self): +        self.file_info = {} +        # Set English language +        self.load("https://egofiles.com/ajax/lang.php?lang=en", just_header=True) + +    def process(self, pyfile): +        if self.premium and (not self.SH_CHECK_TRAFFIC or self.checkTrafficLeft()): +            self.handlePremium() +        else: +            self.handleFree() + +    def handleFree(self): +        self.html = self.load(self.pyfile.url, decode=True) +        self.getFileInfo() + +        # Wait time between free downloads +        if 'For next free download you have to wait' in self.html: +            m = re.search(self.WAIT_TIME_PATTERN, self.html).groupdict('0') +            waittime = int(m['m']) * 60 + int(m['s']) +            self.setWait(waittime, True) +            self.wait() + +        downloadURL = '' +        recaptcha = ReCaptcha(self) +        for i in xrange(5): +            challenge, response = recaptcha.challenge(self.RECAPTCHA_KEY) +            post_data = {'recaptcha_challenge_field': challenge, +                         'recaptcha_response_field': response} +            self.html = self.load(self.pyfile.url, post=post_data, decode=True) +            m = re.search(self.DIRECT_LINK_PATTERN, self.html) +            if not m: +                self.logInfo('Wrong captcha') +                self.invalidCaptcha() +            elif hasattr(m, 'group'): +                downloadURL = m.group('link') +                self.correctCaptcha() +                break +            else: +                self.fail('Unknown error - Plugin may be out of date') + +        if not downloadURL: +            self.fail("No Download url retrieved/all captcha attempts failed") + +        self.download(downloadURL, disposition=True) + +    def handlePremium(self): +        header = self.load(self.pyfile.url, just_header=True) +        if header.has_key('location'): +            self.logDebug('DIRECT LINK from header: ' + header['location']) +            self.download(header['location']) +        else: +            self.html = self.load(self.pyfile.url, decode=True) +            self.getFileInfo() +            m = re.search(r'<a href="(?P<link>[^"]+)">Download ></a>', self.html) +            if not m: +                self.parseError('Unable to detect direct download url') +            else: +                self.logDebug('DIRECT URL from html: ' + m.group('link')) +                self.download(m.group('link'), disposition=True) + + +getInfo = create_getInfo(EgoFilesCom) diff --git a/module/plugins/hoster/FreakshareCom.py b/module/plugins/hoster/FreakshareCom.py index e34edd165..156f697c3 100644 --- a/module/plugins/hoster/FreakshareCom.py +++ b/module/plugins/hoster/FreakshareCom.py @@ -1,167 +1,167 @@ -#!/usr/bin/env python
 -# -*- coding: utf-8 -*-
 -
 -import re
 -from module.plugins.Hoster import Hoster
 -from module.plugins.internal.CaptchaService import ReCaptcha
 -
 -class FreakshareCom(Hoster):
 -    __name__ = "FreakshareCom"
 -    __type__ = "hoster"
 -    __pattern__ = r"http://(?:www\.)?freakshare\.(net|com)/files/\S*?/"
 -    __version__ = "0.37"
 -    __description__ = """Freakshare.com Download Hoster"""
 -    __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
 -        self.wantReconnect = False
 -        self.multiDL = False
 -        self.req_opts = []
 -
 -    def process(self, pyfile):
 -        self.pyfile = pyfile
 -        
 -        pyfile.url = pyfile.url.replace("freakshare.net/","freakshare.com/")
 -
 -        if self.account:
 -            self.html = self.load(pyfile.url, cookies=False)
 -            pyfile.name = self.get_file_name()
 -            self.download(pyfile.url)
 -
 -        else:
 -            self.prepare()
 -            self.get_file_url()
 -
 -            self.download(self.pyfile.url, post=self.req_opts)
 -
 -
 -            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
 -
 -        self.wantReconnect = False
 -        
 -        self.download_html()
 -
 -        if not self.file_exists():
 -            self.offline()
 -            
 -        self.setWait( self.get_waiting_time() )
 -
 -        pyfile.name = self.get_file_name()
 -        pyfile.size = self.get_file_size()
 -            
 -        self.wait()
 -
 -        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):
 -        """ returns the absolute downloadable filepath
 -        """
 -        if self.html is None:
 -            self.download_html()
 -        if not self.wantReconnect:
 -            self.req_opts = self.get_download_options() # get the Post options for the Request
 -            #file_url = self.pyfile.url
 -            #return file_url
 -        else:
 -            self.offline()
 -
 -    def get_file_name(self):
 -        if self.html is None:
 -            self.download_html()
 -        if not self.wantReconnect:
 -            file_name = re.search(r"<h1\sclass=\"box_heading\"\sstyle=\"text-align:center;\">([^ ]+)", self.html)
 -            if file_name is not None:
 -                file_name = file_name.group(1)
 -            else:
 -                file_name = self.pyfile.url
 -            return file_name
 -        else:
 -            return self.pyfile.url
 -    
 -    def get_file_size(self):
 -        size = 0
 -        if self.html is None:
 -            self.download_html()
 -        if not self.wantReconnect:
 -            file_size_check = re.search(r"<h1\sclass=\"box_heading\"\sstyle=\"text-align:center;\">[^ ]+ - ([^ ]+) (\w\w)yte", self.html)
 -            if file_size_check is not None:
 -                units = float(file_size_check.group(1).replace(",", ""))
 -                pow = {'KB': 1, 'MB': 2, 'GB': 3}[file_size_check.group(2)]
 -                size = int(units * 1024 ** pow)
 -
 -        return size
 -    
 -    def get_waiting_time(self):
 -        if self.html is None:
 -            self.download_html()
 -
 -        if "Your Traffic is used up for today" in self.html:
 -            self.wantReconnect = True
 -            return 24*3600
 -
 -        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:
 -            return 60
 -
 -
 -    def file_exists(self):
 -        """ returns True or False
 -        """
 -        if self.html is None:
 -            self.download_html()
 -        if re.search(r"This file does not exist!", self.html) is not None:
 -            return False
 -        else:
 -            return True
 -
 -    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 = dict((n, v) for (v, n) in to_sort)
 -            
 -        herewego = self.load(self.pyfile.url, None, request_options) # the actual download-Page
 -        
 -        # comment this in, when it doesnt work
 -        # with open("DUMP__FS_.HTML", "w") as fp:
 -            # fp.write(herewego)
 -        
 -        to_sort = re.findall(r"<input\stype=\".*?\"\svalue=\"(\S*?)\".*?name=\"(\S*?)\"\s.*?\/>", herewego)
 -        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])
 -
 -        challenge = re.search(r"http://api\.recaptcha\.net/challenge\?k=([0-9A-Za-z]+)", herewego)
 -
 -        if challenge:
 -            re_captcha = ReCaptcha(self)
 -            request_options["recaptcha_challenge_field"], request_options["recaptcha_response_field"] \
 -                = re_captcha.challenge(challenge.group(1))
 -
 -        return request_options
 +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from module.plugins.Hoster import Hoster +from module.plugins.internal.CaptchaService import ReCaptcha + +class FreakshareCom(Hoster): +    __name__ = "FreakshareCom" +    __type__ = "hoster" +    __pattern__ = r"http://(?:www\.)?freakshare\.(net|com)/files/\S*?/" +    __version__ = "0.37" +    __description__ = """Freakshare.com Download Hoster""" +    __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 +        self.wantReconnect = False +        self.multiDL = False +        self.req_opts = [] + +    def process(self, pyfile): +        self.pyfile = pyfile +         +        pyfile.url = pyfile.url.replace("freakshare.net/","freakshare.com/") + +        if self.account: +            self.html = self.load(pyfile.url, cookies=False) +            pyfile.name = self.get_file_name() +            self.download(pyfile.url) + +        else: +            self.prepare() +            self.get_file_url() + +            self.download(self.pyfile.url, post=self.req_opts) + + +            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 + +        self.wantReconnect = False +         +        self.download_html() + +        if not self.file_exists(): +            self.offline() +             +        self.setWait( self.get_waiting_time() ) + +        pyfile.name = self.get_file_name() +        pyfile.size = self.get_file_size() +             +        self.wait() + +        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): +        """ returns the absolute downloadable filepath +        """ +        if self.html is None: +            self.download_html() +        if not self.wantReconnect: +            self.req_opts = self.get_download_options() # get the Post options for the Request +            #file_url = self.pyfile.url +            #return file_url +        else: +            self.offline() + +    def get_file_name(self): +        if self.html is None: +            self.download_html() +        if not self.wantReconnect: +            file_name = re.search(r"<h1\sclass=\"box_heading\"\sstyle=\"text-align:center;\">([^ ]+)", self.html) +            if file_name is not None: +                file_name = file_name.group(1) +            else: +                file_name = self.pyfile.url +            return file_name +        else: +            return self.pyfile.url +     +    def get_file_size(self): +        size = 0 +        if self.html is None: +            self.download_html() +        if not self.wantReconnect: +            file_size_check = re.search(r"<h1\sclass=\"box_heading\"\sstyle=\"text-align:center;\">[^ ]+ - ([^ ]+) (\w\w)yte", self.html) +            if file_size_check is not None: +                units = float(file_size_check.group(1).replace(",", "")) +                pow = {'KB': 1, 'MB': 2, 'GB': 3}[file_size_check.group(2)] +                size = int(units * 1024 ** pow) + +        return size +     +    def get_waiting_time(self): +        if self.html is None: +            self.download_html() + +        if "Your Traffic is used up for today" in self.html: +            self.wantReconnect = True +            return 24*3600 + +        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: +            return 60 + + +    def file_exists(self): +        """ returns True or False +        """ +        if self.html is None: +            self.download_html() +        if re.search(r"This file does not exist!", self.html) is not None: +            return False +        else: +            return True + +    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 = dict((n, v) for (v, n) in to_sort) +             +        herewego = self.load(self.pyfile.url, None, request_options) # the actual download-Page +         +        # comment this in, when it doesnt work +        # with open("DUMP__FS_.HTML", "w") as fp: +            # fp.write(herewego) +         +        to_sort = re.findall(r"<input\stype=\".*?\"\svalue=\"(\S*?)\".*?name=\"(\S*?)\"\s.*?\/>", herewego) +        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]) + +        challenge = re.search(r"http://api\.recaptcha\.net/challenge\?k=([0-9A-Za-z]+)", herewego) + +        if challenge: +            re_captcha = ReCaptcha(self) +            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/Ftp.py b/module/plugins/hoster/Ftp.py index 3bda3b32e..c68f3b237 100644 --- a/module/plugins/hoster/Ftp.py +++ b/module/plugins/hoster/Ftp.py @@ -1,91 +1,91 @@ -# -*- 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
 -    @author: mkaay
 -"""
 -from urlparse import urlparse, urljoin
 -from urllib import quote, unquote
 -import pycurl, re
 -
 -from module.plugins.Hoster import Hoster
 -from module.network.HTTPRequest import BadHeader
 -
 -class Ftp(Hoster):
 -    __name__ = "Ftp"
 -    __version__ = "0.41"
 -    __pattern__ = r'(ftps?|sftp)://(.*?:.*?@)?.*?/.*' # ftp://user:password@ftp.server.org/path/to/file
 -    __type__ = "hoster"
 -    __description__ = """A Plugin that allows you to download from an from an ftp directory"""
 -    __author_name__ = ("jeix", "mkaay", "zoidberg")
 -    __author_mail__ = ("jeix@hasnomail.com", "mkaay@mkaay.de", "zoidberg@mujmail.cz")
 -    
 -    def setup(self):
 -        self.chunkLimit = -1
 -        self.resumeDownload = True   
 -    
 -    def process(self, pyfile):
 -        parsed_url = urlparse(pyfile.url)
 -        netloc = parsed_url.netloc
 -        
 -        pyfile.name = parsed_url.path.rpartition('/')[2]
 -        try:
 -            pyfile.name = unquote(str(pyfile.name)).decode('utf8')
 -        except:
 -            pass        
 -        
 -        if not "@" in netloc:
 -            servers = [ x['login'] for x in self.account.getAllAccounts() ] if self.account else []                             
 -                
 -            if netloc in servers:
 -                self.logDebug("Logging on to %s" % netloc)                
 -                self.req.addAuth(self.account.accounts[netloc]["password"])
 -            else:
 -                for pwd in pyfile.package().password.splitlines(): 
 -                    if ":" in pwd:
 -                        self.req.addAuth(pwd.strip())
 -                        break                            
 -        
 -        self.req.http.c.setopt(pycurl.NOBODY, 1)
 -        
 -        try:
 -            response = self.load(pyfile.url)
 -        except pycurl.error, e:
 -            self.fail("Error %d: %s" % e.args)
 -        
 -        self.req.http.c.setopt(pycurl.NOBODY, 0)        
 -        self.logDebug(self.req.http.header)
 -        
 -        found = re.search(r"Content-Length:\s*(\d+)", response)
 -        if found:
 -            pyfile.size = int(found.group(1))                 
 -            self.download(pyfile.url)
 -        else:
 -            #Naive ftp directory listing          
 -            if re.search(r'^25\d.*?"', self.req.http.header, re.M):            
 -                pyfile.url = pyfile.url.rstrip('/')
 -                pkgname = "/".join((pyfile.package().name,urlparse(pyfile.url).path.rpartition('/')[2]))
 -                pyfile.url += '/'
 -                self.req.http.c.setopt(48, 1) # CURLOPT_DIRLISTONLY
 -                response = self.load(pyfile.url, decode = False)
 -                links = [ pyfile.url + quote(x) for x in response.splitlines() ]
 -                self.logDebug("LINKS", links)
 -                self.core.api.addPackage(pkgname, links, 1)
 -                #self.core.files.addLinks(links, pyfile.package().id)
 -            else:
 -                self.fail("Unexpected server response")
 -            
 +# -*- 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 +    @author: mkaay +""" +from urlparse import urlparse, urljoin +from urllib import quote, unquote +import pycurl, re + +from module.plugins.Hoster import Hoster +from module.network.HTTPRequest import BadHeader + +class Ftp(Hoster): +    __name__ = "Ftp" +    __version__ = "0.41" +    __pattern__ = r'(ftps?|sftp)://(.*?:.*?@)?.*?/.*' # ftp://user:password@ftp.server.org/path/to/file +    __type__ = "hoster" +    __description__ = """A Plugin that allows you to download from an from an ftp directory""" +    __author_name__ = ("jeix", "mkaay", "zoidberg") +    __author_mail__ = ("jeix@hasnomail.com", "mkaay@mkaay.de", "zoidberg@mujmail.cz") +     +    def setup(self): +        self.chunkLimit = -1 +        self.resumeDownload = True    +     +    def process(self, pyfile): +        parsed_url = urlparse(pyfile.url) +        netloc = parsed_url.netloc +         +        pyfile.name = parsed_url.path.rpartition('/')[2] +        try: +            pyfile.name = unquote(str(pyfile.name)).decode('utf8') +        except: +            pass         +         +        if not "@" in netloc: +            servers = [ x['login'] for x in self.account.getAllAccounts() ] if self.account else []                              +                 +            if netloc in servers: +                self.logDebug("Logging on to %s" % netloc)                 +                self.req.addAuth(self.account.accounts[netloc]["password"]) +            else: +                for pwd in pyfile.package().password.splitlines():  +                    if ":" in pwd: +                        self.req.addAuth(pwd.strip()) +                        break                             +         +        self.req.http.c.setopt(pycurl.NOBODY, 1) +         +        try: +            response = self.load(pyfile.url) +        except pycurl.error, e: +            self.fail("Error %d: %s" % e.args) +         +        self.req.http.c.setopt(pycurl.NOBODY, 0)         +        self.logDebug(self.req.http.header) +         +        found = re.search(r"Content-Length:\s*(\d+)", response) +        if found: +            pyfile.size = int(found.group(1))                  +            self.download(pyfile.url) +        else: +            #Naive ftp directory listing           +            if re.search(r'^25\d.*?"', self.req.http.header, re.M):             +                pyfile.url = pyfile.url.rstrip('/') +                pkgname = "/".join((pyfile.package().name,urlparse(pyfile.url).path.rpartition('/')[2])) +                pyfile.url += '/' +                self.req.http.c.setopt(48, 1) # CURLOPT_DIRLISTONLY +                response = self.load(pyfile.url, decode = False) +                links = [ pyfile.url + quote(x) for x in response.splitlines() ] +                self.logDebug("LINKS", links) +                self.core.api.addPackage(pkgname, links, 1) +                #self.core.files.addLinks(links, pyfile.package().id) +            else: +                self.fail("Unexpected server response") +                      
\ No newline at end of file diff --git a/module/plugins/hoster/LuckyShareNet.py b/module/plugins/hoster/LuckyShareNet.py index 5a4a583ff..08e44d9f6 100644 --- a/module/plugins/hoster/LuckyShareNet.py +++ b/module/plugins/hoster/LuckyShareNet.py @@ -1,72 +1,72 @@ -# -*- coding: utf-8 -*-
 -
 -import re
 -from module.lib.bottle import json_loads
 -
 -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
 -from module.plugins.internal.CaptchaService import ReCaptcha
 -
 -
 -class LuckyShareNet(SimpleHoster):
 -    __name__ = "LuckyShareNet"
 -    __type__ = "hoster"
 -    __pattern__ = r"https?://(www\.)?luckyshare.net/(?P<ID>\d{10,})"
 -    __version__ = "0.02"
 -    __description__ = """LuckyShare.net Download Hoster"""
 -    __author_name__ = ("stickell")
 -    __author_mail__ = ("l.stickell@yahoo.it")
 -
 -    FILE_INFO_PATTERN = r"<h1 class='file_name'>(?P<N>\S+)</h1>\s*<span class='file_size'>Filesize: (?P<S>[\d.]+)(?P<U>\w+)</span>"
 -    FILE_OFFLINE_PATTERN = 'There is no such file available'
 -    RECAPTCHA_KEY = '6LdivsgSAAAAANWh-d7rPE1mus4yVWuSQIJKIYNw'
 -
 -    def parseJson(self, rep):
 -        if 'AJAX Error' in rep:
 -            html = self.load(self.pyfile.url, decode=True)
 -            m = re.search(r"waitingtime = (\d+);", html)
 -            if m:
 -                waittime = int(m.group(1))
 -                self.logDebug('You have to wait %d seconds between free downloads' % waittime)
 -                self.retry(wait_time=waittime)
 -            else:
 -                self.parseError('Unable to detect wait time between free downloads')
 -        elif 'Hash expired' in rep:
 -            self.retry(reason='Hash expired')
 -        return json_loads(rep)
 -
 -    # TODO: There should be a filesize limit for free downloads
 -    # TODO: Some files could not be downloaded in free mode
 -    def handleFree(self):
 -        file_id = re.search(self.__pattern__, self.pyfile.url).group('ID')
 -        self.logDebug('File ID: ' + file_id)
 -        rep = self.load(r"http://luckyshare.net/download/request/type/time/file/" + file_id, decode=True)
 -        self.logDebug('JSON: ' + rep)
 -        json = self.parseJson(rep)
 -
 -        self.setWait(int(json['time']))
 -        self.wait()
 -
 -        recaptcha = ReCaptcha(self)
 -        for i in xrange(5):
 -            challenge, response = recaptcha.challenge(self.RECAPTCHA_KEY)
 -            rep = self.load(r"http://luckyshare.net/download/verify/challenge/%s/response/%s/hash/%s" %
 -                            (challenge, response, json['hash']), decode=True)
 -            self.logDebug('JSON: ' + rep)
 -            if 'link' in rep:
 -                json.update(self.parseJson(rep))
 -                self.correctCaptcha()
 -                break
 -            elif 'Verification failed' in rep:
 -                self.logInfo('Wrong captcha')
 -                self.invalidCaptcha()
 -            else:
 -                self.parseError('Unable to get downlaod link')
 -
 -        if not json['link']:
 -            self.fail("No Download url retrieved/all captcha attempts failed")
 -
 -        self.logDebug('Direct URL: ' + json['link'])
 -        self.download(json['link'])
 -
 -
 -getInfo = create_getInfo(LuckyShareNet)
 +# -*- coding: utf-8 -*- + +import re +from module.lib.bottle import json_loads + +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from module.plugins.internal.CaptchaService import ReCaptcha + + +class LuckyShareNet(SimpleHoster): +    __name__ = "LuckyShareNet" +    __type__ = "hoster" +    __pattern__ = r"https?://(www\.)?luckyshare.net/(?P<ID>\d{10,})" +    __version__ = "0.02" +    __description__ = """LuckyShare.net Download Hoster""" +    __author_name__ = ("stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    FILE_INFO_PATTERN = r"<h1 class='file_name'>(?P<N>\S+)</h1>\s*<span class='file_size'>Filesize: (?P<S>[\d.]+)(?P<U>\w+)</span>" +    FILE_OFFLINE_PATTERN = 'There is no such file available' +    RECAPTCHA_KEY = '6LdivsgSAAAAANWh-d7rPE1mus4yVWuSQIJKIYNw' + +    def parseJson(self, rep): +        if 'AJAX Error' in rep: +            html = self.load(self.pyfile.url, decode=True) +            m = re.search(r"waitingtime = (\d+);", html) +            if m: +                waittime = int(m.group(1)) +                self.logDebug('You have to wait %d seconds between free downloads' % waittime) +                self.retry(wait_time=waittime) +            else: +                self.parseError('Unable to detect wait time between free downloads') +        elif 'Hash expired' in rep: +            self.retry(reason='Hash expired') +        return json_loads(rep) + +    # TODO: There should be a filesize limit for free downloads +    # TODO: Some files could not be downloaded in free mode +    def handleFree(self): +        file_id = re.search(self.__pattern__, self.pyfile.url).group('ID') +        self.logDebug('File ID: ' + file_id) +        rep = self.load(r"http://luckyshare.net/download/request/type/time/file/" + file_id, decode=True) +        self.logDebug('JSON: ' + rep) +        json = self.parseJson(rep) + +        self.setWait(int(json['time'])) +        self.wait() + +        recaptcha = ReCaptcha(self) +        for i in xrange(5): +            challenge, response = recaptcha.challenge(self.RECAPTCHA_KEY) +            rep = self.load(r"http://luckyshare.net/download/verify/challenge/%s/response/%s/hash/%s" % +                            (challenge, response, json['hash']), decode=True) +            self.logDebug('JSON: ' + rep) +            if 'link' in rep: +                json.update(self.parseJson(rep)) +                self.correctCaptcha() +                break +            elif 'Verification failed' in rep: +                self.logInfo('Wrong captcha') +                self.invalidCaptcha() +            else: +                self.parseError('Unable to get downlaod link') + +        if not json['link']: +            self.fail("No Download url retrieved/all captcha attempts failed") + +        self.logDebug('Direct URL: ' + json['link']) +        self.download(json['link']) + + +getInfo = create_getInfo(LuckyShareNet) diff --git a/module/plugins/hoster/PornhostCom.py b/module/plugins/hoster/PornhostCom.py index a4124c4a4..ef7961d81 100644 --- a/module/plugins/hoster/PornhostCom.py +++ b/module/plugins/hoster/PornhostCom.py @@ -1,76 +1,76 @@ -#!/usr/bin/env python
 -# -*- coding: utf-8 -*-
 -
 -import re
 -from module.plugins.Hoster import Hoster
 -
 -class PornhostCom(Hoster):
 -    __name__ = "PornhostCom"
 -    __type__ = "hoster"
 -    __pattern__ = r'http://[\w\.]*?pornhost\.com/([0-9]+/[0-9]+\.html|[0-9]+)'
 -    __version__ = "0.2"
 -    __description__ = """Pornhost.com Download Hoster"""
 -    __author_name__ = ("jeix")
 -    __author_mail__ = ("jeix@hasnomail.de")
 -        
 -    def process(self, pyfile):
 -        self.download_html()
 -        if not self.file_exists():
 -            self.offline()
 -            
 -        pyfile.name = self.get_file_name()
 -        self.download(self.get_file_url())
 -        
 -
 -    ###   old interface
 -    def download_html(self):
 -        url = self.pyfile.url
 -        self.html = self.load(url)
 -
 -    def get_file_url(self):
 -        """ returns the absolute downloadable filepath
 -        """
 -        if self.html is None:
 -            self.download_html()
 -
 -        file_url = re.search(r'download this file</label>.*?<a href="(.*?)"', self.html)
 -        if not file_url: 
 -            file_url = re.search(r'"(http://dl[0-9]+\.pornhost\.com/files/.*?/.*?/.*?/.*?/.*?/.*?\..*?)"', self.html)
 -            if not file_url:
 -                file_url = re.search(r'width: 894px; height: 675px">.*?<img src="(.*?)"', self.html)
 -                if not file_url:
 -                    file_url = re.search(r'"http://file[0-9]+\.pornhost\.com/[0-9]+/.*?"', self.html) # TODO: fix this one since it doesn't match
 -
 -        file_url = file_url.group(1).strip()
 -                    
 -        return file_url
 -    
 -    def get_file_name(self):
 -        if self.html is None:
 -            self.download_html()
 -            
 -        name = re.search(r'<title>pornhost\.com - free file hosting with a twist - gallery(.*?)</title>', self.html)
 -        if not name:
 -            name = re.search(r'id="url" value="http://www\.pornhost\.com/(.*?)/"', self.html)
 -            if not name:
 -                name = re.search(r'<title>pornhost\.com - free file hosting with a twist -(.*?)</title>', self.html)
 -                if not name:
 -                    name = re.search(r'"http://file[0-9]+\.pornhost\.com/.*?/(.*?)"', self.html)
 -       
 -        name = name.group(1).strip() + ".flv"
 -        
 -        return name
 -
 -    def file_exists(self):
 -        """ returns True or False
 -        """
 -        if self.html is None:
 -            self.download_html()
 -        
 -        if re.search(r'gallery not found', self.html) is not None \
 -        or re.search(r'You will be redirected to', self.html) is not None:
 -            return False
 -        else:
 -            return True
 -            
 -            
 +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from module.plugins.Hoster import Hoster + +class PornhostCom(Hoster): +    __name__ = "PornhostCom" +    __type__ = "hoster" +    __pattern__ = r'http://[\w\.]*?pornhost\.com/([0-9]+/[0-9]+\.html|[0-9]+)' +    __version__ = "0.2" +    __description__ = """Pornhost.com Download Hoster""" +    __author_name__ = ("jeix") +    __author_mail__ = ("jeix@hasnomail.de") +         +    def process(self, pyfile): +        self.download_html() +        if not self.file_exists(): +            self.offline() +             +        pyfile.name = self.get_file_name() +        self.download(self.get_file_url()) +         + +    ###   old interface +    def download_html(self): +        url = self.pyfile.url +        self.html = self.load(url) + +    def get_file_url(self): +        """ returns the absolute downloadable filepath +        """ +        if self.html is None: +            self.download_html() + +        file_url = re.search(r'download this file</label>.*?<a href="(.*?)"', self.html) +        if not file_url:  +            file_url = re.search(r'"(http://dl[0-9]+\.pornhost\.com/files/.*?/.*?/.*?/.*?/.*?/.*?\..*?)"', self.html) +            if not file_url: +                file_url = re.search(r'width: 894px; height: 675px">.*?<img src="(.*?)"', self.html) +                if not file_url: +                    file_url = re.search(r'"http://file[0-9]+\.pornhost\.com/[0-9]+/.*?"', self.html) # TODO: fix this one since it doesn't match + +        file_url = file_url.group(1).strip() +                     +        return file_url +     +    def get_file_name(self): +        if self.html is None: +            self.download_html() +             +        name = re.search(r'<title>pornhost\.com - free file hosting with a twist - gallery(.*?)</title>', self.html) +        if not name: +            name = re.search(r'id="url" value="http://www\.pornhost\.com/(.*?)/"', self.html) +            if not name: +                name = re.search(r'<title>pornhost\.com - free file hosting with a twist -(.*?)</title>', self.html) +                if not name: +                    name = re.search(r'"http://file[0-9]+\.pornhost\.com/.*?/(.*?)"', self.html) +        +        name = name.group(1).strip() + ".flv" +         +        return name + +    def file_exists(self): +        """ returns True or False +        """ +        if self.html is None: +            self.download_html() +         +        if re.search(r'gallery not found', self.html) is not None \ +        or re.search(r'You will be redirected to', self.html) is not None: +            return False +        else: +            return True +             +             diff --git a/module/plugins/hoster/PornhubCom.py b/module/plugins/hoster/PornhubCom.py index e1ed612b9..c431004d8 100644 --- a/module/plugins/hoster/PornhubCom.py +++ b/module/plugins/hoster/PornhubCom.py @@ -1,83 +1,83 @@ -#!/usr/bin/env python
 -# -*- coding: utf-8 -*-
 -
 -import re
 -from module.plugins.Hoster import Hoster
 -
 -class PornhubCom(Hoster):
 -    __name__ = "PornhubCom"
 -    __type__ = "hoster"
 -    __pattern__ = r'http://[\w\.]*?pornhub\.com/view_video\.php\?viewkey=[\w\d]+'
 -    __version__ = "0.5"
 -    __description__ = """Pornhub.com Download Hoster"""
 -    __author_name__ = ("jeix")
 -    __author_mail__ = ("jeix@hasnomail.de")
 -        
 -    def process(self, pyfile):
 -        self.download_html()
 -        if not self.file_exists():
 -            self.offline()
 -            
 -        pyfile.name = self.get_file_name()
 -        self.download(self.get_file_url())
 -        
 -    def download_html(self):
 -        url = self.pyfile.url
 -        self.html = self.load(url)
 -
 -    def get_file_url(self):
 -        """ returns the absolute downloadable filepath
 -        """
 -        if self.html is None:
 -            self.download_html()
 -
 -        url = "http://www.pornhub.com//gateway.php"
 -        video_id = self.pyfile.url.split('=')[-1]
 -        # thanks to jD team for this one  v
 -        post_data = "\x00\x03\x00\x00\x00\x01\x00\x0c\x70\x6c\x61\x79\x65\x72\x43\x6f\x6e\x66\x69\x67\x00\x02\x2f\x31\x00\x00\x00\x44\x0a\x00\x00\x00\x03\x02\x00"
 -        post_data += chr(len(video_id))
 -        post_data += video_id
 -        post_data += "\x02\x00\x02\x2d\x31\x02\x00\x20"
 -        post_data += "add299463d4410c6d1b1c418868225f7"
 -        
 -        content = self.req.load(url, post=str(post_data))
 -        
 -        new_content = ""
 -        for x in content:
 -            if ord(x) < 32 or ord(x) > 176:
 -                new_content += '#'
 -            else:
 -                new_content += x
 -                
 -        content = new_content
 -        
 -        file_url = re.search(r'flv_url.*(http.*?)##post_roll', content).group(1)
 -
 -        return file_url
 -    
 -    def get_file_name(self):
 -        if self.html is None:
 -            self.download_html()
 -        
 -        match = re.search(r'<title[^>]+>([^<]+) - ', self.html)
 -        if match:
 -            name = match.group(1)
 -        else:
 -            matches = re.findall('<h1>(.*?)</h1>', self.html)
 -            if len(matches) > 1:
 -                name = matches[1]
 -            else:
 -                name = matches[0]
 -        
 -        return name + '.flv'
 -
 -    def file_exists(self):
 -        """ returns True or False
 -        """
 -        if self.html is None:
 -            self.download_html()
 -        
 -        if re.search(r'This video is no longer in our database or is in conversion', self.html) is not None:
 -            return False
 -        else:
 -            return True
 +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from module.plugins.Hoster import Hoster + +class PornhubCom(Hoster): +    __name__ = "PornhubCom" +    __type__ = "hoster" +    __pattern__ = r'http://[\w\.]*?pornhub\.com/view_video\.php\?viewkey=[\w\d]+' +    __version__ = "0.5" +    __description__ = """Pornhub.com Download Hoster""" +    __author_name__ = ("jeix") +    __author_mail__ = ("jeix@hasnomail.de") +         +    def process(self, pyfile): +        self.download_html() +        if not self.file_exists(): +            self.offline() +             +        pyfile.name = self.get_file_name() +        self.download(self.get_file_url()) +         +    def download_html(self): +        url = self.pyfile.url +        self.html = self.load(url) + +    def get_file_url(self): +        """ returns the absolute downloadable filepath +        """ +        if self.html is None: +            self.download_html() + +        url = "http://www.pornhub.com//gateway.php" +        video_id = self.pyfile.url.split('=')[-1] +        # thanks to jD team for this one  v +        post_data = "\x00\x03\x00\x00\x00\x01\x00\x0c\x70\x6c\x61\x79\x65\x72\x43\x6f\x6e\x66\x69\x67\x00\x02\x2f\x31\x00\x00\x00\x44\x0a\x00\x00\x00\x03\x02\x00" +        post_data += chr(len(video_id)) +        post_data += video_id +        post_data += "\x02\x00\x02\x2d\x31\x02\x00\x20" +        post_data += "add299463d4410c6d1b1c418868225f7" +         +        content = self.req.load(url, post=str(post_data)) +         +        new_content = "" +        for x in content: +            if ord(x) < 32 or ord(x) > 176: +                new_content += '#' +            else: +                new_content += x +                 +        content = new_content +         +        file_url = re.search(r'flv_url.*(http.*?)##post_roll', content).group(1) + +        return file_url +     +    def get_file_name(self): +        if self.html is None: +            self.download_html() +         +        match = re.search(r'<title[^>]+>([^<]+) - ', self.html) +        if match: +            name = match.group(1) +        else: +            matches = re.findall('<h1>(.*?)</h1>', self.html) +            if len(matches) > 1: +                name = matches[1] +            else: +                name = matches[0] +         +        return name + '.flv' + +    def file_exists(self): +        """ returns True or False +        """ +        if self.html is None: +            self.download_html() +         +        if re.search(r'This video is no longer in our database or is in conversion', self.html) is not None: +            return False +        else: +            return True diff --git a/module/plugins/hoster/Premium4Me.py b/module/plugins/hoster/Premium4Me.py index 63b3baa83..9a359b9cb 100644 --- a/module/plugins/hoster/Premium4Me.py +++ b/module/plugins/hoster/Premium4Me.py @@ -1,70 +1,70 @@ -#!/usr/bin/env python
 -# -*- coding: utf-8 -*-
 -
 -from urllib import quote
 -from os.path import exists
 -from os import remove
 -
 -from module.plugins.Hoster import Hoster
 -from module.utils import fs_encode
 -
 -
 -class Premium4Me(Hoster):
 -    __name__ = "Premium4Me"
 -    __version__ = "0.08"
 -    __type__ = "hoster"
 -
 -    __pattern__ = r"http://premium.to/.*"
 -    __description__ = """Premium.to hoster plugin"""
 -    __author_name__ = ("RaNaN", "zoidberg", "stickell")
 -    __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz", "l.stickell@yahoo.it")
 -
 -    def setup(self):
 -        self.resumeDownload = True
 -        self.chunkLimit = 1
 -
 -    def process(self, pyfile):
 -        if not self.account:
 -            self.logError(_("Please enter your %s account or deactivate this plugin") % "premium.to")
 -            self.fail("No premium.to account provided")
 -
 -        self.logDebug("premium.to: Old URL: %s" % pyfile.url)
 -
 -        tra = self.getTraffic()
 -
 -        #raise timeout to 2min
 -        self.req.setOption("timeout", 120)
 -
 -        self.download(
 -            "http://premium.to/api/getfile.php?authcode=%s&link=%s" % (self.account.authcode, quote(pyfile.url, "")),
 -            disposition=True)
 -
 -        check = self.checkDownload({"nopremium": "No premium account available"})
 -
 -        if check == "nopremium":
 -            self.retry(60, 300, 'No premium account available')
 -
 -        err = ''
 -        if self.req.http.code == '420':
 -            # Custom error code send - fail
 -            lastDownload = fs_encode(self.lastDownload)
 -
 -            if exists(lastDownload):
 -                f = open(lastDownload, "rb")
 -                err = f.read(256).strip()
 -                f.close()
 -                remove(lastDownload)
 -            else:
 -                err = 'File does not exist'
 -
 -        trb = self.getTraffic()
 -        self.logInfo("Filesize: %d, Traffic used %d, traffic left %d" % (pyfile.size, tra - trb, trb))
 -
 -        if err: self.fail(err)
 -
 -    def getTraffic(self):
 -        try:
 -            traffic = int(self.load("http://premium.to/api/traffic.php?authcode=%s" % self.account.authcode))
 -        except:
 -            traffic = 0
 -        return traffic       
 +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from urllib import quote +from os.path import exists +from os import remove + +from module.plugins.Hoster import Hoster +from module.utils import fs_encode + + +class Premium4Me(Hoster): +    __name__ = "Premium4Me" +    __version__ = "0.08" +    __type__ = "hoster" + +    __pattern__ = r"http://premium.to/.*" +    __description__ = """Premium.to hoster plugin""" +    __author_name__ = ("RaNaN", "zoidberg", "stickell") +    __author_mail__ = ("RaNaN@pyload.org", "zoidberg@mujmail.cz", "l.stickell@yahoo.it") + +    def setup(self): +        self.resumeDownload = True +        self.chunkLimit = 1 + +    def process(self, pyfile): +        if not self.account: +            self.logError(_("Please enter your %s account or deactivate this plugin") % "premium.to") +            self.fail("No premium.to account provided") + +        self.logDebug("premium.to: Old URL: %s" % pyfile.url) + +        tra = self.getTraffic() + +        #raise timeout to 2min +        self.req.setOption("timeout", 120) + +        self.download( +            "http://premium.to/api/getfile.php?authcode=%s&link=%s" % (self.account.authcode, quote(pyfile.url, "")), +            disposition=True) + +        check = self.checkDownload({"nopremium": "No premium account available"}) + +        if check == "nopremium": +            self.retry(60, 300, 'No premium account available') + +        err = '' +        if self.req.http.code == '420': +            # Custom error code send - fail +            lastDownload = fs_encode(self.lastDownload) + +            if exists(lastDownload): +                f = open(lastDownload, "rb") +                err = f.read(256).strip() +                f.close() +                remove(lastDownload) +            else: +                err = 'File does not exist' + +        trb = self.getTraffic() +        self.logInfo("Filesize: %d, Traffic used %d, traffic left %d" % (pyfile.size, tra - trb, trb)) + +        if err: self.fail(err) + +    def getTraffic(self): +        try: +            traffic = int(self.load("http://premium.to/api/traffic.php?authcode=%s" % self.account.authcode)) +        except: +            traffic = 0 +        return traffic        diff --git a/module/plugins/hoster/PremiumizeMe.py b/module/plugins/hoster/PremiumizeMe.py index af21c578a..004bc4074 100644 --- a/module/plugins/hoster/PremiumizeMe.py +++ b/module/plugins/hoster/PremiumizeMe.py @@ -1,50 +1,50 @@ -from module.plugins.Hoster    import Hoster
 -
 -from module.common.json_layer import json_loads
 -
 -class PremiumizeMe(Hoster):
 -    __name__ = "PremiumizeMe"
 -    __version__ = "0.12"
 -    __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 your %s account or deactivate this plugin") % "premiumize.me")
 -            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¶ms[login]=%s¶ms[pass]=%s¶ms[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'])
 +from module.plugins.Hoster    import Hoster + +from module.common.json_layer import json_loads + +class PremiumizeMe(Hoster): +    __name__ = "PremiumizeMe" +    __version__ = "0.12" +    __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 your %s account or deactivate this plugin") % "premiumize.me") +            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¶ms[login]=%s¶ms[pass]=%s¶ms[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/RealdebridCom.py b/module/plugins/hoster/RealdebridCom.py index 98aca68d9..73baff5b3 100644 --- a/module/plugins/hoster/RealdebridCom.py +++ b/module/plugins/hoster/RealdebridCom.py @@ -1,88 +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 parseFileSize, remove_chars
 -from module.common.json_layer import json_loads
 -from module.plugins.Hoster import Hoster
 -
 -class RealdebridCom(Hoster):
 -    __name__ = "RealdebridCom"
 -    __version__ = "0.51"
 -    __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 %s account or deactivate this plugin") % "Real-debrid")
 -            self.fail("No Real-debrid account provided")
 -
 -        self.logDebug("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.logDebug("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)
 -
 +#!/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.51" +    __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 %s account or deactivate this plugin") % "Real-debrid") +            self.fail("No Real-debrid account provided") + +        self.logDebug("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.logDebug("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/RedtubeCom.py b/module/plugins/hoster/RedtubeCom.py index 9ffafd905..c2083e679 100644 --- a/module/plugins/hoster/RedtubeCom.py +++ b/module/plugins/hoster/RedtubeCom.py @@ -1,56 +1,56 @@ -#!/usr/bin/env python
 -# -*- coding: utf-8 -*-
 -
 -import re
 -from module.plugins.Hoster import Hoster
 -from module.unescape import unescape
 -
 -class RedtubeCom(Hoster):
 -    __name__ = "RedtubeCom"
 -    __type__ = "hoster"
 -    __pattern__ = r'http://[\w\.]*?redtube\.com/\d+'
 -    __version__ = "0.2"
 -    __description__ = """Redtube.com Download Hoster"""
 -    __author_name__ = ("jeix")
 -    __author_mail__ = ("jeix@hasnomail.de")
 -        
 -    def process(self, pyfile):
 -        self.download_html()
 -        if not self.file_exists():
 -            self.offline()
 -            
 -        pyfile.name = self.get_file_name()
 -        self.download(self.get_file_url())
 -        
 -    def download_html(self):
 -        url = self.pyfile.url
 -        self.html = self.load(url)
 -
 -    def get_file_url(self):
 -        """ returns the absolute downloadable filepath
 -        """
 -        if self.html is None:
 -            self.download_html()
 -
 -        file_url = unescape(re.search(r'hashlink=(http.*?)"', self.html).group(1))
 -
 -        return file_url
 -    
 -    def get_file_name(self):
 -        if self.html is None:
 -            self.download_html()
 -            
 -        name = re.search('<title>(.*?)- RedTube - Free Porn Videos</title>', self.html).group(1).strip() + ".flv"        
 -        return name
 -
 -    def file_exists(self):
 -        """ returns True or False
 -        """
 -        if self.html is None:
 -            self.download_html()
 -        
 -        if re.search(r'This video has been removed.', self.html) is not None:
 -            return False
 -        else:
 -            return True
 -            
 +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from module.plugins.Hoster import Hoster +from module.unescape import unescape + +class RedtubeCom(Hoster): +    __name__ = "RedtubeCom" +    __type__ = "hoster" +    __pattern__ = r'http://[\w\.]*?redtube\.com/\d+' +    __version__ = "0.2" +    __description__ = """Redtube.com Download Hoster""" +    __author_name__ = ("jeix") +    __author_mail__ = ("jeix@hasnomail.de") +         +    def process(self, pyfile): +        self.download_html() +        if not self.file_exists(): +            self.offline() +             +        pyfile.name = self.get_file_name() +        self.download(self.get_file_url()) +         +    def download_html(self): +        url = self.pyfile.url +        self.html = self.load(url) + +    def get_file_url(self): +        """ returns the absolute downloadable filepath +        """ +        if self.html is None: +            self.download_html() + +        file_url = unescape(re.search(r'hashlink=(http.*?)"', self.html).group(1)) + +        return file_url +     +    def get_file_name(self): +        if self.html is None: +            self.download_html() +             +        name = re.search('<title>(.*?)- RedTube - Free Porn Videos</title>', self.html).group(1).strip() + ".flv"         +        return name + +    def file_exists(self): +        """ returns True or False +        """ +        if self.html is None: +            self.download_html() +         +        if re.search(r'This video has been removed.', self.html) is not None: +            return False +        else: +            return True +             diff --git a/module/plugins/hoster/ShareplaceCom.py b/module/plugins/hoster/ShareplaceCom.py index 24536d351..c55f6703a 100644 --- a/module/plugins/hoster/ShareplaceCom.py +++ b/module/plugins/hoster/ShareplaceCom.py @@ -1,84 +1,84 @@ -#!/usr/bin/env python
 -# -*- coding: utf-8 -*-
 -
 -import re
 -import urllib
 -from module.plugins.Hoster import Hoster
 -
 -class ShareplaceCom(Hoster):
 -    __name__ = "ShareplaceCom"
 -    __type__ = "hoster"
 -    __pattern__ = r"(http://)?(www\.)?shareplace\.(com|org)/\?[a-zA-Z0-9]+"
 -    __version__ = "0.11"
 -    __description__ = """Shareplace.com Download Hoster"""
 -    __author_name__ = ("ACCakut, based on YourfilesTo by jeix and skydancer")
 -    __author_mail__ = ("none")
 -
 -    def setup(self):
 -        self.html = None
 -        self.multiDL = True
 -
 -    def process(self,pyfile):
 -        self.pyfile = pyfile
 -        self.prepare()
 -        self.download(self.get_file_url())
 -    
 -    def prepare(self):
 -        if not self.file_exists():
 -            self.offline()
 -
 -        self.pyfile.name = self.get_file_name()
 -        
 -        wait_time = self.get_waiting_time()
 -        self.setWait(wait_time)
 -        self.logDebug("%s: Waiting %d seconds." % (self.__name__,wait_time))
 -        self.wait()
 -
 -    def get_waiting_time(self):
 -        if self.html is None:
 -            self.download_html()
 -            
 -        #var zzipitime = 15;
 -        m = re.search(r'var zzipitime = (\d+);', self.html)
 -        if m:
 -            sec = int(m.group(1))
 -        else:
 -            sec = 0
 -            
 -        return sec
 -        
 -    def download_html(self):
 -        url = re.sub("shareplace.com\/\?", "shareplace.com//index1.php/?a=", self.pyfile.url)
 -        self.html = self.load(url, decode=True)
 -
 -    def get_file_url(self):
 -        """ returns the absolute downloadable filepath
 -        """
 -        url = re.search(r"var beer = '(.*?)';", self.html)
 -        if url:
 -            url = url.group(1)
 -            url = urllib.unquote(url.replace("http://http:/", "").replace("vvvvvvvvv", "").replace("lllllllll", "").replace("teletubbies", ""))
 -            self.logDebug("URL: %s" % url)
 -            return url
 -        else:
 -            self.fail("absolute filepath could not be found. offline? ")
 -       
 -    def get_file_name(self):
 -        if self.html is None:
 -            self.download_html()
 -
 -        return re.search("<title>\s*(.*?)\s*</title>", self.html).group(1)
 -
 -    def file_exists(self):
 -        """ returns True or False
 -        """
 -        if self.html is None:
 -            self.download_html()
 -            
 -        if re.search(r"HTTP Status 404", self.html) is not None:
 -            return False
 -        else:
 -            return True
 -
 -        
 -
 +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +import urllib +from module.plugins.Hoster import Hoster + +class ShareplaceCom(Hoster): +    __name__ = "ShareplaceCom" +    __type__ = "hoster" +    __pattern__ = r"(http://)?(www\.)?shareplace\.(com|org)/\?[a-zA-Z0-9]+" +    __version__ = "0.11" +    __description__ = """Shareplace.com Download Hoster""" +    __author_name__ = ("ACCakut, based on YourfilesTo by jeix and skydancer") +    __author_mail__ = ("none") + +    def setup(self): +        self.html = None +        self.multiDL = True + +    def process(self,pyfile): +        self.pyfile = pyfile +        self.prepare() +        self.download(self.get_file_url()) +     +    def prepare(self): +        if not self.file_exists(): +            self.offline() + +        self.pyfile.name = self.get_file_name() +         +        wait_time = self.get_waiting_time() +        self.setWait(wait_time) +        self.logDebug("%s: Waiting %d seconds." % (self.__name__,wait_time)) +        self.wait() + +    def get_waiting_time(self): +        if self.html is None: +            self.download_html() +             +        #var zzipitime = 15; +        m = re.search(r'var zzipitime = (\d+);', self.html) +        if m: +            sec = int(m.group(1)) +        else: +            sec = 0 +             +        return sec +         +    def download_html(self): +        url = re.sub("shareplace.com\/\?", "shareplace.com//index1.php/?a=", self.pyfile.url) +        self.html = self.load(url, decode=True) + +    def get_file_url(self): +        """ returns the absolute downloadable filepath +        """ +        url = re.search(r"var beer = '(.*?)';", self.html) +        if url: +            url = url.group(1) +            url = urllib.unquote(url.replace("http://http:/", "").replace("vvvvvvvvv", "").replace("lllllllll", "").replace("teletubbies", "")) +            self.logDebug("URL: %s" % url) +            return url +        else: +            self.fail("absolute filepath could not be found. offline? ") +        +    def get_file_name(self): +        if self.html is None: +            self.download_html() + +        return re.search("<title>\s*(.*?)\s*</title>", self.html).group(1) + +    def file_exists(self): +        """ returns True or False +        """ +        if self.html is None: +            self.download_html() +             +        if re.search(r"HTTP Status 404", self.html) is not None: +            return False +        else: +            return True + +         + diff --git a/module/plugins/hoster/UploadStationCom.py b/module/plugins/hoster/UploadStationCom.py index d24682e4d..96dc7b577 100644 --- a/module/plugins/hoster/UploadStationCom.py +++ b/module/plugins/hoster/UploadStationCom.py @@ -1,21 +1,21 @@ -# -*- coding: utf-8 -*-
 -from module.plugins.hoster.FileserveCom import FileserveCom, checkFile
 -from module.plugins.Plugin import chunks
 -
 -class UploadStationCom(FileserveCom):
 -    __name__ = "UploadStationCom"
 -    __type__ = "hoster"
 -    __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", "zoidberg")
 -    __author_mail__ = ("fragonib[AT]yahoo[DOT]es", "zoidberg@mujmail.cz")
 -            
 -    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">(?:<[^>]*>| )*([^<]*)'
 -    
 -    LONG_WAIT_PATTERN = r'<h1>You have to wait (\d+) (\w+) to download the next file\.</h1>'
 -   
 -def getInfo(urls):
 +# -*- coding: utf-8 -*- +from module.plugins.hoster.FileserveCom import FileserveCom, checkFile +from module.plugins.Plugin import chunks + +class UploadStationCom(FileserveCom): +    __name__ = "UploadStationCom" +    __type__ = "hoster" +    __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", "zoidberg") +    __author_mail__ = ("fragonib[AT]yahoo[DOT]es", "zoidberg@mujmail.cz") +             +    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">(?:<[^>]*>| )*([^<]*)' +     +    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/UploadingCom.py b/module/plugins/hoster/UploadingCom.py index 3037cfd20..a98c3bf71 100644 --- a/module/plugins/hoster/UploadingCom.py +++ b/module/plugins/hoster/UploadingCom.py @@ -1,110 +1,110 @@ -#!/usr/bin/env python
 -# -*- 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 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/)?(?P<ID>[\w\d]+)"
 -    __version__ = "0.33"
 -    __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.*?>The requested file is not found</h2>'
 -        
 -    def process(self, pyfile):
 -        # set lang to english
 -        self.req.cj.setCookie("uploading.com", "lang", "1")
 -        self.req.cj.setCookie("uploading.com", "language", "1")
 -        self.req.cj.setCookie("uploading.com", "setlang", "en")
 -        self.req.cj.setCookie("uploading.com", "_lang", "en")
 -        
 -        if not "/get/" in self.pyfile.url:
 -            self.pyfile.url = self.pyfile.url.replace("/files", "/files/get")
 -        
 -        self.html = self.load(pyfile.url, decode = True)
 -        self.file_info = self.getFileInfo()
 -        
 -        if self.premium:
 -            self.handlePremium()
 -        else:
 -            self.handleFree()                   
 -    
 -    def handlePremium(self):
 -        postData = {'action': 'get_link',
 -                    '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:
 -            url = url.group(1).replace("\\/", "/")
 -            self.download(url)
 -        
 -        raise Exception("Plugin defect.")
 -    
 -    def handleFree(self):
 -        found = re.search('<h2>((Daily )?Download Limit)</h2>', self.html)
 -        if found:
 -            self.pyfile.error = found.group(1)
 -            self.logWarning(self.pyfile.error)
 -            self.retry(max_tries=6, wait_time = 21600 if found.group(2) else 900, reason = self.pyfile.error)  
 -        
 -        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
 -        
 -        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.logInfo("%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")
 -        
 -        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()
 -        
 +#!/usr/bin/env python +# -*- 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 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/)?(?P<ID>[\w\d]+)" +    __version__ = "0.33" +    __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.*?>The requested file is not found</h2>' +         +    def process(self, pyfile): +        # set lang to english +        self.req.cj.setCookie("uploading.com", "lang", "1") +        self.req.cj.setCookie("uploading.com", "language", "1") +        self.req.cj.setCookie("uploading.com", "setlang", "en") +        self.req.cj.setCookie("uploading.com", "_lang", "en") +         +        if not "/get/" in self.pyfile.url: +            self.pyfile.url = self.pyfile.url.replace("/files", "/files/get") +         +        self.html = self.load(pyfile.url, decode = True) +        self.file_info = self.getFileInfo() +         +        if self.premium: +            self.handlePremium() +        else: +            self.handleFree()                    +     +    def handlePremium(self): +        postData = {'action': 'get_link', +                    '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: +            url = url.group(1).replace("\\/", "/") +            self.download(url) +         +        raise Exception("Plugin defect.") +     +    def handleFree(self): +        found = re.search('<h2>((Daily )?Download Limit)</h2>', self.html) +        if found: +            self.pyfile.error = found.group(1) +            self.logWarning(self.pyfile.error) +            self.retry(max_tries=6, wait_time = 21600 if found.group(2) else 900, reason = self.pyfile.error)   +         +        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 +         +        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.logInfo("%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") +         +        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/X7To.py b/module/plugins/hoster/X7To.py index 79adf2a3f..965d84543 100644 --- a/module/plugins/hoster/X7To.py +++ b/module/plugins/hoster/X7To.py @@ -1,93 +1,93 @@ -# -*- coding: utf-8 -*-
 -import re
 -
 -from module.plugins.Hoster import Hoster
 -
 -from module.network.RequestFactory import getURL
 -
 -def getInfo(urls):
 -    yield [(url, 0, 1, url) for url in urls]
 -
 -
 -class X7To(Hoster):
 -    __name__ = "X7To"
 -    __type__ = "hoster"
 -    __pattern__ = r"http://(?:www.)?x7.to/"
 -    __version__ = "0.3"
 -    __description__ = """X7.To File Download Hoster"""
 -    __author_name__ = ("ernieb")
 -    __author_mail__ = ("ernieb")
 -    
 -    FILE_INFO_PATTERN=r'<meta name="description" content="Download: (.*?) \(([0-9,.]+) (KB|MB|GB)\)'
 -
 -    def init(self):
 -        if self.premium:
 -            self.multiDL = False
 -            self.resumeDownload = False
 -            self.chunkLimit = 1
 -        else:
 -            self.multiDL = False
 -
 -        self.file_id = re.search(r"http://x7.to/([a-zA-Z0-9]+)", self.pyfile.url).group(1)
 -        self.logDebug("file id is %s" % self.file_id)
 -        self.pyfile.url = "http://x7.to/" + self.file_id
 -
 -    def process(self, pyfile):
 -        self.fail("Hoster not longer available")
 -
 -    def handlePremium(self):
 -        # check if over limit first
 -        overLimit = re.search(r'<a onClick="cUser.buyTraffic\(\)" id="DL">', self.html)
 -        if overLimit:
 -            self.logDebug("over limit, falling back to free")
 -            self.handleFree()
 -        else:
 -            realurl = re.search(r'<a href="(http://stor.*?)" id="DL">', self.html)
 -            if realurl:
 -                realurl = realurl.group(1)
 -                self.logDebug("premium url found %s" % realurl)
 -            else:
 -                self.logDebug("premium link not found")
 -            self.download(realurl)
 -
 -    def handleFree(self):
 -        # find file id
 -        file_id = re.search(r"var dlID = '(.*?)'", self.html)
 -        if not file_id:
 -            self.fail("Free download id not found")
 -
 -        file_url = "http://x7.to/james/ticket/dl/" + file_id.group(1)
 -        self.logDebug("download id %s" % file_id.group(1))
 -
 -        self.html = self.load(file_url, ref=False, decode=True)
 -
 -        # deal with errors
 -        if "limit-dl" in self.html:
 -            self.logDebug("Limit reached ... waiting")
 -            self.setWait(900,True)
 -            self.wait()
 -            self.retry()
 -
 -        if "limit-parallel" in self.html:
 -            self.fail("Cannot download in parallel")
 -
 -        # no waiting required, go to download
 -        waitCheck = re.search(r"wait:(\d*),", self.html)
 -        if waitCheck:
 -            waitCheck = int(waitCheck.group(1))
 -            self.setWait(waitCheck)
 -            self.wait()
 -
 -        urlCheck = re.search(r"url:'(.*?)'", self.html)
 -        url = None
 -        if urlCheck:
 -            url = urlCheck.group(1)
 -            self.logDebug("free url found %s" % url)
 -
 -        if url:
 -            try:
 -                self.download(url)
 -            except:
 -                self.logDebug("downloading url failed: %s" % url)
 -        else:
 -            self.fail("Free download url found")
 +# -*- coding: utf-8 -*- +import re + +from module.plugins.Hoster import Hoster + +from module.network.RequestFactory import getURL + +def getInfo(urls): +    yield [(url, 0, 1, url) for url in urls] + + +class X7To(Hoster): +    __name__ = "X7To" +    __type__ = "hoster" +    __pattern__ = r"http://(?:www.)?x7.to/" +    __version__ = "0.3" +    __description__ = """X7.To File Download Hoster""" +    __author_name__ = ("ernieb") +    __author_mail__ = ("ernieb") +     +    FILE_INFO_PATTERN=r'<meta name="description" content="Download: (.*?) \(([0-9,.]+) (KB|MB|GB)\)' + +    def init(self): +        if self.premium: +            self.multiDL = False +            self.resumeDownload = False +            self.chunkLimit = 1 +        else: +            self.multiDL = False + +        self.file_id = re.search(r"http://x7.to/([a-zA-Z0-9]+)", self.pyfile.url).group(1) +        self.logDebug("file id is %s" % self.file_id) +        self.pyfile.url = "http://x7.to/" + self.file_id + +    def process(self, pyfile): +        self.fail("Hoster not longer available") + +    def handlePremium(self): +        # check if over limit first +        overLimit = re.search(r'<a onClick="cUser.buyTraffic\(\)" id="DL">', self.html) +        if overLimit: +            self.logDebug("over limit, falling back to free") +            self.handleFree() +        else: +            realurl = re.search(r'<a href="(http://stor.*?)" id="DL">', self.html) +            if realurl: +                realurl = realurl.group(1) +                self.logDebug("premium url found %s" % realurl) +            else: +                self.logDebug("premium link not found") +            self.download(realurl) + +    def handleFree(self): +        # find file id +        file_id = re.search(r"var dlID = '(.*?)'", self.html) +        if not file_id: +            self.fail("Free download id not found") + +        file_url = "http://x7.to/james/ticket/dl/" + file_id.group(1) +        self.logDebug("download id %s" % file_id.group(1)) + +        self.html = self.load(file_url, ref=False, decode=True) + +        # deal with errors +        if "limit-dl" in self.html: +            self.logDebug("Limit reached ... waiting") +            self.setWait(900,True) +            self.wait() +            self.retry() + +        if "limit-parallel" in self.html: +            self.fail("Cannot download in parallel") + +        # no waiting required, go to download +        waitCheck = re.search(r"wait:(\d*),", self.html) +        if waitCheck: +            waitCheck = int(waitCheck.group(1)) +            self.setWait(waitCheck) +            self.wait() + +        urlCheck = re.search(r"url:'(.*?)'", self.html) +        url = None +        if urlCheck: +            url = urlCheck.group(1) +            self.logDebug("free url found %s" % url) + +        if url: +            try: +                self.download(url) +            except: +                self.logDebug("downloading url failed: %s" % url) +        else: +            self.fail("Free download url found") diff --git a/module/plugins/hoster/Xdcc.py b/module/plugins/hoster/Xdcc.py index 92b77f73a..d0630bd29 100644 --- a/module/plugins/hoster/Xdcc.py +++ b/module/plugins/hoster/Xdcc.py @@ -1,229 +1,229 @@ -# -*- 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
 -"""
 -
 -from os.path import join
 -from os.path import exists
 -from os import makedirs
 -import re
 -import sys
 -import time
 -import socket, struct
 -from select import select
 -from module.utils import save_join
 -
 -from module.plugins.Hoster import Hoster
 -
 -
 -class Xdcc(Hoster):
 -    __name__ = "Xdcc"
 -    __version__ = "0.32"
 -    __pattern__ = r'xdcc://.*?(/#?.*?)?/.*?/#?\d+/?' # xdcc://irc.Abjects.net/#channel/[XDCC]|Shit/#0004/
 -    __type__ = "hoster"
 -    __config__ = [
 -                    ("nick", "str", "Nickname", "pyload"),
 -                    ("ident", "str", "Ident", "pyloadident"),
 -                    ("realname", "str", "Realname", "pyloadreal")
 -                 ]
 -    __description__ = """A Plugin that allows you to download from an IRC XDCC bot"""
 -    __author_name__ = ("jeix")
 -    __author_mail__ = ("jeix@hasnomail.com")
 -    
 -    def setup(self):
 -        self.debug   = 0  #0,1,2
 -        self.timeout = 30
 -        self.multiDL = False
 -        
 -        
 -    
 -    def process(self, pyfile):
 -        # change request type
 -        self.req = pyfile.m.core.requestFactory.getRequest(self.__name__, type="XDCC")
 -    
 -        self.pyfile = pyfile
 -        for i in range(0,3):
 -            try:
 -                nmn = self.doDownload(pyfile.url)
 -                self.logDebug("%s: Download of %s finished." % (self.__name__, nmn))
 -                return
 -            except socket.error, e:
 -                if hasattr(e, "errno"):
 -                    errno = e.errno
 -                else:
 -                    errno = e.args[0]
 -                    
 -                if errno in (10054,):
 -                    self.logDebug("XDCC: Server blocked our ip, retry in 5 min")
 -                    self.setWait(300)
 -                    self.wait()
 -                    continue                    
 -
 -                self.fail("Failed due to socket errors. Code: %d" % errno)
 -                
 -        self.fail("Server blocked our ip, retry again later manually")
 -
 -
 -    def doDownload(self, url):
 -        self.pyfile.setStatus("waiting") # real link
 -
 -        download_folder = self.config['general']['download_folder']
 -        location = join(download_folder, self.pyfile.package().folder.decode(sys.getfilesystemencoding()))
 -        if not exists(location): 
 -            makedirs(location)
 -            
 -        m = re.search(r'xdcc://(.*?)/#?(.*?)/(.*?)/#?(\d+)/?', url)
 -        server = m.group(1)
 -        chan   = m.group(2)
 -        bot    = m.group(3)
 -        pack   = m.group(4)
 -        nick   = self.getConfig('nick')
 -        ident  = self.getConfig('ident')
 -        real   = self.getConfig('realname')
 -        
 -        temp = server.split(':')
 -        ln = len(temp)
 -        if ln == 2:
 -            host, port = temp
 -        elif ln == 1:
 -            host, port = temp[0], 6667
 -        else:
 -            self.fail("Invalid hostname for IRC Server (%s)" % server)
 -        
 -        
 -        #######################
 -        # CONNECT TO IRC AND IDLE FOR REAL LINK
 -        dl_time = time.time()
 -        
 -        sock = socket.socket()
 -        sock.connect((host, int(port)))
 -        if nick == "pyload":
 -            nick = "pyload-%d" % (time.time() % 1000) # last 3 digits
 -        sock.send("NICK %s\r\n" % nick)
 -        sock.send("USER %s %s bla :%s\r\n" % (ident, host, real))
 -        time.sleep(3)
 -        sock.send("JOIN #%s\r\n" % chan)
 -        sock.send("PRIVMSG %s :xdcc send #%s\r\n" % (bot, pack))
 -        
 -        # IRC recv loop
 -        readbuffer = ""
 -        done = False
 -        retry = None
 -        m = None
 -        while True:
 -
 -            # done is set if we got our real link
 -            if done:
 -                break
 -        
 -            if retry:
 -                if time.time() > retry:
 -                    retry = None
 -                    dl_time = time.time()
 -                    sock.send("PRIVMSG %s :xdcc send #%s\r\n" % (bot, pack))
 -
 -            else:
 -                if (dl_time + self.timeout) < time.time(): # todo: add in config
 -                    sock.send("QUIT :byebye\r\n")
 -                    sock.close()
 -                    self.fail("XDCC Bot did not answer")
 -
 -
 -            fdset = select([sock], [], [], 0)
 -            if sock not in fdset[0]:
 -                continue
 -                
 -            readbuffer += sock.recv(1024)
 -            temp = readbuffer.split("\n")
 -            readbuffer = temp.pop()
 -
 -            for line in temp:
 -                if self.debug is 2: print "*> " + unicode(line, errors='ignore')
 -                line  = line.rstrip()
 -                first = line.split()
 -
 -                if first[0] == "PING":
 -                    sock.send("PONG %s\r\n" % first[1])
 -                    
 -                if first[0] == "ERROR":
 -                    self.fail("IRC-Error: %s" % line)
 -                    
 -                msg = line.split(None, 3)
 -                if len(msg) != 4:
 -                    continue
 -                    
 -                msg = { \
 -                    "origin":msg[0][1:], \
 -                    "action":msg[1], \
 -                    "target":msg[2], \
 -                    "text"  :msg[3][1:] \
 -                }
 -
 -
 -                if nick == msg["target"][0:len(nick)] and "PRIVMSG" == msg["action"]:
 -                    if msg["text"] == "\x01VERSION\x01":
 -                        self.logDebug("XDCC: Sending CTCP VERSION.")
 -                        sock.send("NOTICE %s :%s\r\n" % (msg['origin'], "pyLoad! IRC Interface"))
 -                    elif msg["text"] == "\x01TIME\x01":
 -                        self.logDebug("Sending CTCP TIME.")
 -                        sock.send("NOTICE %s :%d\r\n" % (msg['origin'], time.time()))
 -                    elif msg["text"] == "\x01LAG\x01":
 -                        pass # don't know how to answer
 -                
 -                if not (bot == msg["origin"][0:len(bot)] 
 -                    and nick == msg["target"][0:len(nick)] 
 -                    and msg["action"] in ("PRIVMSG", "NOTICE")):
 -                    continue
 -                    
 -                if self.debug is 1:
 -                    print "%s: %s" % (msg["origin"], msg["text"])
 -                    
 -                if "You already requested that pack" in msg["text"]:
 -                    retry = time.time() + 300
 -                    
 -                if "you must be on a known channel to request a pack" in msg["text"]:
 -                    self.fail("Wrong channel")
 -            
 -                m = re.match('\x01DCC SEND (.*?) (\d+) (\d+)(?: (\d+))?\x01', msg["text"])
 -                if m:
 -                    done = True
 -                
 -        # get connection data
 -        ip       = socket.inet_ntoa(struct.pack('L', socket.ntohl(int(m.group(2)))))
 -        port     = int(m.group(3))        
 -        packname = m.group(1)
 -        
 -        if len(m.groups()) > 3:
 -            self.req.filesize = int(m.group(4))
 -            
 -        self.pyfile.name = packname
 -        filename = save_join(location, packname)
 -        self.logInfo("XDCC: Downloading %s from %s:%d" % (packname, ip, port))
 -
 -        self.pyfile.setStatus("downloading")
 -        newname = self.req.download(ip, port, filename, sock, self.pyfile.setProgress)
 -        if newname and newname != filename:
 -            self.logInfo("%(name)s saved as %(newname)s" % {"name": self.pyfile.name, "newname": newname})
 -            filename = newname
 -        
 -        # kill IRC socket
 -        # sock.send("QUIT :byebye\r\n")
 -        sock.close()
 -
 -        self.lastDownload = filename
 -        return self.lastDownload
 -        
 +# -*- 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 +""" + +from os.path import join +from os.path import exists +from os import makedirs +import re +import sys +import time +import socket, struct +from select import select +from module.utils import save_join + +from module.plugins.Hoster import Hoster + + +class Xdcc(Hoster): +    __name__ = "Xdcc" +    __version__ = "0.32" +    __pattern__ = r'xdcc://.*?(/#?.*?)?/.*?/#?\d+/?' # xdcc://irc.Abjects.net/#channel/[XDCC]|Shit/#0004/ +    __type__ = "hoster" +    __config__ = [ +                    ("nick", "str", "Nickname", "pyload"), +                    ("ident", "str", "Ident", "pyloadident"), +                    ("realname", "str", "Realname", "pyloadreal") +                 ] +    __description__ = """A Plugin that allows you to download from an IRC XDCC bot""" +    __author_name__ = ("jeix") +    __author_mail__ = ("jeix@hasnomail.com") +     +    def setup(self): +        self.debug   = 0  #0,1,2 +        self.timeout = 30 +        self.multiDL = False +         +         +     +    def process(self, pyfile): +        # change request type +        self.req = pyfile.m.core.requestFactory.getRequest(self.__name__, type="XDCC") +     +        self.pyfile = pyfile +        for i in range(0,3): +            try: +                nmn = self.doDownload(pyfile.url) +                self.logDebug("%s: Download of %s finished." % (self.__name__, nmn)) +                return +            except socket.error, e: +                if hasattr(e, "errno"): +                    errno = e.errno +                else: +                    errno = e.args[0] +                     +                if errno in (10054,): +                    self.logDebug("XDCC: Server blocked our ip, retry in 5 min") +                    self.setWait(300) +                    self.wait() +                    continue                     + +                self.fail("Failed due to socket errors. Code: %d" % errno) +                 +        self.fail("Server blocked our ip, retry again later manually") + + +    def doDownload(self, url): +        self.pyfile.setStatus("waiting") # real link + +        download_folder = self.config['general']['download_folder'] +        location = join(download_folder, self.pyfile.package().folder.decode(sys.getfilesystemencoding())) +        if not exists(location):  +            makedirs(location) +             +        m = re.search(r'xdcc://(.*?)/#?(.*?)/(.*?)/#?(\d+)/?', url) +        server = m.group(1) +        chan   = m.group(2) +        bot    = m.group(3) +        pack   = m.group(4) +        nick   = self.getConfig('nick') +        ident  = self.getConfig('ident') +        real   = self.getConfig('realname') +         +        temp = server.split(':') +        ln = len(temp) +        if ln == 2: +            host, port = temp +        elif ln == 1: +            host, port = temp[0], 6667 +        else: +            self.fail("Invalid hostname for IRC Server (%s)" % server) +         +         +        ####################### +        # CONNECT TO IRC AND IDLE FOR REAL LINK +        dl_time = time.time() +         +        sock = socket.socket() +        sock.connect((host, int(port))) +        if nick == "pyload": +            nick = "pyload-%d" % (time.time() % 1000) # last 3 digits +        sock.send("NICK %s\r\n" % nick) +        sock.send("USER %s %s bla :%s\r\n" % (ident, host, real)) +        time.sleep(3) +        sock.send("JOIN #%s\r\n" % chan) +        sock.send("PRIVMSG %s :xdcc send #%s\r\n" % (bot, pack)) +         +        # IRC recv loop +        readbuffer = "" +        done = False +        retry = None +        m = None +        while True: + +            # done is set if we got our real link +            if done: +                break +         +            if retry: +                if time.time() > retry: +                    retry = None +                    dl_time = time.time() +                    sock.send("PRIVMSG %s :xdcc send #%s\r\n" % (bot, pack)) + +            else: +                if (dl_time + self.timeout) < time.time(): # todo: add in config +                    sock.send("QUIT :byebye\r\n") +                    sock.close() +                    self.fail("XDCC Bot did not answer") + + +            fdset = select([sock], [], [], 0) +            if sock not in fdset[0]: +                continue +                 +            readbuffer += sock.recv(1024) +            temp = readbuffer.split("\n") +            readbuffer = temp.pop() + +            for line in temp: +                if self.debug is 2: print "*> " + unicode(line, errors='ignore') +                line  = line.rstrip() +                first = line.split() + +                if first[0] == "PING": +                    sock.send("PONG %s\r\n" % first[1]) +                     +                if first[0] == "ERROR": +                    self.fail("IRC-Error: %s" % line) +                     +                msg = line.split(None, 3) +                if len(msg) != 4: +                    continue +                     +                msg = { \ +                    "origin":msg[0][1:], \ +                    "action":msg[1], \ +                    "target":msg[2], \ +                    "text"  :msg[3][1:] \ +                } + + +                if nick == msg["target"][0:len(nick)] and "PRIVMSG" == msg["action"]: +                    if msg["text"] == "\x01VERSION\x01": +                        self.logDebug("XDCC: Sending CTCP VERSION.") +                        sock.send("NOTICE %s :%s\r\n" % (msg['origin'], "pyLoad! IRC Interface")) +                    elif msg["text"] == "\x01TIME\x01": +                        self.logDebug("Sending CTCP TIME.") +                        sock.send("NOTICE %s :%d\r\n" % (msg['origin'], time.time())) +                    elif msg["text"] == "\x01LAG\x01": +                        pass # don't know how to answer +                 +                if not (bot == msg["origin"][0:len(bot)]  +                    and nick == msg["target"][0:len(nick)]  +                    and msg["action"] in ("PRIVMSG", "NOTICE")): +                    continue +                     +                if self.debug is 1: +                    print "%s: %s" % (msg["origin"], msg["text"]) +                     +                if "You already requested that pack" in msg["text"]: +                    retry = time.time() + 300 +                     +                if "you must be on a known channel to request a pack" in msg["text"]: +                    self.fail("Wrong channel") +             +                m = re.match('\x01DCC SEND (.*?) (\d+) (\d+)(?: (\d+))?\x01', msg["text"]) +                if m: +                    done = True +                 +        # get connection data +        ip       = socket.inet_ntoa(struct.pack('L', socket.ntohl(int(m.group(2))))) +        port     = int(m.group(3))         +        packname = m.group(1) +         +        if len(m.groups()) > 3: +            self.req.filesize = int(m.group(4)) +             +        self.pyfile.name = packname +        filename = save_join(location, packname) +        self.logInfo("XDCC: Downloading %s from %s:%d" % (packname, ip, port)) + +        self.pyfile.setStatus("downloading") +        newname = self.req.download(ip, port, filename, sock, self.pyfile.setProgress) +        if newname and newname != filename: +            self.logInfo("%(name)s saved as %(newname)s" % {"name": self.pyfile.name, "newname": newname}) +            filename = newname +         +        # kill IRC socket +        # sock.send("QUIT :byebye\r\n") +        sock.close() + +        self.lastDownload = filename +        return self.lastDownload +         diff --git a/module/plugins/hoster/YourfilesTo.py b/module/plugins/hoster/YourfilesTo.py index c2183f8a8..4a192b32a 100644 --- a/module/plugins/hoster/YourfilesTo.py +++ b/module/plugins/hoster/YourfilesTo.py @@ -1,83 +1,83 @@ -#!/usr/bin/env python
 -# -*- coding: utf-8 -*-
 -
 -import re
 -import urllib
 -from module.plugins.Hoster import Hoster
 -
 -class YourfilesTo(Hoster):
 -    __name__ = "YourfilesTo"
 -    __type__ = "hoster"
 -    __pattern__ = r"(http://)?(www\.)?yourfiles\.(to|biz)/\?d=[a-zA-Z0-9]+"
 -    __version__ = "0.21"
 -    __description__ = """Youfiles.to Download Hoster"""
 -    __author_name__ = ("jeix", "skydancer")
 -    __author_mail__ = ("jeix@hasnomail.de", "skydancer@hasnomail.de")
 -
 -    def setup(self):
 -        self.html = None
 -        self.multiDL = True
 -
 -    def process(self,pyfile):
 -        self.pyfile = pyfile
 -        self.prepare()
 -        self.download(self.get_file_url())
 -    
 -    def prepare(self):
 -        if not self.file_exists():
 -            self.offline()
 -
 -        self.pyfile.name = self.get_file_name()
 -        
 -        wait_time = self.get_waiting_time()
 -        self.setWait(wait_time)
 -        self.logDebug("%s: Waiting %d seconds." % (self.__name__,wait_time))
 -        self.wait()
 -
 -    def get_waiting_time(self):
 -        if self.html is None:
 -            self.download_html()
 -            
 -        #var zzipitime = 15;
 -        m = re.search(r'var zzipitime = (\d+);', self.html)
 -        if m:
 -            sec = int(m.group(1))
 -        else:
 -            sec = 0
 -            
 -        return sec
 -        
 -    def download_html(self):
 -        url = self.pyfile.url
 -        self.html = self.load(url)
 -
 -    def get_file_url(self):
 -        """ returns the absolute downloadable filepath
 -        """
 -        url = re.search(r"var bla = '(.*?)';", self.html)
 -        if url:
 -            url = url.group(1)
 -            url = urllib.unquote(url.replace("http://http:/http://", "http://").replace("dumdidum", ""))
 -            return url
 -        else:
 -            self.fail("absolute filepath could not be found. offline? ")
 -       
 -    def get_file_name(self):
 -        if self.html is None:
 -            self.download_html()
 -
 -        return re.search("<title>(.*)</title>", self.html).group(1)
 -
 -    def file_exists(self):
 -        """ returns True or False
 -        """
 -        if self.html is None:
 -            self.download_html()
 -            
 -        if re.search(r"HTTP Status 404", self.html) is not None:
 -            return False
 -        else:
 -            return True
 -
 -        
 -
 +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +import urllib +from module.plugins.Hoster import Hoster + +class YourfilesTo(Hoster): +    __name__ = "YourfilesTo" +    __type__ = "hoster" +    __pattern__ = r"(http://)?(www\.)?yourfiles\.(to|biz)/\?d=[a-zA-Z0-9]+" +    __version__ = "0.21" +    __description__ = """Youfiles.to Download Hoster""" +    __author_name__ = ("jeix", "skydancer") +    __author_mail__ = ("jeix@hasnomail.de", "skydancer@hasnomail.de") + +    def setup(self): +        self.html = None +        self.multiDL = True + +    def process(self,pyfile): +        self.pyfile = pyfile +        self.prepare() +        self.download(self.get_file_url()) +     +    def prepare(self): +        if not self.file_exists(): +            self.offline() + +        self.pyfile.name = self.get_file_name() +         +        wait_time = self.get_waiting_time() +        self.setWait(wait_time) +        self.logDebug("%s: Waiting %d seconds." % (self.__name__,wait_time)) +        self.wait() + +    def get_waiting_time(self): +        if self.html is None: +            self.download_html() +             +        #var zzipitime = 15; +        m = re.search(r'var zzipitime = (\d+);', self.html) +        if m: +            sec = int(m.group(1)) +        else: +            sec = 0 +             +        return sec +         +    def download_html(self): +        url = self.pyfile.url +        self.html = self.load(url) + +    def get_file_url(self): +        """ returns the absolute downloadable filepath +        """ +        url = re.search(r"var bla = '(.*?)';", self.html) +        if url: +            url = url.group(1) +            url = urllib.unquote(url.replace("http://http:/http://", "http://").replace("dumdidum", "")) +            return url +        else: +            self.fail("absolute filepath could not be found. offline? ") +        +    def get_file_name(self): +        if self.html is None: +            self.download_html() + +        return re.search("<title>(.*)</title>", self.html).group(1) + +    def file_exists(self): +        """ returns True or False +        """ +        if self.html is None: +            self.download_html() +             +        if re.search(r"HTTP Status 404", self.html) is not None: +            return False +        else: +            return True + +         + diff --git a/module/plugins/hoster/ZeveraCom.py b/module/plugins/hoster/ZeveraCom.py index 3ad662bb6..92f9e4dcd 100644 --- a/module/plugins/hoster/ZeveraCom.py +++ b/module/plugins/hoster/ZeveraCom.py @@ -1,108 +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.21"
 -    __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 %s account or deactivate this plugin") % "zevera.com")
 -            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'))
 +#!/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.21" +    __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 %s account or deactivate this plugin") % "zevera.com") +            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/web/media/default/css/default.css b/module/web/media/default/css/default.css index fc0d148c2..116f9725a 100644 --- a/module/web/media/default/css/default.css +++ b/module/web/media/default/css/default.css @@ -1,908 +1,908 @@ -.hidden {
 -	display:none;
 -}
 -.leftalign {
 -	text-align:left;
 -}
 -.centeralign {
 -	text-align:center;
 -}
 -.rightalign {
 -	text-align:right;
 -}
 -
 -
 -.dokuwiki div.plugin_translation ul li a.wikilink1:link, .dokuwiki div.plugin_translation ul li a.wikilink1:hover, .dokuwiki div.plugin_translation ul li a.wikilink1:active, .dokuwiki div.plugin_translation ul li a.wikilink1:visited {
 -	background-color:#000080;
 -	color:#fff !important;
 -	text-decoration:none;
 -	padding:0 0.2em;
 -	margin:0.1em 0.2em;
 -	border:none !important;
 -}
 -.dokuwiki div.plugin_translation ul li a.wikilink2:link, .dokuwiki div.plugin_translation ul li a.wikilink2:hover, .dokuwiki div.plugin_translation ul li a.wikilink2:active, .dokuwiki div.plugin_translation ul li a.wikilink2:visited {
 -	background-color:#808080;
 -	color:#fff !important;
 -	text-decoration:none;
 -	padding:0 0.2em;
 -	margin:0.1em 0.2em;
 -	border:none !important;
 -}
 -
 -.dokuwiki div.plugin_translation ul li a:hover img {
 -	opacity:1.0;
 -	height:15px;
 -}
 -
 -body {
 -	margin:0;
 -	padding:0;
 -	background-color:white;
 -	color:black;
 -	font-size:12px;
 -	font-family:Verdana, Helvetica, "Lucida Grande", Lucida, Arial, sans-serif;
 -	font-family:sans-serif;
 -	font-size:99, 96%;
 -	font-size-adjust:none;
 -	font-style:normal;
 -	font-variant:normal;
 -	font-weight:normal;
 -	line-height:normal;
 -}
 -hr {
 -	border-width:0;
 -	border-bottom:1px #aaa dotted;
 -}
 -img {
 -	border:none;
 -}
 -form {
 -	margin:0px;
 -	padding:0px;
 -	border:none;
 -	display:inline;
 -	background:transparent;
 -}
 -ul li {
 -	margin:5px;
 -}
 -textarea {
 -	font-family:monospace;
 -}
 -table {
 -	margin:0.5em 0;
 -	border-collapse:collapse;
 -}
 -td {
 -	padding:0.25em;
 -	border:1pt solid #ADB9CC;
 -}
 -a {
 -	color:#3465a4;
 -	text-decoration:none;
 -}
 -a:hover {
 -	text-decoration:underline;
 -}
 -
 -option {
 -	border:0 none #fff;
 -}
 -strong.highlight {
 -	background-color:#fc9;
 -	padding:1pt;
 -}
 -#pagebottom {
 -	clear:both;
 -}
 -hr {
 -	height:1px;
 -	color:#c0c0c0;
 -	background-color:#c0c0c0;
 -	border:none;
 -	margin:.2em 0 .2em 0;
 -}
 -
 -.invisible {
 -	margin:0px;
 -	border:0px;
 -	padding:0px;
 -	height:0px;
 -	visibility:hidden;
 -}
 -.left {
 -	float:left !important;
 -}
 -.right {
 -	float:right !important;
 -}
 -.center {
 -	text-align:center;
 -}
 -div#body-wrapper {
 -	padding:40px 40px 10px 40px;
 -	font-size:127%;
 -}
 -div#content {
 -	margin-top:-20px;
 -	padding:0;
 -	font-size:14px;
 -	color:black;
 -	line-height:1.5em;
 -}
 -h1, h2, h3, h4, h5, h6 {
 -	background:transparent none repeat scroll 0 0;
 -	border-bottom:1px solid #aaa;
 -	color:black;
 -	font-weight:normal;
 -	margin:0;
 -	padding:0;
 -	padding-bottom:0.17em;
 -	padding-top:0.5em;
 -}
 -h1 {
 -	font-size:188%;
 -	line-height:1.2em;
 -	margin-bottom:0.1em;
 -	padding-bottom:0;
 -}
 -h2 {
 -	font-size:150%;
 -}
 -h3, h4, h5, h6 {
 -	border-bottom:none;
 -	font-weight:bold;
 -}
 -h3 {
 -	font-size:132%;
 -}
 -h4 {
 -	font-size:116%;
 -}
 -h5 {
 -	font-size:100%;
 -}
 -h6 {
 -	font-size:80%;
 -}
 -ul#page-actions, ul#page-actions-more {
 -	float:right;
 -	margin:10px 10px 0 10px;
 -	padding:6px;
 -	color:black;
 -	background-color:#ececec;
 -	list-style-type:none;
 -	white-space: nowrap;
 -	border-radius:5px;
 -	-moz-border-radius:5px;
 -}
 -ul#user-actions {
 -	padding:5px;
 -	margin:0;
 -	display:inline;
 -	color:black;
 -	background-color:#ececec;
 -	list-style-type:none;
 -	-moz-border-radius:3px;
 -	border-radius:3px;
 -}
 -ul#page-actions li, ul#user-actions li, ul#page-actions-more li {
 -	display:inline;
 -}
 -ul#page-actions a, ul#user-actions a, ul#page-actions-more a {
 -	text-decoration:none;
 -	color:black;
 -	display:inline;
 -	margin:0 3px;
 -	padding:2px 0px 2px 18px;
 -}
 -ul#page-actions a:hover, ul#page-actions a:focus, ul#user-actions a:hover, ul#user-actions a:focus {
 -	/*text-decoration:underline;*/
 -}
 -/***************************/
 -ul#page-actions2 {
 -	float:left;
 -	margin:10px 10px 0 10px;
 -	padding:6px;
 -	color:black;
 -	background-color:#ececec;
 -	list-style-type:none;
 -	border-radius:5px;
 -	-moz-border-radius:5px;
 -}
 -ul#user-actions2 {
 -	padding:5px;
 -	margin:0;
 -	display:inline;
 -	color:black;
 -	background-color:#ececec;
 -	list-style-type:none;
 -	border-radius:3px;
 -	-moz-border-radius:3px;
 -}
 -ul#page-actions2 li, ul#user-actions2 li {
 -	display:inline;
 -}
 -ul#page-actions2 a, ul#user-actions2 a {
 -	text-decoration:none;
 -	color:black;
 -	display:inline;
 -	margin:0 3px;
 -	padding:2px 0px 2px 18px;
 -}
 -ul#page-actions2 a:hover, ul#page-actions2 a:focus, ul#user-actions2 a:hover, ul#user-actions2 a:focus,
 -ul#page-actions-more a:hover, ul#page-actions-more a:focus{
 -	color: #4e7bb4;
 -}
 -/****************************/
 -.hidden {
 -	display:none;
 -}
 -
 -a.action.index {
 -	background:transparent url(/media/default/img/wiki-tools-index.png) 0px 1px no-repeat;
 -}
 -a.action.recent {
 -	background:transparent url(/media/default/img/wiki-tools-recent.png) 0px 1px no-repeat;
 -}
 -a.logout {
 -	background:transparent url(/media/default/img/user-actions-logout.png) 0px 1px no-repeat;
 -}
 -
 -a.info {
 -    background:transparent url(/media/default/img/user-info.png) 0px 1px no-repeat;
 -}
 -
 -a.admin {
 -	background:transparent url(/media/default/img/user-actions-admin.png) 0px 1px no-repeat;
 -}
 -a.profile {
 -	background:transparent url(/media/default/img/user-actions-profile.png) 0px 1px no-repeat;
 -}
 -a.create, a.edit {
 -	background:transparent url(/media/default/img/page-tools-edit.png) 0px 1px no-repeat;
 -}
 -a.source, a.show {
 -	background:transparent url(/media/default/img/page-tools-source.png) 0px 1px no-repeat;
 -}
 -a.revisions {
 -	background:transparent url(/media/default/img/page-tools-revisions.png) 0px 1px no-repeat;
 -}
 -a.subscribe, a.unsubscribe {
 -	background:transparent url(/media/default/img/page-tools-subscribe.png) 0px 1px no-repeat;
 -}
 -a.backlink {
 -	background:transparent url(/media/default/img/page-tools-backlinks.png) 0px 1px no-repeat;
 -}
 -a.play {
 -	background:transparent url(/media/default/img/control_play.png) 0px 1px no-repeat;
 -}
 -.time {
 -	background:transparent url(/media/default/img/status_None.png) 0px 1px no-repeat;
 -        padding: 2px 0px 2px 18px;
 -        margin: 0px 3px;
 -}
 -.reconnect {
 -	background:transparent url(/media/default/img/reconnect.png) 0px 1px no-repeat;
 -        padding: 2px 0px 2px 18px;
 -        margin: 0px 3px;
 -}
 -a.play:hover {
 -	background:transparent url(/media/default/img/control_play_blue.png) 0px 1px no-repeat;
 -}
 -a.cancel {
 -	background:transparent url(/media/default/img/control_cancel.png) 0px 1px no-repeat;
 -}
 -a.cancel:hover {
 -	background:transparent url(/media/default/img/control_cancel_blue.png) 0px 1px no-repeat;
 -}
 -a.pause {
 -	background:transparent url(/media/default/img/control_pause.png) 0px 1px no-repeat;
 -}
 -a.pause:hover {
 -	background:transparent url(/media/default/img/control_pause_blue.png) 0px 1px no-repeat;
 -	font-weight: bold;
 -}
 -a.stop {
 -	background:transparent url(/media/default/img/control_stop.png) 0px 1px no-repeat;
 -}
 -a.stop:hover {
 -	background:transparent url(/media/default/img/control_stop_blue.png) 0px 1px no-repeat;
 -}
 -a.add {
 -	background:transparent url(/media/default/img/control_add.png) 0px 1px no-repeat;
 -}
 -a.add:hover {
 -	background:transparent url(/media/default/img/control_add_blue.png) 0px 1px no-repeat;
 -}
 -a.cog {
 -	background:transparent url(/media/default/img/cog.png) 0px 1px no-repeat;
 -}
 -#head-panel {
 -	background:#525252 url(/media/default/img/head_bg1.png) bottom left repeat-x;
 -}
 -#head-panel h1 {
 -	display:none;
 -	margin:0;
 -	text-decoration:none;
 -	padding-top:0.8em;
 -	padding-left:3.3em;
 -	font-size:2.6em;
 -	color:#eeeeec;
 -}
 -#head-panel #head-logo {
 -	float:left;
 -	margin:5px 0 -15px 5px;
 -	padding:0;
 -	overflow:visible;
 -}
 -#head-menu {
 -	background:transparent url(/media/default/img/tabs-border-bottom.png) 0 100% repeat-x;
 -	width:100%;
 -	float:left;
 -	margin:0;
 -	padding:0;
 -	padding-top:0.8em;
 -}
 -#head-menu ul {
 -	list-style:none;
 -	margin:0 1em 0 2em;
 -}
 -#head-menu ul li {
 -	float:left;
 -	margin:0;
 -	margin-left:0.3em;
 -	font-size:14px;
 -	margin-bottom:4px;
 -}
 -#head-menu ul li.selected, #head-menu ul li:hover {
 -	margin-bottom:0px;
 -}
 -#head-menu ul li a img {
 -	height:22px;
 -	width:22px;
 -	vertical-align:middle;
 -}
 -#head-menu ul li a, #head-menu ul li a:link {
 -	float:left;
 -	text-decoration:none;
 -	color:#555;
 -	background:#eaeaea url(/media/default/img/tab-background.png) 0 100% repeat-x;
 -	padding:3px 7px 3px 7px;
 -	border:2px solid #ccc;
 -	border-bottom:0px solid transparent;
 -	padding-bottom:3px;
 -	-moz-border-radius:5px;
 -	border-radius:5px;
 -}
 -#head-menu ul li a:hover, #head-menu ul li a:focus {
 -	color:#111;
 -	padding-bottom:7px;
 -	border-bottom:0px none transparent;
 -	outline:none;
 -	border-bottom-left-radius: 0px;
 -	border-bottom-right-radius: 0px;
 -	-moz-border-radius-bottomright:0px;
 -	-moz-border-radius-bottomleft:0px;
 -}
 -#head-menu ul li a:focus {
 -	margin-bottom:-4px;
 -}
 -#head-menu ul li.selected a {
 -	color:#3566A5;
 -	background:#fff;
 -	padding-bottom:7px;
 -	border-bottom:0px none transparent;
 -	border-bottom-left-radius: 0px;
 -	border-bottom-right-radius: 0px;
 -	-moz-border-radius-bottomright:0px;
 -	-moz-border-radius-bottomleft:0px;
 -}
 -#head-menu ul li.selected a:hover, #head-menu ul li.selected a:focus {
 -	color:#111;
 -}
 -div#head-search-and-login {
 -	float:right;
 -	margin:0 1em 0 0;
 -	background-color:#222;
 -	padding:7px 7px 5px 5px;
 -	color:white;
 -	white-space: nowrap;
 -	border-bottom-left-radius: 6px;
 -	border-bottom-right-radius: 6px;
 -	-moz-border-radius-bottomright:6px;
 -	-moz-border-radius-bottomleft:6px;
 -}
 -div#head-search-and-login form {
 -	display:inline;
 -	padding:0 3px;
 -}
 -div#head-search-and-login form input {
 -	border:2px solid #888;
 -	background:#eee;
 -	font-size:14px;
 -	padding:2px;
 -	border-radius:3px;
 -	-moz-border-radius:3px;
 -}
 -div#head-search-and-login form input:focus {
 -	background:#fff;
 -}
 -#head-search {
 -	font-size:14px;
 -}
 -#head-username, #head-password {
 -	width:80px;
 -	font-size:14px;
 -}
 -#pageinfo {
 -	clear:both;
 -	color:#888;
 -	padding:0.6em 0;
 -	margin:0;
 -}
 -#foot {
 -	font-style:normal;
 -	color:#888;
 -	text-align:center;
 -}
 -#foot a {
 -	color:#aaf;
 -}
 -#foot img {
 -	vertical-align:middle;
 -}
 -div.toc {
 -	border:1px dotted #888;
 -	background:#f0f0f0;
 -	margin:1em 0 1em 1em;
 -	float:right;
 -	font-size:95%;
 -}
 -div.toc .tocheader {
 -	font-weight:bold;
 -	margin:0.5em 1em;
 -}
 -div.toc ol {
 -	margin:1em 0.5em 1em 1em;
 -	padding:0;
 -}
 -div.toc ol li {
 -	margin:0;
 -	padding:0;
 -	margin-left:1em;
 -}
 -div.toc ol ol {
 -	margin:0.5em 0.5em 0.5em 1em;
 -	padding:0;
 -}
 -div.recentchanges table {
 -	clear:both;
 -}
 -div#editor-help {
 -	font-size:90%;
 -	border:1px dotted #888;
 -	padding:0ex 1ex 1ex 1ex;
 -	background:#f7f6f2;
 -}
 -div#preview {
 -	margin-top:1em;
 -}
 -label.block {
 -	display:block;
 -	text-align:right;
 -	font-weight:bold;
 -}
 -label.simple {
 -	display:block;
 -	text-align:left;
 -	font-weight:normal;
 -}
 -label.block input.edit {
 -	width:50%;
 -}
 -/*fieldset {
 -	width:300px;
 -	text-align:center;
 -	padding:0.5em;
 -	margin:auto;
 -}
 -*/
 -div.editor {
 -	margin:0 0 0 0;
 -}
 -table {
 -	margin:0.5em 0;
 -	border-collapse:collapse;
 -}
 -td {
 -	padding:0.25em;
 -	border:1pt solid #ADB9CC;
 -}
 -td p {
 -	margin:0;
 -	padding:0;
 -}
 -.u {
 -	text-decoration:underline;
 -}
 -.footnotes ul {
 -	padding:0 2em;
 -	margin:0 0 1em;
 -}
 -.footnotes li {
 -	list-style:none;
 -}
 -.userpref table, .userpref td {
 -	border:none;
 -}
 -#message {
 -	clear:both;
 -	padding:5px 10px;
 -	background-color:#eee;
 -	border-bottom:2px solid #ccc;
 -}
 -#message p {
 -	margin:5px 0;
 -	padding:0;
 -	font-weight:bold;
 -}
 -#message div.buttons {
 -	font-weight:normal;
 -}
 -.diff {
 -	width:99%;
 -}
 -.diff-title {
 -	background-color:#C0C0C0;
 -}
 -.searchresult dd span {
 -	font-weight:bold;
 -}
 -.boxtext {
 -	font-family:tahoma, arial, sans-serif;
 -	font-size:11px;
 -	color:#000;
 -	float:none;
 -	padding:3px 0 0 10px;
 -}
 -.statusbutton {
 -	width:32px;
 -	height:32px;
 -	float:left;
 -	margin-left:-32px;
 -	margin-right:5px;
 -	opacity:0;
 -	cursor:pointer
 -}
 -.dlsize {
 -	float:left;
 -	padding-right: 8px;
 -}
 -.dlspeed {
 -	float:left;
 -	padding-right: 8px;
 -}
 -.package {
 -	margin-bottom: 10px;
 -}
 -.packagename {
 -	font-weight: bold;
 -}
 -
 -.child {
 -	margin-left: 20px;
 -}
 -.child_status {
 -	margin-right: 10px;
 -}
 -.child_secrow {
 -	font-size: 10px;
 -}
 -
 -.header, .header th {
 -	text-align: left;
 -	font-weight: normal;
 -	background-color:#ececec;
 -	-moz-border-radius:5px;
 -	border-radius:5px;
 -}
 -.progress_bar {
 -	background: #0C0;
 -	height: 5px;
 -	
 -}
 -
 -.queue {
 -	border: none
 -}
 -
 -.queue tr td {
 -	border: none
 -}
 -
 -.header, .header th{
 -	text-align: left;
 -	font-weight: normal;
 -}
 -
 -
 -.clearer
 -{
 -	clear: both;
 -	height: 1px;
 -}
 -
 -.left
 -{
 -	float: left;
 -}
 -
 -.right
 -{
 -	float: right;
 -}
 -
 -
 -.setfield
 -{
 -    display: table-cell;
 -}
 -
 -ul.tabs li a
 -{
 -   padding: 5px 16px 4px 15px;
 -   border: none;
 -   font-weight: bold;
 -
 -    border-radius: 5px 5px 0 0;
 -    -moz-border-radius: 5px 5px 0 0;
 -
 -}
 -
 -
 -#tabs span
 -{
 -    display: none;
 -}
 -
 -#tabs span.selected
 -{
 -    display: inline;
 -}
 -
 -#tabsback
 -{
 -    background-color: #525252;
 -    margin: 2px 0 0;
 -    padding: 6px 4px 1px 4px;
 -
 -    border-top-right-radius: 30px;
 -    border-top-left-radius: 3px;
 -    -moz-border-radius-topright: 30px;
 -    -moz-border-radius-topleft: 3px;
 -}
 -ul.tabs
 -{
 -    list-style-type: none;
 -    margin:0;
 -    padding: 0 40px 0 0;
 -}
 -
 -ul.tabs li
 -{
 -    display: inline;
 -    margin-left: 8px;
 -}
 -
 -
 -ul.tabs li a
 -{
 -    color: #42454a;
 -    background-color: #eaeaea;
 -    border: 1px none #c9c3ba;
 -    margin: 0;
 -    text-decoration: none;
 -
 -    outline: 0;
 -
 -    padding: 5px 16px 4px 15px;
 -    font-weight: bold;
 -
 -     border-radius: 5px 5px 0 0;
 -     -moz-border-radius: 5px 5px 0 0;
 -
 -}
 -
 -ul.tabs li a.selected, ul.tabs li a:hover
 -{
 -    color: #000;
 -    background-color: white;
 -
 -    border-bottom-right-radius: 0;
 -    border-bottom-left-radius: 0;
 -    -moz-border-radius-bottomright: 0;
 -    -moz-border-radius-bottomleft: 0;
 -}
 -
 -ul.tabs li a:hover
 -{
 -    background-color: #f1f4ee;
 -}
 -
 -ul.tabs li a.selected
 -{
 -    font-weight: bold;
 -    background-color: #525252;
 -    padding-bottom: 5px;
 -    color: white;
 -}
 -
 -
 -#tabs-body {
 -    position: relative;
 -    overflow: hidden;
 -}
 -
 -
 -span.tabContent
 -{
 -    border: 2px solid #525252;
 -    margin: 0;
 -    padding: 0;
 -    padding-bottom: 10px;
 -}
 -
 -#tabs-body > span {
 -    display: none;
 -}
 -
 -#tabs-body > span.active {
 -    display: block;
 -}
 -
 -.hide
 -{
 -    display: none;
 -}
 -
 -.settable
 -{
 -    margin: 20px;
 -    border: none;
 -}
 -.settable td
 -{
 -    border: none;
 -    margin: 0;
 -    padding: 5px;
 -}
 -
 -.settable th{
 -    padding-bottom: 8px;
 -}
 -
 -.settable.wide td , .settable.wide th {
 -    padding-left: 15px;
 -    padding-right: 15px;
 -}
 -
 -
 -/*settings navbar*/
 -ul.nav {
 -    margin: -30px 0 0;
 -    padding: 0;
 -	list-style: none;
 -    position: absolute;
 -}
 -
 -
 -ul.nav li {
 -	position: relative;
 -	float: left;
 -	padding: 5px;
 -}
 -
 -ul.nav > li a {
 -    background: white;
 -    -moz-border-radius: 4px 4px 4px 4px;
 -    border: 1px solid #C9C3BA;
 -    border-bottom: medium none;
 -    color: black;
 -}
 -
 -ul.nav ul {
 -	position: absolute;
 -	top: 26px;
 -	left: 10px;
 -	margin: 0;
 -	padding: 0;
 -	list-style: none;
 -	border: 1px solid #AAA;
 -	background: #f1f1f1;
 -	-webkit-box-shadow: 1px 1px 5px #AAA;
 -	-moz-box-shadow: 1px 1px 5px #AAA;
 -	box-shadow: 1px 1px 5px #AAA;
 -    cursor: pointer;
 -}
 -
 -ul.nav .open {
 -	display: block;
 -}
 -
 -ul.nav .close {
 -	display: none;
 -}
 -
 -ul.nav ul li {
 -	float: none;
 -	padding: 0;
 -}
 -
 -ul.nav ul li a {
 -	width: 130px;
 -	background: #f1f1f1;
 -	padding: 3px;
 -	display: block;
 -	font-weight: normal;
 -}
 -
 -ul.nav ul li a:hover {
 -	background: #CDCDCD;
 -}
 -
 -ul.nav ul ul {
 -	left: 137px;
 -	top: 0;
 -}
 -
 -.purr-wrapper{
 -	margin:10px;
 -}
 -
 -/*Purr alert styles*/
 -
 -.purr-alert{
 -	margin-bottom:10px;
 -	padding:10px;
 -	background:#000;
 -	font-size:13px;
 -	font-weight:bold;
 -	color:#FFF;
 -	-moz-border-radius:5px;
 -	-webkit-border-radius:5px;
 -	/*-moz-box-shadow: 0 0 10px rgba(255,255,0,.25);*/
 -	width:300px;
 -}
 -.purr-alert.error{
 -	color:#F55;
 -	padding-left:30px;
 -	background:url(/media/default/img/error.png) no-repeat #000 7px 10px;
 -	width:280px;
 -}
 -.purr-alert.success{
 -	color:#5F5;
 -	padding-left:30px;
 -	background:url(/media/default/img/success.png) no-repeat #000 7px 10px;
 -	width:280px;
 -}
 -.purr-alert.notice{
 -	color:#99F;
 -	padding-left:30px;
 -	background:url(/media/default/img//notice.png) no-repeat #000 7px 10px;
 -	width:280px;
 -}
 -
 -table.system {
 -    border: none;
 -    margin-left: 10px;
 -}
 -
 -table.system td {
 -    border: none
 -}
 -
 -table.system tr > td:first-child {
 -    font-weight: bold;
 -    padding-right: 10px;
 +.hidden { +	display:none; +} +.leftalign { +	text-align:left; +} +.centeralign { +	text-align:center; +} +.rightalign { +	text-align:right; +} + + +.dokuwiki div.plugin_translation ul li a.wikilink1:link, .dokuwiki div.plugin_translation ul li a.wikilink1:hover, .dokuwiki div.plugin_translation ul li a.wikilink1:active, .dokuwiki div.plugin_translation ul li a.wikilink1:visited { +	background-color:#000080; +	color:#fff !important; +	text-decoration:none; +	padding:0 0.2em; +	margin:0.1em 0.2em; +	border:none !important; +} +.dokuwiki div.plugin_translation ul li a.wikilink2:link, .dokuwiki div.plugin_translation ul li a.wikilink2:hover, .dokuwiki div.plugin_translation ul li a.wikilink2:active, .dokuwiki div.plugin_translation ul li a.wikilink2:visited { +	background-color:#808080; +	color:#fff !important; +	text-decoration:none; +	padding:0 0.2em; +	margin:0.1em 0.2em; +	border:none !important; +} + +.dokuwiki div.plugin_translation ul li a:hover img { +	opacity:1.0; +	height:15px; +} + +body { +	margin:0; +	padding:0; +	background-color:white; +	color:black; +	font-size:12px; +	font-family:Verdana, Helvetica, "Lucida Grande", Lucida, Arial, sans-serif; +	font-family:sans-serif; +	font-size:99, 96%; +	font-size-adjust:none; +	font-style:normal; +	font-variant:normal; +	font-weight:normal; +	line-height:normal; +} +hr { +	border-width:0; +	border-bottom:1px #aaa dotted; +} +img { +	border:none; +} +form { +	margin:0px; +	padding:0px; +	border:none; +	display:inline; +	background:transparent; +} +ul li { +	margin:5px; +} +textarea { +	font-family:monospace; +} +table { +	margin:0.5em 0; +	border-collapse:collapse; +} +td { +	padding:0.25em; +	border:1pt solid #ADB9CC; +} +a { +	color:#3465a4; +	text-decoration:none; +} +a:hover { +	text-decoration:underline; +} + +option { +	border:0 none #fff; +} +strong.highlight { +	background-color:#fc9; +	padding:1pt; +} +#pagebottom { +	clear:both; +} +hr { +	height:1px; +	color:#c0c0c0; +	background-color:#c0c0c0; +	border:none; +	margin:.2em 0 .2em 0; +} + +.invisible { +	margin:0px; +	border:0px; +	padding:0px; +	height:0px; +	visibility:hidden; +} +.left { +	float:left !important; +} +.right { +	float:right !important; +} +.center { +	text-align:center; +} +div#body-wrapper { +	padding:40px 40px 10px 40px; +	font-size:127%; +} +div#content { +	margin-top:-20px; +	padding:0; +	font-size:14px; +	color:black; +	line-height:1.5em; +} +h1, h2, h3, h4, h5, h6 { +	background:transparent none repeat scroll 0 0; +	border-bottom:1px solid #aaa; +	color:black; +	font-weight:normal; +	margin:0; +	padding:0; +	padding-bottom:0.17em; +	padding-top:0.5em; +} +h1 { +	font-size:188%; +	line-height:1.2em; +	margin-bottom:0.1em; +	padding-bottom:0; +} +h2 { +	font-size:150%; +} +h3, h4, h5, h6 { +	border-bottom:none; +	font-weight:bold; +} +h3 { +	font-size:132%; +} +h4 { +	font-size:116%; +} +h5 { +	font-size:100%; +} +h6 { +	font-size:80%; +} +ul#page-actions, ul#page-actions-more { +	float:right; +	margin:10px 10px 0 10px; +	padding:6px; +	color:black; +	background-color:#ececec; +	list-style-type:none; +	white-space: nowrap; +	border-radius:5px; +	-moz-border-radius:5px; +} +ul#user-actions { +	padding:5px; +	margin:0; +	display:inline; +	color:black; +	background-color:#ececec; +	list-style-type:none; +	-moz-border-radius:3px; +	border-radius:3px; +} +ul#page-actions li, ul#user-actions li, ul#page-actions-more li { +	display:inline; +} +ul#page-actions a, ul#user-actions a, ul#page-actions-more a { +	text-decoration:none; +	color:black; +	display:inline; +	margin:0 3px; +	padding:2px 0px 2px 18px; +} +ul#page-actions a:hover, ul#page-actions a:focus, ul#user-actions a:hover, ul#user-actions a:focus { +	/*text-decoration:underline;*/ +} +/***************************/ +ul#page-actions2 { +	float:left; +	margin:10px 10px 0 10px; +	padding:6px; +	color:black; +	background-color:#ececec; +	list-style-type:none; +	border-radius:5px; +	-moz-border-radius:5px; +} +ul#user-actions2 { +	padding:5px; +	margin:0; +	display:inline; +	color:black; +	background-color:#ececec; +	list-style-type:none; +	border-radius:3px; +	-moz-border-radius:3px; +} +ul#page-actions2 li, ul#user-actions2 li { +	display:inline; +} +ul#page-actions2 a, ul#user-actions2 a { +	text-decoration:none; +	color:black; +	display:inline; +	margin:0 3px; +	padding:2px 0px 2px 18px; +} +ul#page-actions2 a:hover, ul#page-actions2 a:focus, ul#user-actions2 a:hover, ul#user-actions2 a:focus, +ul#page-actions-more a:hover, ul#page-actions-more a:focus{ +	color: #4e7bb4; +} +/****************************/ +.hidden { +	display:none; +} + +a.action.index { +	background:transparent url(/media/default/img/wiki-tools-index.png) 0px 1px no-repeat; +} +a.action.recent { +	background:transparent url(/media/default/img/wiki-tools-recent.png) 0px 1px no-repeat; +} +a.logout { +	background:transparent url(/media/default/img/user-actions-logout.png) 0px 1px no-repeat; +} + +a.info { +    background:transparent url(/media/default/img/user-info.png) 0px 1px no-repeat; +} + +a.admin { +	background:transparent url(/media/default/img/user-actions-admin.png) 0px 1px no-repeat; +} +a.profile { +	background:transparent url(/media/default/img/user-actions-profile.png) 0px 1px no-repeat; +} +a.create, a.edit { +	background:transparent url(/media/default/img/page-tools-edit.png) 0px 1px no-repeat; +} +a.source, a.show { +	background:transparent url(/media/default/img/page-tools-source.png) 0px 1px no-repeat; +} +a.revisions { +	background:transparent url(/media/default/img/page-tools-revisions.png) 0px 1px no-repeat; +} +a.subscribe, a.unsubscribe { +	background:transparent url(/media/default/img/page-tools-subscribe.png) 0px 1px no-repeat; +} +a.backlink { +	background:transparent url(/media/default/img/page-tools-backlinks.png) 0px 1px no-repeat; +} +a.play { +	background:transparent url(/media/default/img/control_play.png) 0px 1px no-repeat; +} +.time { +	background:transparent url(/media/default/img/status_None.png) 0px 1px no-repeat; +        padding: 2px 0px 2px 18px; +        margin: 0px 3px; +} +.reconnect { +	background:transparent url(/media/default/img/reconnect.png) 0px 1px no-repeat; +        padding: 2px 0px 2px 18px; +        margin: 0px 3px; +} +a.play:hover { +	background:transparent url(/media/default/img/control_play_blue.png) 0px 1px no-repeat; +} +a.cancel { +	background:transparent url(/media/default/img/control_cancel.png) 0px 1px no-repeat; +} +a.cancel:hover { +	background:transparent url(/media/default/img/control_cancel_blue.png) 0px 1px no-repeat; +} +a.pause { +	background:transparent url(/media/default/img/control_pause.png) 0px 1px no-repeat; +} +a.pause:hover { +	background:transparent url(/media/default/img/control_pause_blue.png) 0px 1px no-repeat; +	font-weight: bold; +} +a.stop { +	background:transparent url(/media/default/img/control_stop.png) 0px 1px no-repeat; +} +a.stop:hover { +	background:transparent url(/media/default/img/control_stop_blue.png) 0px 1px no-repeat; +} +a.add { +	background:transparent url(/media/default/img/control_add.png) 0px 1px no-repeat; +} +a.add:hover { +	background:transparent url(/media/default/img/control_add_blue.png) 0px 1px no-repeat; +} +a.cog { +	background:transparent url(/media/default/img/cog.png) 0px 1px no-repeat; +} +#head-panel { +	background:#525252 url(/media/default/img/head_bg1.png) bottom left repeat-x; +} +#head-panel h1 { +	display:none; +	margin:0; +	text-decoration:none; +	padding-top:0.8em; +	padding-left:3.3em; +	font-size:2.6em; +	color:#eeeeec; +} +#head-panel #head-logo { +	float:left; +	margin:5px 0 -15px 5px; +	padding:0; +	overflow:visible; +} +#head-menu { +	background:transparent url(/media/default/img/tabs-border-bottom.png) 0 100% repeat-x; +	width:100%; +	float:left; +	margin:0; +	padding:0; +	padding-top:0.8em; +} +#head-menu ul { +	list-style:none; +	margin:0 1em 0 2em; +} +#head-menu ul li { +	float:left; +	margin:0; +	margin-left:0.3em; +	font-size:14px; +	margin-bottom:4px; +} +#head-menu ul li.selected, #head-menu ul li:hover { +	margin-bottom:0px; +} +#head-menu ul li a img { +	height:22px; +	width:22px; +	vertical-align:middle; +} +#head-menu ul li a, #head-menu ul li a:link { +	float:left; +	text-decoration:none; +	color:#555; +	background:#eaeaea url(/media/default/img/tab-background.png) 0 100% repeat-x; +	padding:3px 7px 3px 7px; +	border:2px solid #ccc; +	border-bottom:0px solid transparent; +	padding-bottom:3px; +	-moz-border-radius:5px; +	border-radius:5px; +} +#head-menu ul li a:hover, #head-menu ul li a:focus { +	color:#111; +	padding-bottom:7px; +	border-bottom:0px none transparent; +	outline:none; +	border-bottom-left-radius: 0px; +	border-bottom-right-radius: 0px; +	-moz-border-radius-bottomright:0px; +	-moz-border-radius-bottomleft:0px; +} +#head-menu ul li a:focus { +	margin-bottom:-4px; +} +#head-menu ul li.selected a { +	color:#3566A5; +	background:#fff; +	padding-bottom:7px; +	border-bottom:0px none transparent; +	border-bottom-left-radius: 0px; +	border-bottom-right-radius: 0px; +	-moz-border-radius-bottomright:0px; +	-moz-border-radius-bottomleft:0px; +} +#head-menu ul li.selected a:hover, #head-menu ul li.selected a:focus { +	color:#111; +} +div#head-search-and-login { +	float:right; +	margin:0 1em 0 0; +	background-color:#222; +	padding:7px 7px 5px 5px; +	color:white; +	white-space: nowrap; +	border-bottom-left-radius: 6px; +	border-bottom-right-radius: 6px; +	-moz-border-radius-bottomright:6px; +	-moz-border-radius-bottomleft:6px; +} +div#head-search-and-login form { +	display:inline; +	padding:0 3px; +} +div#head-search-and-login form input { +	border:2px solid #888; +	background:#eee; +	font-size:14px; +	padding:2px; +	border-radius:3px; +	-moz-border-radius:3px; +} +div#head-search-and-login form input:focus { +	background:#fff; +} +#head-search { +	font-size:14px; +} +#head-username, #head-password { +	width:80px; +	font-size:14px; +} +#pageinfo { +	clear:both; +	color:#888; +	padding:0.6em 0; +	margin:0; +} +#foot { +	font-style:normal; +	color:#888; +	text-align:center; +} +#foot a { +	color:#aaf; +} +#foot img { +	vertical-align:middle; +} +div.toc { +	border:1px dotted #888; +	background:#f0f0f0; +	margin:1em 0 1em 1em; +	float:right; +	font-size:95%; +} +div.toc .tocheader { +	font-weight:bold; +	margin:0.5em 1em; +} +div.toc ol { +	margin:1em 0.5em 1em 1em; +	padding:0; +} +div.toc ol li { +	margin:0; +	padding:0; +	margin-left:1em; +} +div.toc ol ol { +	margin:0.5em 0.5em 0.5em 1em; +	padding:0; +} +div.recentchanges table { +	clear:both; +} +div#editor-help { +	font-size:90%; +	border:1px dotted #888; +	padding:0ex 1ex 1ex 1ex; +	background:#f7f6f2; +} +div#preview { +	margin-top:1em; +} +label.block { +	display:block; +	text-align:right; +	font-weight:bold; +} +label.simple { +	display:block; +	text-align:left; +	font-weight:normal; +} +label.block input.edit { +	width:50%; +} +/*fieldset { +	width:300px; +	text-align:center; +	padding:0.5em; +	margin:auto; +} +*/ +div.editor { +	margin:0 0 0 0; +} +table { +	margin:0.5em 0; +	border-collapse:collapse; +} +td { +	padding:0.25em; +	border:1pt solid #ADB9CC; +} +td p { +	margin:0; +	padding:0; +} +.u { +	text-decoration:underline; +} +.footnotes ul { +	padding:0 2em; +	margin:0 0 1em; +} +.footnotes li { +	list-style:none; +} +.userpref table, .userpref td { +	border:none; +} +#message { +	clear:both; +	padding:5px 10px; +	background-color:#eee; +	border-bottom:2px solid #ccc; +} +#message p { +	margin:5px 0; +	padding:0; +	font-weight:bold; +} +#message div.buttons { +	font-weight:normal; +} +.diff { +	width:99%; +} +.diff-title { +	background-color:#C0C0C0; +} +.searchresult dd span { +	font-weight:bold; +} +.boxtext { +	font-family:tahoma, arial, sans-serif; +	font-size:11px; +	color:#000; +	float:none; +	padding:3px 0 0 10px; +} +.statusbutton { +	width:32px; +	height:32px; +	float:left; +	margin-left:-32px; +	margin-right:5px; +	opacity:0; +	cursor:pointer +} +.dlsize { +	float:left; +	padding-right: 8px; +} +.dlspeed { +	float:left; +	padding-right: 8px; +} +.package { +	margin-bottom: 10px; +} +.packagename { +	font-weight: bold; +} + +.child { +	margin-left: 20px; +} +.child_status { +	margin-right: 10px; +} +.child_secrow { +	font-size: 10px; +} + +.header, .header th { +	text-align: left; +	font-weight: normal; +	background-color:#ececec; +	-moz-border-radius:5px; +	border-radius:5px; +} +.progress_bar { +	background: #0C0; +	height: 5px; +	 +} + +.queue { +	border: none +} + +.queue tr td { +	border: none +} + +.header, .header th{ +	text-align: left; +	font-weight: normal; +} + + +.clearer +{ +	clear: both; +	height: 1px; +} + +.left +{ +	float: left; +} + +.right +{ +	float: right; +} + + +.setfield +{ +    display: table-cell; +} + +ul.tabs li a +{ +   padding: 5px 16px 4px 15px; +   border: none; +   font-weight: bold; + +    border-radius: 5px 5px 0 0; +    -moz-border-radius: 5px 5px 0 0; + +} + + +#tabs span +{ +    display: none; +} + +#tabs span.selected +{ +    display: inline; +} + +#tabsback +{ +    background-color: #525252; +    margin: 2px 0 0; +    padding: 6px 4px 1px 4px; + +    border-top-right-radius: 30px; +    border-top-left-radius: 3px; +    -moz-border-radius-topright: 30px; +    -moz-border-radius-topleft: 3px; +} +ul.tabs +{ +    list-style-type: none; +    margin:0; +    padding: 0 40px 0 0; +} + +ul.tabs li +{ +    display: inline; +    margin-left: 8px; +} + + +ul.tabs li a +{ +    color: #42454a; +    background-color: #eaeaea; +    border: 1px none #c9c3ba; +    margin: 0; +    text-decoration: none; + +    outline: 0; + +    padding: 5px 16px 4px 15px; +    font-weight: bold; + +     border-radius: 5px 5px 0 0; +     -moz-border-radius: 5px 5px 0 0; + +} + +ul.tabs li a.selected, ul.tabs li a:hover +{ +    color: #000; +    background-color: white; + +    border-bottom-right-radius: 0; +    border-bottom-left-radius: 0; +    -moz-border-radius-bottomright: 0; +    -moz-border-radius-bottomleft: 0; +} + +ul.tabs li a:hover +{ +    background-color: #f1f4ee; +} + +ul.tabs li a.selected +{ +    font-weight: bold; +    background-color: #525252; +    padding-bottom: 5px; +    color: white; +} + + +#tabs-body { +    position: relative; +    overflow: hidden; +} + + +span.tabContent +{ +    border: 2px solid #525252; +    margin: 0; +    padding: 0; +    padding-bottom: 10px; +} + +#tabs-body > span { +    display: none; +} + +#tabs-body > span.active { +    display: block; +} + +.hide +{ +    display: none; +} + +.settable +{ +    margin: 20px; +    border: none; +} +.settable td +{ +    border: none; +    margin: 0; +    padding: 5px; +} + +.settable th{ +    padding-bottom: 8px; +} + +.settable.wide td , .settable.wide th { +    padding-left: 15px; +    padding-right: 15px; +} + + +/*settings navbar*/ +ul.nav { +    margin: -30px 0 0; +    padding: 0; +	list-style: none; +    position: absolute; +} + + +ul.nav li { +	position: relative; +	float: left; +	padding: 5px; +} + +ul.nav > li a { +    background: white; +    -moz-border-radius: 4px 4px 4px 4px; +    border: 1px solid #C9C3BA; +    border-bottom: medium none; +    color: black; +} + +ul.nav ul { +	position: absolute; +	top: 26px; +	left: 10px; +	margin: 0; +	padding: 0; +	list-style: none; +	border: 1px solid #AAA; +	background: #f1f1f1; +	-webkit-box-shadow: 1px 1px 5px #AAA; +	-moz-box-shadow: 1px 1px 5px #AAA; +	box-shadow: 1px 1px 5px #AAA; +    cursor: pointer; +} + +ul.nav .open { +	display: block; +} + +ul.nav .close { +	display: none; +} + +ul.nav ul li { +	float: none; +	padding: 0; +} + +ul.nav ul li a { +	width: 130px; +	background: #f1f1f1; +	padding: 3px; +	display: block; +	font-weight: normal; +} + +ul.nav ul li a:hover { +	background: #CDCDCD; +} + +ul.nav ul ul { +	left: 137px; +	top: 0; +} + +.purr-wrapper{ +	margin:10px; +} + +/*Purr alert styles*/ + +.purr-alert{ +	margin-bottom:10px; +	padding:10px; +	background:#000; +	font-size:13px; +	font-weight:bold; +	color:#FFF; +	-moz-border-radius:5px; +	-webkit-border-radius:5px; +	/*-moz-box-shadow: 0 0 10px rgba(255,255,0,.25);*/ +	width:300px; +} +.purr-alert.error{ +	color:#F55; +	padding-left:30px; +	background:url(/media/default/img/error.png) no-repeat #000 7px 10px; +	width:280px; +} +.purr-alert.success{ +	color:#5F5; +	padding-left:30px; +	background:url(/media/default/img/success.png) no-repeat #000 7px 10px; +	width:280px; +} +.purr-alert.notice{ +	color:#99F; +	padding-left:30px; +	background:url(/media/default/img//notice.png) no-repeat #000 7px 10px; +	width:280px; +} + +table.system { +    border: none; +    margin-left: 10px; +} + +table.system td { +    border: none +} + +table.system tr > td:first-child { +    font-weight: bold; +    padding-right: 10px;  }
\ No newline at end of file diff --git a/module/web/media/default/css/window.css b/module/web/media/default/css/window.css index 8b13f55ec..12829868b 100644 --- a/module/web/media/default/css/window.css +++ b/module/web/media/default/css/window.css @@ -1,73 +1,73 @@ -/* ----------- stylized ----------- */
 -.window_box h1{
 -    font-size:14px;
 -    font-weight:bold;
 -    margin-bottom:8px;
 -}
 -.window_box p{
 -    font-size:11px;
 -    color:#666666;
 -    margin-bottom:20px;
 -    border-bottom:solid 1px #b7ddf2;
 -    padding-bottom:10px;
 -}
 -.window_box label{
 -    display:block;
 -    font-weight:bold;
 -    text-align:right;
 -    width:240px;
 -    float:left;
 -}
 -.window_box .small{
 -    color:#666666;
 -    display:block;
 -    font-size:11px;
 -    font-weight:normal;
 -    text-align:right;
 -    width:240px;
 -}
 -.window_box select, .window_box input{
 -    float:left;
 -    font-size:12px;
 -    padding:4px 2px;
 -    border:solid 1px #aacfe4;
 -    width:300px;
 -    margin:2px 0 20px 10px;
 -}
 -.window_box .cont{
 -    float:left;
 -    font-size:12px;
 -    padding: 0px 10px 15px 0px;
 -    width:300px;
 -    margin:0px 0px 0px 10px;
 -}
 -.window_box .cont input{
 -    float: none;
 -    margin: 0px 15px 0px 1px;
 -}
 -.window_box textarea{
 -    float:left;
 -    font-size:12px;
 -    padding:4px 2px;
 -    border:solid 1px #aacfe4;
 -    width:300px;
 -    margin:2px 0 20px 10px;
 -}
 -.window_box button, .styled_button{
 -    clear:both;
 -    margin-left:150px;
 -    width:125px;
 -    height:31px;
 -    background:#666666 url(../img/button.png) no-repeat;
 -    text-align:center;
 -    line-height:31px;
 -    color:#FFFFFF;
 -    font-size:11px;
 -    font-weight:bold;
 -    border: 0px;
 -}
 -
 -.styled_button {
 -    margin-left: 15px;
 -    cursor: pointer;
 -}
 +/* ----------- stylized ----------- */ +.window_box h1{ +    font-size:14px; +    font-weight:bold; +    margin-bottom:8px; +} +.window_box p{ +    font-size:11px; +    color:#666666; +    margin-bottom:20px; +    border-bottom:solid 1px #b7ddf2; +    padding-bottom:10px; +} +.window_box label{ +    display:block; +    font-weight:bold; +    text-align:right; +    width:240px; +    float:left; +} +.window_box .small{ +    color:#666666; +    display:block; +    font-size:11px; +    font-weight:normal; +    text-align:right; +    width:240px; +} +.window_box select, .window_box input{ +    float:left; +    font-size:12px; +    padding:4px 2px; +    border:solid 1px #aacfe4; +    width:300px; +    margin:2px 0 20px 10px; +} +.window_box .cont{ +    float:left; +    font-size:12px; +    padding: 0px 10px 15px 0px; +    width:300px; +    margin:0px 0px 0px 10px; +} +.window_box .cont input{ +    float: none; +    margin: 0px 15px 0px 1px; +} +.window_box textarea{ +    float:left; +    font-size:12px; +    padding:4px 2px; +    border:solid 1px #aacfe4; +    width:300px; +    margin:2px 0 20px 10px; +} +.window_box button, .styled_button{ +    clear:both; +    margin-left:150px; +    width:125px; +    height:31px; +    background:#666666 url(../img/button.png) no-repeat; +    text-align:center; +    line-height:31px; +    color:#FFFFFF; +    font-size:11px; +    font-weight:bold; +    border: 0px; +} + +.styled_button { +    margin-left: 15px; +    cursor: pointer; +} diff --git a/module/web/templates/default/base.html b/module/web/templates/default/base.html index 0b20ecdb0..147c08a37 100644 --- a/module/web/templates/default/base.html +++ b/module/web/templates/default/base.html @@ -1,180 +1,180 @@ -<?xml version="1.0" ?>
 -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 -    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 -<html xmlns="http://www.w3.org/1999/xhtml">
 -<head>
 -
 -<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 -<link rel="stylesheet" type="text/css" href="/media/default/css/default.css"/>
 -<link rel="stylesheet" type="text/css" href="/media/default/css/window.css"/>
 -<link rel="stylesheet" type="text/css" href="/media/default/css/MooDialog.css"/>
 -
 -<script type="text/javascript" src="/media/js/mootools-core-1.4.1.js"></script>
 -<script type="text/javascript" src="/media/js/mootools-more-1.4.0.1.js"></script>
 -<script type="text/javascript" src="/media/js/MooDialog_static.js"></script>
 -<script type="text/javascript" src="/media/js/purr_static.js"></script>
 -
 -
 -<script type="text/javascript" src="/media/js/base.js"></script>
 -
 -<title>{% block title %}pyLoad {{_("Webinterface")}}{% endblock %}</title>
 -
 -{% block head %}
 -{% endblock %}
 -</head>
 -<body>
 -<a class="anchor" name="top" id="top"></a>
 -
 -<div id="head-panel">
 -
 -
 -    <div id="head-search-and-login">
 -    {% block headpanel %}
 -
 -        {% if user.is_authenticated %}
 -
 -
 -{% if update %}
 -<span>
 -<span style="font-weight: bold; margin: 0 2px 0 2px;">{{_("pyLoad Update available!")}}</span>
 -</span>
 -{% endif %}
 -
 -
 -{% if plugins %}
 -<span>
 -<span style="font-weight: bold; margin: 0 2px 0 2px;">{{_("Plugins updated, please restart!")}}</span>
 -</span>
 -{% endif %}
 -
 -<span id="cap_info" style="display: {% if captcha %}inline{%else%}none{% endif %}">
 -<img src="/media/default/img/images.png" alt="Captcha:" style="vertical-align:middle; margin:2px" />
 -<span style="font-weight: bold; cursor: pointer; margin-right: 2px;">{{_("Captcha waiting")}}</span>
 -</span>
 -
 -    <img src="/media/default/img/head-login.png" alt="User:" style="vertical-align:middle; margin:2px" /><span style="padding-right: 2px;">{{user.name}}</span>
 -	<ul id="user-actions">
 -		<li><a href="/logout"  class="action logout" rel="nofollow">{{_("Logout")}}</a></li>
 -		{% if user.is_admin %}
 -		<li><a href="/admin" class="action profile" rel="nofollow">{{_("Administrate")}}</a></li>
 -		{% endif %}
 -        <li><a href="/info"  class="action info" rel="nofollow">{{_("Info")}}</a></li>
 -
 -	</ul>
 -{% else %}
 -    <span style="padding-right: 2px;">{{_("Please Login!")}}</span>
 -{% endif %}
 -
 -    {% endblock %}
 -	</div>
 -
 -	<a href="/"><img id="head-logo" src="/media/default/img/pyload-logo-edited3.5-new-font-small.png" alt="pyLoad" /></a>
 -
 -	<div id="head-menu">
 -		<ul>
 -
 -        {% macro selected(name, right=False) -%}
 -            {% if name in url -%}class="{% if right -%}right {% endif %}selected"{%- endif %}
 -            {% if not name in url and right -%}class="right"{%- endif %}
 -        {%- endmacro %}
 -
 -
 -		{% block menu %}
 -		<li>
 -		    <a href="/" title=""><img src="/media/default/img/head-menu-home.png" alt="" /> {{_("Home")}}</a>
 -		</li>
 -		<li {{ selected('queue') }}>
 -		    <a href="/queue/" title=""><img src="/media/default/img/head-menu-queue.png" alt="" /> {{_("Queue")}}</a>
 -		</li>
 -		<li {{ selected('collector') }}>
 -		    <a href="/collector/" title=""><img src="/media/default/img/head-menu-collector.png" alt="" /> {{_("Collector")}}</a>
 -		</li>
 -		<li {{ selected('downloads') }}>
 -		    <a href="/downloads/" title=""><img src="/media/default/img/head-menu-development.png" alt="" /> {{_("Downloads")}}</a>
 -		</li>
 -{#		<li {{ selected('filemanager') }}>#}
 -{#		    <a href="/filemanager/" title=""><img src="/media/default/img/head-menu-download.png" alt="" /> {{_("FileManager")}}</a>#}
 -{#		</li>#}
 -		<li {{ selected('logs', True) }}>
 -		    <a href="/logs/"  class="action index" accesskey="x" rel="nofollow"><img src="/media/default/img/head-menu-index.png" alt="" />{{_("Logs")}}</a>
 -		</li>
 -		<li {{ selected('settings', True) }}>
 -		    <a href="/settings/"  class="action index" accesskey="x" rel="nofollow"><img src="/media/default/img/head-menu-config.png" alt="" />{{_("Config")}}</a>
 -		</li>
 -		{% endblock %}
 -		
 -		</ul>
 -	</div>
 -
 -	<div style="clear:both;"></div>
 -</div>
 -
 -{% if perms.STATUS %}
 -<ul id="page-actions2">
 -	<li id="action_play"><a href="#"  class="action play" accesskey="o" rel="nofollow">{{_("Start")}}</a></li>
 -    <li id="action_stop"><a href="#"  class="action stop" accesskey="o" rel="nofollow">{{_("Stop")}}</a></li>
 -    <li id="action_cancel"><a href="#"  class="action cancel" accesskey="o" rel="nofollow">{{_("Cancel")}}</a></li>
 -    <li id="action_add"><a href="#"  class="action add" accesskey="o" rel="nofollow" >{{_("Add")}}</a></li>
 -</ul>
 -{% endif %}
 -
 -{% if perms.LIST %}
 -<ul id="page-actions">
 -    <li><span class="time">{{_("Download:")}}</span><a id="time" style=" background-color: {% if status.download %}#8ffc25{% else %} #fc6e26{% endif %}; padding-left: 0cm; padding-right: 0.1cm; "> {% if status.download %}{{_("on")}}{% else %}{{_("off")}}{% endif %}</a></li>
 -    <li><span class="reconnect">{{_("Reconnect:")}}</span><a id="reconnect" style=" background-color: {% if status.reconnect %}#8ffc25{% else %} #fc6e26{% endif %}; padding-left: 0cm; padding-right: 0.1cm; "> {% if status.reconnect %}{{_("on")}}{% else %}{{_("off")}}{% endif %}</a></li>
 -    <li><a class="action backlink">{{_("Speed:")}} <b id="speed">{{ status.speed }}</b></a></li>
 -    <li><a class="action cog">{{_("Active:")}} <b id="aktiv" title="{{_("Active")}}">{{ status.active }}</b> / <b id="aktiv_from" title="{{_("Queued")}}">{{ status.queue }}</b> / <b id="aktiv_total" title="{{_("Total")}}">{{ status.total }}</b></a></li>
 -    <li><a href=""  class="action revisions" accesskey="o" rel="nofollow">{{_("Reload page")}}</a></li>
 -</ul>
 -{% endif %}
 -
 -{% block pageactions %}
 -{% endblock %}
 -<br/>
 -
 -<div id="body-wrapper" class="dokuwiki">
 -
 -<div id="content" lang="en" dir="ltr">
 -
 -<h1>{% block subtitle %}pyLoad - {{_("Webinterface")}}{% endblock %}</h1>
 -
 -{% block statusbar %}
 -{% endblock %}
 -
 -
 -<br/>
 -
 -<div class="level1" style="clear:both">
 -</div>
 -<noscript><h1>Enable JavaScript to use the webinterface.</h1></noscript>
 -
 -{% for message in messages %}
 -	<b><p>{{message}}</p></b>
 -{% endfor %}
 -
 -<div id="load-indicator" style="opacity: 0; float: right; margin-top: -10px;">
 -    <img src="/media/default/img/ajax-loader.gif" alt="" style="padding-right: 5px"/>
 -    {{_("loading")}}
 -</div>
 -
 -{% block content %}
 -{% endblock content %}
 -
 -	<hr style="clear: both;" />
 -
 -<div id="foot">© 2008-2011 pyLoad Team
 -<a href="#top" class="action top" accesskey="x"><span>{{_("Back to top")}}</span></a><br />
 -<!--<div class="breadcrumbs"></div>-->
 -
 -</div>
 -</div>
 -</div>
 -
 -<div style="display: none;">
 -    {% include "default/window.html" %}
 -    {% include "default/captcha.html" %}
 -    {% block hidden %}
 -    {% endblock %}
 -</div>
 -</body>
 -</html>
 +<?xml version="1.0" ?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" +    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> +<link rel="stylesheet" type="text/css" href="/media/default/css/default.css"/> +<link rel="stylesheet" type="text/css" href="/media/default/css/window.css"/> +<link rel="stylesheet" type="text/css" href="/media/default/css/MooDialog.css"/> + +<script type="text/javascript" src="/media/js/mootools-core-1.4.1.js"></script> +<script type="text/javascript" src="/media/js/mootools-more-1.4.0.1.js"></script> +<script type="text/javascript" src="/media/js/MooDialog_static.js"></script> +<script type="text/javascript" src="/media/js/purr_static.js"></script> + + +<script type="text/javascript" src="/media/js/base.js"></script> + +<title>{% block title %}pyLoad {{_("Webinterface")}}{% endblock %}</title> + +{% block head %} +{% endblock %} +</head> +<body> +<a class="anchor" name="top" id="top"></a> + +<div id="head-panel"> + + +    <div id="head-search-and-login"> +    {% block headpanel %} + +        {% if user.is_authenticated %} + + +{% if update %} +<span> +<span style="font-weight: bold; margin: 0 2px 0 2px;">{{_("pyLoad Update available!")}}</span> +</span> +{% endif %} + + +{% if plugins %} +<span> +<span style="font-weight: bold; margin: 0 2px 0 2px;">{{_("Plugins updated, please restart!")}}</span> +</span> +{% endif %} + +<span id="cap_info" style="display: {% if captcha %}inline{%else%}none{% endif %}"> +<img src="/media/default/img/images.png" alt="Captcha:" style="vertical-align:middle; margin:2px" /> +<span style="font-weight: bold; cursor: pointer; margin-right: 2px;">{{_("Captcha waiting")}}</span> +</span> + +    <img src="/media/default/img/head-login.png" alt="User:" style="vertical-align:middle; margin:2px" /><span style="padding-right: 2px;">{{user.name}}</span> +	<ul id="user-actions"> +		<li><a href="/logout"  class="action logout" rel="nofollow">{{_("Logout")}}</a></li> +		{% if user.is_admin %} +		<li><a href="/admin" class="action profile" rel="nofollow">{{_("Administrate")}}</a></li> +		{% endif %} +        <li><a href="/info"  class="action info" rel="nofollow">{{_("Info")}}</a></li> + +	</ul> +{% else %} +    <span style="padding-right: 2px;">{{_("Please Login!")}}</span> +{% endif %} + +    {% endblock %} +	</div> + +	<a href="/"><img id="head-logo" src="/media/default/img/pyload-logo-edited3.5-new-font-small.png" alt="pyLoad" /></a> + +	<div id="head-menu"> +		<ul> + +        {% macro selected(name, right=False) -%} +            {% if name in url -%}class="{% if right -%}right {% endif %}selected"{%- endif %} +            {% if not name in url and right -%}class="right"{%- endif %} +        {%- endmacro %} + + +		{% block menu %} +		<li> +		    <a href="/" title=""><img src="/media/default/img/head-menu-home.png" alt="" /> {{_("Home")}}</a> +		</li> +		<li {{ selected('queue') }}> +		    <a href="/queue/" title=""><img src="/media/default/img/head-menu-queue.png" alt="" /> {{_("Queue")}}</a> +		</li> +		<li {{ selected('collector') }}> +		    <a href="/collector/" title=""><img src="/media/default/img/head-menu-collector.png" alt="" /> {{_("Collector")}}</a> +		</li> +		<li {{ selected('downloads') }}> +		    <a href="/downloads/" title=""><img src="/media/default/img/head-menu-development.png" alt="" /> {{_("Downloads")}}</a> +		</li> +{#		<li {{ selected('filemanager') }}>#} +{#		    <a href="/filemanager/" title=""><img src="/media/default/img/head-menu-download.png" alt="" /> {{_("FileManager")}}</a>#} +{#		</li>#} +		<li {{ selected('logs', True) }}> +		    <a href="/logs/"  class="action index" accesskey="x" rel="nofollow"><img src="/media/default/img/head-menu-index.png" alt="" />{{_("Logs")}}</a> +		</li> +		<li {{ selected('settings', True) }}> +		    <a href="/settings/"  class="action index" accesskey="x" rel="nofollow"><img src="/media/default/img/head-menu-config.png" alt="" />{{_("Config")}}</a> +		</li> +		{% endblock %} +		 +		</ul> +	</div> + +	<div style="clear:both;"></div> +</div> + +{% if perms.STATUS %} +<ul id="page-actions2"> +	<li id="action_play"><a href="#"  class="action play" accesskey="o" rel="nofollow">{{_("Start")}}</a></li> +    <li id="action_stop"><a href="#"  class="action stop" accesskey="o" rel="nofollow">{{_("Stop")}}</a></li> +    <li id="action_cancel"><a href="#"  class="action cancel" accesskey="o" rel="nofollow">{{_("Cancel")}}</a></li> +    <li id="action_add"><a href="#"  class="action add" accesskey="o" rel="nofollow" >{{_("Add")}}</a></li> +</ul> +{% endif %} + +{% if perms.LIST %} +<ul id="page-actions"> +    <li><span class="time">{{_("Download:")}}</span><a id="time" style=" background-color: {% if status.download %}#8ffc25{% else %} #fc6e26{% endif %}; padding-left: 0cm; padding-right: 0.1cm; "> {% if status.download %}{{_("on")}}{% else %}{{_("off")}}{% endif %}</a></li> +    <li><span class="reconnect">{{_("Reconnect:")}}</span><a id="reconnect" style=" background-color: {% if status.reconnect %}#8ffc25{% else %} #fc6e26{% endif %}; padding-left: 0cm; padding-right: 0.1cm; "> {% if status.reconnect %}{{_("on")}}{% else %}{{_("off")}}{% endif %}</a></li> +    <li><a class="action backlink">{{_("Speed:")}} <b id="speed">{{ status.speed }}</b></a></li> +    <li><a class="action cog">{{_("Active:")}} <b id="aktiv" title="{{_("Active")}}">{{ status.active }}</b> / <b id="aktiv_from" title="{{_("Queued")}}">{{ status.queue }}</b> / <b id="aktiv_total" title="{{_("Total")}}">{{ status.total }}</b></a></li> +    <li><a href=""  class="action revisions" accesskey="o" rel="nofollow">{{_("Reload page")}}</a></li> +</ul> +{% endif %} + +{% block pageactions %} +{% endblock %} +<br/> + +<div id="body-wrapper" class="dokuwiki"> + +<div id="content" lang="en" dir="ltr"> + +<h1>{% block subtitle %}pyLoad - {{_("Webinterface")}}{% endblock %}</h1> + +{% block statusbar %} +{% endblock %} + + +<br/> + +<div class="level1" style="clear:both"> +</div> +<noscript><h1>Enable JavaScript to use the webinterface.</h1></noscript> + +{% for message in messages %} +	<b><p>{{message}}</p></b> +{% endfor %} + +<div id="load-indicator" style="opacity: 0; float: right; margin-top: -10px;"> +    <img src="/media/default/img/ajax-loader.gif" alt="" style="padding-right: 5px"/> +    {{_("loading")}} +</div> + +{% block content %} +{% endblock content %} + +	<hr style="clear: both;" /> + +<div id="foot">© 2008-2011 pyLoad Team +<a href="#top" class="action top" accesskey="x"><span>{{_("Back to top")}}</span></a><br /> +<!--<div class="breadcrumbs"></div>--> + +</div> +</div> +</div> + +<div style="display: none;"> +    {% include "default/window.html" %} +    {% include "default/captcha.html" %} +    {% block hidden %} +    {% endblock %} +</div> +</body> +</html> diff --git a/module/web/templates/default/captcha.html b/module/web/templates/default/captcha.html index 332a9c102..288375b76 100644 --- a/module/web/templates/default/captcha.html +++ b/module/web/templates/default/captcha.html @@ -1,42 +1,42 @@ -<!-- Captcha box -->
 -<div id="cap_box" class="window_box">
 -
 -	<form id="cap_form" action="/json/set_captcha" method="POST" enctype="multipart/form-data" onsubmit="return false;">
 -	
 -		<h1>{{_("Captcha reading")}}</h1>
 -		<p id="cap_title">{{_("Please read the text on the captcha.")}}</p>
 -		
 -		<div id="cap_textual">
 -		
 -			<input id="cap_id" name="cap_id" type="hidden" value="" />
 -		
 -			<label>{{_("Captcha")}}
 -			<span class="small">{{_("The captcha.")}}</span>
 -			</label>
 -			<span class="cont">
 -			    <img id="cap_textual_img" src="">
 -			</span>
 -			
 -			<label>{{_("Text")}}
 -			<span class="small">{{_("Input the text on the captcha.")}}</span>
 -			</label>
 -			<input id="cap_result" name="cap_result" type="text" size="20" />
 -					
 -		</div>
 -		
 -		<div id="cap_positional" style="text-align: center">
 -		    <img id="cap_positional_img" src="" style="margin: 10px; cursor:pointer">
 -		</div>
 -
 -		<div id="button_bar" style="text-align: center">
 -			<span>
 -				<button id="cap_submit" type="submit" style="margin-left: 0">{{_("Submit")}}</button>
 -				<button id="cap_reset" type="reset" style="margin-left: 0">{{_("Close")}}</button>
 -			</span>
 -		</div>
 -		
 -		<div class="spacer"></div>
 -	
 -	</form>
 -
 +<!-- Captcha box --> +<div id="cap_box" class="window_box"> + +	<form id="cap_form" action="/json/set_captcha" method="POST" enctype="multipart/form-data" onsubmit="return false;"> +	 +		<h1>{{_("Captcha reading")}}</h1> +		<p id="cap_title">{{_("Please read the text on the captcha.")}}</p> +		 +		<div id="cap_textual"> +		 +			<input id="cap_id" name="cap_id" type="hidden" value="" /> +		 +			<label>{{_("Captcha")}} +			<span class="small">{{_("The captcha.")}}</span> +			</label> +			<span class="cont"> +			    <img id="cap_textual_img" src=""> +			</span> +			 +			<label>{{_("Text")}} +			<span class="small">{{_("Input the text on the captcha.")}}</span> +			</label> +			<input id="cap_result" name="cap_result" type="text" size="20" /> +					 +		</div> +		 +		<div id="cap_positional" style="text-align: center"> +		    <img id="cap_positional_img" src="" style="margin: 10px; cursor:pointer"> +		</div> + +		<div id="button_bar" style="text-align: center"> +			<span> +				<button id="cap_submit" type="submit" style="margin-left: 0">{{_("Submit")}}</button> +				<button id="cap_reset" type="reset" style="margin-left: 0">{{_("Close")}}</button> +			</span> +		</div> +		 +		<div class="spacer"></div> +	 +	</form> +  </div>
\ No newline at end of file diff --git a/module/web/templates/default/home.html b/module/web/templates/default/home.html index 0efb1bcf8..7359e326c 100644 --- a/module/web/templates/default/home.html +++ b/module/web/templates/default/home.html @@ -1,266 +1,266 @@ -{% extends 'default/base.html' %}
 -{% block head %}
 -
 -<script type="text/javascript">
 -
 -var em;
 -var operafix = (navigator.userAgent.toLowerCase().search("opera") >= 0);
 -
 -document.addEvent("domready", function(){
 -	em = new EntryManager();
 -});
 -
 -var EntryManager = new Class({
 -    initialize: function(){
 -        this.json = new Request.JSON({
 -		url: "json/links",
 -                secure: false,
 -                async: true,
 -		onSuccess: this.update.bind(this),
 -		initialDelay: 0,
 -		delay: 2500,
 -		limit: 30000
 -	});
 -	
 -        this.ids = [{% for link in content %}
 -        {% if forloop.last %}
 -            {{ link.id }}
 -        {% else %}
 -         {{ link.id }},
 -        {% endif %}
 -        {% endfor %}];
 -        
 -        this.entries = [];
 -        this.container = $('LinksAktiv');
 -        
 -        this.parseFromContent();
 -            
 -        this.json.startTimer();
 -    },
 -    parseFromContent: function(){
 -        this.ids.each(function(id,index){
 -            var entry = new LinkEntry(id);
 -            entry.parse();
 -            this.entries.push(entry)
 -            }, this);
 -    },
 -    update: function(data){
 -        
 -        try{
 -        this.ids = this.entries.map(function(item){
 -            return item.fid
 -            });
 -        
 -        this.ids.filter(function(id){
 -            return !this.ids.contains(id)
 -        },data).each(function(id){
 -            var index = this.ids.indexOf(id);
 -            this.entries[index].remove();
 -            this.entries = this.entries.filter(function(item){return item.fid != this},id);
 -            this.ids = this.ids.erase(id)
 -            }, this);
 -        
 -        data.links.each(function(link, i){
 -            if (this.ids.contains(link.fid)){
 -                
 -                var index = this.ids.indexOf(link.fid);
 -                this.entries[index].update(link)
 -            
 -            }else{
 -                var entry = new LinkEntry(link.fid);
 -                entry.insert(link);
 -                this.entries.push(entry);
 -                this.ids.push(link.fid);
 -                this.container.adopt(entry.elements.tr,entry.elements.pgbTr);
 -                entry.fade.start('opacity', 1);
 -                entry.fadeBar.start('opacity', 1);
 -                
 -            }
 -            }, this)
 -        }catch(e){
 -            //alert(e)
 -        }
 -    }
 -});
 -
 -
 -var LinkEntry = new Class({
 -        initialize: function(id){
 -            this.fid = id;
 -            this.id = id;
 -        },
 -        parse: function(){
 -            this.elements = {
 -                tr: $("link_{id}".substitute({id: this.id})),
 -                name: $("link_{id}_name".substitute({id: this.id})),
 -                status: $("link_{id}_status".substitute({id: this.id})),
 -                info: $("link_{id}_info".substitute({id: this.id})),
 -                bleft: $("link_{id}_bleft".substitute({id: this.id})),
 -                percent: $("link_{id}_percent".substitute({id: this.id})),
 -                remove: $("link_{id}_remove".substitute({id: this.id})),
 -                pgbTr: $("link_{id}_pgb_tr".substitute({id: this.id})),
 -                pgb: $("link_{id}_pgb".substitute({id: this.id}))
 -            };
 -            this.initEffects();
 -        },
 -        insert: function(item){
 -            try{
 -
 -            this.elements = {
 -                tr: new Element('tr', {
 -                'html': '',
 -                'styles':{
 -                    'opacity': 0
 -                }
 -                }),
 -                name: new Element('td', {
 -                'html': item.name
 -                }),
 -                status: new Element('td', {
 -                'html': item.statusmsg
 -                }),
 -                info: new Element('td', {
 -                'html': item.info
 -                }),
 -                bleft: new Element('td', {
 -                'html': humanFileSize(item.size)
 -                }),
 -                percent: new Element('span', {
 -                'html': item.percent+ '% / '+ humanFileSize(item.size-item.bleft)
 -                }),
 -                remove: new Element('img',{
 -                'src': 'media/default/img/control_cancel.png',
 -                'styles':{
 -                    'vertical-align': 'middle',
 -                    'margin-right': '-20px',
 -                    'margin-left': '5px',
 -                    'margin-top': '-2px',
 -                    'cursor': 'pointer'
 -                }
 -                }),
 -                pgbTr: new Element('tr', {
 -                'html':''
 -                }),
 -                pgb: new Element('div', {
 -                'html': ' ',
 -                'styles':{
 -                    'height': '4px',
 -                    'width': item.percent+'%',
 -                    'background-color': '#ddd'
 -                }
 -                })
 -            };
 -            
 -            this.elements.tr.adopt(this.elements.name,this.elements.status,this.elements.info,this.elements.bleft,new Element('td').adopt(this.elements.percent,this.elements.remove));
 -            this.elements.pgbTr.adopt(new Element('td',{'colspan':5}).adopt(this.elements.pgb));
 -            this.initEffects();
 -            }catch(e){
 -                alert(e)
 -            }
 -        },
 -        initEffects: function(){
 -            if(!operafix)
 -                this.bar = new Fx.Morph(this.elements.pgb, {unit: '%', duration: 5000, link: 'link', fps:30});
 -            this.fade = new Fx.Tween(this.elements.tr);
 -            this.fadeBar = new Fx.Tween(this.elements.pgbTr);
 -            
 -            this.elements.remove.addEvent('click', function(){
 -                new Request({method: 'get', url: '/json/abort_link/'+this.id}).send();
 -            }.bind(this));
 -            
 -        },
 -        update: function(item){
 -                this.elements.name.set('text', item.name);
 -                this.elements.status.set('text', item.statusmsg);
 -                this.elements.info.set('text', item.info);
 -                this.elements.bleft.set('text', item.format_size);
 -                this.elements.percent.set('text', item.percent+ '% / '+ humanFileSize(item.size-item.bleft));
 -                if(!operafix)
 -                {
 -                    this.bar.start({
 -                        'width': item.percent,
 -                        'background-color': [Math.round(120/100*item.percent),100,100].hsbToRgb().rgbToHex()
 -                    });
 -                }
 -                else
 -                {
 -                    this.elements.pgb.set(
 -                        'styles', {
 -                            'height': '4px',
 -                            'width': item.percent+'%',
 -                            'background-color': [Math.round(120/100*item.percent),100,100].hsbToRgb().rgbToHex(),
 -                         });
 -                }
 -        },
 -        remove: function(){
 -                this.fade.start('opacity',0).chain(function(){this.elements.tr.dispose();}.bind(this));
 -                this.fadeBar.start('opacity',0).chain(function(){this.elements.pgbTr.dispose();}.bind(this));
 -
 -        }
 -    });
 -</script>
 -
 -{% endblock %}
 -
 -{% block subtitle %}
 -{{_("Active Downloads")}}
 -{% endblock %}
 -
 -{% block menu %}
 -<li class="selected">
 -    <a href="/" title=""><img src="/media/default/img/head-menu-home.png" alt="" /> {{_("Home")}}</a>
 -</li>
 -<li>
 -    <a href="/queue/" title=""><img src="/media/default/img/head-menu-queue.png" alt="" /> {{_("Queue")}}</a>
 -</li>
 -<li>
 -    <a href="/collector/" title=""><img src="/media/default/img/head-menu-collector.png" alt="" /> {{_("Collector")}}</a>
 -</li>
 -<li>
 -    <a href="/downloads/" title=""><img src="/media/default/img/head-menu-development.png" alt="" /> {{_("Downloads")}}</a>
 -</li>
 -{#<li>#}
 -{#    <a href="/filemanager/" title=""><img src="/media/default/img/head-menu-download.png" alt="" /> {{_("FileManager")}}</a>#}
 -{#</li>#}
 -<li class="right">
 -    <a href="/logs/"  class="action index" accesskey="x" rel="nofollow"><img src="/media/default/img/head-menu-index.png" alt="" />{{_("Logs")}}</a>
 -</li>
 -<li class="right">
 -    <a href="/settings/"  class="action index" accesskey="x" rel="nofollow"><img src="/media/default/img/head-menu-config.png" alt="" />{{_("Config")}}</a>
 -</li>
 -{% endblock %}
 -
 -{% block content %}
 -<table width="100%" class="queue">
 -    <thead>
 -  <tr class="header">
 -    <th>{{_("Name")}}</th>
 -    <th>{{_("Status")}}</th>
 -    <th>{{_("Information")}}</th>
 -    <th>{{_("Size")}}</th>
 -    <th>{{_("Progress")}}</th>
 -  </tr>
 -    </thead>
 -  <tbody id="LinksAktiv">
 -  
 -  {% for link in content %}
 -  <tr id="link_{{ link.id }}">
 -    <td id="link_{{ link.id }}_name">{{ link.name }}</td>
 -    <td id="link_{{ link.id }}_status">{{ link.status }}</td>
 -    <td id="link_{{ link.id }}_info">{{ link.info }}</td>
 -    <td id="link_{{ link.id }}_bleft">{{ link.format_size }}</td>
 -    <td>
 -        <span id="link_{{ link.id }}_percent">{{ link.percent }}% /{{ link.bleft }}</span>
 -        <img id="link_{{ link.id }}_remove" style="vertical-align: middle; margin-right: -20px; margin-left: 5px; margin-top: -2px; cursor:pointer;" src="media/default/img/control_cancel.png"/>
 -    </td>
 -  </tr>
 -  <tr id="link_{{ link.id }}_pgb_tr">
 -    <td colspan="5">
 -        <div id="link_{{ link.id }}_pgb" class="progressBar" style="background-color: green; height:4px; width: {{ link.percent }}%;"> </div>
 -    </td>
 -  </tr>
 -  {% endfor %}
 -  
 -  </tbody>
 -</table>
 +{% extends 'default/base.html' %} +{% block head %} + +<script type="text/javascript"> + +var em; +var operafix = (navigator.userAgent.toLowerCase().search("opera") >= 0); + +document.addEvent("domready", function(){ +	em = new EntryManager(); +}); + +var EntryManager = new Class({ +    initialize: function(){ +        this.json = new Request.JSON({ +		url: "json/links", +                secure: false, +                async: true, +		onSuccess: this.update.bind(this), +		initialDelay: 0, +		delay: 2500, +		limit: 30000 +	}); +	 +        this.ids = [{% for link in content %} +        {% if forloop.last %} +            {{ link.id }} +        {% else %} +         {{ link.id }}, +        {% endif %} +        {% endfor %}]; +         +        this.entries = []; +        this.container = $('LinksAktiv'); +         +        this.parseFromContent(); +             +        this.json.startTimer(); +    }, +    parseFromContent: function(){ +        this.ids.each(function(id,index){ +            var entry = new LinkEntry(id); +            entry.parse(); +            this.entries.push(entry) +            }, this); +    }, +    update: function(data){ +         +        try{ +        this.ids = this.entries.map(function(item){ +            return item.fid +            }); +         +        this.ids.filter(function(id){ +            return !this.ids.contains(id) +        },data).each(function(id){ +            var index = this.ids.indexOf(id); +            this.entries[index].remove(); +            this.entries = this.entries.filter(function(item){return item.fid != this},id); +            this.ids = this.ids.erase(id) +            }, this); +         +        data.links.each(function(link, i){ +            if (this.ids.contains(link.fid)){ +                 +                var index = this.ids.indexOf(link.fid); +                this.entries[index].update(link) +             +            }else{ +                var entry = new LinkEntry(link.fid); +                entry.insert(link); +                this.entries.push(entry); +                this.ids.push(link.fid); +                this.container.adopt(entry.elements.tr,entry.elements.pgbTr); +                entry.fade.start('opacity', 1); +                entry.fadeBar.start('opacity', 1); +                 +            } +            }, this) +        }catch(e){ +            //alert(e) +        } +    } +}); + + +var LinkEntry = new Class({ +        initialize: function(id){ +            this.fid = id; +            this.id = id; +        }, +        parse: function(){ +            this.elements = { +                tr: $("link_{id}".substitute({id: this.id})), +                name: $("link_{id}_name".substitute({id: this.id})), +                status: $("link_{id}_status".substitute({id: this.id})), +                info: $("link_{id}_info".substitute({id: this.id})), +                bleft: $("link_{id}_bleft".substitute({id: this.id})), +                percent: $("link_{id}_percent".substitute({id: this.id})), +                remove: $("link_{id}_remove".substitute({id: this.id})), +                pgbTr: $("link_{id}_pgb_tr".substitute({id: this.id})), +                pgb: $("link_{id}_pgb".substitute({id: this.id})) +            }; +            this.initEffects(); +        }, +        insert: function(item){ +            try{ + +            this.elements = { +                tr: new Element('tr', { +                'html': '', +                'styles':{ +                    'opacity': 0 +                } +                }), +                name: new Element('td', { +                'html': item.name +                }), +                status: new Element('td', { +                'html': item.statusmsg +                }), +                info: new Element('td', { +                'html': item.info +                }), +                bleft: new Element('td', { +                'html': humanFileSize(item.size) +                }), +                percent: new Element('span', { +                'html': item.percent+ '% / '+ humanFileSize(item.size-item.bleft) +                }), +                remove: new Element('img',{ +                'src': 'media/default/img/control_cancel.png', +                'styles':{ +                    'vertical-align': 'middle', +                    'margin-right': '-20px', +                    'margin-left': '5px', +                    'margin-top': '-2px', +                    'cursor': 'pointer' +                } +                }), +                pgbTr: new Element('tr', { +                'html':'' +                }), +                pgb: new Element('div', { +                'html': ' ', +                'styles':{ +                    'height': '4px', +                    'width': item.percent+'%', +                    'background-color': '#ddd' +                } +                }) +            }; +             +            this.elements.tr.adopt(this.elements.name,this.elements.status,this.elements.info,this.elements.bleft,new Element('td').adopt(this.elements.percent,this.elements.remove)); +            this.elements.pgbTr.adopt(new Element('td',{'colspan':5}).adopt(this.elements.pgb)); +            this.initEffects(); +            }catch(e){ +                alert(e) +            } +        }, +        initEffects: function(){ +            if(!operafix) +                this.bar = new Fx.Morph(this.elements.pgb, {unit: '%', duration: 5000, link: 'link', fps:30}); +            this.fade = new Fx.Tween(this.elements.tr); +            this.fadeBar = new Fx.Tween(this.elements.pgbTr); +             +            this.elements.remove.addEvent('click', function(){ +                new Request({method: 'get', url: '/json/abort_link/'+this.id}).send(); +            }.bind(this)); +             +        }, +        update: function(item){ +                this.elements.name.set('text', item.name); +                this.elements.status.set('text', item.statusmsg); +                this.elements.info.set('text', item.info); +                this.elements.bleft.set('text', item.format_size); +                this.elements.percent.set('text', item.percent+ '% / '+ humanFileSize(item.size-item.bleft)); +                if(!operafix) +                { +                    this.bar.start({ +                        'width': item.percent, +                        'background-color': [Math.round(120/100*item.percent),100,100].hsbToRgb().rgbToHex() +                    }); +                } +                else +                { +                    this.elements.pgb.set( +                        'styles', { +                            'height': '4px', +                            'width': item.percent+'%', +                            'background-color': [Math.round(120/100*item.percent),100,100].hsbToRgb().rgbToHex(), +                         }); +                } +        }, +        remove: function(){ +                this.fade.start('opacity',0).chain(function(){this.elements.tr.dispose();}.bind(this)); +                this.fadeBar.start('opacity',0).chain(function(){this.elements.pgbTr.dispose();}.bind(this)); + +        } +    }); +</script> + +{% endblock %} + +{% block subtitle %} +{{_("Active Downloads")}} +{% endblock %} + +{% block menu %} +<li class="selected"> +    <a href="/" title=""><img src="/media/default/img/head-menu-home.png" alt="" /> {{_("Home")}}</a> +</li> +<li> +    <a href="/queue/" title=""><img src="/media/default/img/head-menu-queue.png" alt="" /> {{_("Queue")}}</a> +</li> +<li> +    <a href="/collector/" title=""><img src="/media/default/img/head-menu-collector.png" alt="" /> {{_("Collector")}}</a> +</li> +<li> +    <a href="/downloads/" title=""><img src="/media/default/img/head-menu-development.png" alt="" /> {{_("Downloads")}}</a> +</li> +{#<li>#} +{#    <a href="/filemanager/" title=""><img src="/media/default/img/head-menu-download.png" alt="" /> {{_("FileManager")}}</a>#} +{#</li>#} +<li class="right"> +    <a href="/logs/"  class="action index" accesskey="x" rel="nofollow"><img src="/media/default/img/head-menu-index.png" alt="" />{{_("Logs")}}</a> +</li> +<li class="right"> +    <a href="/settings/"  class="action index" accesskey="x" rel="nofollow"><img src="/media/default/img/head-menu-config.png" alt="" />{{_("Config")}}</a> +</li> +{% endblock %} + +{% block content %} +<table width="100%" class="queue"> +    <thead> +  <tr class="header"> +    <th>{{_("Name")}}</th> +    <th>{{_("Status")}}</th> +    <th>{{_("Information")}}</th> +    <th>{{_("Size")}}</th> +    <th>{{_("Progress")}}</th> +  </tr> +    </thead> +  <tbody id="LinksAktiv"> +   +  {% for link in content %} +  <tr id="link_{{ link.id }}"> +    <td id="link_{{ link.id }}_name">{{ link.name }}</td> +    <td id="link_{{ link.id }}_status">{{ link.status }}</td> +    <td id="link_{{ link.id }}_info">{{ link.info }}</td> +    <td id="link_{{ link.id }}_bleft">{{ link.format_size }}</td> +    <td> +        <span id="link_{{ link.id }}_percent">{{ link.percent }}% /{{ link.bleft }}</span> +        <img id="link_{{ link.id }}_remove" style="vertical-align: middle; margin-right: -20px; margin-left: 5px; margin-top: -2px; cursor:pointer;" src="media/default/img/control_cancel.png"/> +    </td> +  </tr> +  <tr id="link_{{ link.id }}_pgb_tr"> +    <td colspan="5"> +        <div id="link_{{ link.id }}_pgb" class="progressBar" style="background-color: green; height:4px; width: {{ link.percent }}%;"> </div> +    </td> +  </tr> +  {% endfor %} +   +  </tbody> +</table>  {% endblock %}
\ No newline at end of file diff --git a/module/web/templates/default/queue.html b/module/web/templates/default/queue.html index c88fa3568..046abbe49 100644 --- a/module/web/templates/default/queue.html +++ b/module/web/templates/default/queue.html @@ -1,104 +1,104 @@ -{% extends 'default/base.html' %}
 -{% block head %}
 -
 -<script type="text/javascript" src="/media/js/package_ui.js"></script>
 -
 -<script type="text/javascript">
 -
 -document.addEvent("domready", function(){
 -    var pUI = new PackageUI("url", {{ target }});
 -});
 -</script>
 -{% endblock %}
 -
 -{% if target %}
 -    {% set name = _("Queue") %}
 -{% else %}
 -    {% set name = _("Collector") %}
 -{% endif %}
 -
 -{% block title %}{{name}} - {{super()}} {% endblock %}
 -{% block subtitle %}{{name}}{% endblock %}
 -
 -{% block pageactions %}
 -<ul id="page-actions-more">
 -    <li id="del_finished"><a style="padding: 0; font-weight: bold;" href="#">{{_("Delete Finished")}}</a></li>
 -    <li id="restart_failed"><a style="padding: 0; font-weight: bold;" href="#">{{_("Restart Failed")}}</a></li>
 -</ul>
 -{% endblock %}
 -
 -{% block content %}
 -{% autoescape true %}
 -
 -<ul id="package-list" style="list-style: none; padding-left: 0; margin-top: -10px;">
 -{% for package in content %}
 -    <li>
 -<div id="package_{{package.pid}}" class="package">
 -    <div class="order" style="display: none;">{{ package.order }}</div>
 -    
 -    <div class="packagename" style="cursor: pointer">
 -        <img class="package_drag" src="/media/default/img/folder.png" style="cursor: move; margin-bottom: -2px">
 -        <span class="name">{{package.name}}</span>
 -          
 -        <span class="buttons" style="opacity:0">
 -        <img title="{{_("Delete Package")}}" style="cursor: pointer" width="12px" height="12px" src="/media/default/img/delete.png" />
 -          
 -        <img title="{{_("Restart Package")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/media/default/img/arrow_refresh.png" />
 -          
 -        <img title="{{_("Edit Package")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/media/default/img/pencil.png" />
 -          
 -        <img title="{{_("Move Package")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/media/default/img/package_go.png" />
 -        </span>
 -    </div>
 -    {% set progress = (package.linksdone * 100) / package.linkstotal %}
 -
 -    <div id="progress" style="border-radius: 4px; border: 1px solid #AAAAAA; width: 50%; height: 1em">
 -        <div style="width: {{ progress }}%; height: 100%; background-color: #add8e6;"></div>
 -        <label style="font-size: 0.8em; font-weight: bold; padding-left: 5px; position: relative; top: -17px">
 -        {{ package.sizedone|formatsize }} / {{ package.sizetotal|formatsize }}</label>
 -        <label style="font-size: 0.8em; font-weight: bold; padding-right: 5px ;float: right; position: relative; top: -17px">
 -        {{ package.linksdone }} / {{ package.linkstotal }}</label>
 -        </div>
 -    <div style="clear: both; margin-bottom: -10px"></div>
 -
 -    <div id="children_{{package.pid}}" style="display: none;" class="children">
 -    <span class="child_secrow">{{_("Folder:")}} <span class="folder">{{package.folder}}</span> | {{_("Password:")}} <span class="password">{{package.password}}</span></span>
 -    <ul id="sort_children_{{package.pid}}" style="list-style: none; padding-left: 0">
 -    </ul>
 -    </div>
 -</div>
 -    </li>
 -{% endfor %}
 -</ul>
 -{% endautoescape %}
 -{% endblock %}
 -
 -{% block hidden %}
 -<div id="pack_box" class="window_box" style="z-index: 2">
 -    <form id="pack_form" action="/json/edit_package" method="POST" enctype="multipart/form-data">
 -    <h1>{{_("Edit Package")}}</h1>
 -    <p>{{_("Edit the package detais below.")}}</p>
 -    <input name="pack_id" id="pack_id" type="hidden" value=""/>
 -    <label for="pack_name">{{_("Name")}}
 -    <span class="small">{{_("The name of the package.")}}</span>
 -    </label>
 -    <input id="pack_name" name="pack_name" type="text" size="20" />
 -
 -    <label for="pack_folder">{{_("Folder")}}
 -    <span class="small">{{_("Name of subfolder for these downloads.")}}</span>
 -    </label>
 -    <input id="pack_folder" name="pack_folder" type="text" size="20" />
 -
 -    <label for="pack_pws">{{_("Password")}}
 -    <span class="small">{{_("List of passwords used for unrar.")}}</span>
 -    </label>
 -    <textarea rows="3" name="pack_pws" id="pack_pws"></textarea>
 -
 -    <button type="submit">{{_("Submit")}}</button>
 -    <button id="pack_reset" style="margin-left: 0" type="reset" >{{_("Reset")}}</button>
 -    <div class="spacer"></div>
 -
 -    </form>
 -
 -</div>
 +{% extends 'default/base.html' %} +{% block head %} + +<script type="text/javascript" src="/media/js/package_ui.js"></script> + +<script type="text/javascript"> + +document.addEvent("domready", function(){ +    var pUI = new PackageUI("url", {{ target }}); +}); +</script> +{% endblock %} + +{% if target %} +    {% set name = _("Queue") %} +{% else %} +    {% set name = _("Collector") %} +{% endif %} + +{% block title %}{{name}} - {{super()}} {% endblock %} +{% block subtitle %}{{name}}{% endblock %} + +{% block pageactions %} +<ul id="page-actions-more"> +    <li id="del_finished"><a style="padding: 0; font-weight: bold;" href="#">{{_("Delete Finished")}}</a></li> +    <li id="restart_failed"><a style="padding: 0; font-weight: bold;" href="#">{{_("Restart Failed")}}</a></li> +</ul> +{% endblock %} + +{% block content %} +{% autoescape true %} + +<ul id="package-list" style="list-style: none; padding-left: 0; margin-top: -10px;"> +{% for package in content %} +    <li> +<div id="package_{{package.pid}}" class="package"> +    <div class="order" style="display: none;">{{ package.order }}</div> +     +    <div class="packagename" style="cursor: pointer"> +        <img class="package_drag" src="/media/default/img/folder.png" style="cursor: move; margin-bottom: -2px"> +        <span class="name">{{package.name}}</span> +           +        <span class="buttons" style="opacity:0"> +        <img title="{{_("Delete Package")}}" style="cursor: pointer" width="12px" height="12px" src="/media/default/img/delete.png" /> +           +        <img title="{{_("Restart Package")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/media/default/img/arrow_refresh.png" /> +           +        <img title="{{_("Edit Package")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/media/default/img/pencil.png" /> +           +        <img title="{{_("Move Package")}}" style="margin-left: -10px; cursor: pointer" height="12px" src="/media/default/img/package_go.png" /> +        </span> +    </div> +    {% set progress = (package.linksdone * 100) / package.linkstotal %} + +    <div id="progress" style="border-radius: 4px; border: 1px solid #AAAAAA; width: 50%; height: 1em"> +        <div style="width: {{ progress }}%; height: 100%; background-color: #add8e6;"></div> +        <label style="font-size: 0.8em; font-weight: bold; padding-left: 5px; position: relative; top: -17px"> +        {{ package.sizedone|formatsize }} / {{ package.sizetotal|formatsize }}</label> +        <label style="font-size: 0.8em; font-weight: bold; padding-right: 5px ;float: right; position: relative; top: -17px"> +        {{ package.linksdone }} / {{ package.linkstotal }}</label> +        </div> +    <div style="clear: both; margin-bottom: -10px"></div> + +    <div id="children_{{package.pid}}" style="display: none;" class="children"> +    <span class="child_secrow">{{_("Folder:")}} <span class="folder">{{package.folder}}</span> | {{_("Password:")}} <span class="password">{{package.password}}</span></span> +    <ul id="sort_children_{{package.pid}}" style="list-style: none; padding-left: 0"> +    </ul> +    </div> +</div> +    </li> +{% endfor %} +</ul> +{% endautoescape %} +{% endblock %} + +{% block hidden %} +<div id="pack_box" class="window_box" style="z-index: 2"> +    <form id="pack_form" action="/json/edit_package" method="POST" enctype="multipart/form-data"> +    <h1>{{_("Edit Package")}}</h1> +    <p>{{_("Edit the package detais below.")}}</p> +    <input name="pack_id" id="pack_id" type="hidden" value=""/> +    <label for="pack_name">{{_("Name")}} +    <span class="small">{{_("The name of the package.")}}</span> +    </label> +    <input id="pack_name" name="pack_name" type="text" size="20" /> + +    <label for="pack_folder">{{_("Folder")}} +    <span class="small">{{_("Name of subfolder for these downloads.")}}</span> +    </label> +    <input id="pack_folder" name="pack_folder" type="text" size="20" /> + +    <label for="pack_pws">{{_("Password")}} +    <span class="small">{{_("List of passwords used for unrar.")}}</span> +    </label> +    <textarea rows="3" name="pack_pws" id="pack_pws"></textarea> + +    <button type="submit">{{_("Submit")}}</button> +    <button id="pack_reset" style="margin-left: 0" type="reset" >{{_("Reset")}}</button> +    <div class="spacer"></div> + +    </form> + +</div>  {% endblock %}
\ No newline at end of file diff --git a/module/web/templates/default/window.html b/module/web/templates/default/window.html index b61fa7149..a11323fe0 100644 --- a/module/web/templates/default/window.html +++ b/module/web/templates/default/window.html @@ -1,46 +1,46 @@ -<iframe id="upload_target" name="upload_target" src="" style="display: none; width:0;height:0"></iframe>
 -
 -<div id="add_box" class="window_box">
 -<form id="add_form" action="/json/add_package" method="POST" enctype="multipart/form-data">
 -<h1>{{_("Add Package")}}</h1>
 -<p>{{_("Paste your links or upload a container.")}}</p>
 -<label for="add_name">{{_("Name")}}
 -<span class="small">{{_("The name of the new package.")}}</span>
 -</label>
 -<input id="add_name" name="add_name" type="text" size="20" />
 -
 -<label for="add_links">{{_("Links")}}
 -<span class="small">{{_("Paste your links here or any text and press the filter button.")}}</span>
 -<span class="small"> {{ _("Filter urls") }}
 -<img alt="URIParsing" Title="Parse Uri" src="/media/default/img/parseUri.png" style="cursor:pointer; vertical-align: text-bottom;" onclick="parseUri()"/>
 -</span>
 -
 -</label>
 -<textarea rows="5" name="add_links" id="add_links"></textarea>
 -
 -<label for="add_password">{{_("Password")}}
 -    <span class="small">{{_("Password for RAR-Archive")}}</span>
 -</label>
 -<input id="add_password" name="add_password" type="text" size="20">
 -
 -<label>{{_("File")}}
 -<span class="small">{{_("Upload a container.")}}</span>
 -</label>
 -<input type="file" name="add_file" id="add_file"/>
 -
 -<label for="add_dest">{{_("Destination")}}
 -</label>
 -<span class="cont">
 -    {{_("Queue")}}
 -    <input type="radio" name="add_dest" id="add_dest" value="1" checked="checked"/>
 -    {{_("Collector")}}
 -    <input type="radio" name="add_dest" id="add_dest2" value="0"/>
 -</span>
 -
 -<button type="submit">{{_("Add Package")}}</button>
 -<button id="add_reset" style="margin-left:0;" type="reset">{{_("Reset")}}</button>
 -<div class="spacer"></div>
 -
 -</form>
 -
 +<iframe id="upload_target" name="upload_target" src="" style="display: none; width:0;height:0"></iframe> + +<div id="add_box" class="window_box"> +<form id="add_form" action="/json/add_package" method="POST" enctype="multipart/form-data"> +<h1>{{_("Add Package")}}</h1> +<p>{{_("Paste your links or upload a container.")}}</p> +<label for="add_name">{{_("Name")}} +<span class="small">{{_("The name of the new package.")}}</span> +</label> +<input id="add_name" name="add_name" type="text" size="20" /> + +<label for="add_links">{{_("Links")}} +<span class="small">{{_("Paste your links here or any text and press the filter button.")}}</span> +<span class="small"> {{ _("Filter urls") }} +<img alt="URIParsing" Title="Parse Uri" src="/media/default/img/parseUri.png" style="cursor:pointer; vertical-align: text-bottom;" onclick="parseUri()"/> +</span> + +</label> +<textarea rows="5" name="add_links" id="add_links"></textarea> + +<label for="add_password">{{_("Password")}} +    <span class="small">{{_("Password for RAR-Archive")}}</span> +</label> +<input id="add_password" name="add_password" type="text" size="20"> + +<label>{{_("File")}} +<span class="small">{{_("Upload a container.")}}</span> +</label> +<input type="file" name="add_file" id="add_file"/> + +<label for="add_dest">{{_("Destination")}} +</label> +<span class="cont"> +    {{_("Queue")}} +    <input type="radio" name="add_dest" id="add_dest" value="1" checked="checked"/> +    {{_("Collector")}} +    <input type="radio" name="add_dest" id="add_dest2" value="0"/> +</span> + +<button type="submit">{{_("Add Package")}}</button> +<button id="add_reset" style="margin-left:0;" type="reset">{{_("Reset")}}</button> +<div class="spacer"></div> + +</form> +  </div>
\ No newline at end of file | 
