rmega 0.0.6 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +108 -55
- data/lib/rmega/crypto/aes.rb +5 -3
- data/lib/rmega/crypto/aes_ctr.rb +5 -2
- data/lib/rmega/crypto/crypto.rb +13 -8
- data/lib/rmega/crypto/rsa.rb +3 -1
- data/lib/rmega/downloader.rb +13 -16
- data/lib/rmega/loggable.rb +9 -2
- data/lib/rmega/nodes/deletable.rb +16 -0
- data/lib/rmega/nodes/expandable.rb +64 -0
- data/lib/rmega/nodes/factory.rb +41 -0
- data/lib/rmega/nodes/file.rb +39 -0
- data/lib/rmega/nodes/folder.rb +30 -0
- data/lib/rmega/nodes/inbox.rb +8 -0
- data/lib/rmega/nodes/node.rb +58 -100
- data/lib/rmega/nodes/root.rb +12 -0
- data/lib/rmega/nodes/trash.rb +18 -0
- data/lib/rmega/nodes/traversable.rb +26 -0
- data/lib/rmega/options.rb +16 -0
- data/lib/rmega/pool.rb +4 -6
- data/lib/rmega/progress.rb +34 -0
- data/lib/rmega/{api_request_error.rb → request_error.rb} +7 -10
- data/lib/rmega/session.rb +20 -31
- data/lib/rmega/storage.rb +19 -68
- data/lib/rmega/uploader.rb +58 -0
- data/lib/rmega/utils.rb +35 -29
- data/lib/rmega/version.rb +1 -1
- data/lib/rmega.rb +8 -53
- data/rmega.gemspec +2 -2
- data/spec/integration/{file_operations_spec.rb → file_download_spec.rb} +4 -8
- data/spec/integration/folder_operations_spec.rb +27 -15
- data/spec/integration/login_spec.rb +6 -5
- data/spec/integration_spec_helper.rb +12 -4
- data/spec/rmega/lib/utils_spec.rb +0 -7
- data/spec/spec_helper.rb +4 -11
- metadata +18 -24
- data/lib/rmega/nodes/file_node.rb +0 -27
- data/lib/rmega/nodes/folder_node.rb +0 -29
data/lib/rmega/utils.rb
CHANGED
@@ -1,35 +1,16 @@
|
|
1
|
+
require 'rmega/utils'
|
2
|
+
|
1
3
|
module Rmega
|
2
4
|
module Utils
|
3
5
|
extend self
|
4
6
|
|
5
|
-
def
|
6
|
-
return unless Rmega.options.show_progress
|
7
|
-
if increment.zero?
|
8
|
-
@progressbar = nil
|
9
|
-
@progressbar_progress = 0
|
10
|
-
end
|
11
|
-
@progressbar_progress += increment
|
12
|
-
format = "#{direction.to_s.capitalize} in progress #{Utils.format_bytes(@progressbar_progress)} of #{Utils.format_bytes(total)} | %P% | %e "
|
13
|
-
@progressbar ||= ProgressBar.create format: format, total: total
|
14
|
-
@progressbar.reset if increment.zero?
|
15
|
-
@progressbar.format format
|
16
|
-
@progressbar.progress += increment
|
17
|
-
end
|
18
|
-
|
19
|
-
def format_bytes bytes, round = 2
|
20
|
-
units = ['bytes', 'kb', 'MB', 'GB', 'TB', 'PB']
|
21
|
-
e = (bytes == 0 ? 0 : Math.log(bytes)) / Math.log(1024)
|
22
|
-
value = bytes.to_f / (1024 ** e.floor)
|
23
|
-
"#{value.round(round)}#{units[e]}"
|
24
|
-
end
|
25
|
-
|
26
|
-
def str_to_a32 string
|
7
|
+
def str_to_a32(string)
|
27
8
|
pad_to = string.bytesize + ((string.bytesize) % 4)
|
28
9
|
string = string.ljust pad_to, "\x00"
|
29
10
|
string.unpack 'l>*'
|
30
11
|
end
|
31
12
|
|
32
|
-
def a32_to_str
|
13
|
+
def a32_to_str(a32, len = nil)
|
33
14
|
if len
|
34
15
|
b = []
|
35
16
|
len.times do |i|
|
@@ -46,15 +27,15 @@ module Rmega
|
|
46
27
|
@b64a ||= ('A'..'Z').to_a + ('a'..'z').to_a + ('0'..'9').to_a + ["-", "_", "="]
|
47
28
|
end
|
48
29
|
|
49
|
-
def a32_to_base64
|
30
|
+
def a32_to_base64(a32)
|
50
31
|
base64urlencode a32_to_str(a32)
|
51
32
|
end
|
52
33
|
|
53
|
-
def base64_to_a32
|
34
|
+
def base64_to_a32(base64)
|
54
35
|
str_to_a32 base64urldecode(base64)
|
55
36
|
end
|
56
37
|
|
57
|
-
def base64urlencode
|
38
|
+
def base64urlencode(string)
|
58
39
|
i = 0
|
59
40
|
tmp_arr = []
|
60
41
|
|
@@ -81,7 +62,7 @@ module Rmega
|
|
81
62
|
(r != 0) ? enc[0..r - 4] : enc
|
82
63
|
end
|
83
64
|
|
84
|
-
def base64urldecode
|
65
|
+
def base64urldecode(data)
|
85
66
|
data += '=='[((2-data.length*3)&3)..-1]
|
86
67
|
|
87
68
|
i = 0
|
@@ -121,7 +102,7 @@ module Rmega
|
|
121
102
|
tmp_arr.join ''
|
122
103
|
end
|
123
104
|
|
124
|
-
def mpi2b
|
105
|
+
def mpi2b(s)
|
125
106
|
bn = 1
|
126
107
|
r = [0]
|
127
108
|
rn = 0
|
@@ -159,7 +140,7 @@ module Rmega
|
|
159
140
|
r
|
160
141
|
end
|
161
142
|
|
162
|
-
def b2s
|
143
|
+
def b2s(b)
|
163
144
|
bs = 28
|
164
145
|
bm = 268435455
|
165
146
|
bn = 1; bc = 0; r = [0]; rb = 1; rn = 0
|
@@ -196,5 +177,30 @@ module Rmega
|
|
196
177
|
|
197
178
|
rr
|
198
179
|
end
|
180
|
+
|
181
|
+
def chunks(size)
|
182
|
+
list = {}
|
183
|
+
p = 0
|
184
|
+
pp = 0
|
185
|
+
i = 1
|
186
|
+
|
187
|
+
while i <= 8 and p < size - (i * 0x20000)
|
188
|
+
list[p] = i * 0x20000
|
189
|
+
pp = p
|
190
|
+
p += list[p]
|
191
|
+
i += 1
|
192
|
+
end
|
193
|
+
|
194
|
+
while p < size
|
195
|
+
list[p] = 0x100000
|
196
|
+
pp = p
|
197
|
+
p += list[p]
|
198
|
+
end
|
199
|
+
|
200
|
+
if size - pp > 0
|
201
|
+
list[pp] = size - pp
|
202
|
+
end
|
203
|
+
list
|
204
|
+
end
|
199
205
|
end
|
200
206
|
end
|
data/lib/rmega/version.rb
CHANGED
data/lib/rmega.rb
CHANGED
@@ -1,58 +1,13 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
require "json"
|
4
|
-
require "logger"
|
5
|
-
require "ostruct"
|
6
|
-
|
7
|
-
# Gems in the bundle
|
1
|
+
require 'active_support/json'
|
2
|
+
require 'active_support/core_ext/object/to_json'
|
8
3
|
require 'active_support/core_ext/module/delegation'
|
9
4
|
require 'active_support/core_ext/string/inflections'
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
|
14
|
-
|
15
|
-
require
|
16
|
-
require "rmega/loggable"
|
17
|
-
require "rmega/utils"
|
18
|
-
require "rmega/crypto/rsa"
|
19
|
-
require "rmega/crypto/aes"
|
20
|
-
require "rmega/crypto/aes_ctr"
|
21
|
-
require "rmega/crypto/crypto"
|
22
|
-
require "rmega/storage"
|
23
|
-
require "rmega/nodes/node"
|
24
|
-
require "rmega/nodes/file_node"
|
25
|
-
require "rmega/nodes/folder_node"
|
26
|
-
require "rmega/session"
|
27
|
-
require "rmega/api_request_error"
|
28
|
-
require "rmega/pool"
|
29
|
-
require "rmega/downloader"
|
5
|
+
require 'httpclient'
|
6
|
+
require 'ruby-progressbar'
|
7
|
+
require 'execjs'
|
8
|
+
require 'rmega/version'
|
9
|
+
require 'rmega/options'
|
10
|
+
require 'rmega/session'
|
30
11
|
|
31
12
|
module Rmega
|
32
|
-
def self.logger
|
33
|
-
@logger ||= begin
|
34
|
-
logger = Logger.new $stdout
|
35
|
-
logger.formatter = Proc.new { | severity, time, progname, msg| "#{msg}\n" }
|
36
|
-
logger.level = Logger::ERROR
|
37
|
-
logger
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.login email, password
|
42
|
-
session = Session.new email, password
|
43
|
-
session.storage
|
44
|
-
end
|
45
|
-
|
46
|
-
def self.default_options
|
47
|
-
{
|
48
|
-
show_progress: true,
|
49
|
-
upload_timeout: 120,
|
50
|
-
api_request_timeout: 20,
|
51
|
-
api_url: 'https://eu.api.mega.co.nz/cs'
|
52
|
-
}
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.options
|
56
|
-
@options ||= OpenStruct.new default_options
|
57
|
-
end
|
58
13
|
end
|
data/rmega.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |gem|
|
|
6
6
|
gem.email = ["dani.m.mobile@gmail.com"]
|
7
7
|
gem.description = %q{mega.co.nz ruby api}
|
8
8
|
gem.summary = %q{mega.co.nz ruby api}
|
9
|
-
gem.homepage = "https://github.com/
|
9
|
+
gem.homepage = "https://github.com/topac/rmega"
|
10
10
|
|
11
11
|
gem.files = `git ls-files`.split($\)
|
12
12
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
@@ -18,8 +18,8 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.add_development_dependency "pry"
|
19
19
|
gem.add_development_dependency "rspec"
|
20
20
|
gem.add_development_dependency "rake"
|
21
|
+
|
21
22
|
gem.add_dependency "httpclient"
|
22
23
|
gem.add_dependency 'active_support'
|
23
|
-
gem.add_dependency "ruby-progressbar"
|
24
24
|
gem.add_dependency "execjs"
|
25
25
|
end
|
@@ -1,17 +1,13 @@
|
|
1
1
|
require 'integration_spec_helper'
|
2
2
|
require 'fileutils'
|
3
3
|
|
4
|
-
describe 'File
|
4
|
+
describe 'File download' do
|
5
5
|
|
6
6
|
if account_file_exists?
|
7
7
|
|
8
|
-
let(:
|
8
|
+
let(:storage) { login }
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
after { FileUtils.rm_rf(temp_folder) }
|
13
|
-
|
14
|
-
context 'give a public mega url, related to a small file' do
|
10
|
+
context 'given a public mega url (a small file)' do
|
15
11
|
|
16
12
|
# A file called testfile.txt containting the string "helloworld!"
|
17
13
|
let(:url) { 'https://mega.co.nz/#!MAkg2Iab!bc9Y2U6d93IlRRKVYpcC9hLZjS4G278OPdH6nTFPDNQ' }
|
@@ -23,7 +19,7 @@ describe 'File operations' do
|
|
23
19
|
end
|
24
20
|
end
|
25
21
|
|
26
|
-
context '
|
22
|
+
context 'given a public mega url (a big file)' do
|
27
23
|
|
28
24
|
# A file called testfile_big_15mb.txt containting the word "topac" repeated 3145728 times (~ 15mb)
|
29
25
|
let(:url) { 'https://mega.co.nz/#!NYVkDaLD!BKyN5SRpOaEtGnTcwiAqcxmJc7p-k0IPWKAW-471KRE' }
|
@@ -1,30 +1,42 @@
|
|
1
1
|
require 'integration_spec_helper'
|
2
2
|
|
3
3
|
describe 'Folders operations' do
|
4
|
+
|
4
5
|
if account_file_exists?
|
5
|
-
|
6
|
-
|
7
|
-
@
|
8
|
-
@
|
9
|
-
@folder_node = @session.storage.create_folder @parent_node, @folder_name
|
6
|
+
|
7
|
+
before(:all) do
|
8
|
+
@name = "test_folder_#{rand.denominator}_#{rand.denominator}"
|
9
|
+
@storage = login
|
10
10
|
end
|
11
11
|
|
12
|
-
|
13
|
-
@
|
12
|
+
def find_folder
|
13
|
+
@storage.root.folders.find { |f| f.name == @name }
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
node
|
16
|
+
context 'when #create_folder is called on a node' do
|
17
|
+
|
18
|
+
it 'creates a new folder under that node' do
|
19
|
+
folder = @storage.root.create_folder(@name)
|
20
|
+
expect(folder.name).to eql @name
|
21
|
+
end
|
19
22
|
end
|
20
23
|
|
21
|
-
|
22
|
-
|
24
|
+
context 'searching for a folder by its name' do
|
25
|
+
|
26
|
+
it 'returns the matching folder' do
|
27
|
+
expect(find_folder.name).to eql @name
|
28
|
+
end
|
23
29
|
end
|
24
30
|
|
25
|
-
|
26
|
-
|
27
|
-
|
31
|
+
context 'when #delete is called on a folder node' do
|
32
|
+
|
33
|
+
it 'deletes the folder' do
|
34
|
+
expect(find_folder.delete).to eql 0
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'does not find the folder anymore' do
|
38
|
+
expect(find_folder).to be_nil
|
39
|
+
end
|
28
40
|
end
|
29
41
|
end
|
30
42
|
end
|
@@ -1,17 +1,18 @@
|
|
1
1
|
require 'integration_spec_helper'
|
2
2
|
|
3
|
-
describe 'Login
|
3
|
+
describe 'Login' do
|
4
|
+
|
4
5
|
if account_file_exists?
|
6
|
+
|
5
7
|
context 'when email and password are correct' do
|
6
|
-
it 'returns a
|
7
|
-
|
8
|
-
object.should respond_to :nodes
|
8
|
+
it 'returns a Storage object' do
|
9
|
+
expect(login).to respond_to :nodes
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
12
13
|
context 'when email and password are invalid' do
|
13
14
|
it 'raises an error' do
|
14
|
-
|
15
|
+
expect { Rmega.login('a@apple.com', 'b') }.to raise_error(Rmega::RequestError)
|
15
16
|
end
|
16
17
|
end
|
17
18
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require
|
3
|
-
|
2
|
+
require 'yaml'
|
4
3
|
|
5
4
|
def account_file_path
|
6
5
|
File.join File.dirname(__FILE__), 'integration/rmega_account.yml'
|
@@ -14,6 +13,15 @@ def account
|
|
14
13
|
@account ||= YAML.load_file account_file_path
|
15
14
|
end
|
16
15
|
|
17
|
-
def
|
18
|
-
Rmega.login
|
16
|
+
def login
|
17
|
+
Rmega.login(account['email'], account['password'])
|
18
|
+
end
|
19
|
+
|
20
|
+
def temp_folder
|
21
|
+
'/tmp/.rmega_spec'
|
22
|
+
end
|
23
|
+
|
24
|
+
RSpec.configure do |config|
|
25
|
+
config.before { FileUtils.mkdir_p(temp_folder) }
|
26
|
+
config.after { FileUtils.rm_rf(temp_folder) }
|
19
27
|
end
|
@@ -22,13 +22,6 @@ describe Rmega::Utils do
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
describe '#format_bytes' do
|
26
|
-
it 'converts to the correct unit' do
|
27
|
-
described_class.format_bytes(1024, 2).should == '1.0kb'
|
28
|
-
described_class.format_bytes(1024**2).should == '1.0MB'
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
25
|
describe '#a32_to_str' do
|
33
26
|
it 'returns the expected value' do
|
34
27
|
a32 = [1953853537, 1660944384]
|
data/spec/spec_helper.rb
CHANGED
@@ -1,12 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
def libpath
|
4
|
-
File.expand_path File.join(File.dirname(__FILE__), '../lib')
|
5
|
-
end
|
1
|
+
RMEGA_LIB_PATH = File.expand_path File.join(File.dirname(__FILE__), '../lib')
|
2
|
+
$: << RMEGA_LIB_PATH
|
6
3
|
|
7
|
-
|
8
|
-
|
9
|
-
require 'rmega'
|
10
|
-
end
|
11
|
-
|
12
|
-
require_all
|
4
|
+
require 'pry'
|
5
|
+
require 'rmega'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rmega
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-07-
|
12
|
+
date: 2013-07-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: pry
|
@@ -91,22 +91,6 @@ dependencies:
|
|
91
91
|
- - ! '>='
|
92
92
|
- !ruby/object:Gem::Version
|
93
93
|
version: '0'
|
94
|
-
- !ruby/object:Gem::Dependency
|
95
|
-
name: ruby-progressbar
|
96
|
-
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
|
-
requirements:
|
99
|
-
- - ! '>='
|
100
|
-
- !ruby/object:Gem::Version
|
101
|
-
version: '0'
|
102
|
-
type: :runtime
|
103
|
-
prerelease: false
|
104
|
-
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
|
-
requirements:
|
107
|
-
- - ! '>='
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: '0'
|
110
94
|
- !ruby/object:Gem::Dependency
|
111
95
|
name: execjs
|
112
96
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,7 +120,6 @@ files:
|
|
136
120
|
- README.md
|
137
121
|
- Rakefile
|
138
122
|
- lib/rmega.rb
|
139
|
-
- lib/rmega/api_request_error.rb
|
140
123
|
- lib/rmega/crypto/aes.rb
|
141
124
|
- lib/rmega/crypto/aes_ctr.rb
|
142
125
|
- lib/rmega/crypto/crypto.rb
|
@@ -144,16 +127,27 @@ files:
|
|
144
127
|
- lib/rmega/crypto/rsa_mega.js
|
145
128
|
- lib/rmega/downloader.rb
|
146
129
|
- lib/rmega/loggable.rb
|
147
|
-
- lib/rmega/nodes/
|
148
|
-
- lib/rmega/nodes/
|
130
|
+
- lib/rmega/nodes/deletable.rb
|
131
|
+
- lib/rmega/nodes/expandable.rb
|
132
|
+
- lib/rmega/nodes/factory.rb
|
133
|
+
- lib/rmega/nodes/file.rb
|
134
|
+
- lib/rmega/nodes/folder.rb
|
135
|
+
- lib/rmega/nodes/inbox.rb
|
149
136
|
- lib/rmega/nodes/node.rb
|
137
|
+
- lib/rmega/nodes/root.rb
|
138
|
+
- lib/rmega/nodes/trash.rb
|
139
|
+
- lib/rmega/nodes/traversable.rb
|
140
|
+
- lib/rmega/options.rb
|
150
141
|
- lib/rmega/pool.rb
|
142
|
+
- lib/rmega/progress.rb
|
143
|
+
- lib/rmega/request_error.rb
|
151
144
|
- lib/rmega/session.rb
|
152
145
|
- lib/rmega/storage.rb
|
146
|
+
- lib/rmega/uploader.rb
|
153
147
|
- lib/rmega/utils.rb
|
154
148
|
- lib/rmega/version.rb
|
155
149
|
- rmega.gemspec
|
156
|
-
- spec/integration/
|
150
|
+
- spec/integration/file_download_spec.rb
|
157
151
|
- spec/integration/folder_operations_spec.rb
|
158
152
|
- spec/integration/login_spec.rb
|
159
153
|
- spec/integration_spec_helper.rb
|
@@ -161,7 +155,7 @@ files:
|
|
161
155
|
- spec/rmega/lib/crypto/crypto_spec.rb
|
162
156
|
- spec/rmega/lib/utils_spec.rb
|
163
157
|
- spec/spec_helper.rb
|
164
|
-
homepage: https://github.com/
|
158
|
+
homepage: https://github.com/topac/rmega
|
165
159
|
licenses: []
|
166
160
|
post_install_message:
|
167
161
|
rdoc_options: []
|
@@ -186,7 +180,7 @@ signing_key:
|
|
186
180
|
specification_version: 3
|
187
181
|
summary: mega.co.nz ruby api
|
188
182
|
test_files:
|
189
|
-
- spec/integration/
|
183
|
+
- spec/integration/file_download_spec.rb
|
190
184
|
- spec/integration/folder_operations_spec.rb
|
191
185
|
- spec/integration/login_spec.rb
|
192
186
|
- spec/integration_spec_helper.rb
|
@@ -1,27 +0,0 @@
|
|
1
|
-
require_relative '../downloader'
|
2
|
-
|
3
|
-
module Rmega
|
4
|
-
class FileNode < Node
|
5
|
-
def storage_url
|
6
|
-
@storage_url ||= data['g'] || request(a: 'g', g: 1, n: handle)['g']
|
7
|
-
end
|
8
|
-
|
9
|
-
def download(path)
|
10
|
-
path = File.expand_path(path)
|
11
|
-
path = Dir.exists?(path) ? File.join(path, name) : path
|
12
|
-
|
13
|
-
logger.info "Download #{name} (#{filesize} bytes) => #{path}"
|
14
|
-
|
15
|
-
k = decrypted_file_key
|
16
|
-
k = [k[0] ^ k[4], k[1] ^ k[5], k[2] ^ k[6], k[3] ^ k[7]]
|
17
|
-
nonce = decrypted_file_key[4..5]
|
18
|
-
|
19
|
-
donwloader = Downloader.new(base_url: storage_url, filesize: filesize, local_path: path)
|
20
|
-
|
21
|
-
donwloader.download do |start, buffer|
|
22
|
-
nonce = [nonce[0], nonce[1], (start/0x1000000000) >> 0, (start/0x10) >> 0]
|
23
|
-
Crypto::AesCtr.decrypt(k, nonce, buffer)[:data]
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
module Rmega
|
2
|
-
class FolderNode < Node
|
3
|
-
def self.create session, parent_node, folder_name
|
4
|
-
key = Crypto.random_key
|
5
|
-
encrypted_attributes = Utils.a32_to_base64 Crypto.encrypt_attributes(key[0..3], {n: folder_name.strip})
|
6
|
-
encrypted_key = Utils.a32_to_base64 Crypto.encrypt_key(session.master_key, key)
|
7
|
-
n = [{h: 'xxxxxxxx', t: 1, a: encrypted_attributes, k: encrypted_key}]
|
8
|
-
data = session.request a: 'p', t: parent_node.handle, n: n
|
9
|
-
new session, data['f'][0]
|
10
|
-
end
|
11
|
-
|
12
|
-
def children
|
13
|
-
storage.nodes.select { |node| node.parent_handle == handle }
|
14
|
-
end
|
15
|
-
|
16
|
-
def download path
|
17
|
-
children.each do |node|
|
18
|
-
if node.type == :file
|
19
|
-
node.download path
|
20
|
-
elsif node.type == :folder
|
21
|
-
subfolder = File.expand_path File.join(path, node.name)
|
22
|
-
Dir.mkdir(subfolder) unless Dir.exists?(subfolder)
|
23
|
-
node.download subfolder
|
24
|
-
end
|
25
|
-
end
|
26
|
-
nil
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|