yak 1.0.3 → 1.0.4

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 (6) hide show
  1. data/History.txt +14 -0
  2. data/Manifest.txt +1 -0
  3. data/README.txt +12 -10
  4. data/lib/yak.rb +124 -25
  5. data/script/yak_completion +44 -0
  6. metadata +38 -38
data/History.txt CHANGED
@@ -1,3 +1,17 @@
1
+ === 1.0.4 / 2010-02-23
2
+
3
+ * Enhancemennts:
4
+
5
+ * Added support for bash completion
6
+
7
+ * Bugfixes:
8
+
9
+ * Fixed CipherError namespace change for different Ruby versions
10
+
11
+ * List option now only returns keys
12
+
13
+ * Rdoc README processing error fixed
14
+
1
15
  === 1.0.3 / 2010-02-22
2
16
 
3
17
  * Enhancements:
data/Manifest.txt CHANGED
@@ -1,5 +1,6 @@
1
1
  bin/yak
2
2
  lib/yak.rb
3
+ script/yak_completion
3
4
  History.txt
4
5
  Manifest.txt
5
6
  Rakefile
data/README.txt CHANGED
@@ -1,5 +1,7 @@
1
1
  = Yak
2
2
 
3
+ http://github.com/yaksnrainbows/yak
4
+
3
5
  == Description
4
6
 
5
7
  Yak is a simple command line app to store and retrieve passwords securely
@@ -13,17 +15,17 @@ Config can be set in ~/.yakrc.
13
15
 
14
16
  Session is the length of time in seconds that Yak will remember the
15
17
  master password:
16
- :session: 30
18
+ :session : 30
17
19
 
18
20
  If using sessions is not desired and you want to enter the
19
21
  master password every time, set:
20
- :session: false
22
+ :session : false
21
23
 
22
24
  Always set the password by default, use:
23
- :password: plain_text_password
25
+ :password : plain_text_password
24
26
 
25
27
  Turn off password confirmation prompts when a new password is entered:
26
- :confirm_prompt: false
28
+ :confirm_prompt : false
27
29
 
28
30
 
29
31
  == Usage
@@ -43,9 +45,9 @@ Retrieving a saved password:
43
45
  $ yak gmail
44
46
  # copies the gmail password to the clipboard
45
47
 
46
- $ yak --list gmail
47
- >> gmail: my_password
48
- # matches all password keys to /gmail/ and outputs to stdout
48
+ $ yak -p gmail
49
+ >> my_password
50
+ # outputs gmail password to stdout
49
51
 
50
52
  Removing a stored password:
51
53
  $ yak -r gmail
@@ -55,12 +57,12 @@ Changing the master password:
55
57
  $ yak -n
56
58
  # prompts for old password first, then the new password
57
59
 
58
- Listing key/password pairs:
60
+ Listing keys:
59
61
  $ yak --list
60
62
  # returns all saved pairs
61
63
 
62
64
  $ yak --list key
63
- # returns all saved pairs with a key matching /key/
65
+ # returns all keys matching /key/
64
66
 
65
67
  $ yak --list ^key$
66
- # returns unique saved pair with a key matching /^key$/
68
+ # returns unique key matching /^key$/
data/lib/yak.rb CHANGED
@@ -22,12 +22,20 @@ require 'session'
22
22
  # :confirm_prompt: false
23
23
  # To set the path to the yak data file:
24
24
  # :data_file: /path/to/file
25
+ # Using bash completion for stored keys:
26
+ # :bash_completion: true #=> completion only available during session
27
+ # :bash_completion: :always #=> completion always available
25
28
 
26
29
  class Yak
27
30
 
28
- VERSION = "1.0.3"
31
+ # Version of Yak.
32
+ VERSION = "1.0.4"
29
33
 
30
- DEFAULT_CONFIG = {:session => 30}
34
+ # Default config used.
35
+ DEFAULT_CONFIG = {:session => 30, :bash_completion => true}
36
+
37
+ # Different versions of ruby have a different namespace for CipherError
38
+ CIPHER_ERROR = OpenSSL::Cipher::CipherError rescue OpenSSL::CipherError
31
39
 
32
40
  ##
33
41
  # Run Yak with argv:
@@ -46,14 +54,14 @@ class Yak
46
54
 
47
55
  yak = new user, config
48
56
 
49
- yak.connect_data
50
57
  yak.start_session
58
+ yak.connect_data
51
59
 
52
60
  args = [options[:action], yak, options[:key], options[:value]].compact
53
61
 
54
62
  self.send(*args)
55
63
 
56
- rescue OpenSSL::Cipher::CipherError => e
64
+ rescue CIPHER_ERROR => e
57
65
  $stderr << "Bad password.\n"
58
66
  exit 1
59
67
  end
@@ -68,8 +76,42 @@ class Yak
68
76
  return if File.file? user_config_file
69
77
 
70
78
  hl = HighLine.new $stdin, $stderr
71
- hl.say "Thanks for installing Yak!"
79
+ hl.say "\n\nThanks for installing Yak!\n\n"
80
+
81
+ setup_bash_completion
82
+
83
+ data_file = prompt_data_loc user, hl
84
+
85
+ new_config = DEFAULT_CONFIG.merge(:data_file => data_file)
86
+
87
+ make_config_file user, new_config
88
+ end
89
+
90
+
91
+ ##
92
+ # Check and setup bash completion.
93
+
94
+ def self.setup_bash_completion
95
+ completion_dir = "/etc/bash_completion.d"
96
+
97
+ completion_file = File.join File.dirname(__FILE__),
98
+ "../script/yak_completion"
99
+ completion_file = File.expand_path completion_file
100
+
101
+ if File.directory? completion_dir
102
+ FileUtils.cp completion_file, File.join(completion_dir, ".")
103
+ else
104
+ $stderr << "\nError: Could not find directory #{completion_dir}\n"
105
+ $stderr << "If you would like to use yak's bash completion, "
106
+ $stderr << "make sure to source #{completion_file} in .bashrc\n\n"
107
+ end
108
+ end
109
+
72
110
 
111
+ ##
112
+ # Prompt the user for the location of the data file.
113
+
114
+ def self.prompt_data_loc user, hl
73
115
  data_file_opts = []
74
116
 
75
117
  usrhome = File.expand_path "~#{user}/"
@@ -86,10 +128,7 @@ class Yak
86
128
  end
87
129
  end
88
130
 
89
- data_file = File.join data_path, ".yakdata"
90
- new_config = DEFAULT_CONFIG.merge(:data_file => data_file)
91
-
92
- make_config_file user, new_config
131
+ File.join data_path, ".yakdata"
93
132
  end
94
133
 
95
134
 
@@ -112,46 +151,68 @@ class Yak
112
151
 
113
152
  File.open(user_config_file, "w+"){|f| f.write config_str }
114
153
  $stderr << "Created Yak config file #{user_config_file}:\n"
115
- $stderr << "#{config_str}\n"
154
+ $stderr << "#{config_str}---\n\n"
116
155
  end
117
156
 
118
157
 
158
+ ##
159
+ # Remove a key/value pair from a yak instance.
160
+
119
161
  def self.remove yak, name
120
162
  yak.remove name
121
163
  yak.write_data
122
164
  end
123
165
 
124
166
 
167
+ ##
168
+ # Add a key/value pair to a yak instance.
169
+
125
170
  def self.store yak, name, value=nil
126
171
  yak.store name, value
127
172
  yak.write_data
128
173
  end
129
174
 
130
175
 
176
+ ##
177
+ # Get a password value from a yak instance and copy it to the clipboard.
178
+
131
179
  def self.retrieve yak, name
132
180
  send_to_clipboard yak.retrieve(name)
133
181
  end
134
182
 
135
183
 
184
+ ##
185
+ # Get a password value from a yak instance and output it to the stdout.
186
+
136
187
  def self.print_password yak, name
137
188
  $stdout << "#{yak.retrieve(name)}\n"
138
189
  end
139
190
 
140
191
 
192
+ ##
193
+ # Delete the data file of a yak instance after confirming with the user.
194
+
141
195
  def self.delete_data yak
142
196
  yak.delete_data_file! true
143
197
  end
144
198
 
145
199
 
200
+ ##
201
+ # List matched keys of a yak instance.
202
+
146
203
  def self.list yak, name=nil
147
204
  key_regex = /#{name || ".+"}/
148
205
 
149
206
  yak.data.each do |key, value|
150
- $stdout << "#{key}: #{value}\n" if key =~ key_regex
207
+ $stdout << "#{key}\n" if key =~ key_regex
151
208
  end
152
209
  end
153
210
 
154
211
 
212
+ ##
213
+ # Assign a new master password to a yak instance.
214
+ # Prompts the user if no value is given.
215
+
155
216
  def self.new_password yak, value=nil
156
217
  yak.new_password value
157
218
  yak.write_data
@@ -159,30 +220,35 @@ class Yak
159
220
  end
160
221
 
161
222
 
223
+ ##
224
+ # Send the passed string to the keyboard.
225
+ # Only supports darwin (pbcopy), linux (xclip) and cygwin (putclip).
226
+
162
227
  def self.send_to_clipboard string
163
228
  copy_cmd = case RUBY_PLATFORM
164
- when /darwin/
165
- "echo -n \"#{string}\" | pbcopy"
166
- when /linux/
167
- "echo -n \"#{string}\" | xclip"
168
- when /cigwin/
169
- "echo -n \"#{string}\" | putclip"
170
- when /(win|mingw)/
171
- "echo \"#{string}\" | clip"
229
+ when /darwin/ then "pbcopy"
230
+ when /linux/ then "xclip"
231
+ when /cygwin/ then "putclip"
172
232
  else
173
233
  $stderr << "No clipboad cmd for platform #{RUBY_PLATFORM}\n"
174
234
  exit 1
175
235
  end
176
236
 
177
- Session::Bash.new.execute copy_cmd
237
+ Session::Bash.new.execute "echo -n \"#{string}\" | #{copy_cmd}"
178
238
  end
179
239
 
180
240
 
241
+ ##
242
+ # Get a user's yak config file. Typically ~user/.yakrc.
243
+
181
244
  def self.yak_config_file user
182
245
  File.expand_path "~#{user}/.yakrc"
183
246
  end
184
247
 
185
248
 
249
+ ##
250
+ # Parse ARGV data.
251
+
186
252
  def self.parse_args argv
187
253
  options = {}
188
254
 
@@ -192,7 +258,7 @@ class Yak
192
258
  opt.release = nil
193
259
 
194
260
  opt.banner = <<-EOF
195
- #{opt.program_name} is a simple app to store and retrieve passwords securely.
261
+ Yak is a simple app to store and retrieve passwords securely.
196
262
  Retrieved passwords get copied to the clipboard by default.
197
263
 
198
264
  Usage:
@@ -220,7 +286,7 @@ Retrieved passwords get copied to the clipboard by default.
220
286
  end
221
287
 
222
288
  opt.on('-l', '--list [REGEX]',
223
- 'List key/password pairs to the stdout') do |key|
289
+ 'List keys to the stdout') do |key|
224
290
  options[:action] = :list
225
291
  options[:key] = key
226
292
  end
@@ -257,7 +323,7 @@ Retrieved passwords get copied to the clipboard by default.
257
323
  end
258
324
 
259
325
 
260
- attr_reader :user, :data
326
+ attr_reader :user, :data, :use_completion
261
327
 
262
328
  ##
263
329
  # Create a new Yak instance for a given user:
@@ -280,6 +346,9 @@ Retrieved passwords get copied to the clipboard by default.
280
346
  @password_file = File.join @yak_dir, "password"
281
347
  @data_file = options[:data_file] || File.join(@yak_dir, "data")
282
348
 
349
+ @key_list_file = File.join @yak_dir, "keys"
350
+ @use_completion = options[:bash_completion]
351
+
283
352
  @session_pid = nil
284
353
  @session_pid = File.read(@pid_file).to_i if File.file? @pid_file
285
354
 
@@ -297,15 +366,17 @@ Retrieved passwords get copied to the clipboard by default.
297
366
  def start_session
298
367
  return unless @session_length
299
368
 
369
+ pswd = sha_password # Do stdio before writing to file!
370
+
300
371
  end_session if has_session?
301
372
 
302
373
  pid = fork do
303
374
  sleep @session_length
304
- FileUtils.rm_f [@password_file, @pid_file]
375
+ remove_session_files
305
376
  end
306
377
 
378
+ File.open(@password_file, "w+"){|f| f.write pswd }
307
379
  File.open(@pid_file, "w+"){|f| f.write pid }
308
- File.open(@password_file, "w+"){|f| f.write sha_password }
309
380
 
310
381
  Process.detach pid
311
382
  end
@@ -317,7 +388,16 @@ Retrieved passwords get copied to the clipboard by default.
317
388
  def end_session
318
389
  return unless @session_pid
319
390
  Process.kill 9, @session_pid rescue false
391
+ remove_session_files
392
+ end
393
+
394
+
395
+ ##
396
+ # Deletes files used during a session.
397
+
398
+ def remove_session_files
320
399
  FileUtils.rm_f [@password_file, @pid_file]
400
+ FileUtils.rm_f @key_list_file unless @use_completion == :always
321
401
  end
322
402
 
323
403
 
@@ -388,7 +468,11 @@ Retrieved passwords get copied to the clipboard by default.
388
468
  if data_file_exists?
389
469
  data = ""
390
470
  File.open(@data_file, "rb"){|f| data << f.read }
471
+
391
472
  @data = YAML.load decrypt(data)
473
+
474
+ write_key_list if @use_completion
475
+
392
476
  else
393
477
  @data = {}
394
478
  write_data
@@ -443,6 +527,16 @@ Retrieved passwords get copied to the clipboard by default.
443
527
  def write_data password=nil
444
528
  data = encrypt @data.to_yaml, password
445
529
  File.open(@data_file, "w+"){|f| f.write data}
530
+
531
+ write_key_list if @use_completion == :always
532
+ end
533
+
534
+
535
+ ##
536
+ # Write the key list file. Used for bash completion.
537
+
538
+ def write_key_list
539
+ File.open(@key_list_file, "w+"){|f| f.write @data.keys.join(" ") }
446
540
  end
447
541
 
448
542
 
@@ -478,6 +572,11 @@ Retrieved passwords get copied to the clipboard by default.
478
572
  end
479
573
 
480
574
 
575
+ ##
576
+ # Get the cypher output:
577
+ # get_cypher_out :encrypt, plain_string
578
+ # get_cypher_out :decrypt, encrypted_string
579
+
481
580
  def get_cypher_out method, string, password=nil
482
581
  password ||= sha_password
483
582
 
@@ -0,0 +1,44 @@
1
+ #!/bin/bash
2
+
3
+ _valid_yak_option()
4
+ {
5
+ local valid_prevs prevs_num curr_prev prev
6
+
7
+ prev="$1"
8
+
9
+ valid_prevs=( '-a' '--add' '-r' '--remove' '-l' '--list' '-p' '--print' 'yak' )
10
+ prevs_num=${#valid_prevs[@]}
11
+
12
+ for ((i=0;i<$prevs_num;i++)); do
13
+ curr_prev=${valid_prevs[${i}]}
14
+
15
+ if [ "$prev" == $curr_prev ]; then
16
+ echo "$prev"
17
+ return 0
18
+ fi
19
+ done
20
+
21
+ return 1
22
+ }
23
+
24
+ _yak()
25
+ {
26
+ local cur prev opts yak_keys
27
+ COMPREPLY=()
28
+ cur="${COMP_WORDS[COMP_CWORD]}"
29
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
30
+
31
+ yak_keys="$HOME/.yak/keys"
32
+
33
+
34
+ if [ -f "$yak_keys" ] && [ $(_valid_yak_option "$prev") ]; then
35
+ opts=$(cat $yak_keys)
36
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
37
+ return 0
38
+ fi
39
+
40
+ return 1
41
+ }
42
+
43
+ complete -F _yak yak
44
+
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yak
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 4
9
+ version: 1.0.4
5
10
  platform: ruby
6
11
  authors:
7
12
  - Jeremie Castagna
@@ -14,54 +19,46 @@ default_executable:
14
19
  dependencies:
15
20
  - !ruby/object:Gem::Dependency
16
21
  name: highline
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
20
24
  requirements:
21
25
  - - ">="
22
26
  - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 5
30
+ - 1
23
31
  version: 1.5.1
24
- version:
32
+ type: :runtime
33
+ version_requirements: *id001
25
34
  - !ruby/object:Gem::Dependency
26
35
  name: session
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
30
38
  requirements:
31
39
  - - ">="
32
40
  - !ruby/object:Gem::Version
41
+ segments:
42
+ - 2
43
+ - 4
44
+ - 0
33
45
  version: 2.4.0
34
- version:
35
- - !ruby/object:Gem::Dependency
36
- name: rubyforge
37
- type: :development
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- version: 2.0.3
44
- version:
45
- - !ruby/object:Gem::Dependency
46
- name: gemcutter
47
- type: :development
48
- version_requirement:
49
- version_requirements: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- version: 0.3.0
54
- version:
46
+ type: :runtime
47
+ version_requirements: *id002
55
48
  - !ruby/object:Gem::Dependency
56
49
  name: hoe
57
- type: :development
58
- version_requirement:
59
- version_requirements: !ruby/object:Gem::Requirement
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
60
52
  requirements:
61
53
  - - ">="
62
54
  - !ruby/object:Gem::Version
63
- version: 2.5.0
64
- version:
55
+ segments:
56
+ - 2
57
+ - 3
58
+ - 3
59
+ version: 2.3.3
60
+ type: :development
61
+ version_requirements: *id003
65
62
  description: |-
66
63
  Yak is a simple command line app to store and retrieve passwords securely
67
64
  under a master password, and allows one password repository per system user.
@@ -79,12 +76,13 @@ extra_rdoc_files:
79
76
  files:
80
77
  - bin/yak
81
78
  - lib/yak.rb
79
+ - script/yak_completion
82
80
  - History.txt
83
81
  - Manifest.txt
84
82
  - Rakefile
85
83
  - README.txt
86
84
  has_rdoc: true
87
- homepage:
85
+ homepage: http://github.com/yaksnrainbows/yak
88
86
  licenses: []
89
87
 
90
88
  post_install_message:
@@ -97,18 +95,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
97
95
  requirements:
98
96
  - - ">="
99
97
  - !ruby/object:Gem::Version
98
+ segments:
99
+ - 0
100
100
  version: "0"
101
- version:
102
101
  required_rubygems_version: !ruby/object:Gem::Requirement
103
102
  requirements:
104
103
  - - ">="
105
104
  - !ruby/object:Gem::Version
105
+ segments:
106
+ - 0
106
107
  version: "0"
107
- version:
108
108
  requirements: []
109
109
 
110
110
  rubyforge_project: yak
111
- rubygems_version: 1.3.5
111
+ rubygems_version: 1.3.6
112
112
  signing_key:
113
113
  specification_version: 3
114
114
  summary: Yak is a simple command line app to store and retrieve passwords securely under a master password, and allows one password repository per system user