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/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 show_progress direction, total, increment = 0
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 a32, len=nil
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 a32
30
+ def a32_to_base64(a32)
50
31
  base64urlencode a32_to_str(a32)
51
32
  end
52
33
 
53
- def base64_to_a32 base64
34
+ def base64_to_a32(base64)
54
35
  str_to_a32 base64urldecode(base64)
55
36
  end
56
37
 
57
- def base64urlencode string
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 data
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 s
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 b
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
@@ -1,3 +1,3 @@
1
1
  module Rmega
2
- VERSION = "0.0.6"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/rmega.rb CHANGED
@@ -1,58 +1,13 @@
1
- # Gem with ruby 1.9+
2
- require "openssl"
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 "httpclient"
11
- require "execjs"
12
- require "ruby-progressbar"
13
-
14
- # Require all the other files
15
- require "rmega/version"
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/daniele-m/rmega"
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 operations' do
4
+ describe 'File download' do
5
5
 
6
6
  if account_file_exists?
7
7
 
8
- let(:temp_folder) { "/tmp/.rmega_spec" }
8
+ let(:storage) { login }
9
9
 
10
- before { FileUtils.mkdir_p(temp_folder) }
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 'give a public mega url, related to a big file' do
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
- before :all do
6
- @session = storage.session
7
- @parent_node = @session.storage.root_node
8
- @folder_name = "test_folder_#{rand.denominator}_#{rand.denominator}"
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
- it 'creates a new folder' do
13
- @folder_node.should be_kind_of Rmega::Node
12
+ def find_folder
13
+ @storage.root.folders.find { |f| f.name == @name }
14
14
  end
15
15
 
16
- it 'finds the folder' do
17
- node = @session.storage.nodes.find { |n| n.name == @folder_name }
18
- node.should_not be_nil
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
- it 'deletes the folder' do
22
- lambda { @folder_node.delete }.should_not raise_error
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
- it 'does not find the folder anymore' do
26
- node = @session.storage.nodes.find { |n| n.name == @folder_name }
27
- node.should be_nil
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 process' do
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 valid object' do
7
- object = storage
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
- lambda { Rmega.login 'a@apple.com', 'b' }.should raise_error(Rmega::ApiRequestError)
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 "yaml"
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 storage
18
- Rmega.login account['email'], account['password']
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
- require 'pry'
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
- def require_all
8
- $: << libpath
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.6
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-10 00:00:00.000000000 Z
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/file_node.rb
148
- - lib/rmega/nodes/folder_node.rb
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/file_operations_spec.rb
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/daniele-m/rmega
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/file_operations_spec.rb
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