keybox 1.0.0 → 1.1.0
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.
- data/CHANGES +9 -0
- data/README +7 -3
- data/bin/keybox +2 -1
- data/bin/kpg +2 -1
- data/data/dark_bg.color_scheme.yaml +32 -0
- data/data/light_bg.color_scheme.yaml +32 -0
- data/lib/keybox.rb +2 -2
- data/lib/keybox/application/base.rb +27 -12
- data/lib/keybox/application/password_safe.rb +137 -59
- data/lib/keybox/digest.rb +4 -4
- data/lib/keybox/highline_util.rb +91 -0
- data/lib/keybox/storage/container.rb +19 -1
- data/spec/base_app_spec.rb +4 -5
- data/spec/keybox_app_spec.rb +84 -45
- data/spec/kpg_app_spec.rb +12 -12
- data/vendor/highline/highline.rb +704 -0
- data/vendor/highline/highline/color_scheme.rb +120 -0
- data/vendor/highline/highline/import.rb +43 -0
- data/vendor/highline/highline/menu.rb +395 -0
- data/vendor/highline/highline/question.rb +462 -0
- data/vendor/highline/highline/system_extensions.rb +125 -0
- metadata +34 -12
- data/lib/keybox/term_io.rb +0 -163
data/CHANGES
CHANGED
@@ -1,4 +1,13 @@
|
|
1
1
|
= keybox Changelog
|
2
|
+
=== Version 1.1.0
|
3
|
+
|
4
|
+
* keybox now uses HighLine for terminal input/output
|
5
|
+
* Added --color SCHEME option to support custom colorized output
|
6
|
+
and non-colorzed output
|
7
|
+
- ships with light_bg and dark_bg schemes, dark_bg is default
|
8
|
+
* Fixed configuration bug where command line options were not
|
9
|
+
correctly overwriting default options.
|
10
|
+
|
2
11
|
=== Version 1.0.0
|
3
12
|
|
4
13
|
* Initial public release
|
data/README
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Keybox
|
2
2
|
|
3
3
|
* Homepage[http://keybox.rubyforge.org]
|
4
|
-
*
|
4
|
+
* {Rubyforge Project}[http://rubyforge.org/projects/keybox/]
|
5
5
|
* email jeremy at hinegardner dot org
|
6
6
|
|
7
7
|
== DESCRIPTION:
|
@@ -33,6 +33,8 @@ applications.
|
|
33
33
|
General Options:
|
34
34
|
-f, --file DATABASE_FILE The Database File to use
|
35
35
|
-c, --config CONFIG_FILE The Configuration file to use
|
36
|
+
--color SCHEME The color scheme to use
|
37
|
+
none,dark_bg,light_bg,<other>
|
36
38
|
-D, --debug Ouput debug information to STDERR
|
37
39
|
--[no-]use-hash-for-url Use the password hash algorithm
|
38
40
|
for URL accounts
|
@@ -52,6 +54,7 @@ applications.
|
|
52
54
|
-i, --import-from-csv FILE Import from a CSV file
|
53
55
|
-x, --export-to-csv FILE Export contents to a CSV file
|
54
56
|
|
57
|
+
|
55
58
|
* kpg command line application
|
56
59
|
|
57
60
|
Usage: kpg [options]
|
@@ -77,16 +80,17 @@ applications.
|
|
77
80
|
== REQUIREMENTS:
|
78
81
|
|
79
82
|
=== For running:
|
80
|
-
*
|
83
|
+
* For a gem install keybox depends upon HighLine[http://highline.rubyforge.org] >= 1.2.6.
|
84
|
+
* For a source install keybox ships with HighLine 1.2.6
|
81
85
|
|
82
86
|
=== For development:
|
83
|
-
* A basic ruby install that is compiled against OpenSSL >= 0.9.8
|
84
87
|
* rake >= 0.7.1
|
85
88
|
* rcov >= 0.7.0.1
|
86
89
|
* RedCloth >= 3.0.4
|
87
90
|
* rspec >= 0.7.3
|
88
91
|
* rubyforge >= 0.4.0
|
89
92
|
* webgen >= 0.4.1
|
93
|
+
* highline >= 1.2.6
|
90
94
|
|
91
95
|
== INSTALL:
|
92
96
|
|
data/bin/keybox
CHANGED
@@ -6,7 +6,8 @@
|
|
6
6
|
#----------------------------------------------------------------------
|
7
7
|
# bootstrap
|
8
8
|
#----------------------------------------------------------------------
|
9
|
-
|
9
|
+
$: << File.expand_path(File.join(File.dirname(__FILE__),"..","lib"))
|
10
|
+
require 'keybox'
|
10
11
|
require 'keybox/application/password_safe'
|
11
12
|
|
12
13
|
#----------------------------------------------------------------------
|
data/bin/kpg
CHANGED
@@ -6,7 +6,8 @@
|
|
6
6
|
#----------------------------------------------------------------------
|
7
7
|
# bootstrap
|
8
8
|
#----------------------------------------------------------------------
|
9
|
-
|
9
|
+
$: << File.expand_path(File.join(File.dirname(__FILE__),"..","lib"))
|
10
|
+
require 'keybox'
|
10
11
|
require 'keybox/application/password_generator'
|
11
12
|
|
12
13
|
#----------------------------------------------------------------------
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# yaml document for the dark background scheme
|
2
|
+
#
|
3
|
+
# The colorized elements of keybox are:
|
4
|
+
# :prompt -> Whenever you are asked to input information
|
5
|
+
# :header -> Header line on a table of output
|
6
|
+
# :header_bar -> Horizontal bar under a table header
|
7
|
+
# :line_number -> Number at the beginning of a line of tabular
|
8
|
+
# output
|
9
|
+
# :even_row -> Color of an even numbered row of tabular data
|
10
|
+
# :odd_row -> Color of an odd numbered row of tabular data
|
11
|
+
# :information -> Informational message from keybox
|
12
|
+
# :error -> Error message from keybox
|
13
|
+
# :private -> Private data being displayed
|
14
|
+
# :separator -> Separator between name : value pairs
|
15
|
+
# :separator_bar -> Separator displayed entries
|
16
|
+
# :name -> Names from name : value pairs
|
17
|
+
# :value -> Values from name : value pairs
|
18
|
+
---
|
19
|
+
:normal: [ :clear ]
|
20
|
+
:prompt: [ :bold, :white ]
|
21
|
+
:header: [ :bold, :yellow ]
|
22
|
+
:header_bar: [ :blue ]
|
23
|
+
:line_number: [ :bold, :white ]
|
24
|
+
:even_row: [ :bold, :magenta ]
|
25
|
+
:odd_row: [ :bold, :cyan ]
|
26
|
+
:information: [ :bold, :green ]
|
27
|
+
:error: [ :bold, :red ]
|
28
|
+
:private: [ :bold, :red ]
|
29
|
+
:separator: [ :bold, :white ]
|
30
|
+
:separator_bar: [ :bold, :blue ]
|
31
|
+
:name: [ :bold, :blue ]
|
32
|
+
:value: [ :bold, :cyan ]
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# yaml document for the dark background scheme
|
2
|
+
#
|
3
|
+
# The colorized elements of keybox are:
|
4
|
+
# :prompt -> Whenever you are asked to input information
|
5
|
+
# :header -> Header line on a table of output
|
6
|
+
# :header_bar -> Horizontal bar under a table header
|
7
|
+
# :line_number -> Number at the beginning of a line of tabular
|
8
|
+
# output
|
9
|
+
# :even_row -> Color of an even numbered row of tabular data
|
10
|
+
# :odd_row -> Color of an odd numbered row of tabular data
|
11
|
+
# :information -> Informational message from keybox
|
12
|
+
# :error -> Error message from keybox
|
13
|
+
# :private -> Private data being displayed
|
14
|
+
# :separator -> Separator between name : value pairs
|
15
|
+
# :separator_bar -> Separator displayed entries
|
16
|
+
# :name -> Names from name : value pairs
|
17
|
+
# :value -> Values from name : value pairs
|
18
|
+
---
|
19
|
+
:normal: [ :clear ]
|
20
|
+
:prompt: [ :red ]
|
21
|
+
:header: [ :green ]
|
22
|
+
:header_bar: [ :magenta ]
|
23
|
+
:line_number: [ :cyan ]
|
24
|
+
:even_row: [ :blue ]
|
25
|
+
:odd_row: [ :red ]
|
26
|
+
:information: [ :green ]
|
27
|
+
:error: [ :bold, :yellow, :on_red ]
|
28
|
+
:private: [ :bold, :red, :on_black ]
|
29
|
+
:separator: [ :cyan ]
|
30
|
+
:separator_bar: [ :green ]
|
31
|
+
:name: [ :magenta ]
|
32
|
+
:value: [ :blue ]
|
data/lib/keybox.rb
CHANGED
@@ -2,8 +2,9 @@ module Keybox
|
|
2
2
|
APP_ROOT_DIR = File.dirname(File.expand_path(File.join(__FILE__,".."))).freeze
|
3
3
|
APP_LIB_DIR = File.join(APP_ROOT_DIR,"lib").freeze
|
4
4
|
APP_DATA_DIR = File.join(APP_ROOT_DIR,"data").freeze
|
5
|
+
APP_VENDOR_DIR = File.join(APP_ROOT_DIR,"vendor").freeze
|
5
6
|
|
6
|
-
VERSION = [1,
|
7
|
+
VERSION = [1,1,0].freeze
|
7
8
|
AUTHOR = "Jeremy Hinegardner".freeze
|
8
9
|
AUTHOR_EMAIL= "jeremy@hinegardner.org".freeze
|
9
10
|
HOMEPAGE = "http://keybox.rubyforge.org".freeze
|
@@ -25,5 +26,4 @@ require 'keybox/randomizer'
|
|
25
26
|
require 'keybox/storage'
|
26
27
|
require 'keybox/string_generator'
|
27
28
|
require 'keybox/uuid'
|
28
|
-
require 'keybox/term_io'
|
29
29
|
require 'keybox/convert'
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'optparse'
|
2
2
|
require 'ostruct'
|
3
|
+
require 'keybox/highline_util'
|
3
4
|
|
4
5
|
#------------------------------------------------------------------------
|
5
6
|
# Base class for applications in keybox
|
@@ -21,22 +22,21 @@ module Keybox
|
|
21
22
|
attr_accessor :error_message
|
22
23
|
|
23
24
|
# these allow for testing instrumentation
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
attr_reader :stdout
|
26
|
+
attr_reader :stderr
|
27
|
+
attr_reader :stdin
|
28
|
+
attr_reader :highline
|
27
29
|
|
28
30
|
def initialize(argv = [])
|
29
31
|
# make sure we have an empty array, we could be
|
30
32
|
# initially passed nil explicitly
|
31
33
|
argv ||= []
|
32
34
|
|
33
|
-
#
|
34
|
-
|
35
|
-
@stdout = $stdout
|
36
|
-
@stderr = $stderr
|
35
|
+
# setup default io streams
|
36
|
+
set_io
|
37
37
|
|
38
38
|
@options = self.default_options
|
39
|
-
@parsed_options =
|
39
|
+
@parsed_options = OpenStruct.new
|
40
40
|
@parser = self.option_parser
|
41
41
|
@error_message = nil
|
42
42
|
|
@@ -49,6 +49,21 @@ module Keybox
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
+
#
|
53
|
+
# Allow the IO to be reset. This is generally just for
|
54
|
+
# testing instrumentation, but it may be useful for
|
55
|
+
# something else too.
|
56
|
+
#
|
57
|
+
def set_io(stdin = $stdin,stdout = $stdout,stderr = $stderr)
|
58
|
+
# for testing instrumentation
|
59
|
+
@stdin = stdin
|
60
|
+
@stdout = stdout
|
61
|
+
@stderr = stderr
|
62
|
+
|
63
|
+
# Instance of HighLine for the colorization of output
|
64
|
+
@highline = ::HighLine.new(@stdin,@stdout)
|
65
|
+
end
|
66
|
+
|
52
67
|
def option_parser
|
53
68
|
OptionParser.new do |op|
|
54
69
|
op.separator ""
|
@@ -80,7 +95,7 @@ module Keybox
|
|
80
95
|
# then merge in the command line options
|
81
96
|
def merge_options
|
82
97
|
options = default_options.marshal_dump
|
83
|
-
configuration_file_options.each_pair do |key,value|
|
98
|
+
self.configuration_file_options.each_pair do |key,value|
|
84
99
|
options[key] = value
|
85
100
|
end
|
86
101
|
|
@@ -97,17 +112,17 @@ module Keybox
|
|
97
112
|
@stderr.puts @error_message
|
98
113
|
exit 1
|
99
114
|
elsif @parsed_options.show_version then
|
100
|
-
@
|
115
|
+
@highline.say "#{@parser.program_name}: version #{Keybox::VERSION.join(".")}"
|
101
116
|
exit 0
|
102
117
|
elsif @parsed_options.show_help then
|
103
|
-
@
|
118
|
+
@highline.say @parser.to_s
|
104
119
|
exit 0
|
105
120
|
end
|
106
121
|
end
|
107
122
|
|
108
123
|
def run
|
109
124
|
error_version_help
|
110
|
-
@
|
125
|
+
@highline.say "Keybox Base Application. Doing nothing but output this line."
|
111
126
|
end
|
112
127
|
end
|
113
128
|
end
|
@@ -11,14 +11,15 @@ require 'fileutils'
|
|
11
11
|
module Keybox
|
12
12
|
module Application
|
13
13
|
class PasswordSafe < Base
|
14
|
-
include Keybox::
|
14
|
+
include Keybox::HighLineUtil
|
15
15
|
|
16
16
|
attr_accessor :actions
|
17
17
|
attr_reader :db
|
18
18
|
|
19
|
-
DEFAULT_DIRECTORY
|
20
|
-
DEFAULT_DB
|
21
|
-
DEFAULT_CONFIG
|
19
|
+
DEFAULT_DIRECTORY = File.join(ENV["HOME"],".keybox")
|
20
|
+
DEFAULT_DB = File.join(DEFAULT_DIRECTORY,"database.yaml")
|
21
|
+
DEFAULT_CONFIG = File.join(DEFAULT_DIRECTORY,"config.yaml")
|
22
|
+
DEFAULT_COLOR_SCHEME = :dark_bg
|
22
23
|
|
23
24
|
ACTION_LIST = %w(add delete edit show list master-password)
|
24
25
|
|
@@ -48,6 +49,10 @@ module Keybox
|
|
48
49
|
@parsed_options.config_file = cfile
|
49
50
|
end
|
50
51
|
|
52
|
+
op.on("--color SCHEME","The color scheme to use", "none,dark_bg,light_bg,<other>") do |scheme|
|
53
|
+
@parsed_options.color_scheme = scheme.to_sym
|
54
|
+
end
|
55
|
+
|
51
56
|
op.on("-D", "--debug", "Ouput debug information to STDERR") do
|
52
57
|
@parsed_options.debug = true
|
53
58
|
end
|
@@ -56,7 +61,6 @@ module Keybox
|
|
56
61
|
@parsed_options.use_password_hash_for_url = r
|
57
62
|
end
|
58
63
|
|
59
|
-
|
60
64
|
op.separator ""
|
61
65
|
op.separator "Commands, one and only one of these is required:"
|
62
66
|
|
@@ -116,6 +120,7 @@ module Keybox
|
|
116
120
|
options.config_file = Keybox::Application::PasswordSafe::DEFAULT_CONFIG
|
117
121
|
options.db_file = Keybox::Application::PasswordSafe::DEFAULT_DB
|
118
122
|
options.use_password_hash_for_url = false
|
123
|
+
options.color_scheme = Keybox::Application::PasswordSafe::DEFAULT_COLOR_SCHEME
|
119
124
|
return options
|
120
125
|
end
|
121
126
|
|
@@ -126,7 +131,6 @@ module Keybox
|
|
126
131
|
# we use the default unless the parsed_options contain a
|
127
132
|
# configuration file then we use that one
|
128
133
|
def configuration_file_options
|
129
|
-
|
130
134
|
file_path = @parsed_options.config_file || DEFAULT_CONFIG
|
131
135
|
|
132
136
|
# if the file is 0 bytes, then this is illegal and needs
|
@@ -140,13 +144,85 @@ module Keybox
|
|
140
144
|
options = YAML.load_file(file_path) || Hash.new
|
141
145
|
end
|
142
146
|
|
147
|
+
#
|
148
|
+
# load the given color scheme. If the scheme cannot be
|
149
|
+
# found it will default to the +:none+ scheme which has no
|
150
|
+
# color
|
151
|
+
#
|
152
|
+
# The color_scheme file exists either in the application data
|
153
|
+
# directory, or in the same directory as the configuration
|
154
|
+
# file.
|
155
|
+
#
|
156
|
+
# The file name convention for the scheme file is
|
157
|
+
# +schemename.color_scheme.yaml+. So for instance the default
|
158
|
+
# +:dark_bg+ color scheme file is named:
|
159
|
+
#
|
160
|
+
# dark_bg.color_scheme.yaml
|
161
|
+
def load_color_scheme
|
162
|
+
if @options.color_scheme != :none then
|
163
|
+
search_directories = [ Keybox::APP_DATA_DIR, File.dirname(@options.config_file) ]
|
164
|
+
scheme_basename = "#{@options.color_scheme.to_s}.color_scheme.yaml"
|
165
|
+
scheme_path = nil
|
166
|
+
|
167
|
+
# get the path to the file
|
168
|
+
search_directories.each do |sd|
|
169
|
+
if File.exists?(File.join(sd,scheme_basename)) then
|
170
|
+
scheme_path = File.join(sd,scheme_basename)
|
171
|
+
break
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# if we have a file then load it and make sure we have
|
176
|
+
# all the valid labels.
|
177
|
+
if scheme_path then
|
178
|
+
initial_color_scheme = YAML::load(File.read(scheme_path))
|
179
|
+
|
180
|
+
# make sure that everything is a Symbol and in the
|
181
|
+
# process make sure that all of the required labels
|
182
|
+
# are there.
|
183
|
+
color_scheme = {}
|
184
|
+
initial_color_scheme.each_pair do |label,ansi_seq|
|
185
|
+
color_scheme[label.to_sym] = ansi_seq.collect { |a| a.to_sym }
|
186
|
+
end
|
187
|
+
|
188
|
+
# validate that all the required color labels exist
|
189
|
+
if (NONE_SCHEME.keys - color_scheme.keys).size == 0 then
|
190
|
+
::HighLine.color_scheme = ::HighLine::ColorScheme.new(color_scheme)
|
191
|
+
else
|
192
|
+
@options.color_scheme = :none
|
193
|
+
::HighLine.color_scheme = ::HighLine::ColorScheme.new(NONE_SCHEME)
|
194
|
+
|
195
|
+
@stdout.puts "The color scheme in file '#{scheme_path}' is Invalid"
|
196
|
+
@stdout.puts "It is missing the following items:"
|
197
|
+
|
198
|
+
(NONE_SCHEME.keys - color_scheme.keys).each do |missing_label|
|
199
|
+
@stdout.puts "\t :#{missing_label}"
|
200
|
+
end
|
201
|
+
|
202
|
+
@stdout.puts "Not using any color scheme."
|
203
|
+
end
|
204
|
+
|
205
|
+
else
|
206
|
+
# if we don't have a file then set the color
|
207
|
+
# scheme to nil and we're done
|
208
|
+
@options.color_scheme = :none
|
209
|
+
::HighLine.color_scheme = ::HighLine::ColorScheme.new(NONE_SCHEME)
|
210
|
+
end
|
211
|
+
else
|
212
|
+
::HighLine.color_scheme = ::HighLine::ColorScheme.new(NONE_SCHEME)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
#
|
217
|
+
# load the database from its super secret location
|
218
|
+
#
|
143
219
|
def load_database
|
144
220
|
password = nil
|
145
221
|
if not File.exists?(@options.db_file) then
|
146
|
-
|
147
|
-
password = prompt("Initial Password for (#{@options.db_file})",
|
222
|
+
hsay 'Creating initial database.', :information
|
223
|
+
password = prompt("Initial Password for (#{@options.db_file})", :echo => "*", :validate => true)
|
148
224
|
else
|
149
|
-
password = prompt("Password for (#{@options.db_file})",
|
225
|
+
password = prompt("Password for (#{@options.db_file})", :echo => "*")
|
150
226
|
end
|
151
227
|
@db = Keybox::Storage::Container.new(password,@options.db_file)
|
152
228
|
end
|
@@ -172,7 +248,7 @@ module Keybox
|
|
172
248
|
|
173
249
|
end
|
174
250
|
new_entry = gather_info(entry)
|
175
|
-
|
251
|
+
hsay "Adding #{new_entry.title} to database.", :information
|
176
252
|
@db << new_entry
|
177
253
|
end
|
178
254
|
|
@@ -181,19 +257,19 @@ module Keybox
|
|
181
257
|
def gather_info(entry)
|
182
258
|
gathered = false
|
183
259
|
while not gathered do
|
184
|
-
|
260
|
+
hsay "Gathering information for entry '#{entry.title}'", :information
|
185
261
|
|
186
262
|
entry = fill_entry(entry)
|
187
263
|
|
188
264
|
# dump the info we have gathered and make sure that
|
189
265
|
# it is the input that the user wants to store.
|
190
266
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
267
|
+
hsay "-" * 40, :separator_bar
|
268
|
+
hsay entry, :normal
|
269
|
+
hsay "-" * 40, :separator_bar
|
270
|
+
|
271
|
+
|
272
|
+
gathered = hagree "Is this information correct? (y/n)"
|
197
273
|
end
|
198
274
|
|
199
275
|
entry
|
@@ -206,16 +282,16 @@ module Keybox
|
|
206
282
|
matches = @db.find(account)
|
207
283
|
count = 0
|
208
284
|
matches.each do |match|
|
209
|
-
|
210
|
-
|
211
|
-
|
285
|
+
hsay "-" * 40, :separator_bar
|
286
|
+
hsay match, :normal
|
287
|
+
hsay "-" * 40, :separator_bar
|
212
288
|
|
213
|
-
if
|
289
|
+
if hagree "Delete this entry (y/n) ?" then
|
214
290
|
@db.delete(match)
|
215
291
|
count += 1
|
216
292
|
end
|
217
293
|
end
|
218
|
-
|
294
|
+
hsay "#{count} records matching '#{account}' deleted.", :information
|
219
295
|
end
|
220
296
|
|
221
297
|
#
|
@@ -225,19 +301,19 @@ module Keybox
|
|
225
301
|
matches = @db.find(account)
|
226
302
|
count = 0
|
227
303
|
matches.each do |match|
|
228
|
-
|
229
|
-
|
230
|
-
|
304
|
+
hsay "-" * 40, :separator_bar
|
305
|
+
hsay match, :normal
|
306
|
+
hsay "-" * 40, :separator_bar
|
231
307
|
|
232
|
-
if
|
308
|
+
if hagree "Edit this entry (y/n) ?" then
|
233
309
|
entry = gather_info(match)
|
234
310
|
@db.delete(match)
|
235
311
|
@db << entry
|
236
312
|
count += 1
|
237
|
-
|
313
|
+
hsay "Entry '#{entry.title}' updated.", :information
|
238
314
|
end
|
239
315
|
end
|
240
|
-
|
316
|
+
hsay "#{count} records matching '#{account}' edited.", :information
|
241
317
|
end
|
242
318
|
|
243
319
|
#
|
@@ -260,25 +336,26 @@ module Keybox
|
|
260
336
|
|
261
337
|
full_length = lengths.values.inject(0) { |sum,n| sum + n}
|
262
338
|
header = " # #{"Title".ljust(lengths[:title])} #{"Username".ljust(lengths[:username])} #{add_info}"
|
263
|
-
|
339
|
+
hsay header, :header
|
264
340
|
# 3 spaces for number column + 1 space after and 4 spaces between
|
265
341
|
# each other column
|
266
|
-
|
342
|
+
hsay"-" * (header.length), :header_bar
|
267
343
|
|
268
344
|
matches.each_with_index do |match,i|
|
269
|
-
|
345
|
+
line_number = sprintf("%3d", i + 1)
|
270
346
|
# toggle colors
|
271
|
-
color = [:
|
347
|
+
color = [:even_row, :odd_row][i % 2]
|
272
348
|
columns = []
|
273
349
|
[:title, :username, :additional_info].each do |f|
|
274
350
|
t = match.send(f)
|
275
351
|
t = "-" if t.nil? or t.length == 0
|
276
352
|
columns << t.ljust(lengths[f])
|
277
353
|
end
|
278
|
-
|
354
|
+
cdata = columns.join(" " * 4)
|
355
|
+
@highline.say("<%= color('#{line_number}',:line_number) %> <%= color('#{cdata}','#{color}') %>")
|
279
356
|
end
|
280
357
|
else
|
281
|
-
|
358
|
+
hsay "No matching records were found.", :information
|
282
359
|
end
|
283
360
|
end
|
284
361
|
|
@@ -289,31 +366,33 @@ module Keybox
|
|
289
366
|
matches = @db.find(account)
|
290
367
|
if matches.size > 0 then
|
291
368
|
matches.each_with_index do |match,i|
|
292
|
-
|
369
|
+
hsay "#{sprintf("%3d",i + 1)}. #{match.title}", :header
|
293
370
|
max_name_length = match.max_field_length + 1
|
294
371
|
match.each do |name,value|
|
295
372
|
next if name == "title"
|
296
373
|
next if value.length == 0
|
297
374
|
|
298
375
|
name_out = name.rjust(max_name_length)
|
299
|
-
|
300
|
-
color_print " : ", :white
|
376
|
+
@highline.say("<%= color('#{name_out}', :name) %> <%= color(':',:separator) %> ")
|
301
377
|
|
302
378
|
if match.private_field?(name) then
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
379
|
+
@highline.ask(
|
380
|
+
"<%= color('#{value}',:private) %> <%= color('(press any key).', :prompt) %> "
|
381
|
+
) do |q|
|
382
|
+
q.overwrite = true
|
383
|
+
q.echo = false
|
384
|
+
q.character = true
|
385
|
+
end
|
386
|
+
|
387
|
+
@highline.say("<%= color('#{name_out}', :name) %> <%= color(':',:separator) %> <%= color('#{'*' * 20}', :private) %>")
|
309
388
|
else
|
310
|
-
|
389
|
+
hsay value, :value
|
311
390
|
end
|
312
391
|
end
|
313
392
|
@stdout.puts
|
314
393
|
end
|
315
394
|
else
|
316
|
-
|
395
|
+
hsay "No matching records were found.", :information
|
317
396
|
end
|
318
397
|
end
|
319
398
|
|
@@ -321,9 +400,8 @@ module Keybox
|
|
321
400
|
# Change the master password on the database
|
322
401
|
#
|
323
402
|
def master_password(ignore_this)
|
324
|
-
|
325
|
-
|
326
|
-
color_puts "New master password set.", :green
|
403
|
+
@db.passphrase = prompt("Enter new master password", :echo => '*', :validate => true, :width => 45)
|
404
|
+
hsay "New master password set.", :information
|
327
405
|
end
|
328
406
|
|
329
407
|
#
|
@@ -334,14 +412,14 @@ module Keybox
|
|
334
412
|
entries.each do |entry|
|
335
413
|
@db << entry
|
336
414
|
end
|
337
|
-
|
415
|
+
hsay "Imported #{entries.size} records from #{file}.", :information
|
338
416
|
end
|
339
417
|
|
340
418
|
#
|
341
419
|
# Export data from the database into a CSV file
|
342
420
|
def export_to_csv(file)
|
343
421
|
Keybox::Convert::CSV.to_file(@db.records, file)
|
344
|
-
|
422
|
+
hsay "Exported #{@db.records.size} records to #{file}.", :information
|
345
423
|
end
|
346
424
|
|
347
425
|
def fill_entry(entry)
|
@@ -360,12 +438,12 @@ module Keybox
|
|
360
438
|
# we don't echo private field prompts and we validate
|
361
439
|
# them
|
362
440
|
if entry.private_field?(field) then
|
363
|
-
echo =
|
441
|
+
echo = '*'
|
364
442
|
validate = true
|
365
443
|
p = "#{field}"
|
366
444
|
end
|
367
445
|
|
368
|
-
value = prompt(p
|
446
|
+
value = prompt("#{p}",:echo => echo ,:validate => validate,:width => max_length)
|
369
447
|
|
370
448
|
if value.nil? or value.size == 0 then
|
371
449
|
value = default
|
@@ -379,6 +457,7 @@ module Keybox
|
|
379
457
|
begin
|
380
458
|
error_version_help
|
381
459
|
merge_options
|
460
|
+
load_color_scheme
|
382
461
|
load_database
|
383
462
|
|
384
463
|
if @actions.size == 0 then
|
@@ -388,20 +467,19 @@ module Keybox
|
|
388
467
|
self.send(action, param)
|
389
468
|
|
390
469
|
if @db.modified? then
|
391
|
-
|
470
|
+
hsay "Database modified, saving.", :information
|
392
471
|
@db.save
|
393
472
|
else
|
394
|
-
|
473
|
+
hsay "Database not modified.", :information
|
395
474
|
end
|
396
475
|
rescue SignalException => se
|
397
476
|
@stdout.puts
|
398
|
-
|
399
|
-
|
400
|
-
|
477
|
+
hsay "Interrupted", :error
|
478
|
+
hsay "There may be private information on your screen.", :error
|
479
|
+
hsay "Please close this terminal.", :error
|
401
480
|
exit 1
|
402
481
|
rescue StandardError => e
|
403
|
-
|
404
|
-
color_puts "Error: #{e.message}", :red
|
482
|
+
hsay "Error: #{e.message}", :error
|
405
483
|
exit 1
|
406
484
|
end
|
407
485
|
end
|