rmega 0.0.6 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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