diff options
author | Walter Purcaro <vuolter@users.noreply.github.com> | 2015-04-13 10:21:32 +0200 |
---|---|---|
committer | Walter Purcaro <vuolter@users.noreply.github.com> | 2015-04-13 10:21:32 +0200 |
commit | eca20b701c411046e7ededb0462b310124ce3c18 (patch) | |
tree | c5eb36261cfc935f001b816f28f15d1f5afbf7e0 | |
parent | Merge branch 'stable' into 0.4.10 (diff) | |
download | pyload-eca20b701c411046e7ededb0462b310124ce3c18.tar.xz |
Cleanup + fixup + new lib
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | lib/colorama/__init__.py | 7 | ||||
-rw-r--r-- | lib/colorama/ansi.py | 99 | ||||
-rw-r--r-- | lib/colorama/ansitowin32.py | 228 | ||||
-rw-r--r-- | lib/colorama/initialise.py | 66 | ||||
-rw-r--r-- | lib/colorama/win32.py | 146 | ||||
-rw-r--r-- | lib/colorama/winterm.py | 151 | ||||
-rw-r--r-- | lib/colorlog/__init__.py | 14 | ||||
-rw-r--r-- | lib/colorlog/colorlog.py | 137 | ||||
-rw-r--r-- | lib/colorlog/escape_codes.py | 57 | ||||
-rw-r--r-- | lib/colorlog/logging.py | 44 | ||||
-rw-r--r-- | module/plugins/internal/CaptchaService.py | 517 | ||||
-rw-r--r-- | pyload/database/File.py | 10 | ||||
-rw-r--r-- | pyload/datatype/File.py | 2 | ||||
-rw-r--r-- | pyload/plugin/Plugin.py | 15 | ||||
-rw-r--r-- | pyload/plugin/addon/AntiVirus.py | 3 | ||||
-rw-r--r-- | pyload/plugin/addon/UpdateManager.py | 4 | ||||
-rw-r--r-- | pyload/plugin/addon/UserAgentSwitcher.py (renamed from module/plugins/hooks/UserAgentSwitcher.py) | 11 | ||||
-rw-r--r-- | pyload/plugin/captcha/AdsCaptcha.py | 4 | ||||
-rw-r--r-- | pyload/plugin/captcha/ReCaptcha.py | 23 | ||||
-rw-r--r-- | pyload/plugin/captcha/SolveMedia.py | 2 | ||||
-rw-r--r-- | pyload/plugin/container/CCF.py | 5 | ||||
-rw-r--r-- | pyload/plugin/hook/AlldebridCom.py (renamed from module/plugins/hooks/AlldebridComHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/DebridItaliaCom.py (renamed from module/plugins/hooks/DebridItaliaComHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/EasybytezCom.py (renamed from module/plugins/hooks/EasybytezComHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/FastixRu.py (renamed from module/plugins/hooks/FastixRuHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/FreeWayMe.py (renamed from module/plugins/hooks/FreeWayMeHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/LinkdecrypterCom.py (renamed from module/plugins/hooks/LinkdecrypterComHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/LinksnappyCom.py (renamed from module/plugins/hooks/LinksnappyComHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/MegaDebridEu.py (renamed from module/plugins/hooks/MegaDebridEuHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/MegaRapidoNet.py (renamed from module/plugins/hooks/MegaRapidoNetHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/MultihostersCom.py (renamed from module/plugins/hooks/MultihostersComHook.py) | 0 | ||||
-rw-r--r-- | pyload/plugin/hook/MultishareCz.py (renamed from module/plugins/hooks/MultishareCzHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/MyfastfileCom.py (renamed from module/plugins/hooks/MyfastfileComHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/NoPremiumPl.py (renamed from module/plugins/hooks/NoPremiumPlHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/OverLoadMe.py (renamed from module/plugins/hooks/OverLoadMeHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/PremiumTo.py (renamed from module/plugins/hooks/PremiumToHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/PremiumizeMe.py (renamed from module/plugins/hooks/PremiumizeMeHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/PutdriveCom.py (renamed from module/plugins/hooks/PutdriveComHook.py) | 0 | ||||
-rw-r--r-- | pyload/plugin/hook/RPNetBiz.py (renamed from module/plugins/hooks/RPNetBizHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/RapideoPl.py (renamed from module/plugins/hooks/RapideoPlHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/RealdebridCom.py (renamed from module/plugins/hooks/RealdebridComHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/RehostTo.py (renamed from module/plugins/hooks/RehostToHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/SimplyPremiumCom.py (renamed from module/plugins/hooks/SimplyPremiumComHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/SimplydebridCom.py (renamed from module/plugins/hooks/SimplydebridComHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/SmoozedCom.py (renamed from module/plugins/hooks/SmoozedComHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/UnrestrictLi.py (renamed from module/plugins/hooks/UnrestrictLiHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hook/ZeveraCom.py (renamed from module/plugins/hooks/ZeveraComHook.py) | 4 | ||||
-rw-r--r-- | pyload/plugin/hoster/Ftp.py | 10 | ||||
-rw-r--r-- | pyload/plugin/hoster/LolabitsEs.py (renamed from module/plugins/hoster/LolabitsEs.py) | 5 | ||||
-rw-r--r-- | pyload/plugin/hoster/SolidfilesCom.py (renamed from module/plugins/hoster/SolidfilesCom.py) | 5 | ||||
-rw-r--r-- | pyload/plugin/hoster/YadiSk.py (renamed from module/plugins/hoster/YadiSk.py) | 9 | ||||
-rw-r--r-- | pyload/plugin/internal/BasePlugin.py | 10 | ||||
-rw-r--r-- | pyload/plugin/internal/SimpleHoster.py | 14 | ||||
-rw-r--r-- | pyload/plugin/internal/XFSHoster.py | 4 | ||||
-rwxr-xr-x | setup.py | 17 |
56 files changed, 1055 insertions, 662 deletions
diff --git a/.gitignore b/.gitignore index 5b8b4907d..14e8aa543 100644 --- a/.gitignore +++ b/.gitignore @@ -77,7 +77,7 @@ eggs *.pydevproject *.rej _build/ -#module/ +module/ paver-minilib.zip /setup.sh /tesseract/ diff --git a/lib/colorama/__init__.py b/lib/colorama/__init__.py new file mode 100644 index 000000000..4af0c1e11 --- /dev/null +++ b/lib/colorama/__init__.py @@ -0,0 +1,7 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +from .initialise import init, deinit, reinit +from .ansi import Fore, Back, Style, Cursor +from .ansitowin32 import AnsiToWin32 + +__version__ = '0.3.3' + diff --git a/lib/colorama/ansi.py b/lib/colorama/ansi.py new file mode 100644 index 000000000..1cc722500 --- /dev/null +++ b/lib/colorama/ansi.py @@ -0,0 +1,99 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +''' +This module generates ANSI character codes to printing colors to terminals. +See: http://en.wikipedia.org/wiki/ANSI_escape_code +''' + +CSI = '\033[' +OSC = '\033]' +BEL = '\007' + + +def code_to_chars(code): + return CSI + str(code) + 'm' + + +class AnsiCodes(object): + def __init__(self, codes): + for name in dir(codes): + if not name.startswith('_'): + value = getattr(codes, name) + setattr(self, name, code_to_chars(value)) + + +class AnsiCursor(object): + def UP(self, n=1): + return CSI + str(n) + "A" + def DOWN(self, n=1): + return CSI + str(n) + "B" + def FORWARD(self, n=1): + return CSI + str(n) + "C" + def BACK(self, n=1): + return CSI + str(n) + "D" + def POS(self, x=1, y=1): + return CSI + str(y) + ";" + str(x) + "H" + +def set_title(title): + return OSC + "2;" + title + BEL + +def clear_screen(mode=2): + return CSI + str(mode) + "J" + +def clear_line(mode=2): + return CSI + str(mode) + "K" + + +class AnsiFore: + BLACK = 30 + RED = 31 + GREEN = 32 + YELLOW = 33 + BLUE = 34 + MAGENTA = 35 + CYAN = 36 + WHITE = 37 + RESET = 39 + + # These are fairly well supported, but not part of the standard. + LIGHTBLACK_EX = 90 + LIGHTRED_EX = 91 + LIGHTGREEN_EX = 92 + LIGHTYELLOW_EX = 93 + LIGHTBLUE_EX = 94 + LIGHTMAGENTA_EX = 95 + LIGHTCYAN_EX = 96 + LIGHTWHITE_EX = 97 + + +class AnsiBack: + BLACK = 40 + RED = 41 + GREEN = 42 + YELLOW = 43 + BLUE = 44 + MAGENTA = 45 + CYAN = 46 + WHITE = 47 + RESET = 49 + + # These are fairly well supported, but not part of the standard. + LIGHTBLACK_EX = 100 + LIGHTRED_EX = 101 + LIGHTGREEN_EX = 102 + LIGHTYELLOW_EX = 103 + LIGHTBLUE_EX = 104 + LIGHTMAGENTA_EX = 105 + LIGHTCYAN_EX = 106 + LIGHTWHITE_EX = 107 + + +class AnsiStyle: + BRIGHT = 1 + DIM = 2 + NORMAL = 22 + RESET_ALL = 0 + +Fore = AnsiCodes( AnsiFore ) +Back = AnsiCodes( AnsiBack ) +Style = AnsiCodes( AnsiStyle ) +Cursor = AnsiCursor() diff --git a/lib/colorama/ansitowin32.py b/lib/colorama/ansitowin32.py new file mode 100644 index 000000000..62e770c86 --- /dev/null +++ b/lib/colorama/ansitowin32.py @@ -0,0 +1,228 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import re +import sys +import os + +from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style +from .winterm import WinTerm, WinColor, WinStyle +from .win32 import windll + + +winterm = None +if windll is not None: + winterm = WinTerm() + + +def is_a_tty(stream): + return hasattr(stream, 'isatty') and stream.isatty() + + +class StreamWrapper(object): + ''' + Wraps a stream (such as stdout), acting as a transparent proxy for all + attribute access apart from method 'write()', which is delegated to our + Converter instance. + ''' + def __init__(self, wrapped, converter): + # double-underscore everything to prevent clashes with names of + # attributes on the wrapped stream object. + self.__wrapped = wrapped + self.__convertor = converter + + def __getattr__(self, name): + return getattr(self.__wrapped, name) + + def write(self, text): + self.__convertor.write(text) + + +class AnsiToWin32(object): + ''' + Implements a 'write()' method which, on Windows, will strip ANSI character + sequences from the text, and if outputting to a tty, will convert them into + win32 function calls. + ''' + ANSI_CSI_RE = re.compile('\033\[((?:\d|;)*)([a-zA-Z])') # Control Sequence Introducer + ANSI_OSC_RE = re.compile('\033\]((?:.|;)*?)(\x07)') # Operating System Command + + def __init__(self, wrapped, convert=None, strip=None, autoreset=False): + # The wrapped stream (normally sys.stdout or sys.stderr) + self.wrapped = wrapped + + # should we reset colors to defaults after every .write() + self.autoreset = autoreset + + # create the proxy wrapping our output stream + self.stream = StreamWrapper(wrapped, self) + + on_windows = os.name == 'nt' + on_emulated_windows = on_windows and 'TERM' in os.environ + + # should we strip ANSI sequences from our output? + if strip is None: + strip = on_windows and not on_emulated_windows + self.strip = strip + + # should we should convert ANSI sequences into win32 calls? + if convert is None: + convert = on_windows and not wrapped.closed and not on_emulated_windows and is_a_tty(wrapped) + self.convert = convert + + # dict of ansi codes to win32 functions and parameters + self.win32_calls = self.get_win32_calls() + + # are we wrapping stderr? + self.on_stderr = self.wrapped is sys.stderr + + def should_wrap(self): + ''' + True if this class is actually needed. If false, then the output + stream will not be affected, nor will win32 calls be issued, so + wrapping stdout is not actually required. This will generally be + False on non-Windows platforms, unless optional functionality like + autoreset has been requested using kwargs to init() + ''' + return self.convert or self.strip or self.autoreset + + def get_win32_calls(self): + if self.convert and winterm: + return { + AnsiStyle.RESET_ALL: (winterm.reset_all, ), + AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT), + AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL), + AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL), + AnsiFore.BLACK: (winterm.fore, WinColor.BLACK), + AnsiFore.RED: (winterm.fore, WinColor.RED), + AnsiFore.GREEN: (winterm.fore, WinColor.GREEN), + AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW), + AnsiFore.BLUE: (winterm.fore, WinColor.BLUE), + AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA), + AnsiFore.CYAN: (winterm.fore, WinColor.CYAN), + AnsiFore.WHITE: (winterm.fore, WinColor.GREY), + AnsiFore.RESET: (winterm.fore, ), + AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True), + AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True), + AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True), + AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True), + AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True), + AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True), + AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True), + AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True), + AnsiBack.BLACK: (winterm.back, WinColor.BLACK), + AnsiBack.RED: (winterm.back, WinColor.RED), + AnsiBack.GREEN: (winterm.back, WinColor.GREEN), + AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW), + AnsiBack.BLUE: (winterm.back, WinColor.BLUE), + AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA), + AnsiBack.CYAN: (winterm.back, WinColor.CYAN), + AnsiBack.WHITE: (winterm.back, WinColor.GREY), + AnsiBack.RESET: (winterm.back, ), + AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True), + AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True), + AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True), + AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True), + AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True), + AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True), + AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True), + AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True), + } + return dict() + + def write(self, text): + if self.strip or self.convert: + self.write_and_convert(text) + else: + self.wrapped.write(text) + self.wrapped.flush() + if self.autoreset: + self.reset_all() + + + def reset_all(self): + if self.convert: + self.call_win32('m', (0,)) + elif not self.wrapped.closed and is_a_tty(self.wrapped): + self.wrapped.write(Style.RESET_ALL) + + + def write_and_convert(self, text): + ''' + Write the given text to our wrapped stream, stripping any ANSI + sequences from the text, and optionally converting them into win32 + calls. + ''' + cursor = 0 + text = self.convert_osc(text) + for match in self.ANSI_CSI_RE.finditer(text): + start, end = match.span() + self.write_plain_text(text, cursor, start) + self.convert_ansi(*match.groups()) + cursor = end + self.write_plain_text(text, cursor, len(text)) + + + def write_plain_text(self, text, start, end): + if start < end: + self.wrapped.write(text[start:end]) + self.wrapped.flush() + + + def convert_ansi(self, paramstring, command): + if self.convert: + params = self.extract_params(command, paramstring) + self.call_win32(command, params) + + + def extract_params(self, command, paramstring): + if command in 'Hf': + params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';')) + while len(params) < 2: + # defaults: + params = params + (1,) + else: + params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0) + if len(params) == 0: + # defaults: + if command in 'JKm': + params = (0,) + elif command in 'ABCD': + params = (1,) + + return params + + + def call_win32(self, command, params): + if command == 'm': + for param in params: + if param in self.win32_calls: + func_args = self.win32_calls[param] + func = func_args[0] + args = func_args[1:] + kwargs = dict(on_stderr=self.on_stderr) + func(*args, **kwargs) + elif command in 'J': + winterm.erase_screen(params[0], on_stderr=self.on_stderr) + elif command in 'K': + winterm.erase_line(params[0], on_stderr=self.on_stderr) + elif command in 'Hf': # cursor position - absolute + winterm.set_cursor_position(params, on_stderr=self.on_stderr) + elif command in 'ABCD': # cursor position - relative + n = params[0] + # A - up, B - down, C - forward, D - back + x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command] + winterm.cursor_adjust(x, y, on_stderr=self.on_stderr) + + + def convert_osc(self, text): + for match in self.ANSI_OSC_RE.finditer(text): + start, end = match.span() + text = text[:start] + text[end:] + paramstring, command = match.groups() + if command in '\x07': # \x07 = BEL + params = paramstring.split(";") + # 0 - change title and icon (we will only change title) + # 1 - change icon (we don't support this) + # 2 - change title + if params[0] in '02': + winterm.set_title(params[1]) + return text diff --git a/lib/colorama/initialise.py b/lib/colorama/initialise.py new file mode 100644 index 000000000..7e27f84f8 --- /dev/null +++ b/lib/colorama/initialise.py @@ -0,0 +1,66 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import atexit +import sys + +from .ansitowin32 import AnsiToWin32 + + +orig_stdout = sys.stdout +orig_stderr = sys.stderr + +wrapped_stdout = sys.stdout +wrapped_stderr = sys.stderr + +atexit_done = False + + +def reset_all(): + AnsiToWin32(orig_stdout).reset_all() + + +def init(autoreset=False, convert=None, strip=None, wrap=True): + + if not wrap and any([autoreset, convert, strip]): + raise ValueError('wrap=False conflicts with any other arg=True') + + global wrapped_stdout, wrapped_stderr + if sys.stdout is None: + wrapped_stdout = None + else: + sys.stdout = wrapped_stdout = \ + wrap_stream(orig_stdout, convert, strip, autoreset, wrap) + if sys.stderr is None: + wrapped_stderr = None + else: + sys.stderr = wrapped_stderr = \ + wrap_stream(orig_stderr, convert, strip, autoreset, wrap) + + global atexit_done + if not atexit_done: + atexit.register(reset_all) + atexit_done = True + + +def deinit(): + if orig_stdout is not None: + sys.stdout = orig_stdout + if orig_stderr is not None: + sys.stderr = orig_stderr + + +def reinit(): + if wrapped_stdout is not None: + sys.stdout = wrapped_stdout + if wrapped_stderr is not None: + sys.stderr = wrapped_stderr + + +def wrap_stream(stream, convert, strip, autoreset, wrap): + if wrap: + wrapper = AnsiToWin32(stream, + convert=convert, strip=strip, autoreset=autoreset) + if wrapper.should_wrap(): + stream = wrapper.stream + return stream + + diff --git a/lib/colorama/win32.py b/lib/colorama/win32.py new file mode 100644 index 000000000..c604f3721 --- /dev/null +++ b/lib/colorama/win32.py @@ -0,0 +1,146 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. + +# from winbase.h +STDOUT = -11 +STDERR = -12 + +try: + import ctypes + from ctypes import LibraryLoader + windll = LibraryLoader(ctypes.WinDLL) + from ctypes import wintypes +except (AttributeError, ImportError): + windll = None + SetConsoleTextAttribute = lambda *_: None +else: + from ctypes import byref, Structure, c_char, POINTER + + COORD = wintypes._COORD + + class CONSOLE_SCREEN_BUFFER_INFO(Structure): + """struct in wincon.h.""" + _fields_ = [ + ("dwSize", COORD), + ("dwCursorPosition", COORD), + ("wAttributes", wintypes.WORD), + ("srWindow", wintypes.SMALL_RECT), + ("dwMaximumWindowSize", COORD), + ] + def __str__(self): + return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % ( + self.dwSize.Y, self.dwSize.X + , self.dwCursorPosition.Y, self.dwCursorPosition.X + , self.wAttributes + , self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right + , self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X + ) + + _GetStdHandle = windll.kernel32.GetStdHandle + _GetStdHandle.argtypes = [ + wintypes.DWORD, + ] + _GetStdHandle.restype = wintypes.HANDLE + + _GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo + _GetConsoleScreenBufferInfo.argtypes = [ + wintypes.HANDLE, + POINTER(CONSOLE_SCREEN_BUFFER_INFO), + ] + _GetConsoleScreenBufferInfo.restype = wintypes.BOOL + + _SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute + _SetConsoleTextAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, + ] + _SetConsoleTextAttribute.restype = wintypes.BOOL + + _SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition + _SetConsoleCursorPosition.argtypes = [ + wintypes.HANDLE, + COORD, + ] + _SetConsoleCursorPosition.restype = wintypes.BOOL + + _FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA + _FillConsoleOutputCharacterA.argtypes = [ + wintypes.HANDLE, + c_char, + wintypes.DWORD, + COORD, + POINTER(wintypes.DWORD), + ] + _FillConsoleOutputCharacterA.restype = wintypes.BOOL + + _FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute + _FillConsoleOutputAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, + wintypes.DWORD, + COORD, + POINTER(wintypes.DWORD), + ] + _FillConsoleOutputAttribute.restype = wintypes.BOOL + + _SetConsoleTitleW = windll.kernel32.SetConsoleTitleA + _SetConsoleTitleW.argtypes = [ + wintypes.LPCSTR + ] + _SetConsoleTitleW.restype = wintypes.BOOL + + handles = { + STDOUT: _GetStdHandle(STDOUT), + STDERR: _GetStdHandle(STDERR), + } + + def GetConsoleScreenBufferInfo(stream_id=STDOUT): + handle = handles[stream_id] + csbi = CONSOLE_SCREEN_BUFFER_INFO() + success = _GetConsoleScreenBufferInfo( + handle, byref(csbi)) + return csbi + + def SetConsoleTextAttribute(stream_id, attrs): + handle = handles[stream_id] + return _SetConsoleTextAttribute(handle, attrs) + + def SetConsoleCursorPosition(stream_id, position, adjust=True): + position = COORD(*position) + # If the position is out of range, do nothing. + if position.Y <= 0 or position.X <= 0: + return + # Adjust for Windows' SetConsoleCursorPosition: + # 1. being 0-based, while ANSI is 1-based. + # 2. expecting (x,y), while ANSI uses (y,x). + adjusted_position = COORD(position.Y - 1, position.X - 1) + if adjust: + # Adjust for viewport's scroll position + sr = GetConsoleScreenBufferInfo(STDOUT).srWindow + adjusted_position.Y += sr.Top + adjusted_position.X += sr.Left + # Resume normal processing + handle = handles[stream_id] + return _SetConsoleCursorPosition(handle, adjusted_position) + + def FillConsoleOutputCharacter(stream_id, char, length, start): + handle = handles[stream_id] + char = c_char(char.encode()) + length = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + success = _FillConsoleOutputCharacterA( + handle, char, length, start, byref(num_written)) + return num_written.value + + def FillConsoleOutputAttribute(stream_id, attr, length, start): + ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )''' + handle = handles[stream_id] + attribute = wintypes.WORD(attr) + length = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + return _FillConsoleOutputAttribute( + handle, attribute, length, start, byref(num_written)) + + def SetConsoleTitle(title): + return _SetConsoleTitleW(title) diff --git a/lib/colorama/winterm.py b/lib/colorama/winterm.py new file mode 100644 index 000000000..fcc774ffa --- /dev/null +++ b/lib/colorama/winterm.py @@ -0,0 +1,151 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +from . import win32 + + +# from wincon.h +class WinColor(object): + BLACK = 0 + BLUE = 1 + GREEN = 2 + CYAN = 3 + RED = 4 + MAGENTA = 5 + YELLOW = 6 + GREY = 7 + +# from wincon.h +class WinStyle(object): + NORMAL = 0x00 # dim text, dim background + BRIGHT = 0x08 # bright text, dim background + BRIGHT_BACKGROUND = 0x80 # dim text, bright background + +class WinTerm(object): + + def __init__(self): + self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes + self.set_attrs(self._default) + self._default_fore = self._fore + self._default_back = self._back + self._default_style = self._style + + def get_attrs(self): + return self._fore + self._back * 16 + self._style + + def set_attrs(self, value): + self._fore = value & 7 + self._back = (value >> 4) & 7 + self._style = value & (WinStyle.BRIGHT | WinStyle.BRIGHT_BACKGROUND) + + def reset_all(self, on_stderr=None): + self.set_attrs(self._default) + self.set_console(attrs=self._default) + + def fore(self, fore=None, light=False, on_stderr=False): + if fore is None: + fore = self._default_fore + self._fore = fore + if light: + self._style |= WinStyle.BRIGHT + self.set_console(on_stderr=on_stderr) + + def back(self, back=None, light=False, on_stderr=False): + if back is None: + back = self._default_back + self._back = back + if light: + self._style |= WinStyle.BRIGHT_BACKGROUND + self.set_console(on_stderr=on_stderr) + + def style(self, style=None, on_stderr=False): + if style is None: + style = self._default_style + self._style = style + self.set_console(on_stderr=on_stderr) + + def set_console(self, attrs=None, on_stderr=False): + if attrs is None: + attrs = self.get_attrs() + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleTextAttribute(handle, attrs) + + def get_position(self, handle): + position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition + # Because Windows coordinates are 0-based, + # and win32.SetConsoleCursorPosition expects 1-based. + position.X += 1 + position.Y += 1 + return position + + def set_cursor_position(self, position=None, on_stderr=False): + if position is None: + #I'm not currently tracking the position, so there is no default. + #position = self.get_position() + return + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleCursorPosition(handle, position) + + def cursor_adjust(self, x, y, on_stderr=False): + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + position = self.get_position(handle) + adjusted_position = (position.Y + y, position.X + x) + win32.SetConsoleCursorPosition(handle, adjusted_position, adjust=False) + + def erase_screen(self, mode=0, on_stderr=False): + # 0 should clear from the cursor to the end of the screen. + # 1 should clear from the cursor to the beginning of the screen. + # 2 should clear the entire screen, and move cursor to (1,1) + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + csbi = win32.GetConsoleScreenBufferInfo(handle) + # get the number of character cells in the current buffer + cells_in_screen = csbi.dwSize.X * csbi.dwSize.Y + # get number of character cells before current cursor position + cells_before_cursor = csbi.dwSize.X * csbi.dwCursorPosition.Y + csbi.dwCursorPosition.X + if mode == 0: + from_coord = csbi.dwCursorPosition + cells_to_erase = cells_in_screen - cells_before_cursor + if mode == 1: + from_coord = win32.COORD(0, 0) + cells_to_erase = cells_before_cursor + elif mode == 2: + from_coord = win32.COORD(0, 0) + cells_to_erase = cells_in_screen + # fill the entire screen with blanks + win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) + # now set the buffer's attributes accordingly + win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) + if mode == 2: + # put the cursor where needed + win32.SetConsoleCursorPosition(handle, (1, 1)) + + def erase_line(self, mode=0, on_stderr=False): + # 0 should clear from the cursor to the end of the line. + # 1 should clear from the cursor to the beginning of the line. + # 2 should clear the entire line. + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + csbi = win32.GetConsoleScreenBufferInfo(handle) + if mode == 0: + from_coord = csbi.dwCursorPosition + cells_to_erase = csbi.dwSize.X - csbi.dwCursorPosition.X + if mode == 1: + from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) + cells_to_erase = csbi.dwCursorPosition.X + elif mode == 2: + from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) + cells_to_erase = csbi.dwSize.X + # fill the entire screen with blanks + win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) + # now set the buffer's attributes accordingly + win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) + + def set_title(self, title): + win32.SetConsoleTitle(title) diff --git a/lib/colorlog/__init__.py b/lib/colorlog/__init__.py new file mode 100644 index 000000000..1d57f586d --- /dev/null +++ b/lib/colorlog/__init__.py @@ -0,0 +1,14 @@ +"""A logging formatter for colored output.""" + +from __future__ import absolute_import + +from colorlog.colorlog import ( + ColoredFormatter, escape_codes, default_log_colors) + +from colorlog.logging import ( + basicConfig, root, getLogger, log, + debug, info, warning, error, exception, critical) + +__all__ = ('ColoredFormatter', 'default_log_colors', 'escape_codes', + 'basicConfig', 'root', 'getLogger', 'debug', 'info', 'warning', + 'error', 'exception', 'critical', 'log', 'exception') diff --git a/lib/colorlog/colorlog.py b/lib/colorlog/colorlog.py new file mode 100644 index 000000000..49860dd50 --- /dev/null +++ b/lib/colorlog/colorlog.py @@ -0,0 +1,137 @@ +"""The ColoredFormatter class.""" + +from __future__ import absolute_import + +import logging +import collections +import sys + +from colorlog.escape_codes import escape_codes, parse_colors + +__all__ = ('escape_codes', 'default_log_colors', 'ColoredFormatter') + +# The default colors to use for the debug levels +default_log_colors = { + 'DEBUG': 'white', + 'INFO': 'green', + 'WARNING': 'yellow', + 'ERROR': 'red', + 'CRITICAL': 'bold_red', +} + +# The default format to use for each style +default_formats = { + '%': '%(log_color)s%(levelname)s:%(name)s:%(message)s', + '{': '{log_color}{levelname}:{name}:{message}', + '$': '${log_color}${levelname}:${name}:${message}' +} + + +class ColoredRecord(object): + """ + Wraps a LogRecord and attempts to parse missing keys as escape codes. + + When the record is formatted, the logging library uses ``record.__dict__`` + directly - so this class replaced the dict with a ``defaultdict`` that + checks if a missing key is an escape code. + """ + + class __dict(collections.defaultdict): + def __missing__(self, name): + try: + return parse_colors(name) + except Exception: + raise KeyError("{} is not a valid record attribute " + "or color sequence".format(name)) + + def __init__(self, record): + # Replace the internal dict with one that can handle missing keys + self.__dict__ = self.__dict() + self.__dict__.update(record.__dict__) + + # Keep a refrence to the original refrence so ``__getattr__`` can + # access functions that are not in ``__dict__`` + self.__record = record + + def __getattr__(self, name): + return getattr(self.__record, name) + + +class ColoredFormatter(logging.Formatter): + """ + A formatter that allows colors to be placed in the format string. + + Intended to help in creating more readable logging output. + """ + + def __init__(self, fmt=None, datefmt=None, + log_colors=None, reset=True, style='%', + secondary_log_colors=None): + """ + Set the format and colors the ColoredFormatter will use. + + The ``fmt``, ``datefmt`` and ``style`` args are passed on to the + ``logging.Formatter`` constructor. + + The ``secondary_log_colors`` argument can be used to create additional + ``log_color`` attributes. Each key in the dictionary will set + ``log_color_{key}``, using the value to select from a different + ``log_colors`` set. + + :Parameters: + - fmt (str): The format string to use + - datefmt (str): A format string for the date + - log_colors (dict): + A mapping of log level names to color names + - reset (bool): + Implictly append a color reset to all records unless False + - style ('%' or '{' or '$'): + The format style to use. (*No meaning prior to Python 3.2.*) + - secondary_log_colors (dict): + Map secondary ``log_color`` attributes. (*New in version 2.6.*) + """ + if fmt is None: + if sys.version_info > (3, 2): + fmt = default_formats[style] + else: + fmt = default_formats['%'] + + if sys.version_info > (3, 2): + super(ColoredFormatter, self).__init__(fmt, datefmt, style) + elif sys.version_info > (2, 7): + super(ColoredFormatter, self).__init__(fmt, datefmt) + else: + logging.Formatter.__init__(self, fmt, datefmt) + + self.log_colors = ( + log_colors if log_colors is not None else default_log_colors) + self.secondary_log_colors = secondary_log_colors + self.reset = reset + + def color(self, log_colors, name): + """Return escape codes from a ``log_colors`` dict.""" + return parse_colors(log_colors.get(name, "")) + + def format(self, record): + """Format a message from a record object.""" + record = ColoredRecord(record) + record.log_color = self.color(self.log_colors, record.levelname) + + # Set secondary log colors + if self.secondary_log_colors: + for name, log_colors in self.secondary_log_colors.items(): + color = self.color(log_colors, record.levelname) + setattr(record, name + '_log_color', color) + + # Format the message + if sys.version_info > (2, 7): + message = super(ColoredFormatter, self).format(record) + else: + message = logging.Formatter.format(self, record) + + # Add a reset code to the end of the message + # (if it wasn't explicitly added in format str) + if self.reset and not message.endswith(escape_codes['reset']): + message += escape_codes['reset'] + + return message diff --git a/lib/colorlog/escape_codes.py b/lib/colorlog/escape_codes.py new file mode 100644 index 000000000..848eb6489 --- /dev/null +++ b/lib/colorlog/escape_codes.py @@ -0,0 +1,57 @@ +""" +Generates a dictionary of ANSI escape codes. + +http://en.wikipedia.org/wiki/ANSI_escape_code + +Uses colorama as an optional dependancy to support color on Windows +""" + +try: + import colorama +except ImportError: + pass +else: + colorama.init() + +__all__ = ('escape_codes', 'parse_colors') + +# Returns escape codes from format codes +esc = lambda *x: '\033[' + ';'.join(x) + 'm' + +# The initial list of escape codes +escape_codes = { + 'reset': esc('0'), + 'bold': esc('01'), +} + +# The color names +COLORS = [ + 'black', + 'red', + 'green', + 'yellow', + 'blue', + 'purple', + 'cyan', + 'white' +] + +PREFIXES = [ + # Foreground without prefix + ('3', ''), ('01;3', 'bold_'), + + # Foreground with fg_ prefix + ('3', 'fg_'), ('01;3', 'fg_bold_'), + + # Background with bg_ prefix - bold/light works differently + ('4', 'bg_'), ('10', 'bg_bold_'), +] + +for prefix, prefix_name in PREFIXES: + for code, name in enumerate(COLORS): + escape_codes[prefix_name + name] = esc(prefix + str(code)) + + +def parse_colors(sequence): + """Return escape codes from a color sequence.""" + return ''.join(escape_codes[n] for n in sequence.split(',') if n) diff --git a/lib/colorlog/logging.py b/lib/colorlog/logging.py new file mode 100644 index 000000000..13f0c4ffb --- /dev/null +++ b/lib/colorlog/logging.py @@ -0,0 +1,44 @@ +"""Wrappers around the logging module.""" + +from __future__ import absolute_import + +import functools +import logging + +from colorlog.colorlog import ColoredFormatter + +BASIC_FORMAT = "%(log_color)s%(levelname)s%(reset)s:%(name)s:%(message)s" + + +def basicConfig(**kwargs): + """Call ``logging.basicConfig`` and override the formatter it creates.""" + logging.basicConfig(**kwargs) + logging._acquireLock() + try: + stream = logging.root.handlers[0] + stream.setFormatter( + ColoredFormatter( + fmt=kwargs.get('format', BASIC_FORMAT), + datefmt=kwargs.get('datefmt', None))) + finally: + logging._releaseLock() + + +def ensure_configured(func): + """Modify a function to call ``basicConfig`` first if no handlers exist.""" + @functools.wraps(func) + def wrapper(*args, **kwargs): + if len(logging.root.handlers) == 0: + basicConfig() + return func(*args, **kwargs) + return wrapper + +root = logging.root +getLogger = logging.getLogger +debug = ensure_configured(logging.debug) +info = ensure_configured(logging.info) +warning = ensure_configured(logging.warning) +error = ensure_configured(logging.error) +critical = ensure_configured(logging.critical) +log = ensure_configured(logging.log) +exception = ensure_configured(logging.exception) diff --git a/module/plugins/internal/CaptchaService.py b/module/plugins/internal/CaptchaService.py deleted file mode 100644 index ec938079a..000000000 --- a/module/plugins/internal/CaptchaService.py +++ /dev/null @@ -1,517 +0,0 @@ -# -*- coding: utf-8 -*- - -import re -import time - -from base64 import b64encode -from random import random, randint -from urlparse import urljoin, urlparse - -from module.common.json_layer import json_loads -from module.plugins.Plugin import Base - - -#@TODO: Extend (new) Plugin class; remove all `html` args -class CaptchaService(Base): - __name__ = "CaptchaService" - __type__ = "captcha" - __version__ = "0.26" - - __description__ = """Base captcha service plugin""" - __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org")] - - - key = None #: last key detected - - - def __init__(self, plugin): - self.plugin = plugin - super(CaptchaService, self).__init__(plugin.core) - - - def detect_key(self, html=None): - raise NotImplementedError - - - def challenge(self, key=None, html=None): - raise NotImplementedError - - - def result(self, server, challenge): - raise NotImplementedError - - -class ReCaptcha(CaptchaService): - __name__ = "ReCaptcha" - __type__ = "captcha" - __version__ = "0.15" - - __description__ = """ReCaptcha captcha service plugin""" - __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org"), - ("Walter Purcaro", "vuolter@gmail.com"), - ("zapp-brannigan", "fuerst.reinje@web.de")] - - - KEY_V2_PATTERN = r'(?:data-sitekey=["\']|["\']sitekey["\']:\s*["\'])([\w-]+)' - KEY_V1_PATTERN = r'(?:recaptcha(?:/api|\.net)/(?:challenge|noscript)\?k=|Recaptcha\.create\s*\(\s*["\'])([\w-]+)' - - - def detect_key(self, html=None): - if not html: - if hasattr(self.plugin, "html") and self.plugin.html: - html = self.plugin.html - else: - errmsg = _("ReCaptcha html not found") - self.plugin.fail(errmsg) - raise TypeError(errmsg) - - m = re.search(self.KEY_V2_PATTERN, html) or re.search(self.KEY_V1_PATTERN, html) - if m: - self.key = m.group(1).strip() - self.logDebug("Key: %s" % self.key) - return self.key - else: - self.logDebug("Key not found") - return None - - - def challenge(self, key=None, html=None, version=None): - if not key: - if self.detect_key(html): - key = self.key - else: - errmsg = _("ReCaptcha key not found") - self.plugin.fail(errmsg) - raise TypeError(errmsg) - - if version in (1, 2): - return getattr(self, "_challenge_v%s" % version)(key) - - elif not html and hasattr(self.plugin, "html") and self.plugin.html: - version = 2 if re.search(self.KEY_V2_PATTERN, self.plugin.html) else 1 - return self.challenge(key, self.plugin.html, version) - - else: - errmsg = _("ReCaptcha html not found") - self.plugin.fail(errmsg) - raise TypeError(errmsg) - - - def _challenge_v1(self, key): - html = self.plugin.req.load("http://www.google.com/recaptcha/api/challenge", - get={'k': key}) - try: - challenge = re.search("challenge : '(.+?)',", html).group(1) - server = re.search("server : '(.+?)',", html).group(1) - - except AttributeError: - errmsg = _("ReCaptcha challenge pattern not found") - self.plugin.fail(errmsg) - raise AttributeError(errmsg) - - self.logDebug("Challenge: %s" % challenge) - - return self.result(server, challenge), challenge - - - def result(self, server, challenge): - result = self.plugin.decryptCaptcha("%simage" % server, - get={'c': challenge}, - cookies=True, - forceUser=True, - imgtype="jpg") - - self.logDebug("Result: %s" % result) - - return result - - - def _collectApiInfo(self): - html = self.plugin.req.load("http://www.google.com/recaptcha/api.js") - a = re.search(r'po.src = \'(.*?)\';', html).group(1) - vers = a.split("/")[5] - - self.logDebug("API version: %s" %vers) - - language = a.split("__")[1].split(".")[0] - - self.logDebug("API language: %s" % language) - - html = self.plugin.req.load("https://apis.google.com/js/api.js") - b = re.search(r'"h":"(.*?)","', html).group(1) - jsh = b.decode('unicode-escape') - - self.logDebug("API jsh-string: %s" % jsh) - - return vers, language, jsh - - - def _prepareTimeAndRpc(self): - self.plugin.req.load("http://www.google.com/recaptcha/api2/demo") - - millis = int(round(time.time() * 1000)) - - self.logDebug("Time: %s" % millis) - - rand = randint(1, 99999999) - a = "0.%s" % str(rand * 2147483647) - rpc = int(100000000 * float(a)) - - self.logDebug("Rpc-token: %s" % rpc) - - return millis, rpc - - - def _challenge_v2(self, key, parent=None): - if parent is None: - try: - parent = urljoin("http://", urlparse(self.plugin.pyfile.url).netloc) - - except Exception: - parent = "" - - botguardstring = "!A" - vers, language, jsh = self._collectApiInfo() - millis, rpc = self._prepareTimeAndRpc() - - html = self.plugin.req.load("https://www.google.com/recaptcha/api2/anchor", - get={'k' : key, - 'hl' : language, - 'v' : vers, - 'usegapi' : "1", - 'jsh' : "%s#id=IO_%s" % (jsh, millis), - 'parent' : parent, - 'pfname' : "", - 'rpctoken': rpc}) - - token1 = re.search(r'id="recaptcha-token" value="(.*?)">', html) - self.logDebug("Token #1: %s" % token1.group(1)) - - html = self.plugin.req.load("https://www.google.com/recaptcha/api2/frame", - get={'c' : token1.group(1), - 'hl' : language, - 'v' : vers, - 'bg' : botguardstring, - 'k' : key, - 'usegapi': "1", - 'jsh' : jsh}).decode('unicode-escape') - - token2 = re.search(r'"finput","(.*?)",', html) - self.logDebug("Token #2: %s" % token2.group(1)) - - token3 = re.search(r'"rresp","(.*?)",', html) - self.logDebug("Token #3: %s" % token3.group(1)) - - millis_captcha_loading = int(round(time.time() * 1000)) - captcha_response = self.plugin.decryptCaptcha("https://www.google.com/recaptcha/api2/payload", - get={'c':token3.group(1), 'k':key}, - cookies=True, - forceUser=True) - response = b64encode('{"response":"%s"}' % captcha_response) - - self.logDebug("Result: %s" % response) - - timeToSolve = int(round(time.time() * 1000)) - millis_captcha_loading - timeToSolveMore = timeToSolve + int(float("0." + str(randint(1, 99999999))) * 500) - - html = self.plugin.req.load("https://www.google.com/recaptcha/api2/userverify", - post={'k' : key, - 'c' : token3.group(1), - 'response': response, - 't' : timeToSolve, - 'ct' : timeToSolveMore, - 'bg' : botguardstring}) - - token4 = re.search(r'"uvresp","(.*?)",', html) - self.logDebug("Token #4: %s" % token4.group(1)) - - result = token4.group(1) - - return result, None - - -class AdsCaptcha(CaptchaService): - __name__ = "AdsCaptcha" - __type__ = "captcha" - __version__ = "0.08" - - __description__ = """AdsCaptcha captcha service plugin""" - __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org")] - - - CAPTCHAID_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?.*?CaptchaId=(\d+)' - PUBLICKEY_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?.*?PublicKey=([\w-]+)' - - - def detect_key(self, html=None): - if not html: - if hasattr(self.plugin, "html") and self.plugin.html: - html = self.plugin.html - else: - errmsg = _("AdsCaptcha html not found") - self.plugin.fail(errmsg) - raise TypeError(errmsg) - - m = re.search(self.PUBLICKEY_PATTERN, html) - n = re.search(self.CAPTCHAID_PATTERN, html) - if m and n: - self.key = (m.group(1).strip(), n.group(1).strip()) #: key is the tuple(PublicKey, CaptchaId) - self.logDebug("Key|id: %s | %s" % self.key) - return self.key - else: - self.logDebug("Key or id not found") - return None - - - def challenge(self, key=None, html=None): - if not key: - if self.detect_key(html): - key = self.key - else: - errmsg = _("AdsCaptcha key not found") - self.plugin.fail(errmsg) - raise TypeError(errmsg) - - PublicKey, CaptchaId = key - - html = self.plugin.req.load("http://api.adscaptcha.com/Get.aspx", - get={'CaptchaId': CaptchaId, - 'PublicKey': PublicKey}) - try: - challenge = re.search("challenge: '(.+?)',", html).group(1) - server = re.search("server: '(.+?)',", html).group(1) - - except AttributeError: - errmsg = _("AdsCaptcha challenge pattern not found") - self.plugin.fail(errmsg) - raise AttributeError(errmsg) - - self.logDebug("Challenge: %s" % challenge) - - return self.result(server, challenge), challenge - - - def result(self, server, challenge): - result = self.plugin.decryptCaptcha("%sChallenge.aspx" % server, - get={'cid': challenge, 'dummy': random()}, - cookies=True, - imgtype="jpg") - - self.logDebug("Result: %s" % result) - - return result - - -class SolveMedia(CaptchaService): - __name__ = "SolveMedia" - __type__ = "captcha" - __version__ = "0.12" - - __description__ = """SolveMedia captcha service plugin""" - __license__ = "GPLv3" - __authors__ = [("pyLoad Team", "admin@pyload.org")] - - - KEY_PATTERN = r'api\.solvemedia\.com/papi/challenge\.(?:no)?script\?k=(.+?)["\']' - - - def detect_key(self, html=None): - if not html: - if hasattr(self.plugin, "html") and self.plugin.html: - html = self.plugin.html - else: - errmsg = _("SolveMedia html not found") - self.plugin.fail(errmsg) - raise TypeError(errmsg) - - m = re.search(self.KEY_PATTERN, html) - if m: - self.key = m.group(1).strip() - self.logDebug("Key: %s" % self.key) - return self.key - else: - self.logDebug("Key not found") - return None - - - def challenge(self, key=None, html=None): - if not key: - if self.detect_key(html): - key = self.key - else: - errmsg = _("SolveMedia key not found") - self.plugin.fail(errmsg) - raise TypeError(errmsg) - - html = self.plugin.req.load("http://api.solvemedia.com/papi/challenge.noscript", - get={'k': key}) - try: - challenge = re.search(r'<input type=hidden name="adcopy_challenge" id="adcopy_challenge" value="(.+?)">', - html).group(1) - server = "http://api.solvemedia.com/papi/media" - - except AttributeError: - errmsg = _("SolveMedia challenge pattern not found") - self.plugin.fail(errmsg) - raise AttributeError(errmsg) - - self.logDebug("Challenge: %s" % challenge) - - result = self.result(server, challenge) - - try: - magic = re.search(r'name="magic" value="(.+?)"', html).group(1) - - except AttributeError: - self.logDebug("Magic code not found") - - else: - if not self._verify(key, magic, result, challenge): - self.logDebug("Captcha code was invalid") - - return result, challenge - - - def _verify(self, key, magic, result, challenge, ref=None): #@TODO: Clean up - if ref is None: - try: - ref = self.plugin.pyfile.url - - except Exception: - ref = "" - - html = self.plugin.req.load("http://api.solvemedia.com/papi/verify.noscript", - post={'adcopy_response' : result, - 'k' : key, - 'l' : "en", - 't' : "img", - 's' : "standard", - 'magic' : magic, - 'adcopy_challenge' : challenge, - 'ref' : ref}) - try: - html = self.plugin.req.load(re.search(r'URL=(.+?)">', html).group(1)) - gibberish = re.search(r'id=gibberish>(.+?)</textarea>', html).group(1) - - except Exception: - return False - - else: - return True - - - def result(self, server, challenge): - result = self.plugin.decryptCaptcha(server, - get={'c': challenge}, - cookies=True, - imgtype="gif") - - self.logDebug("Result: %s" % result) - - return result - - -class AdYouLike(CaptchaService): - __name__ = "AdYouLike" - __type__ = "captcha" - __version__ = "0.05" - - __description__ = """AdYouLike captcha service plugin""" - __license__ = "GPLv3" - __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - - - AYL_PATTERN = r'Adyoulike\.create\s*\((.+?)\)' - CALLBACK_PATTERN = r'(Adyoulike\.g\._jsonp_\d+)' - - - def detect_key(self, html=None): - if not html: - if hasattr(self.plugin, "html") and self.plugin.html: - html = self.plugin.html - else: - errmsg = _("AdYouLike html not found") - self.plugin.fail(errmsg) - raise TypeError(errmsg) - - m = re.search(self.AYL_PATTERN, html) - n = re.search(self.CALLBACK_PATTERN, html) - if m and n: - self.key = (m.group(1).strip(), n.group(1).strip()) - self.logDebug("Ayl|callback: %s | %s" % self.key) - return self.key #: key is the tuple(ayl, callback) - else: - self.logDebug("Ayl or callback not found") - return None - - - def challenge(self, key=None, html=None): - if not key: - if self.detect_key(html): - key = self.key - else: - errmsg = _("AdYouLike key not found") - self.plugin.fail(errmsg) - raise TypeError(errmsg) - - ayl, callback = key - - # {"adyoulike":{"key":"P~zQ~O0zV0WTiAzC-iw0navWQpCLoYEP"}, - # "all":{"element_id":"ayl_private_cap_92300","lang":"fr","env":"prod"}} - ayl = json_loads(ayl) - - html = self.plugin.req.load("http://api-ayl.appspot.com/challenge", - get={'key' : ayl['adyoulike']['key'], - 'env' : ayl['all']['env'], - 'callback': callback}) - try: - challenge = json_loads(re.search(callback + r'\s*\((.+?)\)', html).group(1)) - - except AttributeError: - errmsg = _("AdYouLike challenge pattern not found") - self.plugin.fail(errmsg) - raise AttributeError(errmsg) - - self.logDebug("Challenge: %s" % challenge) - - return self.result(ayl, challenge), challenge - - - def result(self, server, challenge): - # Adyoulike.g._jsonp_5579316662423138 - # ({"translations":{"fr":{"instructions_visual":"Recopiez « Soonnight » ci-dessous :"}}, - # "site_under":true,"clickable":true,"pixels":{"VIDEO_050":[],"DISPLAY":[],"VIDEO_000":[],"VIDEO_100":[], - # "VIDEO_025":[],"VIDEO_075":[]},"medium_type":"image/adyoulike", - # "iframes":{"big":"<iframe src=\"http://www.soonnight.com/campagn.html\" scrolling=\"no\" - # height=\"250\" width=\"300\" frameborder=\"0\"></iframe>"},"shares":{},"id":256, - # "token":"e6QuI4aRSnbIZJg02IsV6cp4JQ9~MjA1","formats":{"small":{"y":300,"x":0,"w":300,"h":60}, - # "big":{"y":0,"x":0,"w":300,"h":250},"hover":{"y":440,"x":0,"w":300,"h":60}}, - # "tid":"SqwuAdxT1EZoi4B5q0T63LN2AkiCJBg5"}) - - if isinstance(server, basestring): - server = json_loads(server) - - if isinstance(challenge, basestring): - challenge = json_loads(challenge) - - try: - instructions_visual = challenge['translations'][server['all']['lang']]['instructions_visual'] - result = re.search(u'«(.+?)»', instructions_visual).group(1).strip() - - except AttributeError: - errmsg = _("AdYouLike result not found") - self.plugin.fail(errmsg) - raise AttributeError(errmsg) - - result = {'_ayl_captcha_engine' : "adyoulike", - '_ayl_env' : server['all']['env'], - '_ayl_tid' : challenge['tid'], - '_ayl_token_challenge': challenge['token'], - '_ayl_response' : response} - - self.logDebug("Result: %s" % result) - - return result diff --git a/pyload/database/File.py b/pyload/database/File.py index 1fab376b1..857da1ff9 100644 --- a/pyload/database/File.py +++ b/pyload/database/File.py @@ -33,7 +33,7 @@ class FileHandler(object): self.jobCache = {} - self.lock = RLock() # @TODO should be a Lock w/o R + self.lock = RLock() #@TODO: should be a Lock w/o R #self.lock._Verbose__verbose = True self.filecount = -1 # if an invalid value is set get current value from db @@ -111,7 +111,7 @@ class FileHandler(object): self.db.addLinks(data, package) self.core.threadManager.createInfoThread(data, package) - #@TODO change from reloadAll event to package update event + #@TODO: change from reloadAll event to package update event self.core.pullManager.addEvent(ReloadAllEvent("collector")) #-------------------------------------------------------------------------- @@ -278,8 +278,8 @@ class FileHandler(object): def getJob(self, occ): """get suitable job""" - #@TODO clean mess - #@TODO improve selection of valid jobs + #@TODO: clean mess + #@TODO: improve selection of valid jobs if occ in self.jobCache: if self.jobCache[occ]: @@ -815,7 +815,7 @@ class FileMethods(object): def getJob(self, occ): """return pyfile ids, which are suitable for download and dont use a occupied plugin""" - #@TODO improve this hardcoded method + #@TODO: improve this hardcoded method pre = "('CCF', 'DLC', 'LinkList', 'RSDF', 'TXT')" # plugins which are processed in collector cmd = "(" diff --git a/pyload/datatype/File.py b/pyload/datatype/File.py index 0445e8089..0dadbd7f8 100644 --- a/pyload/datatype/File.py +++ b/pyload/datatype/File.py @@ -101,7 +101,7 @@ class PyFile(object): def setStatus(self, status): self.status = statusMap[status] - self.sync() # @TODO needed aslong no better job approving exists + self.sync() #@TODO: needed aslong no better job approving exists def setCustomStatus(self, msg, status="processing"): self.statusname = msg diff --git a/pyload/plugin/Plugin.py b/pyload/plugin/Plugin.py index af70232e0..c14155751 100644 --- a/pyload/plugin/Plugin.py +++ b/pyload/plugin/Plugin.py @@ -7,6 +7,9 @@ from random import randint import os import re +import urllib +import urlparse + from os import remove, makedirs, chmod, stat from os.path import exists, join @@ -17,7 +20,6 @@ if os.name != "nt": from itertools import islice from traceback import print_exc -from urlparse import urlparse from pyload.utils import fs_decode, fs_encode, safe_filename, fs_join, encode @@ -217,7 +219,7 @@ class Plugin(Base): #: captcha task self.cTask = None - self.html = None # @TODO: Move to hoster class in 0.4.10 + self.html = None #@TODO: Move to hoster class in 0.4.10 self.retries = 0 self.init() @@ -490,7 +492,7 @@ class Plugin(Base): if not url: self.fail(_("No url given")) - url = encode(url).strip() # @NOTE: utf8 vs decode -> please use decode attribute in all future plugins + url = urllib.unquote(encode(url).strip()) #@NOTE: utf8 vs decode -> please use decode attribute in all future plugins if self.core.debug: self.logDebug("Load url: " + url, *["%s=%s" % (key, val) for key, val in locals().iteritems() if key not in ("self", "url")]) @@ -555,7 +557,7 @@ class Plugin(Base): if not url: self.fail(_("No url given")) - url = encode(url).strip() + url = urllib.unquote(encode(url).strip()) if self.core.debug: self.logDebug("Download url: " + url, *["%s=%s" % (key, val) for key, val in locals().iteritems() if key not in ("self", "url")]) @@ -564,6 +566,9 @@ class Plugin(Base): self.pyfile.setStatus("downloading") + if disposition: + self.pyfile.name = urlparse.urlparse(url).path.split('/')[-1] or self.pyfile.name + download_folder = self.core.config['general']['download_folder'] location = fs_join(download_folder, self.pyfile.package().folder) @@ -596,7 +601,7 @@ class Plugin(Base): self.pyfile.size = self.req.size if newname: - newname = urlparse(newname).path.split("/")[-1] + newname = urlparse.urlparse(newname).path.split('/')[-1] if disposition and newname != name: self.logInfo(_("%(name)s saved as %(newname)s") % {"name": name, "newname": newname}) diff --git a/pyload/plugin/addon/AntiVirus.py b/pyload/plugin/addon/AntiVirus.py index 2213cddc1..6fae3b532 100644 --- a/pyload/plugin/addon/AntiVirus.py +++ b/pyload/plugin/addon/AntiVirus.py @@ -27,9 +27,6 @@ class AntiVirus(Addon): __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - interval = 0 #@TODO: Remove in 0.4.10 - - def setup(self): self.info = {} #@TODO: Remove in 0.4.10 diff --git a/pyload/plugin/addon/UpdateManager.py b/pyload/plugin/addon/UpdateManager.py index c5bee16a1..0837918d3 100644 --- a/pyload/plugin/addon/UpdateManager.py +++ b/pyload/plugin/addon/UpdateManager.py @@ -32,7 +32,7 @@ class UpdateManager(Addon): __type__ = "addon" __version__ = "0.50" - __config__ = [("activated", "bool", "Activated", True), + __config__ = [("activated", "bool", "Activated", False), ("checkinterval", "int", "Check interval in hours", 8), ("autorestart", "bool", "Auto-restart pyLoad when required", True), @@ -83,7 +83,7 @@ class UpdateManager(Addon): def autoreloadPlugins(self): """ reload and reindex all modified plugins """ modules = filter( - lambda m: m and (m.__name__.startswith("module.plugins.") or + lambda m: m and (m.__name__.startswith("pyload.plugin.") or m.__name__.startswith("userplugins.")) and m.__name__.count(".") >= 2, sys.modules.itervalues() ) diff --git a/module/plugins/hooks/UserAgentSwitcher.py b/pyload/plugin/addon/UserAgentSwitcher.py index 912c2ef09..46807da67 100644 --- a/module/plugins/hooks/UserAgentSwitcher.py +++ b/pyload/plugin/addon/UserAgentSwitcher.py @@ -6,13 +6,13 @@ import os import pycurl import random -from module.plugins.Hook import Hook -from module.utils import fs_encode +from pyload.plugin.Addon import Addon +from pyload.utils import fs_encode -class UserAgentSwitcher(Hook): +class UserAgentSwitcher(Addon): __name__ = "UserAgentSwitcher" - __type__ = "hook" + __type__ = "addon" __version__ = "0.04" __config__ = [("activated", "bool", "Activated" , True ), @@ -25,9 +25,6 @@ class UserAgentSwitcher(Hook): __authors__ = [("Walter Purcaro", "vuolter@gmail.com")] - interval = 0 #@TODO: Remove in 0.4.10 - - def setup(self): self.info = {} #@TODO: Remove in 0.4.10 diff --git a/pyload/plugin/captcha/AdsCaptcha.py b/pyload/plugin/captcha/AdsCaptcha.py index 5b23247c0..89579881f 100644 --- a/pyload/plugin/captcha/AdsCaptcha.py +++ b/pyload/plugin/captcha/AdsCaptcha.py @@ -17,8 +17,8 @@ class AdsCaptcha(Captcha): __authors__ = [("pyLoad Team", "admin@pyload.org")] - CAPTCHAID_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?[^"\']*CaptchaId=(\d+)' - PUBLICKEY_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?[^"\']*PublicKey=([\w-]+)' + CAPTCHAID_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?.*?CaptchaId=(\d+)' + PUBLICKEY_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?.*?PublicKey=([\w-]+)' def detect_key(self, html=None): diff --git a/pyload/plugin/captcha/ReCaptcha.py b/pyload/plugin/captcha/ReCaptcha.py index 6dcb09f55..4920262b2 100644 --- a/pyload/plugin/captcha/ReCaptcha.py +++ b/pyload/plugin/captcha/ReCaptcha.py @@ -13,7 +13,7 @@ from pyload.plugin.Captcha import Captcha class ReCaptcha(Captcha): __name__ = "ReCaptcha" __type__ = "captcha" - __version__ = "0.14" + __version__ = "0.15" __description__ = """ReCaptcha captcha service plugin""" __license__ = "GPLv3" @@ -161,21 +161,12 @@ class ReCaptcha(Captcha): token2 = re.search(r'"finput","(.*?)",', html) self.logDebug("Token #2: %s" % token2.group(1)) - token3 = re.search(r'."asconf".\s,".*?".\s,"(.*?)".', html) + token3 = re.search(r'"rresp","(.*?)",', html) self.logDebug("Token #3: %s" % token3.group(1)) - html = self.plugin.req.load("https://www.google.com/recaptcha/api2/reload", - post={'k' : key, - 'c' : token2.group(1), - 'reason': "fi", - 'fbg' : token3.group(1)}) - - token4 = re.search(r'"rresp","(.*?)",', html) - self.logDebug("Token #4: %s" % token4.group(1)) - millis_captcha_loading = int(round(time.time() * 1000)) captcha_response = self.plugin.decryptCaptcha("https://www.google.com/recaptcha/api2/payload", - get={'c': token4.group(1), 'k': key}, + get={'c':token3.group(1), 'k':key}, cookies=True, forceUser=True) response = b64encode('{"response":"%s"}' % captcha_response) @@ -187,15 +178,15 @@ class ReCaptcha(Captcha): html = self.plugin.req.load("https://www.google.com/recaptcha/api2/userverify", post={'k' : key, - 'c' : token4.group(1), + 'c' : token3.group(1), 'response': response, 't' : timeToSolve, 'ct' : timeToSolveMore, 'bg' : botguardstring}) - token5 = re.search(r'"uvresp","(.*?)",', html) - self.logDebug("Token #5: %s" % token5.group(1)) + token4 = re.search(r'"uvresp","(.*?)",', html) + self.logDebug("Token #4: %s" % token4.group(1)) - result = token5.group(1) + result = token4.group(1) return result, None diff --git a/pyload/plugin/captcha/SolveMedia.py b/pyload/plugin/captcha/SolveMedia.py index 7f421f490..45f7a69e8 100644 --- a/pyload/plugin/captcha/SolveMedia.py +++ b/pyload/plugin/captcha/SolveMedia.py @@ -49,7 +49,7 @@ class SolveMedia(Captcha): html = self.plugin.req.load("http://api.solvemedia.com/papi/challenge.noscript", get={'k': key}) try: - challenge = re.search(r'<input type=hidden name="adcopy_challenge" id="adcopy_challenge" value="([^"]+)">', + challenge = re.search(r'<input type=hidden name="adcopy_challenge" id="adcopy_challenge" value="(.+?)">', html).group(1) server = "http://api.solvemedia.com/papi/media" diff --git a/pyload/plugin/container/CCF.py b/pyload/plugin/container/CCF.py index 65f96033a..d984e23dc 100644 --- a/pyload/plugin/container/CCF.py +++ b/pyload/plugin/container/CCF.py @@ -3,8 +3,7 @@ from __future__ import with_statement import re - -from urllib2 import build_opener +import urllib2 from MultipartPostHandler import MultipartPostHandler @@ -27,7 +26,7 @@ class CCF(Container): def decrypt(self, pyfile): fs_filename = fs_encode(pyfile.url.strip()) - opener = build_opener(MultipartPostHandler) + opener = urllib2.build_opener(MultipartPostHandler) dlc_content = opener.open('http://service.jdownloader.net/dlcrypt/getDLC.php', {'src' : "ccf", diff --git a/module/plugins/hooks/AlldebridComHook.py b/pyload/plugin/hook/AlldebridCom.py index 367181aa4..3d05fb761 100644 --- a/module/plugins/hooks/AlldebridComHook.py +++ b/pyload/plugin/hook/AlldebridCom.py @@ -3,8 +3,8 @@ from pyload.plugin.internal.MultiHook import MultiHook -class AlldebridComHook(MultiHook): - __name__ = "AlldebridComHook" +class AlldebridCom(MultiHook): + __name__ = "AlldebridCom" __type__ = "hook" __version__ = "0.16" diff --git a/module/plugins/hooks/DebridItaliaComHook.py b/pyload/plugin/hook/DebridItaliaCom.py index c1452b520..e7760ba5a 100644 --- a/module/plugins/hooks/DebridItaliaComHook.py +++ b/pyload/plugin/hook/DebridItaliaCom.py @@ -5,8 +5,8 @@ import re from pyload.plugin.internal.MultiHook import MultiHook -class DebridItaliaComHook(MultiHook): - __name__ = "DebridItaliaComHook" +class DebridItaliaCom(MultiHook): + __name__ = "DebridItaliaCom" __type__ = "hook" __version__ = "0.12" diff --git a/module/plugins/hooks/EasybytezComHook.py b/pyload/plugin/hook/EasybytezCom.py index 2f4ed72a8..79640a367 100644 --- a/module/plugins/hooks/EasybytezComHook.py +++ b/pyload/plugin/hook/EasybytezCom.py @@ -5,8 +5,8 @@ import re from pyload.plugin.internal.MultiHook import MultiHook -class EasybytezComHook(MultiHook): - __name__ = "EasybytezComHook" +class EasybytezCom(MultiHook): + __name__ = "EasybytezCom" __type__ = "hook" __version__ = "0.07" diff --git a/module/plugins/hooks/FastixRuHook.py b/pyload/plugin/hook/FastixRu.py index 4e03e887b..d0e2ff2fd 100644 --- a/module/plugins/hooks/FastixRuHook.py +++ b/pyload/plugin/hook/FastixRu.py @@ -4,8 +4,8 @@ from pyload.utils import json_loads from pyload.plugin.internal.MultiHook import MultiHook -class FastixRuHook(MultiHook): - __name__ = "FastixRuHook" +class FastixRu(MultiHook): + __name__ = "FastixRu" __type__ = "hook" __version__ = "0.05" diff --git a/module/plugins/hooks/FreeWayMeHook.py b/pyload/plugin/hook/FreeWayMe.py index c498725f5..086824550 100644 --- a/module/plugins/hooks/FreeWayMeHook.py +++ b/pyload/plugin/hook/FreeWayMe.py @@ -3,8 +3,8 @@ from pyload.plugin.internal.MultiHook import MultiHook -class FreeWayMeHook(MultiHook): - __name__ = "FreeWayMeHook" +class FreeWayMe(MultiHook): + __name__ = "FreeWayMe" __type__ = "hook" __version__ = "0.15" diff --git a/module/plugins/hooks/LinkdecrypterComHook.py b/pyload/plugin/hook/LinkdecrypterCom.py index d8c0018c9..446e33327 100644 --- a/module/plugins/hooks/LinkdecrypterComHook.py +++ b/pyload/plugin/hook/LinkdecrypterCom.py @@ -5,8 +5,8 @@ import re from pyload.plugin.internal.MultiHook import MultiHook -class LinkdecrypterComHook(MultiHook): - __name__ = "LinkdecrypterComHook" +class LinkdecrypterCom(MultiHook): + __name__ = "LinkdecrypterCom" __type__ = "hook" __version__ = "1.04" diff --git a/module/plugins/hooks/LinksnappyComHook.py b/pyload/plugin/hook/LinksnappyCom.py index 22b958b31..7eddc5811 100644 --- a/module/plugins/hooks/LinksnappyComHook.py +++ b/pyload/plugin/hook/LinksnappyCom.py @@ -4,8 +4,8 @@ from pyload.utils import json_loads from pyload.plugin.internal.MultiHook import MultiHook -class LinksnappyComHook(MultiHook): - __name__ = "LinksnappyComHook" +class LinksnappyCom(MultiHook): + __name__ = "LinksnappyCom" __type__ = "hook" __version__ = "0.04" diff --git a/module/plugins/hooks/MegaDebridEuHook.py b/pyload/plugin/hook/MegaDebridEu.py index 1d086b9d1..e373a544b 100644 --- a/module/plugins/hooks/MegaDebridEuHook.py +++ b/pyload/plugin/hook/MegaDebridEu.py @@ -4,8 +4,8 @@ from pyload.utils import json_loads from pyload.plugin.internal.MultiHook import MultiHook -class MegaDebridEuHook(MultiHook): - __name__ = "MegaDebridEuHook" +class MegaDebridEu(MultiHook): + __name__ = "MegaDebridEu" __type__ = "hook" __version__ = "0.05" diff --git a/module/plugins/hooks/MegaRapidoNetHook.py b/pyload/plugin/hook/MegaRapidoNet.py index 1fe8d4923..2f660c939 100644 --- a/module/plugins/hooks/MegaRapidoNetHook.py +++ b/pyload/plugin/hook/MegaRapidoNet.py @@ -5,8 +5,8 @@ import re from pyload.plugin.internal.MultiHook import MultiHook -class MegaRapidoNetHook(MultiHook): - __name__ = "MegaRapidoNetHook" +class MegaRapidoNet(MultiHook): + __name__ = "MegaRapidoNet" __type__ = "hook" __version__ = "0.02" diff --git a/module/plugins/hooks/MultihostersComHook.py b/pyload/plugin/hook/MultihostersCom.py index 7b92089a1..7b92089a1 100644 --- a/module/plugins/hooks/MultihostersComHook.py +++ b/pyload/plugin/hook/MultihostersCom.py diff --git a/module/plugins/hooks/MultishareCzHook.py b/pyload/plugin/hook/MultishareCz.py index 70cc8d7a9..97cbf9b4d 100644 --- a/module/plugins/hooks/MultishareCzHook.py +++ b/pyload/plugin/hook/MultishareCz.py @@ -5,8 +5,8 @@ import re from pyload.plugin.internal.MultiHook import MultiHook -class MultishareCzHook(MultiHook): - __name__ = "MultishareCzHook" +class MultishareCz(MultiHook): + __name__ = "MultishareCz" __type__ = "hook" __version__ = "0.07" diff --git a/module/plugins/hooks/MyfastfileComHook.py b/pyload/plugin/hook/MyfastfileCom.py index a9438f400..3149e832c 100644 --- a/module/plugins/hooks/MyfastfileComHook.py +++ b/pyload/plugin/hook/MyfastfileCom.py @@ -4,8 +4,8 @@ from pyload.plugin.internal.MultiHook import MultiHook from pyload.utils import json_loads -class MyfastfileComHook(MultiHook): - __name__ = "MyfastfileComHook" +class MyfastfileCom(MultiHook): + __name__ = "MyfastfileCom" __type__ = "hook" __version__ = "0.05" diff --git a/module/plugins/hooks/NoPremiumPlHook.py b/pyload/plugin/hook/NoPremiumPl.py index 743f18fc0..93c5b8d1e 100644 --- a/module/plugins/hooks/NoPremiumPlHook.py +++ b/pyload/plugin/hook/NoPremiumPl.py @@ -4,8 +4,8 @@ from pyload.utils import json_loads from pyload.plugin.internal.MultiHook import MultiHook -class NoPremiumPlHook(MultiHook): - __name__ = "NoPremiumPlHook" +class NoPremiumPl(MultiHook): + __name__ = "NoPremiumPl" __type__ = "hook" __version__ = "0.03" diff --git a/module/plugins/hooks/OverLoadMeHook.py b/pyload/plugin/hook/OverLoadMe.py index 58d419416..6db7c1fa2 100644 --- a/module/plugins/hooks/OverLoadMeHook.py +++ b/pyload/plugin/hook/OverLoadMe.py @@ -3,8 +3,8 @@ from pyload.plugin.internal.MultiHook import MultiHook -class OverLoadMeHook(MultiHook): - __name__ = "OverLoadMeHook" +class OverLoadMe(MultiHook): + __name__ = "OverLoadMe" __type__ = "hook" __version__ = "0.04" diff --git a/module/plugins/hooks/PremiumToHook.py b/pyload/plugin/hook/PremiumTo.py index 8cd2ef0e5..51e801c4f 100644 --- a/module/plugins/hooks/PremiumToHook.py +++ b/pyload/plugin/hook/PremiumTo.py @@ -3,8 +3,8 @@ from pyload.plugin.internal.MultiHook import MultiHook -class PremiumToHook(MultiHook): - __name__ = "PremiumToHook" +class PremiumTo(MultiHook): + __name__ = "PremiumTo" __type__ = "hook" __version__ = "0.08" diff --git a/module/plugins/hooks/PremiumizeMeHook.py b/pyload/plugin/hook/PremiumizeMe.py index 1b6444f00..209db7c75 100644 --- a/module/plugins/hooks/PremiumizeMeHook.py +++ b/pyload/plugin/hook/PremiumizeMe.py @@ -4,8 +4,8 @@ from pyload.utils import json_loads from pyload.plugin.internal.MultiHook import MultiHook -class PremiumizeMeHook(MultiHook): - __name__ = "PremiumizeMeHook" +class PremiumizeMe(MultiHook): + __name__ = "PremiumizeMe" __type__ = "hook" __version__ = "0.17" diff --git a/module/plugins/hooks/PutdriveComHook.py b/pyload/plugin/hook/PutdriveCom.py index 85e2f541d..85e2f541d 100644 --- a/module/plugins/hooks/PutdriveComHook.py +++ b/pyload/plugin/hook/PutdriveCom.py diff --git a/module/plugins/hooks/RPNetBizHook.py b/pyload/plugin/hook/RPNetBiz.py index c7893ef46..e8afb4fc0 100644 --- a/module/plugins/hooks/RPNetBizHook.py +++ b/pyload/plugin/hook/RPNetBiz.py @@ -4,8 +4,8 @@ from pyload.utils import json_loads from pyload.plugin.internal.MultiHook import MultiHook -class RPNetBizHook(MultiHook): - __name__ = "RPNetBizHook" +class RPNetBiz(MultiHook): + __name__ = "RPNetBiz" __type__ = "hook" __version__ = "0.14" diff --git a/module/plugins/hooks/RapideoPlHook.py b/pyload/plugin/hook/RapideoPl.py index dd68fb244..74bad2cfd 100644 --- a/module/plugins/hooks/RapideoPlHook.py +++ b/pyload/plugin/hook/RapideoPl.py @@ -4,8 +4,8 @@ from pyload.utils import json_loads from pyload.plugin.internal.MultiHook import MultiHook -class RapideoPlHook(MultiHook): - __name__ = "RapideoPlHook" +class RapideoPl(MultiHook): + __name__ = "RapideoPl" __type__ = "hook" __version__ = "0.03" diff --git a/module/plugins/hooks/RealdebridComHook.py b/pyload/plugin/hook/RealdebridCom.py index 6399d6dc2..74a114105 100644 --- a/module/plugins/hooks/RealdebridComHook.py +++ b/pyload/plugin/hook/RealdebridCom.py @@ -3,8 +3,8 @@ from pyload.plugin.internal.MultiHook import MultiHook -class RealdebridComHook(MultiHook): - __name__ = "RealdebridComHook" +class RealdebridCom(MultiHook): + __name__ = "RealdebridCom" __type__ = "hook" __version__ = "0.46" diff --git a/module/plugins/hooks/RehostToHook.py b/pyload/plugin/hook/RehostTo.py index b55f4cdb7..69978edaa 100644 --- a/module/plugins/hooks/RehostToHook.py +++ b/pyload/plugin/hook/RehostTo.py @@ -3,8 +3,8 @@ from pyload.plugin.internal.MultiHook import MultiHook -class RehostToHook(MultiHook): - __name__ = "RehostToHook" +class RehostTo(MultiHook): + __name__ = "RehostTo" __type__ = "hook" __version__ = "0.50" diff --git a/module/plugins/hooks/SimplyPremiumComHook.py b/pyload/plugin/hook/SimplyPremiumCom.py index ee125cbf6..9f696666f 100644 --- a/module/plugins/hooks/SimplyPremiumComHook.py +++ b/pyload/plugin/hook/SimplyPremiumCom.py @@ -4,8 +4,8 @@ from pyload.utils import json_loads from pyload.plugin.internal.MultiHook import MultiHook -class SimplyPremiumComHook(MultiHook): - __name__ = "SimplyPremiumComHook" +class SimplyPremiumCom(MultiHook): + __name__ = "SimplyPremiumCom" __type__ = "hook" __version__ = "0.05" diff --git a/module/plugins/hooks/SimplydebridComHook.py b/pyload/plugin/hook/SimplydebridCom.py index 2e9da87bd..74eba106e 100644 --- a/module/plugins/hooks/SimplydebridComHook.py +++ b/pyload/plugin/hook/SimplydebridCom.py @@ -3,8 +3,8 @@ from pyload.plugin.internal.MultiHook import MultiHook -class SimplydebridComHook(MultiHook): - __name__ = "SimplydebridComHook" +class SimplydebridCom(MultiHook): + __name__ = "SimplydebridCom" __type__ = "hook" __version__ = "0.04" diff --git a/module/plugins/hooks/SmoozedComHook.py b/pyload/plugin/hook/SmoozedCom.py index 786f85491..37c0d9bcb 100644 --- a/module/plugins/hooks/SmoozedComHook.py +++ b/pyload/plugin/hook/SmoozedCom.py @@ -3,8 +3,8 @@ from pyload.plugin.internal.MultiHook import MultiHook -class SmoozedComHook(MultiHook): - __name__ = "SmoozedComHook" +class SmoozedCom(MultiHook): + __name__ = "SmoozedCom" __type__ = "hook" __version__ = "0.03" diff --git a/module/plugins/hooks/UnrestrictLiHook.py b/pyload/plugin/hook/UnrestrictLi.py index 8f9bdaaf5..a0fb53004 100644 --- a/module/plugins/hooks/UnrestrictLiHook.py +++ b/pyload/plugin/hook/UnrestrictLi.py @@ -4,8 +4,8 @@ from pyload.utils import json_loads from pyload.plugin.internal.MultiHook import MultiHook -class UnrestrictLiHook(MultiHook): - __name__ = "UnrestrictLiHook" +class UnrestrictLi(MultiHook): + __name__ = "UnrestrictLi" __type__ = "hook" __version__ = "0.05" diff --git a/module/plugins/hooks/ZeveraComHook.py b/pyload/plugin/hook/ZeveraCom.py index 83723351e..0ca2e72d2 100644 --- a/module/plugins/hooks/ZeveraComHook.py +++ b/pyload/plugin/hook/ZeveraCom.py @@ -3,8 +3,8 @@ from pyload.plugin.internal.MultiHook import MultiHook -class ZeveraComHook(MultiHook): - __name__ = "ZeveraComHook" +class ZeveraCom(MultiHook): + __name__ = "ZeveraCom" __type__ = "hook" __version__ = "0.05" diff --git a/pyload/plugin/hoster/Ftp.py b/pyload/plugin/hoster/Ftp.py index d7aaa730e..b18e39a1c 100644 --- a/pyload/plugin/hoster/Ftp.py +++ b/pyload/plugin/hoster/Ftp.py @@ -28,16 +28,6 @@ class Ftp(Hoster): self.resumeDownload = True - #: Work-around to `filename*=UTF-8` bug; remove in 0.4.10 - def download(self, url, get={}, post={}, ref=True, cookies=True, disposition=False): - try: - if disposition: - content = urllib2.urlopen(url).info()['Content-Disposition'].split(';') - self.pyfile.name = content[1].split('filename=')[1][1:-1] or self.pyfile.name - finally: - return super(Ftp, self).download(url, get, post, ref, cookies, False) - - def process(self, pyfile): parsed_url = urlparse(pyfile.url) netloc = parsed_url.netloc diff --git a/module/plugins/hoster/LolabitsEs.py b/pyload/plugin/hoster/LolabitsEs.py index 61df5f0bb..dbd392624 100644 --- a/module/plugins/hoster/LolabitsEs.py +++ b/pyload/plugin/hoster/LolabitsEs.py @@ -3,7 +3,7 @@ import HTMLParser import re -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from pyload.plugin.internal.SimpleHoster import SimpleHoster class LolabitsEs(SimpleHoster): @@ -43,6 +43,3 @@ class LolabitsEs(SimpleHoster): '__RequestVerificationToken' : token}).decode('unicode-escape') self.link = HTMLParser.HTMLParser().unescape(re.search(self.LINK_PATTERN, self.html).group(1)) - - -getInfo = create_getInfo(LolabitsEs) diff --git a/module/plugins/hoster/SolidfilesCom.py b/pyload/plugin/hoster/SolidfilesCom.py index d359577d6..e700e861f 100644 --- a/module/plugins/hoster/SolidfilesCom.py +++ b/pyload/plugin/hoster/SolidfilesCom.py @@ -3,7 +3,7 @@ # Test links: # http://www.solidfiles.com/d/609cdb4b1b -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from pyload.plugin.internal.SimpleHoster import SimpleHoster class SolidfilesCom(SimpleHoster): @@ -28,6 +28,3 @@ class SolidfilesCom(SimpleHoster): def setup(self): self.multiDL = True self.chunkLimit = 1 - - -getInfo = create_getInfo(SolidfilesCom) diff --git a/module/plugins/hoster/YadiSk.py b/pyload/plugin/hoster/YadiSk.py index c3749d30d..28576d5d6 100644 --- a/module/plugins/hoster/YadiSk.py +++ b/pyload/plugin/hoster/YadiSk.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -import re import random +import re -from module.common.json_layer import json_loads -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo +from pyload.plugin.internal.SimpleHoster import SimpleHoster +from pyload.utils import json_loads class YadiSk(SimpleHoster): @@ -79,6 +79,3 @@ class YadiSk(SimpleHoster): except Exception: pass - - -getInfo = create_getInfo(YadiSk) diff --git a/pyload/plugin/internal/BasePlugin.py b/pyload/plugin/internal/BasePlugin.py index 7c83ddef0..a0745f99a 100644 --- a/pyload/plugin/internal/BasePlugin.py +++ b/pyload/plugin/internal/BasePlugin.py @@ -41,16 +41,6 @@ class BasePlugin(Hoster): self.resumeDownload = True - #: Work-around to `filename*=UTF-8` bug; remove in 0.4.10 - def download(self, url, get={}, post={}, ref=True, cookies=True, disposition=False): - try: - if disposition: - content = urllib2.urlopen(url).info()['Content-Disposition'].split(';') - self.pyfile.name = content[1].split('filename=')[1][1:-1] or self.pyfile.name - finally: - return super(BasePlugin, self).download(url, get, post, ref, cookies, False) - - def process(self, pyfile): """main function""" diff --git a/pyload/plugin/internal/SimpleHoster.py b/pyload/plugin/internal/SimpleHoster.py index 56170a4fd..fa48f1e25 100644 --- a/pyload/plugin/internal/SimpleHoster.py +++ b/pyload/plugin/internal/SimpleHoster.py @@ -307,7 +307,7 @@ class SimpleHoster(Hoster): LOGIN_ACCOUNT = False #: Set to True to require account login DISPOSITION = True #: Set to True to use any content-disposition value in http header as file name - directLink = getFileURL # @TODO: Remove in 0.4.10 + directLink = getFileURL #@TODO: Remove in 0.4.10 @classmethod @@ -410,13 +410,13 @@ class SimpleHoster(Hoster): self.resumeDownload = self.multiDL = self.premium def prepare(self): - self.pyfile.error = "" # @TODO: Remove in 0.4.10 + self.pyfile.error = "" #@TODO: Remove in 0.4.10 self.info = {} self.html = "" - self.link = "" # @TODO: Move to hoster class in 0.4.10 - self.directDL = False # @TODO: Move to hoster class in 0.4.10 - self.multihost = False # @TODO: Move to hoster class in 0.4.10 + self.link = "" #@TODO: Move to hoster class in 0.4.10 + self.directDL = False #@TODO: Move to hoster class in 0.4.10 + self.multihost = False #@TODO: Move to hoster class in 0.4.10 if not self.getConfig('use_premium', True): self.retryFree() @@ -480,7 +480,7 @@ class SimpleHoster(Hoster): self.downloadLink(self.link, self.DISPOSITION) self.checkFile() - except Fail, e: # @TODO: Move to PluginThread in 0.4.10 + except Fail, e: #@TODO: Move to PluginThread in 0.4.10 if self.premium: self.logWarning(_("Premium download failed")) self.retryFree() @@ -711,7 +711,7 @@ class SimpleHoster(Hoster): self.logInfo(_("Filesize: %i KiB, Traffic left for user %s: %i KiB") % (size, self.user, traffic)) return size <= traffic - def getConfig(self, option, default=''): # @TODO: Remove in 0.4.10 + def getConfig(self, option, default=''): #@TODO: Remove in 0.4.10 """getConfig with default value - sublass may not implements all config options""" try: return self.getConf(option) diff --git a/pyload/plugin/internal/XFSHoster.py b/pyload/plugin/internal/XFSHoster.py index 0e265ce64..db2d2e1d0 100644 --- a/pyload/plugin/internal/XFSHoster.py +++ b/pyload/plugin/internal/XFSHoster.py @@ -29,7 +29,7 @@ class XFSHoster(SimpleHoster): TEXT_ENCODING = False DIRECT_LINK = None - MULTI_HOSTER = True # @NOTE: Should be default to False for safe, but I'm lazy... + MULTI_HOSTER = True #@NOTE: Should be default to False for safe, but I'm lazy... NAME_PATTERN = r'(Filename[ ]*:[ ]*</b>(</td><td nowrap>)?|name="fname"[ ]+value="|<[\w^_]+ class="(file)?name">)\s*(?P<N>.+?)(\s*<|")' SIZE_PATTERN = r'(Size[ ]*:[ ]*</b>(</td><td>)?|File:.*>|</font>\s*\(|<[\w^_]+ class="size">)\s*(?P<S>[\d.,]+)\s*(?P<U>[\w^_]+)' @@ -109,7 +109,7 @@ class XFSHoster(SimpleHoster): self.logError(data['op'] if 'op' in data else _("UNKNOWN")) return "" - self.link = m.group(1).strip() # @TODO: Remove .strip() in 0.4.10 + self.link = m.group(1).strip() #@TODO: Remove .strip() in 0.4.10 def handlePremium(self, pyfile): return self.handleFree(pyfile) @@ -63,14 +63,15 @@ setup( ], extras_require={ - 'Few plugins dependencies': ["BeautifulSoup >= 3.2, < 3.3"] - 'Colored log' : ["colorlog"] - 'Lightweight webserver' : ["bjoern"] - 'RSS support' : ["feedparser"] - 'SSL support' : ["pyOpenSSL"] - 'RSDF/CCF/DLC support' : ["pycrypto"] - 'Captcha recognition' : ["PIL"] - 'JSON speedup' : ["simplejson"] + 'Few plugins dependencies': ["BeautifulSoup >= 3.2, < 3.3"], + 'Colored log' : ["colorlog"], + 'Lightweight webserver' : ["bjoern"], + 'RSS support' : ["feedparser"], + 'SSL support' : ["pyOpenSSL"], + 'RSDF/CCF/DLC support' : ["pycrypto"], + 'Captcha recognition' : ["PIL"], + 'JSON speedup' : ["simplejson"], + 'Trash support' : ["Send2Trash"] }, #setup_requires=["setuptools_hg"], |