mpw 4.0.0 → 4.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.
@@ -1,17 +1,17 @@
1
1
  #!/usr/bin/ruby
2
2
  # MPW is a software to crypt and manage your passwords
3
- # Copyright (C) 2016 Adrien Waksberg <mpw@yae.im>
4
- #
3
+ # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im>
4
+ #
5
5
  # This program is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU General Public License
7
7
  # as published by the Free Software Foundation; either version 2
8
8
  # of the License, or (at your option) any later version.
9
- #
9
+ #
10
10
  # This program is distributed in the hope that it will be useful,
11
11
  # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
12
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
13
  # GNU General Public License for more details.
14
- #
14
+ #
15
15
  # You should have received a copy of the GNU General Public License
16
16
  # along with this program; if not, write to the Free Software
17
17
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -20,140 +20,169 @@ require 'gpgme'
20
20
  require 'yaml'
21
21
  require 'i18n'
22
22
  require 'fileutils'
23
-
23
+
24
24
  module MPW
25
- class Config
26
-
27
- attr_accessor :error_msg
28
-
29
- attr_accessor :gpg_key
30
- attr_accessor :lang
31
- attr_accessor :config_dir
32
- attr_accessor :default_wallet
33
- attr_accessor :wallet_dir
34
- attr_accessor :gpg_exe
35
- attr_accessor :password
36
-
37
- # Constructor
38
- # @args: config_file -> the specify config file
39
- def initialize(config_file=nil)
40
- @config_file = config_file
41
-
42
- if /darwin/ =~ RUBY_PLATFORM
43
- @config_dir = "#{Dir.home}/Library/Preferences/mpw"
44
- elsif /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
45
- @config_dir = "#{Dir.home}/AppData/Local/mpw"
46
- else
47
- @config_dir = "#{Dir.home}/.config/mpw"
48
- end
49
-
50
- @config_file = "#{@config_dir}/mpw.cfg" if @config_file.nil? or @config_file.empty?
51
- end
52
-
53
- # Create a new config file
54
- # @args: options -> hash with values
55
- # @rtrn: true if le config file is create
56
- def setup(options)
57
- gpg_key = options[:gpg_key] || @gpg_key
58
- lang = options[:lang] || @lang
59
- wallet_dir = options[:wallet_dir] || @wallet_dir
60
- default_wallet = options[:default_wallet] || @default_wallet
61
- gpg_exe = options[:gpg_exe] || @gpg_exe
62
- password = { numeric: true,
63
- alpha: true,
64
- special: false,
65
- length: 16,
66
- }
67
-
68
- ['numeric', 'special', 'alpha', 'length'].each do |k|
69
- if options.has_key?("pwd_#{k}".to_sym)
70
- password[k.to_sym] = options["pwd_#{k}".to_sym]
71
- elsif not @password.nil? and @password.has_key?(k.to_sym)
72
- password[k.to_sym] = @password[k.to_sym]
73
- end
74
- end
75
-
76
- if not gpg_key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/
77
- raise I18n.t('error.config.key_bad_format')
78
- end
79
-
80
- wallet_dir = "#{@config_dir}/wallets" if wallet_dir.to_s.empty?
81
- config = { 'gpg_key' => gpg_key,
82
- 'lang' => lang,
83
- 'wallet_dir' => wallet_dir,
84
- 'default_wallet' => default_wallet,
85
- 'gpg_exe' => gpg_exe,
86
- 'password' => password,
87
- }
88
-
89
- FileUtils.mkdir_p(@config_dir, mode: 0700)
90
- FileUtils.mkdir_p(wallet_dir, mode: 0700)
91
-
92
- File.open(@config_file, 'w') do |file|
93
- file << config.to_yaml
94
- end
95
- rescue Exception => e
96
- raise "#{I18n.t('error.config.write')}\n#{e}"
97
- end
98
-
99
- # Setup a new gpg key
100
- # @args: password -> the GPG key password
101
- # name -> the name of user
102
- # length -> length of the GPG key
103
- # expire -> the time of expire to GPG key
104
- # @rtrn: true if the GPG key is create, else false
105
- def setup_gpg_key(password, name, length = 4096, expire = 0)
106
- if name.to_s.empty?
107
- raise "#{I18n.t('error.config.genkey_gpg.name')}"
108
- elsif password.to_s.empty?
109
- raise "#{I18n.t('error.config.genkey_gpg.password')}"
110
- end
111
-
112
- param = ''
113
- param << '<GnupgKeyParms format="internal">' + "\n"
114
- param << "Key-Type: RSA\n"
115
- param << "Key-Length: #{length}\n"
116
- param << "Subkey-Type: ELG-E\n"
117
- param << "Subkey-Length: #{length}\n"
118
- param << "Name-Real: #{name}\n"
119
- param << "Name-Comment: #{name}\n"
120
- param << "Name-Email: #{@gpg_key}\n"
121
- param << "Expire-Date: #{expire}\n"
122
- param << "Passphrase: #{password}\n"
123
- param << "</GnupgKeyParms>\n"
124
-
125
- ctx = GPGME::Ctx.new
126
- ctx.genkey(param, nil, nil)
127
- rescue Exception => e
128
- raise "#{I18n.t('error.config.genkey_gpg.exception')}\n#{e}"
129
- end
130
-
131
- # Load the config file
132
- def load_config
133
- config = YAML::load_file(@config_file)
134
- @gpg_key = config['gpg_key']
135
- @lang = config['lang']
136
- @wallet_dir = config['wallet_dir']
137
- @default_wallet = config['default_wallet']
138
- @gpg_exe = config['gpg_exe']
139
- @password = config['password'] || {}
140
-
141
- raise if @gpg_key.empty? or @wallet_dir.empty?
142
-
143
- I18n.locale = @lang.to_sym
144
- rescue Exception => e
145
- raise "#{I18n.t('error.config.load')}\n#{e}"
146
- end
147
-
148
- # Check if private key exist
149
- # @rtrn: true if the key exist, else false
150
- def check_gpg_key?
151
- ctx = GPGME::Ctx.new
152
- ctx.each_key(@gpg_key, true) do
153
- return true
154
- end
155
-
156
- return false
157
- end
158
- end
25
+ class Config
26
+ attr_accessor :error_msg
27
+
28
+ attr_accessor :gpg_key
29
+ attr_accessor :lang
30
+ attr_accessor :config_dir
31
+ attr_accessor :default_wallet
32
+ attr_accessor :wallet_dir
33
+ attr_accessor :wallet_paths
34
+ attr_accessor :gpg_exe
35
+ attr_accessor :password
36
+ attr_accessor :pinmode
37
+
38
+ # Constructor
39
+ # @args: config_file -> the specify config file
40
+ def initialize(config_file = nil)
41
+ @config_file = config_file
42
+ @config_dir =
43
+ if /darwin/ =~ RUBY_PLATFORM
44
+ "#{Dir.home}/Library/Preferences/mpw"
45
+ elsif /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
46
+ "#{Dir.home}/AppData/Local/mpw"
47
+ else
48
+ "#{Dir.home}/.config/mpw"
49
+ end
50
+
51
+ @config_file = "#{@config_dir}/mpw.cfg" if @config_file.to_s.empty?
52
+ end
53
+
54
+ # Create a new config file
55
+ # @args: options -> hash with values
56
+ # @rtrn: true if le config file is create
57
+ def setup(**options)
58
+ gpg_key = options[:gpg_key] || @gpg_key
59
+ lang = options[:lang] || @lang
60
+ wallet_dir = options[:wallet_dir] || @wallet_dir
61
+ default_wallet = options[:default_wallet] || @default_wallet
62
+ gpg_exe = options[:gpg_exe] || @gpg_exe
63
+ pinmode = options[:pinmode] || @pinmode
64
+ password = { numeric: true,
65
+ alpha: true,
66
+ special: false,
67
+ length: 16 }
68
+
69
+ %w[numeric special alpha length].each do |k|
70
+ if options.key?("pwd_#{k}".to_sym)
71
+ password[k.to_sym] = options["pwd_#{k}".to_sym]
72
+ elsif !@password.nil? && @password.key?(k.to_sym)
73
+ password[k.to_sym] = @password[k.to_sym]
74
+ end
75
+ end
76
+
77
+ unless gpg_key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/
78
+ raise I18n.t('error.config.key_bad_format')
79
+ end
80
+
81
+ wallet_dir = "#{@config_dir}/wallets" if wallet_dir.to_s.empty?
82
+ config = { 'gpg_key' => gpg_key,
83
+ 'lang' => lang,
84
+ 'wallet_dir' => wallet_dir,
85
+ 'default_wallet' => default_wallet,
86
+ 'gpg_exe' => gpg_exe,
87
+ 'password' => password,
88
+ 'pinmode' => pinmode,
89
+ 'wallet_paths' => @wallet_paths }
90
+
91
+ FileUtils.mkdir_p(@config_dir, mode: 0700)
92
+ FileUtils.mkdir_p(wallet_dir, mode: 0700)
93
+
94
+ File.open(@config_file, 'w') do |file|
95
+ file << config.to_yaml
96
+ end
97
+ rescue => e
98
+ raise "#{I18n.t('error.config.write')}\n#{e}"
99
+ end
100
+
101
+ # Setup a new gpg key
102
+ # @args: password -> the GPG key password
103
+ # name -> the name of user
104
+ # length -> length of the GPG key
105
+ # expire -> the time of expire to GPG key
106
+ # @rtrn: true if the GPG key is create, else false
107
+ def setup_gpg_key(password, name, length = 4096, expire = 0)
108
+ raise I18n.t('error.config.genkey_gpg.name') if name.to_s.empty?
109
+ raise I18n.t('error.config.genkey_gpg.password') if password.to_s.empty?
110
+
111
+ param = ''
112
+ param << '<GnupgKeyParms format="internal">' + "\n"
113
+ param << "Key-Type: RSA\n"
114
+ param << "Key-Length: #{length}\n"
115
+ param << "Subkey-Type: ELG-E\n"
116
+ param << "Subkey-Length: #{length}\n"
117
+ param << "Name-Real: #{name}\n"
118
+ param << "Name-Comment: #{name}\n"
119
+ param << "Name-Email: #{@gpg_key}\n"
120
+ param << "Expire-Date: #{expire}\n"
121
+ param << "Passphrase: #{password}\n"
122
+ param << "</GnupgKeyParms>\n"
123
+
124
+ ctx = GPGME::Ctx.new
125
+ ctx.genkey(param, nil, nil)
126
+ rescue => e
127
+ raise "#{I18n.t('error.config.genkey_gpg.exception')}\n#{e}"
128
+ end
129
+
130
+ # Load the config file
131
+ def load_config
132
+ config = YAML.load_file(@config_file)
133
+ @gpg_key = config['gpg_key']
134
+ @lang = config['lang']
135
+ @wallet_dir = config['wallet_dir']
136
+ @wallet_paths = config['wallet_paths'] || {}
137
+ @default_wallet = config['default_wallet']
138
+ @gpg_exe = config['gpg_exe']
139
+ @password = config['password'] || {}
140
+ @pinmode = config['pinmode']
141
+
142
+ raise if @gpg_key.empty? || @wallet_dir.empty?
143
+
144
+ I18n.locale = @lang.to_sym
145
+ rescue => e
146
+ raise "#{I18n.t('error.config.load')}\n#{e}"
147
+ end
148
+
149
+ # Check if private key exist
150
+ # @rtrn: true if the key exist, else false
151
+ def check_gpg_key?
152
+ ctx = GPGME::Ctx.new
153
+ ctx.each_key(@gpg_key, true) do
154
+ return true
155
+ end
156
+
157
+ false
158
+ end
159
+
160
+ # Change the path of one wallet
161
+ # @args: path -> the new directory path
162
+ # wallet -> the wallet name
163
+ def set_wallet_path(path, wallet)
164
+ path = @wallet_dir if path == 'default'
165
+
166
+ return if path == @wallet_dir && File.exist?("#{@wallet_dir}/#{wallet}.mpw")
167
+ return if path == @wallet_paths[wallet]
168
+
169
+ old_wallet_file =
170
+ if @wallet_paths.key?(wallet)
171
+ "#{@wallet_paths[wallet]}/#{wallet}.mpw"
172
+ else
173
+ "#{@wallet_dir}/#{wallet}.mpw"
174
+ end
175
+
176
+ FileUtils.mkdir_p(path) unless Dir.exist?(path)
177
+ FileUtils.mv(old_wallet_file, "#{path}/#{wallet}.mpw") if File.exist?(old_wallet_file)
178
+
179
+ if path == @wallet_dir
180
+ @wallet_paths.delete(wallet)
181
+ else
182
+ @wallet_paths[wallet] = path
183
+ end
184
+
185
+ setup
186
+ end
187
+ end
159
188
  end
@@ -1,109 +1,102 @@
1
1
  #!/usr/bin/ruby
2
2
  # MPW is a software to crypt and manage your passwords
3
- # Copyright (C) 2016 Adrien Waksberg <mpw@yae.im>
4
- #
3
+ # Copyright (C) 2017 Adrien Waksberg <mpw@yae.im>
4
+ #
5
5
  # This program is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU General Public License
7
7
  # as published by the Free Software Foundation; either version 2
8
8
  # of the License, or (at your option) any later version.
9
- #
9
+ #
10
10
  # This program is distributed in the hope that it will be useful,
11
11
  # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
12
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
13
  # GNU General Public License for more details.
14
- #
14
+ #
15
15
  # You should have received a copy of the GNU General Public License
16
16
  # along with this program; if not, write to the Free Software
17
17
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
18
 
19
19
  require 'i18n'
20
-
21
- module MPW
22
- class Item
23
20
 
24
- attr_accessor :id
25
- attr_accessor :group
26
- attr_accessor :host
27
- attr_accessor :protocol
28
- attr_accessor :user
29
- attr_accessor :port
30
- attr_accessor :otp
31
- attr_accessor :comment
32
- attr_accessor :last_edit
33
- attr_accessor :last_sync
34
- attr_accessor :created
21
+ module MPW
22
+ class Item
23
+ attr_accessor :id
24
+ attr_accessor :group
25
+ attr_accessor :host
26
+ attr_accessor :protocol
27
+ attr_accessor :user
28
+ attr_accessor :port
29
+ attr_accessor :otp
30
+ attr_accessor :comment
31
+ attr_accessor :last_edit
32
+ attr_accessor :created
35
33
 
36
- # Constructor
37
- # Create a new item
38
- # @args: options -> a hash of parameter
39
- # raise an error if the hash hasn't the key name
40
- def initialize(options={})
41
- if not options.has_key?(:host) or options[:host].to_s.empty?
42
- raise I18n.t('error.update.host_empty')
43
- end
34
+ # Constructor
35
+ # Create a new item
36
+ # @args: options -> a hash of parameter
37
+ # raise an error if the hash hasn't the key name
38
+ def initialize(**options)
39
+ if !options.key?(:host) || options[:host].to_s.empty?
40
+ raise I18n.t('error.update.host_empty')
41
+ end
44
42
 
45
- if not options.has_key?(:id) or options[:id].to_s.empty? or not options.has_key?(:created) or options[:created].to_s.empty?
46
- @id = generate_id
47
- @created = Time.now.to_i
48
- else
49
- @id = options[:id]
50
- @created = options[:created]
51
- @last_edit = options[:last_edit]
52
- options[:no_update_last_edit] = true
53
- end
43
+ if !options.key?(:id) || options[:id].to_s.empty? || !options.key?(:created) || options[:created].to_s.empty?
44
+ @id = generate_id
45
+ @created = Time.now.to_i
46
+ else
47
+ @id = options[:id]
48
+ @created = options[:created]
49
+ @last_edit = options[:last_edit]
50
+ options[:no_update_last_edit] = true
51
+ end
54
52
 
55
- update(options)
56
- end
53
+ update(options)
54
+ end
57
55
 
58
- # Update the item
59
- # @args: options -> a hash of parameter
60
- def update(options={})
61
- if options.has_key?(:host) and options[:host].to_s.empty?
62
- raise I18n.t('error.update.host_empty')
63
- end
56
+ # Update the item
57
+ # @args: options -> a hash of parameter
58
+ def update(**options)
59
+ if options.key?(:host) && options[:host].to_s.empty?
60
+ raise I18n.t('error.update.host_empty')
61
+ end
64
62
 
65
- @group = options[:group] if options.has_key?(:group)
66
- @host = options[:host] if options.has_key?(:host)
67
- @protocol = options[:protocol] if options.has_key?(:protocol)
68
- @user = options[:user] if options.has_key?(:user)
69
- @port = options[:port].to_i if options.has_key?(:port) and not options[:port].to_s.empty?
70
- @otp = options[:otp] if options.has_key?(:otp)
71
- @comment = options[:comment] if options.has_key?(:comment)
72
- @last_edit = Time.now.to_i if not options.has_key?(:no_update_last_edit)
73
- end
63
+ @group = options[:group] if options.key?(:group)
64
+ @host = options[:host] if options.key?(:host)
65
+ @protocol = options[:protocol] if options.key?(:protocol)
66
+ @user = options[:user] if options.key?(:user)
67
+ @port = options[:port].to_i if options.key?(:port) && !options[:port].to_s.empty?
68
+ @otp = options[:otp] if options.key?(:otp)
69
+ @comment = options[:comment] if options.key?(:comment)
70
+ @last_edit = Time.now.to_i unless options.key?(:no_update_last_edit)
71
+ end
74
72
 
75
- # Update last_sync
76
- def set_last_sync
77
- @last_sync = Time.now.to_i
78
- end
73
+ # Delete all data
74
+ def delete
75
+ @id = nil
76
+ @group = nil
77
+ @host = nil
78
+ @protocol = nil
79
+ @user = nil
80
+ @port = nil
81
+ @otp = nil
82
+ @comment = nil
83
+ @created = nil
84
+ @last_edit = nil
85
+ end
79
86
 
80
- # Delete all data
81
- def delete
82
- @id = nil
83
- @group = nil
84
- @host = nil
85
- @protocol = nil
86
- @user = nil
87
- @port = nil
88
- @otp = nil
89
- @comment = nil
90
- @created = nil
91
- @last_edit = nil
92
- @last_sync = nil
93
- end
87
+ def empty?
88
+ @id.to_s.empty?
89
+ end
94
90
 
95
- def empty?
96
- return @id.to_s.empty?
97
- end
91
+ def nil?
92
+ false
93
+ end
98
94
 
99
- def nil?
100
- return false
101
- end
95
+ private
102
96
 
103
- # Generate an random id
104
- private
105
- def generate_id
106
- return ([*('A'..'Z'),*('a'..'z'),*('0'..'9')]).sample(16).join
107
- end
108
- end
97
+ # Generate an random id
98
+ def generate_id
99
+ [*('A'..'Z'), *('a'..'z'), *('0'..'9')].sample(16).join
100
+ end
101
+ end
109
102
  end