keybox 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +10 -0
- data/lib/keybox.rb +1 -1
- data/lib/keybox/application/base.rb +10 -0
- data/lib/keybox/application/password_safe.rb +5 -5
- data/lib/keybox/highline_util.rb +6 -9
- data/lib/keybox/storage/container.rb +10 -5
- data/lib/keybox/storage/record.rb +6 -0
- data/spec/base_app_spec.rb +15 -17
- data/spec/convert_csv_spec.rb +13 -11
- data/spec/entry_spec.rb +32 -32
- data/spec/keybox_app_spec.rb +85 -78
- data/spec/kpg_app_spec.rb +33 -40
- data/spec/password_hash_spec.rb +3 -3
- data/spec/randomizer_spec.rb +53 -54
- data/spec/storage_container_spec.rb +39 -29
- data/spec/storage_record_spec.rb +21 -21
- data/spec/string_generator_spec.rb +39 -41
- data/spec/uuid_spec.rb +22 -21
- data/vendor/highline/highline.rb +54 -14
- data/vendor/highline/highline/system_extensions.rb +1 -1
- metadata +11 -11
data/spec/storage_record_spec.rb
CHANGED
@@ -1,63 +1,63 @@
|
|
1
1
|
require 'keybox/storage'
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
describe 'a storage record entry' do
|
4
|
+
before(:each) do
|
5
5
|
@data_fields = %w(title username password url additional_data)
|
6
6
|
end
|
7
|
-
|
7
|
+
it 'has a creation date set on instantiation' do
|
8
8
|
e = Keybox::Storage::Record.new
|
9
|
-
e.creation_time.
|
9
|
+
e.creation_time.should be_instance_of(Time)
|
10
10
|
end
|
11
11
|
|
12
|
-
|
12
|
+
it "assigning to a non-existant field creates the appropriate member " do
|
13
13
|
e = Keybox::Storage::Record.new
|
14
14
|
e.junk = "junk"
|
15
15
|
e.junk.should == "junk"
|
16
16
|
end
|
17
17
|
|
18
|
-
|
18
|
+
it 'default values for non-existant fields is nil' do
|
19
19
|
e = Keybox::Storage::Record.new
|
20
20
|
@data_fields.each do |f|
|
21
|
-
e.send(f).
|
21
|
+
e.send(f).should == nil
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
|
25
|
+
it "assigning to a field makes the modification time > creation time" do
|
26
26
|
e = Keybox::Storage::Record.new
|
27
27
|
sleep 1
|
28
28
|
e.testing = "testing"
|
29
|
-
e.modification_time.
|
29
|
+
e.modification_time.should > e.creation_time
|
30
30
|
e.last_access_time.should == e.modification_time
|
31
31
|
end
|
32
32
|
|
33
|
-
|
33
|
+
it "reading a field after assignment the access time > modification time " do
|
34
34
|
e = Keybox::Storage::Record.new
|
35
35
|
e.testing = "testing"
|
36
36
|
sleep 1
|
37
37
|
e.testing
|
38
|
-
e.last_access_time.
|
39
|
-
e.last_access_time.
|
38
|
+
e.last_access_time.should > e.creation_time
|
39
|
+
e.last_access_time.should > e.modification_time
|
40
40
|
end
|
41
41
|
|
42
|
-
|
42
|
+
it "assigning to a modification, creation or acces_time should raise and exception " do
|
43
43
|
e = Keybox::Storage::Record.new
|
44
|
-
lambda {e.modification_time = Time.now}.
|
44
|
+
lambda {e.modification_time = Time.now}.should raise_error(NoMethodError)
|
45
45
|
end
|
46
46
|
|
47
|
-
|
47
|
+
it "assiging multiple items should raise an argument exception" do
|
48
48
|
e = Keybox::Storage::Record.new
|
49
|
-
lambda {e.send(:stuff=,1,2)}.
|
49
|
+
lambda {e.send(:stuff=,1,2)}.should raise_error(ArgumentError)
|
50
50
|
end
|
51
51
|
|
52
|
-
|
52
|
+
it "calling a method with arguments should raise exception" do
|
53
53
|
e = Keybox::Storage::Record.new
|
54
|
-
lambda {e.stuff(1,2)}.
|
54
|
+
lambda {e.stuff(1,2)}.should raise_error(NoMethodError)
|
55
55
|
end
|
56
56
|
|
57
|
-
|
57
|
+
it "comparison between records is valid" do
|
58
58
|
e = Keybox::Storage::Record.new
|
59
59
|
f = e.dup
|
60
|
-
e.
|
61
|
-
e.
|
60
|
+
e.should == e.uuid
|
61
|
+
e.should == f
|
62
62
|
end
|
63
63
|
end
|
@@ -1,114 +1,112 @@
|
|
1
1
|
require 'keybox'
|
2
|
-
|
3
|
-
|
2
|
+
describe Keybox::StringGenerator do
|
3
|
+
before(:each) do
|
4
4
|
@generator = Keybox::StringGenerator.new
|
5
5
|
end
|
6
6
|
|
7
|
-
|
8
|
-
lambda { @generator.generate }.
|
7
|
+
it "should not be used alone" do
|
8
|
+
lambda { @generator.generate }.should raise_error(Keybox::KeyboxError)
|
9
9
|
end
|
10
10
|
|
11
|
-
|
11
|
+
it "cannot have a min length greater than a max length" do
|
12
12
|
@generator.min_length = 90
|
13
|
-
lambda { @generator.generate }.
|
14
|
-
@generator.min_length = 8
|
13
|
+
lambda { @generator.generate }.should raise_error(Keybox::ValidationError)
|
15
14
|
end
|
16
15
|
|
17
|
-
|
16
|
+
it "cannot have a max length less than a min length" do
|
18
17
|
@generator.max_length = 2
|
19
|
-
lambda { @generator.generate }.
|
20
|
-
@generator.max_length = 10
|
18
|
+
lambda { @generator.generate }.should raise_error(Keybox::ValidationError)
|
21
19
|
end
|
22
20
|
|
23
|
-
|
24
|
-
@generator.chunks.
|
21
|
+
it "initially there are no chunks" do
|
22
|
+
@generator.chunks.should have(0).entries
|
25
23
|
end
|
26
24
|
end
|
27
25
|
|
28
|
-
|
29
|
-
|
26
|
+
describe "chargram generator" do
|
27
|
+
before(:each) do
|
30
28
|
@generator = Keybox::CharGramGenerator.new
|
31
29
|
end
|
32
30
|
|
33
|
-
|
34
|
-
@generator.size.
|
31
|
+
it "should have a positive size" do
|
32
|
+
@generator.size.should > 26
|
35
33
|
end
|
36
34
|
|
37
|
-
|
38
|
-
@generator.generate_chunk.size.
|
35
|
+
it "should emit a string with length > 0" do
|
36
|
+
@generator.generate_chunk.size.should > 0
|
39
37
|
end
|
40
38
|
|
41
|
-
|
42
|
-
@generator.generate_chunk.
|
39
|
+
it "should emit an array " do
|
40
|
+
@generator.generate_chunk.should be_instance_of(String)
|
43
41
|
end
|
44
42
|
|
45
|
-
|
43
|
+
it "2 succesive emits should have a common first and last character" do
|
46
44
|
one = @generator.generate_chunk
|
47
45
|
two = @generator.generate_chunk
|
48
46
|
one[-1].should == two[0]
|
49
47
|
end
|
50
48
|
|
51
|
-
|
49
|
+
it "2 calls to generate_chunk should have a string that is 1 less than the 2 chunks" do
|
52
50
|
one = @generator.generate_chunk
|
53
51
|
two = @generator.generate_chunk
|
54
52
|
@generator.to_s.length.should == (one.length + two.length - 1)
|
55
53
|
end
|
56
54
|
end
|
57
55
|
|
58
|
-
|
59
|
-
|
56
|
+
describe "SymbolSetGenerator" do
|
57
|
+
before(:each) do
|
60
58
|
@generator = Keybox::SymbolSetGenerator.new
|
61
59
|
end
|
62
60
|
|
63
|
-
|
61
|
+
it "symbol sets have the right number or characters" do
|
64
62
|
Keybox::SymbolSetGenerator::ALL.size.should == 92
|
65
63
|
end
|
66
64
|
|
67
|
-
|
65
|
+
it "generating chunks should produce an array" do
|
68
66
|
12.times do
|
69
67
|
@generator.generate_chunk
|
70
68
|
end
|
71
|
-
@generator.chunks.
|
69
|
+
@generator.chunks.should have(12).entries
|
72
70
|
end
|
73
71
|
|
74
|
-
|
75
|
-
@generator.generate.
|
76
|
-
@generator.to_s.size.
|
72
|
+
it "generate should produce a string" do
|
73
|
+
@generator.generate.should be_instance_of(String)
|
74
|
+
@generator.to_s.size.should > 0
|
77
75
|
end
|
78
76
|
|
79
|
-
|
77
|
+
it "generating chunks can be cleared" do
|
80
78
|
@generator.generate
|
81
79
|
@generator.clear
|
82
|
-
@generator.chunks.
|
80
|
+
@generator.chunks.should have(0).entries
|
83
81
|
end
|
84
82
|
|
85
|
-
|
83
|
+
it "min and max lengths are respected" do
|
86
84
|
@generator.max_length = 25
|
87
85
|
@generator.min_length = 25
|
88
|
-
@generator.generate.size.
|
86
|
+
@generator.generate.size.should == 25
|
89
87
|
end
|
90
88
|
|
91
|
-
|
89
|
+
it "required sets are utilized" do
|
92
90
|
gen = Keybox::SymbolSetGenerator.new([Keybox::SymbolSet::NUMERAL_ASCII, Keybox::SymbolSet::LOWER_ASCII])
|
93
91
|
gen.required_sets << Keybox::SymbolSet::UPPER_ASCII
|
94
92
|
p = gen.generate
|
95
|
-
gen.required_sets.flatten.uniq.
|
93
|
+
gen.required_sets.flatten.uniq.should be_include(p[0].chr)
|
96
94
|
end
|
97
|
-
|
95
|
+
it "required sets are merged with symbol sets" do
|
98
96
|
gen = Keybox::SymbolSetGenerator.new([Keybox::SymbolSet::NUMERAL_ASCII, Keybox::SymbolSet::LOWER_ASCII])
|
99
97
|
gen.required_sets << Keybox::SymbolSet::UPPER_ASCII
|
100
98
|
gen.required_sets.flatten.uniq.each do |c|
|
101
|
-
gen.symbols.
|
99
|
+
gen.symbols.should be_include(c)
|
102
100
|
end
|
103
101
|
end
|
104
102
|
|
105
|
-
|
103
|
+
it "generated passwords autoclear" do
|
106
104
|
@generator.generate.should_not == @generator.generate
|
107
105
|
end
|
108
106
|
|
109
|
-
|
107
|
+
it "setting min and max should not affect " do
|
110
108
|
g = Keybox::SymbolSetGenerator.new(Keybox::SymbolSet::ALL)
|
111
|
-
g.generate.
|
109
|
+
g.generate.should be_instance_of(String)
|
112
110
|
end
|
113
111
|
|
114
112
|
end
|
data/spec/uuid_spec.rb
CHANGED
@@ -1,29 +1,30 @@
|
|
1
1
|
require 'keybox/uuid'
|
2
|
-
|
3
|
-
|
2
|
+
describe "UUID class" do
|
3
|
+
it "should have 16 bytes" do
|
4
4
|
uuid = Keybox::UUID.new
|
5
5
|
uuid.bytes.size.should == 16
|
6
6
|
end
|
7
7
|
|
8
|
-
|
8
|
+
it "as an array should have 16 members" do
|
9
9
|
uuid = Keybox::UUID.new
|
10
10
|
uuid.to_a.size.should == 16
|
11
11
|
end
|
12
12
|
|
13
|
-
|
13
|
+
it "array elements should have values between 0 and 256 " do
|
14
14
|
uuid = Keybox::UUID.new
|
15
15
|
uuid.to_a.each do |b|
|
16
|
-
b.
|
16
|
+
b.should >= 0
|
17
|
+
b.should <= 256
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
20
|
-
|
21
|
+
it "as a string should match regex" do
|
21
22
|
regex = Keybox::UUID::REGEX
|
22
23
|
uuid = Keybox::UUID.new
|
23
|
-
uuid.to_s.
|
24
|
+
uuid.to_s.should =~ regex
|
24
25
|
end
|
25
26
|
|
26
|
-
|
27
|
+
it "initialized with a string should give a valid uuid" do
|
27
28
|
s = "0123456789abcdef"
|
28
29
|
s_a = s.unpack("C*")
|
29
30
|
s_uuid = sprintf(Keybox::UUID::FORMAT,*s_a)
|
@@ -31,44 +32,44 @@ context "UUID class" do
|
|
31
32
|
uuid.to_s.should == s_uuid
|
32
33
|
end
|
33
34
|
|
34
|
-
|
35
|
+
it "initialized with a string in the format of a uuid is valid " do
|
35
36
|
s = "c8b5a23a-2507-4834-ab19-60f2cb2a5271"
|
36
37
|
uuid = Keybox::UUID.new(s)
|
37
38
|
uuid.to_s.should == s
|
38
39
|
end
|
39
40
|
|
40
|
-
|
41
|
+
it "not enough bytes should throw an expeption" do
|
41
42
|
s = "0123456789"
|
42
|
-
lambda { Keybox::UUID.new(s) }.
|
43
|
+
lambda { Keybox::UUID.new(s) }.should raise_error(ArgumentError)
|
43
44
|
end
|
44
45
|
|
45
|
-
|
46
|
+
it "invalid uuid string should throw an exception" do
|
46
47
|
s = "z8b5a23a-2507-4834-ab19-60f2cb2a5271"
|
47
|
-
lambda { Keybox::UUID.new(s) }.
|
48
|
+
lambda { Keybox::UUID.new(s) }.should raise_error(ArgumentError)
|
48
49
|
end
|
49
50
|
|
50
|
-
|
51
|
-
lambda { Keybox::UUID.new(42) }.
|
51
|
+
it "initialing with a non-string raises an exception" do
|
52
|
+
lambda { Keybox::UUID.new(42) }.should raise_error(ArgumentError)
|
52
53
|
end
|
53
54
|
|
54
|
-
|
55
|
+
it "should equal another keybox created with same data" do
|
55
56
|
s = "c8b5a23a-2507-4834-ab19-60f2cb2a5271"
|
56
57
|
one = Keybox::UUID.new(s)
|
57
58
|
two = Keybox::UUID.new(s)
|
58
59
|
one.should == two
|
59
60
|
end
|
60
61
|
|
61
|
-
|
62
|
+
it "should equal a string that is the same uuid" do
|
62
63
|
s = "c8b5a23a-2507-4834-ab19-60f2cb2a5271"
|
63
64
|
one = Keybox::UUID.new(s)
|
64
65
|
one.should == s
|
65
66
|
end
|
66
67
|
|
67
|
-
|
68
|
+
it "should not equal some other uuid or random string" do
|
68
69
|
s = "c8b5a23a-2507-4834-ab19-60f2cb2a5271"
|
69
70
|
one = Keybox::UUID.new(s)
|
70
|
-
one.
|
71
|
-
one.
|
72
|
-
one.
|
71
|
+
one.should_not == Keybox::UUID.new
|
72
|
+
one.should_not == "i love ruby"
|
73
|
+
one.should_not == 4
|
73
74
|
end
|
74
75
|
end
|
data/vendor/highline/highline.rb
CHANGED
@@ -29,7 +29,7 @@ require "abbrev"
|
|
29
29
|
#
|
30
30
|
class HighLine
|
31
31
|
# The version of the installed library.
|
32
|
-
VERSION = "1.2.
|
32
|
+
VERSION = "1.2.9".freeze
|
33
33
|
|
34
34
|
# An internal HighLine error. User code does not need to trap this.
|
35
35
|
class QuestionError < StandardError
|
@@ -48,6 +48,19 @@ class HighLine
|
|
48
48
|
def self.use_color?
|
49
49
|
@@use_color
|
50
50
|
end
|
51
|
+
|
52
|
+
# The setting used to disable EOF tracking.
|
53
|
+
@@track_eof = true
|
54
|
+
|
55
|
+
# Pass +false+ to _setting_ to turn off HighLine's EOF tracking.
|
56
|
+
def self.track_eof=( setting )
|
57
|
+
@@track_eof = setting
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns true if HighLine is currently tracking EOF for input.
|
61
|
+
def self.track_eof?
|
62
|
+
@@track_eof
|
63
|
+
end
|
51
64
|
|
52
65
|
# The setting used to control color schemes.
|
53
66
|
@@color_scheme = nil
|
@@ -75,7 +88,9 @@ class HighLine
|
|
75
88
|
# An alias for CLEAR.
|
76
89
|
RESET = CLEAR
|
77
90
|
# Erase the current line of terminal output.
|
78
|
-
ERASE_LINE = "\e[K"
|
91
|
+
ERASE_LINE = "\e[K"
|
92
|
+
# Erase the character under the cursor.
|
93
|
+
ERASE_CHAR = "\e[P"
|
79
94
|
# The start of an ANSI bold sequence.
|
80
95
|
BOLD = "\e[1m"
|
81
96
|
# The start of an ANSI dark sequence. (Terminal support uncommon.)
|
@@ -189,9 +204,11 @@ class HighLine
|
|
189
204
|
@question ||= Question.new(question, answer_type, &details)
|
190
205
|
|
191
206
|
return gather if @question.gather
|
192
|
-
|
193
|
-
# readline() needs to handle it's own output
|
194
|
-
|
207
|
+
|
208
|
+
# readline() needs to handle it's own output, but readline only supports
|
209
|
+
# full line reading. Therefore if @question.echo is anything but true,
|
210
|
+
# the prompt will not be issued. And we have to account for that now.
|
211
|
+
say(@question) unless (@question.readline and @question.echo == true)
|
195
212
|
begin
|
196
213
|
@answer = @question.answer_or_default(get_response)
|
197
214
|
unless @question.valid_answer?(@answer)
|
@@ -573,7 +590,8 @@ class HighLine
|
|
573
590
|
|
574
591
|
answer
|
575
592
|
else
|
576
|
-
raise EOFError, "The input stream is exhausted." if
|
593
|
+
raise EOFError, "The input stream is exhausted." if @@track_eof and
|
594
|
+
@input.eof?
|
577
595
|
|
578
596
|
@question.change_case(@question.remove_whitespace(@input.gets))
|
579
597
|
end
|
@@ -598,24 +616,46 @@ class HighLine
|
|
598
616
|
raw_no_echo_mode if stty = CHARACTER_MODE == "stty"
|
599
617
|
|
600
618
|
line = ""
|
619
|
+
backspace_limit = 0
|
601
620
|
begin
|
621
|
+
|
602
622
|
while character = (stty ? @input.getc : get_character(@input))
|
603
|
-
|
623
|
+
# honor backspace and delete
|
624
|
+
if character == 127 or character == 8
|
625
|
+
line.slice!(-1, 1)
|
626
|
+
backspace_limit -= 1
|
627
|
+
else
|
628
|
+
line << character.chr
|
629
|
+
backspace_limit = line.size
|
630
|
+
end
|
604
631
|
# looking for carriage return (decimal 13) or
|
605
632
|
# newline (decimal 10) in raw input
|
606
633
|
break if character == 13 or character == 10 or
|
607
634
|
(@question.limit and line.size == @question.limit)
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
635
|
+
if @question.echo != false
|
636
|
+
if character == 127 or character == 8
|
637
|
+
# only backspace if we have characters on the line to
|
638
|
+
# eliminate, otherwise we'll tromp over the prompt
|
639
|
+
if backspace_limit >= 0 then
|
640
|
+
@output.print("\b#{ERASE_CHAR}")
|
641
|
+
else
|
642
|
+
# do nothing
|
643
|
+
end
|
644
|
+
else
|
645
|
+
@output.print(@question.echo)
|
646
|
+
end
|
647
|
+
@output.flush
|
648
|
+
end
|
615
649
|
end
|
616
650
|
ensure
|
617
651
|
restore_mode if stty
|
618
652
|
end
|
653
|
+
if @question.overwrite
|
654
|
+
@output.print("\r#{ERASE_LINE}")
|
655
|
+
@output.flush
|
656
|
+
else
|
657
|
+
say("\n")
|
658
|
+
end
|
619
659
|
|
620
660
|
@question.change_case(@question.remove_whitespace(line))
|
621
661
|
end
|