Class: Megar::Session

Inherits:
Object
  • Object
show all
Includes:
Connection, Crypto::Support
Defined in:
lib/megar/session.rb

Constant Summary

Constants included from Connection

Connection::DEFAULT_API_ENDPOINT

Instance Attribute Summary collapse

Attributes included from Connection

#sid

Instance Method Summary collapse

Methods included from Connection

#api_endpoint, #api_endpoint=, #api_request, #api_uri, #next_sequence_number!, #sequence_number, #sequence_number=

Methods included from Crypto::Support

#a32_to_base64, #a32_to_str, #accumulate_mac, #aes_cbc_decrypt, #aes_cbc_decrypt_a32, #aes_cbc_encrypt, #aes_cbc_encrypt_a32, #aes_encrypt_a32, #base64_mpi_to_a32, #base64_mpi_to_bn, #base64_to_a32, #base64urldecode, #base64urlencode, #calculate_chunk_mac, #crypto_requirements_met?, #decompose_file_key, #decompose_rsa_private_key, #decompose_rsa_private_key_a32, #decrypt_base64_to_a32, #decrypt_base64_to_str, #decrypt_file_attributes, #decrypt_file_key, #decrypt_key, #decrypt_session_id, #encrypt_file_attributes, #encrypt_key, #get_chunks, #get_file_cipher, #hexstr_to_bstr, #mpi_to_a32, #openssl_rsa_cipher, #openssl_rsa_decrypt, #prepare_key, #prepare_key_pw, #rsa_decrypt, #str_to_a32, #stringhash

Constructor Details

#initialize(options = {}) ⇒ Session

Start a new session, given options hash.

Required options parameters:

email: 'your email address'     -- email for authentication
password: 'your password'       -- password for authentication

Optional options parameters:

api_endpoint: 'url'             -- talk to an alternative API endpoint
autoconnect: true/false         -- performs immediate login if true (default)


23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/megar/session.rb', line 23

def initialize(options={})
  unless crypto_requirements_met?
    raise Megar::CryptoSupportRequirementsError.new(%(
      Oops! Looks like we don't have the necessary OpenSSL support available.

      See https://github.com/tardate/megar/blob/master/README.rdoc for hints on how to
      make sure the correct OpenSSL version is linked with your ruby.
    \n))
  end
  default_options = { autoconnect: true }
  @options = default_options.merge(options.symbolize_keys)
  self.api_endpoint = @options[:api_endpoint] if @options[:api_endpoint]
  connect! if @options[:autoconnect]
end

Instance Attribute Details

#decomposed_rsa_private_keyObject

4 part array of a32



11
12
13
# File 'lib/megar/session.rb', line 11

def decomposed_rsa_private_key
  @decomposed_rsa_private_key
end

#emailObject

Returns the user email (convenience method)



60
61
62
# File 'lib/megar/session.rb', line 60

def email
  @email
end

#master_keyObject

Returns the value of attribute master_key.



9
10
11
# File 'lib/megar/session.rb', line 9

def master_key
  @master_key
end

#optionsObject

Returns the value of attribute options.



6
7
8
# File 'lib/megar/session.rb', line 6

def options
  @options
end

#passwordObject

Returns the user password (convenience method)



65
66
67
# File 'lib/megar/session.rb', line 65

def password
  @password
end

#rsa_private_keyObject

binary string



10
11
12
# File 'lib/megar/session.rb', line 10

def rsa_private_key
  @rsa_private_key
end

Instance Method Details

#connect!Object

Command: perform login session challenge/response. Establishes a user session based on the response to a cryptographic challenge.



55
56
57
# File 'lib/megar/session.rb', line 55

def connect!
  ()
end

#connected?Boolean

Returns authenticated/connected status

Returns:

  • (Boolean)


39
40
41
# File 'lib/megar/session.rb', line 39

def connected?
  !sid.nil?
end

#filesObject

Returns the files collection



81
82
83
84
# File 'lib/megar/session.rb', line 81

def files
  refresh_files! if @files.nil?
  @files
end

#foldersObject

Returns the folder collection



75
76
77
78
# File 'lib/megar/session.rb', line 75

def folders
  refresh_files! if @folders.nil?
  @folders
end

#get_file_download_url_response(node_id) ⇒ Object

Command: requests file download url from the API for the file with id node_id



96
97
98
99
# File 'lib/megar/session.rb', line 96

def get_file_download_url_response(node_id)
  ensure_connected!
  api_request({'a' => 'g', 'g' => 1, 'n' => node_id})
end

#get_file_upload_url_response(size) ⇒ Object

Command: requests file upload url from the API for the file of size



102
103
104
105
# File 'lib/megar/session.rb', line 102

def get_file_upload_url_response(size)
  ensure_connected!
  api_request({'a' => 'u', 's' => size})
end

#handle_files_response(response_data, reset = true) ⇒ Object

Command: decrypt/decode the login response_data received from Mega



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/megar/session.rb', line 131

def handle_files_response(response_data,reset=true)
  reset_files! if reset
  response_data['f'].each do |f|
    item_attributes = {id: f['h'], payload: f.dup, type: f['t'] }
    case f['t']
    when 0 # File
      item_attributes[:key] = k = decrypt_file_key(f)
      item_attributes[:decomposed_key] = key = decompose_file_key(k)
      item_attributes[:attributes] = decrypt_file_attributes(f['a'],key)
      files.add(item_attributes)
    when 1 # Folder
      item_attributes[:key] = k = decrypt_file_key(f)
      item_attributes[:attributes] = decrypt_file_attributes(f['a'],k)
      folders.add(item_attributes)
    when 2,3,4 # Root, Inbox, Trash Bin
      folders.add(item_attributes)
    end
  end
  true
end

#refresh_files!Object



86
87
88
# File 'lib/megar/session.rb', line 86

def refresh_files!
  handle_files_response(get_files_response)
end

#reset_files!Object



90
91
92
93
# File 'lib/megar/session.rb', line 90

def reset_files!
  @folders = Megar::Folders.new(session: self)
  @files = Megar::Files.new(session: self)
end

#rsa_private_key_b64Object

Returns the rsa_private_key base64-encoded



70
71
72
# File 'lib/megar/session.rb', line 70

def rsa_private_key_b64
  base64urlencode(rsa_private_key)
end

#send_file_upload_attributes(folder_id, name, upload_key, meta_mac, completion_file_handle) ⇒ Object

Command: sends updated attributes following file upload to the API



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/megar/session.rb', line 108

def send_file_upload_attributes(folder_id,name,upload_key,meta_mac,completion_file_handle)
  attribs = {'n' => name}
  encrypt_attribs = base64urlencode(encrypt_file_attributes(attribs, upload_key[0,4]))

  key = [upload_key[0] ^ upload_key[4], upload_key[1] ^ upload_key[5],
         upload_key[2] ^ meta_mac[0], upload_key[3] ^ meta_mac[1],
         upload_key[4], upload_key[5], meta_mac[0], meta_mac[1]]

  encrypted_key = a32_to_base64(encrypt_key(key, master_key))
  api_request({
    'a' => 'p',
    't' => folder_id,
    'n' => [{
      'h' => completion_file_handle,
      't' => 0,
      'a' => encrypt_attribs,
      'k' => encrypted_key
    }]
  })
end

#to_sObject

Returns a pretty representation of the session object



44
45
46
47
48
49
50
# File 'lib/megar/session.rb', line 44

def to_s
  if connected?
    "#{self.class.name}: connected as #{email}"
  else
    "#{self.class.name}: not connected"
  end
end