rubyment 0.0.25412377

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.
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: []