rubeepass 0.4.2 → 0.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4c9173d805e33e51cc75649bf98888fe43d1ddf6
4
- data.tar.gz: cf33596494c2237f9d155b0b3b19695159e04e66
3
+ metadata.gz: 27da21673c45cfb2ab29bb1c984f477ea16036d6
4
+ data.tar.gz: 3785cf861668b77aea2d275248f4747e85425c2a
5
5
  SHA512:
6
- metadata.gz: e17d97fee36dec9b46bb7cee8012ceab4cad86f1efab7e5f391597d4b057d4d99bd218a4ff5683474aaba78af0a915f9f3b5ed589bcd424a5cb7c897763fff18
7
- data.tar.gz: ce56faf8900c3425e55fd480966ee5e39a73fc886eda135156a54c52e2e9f8e08726dd84f695755e911a0aa96fc75f8feff2bb7d83d05f2f5328bd50a98fb951
6
+ metadata.gz: 301723a1764cb1f6698e912069e39fb65f1577dd94ad0dbe3e4ed329c495f6bb3110ceea15e0ce6c1ac56bc91ef1758a642742c9d35ce8857d9368f29b79890e
7
+ data.tar.gz: 9edb83c2c117297bd7d731fd610fb81c7606fa9ded5d0deefe046f24408d6652bc99547aa560c41fb027225707f912bd610c72f84c187901e9c19e3bdac4b71a
data/bin/rpass CHANGED
@@ -3,37 +3,57 @@
3
3
  require "colorize"
4
4
  require "djinni"
5
5
  require "io/console"
6
- require "json"
6
+ require "json_config"
7
7
  require "optparse"
8
- require "pathname"
9
8
  require "rubeepass"
10
9
 
11
- class RPassExit
10
+ class RubeePassExit
12
11
  GOOD = 0
13
12
  INVALID_OPTION = 1
14
13
  INVALID_ARGUMENT = 2
15
14
  MISSING_ARGUMENT = 3
16
15
  EXTRA_ARGUMENTS = 4
17
- KDBX_NOT_FOUND = 5
18
- KDBX_NOT_READABLE = 6
19
- KEYFILE_NOT_FOUND = 7
20
- KEYFILE_NOT_READABLE = 8
21
- KDBX_NOT_OPENED = 9
16
+ EXCEPTION = 5
17
+ end
18
+
19
+ class RubeePassConfig < JSONConfig
20
+ def default_config
21
+ set("last_kdbx", nil)
22
+ set("last_keyfile", nil)
23
+ set("timeout", 10)
24
+ end
25
+
26
+ def last_kdbx(kdbx = nil)
27
+ set("last_kdbx", kdbx.to_s) if (kdbx)
28
+ kdbx = get("last_kdbx")
29
+ return nil if (kdbx.nil? || kdbx.empty?)
30
+ return kdbx
31
+ end
32
+
33
+ def last_keyfile(keyfile = nil)
34
+ set("last_keyfile", keyfile.to_s) if (keyfile)
35
+ keyfile = get("last_keyfile")
36
+ return nil if (keyfile.nil? || keyfile.empty?)
37
+ return keyfile
38
+ end
39
+
40
+ def timeout(t = nil)
41
+ set("timeout", t) if (t)
42
+ t = get("timeout")
43
+ case t
44
+ when /[0-9]+/
45
+ return t.to_i
46
+ else
47
+ return nil
48
+ end
49
+ end
22
50
  end
23
51
 
24
52
  def get_password
25
53
  print "Enter password: "
26
- begin
27
- passwd = STDIN.noecho(&:gets)
28
- puts
29
- return passwd.chomp
30
- rescue Interrupt => e
31
- puts
32
- exit RPassExit::GOOD
33
- rescue
34
- puts
35
- exit RPassExit::KDBX_NOT_OPENED
36
- end
54
+ passwd = STDIN.noecho(&:gets)
55
+ puts
56
+ return passwd.chomp
37
57
  end
38
58
 
39
59
  def parse(args)
@@ -44,6 +64,7 @@ def parse(args)
44
64
  options["password"] = nil
45
65
  options["keyfile"] = nil
46
66
  options["timeout"] = nil
67
+ options["verbose"] = false
47
68
 
48
69
  parser = OptionParser.new do |opts|
49
70
  opts.banner = "Usage: #{File.basename($0)} [OPTIONS] [kdbx]"
@@ -75,7 +96,7 @@ def parse(args)
75
96
 
76
97
  opts.on("-h", "--help", "Display this help message") do
77
98
  puts opts
78
- exit RPassExit::GOOD
99
+ exit RubeePassExit::GOOD
79
100
  end
80
101
 
81
102
  opts.on(
@@ -83,7 +104,11 @@ def parse(args)
83
104
  "--keyfile=KEYFILE",
84
105
  "Use specified keyfile"
85
106
  ) do |keyfile|
86
- options["keyfile"] = Pathname.new(keyfile).expand_path
107
+ options["keyfile"] = keyfile
108
+ end
109
+
110
+ opts.on("--nocolor", "Disable colorized output") do
111
+ String.disable_colorization = true
87
112
  end
88
113
 
89
114
  opts.on(
@@ -98,11 +123,19 @@ def parse(args)
98
123
  options["timeout"] = t.to_i
99
124
  end
100
125
 
126
+ opts.on(
127
+ "-v",
128
+ "--verbose",
129
+ "Show backtrace when error occurs"
130
+ ) do
131
+ options["verbose"] = true
132
+ end
133
+
101
134
  opts.on(
102
135
  "",
103
136
  "FORMATS",
104
- "\tgzip",
105
- "\txml"
137
+ " gzip",
138
+ " xml"
106
139
  )
107
140
  end
108
141
 
@@ -111,109 +144,63 @@ def parse(args)
111
144
  rescue OptionParser::InvalidOption => e
112
145
  puts e.message
113
146
  puts parser
114
- exit RPassExit::INVALID_OPTION
147
+ exit RubeePassExit::INVALID_OPTION
115
148
  rescue OptionParser::InvalidArgument => e
116
149
  puts e.message
117
150
  puts parser
118
- exit RPassExit::INVALID_ARGUMENT
151
+ exit RubeePassExit::INVALID_ARGUMENT
119
152
  rescue OptionParser::MissingArgument => e
120
153
  puts e.message
121
154
  puts parser
122
- exit RPassExit::MISSING_ARGUMENT
155
+ exit RubeePassExit::MISSING_ARGUMENT
123
156
  end
124
157
 
125
158
  if (args.length > 1)
126
159
  puts parser
127
- exit RPassExit::EXTRA_ARGUMENTS
160
+ exit RubeePassExit::EXTRA_ARGUMENTS
128
161
  end
129
162
 
130
163
  # Read config
131
- rc = read_rpassrc
164
+ rc = RubeePassConfig.new("~/.rpassrc")
132
165
 
133
166
  # Determine kdbx and keyfile
134
167
  if (args.length == 1)
135
168
  # Use specified kdbx (and keyfile if specified)
136
- options["kdbx"] = Pathname.new(args[0]).expand_path
169
+ options["kdbx"] = args[0]
137
170
  else
138
171
  # Use kdbx from config if stored
139
- if (rc["last_kdbx"] && !rc["last_kdbx"].empty?)
140
- options["kdbx"] = Pathname.new(
141
- rc["last_kdbx"]
142
- ).expand_path
172
+ if (rc.last_kdbx)
173
+ options["kdbx"] = rc.last_kdbx
143
174
  end
144
175
 
145
176
  # Use keyfile from config if stored and not specified already
146
177
  if (options["keyfile"].nil?)
147
- if (rc["last_keyfile"] && !rc["last_keyfile"].empty?)
148
- options["keyfile"] = Pathname.new(
149
- rc["last_keyfile"]
150
- ).expand_path
178
+ if (rc.last_keyfile)
179
+ options["keyfile"] = rc.last_keyfile
151
180
  end
152
181
  end
153
182
  end
154
183
 
155
184
  # Determine timeout
156
185
  if (options["timeout"].nil?)
157
- if (rc["timeout"])
158
- options["timeout"] = rc["timeout"]
159
- else
160
- options["timeout"] = 7
161
- end
186
+ options["timeout"] = 10
187
+ options["timeout"] = rc.timeout if (rc.timeout)
162
188
  end
163
189
 
164
190
  # Throw error if kdbx not specified or in config
165
191
  if (options["kdbx"].nil?)
166
192
  puts parser
167
- exit RPassExit::MISSING_ARGUMENT
168
- end
169
-
170
- # Throw error if kdbx does not exist or is not readable
171
- if (!options["kdbx"].exist?)
172
- puts parser
173
- exit RPassExit::KDBX_NOT_FOUND
174
- elsif (!options["kdbx"].readable?)
175
- puts parser
176
- exit RPassExit::KDBX_NOT_READABLE
177
- end
178
-
179
- # Throw error if keyfile does not exist or is not readable
180
- if (options["keyfile"])
181
- if (!options["keyfile"].exist?)
182
- puts parser
183
- exit RPassExit::KEYFILE_NOT_FOUND
184
- elsif (!options["keyfile"].readable?)
185
- puts parser
186
- exit RPassExit::KEYFILE_NOT_READABLE
187
- end
193
+ exit RubeePassExit::MISSING_ARGUMENT
188
194
  end
189
195
 
190
196
  # Store data in config
191
- rc["last_kdbx"] = options["kdbx"]
192
- rc["last_keyfile"] = options["keyfile"]
193
- rc["timeout"] = options["timeout"]
194
- write_rpassrc(rc)
197
+ rc.last_kdbx(options["kdbx"])
198
+ rc.last_keyfile(options["keyfile"])
199
+ rc.timeout(options["timeout"])
195
200
 
196
201
  return options
197
202
  end
198
203
 
199
- def read_rpassrc
200
- default = Hash.new
201
- default["last_kdbx"] = nil
202
- default["last_keyfile"] = nil
203
- default["timeout"] = 7
204
-
205
- rc_file = Pathname.new("~/.rpassrc").expand_path
206
- return default if (!rc_file.exist? && !rc_file.symlink?)
207
- return JSON.parse(File.read(rc_file))
208
- end
209
-
210
- def write_rpassrc(rc)
211
- rc_file = Pathname.new("~/.rpassrc").expand_path
212
- File.open(rc_file, "w") do |f|
213
- f.write(JSON.pretty_generate(rc))
214
- end
215
- end
216
-
217
204
  options = parse(ARGV)
218
205
 
219
206
  kdbx = options["kdbx"]
@@ -221,39 +208,41 @@ password = options["password"] if (options["password"])
221
208
  password = get_password if (options["password"].nil?)
222
209
  keyfile = options["keyfile"]
223
210
 
224
- keepass = RubeePass.new(kdbx, password, keyfile)
225
-
226
- if (options["export_file"])
227
- begin
228
- keepass.export(
229
- options["export_file"],
230
- options["export_format"]
231
- )
232
- rescue RubeePass::Error::InvalidPasswordError => e
233
- puts e.message
234
- password = get_password
235
- keepass = RubeePass.new(kdbx, password, keyfile)
211
+ begin
212
+ keepass = RubeePass.new(
213
+ kdbx,
214
+ password,
215
+ keyfile,
216
+ !String.disable_colorization
217
+ )
218
+
219
+ loop do
220
+ begin
221
+ if (options["export_file"])
222
+ keepass.export(
223
+ options["export_file"],
224
+ options["export_format"]
225
+ )
226
+ exit RubeePassExit::GOOD
227
+ else
228
+ keepass.open
229
+ end
230
+ break
231
+ rescue RubeePass::Error::InvalidPassword => e
232
+ puts e.message
233
+ password = get_password
234
+ keepass = RubeePass.new(
235
+ kdbx,
236
+ password,
237
+ keyfile,
238
+ !String.disable_colorization
239
+ )
240
+ end
236
241
  end
237
- exit RPassExit::GOOD
238
- end
239
242
 
240
- loop do
241
- begin
242
- keepass.open
243
- break
244
- rescue RubeePass::Error::InvalidPasswordError => e
245
- puts e.message
246
- password = get_password
247
- keepass = RubeePass.new(kdbx, password, keyfile)
248
- rescue RubeePass::Error => e
249
- puts e.message
250
- exit RPassExit::KDBX_NOT_OPENED
251
- end
252
- end
243
+ djinni = Djinni.new
244
+ djinni.load_wishes("#{File.dirname(__FILE__)}/../lib/rubeepass/wish")
253
245
 
254
- djinni = Djinni.new
255
- djinni.load_wishes("#{File.dirname(__FILE__)}/../lib/rubeepass/wish")
256
- begin
257
246
  if (options["command"])
258
247
  djinni.grant_wish(
259
248
  "#{options["command"].chomp}\n",
@@ -269,14 +258,44 @@ begin
269
258
  {
270
259
  "keepass" => keepass,
271
260
  "cwd" => keepass.db,
272
- "clipboard_timeout" => options["timeout"]
261
+ "clipboard_timeout" => options["timeout"],
262
+ "prompt_color" => "light_white"
273
263
  },
274
- "rpass:/> ".white
264
+ "rpass:/> ".light_white
275
265
  )
276
266
  end
277
- # rescue SystemExit => e
267
+ rescue SystemExit
268
+ # Quit from djinni
269
+ # Exit gracefully
270
+ rescue Interrupt
271
+ # ^C
272
+ # Exit gracefully
273
+ rescue Errno::EPIPE
274
+ # Do nothing. This can happen if piping to another program such as
275
+ # less. Usually if less is closed before we're done with STDOUT.
276
+ rescue RubeePass::Error => e
277
+ puts e.message
278
+ exit RubeePassExit::EXCEPTION
279
+ rescue Exception => e
280
+ $stderr.puts "Oops! Looks like an error has occured! If the " \
281
+ "error persists, file a bug at:".word_wrap
282
+ $stderr.puts
283
+ $stderr.puts " https://gitlab.com/mjwhitta/rubeepass/issues"
284
+ $stderr.puts
285
+ $stderr.puts "Maybe the message below will help. If not, you " \
286
+ "can use the --verbose flag to get a backtrace.".word_wrap
287
+
288
+ $stderr.puts e.message.white.on_red
289
+ if (options["verbose"])
290
+ e.backtrace.each do |line|
291
+ $stderr.puts line.light_yellow
292
+ end
293
+ end
294
+ exit RubeePassExit::EXCEPTION
278
295
  ensure
279
- keepass.clear_clipboard
280
- keepass.wait_to_exit
296
+ if (keepass)
297
+ keepass.clear_clipboard
298
+ keepass.wait_to_exit
299
+ end
281
300
  end
282
- exit RPassExit::GOOD
301
+ exit RubeePassExit::GOOD
@@ -22,14 +22,30 @@ class RubeePass::Entry
22
22
  return (self.title.downcase <=> other.title.downcase)
23
23
  end
24
24
 
25
+ def colorize_password(passwd)
26
+ return passwd if (!@colorize)
27
+ return passwd.light_red
28
+ end
29
+ private :colorize_password
30
+
31
+ def colorize_title(title)
32
+ return title if (!@colorize)
33
+ return title.light_green
34
+ end
35
+ private :colorize_title
36
+
25
37
  def details(level = 0, show_passwd = false)
26
38
  lvl = Array.new(level, " ").join
27
39
 
28
40
  ret = Array.new
29
- ret.push("#{lvl}Title : #{@title}".green)
41
+ ret.push(colorize_title("#{lvl}Title : #{@title}"))
30
42
  # ret.push("#{lvl}UUID : #{@uuid}")
31
43
  ret.push("#{lvl}Username : #{@username}")
32
- ret.push("#{lvl}Password : #{password}".red) if (show_passwd)
44
+ if (show_passwd)
45
+ ret.push(
46
+ colorize_password("#{lvl}Password : #{password}")
47
+ )
48
+ end
33
49
  ret.push("#{lvl}Url : #{@url}")
34
50
 
35
51
  first = true
@@ -45,7 +61,7 @@ class RubeePass::Entry
45
61
  return ret.join("\n")
46
62
  end
47
63
 
48
- def self.from_xml(keepass, parent, xml)
64
+ def self.from_xml(keepass, parent, xml, colorize = false)
49
65
  notes = ""
50
66
  password = ""
51
67
  title = ""
@@ -95,7 +111,8 @@ class RubeePass::Entry
95
111
  title,
96
112
  url,
97
113
  username,
98
- uuid
114
+ uuid,
115
+ colorize
99
116
  )
100
117
  end
101
118
 
@@ -105,9 +122,9 @@ class RubeePass::Entry
105
122
  begin
106
123
  data = base64.unpack("m*")[0].fix
107
124
  rescue ArgumentError => e
108
- raise Error::InvalidProtectedDataError.new
125
+ raise Error::InvalidProtectedData.new
109
126
  end
110
- raise Error::InvalidProtectedDataError.new if (data.nil?)
127
+ raise Error::InvalidProtectedData.new if (data.nil?)
111
128
 
112
129
  return keepass.protected_decryptor.add_to_stream(data)
113
130
  end
@@ -120,8 +137,10 @@ class RubeePass::Entry
120
137
  title,
121
138
  url,
122
139
  username,
123
- uuid
140
+ uuid,
141
+ colorize = false
124
142
  )
143
+ @colorize = colorize
125
144
  @group = group
126
145
  @keepass = keepass
127
146
  @notes = notes
@@ -0,0 +1,5 @@
1
+ class RubeePass::Error::FileNotFound < RubeePass::Error
2
+ def initialize(file)
3
+ super("File not found: #{file}")
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class RubeePass::Error::FileNotReadable < RubeePass::Error
2
+ def initialize(file)
3
+ super("File not readable: #{file}")
4
+ end
5
+ end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::InvalidGzipError < RubeePass::Error
3
+ class RubeePass::Error::InvalidGzip < RubeePass::Error
4
4
  def initialize
5
5
  super("Invalid gzip format!")
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::InvalidHeaderError < RubeePass::Error
3
+ class RubeePass::Error::InvalidHeader < RubeePass::Error
4
4
  def initialize
5
5
  super("Invalid header format!")
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::InvalidMagicError < RubeePass::Error
3
+ class RubeePass::Error::InvalidMagic < RubeePass::Error
4
4
  def initialize
5
5
  super("Invalid magic values detected!")
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::InvalidPasswordError < RubeePass::Error
3
+ class RubeePass::Error::InvalidPassword < RubeePass::Error
4
4
  def initialize
5
5
  super("Invalid password provided!")
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::InvalidProtectedDataError < RubeePass::Error
3
+ class RubeePass::Error::InvalidProtectedData < RubeePass::Error
4
4
  def initialize
5
5
  super("Invalid protected data!")
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::InvalidProtectedStreamKeyError < RubeePass::Error
3
+ class RubeePass::Error::InvalidProtectedStreamKey < RubeePass::Error
4
4
  def initialize
5
5
  super("Invalid protected stream key!")
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::InvalidVersionError < RubeePass::Error
3
+ class RubeePass::Error::InvalidVersion < RubeePass::Error
4
4
  def initialize
5
5
  super("Invalid version detected!")
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::InvalidXMLError < RubeePass::Error
3
+ class RubeePass::Error::InvalidXML < RubeePass::Error
4
4
  def initialize
5
5
  super("Invalid xml schema!")
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::NotAESError < RubeePass::Error
3
+ class RubeePass::Error::NotAES < RubeePass::Error
4
4
  def initialize
5
5
  super("Not AES!")
6
6
  end
@@ -1,6 +1,6 @@
1
1
  require "rubeepass/error"
2
2
 
3
- class RubeePass::Error::NotSalsa20Error < RubeePass::Error
3
+ class RubeePass::Error::NotSalsa20 < RubeePass::Error
4
4
  def initialize
5
5
  super("Not a Salsa20 CrsAlgorithm!")
6
6
  end
@@ -1,13 +1,15 @@
1
1
  class RubeePass::Error < RuntimeError
2
2
  end
3
3
 
4
- require "rubeepass/error/invalid_gzip_error"
5
- require "rubeepass/error/invalid_header_error"
6
- require "rubeepass/error/invalid_magic_error"
7
- require "rubeepass/error/invalid_password_error"
8
- require "rubeepass/error/invalid_protected_data_error"
9
- require "rubeepass/error/invalid_protected_stream_key_error"
10
- require "rubeepass/error/invalid_version_error"
11
- require "rubeepass/error/invalid_xml_error"
12
- require "rubeepass/error/not_aes_error"
13
- require "rubeepass/error/not_salsa20_error"
4
+ require "rubeepass/error/file_not_found"
5
+ require "rubeepass/error/file_not_readable"
6
+ require "rubeepass/error/invalid_gzip"
7
+ require "rubeepass/error/invalid_header"
8
+ require "rubeepass/error/invalid_magic"
9
+ require "rubeepass/error/invalid_password"
10
+ require "rubeepass/error/invalid_protected_data"
11
+ require "rubeepass/error/invalid_protected_stream_key"
12
+ require "rubeepass/error/invalid_version"
13
+ require "rubeepass/error/invalid_xml"
14
+ require "rubeepass/error/not_aes"
15
+ require "rubeepass/error/not_salsa20"
@@ -20,12 +20,18 @@ class RubeePass::Group
20
20
  return (self.name.downcase <=> other.name.downcase)
21
21
  end
22
22
 
23
+ def colorize_header(header)
24
+ return header if (!@colorize)
25
+ return header.light_blue
26
+ end
27
+ private :colorize_header
28
+
23
29
  def details(level = 0, show_passwd = false)
24
30
  out = Array.new
25
31
  lvl = Array.new(level, " ").join
26
32
 
27
- group_details = [ "#{@path}".blue ] if (level == 0)
28
- group_details = [ "#{@name}".blue ] if (level != 0)
33
+ group_details = [ colorize_header(@path) ] if (level == 0)
34
+ group_details = [ colorize_header(@name) ] if (level != 0)
29
35
 
30
36
  group_details.each do |line|
31
37
  out.push("#{lvl}#{line}")
@@ -64,7 +70,7 @@ class RubeePass::Group
64
70
  return cwd
65
71
  end
66
72
 
67
- def self.from_xml(keepass, parent, xml)
73
+ def self.from_xml(keepass, parent, xml, colorize = false)
68
74
  name = xml.elements["Name"].text if (parent)
69
75
  name = "" if (name.nil?)
70
76
  name = "/" if (parent.nil?)
@@ -82,7 +88,8 @@ class RubeePass::Group
82
88
  keepass,
83
89
  name,
84
90
  notes,
85
- uuid
91
+ uuid,
92
+ colorize
86
93
  )
87
94
 
88
95
  if (xml.elements["Entry"])
@@ -90,7 +97,8 @@ class RubeePass::Group
90
97
  entry = RubeePass::Entry.from_xml(
91
98
  keepass,
92
99
  group,
93
- entry_xml
100
+ entry_xml,
101
+ colorize
94
102
  )
95
103
  group.entries[entry.title] = entry
96
104
  end
@@ -101,7 +109,8 @@ class RubeePass::Group
101
109
  child = RubeePass::Group.from_xml(
102
110
  keepass,
103
111
  group,
104
- group_xml
112
+ group_xml,
113
+ colorize
105
114
  )
106
115
  group.groups[child.name] = child
107
116
  end
@@ -161,7 +170,15 @@ class RubeePass::Group
161
170
  return false
162
171
  end
163
172
 
164
- def initialize(group, keepass, name, notes, uuid)
173
+ def initialize(
174
+ group,
175
+ keepass,
176
+ name,
177
+ notes,
178
+ uuid,
179
+ colorize = false
180
+ )
181
+ @colorize = colorize
165
182
  @entries = Hash.new
166
183
  @group = group
167
184
  @groups = Hash.new
@@ -13,13 +13,18 @@ class CDWish < Djinni::Wish
13
13
  def execute(args, djinni_env = {})
14
14
  keepass = djinni_env["keepass"]
15
15
  cwd = djinni_env["cwd"]
16
+ prompt_color = djinni_env["prompt_color"]
16
17
 
17
18
  args = keepass.absolute_path(args, cwd.path)
18
19
  new_cwd = keepass.find_group(args)
19
20
 
20
21
  if (new_cwd)
21
22
  djinni_env["cwd"] = new_cwd
22
- prompt = "rpass:#{new_cwd.name}> ".white
23
+ if (prompt_color)
24
+ prompt = "rpass:#{new_cwd.name}> ".send(prompt_color)
25
+ else
26
+ prompt = "rpass:#{new_cwd.name}> "
27
+ end
23
28
  djinni_env["djinni_prompt"] = prompt
24
29
  else
25
30
  puts "Group \"#{args}\" doesn't exist!"
@@ -1,4 +1,3 @@
1
- require "colorize"
2
1
  require "djinni"
3
2
 
4
3
  class CopyWish < Djinni::Wish
@@ -1,4 +1,3 @@
1
- require "colorize"
2
1
  require "djinni"
3
2
 
4
3
  class EchoWish < Djinni::Wish
@@ -1,4 +1,3 @@
1
- require "colorize"
2
1
  require "djinni"
3
2
 
4
3
  class LSWish < Djinni::Wish
@@ -1,4 +1,3 @@
1
- require "colorize"
2
1
  require "djinni"
3
2
 
4
3
  class ShowAllWish < Djinni::Wish
@@ -1,4 +1,3 @@
1
- require "colorize"
2
1
  require "djinni"
3
2
 
4
3
  class ShowWish < Djinni::Wish
data/lib/rubeepass.rb CHANGED
@@ -2,6 +2,7 @@ require "cgi"
2
2
  require "digest"
3
3
  require "openssl"
4
4
  require "os"
5
+ require "pathname"
5
6
  require "rexml/document"
6
7
  require "scoobydoo"
7
8
  require "shellwords"
@@ -173,10 +174,28 @@ class RubeePass
173
174
  return @db.fuzzy_find(input)
174
175
  end
175
176
 
176
- def initialize(kdbx, password, keyfile = nil)
177
- @kdbx = kdbx
178
- @keyfile = keyfile
177
+ def initialize(kdbx, password, keyfile = nil, colorize = false)
178
+ @colorize = colorize
179
+ @kdbx = Pathname.new(kdbx).expand_path
180
+ @keyfile = nil
181
+ @keyfile = Pathname.new(keyfile).expand_path if (keyfile)
179
182
  @password = password
183
+
184
+ if (@kdbx.nil?)
185
+ # TODO
186
+ elsif (!@kdbx.exist?)
187
+ raise RubeePass::Error::FileNotFound.new(@kdbx)
188
+ elsif (!@kdbx.readable?)
189
+ raise RubeePass::Error::FileNotReadable.new(@kdbx)
190
+ end
191
+
192
+ if (@keyfile)
193
+ if (!@keyfile.exist?)
194
+ raise RubeePass::Error::FileNotFound.new(@keyfile)
195
+ elsif (!@keyfile.readable?)
196
+ raise RubeePass::Error::FileNotReadable.new(@keyfile)
197
+ end
198
+ end
180
199
  end
181
200
 
182
201
  def join_key_and_keyfile
@@ -264,28 +283,26 @@ class RubeePass
264
283
  loop do
265
284
  # Read block ID
266
285
  data = file.read(4)
267
- raise Error::InvalidGzipError.new if (data.nil?)
286
+ raise Error::InvalidGzip.new if (data.nil?)
268
287
  id = data.unpack("L*")[0]
269
- raise Error::InvalidGzipError.new if (block_id != id)
288
+ raise Error::InvalidGzip.new if (block_id != id)
270
289
 
271
290
  block_id += 1
272
291
 
273
292
  # Read expected hash
274
293
  data = file.read(32)
275
- raise Error::InvalidGzipError.new if (data.nil?)
294
+ raise Error::InvalidGzip.new if (data.nil?)
276
295
  expected_hash = data
277
296
 
278
297
  # Read size
279
298
  data = file.read(4)
280
- raise Error::InvalidGzipError.new if (data.nil?)
299
+ raise Error::InvalidGzip.new if (data.nil?)
281
300
  size = data.unpack("L*")[0]
282
301
 
283
302
  # Break is size is 0 and expected hash is all 0's
284
303
  if (size == 0)
285
304
  expected_hash.each_byte do |byte|
286
- if (byte != 0)
287
- raise Error::InvalidGzipError.new
288
- end
305
+ raise Error::InvalidGzip.new if (byte != 0)
289
306
  end
290
307
  break
291
308
  end
@@ -296,7 +313,7 @@ class RubeePass
296
313
 
297
314
  # Check that actual hash is same as expected hash
298
315
  if (actual_hash != expected_hash)
299
- raise Error::InvalidGzipError.new
316
+ raise Error::InvalidGzip.new
300
317
  end
301
318
 
302
319
  # Append data
@@ -310,11 +327,11 @@ class RubeePass
310
327
  def parse_xml
311
328
  doc = REXML::Document.new(@xml)
312
329
  if (doc.elements["KeePassFile/Root"].nil?)
313
- raise Error::InvalidXMLError.new
330
+ raise Error::InvalidXML.new
314
331
  end
315
332
 
316
333
  root = doc.elements["KeePassFile/Root"]
317
- @db = Group.from_xml(self, nil, root)
334
+ @db = Group.from_xml(self, nil, root, @colorize)
318
335
  end
319
336
  private :parse_xml
320
337
 
@@ -331,11 +348,11 @@ class RubeePass
331
348
  cipher.update(encrypted) + cipher.final
332
349
  )
333
350
  rescue OpenSSL::Cipher::CipherError => e
334
- raise Error::InvalidPasswordError.new
351
+ raise Error::InvalidPassword.new
335
352
  end
336
353
 
337
354
  if (data.read(32) != @header[@@STREAM_START_BYTES])
338
- raise Error::InvalidPasswordError.new
355
+ raise Error::InvalidPassword.new
339
356
  end
340
357
 
341
358
  @gzip = parse_gzip(data)
@@ -346,11 +363,11 @@ class RubeePass
346
363
  header = Hash.new
347
364
  loop do
348
365
  data = file.read(1)
349
- raise Error::InvalidHeaderError.new if (data.nil?)
366
+ raise Error::InvalidHeader.new if (data.nil?)
350
367
  id = data.unpack("C*")[0]
351
368
 
352
369
  data = file.read(2)
353
- raise Error::InvalidHeaderError.new if (data.nil?)
370
+ raise Error::InvalidHeader.new if (data.nil?)
354
371
  size = data.unpack("S*")[0]
355
372
 
356
373
  data = file.read(size)
@@ -371,11 +388,11 @@ class RubeePass
371
388
  (header[@@MASTER_SEED].length != 32) ||
372
389
  (header[@@TRANSFORM_SEED].length != 32)
373
390
  )
374
- raise Error::InvalidHeaderError.new
391
+ raise Error::InvalidHeader.new
375
392
  elsif (header[@@INNER_RANDOM_STREAM_ID] != irsi)
376
- raise Error::NotSalsaError.new
393
+ raise Error::NotSalsa.new
377
394
  elsif (header[@@CIPHER_ID].unpack("H*")[0] != aes)
378
- raise Error::NotAESError.new
395
+ raise Error::NotAES.new
379
396
  end
380
397
 
381
398
  @header = header
@@ -384,24 +401,20 @@ class RubeePass
384
401
 
385
402
  def read_magic_and_version(file)
386
403
  data = file.read(4)
387
- raise Error::InvalidMagicError.new if (data.nil?)
404
+ raise Error::InvalidMagic.new if (data.nil?)
388
405
  sig1 = data.unpack("L*")[0]
389
- if (sig1 != @@MAGIC_SIG1)
390
- raise Error::InvalidMagicError.new
391
- end
406
+ raise Error::InvalidMagic.new if (sig1 != @@MAGIC_SIG1)
392
407
 
393
408
  data = file.read(4)
394
- raise Error::InvalidMagicError.new if (data.nil?)
409
+ raise Error::InvalidMagic.new if (data.nil?)
395
410
  sig2 = data.unpack("L*")[0]
396
- if (sig2 != @@MAGIC_SIG2)
397
- raise Error::InvalidMagicError.new
398
- end
411
+ raise Error::InvalidMagic.new if (sig2 != @@MAGIC_SIG2)
399
412
 
400
413
  data = file.read(4)
401
- raise Error::InvalidVersionError.new if (data.nil?)
414
+ raise Error::InvalidVersion.new if (data.nil?)
402
415
  ver = data.unpack("L*")[0]
403
416
  if ((ver & 0xffff0000) != @@VERSION)
404
- raise Error::InvalidVersionError.new if (data.nil?)
417
+ raise Error::InvalidVersion.new if (data.nil?)
405
418
  end
406
419
  end
407
420
  private :read_magic_and_version
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubeepass
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miles Whittaker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-18 00:00:00.000000000 Z
11
+ date: 2016-03-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: '5.8'
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 5.8.1
22
+ version: 5.8.4
23
23
  type: :development
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,27 +29,27 @@ dependencies:
29
29
  version: '5.8'
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 5.8.1
32
+ version: 5.8.4
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: rake
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '10.4'
39
+ version: '10.5'
40
40
  - - ">="
41
41
  - !ruby/object:Gem::Version
42
- version: 10.4.2
42
+ version: 10.5.0
43
43
  type: :development
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
46
46
  requirements:
47
47
  - - "~>"
48
48
  - !ruby/object:Gem::Version
49
- version: '10.4'
49
+ version: '10.5'
50
50
  - - ">="
51
51
  - !ruby/object:Gem::Version
52
- version: 10.4.2
52
+ version: 10.5.0
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: colorize
55
55
  requirement: !ruby/object:Gem::Requirement
@@ -79,7 +79,7 @@ dependencies:
79
79
  version: '1.3'
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: 1.3.1
82
+ version: 1.3.3
83
83
  type: :runtime
84
84
  prerelease: false
85
85
  version_requirements: !ruby/object:Gem::Requirement
@@ -89,7 +89,27 @@ dependencies:
89
89
  version: '1.3'
90
90
  - - ">="
91
91
  - !ruby/object:Gem::Version
92
- version: 1.3.1
92
+ version: 1.3.3
93
+ - !ruby/object:Gem::Dependency
94
+ name: json_config
95
+ requirement: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: '0.1'
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 0.1.1
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '0.1'
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: 0.1.1
93
113
  - !ruby/object:Gem::Dependency
94
114
  name: os
95
115
  requirement: !ruby/object:Gem::Requirement
@@ -139,7 +159,7 @@ dependencies:
139
159
  version: '0.1'
140
160
  - - ">="
141
161
  - !ruby/object:Gem::Version
142
- version: 0.1.1
162
+ version: 0.1.3
143
163
  type: :runtime
144
164
  prerelease: false
145
165
  version_requirements: !ruby/object:Gem::Requirement
@@ -149,7 +169,7 @@ dependencies:
149
169
  version: '0.1'
150
170
  - - ">="
151
171
  - !ruby/object:Gem::Version
152
- version: 0.1.1
172
+ version: 0.1.3
153
173
  description: Ruby KeePass 2.x implementation. Currently it is read-only.
154
174
  email: mjwhitta@gmail.com
155
175
  executables:
@@ -161,16 +181,18 @@ files:
161
181
  - lib/rubeepass.rb
162
182
  - lib/rubeepass/entry.rb
163
183
  - lib/rubeepass/error.rb
164
- - lib/rubeepass/error/invalid_gzip_error.rb
165
- - lib/rubeepass/error/invalid_header_error.rb
166
- - lib/rubeepass/error/invalid_magic_error.rb
167
- - lib/rubeepass/error/invalid_password_error.rb
168
- - lib/rubeepass/error/invalid_protected_data_error.rb
169
- - lib/rubeepass/error/invalid_protected_stream_key_error.rb
170
- - lib/rubeepass/error/invalid_version_error.rb
171
- - lib/rubeepass/error/invalid_xml_error.rb
172
- - lib/rubeepass/error/not_aes_error.rb
173
- - lib/rubeepass/error/not_salsa20_error.rb
184
+ - lib/rubeepass/error/file_not_found.rb
185
+ - lib/rubeepass/error/file_not_readable.rb
186
+ - lib/rubeepass/error/invalid_gzip.rb
187
+ - lib/rubeepass/error/invalid_header.rb
188
+ - lib/rubeepass/error/invalid_magic.rb
189
+ - lib/rubeepass/error/invalid_password.rb
190
+ - lib/rubeepass/error/invalid_protected_data.rb
191
+ - lib/rubeepass/error/invalid_protected_stream_key.rb
192
+ - lib/rubeepass/error/invalid_version.rb
193
+ - lib/rubeepass/error/invalid_xml.rb
194
+ - lib/rubeepass/error/not_aes.rb
195
+ - lib/rubeepass/error/not_salsa20.rb
174
196
  - lib/rubeepass/group.rb
175
197
  - lib/rubeepass/protected_decryptor.rb
176
198
  - lib/rubeepass/wish/cd_wish.rb