Class: Rmega::Nodes::Node

Inherits:
Object
  • Object
show all
Includes:
Crypto, Loggable, Traversable, Rmega::NotInspectable
Defined in:
lib/rmega/nodes/node.rb

Direct Known Subclasses

File, Folder, Inbox, Root, Trash

Constant Summary collapse

TYPES =
{0 => :file, 1 => :folder, 2 => :root, 3 => :inbox, 4 => :trash}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Crypto::Rsa

#powm, #rsa_decrypt

Methods included from Crypto::AesCtr

#aes_ctr_cipher, #aes_ctr_decrypt, #aes_ctr_encrypt

Methods included from Crypto::AesEcb

#aes_ecb_cipher, #aes_ecb_decrypt, #aes_ecb_encrypt

Methods included from Crypto::AesCbc

#aes_cbc_cipher, #aes_cbc_decrypt, #aes_cbc_encrypt, #aes_cbc_mac

Methods included from Traversable

#children, #empty?, #files, #folders, #parent

Methods included from Loggable

#logger

Methods included from Rmega::NotInspectable

#inspect

Constructor Details

#initialize(session, data) ⇒ Node

Returns a new instance of Node.



15
16
17
18
# File 'lib/rmega/nodes/node.rb', line 15

def initialize(session, data)
  @session = session
  @data = data
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



9
10
11
# File 'lib/rmega/nodes/node.rb', line 9

def data
  @data
end

#sessionObject (readonly)

Returns the value of attribute session.



9
10
11
# File 'lib/rmega/nodes/node.rb', line 9

def session
  @session
end

Class Method Details

.each_chunk(size, &block) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/rmega/nodes/node.rb', line 83

def self.each_chunk(size, &block)
  start, p = 0, 0

  return if size <= 0

  loop do
    offset = p < 8 ? (131072 * (p += 1)) : 1048576
    next_start = offset + start

    if next_start >= size
      yield(start, size - start)
      break
    else
      yield(start, offset)
      start = next_start
    end
  end
end

Instance Method Details

#attributesObject



118
119
120
121
122
123
124
125
126
# File 'lib/rmega/nodes/node.rb', line 118

def attributes
  encrypted = data['a'] || data['at']
  return if !encrypted or encrypted.empty?
  node_key = NodeKey.load(decrypted_file_key)
  encrypted = Utils.base64urldecode(encrypted)
  encrypted.strip! if encrypted.size % 16 != 0 # Fix possible errors
  json = aes_cbc_decrypt(node_key.aes_key, encrypted)
  JSON.parse json.gsub(/^MEGA/, '').rstrip
end

#decrypted_file_keyObject



106
107
108
109
110
111
112
113
114
115
116
# File 'lib/rmega/nodes/node.rb', line 106

def decrypted_file_key
  h, shared_key = *process_shared_key

  if shared_key
    aes_ecb_decrypt(shared_key, file_keys[h])
  elsif file_key
    aes_ecb_decrypt(master_key, file_key)
  else
    Utils.base64urldecode(public_url.split('!').last)
  end
end

#each_chunk(&block) ⇒ Object



102
103
104
# File 'lib/rmega/nodes/node.rb', line 102

def each_chunk(&block)
  self.class.each_chunk(filesize, &block)
end

#file_keyObject



51
52
53
54
# File 'lib/rmega/nodes/node.rb', line 51

def file_key
  k = file_keys.values.first
  return k ? k : nil
end

#file_keysObject



40
41
42
43
44
45
46
47
48
49
# File 'lib/rmega/nodes/node.rb', line 40

def file_keys
  return {} unless data['k']

  pairs = data['k'].split('/')
  pairs.inject({}) do |hash, pair|
    h, k = pair.split(':')
    hash[h] = Utils.base64urldecode(k)
    hash
  end
end

#handleObject



28
29
30
# File 'lib/rmega/nodes/node.rb', line 28

def handle
  data['h']
end

#nameObject



36
37
38
# File 'lib/rmega/nodes/node.rb', line 36

def name
  attributes['n'] if attributes
end

#parent_handleObject



32
33
34
# File 'lib/rmega/nodes/node.rb', line 32

def parent_handle
  data['p']
end

#process_shared_keyObject



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/rmega/nodes/node.rb', line 60

def process_shared_key
  h = (shared_keys.keys & file_keys.keys).first
  return [h, shared_keys[h]] if h

  sk = data['sk']

  return unless sk

  shared_key = if sk.size > 22
    # Decrypt sk
    sk = Utils.base64_mpi_to_bn(sk)
    sk = rsa_decrypt(sk, rsa_privk)
    sk = sk.to_s(16)
    sk = '0' + sk if sk.size % 2 > 0
    Utils.hexstr_to_bstr(sk)[0..15]
  else
    aes_ecb_decrypt(master_key, Utils.base64urldecode(sk))
  end

  shared_keys[handle] = shared_key
  [handle, shared_key]
end

#public_handleObject



24
25
26
# File 'lib/rmega/nodes/node.rb', line 24

def public_handle
  @public_handle ||= request(a: 'l', n: handle)
end

#public_urlObject



20
21
22
# File 'lib/rmega/nodes/node.rb', line 20

def public_url
  @public_url ||= "https://mega.co.nz/#!#{public_handle}!#{Utils.base64urlencode(decrypted_file_key)}"
end

#shared_root?Boolean

Returns:

  • (Boolean)


56
57
58
# File 'lib/rmega/nodes/node.rb', line 56

def shared_root?
  data['su'] && data['sk'] && data['k']
end

#typeObject



128
129
130
# File 'lib/rmega/nodes/node.rb', line 128

def type
  TYPES[data['t']]
end