safe 0.4 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README +48 -2
- data/Rakefile +1 -1
- data/Release-Notes.txt +6 -0
- data/bin/safe +22 -13
- data/lib/safediff.rb +80 -0
- data/lib/safeentry.rb +11 -3
- data/lib/safeutils.rb +64 -0
- data/test/tc_safediff.rb +52 -0
- data/test/tc_safeutils.rb +56 -0
- metadata +4 -2
data/README
CHANGED
@@ -4,6 +4,34 @@ user IDs and passwords using a single password as the master key. It stores the
|
|
4
4
|
master key as a hash (SHA2), and uses it to encrypt the rest of the data using
|
5
5
|
Blowfish.
|
6
6
|
|
7
|
+
== A Note About Moving from 0.3 to 0.4 ==
|
8
|
+
The format of the file changed slightly. Specifically, the salt and hash values
|
9
|
+
were changed to be attributes of the root safe element. You must edit your
|
10
|
+
.safe.xml file accordingly.
|
11
|
+
|
12
|
+
Example:
|
13
|
+
0.3 version:
|
14
|
+
<safe>
|
15
|
+
<salt>
|
16
|
+
foo
|
17
|
+
</salt>
|
18
|
+
<hash>
|
19
|
+
bar
|
20
|
+
</hash>
|
21
|
+
<entries>
|
22
|
+
...
|
23
|
+
</entries>
|
24
|
+
</salt>
|
25
|
+
|
26
|
+
0.4 version:
|
27
|
+
<safe salt="foo" hash="bar">
|
28
|
+
<entries>
|
29
|
+
...
|
30
|
+
</entries>
|
31
|
+
</salt>
|
32
|
+
|
33
|
+
This is a one-time operation.
|
34
|
+
|
7
35
|
== License ==
|
8
36
|
Safe is licensed under the BSD License. Copyright (c) 2007, Rob Warner
|
9
37
|
|
@@ -37,7 +65,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
37
65
|
To install safe, you must have Ruby and Ruby Gems installed. From the command
|
38
66
|
line, type:
|
39
67
|
|
40
|
-
gem install safe
|
68
|
+
gem install safe
|
41
69
|
|
42
70
|
safe depends on two gems:
|
43
71
|
|
@@ -59,6 +87,7 @@ Windows:
|
|
59
87
|
0.2 -- August 19, 2007
|
60
88
|
0.3 -- September 7, 2007
|
61
89
|
0.4 -- April 4, 2008
|
90
|
+
0.5 -- April 6, 2008
|
62
91
|
|
63
92
|
See Release-Notes.txt for more information
|
64
93
|
|
@@ -107,7 +136,9 @@ Options:
|
|
107
136
|
-l, --list NAME List an entry
|
108
137
|
-v, --version Print version
|
109
138
|
-p, --password Change password
|
110
|
-
|
139
|
+
-f, --diff DIR Diff against password file in directory DIR
|
140
|
+
-m, --merge DIR Merge with password file in directory DIR
|
141
|
+
|
111
142
|
For example, to add an entry to your password file for Rubyforge.org, you type:
|
112
143
|
|
113
144
|
safe -a Rubyforge.org
|
@@ -147,6 +178,21 @@ You will be prompted for your master password, and then your Rubyforge.org
|
|
147
178
|
password is irretrievably deleted. You will not be asked to confirm the
|
148
179
|
deletion.
|
149
180
|
|
181
|
+
== Diff and Merge ==
|
182
|
+
Diffing and merging deviates slightly from diffing and merging other types of
|
183
|
+
files, since typically users want a union of the files without deleting any
|
184
|
+
entries. Consequently, instead of Add/Delete/Change, the output of diff will
|
185
|
+
indicate Master/Other/Change, meaning the entry is only in the Master copy
|
186
|
+
(the one in the directory pointed to by SAFE_DIR), the Other copy (the one in
|
187
|
+
the directory passed on the command line), or is in both but has been Changed,
|
188
|
+
respectively.
|
189
|
+
|
190
|
+
Merge does two things:
|
191
|
+
1) Adds all entries from the Other copy that don't exist in the Master copy
|
192
|
+
to the Master copy
|
193
|
+
2) Interactively performs requested changes to changed entries on the Master
|
194
|
+
copy
|
195
|
+
|
150
196
|
== Backups ==
|
151
197
|
Please back up your .safe.xml file! See License section for disclaimer
|
152
198
|
information.
|
data/Rakefile
CHANGED
@@ -7,7 +7,7 @@ gem_spec = Gem::Specification.new do |spec|
|
|
7
7
|
spec.summary = 'A command-line password storage program'
|
8
8
|
spec.description = %{safe safely stores all your user IDs and passwords,
|
9
9
|
encrypted by a password of your choosing.}
|
10
|
-
spec.version = '0.
|
10
|
+
spec.version = '0.5'
|
11
11
|
|
12
12
|
# Author information
|
13
13
|
spec.author = 'Rob Warner'
|
data/Release-Notes.txt
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
Safe Release Notes
|
2
2
|
------------------
|
3
|
+
0.5 (April 6, 2008)
|
4
|
+
-------------------
|
5
|
+
[FIXED] Version number in help output corrected
|
6
|
+
[NEW] Added diff and merge capabilities
|
7
|
+
[CHANGE] Incorrect password no longer displays stack trace
|
8
|
+
|
3
9
|
0.4 (April 4, 2008)
|
4
10
|
-------------------
|
5
11
|
[FIXED] Passwords stopped authenticating (change in REXML perhaps?--whitespace returned in salt and hash), so moved salt
|
data/bin/safe
CHANGED
@@ -41,7 +41,7 @@ require File.join(File.dirname(__FILE__), '..', 'lib', 'safeutils')
|
|
41
41
|
# TODO support list <NAME> without -l flag
|
42
42
|
|
43
43
|
class Safe
|
44
|
-
SAFE_VERSION = '0.
|
44
|
+
SAFE_VERSION = '0.5'
|
45
45
|
|
46
46
|
# Gets the command line
|
47
47
|
def self.get_command_line
|
@@ -76,6 +76,14 @@ class Safe
|
|
76
76
|
opts.on('-p', '--password', 'Change password') do
|
77
77
|
options[:action] = 'password'
|
78
78
|
end
|
79
|
+
opts.on('-f', '--diff DIR', 'Diff against password file in directory DIR') do |val|
|
80
|
+
options[:name] = val
|
81
|
+
options[:action] = 'diff'
|
82
|
+
end
|
83
|
+
opts.on('-m', '--merge DIR', 'Merge with password file in directory DIR') do |val|
|
84
|
+
options[:name] = val
|
85
|
+
options[:action] = 'merge'
|
86
|
+
end
|
79
87
|
opts.parse! rescue abort [$!.message, opts].join("\n")
|
80
88
|
options
|
81
89
|
end
|
@@ -88,21 +96,22 @@ class Safe
|
|
88
96
|
else
|
89
97
|
begin
|
90
98
|
dir = SafeUtils::get_safe_dir
|
99
|
+
file = SafeUtils::get_safe_file(dir)
|
100
|
+
|
101
|
+
# Perform the requested action
|
102
|
+
case options[:action]
|
103
|
+
when 'list': file.list(options[:name])
|
104
|
+
when 'add': file.add(options[:name])
|
105
|
+
when 'delete': file.delete(options[:name])
|
106
|
+
when 'count': puts file.count
|
107
|
+
when 'password': file.change_password
|
108
|
+
when 'import': SafeUtils::import(file, options[:name])
|
109
|
+
when 'diff': SafeUtils::diff(file, options[:name])
|
110
|
+
when 'merge': SafeUtils::merge(file, options[:name])
|
111
|
+
end
|
91
112
|
rescue
|
92
113
|
abort $!.message
|
93
114
|
end
|
94
|
-
password = SafeUtils::get_password
|
95
|
-
file = SafeFile.new(password, dir)
|
96
|
-
|
97
|
-
# Perform the requested action
|
98
|
-
case options[:action]
|
99
|
-
when 'list': file.list(options[:name])
|
100
|
-
when 'add': file.add(options[:name])
|
101
|
-
when 'delete': file.delete(options[:name])
|
102
|
-
when 'count': puts file.count
|
103
|
-
when 'password': file.change_password
|
104
|
-
when 'import': SafeUtils::import(file, options[:name])
|
105
|
-
end
|
106
115
|
end
|
107
116
|
end
|
108
117
|
end
|
data/lib/safediff.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
########################################################################
|
2
|
+
# safediff.rb
|
3
|
+
# Copyright (c) 2007, Rob Warner
|
4
|
+
#
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
# Redistribution and use in source and binary forms, with or without
|
8
|
+
# modification, are permitted provided that the following conditions are met:
|
9
|
+
#
|
10
|
+
# * Redistributions of source code must retain the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer.
|
12
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
13
|
+
# this list of conditions and the following disclaimer in the documentation
|
14
|
+
# and/or other materials provided with the distribution.
|
15
|
+
# * Neither the name of Rob Warner nor the names of its contributors may be
|
16
|
+
# used to endorse or promote products derived from this software without
|
17
|
+
# specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
20
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
21
|
+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
22
|
+
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
23
|
+
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
24
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
25
|
+
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
26
|
+
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
27
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
28
|
+
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
29
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
########################################################################
|
31
|
+
|
32
|
+
##
|
33
|
+
# SafeDiff
|
34
|
+
# Contains a difference between two safe entries
|
35
|
+
##
|
36
|
+
class SafeDiff
|
37
|
+
attr_accessor :operation, :master, :other
|
38
|
+
|
39
|
+
MASTER = "m"
|
40
|
+
OTHER = "o"
|
41
|
+
CHANGE = "c"
|
42
|
+
|
43
|
+
def initialize(master, other)
|
44
|
+
self.master = master
|
45
|
+
self.other = other
|
46
|
+
compare
|
47
|
+
end
|
48
|
+
|
49
|
+
def compare
|
50
|
+
if self.master != nil && self.master.equals?(self.other)
|
51
|
+
raise "Entries are not different:\n#{self.master.to_s}\n#{self.other.to_s}"
|
52
|
+
elsif self.master != nil && self.other == nil
|
53
|
+
self.operation = MASTER
|
54
|
+
elsif self.master == nil && self.other != nil
|
55
|
+
self.operation = OTHER
|
56
|
+
else
|
57
|
+
self.operation = CHANGE
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_s
|
62
|
+
s = ""
|
63
|
+
s << self.operation
|
64
|
+
s << "\n"
|
65
|
+
if self.operation == MASTER || self.operation == CHANGE
|
66
|
+
s << "< "
|
67
|
+
s << self.master.to_s
|
68
|
+
s << "\n"
|
69
|
+
end
|
70
|
+
if self.operation == CHANGE
|
71
|
+
s << "---\n"
|
72
|
+
end
|
73
|
+
if self.operation == OTHER || self.operation == CHANGE
|
74
|
+
s << "> "
|
75
|
+
s << self.other.to_s
|
76
|
+
s << "\n"
|
77
|
+
end
|
78
|
+
s
|
79
|
+
end
|
80
|
+
end
|
data/lib/safeentry.rb
CHANGED
@@ -37,9 +37,9 @@ class SafeEntry
|
|
37
37
|
attr_accessor :name, :id, :password
|
38
38
|
|
39
39
|
def initialize(name, id, password)
|
40
|
-
|
41
|
-
|
42
|
-
|
40
|
+
self.name = name
|
41
|
+
self.id = id
|
42
|
+
self.password = password
|
43
43
|
end
|
44
44
|
|
45
45
|
def to_s
|
@@ -49,5 +49,13 @@ class SafeEntry
|
|
49
49
|
def <=>(other)
|
50
50
|
self.name.upcase <=> other.name.upcase
|
51
51
|
end
|
52
|
+
|
53
|
+
def equals? other
|
54
|
+
if other == nil
|
55
|
+
false
|
56
|
+
else
|
57
|
+
self.name == other.name && self.id == other.id && self.password == other.password
|
58
|
+
end
|
59
|
+
end
|
52
60
|
end
|
53
61
|
|
data/lib/safeutils.rb
CHANGED
@@ -28,6 +28,7 @@
|
|
28
28
|
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
29
29
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
30
|
########################################################################
|
31
|
+
require File.join(File.dirname(__FILE__), 'safediff')
|
31
32
|
require 'highline/import'
|
32
33
|
|
33
34
|
##
|
@@ -73,4 +74,67 @@ class SafeUtils
|
|
73
74
|
raise "Problem importing file #{import_file}"
|
74
75
|
end
|
75
76
|
end
|
77
|
+
|
78
|
+
def SafeUtils.get_safe_file(dir, prompt = 'Password: ')
|
79
|
+
password = SafeUtils::get_password(prompt)
|
80
|
+
SafeFile.new(password, dir)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Diffs two .safe.xml files
|
84
|
+
def SafeUtils.diff(safe_file, dir)
|
85
|
+
other_file = get_safe_file(dir, "#{dir} Password: ")
|
86
|
+
diffs = get_diffs(safe_file, other_file)
|
87
|
+
puts diffs
|
88
|
+
end
|
89
|
+
|
90
|
+
# Merges two .safe.xml files
|
91
|
+
def SafeUtils.merge(safe_file, dir)
|
92
|
+
other_file = get_safe_file(dir, "#{dir} Password: ")
|
93
|
+
diffs = get_diffs(safe_file, other_file)
|
94
|
+
do_merge safe_file, diffs
|
95
|
+
safe_file.save
|
96
|
+
end
|
97
|
+
|
98
|
+
# Returns the SafeDiff objects in an Array
|
99
|
+
def SafeUtils.get_diffs(safe_file, other_file)
|
100
|
+
diffs = Array.new
|
101
|
+
|
102
|
+
# Find master-only and changes
|
103
|
+
safe_file.entries.each_value do |entry|
|
104
|
+
if other_file.entries.has_key? entry.name
|
105
|
+
other_entry = other_file.entries[entry.name]
|
106
|
+
diffs << SafeDiff.new(entry, other_entry) unless entry.equals? other_entry
|
107
|
+
else
|
108
|
+
diffs << SafeDiff.new(entry, nil)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Find other-only
|
113
|
+
other_file.entries.each_value do |entry|
|
114
|
+
if !safe_file.entries.has_key? entry.name
|
115
|
+
diffs << SafeDiff.new(nil, entry)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
diffs
|
120
|
+
end
|
121
|
+
|
122
|
+
def SafeUtils.do_merge(safe_file, diffs, override_master = false)
|
123
|
+
diffs.each do |diff|
|
124
|
+
case diff.operation
|
125
|
+
when SafeDiff::MASTER: # Do nothing
|
126
|
+
when SafeDiff::OTHER: # Add to safe file
|
127
|
+
safe_file.insert(diff.other.name, diff.other.id, diff.other.password)
|
128
|
+
when SafeDiff::CHANGE: # Update safe file
|
129
|
+
if override_master || replace_master?(diff)
|
130
|
+
safe_file.insert(diff.other.name, diff.other.id, diff.other.password)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def SafeUtils.replace_master?(diff)
|
137
|
+
print "Replace:\n\t#{diff.master.to_s}\nWith:\n\t#{diff.other.to_s}\n?"
|
138
|
+
gets.chomp == 'y'
|
139
|
+
end
|
76
140
|
end
|
data/test/tc_safediff.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
########################################################################
|
2
|
+
# tc_safediff.rb
|
3
|
+
# Copyright (c) 2007 Rob Warner.
|
4
|
+
# All rights reserved. This program and the accompanying materials
|
5
|
+
# are made available under the terms of the Eclipse Public License v1.0
|
6
|
+
# which accompanies this distribution, and is available at
|
7
|
+
# http://www.eclipse.org/legal/epl-v10.html
|
8
|
+
########################################################################
|
9
|
+
|
10
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'safediff')
|
11
|
+
require 'test/unit'
|
12
|
+
|
13
|
+
class SafeDiffTest < Test::Unit::TestCase
|
14
|
+
def test_diff
|
15
|
+
e1 = SafeEntry.new('apple', 'baker', 'charlie')
|
16
|
+
e2 = SafeEntry.new('apple', 'baker', 'charlie')
|
17
|
+
e3 = SafeEntry.new('apple1', 'baker', 'charlie')
|
18
|
+
e4 = SafeEntry.new('apple', 'baker1', 'charlie')
|
19
|
+
e5 = SafeEntry.new('apple', 'baker', 'charlie1')
|
20
|
+
|
21
|
+
# Test two equal entries
|
22
|
+
begin
|
23
|
+
diff = SafeDiff.new e1, e2
|
24
|
+
rescue RuntimeError
|
25
|
+
assert_equal "Entries are not different:\n#{e1.to_s}\n#{e2.to_s}", $!.message
|
26
|
+
end
|
27
|
+
|
28
|
+
# Test an OTHER
|
29
|
+
diff = SafeDiff.new nil, e1
|
30
|
+
assert_equal diff.operation, SafeDiff::OTHER
|
31
|
+
assert_equal diff.to_s, "#{SafeDiff::OTHER}\n> #{e1.to_s}\n"
|
32
|
+
|
33
|
+
# Test a MASTER
|
34
|
+
diff = SafeDiff.new e1, nil
|
35
|
+
assert_equal diff.operation, SafeDiff::MASTER
|
36
|
+
assert_equal diff.to_s, "#{SafeDiff::MASTER}\n< #{e1.to_s}\n"
|
37
|
+
|
38
|
+
# Test a change
|
39
|
+
diff = SafeDiff.new e1, e3
|
40
|
+
assert_equal diff.operation, SafeDiff::CHANGE
|
41
|
+
assert_equal diff.to_s, "#{SafeDiff::CHANGE}\n< #{e1.to_s}\n---\n> #{e3.to_s}\n"
|
42
|
+
|
43
|
+
# Test various changes
|
44
|
+
diff = SafeDiff.new e1, e4
|
45
|
+
assert_equal diff.operation, SafeDiff::CHANGE
|
46
|
+
assert_equal diff.to_s, "#{SafeDiff::CHANGE}\n< #{e1.to_s}\n---\n> #{e4.to_s}\n"
|
47
|
+
|
48
|
+
diff = SafeDiff.new e1, e5
|
49
|
+
assert_equal diff.operation, SafeDiff::CHANGE
|
50
|
+
assert_equal diff.to_s, "#{SafeDiff::CHANGE}\n< #{e1.to_s}\n---\n> #{e5.to_s}\n"
|
51
|
+
end
|
52
|
+
end
|
data/test/tc_safeutils.rb
CHANGED
@@ -42,4 +42,60 @@ class SafeUtilsTest < Test::Unit::TestCase
|
|
42
42
|
# Make sure the directory exists
|
43
43
|
FileUtils::cd dir
|
44
44
|
end
|
45
|
+
|
46
|
+
def test_diff
|
47
|
+
f1 = SafeFile.new("password", ".")
|
48
|
+
f2 = SafeFile.new("password", ".", ".safe2.xml")
|
49
|
+
|
50
|
+
f1.insert('apple', 'baker', 'charlie')
|
51
|
+
diffs = SafeUtils.get_diffs(f1, f2)
|
52
|
+
assert_equal 1, diffs.length
|
53
|
+
assert_equal "m\n< apple\tbaker\tcharlie\n", diffs[0].to_s
|
54
|
+
|
55
|
+
f2.insert('apple', 'baker', 'charlie')
|
56
|
+
diffs = SafeUtils.get_diffs(f1, f2)
|
57
|
+
assert_equal 0, diffs.length
|
58
|
+
|
59
|
+
f2.insert('foo', 'bar', 'baz')
|
60
|
+
diffs = SafeUtils.get_diffs(f1, f2)
|
61
|
+
assert_equal 1, diffs.length
|
62
|
+
assert_equal "o\n> foo\tbar\tbaz\n", diffs[0].to_s
|
63
|
+
|
64
|
+
f2.insert('apple', 'ibm', 'compaq')
|
65
|
+
f2.delete('foo')
|
66
|
+
diffs = SafeUtils.get_diffs(f1, f2)
|
67
|
+
assert_equal 1, diffs.length
|
68
|
+
assert_equal "c\n< apple\tbaker\tcharlie\n---\n> apple\tibm\tcompaq\n", diffs[0].to_s
|
69
|
+
|
70
|
+
FileUtils::rm("./.safe2.xml")
|
71
|
+
FileUtils::rm("./.safe.xml")
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_merge
|
75
|
+
f1 = SafeFile.new("password", ".")
|
76
|
+
f2 = SafeFile.new("password", ".", ".safe2.xml")
|
77
|
+
|
78
|
+
f1.insert('apple', 'baker', 'charlie')
|
79
|
+
f1.insert('one', 'baker', 'charlie')
|
80
|
+
f1.insert('two', 'baker', 'charlie')
|
81
|
+
f1.insert('three', 'baker', 'charlie')
|
82
|
+
f1.insert('four', 'baker', 'charlie')
|
83
|
+
f1.insert('five', 'baker', 'charlie')
|
84
|
+
|
85
|
+
f2.insert('three', 'baker', 'charlie')
|
86
|
+
f2.insert('four', 'goober', 'raisinet')
|
87
|
+
f2.insert('five', 'coke', 'pepsi')
|
88
|
+
f2.insert('six', 'baker', 'charlie')
|
89
|
+
f2.insert('seven', 'baker', 'charlie')
|
90
|
+
f2.insert('eight', 'baker', 'charlie')
|
91
|
+
|
92
|
+
diffs = SafeUtils.get_diffs(f1, f2)
|
93
|
+
SafeUtils.do_merge(f1, diffs, true)
|
94
|
+
assert_equal 9, f1.count
|
95
|
+
assert_equal "four\tgoober\traisinet", f1.entries['four'].to_s
|
96
|
+
assert_equal "five\tcoke\tpepsi", f1.entries['five'].to_s
|
97
|
+
|
98
|
+
FileUtils::rm("./.safe2.xml")
|
99
|
+
FileUtils::rm("./.safe.xml")
|
100
|
+
end
|
45
101
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: safe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "0.
|
4
|
+
version: "0.5"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rob Warner
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-04-
|
12
|
+
date: 2008-04-06 00:00:00 -04:00
|
13
13
|
default_executable: safe
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -40,6 +40,7 @@ extra_rdoc_files: []
|
|
40
40
|
|
41
41
|
files:
|
42
42
|
- README
|
43
|
+
- lib/safediff.rb
|
43
44
|
- lib/safeentry.rb
|
44
45
|
- lib/safefile.rb
|
45
46
|
- lib/safeutils.rb
|
@@ -73,6 +74,7 @@ signing_key:
|
|
73
74
|
specification_version: 2
|
74
75
|
summary: A command-line password storage program
|
75
76
|
test_files:
|
77
|
+
- test/tc_safediff.rb
|
76
78
|
- test/tc_safeentry.rb
|
77
79
|
- test/tc_safefile.rb
|
78
80
|
- test/tc_safeutils.rb
|