From 304a42b914cde43a31a935181b0f952c726eee54 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 12 May 2015 14:03:56 +0200 Subject: Other import fixes (2) --- pyload/Database/User.py | 10 +- pyload/Thread/Addon.py | 3 - pyload/Thread/Decrypter.py | 3 - pyload/Thread/Download.py | 3 - pyload/Thread/Info.py | 3 - pyload/Thread/Plugin.py | 17 +- pyload/config/Setup.py | 7 +- pyload/manager/Addon.py | 5 +- pyload/manager/Scheduler.py | 7 +- pyload/network/HTTPRequest.py | 11 +- pyload/plugin/account/AlldebridCom.py | 4 +- pyload/plugin/addon/SkipRev.py | 5 +- pyload/plugin/container/DLC.py | 6 +- pyload/plugin/container/RSDF.py | 6 +- pyload/plugin/crypter/DuckCryptInfo.py | 6 +- pyload/plugin/crypter/FilecryptCc.py | 4 +- pyload/plugin/crypter/HoerbuchIn.py | 4 +- pyload/plugin/crypter/LinkCryptWs.py | 4 +- pyload/plugin/crypter/NCryptIn.py | 4 +- pyload/plugin/crypter/RelinkUs.py | 5 +- pyload/plugin/crypter/SafelinkingNet.py | 4 +- pyload/plugin/crypter/ShareLinksBiz.py | 5 +- pyload/plugin/hoster/MegaCoNz.py | 9 +- pyload/plugin/hoster/TurbobitNet.py | 4 +- pyload/plugin/hoster/ZDF.py | 5 +- pyload/plugin/hoster/ZippyshareCom.py | 4 +- pyload/remote/ClickNLoadBackend.py | 15 +- pyload/remote/thriftbackend/ThriftTest.py | 7 +- pyload/utils/filters.py | 68 ++++ pyload/utils/middlewares.py | 144 ++++++++ pyload/webui/__init__.py | 13 +- pyload/webui/app/__init__.py | 2 +- pyload/webui/app/pyload.py | 526 ++++++++++++++++++++++++++++++ pyload/webui/app/pyloadweb.py | 526 ------------------------------ pyload/webui/app/utils.py | 2 - pyload/webui/filters.py | 68 ---- pyload/webui/middlewares.py | 144 -------- 37 files changed, 820 insertions(+), 843 deletions(-) create mode 100644 pyload/utils/filters.py create mode 100644 pyload/utils/middlewares.py create mode 100644 pyload/webui/app/pyload.py delete mode 100644 pyload/webui/app/pyloadweb.py delete mode 100644 pyload/webui/filters.py delete mode 100644 pyload/webui/middlewares.py (limited to 'pyload') diff --git a/pyload/Database/User.py b/pyload/Database/User.py index dc60ce23a..a91e16cc6 100644 --- a/pyload/Database/User.py +++ b/pyload/Database/User.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # @author: mkaay -from hashlib import sha1 +import hashlib import random from pyload.Database import DatabaseBackend, style @@ -20,7 +20,7 @@ class UserMethods(object): salt = r[2][:5] pw = r[2][5:] - h = sha1(salt + password) + h = hashlib.sha1(salt + password) if h.hexdigest() == pw: return {"id": r[0], "name": r[1], "role": r[3], "permission": r[4], "template": r[5], "email": r[6]} @@ -31,7 +31,7 @@ class UserMethods(object): @style.queue def addUser(db, user, password): salt = reduce(lambda x, y: x + y, [str(random.randint(0, 9)) for _i in xrange(0, 5)]) - h = sha1(salt + password) + h = hashlib.sha1(salt + password) password = salt + h.hexdigest() c = db.c @@ -51,10 +51,10 @@ class UserMethods(object): salt = r[2][:5] pw = r[2][5:] - h = sha1(salt + oldpw) + h = hashlib.sha1(salt + oldpw) if h.hexdigest() == pw: salt = reduce(lambda x, y: x + y, [str(random.randint(0, 9)) for _i in xrange(0, 5)]) - h = sha1(salt + newpw) + h = hashlib.sha1(salt + newpw) password = salt + h.hexdigest() db.c.execute("UPDATE users SET password=? WHERE name=?", (password, user)) diff --git a/pyload/Thread/Addon.py b/pyload/Thread/Addon.py index e28fafd29..24a2fc26a 100644 --- a/pyload/Thread/Addon.py +++ b/pyload/Thread/Addon.py @@ -8,9 +8,6 @@ import sys import time import traceback -from pprint import pformat -from types import MethodType - from pyload.Thread.Plugin import PluginThread diff --git a/pyload/Thread/Decrypter.py b/pyload/Thread/Decrypter.py index d4afac730..5a8cff7c1 100644 --- a/pyload/Thread/Decrypter.py +++ b/pyload/Thread/Decrypter.py @@ -7,9 +7,6 @@ import sys import time import traceback -from pprint import pformat -from types import MethodType - from pyload.Thread.Plugin import PluginThread from pyload.plugin.Plugin import Abort, Fail, Retry diff --git a/pyload/Thread/Download.py b/pyload/Thread/Download.py index c20c7277e..49f6145ce 100644 --- a/pyload/Thread/Download.py +++ b/pyload/Thread/Download.py @@ -9,9 +9,6 @@ import traceback import pycurl -from pprint import pformat -from types import MethodType - from pyload.Thread.Plugin import PluginThread from pyload.plugin.Plugin import Abort, Fail, Reconnect, Retry, SkipDownload diff --git a/pyload/Thread/Info.py b/pyload/Thread/Info.py index 780a384bb..cf76fda4b 100644 --- a/pyload/Thread/Info.py +++ b/pyload/Thread/Info.py @@ -7,9 +7,6 @@ import sys import time import traceback -from pprint import pformat -from types import MethodType - from pyload.Api import OnlineStatus from pyload.Datatype import PyFile from pyload.Thread.Plugin import PluginThread diff --git a/pyload/Thread/Plugin.py b/pyload/Thread/Plugin.py index ee1418a7d..cba82946d 100644 --- a/pyload/Thread/Plugin.py +++ b/pyload/Thread/Plugin.py @@ -9,9 +9,8 @@ import sys import threading import time import traceback - -from pprint import pformat -from types import MethodType +import pprint +import types from pyload.Api import OnlineStatus from pyload.Datatype import PyFile @@ -87,7 +86,7 @@ class PluginThread(threading.Thread): for key, value in frame.f_locals.items(): dump += "\t%20s = " % key try: - dump += pformat(value) + "\n" + dump += pprint.pformat(value) + "\n" except Exception, e: dump += " " + str(e) + "\n" @@ -99,10 +98,10 @@ class PluginThread(threading.Thread): for name in dir(pyfile.plugin): attr = getattr(pyfile.plugin, name) - if not name.endswith("__") and type(attr) != MethodType: + if not name.endswith("__") and type(attr) != types.MethodType: dump += "\t%20s = " % name try: - dump += pformat(attr) + "\n" + dump += pprint.pformat(attr) + "\n" except Exception, e: dump += " " + str(e) + "\n" @@ -110,16 +109,16 @@ class PluginThread(threading.Thread): for name in dir(pyfile): attr = getattr(pyfile, name) - if not name.endswith("__") and type(attr) != MethodType: + if not name.endswith("__") and type(attr) != types.MethodType: dump += "\t%20s = " % name try: - dump += pformat(attr) + "\n" + dump += pprint.pformat(attr) + "\n" except Exception, e: dump += " " + str(e) + "\n" if pyfile.pluginname in self.m.core.config.plugin: dump += "\n\nCONFIG: \n\n" - dump += pformat(self.m.core.config.plugin[pyfile.pluginname]) + "\n" + dump += pprint.pformat(self.m.core.config.plugin[pyfile.pluginname]) + "\n" return dump diff --git a/pyload/config/Setup.py b/pyload/config/Setup.py index 1486eadca..fdf2524f5 100644 --- a/pyload/config/Setup.py +++ b/pyload/config/Setup.py @@ -4,12 +4,11 @@ from __future__ import with_statement import __builtin__ +import getpass import os import subprocess import sys -from getpass import getpass - from pyload.network.JsEngine import JsEngine from pyload.utils import get_console_encoding, load_translation, fs_join, versiontuple @@ -510,7 +509,7 @@ class SetupAssistant(object): pwlen = 8 while p1 != p2: sys.stdout.write(_("Password: ")) - p1 = getpass("").strip("\n\r") + p1 = getpass.getpass("").strip("\n\r") if len(p1) < pwlen: print @@ -524,7 +523,7 @@ class SetupAssistant(object): continue sys.stdout.write(_("Password (again): ")) - p2 = getpass("").strip("\n\r") + p2 = getpass.getpass("").strip("\n\r") if p1 == p2: print diff --git a/pyload/manager/Addon.py b/pyload/manager/Addon.py index 98b66189a..a632111ea 100644 --- a/pyload/manager/Addon.py +++ b/pyload/manager/Addon.py @@ -6,8 +6,7 @@ import __builtin__ import threading import traceback - -from types import MethodType +import types from pyload.Thread import AddonThread from pyload.manager.Plugin import literal_eval @@ -55,7 +54,7 @@ class AddonManager(object): self.events = {} #: contains events # registering callback for config event - self.core.config.pluginCB = MethodType(self.dispatchEvent, "pluginConfigChanged", basestring) #@TODO: Rename event pluginConfigChanged + self.core.config.pluginCB = types.MethodType(self.dispatchEvent, "pluginConfigChanged", basestring) #@TODO: Rename event pluginConfigChanged self.addEvent("pluginConfigChanged", self.manageAddon) diff --git a/pyload/manager/Scheduler.py b/pyload/manager/Scheduler.py index 630e43022..b82768aff 100644 --- a/pyload/manager/Scheduler.py +++ b/pyload/manager/Scheduler.py @@ -1,11 +1,10 @@ # -*- coding: utf-8 -*- # @author: mkaay +import heapq import threading import time -from heapq import heappop, heappush - class AlreadyCalled(Exception): pass @@ -125,7 +124,7 @@ class PriorityQueue(object): def put(self, element): self.lock.acquire() - heappush(self.queue, element) + heapq.heappush(self.queue, element) self.lock.release() @@ -133,7 +132,7 @@ class PriorityQueue(object): """ return element or None """ self.lock.acquire() try: - el = heappop(self.queue) + el = heapq.heappop(self.queue) return el except IndexError: return None, None diff --git a/pyload/network/HTTPRequest.py b/pyload/network/HTTPRequest.py index 22a4cc604..e450cacfe 100644 --- a/pyload/network/HTTPRequest.py +++ b/pyload/network/HTTPRequest.py @@ -3,15 +3,14 @@ from __future__ import with_statement +import cStringIO import codecs +import httplib import logging import urllib import pycurl -from httplib import responses -from cStringIO import StringIO - from pyload.plugin.Plugin import Abort, Fail from pyload.utils import encode @@ -31,7 +30,7 @@ bad_headers = range(400, 404) + range(405, 418) + range(500, 506) class BadHeader(Exception): def __init__(self, code, content=""): - Exception.__init__(self, "Bad server response: %s %s" % (code, responses[int(code)])) + Exception.__init__(self, "Bad server response: %s %s" % (code, httplib.responses[int(code)])) self.code = code self.content = content @@ -40,7 +39,7 @@ class HTTPRequest(object): def __init__(self, cookies=None, options=None): self.c = pycurl.Curl() - self.rep = StringIO() + self.rep = cStringIO.StringIO() self.cj = cookies #: cookiejar @@ -244,7 +243,7 @@ class HTTPRequest(object): else: value = self.rep.getvalue() self.rep.close() - self.rep = StringIO() + self.rep = cStringIO.StringIO() return value diff --git a/pyload/plugin/account/AlldebridCom.py b/pyload/plugin/account/AlldebridCom.py index efc5753f8..6ba7a80f9 100644 --- a/pyload/plugin/account/AlldebridCom.py +++ b/pyload/plugin/account/AlldebridCom.py @@ -4,7 +4,7 @@ import re import time import xml.dom.minidom as dom -from BeautifulSoup import BeautifulSoup +import BeautifulSoup from pyload.plugin.Account import Account @@ -22,7 +22,7 @@ class AlldebridCom(Account): def loadAccountInfo(self, user, req): data = self.getAccountData(user) html = req.load("http://www.alldebrid.com/account/") - soup = BeautifulSoup(html) + soup = BeautifulSoup.BeautifulSoup(html) # Try to parse expiration date directly from the control panel page (better accuracy) try: diff --git a/pyload/plugin/addon/SkipRev.py b/pyload/plugin/addon/SkipRev.py index b54e66af5..b19650710 100644 --- a/pyload/plugin/addon/SkipRev.py +++ b/pyload/plugin/addon/SkipRev.py @@ -3,8 +3,7 @@ import re import urllib import urlparse - -from types import MethodType +import types from pyload.datatype.File import PyFile from pyload.plugin.Addon import Addon @@ -75,7 +74,7 @@ class SkipRev(Addon): if not hasattr(pyfile.plugin, "_setup"): # Work-around: inject status checker inside the preprocessing routine of the plugin pyfile.plugin._setup = pyfile.plugin.setup - pyfile.plugin.setup = MethodType(self._setup, pyfile.plugin) + pyfile.plugin.setup = types.MethodType(self._setup, pyfile.plugin) def downloadFailed(self, pyfile): diff --git a/pyload/plugin/container/DLC.py b/pyload/plugin/container/DLC.py index b2bfea30e..39b1597b0 100644 --- a/pyload/plugin/container/DLC.py +++ b/pyload/plugin/container/DLC.py @@ -5,7 +5,7 @@ from __future__ import with_statement import re import xml.dom.minidom -from Crypto.Cipher import AES +import Crypto from pyload.plugin.Container import Container from pyload.utils import decode, fs_encode @@ -49,9 +49,9 @@ class DLC(Container): except AttributeError: self.fail(_("Container is corrupted")) - key = iv = AES.new(self.KEY, AES.MODE_CBC, self.IV).decrypt(rc) + key = iv = Crypto.Cipher.AES.new(self.KEY, Crypto.Cipher.AES.MODE_CBC, self.IV).decrypt(rc) - self.data = AES.new(key, AES.MODE_CBC, iv).decrypt(dlc_data).decode('base64') + self.data = Crypto.Cipher.AES.new(key, Crypto.Cipher.AES.MODE_CBC, iv).decrypt(dlc_data).decode('base64') self.packages = [(name or pyfile.name, links, name or pyfile.name) \ for name, links in self.getPackages()] diff --git a/pyload/plugin/container/RSDF.py b/pyload/plugin/container/RSDF.py index 6f56ec06a..1de8ad8d4 100644 --- a/pyload/plugin/container/RSDF.py +++ b/pyload/plugin/container/RSDF.py @@ -5,7 +5,7 @@ from __future__ import with_statement import binascii import re -from Crypto.Cipher import AES +import Crypto from pyload.plugin.Container import Container from pyload.utils import fs_encode @@ -33,8 +33,8 @@ class RSDF(Container): KEY = binascii.unhexlify(self.KEY) IV = binascii.unhexlify(self.IV) - iv = AES.new(KEY, AES.MODE_ECB).encrypt(IV) - cipher = AES.new(KEY, AES.MODE_CFB, iv) + iv = Crypto.Cipher.AES.new(KEY, Crypto.Cipher.AES.MODE_ECB).encrypt(IV) + cipher = Crypto.Cipher.AES.new(KEY, Crypto.Cipher.AES.MODE_CFB, iv) try: fs_filename = fs_encode(pyfile.url.strip()) diff --git a/pyload/plugin/crypter/DuckCryptInfo.py b/pyload/plugin/crypter/DuckCryptInfo.py index 3463d44f9..64d6568ce 100644 --- a/pyload/plugin/crypter/DuckCryptInfo.py +++ b/pyload/plugin/crypter/DuckCryptInfo.py @@ -2,7 +2,7 @@ import re -from BeautifulSoup import BeautifulSoup +import BeautifulSoup from pyload.plugin.Crypter import Crypter @@ -41,7 +41,7 @@ class DuckCryptInfo(Crypter): m = re.match(self.__pattern, html) self.logDebug("Redirectet to " + str(m.group(0))) html = self.load(str(m.group(0))) - soup = BeautifulSoup(html) + soup = BeautifulSoup.BeautifulSoup(html) cryptlinks = soup.findAll("div", attrs={"class": "folderbox"}) self.logDebug("Redirectet to " + str(cryptlinks)) if not cryptlinks: @@ -53,7 +53,7 @@ class DuckCryptInfo(Crypter): def handleLink(self, url): html = self.load(url) - soup = BeautifulSoup(html) + soup = BeautifulSoup.BeautifulSoup(html) self.urls = [soup.find("iframe")['src']] if not self.urls: self.logInfo(_("No link found")) diff --git a/pyload/plugin/crypter/FilecryptCc.py b/pyload/plugin/crypter/FilecryptCc.py index db939357a..0507a580b 100644 --- a/pyload/plugin/crypter/FilecryptCc.py +++ b/pyload/plugin/crypter/FilecryptCc.py @@ -7,7 +7,7 @@ import binascii import re import urlparse -from Crypto.Cipher import AES +import Crypto from pyload.plugin.Crypter import Crypter from pyload.plugin.captcha.ReCaptcha import ReCaptcha @@ -169,7 +169,7 @@ class FilecryptCc(Crypter): # Decrypt Key = key IV = key - obj = AES.new(Key, AES.MODE_CBC, IV) + obj = Crypto.Cipher.AES.new(Key, Crypto.Cipher.AES.MODE_CBC, IV) text = obj.decrypt(crypted.decode('base64')) # Extract links diff --git a/pyload/plugin/crypter/HoerbuchIn.py b/pyload/plugin/crypter/HoerbuchIn.py index 500dad8cc..455d0abdf 100644 --- a/pyload/plugin/crypter/HoerbuchIn.py +++ b/pyload/plugin/crypter/HoerbuchIn.py @@ -2,7 +2,7 @@ import re -from BeautifulSoup import BeautifulSoup, BeautifulStoneSoup +import BeautifulSoup, BeautifulStoneSoup from pyload.plugin.Crypter import Crypter @@ -31,7 +31,7 @@ class HoerbuchIn(Crypter): if self.article.match(pyfile.url): html = self.load(pyfile.url) - soup = BeautifulSoup(html, convertEntities=BeautifulStoneSoup.HTML_ENTITIES) + soup = BeautifulSoup.BeautifulSoup(html, convertEntities=BeautifulStoneSoup.HTML_ENTITIES) abookname = soup.find("a", attrs={"rel": "bookmark"}).text for a in soup.findAll("a", attrs={"href": self.protection}): diff --git a/pyload/plugin/crypter/LinkCryptWs.py b/pyload/plugin/crypter/LinkCryptWs.py index c997cbf9f..98a796aed 100644 --- a/pyload/plugin/crypter/LinkCryptWs.py +++ b/pyload/plugin/crypter/LinkCryptWs.py @@ -5,7 +5,7 @@ import re import pycurl -from Crypto.Cipher import AES +import Crypto from pyload.plugin.Crypter import Crypter from pyload.utils import html_unescape @@ -309,7 +309,7 @@ class LinkCryptWs(Crypter): # Decrypt Key = key IV = key - obj = AES.new(Key, AES.MODE_CBC, IV) + obj = Crypto.Cipher.AES.new(Key, Crypto.Cipher.AES.MODE_CBC, IV) text = obj.decrypt(crypted.decode('base64')) # Extract links diff --git a/pyload/plugin/crypter/NCryptIn.py b/pyload/plugin/crypter/NCryptIn.py index bc9702f21..2b357395b 100644 --- a/pyload/plugin/crypter/NCryptIn.py +++ b/pyload/plugin/crypter/NCryptIn.py @@ -3,7 +3,7 @@ import binascii import re -from Crypto.Cipher import AES +import Crypto from pyload.plugin.Crypter import Crypter from pyload.plugin.captcha.ReCaptcha import ReCaptcha @@ -298,7 +298,7 @@ class NCryptIn(Crypter): # Decrypt Key = key IV = key - obj = AES.new(Key, AES.MODE_CBC, IV) + obj = Crypto.Cipher.AES.new(Key, Crypto.Cipher.AES.MODE_CBC, IV) text = obj.decrypt(crypted.decode('base64')) # Extract links diff --git a/pyload/plugin/crypter/RelinkUs.py b/pyload/plugin/crypter/RelinkUs.py index 2b9a85401..3ffc33c12 100644 --- a/pyload/plugin/crypter/RelinkUs.py +++ b/pyload/plugin/crypter/RelinkUs.py @@ -6,7 +6,8 @@ import binascii import re import os -from Crypto.Cipher import AES +import Crypto + from pyload.plugin.Crypter import Crypter from pyload.utils import fs_join @@ -281,7 +282,7 @@ class RelinkUs(Crypter): # Decrypt Key = key IV = key - obj = AES.new(Key, AES.MODE_CBC, IV) + obj = Crypto.Cipher.AES.new(Key, Crypto.Cipher.AES.MODE_CBC, IV) text = obj.decrypt(crypted.decode('base64')) # Extract links diff --git a/pyload/plugin/crypter/SafelinkingNet.py b/pyload/plugin/crypter/SafelinkingNet.py index a949d17b1..71f41469b 100644 --- a/pyload/plugin/crypter/SafelinkingNet.py +++ b/pyload/plugin/crypter/SafelinkingNet.py @@ -2,7 +2,7 @@ import re -from BeautifulSoup import BeautifulSoup +import BeautifulSoup from pyload.utils import json_loads from pyload.plugin.Crypter import Crypter @@ -66,7 +66,7 @@ class SafelinkingNet(Crypter): break pyfile.package().password = "" - soup = BeautifulSoup(self.html) + soup = BeautifulSoup.BeautifulSoup(self.html) scripts = soup.findAll("script") for s in scripts: if "d_links" in s.text: diff --git a/pyload/plugin/crypter/ShareLinksBiz.py b/pyload/plugin/crypter/ShareLinksBiz.py index 8add5214d..25e891f3b 100644 --- a/pyload/plugin/crypter/ShareLinksBiz.py +++ b/pyload/plugin/crypter/ShareLinksBiz.py @@ -3,7 +3,8 @@ import binascii import re -from Crypto.Cipher import AES +import Crypto + from pyload.plugin.Crypter import Crypter @@ -267,7 +268,7 @@ class ShareLinksBiz(Crypter): # Decrypt Key = key IV = key - obj = AES.new(Key, AES.MODE_CBC, IV) + obj = Crypto.Cipher.AES.new(Key, Crypto.Cipher.AES.MODE_CBC, IV) text = obj.decrypt(crypted.decode('base64')) # Extract links diff --git a/pyload/plugin/hoster/MegaCoNz.py b/pyload/plugin/hoster/MegaCoNz.py index 2e6735ee6..83409fde9 100644 --- a/pyload/plugin/hoster/MegaCoNz.py +++ b/pyload/plugin/hoster/MegaCoNz.py @@ -7,8 +7,7 @@ import os import random import re -from Crypto.Cipher import AES -from Crypto.Util import Counter +import Crypto from pyload.utils import json_loads, json_dumps from pyload.plugin.Hoster import Hoster @@ -90,7 +89,7 @@ class MegaCoNz(Hoster): def decryptAttr(self, data, key): k, iv, meta_mac = self.getCipherKey(key) - cbc = AES.new(k, AES.MODE_CBC, "\0" * 16) + cbc = Crypto.Cipher.AES.new(k, Crypto.Cipher.AES.MODE_CBC, "\0" * 16) attr = decode(cbc.decrypt(self.b64_decode(data))) self.logDebug("Decrypted Attr: %s" % attr) @@ -109,8 +108,8 @@ class MegaCoNz(Hoster): # convert counter to long and shift bytes k, iv, meta_mac = self.getCipherKey(key) - ctr = Counter.new(128, initial_value=long(n.encode("hex"), 16) << 64) - cipher = AES.new(k, AES.MODE_CTR, counter=ctr) + ctr = Crypto.Util.Counter.new(128, initial_value=long(n.encode("hex"), 16) << 64) + cipher = Crypto.Cipher.AES.new(k, Crypto.Cipher.AES.MODE_CTR, counter=ctr) self.pyfile.setStatus("decrypting") self.pyfile.setProgress(0) diff --git a/pyload/plugin/hoster/TurbobitNet.py b/pyload/plugin/hoster/TurbobitNet.py index bcbeddd17..8138e2e23 100644 --- a/pyload/plugin/hoster/TurbobitNet.py +++ b/pyload/plugin/hoster/TurbobitNet.py @@ -7,7 +7,7 @@ import re import time import urllib -from Crypto.Cipher import ARC4 +import Crypto from pyload.network.RequestFactory import getURL from pyload.plugin.captcha.ReCaptcha import ReCaptcha @@ -155,7 +155,7 @@ class TurbobitNet(SimpleHoster): def decrypt(self, data): - cipher = ARC4.new(binascii.hexlify('E\x15\xa1\x9e\xa3M\xa0\xc6\xa0\x84\xb6H\x83\xa8o\xa0')) + cipher = Crypto.Cipher.ARC4.new(binascii.hexlify('E\x15\xa1\x9e\xa3M\xa0\xc6\xa0\x84\xb6H\x83\xa8o\xa0')) return binascii.unhexlify(cipher.encrypt(binascii.unhexlify(data))) diff --git a/pyload/plugin/hoster/ZDF.py b/pyload/plugin/hoster/ZDF.py index c02eadc23..8272cfd93 100644 --- a/pyload/plugin/hoster/ZDF.py +++ b/pyload/plugin/hoster/ZDF.py @@ -1,8 +1,7 @@ # -*- coding: utf-8 -*- import re - -from xml.etree.ElementTree import fromstring +import xml from pyload.plugin.Hoster import Hoster @@ -42,7 +41,7 @@ class ZDF(Hoster): def process(self, pyfile): - xml = fromstring(self.load(self.XML_API % self.get_id(pyfile.url))) + xml = xml.etree.ElementTree.fromstring(self.load(self.XML_API % self.get_id(pyfile.url))) status = xml.findtext("./status/statuscode") if status != "ok": diff --git a/pyload/plugin/hoster/ZippyshareCom.py b/pyload/plugin/hoster/ZippyshareCom.py index 40a879b55..df9af062b 100644 --- a/pyload/plugin/hoster/ZippyshareCom.py +++ b/pyload/plugin/hoster/ZippyshareCom.py @@ -3,7 +3,7 @@ import re import urllib -from BeautifulSoup import BeautifulSoup +import BeautifulSoup from pyload.plugin.captcha.ReCaptcha import ReCaptcha from pyload.plugin.internal.SimpleHoster import SimpleHoster @@ -59,7 +59,7 @@ class ZippyshareCom(SimpleHoster): def get_link(self): # get all the scripts inside the html body - soup = BeautifulSoup(self.html) + soup = BeautifulSoup.BeautifulSoup(self.html) scripts = (s.getText().strip() for s in soup.body.findAll('script', type='text/javascript')) # meant to be populated with the initialization of all the DOM elements found in the scripts diff --git a/pyload/remote/ClickNLoadBackend.py b/pyload/remote/ClickNLoadBackend.py index 99571fe8b..ece2dc316 100644 --- a/pyload/remote/ClickNLoadBackend.py +++ b/pyload/remote/ClickNLoadBackend.py @@ -1,16 +1,15 @@ # -*- coding: utf-8 -*- # @author: RaNaN +import BaseHTTPServer import base64 import binascii +import cgi import re import urllib -from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler -from cgi import FieldStorage - try: - from Crypto.Cipher import AES + import Crypto except Exception: pass @@ -23,7 +22,7 @@ js = None class ClickNLoadBackend(BackendBase): def setup(self, host, port): - self.httpd = HTTPServer((host, port), CNLHandler) + self.httpd = BaseHTTPServer.HTTPServer((host, port), CNLHandler) global core, js core = self.m.core js = core.js @@ -34,7 +33,7 @@ class ClickNLoadBackend(BackendBase): self.httpd.handle_request() -class CNLHandler(BaseHTTPRequestHandler): +class CNLHandler(BaseHTTPServer.BaseHTTPRequestHandler): def add_package(self, name, urls, queue=0): print "name", name @@ -94,7 +93,7 @@ class CNLHandler(BaseHTTPRequestHandler): def do_POST(self): - form = FieldStorage( + form = cgi.FieldStorage( fp=self.rfile, headers=self.headers, environ={'REQUEST_METHOD': 'POST', @@ -137,7 +136,7 @@ class CNLHandler(BaseHTTPRequestHandler): Key = binascii.unhexlify(jk) IV = Key - obj = AES.new(Key, AES.MODE_CBC, IV) + obj = Crypto.Cipher.AES.new(Key, Crypto.Cipher.AES.MODE_CBC, IV) result = obj.decrypt(crypted).replace("\x00", "").replace("\r", "").split("\n") result = filter(lambda x: x != "", result) diff --git a/pyload/remote/thriftbackend/ThriftTest.py b/pyload/remote/thriftbackend/ThriftTest.py index d8adf476e..3ea67682b 100644 --- a/pyload/remote/thriftbackend/ThriftTest.py +++ b/pyload/remote/thriftbackend/ThriftTest.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- +import getpass import os import platform import sys import time +import xmlrpclib from pyload.remote.thriftbackend.thriftgen.pyload import Pyload from pyload.remote.thriftbackend.thriftgen.pyload.ttypes import * @@ -14,8 +16,6 @@ from thrift.transport import TTransport from Protocol import Protocol -import xmlrpclib - def bench(f, *args, **kwargs): s = time.time() @@ -27,9 +27,8 @@ def bench(f, *args, **kwargs): print "%s: %f s" % (f.__name__, e-s) return ret -from getpass import getpass user = raw_input("user ") -passwd = getpass("password ") +passwd = getpass.getpass("password ") server_url = "http%s://%s:%s@%s:%s/" % ( "", diff --git a/pyload/utils/filters.py b/pyload/utils/filters.py new file mode 100644 index 000000000..9d4d47c04 --- /dev/null +++ b/pyload/utils/filters.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- + +import os + +quotechar = "::/" + +try: + from os.path import relpath +except Exception: + from posixpath import curdir, sep, pardir + + + def os.relpath(path, start=curdir): + """Return a relative version of a path""" + if not path: + raise ValueError("no path specified") + start_list = os.path.abspath(start).split(sep) + path_list = os.path.abspath(path).split(sep) + # Work out how much of the filepath is shared by start and path. + i = len(os.path.commonprefix([start_list, path_list])) + rel_list = [pardir] * (len(start_list) - i) + path_list[i:] + if not rel_list: + return curdir + return os.path.join(*rel_list) + + +def quotepath(path): + try: + return path.replace("../", quotechar) + except AttributeError: + return path + except Exception: + return "" + + +def unquotepath(path): + try: + return path.replace(quotechar, "../") + except AttributeError: + return path + except Exception: + return "" + + +def path_make_absolute(path): + p = os.path.abspath(path) + if p[-1] == os.path.sep: + return p + else: + return p + os.path.sep + + +def path_make_relative(path): + p = os.relpath(path) + if p[-1] == os.path.sep: + return p + else: + return p + os.path.sep + + +def truncate(value, n): + if (n - len(value)) < 3: + return value[:n] + "..." + return value + + +def date(date, format): + return date diff --git a/pyload/utils/middlewares.py b/pyload/utils/middlewares.py new file mode 100644 index 000000000..c3f4952db --- /dev/null +++ b/pyload/utils/middlewares.py @@ -0,0 +1,144 @@ +# -*- coding: utf-8 -*- + +import gzip + +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO + + +class StripPathMiddleware(object): + + def __init__(self, app): + self.app = app + + + def __call__(self, e, h): + e['PATH_INFO'] = e['PATH_INFO'].rstrip('/') + return self.app(e, h) + + +class PrefixMiddleware(object): + + def __init__(self, app, prefix="/pyload"): + self.app = app + self.prefix = prefix + + + def __call__(self, e, h): + path = e['PATH_INFO'] + if path.startswith(self.prefix): + e['PATH_INFO'] = path.replace(self.prefix, "", 1) + return self.app(e, h) + +# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) +# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php + +# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) +# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php + +# WSGI middleware +# Gzip-encodes the response. + + +class GZipMiddleWare(object): + + def __init__(self, application, compress_level=6): + self.application = application + self.compress_level = int(compress_level) + + + def __call__(self, environ, start_response): + if 'gzip' not in environ.get('HTTP_ACCEPT_ENCODING', ''): + # nothing for us to do, so this middleware will + # be a no-op: + return self.application(environ, start_response) + response = GzipResponse(start_response, self.compress_level) + app_iter = self.application(environ, + response.gzip_start_response) + if app_iter is not None: + response.finish_response(app_iter) + + return response.write() + + +def header_value(headers, key): + for header, value in headers: + if key.lower() == header.lower(): + return value + + +def update_header(headers, key, value): + remove_header(headers, key) + headers.append((key, value)) + + +def remove_header(headers, key): + for header, value in headers: + if key.lower() == header.lower(): + headers.remove((header, value)) + break + + +class GzipResponse(object): + + def __init__(self, start_response, compress_level): + self.start_response = start_response + self.compress_level = compress_level + self.buffer = StringIO() + self.compressible = False + self.content_length = None + self.headers = () + + + def gzip_start_response(self, status, headers, exc_info=None): + self.headers = headers + ct = header_value(headers, 'content-type') + ce = header_value(headers, 'content-encoding') + cl = header_value(headers, 'content-length') + if cl: + cl = int(cl) + else: + cl = 201 + self.compressible = False + if ct and (ct.startswith('text/') or ct.startswith('application/')) and 'zip' not in ct and cl > 200: + self.compressible = True + if ce: + self.compressible = False + if self.compressible: + headers.append(('content-encoding', 'gzip')) + remove_header(headers, 'content-length') + self.headers = headers + self.status = status + return self.buffer.write + + + def write(self): + out = self.buffer + out.seek(0) + s = out.getvalue() + out.close() + return [s] + + + def finish_response(self, app_iter): + if self.compressible: + output = gzip.GzipFile(mode='wb', compresslevel=self.compress_level, fileobj=self.buffer) + else: + output = self.buffer + try: + for s in app_iter: + output.write(s) + if self.compressible: + output.close() + finally: + if hasattr(app_iter, 'close'): + try: + app_iter.close() + except Exception: + pass + + content_length = self.buffer.tell() + update_header(self.headers, "Content-Length", str(content_length)) + self.start_response(self.status, self.headers) diff --git a/pyload/webui/__init__.py b/pyload/webui/__init__.py index 472e1a4f7..70928c458 100644 --- a/pyload/webui/__init__.py +++ b/pyload/webui/__init__.py @@ -5,13 +5,12 @@ import os import sys import bottle +import jinja2 import pyload.utils.pylgettext as gettext -from jinja2 import Environment, FileSystemLoader, PrefixLoader, FileSystemBytecodeCache - from pyload.Thread import Server -from pyload.Webui.middlewares import StripPathMiddleware, GZipMiddleWare, PrefixMiddleware +from pyload.utils.middlewares import StripPathMiddleware, GZipMiddleWare, PrefixMiddleware from pyload.network.JsEngine import JsEngine from pyload.utils import decode, formatSize @@ -53,14 +52,14 @@ cache = os.path.join("tmp", "jinja_cache") if not os.path.exists(cache): os.makedirs(cache) -bcc = FileSystemBytecodeCache(cache, '%s.cache') +bcc = jinja2.FileSystemBytecodeCache(cache, '%s.cache') -loader = FileSystemLoader([THEME_DIR, os.path.join(THEME_DIR, THEME)]) +loader = jinja2.FileSystemLoader([THEME_DIR, os.path.join(THEME_DIR, THEME)]) -env = Environment(loader=loader, extensions=['jinja2.ext.i18n', 'jinja2.ext.autoescape'], trim_blocks=True, auto_reload=False, +env = jinja2.Environment(loader=loader, extensions=['jinja2.ext.i18n', 'jinja2.ext.autoescape'], trim_blocks=True, auto_reload=False, bytecode_cache=bcc) -from filters import quotepath, path_make_relative, path_make_absolute, truncate, date +from pyload.utils.filters import quotepath, path_make_relative, path_make_absolute, truncate, date env.filters['quotepath'] = quotepath env.filters['truncate'] = truncate diff --git a/pyload/webui/app/__init__.py b/pyload/webui/app/__init__.py index 43c9ecbe9..39d0fadd5 100644 --- a/pyload/webui/app/__init__.py +++ b/pyload/webui/app/__init__.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- -from pyload.webui.app import api, cnl, json, pyloadweb +from pyload.webui.app import api, cnl, json, pyload diff --git a/pyload/webui/app/pyload.py b/pyload/webui/app/pyload.py new file mode 100644 index 000000000..58acdf12c --- /dev/null +++ b/pyload/webui/app/pyload.py @@ -0,0 +1,526 @@ +# -*- coding: utf-8 -*- +# @author: RaNaN + +import datetime +import operator +import os +import sys +import time +import urllib + +import bottle + +from pyload.webui import PYLOAD, PYLOAD_DIR, THEME_DIR, THEME, SETUP, env + +from pyload.webui.app.utils import render_to_response, parse_permissions, parse_userdata, \ + login_required, get_permission, set_permission, permlist, toDict, set_session + +from pyload.utils.filters import relpath, unquotepath + +from pyload.utils import formatSize, fs_join, fs_encode, fs_decode + +# Helper + + +def pre_processor(): + s = request.environ.get('beaker.session') + user = parse_userdata(s) + perms = parse_permissions(s) + status = {} + captcha = False + update = False + plugins = False + if user['is_authenticated']: + status = PYLOAD.statusServer() + info = PYLOAD.getInfoByPlugin("UpdateManager") + captcha = PYLOAD.isCaptchaWaiting() + + # check if update check is available + if info: + if info['pyload'] == "True": + update = info['version'] + if info['plugins'] == "True": + plugins = True + + return {"user": user, + 'status': status, + 'captcha': captcha, + 'perms': perms, + 'url': request.url, + 'update': update, + 'plugins': plugins} + + +def base(messages): + return render_to_response('base.html', {'messages': messages}, [pre_processor]) + + +# Views +@bottle.error(403) +def error403(code): + return "The parameter you passed has the wrong format" + + +@bottle.error(404) +def error404(code): + return "Sorry, this page does not exist" + + +@bottle.error(500) +def error500(error): + traceback = error.traceback + if traceback: + print traceback + return base(["An Error occured, please enable debug mode to get more details.", error, + traceback.replace("\n", "
") if traceback else "No Traceback"]) + + +@bottle.route('//') +def server_min(theme, file): + filename = os.path.join(THEME_DIR, THEME, theme, file) + if not os.path.isfile(filename): + file = file.replace(".min.", ".") + if file.endswith(".js"): + return server_js(theme, file) + else: + return server_static(theme, file) + + +@bottle.route('//') +def server_js(theme, file): + response.headers['Content-Type'] = "text/javascript; charset=UTF-8" + + if "/render/" in file or ".render." in file or True: + response.headers['Expires'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT", + time.gmtime(time.time() + 24 * 7 * 60 * 60)) + response.headers['Cache-control'] = "public" + + path = "/".join((theme, file)) + return env.get_template(path).render() + else: + return server_static(theme, file) + + +@bottle.route('//') +def server_static(theme, file): + response.headers['Expires'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT", + time.gmtime(time.time() + 24 * 7 * 60 * 60)) + response.headers['Cache-control'] = "public" + + return bottle.static_file(file, root=join(THEME_DIR, THEME, theme)) + + +@bottle.route('/favicon.ico') +def favicon(): + return bottle.static_file("icon.ico", root=join(PYLOAD_DIR, "docs", "resources")) + + +@bottle.route('/login', method="GET") +def login(): + if not PYLOAD and SETUP: + bottle.redirect("/setup") + else: + return render_to_response("login.html", proc=[pre_processor]) + + +@bottle.route('/nopermission') +def nopermission(): + return base([_("You dont have permission to access this page.")]) + + +@bottle.route('/login', method='POST') +def login_post(): + user = request.forms.get("username") + password = request.forms.get("password") + + info = PYLOAD.checkAuth(user, password) + + if not info: + return render_to_response("login.html", {"errors": True}, [pre_processor]) + + set_session(request, info) + return bottle.redirect("/") + + +@bottle.route('/logout') +def logout(): + s = request.environ.get('beaker.session') + s.delete() + return render_to_response("logout.html", proc=[pre_processor]) + + +@bottle.route('/') +@bottle.route('/home') +@login_required("LIST") +def home(): + try: + res = [toDict(x) for x in PYLOAD.statusDownloads()] + except Exception: + s = request.environ.get('beaker.session') + s.delete() + return bottle.redirect("/login") + + for link in res: + if link['status'] == 12: + link['information'] = "%s kB @ %s kB/s" % (link['size'] - link['bleft'], link['speed']) + + return render_to_response("home.html", {"res": res}, [pre_processor]) + + +@bottle.route('/queue') +@login_required("LIST") +def queue(): + queue = PYLOAD.getQueue() + + queue.sort(key=operator.attrgetter("order")) + + return render_to_response('queue.html', {'content': queue, 'target': 1}, [pre_processor]) + + +@bottle.route('/collector') +@login_required('LIST') +def collector(): + queue = PYLOAD.getCollector() + + queue.sort(key=operator.attrgetter("order")) + + return render_to_response('queue.html', {'content': queue, 'target': 0}, [pre_processor]) + + +@bottle.route('/downloads') +@login_required('DOWNLOAD') +def downloads(): + root = PYLOAD.getConfigValue("general", "download_folder") + + if not os.path.isdir(root): + return base([_('Download directory not found.')]) + data = { + 'folder': [], + 'files': [] + } + + items = os.listdir(fs_encode(root)) + + for item in sorted([fs_decode(x) for x in items]): + if os.path.isdir(fs_join(root, item)): + folder = { + 'name': item, + 'path': item, + 'files': [] + } + files = os.listdir(fs_join(root, item)) + for file in sorted([fs_decode(x) for x in files]): + try: + if os.path.isfile(fs_join(root, item, file)): + folder['files'].append(file) + except Exception: + pass + + data['folder'].append(folder) + elif os.path.isfile(os.path.join(root, item)): + data['files'].append(item) + + return render_to_response('downloads.html', {'files': data}, [pre_processor]) + + +@bottle.route('/downloads/get/') +@login_required("DOWNLOAD") +def get_download(path): + path = urllib.unquote(path).decode("utf8") + #@TODO some files can not be downloaded + + root = PYLOAD.getConfigValue("general", "download_folder") + + path = path.replace("..", "") + return bottle.static_file(fs_encode(path), fs_encode(root)) + + +@bottle.route('/settings') +@login_required('SETTINGS') +def config(): + conf = PYLOAD.getConfig() + plugin = PYLOAD.getPluginConfig() + conf_menu = [] + plugin_menu = [] + + for entry in sorted(conf.keys()): + conf_menu.append((entry, conf[entry].description)) + + last_name = None + for entry in sorted(plugin.keys()): + desc = plugin[entry].description + name, none, type = desc.partition("_") + + if type in PYLOAD.core.pluginManager.TYPES: + if name == last_name or len([a for a, b in plugin.iteritems() if b.description.startswith(name + "_")]) > 1: + desc = name + " (" + type.title() + ")" + else: + desc = name + last_name = name + plugin_menu.append((entry, desc)) + + accs = PYLOAD.getAccounts(False) + + for data in accs: + if data.trafficleft == -1: + data.trafficleft = _("unlimited") + elif not data.trafficleft: + data.trafficleft = _("not available") + else: + data.trafficleft = formatSize(data.trafficleft) + + if data.validuntil == -1: + data.validuntil = _("unlimited") + elif not data.validuntil: + data.validuntil = _("not available") + else: + t = time.localtime(data.validuntil) + data.validuntil = time.strftime("%d.%m.%Y - %H:%M:%S", t) + + try: + data.options['time'] = data.options['time'][0] + except Exception: + data.options['time'] = "0:00-0:00" + + if "limitDL" in data.options: + data.options['limitdl'] = data.options['limitDL'][0] + else: + data.options['limitdl'] = "0" + + return render_to_response('settings.html', + {'conf': {'plugin': plugin_menu, 'general': conf_menu, 'accs': accs}, + 'types': PYLOAD.getAccountTypes()}, + [pre_processor]) + + +@bottle.route('/filechooser') +@bottle.route('/pathchooser') +@bottle.route('/filechooser/') +@bottle.route('/pathchooser/') +@login_required('STATUS') +def os.path(file="", path=""): + type = "file" if file else "folder" + + path = os.path.normpath(unquotepath(path)) + + if os.path.isfile(path): + oldfile = path + path = os.path.dirname(path) + else: + oldfile = '' + + abs = False + + if os.path.isdir(path): + if os.path.isabs(path): + cwd = os.path.abspath(path) + abs = True + else: + cwd = os.relpath(path) + else: + cwd = os.getcwd() + + try: + cwd = cwd.encode("utf8") + except Exception: + pass + + cwd = os.path.normpath(os.path.abspath(cwd)) + parentdir = os.path.dirname(cwd) + if not abs: + if os.path.abspath(cwd) == "/": + cwd = os.relpath(cwd) + else: + cwd = os.relpath(cwd) + os.path.sep + parentdir = os.relpath(parentdir) + os.path.sep + + if os.path.abspath(cwd) == "/": + parentdir = "" + + try: + folders = os.listdir(cwd) + except Exception: + folders = [] + + files = [] + + for f in folders: + try: + f = f.decode(sys.getfilesystemencoding()) + data = {'name': f, 'fullpath': os.path.join(cwd, f)} + data['sort'] = data['fullpath'].lower() + data['modified'] = datetime.datetime.fromtimestamp(int(os.path.getmtime(os.path.join(cwd, f)))) + data['ext'] = os.path.splitext(f)[1] + except Exception: + continue + + data['type'] = 'dir' if os.path.isdir(os.path.join(cwd, f)) else 'file' + + if os.path.isfile(os.path.join(cwd, f)): + data['size'] = os.path.getsize(os.path.join(cwd, f)) + + power = 0 + while (data['size'] / 1024) > 0.3: + power += 1 + data['size'] /= 1024. + units = ('', 'K', 'M', 'G', 'T') + data['unit'] = units[power] + 'Byte' + else: + data['size'] = '' + + files.append(data) + + files = sorted(files, key=operator.itemgetter('type', 'sort')) + + return render_to_response('pathchooser.html', + {'cwd': cwd, 'files': files, 'parentdir': parentdir, 'type': type, 'oldfile': oldfile, + 'absolute': abs}, []) + + +@bottle.route('/logs') +@bottle.route('/logs', method='POST') +@bottle.route('/logs/') +@bottle.route('/logs/', method='POST') +@login_required('LOGS') +def logs(item=-1): + s = request.environ.get('beaker.session') + + perpage = s.get('perpage', 34) + reversed = s.get('reversed', False) + + warning = "" + conf = PYLOAD.getConfigValue("log", "file_log") + color_template = PYLOAD.getConfigValue("log", "color_template") if PYLOAD.getConfigValue("log", "color_console") else "" + if not conf: + warning = "Warning: File log is disabled, see settings page." + + perpage_p = ((20, 20), (34, 34), (40, 40), (100, 100), (0, 'all')) + fro = None + + if request.environ.get('REQUEST_METHOD', "GET") == "POST": + try: + fro = datetime.datetime.strptime(request.forms['from'], '%d.%m.%Y %H:%M:%S') + except Exception: + pass + try: + perpage = int(request.forms['perpage']) + s['perpage'] = perpage + + reversed = bool(request.forms.get('reversed', False)) + s['reversed'] = reversed + except Exception: + pass + + s.save() + + try: + item = int(item) + except Exception: + pass + + log = PYLOAD.getLog() + if not perpage: + item = 1 + + if item < 1 or type(item) is not int: + item = 1 if len(log) - perpage + 1 < 1 else len(log) - perpage + 1 + + if type(fro) is datetime.datetime: #: we will search for datetime.datetime + item = -1 + + data = [] + counter = 0 + perpagecheck = 0 + for l in log: + counter += 1 + + if counter >= item: + try: + date, time, level, message = l.decode("utf8", "ignore").split(" ", 3) + dtime = datetime.datetime.strptime(date + ' ' + time, '%Y-%m-%d %H:%M:%S') + except Exception: + dtime = None + date = '?' + time = ' ' + level = '?' + message = l + if item == -1 and dtime is not None and fro <= dtime: + item = counter #: found our datetime.datetime + if item >= 0: + data.append({'line': counter, 'date': date + " " + time, 'level': level, 'message': message}) + perpagecheck += 1 + if fro is None and dtime is not None: #: if fro not set set it to first showed line + fro = dtime + if perpagecheck >= perpage > 0: + break + + if fro is None: #: still not set, empty log? + fro = datetime.datetime.now() + if reversed: + data.reverse() + return render_to_response('logs.html', {'warning': warning, 'log': data, 'from': fro.strftime('%d.%m.%Y %H:%M:%S'), + 'reversed': reversed, 'perpage': perpage, 'perpage_p': sorted(perpage_p), + 'iprev': 1 if item - perpage < 1 else item - perpage, + 'inext': (item + perpage) if item + perpage < len(log) else item, + 'color_template': color_template.title()}, + [pre_processor]) + + +@bottle.route('/admin') +@bottle.route('/admin', method='POST') +@login_required("ADMIN") +def admin(): + # convert to dict + user = dict((name, toDict(y)) for name, y in PYLOAD.getAllUserData().iteritems()) + perms = permlist() + + for data in user.itervalues(): + data['perms'] = {} + get_permission(data['perms'], data['permission']) + data['perms']['admin'] = data['role'] is 0 + + s = request.environ.get('beaker.session') + if request.environ.get('REQUEST_METHOD', "GET") == "POST": + for name in user: + if request.POST.get("%s|admin" % name, False): + user[name]['role'] = 0 + user[name]['perms']['admin'] = True + elif name != s['name']: + user[name]['role'] = 1 + user[name]['perms']['admin'] = False + + # set all perms to false + for perm in perms: + user[name]['perms'][perm] = False + + for perm in request.POST.getall("%s|perms" % name): + user[name]['perms'][perm] = True + + user[name]['permission'] = set_permission(user[name]['perms']) + + PYLOAD.setUserPermission(name, user[name]['permission'], user[name]['role']) + + return render_to_response("admin.html", {"users": user, "permlist": perms}, [pre_processor]) + + +@bottle.route('/setup') +def setup(): + return base([_("Run pyload.py -s to access the setup.")]) + + +@bottle.route('/info') +def info(): + conf = PYLOAD.getConfigDict() + extra = os.uname() if hasattr(os, "uname") else tuple() + + data = {"python" : sys.version, + "os" : " ".join((os.name, sys.platform) + extra), + "version" : PYLOAD.getServerVersion(), + "folder" : os.path.abspath(PYLOAD_DIR), "config": os.path.abspath(""), + "download" : os.path.abspath(conf['general']['download_folder']['value']), + "freespace": formatSize(PYLOAD.freeSpace()), + "remote" : conf['remote']['port']['value'], + "webif" : conf['webui']['port']['value'], + "language" : conf['general']['language']['value']} + + return render_to_response("info.html", data, [pre_processor]) diff --git a/pyload/webui/app/pyloadweb.py b/pyload/webui/app/pyloadweb.py deleted file mode 100644 index 27532b86e..000000000 --- a/pyload/webui/app/pyloadweb.py +++ /dev/null @@ -1,526 +0,0 @@ -# -*- coding: utf-8 -*- -# @author: RaNaN - -import datetime -import operator -import os -import sys -import time -import urllib - -import bottle - -from pyload.webui import PYLOAD, PYLOAD_DIR, THEME_DIR, THEME, SETUP, env - -from pyload.webui.app.utils import render_to_response, parse_permissions, parse_userdata, \ - login_required, get_permission, set_permission, permlist, toDict, set_session - -from pyload.webui.filters import relpath, unquotepath - -from pyload.utils import formatSize, fs_join, fs_encode, fs_decode - -# Helper - - -def pre_processor(): - s = request.environ.get('beaker.session') - user = parse_userdata(s) - perms = parse_permissions(s) - status = {} - captcha = False - update = False - plugins = False - if user['is_authenticated']: - status = PYLOAD.statusServer() - info = PYLOAD.getInfoByPlugin("UpdateManager") - captcha = PYLOAD.isCaptchaWaiting() - - # check if update check is available - if info: - if info['pyload'] == "True": - update = info['version'] - if info['plugins'] == "True": - plugins = True - - return {"user": user, - 'status': status, - 'captcha': captcha, - 'perms': perms, - 'url': request.url, - 'update': update, - 'plugins': plugins} - - -def base(messages): - return render_to_response('base.html', {'messages': messages}, [pre_processor]) - - -# Views -@bottle.error(403) -def error403(code): - return "The parameter you passed has the wrong format" - - -@bottle.error(404) -def error404(code): - return "Sorry, this page does not exist" - - -@bottle.error(500) -def error500(error): - traceback = error.traceback - if traceback: - print traceback - return base(["An Error occured, please enable debug mode to get more details.", error, - traceback.replace("\n", "
") if traceback else "No Traceback"]) - - -@bottle.route('//') -def server_min(theme, file): - filename = os.path.join(THEME_DIR, THEME, theme, file) - if not os.path.isfile(filename): - file = file.replace(".min.", ".") - if file.endswith(".js"): - return server_js(theme, file) - else: - return server_static(theme, file) - - -@bottle.route('//') -def server_js(theme, file): - response.headers['Content-Type'] = "text/javascript; charset=UTF-8" - - if "/render/" in file or ".render." in file or True: - response.headers['Expires'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT", - time.gmtime(time.time() + 24 * 7 * 60 * 60)) - response.headers['Cache-control'] = "public" - - path = "/".join((theme, file)) - return env.get_template(path).render() - else: - return server_static(theme, file) - - -@bottle.route('//') -def server_static(theme, file): - response.headers['Expires'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT", - time.gmtime(time.time() + 24 * 7 * 60 * 60)) - response.headers['Cache-control'] = "public" - - return bottle.static_file(file, root=join(THEME_DIR, THEME, theme)) - - -@bottle.route('/favicon.ico') -def favicon(): - return bottle.static_file("icon.ico", root=join(PYLOAD_DIR, "docs", "resources")) - - -@bottle.route('/login', method="GET") -def login(): - if not PYLOAD and SETUP: - bottle.redirect("/setup") - else: - return render_to_response("login.html", proc=[pre_processor]) - - -@bottle.route('/nopermission') -def nopermission(): - return base([_("You dont have permission to access this page.")]) - - -@bottle.route('/login', method='POST') -def login_post(): - user = request.forms.get("username") - password = request.forms.get("password") - - info = PYLOAD.checkAuth(user, password) - - if not info: - return render_to_response("login.html", {"errors": True}, [pre_processor]) - - set_session(request, info) - return bottle.redirect("/") - - -@bottle.route('/logout') -def logout(): - s = request.environ.get('beaker.session') - s.delete() - return render_to_response("logout.html", proc=[pre_processor]) - - -@bottle.route('/') -@bottle.route('/home') -@login_required("LIST") -def home(): - try: - res = [toDict(x) for x in PYLOAD.statusDownloads()] - except Exception: - s = request.environ.get('beaker.session') - s.delete() - return bottle.redirect("/login") - - for link in res: - if link['status'] == 12: - link['information'] = "%s kB @ %s kB/s" % (link['size'] - link['bleft'], link['speed']) - - return render_to_response("home.html", {"res": res}, [pre_processor]) - - -@bottle.route('/queue') -@login_required("LIST") -def queue(): - queue = PYLOAD.getQueue() - - queue.sort(key=operator.attrgetter("order")) - - return render_to_response('queue.html', {'content': queue, 'target': 1}, [pre_processor]) - - -@bottle.route('/collector') -@login_required('LIST') -def collector(): - queue = PYLOAD.getCollector() - - queue.sort(key=operator.attrgetter("order")) - - return render_to_response('queue.html', {'content': queue, 'target': 0}, [pre_processor]) - - -@bottle.route('/downloads') -@login_required('DOWNLOAD') -def downloads(): - root = PYLOAD.getConfigValue("general", "download_folder") - - if not os.path.isdir(root): - return base([_('Download directory not found.')]) - data = { - 'folder': [], - 'files': [] - } - - items = os.listdir(fs_encode(root)) - - for item in sorted([fs_decode(x) for x in items]): - if os.path.isdir(fs_join(root, item)): - folder = { - 'name': item, - 'path': item, - 'files': [] - } - files = os.listdir(fs_join(root, item)) - for file in sorted([fs_decode(x) for x in files]): - try: - if os.path.isfile(fs_join(root, item, file)): - folder['files'].append(file) - except Exception: - pass - - data['folder'].append(folder) - elif os.path.isfile(os.path.join(root, item)): - data['files'].append(item) - - return render_to_response('downloads.html', {'files': data}, [pre_processor]) - - -@bottle.route('/downloads/get/') -@login_required("DOWNLOAD") -def get_download(path): - path = urllib.unquote(path).decode("utf8") - #@TODO some files can not be downloaded - - root = PYLOAD.getConfigValue("general", "download_folder") - - path = path.replace("..", "") - return bottle.static_file(fs_encode(path), fs_encode(root)) - - -@bottle.route('/settings') -@login_required('SETTINGS') -def config(): - conf = PYLOAD.getConfig() - plugin = PYLOAD.getPluginConfig() - conf_menu = [] - plugin_menu = [] - - for entry in sorted(conf.keys()): - conf_menu.append((entry, conf[entry].description)) - - last_name = None - for entry in sorted(plugin.keys()): - desc = plugin[entry].description - name, none, type = desc.partition("_") - - if type in PYLOAD.core.pluginManager.TYPES: - if name == last_name or len([a for a, b in plugin.iteritems() if b.description.startswith(name + "_")]) > 1: - desc = name + " (" + type.title() + ")" - else: - desc = name - last_name = name - plugin_menu.append((entry, desc)) - - accs = PYLOAD.getAccounts(False) - - for data in accs: - if data.trafficleft == -1: - data.trafficleft = _("unlimited") - elif not data.trafficleft: - data.trafficleft = _("not available") - else: - data.trafficleft = formatSize(data.trafficleft) - - if data.validuntil == -1: - data.validuntil = _("unlimited") - elif not data.validuntil: - data.validuntil = _("not available") - else: - t = time.localtime(data.validuntil) - data.validuntil = time.strftime("%d.%m.%Y - %H:%M:%S", t) - - try: - data.options['time'] = data.options['time'][0] - except Exception: - data.options['time'] = "0:00-0:00" - - if "limitDL" in data.options: - data.options['limitdl'] = data.options['limitDL'][0] - else: - data.options['limitdl'] = "0" - - return render_to_response('settings.html', - {'conf': {'plugin': plugin_menu, 'general': conf_menu, 'accs': accs}, - 'types': PYLOAD.getAccountTypes()}, - [pre_processor]) - - -@bottle.route('/filechooser') -@bottle.route('/pathchooser') -@bottle.route('/filechooser/') -@bottle.route('/pathchooser/') -@login_required('STATUS') -def os.path(file="", path=""): - type = "file" if file else "folder" - - path = os.path.normpath(unquotepath(path)) - - if os.path.isfile(path): - oldfile = path - path = os.path.dirname(path) - else: - oldfile = '' - - abs = False - - if os.path.isdir(path): - if os.path.isabs(path): - cwd = os.path.abspath(path) - abs = True - else: - cwd = os.relpath(path) - else: - cwd = os.getcwd() - - try: - cwd = cwd.encode("utf8") - except Exception: - pass - - cwd = os.path.normpath(os.path.abspath(cwd)) - parentdir = os.path.dirname(cwd) - if not abs: - if os.path.abspath(cwd) == "/": - cwd = os.relpath(cwd) - else: - cwd = os.relpath(cwd) + os.path.sep - parentdir = os.relpath(parentdir) + os.path.sep - - if os.path.abspath(cwd) == "/": - parentdir = "" - - try: - folders = os.listdir(cwd) - except Exception: - folders = [] - - files = [] - - for f in folders: - try: - f = f.decode(sys.getfilesystemencoding()) - data = {'name': f, 'fullpath': os.path.join(cwd, f)} - data['sort'] = data['fullpath'].lower() - data['modified'] = datetime.datetime.fromtimestamp(int(os.path.getmtime(os.path.join(cwd, f)))) - data['ext'] = os.path.splitext(f)[1] - except Exception: - continue - - data['type'] = 'dir' if os.path.isdir(os.path.join(cwd, f)) else 'file' - - if os.path.isfile(os.path.join(cwd, f)): - data['size'] = os.path.getsize(os.path.join(cwd, f)) - - power = 0 - while (data['size'] / 1024) > 0.3: - power += 1 - data['size'] /= 1024. - units = ('', 'K', 'M', 'G', 'T') - data['unit'] = units[power] + 'Byte' - else: - data['size'] = '' - - files.append(data) - - files = sorted(files, key=operator.itemgetter('type', 'sort')) - - return render_to_response('pathchooser.html', - {'cwd': cwd, 'files': files, 'parentdir': parentdir, 'type': type, 'oldfile': oldfile, - 'absolute': abs}, []) - - -@bottle.route('/logs') -@bottle.route('/logs', method='POST') -@bottle.route('/logs/') -@bottle.route('/logs/', method='POST') -@login_required('LOGS') -def logs(item=-1): - s = request.environ.get('beaker.session') - - perpage = s.get('perpage', 34) - reversed = s.get('reversed', False) - - warning = "" - conf = PYLOAD.getConfigValue("log", "file_log") - color_template = PYLOAD.getConfigValue("log", "color_template") if PYLOAD.getConfigValue("log", "color_console") else "" - if not conf: - warning = "Warning: File log is disabled, see settings page." - - perpage_p = ((20, 20), (34, 34), (40, 40), (100, 100), (0, 'all')) - fro = None - - if request.environ.get('REQUEST_METHOD', "GET") == "POST": - try: - fro = datetime.datetime.strptime(request.forms['from'], '%d.%m.%Y %H:%M:%S') - except Exception: - pass - try: - perpage = int(request.forms['perpage']) - s['perpage'] = perpage - - reversed = bool(request.forms.get('reversed', False)) - s['reversed'] = reversed - except Exception: - pass - - s.save() - - try: - item = int(item) - except Exception: - pass - - log = PYLOAD.getLog() - if not perpage: - item = 1 - - if item < 1 or type(item) is not int: - item = 1 if len(log) - perpage + 1 < 1 else len(log) - perpage + 1 - - if type(fro) is datetime.datetime: #: we will search for datetime.datetime - item = -1 - - data = [] - counter = 0 - perpagecheck = 0 - for l in log: - counter += 1 - - if counter >= item: - try: - date, time, level, message = l.decode("utf8", "ignore").split(" ", 3) - dtime = datetime.datetime.strptime(date + ' ' + time, '%Y-%m-%d %H:%M:%S') - except Exception: - dtime = None - date = '?' - time = ' ' - level = '?' - message = l - if item == -1 and dtime is not None and fro <= dtime: - item = counter #: found our datetime.datetime - if item >= 0: - data.append({'line': counter, 'date': date + " " + time, 'level': level, 'message': message}) - perpagecheck += 1 - if fro is None and dtime is not None: #: if fro not set set it to first showed line - fro = dtime - if perpagecheck >= perpage > 0: - break - - if fro is None: #: still not set, empty log? - fro = datetime.datetime.now() - if reversed: - data.reverse() - return render_to_response('logs.html', {'warning': warning, 'log': data, 'from': fro.strftime('%d.%m.%Y %H:%M:%S'), - 'reversed': reversed, 'perpage': perpage, 'perpage_p': sorted(perpage_p), - 'iprev': 1 if item - perpage < 1 else item - perpage, - 'inext': (item + perpage) if item + perpage < len(log) else item, - 'color_template': color_template.title()}, - [pre_processor]) - - -@bottle.route('/admin') -@bottle.route('/admin', method='POST') -@login_required("ADMIN") -def admin(): - # convert to dict - user = dict((name, toDict(y)) for name, y in PYLOAD.getAllUserData().iteritems()) - perms = permlist() - - for data in user.itervalues(): - data['perms'] = {} - get_permission(data['perms'], data['permission']) - data['perms']['admin'] = data['role'] is 0 - - s = request.environ.get('beaker.session') - if request.environ.get('REQUEST_METHOD', "GET") == "POST": - for name in user: - if request.POST.get("%s|admin" % name, False): - user[name]['role'] = 0 - user[name]['perms']['admin'] = True - elif name != s['name']: - user[name]['role'] = 1 - user[name]['perms']['admin'] = False - - # set all perms to false - for perm in perms: - user[name]['perms'][perm] = False - - for perm in request.POST.getall("%s|perms" % name): - user[name]['perms'][perm] = True - - user[name]['permission'] = set_permission(user[name]['perms']) - - PYLOAD.setUserPermission(name, user[name]['permission'], user[name]['role']) - - return render_to_response("admin.html", {"users": user, "permlist": perms}, [pre_processor]) - - -@bottle.route('/setup') -def setup(): - return base([_("Run pyload.py -s to access the setup.")]) - - -@bottle.route('/info') -def info(): - conf = PYLOAD.getConfigDict() - extra = os.uname() if hasattr(os, "uname") else tuple() - - data = {"python" : sys.version, - "os" : " ".join((os.name, sys.platform) + extra), - "version" : PYLOAD.getServerVersion(), - "folder" : os.path.abspath(PYLOAD_DIR), "config": os.path.abspath(""), - "download" : os.path.abspath(conf['general']['download_folder']['value']), - "freespace": formatSize(PYLOAD.freeSpace()), - "remote" : conf['remote']['port']['value'], - "webif" : conf['webui']['port']['value'], - "language" : conf['general']['language']['value']} - - return render_to_response("info.html", data, [pre_processor]) diff --git a/pyload/webui/app/utils.py b/pyload/webui/app/utils.py index 3526f2615..2e7cf76c5 100644 --- a/pyload/webui/app/utils.py +++ b/pyload/webui/app/utils.py @@ -86,10 +86,8 @@ def parse_userdata(session): def login_required(perm=None): - def _dec(func): - def _view(*args, **kwargs): s = request.environ.get('beaker.session') if s.get("name", None) and s.get("authenticated", False): diff --git a/pyload/webui/filters.py b/pyload/webui/filters.py deleted file mode 100644 index 9d4d47c04..000000000 --- a/pyload/webui/filters.py +++ /dev/null @@ -1,68 +0,0 @@ -# -*- coding: utf-8 -*- - -import os - -quotechar = "::/" - -try: - from os.path import relpath -except Exception: - from posixpath import curdir, sep, pardir - - - def os.relpath(path, start=curdir): - """Return a relative version of a path""" - if not path: - raise ValueError("no path specified") - start_list = os.path.abspath(start).split(sep) - path_list = os.path.abspath(path).split(sep) - # Work out how much of the filepath is shared by start and path. - i = len(os.path.commonprefix([start_list, path_list])) - rel_list = [pardir] * (len(start_list) - i) + path_list[i:] - if not rel_list: - return curdir - return os.path.join(*rel_list) - - -def quotepath(path): - try: - return path.replace("../", quotechar) - except AttributeError: - return path - except Exception: - return "" - - -def unquotepath(path): - try: - return path.replace(quotechar, "../") - except AttributeError: - return path - except Exception: - return "" - - -def path_make_absolute(path): - p = os.path.abspath(path) - if p[-1] == os.path.sep: - return p - else: - return p + os.path.sep - - -def path_make_relative(path): - p = os.relpath(path) - if p[-1] == os.path.sep: - return p - else: - return p + os.path.sep - - -def truncate(value, n): - if (n - len(value)) < 3: - return value[:n] + "..." - return value - - -def date(date, format): - return date diff --git a/pyload/webui/middlewares.py b/pyload/webui/middlewares.py deleted file mode 100644 index c3f4952db..000000000 --- a/pyload/webui/middlewares.py +++ /dev/null @@ -1,144 +0,0 @@ -# -*- coding: utf-8 -*- - -import gzip - -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO - - -class StripPathMiddleware(object): - - def __init__(self, app): - self.app = app - - - def __call__(self, e, h): - e['PATH_INFO'] = e['PATH_INFO'].rstrip('/') - return self.app(e, h) - - -class PrefixMiddleware(object): - - def __init__(self, app, prefix="/pyload"): - self.app = app - self.prefix = prefix - - - def __call__(self, e, h): - path = e['PATH_INFO'] - if path.startswith(self.prefix): - e['PATH_INFO'] = path.replace(self.prefix, "", 1) - return self.app(e, h) - -# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) -# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php - -# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) -# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php - -# WSGI middleware -# Gzip-encodes the response. - - -class GZipMiddleWare(object): - - def __init__(self, application, compress_level=6): - self.application = application - self.compress_level = int(compress_level) - - - def __call__(self, environ, start_response): - if 'gzip' not in environ.get('HTTP_ACCEPT_ENCODING', ''): - # nothing for us to do, so this middleware will - # be a no-op: - return self.application(environ, start_response) - response = GzipResponse(start_response, self.compress_level) - app_iter = self.application(environ, - response.gzip_start_response) - if app_iter is not None: - response.finish_response(app_iter) - - return response.write() - - -def header_value(headers, key): - for header, value in headers: - if key.lower() == header.lower(): - return value - - -def update_header(headers, key, value): - remove_header(headers, key) - headers.append((key, value)) - - -def remove_header(headers, key): - for header, value in headers: - if key.lower() == header.lower(): - headers.remove((header, value)) - break - - -class GzipResponse(object): - - def __init__(self, start_response, compress_level): - self.start_response = start_response - self.compress_level = compress_level - self.buffer = StringIO() - self.compressible = False - self.content_length = None - self.headers = () - - - def gzip_start_response(self, status, headers, exc_info=None): - self.headers = headers - ct = header_value(headers, 'content-type') - ce = header_value(headers, 'content-encoding') - cl = header_value(headers, 'content-length') - if cl: - cl = int(cl) - else: - cl = 201 - self.compressible = False - if ct and (ct.startswith('text/') or ct.startswith('application/')) and 'zip' not in ct and cl > 200: - self.compressible = True - if ce: - self.compressible = False - if self.compressible: - headers.append(('content-encoding', 'gzip')) - remove_header(headers, 'content-length') - self.headers = headers - self.status = status - return self.buffer.write - - - def write(self): - out = self.buffer - out.seek(0) - s = out.getvalue() - out.close() - return [s] - - - def finish_response(self, app_iter): - if self.compressible: - output = gzip.GzipFile(mode='wb', compresslevel=self.compress_level, fileobj=self.buffer) - else: - output = self.buffer - try: - for s in app_iter: - output.write(s) - if self.compressible: - output.close() - finally: - if hasattr(app_iter, 'close'): - try: - app_iter.close() - except Exception: - pass - - content_length = self.buffer.tell() - update_header(self.headers, "Content-Length", str(content_length)) - self.start_response(self.status, self.headers) -- cgit v1.2.3