rubyment 0.0.25412377

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/rubyment.rb +928 -0
  3. metadata +44 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a9208f93d3d661766f031a48cdf67ce3f51e0428
4
+ data.tar.gz: 59ef6e69fed727e3c89ca47381e295d56b2d6522
5
+ SHA512:
6
+ metadata.gz: '09829192637dbe01786a49d5b29029f63626a30292249c3ead3dc6ff1cb2d57a3ed8c93af96394ef42c194aaf429221f0b9504ac757d8ca72d2dec82608bdd0d'
7
+ data.tar.gz: a35573505864cab6d7c5521709bbb41130673f3d9989d6c10520cbfe0ca9e4046d3f9df2929f9b92cc55a966d1abaf72253847139e9c2328d23b83c614ca14b0
data/lib/rubyment.rb ADDED
@@ -0,0 +1,928 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Collection of Ruby functions
4
+ # * output
5
+ # normally outputs to STDERR, with
6
+ # no mercy
7
+ # STDOUT, just qualified output:
8
+ # only if the function is expected
9
+ # to output something
10
+ class Rubyment
11
+
12
+ # invoke first arg with following args
13
+ # used by initialize
14
+ def invoke args=ARGV
15
+ begin
16
+ # this condition could become ambiguous only when
17
+ # a function has only one argument (if it has
18
+ # more, the rescue case would fail anyway. if
19
+ # it has zero, both are equally OK).
20
+ # In only one argument case, it is better not to
21
+ # splat -- because most of the functions takes
22
+ # an array as argument. the drawback is that
23
+ # functions taking only one argument can't be
24
+ # called from the command line (an array will
25
+ # be given to them)
26
+ self.method(args[0]).call (args[1..-1])
27
+ rescue ArgumentError => e
28
+ self.method(args[0]).call *(args[1..-1])
29
+ end
30
+ end
31
+
32
+ def initialize memory = {}
33
+ @memory = {
34
+ :invoke => [],
35
+ :stderr => STDERR,
36
+ :stdout => STDOUT,
37
+ :stdin => STDIN,
38
+ :time => Time.now,
39
+ :basic_version => (Time.now.to_i / 60), # new one every minute
40
+ :filepath => __FILE__,
41
+ :running_dir => Dir.pwd,
42
+ :home_dir => Dir.home,
43
+ :system_user => ENV['USER'] || ENV['USERNAME'],
44
+ :system_user_is_super => ENV['USER'] == "root", # changed plan: platform indenpend.
45
+ :static_separator_key => "strings_having_this_string_not_guaranteed_to_work",
46
+ :static_end_key => "strings_havinng_this_string_also_not_guaranteed_to_work",
47
+ }
48
+ @memory.update memory
49
+ invoke @memory[:invoke].to_a
50
+ end
51
+
52
+
53
+ # enables the possibility to inkove a second method with
54
+ # the results of a first one. eg, the results of a method
55
+ # called file_permissions_octal which returns without output
56
+ # can be output as:
57
+ # [ "puts", "file_permissions_octal", "/"]
58
+ # TODO; flawed example
59
+ def invoke_double args=ARGV
60
+ second_invokation, first_invokation = [args[0], args[1..-1]]
61
+ first_invokation_result = (invoke first_invokation)
62
+ invoke [second_invokation] + [first_invokation_result].flatten(1)
63
+ end
64
+
65
+ # if file is a nonexisting filepath, or by any reason
66
+ # throws any exception, it will be treated as contents
67
+ # instead, and the filename will treated as ""
68
+ # file can be a url, if 'open-uri' is available.
69
+ def file_backup file = __FILE__ , dir = '/tmp/', append = ('-' + Time.now.hash.abs.to_s), prepend='/'
70
+ stderr = @memory[:stderr]
71
+ (require 'open-uri') && open_uri = true
72
+ require 'fileutils'
73
+ file_is_filename = true
74
+ open_uri && (
75
+ contents = open(file).read rescue (file_is_filename = false) || file
76
+ ) || (
77
+ contents = File.read file rescue (file_is_filename = false) || file
78
+ )
79
+ stderr.puts "location = dir:#{dir} + prepend:#{prepend} + (#{file_is_filename} && #{file} || '' ) + #{append}"
80
+ location = dir + prepend + (file_is_filename && file || '' ) + append
81
+ stderr.puts "FileUtils.mkdir_p File.dirname #{location}" # note "~" doesn't work
82
+ FileUtils.mkdir_p File.dirname location # note "~" doesn't work
83
+ File.write location, contents
84
+ contents
85
+ end
86
+
87
+
88
+ # args:
89
+ # path (String)
90
+ # returns:
91
+ # file_permissions_octal (Integer, ready to go to chmod, or nil,
92
+ # if file doesn't exist)
93
+ def file_permissions_octal path
94
+ File.stat(path).mode.to_s(8).split("")[-4..-1].join.to_i(8) rescue nil
95
+ end
96
+
97
+
98
+ # save url contents to a local file location
99
+ # url can be a uri to a local file
100
+ # args:
101
+ # url (String), location (String), wtime (Integer)
102
+ # more (Hash)
103
+ # details:
104
+ # more[:username], more[:password] for http_basic_authentication
105
+ # returns
106
+ # contents of url (String)
107
+ def save_file url, location, wtime=0, more = {}
108
+ require 'open-uri'
109
+ require 'fileutils'
110
+ FileUtils.mkdir_p File.dirname location # note "~" doesn't work
111
+ user = more[:username]
112
+ pw = more[:password]
113
+ contents = open(url, :http_basic_authentication => [user, pw]).read
114
+ r = File.write location, contents
115
+ sleep wtime
116
+ contents
117
+ end
118
+
119
+
120
+ # returns url contents
121
+ def url_to_str url, rescue_value=nil
122
+ require 'open-uri'
123
+ contents = open(url).read rescue rescue_value
124
+ end
125
+
126
+
127
+ # returns the contents of file (or empty, or a default
128
+ # if a second parameter is given).
129
+ # if file is a nonexisting filepath, or by any reason
130
+ # throws any exception, it will be treated as contents
131
+ # instead
132
+ # file can be a url, if 'open-uri' is available.
133
+ def filepath_or_contents file, contents = ""
134
+ stderr = @memory[:stderr]
135
+ (require 'open-uri') && open_uri = true
136
+ require 'fileutils'
137
+ file = file.to_s
138
+ file_is_filename = true
139
+ open_uri && (
140
+ contents = open(file).read rescue (file_is_filename = false) || file
141
+ ) || (
142
+ contents = File.read file rescue (file_is_filename = false) || file
143
+ )
144
+ contents
145
+ end
146
+
147
+ # returns the first value of args if it is a non empty
148
+ # string, or prompt for a multi line string.
149
+ # useful for reading file contents, e.g.
150
+ def input_non_empty_string_or_multiline_prompt args=ARGV
151
+ stderr = @memory[:stderr]
152
+ stderr.print "multiline[control-D to stop]:"
153
+ args.shift.to_s.split("\0").first || readlines.join
154
+ end
155
+
156
+
157
+ # returns the filepath_or_contents of the first value of args
158
+ # if it is a non empty string,
159
+ # or prompt for a multi line string.
160
+ # useful for reading file contents, e.g.
161
+ def input_non_empty_filepath_or_contents_or_multiline_prompt args=ARGV
162
+ stderr = @memory[:stderr]
163
+ stderr.print "multiline[control-D to stop]:"
164
+ (filepath_or_contents args.shift).to_s.split("\0").first || readlines.join
165
+ end
166
+
167
+
168
+ # opens an echoing prompt, if arg1 is nil or empty
169
+ # args:
170
+ # [ arg1 (String or nil)]
171
+ def input_single_line args=ARGV
172
+ stderr = @memory[:stderr]
173
+ stdin = @memory[:stdin]
174
+ stderr.print "single line:"
175
+ args.shift.to_s.split("\0").first || stdin.gets.chomp
176
+ end
177
+
178
+
179
+ # opens a non-echoing prompt, if arg1 is nil or empty
180
+ # args:
181
+ # [ arg1 (String or nil)]
182
+ def input_single_line_non_echo args=ARGV
183
+ stderr = @memory[:stderr]
184
+ stdin = @memory[:stdin]
185
+ require "io/console"
186
+ stderr.print "non echo single line:"
187
+ args.shift.to_s.split("\0").first || stdin.noecho{ stdin.gets}.chomp
188
+ end
189
+
190
+
191
+ # opens an echoing multiline prompt, if arg1 is nil or empty
192
+ # args:
193
+ # [ arg1 (String or nil)]
194
+ def input_multi_line args=ARGV
195
+ stderr = @memory[:stderr]
196
+ stdin = @memory[:stdin]
197
+ stderr.print "multiline[control-D to stop]:"
198
+ args.shift.to_s.split("\0").first || stdin.readlines.join
199
+ end
200
+
201
+
202
+ # opens a non-echoing multiline prompt, if arg1 is nil or empty
203
+ # args:
204
+ # [ arg1 (String or nil)]
205
+ def input_multi_line_non_echo args=ARGV
206
+ stderr = @memory[:stderr]
207
+ stdin = @memory[:stdin]
208
+ require "io/console"
209
+ stderr.print "multiline[control-D to stop]:"
210
+ args.shift.to_s.split("\0").first || stdin.noecho{ stdin.readlines}.join.chomp
211
+ end
212
+
213
+
214
+ def input_shift_or_empty_string args=ARGV, default = ''
215
+ args.shift || default
216
+ end
217
+
218
+ def input_shift args=ARGV
219
+ args.shift
220
+ end
221
+
222
+
223
+ # outputs in such a way that it can be given
224
+ # as an array of parameters via bash shell
225
+ # not fully tested, use with caution.
226
+ def output_array_to_shell args=ARGV
227
+ args.map {|arg|
228
+ "\"" << (arg && arg.to_s || "") << "\""
229
+ }.join " "
230
+ end
231
+
232
+ # place a \n at every max_column chars
233
+ # approximately (a word can be bigger
234
+ # than max_column, and some other
235
+ # situations)
236
+ def string_in_columns s, max_column=80
237
+ max_column = max_column.to_i
238
+ as = 0 ; ln = 0 ; t = s.split.chunk {|l| ((l.size + as) <= max_column ) && (as += l.size ) && ln || (as = l.size; ln += 1) }.entries.map {|a| a.last.join(" ") }.join("\n")
239
+ t
240
+ end
241
+
242
+
243
+ # planned changes:
244
+ # use stdin from memory instead
245
+ def shell_string_in_columns args=ARGV
246
+ stderr = @memory[:stderr]
247
+ time = @memory[:time]
248
+ number_of_columns = input_shift args
249
+ text = input_non_empty_filepath_or_contents_or_multiline_prompt args
250
+ puts (string_in_columns text, number_of_columns)
251
+ end
252
+
253
+
254
+ # print arguments given
255
+ def main args=ARGV
256
+ stderr = @memory[:stderr]
257
+ time = @memory[:time]
258
+ puts args.join " "
259
+ end
260
+
261
+
262
+ # makes a rest request.
263
+ # for now, the parameters must still be hardcoded.
264
+ def rest_request args=ARGV
265
+ require 'base64'
266
+ require 'rest-client'
267
+ require 'json'
268
+ stderr = @memory[:stderr]
269
+ time = @memory[:time]
270
+
271
+ atlasian_account="my_atlasian_account"
272
+ jira_host = "https://mydomain.atlassian.net/"
273
+ issue = "JIRAISSUE-6517"
274
+ url = "#{jira_host}/rest/api/2/issue/#{issue}/comment"
275
+ # ways to set base64_auth:
276
+ # 1) programmatically: let pw in plain text:
277
+ # auth = "my_user:my_pw"
278
+ # base64_auth = Base64.encode64 auth
279
+ # 2) a bit safer (this hash can be still used
280
+ # to hijack your account):
281
+ # echo "my_user:my_pw" | base64 # let a whitespace in the beginning
282
+ base64_auth = "bXlfdXNlcjpteV9wdwo="
283
+ # todo: it has to be interactive, or fetch from a keying
284
+ # to achieve good security standards
285
+ method = :get
286
+ method = :post
287
+ timeout = 2000
288
+ headers = {"Authorization" => "Basic #{base64_auth}" }
289
+ verify_ssl = true
290
+ json =<<-ENDHEREDOC
291
+ {
292
+ "body" : "my comment"
293
+ }
294
+ ENDHEREDOC
295
+ payload = "#{json}"
296
+ request_execution = RestClient::Request.execute(:method => method, :url => url, :payload => payload, :headers => headers, :verify_ssl => verify_ssl, :timeout => timeout)
297
+ parsed_json = JSON.parse request_execution.to_s
298
+ stderr.puts parsed_json
299
+ parsed_json
300
+ end
301
+
302
+
303
+ # generates (by default) a 128 bit key for a Cipher (e.g. AES)
304
+ # args:
305
+ # [ password, salt, iter, key_len ]
306
+ # returns:
307
+ # [key, password, salt, iter, key_len]
308
+ #
309
+ # planned changes:
310
+ # ensure that random_bytes == key_len
311
+ def generate_pbkdf2_key args=ARGV
312
+ require 'openssl'
313
+ password, salt, iter, key_len = args
314
+ iter = (iter.to_i > 0) && iter.to_i || 20000
315
+ key_len = (salt.to_s.split("\0").first && salt.to_s.size > 0 && salt.size || 16)
316
+ salt = salt.to_s.split("\0").first || OpenSSL::Random.random_bytes(key_len)
317
+ key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(password.to_s, salt.to_s, iter.to_i, key_len.to_i)
318
+ [key, password, salt, iter, key_len]
319
+ end
320
+
321
+
322
+ # decrypt encrypted (string), having password (string), iv (string),
323
+ # big_file(bool) is a flag to set padding to 0.
324
+ #
325
+ # planned changes:
326
+ # add metadata information to encrypted
327
+ # decipher.key = Digest::SHA256.hexdigest is not the best security.
328
+ # encrypted could be called base64_encrypted
329
+ # iv could be called base64_iv
330
+ # get only one string, not encrypted and iv (see enc planned changes)
331
+ # remove dependence on the uniqueness of ending
332
+ #
333
+ def dec args=ARGV
334
+ require 'openssl'
335
+ require 'base64'
336
+ memory = @memory
337
+ static_end_key = memory[:static_end_key]
338
+ password, iv, encrypted, ending, base64_salt, base64_iter = args
339
+ salt = Base64.decode64 base64_salt
340
+ iter = Base64.decode64 base64_iter
341
+ ending = ending.to_s.split("\0").first || static_end_key
342
+ key, password, salt, iter = (
343
+ generate_pbkdf2_key [password, salt, iter]
344
+ )|| [nil, password, salt, iter]
345
+
346
+ decipher = OpenSSL::Cipher.new('aes-128-cbc')
347
+ decipher.decrypt
348
+ decipher.padding = 0
349
+
350
+ decipher.key = key || (Digest::SHA256.hexdigest password)
351
+ decipher.iv = Base64.decode64 iv
352
+ plain = decipher.update(Base64.decode64 encrypted) + decipher.final
353
+ # split is not the ideal, if ever ending is duplicated it won't
354
+ # work. also may be innefficient.
355
+ (plain.split ending).first
356
+
357
+ end
358
+
359
+
360
+ # prompts for arguments to dec function
361
+ # args:
362
+ # [ iv, encrypted, password ] (all Strings)
363
+ # returns:
364
+ # [password, encrypted, iv] (all Strings)
365
+ # planned changes:
366
+ # call separate functions.
367
+ #
368
+ def shell_dec_input args=ARGV
369
+ require 'stringio'
370
+ require "io/console"
371
+ memory = @memory
372
+ debug = memory[:debug]
373
+ stderr = memory[:stderr]
374
+ stdout = memory[:stdout]
375
+ stdin = memory[:stdin]
376
+
377
+ stderr.print "iv:"
378
+ # basically => any string other than "" or the default one:
379
+ iv = args.shift.to_s.split("\0").first
380
+ iv = (url_to_str iv) || iv.to_s.split("\0").first || (url_to_str 'out.enc.iv.base64')
381
+ debug && (stderr.puts iv)
382
+ stderr.puts
383
+ stderr.print "encrypted:"
384
+ # basically => any string other than "" or the default one:
385
+ encrypted = args.shift.to_s.split("\0").first
386
+ encrypted = (url_to_str encrypted) || encrypted.to_s.split("\0").first || (url_to_str 'out.enc.encrypted.base64')
387
+ debug && (stderr.puts "#{encrypted}")
388
+ stderr.puts
389
+ stderr.print "password:"
390
+ password = args.shift.to_s.split("\0").first || begin stdin.noecho{ stdin.gets}.chomp rescue gets.chomp end
391
+ stderr.puts
392
+ [password, encrypted, iv]
393
+ end
394
+
395
+
396
+ # and output the decrypted data to stdout.
397
+ #
398
+ # planned changes:
399
+ # stop argument shifting.
400
+ # call separate functions.
401
+ #
402
+ def shell_dec_output args=ARGV
403
+ memory = @memory
404
+ stdout = memory[:stdout]
405
+ pw_plain, reserved_for_future = args
406
+ stdout.puts pw_plain
407
+ end
408
+
409
+
410
+ # prompts for arguments to dec, calls dec,
411
+ # and output the decrypted data to stdout.
412
+ # args:
413
+ # (forwarded to shell_dec_input, as of now:
414
+ # returns:
415
+ # nil
416
+ #
417
+ # planned changes:
418
+ # stop argument shifting.
419
+ # call separate functions.
420
+ #
421
+ def shell_dec args=ARGV
422
+ require 'json'
423
+ require 'base64'
424
+ memory = @memory
425
+ stderr = memory[:stderr]
426
+ password, base64_json_serialized_data, iv_deprecated = shell_dec_input args
427
+ metadata = JSON.parse Base64.decode64 base64_json_serialized_data
428
+ base64_iv = metadata["base64_iv"]
429
+ base64_encrypted = metadata["base64_encrypted"]
430
+ base64_salt = metadata["base64_salt"]
431
+ base64_iter = metadata["base64_iter"]
432
+ base64_key = metadata["base64_key" ]
433
+ ending = nil
434
+ pw_plain = dec [password, base64_iv, base64_encrypted, ending, base64_salt, base64_iter]
435
+ # p pw_plain
436
+ shell_dec_output [pw_plain]
437
+ end
438
+
439
+ # encrypt data (string), with password (string)
440
+ # returns [base64_iv, base64_encrypted]
441
+ #
442
+ # planned changes:
443
+ # add metadata information to encrypted
444
+ # return only one string, having encrypted + metadata (having iv)
445
+ # add string length to metadata
446
+ # decipher.key = Digest::SHA256.hexdigest is not the best security.
447
+ #
448
+ def enc args=ARGV
449
+ require 'openssl'
450
+ require 'base64'
451
+ memory = @memory
452
+ static_end_key = memory[:static_end_key]
453
+ password, data, ending, salt, iter = args
454
+ ending ||= static_end_key
455
+ key, password, salt, iter = (
456
+ generate_pbkdf2_key [password, salt, iter]
457
+ )|| [nil, password, salt, iter]
458
+
459
+ cipher = OpenSSL::Cipher.new('aes-128-cbc')
460
+ cipher.encrypt
461
+
462
+ cipher.key = key || (Digest::SHA256.hexdigest password)
463
+ iv = cipher.random_iv
464
+ encrypted = cipher.update(data + ending) + cipher.final
465
+
466
+ base64_iv = Base64.encode64 iv
467
+ base64_encrypted = Base64.encode64 encrypted
468
+ base64_salt = Base64.encode64 salt.to_s
469
+ base64_iter = Base64.encode64 iter.to_s
470
+ base64_key = Base64.encode64 key.to_s
471
+
472
+ [base64_encrypted, base64_iv, base64_salt, base64_iter, base64_key]
473
+ end
474
+
475
+
476
+ # prompts for arguments to dec
477
+ # args:
478
+ # [ multiline_data, data_file, single_line_data, password, encrypted_base64_filename, enc_iv_base64_filename_deprecated] (all Strings)
479
+ # returns:
480
+ # [password, data, encrypted_base64_filename, enc_iv_base64_filename_deprecated]
481
+ #
482
+ # planned changes:
483
+ # call separate functions.
484
+ # stop argument shifting.
485
+ #
486
+ def shell_enc_input args=ARGV
487
+ memory = @memory
488
+ stderr = @memory[:stderr]
489
+ stdout = @memory[:stdout]
490
+ stdin = @memory[:stdin]
491
+ debug = memory[:debug]
492
+ require 'stringio'
493
+ require "io/console"
494
+
495
+ data = ""
496
+ stderr.print "multi_line_data[ data 1/3, echoing, control-D to stop]:"
497
+ data += args.shift || (stdin.readlines.join rescue readlines.join)
498
+ stderr.puts
499
+ stderr.print "data_file [data 2/3]:"
500
+ data_file = args.shift || (stdin.gets.chomp rescue gets.chomp)
501
+ data += url_to_str data_file, ""
502
+ stderr.puts
503
+ stderr.print "single_line_data[data 3/3, no echo part]:"
504
+ data += args.shift || begin stdin.noecho{ stdin.gets}.chomp rescue gets.chomp end
505
+ stderr.puts
506
+ stderr.print "password:"
507
+ password = args.shift.to_s.split("\0").first || begin stdin.noecho{ stdin.gets}.chomp rescue gets.chomp end
508
+ stderr.puts
509
+ stderr.print "encrypted_base64_filename[default=out.enc.encrypted.base64]:"
510
+ # basically => any string other than "" or the default one:
511
+ encrypted_base64_filename = args.shift.to_s.split("\0").first || "out.enc.encrypted.base64"
512
+ stderr.puts encrypted_base64_filename
513
+ stderr.puts
514
+ stderr.print "enc_iv_base64_filename[DEPRECATED]:"
515
+ # basically => any string other than "" or the default one:
516
+ enc_iv_base64_filename_deprecated = args.shift.to_s.split("\0").first || "out.enc.iv.base64"
517
+ stderr.puts enc_iv_base64_filename_deprecated
518
+
519
+ [password, data, encrypted_base64_filename, enc_iv_base64_filename_deprecated]
520
+ end
521
+
522
+
523
+ # outputs the results from enc
524
+ def shell_enc_output args=ARGV
525
+ memory = @memory
526
+ stderr = memory[:stderr]
527
+ base64_encrypted, base64_iv, encrypted_base64_filename, enc_iv_base64_filename_deprecated = args
528
+ puts base64_iv
529
+ puts base64_encrypted
530
+ File.write encrypted_base64_filename, base64_encrypted
531
+ stderr.puts
532
+ end
533
+
534
+
535
+ # shell_enc
536
+ # args
537
+ # [password, data, encrypted_base64_filename, enc_iv_base64_filename_deprecated] (all Strings)
538
+ # encrypts data using password and stores to encrypted_base64_filename
539
+ # returns
540
+ # nil
541
+ #
542
+ # planned changes:
543
+ # encrypted_base64_filename
544
+ def shell_enc args=ARGV
545
+ require 'json'
546
+ require 'base64'
547
+ require 'openssl'
548
+ password, data, encrypted_base64_filename, enc_iv_base64_filename_deprecated = shell_enc_input args
549
+ salt = nil
550
+ iter = nil
551
+ ending = nil
552
+ base64_encrypted, base64_iv, base64_salt, base64_iter, base64_key = enc [password, data, ending, salt, iter]
553
+ metadata = {
554
+ "metadata" => "Metadata",
555
+ "base64_iv" => base64_iv,
556
+ "base64_encrypted" => base64_encrypted,
557
+ "base64_salt" => base64_salt,
558
+ "base64_iter" => base64_iter,
559
+ }
560
+ base64_json_serialized_data = Base64.encode64 JSON.pretty_generate metadata
561
+ shell_enc_output [base64_json_serialized_data, base64_iv, encrypted_base64_filename ]
562
+ end
563
+
564
+
565
+ # serialize_json_metadata
566
+ # args:
567
+ # [payload (String), metadata (Hash), separator (String)]
568
+ # prepends a JSON dump of metadata followed by separator
569
+ # to a copy of payload, and returns it.
570
+ def serialize_json_metadata args=ARGV
571
+ require 'json'
572
+ memory = @memory
573
+ static_separator = memory[:static_separator_key]
574
+ payload, metadata, separator = args
575
+ metadata ||= { }
576
+ separator ||= static_separator
577
+ serialized_string = (JSON.pretty_generate metadata) + separator + payload
578
+ end
579
+
580
+
581
+ # deserialize_json_metadata
582
+ # args:
583
+ # [serialized_string (String), separator (String)]
584
+ # undo what serialize_json_metadata
585
+ # returns array:
586
+ # [payload (String), metadata (Hash or String), separator (String)]
587
+ # metadata is returned as Hash after a JSON.parse, but in case
588
+ # of any failure, it returns the String itself.
589
+ def deserialize_json_metadata args=ARGV
590
+ require 'json'
591
+ memory = @memory
592
+ static_separator = memory[:static_separator_key]
593
+ serialized_string, separator = args
594
+ separator ||= static_separator
595
+ metadata_json, payload = serialized_string.to_s.split separator
596
+ metadata = (JSON.parse metadata_json) rescue metadata_json
597
+ [payload, metadata, separator]
598
+ end
599
+
600
+
601
+ # test__json_metadata_serialization
602
+ # sanity test for serialize_json_metadata and deserialize_json_metadata
603
+ def test__json_metadata_serialization args=ARGV
604
+ judgement = true
605
+ payload = "Payload"
606
+ # note: keys with : instead can't be recovered, because
607
+ # they aren't described in JSON files
608
+ metadata = { "metadata" => "Metadata" }
609
+ serialized = (serialize_json_metadata [payload, metadata ])
610
+ new_payload, new_metadata = deserialize_json_metadata [serialized]
611
+ judgement =
612
+ [ [payload, new_payload, "payload"], [metadata, new_metadata, "metadata"]]
613
+ .map(&method("expect_equal")).all?
614
+ end
615
+
616
+
617
+ # format strings for expect_format_string
618
+ def expect_format_string args=ARGV
619
+ memory = @memory
620
+ debug = memory[:debug]
621
+ prepend_text, value_before, value_after, value_label, comparison_text = args
622
+ "#{prepend_text} #{value_label}: #{value_before} #{comparison_text} #{value_after}"
623
+ end
624
+
625
+
626
+ # expect_equal
627
+ # args:
628
+ # [ value_before (Object), value_after (Object), value_label (String) ]
629
+ # returns the value of testing value_before == value_after, printing to
630
+ # stderr upon failure
631
+ def expect_equal args=ARGV
632
+ memory = @memory
633
+ stderr = memory[:stderr]
634
+ value_before, value_after, value_label = args
635
+ judgement = (value_before == value_after)
636
+ (!judgement) && (stderr.puts expect_format_string ["unexpected", value_before, value_after, value_label, "!="])
637
+ judgement
638
+ end
639
+
640
+
641
+ # test__shell_enc_dec
642
+ # sanity test for shell_enc and shell_dec
643
+ # planned changes:
644
+ # don't output to stdout
645
+ def test__shell_enc_dec args=ARGV
646
+ shell_enc ["my secret", "", "", "tijolo22", "", ""]
647
+ # shell_dec will read from the output file:
648
+ judgement = ( shell_dec ["", "", "tijolo22"] || true) rescue false
649
+ end
650
+
651
+
652
+ # test for enc and dec.
653
+ # "" and nil are expected to be treated
654
+ # as the same.
655
+ def test__enc_dec_nil args=ARGV
656
+ nil_case = dec [nil, "ltUQIxgRAeUNXPNTTps8FQ==\n", "xyeqxw/TzkyXtOxpDqAl58SNAvXPyNZ89B5JGtwDkcbjo0vObgPsh5FrgZJs\nHPjofsyXnljnTrHpDoQeDVezo9wBZ74NU+TSi/GssX605oE=\n", nil, "TU4o3IKiFWki3rZ3lMchLQ==\n", "MjAwMDA=\n"]
657
+ # args inspect in enc
658
+ p output_array_to_shell [nil, "ltUQIxgRAeUNXPNTTps8FQ==\n", "xyeqxw/TzkyXtOxpDqAl58SNAvXPyNZ89B5JGtwDkcbjo0vObgPsh5FrgZJs\nHPjofsyXnljnTrHpDoQeDVezo9wBZ74NU+TSi/GssX605oE=\n", nil, "TU4o3IKiFWki3rZ3lMchLQ==\n", "MjAwMDA=\n"]
659
+ p "--"
660
+ puts output_array_to_shell [nil, "ltUQIxgRAeUNXPNTTps8FQ==\n", "xyeqxw/TzkyXtOxpDqAl58SNAvXPyNZ89B5JGtwDkcbjo0vObgPsh5FrgZJs\nHPjofsyXnljnTrHpDoQeDVezo9wBZ74NU+TSi/GssX605oE=\n", nil, "TU4o3IKiFWki3rZ3lMchLQ==\n", "MjAwMDA=\n"]
661
+ return
662
+ # [nil, "ltUQIxgRAeUNXPNTTps8FQ==\n", "xyeqxw/TzkyXtOxpDqAl58SNAvXPyNZ89B5JGtwDkcbjo0vObgPsh5FrgZJs\nHPjofsyXnljnTrHpDoQeDVezo9wBZ74NU+TSi/GssX605oE=\n", nil, "TU4o3IKiFWki3rZ3lMchLQ==\n", "MjAwMDA=\n"]
663
+ empty = dec ["", "ltUQIxgRAeUNXPNTTps8FQ==\n", "xyeqxw/TzkyXtOxpDqAl58SNAvXPyNZ89B5JGtwDkcbjo0vObgPsh5FrgZJs\nHPjofsyXnljnTrHpDoQeDVezo9wBZ74NU+TSi/GssX605oE=\n", "", "TU4o3IKiFWki3rZ3lMchLQ==\n", "MjAwMDA=\n"]
664
+ # /rubyment.rb dec "" "ltUQIxgRAeUNXPNTTps8FQ==\n" "xyeqxw/TzkyXtOxpDqAl58SNAvXPyNZ89B5JGtwDkcbjo0vObgPsh5FrgZJs\nHPjofsyXnljnTrHpDoQeDVezo9wBZ74NU+TSi/GssX605oE=\n" "" "TU4o3IKiFWki3rZ3lMchLQ==\n" "MjAwMDA=\n"
665
+ # args inpect in dec:
666
+ # ["", "ltUQIxgRAeUNXPNTTps8FQ==\\n", "xyeqxw/TzkyXtOxpDqAl58SNAvXPyNZ89B5JGtwDkcbjo0vObgPsh5FrgZJs\\nHPjofsyXnljnTrHpDoQeDVezo9wBZ74NU+TSi/GssX605oE=\\n", "", "TU4o3IKiFWki3rZ3lMchLQ==\\n", "MjAwMDA=\\n"]
667
+
668
+ judgement =
669
+ [
670
+ [nil_case, empty, "empty_nil_equality"]
671
+ ].map(&method("expect_equal")).all?
672
+ end
673
+
674
+
675
+ # test for enc and dec and output_array_to_shell.
676
+ # output_array_to_shell should create proper arguments
677
+ # to dec
678
+ # TODO: invalid test -- that can't yet be ensured
679
+ def test__enc_dec_shell_programatically args=ARGV
680
+ stderr = @memory[:stderr]
681
+ stderr.puts "test invalid; skip"
682
+ shell = nil
683
+ programatically = nil
684
+ judgement =
685
+ [
686
+ [shell, programatically, "shell_programatically_equality"]
687
+ ].map(&method("expect_equal")).all?
688
+ end
689
+
690
+
691
+ # test for enc and dec.
692
+ # good idea is to use this function once with the desired
693
+ # data, password, and use the stderr output
694
+ def test__enc_dec args=ARGV
695
+ stderr = @memory[:stderr]
696
+ data, password = args
697
+ stderr.print "[data]"
698
+ data = input_multi_line_non_echo [data]
699
+ stderr.print "[password]"
700
+ password = input_single_line_non_echo [password]
701
+ base64_encrypted, base64_iv, base64_salt, base64_iter, base64_key = enc [password, data]
702
+ dec_args = [password, base64_iv, base64_encrypted, nil, base64_salt, base64_iter]
703
+ stderr.puts "# programmatically:"
704
+ stderr.puts "dec " + dec_args.to_s
705
+ stderr.puts "# shell: "
706
+ stderr.puts "#{$0} invoke_double p dec " + (output_array_to_shell dec_args).to_s
707
+ data_plain = dec [password, base64_iv, base64_encrypted, nil, base64_salt, base64_iter]
708
+ judgement =
709
+ [
710
+ [data, data_plain, "data"]
711
+ ].map(&method("expect_equal")).all?
712
+ end
713
+
714
+
715
+ # rubyment_gem_spec
716
+ # args: none
717
+ # returns: a gem spec string for Rubyment
718
+ def rubyment_gem_spec args=ARGV
719
+ memory = @memory
720
+ basic_version = memory[:basic_version]
721
+ contents =<<-ENDHEREDOC
722
+ Gem::Specification.new do |s|
723
+ s.name = 'rubyment'
724
+ s.version = '0.0.#{basic_version}'
725
+ s.date = '2018-04-23'
726
+ s.summary = "a set of ruby helpers"
727
+ s.description = "a gem for keeping Rubyment, a set of ruby helpers"
728
+ s.authors = ["Ribamar Santarosa"]
729
+ s.email = 'ribamar@gmail.com'
730
+ s.files = ["lib/rubyment.rb"]
731
+ s.homepage =
732
+ 'http://rubygems.org/gems/rubyment'
733
+ s.license = 'GPL-3.0'
734
+ end
735
+ ENDHEREDOC
736
+ contents
737
+ end
738
+
739
+ # test for rubyment_gem_spec. outputs the contents
740
+ # returned by that function.
741
+ # args: none
742
+ # returns: none
743
+ def test__rubyment_gem_spec args=ARGV
744
+ puts rubyment_gem_spec
745
+ end
746
+
747
+ # gem_build
748
+ # args:
749
+ # [gem_spec_path (String), gem_spec_contents (String)]
750
+ # returns:
751
+ # console output of gem build (String)
752
+ def gem_build args=ARGV
753
+ gem_spec_path, gem_spec_contents = args
754
+ require 'fileutils'
755
+ FileUtils.mkdir_p File.dirname gem_spec_path
756
+ File.write gem_spec_path, gem_spec_contents || (File.read gem_spec_path)
757
+ `gem build #{gem_spec_path}`
758
+ end
759
+
760
+ # test for gem_build: builds gem for this rubyment file
761
+ # after it, these commands will install/uninstall it:
762
+ # sudo gem install $PWD/rubyment-0.0.#{@memory[:basic_version]} ; gem list | grep -i rubyment ; sudo gem uninstall rubyment
763
+ # dependee:
764
+ # test__gem_install_validate_uninstall
765
+ # args:
766
+ # [gem_spec_path (String), gem_spec_contents (String)]
767
+ # returns: none
768
+ # outputs of gem build (String)
769
+ def test__gem_build args=ARGV
770
+ require 'fileutils'
771
+ FileUtils.mkdir_p 'lib'
772
+ save_file __FILE__, 'lib/rubyment.rb'
773
+ puts gem_build ["rubyment.spec", rubyment_gem_spec ]
774
+ end
775
+
776
+ # gem_install
777
+ # args:
778
+ # [gem_spec (String)]
779
+ # returns:
780
+ # console output of gem install (String)
781
+ def gem_install args=ARGV
782
+ system_user_is_super = @memory[:system_user_is_super]
783
+ gem_spec, user_install = args
784
+ user_install ||= (!system_user_is_super) && "--user-install" || ""
785
+ `gem install #{user_install} #{gem_spec}`
786
+ end
787
+
788
+ # gem_push
789
+ # args:
790
+ # [gem_spec (String)]
791
+ # returns:
792
+ # console output of gem push (String)
793
+ def gem_push args=ARGV
794
+ gem_spec, future_arg = args
795
+ (File.chmod 0600, gem_spec) # rescue nil
796
+ stderr = @memory[:stderr]
797
+ stderr.puts `ls -lh #{gem_spec}`
798
+ `gem push #{gem_spec}`
799
+ end
800
+
801
+ # gem_uninstall
802
+ # args:
803
+ # [gem_spec (String)]
804
+ # returns:
805
+ # console output of gem uninstall (String)
806
+ def gem_uninstall args=ARGV
807
+ system_user_is_super = @memory[:system_user_is_super]
808
+ gem_spec, user_install = args
809
+ user_install ||= (!system_user_is_super) && "--user-install" || ""
810
+ `gem uninstall #{user_install} #{gem_spec}`
811
+ end
812
+
813
+ # gem_list
814
+ # args:
815
+ # [gem_spec (String)]
816
+ # returns:
817
+ # console output of gem install (String)
818
+ def gem_list args=ARGV
819
+ gem_spec, future_arg = args
820
+ `gem list | grep #{gem_spec}`
821
+ end
822
+
823
+ # system_rubyment
824
+ # requires a system's Rubyment and invoke it using args
825
+ # args:
826
+ # args (Array)
827
+ # returns:
828
+ # Rubyment or false
829
+ def system_rubyment args=ARGV
830
+ begin
831
+ require 'rubyment'
832
+ Rubyment.new({:invoke => args })
833
+ rescue LoadError
834
+ nil
835
+ end
836
+ end
837
+
838
+ # test for system_rubyment
839
+ # dependee:
840
+ # test__gem_install_validate_uninstall
841
+ # args:
842
+ # args (Array or nil)
843
+ # returns:
844
+ # Rubyment or false
845
+ def test__system_rubyment args=ARGV
846
+ rubyment_args = (args.to_a.size > 0 && args) || ["main", "tested system_rubyment"]
847
+ p system_rubyment rubyment_args
848
+ end
849
+
850
+
851
+ # test for gem_build, gem_install, gem_list
852
+ # system_rubyment, gem_uninstall
853
+ # args:
854
+ # args (Array or nil)
855
+ # returns:
856
+ # Rubyment or false
857
+ def test__gem_build_install_validate_uninstall args=ARGV
858
+ memory = @memory
859
+ basic_version = memory[:basic_version]
860
+ running_dir = memory[:running_dir]
861
+ test__gem_build []
862
+ gem_uninstall ["rubyment"]
863
+ puts gem_list ["rubyment"]
864
+ gem_install ["#{running_dir}/rubyment-0.0.#{basic_version}.gem"]
865
+ puts gem_list ["rubyment"]
866
+ v = test__system_rubyment []
867
+ gem_uninstall ["rubyment"]
868
+ v
869
+ end
870
+
871
+
872
+ # gets the api key needed to push gems to rubygems.
873
+ # prompts for arguments when username or password
874
+ # not provided.
875
+ # args:
876
+ # [username (String or nil), password (String or nil),
877
+ # file_destination (String, "/dev/null" if empty/nil given)]
878
+ # returns
879
+ # key_contents (String)
880
+ def gem_get_api_key args=ARGV
881
+ require 'fileutils'
882
+ username, password, file_destination = args
883
+ username = input_single_line [username]
884
+ password = input_single_line_non_echo [password]
885
+ file_destination = file_destination.to_s.split("\0").first || "/dev/null"
886
+ FileUtils.mkdir_p File.dirname file_destination
887
+ key_contents = save_file "https://rubygems.org/api/v1/api_key.yaml",
888
+ file_destination, 0, {:username => username, :password => password }
889
+ (File.chmod 0600, file_destination) # rescue nil
890
+ key_contents
891
+ end
892
+
893
+
894
+ # test for test__gem_get_api_key
895
+ # args:
896
+ # (Array - forwarded to gem_get_api_key)
897
+ # returns:
898
+ # nil
899
+ def test__gem_get_api_key args=ARGV
900
+ puts gem_get_api_key args
901
+ end
902
+
903
+ # test for gem_build, gem_install, gem_list
904
+ # system_rubyment, gem_uninstall
905
+ # args:
906
+ # args (Array or nil)
907
+ # returns:
908
+ # Rubyment or false
909
+ def test__gem_complete_flow args=ARGV
910
+ memory = @memory
911
+ running_dir = memory[:running_dir]
912
+ home_dir = memory[:home_dir]
913
+ basic_version = memory[:basic_version]
914
+ gem_api_key_file = "#{home_dir}/.gem/credentials"
915
+ permissions = file_permissions_octal gem_api_key_file
916
+ credentials_contents = url_to_str gem_api_key_file, ""
917
+ gem_get_api_key [args[0], args[1], gem_api_key_file]
918
+ validated = test__gem_build_install_validate_uninstall []
919
+ puts validated && (gem_push ["#{running_dir}/rubyment-0.0.#{basic_version}.gem"])
920
+ File.write gem_api_key_file, credentials_contents
921
+ File.chmod permissions, gem_api_key_file
922
+ end
923
+
924
+
925
+ end
926
+
927
+ (__FILE__ == $0) && Rubyment.new({:invoke => ARGV})
928
+
metadata ADDED
@@ -0,0 +1,44 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubyment
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.25412377
5
+ platform: ruby
6
+ authors:
7
+ - Ribamar Santarosa
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-04-23 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: a gem for keeping Rubyment, a set of ruby helpers
14
+ email: ribamar@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/rubyment.rb
20
+ homepage: http://rubygems.org/gems/rubyment
21
+ licenses:
22
+ - GPL-3.0
23
+ metadata: {}
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ required_rubygems_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ requirements: []
39
+ rubyforge_project:
40
+ rubygems_version: 2.5.2.1
41
+ signing_key:
42
+ specification_version: 4
43
+ summary: a set of ruby helpers
44
+ test_files: []