python 3 support
This commit is contained in:
parent
2cb2148ddc
commit
321ccbfa7f
4 changed files with 49 additions and 28 deletions
14
examples.py
14
examples.py
|
@ -27,16 +27,16 @@ def test():
|
||||||
files = m.get_files()
|
files = m.get_files()
|
||||||
|
|
||||||
# get account disk quota in MB
|
# get account disk quota in MB
|
||||||
print(m.get_quota())
|
print((m.get_quota()))
|
||||||
# get account storage space
|
# get account storage space
|
||||||
print(m.get_storage_space())
|
print((m.get_storage_space()))
|
||||||
|
|
||||||
# example iterate over files
|
# example iterate over files
|
||||||
for file in files:
|
for file in files:
|
||||||
print(files[file])
|
print((files[file]))
|
||||||
|
|
||||||
# upload file
|
# upload file
|
||||||
print(m.upload('examples.py'))
|
print((m.upload('examples.py')))
|
||||||
|
|
||||||
# search for a file in account
|
# search for a file in account
|
||||||
file = m.find('examples.py')
|
file = m.find('examples.py')
|
||||||
|
@ -47,17 +47,17 @@ def test():
|
||||||
print(link)
|
print(link)
|
||||||
|
|
||||||
# download file. by file object or url
|
# download file. by file object or url
|
||||||
print m.download(file, '/tmp')
|
print(m.download(file, '/tmp'))
|
||||||
# m.download_url(link)
|
# m.download_url(link)
|
||||||
|
|
||||||
# delete or destroy file. by id or url
|
# delete or destroy file. by id or url
|
||||||
print(m.delete(file[0]))
|
print((m.delete(file[0])))
|
||||||
# print(m.destroy(file[0]))
|
# print(m.destroy(file[0]))
|
||||||
# print(m.delete_url(link))
|
# print(m.delete_url(link))
|
||||||
# print(m.destroy_url(link))
|
# print(m.destroy_url(link))
|
||||||
|
|
||||||
# empty trash
|
# empty trash
|
||||||
print(m.empty_trash())
|
print((m.empty_trash()))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -4,15 +4,33 @@ import base64
|
||||||
import struct
|
import struct
|
||||||
import binascii
|
import binascii
|
||||||
import random
|
import random
|
||||||
|
import sys
|
||||||
|
|
||||||
|
### Python3 compatibility
|
||||||
|
if sys.version_info < (3, ):
|
||||||
|
|
||||||
|
def makebyte(x):
|
||||||
|
return x
|
||||||
|
|
||||||
|
def makestring(x):
|
||||||
|
return x
|
||||||
|
else:
|
||||||
|
import codecs
|
||||||
|
|
||||||
|
def makebyte(x):
|
||||||
|
return codecs.latin_1_encode(x)[0]
|
||||||
|
|
||||||
|
def makestring(x):
|
||||||
|
return codecs.latin_1_decode(x)[0]
|
||||||
|
|
||||||
|
|
||||||
def aes_cbc_encrypt(data, key):
|
def aes_cbc_encrypt(data, key):
|
||||||
aes_cipher = AES.new(key, AES.MODE_CBC, '\0' * 16)
|
aes_cipher = AES.new(key, AES.MODE_CBC, makebyte('\0' * 16))
|
||||||
return aes_cipher.encrypt(data)
|
return aes_cipher.encrypt(data)
|
||||||
|
|
||||||
|
|
||||||
def aes_cbc_decrypt(data, key):
|
def aes_cbc_decrypt(data, key):
|
||||||
aes_cipher = AES.new(key, AES.MODE_CBC, '\0' * 16)
|
aes_cipher = AES.new(key, AES.MODE_CBC, makebyte('\0' * 16))
|
||||||
return aes_cipher.decrypt(data)
|
return aes_cipher.decrypt(data)
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,14 +77,16 @@ def decrypt_key(a, key):
|
||||||
|
|
||||||
|
|
||||||
def encrypt_attr(attr, key):
|
def encrypt_attr(attr, key):
|
||||||
attr = 'MEGA' + json.dumps(attr)
|
attr = makebyte('MEGA' + json.dumps(attr))
|
||||||
if len(attr) % 16:
|
if len(attr) % 16:
|
||||||
attr += '\0' * (16 - len(attr) % 16)
|
attr += b'\0' * (16 - len(attr) % 16)
|
||||||
return aes_cbc_encrypt(attr, a32_to_str(key))
|
return aes_cbc_encrypt(attr, a32_to_str(key))
|
||||||
|
|
||||||
|
|
||||||
def decrypt_attr(attr, key):
|
def decrypt_attr(attr, key):
|
||||||
attr = aes_cbc_decrypt(attr, a32_to_str(key)).rstrip('\0')
|
attr = aes_cbc_decrypt(attr, a32_to_str(key))
|
||||||
|
attr = makestring(attr)
|
||||||
|
attr = attr.rstrip('\0')
|
||||||
return json.loads(attr[4:]) if attr[:6] == 'MEGA{"' else False
|
return json.loads(attr[4:]) if attr[:6] == 'MEGA{"' else False
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,9 +95,11 @@ def a32_to_str(a):
|
||||||
|
|
||||||
|
|
||||||
def str_to_a32(b):
|
def str_to_a32(b):
|
||||||
|
if isinstance(b, str):
|
||||||
|
b = makebyte(b)
|
||||||
if len(b) % 4:
|
if len(b) % 4:
|
||||||
# pad to multiple of 4
|
# pad to multiple of 4
|
||||||
b += '\0' * (4 - len(b) % 4)
|
b += b'\0' * (4 - len(b) % 4)
|
||||||
return struct.unpack('>%dI' % (len(b) / 4), b)
|
return struct.unpack('>%dI' % (len(b) / 4), b)
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,6 +120,7 @@ def base64_to_a32(s):
|
||||||
|
|
||||||
def base64_url_encode(data):
|
def base64_url_encode(data):
|
||||||
data = base64.b64encode(data)
|
data = base64.b64encode(data)
|
||||||
|
data = makestring(data)
|
||||||
for search, replace in (('+', '-'), ('/', '_'), ('=', '')):
|
for search, replace in (('+', '-'), ('/', '_'), ('=', '')):
|
||||||
data = data.replace(search, replace)
|
data = data.replace(search, replace)
|
||||||
return data
|
return data
|
||||||
|
@ -118,7 +141,6 @@ def get_chunks(size):
|
||||||
yield (p, size - p)
|
yield (p, size - p)
|
||||||
|
|
||||||
|
|
||||||
# more general functions
|
|
||||||
def make_id(length):
|
def make_id(length):
|
||||||
text = ''
|
text = ''
|
||||||
possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||||
|
|
24
mega/mega.py
24
mega/mega.py
|
@ -59,9 +59,7 @@ class Mega(object):
|
||||||
a32_to_base64(encrypt_key(master_key, password_key)),
|
a32_to_base64(encrypt_key(master_key, password_key)),
|
||||||
'ts':
|
'ts':
|
||||||
base64_url_encode(
|
base64_url_encode(
|
||||||
a32_to_str(session_self_challenge) + a32_to_str(
|
a32_to_str(session_self_challenge) + a32_to_str(encrypt_key(session_self_challenge, master_key))
|
||||||
encrypt_key(session_self_challenge, master_key)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -101,7 +99,7 @@ class Mega(object):
|
||||||
encrypted_sid = mpi_to_int(base64_url_decode(resp['csid']))
|
encrypted_sid = mpi_to_int(base64_url_decode(resp['csid']))
|
||||||
rsa_decrypter = RSA.construct(
|
rsa_decrypter = RSA.construct(
|
||||||
(
|
(
|
||||||
self.rsa_private_key[0] * self.rsa_private_key[1], 0L,
|
self.rsa_private_key[0] * self.rsa_private_key[1], 0,
|
||||||
self.rsa_private_key[2], self.rsa_private_key[0],
|
self.rsa_private_key[2], self.rsa_private_key[0],
|
||||||
self.rsa_private_key[1]
|
self.rsa_private_key[1]
|
||||||
)
|
)
|
||||||
|
@ -256,7 +254,7 @@ class Mega(object):
|
||||||
found = False
|
found = False
|
||||||
for foldername in paths:
|
for foldername in paths:
|
||||||
if foldername != '':
|
if foldername != '':
|
||||||
for file in files.iteritems():
|
for file in files.items():
|
||||||
if file[1]['a'] and file[1]['t'] and \
|
if file[1]['a'] and file[1]['t'] and \
|
||||||
file[1]['a']['n'] == foldername:
|
file[1]['a']['n'] == foldername:
|
||||||
if parent_desc == file[1]['p']:
|
if parent_desc == file[1]['p']:
|
||||||
|
@ -273,7 +271,7 @@ class Mega(object):
|
||||||
Return file object from given filename
|
Return file object from given filename
|
||||||
"""
|
"""
|
||||||
files = self.get_files()
|
files = self.get_files()
|
||||||
for file in files.items():
|
for file in list(files.items()):
|
||||||
if not isinstance(file[1]['a'], dict):
|
if not isinstance(file[1]['a'], dict):
|
||||||
continue
|
continue
|
||||||
if file[1]['a'] and file[1]['a']['n'] == filename:
|
if file[1]['a'] and file[1]['a']['n'] == filename:
|
||||||
|
@ -348,7 +346,7 @@ class Mega(object):
|
||||||
4: special trash bin
|
4: special trash bin
|
||||||
"""
|
"""
|
||||||
nodes = self.get_files()
|
nodes = self.get_files()
|
||||||
for node in nodes.items():
|
for node in list(nodes.items()):
|
||||||
if node[1]['t'] == type:
|
if node[1]['t'] == type:
|
||||||
return node
|
return node
|
||||||
|
|
||||||
|
@ -385,7 +383,7 @@ class Mega(object):
|
||||||
node_id = None
|
node_id = None
|
||||||
|
|
||||||
for i in node_data['f']:
|
for i in node_data['f']:
|
||||||
if i['h'] != u'':
|
if i['h'] != '':
|
||||||
node_id = i['h']
|
node_id = i['h']
|
||||||
return node_id
|
return node_id
|
||||||
|
|
||||||
|
@ -608,11 +606,11 @@ class Mega(object):
|
||||||
if self.options.get('verbose') is True:
|
if self.options.get('verbose') is True:
|
||||||
# temp file size
|
# temp file size
|
||||||
file_info = os.stat(temp_output_file.name)
|
file_info = os.stat(temp_output_file.name)
|
||||||
print(
|
print((
|
||||||
'{0} of {1} downloaded'.format(
|
'{0} of {1} downloaded'.format(
|
||||||
file_info.st_size, file_size
|
file_info.st_size, file_size
|
||||||
)
|
)
|
||||||
)
|
))
|
||||||
|
|
||||||
file_mac = str_to_a32(mac_str)
|
file_mac = str_to_a32(mac_str)
|
||||||
|
|
||||||
|
@ -685,11 +683,11 @@ class Mega(object):
|
||||||
|
|
||||||
if self.options.get('verbose') is True:
|
if self.options.get('verbose') is True:
|
||||||
# upload progress
|
# upload progress
|
||||||
print(
|
print((
|
||||||
'{0} of {1} uploaded'.format(
|
'{0} of {1} uploaded'.format(
|
||||||
upload_progress, file_size
|
upload_progress, file_size
|
||||||
)
|
)
|
||||||
)
|
))
|
||||||
else:
|
else:
|
||||||
output_file = requests.post(
|
output_file = requests.post(
|
||||||
ul_url + "/0", data='', timeout=self.timeout
|
ul_url + "/0", data='', timeout=self.timeout
|
||||||
|
@ -818,7 +816,7 @@ class Mega(object):
|
||||||
# determine target_node_id
|
# determine target_node_id
|
||||||
if type(target) == int:
|
if type(target) == int:
|
||||||
target_node_id = str(self.get_node_by_type(target)[0])
|
target_node_id = str(self.get_node_by_type(target)[0])
|
||||||
elif type(target) in (str, unicode):
|
elif type(target) in (str, str):
|
||||||
target_node_id = target
|
target_node_id = target
|
||||||
else:
|
else:
|
||||||
file = target[1]
|
file = target[1]
|
||||||
|
|
3
tox.ini
3
tox.ini
|
@ -5,7 +5,8 @@ envlist = py{27,37}-normal,lint
|
||||||
commands =
|
commands =
|
||||||
flake8 {toxinidir}/src/
|
flake8 {toxinidir}/src/
|
||||||
coverage erase
|
coverage erase
|
||||||
PYTHONPATH=. pytest --cov=. {toxinidir}/tests/tests.py
|
python setup.py install
|
||||||
|
pytest {toxinidir}/tests/tests.py
|
||||||
|
|
||||||
deps =
|
deps =
|
||||||
-rrequirements-dev.txt
|
-rrequirements-dev.txt
|
||||||
|
|
Loading…
Reference in a new issue