startapp 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (156) hide show
  1. checksums.yaml +7 -0
  2. data/COPYRIGHT +1 -0
  3. data/LICENSE +11 -0
  4. data/README.md +95 -0
  5. data/Rakefile +6 -0
  6. data/autocomplete/rhc_bash +1672 -0
  7. data/bin/app +37 -0
  8. data/conf/express.conf +8 -0
  9. data/features/assets/deploy.tar.gz +0 -0
  10. data/features/core_feature.rb +191 -0
  11. data/features/deployments_feature.rb +129 -0
  12. data/features/domains_feature.rb +58 -0
  13. data/features/keys_feature.rb +37 -0
  14. data/features/members_feature.rb +166 -0
  15. data/lib/rhc/auth/basic.rb +64 -0
  16. data/lib/rhc/auth/token.rb +102 -0
  17. data/lib/rhc/auth/token_store.rb +53 -0
  18. data/lib/rhc/auth.rb +5 -0
  19. data/lib/rhc/autocomplete.rb +66 -0
  20. data/lib/rhc/autocomplete_templates/bash.erb +39 -0
  21. data/lib/rhc/cartridge_helpers.rb +118 -0
  22. data/lib/rhc/cli.rb +40 -0
  23. data/lib/rhc/command_runner.rb +185 -0
  24. data/lib/rhc/commands/account.rb +25 -0
  25. data/lib/rhc/commands/alias.rb +124 -0
  26. data/lib/rhc/commands/app.rb +726 -0
  27. data/lib/rhc/commands/apps.rb +20 -0
  28. data/lib/rhc/commands/authorization.rb +115 -0
  29. data/lib/rhc/commands/base.rb +174 -0
  30. data/lib/rhc/commands/cartridge.rb +329 -0
  31. data/lib/rhc/commands/clone.rb +66 -0
  32. data/lib/rhc/commands/configure.rb +20 -0
  33. data/lib/rhc/commands/create.rb +100 -0
  34. data/lib/rhc/commands/delete.rb +19 -0
  35. data/lib/rhc/commands/deploy.rb +32 -0
  36. data/lib/rhc/commands/deployment.rb +82 -0
  37. data/lib/rhc/commands/domain.rb +172 -0
  38. data/lib/rhc/commands/env.rb +142 -0
  39. data/lib/rhc/commands/force_stop.rb +17 -0
  40. data/lib/rhc/commands/git_clone.rb +34 -0
  41. data/lib/rhc/commands/logout.rb +51 -0
  42. data/lib/rhc/commands/logs.rb +21 -0
  43. data/lib/rhc/commands/member.rb +148 -0
  44. data/lib/rhc/commands/port_forward.rb +197 -0
  45. data/lib/rhc/commands/reload.rb +17 -0
  46. data/lib/rhc/commands/restart.rb +17 -0
  47. data/lib/rhc/commands/scp.rb +54 -0
  48. data/lib/rhc/commands/server.rb +40 -0
  49. data/lib/rhc/commands/setup.rb +60 -0
  50. data/lib/rhc/commands/show.rb +43 -0
  51. data/lib/rhc/commands/snapshot.rb +137 -0
  52. data/lib/rhc/commands/ssh.rb +51 -0
  53. data/lib/rhc/commands/sshkey.rb +97 -0
  54. data/lib/rhc/commands/start.rb +17 -0
  55. data/lib/rhc/commands/stop.rb +17 -0
  56. data/lib/rhc/commands/tail.rb +47 -0
  57. data/lib/rhc/commands/threaddump.rb +14 -0
  58. data/lib/rhc/commands/tidy.rb +17 -0
  59. data/lib/rhc/commands.rb +396 -0
  60. data/lib/rhc/config.rb +321 -0
  61. data/lib/rhc/context_helper.rb +121 -0
  62. data/lib/rhc/core_ext.rb +202 -0
  63. data/lib/rhc/coverage_helper.rb +33 -0
  64. data/lib/rhc/deployment_helpers.rb +111 -0
  65. data/lib/rhc/exceptions.rb +256 -0
  66. data/lib/rhc/git_helpers.rb +106 -0
  67. data/lib/rhc/help_formatter.rb +55 -0
  68. data/lib/rhc/helpers.rb +481 -0
  69. data/lib/rhc/highline_extensions.rb +479 -0
  70. data/lib/rhc/json.rb +51 -0
  71. data/lib/rhc/output_helpers.rb +260 -0
  72. data/lib/rhc/rest/activation.rb +11 -0
  73. data/lib/rhc/rest/alias.rb +42 -0
  74. data/lib/rhc/rest/api.rb +87 -0
  75. data/lib/rhc/rest/application.rb +348 -0
  76. data/lib/rhc/rest/attributes.rb +36 -0
  77. data/lib/rhc/rest/authorization.rb +8 -0
  78. data/lib/rhc/rest/base.rb +79 -0
  79. data/lib/rhc/rest/cartridge.rb +162 -0
  80. data/lib/rhc/rest/client.rb +650 -0
  81. data/lib/rhc/rest/deployment.rb +18 -0
  82. data/lib/rhc/rest/domain.rb +98 -0
  83. data/lib/rhc/rest/environment_variable.rb +15 -0
  84. data/lib/rhc/rest/gear_group.rb +16 -0
  85. data/lib/rhc/rest/httpclient.rb +145 -0
  86. data/lib/rhc/rest/key.rb +44 -0
  87. data/lib/rhc/rest/membership.rb +105 -0
  88. data/lib/rhc/rest/mock.rb +1042 -0
  89. data/lib/rhc/rest/user.rb +32 -0
  90. data/lib/rhc/rest.rb +148 -0
  91. data/lib/rhc/scp_helpers.rb +27 -0
  92. data/lib/rhc/ssh_helpers.rb +380 -0
  93. data/lib/rhc/tar_gz.rb +51 -0
  94. data/lib/rhc/usage_templates/command_help.erb +51 -0
  95. data/lib/rhc/usage_templates/command_syntax_help.erb +11 -0
  96. data/lib/rhc/usage_templates/help.erb +61 -0
  97. data/lib/rhc/usage_templates/missing_help.erb +1 -0
  98. data/lib/rhc/usage_templates/options_help.erb +12 -0
  99. data/lib/rhc/vendor/okjson.rb +600 -0
  100. data/lib/rhc/vendor/parseconfig.rb +178 -0
  101. data/lib/rhc/vendor/sshkey.rb +253 -0
  102. data/lib/rhc/vendor/zliby.rb +628 -0
  103. data/lib/rhc/version.rb +5 -0
  104. data/lib/rhc/wizard.rb +637 -0
  105. data/lib/rhc.rb +34 -0
  106. data/spec/coverage_helper.rb +82 -0
  107. data/spec/direct_execution_helper.rb +339 -0
  108. data/spec/keys/example.pem +23 -0
  109. data/spec/keys/example_private.pem +27 -0
  110. data/spec/keys/server.pem +19 -0
  111. data/spec/rest_spec_helper.rb +31 -0
  112. data/spec/rhc/assets/cert.crt +22 -0
  113. data/spec/rhc/assets/cert_key_rsa +27 -0
  114. data/spec/rhc/assets/empty.txt +0 -0
  115. data/spec/rhc/assets/env_vars.txt +7 -0
  116. data/spec/rhc/assets/env_vars_2.txt +1 -0
  117. data/spec/rhc/assets/foo.txt +1 -0
  118. data/spec/rhc/assets/targz_corrupted.tar.gz +1 -0
  119. data/spec/rhc/assets/targz_sample.tar.gz +0 -0
  120. data/spec/rhc/auth_spec.rb +442 -0
  121. data/spec/rhc/cli_spec.rb +186 -0
  122. data/spec/rhc/command_spec.rb +435 -0
  123. data/spec/rhc/commands/account_spec.rb +42 -0
  124. data/spec/rhc/commands/alias_spec.rb +333 -0
  125. data/spec/rhc/commands/app_spec.rb +777 -0
  126. data/spec/rhc/commands/apps_spec.rb +39 -0
  127. data/spec/rhc/commands/authorization_spec.rb +157 -0
  128. data/spec/rhc/commands/cartridge_spec.rb +665 -0
  129. data/spec/rhc/commands/clone_spec.rb +41 -0
  130. data/spec/rhc/commands/deployment_spec.rb +327 -0
  131. data/spec/rhc/commands/domain_spec.rb +401 -0
  132. data/spec/rhc/commands/env_spec.rb +493 -0
  133. data/spec/rhc/commands/git_clone_spec.rb +102 -0
  134. data/spec/rhc/commands/logout_spec.rb +86 -0
  135. data/spec/rhc/commands/member_spec.rb +247 -0
  136. data/spec/rhc/commands/port_forward_spec.rb +217 -0
  137. data/spec/rhc/commands/scp_spec.rb +77 -0
  138. data/spec/rhc/commands/server_spec.rb +69 -0
  139. data/spec/rhc/commands/setup_spec.rb +118 -0
  140. data/spec/rhc/commands/snapshot_spec.rb +179 -0
  141. data/spec/rhc/commands/ssh_spec.rb +163 -0
  142. data/spec/rhc/commands/sshkey_spec.rb +188 -0
  143. data/spec/rhc/commands/tail_spec.rb +81 -0
  144. data/spec/rhc/commands/threaddump_spec.rb +84 -0
  145. data/spec/rhc/config_spec.rb +407 -0
  146. data/spec/rhc/helpers_spec.rb +531 -0
  147. data/spec/rhc/highline_extensions_spec.rb +314 -0
  148. data/spec/rhc/json_spec.rb +30 -0
  149. data/spec/rhc/rest_application_spec.rb +258 -0
  150. data/spec/rhc/rest_client_spec.rb +752 -0
  151. data/spec/rhc/rest_spec.rb +740 -0
  152. data/spec/rhc/targz_spec.rb +55 -0
  153. data/spec/rhc/wizard_spec.rb +756 -0
  154. data/spec/spec_helper.rb +575 -0
  155. data/spec/wizard_spec_helper.rb +330 -0
  156. metadata +469 -0
@@ -0,0 +1,178 @@
1
+ # modified version of parseconfig rubygem module
2
+ #
3
+ # Author:: BJ Dierkes <derks@bjdierkes.com>
4
+ # Copyright:: Copyright (c) 2006,2012 BJ Dierkes
5
+ # License:: MIT
6
+ # URL:: https://github.com/derks/ruby-parseconfig
7
+ #
8
+
9
+ # This class was written to simplify the parsing of configuration
10
+ # files in the format of "param = value". Please review the
11
+ # demo files included with this package.
12
+ #
13
+ # For further information please refer to the './doc' directory
14
+ # as well as the ChangeLog and README files included.
15
+ #
16
+
17
+ # Note: A group is a set of parameters defined for a subpart of a
18
+ # config file
19
+
20
+ module RHC
21
+ module Vendor
22
+ class ParseConfig
23
+
24
+ Version = '1.0.2'
25
+
26
+ attr_accessor :config_file, :params, :groups
27
+
28
+ # Initialize the class with the path to the 'config_file'
29
+ # The class objects are dynamically generated by the
30
+ # name of the 'param' in the config file. Therefore, if
31
+ # the config file is 'param = value' then the itializer
32
+ # will eval "@param = value"
33
+ #
34
+ def initialize(config_file=nil)
35
+ @config_file = config_file
36
+ @params = {}
37
+ @groups = []
38
+
39
+ if(self.config_file)
40
+ self.validate_config()
41
+ self.import_config()
42
+ end
43
+ end
44
+
45
+ # Validate the config file, and contents
46
+ def validate_config()
47
+ if !File.readable?(self.config_file)
48
+ raise Errno::EACCES, "#{self.config_file} is not readable"
49
+ end
50
+
51
+ # FIX ME: need to validate contents/structure?
52
+ end
53
+
54
+ # Import data from the config to our config object.
55
+ def import_config()
56
+ # The config is top down.. anything after a [group] gets added as part
57
+ # of that group until a new [group] is found.
58
+ group = nil
59
+ File.open(self.config_file) { |f| f.each do |line|
60
+ line.strip!
61
+ unless (/^\#/.match(line))
62
+ if(/\s*=\s*/.match(line))
63
+ param, value = line.split(/\s*=\s*/, 2)
64
+ var_name = "#{param}".chomp.strip
65
+ value = value.chomp.strip
66
+ new_value = ''
67
+ if (value)
68
+ if value =~ /^['"](.*)['"]$/
69
+ new_value = $1
70
+ else
71
+ new_value = value
72
+ end
73
+ else
74
+ new_value = ''
75
+ end
76
+
77
+ if group
78
+ self.add_to_group(group, var_name, new_value)
79
+ else
80
+ self.add(var_name, new_value)
81
+ end
82
+
83
+ elsif(/^\[(.+)\]$/.match(line).to_a != [])
84
+ group = /^\[(.+)\]$/.match(line).to_a[1]
85
+ self.add(group, {})
86
+
87
+ end
88
+ end
89
+ end }
90
+ end
91
+
92
+ # This method will provide the value held by the object "@param"
93
+ # where "@param" is actually the name of the param in the config
94
+ # file.
95
+ #
96
+ # DEPRECATED - will be removed in future versions
97
+ #
98
+ def get_value(param)
99
+ puts "ParseConfig Deprecation Warning: get_value() is deprecated. Use " + \
100
+ "config['param'] or config['group']['param'] instead."
101
+ return self.params[param]
102
+ end
103
+
104
+ # This method is a shortcut to accessing the @params variable
105
+ def [](param)
106
+ return self.params[param]
107
+ end
108
+
109
+ # This method returns all parameters/groups defined in a config file.
110
+ def get_params()
111
+ return self.params.keys
112
+ end
113
+
114
+ # List available sub-groups of the config.
115
+ def get_groups()
116
+ return self.groups
117
+ end
118
+
119
+ # This method adds an element to the config object (not the config file)
120
+ # By adding a Hash, you create a new group
121
+ def add(param_name, value)
122
+ if value.class == Hash
123
+ if self.params.has_key?(param_name)
124
+ if self.params[param_name].class == Hash
125
+ self.params[param_name].merge!(value)
126
+ elsif self.params.has_key?(param_name)
127
+ if self.params[param_name].class != value.class
128
+ raise ArgumentError, "#{param_name} already exists, and is of different type!"
129
+ end
130
+ end
131
+ else
132
+ self.params[param_name] = value
133
+ end
134
+ if ! self.groups.include?(param_name)
135
+ self.groups.push(param_name)
136
+ end
137
+ else
138
+ self.params[param_name] = value
139
+ end
140
+ end
141
+
142
+ # Add parameters to a group. Note that parameters with the same name
143
+ # could be placed in different groups
144
+ def add_to_group(group, param_name, value)
145
+ if ! self.groups.include?(group)
146
+ self.add(group, {})
147
+ end
148
+ self.params[group][param_name] = value
149
+ end
150
+
151
+ # Writes out the config file to output_stream
152
+ def write(output_stream=STDOUT)
153
+ self.params.each do |name,value|
154
+ if value.class.to_s != 'Hash'
155
+ if value.scan(/\w+/).length > 1
156
+ output_stream.puts "#{name} = \"#{value}\""
157
+ else
158
+ output_stream.puts "#{name} = #{value}"
159
+ end
160
+ end
161
+ end
162
+ output_stream.puts "\n"
163
+
164
+ self.groups.each do |group|
165
+ output_stream.puts "[#{group}]"
166
+ self.params[group].each do |param, value|
167
+ if value.scan(/\w+/).length > 1
168
+ output_stream.puts "#{param} = \"#{value}\""
169
+ else
170
+ output_stream.puts "#{param} = #{value}"
171
+ end
172
+ end
173
+ output_stream.puts "\n"
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,253 @@
1
+ # modified version of SSHKey rubygem module
2
+ # https://github.com/bensie/sshkey
3
+ #
4
+ # Copyright (c) 2011 James Miller
5
+
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+
25
+ require 'openssl'
26
+ require 'base64'
27
+ require 'digest/md5'
28
+ require 'digest/sha1'
29
+
30
+ module RHC
31
+ module Vendor
32
+ class SSHKey
33
+ SSH_TYPES = {"rsa" => "ssh-rsa", "dsa" => "ssh-dss"}
34
+ SSH_CONVERSION = {"rsa" => ["e", "n"], "dsa" => ["p", "q", "g", "pub_key"]}
35
+
36
+ attr_reader :key_object, :comment, :type
37
+ attr_accessor :passphrase
38
+
39
+ class << self
40
+ # Generate a new keypair and return an SSHKey object
41
+ #
42
+ # The default behavior when providing no options will generate a 2048-bit RSA
43
+ # keypair.
44
+ #
45
+ # ==== Parameters
46
+ # * options<~Hash>:
47
+ # * :type<~String> - "rsa" or "dsa", "rsa" by default
48
+ # * :bits<~Integer> - Bit length
49
+ # * :comment<~String> - Comment to use for the public key, defaults to ""
50
+ # * :passphrase<~String> - Encrypt the key with this passphrase
51
+ #
52
+ def generate(options = {})
53
+ type = options[:type] || "rsa"
54
+
55
+ # JRuby modulus size must range from 512 to 1024
56
+ default_bits = type == "rsa" ? 2048 : 1024
57
+
58
+ bits = options[:bits] || default_bits
59
+ cipher = OpenSSL::Cipher::Cipher.new("AES-128-CBC") if options[:passphrase]
60
+
61
+ case type.downcase
62
+ when "rsa" then new(OpenSSL::PKey::RSA.generate(bits).to_pem(cipher, options[:passphrase]), options)
63
+ when "dsa" then new(OpenSSL::PKey::DSA.generate(bits).to_pem(cipher, options[:passphrase]), options)
64
+ else
65
+ raise "Unknown key type: #{type}"
66
+ end
67
+ end
68
+
69
+ # Validate an existing SSH public key
70
+ #
71
+ # Returns true or false depending on the validity of the public key provided
72
+ #
73
+ # ==== Parameters
74
+ # * ssh_public_key<~String> - "ssh-rsa AAAAB3NzaC1yc2EA...."
75
+ #
76
+ def valid_ssh_public_key?(ssh_public_key)
77
+ ssh_type, encoded_key = ssh_public_key.split(" ")
78
+ type = SSH_TYPES.invert[ssh_type]
79
+ prefix = [0,0,0,7].pack("C*")
80
+ decoded = Base64.decode64(encoded_key)
81
+
82
+ # Base64 decoding is too permissive, so we should validate if encoding is correct
83
+ return false unless Base64.encode64(decoded).gsub("\n", "") == encoded_key
84
+ return false unless decoded.sub!(/^#{prefix}#{ssh_type}/, "")
85
+
86
+ unpacked = decoded.unpack("C*")
87
+ data = []
88
+ index = 0
89
+ until unpacked[index].nil?
90
+ datum_size = from_byte_array unpacked[index..index+4-1], 4
91
+ index = index + 4
92
+ datum = from_byte_array unpacked[index..index+datum_size-1], datum_size
93
+ data << datum
94
+ index = index + datum_size
95
+ end
96
+
97
+ SSH_CONVERSION[type].size == data.size
98
+ rescue
99
+ false
100
+ end
101
+
102
+ # Fingerprints
103
+ #
104
+ # Accepts either a public or private key
105
+ #
106
+ # MD5 fingerprint for the given SSH key
107
+ def md5_fingerprint(key)
108
+ if key.match(/PRIVATE/)
109
+ new(key).md5_fingerprint
110
+ else
111
+ Digest::MD5.hexdigest(decoded_key(key)).gsub(fingerprint_regex, '\1:\2')
112
+ end
113
+ end
114
+ alias_method :fingerprint, :md5_fingerprint
115
+
116
+ # SHA1 fingerprint for the given SSH key
117
+ def sha1_fingerprint(key)
118
+ if key.match(/PRIVATE/)
119
+ new(key).sha1_fingerprint
120
+ else
121
+ Digest::SHA1.hexdigest(decoded_key(key)).gsub(fingerprint_regex, '\1:\2')
122
+ end
123
+ end
124
+
125
+ private
126
+
127
+ def from_byte_array(byte_array, expected_size = nil)
128
+ num = 0
129
+ raise "Byte array too short" if !expected_size.nil? && expected_size != byte_array.size
130
+ byte_array.reverse.each_with_index do |item, index|
131
+ num += item * 256**(index)
132
+ end
133
+ num
134
+ end
135
+
136
+ def decoded_key(key)
137
+ Base64.decode64(key.chomp.gsub(/ssh-[dr]s[as] /, ''))
138
+ end
139
+
140
+ def fingerprint_regex
141
+ /(.{2})(?=.)/
142
+ end
143
+ end
144
+
145
+ # Create a new SSHKey object
146
+ #
147
+ # ==== Parameters
148
+ # * private_key - Existing RSA or DSA private key
149
+ # * options<~Hash>
150
+ # * :comment<~String> - Comment to use for the public key, defaults to ""
151
+ # * :passphrase<~String> - If the key is encrypted, supply the passphrase
152
+ #
153
+ def initialize(private_key, options = {})
154
+ @passphrase = options[:passphrase]
155
+ @comment = options[:comment] || ""
156
+ begin
157
+ @key_object = OpenSSL::PKey::RSA.new(private_key, passphrase)
158
+ @type = "rsa"
159
+ rescue
160
+ @key_object = OpenSSL::PKey::DSA.new(private_key, passphrase)
161
+ @type = "dsa"
162
+ end
163
+ end
164
+
165
+ # Fetch the RSA/DSA private key
166
+ #
167
+ # rsa_private_key and dsa_private_key are aliased for backward compatibility
168
+ def private_key
169
+ key_object.to_pem
170
+ end
171
+ alias_method :rsa_private_key, :private_key
172
+ alias_method :dsa_private_key, :private_key
173
+
174
+ # Fetch the encrypted RSA/DSA private key using the passphrase provided
175
+ #
176
+ # If no passphrase is set, returns the unencrypted private key
177
+ def encrypted_private_key
178
+ return private_key unless passphrase
179
+ key_object.to_pem(OpenSSL::Cipher::Cipher.new("AES-128-CBC"), passphrase)
180
+ end
181
+
182
+ # Fetch the RSA/DSA public key
183
+ #
184
+ # rsa_public_key and dsa_public_key are aliased for backward compatibility
185
+ def public_key
186
+ key_object.public_key.to_pem
187
+ end
188
+ alias_method :rsa_public_key, :public_key
189
+ alias_method :dsa_public_key, :public_key
190
+
191
+ # SSH public key
192
+ def ssh_public_key
193
+ [SSH_TYPES[type], Base64.encode64(ssh_public_key_conversion).gsub("\n", ""), comment].join(" ").strip
194
+ end
195
+
196
+ # Fingerprints
197
+ #
198
+ # MD5 fingerprint for the given SSH public key
199
+ def md5_fingerprint
200
+ Digest::MD5.hexdigest(ssh_public_key_conversion).gsub(/(.{2})(?=.)/, '\1:\2')
201
+ end
202
+ alias_method :fingerprint, :md5_fingerprint
203
+
204
+ # SHA1 fingerprint for the given SSH public key
205
+ def sha1_fingerprint
206
+ Digest::SHA1.hexdigest(ssh_public_key_conversion).gsub(/(.{2})(?=.)/, '\1:\2')
207
+ end
208
+
209
+ private
210
+
211
+ # SSH Public Key Conversion
212
+ #
213
+ # All data type encoding is defined in the section #5 of RFC #4251.
214
+ # String and mpint (multiple precision integer) types are encoded this way:
215
+ # 4-bytes word: data length (unsigned big-endian 32 bits integer)
216
+ # n bytes: binary representation of the data
217
+
218
+ # For instance, the "ssh-rsa" string is encoded as the following byte array
219
+ # [0, 0, 0, 7, 's', 's', 'h', '-', 'r', 's', 'a']
220
+ def ssh_public_key_conversion
221
+ out = [0,0,0,7].pack("C*")
222
+ out += SSH_TYPES[type]
223
+
224
+ SSH_CONVERSION[type].each do |method|
225
+ byte_array = to_byte_array(key_object.public_key.send(method).to_i)
226
+ out += encode_unsigned_int_32(byte_array.length).pack("c*")
227
+ out += byte_array.pack("C*")
228
+ end
229
+
230
+ return out
231
+ end
232
+
233
+ def encode_unsigned_int_32(value)
234
+ out = []
235
+ out[0] = value >> 24 & 0xff
236
+ out[1] = value >> 16 & 0xff
237
+ out[2] = value >> 8 & 0xff
238
+ out[3] = value & 0xff
239
+ return out
240
+ end
241
+
242
+ def to_byte_array(num)
243
+ result = []
244
+ begin
245
+ result << (num & 0xff)
246
+ num >>= 8
247
+ end until (num == 0 || num == -1) && (result.last[7] == num[7])
248
+ result.reverse
249
+ end
250
+
251
+ end
252
+ end
253
+ end