Module: PWS::Runner

Defined in:
lib/pws/runner.rb

Constant Summary collapse

SINGLE_OPTIONS =
Regexp.union *%w[
  cwd
].freeze

Class Method Summary collapse

Class Method Details

.parse_cli_arguments(argv = $*.dup) ⇒ Object

some simple option parsing returns action, arguments, options only accepts options with value as next arg, except breaking special cases



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/pws/runner.rb', line 12

def parse_cli_arguments(argv = $*.dup)
  action    = nil
  options   = {}
  arguments = []
  argv.unshift(nil) # easier parsing
  
  argv.each_cons(2){ |prev_arg, arg|
    case arg
    when '-'
      # ignore
    when /^--(help|version)$/
      return [$1.to_sym, [], {}]
    when /^--(#{SINGLE_OPTIONS})/ # special single options
      options[$1.to_sym] = true
    when /^--/
      # parse option in next iteration
    when /^-([^-].*)$/
      options[:namespace] = $1
    else
      if prev_arg =~ /^--(.+)$/ && SINGLE_OPTIONS !~ opt = $1
        options[opt.to_sym] = arg
      elsif !action
        action = arg.to_sym
      else
        arguments << arg
      end
    end
  }
  
  [action || :show, arguments, options]
end

.run(action, arguments, options) ⇒ Object

makes the Ruby safe usable from the cli



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/pws/runner.rb', line 45

def run(action, arguments, options)
  case action
  when :v, :version
    puts "pws #{PWS::VERSION} by " + Paint["J-_-L", :bold] + " <https://github.com/janlelis/pws>"
  when :help, :actions, :commands
    puts(<<HELP)
  
  #{Paint["Usage", :underline]}
  
  #{Paint['pws', :bold]} [-namespace] action [arguments] [--options]
  
  #{Paint["Info", :underline]}
  
  pws allows you to manage passwords in encryted password files (safes). It
  operates on the file specified in the environment variable PWS or on "~/.pws".
  Using a single dash, you can set a namespace that will be appended to the
  filename, e.g. `pws -work show` will operate on "~/.pws-work".
  
  #{Paint["Available Actions", :underline]}
  
  #{Paint['ls', :bold]} / list / show / status ( pattern = nil )
  Lists all available password entries. Optionally takes a regex filter.
  
  #{Paint['get', :bold]} / entry / copy / password / for ( name, seconds = 10 )
  Copies the password for <name> to the clipboard. The second argument specifies,
  how long the password is kept in the clipboard (0 = no deletion).
  Please keep in mind that other programs can access (and log) the contents
  of your clipboard.

  #{Paint['ps', :bold]} / print-screen ( name, seconds = 10 )
  Displays the password on stdout. The second argument specifies,
  how long the password is shown (0 = no deletion).
  Please keep in mind that the password will appear in your shell's logfile,
  for example, in "~/.bash_history"

  #{Paint['add', :bold]} / set / store / create ( name, password = nil )
  Stores a new password entry. The second argument can be the password, but
  it's recommended to not pass it, but enter it interactively.
  
  #{Paint['gen', :bold]} / generate ( name, seconds = 10, length = 64, char_pool )
  Generates a new password for <name> and then copies it to the clipboard, like
  get (the second argument is the time - it gets passed to get). The third
  argument sets the password length. The fourth argument allows you to pass a
  character pool that is used for generating the passwords.
  
  #{Paint['update', :bold]} / update-add ( name, password = nil )
  Updates an existing password entry.
  
  #{Paint['update-gen', :bold]} / update-generate( name, seconds = 10, length = 64, char_pool )
  Updates an existing password entry using the generate method.
  
  #{Paint['rm', :bold]} / remove / del / delete ( name )
  Removes a password entry.
  
  #{Paint['mv', :bold]} / move / rename ( old_name, new_name )
  Renames a password entry.
  
  #{Paint['master', :bold]} ( password = nil )
  Changes the master password.
  
  #{Paint['resave', :bold]} / convert
  Just save the safe. Useful for converting the file format.
  
  #{Paint['v', :bold]} / version
  Displays version and website.
  
  #{Paint['help', :bold]} / actions / commands
  Displays this help.

  #{Paint["Available Options", :underline]}
  
  #{Paint['--in', :bold]}
  Specifies the password file input format. Neccessary to convert 0.9 safes.
  Supported values: 0.9 1.0
  
  #{Paint['--out', :bold]}
  Specifies the password file output format. Ignored for non-writing actions,
  e.g. get. Defaults to the current version.
  Supported values: 1.0
  
  #{Paint['--filename', :bold]}
  Path to the password safe to use. Overrides usual path and any namespaces.
  
  #{Paint['--cwd', :bold]}
  Use a .pws file in the current directory instead of the one specified in
  ENV['PWS'] or with --filename.
  
  #{Paint['--iterations', :bold]}
  Sets the number of sha iterations used to transform your password into the
  encryption key (pbkdf2). A higher number takes longer to compute, but makes
  it harder for attacker to bruteforce your password.
  
  #{Paint['--seconds', :bold]}, #{Paint['--length', :bold]}, #{Paint['--charpool', :bold]}, #{Paint['--exclude', :bold]}
  Preset options for specific actions.
  
  #{Paint["ENV Variables", :underline]}
  
  You can use environment variables to customize the default settings of pws.
  Except for PWS (info at top), the following variables can be used:
  
  PWS_SECONDS
  PWS_LENGTH
  PWS_CHARPOOL
  PWS_ITERATIONS

HELP
  else # redirect to safe
    if PWS.public_instance_methods(false).include?(action)
      status = PWS.new(options).public_send(action, *arguments.map{ |a|
        a.unpack('a*')[0] # ignore encoding
      })
      exit(status ? 0 : 2)
    else
      raise ArgumentError, "Unknown action: #{action}\nPlease see `pws --help` for a list of available commands!"
    end
  end
rescue PWS::NoLegacyAccess
  pa "NO ACCESS", :red, :bold
  pa 'The password safe you are trying to access migth be a version 0.9 password file', :red
  pa 'If this is the case, you will need to convert it to a version 1.0 password file by calling:', :red
  pa 'pws resave --in 0.9 --out 1.0', :red
  exit(3)
rescue PWS::NoAccess
  # pa $!.message.capitalize, :red, :bold
  pa "NO ACCESS", :red, :bold
  exit(3)
rescue ArgumentError
  pa $!.message.capitalize, :red
  exit(4)
rescue Interrupt
  system 'stty echo' if $stdin.tty? # ensure terminal's working
  pa "..canceled", :red
  exit(5)
end