python 3 support

This commit is contained in:
Richard O'Dwyer 2019-10-16 21:59:31 +01:00
parent 2cb2148ddc
commit 321ccbfa7f
4 changed files with 49 additions and 28 deletions

View file

@ -27,16 +27,16 @@ def test():
files = m.get_files()
# get account disk quota in MB
print(m.get_quota())
print((m.get_quota()))
# get account storage space
print(m.get_storage_space())
print((m.get_storage_space()))
# example iterate over files
for file in files:
print(files[file])
print((files[file]))
# upload file
print(m.upload('examples.py'))
print((m.upload('examples.py')))
# search for a file in account
file = m.find('examples.py')
@ -47,17 +47,17 @@ def test():
print(link)
# download file. by file object or url
print m.download(file, '/tmp')
print(m.download(file, '/tmp'))
# m.download_url(link)
# 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.delete_url(link))
# print(m.destroy_url(link))
# empty trash
print(m.empty_trash())
print((m.empty_trash()))
if __name__ == '__main__':

View file

@ -4,15 +4,33 @@ import base64
import struct
import binascii
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):
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)
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)
@ -59,14 +77,16 @@ def decrypt_key(a, key):
def encrypt_attr(attr, key):
attr = 'MEGA' + json.dumps(attr)
attr = makebyte('MEGA' + json.dumps(attr))
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))
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
@ -75,9 +95,11 @@ def a32_to_str(a):
def str_to_a32(b):
if isinstance(b, str):
b = makebyte(b)
if len(b) % 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)
@ -98,6 +120,7 @@ def base64_to_a32(s):
def base64_url_encode(data):
data = base64.b64encode(data)
data = makestring(data)
for search, replace in (('+', '-'), ('/', '_'), ('=', '')):
data = data.replace(search, replace)
return data
@ -118,7 +141,6 @@ def get_chunks(size):
yield (p, size - p)
# more general functions
def make_id(length):
text = ''
possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"

View file

@ -59,9 +59,7 @@ class Mega(object):
a32_to_base64(encrypt_key(master_key, password_key)),
'ts':
base64_url_encode(
a32_to_str(session_self_challenge) + a32_to_str(
encrypt_key(session_self_challenge, master_key)
)
a32_to_str(session_self_challenge) + a32_to_str(encrypt_key(session_self_challenge, master_key))
)
}
)
@ -101,7 +99,7 @@ class Mega(object):
encrypted_sid = mpi_to_int(base64_url_decode(resp['csid']))
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[1]
)
@ -256,7 +254,7 @@ class Mega(object):
found = False
for foldername in paths:
if foldername != '':
for file in files.iteritems():
for file in files.items():
if file[1]['a'] and file[1]['t'] and \
file[1]['a']['n'] == foldername:
if parent_desc == file[1]['p']:
@ -273,7 +271,7 @@ class Mega(object):
Return file object from given filename
"""
files = self.get_files()
for file in files.items():
for file in list(files.items()):
if not isinstance(file[1]['a'], dict):
continue
if file[1]['a'] and file[1]['a']['n'] == filename:
@ -348,7 +346,7 @@ class Mega(object):
4: special trash bin
"""
nodes = self.get_files()
for node in nodes.items():
for node in list(nodes.items()):
if node[1]['t'] == type:
return node
@ -385,7 +383,7 @@ class Mega(object):
node_id = None
for i in node_data['f']:
if i['h'] != u'':
if i['h'] != '':
node_id = i['h']
return node_id
@ -608,11 +606,11 @@ class Mega(object):
if self.options.get('verbose') is True:
# temp file size
file_info = os.stat(temp_output_file.name)
print(
print((
'{0} of {1} downloaded'.format(
file_info.st_size, file_size
)
)
))
file_mac = str_to_a32(mac_str)
@ -685,11 +683,11 @@ class Mega(object):
if self.options.get('verbose') is True:
# upload progress
print(
print((
'{0} of {1} uploaded'.format(
upload_progress, file_size
)
)
))
else:
output_file = requests.post(
ul_url + "/0", data='', timeout=self.timeout
@ -818,7 +816,7 @@ class Mega(object):
# determine target_node_id
if type(target) == int:
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
else:
file = target[1]

View file

@ -5,7 +5,8 @@ envlist = py{27,37}-normal,lint
commands =
flake8 {toxinidir}/src/
coverage erase
PYTHONPATH=. pytest --cov=. {toxinidir}/tests/tests.py
python setup.py install
pytest {toxinidir}/tests/tests.py
deps =
-rrequirements-dev.txt