Merge pull request #21 from gissehel/sharedfolders
Shared keys now works for file comming from shared folders that aren't shared anymore
This commit is contained in:
commit
10b4a883a8
1 changed files with 44 additions and 46 deletions
90
mega/mega.py
90
mega/mega.py
|
@ -38,7 +38,6 @@ class Mega(object):
|
||||||
def _login_process(self, resp, password):
|
def _login_process(self, resp, password):
|
||||||
encrypted_master_key = base64_to_a32(resp['k'])
|
encrypted_master_key = base64_to_a32(resp['k'])
|
||||||
self.master_key = decrypt_key(encrypted_master_key, password)
|
self.master_key = decrypt_key(encrypted_master_key, password)
|
||||||
self.users_keys = dict()
|
|
||||||
if 'tsid' in resp:
|
if 'tsid' in resp:
|
||||||
tsid = base64_url_decode(resp['tsid'])
|
tsid = base64_url_decode(resp['tsid'])
|
||||||
key_encrypted = a32_to_str(
|
key_encrypted = a32_to_str(
|
||||||
|
@ -100,23 +99,33 @@ class Mega(object):
|
||||||
else:
|
else:
|
||||||
raise RequestError('Url key missing')
|
raise RequestError('Url key missing')
|
||||||
|
|
||||||
def process_file(self, file):
|
def process_file(self, file, shared_keys):
|
||||||
"""
|
"""
|
||||||
Process a file
|
Process a file
|
||||||
"""
|
"""
|
||||||
if file['t'] == 0 or file['t'] == 1:
|
if file['t'] == 0 or file['t'] == 1:
|
||||||
|
keys = dict(keypart.split(':',1) for keypart in file['k'].split('/'))
|
||||||
uid = file['u']
|
uid = file['u']
|
||||||
keys = file['k'].split('/')
|
|
||||||
regex = re.compile('^%s:.*$' % uid)
|
|
||||||
key = None
|
key = None
|
||||||
for keytmp in keys:
|
|
||||||
if regex.match(keytmp):
|
|
||||||
key = keytmp[keytmp.index(':') + 1:]
|
|
||||||
break
|
|
||||||
|
|
||||||
# my objects
|
# my objects
|
||||||
if key:
|
if uid in keys :
|
||||||
key = decrypt_key(base64_to_a32(key), self.master_key)
|
key = decrypt_key(base64_to_a32( keys[uid] ), self.master_key)
|
||||||
|
# shared folders
|
||||||
|
elif 'su' in file and 'sk' in file and ':' in file['k']:
|
||||||
|
shared_key = decrypt_key(base64_to_a32(file['sk']),self.master_key)
|
||||||
|
key = decrypt_key(base64_to_a32(keys[file['h']]),shared_key)
|
||||||
|
if file['su'] not in shared_keys :
|
||||||
|
shared_keys[file['su']] = {}
|
||||||
|
shared_keys[file['su']][file['h']] = shared_key
|
||||||
|
# shared files
|
||||||
|
elif file['u'] and file['u'] in shared_keys :
|
||||||
|
for hkey in shared_keys[file['u']] :
|
||||||
|
shared_key = shared_keys[file['u']][hkey]
|
||||||
|
if hkey in keys :
|
||||||
|
key = keys[hkey]
|
||||||
|
key = decrypt_key(base64_to_a32(key),shared_key)
|
||||||
|
break
|
||||||
|
if key is not None :
|
||||||
# file
|
# file
|
||||||
if file['t'] == 0:
|
if file['t'] == 0:
|
||||||
k = (key[0] ^ key[4], key[1] ^ key[5], key[2] ^ key[6],
|
k = (key[0] ^ key[4], key[1] ^ key[5], key[2] ^ key[6],
|
||||||
|
@ -129,39 +138,6 @@ class Mega(object):
|
||||||
attributes = base64_url_decode(file['a'])
|
attributes = base64_url_decode(file['a'])
|
||||||
attributes = decrypt_attr(attributes, k)
|
attributes = decrypt_attr(attributes, k)
|
||||||
file['a'] = attributes
|
file['a'] = attributes
|
||||||
# shared folders
|
|
||||||
elif 'su' in file and 'sk' in file and ':' in file['k']:
|
|
||||||
user_key = decrypt_key(base64_to_a32(file['sk']),
|
|
||||||
self.master_key)
|
|
||||||
key = decrypt_key(base64_to_a32(file['k'].split(':')[1]),
|
|
||||||
user_key)
|
|
||||||
# save user_key to decrypt shared files
|
|
||||||
self.users_keys[file['su']] = user_key
|
|
||||||
if file['t'] == 0:
|
|
||||||
k = (key[0] ^ key[4], key[1] ^ key[5], key[2] ^ key[6],
|
|
||||||
key[3] ^ key[7])
|
|
||||||
file['iv'] = key[4:6] + (0, 0)
|
|
||||||
file['meta_mac'] = key[6:8]
|
|
||||||
else:
|
|
||||||
k = key
|
|
||||||
attributes = base64_url_decode(file['a'])
|
|
||||||
attributes = decrypt_attr(attributes, k)
|
|
||||||
file['a'] = attributes
|
|
||||||
# shared files
|
|
||||||
elif file['u'] and ':' in file['k']:
|
|
||||||
user_key = self.users_keys[file['u']]
|
|
||||||
key = decrypt_key(base64_to_a32(file['k'].split(':')[1]),
|
|
||||||
user_key)
|
|
||||||
if file['t'] == 0:
|
|
||||||
k = (key[0] ^ key[4], key[1] ^ key[5], key[2] ^ key[6],
|
|
||||||
key[3] ^ key[7])
|
|
||||||
file['iv'] = key[4:6] + (0, 0)
|
|
||||||
file['meta_mac'] = key[6:8]
|
|
||||||
else:
|
|
||||||
k = key
|
|
||||||
attributes = base64_url_decode(file['a'])
|
|
||||||
attributes = decrypt_attr(attributes, k)
|
|
||||||
file['a'] = attributes
|
|
||||||
# other => wrong object
|
# other => wrong object
|
||||||
elif file['k'] == '':
|
elif file['k'] == '':
|
||||||
file['a'] = False
|
file['a'] = False
|
||||||
|
@ -176,6 +152,24 @@ class Mega(object):
|
||||||
file['a'] = {'n': 'Rubbish Bin'}
|
file['a'] = {'n': 'Rubbish Bin'}
|
||||||
return file
|
return file
|
||||||
|
|
||||||
|
def init_shared_keys(self,files,shared_keys) :
|
||||||
|
'''
|
||||||
|
Init shared key not associated with a user.
|
||||||
|
It seems to happen when a folder is shared,
|
||||||
|
some files are exachanged and then the
|
||||||
|
folder is not shared anymore.
|
||||||
|
Keys are stored in files['s'] and files['ok']
|
||||||
|
'''
|
||||||
|
ok_dict = {}
|
||||||
|
for ok_item in files['ok'] :
|
||||||
|
shared_key = decrypt_key(base64_to_a32(ok_item['k']),self.master_key)
|
||||||
|
ok_dict[ok_item['h']] = shared_key
|
||||||
|
for s_item in files['s'] :
|
||||||
|
if s_item['u'] not in shared_keys :
|
||||||
|
shared_keys[s_item['u']] = {}
|
||||||
|
if s_item['h'] in ok_dict :
|
||||||
|
shared_keys[s_item['u']][s_item['h']] = ok_dict[s_item['h']]
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# GET
|
# GET
|
||||||
def find(self, filename):
|
def find(self, filename):
|
||||||
|
@ -193,8 +187,10 @@ class Mega(object):
|
||||||
'''
|
'''
|
||||||
files = self.api_request({'a': 'f', 'c': 1})
|
files = self.api_request({'a': 'f', 'c': 1})
|
||||||
files_dict = {}
|
files_dict = {}
|
||||||
|
shared_keys = {}
|
||||||
|
self.init_shared_keys(files,shared_keys)
|
||||||
for file in files['f']:
|
for file in files['f']:
|
||||||
processed_file = self.process_file(file)
|
processed_file = self.process_file(file,shared_keys)
|
||||||
#ensure each file has a name before returning
|
#ensure each file has a name before returning
|
||||||
if processed_file['a']:
|
if processed_file['a']:
|
||||||
files_dict[file['h']] = processed_file
|
files_dict[file['h']] = processed_file
|
||||||
|
@ -261,8 +257,10 @@ class Mega(object):
|
||||||
node_id = self.get_node_by_type(target)
|
node_id = self.get_node_by_type(target)
|
||||||
files = self.api_request({'a': 'f', 'c': 1})
|
files = self.api_request({'a': 'f', 'c': 1})
|
||||||
files_dict = {}
|
files_dict = {}
|
||||||
|
shared_keys = {}
|
||||||
|
self.init_shared_keys(files,shared_keys)
|
||||||
for file in files['f']:
|
for file in files['f']:
|
||||||
processed_file = self.process_file(file)
|
processed_file = self.process_file(file,shared_keys)
|
||||||
if processed_file['a'] and processed_file['p'] == node_id[0]:
|
if processed_file['a'] and processed_file['p'] == node_id[0]:
|
||||||
files_dict[file['h']] = processed_file
|
files_dict[file['h']] = processed_file
|
||||||
return files_dict
|
return files_dict
|
||||||
|
|
Loading…
Reference in a new issue