pws 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -19,9 +19,20 @@ Originally based on [this tutorial](http://rbjl.net/41-tutorial-build-your-own-p
19
19
 
20
20
  Cucumber specs loosely based on [the ones](https://github.com/thecatwasnot/passwordsafe/blob/master/features/) by thecatwasnot - thanks
21
21
 
22
+ Features coming in 1.0
23
+ ---
24
+ Around March or April 2012
25
+
26
+ * Significantly improved crypto methods
27
+ * Tests for the crypto stuff
28
+ * Different storage format, but will be backwards compatible
29
+ * Little UI tweaks
30
+
22
31
  Contributions by
23
32
  ---
24
33
  * [brianewing](https://github.com/brianewing/)
34
+ * [dquimper](https://github.com/dquimper/)
35
+ * [grapz](https://github.com/grapz/)
25
36
 
26
37
  Copyright
27
38
  ---
data/Rakefile CHANGED
@@ -28,8 +28,10 @@ task :gemspec do
28
28
  gemspec.validate
29
29
  end
30
30
 
31
- require 'cucumber/rake/task'
32
- Cucumber::Rake::Task.new(:spec)
31
+ desc 'Run cucumber and rspec specs'
32
+ task :spec do
33
+ sh %[rspec spec] and sh %[cucumber features]
34
+ end
33
35
 
34
36
  task :default => :spec
35
37
  task :test => :spec
data/bin/pws CHANGED
@@ -1,89 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require_relative '../lib/pws'
4
-
5
- action_or_namespace = $*.shift
6
-
7
- if action_or_namespace =~ /^-.*$/
8
- @action = $*.shift
9
- @namespace = $& unless $& == ?-
10
- else
11
- @action = action_or_namespace
12
- @namespace = nil
13
- end
14
-
15
- @action = @action ? @action.to_sym : :show
16
- @args = [*$*]
17
-
18
- begin
19
- case @action
20
- when :v, :version
21
- puts "pws #{PWS::VERSION} by " + Paint["J-_-L", :bold] + " <https://github.com/janlelis/pws>"
22
- when :help, :actions, :commands
23
- puts \
24
- <<HELP
25
-
26
- #{Paint["Usage", :underline]}
27
-
28
- #{Paint['pws', :bold]} [-namespace] action [arguments]
29
-
30
- #{Paint["Info", :underline]}
31
-
32
- pws allows you to manage passwords in encryted password files (safes). It
33
- operates on the file specified in the environment variable PWS or on "~/.pws".
34
- You can apply a namespace as first parameter that will be appended to the
35
- filename, e.g. `pws -work show` with usual env would use "~/.pws-work".
36
-
37
- #{Paint["Available actions", :underline]}
38
-
39
- #{Paint['ls', :bold]} / list / show / status
40
- Lists all available password entries.
41
-
42
- #{Paint['add', :bold]} / set / store / create ( name, password = nil )
43
- Stores a new password entry. The second argument can be the password, but
44
- it's recommended to not pass it, but enter it interactively.
45
-
46
- #{Paint['get', :bold]} / entry / copy / password / for ( name, seconds = 10 )
47
- Copies the password for <name> to the clipboard. The second argument specifies,
48
- how long the password is kept in the clipboard (0 = no deletion).
49
-
50
- #{Paint['gen', :bold]} / generate ( name, seconds = 10, length = 64, char_pool )
51
- Generates a new password for <name> and then copies it to the clipboard, like
52
- get (the second argument is the time - it gets passed to get). The third
53
- argument sets the password length. The fourth argument allows you to pass a
54
- character pool that is used for generating the passwords.
55
-
56
- #{Paint['rm', :bold]} / remove / del / delete ( name )
57
- Removes a password entry.
58
-
59
- #{Paint['mv', :bold]} / move / rename ( old_name, new_name )
60
- Renames a password entry.
61
-
62
- #{Paint['master', :bold]} ( password = nil )
63
- Changes the master password.
64
-
65
- #{Paint['v', :bold]} / version
66
- Displays version and website.
67
-
68
- #{Paint['help', :bold]} / actions / commands
69
- Displays this help.
70
-
71
- HELP
72
- else # redirect to safe
73
- if PWS.public_instance_methods(false).include?(@action)
74
- PWS.new(nil, @namespace).send @action, *@args
75
- else
76
- pa "Unknown action: #@action\nPlease see `pws help` for a list of available commands!", :red
77
- end
78
- end
79
- rescue PWS::NoAccess
80
- # pa $!.message.capitalize, :red, :bold
81
- pa "NO ACCESS", :red, :bold
82
- rescue ArgumentError
83
- pa $!.message.capitalize, :red
84
- rescue Interrupt
85
- system 'stty echo' if $stdin.tty? # ensure terminal's working
86
- pa "..canceled", :red
87
- end
3
+ require_relative '../lib/pws/runner'
4
+ PWS::Runner.run(*PWS::Runner.parse_cli_arguments)
88
5
 
89
6
  # J-_-L
@@ -21,7 +21,18 @@ Feature: Generate
21
21
  Then the output should contain "Master password:"
22
22
  And the output should contain "The password for github has been added"
23
23
  And the output should contain "The password for github is now available in your clipboard for 1 second"
24
-
24
+
25
+ @wait-11s
26
+ @slow-hack
27
+ Scenario: Generate a new password for "github", PWS_SECONDS set to 5, gets passed to the get as keep-in-clipboard time
28
+ Given A safe exists with master password "my_master_password"
29
+ When I set env variable "PWS_SECONDS" to "5"
30
+ And I run `pws generate github` interactively
31
+ And I type "my_master_password"
32
+ Then the output should contain "Master password:"
33
+ And the output should contain "The password for github has been added"
34
+ And the output should contain "The password for github is now available in your clipboard for 5 seconds"
35
+
25
36
  @slow-hack
26
37
  Scenario: Generate a new password for "github", third parameter defines password length
27
38
  Given A safe exists with master password "my_master_password"
@@ -42,6 +53,17 @@ Feature: Generate
42
53
  And the output should contain "The password for github has been copied to your clipboard"
43
54
  And the clipboard should match /^.{64}$/
44
55
 
56
+ @slow-hack
57
+ Scenario: Generate a new password for "github", default length of PWS_GEN_LENGTH
58
+ Given A safe exists with master password "my_master_password"
59
+ When I set env variable "PWS_LENGTH" to "15"
60
+ And I run `pws generate github 0` interactively
61
+ And I type "my_master_password"
62
+ Then the output should contain "Master password:"
63
+ And the output should contain "The password for github has been added"
64
+ And the output should contain "The password for github has been copied to your clipboard"
65
+ And the clipboard should match /^.{15}$/
66
+
45
67
  @slow-hack
46
68
  Scenario: Generate a new password for "github", fourth parameter defines a char pool used for generation
47
69
  Given A safe exists with master password "my_master_password"
@@ -62,4 +84,15 @@ Feature: Generate
62
84
  And the output should contain "The password for github has been copied to your clipboard"
63
85
  And the clipboard should match ^[!\"\#$%&'()*+,\-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\[\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~]+$
64
86
 
65
-
87
+ @slow-hack
88
+ Scenario: Generate a new password for "github", the default char pool PWS_GEN_CHARPOOL
89
+ Given A safe exists with master password "my_master_password"
90
+ When I set env variable "PWS_CHARPOOL" to "a"
91
+ When I run `pws generate github 0` interactively
92
+ And I type "my_master_password"
93
+ Then the output should contain "Master password:"
94
+ And the output should contain "The password for github has been added"
95
+ And the output should contain "The password for github has been copied to your clipboard"
96
+ And the clipboard should match ^a{64}$
97
+
98
+
@@ -25,7 +25,16 @@ Feature: Get
25
25
  And I type "my_master_password"
26
26
  Then the output should contain "Master password:"
27
27
  And the output should contain "The password for github is now available in your clipboard for 1 second"
28
-
28
+
29
+ @wait-11s
30
+ Scenario: Get the password for "github" (which exists) and keep it in the clipboard for 5 seconds when PWS_SECONDS is set to 5
31
+ Given A safe exists with master password "my_master_password" and a key "github" with password "github_password"
32
+ When I set env variable "PWS_SECONDS" to "5"
33
+ And I run `pws get github` interactively
34
+ And I type "my_master_password"
35
+ Then the output should contain "Master password:"
36
+ And the output should contain "The password for github is now available in your clipboard for 5 seconds"
37
+
29
38
  Scenario: Get the password for "github" (which exists) and ensure that the original clipboard content gets restored
30
39
  Given A safe exists with master password "my_master_password" and a key "github" with password "github_password"
31
40
  Given A clipboard content of "blubb"
@@ -15,6 +15,26 @@ Feature: Show
15
15
  And the output should contain "password"
16
16
  And the output should contain "entries"
17
17
 
18
+ Scenario: Show the list and filter for regex
19
+ Given A safe exists with master password "my_master_password" and keys
20
+ | some-abc | 123 |
21
+ | password-aDc! | 345 |
22
+ | entries | 678 |
23
+ When I run `pws show a.c` interactively
24
+ And I type "my_master_password"
25
+ Then the output should contain "Entries"
26
+ And the output should contain "some-abc"
27
+ And the output should contain "password-aDc!"
28
+
29
+ Scenario: Show the list and filter for regex, but regex is invalid
30
+ Given A safe exists with master password "my_master_password" and keys
31
+ | some-abc | 123 |
32
+ | password-aDc! | 345 |
33
+ | entries | 678 |
34
+ When I run `pws show "(("` interactively
35
+ And I type "my_master_password"
36
+ Then the output should contain "Invalid regex"
37
+
18
38
  Scenario: Show the list (but there is no entry yet)
19
39
  Given A safe exists with master password "my_master_password"
20
40
  When I run `pws show` interactively
@@ -1,6 +1,7 @@
1
1
  def create_safe(master, key_hash = {})
2
+ ENV["PWS_CHARPOOL"] = ENV["PWS_LENGTH"] = ENV["PWS_SECONDS"] = nil
2
3
  restore, $stdout = $stdout, StringIO.new # tmp silence $stdout
3
- pws = PWS.new ENV["PWS"], nil, master
4
+ pws = PWS.new(password: master)
4
5
  key_hash.each{ |key, password|
5
6
  pws.add key, password
6
7
  }
@@ -34,3 +35,7 @@ end
34
35
  Then /^the clipboard should match ([^\/].+)$/ do |expected|
35
36
  assert_matching_output(expected, Clipboard.paste)
36
37
  end
38
+
39
+ When /^I set env variable "(\w+)" to "([^"]*)"$/ do |var, value|
40
+ ENV[var] = value
41
+ end
@@ -21,7 +21,7 @@ END{
21
21
  }
22
22
 
23
23
  Around do |_, block|
24
- # NOTE: You cannot parallelize the tests, because they use the clipboard and the env var...
24
+ # NOTE: You cannot parallelize the tests, because they use the clipboard and the env vars...
25
25
  Clipboard.clear
26
26
  ENV["PWS"] = File.expand_path('pws-test-' + SecureRandom.uuid)
27
27
 
data/lib/pws.rb CHANGED
@@ -10,36 +10,56 @@ require 'paint/pa'
10
10
  class PWS
11
11
  class NoAccess < StandardError; end
12
12
 
13
+ attr_reader :filename, :options
14
+
13
15
  # Creates a new password safe. Takes the path to the password file, by default: ~/.pws
14
16
  # Second parameter allows namespaces that get appended to the file name (uses another safe)
15
17
  # You can pass the master password as third parameter (not recommended)
16
- def initialize(filename = nil, namespace = nil, password = nil)
17
- @pw_file = File.expand_path(filename || ENV["PWS"] || '~/.pws')
18
- @pw_file << namespace if namespace
19
- access_safe(password)
18
+ def initialize(options)
19
+ collect_options(options)
20
+ @filename = File.expand_path(@options[:filename])
21
+ @filename << '-' << @options[:namespace] if @options[:namespace]
22
+
23
+ access_safe(options[:password])
20
24
  read_safe
21
25
  end
22
26
 
27
+ def collect_options(options = {})
28
+ @options = options
29
+ @options[:filename] ||= ENV["PWS"] || '~/.pws'
30
+ @options[:seconds] ||= ENV['PWS_SECONDS'] || 10
31
+ @options[:length] ||= ENV['PWS_LENGTH'] || 64
32
+ @options[:charpool] ||= ENV['PWS_CHARPOOL'] || (33..126).map(&:chr).join
33
+ end
34
+
23
35
  # Shows a password entry list
24
- def show
25
- if @pw_data.empty?
26
- pa %[There aren't any passwords stored at #{@pw_file}, yet], :red
36
+ def show(pattern = nil)
37
+ if @data.empty?
38
+ pa %[There aren't any passwords stored at #{@filename}, yet], :red
27
39
  else
28
- puts Paint["Entries", :underline] + %[ in ] + @pw_file
29
- puts @pw_data.keys.sort.map{ |key| %[- #{key}\n] }.join
40
+ if pattern
41
+ keys = @data.keys.grep /#{pattern}/
42
+ else
43
+ keys = @data.keys
44
+ end
45
+ puts Paint["Entries", :underline] + %[ in ] + @filename
46
+ puts keys.sort.map{ |key| %[- #{key}\n] }.join
30
47
  end
31
48
  return true
49
+ rescue RegexpError
50
+ pa %[Invalid regex given], :red
51
+ return false
32
52
  end
33
53
  aliases_for :show, :ls, :list, :status
34
54
 
35
55
  # Add a password entry, params: name, password (optional, opens prompt if not given)
36
56
  def add(key, password = nil)
37
- if @pw_data[key]
57
+ if @data[key]
38
58
  pa %[There is already a password stored for #{key}. You need to remove it before creating a new one!], :red
39
59
  return false
40
60
  else
41
- @pw_data[key] = password || ask_for_password(%[please enter a password for #{key}], :yellow)
42
- if @pw_data[key].empty?
61
+ @data[key] = password || ask_for_password(%[please enter a password for #{key}], :yellow)
62
+ if @data[key].empty?
43
63
  pa %[Cannot add an empty password!], :red
44
64
  return false
45
65
  else
@@ -49,11 +69,11 @@ class PWS
49
69
  end
50
70
  end
51
71
  end
52
- aliases_for :add, :set, :store, :create, :[]= # using zucker/alias_for
72
+ aliases_for :add, :set, :store, :create, :[]=
53
73
 
54
74
  # Gets the password entry and copies it to the clipboard. The second parameter is the time in seconds it stays there
55
- def get(key, seconds = 10)
56
- if pw_plaintext = @pw_data[key]
75
+ def get(key, seconds = @options[:seconds])
76
+ if pw_plaintext = @data[key]
57
77
  if seconds && seconds.to_i > 0
58
78
  original_clipboard_content = Clipboard.paste
59
79
  Clipboard.copy pw_plaintext
@@ -81,13 +101,13 @@ class PWS
81
101
  # Adds a password entry with a freshly generated random password
82
102
  def generate(
83
103
  key,
84
- seconds = 10,
85
- length = 64,
86
- char_pool = (32..126).map(&:chr).join.gsub(/\s/, '')
104
+ seconds = @options[:seconds],
105
+ length = @options[:length],
106
+ charpool = @options[:charpool]
87
107
  )
88
- char_pool_size = char_pool.size
108
+ charpool_size = charpool.size
89
109
  new_pw = (1..length.to_i).map{
90
- char_pool[SecureRandom.random_number(char_pool_size)]
110
+ charpool[SecureRandom.random_number(charpool_size)]
91
111
  }.join
92
112
 
93
113
  if add(key, new_pw)
@@ -98,7 +118,7 @@ class PWS
98
118
 
99
119
  # Removes a specific password entry
100
120
  def remove(key)
101
- if @pw_data.delete key
121
+ if @data.delete key
102
122
  write_safe
103
123
  pa %[The password for #{key} has been removed], :green
104
124
  return true
@@ -111,14 +131,14 @@ class PWS
111
131
 
112
132
  # Removes a specific password entry
113
133
  def rename(old_key, new_key)
114
- if !@pw_data[old_key]
134
+ if !@data[old_key]
115
135
  pa %[No password found for #{old_key}!], :red
116
136
  return false
117
- elsif @pw_data[new_key]
137
+ elsif @data[new_key]
118
138
  pa %[There is already a password stored for #{new_key}. You need to remove it before naming another one #{new_key}!], :red
119
139
  return false
120
140
  else
121
- @pw_data[new_key] = @pw_data.delete(old_key)
141
+ @data[new_key] = @data.delete(old_key)
122
142
  write_safe
123
143
  pa %[The password entry #{old_key} has been renamed to #{new_key}], :green
124
144
  return true
@@ -136,7 +156,7 @@ class PWS
136
156
  return false
137
157
  end
138
158
  end
139
- @pw_hash = Encryptor.hash(password)
159
+ @hash = Encryptor.hash(password)
140
160
  write_safe
141
161
  pa %[The master password has been changed], :green
142
162
  return true
@@ -152,35 +172,40 @@ class PWS
152
172
 
153
173
  # Tries to load and decrypt the password safe from the pwfile
154
174
  def read_safe
155
- pwdata_raw = File.read(@pw_file)
175
+ pwdata_raw = File.read(@filename)
156
176
  pwdata_encrypted = pwdata_raw.force_encoding("ascii")
157
- pwdata_dump = Encryptor.decrypt(pwdata_encrypted, @pw_hash)
177
+ pwdata_dump = Encryptor.decrypt(pwdata_encrypted, @hash)
158
178
  pwdata_with_redundancy = Marshal.load(pwdata_dump)
159
- @pw_data = remove_redundancy(pwdata_with_redundancy)
179
+ @data = remove_redundancy(pwdata_with_redundancy)
160
180
  pa %[ACCESS GRANTED], :green
161
181
  rescue
162
182
  fail NoAccess, %[Could not load and decrypt the password safe!]
163
183
  end
164
184
 
165
185
  # Tries to encrypt and save the password safe into the pwfile
166
- def write_safe
167
- pwdata_with_redundancy = add_redundancy(@pw_data || {})
186
+ def write_safe(new_safe = false)
187
+ pwdata_with_redundancy = add_redundancy(@data || {})
168
188
  pwdata_dump = Marshal.dump(pwdata_with_redundancy)
169
- pwdata_encrypted = Encryptor.encrypt(pwdata_dump, @pw_hash)
170
- File.open(@pw_file, 'w'){ |f| f.write(pwdata_encrypted) }
189
+ pwdata_encrypted = Encryptor.encrypt(pwdata_dump, @hash)
190
+ if new_safe
191
+ FileUtils.mkdir_p(File.dirname(@filename))
192
+ FileUtils.touch(@filename)
193
+ File.chmod(0600, @filename)
194
+ end
195
+ File.open(@filename, 'w'){ |f| f.write(pwdata_encrypted) }
171
196
  rescue
172
197
  fail NoAccess, %[Could not encrypt and save the password safe!]
173
198
  end
174
199
 
175
200
  # Checks if the file is accessible or create a new one
176
201
  def access_safe(password = nil)
177
- if !File.file? @pw_file
178
- pa %[No password safe detected, creating one at #@pw_file], :blue, :bold
179
- @pw_hash = Encryptor.hash password || ask_for_password(%[please enter a new master password], :yellow, :bold)
180
- write_safe
202
+ if !File.file? @filename
203
+ pa %[No password safe detected, creating one at #@filename], :blue, :bold
204
+ @hash = Encryptor.hash password || ask_for_password(%[please enter a new master password], :yellow, :bold)
205
+ write_safe(true)
181
206
  else
182
- print %[Access password safe at #@pw_file | ]
183
- @pw_hash = Encryptor.hash password || ask_for_password(%[master password])
207
+ print %[Access password safe at #@filename | ]
208
+ @hash = Encryptor.hash password || ask_for_password(%[master password])
184
209
  end
185
210
  end
186
211
 
@@ -0,0 +1,111 @@
1
+ require_relative '../pws'
2
+
3
+ module PWS::Runner
4
+ class << self
5
+ # some simple option parsing
6
+ # returns action, arguments, options
7
+ # only accepts options with value as next arg, except breaking special cases
8
+ def parse_cli_arguments(argv = $*.dup)
9
+ action = nil
10
+ options = {}
11
+ arguments = []
12
+ argv.unshift(nil) # easier parsing
13
+
14
+ argv.each_cons(2){ |prev_arg, arg|
15
+ case arg
16
+ when '-'
17
+ # ignore
18
+ when /^--(help|version)$/
19
+ return [$1.to_sym, [], {}]
20
+ when /^--/
21
+ # parse option in next iteration
22
+ when /^-([^-].*)$/
23
+ options[:namespace] = $1
24
+ else
25
+ if prev_arg =~ /^--(.+)$/
26
+ options[$1.to_sym] = arg
27
+ elsif !action
28
+ action = arg.to_sym
29
+ else
30
+ arguments << arg
31
+ end
32
+ end
33
+ }
34
+
35
+ [action || :show, arguments, options]
36
+ end
37
+
38
+ # makes the Ruby safe more usable
39
+ def run(action, arguments, options)
40
+ case action
41
+ when :v, :version
42
+ puts "pws #{PWS::VERSION} by " + Paint["J-_-L", :bold] + " <https://github.com/janlelis/pws>"
43
+ when :help, :actions, :commands
44
+ puts(<<HELP)
45
+
46
+ #{Paint["Usage", :underline]}
47
+
48
+ #{Paint['pws', :bold]} [-namespace] action [arguments]
49
+
50
+ #{Paint["Info", :underline]}
51
+
52
+ pws allows you to manage passwords in encryted password files (safes). It
53
+ operates on the file specified in the environment variable PWS or on "~/.pws".
54
+ You can apply a namespace as first parameter that will be appended to the
55
+ filename, e.g. `pws -work show` with usual env would use "~/.pws-work".
56
+
57
+ #{Paint["Available actions", :underline]}
58
+
59
+ #{Paint['ls', :bold]} / list / show / status ( pattern = nil )
60
+ Lists all available password entries. Optionally takes a regex filter.
61
+
62
+ #{Paint['add', :bold]} / set / store / create ( name, password = nil )
63
+ Stores a new password entry. The second argument can be the password, but
64
+ it's recommended to not pass it, but enter it interactively.
65
+
66
+ #{Paint['get', :bold]} / entry / copy / password / for ( name, seconds = 10 )
67
+ Copies the password for <name> to the clipboard. The second argument specifies,
68
+ how long the password is kept in the clipboard (0 = no deletion).
69
+
70
+ #{Paint['gen', :bold]} / generate ( name, seconds = 10, length = 64, char_pool )
71
+ Generates a new password for <name> and then copies it to the clipboard, like
72
+ get (the second argument is the time - it gets passed to get). The third
73
+ argument sets the password length. The fourth argument allows you to pass a
74
+ character pool that is used for generating the passwords.
75
+
76
+ #{Paint['rm', :bold]} / remove / del / delete ( name )
77
+ Removes a password entry.
78
+
79
+ #{Paint['mv', :bold]} / move / rename ( old_name, new_name )
80
+ Renames a password entry.
81
+
82
+ #{Paint['master', :bold]} ( password = nil )
83
+ Changes the master password.
84
+
85
+ #{Paint['v', :bold]} / version
86
+ Displays version and website.
87
+
88
+ #{Paint['help', :bold]} / actions / commands
89
+ Displays this help.
90
+
91
+ HELP
92
+ else # redirect to safe
93
+ if PWS.public_instance_methods(false).include?(action)
94
+ PWS.new(options).public_send(action, *arguments)
95
+ else
96
+ pa "Unknown action: #{action}\nPlease see `pws --help` for a list of available commands!", :red
97
+ end
98
+ end
99
+ rescue PWS::NoAccess
100
+ # pa $!.message.capitalize, :red, :bold
101
+ pa "NO ACCESS", :red, :bold
102
+ rescue ArgumentError
103
+ pa $!.message.capitalize, :red
104
+ rescue Interrupt
105
+ system 'stty echo' if $stdin.tty? # ensure terminal's working
106
+ pa "..canceled", :red
107
+ end
108
+ end
109
+ end
110
+
111
+ # J-_-L
@@ -1,3 +1,3 @@
1
1
  class PWS
2
- VERSION = '0.9.1'
2
+ VERSION = '0.9.2'.dup
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pws
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.9.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-24 00:00:00.000000000 Z
12
+ date: 2012-04-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: clipboard
16
- requirement: &13917980 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: 1.0.1
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *13917980
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 1.0.1
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: zucker
27
- requirement: &13916940 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: '12.1'
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *13916940
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '12.1'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: paint
38
- requirement: &13887320 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: 0.8.4
44
54
  type: :runtime
45
55
  prerelease: false
46
- version_requirements: *13887320
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.8.4
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: rake
49
- requirement: &13886440 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
@@ -54,10 +69,15 @@ dependencies:
54
69
  version: '0'
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *13886440
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: cucumber
60
- requirement: &13885760 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
61
81
  none: false
62
82
  requirements:
63
83
  - - ! '>='
@@ -65,10 +85,15 @@ dependencies:
65
85
  version: '0'
66
86
  type: :development
67
87
  prerelease: false
68
- version_requirements: *13885760
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
69
94
  - !ruby/object:Gem::Dependency
70
95
  name: aruba
71
- requirement: &13885120 !ruby/object:Gem::Requirement
96
+ requirement: !ruby/object:Gem::Requirement
72
97
  none: false
73
98
  requirements:
74
99
  - - ! '>='
@@ -76,7 +101,12 @@ dependencies:
76
101
  version: '0'
77
102
  type: :development
78
103
  prerelease: false
79
- version_requirements: *13885120
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
80
110
  description: pws is a command-line password safe. Please run `pws help` for usage
81
111
  information.
82
112
  email: mail@janlelis.de
@@ -87,22 +117,23 @@ extra_rdoc_files:
87
117
  - README.md
88
118
  - LICENSE
89
119
  files:
90
- - lib/pws/encryptor.rb
91
120
  - lib/pws/version.rb
121
+ - lib/pws/encryptor.rb
122
+ - lib/pws/runner.rb
92
123
  - lib/pws.rb
93
124
  - bin/pws
94
- - features/step_definitions/pws_steps.rb
95
- - features/remove.feature
96
- - features/namespaces.feature
97
- - features/generate.feature
98
- - features/rename.feature
99
125
  - features/show.feature
100
- - features/add.feature
101
126
  - features/access.feature
102
- - features/master.feature
127
+ - features/misc.feature
103
128
  - features/get.feature
129
+ - features/master.feature
130
+ - features/remove.feature
131
+ - features/namespaces.feature
132
+ - features/add.feature
104
133
  - features/support/env.rb
105
- - features/misc.feature
134
+ - features/rename.feature
135
+ - features/generate.feature
136
+ - features/step_definitions/pws_steps.rb
106
137
  - Rakefile
107
138
  - pws.gemspec
108
139
  - README.md
@@ -130,7 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
130
161
  version: '0'
131
162
  requirements: []
132
163
  rubyforge_project:
133
- rubygems_version: 1.8.11
164
+ rubygems_version: 1.8.23
134
165
  signing_key:
135
166
  specification_version: 3
136
167
  summary: pws is a cli password safe.