From 5060e4c6374a5116d0d8b02528f910f8c5f8bcf9 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 15 Jul 2014 16:25:41 +0200 Subject: Fix code indentation, some bad whitespaces and missing authors + use 'not' instead 'is None' + replace __pattern__'s r" with r' + other minor cosmetics --- module/plugins/hoster/MegaNz.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'module/plugins/hoster/MegaNz.py') diff --git a/module/plugins/hoster/MegaNz.py b/module/plugins/hoster/MegaNz.py index a55220bc2..a396204ab 100644 --- a/module/plugins/hoster/MegaNz.py +++ b/module/plugins/hoster/MegaNz.py @@ -22,8 +22,8 @@ class MegaNz(Hoster): __pattern__ = r'https?://([a-z0-9]+\.)?mega\.co\.nz/#!([a-zA-Z0-9!_\-]+)' __version__ = "0.14" __description__ = """Mega.co.nz hoster plugin""" - __author_name__ = ("RaNaN", ) - __author_mail__ = ("ranan@pyload.org", ) + __author_name__ = "RaNaN" + __author_mail__ = "ranan@pyload.org" API_URL = "https://g.api.mega.co.nz/cs?id=%d" FILE_SUFFIX = ".crypted" -- cgit v1.2.3 From 7b8c458cca7d21a029620f98e453f746fce69cd1 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Mon, 14 Jul 2014 16:10:01 +0200 Subject: Prefer single quote for dict key name --- module/plugins/hoster/MegaNz.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'module/plugins/hoster/MegaNz.py') diff --git a/module/plugins/hoster/MegaNz.py b/module/plugins/hoster/MegaNz.py index a396204ab..cf35f2d2d 100644 --- a/module/plugins/hoster/MegaNz.py +++ b/module/plugins/hoster/MegaNz.py @@ -110,7 +110,7 @@ class MegaNz(Hoster): dl = self.callApi(a="g", g=1, p=node, ssl=1)[0] if "e" in dl: - e = dl["e"] + e = dl['e'] # ETEMPUNAVAIL (-18): Resource temporarily not available, please try again later if e == -18: self.retry() @@ -121,12 +121,12 @@ class MegaNz(Hoster): # EACCESS (-11): Access violation (e.g., trying to write to a read-only share) key = self.b64_decode(key) - attr = self.decryptAttr(dl["at"], key) + attr = self.decryptAttr(dl['at'], key) - pyfile.name = attr["n"] + self.FILE_SUFFIX + pyfile.name = attr['n'] + self.FILE_SUFFIX - self.download(dl["g"]) + self.download(dl['g']) self.decryptFile(key) # Everything is finished and final name can be set - pyfile.name = attr["n"] + pyfile.name = attr['n'] -- cgit v1.2.3 From ba916633f2bedb04c7358000b91aed69f52e8e43 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 1 Aug 2014 19:35:59 +0200 Subject: Remove trailing whitespaces + remove license headers + import urllib methods directly + sort and fix key attributes + use save_join instead join + sort some import declarations + other minor code cosmetics --- module/plugins/hoster/MegaNz.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'module/plugins/hoster/MegaNz.py') diff --git a/module/plugins/hoster/MegaNz.py b/module/plugins/hoster/MegaNz.py index cf35f2d2d..5562aad06 100644 --- a/module/plugins/hoster/MegaNz.py +++ b/module/plugins/hoster/MegaNz.py @@ -1,26 +1,25 @@ # -*- coding: utf-8 -*- -import re import random -from array import array -from os import remove -from base64 import standard_b64decode +import re from Crypto.Cipher import AES from Crypto.Util import Counter +from array import array +from base64 import standard_b64decode +from os import remove from module.common.json_layer import json_loads, json_dumps from module.plugins.Hoster import Hoster -#def getInfo(urls): -# pass - class MegaNz(Hoster): __name__ = "MegaNz" __type__ = "hoster" - __pattern__ = r'https?://([a-z0-9]+\.)?mega\.co\.nz/#!([a-zA-Z0-9!_\-]+)' __version__ = "0.14" + + __pattern__ = r'https?://([a-z0-9]+\.)?mega\.co\.nz/#!([a-zA-Z0-9!_\-]+)' + __description__ = """Mega.co.nz hoster plugin""" __author_name__ = "RaNaN" __author_mail__ = "ranan@pyload.org" @@ -28,6 +27,7 @@ class MegaNz(Hoster): API_URL = "https://g.api.mega.co.nz/cs?id=%d" FILE_SUFFIX = ".crypted" + def b64_decode(self, data): data = data.replace("-", "+").replace("_", "/") return standard_b64decode(data + '=' * (-len(data) % 4)) -- cgit v1.2.3 From b0868ae6446078bacf1635dde5e4ab316b4a94cb Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 7 Oct 2014 18:57:59 +0200 Subject: New __authors__ key replaces __author_name__ and __author_mail__ + Whitespaces and EOF fixup --- module/plugins/hoster/MegaNz.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'module/plugins/hoster/MegaNz.py') diff --git a/module/plugins/hoster/MegaNz.py b/module/plugins/hoster/MegaNz.py index 5562aad06..fb7006627 100644 --- a/module/plugins/hoster/MegaNz.py +++ b/module/plugins/hoster/MegaNz.py @@ -21,8 +21,8 @@ class MegaNz(Hoster): __pattern__ = r'https?://([a-z0-9]+\.)?mega\.co\.nz/#!([a-zA-Z0-9!_\-]+)' __description__ = """Mega.co.nz hoster plugin""" - __author_name__ = "RaNaN" - __author_mail__ = "ranan@pyload.org" + __authors__ = [("RaNaN", "ranan@pyload.org")] + API_URL = "https://g.api.mega.co.nz/cs?id=%d" FILE_SUFFIX = ".crypted" -- cgit v1.2.3 From ae7a7e66981456e5bbe2b54006d79b6f907be7a4 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Wed, 8 Oct 2014 20:18:13 +0200 Subject: Add __license__ key attribute to plugins --- module/plugins/hoster/MegaNz.py | 1 + 1 file changed, 1 insertion(+) (limited to 'module/plugins/hoster/MegaNz.py') diff --git a/module/plugins/hoster/MegaNz.py b/module/plugins/hoster/MegaNz.py index fb7006627..10eac6236 100644 --- a/module/plugins/hoster/MegaNz.py +++ b/module/plugins/hoster/MegaNz.py @@ -21,6 +21,7 @@ class MegaNz(Hoster): __pattern__ = r'https?://([a-z0-9]+\.)?mega\.co\.nz/#!([a-zA-Z0-9!_\-]+)' __description__ = """Mega.co.nz hoster plugin""" + __license__ = "GPLv3" __authors__ = [("RaNaN", "ranan@pyload.org")] -- cgit v1.2.3 From f76e5c2336718dca9da8033ba22cd83c72c7b3b3 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sat, 11 Oct 2014 15:14:28 +0200 Subject: Pattern update 1 --- module/plugins/hoster/MegaNz.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'module/plugins/hoster/MegaNz.py') diff --git a/module/plugins/hoster/MegaNz.py b/module/plugins/hoster/MegaNz.py index 10eac6236..91719b86b 100644 --- a/module/plugins/hoster/MegaNz.py +++ b/module/plugins/hoster/MegaNz.py @@ -18,7 +18,7 @@ class MegaNz(Hoster): __type__ = "hoster" __version__ = "0.14" - __pattern__ = r'https?://([a-z0-9]+\.)?mega\.co\.nz/#!([a-zA-Z0-9!_\-]+)' + __pattern__ = r'https?://(\w+\.)?mega\.co\.nz/#!([\w!-]+)' __description__ = """Mega.co.nz hoster plugin""" __license__ = "GPLv3" -- cgit v1.2.3 From 37fcdffac990eaf024fdc33a026fcf566e9e263f Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sat, 11 Oct 2014 23:59:07 +0200 Subject: [MegaNz] Fix decryptAttr --- module/plugins/hoster/MegaNz.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'module/plugins/hoster/MegaNz.py') diff --git a/module/plugins/hoster/MegaNz.py b/module/plugins/hoster/MegaNz.py index 91719b86b..2e6aaa273 100644 --- a/module/plugins/hoster/MegaNz.py +++ b/module/plugins/hoster/MegaNz.py @@ -16,7 +16,7 @@ from module.plugins.Hoster import Hoster class MegaNz(Hoster): __name__ = "MegaNz" __type__ = "hoster" - __version__ = "0.14" + __version__ = "0.15" __pattern__ = r'https?://(\w+\.)?mega\.co\.nz/#!([\w!-]+)' @@ -33,12 +33,14 @@ class MegaNz(Hoster): data = data.replace("-", "+").replace("_", "/") return standard_b64decode(data + '=' * (-len(data) % 4)) + def getCipherKey(self, key): """ Construct the cipher key from the given data """ a = array("I", key) key_array = array("I", [a[0] ^ a[4], a[1] ^ a[5], a[2] ^ a[6], a[3] ^ a[7]]) return key_array + def callApi(self, **kwargs): """ Dispatch a call to the api, see https://mega.co.nz/#developers """ # generate a session id, no idea where to obtain elsewhere @@ -48,8 +50,8 @@ class MegaNz(Hoster): self.logDebug("Api Response: " + resp) return json_loads(resp) - def decryptAttr(self, data, key): + def decryptAttr(self, data, key): cbc = AES.new(self.getCipherKey(key), AES.MODE_CBC, "\0" * 16) attr = cbc.decrypt(self.b64_decode(data)) self.logDebug("Decrypted Attr: " + attr) @@ -57,7 +59,8 @@ class MegaNz(Hoster): self.fail(_("Decryption failed")) # Data is padded, 0-bytes must be stripped - return json_loads(attr.replace("MEGA", "").rstrip("\0").strip()) + return json_loads(re.search(r'{.+?}', attr).group(0)) + def decryptFile(self, key): """ Decrypts the file at lastDownload` """ @@ -92,8 +95,8 @@ class MegaNz(Hoster): self.lastDownload = file_decrypted - def process(self, pyfile): + def process(self, pyfile): key = None # match is guaranteed because plugin was chosen to handle url -- cgit v1.2.3 From 34984dae733c3f3d47b41a0acfba3724d53c65a1 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Tue, 28 Oct 2014 16:52:10 +0100 Subject: Code cosmetics: plugin class attributes --- module/plugins/hoster/MegaNz.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'module/plugins/hoster/MegaNz.py') diff --git a/module/plugins/hoster/MegaNz.py b/module/plugins/hoster/MegaNz.py index 2e6aaa273..bbf18eed7 100644 --- a/module/plugins/hoster/MegaNz.py +++ b/module/plugins/hoster/MegaNz.py @@ -14,15 +14,15 @@ from module.plugins.Hoster import Hoster class MegaNz(Hoster): - __name__ = "MegaNz" - __type__ = "hoster" + __name__ = "MegaNz" + __type__ = "hoster" __version__ = "0.15" __pattern__ = r'https?://(\w+\.)?mega\.co\.nz/#!([\w!-]+)' __description__ = """Mega.co.nz hoster plugin""" - __license__ = "GPLv3" - __authors__ = [("RaNaN", "ranan@pyload.org")] + __license__ = "GPLv3" + __authors__ = [("RaNaN", "ranan@pyload.org")] API_URL = "https://g.api.mega.co.nz/cs?id=%d" -- cgit v1.2.3 From a591f5617de1280441012ddf846ccc1088963f47 Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Sat, 1 Nov 2014 00:05:44 +0100 Subject: [MegaNz] Fix SSL protocol error (thx cocoto) --- module/plugins/hoster/MegaNz.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'module/plugins/hoster/MegaNz.py') diff --git a/module/plugins/hoster/MegaNz.py b/module/plugins/hoster/MegaNz.py index bbf18eed7..06c2afc84 100644 --- a/module/plugins/hoster/MegaNz.py +++ b/module/plugins/hoster/MegaNz.py @@ -3,12 +3,14 @@ import random import re -from Crypto.Cipher import AES -from Crypto.Util import Counter from array import array from base64 import standard_b64decode from os import remove +from Crypto.Cipher import AES +from Crypto.Util import Counter +from pycurl import SSL_CIPHER_LIST + from module.common.json_layer import json_loads, json_dumps from module.plugins.Hoster import Hoster @@ -16,7 +18,7 @@ from module.plugins.Hoster import Hoster class MegaNz(Hoster): __name__ = "MegaNz" __type__ = "hoster" - __version__ = "0.15" + __version__ = "0.16" __pattern__ = r'https?://(\w+\.)?mega\.co\.nz/#!([\w!-]+)' @@ -129,6 +131,8 @@ class MegaNz(Hoster): pyfile.name = attr['n'] + self.FILE_SUFFIX + self.req.http.c.setopt(SSL_CIPHER_LIST, "RC4-MD5:DEFAULT") + self.download(dl['g']) self.decryptFile(key) -- cgit v1.2.3 From 776a6ced27fa0fe813871dda61b8eee869e8355d Mon Sep 17 00:00:00 2001 From: Walter Purcaro Date: Fri, 7 Nov 2014 19:36:02 +0100 Subject: Rename MegaNz to MegaCoNz --- module/plugins/hoster/MegaNz.py | 140 ---------------------------------------- 1 file changed, 140 deletions(-) delete mode 100644 module/plugins/hoster/MegaNz.py (limited to 'module/plugins/hoster/MegaNz.py') diff --git a/module/plugins/hoster/MegaNz.py b/module/plugins/hoster/MegaNz.py deleted file mode 100644 index 06c2afc84..000000000 --- a/module/plugins/hoster/MegaNz.py +++ /dev/null @@ -1,140 +0,0 @@ -# -*- coding: utf-8 -*- - -import random -import re - -from array import array -from base64 import standard_b64decode -from os import remove - -from Crypto.Cipher import AES -from Crypto.Util import Counter -from pycurl import SSL_CIPHER_LIST - -from module.common.json_layer import json_loads, json_dumps -from module.plugins.Hoster import Hoster - - -class MegaNz(Hoster): - __name__ = "MegaNz" - __type__ = "hoster" - __version__ = "0.16" - - __pattern__ = r'https?://(\w+\.)?mega\.co\.nz/#!([\w!-]+)' - - __description__ = """Mega.co.nz hoster plugin""" - __license__ = "GPLv3" - __authors__ = [("RaNaN", "ranan@pyload.org")] - - - API_URL = "https://g.api.mega.co.nz/cs?id=%d" - FILE_SUFFIX = ".crypted" - - - def b64_decode(self, data): - data = data.replace("-", "+").replace("_", "/") - return standard_b64decode(data + '=' * (-len(data) % 4)) - - - def getCipherKey(self, key): - """ Construct the cipher key from the given data """ - a = array("I", key) - key_array = array("I", [a[0] ^ a[4], a[1] ^ a[5], a[2] ^ a[6], a[3] ^ a[7]]) - return key_array - - - def callApi(self, **kwargs): - """ Dispatch a call to the api, see https://mega.co.nz/#developers """ - # generate a session id, no idea where to obtain elsewhere - uid = random.randint(10 << 9, 10 ** 10) - - resp = self.load(self.API_URL % uid, post=json_dumps([kwargs])) - self.logDebug("Api Response: " + resp) - return json_loads(resp) - - - def decryptAttr(self, data, key): - cbc = AES.new(self.getCipherKey(key), AES.MODE_CBC, "\0" * 16) - attr = cbc.decrypt(self.b64_decode(data)) - self.logDebug("Decrypted Attr: " + attr) - if not attr.startswith("MEGA"): - self.fail(_("Decryption failed")) - - # Data is padded, 0-bytes must be stripped - return json_loads(re.search(r'{.+?}', attr).group(0)) - - - def decryptFile(self, key): - """ Decrypts the file at lastDownload` """ - - # upper 64 bit of counter start - n = key[16:24] - - # convert counter to long and shift bytes - ctr = Counter.new(128, initial_value=long(n.encode("hex"), 16) << 64) - cipher = AES.new(self.getCipherKey(key), AES.MODE_CTR, counter=ctr) - - self.pyfile.setStatus("decrypting") - - file_crypted = self.lastDownload - file_decrypted = file_crypted.rsplit(self.FILE_SUFFIX)[0] - f = open(file_crypted, "rb") - df = open(file_decrypted, "wb") - - # TODO: calculate CBC-MAC for checksum - - size = 2 ** 15 # buffer size, 32k - while True: - buf = f.read(size) - if not buf: - break - - df.write(cipher.decrypt(buf)) - - f.close() - df.close() - remove(file_crypted) - - self.lastDownload = file_decrypted - - - def process(self, pyfile): - key = None - - # match is guaranteed because plugin was chosen to handle url - node = re.match(self.__pattern__, pyfile.url).group(2) - if "!" in node: - node, key = node.split("!") - - self.logDebug("File id: %s | Key: %s" % (node, key)) - - if not key: - self.fail(_("No file key provided in the URL")) - - # g is for requesting a download url - # this is similar to the calls in the mega js app, documentation is very bad - dl = self.callApi(a="g", g=1, p=node, ssl=1)[0] - - if "e" in dl: - e = dl['e'] - # ETEMPUNAVAIL (-18): Resource temporarily not available, please try again later - if e == -18: - self.retry() - else: - self.fail(_("Error code:") + e) - - # TODO: map other error codes, e.g - # EACCESS (-11): Access violation (e.g., trying to write to a read-only share) - - key = self.b64_decode(key) - attr = self.decryptAttr(dl['at'], key) - - pyfile.name = attr['n'] + self.FILE_SUFFIX - - self.req.http.c.setopt(SSL_CIPHER_LIST, "RC4-MD5:DEFAULT") - - self.download(dl['g']) - self.decryptFile(key) - - # Everything is finished and final name can be set - pyfile.name = attr['n'] -- cgit v1.2.3