34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
# File 'lib/rmega/nodes/uploadable.rb', line 34
def upload(path)
path = ::File.expand_path(path)
filesize = ::File.size(path)
raise "Empty file - #{path}" if filesize == 0
file = ::File.open(path, 'rb')
rnd_node_key = NodeKey.random
file_handle = nil
base_url = upload_url(filesize)
pool = Pool.new
read_mutex = Mutex.new
progress = Progress.new(filesize, caption: 'Upload', filename: ::File.basename(path))
chunk_macs = {}
self.class.each_chunk(filesize) do |start, size|
pool.process do
clean_buffer = nil
read_mutex.synchronize do
clean_buffer = read_chunk(file, start, size)
end
encrypted_buffer, chunk_mac = *encrypt_chunck(start, clean_buffer, rnd_node_key.aes_key, rnd_node_key.ctr_nonce)
file_handle = upload_chunk(base_url, start, encrypted_buffer)
chunk_macs[start] = chunk_mac
progress.increment(size)
end
end
pool.shutdown
_attr = serialize_attributes(:n => ::File.basename(path))
_attr = aes_cbc_encrypt(rnd_node_key.aes_key, _attr)
file_mac = aes_cbc_mac(rnd_node_key.aes_key, chunk_macs.sort.map(&:last).join, "\x0"*16)
rnd_node_key.meta_mac = Utils.compact_to_8_bytes(file_mac)
encrypted_key = aes_ecb_encrypt(session.master_key, rnd_node_key.generate)
resp = request(a: 'p', t: handle, n: [
{h: file_handle, t: 0, a: Utils.base64urlencode(_attr), k: Utils.base64urlencode(encrypted_key)}
])
return Nodes::Factory.build(session, resp['f'][0])
ensure
file.close if file
end
|