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()
|
||||
|
||||
# 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__':
|
||||
|
|
|
@ -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"
|
||||
|
|
24
mega/mega.py
24
mega/mega.py
|
@ -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]
|
||||
|
|
3
tox.ini
3
tox.ini
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue